Optimize various rendering effects with GPUDrawPass

This commit is contained in:
2026-04-23 14:30:02 +02:00
parent c3ea883b21
commit 84b53bb9c8
9 changed files with 135 additions and 66 deletions
+6 -2
View File
@@ -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();
+12
View File
@@ -150,6 +150,18 @@ struct FLAXENGINE_API GPUDrawPass : GPUPass
Context->BeginDrawPass(*this);
}
GPUDrawPass(GPUContext* context, Span<GPUTextureView*> renderTargets, Span<GPUDrawPassAction> 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();
@@ -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);
@@ -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)
+5 -2
View File
@@ -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;
+6 -2
View File
@@ -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);
+50 -34
View File
@@ -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<float>(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);
@@ -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);
+36 -19
View File
@@ -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())
{