47 QSSG_ASSERT(!data.renderedCameras.isEmpty(),
return);
48 camera = data.renderedCameras[0];
50 const auto &renderedDepthWriteObjects = data.getSortedRenderedDepthWriteObjects(*
camera);
51 const auto &renderedOpaqueDepthPrepassObjects = data.getSortedrenderedOpaqueDepthPrepassObjects(*
camera);
53 QSSG_ASSERT(shadowPassObjects.isEmpty(), shadowPassObjects.clear());
55 for (
const auto &handles : { &renderedDepthWriteObjects, &renderedOpaqueDepthPrepassObjects }) {
56 for (
const auto &handle : *handles) {
57 if (handle.obj->renderableFlags.castsShadows())
58 shadowPassObjects.push_back(handle);
62 globalLights = data.globalLights;
64 enabled = !shadowPassObjects.isEmpty() || !globalLights.isEmpty();
67 shadowMapManager = data.requestShadowMapManager();
69 ps = data.getPipelineState();
70 ps.flags |= { QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled };
73 ps.slopeScaledDepthBias = 1.5f;
75 const auto &sortedOpaqueObjects = data.getSortedOpaqueRenderableObjects(*
camera);
76 const auto &sortedTransparentObjects = data.getSortedTransparentRenderableObjects(*
camera);
77 const auto [casting, receiving] = calculateSortedObjectBounds(sortedOpaqueObjects,
78 sortedTransparentObjects);
79 castingObjectsBox = casting;
80 receivingObjectsBox = receiving;
83 debugCamera = std::make_unique<QSSGRenderCamera>(QSSGRenderGraphObject::Type::OrthographicCamera);
144 QSSG_ASSERT(!data.renderedCameras.isEmpty(),
return);
145 QSSGRenderCamera *camera = data.renderedCameras[0];
147 ps = data.getPipelineState();
148 ps.flags |= { QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled,
149 QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled,
150 QSSGRhiGraphicsPipelineState::Flag::BlendEnabled };
152 reflectionProbes = { data.reflectionProbesView.begin(), data.reflectionProbesView.end() };
153 reflectionMapManager = data.requestReflectionMapManager();
155 const auto &sortedOpaqueObjects = data.getSortedOpaqueRenderableObjects(*camera);
156 const auto &sortedTransparentObjects = data.getSortedTransparentRenderableObjects(*camera);
157 const auto &sortedScreenTextureObjects = data.getSortedScreenTextureRenderableObjects(*camera);
159 QSSG_ASSERT(reflectionPassObjects.isEmpty(), reflectionPassObjects.clear());
163 for (
const auto &handles : { &sortedOpaqueObjects, &sortedTransparentObjects, &sortedScreenTextureObjects }) {
164 for (
const auto &handle : *handles) {
165 if (handle.obj->renderableFlags.testFlag(QSSGRenderableObjectFlag::CastsReflections))
166 reflectionPassObjects.push_back(handle);
236 QSSG_ASSERT(!data.renderedCameras.isEmpty(),
return);
237 QSSGRenderCamera *camera = data.renderedCameras[0];
239 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
240 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
241 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
242 ps = data.getPipelineState();
244 renderedDepthWriteObjects = data.getSortedRenderedDepthWriteObjects(*camera);
245 renderedOpaqueDepthPrepassObjects = data.getSortedrenderedOpaqueDepthPrepassObjects(*camera);
247 cb->debugMarkBegin(QByteArrayLiteral(
"Quick3D prepare Z prepass"));
248 Q_TRACE_SCOPE(QSSG_renderPass, QStringLiteral(
"Quick3D prepare Z prepass"));
249 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
250 active = rhiPrepareDepthPass(rhiCtx.get(),
this, ps, rhiCtx->mainRenderPassDescriptor(), data,
251 renderedDepthWriteObjects, renderedOpaqueDepthPrepassObjects,
252 rhiCtx->mainPassSampleCount(), data.layer.viewCount);
253 data.setZPrePassPrepResult(
active);
255 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"prepare_z_prepass"));
295 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
296 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
298 rhiAoTexture = data.getRenderResult(QSSGFrameData::RenderResult::AoTexture);
299 rhiDepthTexture = data.getRenderResult(QSSGFrameData::RenderResult::DepthTexture);
300 QSSG_ASSERT_X(!data.renderedCameras.isEmpty(),
"Preparing AO pass failed, missing camera",
return);
301 camera = data.renderedCameras[0];
302 QSSG_ASSERT_X((rhiDepthTexture && rhiDepthTexture->isValid()),
"Preparing AO pass failed, missing equired texture(s)",
return);
304 const auto &shaderCache = renderer.contextInterface()->shaderCache();
305 ssaoShaderPipeline = shaderCache->getBuiltInRhiShaders().getRhiSsaoShader(data.layer.viewCount);
306 aoSettings = { data.layer.aoStrength, data.layer.aoDistance, data.layer.aoSoftness, data.layer.aoBias, data.layer.aoSamplerate, data.layer.aoDither };
308 ps = data.getPipelineState();
309 const auto &layerPrepResult = data.layerPrepResult;
310 const bool ready = rhiAoTexture && rhiPrepareAoTexture(rhiCtx.get(), layerPrepResult.textureDimensions(), rhiAoTexture, data.layer.viewCount);
312 if (Q_UNLIKELY(!ready))
313 rhiAoTexture =
nullptr;
365void DepthMapPass::renderPrep(QSSGRenderer &renderer, QSSGLayerRenderData &data)
367 using namespace RenderHelpers;
369 QSSG_ASSERT(!data.renderedCameras.isEmpty(),
return);
370 QSSGRenderCamera *camera = data.renderedCameras[0];
372 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
373 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
374 const auto &layerPrepResult = data.layerPrepResult;
376 ps = data.getPipelineState();
378 if (m_multisampling) {
379 ps.samples = rhiCtx->mainPassSampleCount();
380 rhiDepthTexture = data.getRenderResult(QSSGFrameData::RenderResult::DepthTextureMS);
383 rhiDepthTexture = data.getRenderResult(QSSGFrameData::RenderResult::DepthTexture);
386 if (Q_LIKELY(rhiDepthTexture && rhiPrepareDepthTexture(rhiCtx.get(), layerPrepResult.textureDimensions(), rhiDepthTexture, data.layer.viewCount, ps.samples))) {
387 sortedOpaqueObjects = data.getSortedOpaqueRenderableObjects(*camera);
388 sortedTransparentObjects = data.getSortedTransparentRenderableObjects(*camera);
390 ready = rhiPrepareDepthPass(rhiCtx.get(),
this, ps, rhiDepthTexture->rpDesc, data,
391 sortedOpaqueObjects, sortedTransparentObjects,
392 ps.samples, data.layer.viewCount);
395 if (Q_UNLIKELY(!ready))
396 rhiDepthTexture =
nullptr;
399void DepthMapPass::renderPass(QSSGRenderer &renderer)
401 using namespace RenderHelpers;
419 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
420 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
421 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
422 cb->debugMarkBegin(QByteArrayLiteral(
"Quick3D depth texture"));
424 if (Q_LIKELY(rhiDepthTexture && rhiDepthTexture->isValid())) {
425 bool needsSetViewport =
true;
426 cb->beginPass(rhiDepthTexture->rt, Qt::transparent, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
427 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rhiDepthTexture->rt));
428 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
436 rhiRenderDepthPass(rhiCtx.get(), ps, sortedOpaqueObjects, {}, &needsSetViewport);
438 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
439 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"depth_texture"));
455void NormalPass::renderPrep(QSSGRenderer &renderer, QSSGLayerRenderData &data)
457 using namespace RenderHelpers;
459 QSSG_ASSERT(!data.renderedCameras.isEmpty(),
return);
460 QSSGRenderCamera *camera = data.renderedCameras[0];
462 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
463 QRhi *rhi = rhiCtx->rhi();
465 const auto &layerPrepResult = data.layerPrepResult;
472 ps = data.getPipelineState();
476 sortedOpaqueObjects = data.getSortedOpaqueRenderableObjects(*camera);
480 QSSGShaderFeatures shaderFeatures = data.getShaderFeatures();
481 shaderFeatures.set(QSSGShaderFeatures::Feature::NormalPass,
true);
483 normalTexture = data.getRenderResult(QSSGFrameData::RenderResult::NormalTexture);
485 const QSize size = layerPrepResult.textureDimensions();
486 bool needsBuild =
false;
488 if (!normalTexture->texture) {
489 QRhiTexture::Format format = QRhiTexture::RGBA16F;
490 if (!rhi->isTextureFormatSupported(format)) {
491 qWarning(
"No float formats, not great");
492 format = QRhiTexture::RGBA8;
494 normalTexture->texture = rhiCtx->rhi()->newTexture(format, size, 1, QRhiTexture::RenderTarget);
496 normalTexture->texture->setName(QByteArrayLiteral(
"Normal texture"));
497 }
else if (normalTexture->texture->pixelSize() != size) {
498 normalTexture->texture->setPixelSize(size);
502 if (!normalTexture->depthStencil) {
503 normalTexture->depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, size);
505 }
else if (normalTexture->depthStencil->pixelSize() != size) {
506 normalTexture->depthStencil->setPixelSize(size);
511 if (!normalTexture->texture->create()) {
512 qWarning(
"Failed to build normal texture (size %dx%d, format %d)",
513 size.width(), size.height(),
int(normalTexture->texture->format()));
514 normalTexture->reset();
518 if (!normalTexture->depthStencil->create()) {
519 qWarning(
"Failed to build depth-stencil buffer for normal texture (size %dx%d)",
520 size.width(), size.height());
521 normalTexture->reset();
525 normalTexture->resetRenderTarget();
527 QRhiTextureRenderTargetDescription rtDesc;
528 QRhiColorAttachment colorAttachment(normalTexture->texture);
529 rtDesc.setColorAttachments({ colorAttachment });
530 rtDesc.setDepthStencilBuffer(normalTexture->depthStencil);
532 normalTexture->rt = rhi->newTextureRenderTarget(rtDesc);
533 normalTexture->rt->setName(QByteArrayLiteral(
"Normal texture RT"));
534 normalTexture->rpDesc = normalTexture->rt->newCompatibleRenderPassDescriptor();
535 normalTexture->rt->setRenderPassDescriptor(normalTexture->rpDesc);
536 if (!normalTexture->rt->create()) {
537 qWarning(
"Failed to build render target for normal texture");
538 normalTexture->reset();
543 rhiPrepareNormalPass(rhiCtx.get(),
this, ps, normalTexture->rpDesc, data, sortedOpaqueObjects);
546void NormalPass::renderPass(QSSGRenderer &renderer)
548 using namespace RenderHelpers;
550 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
551 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
552 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
553 cb->debugMarkBegin(QByteArrayLiteral(
"Quick3D normal texture"));
555 if (Q_LIKELY(normalTexture && normalTexture->isValid())) {
556 bool needsSetViewport =
true;
557 cb->beginPass(normalTexture->rt, Qt::transparent, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
558 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(normalTexture->rt));
559 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
561 rhiRenderNormalPass(rhiCtx.get(), ps, sortedOpaqueObjects, &needsSetViewport);
564 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
565 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"normal_texture"));
585 QSSG_ASSERT(!data.renderedCameras.isEmpty(),
return);
586 QSSGRenderCamera *camera = data.renderedCameras[0];
588 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
589 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
590 rhiScreenTexture = data.getRenderResult(QSSGFrameData::RenderResult::ScreenTexture);
591 auto &layer = data.layer;
592 const auto &layerPrepResult = data.layerPrepResult;
593 wantsMips = layerPrepResult.getFlags().requiresMipmapsForScreenTexture();
594 sortedOpaqueObjects = data.getSortedOpaqueRenderableObjects(*camera);
595 ps = data.getPipelineState();
597 ps.viewCount = data.layer.viewCount;
599 if (layer.background == QSSGRenderLayer::Background::Color)
600 clearColor = QColor::fromRgbF(layer.clearColor.x(), layer.clearColor.y(), layer.clearColor.z());
602 if (rhiCtx->rhi()->isFeatureSupported(QRhi::TexelFetch)) {
603 if (layer.background == QSSGRenderLayer::Background::SkyBoxCubeMap && layer.skyBoxCubeMap) {
604 if (!skyboxCubeMapPass)
605 skyboxCubeMapPass = SkyboxCubeMapPass();
607 skyboxCubeMapPass->skipTonemapping =
true;
608 skyboxCubeMapPass->renderPrep(renderer, data);
613 skyboxCubeMapPass->ps.samples = ps.samples;
615 skyboxPass = std::nullopt;
616 }
else if (layer.background == QSSGRenderLayer::Background::SkyBox && layer.lightProbe) {
618 skyboxPass = SkyboxPass();
620 skyboxPass->skipTonemapping =
true;
621 skyboxPass->renderPrep(renderer, data);
623 skyboxPass->ps.samples = ps.samples;
625 skyboxCubeMapPass = std::nullopt;
630 if (Q_LIKELY(rhiScreenTexture && rhiPrepareScreenTexture(rhiCtx.get(), layerPrepResult.textureDimensions(), wantsMips, rhiScreenTexture, layer.viewCount))) {
632 if (skyboxCubeMapPass)
633 skyboxCubeMapPass->rpDesc = rhiScreenTexture->rpDesc;
635 skyboxPass->rpDesc = rhiScreenTexture->rpDesc;
639 shaderFeatures = data.getShaderFeatures();
640 shaderFeatures.disableTonemapping();
641 const auto &sortedOpaqueObjects = data.getSortedOpaqueRenderableObjects(*camera);
642 for (
const auto &handle : sortedOpaqueObjects) {
644 bool recRef = handle.obj->renderableFlags.receivesReflections();
645 handle.obj->renderableFlags.setReceivesReflections(
false);
646 rhiPrepareRenderable(rhiCtx.get(),
this, data, *handle.obj, rhiScreenTexture->rpDesc, &ps, shaderFeatures, 1, data.layer.viewCount);
647 handle.obj->renderableFlags.setReceivesReflections(recRef);
651 if (Q_UNLIKELY(!ready))
652 rhiScreenTexture =
nullptr;
669 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
670 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
671 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
673 cb->debugMarkBegin(QByteArrayLiteral(
"Quick3D screen texture"));
675 if (Q_LIKELY(rhiScreenTexture && rhiScreenTexture->isValid())) {
676 cb->beginPass(rhiScreenTexture->rt, clearColor, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
677 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(rhiScreenTexture->rt));
678 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
680 bool needsSetViewport =
true;
681 for (
const auto &handle : std::as_const(sortedOpaqueObjects))
682 rhiRenderRenderable(rhiCtx.get(), ps, *handle.obj, &needsSetViewport);
684 if (skyboxCubeMapPass)
685 skyboxCubeMapPass->renderPass(renderer);
687 skyboxPass->renderPass(renderer);
689 QRhiResourceUpdateBatch *rub =
nullptr;
691 rub = rhiCtx->rhi()->nextResourceUpdateBatch();
692 rub->generateMips(rhiScreenTexture->texture);
695 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
696 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"screen_texture"));
718 QSSG_ASSERT(!data.renderedCameras.isEmpty(),
return);
719 QSSGRenderCamera *camera = data.renderedCameras[0];
721 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
722 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
723 rhiScreenTexture = data.getRenderResult(QSSGFrameData::RenderResult::ScreenTexture);
724 QSSG_ASSERT_X(rhiScreenTexture && rhiScreenTexture->isValid(),
"Invalid screen texture!",
return);
726 const auto &layer = data.layer;
727 const auto shaderFeatures = data.getShaderFeatures();
728 const bool layerEnableDepthTest = layer.layerFlags.testFlag(QSSGRenderLayer::LayerFlag::EnableDepthTest);
730 QRhiRenderPassDescriptor *mainRpDesc = rhiCtx->mainRenderPassDescriptor();
731 const int samples = rhiCtx->mainPassSampleCount();
732 const int viewCount = data.layer.viewCount;
735 ps = data.getPipelineState();
736 const bool depthTestEnabled = (data.screenMapPass.ps.flags.testFlag(QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled));
737 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled, depthTestEnabled);
738 const bool depthWriteEnabled = (data.screenMapPass.ps.flags.testFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled));
739 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled, depthWriteEnabled);
740 sortedScreenTextureObjects = data.getSortedScreenTextureRenderableObjects(*camera);
741 for (
const auto &handle : std::as_const(sortedScreenTextureObjects)) {
742 QSSGRenderableObject *theObject = handle.obj;
743 const auto depthWriteMode = theObject->depthWriteMode;
744 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled, theObject->renderableFlags.hasTransparency());
745 const bool curDepthWriteEnabled = !(depthWriteMode == QSSGDepthDrawMode::Never || depthWriteMode == QSSGDepthDrawMode::OpaquePrePass
746 || data.isZPrePassActive() || !layerEnableDepthTest);
747 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled, curDepthWriteEnabled);
748 RenderHelpers::rhiPrepareRenderable(rhiCtx.get(),
this, data, *theObject, mainRpDesc, &ps, shaderFeatures, samples, viewCount);
784 QSSGRhiGraphicsPipelineState &ps,
785 QSSGShaderFeatures shaderFeatures,
786 QRhiRenderPassDescriptor *rpDesc,
787 const QSSGRenderableObjectList &sortedOpaqueObjects)
789 const auto &rhiCtx = ctx.rhiContext();
790 QSSG_ASSERT(rpDesc && rhiCtx->rhi()->isRecordingFrame(),
return);
792 const auto &layer = data.layer;
793 const bool layerEnableDepthTest = layer.layerFlags.testFlag(QSSGRenderLayer::LayerFlag::EnableDepthTest);
795 for (
const auto &handle : std::as_const(sortedOpaqueObjects)) {
796 QSSGRenderableObject *theObject = handle.obj;
797 const auto depthWriteMode = theObject->depthWriteMode;
798 const bool curDepthWriteEnabled = !(depthWriteMode == QSSGDepthDrawMode::Never ||
799 depthWriteMode == QSSGDepthDrawMode::OpaquePrePass ||
800 data.isZPrePassActive() || !layerEnableDepthTest);
801 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled, curDepthWriteEnabled);
802 RenderHelpers::rhiPrepareRenderable(rhiCtx.get(), passKey, data, *theObject, rpDesc, &ps, shaderFeatures, ps.samples, ps.viewCount);
821 auto *ctx = renderer.contextInterface();
822 const auto &rhiCtx = ctx->rhiContext();
823 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
824 QSSG_ASSERT(!data.renderedCameras.isEmpty() && data.renderedCameraData.has_value() ,
return);
825 QSSGRenderCamera *camera = data.renderedCameras[0];
827 ps = data.getPipelineState();
828 ps.samples = rhiCtx->mainPassSampleCount();
829 ps.viewCount = data.layer.viewCount;
830 ps.depthFunc = QRhiGraphicsPipeline::LessOrEqual;
831 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
false);
834 sortedOpaqueObjects = data.getSortedOpaqueRenderableObjects(*camera);
835 shaderFeatures = data.getShaderFeatures();
837 QRhiRenderPassDescriptor *mainRpDesc = rhiCtx->mainRenderPassDescriptor();
838 prep(*ctx, data,
this, ps, shaderFeatures, mainRpDesc, sortedOpaqueObjects);
867 QSSGRhiGraphicsPipelineState &ps,
868 QSSGShaderFeatures shaderFeatures,
869 QRhiRenderPassDescriptor *rpDesc,
870 const QSSGRenderableObjectList &sortedTransparentObjects,
873 const auto &rhiCtx = ctx.rhiContext();
874 QSSG_ASSERT(rpDesc && rhiCtx->rhi()->isRecordingFrame(),
return);
876 const bool zPrePassActive = data.isZPrePassActive();
877 for (
const auto &handle : std::as_const(sortedTransparentObjects)) {
878 QSSGRenderableObject *theObject = handle.obj;
879 const auto depthWriteMode = theObject->depthWriteMode;
880 const bool curDepthWriteEnabled = (depthWriteMode == QSSGDepthDrawMode::Always && !zPrePassActive);
881 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled, curDepthWriteEnabled);
882 if (!(theObject->renderableFlags.isCompletelyTransparent())) {
883 RenderHelpers::rhiPrepareRenderable(rhiCtx.get(), passKey, data, *theObject, rpDesc, &ps, shaderFeatures,
884 ps.samples, ps.viewCount,
nullptr,
nullptr, QSSGRenderTextureCubeFaceNone,
nullptr, oit);
908 auto *ctx = renderer.contextInterface();
909 const auto &rhiCtx = ctx->rhiContext();
911 QSSG_ASSERT(!data.renderedCameras.isEmpty() && data.renderedCameraData.has_value() ,
return);
912 QSSGRenderCamera *camera = data.renderedCameras[0];
914 QRhiRenderPassDescriptor *mainRpDesc = rhiCtx->mainRenderPassDescriptor();
916 ps = data.getPipelineState();
917 ps.samples = rhiCtx->mainPassSampleCount();
918 ps.viewCount = data.layer.viewCount;
921 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
true);
922 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled,
false);
924 shaderFeatures = data.getShaderFeatures();
925 sortedTransparentObjects = data.getSortedTransparentRenderableObjects(*camera);
927 prep(*ctx, data,
this, ps, shaderFeatures, mainRpDesc, sortedTransparentObjects);
981 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
982 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
985 QRhiShaderResourceBindings *srb = layer->skyBoxSrb;
988 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
989 Q_TRACE_SCOPE(QSSG_renderPass, QStringLiteral(
"Quick3D render skybox"));
994 QSSGRenderLayer::TonemapMode tonemapMode = skipTonemapping && (layer->tonemapMode != QSSGRenderLayer::TonemapMode::Custom) ? QSSGRenderLayer::TonemapMode::None : layer->tonemapMode;
995 const auto &shaderCache = renderer.contextInterface()->shaderCache();
996 auto shaderPipeline = shaderCache->getBuiltInRhiShaders().getRhiSkyBoxShader(tonemapMode, layer->skyBoxIsRgbe8, layer->viewCount);
998 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, shaderPipeline.get());
999 renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx.get(), &ps, srb, rpDesc, { QSSGRhiQuadRenderer::DepthTest | QSSGRhiQuadRenderer::RenderBehind });
1000 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"skybox_map"));
1012 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
1013 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
1014 QSSG_ASSERT(!data.renderedCameras.isEmpty(),
return);
1015 QSSG_ASSERT(data.renderedCameras.count() == data.layer.viewCount,
return);
1016 layer = &data.layer;
1019 rpDesc = rhiCtx->mainRenderPassDescriptor();
1020 ps = data.getPipelineState();
1021 ps.samples = rhiCtx->mainPassSampleCount();
1022 ps.viewCount = data.layer.viewCount;
1023 ps.polygonMode = QRhiGraphicsPipeline::Fill;
1025 QSSGRenderLayer::TonemapMode tonemapMode = skipTonemapping && (layer->tonemapMode != QSSGRenderLayer::TonemapMode::Custom) ? QSSGRenderLayer::TonemapMode::None : layer->tonemapMode;
1027 const auto &shaderCache = renderer.contextInterface()->shaderCache();
1028 skyBoxCubeShader = shaderCache->getBuiltInRhiShaders().getRhiSkyBoxCubeShader(tonemapMode, !data.layer.skyBoxIsSrgb, data.layer.viewCount);
1030 RenderHelpers::rhiPrepareSkyBox(rhiCtx.get(),
this, *layer, data.renderedCameras, renderer, uint(tonemapMode));
1058 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
1059 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
1060 const auto &layer = data.layer;
1062 const auto &item2Ds = data.getRenderableItem2Ds();
1063 prepdItem2DRenderers.reserve(size_t(item2Ds.size()));
1068 renderer.beginSubLayerRender(data);
1069 const auto &rpd = data.getItem2DRenderPassDescriptor();
1071 for (
const auto *item2D: std::as_const(item2Ds)) {
1073 auto item2DData = data.getItem2DRenderer(*item2D);
1074 const auto &mvps = data.getItem2DMvps(*item2D);
1075 QSGRenderer *renderer2d = item2DData;
1080 if (renderer2d && renderer2d->currentRhi() != rhiCtx->rhi()) {
1081 static bool contextWarningShown =
false;
1082 if (!contextWarningShown) {
1083 qWarning () <<
"Scene with embedded 2D content can only be rendered in one window.";
1084 contextWarningShown =
true;
1091 auto layerPrepResult = data.layerPrepResult;
1093 QRhiRenderTarget *renderTarget = rhiCtx->renderTarget();
1094 renderer2d->setDevicePixelRatio(renderTarget->devicePixelRatio());
1095 const QRect deviceRect(QPoint(0, 0), renderTarget->pixelSize());
1096 const int viewCount = data.layer.viewCount;
1097 if (layer.scissorRect.isValid()) {
1098 QRect effScissor = layer.scissorRect & layerPrepResult.getViewport().toRect();
1099 QMatrix4x4 correctionMat = correctMVPForScissor(layerPrepResult.getViewport(),
1101 rhiCtx->rhi()->isYUpInNDC());
1102 for (
int viewIndex = 0; viewIndex < viewCount; ++viewIndex) {
1103 const QMatrix4x4 projectionMatrix = correctionMat * mvps[viewIndex];
1104 renderer2d->setProjectionMatrix(projectionMatrix, viewIndex);
1106 renderer2d->setViewportRect(effScissor);
1108 for (
int viewIndex = 0; viewIndex < viewCount; ++viewIndex)
1109 renderer2d->setProjectionMatrix(mvps[viewIndex], viewIndex);
1110 renderer2d->setViewportRect(RenderHelpers::correctViewportCoordinates(layerPrepResult.getViewport(), deviceRect));
1112 renderer2d->setDeviceRect(deviceRect);
1113 QSGRenderTarget sgRt(renderTarget, rpd.get(), rhiCtx->commandBuffer());
1114 sgRt.multiViewCount = data.layer.viewCount;
1115 renderer2d->setRenderTarget(sgRt);
1116 renderer2d->prepareSceneInline();
1117 prepdItem2DRenderers.push_back(renderer2d);
1119 renderer.endSubLayerRender(data);
1149 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
1150 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
1151 QSSG_ASSERT(!data.renderedCameras.isEmpty(),
return);
1152 QSSG_ASSERT(data.renderedCameras.count() == data.layer.viewCount,
return);
1153 layer = &data.layer;
1156 const auto &shaderCache = renderer.contextInterface()->shaderCache();
1157 gridShader = shaderCache->getBuiltInRhiShaders().getRhiGridShader(data.layer.viewCount);
1159 ps = data.getPipelineState();
1160 ps.samples = rhiCtx->mainPassSampleCount();
1161 ps.viewCount = data.layer.viewCount;
1162 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
true);
1163 ps.polygonMode = QRhiGraphicsPipeline::Fill;
1165 RenderHelpers::rhiPrepareGrid(rhiCtx.get(),
this, *layer, data.renderedCameras, renderer);
1170 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
1171 QSSG_ASSERT(gridShader && rhiCtx->rhi()->isRecordingFrame(),
return);
1172 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1174 cb->debugMarkBegin(QByteArrayLiteral(
"Quick3D render grid"));
1175 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1176 Q_TRACE_SCOPE(QSSG_renderPass, QStringLiteral(
"Quick3D render grid"));
1177 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, gridShader.get());
1178 QRhiShaderResourceBindings *srb = layer->gridSrb;
1179 QRhiRenderPassDescriptor *rpDesc = rhiCtx->mainRenderPassDescriptor();
1180 renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx.get(), &ps, srb, rpDesc, { QSSGRhiQuadRenderer::DepthTest });
1181 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"render_grid"));
1192 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
1193 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
1194 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx.get());
1195 QSSG_ASSERT(!data.renderedCameras.isEmpty(),
return);
1196 QSSG_ASSERT(data.renderedCameras.count() == data.layer.viewCount,
return);
1198 const auto &shaderCache = renderer.contextInterface()->shaderCache();
1199 debugObjectShader = shaderCache->getBuiltInRhiShaders().getRhiDebugObjectShader(data.layer.viewCount);
1200 ps = data.getPipelineState();
1201 ps.samples = rhiCtx->mainPassSampleCount();
1202 ps.viewCount = data.layer.viewCount;
1205 const auto &debugDraw = renderer.contextInterface()->debugDrawSystem();
1206 if (debugDraw && debugDraw->hasContent()) {
1207 QRhi *rhi = rhiCtx->rhi();
1208 QRhiResourceUpdateBatch *rub = rhi->nextResourceUpdateBatch();
1209 debugDraw->prepareGeometry(rhiCtx.get(), rub);
1210 QSSGRhiDrawCallData &dcd = rhiCtxD->drawCallData({
this,
nullptr,
nullptr, 0 });
1212 dcd.ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64 * data.renderedCameras.count());
1215 char *ubufData = dcd.ubuf->beginFullDynamicBufferUpdateForCurrentFrame();
1216 QMatrix4x4 viewProjection(Qt::Uninitialized);
1217 QMatrix4x4 cameraGlobalTransform(Qt::Uninitialized);
1218 for (qsizetype viewIdx = 0; viewIdx < data.renderedCameras.count(); ++viewIdx) {
1219 cameraGlobalTransform = data.getGlobalTransform(*data.renderedCameras[viewIdx]);
1220 data.renderedCameras[viewIdx]->calculateViewProjectionMatrix(cameraGlobalTransform, viewProjection);
1221 viewProjection = rhi->clipSpaceCorrMatrix() * viewProjection;
1222 memcpy(ubufData, viewProjection.constData() + viewIdx * 64, 64);
1224 dcd.ubuf->endFullDynamicBufferUpdateForCurrentFrame();
1226 QSSGRhiShaderResourceBindingList bindings;
1227 bindings.addUniformBuffer(0, QRhiShaderResourceBinding::VertexStage, dcd.ubuf);
1228 dcd.srb = rhiCtxD->srb(bindings);
1230 rhiCtx->commandBuffer()->resourceUpdate(rub);
1236 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
1237 QSSG_ASSERT(debugObjectShader && rhiCtx->rhi()->isRecordingFrame(),
return);
1238 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1239 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx.get());
1241 const auto &debugDraw = renderer.contextInterface()->debugDrawSystem();
1242 if (debugDraw && debugDraw->hasContent()) {
1243 cb->debugMarkBegin(QByteArrayLiteral(
"Quick 3D debug objects"));
1244 Q_TRACE_SCOPE(QSSG_renderPass, QStringLiteral(
"Quick 3D debug objects"));
1245 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1246 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, debugObjectShader.get());
1247 QSSGRhiDrawCallData &dcd = rhiCtxD->drawCallData({
this,
nullptr,
nullptr, 0 });
1248 QRhiShaderResourceBindings *srb = dcd.srb;
1249 QRhiRenderPassDescriptor *rpDesc = rhiCtx->mainRenderPassDescriptor();
1250 debugDraw->recordRenderDebugObjects(rhiCtx.get(), &ps, srb, rpDesc);
1252 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"debug_objects"));
1294 auto *ctx = renderer.contextInterface();
1295 const auto &rhiCtx = ctx->rhiContext();
1296 auto *rhi = rhiCtx->rhi();
1298 QSSG_ASSERT(!data.renderedCameras.isEmpty() && data.renderedCameraData.has_value() ,
return);
1299 QSSGRenderCamera *camera = data.renderedCameras[0];
1301 ps = data.getPipelineState();
1302 ps.samples = rhiCtx->mainPassSampleCount();
1303 ps.viewCount = rhiCtx->mainPassViewCount();
1305 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
true);
1306 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled,
false);
1308 shaderFeatures = data.getShaderFeatures();
1309 sortedTransparentObjects = data.getSortedTransparentRenderableObjects(*camera);
1311 if (method == QSSGRenderLayer::OITMethod::WeightedBlended) {
1312 ps.colorAttachmentCount = 2;
1314 rhiAccumTexture = data.getRenderResult(QSSGFrameData::RenderResult::AccumTexture);
1315 rhiRevealageTexture = data.getRenderResult(QSSGFrameData::RenderResult::RevealageTexture);
1317 rhiDepthTexture = data.getRenderResult(QSSGFrameData::RenderResult::DepthTextureMS);
1319 rhiDepthTexture = data.getRenderResult(QSSGFrameData::RenderResult::DepthTexture);
1320 if (!rhiDepthTexture->isValid())
1322 auto &oitrt = data.getOitRenderContext();
1323 if (!oitrt.oitRenderTarget || oitrt.oitRenderTarget->pixelSize() != data.layerPrepResult.textureDimensions()
1324 || rhiDepthTexture->texture != oitrt.oitRenderTarget->description().depthTexture()
1325 || ps.samples != oitrt.oitRenderTarget->sampleCount()) {
1326 if (oitrt.oitRenderTarget) {
1327 rhiAccumTexture->texture->destroy();
1328 rhiRevealageTexture->texture->destroy();
1329 oitrt.oitRenderTarget->destroy();
1330 oitrt.renderPassDescriptor->destroy();
1331 oitrt.oitRenderTarget =
nullptr;
1333 const QRhiTexture::Flags textureFlags = QRhiTexture::RenderTarget;
1334 if (ps.viewCount >= 2) {
1335 rhiAccumTexture->texture = rhi->newTextureArray(QRhiTexture::RGBA16F, ps.viewCount, data.layerPrepResult.textureDimensions(), ps.samples, textureFlags);
1336 rhiRevealageTexture->texture = rhi->newTextureArray(QRhiTexture::R16F, ps.viewCount, data.layerPrepResult.textureDimensions(), ps.samples, textureFlags);
1338 rhiAccumTexture->texture = rhi->newTexture(QRhiTexture::RGBA16F, data.layerPrepResult.textureDimensions(), ps.samples, textureFlags);
1339 rhiRevealageTexture->texture = rhi->newTexture(QRhiTexture::R16F, data.layerPrepResult.textureDimensions(), ps.samples, textureFlags);
1341 rhiAccumTexture->texture->create();
1342 rhiRevealageTexture->texture->create();
1344 QRhiTextureRenderTargetDescription desc;
1345 desc.setColorAttachments({{rhiAccumTexture->texture}, {rhiRevealageTexture->texture}});
1346 desc.setDepthTexture(rhiDepthTexture->texture);
1348 if (oitrt.oitRenderTarget ==
nullptr) {
1349 oitrt.oitRenderTarget = rhi->newTextureRenderTarget(desc, QRhiTextureRenderTarget::PreserveDepthStencilContents);
1350 oitrt.renderPassDescriptor = oitrt.oitRenderTarget->newCompatibleRenderPassDescriptor();
1351 oitrt.oitRenderTarget->setRenderPassDescriptor(oitrt.renderPassDescriptor);
1352 oitrt.oitRenderTarget->create();
1354 renderTarget = oitrt.oitRenderTarget;
1357 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx.get());
1358 const auto &shaderCache = renderer.contextInterface()->shaderCache();
1359 clearPipeline = shaderCache->getBuiltInRhiShaders().getRhiClearMRTShader();
1361 QSSGRhiShaderResourceBindingList bindings;
1362 QVector4D clearData[2];
1363 clearData[0] = QVector4D(0.0, 0.0, 0.0, 0.0);
1364 clearData[1] = QVector4D(1.0, 1.0, 1.0, 1.0);
1366 QSSGRhiDrawCallData &dcd(rhiCtxD->drawCallData({
this,
nullptr,
nullptr, 0 }));
1367 QRhiBuffer *&ubuf = dcd.ubuf;
1368 const int ubufSize =
sizeof(clearData);
1370 ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, ubufSize);
1374 QRhiResourceUpdateBatch *rub = rhi->nextResourceUpdateBatch();
1375 rub->updateDynamicBuffer(ubuf, 0, ubufSize, &clearData);
1376 renderer.rhiQuadRenderer()->prepareQuad(rhiCtx.get(), rub);
1378 bindings.addUniformBuffer(0, QRhiShaderResourceBinding::FragmentStage, ubuf);
1380 clearSrb = rhiCtxD->srb(bindings);
1382 ps.targetBlend[0].srcAlpha = QRhiGraphicsPipeline::One;
1383 ps.targetBlend[0].srcColor = QRhiGraphicsPipeline::One;
1384 ps.targetBlend[0].dstAlpha = QRhiGraphicsPipeline::One;
1385 ps.targetBlend[0].dstColor = QRhiGraphicsPipeline::One;
1386 ps.targetBlend[1].srcAlpha = QRhiGraphicsPipeline::Zero;
1387 ps.targetBlend[1].srcColor = QRhiGraphicsPipeline::Zero;
1388 ps.targetBlend[1].dstAlpha = QRhiGraphicsPipeline::OneMinusSrcAlpha;
1389 ps.targetBlend[1].dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
1391 TransparentPass::prep(*ctx, data,
this, ps, shaderFeatures, oitrt.renderPassDescriptor, sortedTransparentObjects,
true);
1397 auto *ctx = renderer.contextInterface();
1398 const auto &rhiCtx = ctx->rhiContext();
1399 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
1400 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1402 if (method == QSSGRenderLayer::OITMethod::WeightedBlended) {
1403 if (Q_LIKELY(renderTarget)) {
1404 cb->beginPass(renderTarget, Qt::black, {});
1406 QRhiShaderResourceBindings *srb = clearSrb;
1408 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
false);
1409 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, clearPipeline.get());
1410 renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx.get(), &ps, srb, renderTarget->renderPassDescriptor(), {});
1411 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
true);
1413 cb->debugMarkBegin(QByteArrayLiteral(
"Quick3D render order-independent alpha"));
1414 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
1415 Q_TRACE(QSSG_renderPass_entry, QStringLiteral(
"Quick3D render order-independent alpha"));
1416 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled,
true);
1417 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled,
false);
1418 TransparentPass::render(*ctx, ps, sortedTransparentObjects);
1420 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"transparent_order_independent_pass"));
1421 Q_TRACE(QSSG_renderPass_exit);
1471 const auto &rhiCtx = renderer.contextInterface()->rhiContext();
1472 QSSG_ASSERT(rhiCtx->rhi()->isRecordingFrame(),
return);
1473 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
1475 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx.get());
1477 if (!rhiAccumTexture->texture || !rhiRevealageTexture->texture)
1480 if (method == QSSGRenderLayer::OITMethod::WeightedBlended) {
1481 QSSGRhiShaderResourceBindingList bindings;
1483 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Nearest,
1484 QRhiSampler::Nearest,
1486 QRhiSampler::ClampToEdge,
1487 QRhiSampler::ClampToEdge,
1488 QRhiSampler::ClampToEdge });
1489 bindings.addTexture(1, QRhiShaderResourceBinding::FragmentStage, rhiAccumTexture->texture, sampler);
1490 bindings.addTexture(2, QRhiShaderResourceBinding::FragmentStage, rhiRevealageTexture->texture, sampler);
1492 compositeSrb = rhiCtxD->srb(bindings);
1494 QRhiShaderResourceBindings *srb = compositeSrb;
1497 cb->debugMarkBegin(QByteArrayLiteral(
"Quick3D revealage"));
1498 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, compositeShaderPipeline.get());
1499 ps.flags.setFlag(QSSGRhiGraphicsPipelineState::Flag::BlendEnabled,
true);
1500 renderer.rhiQuadRenderer()->recordRenderQuad(rhiCtx.get(), &ps, srb, rhiCtx->mainRenderPassDescriptor(),
1501 { QSSGRhiQuadRenderer::UvCoords | QSSGRhiQuadRenderer::DepthTest | QSSGRhiQuadRenderer::PremulBlend});
1502 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"revealage"));