5
5
#define protected public
6
6
#define private public
7
7
#include < private/qsgrenderer_p.h>
8
+ #include < private/qsgbatchrenderer_p.h>
8
9
#undef protected
9
10
#undef private
10
11
@@ -302,19 +303,22 @@ class Q_DECL_HIDDEN RhiManager : public DataManager<RhiManager, void>
302
303
}
303
304
304
305
void sync (const QSize &pixelSize, QSGRootNode *rootNode,
305
- const QMatrix4x4 &matrix = {}, QSGRenderer *base = nullptr ,
306
- const QVector2D &dpr = {}) {
306
+ const QMatrix4x4 &matrix = {}, const QMatrix4x4 &baseProjectionMatrix = {} ,
307
+ QSGRenderer *base = nullptr , const QVector2D &dpr = {}) {
307
308
Q_ASSERT (!renderer->rootNode ());
308
309
309
310
if (base) {
310
311
renderer->setDevicePixelRatio (base->devicePixelRatio ());
311
312
renderer->setDeviceRect (base->deviceRect ());
312
313
renderer->setViewportRect (base->viewportRect ());
314
+
315
+ // The m22 and m23 is control the z-order for depth test.
316
+ // If have a base QSGRenderer, we should inherit the depth test from
317
+ // baseProjectionMatrix.
318
+ renderer->setProjectionMatrix (baseProjectionMatrix);
313
319
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
314
- renderer->setProjectionMatrix (base->projectionMatrix (0 ));
315
320
renderer->setProjectionMatrixWithNativeNDC (base->projectionMatrixWithNativeNDC (0 ));
316
321
#else
317
- renderer->setProjectionMatrix (base->projectionMatrix ());
318
322
renderer->setProjectionMatrixWithNativeNDC (base->projectionMatrixWithNativeNDC ());
319
323
#endif
320
324
} else {
@@ -360,28 +364,53 @@ class Q_DECL_HIDDEN RhiManager : public DataManager<RhiManager, void>
360
364
return true ;
361
365
}
362
366
363
- bool render (qreal oldDPR, QRhiCommandBuffer* &oldCB) {
367
+ bool render (qreal oldDPR, QRhiCommandBuffer* &oldCB, bool forceDepthTest = false ) {
364
368
Q_ASSERT (renderer->m_is_rendering );
365
369
renderer->render ();
366
370
renderer->m_is_rendering = false ;
367
371
renderer->m_changed_emitted = false ;
368
372
369
373
context->prepareSync (oldDPR, oldCB, graphicsConfiguration ());
374
+ bool ok = false ;
375
+
376
+ do {
377
+ if (forceDepthTest && Q_LIKELY (isBatchRenderer)) {
378
+ auto batchRenderer = static_cast <QSGBatchRenderer::Renderer*>(renderer);
379
+ if (auto sm = batchRenderer->m_shaderManager ) {
380
+ if (Q_LIKELY (!sm->pipelineCache .isEmpty ())) {
381
+ QVector<std::pair<QRhiGraphicsPipeline*, bool >> tmp;
382
+ tmp.reserve (sm->pipelineCache .size ());
383
+
384
+ for (auto pipeline : std::as_const (sm->pipelineCache )) {
385
+ tmp.append ({pipeline, pipeline->hasDepthTest ()});
386
+ pipeline->setDepthTest (true );
387
+ }
388
+ ok = rhi ()->endOffscreenFrame () == QRhi::FrameOpSuccess;
389
+ Q_ASSERT (tmp.size () == sm->pipelineCache .size ());
390
+ for (auto i : std::as_const (tmp))
391
+ i.first ->setDepthTest (i.second );
392
+
393
+ break ;
394
+ }
395
+ }
396
+ }
397
+
398
+ ok = rhi ()->endOffscreenFrame () == QRhi::FrameOpSuccess;
399
+ } while (false );
370
400
371
- bool ok = rhi ()->endOffscreenFrame () == QRhi::FrameOpSuccess;
372
401
renderer->setRootNode (nullptr );
373
402
374
403
return ok;
375
404
}
376
405
377
- inline bool render (QRhiRenderTarget *rt) {
406
+ inline bool render (QRhiRenderTarget *rt, bool forceDepthTest = false ) {
378
407
qreal oldDPR;
379
408
QRhiCommandBuffer *oldCB;
380
409
381
410
if (!preprocess (rt, oldDPR, oldCB))
382
411
return false ;
383
412
384
- return render (oldDPR, oldCB);
413
+ return render (oldDPR, oldCB, forceDepthTest );
385
414
}
386
415
387
416
private:
@@ -404,7 +433,13 @@ class Q_DECL_HIDDEN RhiManager : public DataManager<RhiManager, void>
404
433
m_rhi->offscreenSurface = fallbackSurface.release ();
405
434
406
435
context = QQuickWindowPrivate::get (owner)->context ;
436
+ // Don't use RenderMode2D, when use this renderer on an exists renderTarget
437
+ // we need to ensure the renderer don't overwrite the depth buffer, because
438
+ // the exists renderTarget is using in the other QSGRenderer, maybe that
439
+ // renderer is using depth test, and the other QSGRenderer is not finished render.
440
+ // For an example: RhiNode to render its content nodes on an exists renderTarget.
407
441
renderer = context->createRenderer (QSGRendererInterface::RenderMode2DNoDepthBuffer);
442
+ isBatchRenderer = dynamic_cast <QSGBatchRenderer::Renderer*>(renderer);
408
443
}
409
444
410
445
~RhiManager () {
@@ -447,6 +482,7 @@ class Q_DECL_HIDDEN RhiManager : public DataManager<RhiManager, void>
447
482
448
483
QSGRenderContext *context;
449
484
QSGRenderer *renderer;
485
+ bool isBatchRenderer = false ;
450
486
451
487
QScopedPointer<Rhi> m_rhi;
452
488
};
@@ -523,6 +559,17 @@ class Q_DECL_HIDDEN RhiNode : public WRenderBufferNode {
523
559
return {0 };
524
560
}
525
561
562
+ // ###: Should disable DepthAwareRendering here, because
563
+ // if enable depth test, Qt will render the opaque nodes first,
564
+ // maybe an opaque node's z-order is higher than the render node,
565
+ // will get the wrong texture when copy texture in RhiNode::render.
566
+ // But the opaque node will be cover the wrong area to the
567
+ // RhiNode::renderTarget after RhiNode::render, but if you using
568
+ // MultiEffect's blur effect for the copied texture, the blur result
569
+ // will contains the opaque node's contains. Fortunately, this kind
570
+ // of problem is not very obvious.
571
+ //
572
+ // We should fix this bug in Qt in the future.
526
573
RenderingFlags flags () const override {
527
574
if (Q_UNLIKELY (!contentNode))
528
575
return BoundedRectRendering | DepthAwareRendering;
@@ -672,7 +719,7 @@ class Q_DECL_HIDDEN RhiNode : public WRenderBufferNode {
672
719
const QPointF sourcePos = renderMatrix.map (m_rect.topLeft ());
673
720
renderData->imageNode ->setRect (QRectF (-(devicePixelRatio - 1 ) * sourcePos, ct->pixelSize ()));
674
721
675
- rhi->sync (texture->data ->pixelSize (), &renderData->rootNode , renderMatrix.inverted (), nullptr ,
722
+ rhi->sync (texture->data ->pixelSize (), &renderData->rootNode , renderMatrix.inverted (), {}, nullptr ,
676
723
{texture->data ->pixelSize ().width () / float (m_rect.width () * devicePixelRatio),
677
724
texture->data ->pixelSize ().height () / float (m_rect.height () * devicePixelRatio)});
678
725
rhi->render (renderData->rt .get ());
@@ -707,6 +754,10 @@ class Q_DECL_HIDDEN RhiNode : public WRenderBufferNode {
707
754
textureRT->setFlags (QRhiTextureRenderTarget::PreserveColorContents
708
755
| QRhiTextureRenderTarget::PreserveDepthStencilContents);
709
756
auto currentRenderer = maybeBufferRenderer ();
757
+ // If the source renderer enable depth test, we should enable depth test also,
758
+ // to ensure the contentNode's z order on RenderMode2DNoDepthBuffer render mode.
759
+ const bool forceDepthTest = currentRenderer->currentBatchRenderer ()
760
+ && currentRenderer->currentBatchRenderer ()->useDepthBuffer ();
710
761
711
762
if (clipList () || inheritedOpacity () < 1.0 ) {
712
763
if (!node)
@@ -736,7 +787,7 @@ class Q_DECL_HIDDEN RhiNode : public WRenderBufferNode {
736
787
737
788
overrideChildNodesTo (contentNode, childContainer);
738
789
739
- rhi->sync (ct->pixelSize (), &node->rootNode , {},
790
+ rhi->sync (ct->pixelSize (), &node->rootNode , {}, * projectionMatrix (),
740
791
currentRenderer ? currentRenderer->currentRenderer () : nullptr );
741
792
qreal oldDPR;
742
793
QRhiCommandBuffer *oldCB;
@@ -753,16 +804,15 @@ class Q_DECL_HIDDEN RhiNode : public WRenderBufferNode {
753
804
}
754
805
}
755
806
756
- rhi->render (oldDPR, oldCB);
807
+ rhi->render (oldDPR, oldCB, forceDepthTest );
757
808
}
758
809
759
810
restoreChildNodesTo (childContainer, contentNode);
760
811
} else {
761
812
node.reset ();
762
-
763
- rhi->sync (ct->pixelSize (), contentNode, *this ->matrix (),
813
+ rhi->sync (ct->pixelSize (), contentNode, *this ->matrix (), *projectionMatrix (),
764
814
currentRenderer ? currentRenderer->currentRenderer () : nullptr );
765
- rhi->render (textureRT);
815
+ rhi->render (textureRT, forceDepthTest );
766
816
}
767
817
768
818
textureRT->setFlags (saveFlags);
0 commit comments