diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-11-25 21:36:23 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-12-16 17:24:14 +0100 |
commit | b2cd9c9675e4345a0d0cd91d18dde9209fcf8048 (patch) | |
tree | 7c1340562f8113173273681c1c18522701bb1d8c /src/quick/scenegraph | |
parent | 8200c7500f5d1b7bf83742df903fea3f52e50fbf (diff) |
Share pipeline state objects between layer renderers
...as long as the renderpass descriptors are compatible.
Relies on the new QRhiRenderPassDescriptor::isCompatible() function.
In the nodetypes_ng manual test this brings down the number of pipelines
created from 16 to 8 in the layer test scene (because most layers use
the same materials there, so many pipelines can be reused between them -
previously this was prevented by the comparison-by-pointer for the
QRhiRenderPassDescriptors). Additionally, any application with more than one
layer (Item.layer enabled or ShaderEffect) in the scene will benefit from this.
Task-number: QTBUG-80318
Change-Id: Id7437a3baac31891a231643d4787da7186ac107e
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Diffstat (limited to 'src/quick/scenegraph')
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 23 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h | 109 |
2 files changed, 69 insertions, 63 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index add1f3d235..4f911420ce 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -383,6 +383,9 @@ void ShaderManager::invalidated() qDeleteAll(srbCache); srbCache.clear(); + + qDeleteAll(pipelineCache); + pipelineCache.clear(); } void ShaderManager::clearCachedRendererData() @@ -1107,13 +1110,9 @@ void Renderer::destroyGraphicsResources() // are going to destroy. m_shaderManager->clearCachedRendererData(); - qDeleteAll(m_pipelines); qDeleteAll(m_samplers); - m_stencilClipCommon.reset(); - delete m_dummyTexture; - m_visualizer->releaseResources(); } @@ -1123,7 +1122,6 @@ void Renderer::releaseCachedResources() destroyGraphicsResources(); - m_pipelines.clear(); m_samplers.clear(); m_dummyTexture = nullptr; @@ -3241,15 +3239,17 @@ static inline bool needsBlendConstant(QRhiGraphicsPipeline::BlendFactor f) bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms) // RHI only, [prepare step] { - // In unmerged batches the srbs in the elements are all compatible layout-wise. + // In unmerged batches the srbs in the elements are all compatible + // layout-wise. Note the key's == and qHash implementations: the rp desc and + // srb are tested for (layout) compatibility, not pointer equality. const GraphicsPipelineStateKey k { m_gstate, sms, renderPassDescriptor(), e->srb }; // Note: dynamic state (viewport rect, scissor rect, stencil ref, blend // constant) is never a part of GraphicsState/QRhiGraphicsPipeline. // See if there is an existing, matching pipeline state object. - auto it = m_pipelines.constFind(k); - if (it != m_pipelines.constEnd()) { + auto it = m_shaderManager->pipelineCache.constFind(k); + if (it != m_shaderManager->pipelineCache.constEnd()) { e->ps = *it; return true; } @@ -3306,7 +3306,7 @@ bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms) return false; } - m_pipelines.insert(k, ps); + m_shaderManager->pipelineCache.insert(k, ps); e->ps = ps; return true; } @@ -4647,7 +4647,7 @@ bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKe { return a.state == b.state && a.sms->programRhi.program == b.sms->programRhi.program - && a.rpDesc == b.rpDesc + && a.compatibleRenderPassDescriptor->isCompatible(b.compatibleRenderPassDescriptor) && a.layoutCompatibleSrb->isLayoutCompatible(b.layoutCompatibleSrb); } @@ -4658,7 +4658,8 @@ bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKe uint qHash(const GraphicsPipelineStateKey &k, uint seed) Q_DECL_NOTHROW { - return qHash(k.state, seed) + qHash(k.sms->programRhi.program, seed) + qHash(k.rpDesc, seed); + // no srb and rp included due to their special comparison semantics and lack of hash keys + return qHash(k.state, seed) + qHash(k.sms->programRhi.program, seed); } Visualizer::Visualizer(Renderer *renderer) diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 297df2232a..878b63fc8c 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -626,27 +626,65 @@ private: QMatrix4x4 m_identityMatrix; }; +struct GraphicsState +{ + bool depthTest = false; + bool depthWrite = false; + QRhiGraphicsPipeline::CompareOp depthFunc = QRhiGraphicsPipeline::Less; + bool blending = false; + QRhiGraphicsPipeline::BlendFactor srcColor = QRhiGraphicsPipeline::One; + QRhiGraphicsPipeline::BlendFactor dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha; + QRhiGraphicsPipeline::ColorMask colorWrite = QRhiGraphicsPipeline::ColorMask(0xF); + QRhiGraphicsPipeline::CullMode cullMode = QRhiGraphicsPipeline::None; + bool usesScissor = false; + bool stencilTest = false; + int sampleCount = 1; + QSGGeometry::DrawingMode drawMode = QSGGeometry::DrawTriangles; + float lineWidth = 1.0f; +}; + +bool operator==(const GraphicsState &a, const GraphicsState &b) Q_DECL_NOTHROW; +bool operator!=(const GraphicsState &a, const GraphicsState &b) Q_DECL_NOTHROW; +uint qHash(const GraphicsState &s, uint seed = 0) Q_DECL_NOTHROW; + +struct ShaderManagerShader; + +struct GraphicsPipelineStateKey +{ + GraphicsState state; + const ShaderManagerShader *sms; + const QRhiRenderPassDescriptor *compatibleRenderPassDescriptor; + const QRhiShaderResourceBindings *layoutCompatibleSrb; +}; + +bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) Q_DECL_NOTHROW; +bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) Q_DECL_NOTHROW; +uint qHash(const GraphicsPipelineStateKey &k, uint seed = 0) Q_DECL_NOTHROW; + +struct ShaderManagerShader +{ + ~ShaderManagerShader() { + delete programRhi.program; + delete programGL.program; + } + struct { + QSGMaterialShader *program = nullptr; + int pos_order; + } programGL; + struct { + QSGMaterialRhiShader *program = nullptr; + QRhiVertexInputLayout inputLayout; + QVarLengthArray<QRhiGraphicsShaderStage, 2> shaderStages; + } programRhi; + + float lastOpacity; +}; + class ShaderManager : public QObject { Q_OBJECT public: - struct Shader { - ~Shader() { - delete programRhi.program; - delete programGL.program; - } - struct { - QSGMaterialShader *program = nullptr; - int pos_order; - } programGL; - struct { - QSGMaterialRhiShader *program = nullptr; - QRhiVertexInputLayout inputLayout; - QVarLengthArray<QRhiGraphicsShaderStage, 2> shaderStages; - } programRhi; - - float lastOpacity; - }; + using Shader = ShaderManagerShader; ShaderManager(QSGDefaultRenderContext *ctx) : blitProgram(nullptr), context(ctx) { } ~ShaderManager() { @@ -657,9 +695,10 @@ public: void clearCachedRendererData(); using ShaderResourceBindingList = QVarLengthArray<QRhiShaderResourceBinding, 8>; - QRhiShaderResourceBindings *srb(const ShaderResourceBindingList &bindings); + QHash<GraphicsPipelineStateKey, QRhiGraphicsPipeline *> pipelineCache; + public Q_SLOTS: void invalidated(); @@ -677,39 +716,6 @@ private: QHash<ShaderResourceBindingList, QRhiShaderResourceBindings *> srbCache; }; -struct GraphicsState -{ - bool depthTest = false; - bool depthWrite = false; - QRhiGraphicsPipeline::CompareOp depthFunc = QRhiGraphicsPipeline::Less; - bool blending = false; - QRhiGraphicsPipeline::BlendFactor srcColor = QRhiGraphicsPipeline::One; - QRhiGraphicsPipeline::BlendFactor dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha; - QRhiGraphicsPipeline::ColorMask colorWrite = QRhiGraphicsPipeline::ColorMask(0xF); - QRhiGraphicsPipeline::CullMode cullMode = QRhiGraphicsPipeline::None; - bool usesScissor = false; - bool stencilTest = false; - int sampleCount = 1; - QSGGeometry::DrawingMode drawMode = QSGGeometry::DrawTriangles; - float lineWidth = 1.0f; -}; - -bool operator==(const GraphicsState &a, const GraphicsState &b) Q_DECL_NOTHROW; -bool operator!=(const GraphicsState &a, const GraphicsState &b) Q_DECL_NOTHROW; -uint qHash(const GraphicsState &s, uint seed = 0) Q_DECL_NOTHROW; - -struct GraphicsPipelineStateKey -{ - GraphicsState state; - const ShaderManager::Shader *sms; - const QRhiRenderPassDescriptor *rpDesc; - const QRhiShaderResourceBindings *layoutCompatibleSrb; -}; - -bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) Q_DECL_NOTHROW; -bool operator!=(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) Q_DECL_NOTHROW; -uint qHash(const GraphicsPipelineStateKey &k, uint seed = 0) Q_DECL_NOTHROW; - struct RenderPassState { QRhiViewport viewport; @@ -903,7 +909,6 @@ private: GraphicsState m_gstate; RenderPassState m_pstate; QStack<GraphicsState> m_gstateStack; - QHash<GraphicsPipelineStateKey, QRhiGraphicsPipeline *> m_pipelines; QHash<QSGSamplerDescription, QRhiSampler *> m_samplers; QRhiTexture *m_dummyTexture = nullptr; |