307 QRhiTexture *currentTexture = m_texture;
311 m_renderStats->startRenderPrepare();
313 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DPrepareFrame);
315 QSSGRhiContext *rhiCtx = m_sgContext->rhiContext().get();
316 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
318 rhiCtxD->setMainRenderPassDescriptor(m_textureRenderPassDescriptor);
319 rhiCtxD->setRenderTarget(m_textureRenderTarget);
321 QRhiCommandBuffer *cb =
nullptr;
322 QRhiSwapChain *swapchain = qw->swapChain();
324 cb = swapchain->currentFrameCommandBuffer();
325 rhiCtxD->setCommandBuffer(cb);
327 QSGRendererInterface *rif = qw->rendererInterface();
328 cb =
static_cast<QRhiCommandBuffer *>(
329 rif->getResource(qw, QSGRendererInterface::RhiRedirectCommandBuffer));
331 rhiCtxD->setCommandBuffer(cb);
333 qWarning(
"Neither swapchain nor redirected command buffer are available.");
334 return currentTexture;
340 rhiCtxD->setMainPassSampleCount(m_msaaRenderBufferLegacy ? m_msaaRenderBufferLegacy->sampleCount() :
341 (m_msaaRenderTexture ? m_msaaRenderTexture->sampleCount() :
342 (m_msaaMultiViewRenderBuffer ? m_msaaMultiViewRenderBuffer->sampleCount() : 1)));
346 int ssaaAdjustedWidth = m_surfaceSize.width();
347 int ssaaAdjustedHeight = m_surfaceSize.height();
348 if (m_layer->antialiasingMode == QSSGRenderLayer::AAMode::SSAA) {
349 ssaaAdjustedWidth *= m_layer->ssaaMultiplier;
350 ssaaAdjustedHeight *= m_layer->ssaaMultiplier;
353 Q_TRACE(QSSG_prepareFrame_entry, ssaaAdjustedWidth, ssaaAdjustedHeight);
355 float dpr = m_sgContext->renderer()->dpr();
356 const QRect vp = QRect(0, 0, ssaaAdjustedWidth, ssaaAdjustedHeight);
361 m_renderStats->endRenderPrepare();
363 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DPrepareFrame, quint64(ssaaAdjustedWidth) | quint64(ssaaAdjustedHeight) << 32, profilingId);
365 Q_TRACE(QSSG_prepareFrame_exit);
367 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderFrame);
368 Q_TRACE(QSSG_renderFrame_entry, ssaaAdjustedWidth, ssaaAdjustedHeight);
370 m_renderStats->startRender();
372 QColor clearColor = Qt::transparent;
373 if (m_backgroundMode == QSSGRenderLayer::Background::Color
374 || (m_backgroundMode == QSSGRenderLayer::Background::SkyBoxCubeMap && !m_layer->skyBoxCubeMap)
375 || (m_backgroundMode == QSSGRenderLayer::Background::SkyBox && !m_layer->lightProbe)
376 || (m_backgroundMode == QSSGRenderLayer::Background::SkyMaterial && !m_layer->skyMaterial)) {
379 clearColor = m_layer->firstEffect ? m_linearBackgroundColor : m_tonemappedBackgroundColor;
384 cb->beginPass(m_textureRenderTarget, clearColor, { 1.0f, 0 },
nullptr, rhiCtx->commonPassFlags());
385 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
386 QSSGRHICTX_STAT(rhiCtx, beginRenderPass(m_textureRenderTarget));
389 QSSGRHICTX_STAT(rhiCtx, endRenderPass());
390 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, quint64(ssaaAdjustedWidth) | quint64(ssaaAdjustedHeight) << 32, QByteArrayLiteral(
"main"));
392 const bool temporalAA = m_layer->temporalAAIsActive;
393 const bool progressiveAA = m_layer->progressiveAAIsActive;
394 const bool superSamplingAA = m_layer->antialiasingMode == QSSGRenderLayer::AAMode::SSAA;
395 QRhi *rhi = rhiCtx->rhi();
397 currentTexture = superSamplingAA ? m_ssaaTexture : m_texture;
400 if (m_effectSystem && m_layer->firstEffect && !m_layer->renderedCameras.isEmpty()) {
401 const auto &renderer = m_sgContext->renderer();
403 Q_ASSERT(theRenderData);
404 QRhiTexture *theDepthTexture = theRenderData->getRenderResult(QSSGRenderResult::Key::DepthTexture)->texture;
405 QRhiTexture *theNormalTexture = theRenderData->getRenderResult(QSSGRenderResult::Key::NormalTexture)->texture;
406 QRhiTexture *theMotionVectorTexture = theRenderData->getRenderResult(QSSGRenderResult::Key::MotionVectorTexture)->texture;
408 currentTexture = m_effectSystem->process(*m_layer,
412 theMotionVectorTexture);
415 if ((progressiveAA || temporalAA) && m_prevTempAATexture) {
416 cb->debugMarkBegin(QByteArrayLiteral(
"Temporal AA"));
417 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
418 Q_TRACE_SCOPE(QSSG_renderPass, QStringLiteral(
"Temporal AA"));
419 QRhiTexture *blendResult;
420 uint *aaIndex = progressiveAA ? &m_layer->progAAPassIndex : &m_layer->tempAAPassIndex;
423 if ((temporalAA && m_layer->temporalAAMode != QSSGRenderLayer::TAAMode::MotionVector) ||
425 (temporalAA && m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector ?
426 quint32(QSSGLayerRenderData::MAX_AA_LEVELS) :
427 quint32(m_layer->antialiasingQuality))) {
428 const auto &renderer = m_sgContext->renderer();
430 QRhiResourceUpdateBatch *rub = rhi->nextResourceUpdateBatch();
431 QSSGRhiDrawCallData &dcd(rhiCtxD->drawCallData({ m_layer,
nullptr,
nullptr, 0 }));
432 QRhiBuffer *&ubuf = dcd.ubuf;
433 const int ubufSize = 4 *
sizeof(
float);
435 ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, ubufSize);
438 int idx = *aaIndex - 1;
440 const QSize textureSize = m_prevTempAATexture->pixelSize();
441 QVector4D bufferData;
443 bufferData = QVector4D(s_ProgressiveAABlendFactors[idx]);
444 else if (m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::Default)
445 bufferData = QVector4D(s_TemporalAABlendFactors);
447 bufferData = QVector4D(1.0f / qMax(textureSize.width(), 1), 1.0f / qMax(textureSize.height(), 1),
448 0.9f + (qMin(qMax(m_layer->temporalAAStrength, 0.3f), 1.0f) - 0.3f) / 0.7f * 0.09f, 0.0f);
450 rub->updateDynamicBuffer(ubuf, 0, 4 *
sizeof(
float), &bufferData);
451 QSSGRhiGraphicsPipelineState ps;
452 ps.viewport = QRhiViewport(0, 0,
float(textureSize.width()),
float(textureSize.height()));
454 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
455 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
456 QSSGRhiShaderResourceBindingList bindings;
457 bindings.addUniformBuffer(0, QRhiShaderResourceBinding::FragmentStage, ubuf);
458 bindings.addTexture(1, QRhiShaderResourceBinding::FragmentStage, currentTexture, sampler);
459 bindings.addTexture(2, QRhiShaderResourceBinding::FragmentStage, m_prevTempAATexture, sampler);
460 if (m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector) {
462 Q_ASSERT(theRenderData);
463 QRhiTexture *theDepthTexture = theRenderData->getRenderResult(QSSGRenderResult::Key::DepthTexture)->texture;
464 QRhiTexture *theMotionVectorTexture = theRenderData->getRenderResult(QSSGRenderResult::Key::MotionVectorTexture)->texture;
465 bindings.addTexture(3, QRhiShaderResourceBinding::FragmentStage, theDepthTexture, sampler);
466 bindings.addTexture(4, QRhiShaderResourceBinding::FragmentStage, theMotionVectorTexture, sampler);
467 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, m_sgContext->shaderCache()->getBuiltInRhiShaders().getRhiTemporalAAShader().get());
472 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, m_sgContext->shaderCache()->getBuiltInRhiShaders().getRhiProgressiveAAShader().get());
475 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
476 renderer->rhiQuadRenderer()->prepareQuad(rhiCtx, rub);
477 renderer->rhiQuadRenderer()->recordRenderQuadPass(rhiCtx, &ps, srb, m_temporalAARenderTarget, QSSGRhiQuadRenderer::UvCoords);
478 blendResult = m_temporalAATexture;
480 blendResult = m_prevTempAATexture;
484 blendResult = currentTexture;
487 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
489 const bool isMotionVector = m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector;
490 const quint32 aaLimit = (temporalAA && isMotionVector) ? quint32(QSSGLayerRenderData::MAX_AA_LEVELS) : quint32(m_layer->antialiasingQuality);
492 const bool aaActive = (temporalAA && !isMotionVector) || (*aaIndex < aaLimit);
493 const bool usePrevTexture = m_prevTempAATexture !=
nullptr;
495 if (aaActive && usePrevTexture) {
496 QRhiTexture *copySource = (blendResult && (progressiveAA || isMotionVector)) ? blendResult : currentTexture;
499 auto *rub = rhi->nextResourceUpdateBatch();
500 rub->copyTexture(m_prevTempAATexture, copySource);
501 cb->resourceUpdate(rub);
507 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"temporal_aa"));
509 currentTexture = blendResult;
512 if (m_layer->antialiasingMode == QSSGRenderLayer::AAMode::SSAA) {
522 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
523 const auto &renderer = m_sgContext->renderer();
525 cb->debugMarkBegin(QByteArrayLiteral(
"SSAA downsample"));
526 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DRenderPass);
528 Q_TRACE_SCOPE(QSSG_renderPass, QStringLiteral(
"SSAA downsample"));
530 renderer->rhiQuadRenderer()->prepareQuad(rhiCtx,
nullptr);
537 const auto &shaderPipeline = m_sgContext->shaderCache()->getBuiltInRhiShaders().getRhiSupersampleResolveShader(m_layer->viewCount);
539 QRhiSampler *sampler = rhiCtx->sampler({ QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
540 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge, QRhiSampler::Repeat });
541 QSSGRhiShaderResourceBindingList bindings;
542 bindings.addTexture(0, QRhiShaderResourceBinding::FragmentStage, currentTexture, sampler);
543 QRhiShaderResourceBindings *srb = rhiCtxD->srb(bindings);
545 QSSGRhiGraphicsPipelineState ps;
546 ps.viewport = QRhiViewport(0, 0,
float(m_surfaceSize.width()),
float(m_surfaceSize.height()));
547 ps.viewCount = m_layer->viewCount;
548 QSSGRhiGraphicsPipelineStatePrivate::setShaderPipeline(ps, shaderPipeline.get());
550 renderer->rhiQuadRenderer()->recordRenderQuadPass(rhiCtx, &ps, srb, m_ssaaTextureToTextureRenderTarget, QSSGRhiQuadRenderer::UvCoords);
552 Q_QUICK3D_PROFILE_END_WITH_STRING(QQuick3DProfiler::Quick3DRenderPass, 0, QByteArrayLiteral(
"ssaa_downsample"));
554 currentTexture = m_texture;
557 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DRenderFrame,
558 STAT_PAYLOAD(QSSGRhiContextStats::get(*rhiCtx)),
562 m_renderStats->endRender(dumpRenderTimes());
563 Q_TRACE(QSSG_renderFrame_exit);
566 if (m_layer && m_layer->skyMaterial && m_layer->skyMaterial->wantsMoreFrames)
567 ++m_requestedFramesCount;
569 return currentTexture;
651 Q_TRACE_SCOPE(QSSG_synchronize, view3D, size, dpr);
653 Q_ASSERT(view3D !=
nullptr);
654 QSSGRhiContext *rhiCtx = m_sgContext->rhiContext().get();
655 Q_ASSERT(rhiCtx !=
nullptr);
659 m_layer =
new QSSGRenderLayer();
661 bool newRenderStats =
false;
662 if (!m_renderStats) {
663 m_renderStats = view3D->renderStats();
664 newRenderStats =
true;
668 m_renderStats->startSync();
670 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DSynchronizeFrame);
672 m_sgContext->renderer()->setDpr(dpr);
673 bool layerSizeIsDirty = m_surfaceSize != size;
674 m_surfaceSize = size;
676 QQuick3DSceneEnvironment *environment = view3D->environment();
677 if (environment->lightmapper()) {
678 QQuick3DLightmapper *lightmapper = environment->lightmapper();
679 lmOptions.opacityThreshold = lightmapper->opacityThreshold();
680 lmOptions.bias = lightmapper->bias();
681 lmOptions.useAdaptiveBias = lightmapper->isAdaptiveBiasEnabled();
682 lmOptions.indirectLightEnabled = lightmapper->isIndirectLightEnabled();
683 lmOptions.indirectLightSamples = lightmapper->samples();
684 lmOptions.indirectLightWorkgroupSize = lightmapper->indirectLightWorkgroupSize();
685 lmOptions.indirectLightBounces = lightmapper->bounces();
686 lmOptions.indirectLightFactor = lightmapper->indirectLightFactor();
687 lmOptions.sigma = lightmapper->denoiseSigma();
688 lmOptions.texelsPerUnit = lightmapper->texelsPerUnit();
694 if (environment->m_dirtyFlags & QQuick3DSceneEnvironment::InternalDirtyFlag::LightmapperDirty) {
695 environment->m_dirtyFlags &= ~QQuick3DSceneEnvironment::InternalDirtyFlag::LightmapperDirty;
697 const QQmlContext *context = qmlContext(view3D);
698 const QUrl originalSource = environment->lightmapper() ? environment->lightmapper()->source()
699 : QUrl::fromLocalFile(QStringLiteral(
"lightmaps.bin"));
700 const auto resolvedUrl = context ? context->resolvedUrl(originalSource) : originalSource;
701 const auto qmlSource = QQmlFile::urlToLocalFileOrQrc(resolvedUrl);
702 const QString lightmapSource = qmlSource.isEmpty() ? originalSource.path() : qmlSource;
703 lmOptions.source = lightmapSource;
704 m_layer->lightmapSource = lightmapSource;
707 m_sgContext->bufferManager()->setLightmapSource(m_layer->lightmapSource);
708 if (QQuick3DSceneManager *sceneManager = QQuick3DObjectPrivate::get(view3D->scene())->sceneManager)
709 sceneManager->lightmapSourceTracker = { m_layer->lightmapSource,
true };
713 QSet<QSSGRenderGraphObject *> resourceLoaders;
714 QQuick3DWindowAttachment::SyncResult requestSharedUpdate = QQuick3DWindowAttachment::SyncResultFlag::None;
715 if (
auto window = view3D->window()) {
716 if (!winAttacment || winAttacment->window() != window)
717 winAttacment = QQuick3DSceneManager::getOrSetWindowAttachment(*window);
719 if (winAttacment && winAttacment->rci() != m_sgContext)
720 winAttacment->setRci(m_sgContext);
722 QSSGRenderRoot *rootNode = winAttacment->rootNode();
723 if (m_layer->rootNode != rootNode) {
724 Q_ASSERT(m_layer->rootNode ==
nullptr);
725 rootNode->addChild(*m_layer);
726 rootNode->setStartVersion(m_layer->h.version());
727 m_layer->ref(rootNode);
731 requestSharedUpdate |= winAttacment->synchronize(resourceLoaders);
735 QQuick3DNode *importScene = view3D->importScene();
737 QQuick3DSceneManager *importSceneManager = QQuick3DObjectPrivate::get(importScene)->sceneManager;
740 if (
auto window = importSceneManager->window(); window && window != view3D->window()) {
741 if (
auto winAttacment = importSceneManager->wattached) {
743 auto rci = winAttacment->rci();
744 const bool inlineSync = (rci && rci->rhi() && (rci->rhi()->thread() == m_sgContext->rhi()->thread()));
748 winAttacment->synchronize(resourceLoaders);
749 }
else if (rci && !window->isExposed()) {
751 winAttacment->synchronize(resourceLoaders);
752 }
else if (!rci || (requestSharedUpdate & QQuick3DWindowAttachment::SyncResultFlag::SharedResourcesDirty)) {
757 winAttacment->requestUpdate();
770 m_layer->viewCount = rhiCtx->mainPassViewCount();
771 updateLayerNode(*m_layer, *view3D, resourceLoaders.values());
775 m_requestedFramesCount = 0;
776 if (m_layer->isProgressiveAAEnabled() || m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector) {
783 m_requestedFramesCount = (m_layer->temporalAAMode == QSSGRenderLayer::TAAMode::MotionVector ? 45 :
784 int(m_layer->antialiasingQuality) + 1);
785 }
else if (m_layer->isTemporalAAEnabled()) {
790 m_requestedFramesCount = (m_aaIsDirty || m_temporalIsDirty) ? QSSGLayerRenderData::MAX_TEMPORAL_AA_LEVELS : 1;
795 for (QSSGRenderEffect *effectNode = m_layer->firstEffect; effectNode; effectNode = effectNode->m_nextEffect)
796 effectNode->finalizeShaders(*m_layer, m_sgContext.get());
803 if (QQuick3DSceneManager *sm = QQuick3DObjectPrivate::get(view3D->scene())->sceneManager; sm) {
804 for (QSSGRenderUserPass *userPass : std::as_const(sm->userRenderPasses))
805 userPass->role = QSSGRenderUserPass::Role::TopLevel;
806 for (QSSGRenderUserPass *userPass : std::as_const(sm->userRenderPasses)) {
807 for (
const QSSGCommand *cmd : std::as_const(userPass->commands)) {
808 if (cmd->m_type != CommandType::SubRenderPass)
810 const auto *subCmd =
static_cast<
const QSSGSubRenderPass *>(cmd);
811 if (subCmd->m_userPassId == QSSGResourceId::Invalid)
813 if (
auto *subPass = QSSGRenderGraphObjectUtils::getResource<QSSGRenderUserPass>(subCmd->m_userPassId))
814 subPass->role = QSSGRenderUserPass::Role::SubPass;
818 QSSGUserRenderPassManagerPtr upm;
819 if (m_layer->renderData)
820 upm = m_layer->renderData->requestUserRenderPassManager();
822 for (QSSGRenderUserPass *userPass : std::as_const(sm->userRenderPasses)) {
823 if (userPass->role == QSSGRenderUserPass::Role::TopLevel)
824 upm->unscheduleUserPass(userPass);
827 for (QSSGRenderUserPass *userPass : std::as_const(sm->userRenderPasses)) {
828 userPass->finalizeShaders(*m_sgContext);
829 if (upm && userPass->role == QSSGRenderUserPass::Role::TopLevel)
830 upm->scheduleUserPass(userPass);
835 m_renderStats->setRhiContext(rhiCtx, m_layer);
837 static const auto getStageIndex = [](
const QSSGRenderExtension &ext) -> size_t {
838 const QSSGRenderExtension::RenderMode mode = ext.mode();
839 const QSSGRenderExtension::RenderStage stage = ext.stage();
842 if (mode == QSSGRenderExtension::RenderMode::Standalone)
843 return size_t(QSSGRenderLayer::RenderExtensionStage::TextureProviders);
846 case QSSGRenderExtension::RenderStage::PreColor:
847 return size_t(QSSGRenderLayer::RenderExtensionStage::Underlay);
848 case QSSGRenderExtension::RenderStage::PostColor:
849 return size_t(QSSGRenderLayer::RenderExtensionStage::Overlay);
852 Q_UNREACHABLE_RETURN(size_t(QSSGRenderLayer::RenderExtensionStage::Underlay));
858 if (QQuick3DSceneManager *sm = QQuick3DObjectPrivate::get(view3D->scene())->sceneManager; sm) {
859 const bool rebuildExtensionLists = (requestSharedUpdate & QQuick3DWindowAttachment::SyncResultFlag::ExtensionsDiry)
860 || view3D->extensionListDirty()
861 || sm->autoRegisteredExtensionsDirty;
866 if (rebuildExtensionLists) {
868 for (size_t i = 0; i != size_t(QSSGRenderLayer::RenderExtensionStage::Count); ++i)
869 m_layer->renderExtensions[i].clear();
872 const auto &extensions = view3D->extensionList();
873 for (
const auto &ext : extensions) {
874 const auto type = QQuick3DObjectPrivate::get(ext)->type;
875 if (QSSGRenderGraphObject::isExtension(type)) {
876 if (type == QSSGRenderGraphObject::Type::RenderExtension) {
877 if (
auto *renderExt = qobject_cast<QQuick3DRenderExtension *>(ext)) {
878 if (QSSGRenderExtension *ssgExt =
static_cast<QSSGRenderExtension *>(QQuick3DObjectPrivate::get(renderExt)->spatialNode)) {
879 const auto stage = getStageIndex(*ssgExt);
880 auto &list = m_layer->renderExtensions[size_t(stage)];
881 bfs(qobject_cast<QQuick3DRenderExtension *>(ext), list);
888 view3D->clearExtensionListDirty();
892 if (sm->autoRegisteredExtensionsDirty) {
893 for (QSSGRenderExtension *ae : std::as_const(sm->autoRegisteredExtensions))
894 m_layer->renderExtensions[getStageIndex(*ae)].push_back(ae);
895 sm->autoRegisteredExtensionsDirty =
false;
899 bool postProcessingNeeded = m_layer->firstEffect;
900 bool postProcessingWasActive = m_effectSystem;
901 QSSGRenderTextureFormat::Format effectOutputFormatOverride = QSSGRenderTextureFormat::Unknown;
902 if (postProcessingNeeded) {
903 QSSGRenderEffect *lastEffect = m_layer->firstEffect;
904 while (lastEffect->m_nextEffect)
905 lastEffect = lastEffect->m_nextEffect;
906 effectOutputFormatOverride = QSSGRhiEffectSystem::overriddenOutputFormat(lastEffect);
908 const auto layerTextureFormat = [effectOutputFormatOverride, view3D](QRhi *rhi,
bool postProc) {
909 if (effectOutputFormatOverride != QSSGRenderTextureFormat::Unknown)
910 return QSSGBufferManager::toRhiFormat(effectOutputFormatOverride);
925 const QRhiTexture::Format preferredPostProcFormat = QRhiTexture::RGBA16F;
926 if (postProc && rhi->isTextureFormatSupported(preferredPostProcFormat))
927 return preferredPostProcFormat;
929#if QT_CONFIG(quick_shadereffect)
930 const QRhiTexture::Format preferredView3DFormat = toRhiTextureFormat(view3D->renderFormat());
931 if (rhi->isTextureFormatSupported(preferredView3DFormat))
932 return preferredView3DFormat;
935 return QRhiTexture::RGBA8;
937 bool postProcessingStateDirty = postProcessingNeeded != postProcessingWasActive;
940 m_backgroundMode = QSSGRenderLayer::Background(view3D->environment()->backgroundMode());
944 QColor currentUserBackgroundColor = view3D->environment()->clearColor();
945 if (m_userBackgroundColor != currentUserBackgroundColor) {
946 m_userBackgroundColor = currentUserBackgroundColor;
947 m_linearBackgroundColor = QSSGUtils::color::sRGBToLinearColor(m_userBackgroundColor);
948 const QVector3D tc = tonemapRgb(QVector3D(m_linearBackgroundColor.redF(),
949 m_linearBackgroundColor.greenF(),
950 m_linearBackgroundColor.blueF()),
951 view3D->environment()->tonemapMode());
952 m_tonemappedBackgroundColor = QColor::fromRgbF(tc.x(), tc.y(), tc.z(), m_linearBackgroundColor.alphaF());
954 m_layer->scissorRect = QRect(view3D->environment()->scissorRect().topLeft() * dpr,
955 view3D->environment()->scissorRect().size() * dpr);
961 auto sceneRootNode =
static_cast<QSSGRenderNode*>(QQuick3DObjectPrivate::get(view3D->scene())->spatialNode);
962 if (sceneRootNode != m_sceneRootNode) {
964 removeNodeFromLayer(m_sceneRootNode);
967 addNodeToLayer(sceneRootNode);
969 m_sceneRootNode = sceneRootNode;
973 QSSGRenderNode *importSceneRootNode =
nullptr;
975 importSceneRootNode =
static_cast<QSSGRenderNode*>(QQuick3DObjectPrivate::get(importScene)->spatialNode);
977 if (importSceneRootNode != m_importSceneRootNode) {
978 if (m_importSceneRootNode)
979 m_layer->removeImportScene(*m_importSceneRootNode);
981 if (importSceneRootNode) {
985 QObject *sceneParent = importScene->parent();
986 bool isEmbedded =
false;
987 while (sceneParent) {
988 if (sceneParent == view3D) {
992 sceneParent = sceneParent->parent();
995 m_layer->setImportScene(*importSceneRootNode);
998 m_importSceneRootNode = importSceneRootNode;
1006 QSSGRenderRoot *rootNode = winAttacment->rootNode();
1007 if (rootNode->isDirty(QSSGRenderRoot::DirtyFlag::TreeDirty)) {
1008 rootNode->reindex();
1012 if (QQuick3DSceneManager *sm = QQuick3DObjectPrivate::get(view3D->scene())->sceneManager; sm) {
1013 for (QSSGRenderUserPass *userPass : std::as_const(sm->userRenderPasses)) {
1014 if (
const auto *fo = sm->lookUpNode(userPass); fo && fo->parentItem()) {
1015 const auto *pi = fo->parentItem();
1016 if (
const QSSGRenderGraphObject *parentNode = QQuick3DObjectPrivate::get(pi)->spatialNode; parentNode && QSSGRenderGraphObject::isNodeType(parentNode->type))
1017 userPass->setDependencyIndex(
static_cast<
const QSSGRenderNode *>(parentNode)->h.index());
1019 userPass->setDependencyIndex(0);
1026 maybeSetupLightmapBaking(view3D);
1028 if (m_useFBO && rhiCtx->isValid()) {
1029 QRhi *rhi = rhiCtx->rhi();
1030 const QSize renderSize = m_layer->isSsaaEnabled() ? m_surfaceSize * m_layer->ssaaMultiplier : m_surfaceSize;
1034 if (layerSizeIsDirty || postProcessingStateDirty) {
1035 m_texture->setPixelSize(m_surfaceSize);
1036 m_texture->setFormat(layerTextureFormat(rhi, postProcessingNeeded));
1037 m_texture->create();
1048 if (postProcessingStateDirty && (m_layer->antialiasingMode != QSSGRenderLayer::AAMode::NoAA || m_layer->isTemporalAAEnabled())) {
1049 releaseAaDependentRhiResources();
1051 if (m_ssaaTexture) {
1052 m_ssaaTexture->setPixelSize(renderSize);
1053 m_ssaaTexture->create();
1055 if (m_depthStencilBuffer) {
1056 m_depthStencilBuffer->setPixelSize(renderSize);
1057 m_depthStencilBuffer->create();
1059 if (m_multiViewDepthStencilBuffer) {
1060 m_multiViewDepthStencilBuffer->setPixelSize(renderSize);
1061 m_multiViewDepthStencilBuffer->create();
1063 if (m_msaaRenderBufferLegacy) {
1064 m_msaaRenderBufferLegacy->setPixelSize(renderSize);
1065 m_msaaRenderBufferLegacy->create();
1067 if (m_msaaRenderTexture) {
1068 m_msaaRenderTexture->setPixelSize(renderSize);
1069 m_msaaRenderTexture->create();
1071 if (m_msaaMultiViewRenderBuffer) {
1072 m_msaaMultiViewRenderBuffer->setPixelSize(renderSize);
1073 m_msaaMultiViewRenderBuffer->create();
1079 if (postProcessingStateDirty) {
1080 delete m_textureRenderPassDescriptor;
1081 m_textureRenderPassDescriptor = m_textureRenderTarget->newCompatibleRenderPassDescriptor();
1082 m_textureRenderTarget->setRenderPassDescriptor(m_textureRenderPassDescriptor);
1084 m_textureRenderTarget->create();
1085 if (m_ssaaTextureToTextureRenderTarget)
1086 m_ssaaTextureToTextureRenderTarget->create();
1088 if (m_temporalAATexture) {
1089 m_temporalAATexture->setPixelSize(renderSize);
1090 m_temporalAATexture->create();
1092 if (m_prevTempAATexture) {
1093 m_prevTempAATexture->setPixelSize(renderSize);
1094 m_prevTempAATexture->create();
1096 if (m_temporalAARenderTarget)
1097 m_temporalAARenderTarget->create();
1100 }
else if (m_aaIsDirty && rhi->backend() == QRhi::Metal) {
1101 m_texture->create();
1105 releaseAaDependentRhiResources();
1108 const QRhiTexture::Flags textureFlags = QRhiTexture::RenderTarget
1109 | QRhiTexture::UsedAsTransferSource;
1110 const QRhiTexture::Format textureFormat = layerTextureFormat(rhi, postProcessingNeeded);
1113 if (m_layer->viewCount >= 2)
1114 m_texture = rhi->newTextureArray(textureFormat, m_layer->viewCount, m_surfaceSize, 1, textureFlags);
1116 m_texture = rhi->newTexture(textureFormat, m_surfaceSize, 1, textureFlags);
1117 m_texture->create();
1120 if (!m_ssaaTexture && m_layer->isSsaaEnabled()) {
1121 if (m_layer->viewCount >= 2)
1122 m_ssaaTexture = rhi->newTextureArray(textureFormat, m_layer->viewCount, renderSize, 1, textureFlags);
1124 m_ssaaTexture = rhi->newTexture(textureFormat, renderSize, 1, textureFlags);
1125 m_ssaaTexture->create();
1128 if (m_timeBasedAA && !m_temporalAATexture) {
1129 m_temporalAATexture = rhi->newTexture(textureFormat, renderSize, 1, textureFlags);
1130 m_temporalAATexture->create();
1131 m_prevTempAATexture = rhi->newTexture(textureFormat, renderSize, 1, textureFlags);
1132 m_prevTempAATexture->create();
1136 if (m_aaIsDirty || layerSizeIsDirty)
1137 m_layer->tempAAPassIndex = m_layer->progAAPassIndex = 0;
1141 if (m_layer->antialiasingMode == QSSGRenderLayer::AAMode::MSAA) {
1142 if (rhi->isFeatureSupported(QRhi::MultisampleRenderBuffer)) {
1143 m_samples = qMax(1,
int(m_layer->antialiasingQuality));
1149 const QVector<
int> supported = rhi->supportedSampleCounts();
1150 if (!supported.contains(m_samples)) {
1151 if (!supported.isEmpty()) {
1152 auto it = std::lower_bound(supported.cbegin(), supported.cend(), m_samples);
1153 m_samples = it == supported.cend() ? supported.last() : *it;
1159 static bool warned =
false;
1162 qWarning(
"Multisample renderbuffers are not supported, disabling MSAA for Offscreen View3D");
1168 if (m_layer->viewCount >= 2) {
1169 if (!m_multiViewDepthStencilBuffer) {
1170 const auto format = rhi->isTextureFormatSupported(QRhiTexture::D24S8) ? QRhiTexture::D24S8 : QRhiTexture::D32FS8;
1171 m_multiViewDepthStencilBuffer = rhi->newTextureArray(format, m_layer->viewCount, renderSize,
1172 m_samples, QRhiTexture::RenderTarget);
1173 m_multiViewDepthStencilBuffer->create();
1176 if (!m_depthStencilBuffer) {
1177 m_depthStencilBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, renderSize, m_samples);
1178 m_depthStencilBuffer->create();
1182 if (!m_textureRenderTarget) {
1183 QRhiTextureRenderTargetDescription rtDesc;
1184 QRhiColorAttachment att;
1185 if (m_samples > 1) {
1186 if (m_layer->viewCount >= 2) {
1187 m_msaaMultiViewRenderBuffer = rhi->newTextureArray(textureFormat, m_layer->viewCount, renderSize, m_samples, QRhiTexture::RenderTarget);
1188 m_msaaMultiViewRenderBuffer->create();
1189 att.setTexture(m_msaaMultiViewRenderBuffer);
1191 if (!rhi->isFeatureSupported(QRhi::MultisampleTexture)) {
1193 m_msaaRenderBufferLegacy = rhi->newRenderBuffer(QRhiRenderBuffer::Color, renderSize, m_samples, {}, m_texture->format());
1194 m_msaaRenderBufferLegacy->create();
1195 att.setRenderBuffer(m_msaaRenderBufferLegacy);
1202 m_msaaRenderTexture = rhi->newTexture(textureFormat, renderSize, m_samples, QRhiTexture::RenderTarget);
1203 m_msaaRenderTexture->create();
1204 att.setTexture(m_msaaRenderTexture);
1207 att.setResolveTexture(m_texture);
1209 if (m_layer->antialiasingMode == QSSGRenderLayer::AAMode::SSAA)
1210 att.setTexture(m_ssaaTexture);
1212 att.setTexture(m_texture);
1214 att.setMultiViewCount(m_layer->viewCount);
1215 rtDesc.setColorAttachments({ att });
1216 if (m_depthStencilBuffer)
1217 rtDesc.setDepthStencilBuffer(m_depthStencilBuffer);
1218 if (m_multiViewDepthStencilBuffer)
1219 rtDesc.setDepthTexture(m_multiViewDepthStencilBuffer);
1221 m_textureRenderTarget = rhi->newTextureRenderTarget(rtDesc);
1222 m_textureRenderTarget->setName(QByteArrayLiteral(
"View3D"));
1223 m_textureRenderPassDescriptor = m_textureRenderTarget->newCompatibleRenderPassDescriptor();
1224 m_textureRenderTarget->setRenderPassDescriptor(m_textureRenderPassDescriptor);
1225 m_textureRenderTarget->create();
1228 if (!m_ssaaTextureToTextureRenderTarget && m_layer->antialiasingMode == QSSGRenderLayer::AAMode::SSAA) {
1229 QRhiColorAttachment att(m_texture);
1230 att.setMultiViewCount(m_layer->viewCount);
1231 m_ssaaTextureToTextureRenderTarget = rhi->newTextureRenderTarget(QRhiTextureRenderTargetDescription({ att }));
1232 m_ssaaTextureToTextureRenderTarget->setName(QByteArrayLiteral(
"SSAA texture"));
1233 m_ssaaTextureToTextureRenderPassDescriptor = m_ssaaTextureToTextureRenderTarget->newCompatibleRenderPassDescriptor();
1234 m_ssaaTextureToTextureRenderTarget->setRenderPassDescriptor(m_ssaaTextureToTextureRenderPassDescriptor);
1235 m_ssaaTextureToTextureRenderTarget->create();
1238 if (m_layer->firstEffect) {
1239 if (!m_effectSystem)
1240 m_effectSystem =
new QSSGRhiEffectSystem(m_sgContext);
1241 m_effectSystem->setup(renderSize);
1242 }
else if (m_effectSystem) {
1243 delete m_effectSystem;
1244 m_effectSystem =
nullptr;
1247 if (m_timeBasedAA && !m_temporalAARenderTarget) {
1248 m_temporalAARenderTarget = rhi->newTextureRenderTarget({ m_temporalAATexture });
1249 m_temporalAARenderTarget->setName(QByteArrayLiteral(
"Temporal AA texture"));
1250 m_temporalAARenderPassDescriptor = m_temporalAARenderTarget->newCompatibleRenderPassDescriptor();
1251 m_temporalAARenderTarget->setRenderPassDescriptor(m_temporalAARenderPassDescriptor);
1252 m_temporalAARenderTarget->create();
1255 m_textureNeedsFlip = rhi->isYUpInFramebuffer();
1256 m_aaIsDirty =
false;
1260 m_renderStats->endSync(dumpRenderTimes());
1262 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DSynchronizeFrame, quint64(m_surfaceSize.width()) | quint64(m_surfaceSize.height()) << 32, profilingId);