Files
maszyna/betterRenderer/renderer/source/gbufferlighting.cpp
2025-04-15 01:32:56 +02:00

366 lines
16 KiB
C++

#include "gbufferlighting.h"
#include <nvrhi/utils.h>
#include <glm/gtc/packing.hpp>
#include "gbuffer.h"
#include "nvrendererbackend.h"
#include "ssao.h"
#include "config.h"
void GbufferLighting::Init() {
auto fb_info = m_renderer->m_gbuffer->m_framebuffer->getFramebufferInfo();
m_width = fb_info.width;
m_height = fb_info.height;
m_tiles_x = (m_width + 7) / 8;
m_tiles_y = (m_height + 7) / 8;
m_frustum_buffer = m_renderer->GetBackend()->GetDevice()->createBuffer(
nvrhi::BufferDesc()
.setDebugName("Forward Plus Frustum Buffer")
.setStructStride(4 * sizeof(glm::vec4) + 10 * sizeof(float))
.setByteSize(m_tiles_x * m_tiles_y * (4 * sizeof(glm::vec4) + 10 * sizeof(float)))
.setCanHaveUAVs(true)
.setInitialState(nvrhi::ResourceStates::UnorderedAccess)
.setKeepInitialState(true));
m_view_params_buffer = m_renderer->GetBackend()->GetDevice()->createBuffer(
nvrhi::utils::CreateVolatileConstantBufferDesc(
sizeof(ViewParams), "Forward Plus View Parameters", 16)
.setInitialState(nvrhi::ResourceStates::ConstantBuffer)
.setKeepInitialState(true));
m_dispatch_params_buffer =
m_renderer->GetBackend()->GetDevice()->createBuffer(
nvrhi::utils::CreateVolatileConstantBufferDesc(
sizeof(ViewParams), "Forward Plus Dispatch Parameters", 16)
.setInitialState(nvrhi::ResourceStates::ConstantBuffer)
.setKeepInitialState(true));
{
auto atomic_counter_desc =
nvrhi::BufferDesc()
.setInitialState(nvrhi::ResourceStates::UnorderedAccess)
.setStructStride(sizeof(uint32_t))
.setKeepInitialState(true)
.setByteSize(sizeof(uint32_t))
.setCanHaveUAVs(true);
m_atomic_counter_lights_opaque =
m_renderer->GetBackend()->GetDevice()->createBuffer(
nvrhi::BufferDesc(atomic_counter_desc)
.setDebugName("Forward Plus Atomic Counter Lights Opaque"));
m_atomic_counter_lights_transparent =
m_renderer->GetBackend()->GetDevice()->createBuffer(
nvrhi::BufferDesc(atomic_counter_desc)
.setDebugName(
"Forward Plus Atomic Counter Lights Transparent"));
}
{
auto index_buffer_desc =
nvrhi::BufferDesc()
.setInitialState(nvrhi::ResourceStates::UnorderedAccess)
.setStructStride(sizeof(uint32_t))
.setKeepInitialState(true)
.setByteSize(sizeof(uint32_t) * m_tiles_x * m_tiles_y * 64)
.setCanHaveUAVs(true);
m_index_buffer_lights_opaque =
m_renderer->GetBackend()->GetDevice()->createBuffer(
nvrhi::BufferDesc(index_buffer_desc)
.setDebugName("Forward Plus Index Buffer Lights Opaque"));
m_index_buffer_lights_transparent =
m_renderer->GetBackend()->GetDevice()->createBuffer(
nvrhi::BufferDesc(index_buffer_desc)
.setDebugName("Forward Plus Index Buffer Lights Transparent"));
}
{
auto index_grid_desc =
nvrhi::TextureDesc()
.setInitialState(nvrhi::ResourceStates::UnorderedAccess)
.setFormat(nvrhi::Format::RG32_UINT)
.setKeepInitialState(true)
.setWidth(m_tiles_x)
.setHeight(m_tiles_y)
.setIsUAV(true);
m_index_grid_lights_opaque =
m_renderer->GetBackend()->GetDevice()->createTexture(
nvrhi::TextureDesc(index_grid_desc)
.setDebugName("Forward Plus Index Grid Lights Opaque"));
m_index_grid_lights_transparent =
m_renderer->GetBackend()->GetDevice()->createTexture(
nvrhi::TextureDesc(index_grid_desc)
.setDebugName("Forward Plus Index Grid Lights Transparent"));
}
{
m_lighting_buffer_capacity =
NvRenderer::Config()->m_lighting.m_max_lights_per_scene;
m_light_buffer = m_renderer->GetBackend()->GetDevice()->createBuffer(
nvrhi::BufferDesc()
.setInitialState(nvrhi::ResourceStates::ShaderResource)
.setKeepInitialState(true)
.setByteSize(m_lighting_buffer_capacity *
sizeof(m_packed_buffer[0]))
.setStructStride(sizeof(m_packed_buffer[0]))
.setDebugName("Light Buffer"));
}
RegisterResource(true, "forwardplus_light_buffer", m_light_buffer,
nvrhi::ResourceType::StructuredBuffer_SRV);
RegisterResource(true, "forwardplus_index_grid_opaque",
m_index_grid_lights_opaque,
nvrhi::ResourceType::Texture_SRV);
RegisterResource(true, "forwardplus_index_grid_transparent",
m_index_grid_lights_transparent,
nvrhi::ResourceType::Texture_SRV);
RegisterResource(true, "forwardplus_index_buffer_opaque",
m_index_buffer_lights_opaque,
nvrhi::ResourceType::StructuredBuffer_SRV);
RegisterResource(true, "forwardplus_index_buffer_transparent",
m_index_buffer_lights_transparent,
nvrhi::ResourceType::StructuredBuffer_SRV);
{
nvrhi::BindingLayoutHandle binding_layout_comp_frustums;
nvrhi::utils::CreateBindingSetAndLayout(
m_renderer->GetBackend()->GetDevice(), nvrhi::ShaderType::Compute, 0,
nvrhi::BindingSetDesc()
.addItem(
nvrhi::BindingSetItem::ConstantBuffer(3, m_view_params_buffer))
.addItem(nvrhi::BindingSetItem::ConstantBuffer(
4, m_dispatch_params_buffer))
.addItem(nvrhi::BindingSetItem::StructuredBuffer_UAV(
0, m_frustum_buffer)),
binding_layout_comp_frustums, m_bindings_comp_frustums);
auto cs_comp_frustums = m_renderer->m_backend->CreateShader(
"forwardplus_compute_frustums", nvrhi::ShaderType::Compute);
m_pso_comp_frustums =
m_renderer->GetBackend()->GetDevice()->createComputePipeline(
nvrhi::ComputePipelineDesc()
.addBindingLayout(binding_layout_comp_frustums)
.setComputeShader(cs_comp_frustums));
}
{
nvrhi::BindingLayoutHandle binding_layout_cull_lights;
nvrhi::utils::CreateBindingSetAndLayout(
m_renderer->GetBackend()->GetDevice(), nvrhi::ShaderType::Compute, 0,
nvrhi::BindingSetDesc()
.addItem(
nvrhi::BindingSetItem::ConstantBuffer(3, m_view_params_buffer))
.addItem(nvrhi::BindingSetItem::ConstantBuffer(
4, m_dispatch_params_buffer))
.addItem(nvrhi::BindingSetItem::Texture_SRV(
3, m_renderer->m_gbuffer->m_gbuffer_depth))
.addItem(
nvrhi::BindingSetItem::StructuredBuffer_SRV(8, m_light_buffer))
.addItem(nvrhi::BindingSetItem::StructuredBuffer_SRV(
9, m_frustum_buffer))
.addItem(nvrhi::BindingSetItem::StructuredBuffer_UAV(
1, m_atomic_counter_lights_opaque))
.addItem(nvrhi::BindingSetItem::StructuredBuffer_UAV(
2, m_atomic_counter_lights_transparent))
.addItem(nvrhi::BindingSetItem::StructuredBuffer_UAV(
3, m_index_buffer_lights_opaque))
.addItem(nvrhi::BindingSetItem::StructuredBuffer_UAV(
4, m_index_buffer_lights_transparent))
.addItem(nvrhi::BindingSetItem::Texture_UAV(
5, m_index_grid_lights_opaque))
.addItem(nvrhi::BindingSetItem::Texture_UAV(
6, m_index_grid_lights_transparent)),
binding_layout_cull_lights, m_bindings_cull_lights);
auto cs_cull_lights = m_renderer->m_backend->CreateShader(
"forwardplus_cull_lights", nvrhi::ShaderType::Compute);
m_pso_cull_lights =
m_renderer->GetBackend()->GetDevice()->createComputePipeline(
nvrhi::ComputePipelineDesc()
.addBindingLayout(binding_layout_cull_lights)
.setComputeShader(cs_cull_lights));
}
// auto texture_desc =
// nvrhi::TextureDesc()
// .setWidth(m_width)
// .setHeight(m_height)
// .setFormat(nvrhi::Format::R11G11B10_FLOAT)
// .setIsUAV(true)
// .setInitialState(nvrhi::ResourceStates::ShaderResource)
// .setKeepInitialState(true);
//texture_desc
// texture_desc.setDebugName("Deferred Diffuse Buffer");
// m_diffuse_texture =
// m_renderer->GetBackend()->GetDevice()->createTexture(texture_desc);
// RegisterResource(true, "deferred_lights", m_diffuse_texture,
// nvrhi::ResourceType::Texture_SRV);
//
// m_view_constants = m_renderer->GetBackend()->GetDevice()->createBuffer(
// nvrhi::utils::CreateVolatileConstantBufferDesc(
// sizeof(ViewConstants), "Deferred Lighting Constants", 16)
// .setInitialState(nvrhi::ResourceStates::ConstantBuffer)
// .setKeepInitialState(true));
//
// nvrhi::BindingLayoutHandle binding_layout_spot;
// nvrhi::BindingLayoutHandle binding_layout_clear;
//
// nvrhi::utils::CreateBindingSetAndLayout(
// m_renderer->GetBackend()->GetDevice(), nvrhi::ShaderType::Compute, 0,
// nvrhi::BindingSetDesc().addItem(
// nvrhi::BindingSetItem::Texture_UAV(0, m_diffuse_texture)),
// binding_layout_clear, m_binding_set_clear);
//
// nvrhi::utils::CreateBindingSetAndLayout(
// m_renderer->GetBackend()->GetDevice(), nvrhi::ShaderType::Compute, 0,
// nvrhi::BindingSetDesc()
// .addItem(nvrhi::BindingSetItem::ConstantBuffer(0, m_view_constants))
// .addItem(nvrhi::BindingSetItem::PushConstants(
// 1, sizeof(PushConstantsSpotLight)))
// .addItem(nvrhi::BindingSetItem::Texture_UAV(0, m_diffuse_texture))
// .addItem(nvrhi::BindingSetItem::Texture_SRV(
// 0, m_renderer->m_gbuffer->m_gbuffer_depth))
// .addItem(nvrhi::BindingSetItem::Texture_SRV(
// 1, m_renderer->m_gbuffer->m_gbuffer_normal))
// .addItem(nvrhi::BindingSetItem::Texture_SRV(
// 2, m_renderer->m_gbuffer->m_gbuffer_params))
// .addItem(nvrhi::BindingSetItem::Texture_SRV(
// 3, m_renderer->m_gbuffer->m_gbuffer_diffuse))
// .addItem(nvrhi::BindingSetItem::Texture_SRV(
// 5, m_renderer->m_ssao->m_outputAO)),
// binding_layout_spot, m_binding_set_spotlight);
//
// auto clear_shader = m_renderer->m_backend->CreateShader(
// "gbuffer_light_clear", nvrhi::ShaderType::Compute);
// auto spotlight_shader = m_renderer->m_backend->CreateShader(
// "gbuffer_light_spot", nvrhi::ShaderType::Compute);
//
// m_pso_clear = m_renderer->m_backend->GetDevice()->createComputePipeline(
// nvrhi::ComputePipelineDesc()
// .setComputeShader(clear_shader)
// .addBindingLayout(binding_layout_clear));
//
// m_pso_spotlight = m_renderer->m_backend->GetDevice()->createComputePipeline(
// nvrhi::ComputePipelineDesc()
// .setComputeShader(spotlight_shader)
// .addBindingLayout(binding_layout_spot));
}
void GbufferLighting::Render(const NvRenderer::RenderPass& pass) {
// ViewConstants view_constants{};
// view_constants.m_inverse_model_view =
// static_cast<glm::mat4>(glm::inverse(pass.m_transform));
// view_constants.m_inverse_projection =
// static_cast<glm::mat4>(glm::inverse(pass.m_projection));
// pass.m_command_list_draw->writeBuffer(m_view_constants, &view_constants,
// sizeof(view_constants));
m_packed_buffer.clear();
for (int i = 0; i < m_renderer->m_renderable_spotlights.size(); ++i) {
if (i >= m_lighting_buffer_capacity) break;
auto& light = m_packed_buffer.emplace_back(
m_renderer->m_renderable_spotlights[i], pass.m_origin);
}
pass.m_command_list_draw->writeBuffer(
m_light_buffer, m_packed_buffer.data(),
m_packed_buffer.size() * sizeof(m_packed_buffer[0]));
ViewParams view_params{};
view_params.m_inverse_projection =
static_cast<glm::mat4>(glm::inverse(pass.m_projection));
view_params.m_view = static_cast<glm::mat4>(pass.m_transform);
view_params.m_screen_dimensions = {m_width, m_height};
view_params.m_num_lights = m_packed_buffer.size();
pass.m_command_list_draw->writeBuffer(m_view_params_buffer, &view_params,
sizeof(view_params));
{
DispatchParams dispatch_params{};
dispatch_params.m_num_threads = {m_tiles_x, m_tiles_y, 1u};
dispatch_params.m_num_thread_groups =
(dispatch_params.m_num_threads + 7u) / 8u;
pass.m_command_list_draw->writeBuffer(
m_dispatch_params_buffer, &dispatch_params, sizeof(dispatch_params));
pass.m_command_list_draw->setComputeState(
nvrhi::ComputeState()
.setPipeline(m_pso_comp_frustums)
.addBindingSet(m_bindings_comp_frustums));
pass.m_command_list_draw->dispatch(dispatch_params.m_num_thread_groups.x,
dispatch_params.m_num_thread_groups.y,
dispatch_params.m_num_thread_groups.z);
}
{
DispatchParams dispatch_params{};
dispatch_params.m_num_thread_groups = {m_tiles_x, m_tiles_y, 1u};
dispatch_params.m_num_threads = dispatch_params.m_num_thread_groups * 8u;
pass.m_command_list_draw->writeBuffer(
m_dispatch_params_buffer, &dispatch_params, sizeof(dispatch_params));
uint32_t zero = 0;
pass.m_command_list_draw->writeBuffer(m_atomic_counter_lights_opaque, &zero,
sizeof(zero));
pass.m_command_list_draw->writeBuffer(m_atomic_counter_lights_transparent,
&zero, sizeof(zero));
pass.m_command_list_draw->setComputeState(
nvrhi::ComputeState()
.setPipeline(m_pso_cull_lights)
.addBindingSet(m_bindings_cull_lights));
pass.m_command_list_draw->dispatch(dispatch_params.m_num_thread_groups.x,
dispatch_params.m_num_thread_groups.y,
dispatch_params.m_num_thread_groups.z);
}
// {
// pass.m_command_list_draw->setComputeState(
// nvrhi::ComputeState()
// .setPipeline(m_pso_clear)
// .addBindingSet(m_binding_set_clear));
// pass.m_command_list_draw->dispatch((m_width + 7) / 8, (m_height + 7) / 8);
// }
//
// for (const auto& spotlight : m_renderer->m_renderable_spotlights) {
// PushConstantsSpotLight push_constants{};
// push_constants.m_origin = spotlight.m_origin - pass.m_origin;
// push_constants.m_radius_sqr = spotlight.m_radius * spotlight.m_radius;
// push_constants.m_direction = spotlight.m_direction;
// push_constants.m_cos_inner_cone = spotlight.m_cos_inner_cone;
// push_constants.m_cos_outer_cone = spotlight.m_cos_outer_cone;
// push_constants.m_color = spotlight.m_color;
//
// pass.m_command_list_draw->setComputeState(
// nvrhi::ComputeState()
// .setPipeline(m_pso_spotlight)
// .addBindingSet(m_binding_set_spotlight));
// pass.m_command_list_draw->setPushConstants(&push_constants,
// sizeof(push_constants));
// pass.m_command_list_draw->dispatch((m_width + 7) / 8, (m_height + 7) / 8);
// }
}
GbufferLighting::PackedSpotLight::PackedSpotLight(
const NvRenderer::Renderable::SpotLight& spotlight,
glm::dvec3 const& origin) {
m_origin = spotlight.m_origin - origin;
m_radius = spotlight.m_radius;
m_direction_cos_inner =
glm::packHalf4x16({spotlight.m_direction, spotlight.m_cos_inner_cone});
glm::vec3 color =
spotlight.m_color.r * glm::vec3(0.4123908f, 0.21263901f, 0.01933082f) +
spotlight.m_color.g * glm::vec3(0.35758434f, 0.71516868f, 0.11919478f) +
spotlight.m_color.b * glm::vec3(0.18048079f, 0.07219232f, 0.95053215f);
m_color_cos_outer = glm::packHalf4x16({color, spotlight.m_cos_outer_cone});
}