diff options
author | Laszlo Agocs <[email protected]> | 2020-06-05 18:10:30 +0200 |
---|---|---|
committer | Laszlo Agocs <[email protected]> | 2020-06-09 21:13:21 +0200 |
commit | 22d8db1e115b120ce2f62896eb7fea452348941e (patch) | |
tree | beb189edc62ce1a5bee433827415f0dd95fe7272 /src | |
parent | 84b53c165e9d492a547c04499450007d2c293bc8 (diff) |
Add perspective 3D plane render mode
One can now do rc->createRenderer(QSGRenderContext::RenderMode3D) in Quick3D.
By default nothing changes, both QQuickWindow and QSGRhiLayer default to
either RenderMode2D or RenderMode2DNoDepthBuffer, depending on
QSG_NO_DEPTH_BUFFER. (the environment variable handling is moved out of
qsgbatchrenderer.cpp however, leaving it up to whoever is creating the
renderer to passing the appropriate flag)
The RenderMode3D mode is a modified version of the QSG_NO_DEPTH_BUFFER case:
only alpha batches are used, which are then rendered back to front. The
difference is that this is done with depth test on (no write), so the
2D content gets depth tested against whatever is already in the depth buffer.
Then, there's an additional depth "post pass" to fill the depth buffer with the
2D content. This must be separate from the color-write enabled stage because
otherwise unavoidable Z fighting would occur. By filling the depth buffer,
other 3D or 2D content, that is rendered afterwards, can depth test correctly
against the 2D elements rendered here.
customRenderMode and related functions are renamed to visualization
(because that's what it is about), in order to prevent confusing name
clashes.
Change-Id: I0d43b273e0a8020af05a652a236c0ad5fb150685
Reviewed-by: Andy Nichols <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 11 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 2 | ||||
-rw-r--r-- | src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp | 2 | ||||
-rw-r--r-- | src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h | 2 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 105 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h | 34 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgrenderer_p.h | 4 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgcontext_p.h | 8 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgdefaultrendercontext.cpp | 4 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgdefaultrendercontext_p.h | 2 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgrhilayer.cpp | 5 |
11 files changed, 122 insertions, 57 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 7fe5325f5b..02fc8a959b 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -582,7 +582,10 @@ void QQuickWindowPrivate::syncSceneGraph() QSGRootNode *rootNode = new QSGRootNode; rootNode->appendChildNode(QQuickItemPrivate::get(contentItem)->itemNode()); - renderer = context->createRenderer(); + static const bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER"); + static const QSGRenderContext::RenderMode renderMode = useDepth ? QSGRenderContext::RenderMode2D + : QSGRenderContext::RenderMode2DNoDepthBuffer; + renderer = context->createRenderer(renderMode); renderer->setRootNode(rootNode); } @@ -597,7 +600,7 @@ void QQuickWindowPrivate::syncSceneGraph() mode |= QSGAbstractRenderer::ClearColorBuffer; renderer->setClearMode(mode); - renderer->setCustomRenderMode(customRenderMode); + renderer->setVisualizationMode(visualizationMode); emit q->afterSynchronizing(); runAndClearJobs(&afterSynchronizingJobs); @@ -712,7 +715,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa else context->endNextFrame(renderer); - if (renderer && renderer->hasCustomRenderModeWithContinuousUpdate()) { + if (renderer && renderer->hasVisualizationModeWithContinuousUpdate()) { // For the overdraw visualizer. This update is not urgent so avoid a // direct update() call, this is only here to keep the overdraw // visualization box rotating even when the scene is static. @@ -783,7 +786,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control) contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope; contentItem->setSize(q->size()); - customRenderMode = qgetenv("QSG_VISUALIZE"); + visualizationMode = qgetenv("QSG_VISUALIZE"); renderControl = control; if (renderControl) QQuickRenderControlPrivate::get(renderControl)->window = q; diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index c1a49b69ff..9adbdeec51 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -262,7 +262,7 @@ public: QSGRenderContext *context; QSGRenderer *renderer; - QByteArray customRenderMode; // Default renderer supports "clip", "overdraw", "changes", "batches" and blank. + QByteArray visualizationMode; // Default renderer supports "clip", "overdraw", "changes", "batches" and blank. QSGRenderLoop *windowManager; QQuickRenderControl *renderControl; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp index 4cb016562f..4f61e615f6 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp @@ -151,7 +151,7 @@ QSGTexture *QSGSoftwareRenderContext::createTexture(const QImage &image, uint fl return new QSGSoftwarePixmapTexture(image, flags); } -QSGRenderer *QSGSoftwareRenderContext::createRenderer() +QSGRenderer *QSGSoftwareRenderContext::createRenderer(RenderMode) { return new QSGSoftwareRenderer(this); } diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h index 22f64bc70c..c523bfbb13 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h @@ -74,7 +74,7 @@ public: void invalidate() override; void renderNextFrame(QSGRenderer *renderer) override; QSGTexture *createTexture(const QImage &image, uint flags = CreateTexture_Alpha) const override; - QSGRenderer *createRenderer() override; + QSGRenderer *createRenderer(RenderMode) override; int maxTextureSize() const override; bool m_initialized; diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 6147fa4d6a..065a3df3bf 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -888,15 +888,16 @@ static int qsg_countNodesInBatches(const QDataBuffer<Batch *> &batches) return sum; } -Renderer::Renderer(QSGDefaultRenderContext *ctx) +Renderer::Renderer(QSGDefaultRenderContext *ctx, QSGRenderContext::RenderMode renderMode) : QSGRenderer(ctx) , m_context(ctx) + , m_renderMode(renderMode) , m_opaqueRenderList(64) , m_alphaRenderList(64) , m_nextRenderOrder(0) , m_partialRebuild(false) , m_partialRebuildRoot(nullptr) - , m_useDepthBuffer(true) + , m_forceNoDepthBuffer(false) , m_opaqueBatches(16) , m_alphaBatches(16) , m_batchPool(16) @@ -943,9 +944,6 @@ Renderer::Renderer(QSGDefaultRenderContext *ctx) qDebug("Batch thresholds: nodes: %d vertices: %d", m_batchNodeThreshold, m_batchVertexThreshold); } - - static const bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER"); - m_useDepthBuffer = useDepth; } static void qsg_wipeBuffer(Buffer *buffer) @@ -1216,7 +1214,7 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent) Q_ASSERT(!m_renderNodeElements.contains(rn)); m_renderNodeElements.insert(e->renderNode, e); if (!rn->flags().testFlag(QSGRenderNode::DepthAwareRendering)) - m_useDepthBuffer = false; + m_forceNoDepthBuffer = true; m_rebuild |= FullRebuild; } @@ -1273,11 +1271,8 @@ void Renderer::nodeWasRemoved(Node *node) if (e) { e->removed = true; m_elementsToDelete.add(e); - - if (m_renderNodeElements.isEmpty()) { - static const bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER"); - m_useDepthBuffer = useDepth; - } + if (m_renderNodeElements.isEmpty()) + m_forceNoDepthBuffer = false; } } @@ -1476,7 +1471,7 @@ void Renderer::buildRenderLists(QSGNode *node) Q_ASSERT(e); bool opaque = gn->inheritedOpacity() > OPAQUE_LIMIT && !(gn->activeMaterial()->flags() & QSGMaterial::Blending); - if (opaque && m_useDepthBuffer) + if (opaque && useDepthBuffer()) m_opaqueRenderList << e; else m_alphaRenderList << e; @@ -1906,7 +1901,7 @@ void Renderer::uploadMergedElement(Element *e, int vaOffset, char **vertexData, } } - if (m_useDepthBuffer) { + if (useDepthBuffer()) { float *vzorder = (float *) *zData; float zorder = 1.0f - e->order * m_zRange; for (int i=0; i<vCount; ++i) @@ -2066,7 +2061,7 @@ void Renderer::uploadBatch(Batch *b) int ibufferSize = 0; if (b->merged) { ibufferSize = b->indexCount * mergedIndexElemSize(); - if (m_useDepthBuffer) + if (useDepthBuffer()) bufferSize += b->vertexCount * sizeof(float); } else { ibufferSize = unmergedIndexSize; @@ -2088,7 +2083,7 @@ void Renderer::uploadBatch(Batch *b) char *zData = vertexData + b->vertexCount * g->sizeOfVertex(); char *indexData = separateIndexBuffer ? b->ibo.data - : zData + (int(m_useDepthBuffer) * b->vertexCount * sizeof(float)); + : zData + (int(useDepthBuffer()) * b->vertexCount * sizeof(float)); quint16 iOffset16 = 0; quint32 iOffset32 = 0; @@ -2189,7 +2184,7 @@ void Renderer::uploadBatch(Batch *b) dump << ") "; offset += attr.tupleSize * size_of_type(attr.type); } - if (b->merged && m_useDepthBuffer) { + if (b->merged && useDepthBuffer()) { float zorder = ((float*)(b->vbo.data + b->vertexCount * g->sizeOfVertex()))[i]; dump << " Z:(" << zorder << ")"; } @@ -2609,7 +2604,7 @@ static inline bool needsBlendConstant(QRhiGraphicsPipeline::BlendFactor f) // available from Batch/Element at this stage. Bookkeeping of state in the // renderpass is done via m_pstate. -bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms) +bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms, bool depthPostPass) { // In unmerged batches the srbs in the elements are all compatible // layout-wise. Note the key's == and qHash implementations: the rp desc and @@ -2622,7 +2617,10 @@ bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms) // See if there is an existing, matching pipeline state object. auto it = m_shaderManager->pipelineCache.constFind(k); if (it != m_shaderManager->pipelineCache.constEnd()) { - e->ps = *it; + if (depthPostPass) + e->depthPostPassPs = *it; + else + e->ps = *it; return true; } @@ -2678,7 +2676,10 @@ bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms) } m_shaderManager->pipelineCache.insert(k, ps); - e->ps = ps; + if (depthPostPass) + e->depthPostPassPs = ps; + else + e->ps = ps; return true; } @@ -2960,7 +2961,7 @@ bool Renderer::prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *rende updateClipState(gn->clipList(), batch); const QSGGeometry *g = gn->geometry(); - ShaderManager::Shader *sms = m_useDepthBuffer ? m_shaderManager->prepareMaterial(material, g) + ShaderManager::Shader *sms = useDepthBuffer() ? m_shaderManager->prepareMaterial(material, g) : m_shaderManager->prepareMaterialNoRewrite(material, g); if (!sms) return false; @@ -3033,6 +3034,13 @@ bool Renderer::prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *rende if (!hasPipeline) return false; + if (m_renderMode == QSGRenderContext::RenderMode3D) { + m_gstateStack.push(m_gstate); + setStateForDepthPostPass(); + ensurePipelineState(e, sms, true); + m_gstate = m_gstateStack.pop(); + } + batch->ubufDataValid = true; m_currentMaterial = material; @@ -3068,7 +3076,7 @@ void Renderer::checkLineWidth(QSGGeometry *g) } } -void Renderer::renderMergedBatch(PreparedRenderBatch *renderBatch) +void Renderer::renderMergedBatch(PreparedRenderBatch *renderBatch, bool depthPostPass) { const Batch *batch = renderBatch->batch; Element *e = batch->first; @@ -3080,7 +3088,7 @@ void Renderer::renderMergedBatch(PreparedRenderBatch *renderBatch) enqueueStencilDraw(batch); QRhiCommandBuffer *cb = commandBuffer(); - setGraphicsPipeline(cb, batch, e); + setGraphicsPipeline(cb, batch, e, depthPostPass); for (int i = 0, ie = batch->drawSets.size(); i != ie; ++i) { const DrawSet &draw = batch->drawSets.at(i); @@ -3088,7 +3096,7 @@ void Renderer::renderMergedBatch(PreparedRenderBatch *renderBatch) { batch->vbo.buf, quint32(draw.vertices) }, { batch->vbo.buf, quint32(draw.zorders) } }; - cb->setVertexInput(VERTEX_BUFFER_BINDING, m_useDepthBuffer ? 2 : 1, vbufBindings, + cb->setVertexInput(VERTEX_BUFFER_BINDING, useDepthBuffer() ? 2 : 1, vbufBindings, batch->ibo.buf, draw.indices, m_uint32IndexForRhi ? QRhiCommandBuffer::IndexUInt32 : QRhiCommandBuffer::IndexUInt16); cb->drawIndexed(draw.indexCount); @@ -3183,6 +3191,7 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren int ubufOffset = 0; QRhiGraphicsPipeline *ps = nullptr; + QRhiGraphicsPipeline *depthPostPassPs = nullptr; e = batch->first; while (e) { gn = e->node; @@ -3192,7 +3201,7 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren m_current_projection_matrix = projectionMatrix(); m_current_projection_matrix_native_ndc = projectionMatrixWithNativeNDC(); - if (m_useDepthBuffer) { + if (useDepthBuffer()) { m_current_projection_matrix(2, 2) = m_zRange; m_current_projection_matrix(2, 3) = 1.0f - e->order * m_zRange; } @@ -3231,8 +3240,17 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren return false; } ps = e->ps; + if (m_renderMode == QSGRenderContext::RenderMode3D) { + m_gstateStack.push(m_gstate); + setStateForDepthPostPass(); + ensurePipelineState(e, sms, true); + m_gstate = m_gstateStack.pop(); + depthPostPassPs = e->depthPostPassPs; + } } else { e->ps = ps; + if (m_renderMode == QSGRenderContext::RenderMode3D) + e->depthPostPassPs = depthPostPassPs; } // We don't need to bother with asking each node for its material as they @@ -3256,7 +3274,7 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren return true; } -void Renderer::renderUnmergedBatch(PreparedRenderBatch *renderBatch) +void Renderer::renderUnmergedBatch(PreparedRenderBatch *renderBatch, bool depthPostPass) { const Batch *batch = renderBatch->batch; Element *e = batch->first; @@ -3275,7 +3293,7 @@ void Renderer::renderUnmergedBatch(PreparedRenderBatch *renderBatch) checkLineWidth(g); const int effectiveIndexSize = m_uint32IndexForRhi ? sizeof(quint32) : g->sizeOfIndex(); - setGraphicsPipeline(cb, batch, e); + setGraphicsPipeline(cb, batch, e, depthPostPass); const QRhiCommandBuffer::VertexInput vbufBinding(batch->vbo.buf, vOffset); if (g->indexCount()) { @@ -3296,9 +3314,9 @@ void Renderer::renderUnmergedBatch(PreparedRenderBatch *renderBatch) } } -void Renderer::setGraphicsPipeline(QRhiCommandBuffer *cb, const Batch *batch, Element *e) +void Renderer::setGraphicsPipeline(QRhiCommandBuffer *cb, const Batch *batch, Element *e, bool depthPostPass) { - cb->setGraphicsPipeline(e->ps); + cb->setGraphicsPipeline(depthPostPass ? e->depthPostPassPs : e->ps); if (!m_pstate.viewportSet) { m_pstate.viewportSet = true; @@ -3553,8 +3571,8 @@ void Renderer::prepareRenderPass(RenderPassContext *ctx) m_pstate.viewportSet = false; m_pstate.scissorSet = false; - m_gstate.depthTest = m_useDepthBuffer; - m_gstate.depthWrite = m_useDepthBuffer; + m_gstate.depthTest = useDepthBuffer(); + m_gstate.depthWrite = useDepthBuffer(); m_gstate.depthFunc = QRhiGraphicsPipeline::Less; m_gstate.blending = false; @@ -3586,10 +3604,18 @@ void Renderer::prepareRenderPass(RenderPassContext *ctx) m_gstate.blending = true; // factors never change, always set for premultiplied alpha based blending - // depth test stays enabled (if m_useDepthBuffer, that is) but no need + // depth test stays enabled (if useDepthBuffer(), that is) but no need // to write out depth from the transparent (back-to-front) pass m_gstate.depthWrite = false; + // special case: the 3D plane mode tests against the depth buffer, but does + // not write (and all batches are alpha because this render mode evaluates + // to useDepthBuffer()==false) + if (m_renderMode == QSGRenderContext::RenderMode3D) { + Q_ASSERT(m_opaqueBatches.isEmpty()); + m_gstate.depthTest = true; + } + ctx->alphaRenderBatches.clear(); if (Q_LIKELY(renderAlpha)) { for (int i = 0, ie = m_alphaBatches.size(); i != ie; ++i) { @@ -3662,6 +3688,17 @@ void Renderer::recordRenderPass(RenderPassContext *ctx) renderUnmergedBatch(renderBatch); } + if (m_renderMode == QSGRenderContext::RenderMode3D) { + // depth post-pass + for (int i = 0, ie = ctx->alphaRenderBatches.count(); i != ie; ++i) { + PreparedRenderBatch *renderBatch = &ctx->alphaRenderBatches[i]; + if (renderBatch->batch->merged) + renderMergedBatch(renderBatch, true); + else if (!renderBatch->batch->isRenderNode) // rendernodes are skipped here for now + renderUnmergedBatch(renderBatch, true); + } + } + if (m_currentShader) setActiveRhiShader(nullptr, nullptr); @@ -3770,7 +3807,7 @@ void Renderer::renderRhiRenderNode(const Batch *batch) QSGRenderNodePrivate *rd = QSGRenderNodePrivate::get(e->renderNode); QMatrix4x4 pm = projectionMatrix(); - if (m_useDepthBuffer) { + if (useDepthBuffer()) { pm(2, 2) = m_zRange; pm(2, 3) = 1.0f - e->order * m_zRange; } @@ -3811,7 +3848,7 @@ void Renderer::renderRhiRenderNode(const Batch *batch) // which is in renderpass recording state. } -void Renderer::setCustomRenderMode(const QByteArray &mode) +void Renderer::setVisualizationMode(const QByteArray &mode) { if (mode.isEmpty()) m_visualizer->setMode(Visualizer::VisualizeNothing); @@ -3825,7 +3862,7 @@ void Renderer::setCustomRenderMode(const QByteArray &mode) m_visualizer->setMode(Visualizer::VisualizeChanges); } -bool Renderer::hasCustomRenderModeWithContinuousUpdate() const +bool Renderer::hasVisualizationModeWithContinuousUpdate() const { return m_visualizer->mode() == Visualizer::VisualizeOverdraw; } diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index bafcb7ebde..38e0e84e39 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -336,6 +336,7 @@ struct Element { int order = 0; QRhiShaderResourceBindings *srb = nullptr; QRhiGraphicsPipeline *ps = nullptr; + QRhiGraphicsPipeline *depthPostPassPs = nullptr; uint boundsComputed : 1; uint boundsOutsideFloatRange : 1; @@ -752,7 +753,7 @@ protected: class Q_QUICK_PRIVATE_EXPORT Renderer : public QSGRenderer { public: - Renderer(QSGDefaultRenderContext *); + Renderer(QSGDefaultRenderContext *ctx, QSGRenderContext::RenderMode renderMode = QSGRenderContext::RenderMode2D); ~Renderer(); protected: @@ -821,7 +822,7 @@ private: void uploadBatch(Batch *b); void uploadMergedElement(Element *e, int vaOffset, char **vertexData, char **zData, char **indexData, void *iBasePtr, int *indexCount); - bool ensurePipelineState(Element *e, const ShaderManager::Shader *sms); + bool ensurePipelineState(Element *e, const ShaderManager::Shader *sms, bool depthPostPass = false); QRhiTexture *dummyTexture(); void updateMaterialDynamicData(ShaderManager::Shader *sms, QSGMaterialShader::RenderState &renderState, QSGMaterial *material, ShaderManager::ShaderResourceBindingList *bindings, @@ -830,10 +831,10 @@ private: QSGMaterial *material, Batch *batch, bool *gstateChanged); void checkLineWidth(QSGGeometry *g); bool prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *renderBatch); - void renderMergedBatch(PreparedRenderBatch *renderBatch); + void renderMergedBatch(PreparedRenderBatch *renderBatch, bool depthPostPass = false); bool prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *renderBatch); - void renderUnmergedBatch(PreparedRenderBatch *renderBatch); - void setGraphicsPipeline(QRhiCommandBuffer *cb, const Batch *batch, Element *e); + void renderUnmergedBatch(PreparedRenderBatch *renderBatch, bool depthPostPass = false); + void setGraphicsPipeline(QRhiCommandBuffer *cb, const Batch *batch, Element *e, bool depthPostPass = false); void renderMergedBatch(const Batch *batch); // GL void renderUnmergedBatch(const Batch *batch); // GL ClipState::ClipType updateStencilClip(const QSGClipNode *clip); @@ -863,20 +864,20 @@ private: inline Batch *newBatch(); void invalidateAndRecycleBatch(Batch *b); - void setCustomRenderMode(const QByteArray &mode) override; - bool hasCustomRenderModeWithContinuousUpdate() const override; + void setVisualizationMode(const QByteArray &mode) override; + bool hasVisualizationModeWithContinuousUpdate() const override; void invalidatePipelineCacheDependency(QRhiRenderPassDescriptor *rpDesc) override; QSGDefaultRenderContext *m_context; + QSGRenderContext::RenderMode m_renderMode; QSet<Node *> m_taggedRoots; QDataBuffer<Element *> m_opaqueRenderList; QDataBuffer<Element *> m_alphaRenderList; int m_nextRenderOrder; bool m_partialRebuild; QSGNode *m_partialRebuildRoot; - - bool m_useDepthBuffer; + bool m_forceNoDepthBuffer; QHash<QSGRenderNode *, RenderNodeElement *> m_renderNodeElements; QDataBuffer<Batch *> m_opaqueBatches; @@ -932,6 +933,8 @@ private: } m_stencilClipCommon; inline int mergedIndexElemSize() const; + inline bool useDepthBuffer() const; + inline void setStateForDepthPostPass(); }; Batch *Renderer::newBatch() @@ -959,6 +962,19 @@ int Renderer::mergedIndexElemSize() const return m_uint32IndexForRhi ? sizeof(quint32) : sizeof(quint16); } +bool Renderer::useDepthBuffer() const +{ + return !m_forceNoDepthBuffer && m_renderMode == QSGRenderContext::RenderMode2D; +} + +void Renderer::setStateForDepthPostPass() +{ + m_gstate.colorWrite = {}; + m_gstate.depthWrite = true; + m_gstate.depthTest = true; + m_gstate.depthFunc = QRhiGraphicsPipeline::Less; +} + void Renderer::StencilClipCommonData::reset() { delete replacePs; diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h index b597002967..0c9a424abc 100644 --- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h @@ -94,8 +94,8 @@ public: QSGNodeUpdater *nodeUpdater() const; void setNodeUpdater(QSGNodeUpdater *updater); inline QSGMaterialShader::RenderState state(QSGMaterialShader::RenderState::DirtyStates dirty) const; - virtual void setCustomRenderMode(const QByteArray &) { } - virtual bool hasCustomRenderModeWithContinuousUpdate() const { return false; } + virtual void setVisualizationMode(const QByteArray &) { } + virtual bool hasVisualizationModeWithContinuousUpdate() const { return false; } virtual void releaseCachedResources() { } virtual void invalidatePipelineCacheDependency(QRhiRenderPassDescriptor *) { } diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index 1696ee9cba..934753598b 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -155,6 +155,12 @@ class Q_QUICK_PRIVATE_EXPORT QSGRenderContext : public QObject { Q_OBJECT public: + enum RenderMode { + RenderMode2D, + RenderMode2DNoDepthBuffer, + RenderMode3D + }; + enum CreateTextureFlags { CreateTexture_Alpha = 0x1, CreateTexture_Atlas = 0x2, @@ -195,7 +201,7 @@ public: QSGTexture *textureForFactory(QQuickTextureFactory *factory, QQuickWindow *window); virtual QSGTexture *createTexture(const QImage &image, uint flags = CreateTexture_Alpha) const = 0; - virtual QSGRenderer *createRenderer() = 0; + virtual QSGRenderer *createRenderer(RenderMode renderMode = RenderMode2D) = 0; virtual QSGTexture *compressedTextureForFactory(const QSGCompressedTextureFactory *) const; virtual void setAttachToGraphicsContext(bool attach) { Q_UNUSED(attach); } diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp index 8faa4b8433..e3071c78cc 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp +++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp @@ -281,9 +281,9 @@ QSGTexture *QSGDefaultRenderContext::createTexture(const QImage &image, uint fla return texture; } -QSGRenderer *QSGDefaultRenderContext::createRenderer() +QSGRenderer *QSGDefaultRenderContext::createRenderer(RenderMode renderMode) { - return new QSGBatchRenderer::Renderer(this); + return new QSGBatchRenderer::Renderer(this, renderMode); } QSGTexture *QSGDefaultRenderContext::compressedTextureForFactory(const QSGCompressedTextureFactory *factory) const diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h index d5d2af35ff..ac55fe4b6e 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h +++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h @@ -125,7 +125,7 @@ public: QSGDepthStencilBufferManager *depthStencilBufferManager(); QSGTexture *createTexture(const QImage &image, uint flags) const override; - QSGRenderer *createRenderer() override; + QSGRenderer *createRenderer(RenderMode renderMode = RenderMode2D) override; QSGTexture *compressedTextureForFactory(const QSGCompressedTextureFactory *factory) const override; virtual void initializeRhiShader(QSGMaterialShader *shader, QShader::Variant shaderVariant); diff --git a/src/quick/scenegraph/qsgrhilayer.cpp b/src/quick/scenegraph/qsgrhilayer.cpp index 459c1872a3..d70f5e97ab 100644 --- a/src/quick/scenegraph/qsgrhilayer.cpp +++ b/src/quick/scenegraph/qsgrhilayer.cpp @@ -352,7 +352,10 @@ void QSGRhiLayer::grab() return; if (!m_renderer) { - m_renderer = m_context->createRenderer(); + static const bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER"); + static const QSGRenderContext::RenderMode renderMode = useDepth ? QSGRenderContext::RenderMode2D + : QSGRenderContext::RenderMode2DNoDepthBuffer; + m_renderer = m_context->createRenderer(renderMode); connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture())); } m_renderer->setRootNode(static_cast<QSGRootNode *>(root)); |