|
|
|
@@ -128,6 +128,7 @@ void CPostprocManager::Cleanup()
|
|
|
|
|
m_PingFramebuffer.reset();
|
|
|
|
|
m_PongFramebuffer.reset();
|
|
|
|
|
|
|
|
|
|
m_PBROutputTexture.reset();
|
|
|
|
|
m_ColorTex1.reset();
|
|
|
|
|
m_ColorTex2.reset();
|
|
|
|
|
m_DepthTex.reset();
|
|
|
|
@@ -147,6 +148,9 @@ void CPostprocManager::Initialize()
|
|
|
|
|
if (m_IsInitialized)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (g_ConfigDB.Get("pbr", false))
|
|
|
|
|
InitializePBR();
|
|
|
|
|
|
|
|
|
|
const std::array<Renderer::Backend::SVertexAttributeFormat, 2> attributes{{
|
|
|
|
|
{Renderer::Backend::VertexAttributeStream::POSITION,
|
|
|
|
|
Renderer::Backend::Format::R32G32_SFLOAT, 0, sizeof(float) * 2,
|
|
|
|
@@ -183,6 +187,40 @@ void CPostprocManager::Initialize()
|
|
|
|
|
m_DownscaleComputeTech = g_Renderer.GetShaderManager().LoadEffect(CStrIntern("compute_downscale"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CPostprocManager::InitializePBR()
|
|
|
|
|
{
|
|
|
|
|
const bool PBRSupported{
|
|
|
|
|
m_Device->GetCapabilities().computeShaders &&
|
|
|
|
|
m_Device->IsFramebufferFormatSupported(Renderer::Backend::Format::R16G16B16A16_SFLOAT)};
|
|
|
|
|
if (!PBRSupported)
|
|
|
|
|
{
|
|
|
|
|
m_PBREnabled = false;
|
|
|
|
|
LOGWARNING("PBR is unsupported for the current renderer backend");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_FramebufferColorFormat = Renderer::Backend::Format::R16G16B16A16_SFLOAT;
|
|
|
|
|
const std::string framebufferFormatName{g_ConfigDB.Get("pbr.framebufferformat", std::string{})};
|
|
|
|
|
if (framebufferFormatName == "rgba32")
|
|
|
|
|
{
|
|
|
|
|
if (m_Device->IsFramebufferFormatSupported(Renderer::Backend::Format::R32G32B32A32_SFLOAT))
|
|
|
|
|
m_FramebufferColorFormat = Renderer::Backend::Format::R32G32B32A32_SFLOAT;
|
|
|
|
|
else
|
|
|
|
|
LOGWARNING("%s is unsupported", framebufferFormatName);
|
|
|
|
|
}
|
|
|
|
|
else if (framebufferFormatName == "r11g11b10")
|
|
|
|
|
{
|
|
|
|
|
if (m_Device->IsFramebufferFormatSupported(Renderer::Backend::Format::B10G11R11_UFLOAT))
|
|
|
|
|
m_FramebufferColorFormat = Renderer::Backend::Format::B10G11R11_UFLOAT;
|
|
|
|
|
else
|
|
|
|
|
LOGWARNING("%s is unsupported", framebufferFormatName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_ResolvePBRComputeTech = g_Renderer.GetShaderManager().LoadEffect(str_compute_resolve_pbr);
|
|
|
|
|
if (m_ResolvePBRComputeTech)
|
|
|
|
|
m_PBREnabled = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CPostprocManager::Resize()
|
|
|
|
|
{
|
|
|
|
|
RecalculateSize(g_Renderer.GetWidth(), g_Renderer.GetHeight());
|
|
|
|
@@ -196,21 +234,33 @@ void CPostprocManager::RecreateBuffers()
|
|
|
|
|
{
|
|
|
|
|
Cleanup();
|
|
|
|
|
|
|
|
|
|
#define GEN_BUFFER_RGBA(name, w, h) \
|
|
|
|
|
name = m_Device->CreateTexture2D( \
|
|
|
|
|
"PostProc" #name, \
|
|
|
|
|
Renderer::Backend::ITexture::Usage::SAMPLED | \
|
|
|
|
|
Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT | \
|
|
|
|
|
Renderer::Backend::ITexture::Usage::TRANSFER_SRC | \
|
|
|
|
|
Renderer::Backend::ITexture::Usage::TRANSFER_DST, \
|
|
|
|
|
Renderer::Backend::Format::R8G8B8A8_UNORM, w, h, \
|
|
|
|
|
Renderer::Backend::Sampler::MakeDefaultSampler( \
|
|
|
|
|
Renderer::Backend::Sampler::Filter::LINEAR, \
|
|
|
|
|
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE));
|
|
|
|
|
const auto defaultSampler{
|
|
|
|
|
Renderer::Backend::Sampler::MakeDefaultSampler(
|
|
|
|
|
Renderer::Backend::Sampler::Filter::LINEAR,
|
|
|
|
|
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)};
|
|
|
|
|
const uint32_t colorTextureUsage{
|
|
|
|
|
Renderer::Backend::ITexture::Usage::SAMPLED |
|
|
|
|
|
Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT |
|
|
|
|
|
Renderer::Backend::ITexture::Usage::TRANSFER_SRC |
|
|
|
|
|
Renderer::Backend::ITexture::Usage::TRANSFER_DST};
|
|
|
|
|
|
|
|
|
|
if (m_PBREnabled)
|
|
|
|
|
{
|
|
|
|
|
m_PBROutputTexture = m_Device->CreateTexture2D(
|
|
|
|
|
"PostProcPBROutput", colorTextureUsage,
|
|
|
|
|
m_FramebufferColorFormat,
|
|
|
|
|
m_Width, m_Height, defaultSampler);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Two fullscreen ping-pong textures.
|
|
|
|
|
GEN_BUFFER_RGBA(m_ColorTex1, m_Width, m_Height);
|
|
|
|
|
GEN_BUFFER_RGBA(m_ColorTex2, m_Width, m_Height);
|
|
|
|
|
m_ColorTex1 = m_Device->CreateTexture2D(
|
|
|
|
|
"PostProcColor1", colorTextureUsage | (m_PBREnabled ? Renderer::Backend::ITexture::Usage::STORAGE : 0),
|
|
|
|
|
Renderer::Backend::Format::R8G8B8A8_UNORM,
|
|
|
|
|
m_Width, m_Height, defaultSampler);
|
|
|
|
|
m_ColorTex2 = m_Device->CreateTexture2D(
|
|
|
|
|
"PostProcColor2", colorTextureUsage | (m_PBREnabled ? Renderer::Backend::ITexture::Usage::STORAGE : 0),
|
|
|
|
|
Renderer::Backend::Format::R8G8B8A8_UNORM,
|
|
|
|
|
m_Width, m_Height, defaultSampler);
|
|
|
|
|
|
|
|
|
|
if (m_UnscaledWidth != m_Width && m_Device->GetCapabilities().computeShaders)
|
|
|
|
|
{
|
|
|
|
@@ -257,7 +307,10 @@ void CPostprocManager::RecreateBuffers()
|
|
|
|
|
{
|
|
|
|
|
for (BlurScale::Step& step : scale.steps)
|
|
|
|
|
{
|
|
|
|
|
GEN_BUFFER_RGBA(step.texture, width, height);
|
|
|
|
|
step.texture = m_Device->CreateTexture2D(
|
|
|
|
|
"PostProcBlurStep", colorTextureUsage,
|
|
|
|
|
Renderer::Backend::Format::R8G8B8A8_UNORM,
|
|
|
|
|
width, height, defaultSampler);
|
|
|
|
|
Renderer::Backend::SColorAttachment colorAttachment{};
|
|
|
|
|
colorAttachment.texture = step.texture.get();
|
|
|
|
|
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::LOAD;
|
|
|
|
@@ -270,8 +323,6 @@ void CPostprocManager::RecreateBuffers()
|
|
|
|
|
height = std::max(1u, height / 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef GEN_BUFFER_RGBA
|
|
|
|
|
|
|
|
|
|
// Allocate the Depth/Stencil texture.
|
|
|
|
|
m_DepthTex = m_Device->CreateTexture2D("PostProcDepthTexture",
|
|
|
|
|
Renderer::Backend::ITexture::Usage::SAMPLED |
|
|
|
|
@@ -285,24 +336,14 @@ void CPostprocManager::RecreateBuffers()
|
|
|
|
|
Renderer::Backend::Sampler::Filter::LINEAR,
|
|
|
|
|
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE));
|
|
|
|
|
|
|
|
|
|
RecreateCaptureFramebuffer();
|
|
|
|
|
|
|
|
|
|
// Set up the framebuffers with some initial textures.
|
|
|
|
|
Renderer::Backend::SColorAttachment colorAttachment{};
|
|
|
|
|
colorAttachment.texture = m_ColorTex1.get();
|
|
|
|
|
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::DONT_CARE;
|
|
|
|
|
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
|
|
|
|
|
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
|
|
|
|
|
|
|
|
|
|
Renderer::Backend::SDepthStencilAttachment depthStencilAttachment{};
|
|
|
|
|
depthStencilAttachment.texture = m_DepthTex.get();
|
|
|
|
|
depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
|
|
|
|
|
depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
|
|
|
|
|
|
|
|
|
|
m_CaptureFramebuffer = m_Device->CreateFramebuffer("PostprocCaptureFramebuffer",
|
|
|
|
|
&colorAttachment, &depthStencilAttachment);
|
|
|
|
|
|
|
|
|
|
colorAttachment.texture = m_ColorTex1.get();
|
|
|
|
|
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::LOAD;
|
|
|
|
|
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
|
|
|
|
|
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
|
|
|
|
|
m_PingFramebuffer = m_Device->CreateFramebuffer("PostprocPingFramebuffer",
|
|
|
|
|
&colorAttachment, nullptr);
|
|
|
|
|
|
|
|
|
@@ -310,7 +351,7 @@ void CPostprocManager::RecreateBuffers()
|
|
|
|
|
m_PongFramebuffer = m_Device->CreateFramebuffer("PostprocPongFramebuffer",
|
|
|
|
|
&colorAttachment, nullptr);
|
|
|
|
|
|
|
|
|
|
if (!m_CaptureFramebuffer || !m_PingFramebuffer || !m_PongFramebuffer)
|
|
|
|
|
if (!m_PingFramebuffer || !m_PongFramebuffer)
|
|
|
|
|
{
|
|
|
|
|
LOGWARNING("Failed to create postproc framebuffers");
|
|
|
|
|
g_RenderingOptions.SetPostProc(false);
|
|
|
|
@@ -323,6 +364,28 @@ void CPostprocManager::RecreateBuffers()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CPostprocManager::RecreateCaptureFramebuffer()
|
|
|
|
|
{
|
|
|
|
|
Renderer::Backend::SColorAttachment colorAttachment{};
|
|
|
|
|
colorAttachment.texture = m_PBREnabled ? m_PBROutputTexture.get() : m_ColorTex1.get();
|
|
|
|
|
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::DONT_CARE;
|
|
|
|
|
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
|
|
|
|
|
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
|
|
|
|
|
|
|
|
|
|
Renderer::Backend::SDepthStencilAttachment depthStencilAttachment{};
|
|
|
|
|
depthStencilAttachment.texture = m_DepthTex.get();
|
|
|
|
|
depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
|
|
|
|
|
depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
|
|
|
|
|
|
|
|
|
|
m_CaptureFramebuffer = m_Device->CreateFramebuffer("PostprocCaptureFramebuffer",
|
|
|
|
|
&colorAttachment, m_UsingMultisampleBuffer ? nullptr : &depthStencilAttachment);
|
|
|
|
|
|
|
|
|
|
if (!m_CaptureFramebuffer)
|
|
|
|
|
{
|
|
|
|
|
LOGWARNING("Failed to create postproc capture framebuffer");
|
|
|
|
|
g_RenderingOptions.SetPostProc(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CPostprocManager::ApplyBlurDownscale2x(
|
|
|
|
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
|
|
|
@@ -698,17 +761,15 @@ void CPostprocManager::ApplyPostproc(
|
|
|
|
|
{
|
|
|
|
|
ENSURE(m_IsInitialized);
|
|
|
|
|
|
|
|
|
|
// Don't do anything if we are using the default effect and no AA.
|
|
|
|
|
const bool hasEffects{m_PostProcEffect != L"default"};
|
|
|
|
|
const bool hasAA{m_AATech};
|
|
|
|
|
const bool hasSharp{m_SharpTech};
|
|
|
|
|
if (!hasEffects && !hasAA && !hasSharp)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
PROFILE3_GPU(deviceCommandContext, "Render postproc");
|
|
|
|
|
GPU_SCOPED_LABEL(deviceCommandContext, "Render postproc");
|
|
|
|
|
|
|
|
|
|
if (hasEffects)
|
|
|
|
|
if (m_PBREnabled)
|
|
|
|
|
{
|
|
|
|
|
ResolvePBR(deviceCommandContext);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!m_PBREnabled && m_PostProcEffect != L"default")
|
|
|
|
|
{
|
|
|
|
|
// First render blur textures. Note that this only happens ONLY ONCE, before any effects are applied!
|
|
|
|
|
// (This may need to change depending on future usage, however that will have a fps hit)
|
|
|
|
@@ -717,13 +778,13 @@ void CPostprocManager::ApplyPostproc(
|
|
|
|
|
ApplyEffect(deviceCommandContext, m_PostProcTech, pass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hasAA)
|
|
|
|
|
if (m_AATech)
|
|
|
|
|
{
|
|
|
|
|
for (int pass = 0; pass < m_AATech->GetNumPasses(); ++pass)
|
|
|
|
|
ApplyEffect(deviceCommandContext, m_AATech, pass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hasSharp && !ShouldUpscale())
|
|
|
|
|
if (m_SharpTech && !ShouldUpscale())
|
|
|
|
|
{
|
|
|
|
|
for (int pass = 0; pass < m_SharpTech->GetNumPasses(); ++pass)
|
|
|
|
|
ApplyEffect(deviceCommandContext, m_SharpTech, pass);
|
|
|
|
@@ -815,6 +876,8 @@ void CPostprocManager::UpdateAntiAliasingTechnique()
|
|
|
|
|
m_UsingMultisampleBuffer = true;
|
|
|
|
|
CreateMultisampleBuffer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RecreateCaptureFramebuffer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CPostprocManager::UpdateSharpeningTechnique()
|
|
|
|
@@ -871,7 +934,7 @@ void CPostprocManager::CreateMultisampleBuffer()
|
|
|
|
|
Renderer::Backend::ITexture::Type::TEXTURE_2D_MULTISAMPLE,
|
|
|
|
|
Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT |
|
|
|
|
|
Renderer::Backend::ITexture::Usage::TRANSFER_SRC,
|
|
|
|
|
Renderer::Backend::Format::R8G8B8A8_UNORM, m_Width, m_Height,
|
|
|
|
|
m_FramebufferColorFormat, m_Width, m_Height,
|
|
|
|
|
Renderer::Backend::Sampler::MakeDefaultSampler(
|
|
|
|
|
Renderer::Backend::Sampler::Filter::LINEAR,
|
|
|
|
|
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1, m_MultisampleCount);
|
|
|
|
@@ -935,7 +998,42 @@ void CPostprocManager::ResolveMultisampleFramebuffer(
|
|
|
|
|
|
|
|
|
|
GPU_SCOPED_LABEL(deviceCommandContext, "Resolve postproc multisample");
|
|
|
|
|
deviceCommandContext->ResolveFramebuffer(
|
|
|
|
|
m_MultisampleFramebuffer.get(), m_PingFramebuffer.get());
|
|
|
|
|
m_MultisampleFramebuffer.get(),
|
|
|
|
|
m_PBREnabled ? m_CaptureFramebuffer.get() : m_PingFramebuffer.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CPostprocManager::ResolvePBR(
|
|
|
|
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
|
|
|
|
|
{
|
|
|
|
|
ENSURE(m_PBREnabled);
|
|
|
|
|
ENSURE(m_ResolvePBRComputeTech);
|
|
|
|
|
|
|
|
|
|
GPU_SCOPED_LABEL(deviceCommandContext, "Resolve PBR");
|
|
|
|
|
|
|
|
|
|
Renderer::Backend::IShaderProgram* shaderProgram{m_ResolvePBRComputeTech->GetShader()};
|
|
|
|
|
|
|
|
|
|
Renderer::Backend::ITexture* source{m_PBROutputTexture.get()};
|
|
|
|
|
Renderer::Backend::ITexture* destination{m_ColorTex1.get()};
|
|
|
|
|
|
|
|
|
|
const std::array<float, 4> screenSize{{
|
|
|
|
|
static_cast<float>(m_Width), static_cast<float>(m_Height),
|
|
|
|
|
1.0f / static_cast<float>(m_Width), 1.0f / static_cast<float>(m_Height)}};
|
|
|
|
|
|
|
|
|
|
constexpr uint32_t threadGroupWorkRegionDim{8};
|
|
|
|
|
const uint32_t dispatchGroupCountX{DivideRoundUp(m_Width, threadGroupWorkRegionDim)};
|
|
|
|
|
const uint32_t dispatchGroupCountY{DivideRoundUp(m_Height, threadGroupWorkRegionDim)};
|
|
|
|
|
|
|
|
|
|
deviceCommandContext->BeginComputePass();
|
|
|
|
|
deviceCommandContext->SetComputePipelineState(
|
|
|
|
|
m_ResolvePBRComputeTech->GetComputePipelineState());
|
|
|
|
|
deviceCommandContext->SetUniform(shaderProgram->GetBindingSlot(str_screenSize), screenSize);
|
|
|
|
|
// Mapping [0.0, 1.0] to [-2.0, 2.0].
|
|
|
|
|
deviceCommandContext->SetUniform(shaderProgram->GetBindingSlot(str_exposure),
|
|
|
|
|
std::exp2f((g_RenderingOptions.GetPBRBrightness() - 0.5f) * 4.0f));
|
|
|
|
|
deviceCommandContext->SetTexture(shaderProgram->GetBindingSlot(str_inTex), source);
|
|
|
|
|
deviceCommandContext->SetStorageTexture(shaderProgram->GetBindingSlot(str_outTex), destination);
|
|
|
|
|
deviceCommandContext->Dispatch(dispatchGroupCountX, dispatchGroupCountY, 1);
|
|
|
|
|
deviceCommandContext->EndComputePass();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CPostprocManager::RecalculateSize(const uint32_t width, const uint32_t height)
|
|
|
|
|