diff options
Diffstat (limited to 'src/quick/scenegraph')
-rw-r--r-- | src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp | 5 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgrendererinterface.cpp | 9 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgadaptationlayer.cpp | 26 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgadaptationlayer_p.h | 133 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgcontext.cpp | 26 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgcontext_p.h | 5 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgcontextplugin_p.h | 2 |
7 files changed, 203 insertions, 3 deletions
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp index 05628ea69c..0e2f4f5382 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareadaptation.cpp @@ -65,7 +65,10 @@ QSGContext *QSGSoftwareAdaptation::create(const QString &) const QSGContextFactoryInterface::Flags QSGSoftwareAdaptation::flags(const QString &) const { - return QSGContextFactoryInterface::SupportsShaderEffectV2; + // Claim we support adaptable shader effects, then return null for the + // shader effect node. The result is shader effects not being rendered, + // with the application working fine in all other respects. + return QSGContextFactoryInterface::SupportsShaderEffectNode; } QSGRenderLoop *QSGSoftwareAdaptation::createWindowManager() diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp index 6a01fac212..b680dbe3d5 100644 --- a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp +++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp @@ -87,6 +87,11 @@ QSGRendererInterface::~QSGRendererInterface() \fn QSGRenderNode::GraphicsAPI QSGRenderNode::graphicsAPI() const Returns the graphics API that is in use by the Qt Quick scenegraph. + + \note This function can be called on any thread. However, the renderer + interface's lifetime may be tied to the render thread and therefore calling + this function from other threads during the process of application shutdown + or QQuickWindow closing is likely to become invalid. */ /*! @@ -98,6 +103,8 @@ QSGRendererInterface::~QSGRendererInterface() pointer to an opaque handle that needs to be dereferenced first (for example, \c{VkDevice dev = *static_cast<VkDevice *>(result)}). The latter is necessary since such handles may have sizes different from a pointer. + + \note This function must only be called on the render thread. */ void *QSGRendererInterface::getResource(Resource resource) const { @@ -109,6 +116,8 @@ void *QSGRendererInterface::getResource(Resource resource) const Queries a graphics resource. \a resource is a backend-specific key. This allows supporting any future resources that are not listed in the Resource enum. + + \note This function must only be called on the render thread. */ void *QSGRendererInterface::getResource(const char *resource) const { diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp index e8ef6befcd..b0259c50b0 100644 --- a/src/quick/scenegraph/qsgadaptationlayer.cpp +++ b/src/quick/scenegraph/qsgadaptationlayer.cpp @@ -519,4 +519,30 @@ void QSGNodeVisitorEx::visitChildren(QSGNode *node) } } +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QSGGuiThreadShaderEffectManager::ShaderInfo::InputParameter &p) +{ + debug << p.semanticName << p.semanticIndex; + return debug; +} +QDebug operator<<(QDebug debug, const QSGGuiThreadShaderEffectManager::ShaderInfo::Variable &v) +{ + debug << v.name; + switch (v.type) { + case QSGGuiThreadShaderEffectManager::ShaderInfo::Constant: + debug << "cvar" << "offset" << v.offset << "size" << v.size; + break; + case QSGGuiThreadShaderEffectManager::ShaderInfo::Sampler: + debug << "sampler" << "bindpoint" << v.bindPoint; + break; + case QSGGuiThreadShaderEffectManager::ShaderInfo::Texture: + debug << "texture" << "bindpoint" << v.bindPoint; + break; + default: + break; + } + return debug; +} +#endif + QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index 78bb07599f..5155cdd719 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -223,6 +223,139 @@ Q_SIGNALS: void scheduledUpdateCompleted(); }; +class Q_QUICK_PRIVATE_EXPORT QSGGuiThreadShaderEffectManager : public QObject +{ + Q_OBJECT + +public: + // Enum values must match ShaderEffect. + enum ShaderType { + GLSL, + HLSL, + Metal + }; + enum ShaderCompilationType { + RuntimeCompilation = 0x01, + OfflineCompilation = 0x02 + }; + enum ShaderSourceType { + ShaderSourceString = 0x01, + ShaderSourceFile = 0x02, + ShaderByteCode = 0x04 + }; + enum Status { + Compiled, + Uncompiled, + Error + }; + + virtual ShaderType shaderType() const = 0; + virtual int shaderCompilationType() const = 0; + virtual int shaderSourceType() const = 0; + + virtual bool hasSeparateSamplerAndTextureObjects() const = 0; + + virtual QString log() const = 0; + virtual Status status() const = 0; + + struct ShaderInfo { + enum Type { + TypeVertex, + TypeFragment, + TypeOther + }; + enum VariableType { + Constant, // cbuffer members or uniforms + Sampler, + Texture // for APIs with separate texture and sampler objects + }; + struct InputParameter { + InputParameter() : semanticIndex(0) { } + // Semantics use the D3D keys (POSITION, TEXCOORD). + // Attribute name based APIs can map based on pre-defined names. + QByteArray semanticName; + int semanticIndex; + }; + struct Variable { + Variable() : type(Constant), offset(0), size(0), bindPoint(0) { } + VariableType type; + QByteArray name; + uint offset; // for cbuffer members + uint size; // for cbuffer members + int bindPoint; // for textures and samplers; for register-based APIs + }; + + QByteArray blob; // source or bytecode + Type type; + QVector<InputParameter> inputParameters; + QVector<Variable> variables; + }; + + virtual bool reflect(const QByteArray &src, ShaderInfo *result) = 0; + +Q_SIGNALS: + void textureChanged(); + void logAndStatusChanged(); +}; + +#ifndef QT_NO_DEBUG_STREAM +Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug debug, const QSGGuiThreadShaderEffectManager::ShaderInfo::InputParameter &p); +Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug debug, const QSGGuiThreadShaderEffectManager::ShaderInfo::Variable &v); +#endif + +class Q_QUICK_PRIVATE_EXPORT QSGShaderEffectNode : public QSGVisitableNode +{ +public: + enum DirtyShaderFlag { + DirtyShaderVertex = 0x01, + DirtyShaderFragment = 0x02, + DirtyShaderConstant = 0x04, + DirtyShaderTexture = 0x08, + DirtyShaderGeometry = 0x10, + DirtyShaderMesh = 0x20 + }; + Q_DECLARE_FLAGS(DirtyShaderFlags, DirtyShaderFlag) + + enum CullMode { // must match ShaderEffect + NoCulling, + BackFaceCulling, + FrontFaceCulling + }; + + struct VariableData { + enum SpecialType { None, Unused, SubRect, Opacity, Matrix, Source }; + + QVariant value; + SpecialType specialType; + }; + + struct ShaderData { + ShaderData() : valid(false) { } + bool valid; + QSGGuiThreadShaderEffectManager::ShaderInfo shaderInfo; + QVector<VariableData> varData; + }; + + struct SyncData { + DirtyShaderFlags dirty; + CullMode cullMode; + bool blending; + bool supportsAtlasTextures; + ShaderData *vertexShader; + ShaderData *fragmentShader; + }; + + // Each ShaderEffect item has one node (render thread) and one manager (gui thread). + QSGShaderEffectNode(QSGGuiThreadShaderEffectManager *) { } + + virtual QRectF normalizedTextureSubRect() const = 0; + virtual void sync(SyncData *syncData) = 0; + + void accept(QSGNodeVisitorEx *visitor) override { if (visitor->visit(this)) visitor->visitChildren(this); visitor->endVisit(this); } +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QSGShaderEffectNode::DirtyShaderFlags) + class Q_QUICK_PRIVATE_EXPORT QSGGlyphNode : public QSGVisitableNode { public: diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 0f0a7be3b2..27d0f01753 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -277,11 +277,29 @@ QSGRectangleNode *QSGContext::createRectangleNode(const QRectF &rect, const QCol return node; } +/*! + Creates a new shader effect helper instance. This function is called on the + gui thread, unlike the others. This is necessary in order to provide + adaptable, backend-specific shader effect functionality to the gui thread too. + */ +QSGGuiThreadShaderEffectManager *QSGContext::createGuiThreadShaderEffectManager() +{ + return nullptr; +} /*! - Creates a new animation driver. + Creates a new shader effect node. The default of returning nullptr is + valid as long as the backend does not claim SupportsShaderEffectNode or + ignoring ShaderEffect elements is acceptable. */ +QSGShaderEffectNode *QSGContext::createShaderEffectNode(QSGRenderContext *, QSGGuiThreadShaderEffectManager *) +{ + return nullptr; +} +/*! + Creates a new animation driver. + */ QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent) { return new QSGAnimationDriver(parent); @@ -296,6 +314,12 @@ QSize QSGContext::minimumFBOSize() const return QSize(1, 1); } +/*! + Returns a pointer to the (presumably) global renderer interface. + + \note This function may be called on the gui thread in order to get access + to QSGRendererInterface::graphicsAPI(). + */ QSGRendererInterface *QSGContext::rendererInterface(QSGRenderContext *renderContext) { Q_UNUSED(renderContext); diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index 19a8636f19..2139377ebb 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -83,6 +83,8 @@ class QSGDistanceFieldGlyphCacheManager; class QSGContext; class QQuickPaintedItem; class QSGRendererInterface; +class QSGShaderEffectNode; +class QSGGuiThreadShaderEffectManager; Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_RENDERLOOP) Q_DECLARE_LOGGING_CATEGORY(QSG_LOG_TIME_COMPILATION) @@ -166,6 +168,9 @@ public: virtual QSGGlyphNode *createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode) = 0; virtual QSGNinePatchNode *createNinePatchNode() = 0; virtual QSGLayer *createLayer(QSGRenderContext *renderContext) = 0; + virtual QSGGuiThreadShaderEffectManager *createGuiThreadShaderEffectManager(); + virtual QSGShaderEffectNode *createShaderEffectNode(QSGRenderContext *renderContext, + QSGGuiThreadShaderEffectManager *mgr); virtual QAnimationDriver *createAnimationDriver(QObject *parent); virtual QSize minimumFBOSize() const; diff --git a/src/quick/scenegraph/qsgcontextplugin_p.h b/src/quick/scenegraph/qsgcontextplugin_p.h index 779dca62fc..08c3d21408 100644 --- a/src/quick/scenegraph/qsgcontextplugin_p.h +++ b/src/quick/scenegraph/qsgcontextplugin_p.h @@ -65,7 +65,7 @@ class QSGRenderLoop; struct Q_QUICK_PRIVATE_EXPORT QSGContextFactoryInterface : public QFactoryInterface { enum Flag { - SupportsShaderEffectV2 = 0x01 + SupportsShaderEffectNode = 0x01 }; Q_DECLARE_FLAGS(Flags, Flag) |