diff options
Diffstat (limited to 'src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp')
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 133 |
1 files changed, 72 insertions, 61 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 34027cbac7..ce3c4aac4f 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -62,6 +62,8 @@ #include "qsgopenglvisualizer_p.h" #include "qsgrhivisualizer_p.h" +#include <qtquick_tracepoints_p.h> + #include <algorithm> #ifndef GL_DOUBLE @@ -270,6 +272,7 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material, boo return nullptr; } + Q_TRACE_SCOPE(QSG_prepareMaterial); if (QSG_LOG_TIME_COMPILATION().isDebugEnabled()) qsg_renderer_timer.start(); Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphContextFrame); @@ -332,6 +335,7 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate return nullptr; } + Q_TRACE_SCOPE(QSG_prepareMaterial); if (QSG_LOG_TIME_COMPILATION().isDebugEnabled()) qsg_renderer_timer.start(); Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphContextFrame); @@ -379,6 +383,9 @@ void ShaderManager::invalidated() qDeleteAll(srbCache); srbCache.clear(); + + qDeleteAll(pipelineCache); + pipelineCache.clear(); } void ShaderManager::clearCachedRendererData() @@ -447,13 +454,13 @@ void qsg_dumpShadowRoots(Node *n) QByteArray ind(indent, ' '); if (n->type() == QSGNode::ClipNodeType || n->isBatchRoot) { - qDebug() << ind.constData() << "[X]" << n->sgNode << hex << uint(n->sgNode->flags()); + qDebug() << ind.constData() << "[X]" << n->sgNode << Qt::hex << uint(n->sgNode->flags()); qsg_dumpShadowRoots(n->rootInfo(), indent); } else { QDebug d = qDebug(); - d << ind.constData() << "[ ]" << n->sgNode << hex << uint(n->sgNode->flags()); + d << ind.constData() << "[ ]" << n->sgNode << Qt::hex << uint(n->sgNode->flags()); if (n->type() == QSGNode::GeometryNodeType) - d << "order" << dec << n->element()->order; + d << "order" << Qt::dec << n->element()->order; } SHADOWNODE_TRAVERSE(n) @@ -546,7 +553,7 @@ void Updater::visitNode(Node *n) m_added = count; m_force_update = force; - n->dirtyState = nullptr; + n->dirtyState = {}; } void Updater::visitClipNode(Node *n) @@ -1024,6 +1031,7 @@ Renderer::Renderer(QSGDefaultRenderContext *ctx) ? "static" : (m_bufferStrategy == GL_DYNAMIC_DRAW ? "dynamic" : "stream"))); } + static const bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER"); if (!m_rhi) { // If rendering with an OpenGL Core profile context, we need to create a VAO // to hold our vertex specification state. @@ -1031,9 +1039,9 @@ Renderer::Renderer(QSGDefaultRenderContext *ctx) m_vao = new QOpenGLVertexArrayObject(this); m_vao->create(); } - - bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER"); m_useDepthBuffer = useDepth && ctx->openglContext()->format().depthBufferSize() > 0; + } else { + m_useDepthBuffer = useDepth; } } @@ -1103,13 +1111,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(); } @@ -1119,7 +1123,6 @@ void Renderer::releaseCachedResources() destroyGraphicsResources(); - m_pipelines.clear(); m_samplers.clear(); m_dummyTexture = nullptr; @@ -1399,12 +1402,11 @@ void Renderer::nodeWasRemoved(Node *node) m_elementsToDelete.add(e); if (m_renderNodeElements.isEmpty()) { - if (m_rhi) { - m_useDepthBuffer = true; - } else { - static bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER"); + static const bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER"); + if (m_rhi) + m_useDepthBuffer = useDepth; + else m_useDepthBuffer = useDepth && m_context->openglContext()->format().depthBufferSize() > 0; - } } } } @@ -2339,7 +2341,7 @@ void Renderer::uploadBatch(Batch *b) iDump << " -- Index Data, count:" << b->indexCount; for (int i=0; i<b->indexCount; ++i) { if ((i % 24) == 0) - iDump << endl << " --- "; + iDump << Qt::endl << " --- "; iDump << id[i]; } } @@ -2352,7 +2354,7 @@ void Renderer::uploadBatch(Batch *b) iDump << " -- Index Data, count:" << b->indexCount; for (int i=0; i<b->indexCount; ++i) { if ((i % 24) == 0) - iDump << endl << " --- "; + iDump << Qt::endl << " --- "; iDump << id[i]; } } @@ -2627,7 +2629,7 @@ QRhiGraphicsPipeline *Renderer::buildStencilPipeline(const Batch *batch, bool fi QRhiGraphicsPipeline *ps = m_rhi->newGraphicsPipeline(); ps->setFlags(QRhiGraphicsPipeline::UsesStencilRef); QRhiGraphicsPipeline::TargetBlend blend; - blend.colorWrite = 0; + blend.colorWrite = {}; ps->setTargetBlends({ blend }); ps->setSampleCount(renderTarget()->sampleCount()); ps->setStencilTest(true); @@ -3237,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; } @@ -3257,7 +3261,7 @@ bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms) ps->setShaderResourceBindings(e->srb); ps->setRenderPassDescriptor(renderPassDescriptor()); - QRhiGraphicsPipeline::Flags flags = 0; + QRhiGraphicsPipeline::Flags flags; if (needsBlendConstant(m_gstate.srcColor) || needsBlendConstant(m_gstate.dstColor)) flags |= QRhiGraphicsPipeline::UsesBlendConstants; if (m_gstate.usesScissor) @@ -3302,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; } @@ -3713,7 +3717,7 @@ void Renderer::renderMergedBatch(PreparedRenderBatch *renderBatch) // split prep { batch->vbo.buf, quint32(draw.vertices) }, { batch->vbo.buf, quint32(draw.zorders) } }; - cb->setVertexInput(VERTEX_BUFFER_BINDING, 2, vbufBindings, + cb->setVertexInput(VERTEX_BUFFER_BINDING, m_useDepthBuffer ? 2 : 1, vbufBindings, batch->ibo.buf, draw.indices, m_uint32IndexForRhi ? QRhiCommandBuffer::IndexUInt32 : QRhiCommandBuffer::IndexUInt16); cb->drawIndexed(draw.indexCount); @@ -3957,8 +3961,8 @@ void Renderer::setGraphicsPipeline(QRhiCommandBuffer *cb, const Batch *batch, El void Renderer::renderBatches() { if (Q_UNLIKELY(debug_render())) { - qDebug().nospace() << "Rendering:" << endl - << " -> Opaque: " << qsg_countNodesInBatches(m_opaqueBatches) << " nodes in " << m_opaqueBatches.size() << " batches..." << endl + qDebug().nospace() << "Rendering:" << Qt::endl + << " -> Opaque: " << qsg_countNodesInBatches(m_opaqueBatches) << " nodes in " << m_opaqueBatches.size() << " batches..." << Qt::endl << " -> Alpha: " << qsg_countNodesInBatches(m_alphaBatches) << " nodes in " << m_alphaBatches.size() << " batches..."; } @@ -4049,8 +4053,8 @@ void Renderer::renderBatches() m_pstate.viewportSet = false; m_pstate.scissorSet = false; - m_gstate.depthTest = true; - m_gstate.depthWrite = true; + m_gstate.depthTest = m_useDepthBuffer; + m_gstate.depthWrite = m_useDepthBuffer; m_gstate.depthFunc = QRhiGraphicsPipeline::Less; m_gstate.blending = false; @@ -4082,8 +4086,8 @@ void Renderer::renderBatches() m_gstate.blending = true; // factors never change, always set for premultiplied alpha based blending - // depth test stays enabled but no need to write out depth from the - // transparent (back-to-front) pass + // depth test stays enabled (if m_useDepthBuffer, that is) but no need + // to write out depth from the transparent (back-to-front) pass m_gstate.depthWrite = false; QVarLengthArray<PreparedRenderBatch, 64> alphaRenderBatches; @@ -4504,6 +4508,35 @@ bool Renderer::prepareRhiRenderNode(Batch *batch, PreparedRenderBatch *renderBat updateClipState(rd->m_clip_list, batch); + QSGNode *xform = e->renderNode->parent(); + QMatrix4x4 matrix; + QSGNode *root = rootNode(); + if (e->root) { + matrix = qsg_matrixForRoot(e->root); + root = e->root->sgNode; + } + while (xform != root) { + if (xform->type() == QSGNode::TransformNodeType) { + matrix = matrix * static_cast<QSGTransformNode *>(xform)->combinedMatrix(); + break; + } + xform = xform->parent(); + } + rd->m_matrix = &matrix; + + QSGNode *opacity = e->renderNode->parent(); + rd->m_opacity = 1.0; + while (opacity != rootNode()) { + if (opacity->type() == QSGNode::OpacityNodeType) { + rd->m_opacity = static_cast<QSGOpacityNode *>(opacity)->combinedOpacity(); + break; + } + opacity = opacity->parent(); + } + + if (rd->m_prepareCallback) + rd->m_prepareCallback(); + renderBatch->batch = batch; renderBatch->sms = nullptr; @@ -4532,38 +4565,15 @@ void Renderer::renderRhiRenderNode(const Batch *batch) // split prepare-render ( state.m_scissorEnabled = batch->clipState.type & ClipState::ScissorClip; state.m_stencilEnabled = batch->clipState.type & ClipState::StencilClip; - QSGNode *xform = e->renderNode->parent(); - QMatrix4x4 matrix; - QSGNode *root = rootNode(); - if (e->root) { - matrix = qsg_matrixForRoot(e->root); - root = e->root->sgNode; - } - while (xform != root) { - if (xform->type() == QSGNode::TransformNodeType) { - matrix = matrix * static_cast<QSGTransformNode *>(xform)->combinedMatrix(); - break; - } - xform = xform->parent(); - } - rd->m_matrix = &matrix; - - QSGNode *opacity = e->renderNode->parent(); - rd->m_opacity = 1.0; - while (opacity != rootNode()) { - if (opacity->type() == QSGNode::OpacityNodeType) { - rd->m_opacity = static_cast<QSGOpacityNode *>(opacity)->combinedOpacity(); - break; - } - opacity = opacity->parent(); - } - const QSGRenderNode::StateFlags changes = e->renderNode->changedStates(); QRhiCommandBuffer *cb = commandBuffer(); - cb->beginExternal(); + const bool needsExternal = rd->m_needsExternalRendering; + if (needsExternal) + cb->beginExternal(); e->renderNode->render(&state); - cb->endExternal(); + if (needsExternal) + cb->endExternal(); rd->m_matrix = nullptr; rd->m_clip_list = nullptr; @@ -4643,7 +4653,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); } @@ -4654,7 +4664,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) |