aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLaszlo Agocs <[email protected]>2020-06-05 18:10:30 +0200
committerLaszlo Agocs <[email protected]>2020-06-09 21:13:21 +0200
commit22d8db1e115b120ce2f62896eb7fea452348941e (patch)
treebeb189edc62ce1a5bee433827415f0dd95fe7272 /src
parent84b53c165e9d492a547c04499450007d2c293bc8 (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.cpp11
-rw-r--r--src/quick/items/qquickwindow_p.h2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarecontext_p.h2
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp105
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h34
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h4
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h8
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp4
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext_p.h2
-rw-r--r--src/quick/scenegraph/qsgrhilayer.cpp5
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));