Add support for rendering percentage scale with upscaling to backbuffer
This commit is contained in:
@@ -90,7 +90,7 @@ GPUTexture* RenderBuffers::RequestHalfResDepth(GPUContext* context)
|
||||
}
|
||||
|
||||
// Generate depth
|
||||
MultiScaler::Instance()->DownscaleDepth(context, halfDepthWidth, halfDepthHeight, DepthBuffer->View(), HalfResDepth->View());
|
||||
MultiScaler::Instance()->DownscaleDepth(context, halfDepthWidth, halfDepthHeight, DepthBuffer, HalfResDepth->View());
|
||||
|
||||
return HalfResDepth;
|
||||
}
|
||||
|
||||
@@ -296,13 +296,27 @@ void SceneRenderTask::OnPostRender(GPUContext* context, RenderContext& renderCon
|
||||
|
||||
Viewport SceneRenderTask::GetViewport() const
|
||||
{
|
||||
Viewport viewport;
|
||||
if (Output)
|
||||
viewport = Viewport(0, 0, static_cast<float>(Output->Width()), static_cast<float>(Output->Height()));
|
||||
else if (SwapChain)
|
||||
viewport = Viewport(0, 0, static_cast<float>(SwapChain->GetWidth()), static_cast<float>(SwapChain->GetHeight()));
|
||||
else if (Buffers != nullptr)
|
||||
viewport = Buffers->GetViewport();
|
||||
else
|
||||
viewport = Viewport(0, 0, 1280, 720);
|
||||
viewport.Width *= RenderingPercentage;
|
||||
viewport.Height *= RenderingPercentage;
|
||||
return viewport;
|
||||
}
|
||||
|
||||
Viewport SceneRenderTask::GetOutputViewport() const
|
||||
{
|
||||
if (Output && Output->IsAllocated())
|
||||
return Viewport(0, 0, static_cast<float>(Output->Width()), static_cast<float>(Output->Height()));
|
||||
if (SwapChain)
|
||||
return Viewport(0, 0, static_cast<float>(SwapChain->GetWidth()), static_cast<float>(SwapChain->GetHeight()));
|
||||
if (Buffers != nullptr)
|
||||
return Buffers->GetViewport();
|
||||
return Viewport(0, 0, 1280, 720);
|
||||
return GetViewport();
|
||||
}
|
||||
|
||||
GPUTextureView* SceneRenderTask::GetOutputView() const
|
||||
@@ -352,11 +366,11 @@ void SceneRenderTask::OnBegin(GPUContext* context)
|
||||
// Setup render buffers for the output rendering resolution
|
||||
if (Output)
|
||||
{
|
||||
Buffers->Init(Output->Width(), Output->Height());
|
||||
Buffers->Init((int32)((float)Output->Width() * RenderingPercentage), (int32)((float)Output->Height() * RenderingPercentage));
|
||||
}
|
||||
else if (SwapChain)
|
||||
{
|
||||
Buffers->Init(SwapChain->GetWidth(), SwapChain->GetHeight());
|
||||
Buffers->Init((int32)((float)SwapChain->GetWidth() * RenderingPercentage), (int32)((float)SwapChain->GetHeight() * RenderingPercentage));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,7 +399,7 @@ bool SceneRenderTask::Resize(int32 width, int32 height)
|
||||
{
|
||||
if (Output && Output->Resize(width, height))
|
||||
return true;
|
||||
if (Buffers && Buffers->Init(width, height))
|
||||
if (Buffers && Buffers->Init((int32)((float)width * RenderingPercentage), (int32)((float)height * RenderingPercentage)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -423,7 +437,7 @@ void MainRenderTask::OnBegin(GPUContext* context)
|
||||
#if !USE_EDITOR
|
||||
// Sync render buffers size with the backbuffer
|
||||
const auto size = Screen::GetSize();
|
||||
Buffers->Init((int32)size.X, (int32)size.Y);
|
||||
Buffers->Init((int32)(size.X * RenderingPercentage), (int32)(size.Y * RenderingPercentage));
|
||||
#endif
|
||||
|
||||
SceneRenderTask::OnBegin(context);
|
||||
|
||||
@@ -263,6 +263,11 @@ public:
|
||||
/// </summary>
|
||||
API_FIELD() ActorsSources ActorsSource = ActorsSources::Scenes;
|
||||
|
||||
/// <summary>
|
||||
/// The scale of the rendering resolution relative to the output dimensions. If lower than 1 the scene and postprocessing will be rendered at a lower resolution and upscaled to the output backbuffer.
|
||||
/// </summary>
|
||||
API_FIELD() float RenderingPercentage = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The custom set of actors to render.
|
||||
/// </summary>
|
||||
@@ -336,10 +341,15 @@ public:
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets the rendering render task viewport.
|
||||
/// Gets the rendering render task viewport (before upsampling).
|
||||
/// </summary>
|
||||
API_PROPERTY() Viewport GetViewport() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the rendering output viewport (after upsampling).
|
||||
/// </summary>
|
||||
API_PROPERTY() Viewport GetOutputViewport() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the rendering output view.
|
||||
/// </summary>
|
||||
|
||||
@@ -326,12 +326,12 @@ void RenderList::RunCustomPostFxPass(GPUContext* context, RenderContext& renderC
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderList::HasAnyPostAA(RenderContext& renderContext) const
|
||||
bool RenderList::HasAnyPostFx(RenderContext& renderContext, PostProcessEffectLocation postProcess, MaterialPostFxLocation materialPostFx) const
|
||||
{
|
||||
for (int32 i = 0; i < Settings.PostFxMaterials.Materials.Count(); i++)
|
||||
{
|
||||
auto material = Settings.PostFxMaterials.Materials[i].Get();
|
||||
if (material && material->IsReady() && material->IsPostFx() && material->GetInfo().PostFxLocation == MaterialPostFxLocation::AfterAntiAliasingPass)
|
||||
if (material && material->IsReady() && material->IsPostFx() && material->GetInfo().PostFxLocation == materialPostFx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -341,7 +341,7 @@ bool RenderList::HasAnyPostAA(RenderContext& renderContext) const
|
||||
for (int32 i = 0; i < renderContext.List->PostFx.Count(); i++)
|
||||
{
|
||||
auto fx = renderContext.List->PostFx[i];
|
||||
if (fx->IsReady() && fx->GetLocation() == PostProcessEffectLocation::AfterAntiAliasingPass)
|
||||
if (fx->IsReady() && fx->GetLocation() == postProcess)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -489,11 +489,13 @@ public:
|
||||
void RunCustomPostFxPass(GPUContext* context, RenderContext& renderContext, PostProcessEffectLocation location, GPUTexture*& input, GPUTexture*& output);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether any Custom PostFx or Material PostFx has to be rendered after AA pass. Used to pick a faster rendering path by the frame rendering module.
|
||||
/// Determines whether any Custom PostFx or Material PostFx specified by given type. Used to pick a faster rendering path by the frame rendering module.
|
||||
/// </summary>
|
||||
/// <param name="renderContext">The rendering context.</param>
|
||||
/// <returns>True if render any postFx after AA, otherwise false.</returns>
|
||||
bool HasAnyPostAA(RenderContext& renderContext) const;
|
||||
/// <param name="postProcess">The PostFx location to check (for scripts).</param>
|
||||
/// <param name="materialPostFx">The PostFx location to check (for materials).</param>
|
||||
/// <returns>True if render any postFx of the given type, otherwise false.</returns>
|
||||
bool HasAnyPostFx(RenderContext& renderContext, PostProcessEffectLocation postProcess, MaterialPostFxLocation materialPostFx) const;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -332,7 +332,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
|
||||
// Render reflections debug view
|
||||
context->ResetRenderTarget();
|
||||
context->SetRenderTarget(task->GetOutputView());
|
||||
context->SetViewportAndScissors((float)renderContext.Buffers->GetWidth(), (float)renderContext.Buffers->GetHeight());
|
||||
context->SetViewportAndScissors(task->GetOutputViewport());
|
||||
context->Draw(lightBuffer->View());
|
||||
RenderTargetPool::Release(lightBuffer);
|
||||
return;
|
||||
@@ -349,7 +349,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
|
||||
{
|
||||
context->ResetRenderTarget();
|
||||
context->SetRenderTarget(task->GetOutputView());
|
||||
context->SetViewportAndScissors((float)renderContext.Buffers->GetWidth(), (float)renderContext.Buffers->GetHeight());
|
||||
context->SetViewportAndScissors(task->GetOutputViewport());
|
||||
GBufferPass::Instance()->RenderDebug(renderContext);
|
||||
RenderTargetPool::Release(lightBuffer);
|
||||
return;
|
||||
@@ -367,7 +367,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
|
||||
RenderTargetPool::Release(lightBuffer);
|
||||
context->ResetRenderTarget();
|
||||
context->SetRenderTarget(task->GetOutputView());
|
||||
context->SetViewportAndScissors((float)renderContext.Buffers->GetWidth(), (float)renderContext.Buffers->GetHeight());
|
||||
context->SetViewportAndScissors(task->GetOutputViewport());
|
||||
context->Draw(tempBuffer);
|
||||
return;
|
||||
}
|
||||
@@ -381,7 +381,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
|
||||
{
|
||||
context->ResetRenderTarget();
|
||||
context->SetRenderTarget(task->GetOutputView());
|
||||
context->SetViewportAndScissors((float)renderContext.Buffers->GetWidth(), (float)renderContext.Buffers->GetHeight());
|
||||
context->SetViewportAndScissors(task->GetOutputViewport());
|
||||
context->Draw(lightBuffer);
|
||||
RenderTargetPool::Release(lightBuffer);
|
||||
return;
|
||||
@@ -421,7 +421,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
|
||||
if (renderContext.View.Mode == ViewMode::NoPostFx || renderContext.View.Mode == ViewMode::Wireframe)
|
||||
{
|
||||
context->SetRenderTarget(task->GetOutputView());
|
||||
context->SetViewportAndScissors((float)renderContext.Buffers->GetWidth(), (float)renderContext.Buffers->GetHeight());
|
||||
context->SetViewportAndScissors(task->GetOutputViewport());
|
||||
context->Draw(forwardPassResult);
|
||||
return;
|
||||
}
|
||||
@@ -475,13 +475,13 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
|
||||
{
|
||||
context->ResetRenderTarget();
|
||||
context->SetRenderTarget(task->GetOutputView());
|
||||
context->SetViewportAndScissors((float)renderContext.Buffers->GetWidth(), (float)renderContext.Buffers->GetHeight());
|
||||
context->SetViewportAndScissors(task->GetOutputViewport());
|
||||
MotionBlurPass::Instance()->RenderDebug(renderContext, frameBuffer->View());
|
||||
return;
|
||||
}
|
||||
|
||||
// Anti Aliasing
|
||||
if (!renderContext.List->HasAnyPostAA(renderContext))
|
||||
if (!renderContext.List->HasAnyPostFx(renderContext, PostProcessEffectLocation::AfterAntiAliasingPass, MaterialPostFxLocation::AfterAntiAliasingPass) && Math::IsOne(task->RenderingPercentage))
|
||||
{
|
||||
// AA -> Back Buffer
|
||||
RenderAntiAliasingPass(renderContext, frameBuffer, task->GetOutputView());
|
||||
@@ -495,12 +495,17 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
|
||||
renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::AfterAntiAliasingPass, frameBuffer, tempBuffer);
|
||||
renderContext.List->RunMaterialPostFxPass(context, renderContext, MaterialPostFxLocation::AfterAntiAliasingPass, frameBuffer, tempBuffer);
|
||||
|
||||
// PostFx -> Back Buffer
|
||||
// PostFx -> (up-scaling) -> Back Buffer
|
||||
if (Math::IsOne(task->RenderingPercentage))
|
||||
{
|
||||
PROFILE_GPU("Copy frame");
|
||||
context->SetRenderTarget(task->GetOutputView());
|
||||
context->SetViewportAndScissors((float)renderContext.Buffers->GetWidth(), (float)renderContext.Buffers->GetHeight());
|
||||
context->SetViewportAndScissors(task->GetViewport());
|
||||
context->Draw(frameBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
MultiScaler::Instance()->Upscale(context, task->GetOutputViewport(), frameBuffer, task->GetOutputView());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,8 +187,8 @@ void ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPUTexture
|
||||
const bool useTemporal = settings.TemporalEffect && !renderContext.Task->IsCameraCut;
|
||||
|
||||
// Prepare resolutions for passes
|
||||
const int32 width = renderContext.Buffers->GetWidth();
|
||||
const int32 height = renderContext.Buffers->GetHeight();
|
||||
const int32 width = buffers->GetWidth();
|
||||
const int32 height = buffers->GetHeight();
|
||||
const int32 traceWidth = width / static_cast<int32>(settings.RayTracePassResolution);
|
||||
const int32 traceHeight = height / static_cast<int32>(settings.RayTracePassResolution);
|
||||
const int32 resolveWidth = width / static_cast<int32>(settings.RayTracePassResolution);
|
||||
@@ -262,7 +262,7 @@ void ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPUTexture
|
||||
const double integral = round(time / scale) * scale;
|
||||
data.TemporalTime = static_cast<float>(time - integral);
|
||||
|
||||
renderContext.Buffers->LastFrameTemporalSSR = Engine::FrameCount;
|
||||
buffers->LastFrameTemporalSSR = Engine::FrameCount;
|
||||
if (buffers->TemporalSSR == nullptr)
|
||||
{
|
||||
// Missing temporal buffer
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
#include "Engine/Graphics/Textures/GPUTexture.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
|
||||
MultiScaler::MultiScaler()
|
||||
: _psHalfDepth(nullptr)
|
||||
{
|
||||
}
|
||||
PACK_STRUCT(struct Data {
|
||||
Vector2 TexelSize;
|
||||
Vector2 Padding;
|
||||
});
|
||||
|
||||
String MultiScaler::ToString() const
|
||||
{
|
||||
@@ -21,6 +21,7 @@ bool MultiScaler::Init()
|
||||
_psBlur5.CreatePipelineStates();
|
||||
_psBlur9.CreatePipelineStates();
|
||||
_psBlur13.CreatePipelineStates();
|
||||
_psUpscale = GPUDevice::Instance->CreatePipelineState();
|
||||
|
||||
// Load asset
|
||||
_shader = Content::LoadAsyncInternal<Shader>(TEXT("Shaders/MultiScaler"));
|
||||
@@ -64,6 +65,12 @@ bool MultiScaler::setupResources()
|
||||
if (_psBlur13.Create(psDesc, shader, "PS_Blur13"))
|
||||
return true;
|
||||
}
|
||||
if (!_psUpscale->IsValid())
|
||||
{
|
||||
psDesc.PS = shader->GetPS("PS_Upscale");
|
||||
if (_psUpscale->Init(psDesc))
|
||||
return true;
|
||||
}
|
||||
if (!_psHalfDepth->IsValid())
|
||||
{
|
||||
psDesc.PS = shader->GetPS("PS_HalfDepth");
|
||||
@@ -84,6 +91,7 @@ void MultiScaler::Dispose()
|
||||
|
||||
// Cleanup
|
||||
SAFE_DELETE_GPU_RESOURCE(_psHalfDepth);
|
||||
SAFE_DELETE_GPU_RESOURCE(_psUpscale);
|
||||
_psBlur5.Delete();
|
||||
_psBlur9.Delete();
|
||||
_psBlur13.Delete();
|
||||
@@ -120,14 +128,14 @@ void MultiScaler::Filter(const FilterMode mode, GPUContext* context, const int32
|
||||
ps = &_psBlur13;
|
||||
break;
|
||||
default:
|
||||
CRASH;
|
||||
CRASH;
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare
|
||||
Data data;
|
||||
data.TexelSize.X = 1.0f / width;
|
||||
data.TexelSize.Y = 1.0f / height;
|
||||
data.TexelSize.X = 1.0f / (float)width;
|
||||
data.TexelSize.Y = 1.0f / (float)height;
|
||||
auto cb = _shader->GetShader()->GetCB(0);
|
||||
context->UpdateCB(cb, &data);
|
||||
context->BindCB(0, cb);
|
||||
@@ -176,7 +184,7 @@ void MultiScaler::Filter(const FilterMode mode, GPUContext* context, const int32
|
||||
ps = &_psBlur13;
|
||||
break;
|
||||
default:
|
||||
CRASH;
|
||||
CRASH;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -205,7 +213,7 @@ void MultiScaler::Filter(const FilterMode mode, GPUContext* context, const int32
|
||||
context->ResetRenderTarget();
|
||||
}
|
||||
|
||||
void MultiScaler::DownscaleDepth(GPUContext* context, int32 dstWidth, int32 dstHeight, GPUTextureView* src, GPUTextureView* dst)
|
||||
void MultiScaler::DownscaleDepth(GPUContext* context, int32 dstWidth, int32 dstHeight, GPUTexture* src, GPUTextureView* dst)
|
||||
{
|
||||
PROFILE_GPU_CPU("Downscale Depth");
|
||||
|
||||
@@ -219,8 +227,8 @@ void MultiScaler::DownscaleDepth(GPUContext* context, int32 dstWidth, int32 dstH
|
||||
|
||||
// Prepare
|
||||
Data data;
|
||||
data.TexelSize.X = 2.0f / (float)dstWidth;
|
||||
data.TexelSize.Y = 2.0f / (float)dstHeight;
|
||||
data.TexelSize.X = 1.0f / (float)src->Width();
|
||||
data.TexelSize.Y = 1.0f / (float)src->Height();
|
||||
auto cb = _shader->GetShader()->GetCB(0);
|
||||
context->UpdateCB(cb, &data);
|
||||
context->BindCB(0, cb);
|
||||
@@ -236,3 +244,31 @@ void MultiScaler::DownscaleDepth(GPUContext* context, int32 dstWidth, int32 dstH
|
||||
context->ResetRenderTarget();
|
||||
context->UnBindCB(0);
|
||||
}
|
||||
|
||||
void MultiScaler::Upscale(GPUContext* context, const Viewport& viewport, GPUTexture* src, GPUTextureView* dst)
|
||||
{
|
||||
PROFILE_GPU_CPU("Upscale");
|
||||
|
||||
context->SetViewportAndScissors(viewport);
|
||||
context->SetRenderTarget(dst);
|
||||
|
||||
if (checkIfSkipPass())
|
||||
{
|
||||
context->Draw(src);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data data;
|
||||
data.TexelSize.X = 1.0f / (float)src->Width();
|
||||
data.TexelSize.Y = 1.0f / (float)src->Height();
|
||||
auto cb = _shader->GetShader()->GetCB(0);
|
||||
context->UpdateCB(cb, &data);
|
||||
context->BindCB(0, cb);
|
||||
context->BindSR(0, src);
|
||||
context->SetState(_psUpscale);
|
||||
context->DrawFullscreenTriangle();
|
||||
context->UnBindCB(0);
|
||||
}
|
||||
|
||||
context->ResetRenderTarget();
|
||||
}
|
||||
|
||||
@@ -12,23 +12,12 @@ class MultiScaler : public RendererPass<MultiScaler>
|
||||
{
|
||||
private:
|
||||
|
||||
PACK_STRUCT(struct Data {
|
||||
Vector2 TexelSize;
|
||||
Vector2 Padding;
|
||||
});
|
||||
|
||||
AssetReference<Shader> _shader;
|
||||
GPUPipelineState* _psHalfDepth;
|
||||
GPUPipelineState* _psHalfDepth = nullptr;
|
||||
GPUPipelineStatePermutationsPs<2> _psBlur5;
|
||||
GPUPipelineStatePermutationsPs<2> _psBlur9;
|
||||
GPUPipelineStatePermutationsPs<2> _psBlur13;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Init
|
||||
/// </summary>
|
||||
MultiScaler();
|
||||
GPUPipelineState* _psUpscale = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
@@ -84,7 +73,16 @@ public:
|
||||
/// <param name="dstHeight">The height of the destination texture (in pixels).</param>
|
||||
/// <param name="src">The source texture.</param>
|
||||
/// <param name="dst">The destination texture.</param>
|
||||
void DownscaleDepth(GPUContext* context, int32 dstWidth, int32 dstHeight, GPUTextureView* src, GPUTextureView* dst);
|
||||
void DownscaleDepth(GPUContext* context, int32 dstWidth, int32 dstHeight, GPUTexture* src, GPUTextureView* dst);
|
||||
|
||||
/// <summary>
|
||||
/// Upscales the texture.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="viewport">The viewport of the destination texture.</param>
|
||||
/// <param name="src">The source texture.</param>
|
||||
/// <param name="dst">The destination texture.</param>
|
||||
void Upscale(GPUContext* context, const Viewport& viewport, GPUTexture* src, GPUTextureView* dst);
|
||||
|
||||
public:
|
||||
|
||||
@@ -96,6 +94,7 @@ public:
|
||||
void OnShaderReloading(Asset* obj)
|
||||
{
|
||||
_psHalfDepth->ReleaseGPU();
|
||||
_psUpscale->ReleaseGPU();
|
||||
_psBlur5.Release();
|
||||
_psBlur9.Release();
|
||||
_psBlur13.Release();
|
||||
|
||||
Reference in New Issue
Block a user