diff options
author | Laszlo Agocs <laszlo.agocs@theqtcompany.com> | 2016-04-28 15:49:26 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@theqtcompany.com> | 2016-04-29 09:36:43 +0000 |
commit | 3169744ab415268a9b6ff544d1bd49031ef3c08a (patch) | |
tree | 18362e5a8dd62ab940e82a9f055be50c75432866 /src/quick/items | |
parent | cb1033fd603a438041a16ba55547d77133ad1e79 (diff) |
D3D12: Fix 'ShaderEffect in a ShaderEffectSource as property value'
Import (and clean up) the dropshadow from the shadereffects example.
This is very useful since it tests a lot more paths and cases than
the wobble.
To overcome the issue of not having some of functionality available before
the item is added to a window, make QQuickGenericShaderEffect smarter and
enhance the documentation.
The handling of vertical mirroring is revised. The GLSL and HLSL version of
the dropshadow shaders produce correct, identical output now.
Change-Id: I94800997bfba781140d80720eb6f340cda480747
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/quick/items')
-rw-r--r-- | src/quick/items/qquickgenericshadereffect.cpp | 48 | ||||
-rw-r--r-- | src/quick/items/qquickgenericshadereffect_p.h | 2 | ||||
-rw-r--r-- | src/quick/items/qquickshadereffect.cpp | 67 | ||||
-rw-r--r-- | src/quick/items/qquickshadereffect_p.h | 4 |
4 files changed, 96 insertions, 25 deletions
diff --git a/src/quick/items/qquickgenericshadereffect.cpp b/src/quick/items/qquickgenericshadereffect.cpp index ae34a65a2f..49ed25f799 100644 --- a/src/quick/items/qquickgenericshadereffect.cpp +++ b/src/quick/items/qquickgenericshadereffect.cpp @@ -61,6 +61,7 @@ QQuickGenericShaderEffect::QQuickGenericShaderEffect(QQuickShaderEffect *item, Q , m_mgr(nullptr) , m_dirty(0) { + connect(m_item, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(itemWindowChanged(QQuickWindow*))); } QQuickGenericShaderEffect::~QQuickGenericShaderEffect() @@ -76,7 +77,11 @@ QQuickGenericShaderEffect::~QQuickGenericShaderEffect() void QQuickGenericShaderEffect::setFragmentShader(const QByteArray &src) { - if (m_fragShader.constData() == src.constData()) + // Compare the actual values since they are often just filenames. + // Optimizing by comparing constData() is a bad idea since seemingly static + // strings in QML may in fact have different addresses when a binding + // triggers assigning the "same" value to the property. + if (m_fragShader == src) return; m_fragShader = src; @@ -91,7 +96,7 @@ void QQuickGenericShaderEffect::setFragmentShader(const QByteArray &src) void QQuickGenericShaderEffect::setVertexShader(const QByteArray &src) { - if (m_vertShader.constData() == src.constData()) + if (m_vertShader == src) return; m_vertShader = src; @@ -192,7 +197,7 @@ QQuickShaderEffect::Status QQuickGenericShaderEffect::status() const { QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager(); if (!mgr) - return QQuickShaderEffect::Error; + return QQuickShaderEffect::Uncompiled; return QQuickShaderEffect::Status(mgr->status()); } @@ -201,7 +206,7 @@ QQuickShaderEffect::ShaderType QQuickGenericShaderEffect::shaderType() const { QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager(); if (!mgr) - return QQuickShaderEffect::HLSL; + return QQuickShaderEffect::ShaderType(0); return QQuickShaderEffect::ShaderType(mgr->shaderType()); } @@ -210,7 +215,7 @@ QQuickShaderEffect::ShaderCompilationType QQuickGenericShaderEffect::shaderCompi { QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager(); if (!mgr) - return QQuickShaderEffect::OfflineCompilation; + return QQuickShaderEffect::ShaderCompilationType(0); return QQuickShaderEffect::ShaderCompilationType(mgr->shaderCompilationType()); } @@ -219,7 +224,7 @@ QQuickShaderEffect::ShaderSourceType QQuickGenericShaderEffect::shaderSourceType { QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager(); if (!mgr) - return QQuickShaderEffect::ShaderByteCode; + return QQuickShaderEffect::ShaderSourceType(0); return QQuickShaderEffect::ShaderSourceType(mgr->shaderSourceType()); } @@ -348,20 +353,41 @@ QSGGuiThreadShaderEffectManager *QQuickGenericShaderEffect::shaderEffectManager( if (w && w->isSceneGraphInitialized()) { m_mgr = QQuickWindowPrivate::get(w)->context->sceneGraphContext()->createGuiThreadShaderEffectManager(); if (m_mgr) { - QObject::connect(m_mgr, SIGNAL(logAndStatusChanged()), m_item, SIGNAL(logChanged())); - QObject::connect(m_mgr, SIGNAL(logAndStatusChanged()), m_item, SIGNAL(statusChanged())); - QObject::connect(m_mgr, SIGNAL(textureChanged()), this, SLOT(markGeometryDirtyAndUpdateIfSupportsAtlas())); + connect(m_mgr, SIGNAL(logAndStatusChanged()), m_item, SIGNAL(logChanged())); + connect(m_mgr, SIGNAL(logAndStatusChanged()), m_item, SIGNAL(statusChanged())); + connect(m_mgr, SIGNAL(textureChanged()), this, SLOT(markGeometryDirtyAndUpdateIfSupportsAtlas())); } } else if (!w) { - qWarning("ShaderEffect: Backend specifics cannot be queried until the item has a window"); + // Wait until itemWindowChanged() gets called. Return null for now. } else { - qWarning("ShaderEffect: Backend specifics cannot be queried until the scenegraph has initialized"); + // Have window, but no scenegraph -> ensure the signal is connected. Return null for now. + const_cast<QQuickGenericShaderEffect *>(this)->itemWindowChanged(w); } } return m_mgr; } +void QQuickGenericShaderEffect::itemWindowChanged(QQuickWindow *w) +{ + if (w) { + if (w->isSceneGraphInitialized()) + backendChanged(); + else + connect(w, SIGNAL(sceneGraphInitialized()), this, SLOT(backendChanged()), Qt::UniqueConnection); + } +} + +void QQuickGenericShaderEffect::backendChanged() +{ + disconnect(m_item->window(), SIGNAL(sceneGraphInitialized()), this, SLOT(backendChanged())); + emit m_item->logChanged(); + emit m_item->statusChanged(); + emit m_item->shaderTypeChanged(); + emit m_item->shaderCompilationTypeChanged(); + emit m_item->shaderSourceTypeChanged(); +} + void QQuickGenericShaderEffect::disconnectSignals(Shader shaderType) { for (auto &sm : m_signalMappers[shaderType]) { diff --git a/src/quick/items/qquickgenericshadereffect_p.h b/src/quick/items/qquickgenericshadereffect_p.h index 5f6652ec32..2af7d1156a 100644 --- a/src/quick/items/qquickgenericshadereffect_p.h +++ b/src/quick/items/qquickgenericshadereffect_p.h @@ -105,6 +105,8 @@ private slots: void sourceDestroyed(QObject *object); void markGeometryDirtyAndUpdate(); void markGeometryDirtyAndUpdateIfSupportsAtlas(); + void itemWindowChanged(QQuickWindow *w); + void backendChanged(); private: QSGGuiThreadShaderEffectManager *shaderEffectManager() const; diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index 36fc7ef3c8..560c49fb7c 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -321,6 +321,12 @@ QT_BEGIN_NAMESPACE \endcode \endtable + \note With OpenGL the \c y coordinate runs from bottom to top whereas with + Direct 3D it goes top to bottom. For shader effect sources Qt Quick hides + the difference by treating QtQuick::ShaderEffectSource::textureMirroring as + appropriate, meaning texture coordinates in HLSL version of the shaders + will not need any adjustments compared to the equivalent GLSL code. + \section1 ShaderEffect and Item Layers The ShaderEffect type can be combined with \l {Item Layers} {layered items}. @@ -644,12 +650,23 @@ QQuickShaderEffect::Status QQuickShaderEffect::status() const } /*! - \qmlproperty QtQuick::ShaderEffect::ShaderType QtQuick::ShaderEffect::shaderType + \qmlproperty enumeration QtQuick::ShaderEffect::shaderType This property contains the shading language supported by the current Qt Quick backend the application is using. - With OpenGL the value is GLSL. + \list + \li ShaderEffect.UnknownShadingLanguage - Not yet known due to no window and scenegraph associated + \li ShaderEffect.GLSL - GLSL or GLSL ES + \li ShaderEffect.HLSL - HLSL + \endlist + + \note The value is only up-to-date once the item is associated with a + window and the window's scenegraph has initialized. Bindings relying on the + value have to keep this in mind since the value may change from + ShaderEffect.UnknownShadingLanguage to the actual value after component + initialization is complete. This is particularly relevant for ShaderEffect + items inside ShaderEffectSource items set as property values. \since 5.8 \since QtQuick 2.8 @@ -667,14 +684,26 @@ QQuickShaderEffect::ShaderType QQuickShaderEffect::shaderType() const } /*! - \qmlproperty QtQuick::ShaderEffect::ShaderCompilationType QtQuick::ShaderEffect::shaderCompilationType + \qmlproperty enumeration QtQuick::ShaderEffect::shaderCompilationType This property contains a bitmask of the shader compilation approaches supported by the current Qt Quick backend the application is using. - With OpenGL the value is RuntimeCompilation, which corresponds to the - traditional way of using ShaderEffect. Non-OpenGL backends are expected to - focus more on OfflineCompilation, however. + \list + \li ShaderEffect.RuntimeCompilation + \li ShaderEffect.OfflineCompilation + \endlist + + With OpenGL the value is ShaderEffect.RuntimeCompilation, which corresponds + to the traditional way of using ShaderEffect. Non-OpenGL backends are + expected to focus more on ShaderEffect.OfflineCompilation, however. + + \note The value is only up-to-date once the item is associated with a + window and the window's scenegraph has initialized. Bindings relying on the + value have to keep this in mind since the value may change from \c 0 to the + actual bitmask after component initialization is complete. This is + particularly relevant for ShaderEffect items inside ShaderEffectSource + items set as property values. \since 5.8 \since QtQuick 2.8 @@ -692,16 +721,30 @@ QQuickShaderEffect::ShaderCompilationType QQuickShaderEffect::shaderCompilationT } /*! - \qmlproperty QtQuick::ShaderEffect::ShaderSourceType QtQuick::ShaderEffect::shaderSourceType + \qmlproperty enumeration QtQuick::ShaderEffect::shaderSourceType This property contains a bitmask of the supported ways of providing shader sources. - With OpenGL the value is ShaderSourceString, which corresponds to the - traditional way of inlining GLSL source code into QML. Other, non-OpenGL Qt - Quick backends may however decide not to support inlined shader sources, or - even shader sources at all. In this case shaders are expected to be - pre-compiled into formats like SPIR-V or D3D shader bytecode. + \list + \li ShaderEffect.ShaderSourceString + \li ShaderEffect.ShaderSourceFile + \li ShaderEffect.ShaderByteCode + \endlist + + With OpenGL the value is ShaderEffect.ShaderSourceString, which corresponds + to the traditional way of inlining GLSL source code into QML. Other, + non-OpenGL Qt Quick backends may however decide not to support inlined + shader sources, or even shader sources at all. In this case shaders are + expected to be pre-compiled into formats like SPIR-V or D3D shader + bytecode. + + \note The value is only up-to-date once the item is associated with a + window and the window's scenegraph has initialized. Bindings relying on the + value have to keep this in mind since the value may change from \c 0 to the + actual bitmask after component initialization is complete. This is + particularly relevant for ShaderEffect items inside ShaderEffectSource + items set as property values. \since 5.8 \since QtQuick 2.8 diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h index 390703350f..0410514c36 100644 --- a/src/quick/items/qquickshadereffect_p.h +++ b/src/quick/items/qquickshadereffect_p.h @@ -90,9 +90,9 @@ public: Q_ENUM(Status) enum ShaderType { + UnknownShadingLanguage, GLSL, - HLSL, - Metal + HLSL }; Q_ENUM(ShaderType) |