310 QRhiTexture *currentTexture = m_texture;
314 m_renderStats->startRenderPrepare();
316 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DPrepareFrame);
318 QSSGRhiContext *rhiCtx = m_sgContext->rhiContext().get();
319 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
321 rhiCtxD->setMainRenderPassDescriptor(m_textureRenderPassDescriptor);
322 rhiCtxD->setRenderTarget(m_textureRenderTarget);
324 QRhiCommandBuffer *cb =
nullptr;
325 QRhiSwapChain *swapchain = qw->swapChain();
327 cb = swapchain->currentFrameCommandBuffer();
328 rhiCtxD->setCommandBuffer(cb);
330 QSGRendererInterface *rif = qw->rendererInterface();
331 cb =
static_cast<QRhiCommandBuffer *>(
332 rif->getResource(qw, QSGRendererInterface::RhiRedirectCommandBuffer));
334 rhiCtxD->setCommandBuffer(cb);
336 qWarning(
"Neither swapchain nor redirected command buffer are available.");
337 return currentTexture;
343 rhiCtxD->setMainPassSampleCount(m_msaaRenderBufferLegacy ? m_msaaRenderBufferLegacy->sampleCount() :
344 (m_msaaRenderTexture ? m_msaaRenderTexture->sampleCount() :
345 (m_msaaMultiViewRenderBuffer ? m_msaaMultiViewRenderBuffer->sampleCount() : 1)));
349 int ssaaAdjustedWidth = m_surfaceSize.width();
350 int ssaaAdjustedHeight = m_surfaceSize.height();
351 if (m_layer->antialiasingMode == QSSGRenderLayer::AAMode::SSAA) {
352 ssaaAdjustedWidth *= m_layer->ssaaMultiplier;
353 ssaaAdjustedHeight *= m_layer->ssaaMultiplier;
356 Q_TRACE(QSSG_prepareFrame_entry, ssaaAdjustedWidth, ssaaAdjustedHeight);
358 float dpr = m_sgContext->renderer()->dpr();
359 const QRect vp = QRect(0, 0, ssaaAdjustedWidth, ssaaAdjustedHeight);
364 m_renderStats->endRenderPrepare();
366 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DPrepareFrame, quint64(ssaaAdjustedWidth) | quint64(ssaaAdjustedHeight) << 32, profilingId);
368 Q_TRACE(QSSG_prepareFrame_exit);
370 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderFrame);
371 Q_TRACE(QSSG_renderFrame_entry, ssaaAdjustedWidth, ssaaAdjustedHeight);
373 m_renderStats->startRender();
375 QColor clearColor = Qt::transparent;
376 if (m_backgroundMode == QSSGRenderLayer::Background::Color
377 || (m_backgroundMode == QSSGRenderLayer::Background::SkyBoxCubeMap && !m_layer->skyBoxCubeMap)
378 || (m_backgroundMode == QSSGRenderLayer::Background::SkyBox && !m_layer->lightProbe)
379 || (m_backgroundMode == QSSGRenderLayer::Background::SkyMaterial && !m_layer->skyMaterial)) {
382 clearColor = m_layer->firstEffect ? m_linearBackgroundColor : m_tonemappedBackgroundColor;
387 cb->beginPass(m_textureRenderTarget, clearColor, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
388 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
389 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(m_textureRenderTarget));
392 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
393 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, quint64(ssaaAdjustedWidth) | quint64(ssaaAdjustedHeight) << 32, QByteArrayLiteral(
"main"));
395 const bool temporalAA = m_layer->temporalAAIsActive;
396 const bool progressiveAA = m_layer->progressiveAAIsActive;
397 const bool superSamplingAA = m_layer->antialiasingMode == QSSGRenderLayer::AAMode::SSAA;
398 QRhi *rhi = rhiCtx->rhi();
400 currentTexture = superSamplingAA ? m_ssaaTexture : m_texture;
403 if (m_effectSystem && m_layer->firstEffect && !m_layer->renderedCameras.isEmpty()) {
404 const auto &renderer = m_sgContext->renderer();
406 Q_ASSERT(theRenderData);
407 QRhiTexture *theDepthTexture = theRenderData->getRenderResult(QSSGRenderResult::Key::DepthTexture)->texture;
408 QRhiTexture *theNormalTexture = theRenderData->getRenderResult(QSSGRenderResult::Key::NormalTexture)->texture;
409 QRhiTexture *theMotionVectorTexture = theRenderData->getRenderResult(QSSGRenderResult::Key::MotionVectorTexture)->texture;
411 currentTexture = m_effectSystem->process(*m_layer,
415 theMotionVectorTexture);
418 if ((progressiveAA || temporalAA) && m_prevTempAATexture) {
419 cb->debugMarkBegin(QByteArrayLiteral(
"Temporal AA"));
420 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
421 Q_TRACE_SCOPE(QSSG_renderPass, QStringLiteral(
"Temporal AA"));
422 QRhiTexture *blendResult;
423 uint *aaIndex = progressiveAA ? &m_layer->progAAPassIndex : &m_layer->tempAAPassIndex;
426 if ((temporalAA && m_layer->temporalAAMode != QSSGRenderLayer::TAAMode::MotionVector) ||
428 (temporalAA && m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector ?
429 quint32(QSSGLayerRenderData::MAX_AA_LEVELS) :
430 quint32(m_layer->antialiasingQuality))) {
431 const auto &renderer = m_sgContext->renderer();
433 QRhiResourceUpdateBatch *rub = rhi->nextResourceUpdateBatch();
434 QSSGRhiDrawCallData &dcd(rhiCtxD->drawCallData({ m_layer,
nullptr,
nullptr,
nullptr, 0 }));
435 QRhiBuffer *&ubuf = dcd.ubuf;
436 const int ubufSize = 4 *
sizeof(
float);
438 ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, ubufSize);
441 int idx = *aaIndex - 1;
443 const QSize textureSize = m_prevTempAATexture->pixelSize();
444 QVector4D bufferData;
446 bufferData = QVector4D(s_ProgressiveAABlendFactors[idx]);
447 else if (m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::Default)
448 bufferData = QVector4D(s_TemporalAABlendFactors);
450 bufferData = QVector4D(1.0f / qMax(textureSize.width(), 1), 1.0f / qMax(textureSize.height(), 1),
451 0.9f + (qMin(qMax(m_layer->temporalAAStrength, 0.3f), 1.0f) - 0.3f) / 0.7f * 0.09f, 0.0f);
453 rub->updateDynamicBuffer(ubuf, 0, 4 *
sizeof(
float), &bufferData);
454 QSSGRhiGraphicsPipelineState ps;
455 ps.viewport = QRhiViewport(0, 0,
float(textureSize.width()),
float(textureSize.height()));
457 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
458 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
459 QSSGRhiShaderResourceBindingList bindings;
460 bindings.addUniformBuffer(0, QRhiShaderResourceBinding::FragmentStage, ubuf);
461 bindings.addTexture(1, QRhiShaderResourceBinding::FragmentStage, currentTexture, sampler);
462 bindings.addTexture(2, QRhiShaderResourceBinding::FragmentStage, m_prevTempAATexture, sampler);
463 if (m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector) {
465 Q_ASSERT(theRenderData);
466 QRhiTexture *theDepthTexture = theRenderData->getRenderResult(QSSGRenderResult::Key::DepthTexture)->texture;
467 QRhiTexture *theMotionVectorTexture = theRenderData->getRenderResult(QSSGRenderResult::Key::MotionVectorTexture)->texture;
468 bindings.addTexture(3, QRhiShaderResourceBinding::FragmentStage, theDepthTexture, sampler);
469 bindings.addTexture(4, QRhiShaderResourceBinding::FragmentStage, theMotionVectorTexture, sampler);
470 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, m_sgContext->shaderCache()->getBuiltInRhiShaders().getRhiTemporalAAShader().get());
475 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, m_sgContext->shaderCache()->getBuiltInRhiShaders().getRhiProgressiveAAShader().get());
478 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
479 renderer->rhiQuadRenderer()->prepareQuad(rhiCtx, rub);
480 renderer->rhiQuadRenderer()->recordRenderQuadPass(rhiCtx, &ps, srb, m_temporalAARenderTarget, QSSGRhiQuadRenderer::UvCoords);
481 blendResult = m_temporalAATexture;
483 blendResult = m_prevTempAATexture;
487 blendResult = currentTexture;
490 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
492 const bool isMotionVector = m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector;
493 const quint32 aaLimit = (temporalAA && isMotionVector) ? quint32(QSSGLayerRenderData::MAX_AA_LEVELS) : quint32(m_layer->antialiasingQuality);
495 const bool aaActive = (temporalAA && !isMotionVector) || (*aaIndex < aaLimit);
496 const bool usePrevTexture = m_prevTempAATexture !=
nullptr;
498 if (aaActive && usePrevTexture) {
499 QRhiTexture *copySource = (blendResult && (progressiveAA || isMotionVector)) ? blendResult : currentTexture;
502 auto *rub = rhi->nextResourceUpdateBatch();
503 rub->copyTexture(m_prevTempAATexture, copySource);
504 cb->resourceUpdate(rub);
510 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"temporal_aa"));
512 currentTexture = blendResult;
515 if (m_layer->antialiasingMode == QSSGRenderLayer::AAMode::SSAA) {
525 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
526 const auto &renderer = m_sgContext->renderer();
528 cb->debugMarkBegin(QByteArrayLiteral(
"SSAA downsample"));
529 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
531 Q_TRACE_SCOPE(QSSG_renderPass, QStringLiteral(
"SSAA downsample"));
533 renderer->rhiQuadRenderer()->prepareQuad(rhiCtx,
nullptr);
540 const auto &shaderPipeline = m_sgContext->shaderCache()->getBuiltInRhiShaders().getRhiSupersampleResolveShader(m_layer->viewCount);
542 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
543 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
544 QSSGRhiShaderResourceBindingList bindings;
545 bindings.addTexture(0, QRhiShaderResourceBinding::FragmentStage, currentTexture, sampler);
546 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
548 QSSGRhiGraphicsPipelineState ps;
549 ps.viewport = QRhiViewport(0, 0,
float(m_surfaceSize.width()),
float(m_surfaceSize.height()));
550 ps.viewCount = m_layer->viewCount;
551 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, shaderPipeline.get());
553 renderer->rhiQuadRenderer()->recordRenderQuadPass(rhiCtx, &ps, srb, m_ssaaTextureToTextureRenderTarget, QSSGRhiQuadRenderer::UvCoords);
555 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"ssaa_downsample"));
557 currentTexture = m_texture;
560 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DRenderFrame,
561 STAT_PAYLOAD(QSSGRhiContextStats::get(*rhiCtx)),
565 m_renderStats->endRender(dumpRenderTimes());
566 Q_TRACE(QSSG_renderFrame_exit);
569 if (m_layer && m_layer->skyMaterial && m_layer->skyMaterial->wantsMoreFrames)
570 ++m_requestedFramesCount;
572 return currentTexture;
654 Q_TRACE_SCOPE(QSSG_synchronize, view3D, size, dpr);
656 Q_ASSERT(view3D !=
nullptr);
657 QSSGRhiContext *rhiCtx = m_sgContext->rhiContext().get();
658 Q_ASSERT(rhiCtx !=
nullptr);
662 m_layer =
new QSSGRenderLayer();
664 bool newRenderStats =
false;
665 if (!m_renderStats) {
666 m_renderStats = view3D->renderStats();
667 newRenderStats =
true;
671 m_renderStats->startSync();
673 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DSynchronizeFrame);
675 m_sgContext->renderer()->setDpr(dpr);
676 bool layerSizeIsDirty = m_surfaceSize != size;
677 m_surfaceSize = size;
679 QQuick3DSceneEnvironment *environment = view3D->environment();
680 if (environment->lightmapper()) {
681 QQuick3DLightmapper *lightmapper = environment->lightmapper();
682 lmOptions.opacityThreshold = lightmapper->opacityThreshold();
683 lmOptions.bias = lightmapper->bias();
684 lmOptions.useAdaptiveBias = lightmapper->isAdaptiveBiasEnabled();
685 lmOptions.indirectLightEnabled = lightmapper->isIndirectLightEnabled();
686 lmOptions.indirectLightSamples = lightmapper->samples();
687 lmOptions.indirectLightWorkgroupSize = lightmapper->indirectLightWorkgroupSize();
688 lmOptions.indirectLightBounces = lightmapper->bounces();
689 lmOptions.indirectLightFactor = lightmapper->indirectLightFactor();
690 lmOptions.sigma = lightmapper->denoiseSigma();
691 lmOptions.texelsPerUnit = lightmapper->texelsPerUnit();
697 if (environment->m_dirtyFlags & QQuick3DSceneEnvironment::InternalDirtyFlag::LightmapperDirty) {
698 environment->m_dirtyFlags &= ~QQuick3DSceneEnvironment::InternalDirtyFlag::LightmapperDirty;
700 const QQmlContext *context = qmlContext(view3D);
701 const QUrl originalSource = environment->lightmapper() ? environment->lightmapper()->source()
702 : QUrl::fromLocalFile(QStringLiteral(
"lightmaps.bin"));
703 const auto resolvedUrl = context ? context->resolvedUrl(originalSource) : originalSource;
704 const auto qmlSource = QQmlFile::urlToLocalFileOrQrc(resolvedUrl);
705 const QString lightmapSource = qmlSource.isEmpty() ? originalSource.path() : qmlSource;
706 lmOptions.source = lightmapSource;
707 m_layer->lightmapSource = lightmapSource;
710 m_sgContext->bufferManager()->setLightmapSource(m_layer->lightmapSource);
711 if (QQuick3DSceneManager *sceneManager = QQuick3DObjectPrivate::get(view3D->scene())->sceneManager)
712 sceneManager->lightmapSourceTracker = { m_layer->lightmapSource,
true };
716 QSet<QSSGRenderGraphObject *> resourceLoaders;
717 QQuick3DWindowAttachment::SyncResult requestSharedUpdate = QQuick3DWindowAttachment::SyncResultFlag::None;
718 if (
auto window = view3D->window()) {
719 if (!winAttacment || winAttacment->window() != window)
720 winAttacment = QQuick3DSceneManager::getOrSetWindowAttachment(*window);
722 if (winAttacment && winAttacment->rci() != m_sgContext)
723 winAttacment->setRci(m_sgContext);
725 QSSGRenderRoot *rootNode = winAttacment->rootNode();
726 if (m_layer->rootNode != rootNode) {
727 Q_ASSERT(m_layer->rootNode ==
nullptr);
728 rootNode->addChild(*m_layer);
729 rootNode->setStartVersion(m_layer->h.version());
730 m_layer->ref(rootNode);
734 requestSharedUpdate |= winAttacment->synchronize(resourceLoaders);
738 QQuick3DNode *importScene = view3D->importScene();
740 QQuick3DSceneManager *importSceneManager = QQuick3DObjectPrivate::get(importScene)->sceneManager;
743 if (
auto window = importSceneManager->window(); window && window != view3D->window()) {
744 if (
auto winAttacment = importSceneManager->wattached) {
746 auto rci = winAttacment->rci();
747 const bool inlineSync = (rci && rci->rhi() && (rci->rhi()->thread() == m_sgContext->rhi()->thread()));
751 winAttacment->synchronize(resourceLoaders);
752 }
else if (rci && !window->isExposed()) {
754 winAttacment->synchronize(resourceLoaders);
755 }
else if (!rci || (requestSharedUpdate & QQuick3DWindowAttachment::SyncResultFlag::SharedResourcesDirty)) {
760 winAttacment->requestUpdate();
773 m_layer->viewCount = rhiCtx->mainPassViewCount();
774 updateLayerNode(*m_layer, *view3D, resourceLoaders.values());
780 if (view3D->m_visibilityChanged) {
781 view3D->m_visibilityChanged =
false;
782 m_layer->markDirty(QSSGRenderLayer::DirtyFlag::VisibilityDirty);
787 m_requestedFramesCount = 0;
788 if (m_layer->isProgressiveAAEnabled() || m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector) {
795 m_requestedFramesCount = (m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector ? 45 :
796 int(m_layer->antialiasingQuality) + 1);
797 }
else if (m_layer->isTemporalAAEnabled()) {
802 m_requestedFramesCount = (m_aaIsDirty || m_temporalIsDirty) ? QSSGLayerRenderData::MAX_TEMPORAL_AA_LEVELS : 1;
807 for (QSSGRenderEffect *effectNode = m_layer->firstEffect; effectNode; effectNode = effectNode->m_nextEffect)
808 effectNode->finalizeShaders(*m_layer, m_sgContext.get());
826 if (QQuick3DSceneManager *sm = QQuick3DObjectPrivate::get(view3D->scene())->sceneManager; sm) {
830 if (sm->userRenderPassesDirty) {
834 for (QSSGRenderUserPass *userPass : std::as_const(sm->userRenderPasses)) {
835 if (userPass->role != QSSGRenderUserPass::Role::SubPass)
837 for (
const QSSGCommand *cmd : std::as_const(userPass->commands)) {
838 if (cmd->m_type == CommandType::ColorAttachment
839 || cmd->m_type == CommandType::DepthStencilAttachment
840 || cmd->m_type == CommandType::DepthTextureAttachment) {
841 qWarning() <<
"RenderPass" << sm->lookUpNode(userPass)
842 <<
"is used as a sub-pass; its" << cmd->typeAsString()
843 <<
"command is ignored because a sub-pass renders into its parent's render target.";
854 for (QSSGRenderUserPass *userPass : std::as_const(sm->userRenderPasses)) {
855 userPass->m_nestingDepth = 0;
856 if (userPass->role != QSSGRenderUserPass::Role::TopLevel)
858 const QQuick3DObject *fo = sm->lookUpNode(userPass);
862 for (QQuick3DObject *p = fo->parentItem(); p; p = p->parentItem()) {
863 if (QSSGRenderGraphObjectUtils::isUserRenderPass(QQuick3DObjectPrivate::get(p)->type))
866 userPass->m_nestingDepth = depth;
868 quint32 declarationOrder = 0;
869 for (QSSGRenderUserPass *userPass : std::as_const(sm->userRenderPasses)) {
870 if (userPass->role == QSSGRenderUserPass::Role::TopLevel)
871 userPass->m_declarationOrder = declarationOrder++;
873 sm->userRenderPassesDirty =
false;
876 QSSGUserRenderPassManager::UserPassSet topLevelPasses;
877 topLevelPasses.reserve(sm->userRenderPasses.size());
878 for (QSSGRenderUserPass *userPass : std::as_const(sm->userRenderPasses)) {
879 userPass->finalizeShaders(*m_sgContext);
880 if (userPass->role == QSSGRenderUserPass::Role::TopLevel)
881 topLevelPasses.push_back(userPass);
886 if (m_layer->renderData) {
887 if (
const QSSGUserRenderPassManagerPtr &upm = m_layer->renderData->requestUserRenderPassManager())
888 upm->setScheduledPasses(topLevelPasses);
893 m_renderStats->setRhiContext(rhiCtx, m_layer);
895 static const auto getStageIndex = [](
const QSSGRenderExtension &ext) -> size_t {
896 const QSSGRenderExtension::RenderMode mode = ext.mode();
897 const QSSGRenderExtension::RenderStage stage = ext.stage();
900 if (mode == QSSGRenderExtension::RenderMode::Standalone)
901 return size_t(QSSGRenderLayer::RenderExtensionStage::TextureProviders);
904 case QSSGRenderExtension::RenderStage::PreColor:
905 return size_t(QSSGRenderLayer::RenderExtensionStage::Underlay);
906 case QSSGRenderExtension::RenderStage::PostColor:
907 return size_t(QSSGRenderLayer::RenderExtensionStage::Overlay);
910 Q_UNREACHABLE_RETURN(size_t(QSSGRenderLayer::RenderExtensionStage::Underlay));
916 if (QQuick3DSceneManager *sm = QQuick3DObjectPrivate::get(view3D->scene())->sceneManager; sm) {
917 const bool rebuildExtensionLists = (requestSharedUpdate & QQuick3DWindowAttachment::SyncResultFlag::ExtensionsDiry)
918 || view3D->extensionListDirty()
919 || sm->autoRegisteredExtensionsDirty;
924 if (rebuildExtensionLists) {
926 for (size_t i = 0; i != size_t(QSSGRenderLayer::RenderExtensionStage::Count); ++i)
927 m_layer->renderExtensions[i].clear();
930 const auto &extensions = view3D->extensionList();
931 for (
const auto &ext : extensions) {
932 const auto type = QQuick3DObjectPrivate::get(ext)->type;
933 if (QSSGRenderGraphObject::isExtension(type)) {
934 if (type == QSSGRenderGraphObject::Type::RenderExtension) {
935 if (
auto *renderExt = qobject_cast<QQuick3DRenderExtension *>(ext)) {
936 if (QSSGRenderExtension *ssgExt =
static_cast<QSSGRenderExtension *>(QQuick3DObjectPrivate::get(renderExt)->spatialNode)) {
937 const auto stage = getStageIndex(*ssgExt);
938 auto &list = m_layer->renderExtensions[size_t(stage)];
939 bfs(qobject_cast<QQuick3DRenderExtension *>(ext), list);
946 view3D->clearExtensionListDirty();
950 if (sm->autoRegisteredExtensionsDirty) {
951 for (QSSGRenderExtension *ae : std::as_const(sm->autoRegisteredExtensions))
952 m_layer->renderExtensions[getStageIndex(*ae)].push_back(ae);
953 sm->autoRegisteredExtensionsDirty =
false;
957 bool postProcessingNeeded = m_layer->firstEffect;
958 bool postProcessingWasActive = m_effectSystem;
959 QSSGRenderTextureFormat::Format effectOutputFormatOverride = QSSGRenderTextureFormat::Unknown;
960 if (postProcessingNeeded) {
961 QSSGRenderEffect *lastEffect = m_layer->firstEffect;
962 while (lastEffect->m_nextEffect)
963 lastEffect = lastEffect->m_nextEffect;
964 effectOutputFormatOverride = QSSGRhiEffectSystem::overriddenOutputFormat(lastEffect);
966 const auto layerTextureFormat = [effectOutputFormatOverride, view3D](QRhi *rhi,
bool postProc) {
967 if (effectOutputFormatOverride != QSSGRenderTextureFormat::Unknown)
968 return QSSGBufferManager::toRhiFormat(effectOutputFormatOverride);
983 const QRhiTexture::Format preferredPostProcFormat = QRhiTexture::RGBA16F;
984 if (postProc && rhi->isTextureFormatSupported(preferredPostProcFormat))
985 return preferredPostProcFormat;
987#if QT_CONFIG(quick_shadereffect)
988 const QRhiTexture::Format preferredView3DFormat = toRhiTextureFormat(view3D->renderFormat());
989 if (rhi->isTextureFormatSupported(preferredView3DFormat))
990 return preferredView3DFormat;
993 return QRhiTexture::RGBA8;
995 bool postProcessingStateDirty = postProcessingNeeded != postProcessingWasActive;
998 m_backgroundMode = QSSGRenderLayer::Background(view3D->environment()->backgroundMode());
1002 QColor currentUserBackgroundColor = view3D->environment()->clearColor();
1003 if (m_userBackgroundColor != currentUserBackgroundColor) {
1004 m_userBackgroundColor = currentUserBackgroundColor;
1005 m_linearBackgroundColor = QSSGUtils::color::sRGBToLinearColor(m_userBackgroundColor);
1006 const QVector3D tc = tonemapRgb(QVector3D(m_linearBackgroundColor.redF(),
1007 m_linearBackgroundColor.greenF(),
1008 m_linearBackgroundColor.blueF()),
1009 view3D->environment()->tonemapMode());
1010 m_tonemappedBackgroundColor = QColor::fromRgbF(tc.x(), tc.y(), tc.z(), m_linearBackgroundColor.alphaF());
1012 m_layer->scissorRect = QRect(view3D->environment()->scissorRect().topLeft() * dpr,
1013 view3D->environment()->scissorRect().size() * dpr);
1019 auto sceneRootNode =
static_cast<QSSGRenderNode*>(QQuick3DObjectPrivate::get(view3D->scene())->spatialNode);
1020 if (sceneRootNode != m_sceneRootNode) {
1021 if (m_sceneRootNode)
1022 removeNodeFromLayer(m_sceneRootNode);
1025 addNodeToLayer(sceneRootNode);
1027 m_sceneRootNode = sceneRootNode;
1031 QSSGRenderNode *importSceneRootNode =
nullptr;
1033 importSceneRootNode =
static_cast<QSSGRenderNode*>(QQuick3DObjectPrivate::get(importScene)->spatialNode);
1035 if (importSceneRootNode != m_importSceneRootNode) {
1036 if (m_importSceneRootNode)
1037 m_layer->removeImportScene(*m_importSceneRootNode);
1039 if (importSceneRootNode) {
1043 QObject *sceneParent = importScene->parent();
1044 bool isEmbedded =
false;
1045 while (sceneParent) {
1046 if (sceneParent == view3D) {
1050 sceneParent = sceneParent->parent();
1053 m_layer->setImportScene(*importSceneRootNode);
1056 m_importSceneRootNode = importSceneRootNode;
1064 QSSGRenderRoot *rootNode = winAttacment->rootNode();
1065 if (rootNode->isDirty(QSSGRenderRoot::DirtyFlag::TreeDirty)) {
1066 rootNode->reindex();
1070 maybeSetupLightmapBaking(view3D);
1072 if (m_useFBO && rhiCtx->isValid()) {
1073 QRhi *rhi = rhiCtx->rhi();
1074 const QSize renderSize = m_layer->isSsaaEnabled() ? m_surfaceSize * m_layer->ssaaMultiplier : m_surfaceSize;
1078 if (layerSizeIsDirty || postProcessingStateDirty) {
1079 m_texture->setPixelSize(m_surfaceSize);
1080 m_texture->setFormat(layerTextureFormat(rhi, postProcessingNeeded));
1081 m_texture->create();
1092 if (postProcessingStateDirty && (m_layer->antialiasingMode != QSSGRenderLayer::AAMode::NoAA || m_layer->isTemporalAAEnabled())) {
1093 releaseAaDependentRhiResources();
1095 if (m_ssaaTexture) {
1096 m_ssaaTexture->setPixelSize(renderSize);
1097 m_ssaaTexture->create();
1099 if (m_depthStencilBuffer) {
1100 m_depthStencilBuffer->setPixelSize(renderSize);
1101 m_depthStencilBuffer->create();
1103 if (m_multiViewDepthStencilBuffer) {
1104 m_multiViewDepthStencilBuffer->setPixelSize(renderSize);
1105 m_multiViewDepthStencilBuffer->create();
1107 if (m_msaaRenderBufferLegacy) {
1108 m_msaaRenderBufferLegacy->setPixelSize(renderSize);
1109 m_msaaRenderBufferLegacy->create();
1111 if (m_msaaRenderTexture) {
1112 m_msaaRenderTexture->setPixelSize(renderSize);
1113 m_msaaRenderTexture->create();
1115 if (m_msaaMultiViewRenderBuffer) {
1116 m_msaaMultiViewRenderBuffer->setPixelSize(renderSize);
1117 m_msaaMultiViewRenderBuffer->create();
1123 if (postProcessingStateDirty) {
1124 delete m_textureRenderPassDescriptor;
1125 m_textureRenderPassDescriptor = m_textureRenderTarget->newCompatibleRenderPassDescriptor();
1126 m_textureRenderTarget->setRenderPassDescriptor(m_textureRenderPassDescriptor);
1128 m_textureRenderTarget->create();
1129 if (m_ssaaTextureToTextureRenderTarget)
1130 m_ssaaTextureToTextureRenderTarget->create();
1132 if (m_temporalAATexture) {
1133 m_temporalAATexture->setPixelSize(renderSize);
1134 m_temporalAATexture->create();
1136 if (m_prevTempAATexture) {
1137 m_prevTempAATexture->setPixelSize(renderSize);
1138 m_prevTempAATexture->create();
1140 if (m_temporalAARenderTarget)
1141 m_temporalAARenderTarget->create();
1144 }
else if (m_aaIsDirty && rhi->backend() == QRhi::Metal) {
1145 m_texture->create();
1149 releaseAaDependentRhiResources();
1152 const QRhiTexture::Flags textureFlags = QRhiTexture::RenderTarget
1153 | QRhiTexture::UsedAsTransferSource;
1154 const QRhiTexture::Format textureFormat = layerTextureFormat(rhi, postProcessingNeeded);
1157 if (m_layer->viewCount >= 2)
1158 m_texture = rhi->newTextureArray(textureFormat, m_layer->viewCount, m_surfaceSize, 1, textureFlags);
1160 m_texture = rhi->newTexture(textureFormat, m_surfaceSize, 1, textureFlags);
1161 m_texture->create();
1164 if (!m_ssaaTexture && m_layer->isSsaaEnabled()) {
1165 if (m_layer->viewCount >= 2)
1166 m_ssaaTexture = rhi->newTextureArray(textureFormat, m_layer->viewCount, renderSize, 1, textureFlags);
1168 m_ssaaTexture = rhi->newTexture(textureFormat, renderSize, 1, textureFlags);
1169 m_ssaaTexture->create();
1172 if (m_timeBasedAA && !m_temporalAATexture) {
1173 m_temporalAATexture = rhi->newTexture(textureFormat, renderSize, 1, textureFlags);
1174 m_temporalAATexture->create();
1175 m_prevTempAATexture = rhi->newTexture(textureFormat, renderSize, 1, textureFlags);
1176 m_prevTempAATexture->create();
1180 if (m_aaIsDirty || layerSizeIsDirty)
1181 m_layer->tempAAPassIndex = m_layer->progAAPassIndex = 0;
1185 if (m_layer->antialiasingMode == QSSGRenderLayer::AAMode::MSAA) {
1186 if (rhi->isFeatureSupported(QRhi::MultisampleRenderBuffer)) {
1187 m_samples = qMax(1,
int(m_layer->antialiasingQuality));
1193 const QVector<
int> supported = rhi->supportedSampleCounts();
1194 if (!supported.contains(m_samples)) {
1195 if (!supported.isEmpty()) {
1196 auto it = std::lower_bound(supported.cbegin(), supported.cend(), m_samples);
1197 m_samples = it == supported.cend() ? supported.last() : *it;
1203 static bool warned =
false;
1206 qWarning(
"Multisample renderbuffers are not supported, disabling MSAA for Offscreen View3D");
1212 if (m_layer->viewCount >= 2) {
1213 if (!m_multiViewDepthStencilBuffer) {
1214 const auto format = rhi->isTextureFormatSupported(QRhiTexture::D24S8) ? QRhiTexture::D24S8 : QRhiTexture::D32FS8;
1215 m_multiViewDepthStencilBuffer = rhi->newTextureArray(format, m_layer->viewCount, renderSize,
1216 m_samples, QRhiTexture::RenderTarget);
1217 m_multiViewDepthStencilBuffer->create();
1220 if (!m_depthStencilBuffer) {
1221 m_depthStencilBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, renderSize, m_samples);
1222 m_depthStencilBuffer->create();
1226 if (!m_textureRenderTarget) {
1227 QRhiTextureRenderTargetDescription rtDesc;
1228 QRhiColorAttachment att;
1229 if (m_samples > 1) {
1230 if (m_layer->viewCount >= 2) {
1231 m_msaaMultiViewRenderBuffer = rhi->newTextureArray(textureFormat, m_layer->viewCount, renderSize, m_samples, QRhiTexture::RenderTarget);
1232 m_msaaMultiViewRenderBuffer->create();
1233 att.setTexture(m_msaaMultiViewRenderBuffer);
1235 if (!rhi->isFeatureSupported(QRhi::MultisampleTexture)) {
1237 m_msaaRenderBufferLegacy = rhi->newRenderBuffer(QRhiRenderBuffer::Color, renderSize, m_samples, {}, m_texture->format());
1238 m_msaaRenderBufferLegacy->create();
1239 att.setRenderBuffer(m_msaaRenderBufferLegacy);
1246 m_msaaRenderTexture = rhi->newTexture(textureFormat, renderSize, m_samples, QRhiTexture::RenderTarget);
1247 m_msaaRenderTexture->create();
1248 att.setTexture(m_msaaRenderTexture);
1251 att.setResolveTexture(m_texture);
1253 if (m_layer->antialiasingMode == QSSGRenderLayer::AAMode::SSAA)
1254 att.setTexture(m_ssaaTexture);
1256 att.setTexture(m_texture);
1258 att.setMultiViewCount(m_layer->viewCount);
1259 rtDesc.setColorAttachments({ att });
1260 if (m_depthStencilBuffer)
1261 rtDesc.setDepthStencilBuffer(m_depthStencilBuffer);
1262 if (m_multiViewDepthStencilBuffer)
1263 rtDesc.setDepthTexture(m_multiViewDepthStencilBuffer);
1265 m_textureRenderTarget = rhi->newTextureRenderTarget(rtDesc);
1266 m_textureRenderTarget->setName(QByteArrayLiteral(
"View3D"));
1267 m_textureRenderPassDescriptor = m_textureRenderTarget->newCompatibleRenderPassDescriptor();
1268 m_textureRenderTarget->setRenderPassDescriptor(m_textureRenderPassDescriptor);
1269 m_textureRenderTarget->create();
1272 if (!m_ssaaTextureToTextureRenderTarget && m_layer->antialiasingMode == QSSGRenderLayer::AAMode::SSAA) {
1273 QRhiColorAttachment att(m_texture);
1274 att.setMultiViewCount(m_layer->viewCount);
1275 m_ssaaTextureToTextureRenderTarget = rhi->newTextureRenderTarget(QRhiTextureRenderTargetDescription({ att }));
1276 m_ssaaTextureToTextureRenderTarget->setName(QByteArrayLiteral(
"SSAA texture"));
1277 m_ssaaTextureToTextureRenderPassDescriptor = m_ssaaTextureToTextureRenderTarget->newCompatibleRenderPassDescriptor();
1278 m_ssaaTextureToTextureRenderTarget->setRenderPassDescriptor(m_ssaaTextureToTextureRenderPassDescriptor);
1279 m_ssaaTextureToTextureRenderTarget->create();
1282 if (m_layer->firstEffect) {
1283 if (!m_effectSystem)
1284 m_effectSystem =
new QSSGRhiEffectSystem(m_sgContext);
1285 m_effectSystem->setup(renderSize);
1286 }
else if (m_effectSystem) {
1287 delete m_effectSystem;
1288 m_effectSystem =
nullptr;
1291 if (m_timeBasedAA && !m_temporalAARenderTarget) {
1292 m_temporalAARenderTarget = rhi->newTextureRenderTarget({ m_temporalAATexture });
1293 m_temporalAARenderTarget->setName(QByteArrayLiteral(
"Temporal AA texture"));
1294 m_temporalAARenderPassDescriptor = m_temporalAARenderTarget->newCompatibleRenderPassDescriptor();
1295 m_temporalAARenderTarget->setRenderPassDescriptor(m_temporalAARenderPassDescriptor);
1296 m_temporalAARenderTarget->create();
1299 m_textureNeedsFlip = rhi->isYUpInFramebuffer();
1300 m_aaIsDirty =
false;
1304 m_renderStats->endSync(dumpRenderTimes());
1306 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DSynchronizeFrame, quint64(m_surfaceSize.width()) | quint64(m_surfaceSize.height()) << 32, profilingId);