mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
276 lines
11 KiB
C++
276 lines
11 KiB
C++
#include "ssao.h"
|
|
|
|
#include <nvrhi/nvrhi.h>
|
|
#include <nvrhi/utils.h>
|
|
|
|
#include <glm/glm.hpp>
|
|
|
|
#include "XeGTAO.h"
|
|
#include "gbuffer.h"
|
|
#include "nvrenderer/nvrenderer.h"
|
|
#include "nvrendererbackend.h"
|
|
|
|
NvSsao::NvSsao(NvRenderer* renderer)
|
|
: m_backend(renderer->m_backend.get()),
|
|
m_gbuffer(renderer->m_gbuffer.get()),
|
|
m_width(0),
|
|
m_height(0) {}
|
|
|
|
void NvSsao::Init() {
|
|
using namespace nvrhi;
|
|
m_CSPrefilterDepths16x16 = m_backend->CreateShader(
|
|
"gtao_CSPrefilterDepths16x16", ShaderType::Compute);
|
|
m_CSGTAOLow = m_backend->CreateShader("gtao_CSGTAOLow", ShaderType::Compute);
|
|
m_CSGTAOMedium =
|
|
m_backend->CreateShader("gtao_CSGTAOMedium", ShaderType::Compute);
|
|
m_CSGTAOHigh =
|
|
m_backend->CreateShader("gtao_CSGTAOHigh", ShaderType::Compute);
|
|
m_CSGTAOUltra =
|
|
m_backend->CreateShader("gtao_CSGTAOUltra", ShaderType::Compute);
|
|
m_CSDenoisePass =
|
|
m_backend->CreateShader("gtao_CSDenoisePass", ShaderType::Compute);
|
|
m_CSDenoiseLastPass =
|
|
m_backend->CreateShader("gtao_CSDenoiseLastPass", ShaderType::Compute);
|
|
|
|
m_width = m_gbuffer->m_framebuffer->getFramebufferInfo().width;
|
|
m_height = m_gbuffer->m_framebuffer->getFramebufferInfo().height;
|
|
|
|
m_constantBuffer = m_backend->GetDevice()->createBuffer(
|
|
nvrhi::utils::CreateStaticConstantBufferDesc(
|
|
sizeof(XeGTAO::GTAOConstants), "XeGTAO Constants")
|
|
.setInitialState(ResourceStates::ConstantBuffer)
|
|
.setKeepInitialState(true));
|
|
|
|
m_workingDepths = m_backend->GetDevice()->createTexture(
|
|
nvrhi::TextureDesc()
|
|
.setDebugName("XeGTAO Working Depths")
|
|
.setWidth(m_width)
|
|
.setHeight(m_height)
|
|
.setIsUAV(true)
|
|
.setFormat(Format::R32_FLOAT)
|
|
.setMipLevels(XE_GTAO_DEPTH_MIP_LEVELS)
|
|
.setInitialState(ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true));
|
|
|
|
m_workingEdges = m_backend->GetDevice()->createTexture(
|
|
nvrhi::TextureDesc()
|
|
.setDebugName("XeGTAO Working Edges")
|
|
.setWidth(m_width)
|
|
.setHeight(m_height)
|
|
.setIsUAV(true)
|
|
.setFormat(Format::R8_UNORM)
|
|
.setInitialState(ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true));
|
|
|
|
m_debugImage = m_backend->GetDevice()->createTexture(
|
|
nvrhi::TextureDesc()
|
|
.setDebugName("XeGTAO Debug Image")
|
|
.setWidth(m_width)
|
|
.setHeight(m_height)
|
|
.setIsUAV(true)
|
|
.setFormat(Format::R11G11B10_FLOAT)
|
|
.setInitialState(ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true));
|
|
|
|
m_workingAOTerm = m_backend->GetDevice()->createTexture(
|
|
nvrhi::TextureDesc()
|
|
.setDebugName("XeGTAO Working AO Term A")
|
|
.setWidth(m_width)
|
|
.setHeight(m_height)
|
|
.setIsUAV(true)
|
|
.setFormat(Format::R32_UINT)
|
|
.setInitialState(ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true));
|
|
|
|
m_workingAOTermPong = m_backend->GetDevice()->createTexture(
|
|
nvrhi::TextureDesc()
|
|
.setDebugName("XeGTAO Working AO Term B")
|
|
.setWidth(m_width)
|
|
.setHeight(m_height)
|
|
.setIsUAV(true)
|
|
.setFormat(Format::R32_UINT)
|
|
.setInitialState(ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true));
|
|
|
|
m_outputAO = m_backend->GetDevice()->createTexture(
|
|
nvrhi::TextureDesc()
|
|
.setDebugName("XeGTAO Output AO")
|
|
.setWidth(m_width)
|
|
.setHeight(m_height)
|
|
.setIsUAV(true)
|
|
.setFormat(Format::RGBA8_UNORM)
|
|
.setIsTypeless(true)
|
|
.setInitialState(ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true));
|
|
|
|
SamplerHandle sampler_point = m_SamplerPoint = m_backend->GetDevice()->createSampler(
|
|
nvrhi::SamplerDesc()
|
|
.setAllAddressModes(SamplerAddressMode::Clamp)
|
|
.setAllFilters(false));
|
|
|
|
{
|
|
BindingLayoutHandle blPrefilterDepths;
|
|
BindingSetDesc bsDescPrefilter =
|
|
BindingSetDesc()
|
|
.addItem(BindingSetItem::ConstantBuffer(0, m_constantBuffer))
|
|
.addItem(BindingSetItem::Texture_SRV(0, m_gbuffer->m_gbuffer_depth))
|
|
.addItem(BindingSetItem::Sampler(0, sampler_point));
|
|
for (int i = 0; i < XE_GTAO_DEPTH_MIP_LEVELS; ++i) {
|
|
bsDescPrefilter.addItem(
|
|
BindingSetItem::Texture_UAV(i, m_workingDepths, Format::UNKNOWN,
|
|
TextureSubresourceSet(i, 1, 0, 1)));
|
|
}
|
|
utils::CreateBindingSetAndLayout(m_backend->GetDevice(),
|
|
ShaderType::Compute, 0, bsDescPrefilter,
|
|
blPrefilterDepths, m_BSPrefilterDepths);
|
|
m_PSOPrefilterDepths = m_backend->GetDevice()->createComputePipeline(
|
|
ComputePipelineDesc()
|
|
.setComputeShader(m_CSPrefilterDepths16x16)
|
|
.addBindingLayout(blPrefilterDepths));
|
|
}
|
|
|
|
{
|
|
BindingLayoutHandle blGTAO;
|
|
utils::CreateBindingSetAndLayout(
|
|
m_backend->GetDevice(), ShaderType::Compute, 0,
|
|
BindingSetDesc()
|
|
.addItem(BindingSetItem::ConstantBuffer(0, m_constantBuffer))
|
|
.addItem(BindingSetItem ::Texture_SRV(0, m_workingDepths))
|
|
.addItem(BindingSetItem::Texture_UAV(0, m_workingAOTerm))
|
|
.addItem(BindingSetItem::Texture_UAV(1, m_workingEdges))
|
|
.addItem(BindingSetItem::Texture_UAV(2, m_debugImage))
|
|
.addItem(BindingSetItem::Sampler(0, sampler_point)),
|
|
blGTAO, m_BSGTAO);
|
|
m_PSOGTAO = m_backend->GetDevice()->createComputePipeline(
|
|
ComputePipelineDesc()
|
|
.setComputeShader(m_CSGTAOHigh)
|
|
.addBindingLayout(blGTAO));
|
|
}
|
|
|
|
{
|
|
BindingLayoutHandle blDenoise;
|
|
m_BLDenoise = m_backend->GetDevice()->createBindingLayout(
|
|
BindingLayoutDesc()
|
|
.setVisibility(nvrhi::ShaderType::Compute)
|
|
.addItem(BindingLayoutItem::ConstantBuffer(0))
|
|
.addItem(BindingLayoutItem::Texture_SRV(0))
|
|
.addItem(BindingLayoutItem::Texture_SRV(1))
|
|
.addItem(BindingLayoutItem::Texture_UAV(0))
|
|
.addItem(BindingLayoutItem::Texture_UAV(1))
|
|
.addItem(BindingLayoutItem::Texture_UAV(2))
|
|
.addItem(BindingLayoutItem::Sampler(0)));
|
|
utils::CreateBindingSetAndLayout(
|
|
m_backend->GetDevice(), ShaderType::Compute, 0,
|
|
BindingSetDesc()
|
|
.addItem(BindingSetItem::ConstantBuffer(0, m_constantBuffer))
|
|
.addItem(BindingSetItem::Texture_SRV(1, m_workingEdges))
|
|
.addItem(BindingSetItem::Texture_UAV(2, m_debugImage))
|
|
.addItem(BindingSetItem::Sampler(0, sampler_point)),
|
|
blDenoise, m_BSDenoise);
|
|
m_PSODenoise = m_backend->GetDevice()->createComputePipeline(
|
|
ComputePipelineDesc()
|
|
.setComputeShader(m_CSDenoisePass)
|
|
//.addBindingLayout(blDenoise)
|
|
.addBindingLayout(m_BLDenoise));
|
|
m_PSODenoiseLastPass = m_backend->GetDevice()->createComputePipeline(
|
|
ComputePipelineDesc()
|
|
.setComputeShader(m_CSDenoiseLastPass)
|
|
//.addBindingLayout(blDenoise)
|
|
.addBindingLayout(m_BLDenoise));
|
|
}
|
|
}
|
|
|
|
void NvSsao::Render(nvrhi::ICommandList* command_list,
|
|
const glm::mat4& projection, size_t frame_index) {
|
|
command_list->beginMarker("XeGTAO");
|
|
|
|
XeGTAO::GTAOConstants constants{};
|
|
XeGTAO::GTAOUpdateConstants(constants, m_width, m_height, settings,
|
|
projection, false, frame_index);
|
|
command_list->writeBuffer(m_constantBuffer, &constants, sizeof(constants));
|
|
|
|
{
|
|
command_list->beginMarker("Prefilter Depth");
|
|
nvrhi::ComputeState state;
|
|
state.setPipeline(m_PSOPrefilterDepths);
|
|
state.addBindingSet(m_BSPrefilterDepths);
|
|
|
|
command_list->setComputeState(state);
|
|
command_list->dispatch((m_width + 16 - 1) / 16, (m_height + 16 - 1) / 16,
|
|
1);
|
|
command_list->endMarker();
|
|
}
|
|
|
|
{
|
|
command_list->beginMarker("Main Pass");
|
|
nvrhi::ComputeState state;
|
|
state.setPipeline(m_PSOGTAO);
|
|
state.addBindingSet(m_BSGTAO);
|
|
|
|
command_list->setComputeState(state);
|
|
command_list->dispatch(
|
|
(m_width + XE_GTAO_NUMTHREADS_X - 1) / XE_GTAO_NUMTHREADS_X,
|
|
(m_height + XE_GTAO_NUMTHREADS_Y - 1) / XE_GTAO_NUMTHREADS_Y, 1);
|
|
command_list->endMarker();
|
|
}
|
|
|
|
{
|
|
command_list->beginMarker("Denoise Pass");
|
|
int num_passes = settings.DenoisePasses;
|
|
nvrhi::ITexture* ping = m_workingAOTerm;
|
|
nvrhi::ITexture* pong = m_workingAOTermPong;
|
|
for (int i = 0; i < num_passes; ++i) {
|
|
nvrhi::ComputeState state;
|
|
bool last_pass = i == num_passes - 1;
|
|
auto bindingSet = m_backend->GetDevice()->createBindingSet(
|
|
nvrhi::BindingSetDesc()
|
|
.addItem(
|
|
nvrhi::BindingSetItem::ConstantBuffer(0, m_constantBuffer))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(0, ping))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
1, m_workingEdges))
|
|
.addItem(nvrhi::BindingSetItem::Texture_UAV(
|
|
0, last_pass ? m_outputAO.Get() : pong,
|
|
nvrhi::Format::R32_UINT))
|
|
.addItem(nvrhi::BindingSetItem::Texture_UAV(1, m_workingEdges))
|
|
.addItem(nvrhi::BindingSetItem::Texture_UAV(2, m_debugImage))
|
|
.addItem(nvrhi::BindingSetItem::Sampler(0, m_SamplerPoint)),
|
|
m_BLDenoise);
|
|
state.setPipeline(last_pass ? m_PSODenoiseLastPass : m_PSODenoise);
|
|
// state.addBindingSet(m_BSDenoise);
|
|
state.addBindingSet(bindingSet);
|
|
|
|
command_list->setComputeState(state);
|
|
command_list->dispatch(
|
|
(m_width + (XE_GTAO_NUMTHREADS_X * 2) - 1) /
|
|
(XE_GTAO_NUMTHREADS_X * 2),
|
|
(m_height + XE_GTAO_NUMTHREADS_Y - 1) / XE_GTAO_NUMTHREADS_Y, 1);
|
|
std::swap(ping, pong);
|
|
}
|
|
command_list->endMarker();
|
|
|
|
command_list->setTextureState(m_outputAO, nvrhi::AllSubresources,
|
|
nvrhi::ResourceStates::ShaderResource);
|
|
}
|
|
command_list->endMarker();
|
|
}
|
|
|
|
void NvSsao::OnGui(bool const open_now) {
|
|
static bool open = false;
|
|
open |= open_now;
|
|
if(open && ImGui::Begin("GTAO Settings", &open)) {
|
|
ImGui::InputInt("Quality level", &settings.QualityLevel);
|
|
ImGui::InputInt("Denoise passes", &settings.DenoisePasses);
|
|
ImGui::InputFloat("Radius", &settings.Radius);
|
|
if(ImGui::CollapsingHeader("Advanced")) {
|
|
ImGui::InputFloat("Radius multiplier", &settings.RadiusMultiplier);
|
|
ImGui::InputFloat("Falloff range", &settings.FalloffRange);
|
|
ImGui::InputFloat("Sample distribution power", &settings.SampleDistributionPower);
|
|
ImGui::InputFloat("Thin occluder compensation", &settings.ThinOccluderCompensation);
|
|
ImGui::InputFloat("Final value power", &settings.FinalValuePower);
|
|
ImGui::InputFloat("Depth MIP sampling offset", &settings.DepthMIPSamplingOffset);
|
|
}
|
|
ImGui::End();
|
|
}
|
|
}
|