diff options
Diffstat (limited to 'src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp')
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 236 |
1 files changed, 186 insertions, 50 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index cbf459555f..6c084ec441 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -22,7 +22,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_DEBUG -Q_QUICK_PRIVATE_EXPORT bool qsg_test_and_clear_material_failure(); +Q_QUICK_EXPORT bool qsg_test_and_clear_material_failure(); #endif int qt_sg_envInt(const char *name, int defaultValue); @@ -201,13 +201,22 @@ QRhiGraphicsPipeline::Topology qsg_topology(int geomDrawMode) return topology; } +void qsg_setMultiViewFlagsOnMaterial(QSGMaterial *material, int multiViewCount) +{ + material->setFlag(QSGMaterial::MultiView2, multiViewCount == 2); + material->setFlag(QSGMaterial::MultiView3, multiViewCount == 3); + material->setFlag(QSGMaterial::MultiView4, multiViewCount == 4); +} + ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material, const QSGGeometry *geometry, - QSGRendererInterface::RenderMode renderMode) + QSGRendererInterface::RenderMode renderMode, + int multiViewCount) { - QSGMaterialType *type = material->type(); + qsg_setMultiViewFlagsOnMaterial(material, multiViewCount); - ShaderKey key = qMakePair(type, renderMode); + QSGMaterialType *type = material->type(); + ShaderKey key = { type, renderMode, multiViewCount }; Shader *shader = rewrittenShaders.value(key, nullptr); if (shader) return shader; @@ -219,8 +228,8 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material, shader->inputLayout = calculateVertexInputLayout(s, geometry, true); QSGMaterialShaderPrivate *sD = QSGMaterialShaderPrivate::get(s); shader->stages = { - { QRhiGraphicsShaderStage::Vertex, sD->shader(QShader::VertexStage), QShader::BatchableVertexShader }, - { QRhiGraphicsShaderStage::Fragment, sD->shader(QShader::FragmentStage) } + { QRhiShaderStage::Vertex, sD->shader(QShader::VertexStage), QShader::BatchableVertexShader }, + { QRhiShaderStage::Fragment, sD->shader(QShader::FragmentStage) } }; shader->lastOpacity = 0; @@ -231,11 +240,13 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material, ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *material, const QSGGeometry *geometry, - QSGRendererInterface::RenderMode renderMode) + QSGRendererInterface::RenderMode renderMode, + int multiViewCount) { - QSGMaterialType *type = material->type(); + qsg_setMultiViewFlagsOnMaterial(material, multiViewCount); - ShaderKey key = qMakePair(type, renderMode); + QSGMaterialType *type = material->type(); + ShaderKey key = { type, renderMode, multiViewCount }; Shader *shader = stockShaders.value(key, nullptr); if (shader) return shader; @@ -247,8 +258,8 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate shader->inputLayout = calculateVertexInputLayout(s, geometry, false); QSGMaterialShaderPrivate *sD = QSGMaterialShaderPrivate::get(s); shader->stages = { - { QRhiGraphicsShaderStage::Vertex, sD->shader(QShader::VertexStage) }, - { QRhiGraphicsShaderStage::Fragment, sD->shader(QShader::FragmentStage) } + { QRhiShaderStage::Vertex, sD->shader(QShader::VertexStage) }, + { QRhiShaderStage::Fragment, sD->shader(QShader::FragmentStage) } }; shader->lastOpacity = 0; @@ -696,7 +707,7 @@ BatchCompatibility Batch::isMaterialCompatible(Element *e) const QSGMaterial *m = e->node->activeMaterial(); QSGMaterial *nm = n->node->activeMaterial(); - return (nm->type() == m->type() && nm->compare(m) == 0) + return (nm->type() == m->type() && nm->viewCount() == m->viewCount() && nm->compare(m) == 0) ? BatchIsCompatible : BatchBreaksOnCompare; } @@ -839,6 +850,8 @@ Renderer::Renderer(QSGDefaultRenderContext *ctx, QSGRendererInterface::RenderMod , m_elementsToDelete(64) , m_tmpAlphaElements(16) , m_tmpOpaqueElements(16) + , m_vboPool(16) + , m_iboPool(16) , m_rebuild(FullRebuild) , m_zRange(0) #if defined(QSGBATCHRENDERER_INVALIDATE_WEDGED_NODES) @@ -915,6 +928,10 @@ Renderer::~Renderer() qsg_wipeBatch(m_alphaBatches.at(i)); for (int i = 0; i < m_batchPool.size(); ++i) qsg_wipeBatch(m_batchPool.at(i)); + for (int i = 0; i < m_vboPool.size(); ++i) + delete m_vboPool.at(i); + for (int i = 0; i < m_iboPool.size(); ++i) + delete m_iboPool.at(i); } for (Node *n : std::as_const(m_nodes)) { @@ -960,12 +977,28 @@ void Renderer::releaseCachedResources() m_rhi->releaseCachedResources(); - m_vertexUploadPool.resize(0); - m_indexUploadPool.resize(0); + m_vertexUploadPool.shrink(0); + m_vertexUploadPool.reset(); + m_indexUploadPool.shrink(0); + m_indexUploadPool.reset(); + + for (int i = 0; i < m_vboPool.size(); ++i) + delete m_vboPool.at(i); + m_vboPool.reset(); + + for (int i = 0; i < m_iboPool.size(); ++i) + delete m_iboPool.at(i); + m_iboPool.reset(); } void Renderer::invalidateAndRecycleBatch(Batch *b) { + if (b->vbo.buf != nullptr) + m_vboPool.add(b->vbo.buf); + if (b->ibo.buf != nullptr) + m_iboPool.add(b->ibo.buf); + b->vbo.buf = nullptr; + b->ibo.buf = nullptr; b->invalidate(); for (int i=0; i<m_batchPool.size(); ++i) if (b == m_batchPool.at(i)) @@ -994,8 +1027,9 @@ void Renderer::unmap(Buffer *buffer, bool isIndexBuf) { // Batches are pooled and reused which means the QRhiBuffer will be // still valid in a recycled Batch. We only hit the newBuffer() path - // for brand new Batches. - if (!buffer->buf) { + // when there are no buffers to recycle. + QDataBuffer<QRhiBuffer *> *bufferPool = isIndexBuf ? &m_iboPool : &m_vboPool; + if (!buffer->buf && bufferPool->isEmpty()) { buffer->buf = m_rhi->newBuffer(QRhiBuffer::Immutable, isIndexBuf ? QRhiBuffer::IndexBuffer : QRhiBuffer::VertexBuffer, buffer->size); @@ -1005,6 +1039,28 @@ void Renderer::unmap(Buffer *buffer, bool isIndexBuf) buffer->buf = nullptr; } } else { + if (!buffer->buf) { + const quint32 expectedSize = buffer->size; + qsizetype foundBufferIndex = 0; + for (qsizetype i = 0; i < bufferPool->size(); ++i) { + QRhiBuffer *testBuffer = bufferPool->at(i); + if (!buffer->buf + || (testBuffer->size() >= expectedSize && testBuffer->size() < buffer->buf->size()) + || (testBuffer->size() < expectedSize && testBuffer->size() > buffer->buf->size())) { + foundBufferIndex = i; + buffer->buf = testBuffer; + if (buffer->buf->size() == expectedSize) + break; + } + } + + if (foundBufferIndex < bufferPool->size() - 1) { + qSwap(bufferPool->data()[foundBufferIndex], + bufferPool->data()[bufferPool->size() - 1]); + } + bufferPool->pop_back(); + } + bool needsRebuild = false; if (buffer->buf->size() < buffer->size) { buffer->buf->setSize(buffer->size); @@ -1220,8 +1276,13 @@ void Renderer::nodeWasRemoved(Node *node) if (e) { e->removed = true; m_elementsToDelete.add(e); - if (m_renderNodeElements.isEmpty()) + if (m_renderNodeElements.isEmpty()) { m_forceNoDepthBuffer = false; + // Must have a full rebuild given useDepthBuffer() now returns + // a different value than before, meaning there can once again + // be an opaque pass. + m_rebuild |= FullRebuild; + } if (e->batch != nullptr) e->batch->needsPurge = true; @@ -1680,6 +1741,7 @@ void Renderer::prepareOpaqueBatches() && gni->geometry()->attributes() == gnj->geometry()->attributes() && gni->inheritedOpacity() == gnj->inheritedOpacity() && gni->activeMaterial()->type() == gnj->activeMaterial()->type() + && gni->activeMaterial()->viewCount() == gnj->activeMaterial()->viewCount() && gni->activeMaterial()->compare(gnj->activeMaterial()) == 0) { ej->batch = batch; next->nextInBatch = ej; @@ -1791,6 +1853,7 @@ void Renderer::prepareAlphaBatches() && gni->geometry()->attributes() == gnj->geometry()->attributes() && gni->inheritedOpacity() == gnj->inheritedOpacity() && gni->activeMaterial()->type() == gnj->activeMaterial()->type() + && gni->activeMaterial()->viewCount() == gnj->activeMaterial()->viewCount() && gni->activeMaterial()->compare(gnj->activeMaterial()) == 0) { if (!overlapBounds.intersects(ej->bounds) || !checkOverlap(i+1, j - 1, ej->bounds)) { ej->batch = batch; @@ -1994,7 +2057,7 @@ void Renderer::uploadBatch(Batch *b) bool canMerge = (g->drawingMode() == QSGGeometry::DrawTriangles || g->drawingMode() == QSGGeometry::DrawTriangleStrip || g->drawingMode() == QSGGeometry::DrawLines || g->drawingMode() == QSGGeometry::DrawPoints) && b->positionAttribute >= 0 - && g->indexType() == QSGGeometry::UnsignedShortType + && (g->indexType() == QSGGeometry::UnsignedShortType && g->indexCount() > 0) && (flags & (QSGMaterial::NoBatching | QSGMaterial_FullMatrix)) == 0 && ((flags & QSGMaterial::RequiresFullMatrixExceptTranslate) == 0 || b->isTranslateOnlyToRoot()) && b->isSafeToBatch(); @@ -2243,8 +2306,10 @@ QRhiGraphicsPipeline *Renderer::buildStencilPipeline(const Batch *batch, bool fi ps->setTopology(m_stencilClipCommon.topology); - ps->setShaderStages({ QRhiGraphicsShaderStage(QRhiGraphicsShaderStage::Vertex, m_stencilClipCommon.vs), - QRhiGraphicsShaderStage(QRhiGraphicsShaderStage::Fragment, m_stencilClipCommon.fs) }); + ps->setMultiViewCount(renderTarget().multiViewCount); + + ps->setShaderStages({ QRhiShaderStage(QRhiShaderStage::Vertex, m_stencilClipCommon.vs), + QRhiShaderStage(QRhiShaderStage::Fragment, m_stencilClipCommon.fs) }); ps->setVertexInputLayout(m_stencilClipCommon.inputLayout); ps->setShaderResourceBindings(batch->stencilClipState.srb); // use something, it just needs to be layout-compatible ps->setRenderPassDescriptor(renderTarget().rpDesc); @@ -2291,7 +2356,7 @@ void Renderer::updateClipState(const QSGClipNode *clipList, Batch *batch) const quint32 StencilClipUbufSize = 64; while (clip) { - QMatrix4x4 m = m_current_projection_matrix_native_ndc; + QMatrix4x4 m = m_current_projection_matrix_native_ndc[0]; // never hit for 3D and so multiview if (clip->matrix()) m *= *clip->matrix(); @@ -2462,7 +2527,7 @@ void Renderer::updateClipState(const QSGClipNode *clipList, Batch *batch) drawCall.ubufOffset = aligned(uOffset, m_ubufAlignment); uOffset = drawCall.ubufOffset + StencilClipUbufSize; - QMatrix4x4 matrixYUpNDC = m_current_projection_matrix; + QMatrix4x4 matrixYUpNDC = m_current_projection_matrix[0]; if (clip->matrix()) matrixYUpNDC *= *clip->matrix(); @@ -2636,6 +2701,7 @@ bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms, ps->setTopology(qsg_topology(m_gstate.drawMode)); ps->setCullMode(m_gstate.cullMode); ps->setPolygonMode(m_gstate.polygonMode); + ps->setMultiViewCount(m_gstate.multiViewCount); QRhiGraphicsPipeline::TargetBlend blend; blend.colorWrite = m_gstate.colorWrite; @@ -2644,6 +2710,8 @@ bool Renderer::ensurePipelineState(Element *e, const ShaderManager::Shader *sms, blend.dstColor = m_gstate.dstColor; blend.srcAlpha = m_gstate.srcAlpha; blend.dstAlpha = m_gstate.dstAlpha; + blend.opColor = m_gstate.opColor; + blend.opAlpha = m_gstate.opAlpha; ps->setTargetBlends({ blend }); ps->setDepthTest(m_gstate.depthTest); @@ -2775,6 +2843,7 @@ static void rendererToMaterialGraphicsState(QSGMaterialShader::GraphicsPipelineS // the enum values should match, sanity check it Q_ASSERT(int(QSGMaterialShader::GraphicsPipelineState::OneMinusSrc1Alpha) == int(QRhiGraphicsPipeline::OneMinusSrc1Alpha)); + Q_ASSERT(int(QSGMaterialShader::GraphicsPipelineState::BlendOpMax) == int(QRhiGraphicsPipeline::Max)); Q_ASSERT(int(QSGMaterialShader::GraphicsPipelineState::A) == int(QRhiGraphicsPipeline::A)); Q_ASSERT(int(QSGMaterialShader::GraphicsPipelineState::CullBack) == int(QRhiGraphicsPipeline::Back)); Q_ASSERT(int(QSGMaterialShader::GraphicsPipelineState::Line) == int(QRhiGraphicsPipeline::Line)); @@ -2792,6 +2861,9 @@ static void rendererToMaterialGraphicsState(QSGMaterialShader::GraphicsPipelineS dst->srcAlpha = QSGMaterialShader::GraphicsPipelineState::BlendFactor(src->srcAlpha); dst->dstAlpha = QSGMaterialShader::GraphicsPipelineState::BlendFactor(src->dstAlpha); + dst->opColor = QSGMaterialShader::GraphicsPipelineState::BlendOp(src->opColor); + dst->opAlpha = QSGMaterialShader::GraphicsPipelineState::BlendOp(src->opAlpha); + dst->colorWrite = QSGMaterialShader::GraphicsPipelineState::ColorMask(int(src->colorWrite)); dst->cullMode = QSGMaterialShader::GraphicsPipelineState::CullMode(src->cullMode); @@ -2811,6 +2883,8 @@ static void materialToRendererGraphicsState(GraphicsState *dst, dst->srcAlpha = dst->srcColor; dst->dstAlpha = dst->dstColor; } + dst->opColor = QRhiGraphicsPipeline::BlendOp(src->opColor); + dst->opAlpha = QRhiGraphicsPipeline::BlendOp(src->opAlpha); dst->colorWrite = QRhiGraphicsPipeline::ColorMask(int(src->colorWrite)); dst->cullMode = QRhiGraphicsPipeline::CullMode(src->cullMode); dst->polygonMode = QRhiGraphicsPipeline::PolygonMode(src->polygonMode); @@ -3079,16 +3153,24 @@ bool Renderer::prepareRenderMergedBatch(Batch *batch, PreparedRenderBatch *rende else m_current_model_view_matrix.setToIdentity(); m_current_determinant = m_current_model_view_matrix.determinant(); - m_current_projection_matrix = projectionMatrix(); - m_current_projection_matrix_native_ndc = projectionMatrixWithNativeNDC(); + + const int viewCount = projectionMatrixCount(); + m_current_projection_matrix.resize(viewCount); + for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex) + m_current_projection_matrix[viewIndex] = projectionMatrix(viewIndex); + + m_current_projection_matrix_native_ndc.resize(projectionMatrixWithNativeNDCCount()); + for (int viewIndex = 0; viewIndex < projectionMatrixWithNativeNDCCount(); ++viewIndex) + m_current_projection_matrix_native_ndc[viewIndex] = projectionMatrixWithNativeNDC(viewIndex); QSGMaterial *material = gn->activeMaterial(); if (m_renderMode != QSGRendererInterface::RenderMode3D) updateClipState(gn->clipList(), batch); const QSGGeometry *g = gn->geometry(); - ShaderManager::Shader *sms = useDepthBuffer() ? m_shaderManager->prepareMaterial(material, g, m_renderMode) - : m_shaderManager->prepareMaterialNoRewrite(material, g, m_renderMode); + const int multiViewCount = renderTarget().multiViewCount; + ShaderManager::Shader *sms = useDepthBuffer() ? m_shaderManager->prepareMaterial(material, g, m_renderMode, multiViewCount) + : m_shaderManager->prepareMaterialNoRewrite(material, g, m_renderMode, multiViewCount); if (!sms) return false; @@ -3252,8 +3334,14 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren batch->uploadedThisFrame = false; } - m_current_projection_matrix = projectionMatrix(); - m_current_projection_matrix_native_ndc = projectionMatrixWithNativeNDC(); + const int viewCount = projectionMatrixCount(); + m_current_projection_matrix.resize(viewCount); + for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex) + m_current_projection_matrix[viewIndex] = projectionMatrix(viewIndex); + + m_current_projection_matrix_native_ndc.resize(projectionMatrixWithNativeNDCCount()); + for (int viewIndex = 0; viewIndex < projectionMatrixWithNativeNDCCount(); ++viewIndex) + m_current_projection_matrix_native_ndc[viewIndex] = projectionMatrixWithNativeNDC(viewIndex); QSGGeometryNode *gn = e->node; if (m_renderMode != QSGRendererInterface::RenderMode3D) @@ -3266,7 +3354,7 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren // unmerged batch since the material (and so the shaders) is the same. QSGGeometry *g = gn->geometry(); QSGMaterial *material = gn->activeMaterial(); - ShaderManager::Shader *sms = m_shaderManager->prepareMaterialNoRewrite(material, g); + ShaderManager::Shader *sms = m_shaderManager->prepareMaterialNoRewrite(material, g, m_renderMode, renderTarget().multiViewCount); if (!sms) return false; @@ -3326,11 +3414,19 @@ bool Renderer::prepareRenderUnmergedBatch(Batch *batch, PreparedRenderBatch *ren m_current_model_view_matrix = rootMatrix * *gn->matrix(); m_current_determinant = m_current_model_view_matrix.determinant(); - m_current_projection_matrix = projectionMatrix(); - m_current_projection_matrix_native_ndc = projectionMatrixWithNativeNDC(); + const int viewCount = projectionMatrixCount(); + m_current_projection_matrix.resize(viewCount); + for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex) + m_current_projection_matrix[viewIndex] = projectionMatrix(viewIndex); + + m_current_projection_matrix_native_ndc.resize(projectionMatrixWithNativeNDCCount()); + for (int viewIndex = 0; viewIndex < projectionMatrixWithNativeNDCCount(); ++viewIndex) + m_current_projection_matrix_native_ndc[viewIndex] = projectionMatrixWithNativeNDC(viewIndex); + if (useDepthBuffer()) { - m_current_projection_matrix(2, 2) = m_zRange; - m_current_projection_matrix(2, 3) = calculateElementZOrder(e, m_zRange); + // this cannot be multiview + m_current_projection_matrix[0](2, 2) = m_zRange; + m_current_projection_matrix[0](2, 3) = calculateElementZOrder(e, m_zRange); } QSGMaterialShader::RenderState renderState = state(QSGMaterialShader::RenderState::DirtyStates(int(dirty))); @@ -3664,14 +3760,14 @@ void Renderer::prepareRenderPass(RenderPassContext *ctx) if (Q_UNLIKELY(debug_render())) ctx->timeSorting = ctx->timer.restart(); - quint32 largestVBO = 0; - quint32 largestIBO = 0; + // Set size to 0, nothing is deallocated, they will "grow" again + // as part of uploadBatch. + m_vertexUploadPool.reset(); + m_indexUploadPool.reset(); if (Q_UNLIKELY(debug_upload())) qDebug("Uploading Opaque Batches:"); for (int i=0; i<m_opaqueBatches.size(); ++i) { Batch *b = m_opaqueBatches.at(i); - largestVBO = qMax(b->vbo.size, largestVBO); - largestIBO = qMax(b->ibo.size, largestIBO); uploadBatch(b); } if (Q_UNLIKELY(debug_render())) ctx->timeUploadOpaque = ctx->timer.restart(); @@ -3680,14 +3776,9 @@ void Renderer::prepareRenderPass(RenderPassContext *ctx) for (int i=0; i<m_alphaBatches.size(); ++i) { Batch *b = m_alphaBatches.at(i); uploadBatch(b); - largestVBO = qMax(b->vbo.size, largestVBO); - largestIBO = qMax(b->ibo.size, largestIBO); } if (Q_UNLIKELY(debug_render())) ctx->timeUploadAlpha = ctx->timer.restart(); - m_vertexUploadPool.resize(largestVBO); - m_indexUploadPool.resize(largestIBO); - if (Q_UNLIKELY(debug_render())) { qDebug().nospace() << "Rendering:" << Qt::endl << " -> Opaque: " << qsg_countNodesInBatches(m_opaqueBatches) << " nodes in " << m_opaqueBatches.size() << " batches..." << Qt::endl @@ -3728,6 +3819,7 @@ void Renderer::prepareRenderPass(RenderPassContext *ctx) m_gstate.stencilTest = false; m_gstate.sampleCount = renderTarget().rt->sampleCount(); + m_gstate.multiViewCount = renderTarget().multiViewCount; ctx->opaqueRenderBatches.clear(); if (Q_LIKELY(renderOpaque)) { @@ -3825,6 +3917,8 @@ void Renderer::recordRenderPass(RenderPassContext *ctx) cb->debugMarkBegin(QByteArrayLiteral("Qt Quick scene render")); for (int i = 0, ie = ctx->opaqueRenderBatches.size(); i != ie; ++i) { + if (i == 0) + cb->debugMarkMsg(QByteArrayLiteral("Qt Quick opaque batches")); PreparedRenderBatch *renderBatch = &ctx->opaqueRenderBatches[i]; if (renderBatch->batch->merged) renderMergedBatch(renderBatch); @@ -3833,6 +3927,12 @@ void Renderer::recordRenderPass(RenderPassContext *ctx) } for (int i = 0, ie = ctx->alphaRenderBatches.size(); i != ie; ++i) { + if (i == 0) { + if (m_renderMode == QSGRendererInterface::RenderMode3D) + cb->debugMarkMsg(QByteArrayLiteral("Qt Quick 2D-in-3D batches")); + else + cb->debugMarkMsg(QByteArrayLiteral("Qt Quick alpha batches")); + } PreparedRenderBatch *renderBatch = &ctx->alphaRenderBatches[i]; if (renderBatch->batch->merged) renderMergedBatch(renderBatch); @@ -3843,8 +3943,15 @@ void Renderer::recordRenderPass(RenderPassContext *ctx) } if (m_renderMode == QSGRendererInterface::RenderMode3D) { - // depth post-pass + // Depth post-pass to fill up the depth buffer in a way that it + // corresponds to what got rendered to the color buffer in the previous + // (alpha) pass. The previous pass cannot enable depth write due to Z + // fighting. Rather, do it separately in a dedicated color-write-off, + // depth-write-on pass. This enables the 3D content drawn afterwards to + // depth test against the 2D items' rendering. for (int i = 0, ie = ctx->alphaRenderBatches.size(); i != ie; ++i) { + if (i == 0) + cb->debugMarkMsg(QByteArrayLiteral("Qt Quick 2D-in-3D depth post-pass")); PreparedRenderBatch *renderBatch = &ctx->alphaRenderBatches[i]; if (renderBatch->batch->merged) renderMergedBatch(renderBatch, true); @@ -3933,7 +4040,8 @@ bool Renderer::prepareRhiRenderNode(Batch *batch, PreparedRenderBatch *renderBat } xform = xform->parent(); } - rd->m_matrix = &matrix; + rd->m_localMatrix = matrix; + rd->m_matrix = &rd->m_localMatrix; QSGNode *opacity = e->renderNode->parent(); rd->m_opacity = 1.0; @@ -3947,10 +4055,15 @@ bool Renderer::prepareRhiRenderNode(Batch *batch, PreparedRenderBatch *renderBat rd->m_rt = renderTarget(); - rd->m_projectionMatrix = projectionMatrix(); + const int viewCount = projectionMatrixCount(); + rd->m_projectionMatrix.resize(viewCount); + for (int viewIndex = 0; viewIndex < viewCount; ++viewIndex) + rd->m_projectionMatrix[viewIndex] = projectionMatrix(viewIndex); + if (useDepthBuffer()) { - rd->m_projectionMatrix(2, 2) = m_zRange; - rd->m_projectionMatrix(2, 3) = calculateElementZOrder(e, m_zRange); + // this cannot be multiview + rd->m_projectionMatrix[0](2, 2) = m_zRange; + rd->m_projectionMatrix[0](2, 3) = calculateElementZOrder(e, m_zRange); } e->renderNode->prepare(); @@ -3970,7 +4083,9 @@ void Renderer::renderRhiRenderNode(const Batch *batch) QSGRenderNodePrivate *rd = QSGRenderNodePrivate::get(e->renderNode); RenderNodeState state; - state.m_projectionMatrix = &rd->m_projectionMatrix; + // Expose only the first matrix through the state object, the rest are + // queriable through the QSGRenderNode getters anyway. + state.m_projectionMatrix = &rd->m_projectionMatrix[0]; const std::array<int, 4> scissor = batch->clipState.scissor.scissor(); state.m_scissorRect = QRect(scissor[0], scissor[1], scissor[2], scissor[3]); state.m_stencilValue = batch->clipState.stencilRef; @@ -4034,6 +4149,8 @@ bool operator==(const GraphicsState &a, const GraphicsState &b) noexcept && a.dstColor == b.dstColor && a.srcAlpha == b.srcAlpha && a.dstAlpha == b.dstAlpha + && a.opColor == b.opColor + && a.opAlpha == b.opAlpha && a.colorWrite == b.colorWrite && a.cullMode == b.cullMode && a.usesScissor == b.usesScissor @@ -4041,7 +4158,8 @@ bool operator==(const GraphicsState &a, const GraphicsState &b) noexcept && a.sampleCount == b.sampleCount && a.drawMode == b.drawMode && a.lineWidth == b.lineWidth - && a.polygonMode == b.polygonMode; + && a.polygonMode == b.polygonMode + && a.multiViewCount == b.multiViewCount; } bool operator!=(const GraphicsState &a, const GraphicsState &b) noexcept @@ -4061,7 +4179,8 @@ size_t qHash(const GraphicsState &s, size_t seed) noexcept + s.cullMode + s.usesScissor + s.stencilTest - + s.sampleCount; + + s.sampleCount + + s.multiViewCount; } bool operator==(const GraphicsPipelineStateKey &a, const GraphicsPipelineStateKey &b) noexcept @@ -4085,6 +4204,23 @@ size_t qHash(const GraphicsPipelineStateKey &k, size_t seed) noexcept ^ k.extra.srbLayoutDescriptionHash; } +bool operator==(const ShaderKey &a, const ShaderKey &b) noexcept +{ + return a.type == b.type + && a.renderMode == b.renderMode + && a.multiViewCount == b.multiViewCount; +} + +bool operator!=(const ShaderKey &a, const ShaderKey &b) noexcept +{ + return !(a == b); +} + +size_t qHash(const ShaderKey &k, size_t seed) noexcept +{ + return qHash(k.type, seed) ^ int(k.renderMode) ^ k.multiViewCount; +} + Visualizer::Visualizer(Renderer *renderer) : m_renderer(renderer), m_visualizeMode(VisualizeNothing) |