From 84b53bb9c83c0fe508cf98de247075df9447016e Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 23 Apr 2026 14:30:02 +0200 Subject: [PATCH] Optimize various rendering effects with `GPUDrawPass` --- Source/Engine/Graphics/GPUContext.cpp | 8 +- Source/Engine/Graphics/GPUPass.h | 12 +++ .../GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp | 3 +- .../Engine/Renderer/AmbientOcclusionPass.cpp | 7 +- Source/Engine/Renderer/AntiAliasing/FXAA.cpp | 7 +- Source/Engine/Renderer/ColorGradingPass.cpp | 8 +- Source/Engine/Renderer/PostProcessingPass.cpp | 84 +++++++++++-------- .../Renderer/ScreenSpaceReflectionsPass.cpp | 17 +++- Source/Engine/Renderer/Utils/MultiScaler.cpp | 55 +++++++----- 9 files changed, 135 insertions(+), 66 deletions(-) diff --git a/Source/Engine/Graphics/GPUContext.cpp b/Source/Engine/Graphics/GPUContext.cpp index bec817cb9..c7d40a964 100644 --- a/Source/Engine/Graphics/GPUContext.cpp +++ b/Source/Engine/Graphics/GPUContext.cpp @@ -95,8 +95,10 @@ void GPUContext::Draw(GPUTexture* dst, GPUTexture* src) ResetRenderTarget(); const float width = (float)dst->Width(); const float height = (float)dst->Height(); + auto rt = dst->View(); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(this, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); SetViewport(width, height); - SetRenderTarget(dst->View()); BindSR(0, src->View()); SetState(_device->GetCopyLinearPS()); DrawFullscreenTriangle(); @@ -108,8 +110,10 @@ void GPUContext::Draw(GPUTexture* dst, GPUTextureView* src) ResetRenderTarget(); const float width = (float)dst->Width(); const float height = (float)dst->Height(); + auto rt = dst->View(); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(this, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); SetViewport(width, height); - SetRenderTarget(dst->View()); BindSR(0, src); SetState(_device->GetCopyLinearPS()); DrawFullscreenTriangle(); diff --git a/Source/Engine/Graphics/GPUPass.h b/Source/Engine/Graphics/GPUPass.h index 7f98c15ce..3aaf9bf2f 100644 --- a/Source/Engine/Graphics/GPUPass.h +++ b/Source/Engine/Graphics/GPUPass.h @@ -150,6 +150,18 @@ struct FLAXENGINE_API GPUDrawPass : GPUPass Context->BeginDrawPass(*this); } + GPUDrawPass(GPUContext* context, Span renderTargets, Span renderTargetsActions) + : GPUPass(context) + , DepthBuffer(nullptr) + , RenderTargets(renderTargets.Get()) + , RenderTargetsActions(renderTargetsActions.Get()) + , RenderTargetsCount(renderTargets.Length()) + , DepthAction(GPUDrawPassAction::None) + { + ASSERT_LOW_LAYER(renderTargets.Length() == renderTargetsActions.Length()); + Context->BeginDrawPass(*this); + } + ~GPUDrawPass() { Context->EndDrawPass(); diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp index 4876e719a..de04158f0 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp @@ -447,7 +447,8 @@ void DeferredDeletionQueueVulkan::EnqueueGenericResource(Type type, uint64 handl uint32 GetHash(const RenderTargetLayoutVulkan& key) { uint32 hash = (int32)key.MSAA * 11; - CombineHash(hash, key.Flags); + CombineHash(hash, (uint32)(key.Flags & MAX_uint32)); + CombineHash(hash, (uint32)((key.Flags >> 32) & MAX_uint32)); CombineHash(hash, (uint32)key.DepthFormat * 93473262); CombineHash(hash, key.Extent.width); CombineHash(hash, key.Extent.height); diff --git a/Source/Engine/Renderer/AmbientOcclusionPass.cpp b/Source/Engine/Renderer/AmbientOcclusionPass.cpp index 341270a61..2766fe465 100644 --- a/Source/Engine/Renderer/AmbientOcclusionPass.cpp +++ b/Source/Engine/Renderer/AmbientOcclusionPass.cpp @@ -8,6 +8,7 @@ #include "Engine/Graphics/Graphics.h" #include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" +#include "Engine/Graphics/GPUPass.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderTools.h" @@ -482,7 +483,8 @@ void AmbientOcclusionPass::Render(RenderContext& renderContext) if (blurPasses == 0) rts = m_finalResults->View(pass); - context->SetRenderTarget(nullptr, rts); + GPUDrawPassAction rtsAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rts, 1), ToSpan(&rtsAction, 1)); context->BindSR(SSAO_TEXTURE_SLOT0, m_halfDepths[pass]); context->BindSR(SSAO_TEXTURE_SLOT1, renderContext.Buffers->GBuffer1); context->SetState(_psGenerate[settings.QualityLevel]); @@ -504,7 +506,8 @@ void AmbientOcclusionPass::Render(RenderContext& renderContext) if (i == (blurPasses - 1)) rts = m_finalResults->View(pass); - context->SetRenderTarget(nullptr, rts); + GPUDrawPassAction rtsAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rts, 1), ToSpan(&rtsAction, 1)); context->BindSR(SSAO_TEXTURE_SLOT0, pPingRT); if (settings.QualityLevel == 0) diff --git a/Source/Engine/Renderer/AntiAliasing/FXAA.cpp b/Source/Engine/Renderer/AntiAliasing/FXAA.cpp index 00dfb0cdd..2d5e40a14 100644 --- a/Source/Engine/Renderer/AntiAliasing/FXAA.cpp +++ b/Source/Engine/Renderer/AntiAliasing/FXAA.cpp @@ -4,6 +4,7 @@ #include "Engine/Content/Assets/Shader.h" #include "Engine/Content/Content.h" #include "Engine/Graphics/GPUContext.h" +#include "Engine/Graphics/GPUPass.h" #include "Engine/Graphics/Graphics.h" #include "Engine/Graphics/RenderTask.h" @@ -61,7 +62,9 @@ void FXAA::Dispose() void FXAA::Render(RenderContext& renderContext, GPUTexture* input, GPUTextureView* output) { auto context = GPUDevice::Instance->GetMainContext(); - context->SetRenderTarget(output); + + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&output, 1), ToSpan(&rtAction, 1)); if (checkIfSkipPass()) { // Resources are missing. Do not perform rendering, just copy input frame. @@ -69,7 +72,7 @@ void FXAA::Render(RenderContext& renderContext, GPUTexture* input, GPUTextureVie return; } PROFILE_GPU_CPU("Fast Approximate Antialiasing"); - + // Bind input Data data; data.ScreenSize = renderContext.View.ScreenSize; diff --git a/Source/Engine/Renderer/ColorGradingPass.cpp b/Source/Engine/Renderer/ColorGradingPass.cpp index c0b40d3f6..0f5134b6c 100644 --- a/Source/Engine/Renderer/ColorGradingPass.cpp +++ b/Source/Engine/Renderer/ColorGradingPass.cpp @@ -6,6 +6,7 @@ #include "Engine/Engine/Engine.h" #include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPULimits.h" +#include "Engine/Graphics/GPUPass.h" #include "Engine/Graphics/Graphics.h" #include "Engine/Graphics/RenderTargetPool.h" #include "Engine/Graphics/RenderTask.h" @@ -252,10 +253,12 @@ GPUTexture* ColorGradingPass::RenderLUT(RenderContext& renderContext) context->SetViewportAndScissors((float)lutDesc.Width, (float)lutDesc.Height); context->SetState(_psLut.Get((int32)toneMapping.Mode)); context->BindSR(0, lutTexture); + auto rtAction = GPUDrawPassAction::Store; #if GPU_ALLOW_GEOMETRY_SHADERS if (use3D) { - context->SetRenderTarget(colorGradingBuffer.LUT->ViewVolume()); + auto rt = colorGradingBuffer.LUT->ViewVolume(); + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); // Render one fullscreen-triangle per slice intersecting the bounds const int32 numInstances = lutDesc.Depth; @@ -264,7 +267,8 @@ GPUTexture* ColorGradingPass::RenderLUT(RenderContext& renderContext) else #endif { - context->SetRenderTarget(colorGradingBuffer.LUT->View()); + auto rt = colorGradingBuffer.LUT->View(); + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); context->DrawFullscreenTriangle(); } context->UnBindSR(0); diff --git a/Source/Engine/Renderer/PostProcessingPass.cpp b/Source/Engine/Renderer/PostProcessingPass.cpp index 206087303..da81f9744 100644 --- a/Source/Engine/Renderer/PostProcessingPass.cpp +++ b/Source/Engine/Renderer/PostProcessingPass.cpp @@ -9,6 +9,7 @@ #include "Engine/Graphics/RenderTools.h" #include "Engine/Graphics/RenderTargetPool.h" #include "Engine/Engine/Time.h" +#include "Engine/Graphics/GPUPass.h" #define GB_RADIUS 6 #define GB_KERNEL_SIZE (GB_RADIUS * 2 + 1) @@ -415,8 +416,9 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input, { const int32 mipWidth = w2 >> mip; const int32 mipHeight = h2 >> mip; - - context->SetRenderTarget(bloomBuffer1->View(0, mip)); + auto rt = bloomBuffer1->View(0, mip); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); context->SetViewportAndScissors((float)mipWidth, (float)mipHeight); context->BindSR(0, bloomBuffer1->View(0, mip - 1)); context->SetState(_psBloomDownsample); @@ -438,7 +440,9 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input, data.BloomLayer = static_cast(mip); context->UpdateCB(cb0, &data); - context->SetRenderTarget(bloomBuffer2->View(0, mip)); + auto rt = bloomBuffer2->View(0, mip); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); context->SetViewportAndScissors((float)mipWidth, (float)mipHeight); context->BindSR(0, upscaleBuffer->View(0, mip + 1)); context->BindSR(1, bloomBuffer1->View(0, mip + 1)); @@ -470,13 +474,17 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input, context->BindSR(6, GetCustomOrDefault(settings.LensFlares.LensColor, _defaultLensColor, TEXT("Engine/Textures/DefaultLensColor"))); // Render lens flares - context->SetRenderTarget(bloomBuffer2->View(0, 1)); - context->SetViewportAndScissors((float)w4, (float)h4); - context->BindSR(3, bloomBuffer1->View(0, 1)); // Use mip 1 of bloomBuffer1 as source - context->SetState(_psGenGhosts); - context->DrawFullscreenTriangle(); - context->ResetRenderTarget(); - context->UnBindSR(3); + { + auto rt = bloomBuffer2->View(0, 1); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); + context->SetViewportAndScissors((float)w4, (float)h4); + context->BindSR(3, bloomBuffer1->View(0, 1)); // Use mip 1 of bloomBuffer1 as source + context->SetState(_psGenGhosts); + context->DrawFullscreenTriangle(); + context->ResetRenderTarget(); + context->UnBindSR(3); + } // Gaussian blur kernel GaussianBlurData gbData; @@ -486,24 +494,32 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input, GB_ComputeKernel(2.0f, gbData.Size.X, gbData.Size.Y, GaussianBlurCacheH, GaussianBlurCacheV); // Gaussian blur H - Platform::MemoryCopy(gbData.GaussianBlurCache, GaussianBlurCacheH, sizeof(GaussianBlurCacheH)); - context->UpdateCB(cb1, &gbData); - context->BindCB(1, cb1); - context->SetRenderTarget(bloomBuffer1->View(0, 1)); - context->BindSR(0, bloomBuffer2->View(0, 1)); - context->SetState(_psBlurH); - context->DrawFullscreenTriangle(); - context->ResetRenderTarget(); + { + auto rt = bloomBuffer1->View(0, 1); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); + Platform::MemoryCopy(gbData.GaussianBlurCache, GaussianBlurCacheH, sizeof(GaussianBlurCacheH)); + context->UpdateCB(cb1, &gbData); + context->BindCB(1, cb1); + context->BindSR(0, bloomBuffer2->View(0, 1)); + context->SetState(_psBlurH); + context->DrawFullscreenTriangle(); + context->ResetRenderTarget(); + } // Gaussian blur V - Platform::MemoryCopy(gbData.GaussianBlurCache, GaussianBlurCacheV, sizeof(GaussianBlurCacheV)); - context->UpdateCB(cb1, &gbData); - context->BindCB(1, cb1); - context->SetRenderTarget(bloomBuffer2->View(0, 1)); - context->BindSR(0, bloomBuffer1->View(0, 1)); - context->SetState(_psBlurV); - context->DrawFullscreenTriangle(); - context->ResetRenderTarget(); + { + auto rt = bloomBuffer2->View(0, 1); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); + Platform::MemoryCopy(gbData.GaussianBlurCache, GaussianBlurCacheV, sizeof(GaussianBlurCacheV)); + context->UpdateCB(cb1, &gbData); + context->BindCB(1, cb1); + context->BindSR(0, bloomBuffer1->View(0, 1)); + context->SetState(_psBlurV); + context->DrawFullscreenTriangle(); + context->ResetRenderTarget(); + } // Set lens flares output context->BindSR(3, bloomBuffer2->View(0, 1)); @@ -516,10 +532,6 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input, //////////////////////////////////////////////////////////////////////////////////// // Final composite - // TODO: consider to use more compute shader for post processing - - // TODO: maybe don't use this rt swap and start using GetTempRt to make this design easier - // Check if use Tone Mapping + Color Grading LUT int32 compositePermutationIndex = 0; GPUTextureView* colorGradingLutView = nullptr; @@ -553,10 +565,14 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input, context->BindSR(7, colorGradingLutView); // Composite final frame during single pass (done in full resolution) - context->SetViewportAndScissors((float)output->Width(), (float)output->Height()); - context->SetRenderTarget(*output); - context->SetState(_psComposite.Get(compositePermutationIndex)); - context->DrawFullscreenTriangle(); + { + auto rt = output->View(); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); + context->SetViewportAndScissors((float)output->Width(), (float)output->Height()); + context->SetState(_psComposite.Get(compositePermutationIndex)); + context->DrawFullscreenTriangle(); + } // Cleanup RenderTargetPool::Release(bloomBuffer1); diff --git a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp index 1aa5d7a18..bb113fbc2 100644 --- a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp +++ b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp @@ -16,6 +16,7 @@ #include "Engine/Graphics/RenderTargetPool.h" #include "Engine/Graphics/RenderBuffers.h" #include "Engine/Graphics/GPUContext.h" +#include "Engine/Graphics/GPUPass.h" // Shader input texture slots mapping #define TEXTURE0 4 @@ -278,6 +279,9 @@ GPUTexture* ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPU // Combine pass { PROFILE_GPU("Combine"); + auto rt = colorBuffer0->View(0); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); context->BindSR(0, buffers->GBuffer0); context->BindSR(1, buffers->GBuffer1); context->BindSR(2, buffers->GBuffer2); @@ -286,7 +290,6 @@ GPUTexture* ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPU context->BindSR(TEXTURE1, reflectionsRT); context->BindSR(TEXTURE2, _preIntegratedGF->GetTexture()); context->SetViewportAndScissors((float)colorBufferWidth, (float)colorBufferHeight); - context->SetRenderTarget(colorBuffer0->View(0)); context->SetState(_psCombinePass); context->DrawFullscreenTriangle(); context->UnBindSR(TEXTURE1); @@ -324,8 +327,10 @@ GPUTexture* ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPU // Ray Trace Pass { PROFILE_GPU("RayTrace"); + auto rt = traceBuffer->View(); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); context->SetViewportAndScissors((float)traceWidth, (float)traceHeight); - context->SetRenderTarget(*traceBuffer); context->BindSR(3, depthBufferTrace); context->BindSR(TEXTURE0, colorBuffer0->View()); if (useGlobalSurfaceAtlas) @@ -347,8 +352,10 @@ GPUTexture* ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPU // Resolve Pass { PROFILE_GPU("Resolve"); + auto rt = resolveBuffer->View(); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); context->SetViewportAndScissors((float)resolveWidth, (float)resolveHeight); - context->SetRenderTarget(resolveBuffer->View()); context->BindSR(TEXTURE0, traceBuffer->View()); context->SetState(_psResolvePass.Get(resolvePassIndex)); context->DrawFullscreenTriangle(); @@ -381,7 +388,9 @@ GPUTexture* ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPU } else { - context->SetRenderTarget(newTemporal->View()); + auto rt = newTemporal->View(); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); context->BindSR(TEXTURE0, resolveBuffer); context->BindSR(TEXTURE1, buffers->TemporalSSR); context->BindSR(TEXTURE2, buffers->MotionVectors && buffers->MotionVectors->IsAllocated() ? buffers->MotionVectors->View() : nullptr); diff --git a/Source/Engine/Renderer/Utils/MultiScaler.cpp b/Source/Engine/Renderer/Utils/MultiScaler.cpp index acfe9b001..e878d1e5c 100644 --- a/Source/Engine/Renderer/Utils/MultiScaler.cpp +++ b/Source/Engine/Renderer/Utils/MultiScaler.cpp @@ -4,6 +4,7 @@ #include "Engine/Graphics/Textures/GPUTexture.h" #include "Engine/Graphics/GPUContext.h" #include "Engine/Content/Content.h" +#include "Engine/Graphics/GPUPass.h" GPU_CB_STRUCT(Data { Float2 TexelSize; @@ -142,20 +143,25 @@ void MultiScaler::Filter(FilterMode mode, GPUContext* context, int32 width, int3 auto cb = _shader->GetShader()->GetCB(0); context->UpdateCB(cb, &data); context->BindCB(0, cb); + auto rtAction = GPUDrawPassAction::Store; // Convolve horizontal - context->BindSR(0, src); - context->SetRenderTarget(tmp); - context->SetState(ps->Get(0)); - context->DrawFullscreenTriangle(); + { + GPUDrawPass drawPass(context, ToSpan(&tmp, 1), ToSpan(&rtAction, 1)); + context->BindSR(0, src); + context->SetState(ps->Get(0)); + context->DrawFullscreenTriangle(); + } context->ResetRenderTarget(); // Convolve vertical - context->BindSR(0, tmp); - context->SetRenderTarget(dst); - context->SetState(ps->Get(1)); - context->DrawFullscreenTriangle(); + { + GPUDrawPass drawPass(context, ToSpan(&dst, 1), ToSpan(&rtAction, 1)); + context->BindSR(0, tmp); + context->SetState(ps->Get(1)); + context->DrawFullscreenTriangle(); + } context->ResetRenderTarget(); } @@ -194,20 +200,26 @@ void MultiScaler::Filter(FilterMode mode, GPUContext* context, int32 width, int3 auto cb = _shader->GetShader()->GetCB(0); context->UpdateCB(cb, &data); context->BindCB(0, cb); + auto rtAction = GPUDrawPassAction::Store; // Convolve horizontal - context->BindSR(0, srcDst); - context->SetRenderTarget(tmp); - context->SetState(ps->Get(0)); - context->DrawFullscreenTriangle(); + { + GPUDrawPass drawPass(context, ToSpan(&tmp, 1), ToSpan(&rtAction, 1)); + context->BindSR(0, srcDst); + context->SetRenderTarget(tmp); + context->SetState(ps->Get(0)); + context->DrawFullscreenTriangle(); + } context->ResetRenderTarget(); // Convolve vertical - context->BindSR(0, tmp); - context->SetRenderTarget(srcDst); - context->SetState(ps->Get(1)); - context->DrawFullscreenTriangle(); + { + GPUDrawPass drawPass(context, ToSpan(&srcDst, 1), ToSpan(&rtAction, 1)); + context->BindSR(0, tmp); + context->SetState(ps->Get(1)); + context->DrawFullscreenTriangle(); + } context->ResetRenderTarget(); } @@ -266,8 +278,10 @@ void MultiScaler::BuildHiZ(GPUContext* context, GPUTexture* srcDepth, GPUTexture } else { + auto rt = dstHiZ->View(); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); context->SetViewportAndScissors((float)dstWidth, (float)dstHeight); - context->SetRenderTarget(dstHiZ->View()); context->BindSR(0, srcDepth); context->SetState(_psHalfDepth[2]); context->DrawFullscreenTriangle(); @@ -280,8 +294,10 @@ void MultiScaler::BuildHiZ(GPUContext* context, GPUTexture* srcDepth, GPUTexture const int32 mipHeight = Math::Max(dstHeight >> mip, 1); context->ResetRenderTarget(); + auto rt = dstHiZ->View(0, mip); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&rt, 1), ToSpan(&rtAction, 1)); context->SetViewportAndScissors((float)mipWidth, (float)mipHeight); - context->SetRenderTarget(dstHiZ->View(0, mip)); context->BindSR(0, dstHiZ->View(0, mip - 1)); context->SetState(_psHalfDepth[2]); context->DrawFullscreenTriangle(); @@ -295,8 +311,9 @@ void MultiScaler::Upscale(GPUContext* context, const Viewport& viewport, GPUText { PROFILE_GPU_CPU("Upscale"); + auto rtAction = GPUDrawPassAction::Store; + GPUDrawPass drawPass(context, ToSpan(&dst, 1), ToSpan(&rtAction, 1)); context->SetViewportAndScissors(viewport); - context->SetRenderTarget(dst); if (checkIfSkipPass()) {