mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
982 lines
40 KiB
C++
982 lines
40 KiB
C++
#include "environment.h"
|
|
|
|
#include <fmt/format.h>
|
|
#include <nvrhi/utils.h>
|
|
|
|
#include "config.h"
|
|
#include "gbuffer.h"
|
|
#include "nvrenderer/nvrenderer.h"
|
|
#include "nvrendererbackend.h"
|
|
#include "nvtexture.h"
|
|
#include "simulationenvironment.h"
|
|
#include "sky.h"
|
|
|
|
int MaEnvironment::GetCurrentSetIndex() {
|
|
if (m_locked_set_index >= 0 && IsReady()) {
|
|
m_current_set_index = std::exchange(m_locked_set_index, -1);
|
|
}
|
|
return m_current_set_index;
|
|
}
|
|
|
|
nvrhi::BindingSetHandle MaEnvironment::GetBindingSet(int pass, int mip, int set,
|
|
NvGbuffer* gbuffer_cube) {
|
|
using namespace nvrhi;
|
|
static std::map<int, BindingSetHandle> cache{};
|
|
auto& handle =
|
|
cache[((set & 0xf) << 28) | ((pass & 0xfff) << 16) | (mip & 0xffff)];
|
|
if (!handle) {
|
|
switch (pass) {
|
|
case 1:
|
|
if (!mip) {
|
|
int previous_set = set - 1;
|
|
while (previous_set < 0)
|
|
previous_set += std::size(m_dynamic_envmap_diffuse);
|
|
handle = m_backend->GetDevice()->createBindingSet(
|
|
BindingSetDesc()
|
|
.addItem(BindingSetItem::Texture_SRV(0, m_skybox))
|
|
.addItem(BindingSetItem::Texture_SRV(
|
|
1, gbuffer_cube->m_gbuffer_diffuse, Format::UNKNOWN,
|
|
AllSubresources))
|
|
.addItem(BindingSetItem::Texture_SRV(
|
|
2, gbuffer_cube->m_gbuffer_normal, Format::UNKNOWN,
|
|
AllSubresources))
|
|
.addItem(BindingSetItem::Texture_SRV(
|
|
3, gbuffer_cube->m_gbuffer_params, Format::UNKNOWN,
|
|
AllSubresources))
|
|
.addItem(BindingSetItem::Texture_SRV(
|
|
4, gbuffer_cube->m_gbuffer_depth, Format::UNKNOWN,
|
|
AllSubresources))
|
|
.addItem(BindingSetItem::Texture_SRV(
|
|
5, m_dynamic_envmap_diffuse[previous_set],
|
|
Format::UNKNOWN, AllSubresources))
|
|
.addItem(BindingSetItem::Texture_SRV(13, m_sky_texture))
|
|
.addItem(BindingSetItem::Texture_SRV(14, m_aerial_lut))
|
|
.addItem(BindingSetItem::Texture_SRV(15, m_clouds_texture))
|
|
.addItem(BindingSetItem::Texture_SRV(16, m_high_clouds_texture))
|
|
.addItem(BindingSetItem::Texture_UAV(
|
|
0, m_dynamic_skybox[set], Format::UNKNOWN,
|
|
TextureSubresourceSet(
|
|
0, 1, 0, TextureSubresourceSet::AllArraySlices),
|
|
TextureDimension::Texture2DArray))
|
|
.addItem(BindingSetItem::Sampler(0, m_sampler_linear_clamp))
|
|
.addItem(BindingSetItem::Sampler(1, m_sampler_point_clamp))
|
|
.addItem(BindingSetItem::Sampler(13, m_sampler_linear_clamp))
|
|
.addItem(BindingSetItem::Sampler(15, m_sampler_linear_clamp))
|
|
.addItem(BindingSetItem::ConstantBuffer(
|
|
13, m_sky->m_sky_constants))
|
|
.addItem(BindingSetItem::ConstantBuffer(
|
|
1, m_face_inverse_projection_buffer))
|
|
.addItem(BindingSetItem::PushConstants(
|
|
0, sizeof(CubeLightingConstants))),
|
|
m_bl_gbuffer_lighting);
|
|
} else {
|
|
handle = m_backend->GetDevice()->createBindingSet(
|
|
BindingSetDesc()
|
|
.addItem(BindingSetItem::Texture_SRV(
|
|
1, m_dynamic_skybox[set], Format::UNKNOWN,
|
|
TextureSubresourceSet(
|
|
mip - 1, 1, 0,
|
|
TextureSubresourceSet::AllArraySlices)))
|
|
.addItem(BindingSetItem::Texture_UAV(
|
|
0, m_dynamic_skybox[set], Format::UNKNOWN,
|
|
TextureSubresourceSet(
|
|
mip, 1, 0, TextureSubresourceSet::AllArraySlices),
|
|
TextureDimension::Texture2DArray))
|
|
.addItem(BindingSetItem::Sampler(1, m_sampler_linear_clamp))
|
|
.addItem(BindingSetItem::PushConstants(
|
|
0, sizeof(EnvironmentFilterConstants))),
|
|
m_bl_diffuse_ibl);
|
|
}
|
|
break;
|
|
case 2:
|
|
handle = m_backend->GetDevice()->createBindingSet(
|
|
BindingSetDesc()
|
|
.addItem(BindingSetItem::Texture_SRV(
|
|
1, m_dynamic_skybox[set], Format::UNKNOWN,
|
|
TextureSubresourceSet(
|
|
0, TextureSubresourceSet::AllMipLevels, 0,
|
|
TextureSubresourceSet::AllArraySlices)))
|
|
.addItem(BindingSetItem::Texture_UAV(
|
|
0, m_dynamic_envmap_diffuse[set], Format::UNKNOWN,
|
|
AllSubresources, TextureDimension::Texture2DArray))
|
|
.addItem(BindingSetItem::Sampler(1, m_sampler_linear_clamp))
|
|
.addItem(BindingSetItem::PushConstants(
|
|
0, sizeof(EnvironmentFilterConstants))),
|
|
m_bl_diffuse_ibl);
|
|
break;
|
|
case 3:
|
|
handle = m_backend->GetDevice()->createBindingSet(
|
|
BindingSetDesc()
|
|
.addItem(BindingSetItem::Texture_SRV(
|
|
1, m_dynamic_skybox[set], Format::UNKNOWN,
|
|
TextureSubresourceSet(
|
|
0, TextureSubresourceSet::AllMipLevels, 0,
|
|
TextureSubresourceSet::AllArraySlices)))
|
|
.addItem(BindingSetItem::Texture_UAV(
|
|
0, m_dynamic_envmap_specular[set], Format::UNKNOWN,
|
|
TextureSubresourceSet(
|
|
mip, 1, 0, TextureSubresourceSet::AllArraySlices),
|
|
TextureDimension::Texture2DArray))
|
|
.addItem(BindingSetItem::Sampler(1, m_sampler_linear_clamp))
|
|
.addItem(BindingSetItem::PushConstants(
|
|
0, sizeof(EnvironmentFilterConstants))),
|
|
m_bl_diffuse_ibl);
|
|
break;
|
|
}
|
|
}
|
|
return handle;
|
|
}
|
|
|
|
MaEnvironment::MaEnvironment(NvRenderer* renderer)
|
|
: MaResourceRegistry(renderer),
|
|
m_renderer(renderer),
|
|
m_backend(renderer->m_backend.get()),
|
|
m_gbuffer(renderer->m_gbuffer.get()),
|
|
m_sky() {}
|
|
|
|
void MaEnvironment::Init(const std::string& texture, float pre_exposure) {
|
|
m_sky = m_renderer->m_sky.get();
|
|
InitResourceRegistry();
|
|
using namespace nvrhi;
|
|
m_cs_sample_equirectangular = m_backend->CreateShader(
|
|
"envmap_CSSampleEquirectangular", ShaderType::Compute);
|
|
m_cs_diffuse_ibl =
|
|
m_backend->CreateShader("envmap_CSDiffuseIBL", ShaderType::Compute);
|
|
m_cs_specular_ibl =
|
|
m_backend->CreateShader("envmap_CSSpecularIBL", ShaderType::Compute);
|
|
m_cs_generate_mip =
|
|
m_backend->CreateShader("envmap_CSGenerateCubeMip", ShaderType::Compute);
|
|
m_cs_integrate_brdf =
|
|
m_backend->CreateShader("envmap_CSIntegrateBRDF", ShaderType::Compute);
|
|
m_cs_gbuffer_lighting =
|
|
m_backend->CreateShader("gbuffer_cube_lighting", ShaderType::Compute);
|
|
|
|
m_face_inverse_projection_buffer = m_backend->GetDevice()->createBuffer(
|
|
nvrhi::utils::CreateStaticConstantBufferDesc(
|
|
sizeof(glm::mat4), "Inverse Face Projection Buffer")
|
|
.setInitialState(nvrhi::ResourceStates::ConstantBuffer)
|
|
.setKeepInitialState(true));
|
|
|
|
{
|
|
auto command_list = m_backend->GetDevice()->createCommandList();
|
|
glm::mat4 inverse_projection = glm::inverse(
|
|
glm::perspectiveFovRH_ZO(glm::radians(90.f), 1.f, 1.f, .1f,
|
|
Global.reflectiontune.range_instances));
|
|
command_list->open();
|
|
command_list->writeBuffer(m_face_inverse_projection_buffer,
|
|
&inverse_projection, sizeof(inverse_projection));
|
|
command_list->close();
|
|
m_backend->GetDevice()->executeCommandList(command_list);
|
|
}
|
|
|
|
m_bl_gbuffer_lighting = m_backend->GetDevice()->createBindingLayout(
|
|
BindingLayoutDesc()
|
|
.setVisibility(ShaderType::Compute)
|
|
.addItem(BindingLayoutItem::Texture_SRV(0))
|
|
.addItem(BindingLayoutItem::Texture_SRV(1))
|
|
.addItem(BindingLayoutItem::Texture_SRV(2))
|
|
.addItem(BindingLayoutItem::Texture_SRV(3))
|
|
.addItem(BindingLayoutItem::Texture_SRV(4))
|
|
.addItem(BindingLayoutItem::Texture_SRV(5))
|
|
.addItem(BindingLayoutItem::Texture_SRV(13))
|
|
.addItem(BindingLayoutItem::Texture_SRV(14))
|
|
.addItem(BindingLayoutItem::Texture_SRV(15))
|
|
.addItem(BindingLayoutItem::Texture_SRV(16))
|
|
.addItem(BindingLayoutItem::Texture_UAV(0))
|
|
.addItem(BindingLayoutItem::Sampler(0))
|
|
.addItem(BindingLayoutItem::Sampler(1))
|
|
.addItem(BindingLayoutItem::Sampler(13))
|
|
.addItem(BindingLayoutItem::Sampler(15))
|
|
.addItem(BindingLayoutItem::VolatileConstantBuffer(13))
|
|
.addItem(BindingLayoutItem::ConstantBuffer(1))
|
|
.addItem(BindingLayoutItem::PushConstants(
|
|
0, sizeof(CubeLightingConstants))));
|
|
m_pso_gbuffer_lighting = m_backend->GetDevice()->createComputePipeline(
|
|
ComputePipelineDesc()
|
|
.addBindingLayout(m_bl_gbuffer_lighting)
|
|
.setComputeShader(m_cs_gbuffer_lighting));
|
|
|
|
m_bl_sample_equirectangular = m_backend->GetDevice()->createBindingLayout(
|
|
BindingLayoutDesc()
|
|
.setVisibility(ShaderType::Compute)
|
|
.addItem(BindingLayoutItem::Texture_SRV(0))
|
|
.addItem(BindingLayoutItem::Texture_UAV(0))
|
|
.addItem(BindingLayoutItem::Sampler(0))
|
|
.addItem(BindingLayoutItem::PushConstants(
|
|
0, sizeof(EnvironmentFilterConstants))));
|
|
m_pso_sample_equirectangular = m_backend->GetDevice()->createComputePipeline(
|
|
ComputePipelineDesc()
|
|
.addBindingLayout(m_bl_sample_equirectangular)
|
|
.setComputeShader(m_cs_sample_equirectangular));
|
|
|
|
m_bl_diffuse_ibl = m_backend->GetDevice()->createBindingLayout(
|
|
BindingLayoutDesc()
|
|
.setVisibility(ShaderType::Compute)
|
|
.addItem(BindingLayoutItem::Texture_SRV(1))
|
|
.addItem(BindingLayoutItem::Texture_UAV(0))
|
|
.addItem(BindingLayoutItem::Sampler(1))
|
|
.addItem(BindingLayoutItem::PushConstants(
|
|
0, sizeof(EnvironmentFilterConstants))));
|
|
m_pso_diffuse_ibl = m_backend->GetDevice()->createComputePipeline(
|
|
ComputePipelineDesc()
|
|
.addBindingLayout(m_bl_diffuse_ibl)
|
|
.setComputeShader(m_cs_diffuse_ibl));
|
|
|
|
m_pso_generate_mip = m_backend->GetDevice()->createComputePipeline(
|
|
ComputePipelineDesc()
|
|
.addBindingLayout(m_bl_diffuse_ibl)
|
|
.setComputeShader(m_cs_generate_mip));
|
|
|
|
m_pso_specular_ibl = m_backend->GetDevice()->createComputePipeline(
|
|
ComputePipelineDesc()
|
|
.addBindingLayout(m_bl_diffuse_ibl)
|
|
.setComputeShader(m_cs_specular_ibl));
|
|
|
|
m_bl_integrate_brdf = m_backend->GetDevice()->createBindingLayout(
|
|
BindingLayoutDesc()
|
|
.setVisibility(ShaderType::Compute)
|
|
.addItem(BindingLayoutItem::Texture_UAV(1))
|
|
.addItem(BindingLayoutItem::PushConstants(
|
|
0, sizeof(EnvironmentFilterConstants))));
|
|
|
|
m_pso_integrate_brdf = m_backend->GetDevice()->createComputePipeline(
|
|
ComputePipelineDesc()
|
|
.addBindingLayout(m_bl_integrate_brdf)
|
|
.setComputeShader(m_cs_integrate_brdf));
|
|
|
|
int skybox_width = NvRenderer::Config()->m_envmap_resolution;
|
|
int dynamic_skybox_width = NvRenderer::Config()->m_envmap_resolution;
|
|
int skybox_mips = static_cast<int>(floor(log2(skybox_width))) + 1;
|
|
int dynamic_skybox_mips =
|
|
static_cast<int>(floor(log2(dynamic_skybox_width))) + 1;
|
|
int diffuse_width = 64;
|
|
int specular_width = NvRenderer::Config()->m_envmap_resolution;
|
|
int dynamic_specular_width = NvRenderer::Config()->m_envmap_resolution;
|
|
int specular_mips = 6;
|
|
|
|
m_skybox = m_backend->GetDevice()->createTexture(
|
|
TextureDesc()
|
|
.setDimension(TextureDimension::TextureCube)
|
|
.setFormat(Format::R11G11B10_FLOAT)
|
|
.setArraySize(6)
|
|
.setWidth(skybox_width)
|
|
.setHeight(skybox_width)
|
|
.setMipLevels(skybox_mips)
|
|
.setIsUAV(true)
|
|
.setInitialState(ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true)
|
|
.setDebugName("Skybox"));
|
|
|
|
m_dynamic_skybox[0] = m_backend->GetDevice()->createTexture(
|
|
TextureDesc()
|
|
.setDimension(TextureDimension::TextureCube)
|
|
.setFormat(Format::R11G11B10_FLOAT)
|
|
.setArraySize(6)
|
|
.setWidth(dynamic_skybox_width)
|
|
.setHeight(dynamic_skybox_width)
|
|
.setMipLevels(dynamic_skybox_mips)
|
|
.setIsUAV(true)
|
|
.setInitialState(ResourceStates::UnorderedAccess)
|
|
.setKeepInitialState(true)
|
|
.setDebugName("Dynamic Skybox"));
|
|
|
|
m_dynamic_skybox[1] = m_backend->GetDevice()->createTexture(
|
|
TextureDesc()
|
|
.setDimension(TextureDimension::TextureCube)
|
|
.setFormat(Format::R11G11B10_FLOAT)
|
|
.setArraySize(6)
|
|
.setWidth(dynamic_skybox_width)
|
|
.setHeight(dynamic_skybox_width)
|
|
.setMipLevels(dynamic_skybox_mips)
|
|
.setIsUAV(true)
|
|
.setInitialState(ResourceStates::UnorderedAccess)
|
|
.setKeepInitialState(true)
|
|
.setDebugName("Dynamic Skybox"));
|
|
|
|
m_sampler_linear_clamp_v_repeat_h = m_backend->GetDevice()->createSampler(
|
|
SamplerDesc()
|
|
.setAllAddressModes(SamplerAddressMode::Clamp)
|
|
.setAddressU(SamplerAddressMode::Repeat)
|
|
.setAllFilters(true));
|
|
|
|
m_sampler_linear_clamp = m_backend->GetDevice()->createSampler(
|
|
SamplerDesc()
|
|
.setAllAddressModes(SamplerAddressMode::Clamp)
|
|
.setAllFilters(true));
|
|
|
|
m_sampler_point_clamp = m_backend->GetDevice()->createSampler(
|
|
SamplerDesc()
|
|
.setAllAddressModes(SamplerAddressMode::Clamp)
|
|
.setAllFilters(false));
|
|
CommandListHandle command_list = m_backend->GetDevice()->createCommandList();
|
|
command_list->open();
|
|
|
|
RegisterResource(true, "sampler_linear_clamp_v_repeat_h",
|
|
m_sampler_linear_clamp_v_repeat_h, ResourceType::Sampler);
|
|
|
|
{
|
|
size_t texture_handle_clouds =
|
|
m_renderer->GetTextureManager()->FetchTexture(
|
|
NvRenderer::Config()->m_cloud_texture, GL_RGBA, 0, false);
|
|
size_t texture_handle_high_clouds =
|
|
m_renderer->GetTextureManager()->FetchTexture(
|
|
NvRenderer::Config()->m_high_cloud_texture, GL_R, 0, false);
|
|
nvrhi::CommandListHandle command_list =
|
|
m_backend->GetDevice()->createCommandList();
|
|
command_list->open();
|
|
m_clouds_texture = m_renderer->GetTextureManager()->GetRhiTexture(
|
|
texture_handle_clouds, command_list);
|
|
m_high_clouds_texture = m_renderer->GetTextureManager()->GetRhiTexture(
|
|
texture_handle_high_clouds, command_list);
|
|
|
|
command_list->close();
|
|
m_backend->GetDevice()->executeCommandList(command_list);
|
|
}
|
|
|
|
{
|
|
m_brdf_lut = m_backend->GetDevice()->createTexture(
|
|
TextureDesc()
|
|
.setFormat(Format::RG16_FLOAT)
|
|
.setDimension(TextureDimension::Texture2D)
|
|
.setWidth(512)
|
|
.setHeight(512)
|
|
.setMipLevels(1)
|
|
.setIsUAV(true)
|
|
.setInitialState(ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true)
|
|
.setDebugName("BRDF LUT"));
|
|
|
|
RegisterResource(true, "env_brdf_lut", m_brdf_lut,
|
|
ResourceType::Texture_SRV);
|
|
|
|
BindingSetHandle binding_set = m_backend->GetDevice()->createBindingSet(
|
|
BindingSetDesc()
|
|
.addItem(BindingSetItem::Texture_UAV(1, m_brdf_lut))
|
|
.addItem(BindingSetItem::PushConstants(
|
|
0, sizeof(EnvironmentFilterConstants))),
|
|
m_bl_integrate_brdf);
|
|
|
|
ComputeState compute_state = ComputeState()
|
|
.setPipeline(m_pso_integrate_brdf)
|
|
.addBindingSet(binding_set);
|
|
|
|
int target_width = m_brdf_lut->getDesc().width;
|
|
int target_height = m_brdf_lut->getDesc().height;
|
|
command_list->setComputeState(compute_state);
|
|
|
|
EnvironmentFilterConstants filter_constants{};
|
|
filter_constants.m_sample_count = 4096;
|
|
command_list->setPushConstants(&filter_constants, sizeof(filter_constants));
|
|
|
|
command_list->dispatch((target_width + 31) / 32, (target_height + 31) / 32,
|
|
1);
|
|
}
|
|
|
|
{
|
|
m_envmap_diffuse = m_backend->GetDevice()->createTexture(
|
|
TextureDesc()
|
|
.setArraySize(6)
|
|
.setFormat(Format::R11G11B10_FLOAT)
|
|
.setDimension(TextureDimension::TextureCube)
|
|
.setWidth(diffuse_width)
|
|
.setHeight(diffuse_width)
|
|
.setMipLevels(1)
|
|
.setIsUAV(true)
|
|
.setInitialState(ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true)
|
|
.setDebugName("Diffuse IBL"));
|
|
for (int i = 0; i < std::size(m_dynamic_envmap_diffuse); ++i) {
|
|
auto debug_name = fmt::format("Dynamic Diffuse IBL[{}]", i);
|
|
auto resource_name = fmt::format("env_dynamic_diffuse_{}", i);
|
|
m_dynamic_envmap_diffuse[i] = m_backend->GetDevice()->createTexture(
|
|
TextureDesc()
|
|
.setArraySize(6)
|
|
.setFormat(Format::R11G11B10_FLOAT)
|
|
.setDimension(TextureDimension::TextureCube)
|
|
.setWidth(diffuse_width)
|
|
.setHeight(diffuse_width)
|
|
.setMipLevels(1)
|
|
.setIsUAV(true)
|
|
.setInitialState(i ? ResourceStates::UnorderedAccess
|
|
: ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true)
|
|
.setDebugName(debug_name.c_str()));
|
|
}
|
|
RegisterResource(true, "env_dynamic_diffuse", m_dynamic_envmap_diffuse[0],
|
|
ResourceType::Texture_SRV);
|
|
}
|
|
|
|
{
|
|
m_envmap_specular = m_backend->GetDevice()->createTexture(
|
|
TextureDesc()
|
|
.setArraySize(6)
|
|
.setFormat(Format::R11G11B10_FLOAT)
|
|
.setDimension(TextureDimension::TextureCube)
|
|
.setWidth(specular_width)
|
|
.setHeight(specular_width)
|
|
.setMipLevels(specular_mips)
|
|
.setIsUAV(true)
|
|
.setInitialState(ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true)
|
|
.setDebugName("Specular IBL"));
|
|
for (int i = 0; i < std::size(m_dynamic_envmap_specular); ++i) {
|
|
auto debug_name = fmt::format("Dynamic Specular IBL[{}]", i);
|
|
auto resource_name = fmt::format("env_dynamic_specular_{}", i);
|
|
m_dynamic_envmap_specular[i] = m_backend->GetDevice()->createTexture(
|
|
TextureDesc()
|
|
.setArraySize(6)
|
|
.setFormat(Format::R11G11B10_FLOAT)
|
|
.setDimension(TextureDimension::TextureCube)
|
|
.setWidth(dynamic_specular_width)
|
|
.setHeight(dynamic_specular_width)
|
|
.setMipLevels(specular_mips)
|
|
.setIsUAV(true)
|
|
.setInitialState(i ? ResourceStates::UnorderedAccess
|
|
: ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true)
|
|
.setDebugName(debug_name.c_str()));
|
|
}
|
|
RegisterResource(true, "env_dynamic_specular", m_dynamic_envmap_specular[0],
|
|
ResourceType::Texture_SRV);
|
|
}
|
|
|
|
RegisterResource(true, "sky_clouds", m_clouds_texture,
|
|
nvrhi::ResourceType::Texture_SRV);
|
|
|
|
m_sky_texture = m_backend->GetDevice()->createTexture(
|
|
TextureDesc(m_sky->m_aerial_lut->m_sky_texture->getDesc())
|
|
.setDebugName("Envmap Sky Texture"));
|
|
|
|
m_aerial_lut = m_backend->GetDevice()->createTexture(
|
|
TextureDesc(m_sky->m_aerial_lut->m_lut->getDesc())
|
|
.setDebugName("Envmap Aerial LUT"));
|
|
|
|
command_list->close();
|
|
m_backend->GetDevice()->executeCommandList(command_list);
|
|
|
|
m_environment_pass = std::make_shared<EnvironmentRenderPass>(this);
|
|
m_environment_pass->Init();
|
|
}
|
|
|
|
void MaEnvironment::Render(nvrhi::ICommandList* command_list,
|
|
glm::dmat4 const& jitter,
|
|
glm::dmat4 const& projection, glm::dmat4 const& view,
|
|
glm::dmat4 const& previous_view_projection) {
|
|
m_environment_pass->UpdateConstants(command_list, jitter, projection, view,
|
|
previous_view_projection);
|
|
m_environment_pass->Render(command_list);
|
|
}
|
|
|
|
void MaEnvironment::Filter(uint64_t sky_instance_id, NvGbuffer* gbuffer_cube) {
|
|
using namespace nvrhi;
|
|
int pixels_per_pass_sqr = m_pixels_per_pass * m_pixels_per_pass;
|
|
int target_set_index = 1;
|
|
int source_set_index = 0;
|
|
|
|
static uint64_t prev_instance = -1;
|
|
if (filter_step == 0) {
|
|
if (!IsReady()) {
|
|
return;
|
|
}
|
|
// m_locked_set_index = (GetCurrentSetIndex() + 1) % 2;
|
|
m_ready_handle = m_backend->GetDevice()->createEventQuery();
|
|
|
|
// CommandListHandle transition_command_list =
|
|
// m_backend->GetDevice()->createCommandList();
|
|
// transition_command_list->open();
|
|
//
|
|
// transition_command_list->setTextureState(m_sky->m_aerial_lut->m_sky_texture,
|
|
// nvrhi::AllSubresources,
|
|
// nvrhi::ResourceStates::Common);
|
|
// transition_command_list->setTextureState(m_sky->m_aerial_lut->m_lut,
|
|
// nvrhi::AllSubresources,
|
|
// nvrhi::ResourceStates::Common);
|
|
//
|
|
// transition_command_list->close();
|
|
// auto transition_id =
|
|
// m_backend->GetDevice()->executeCommandList(transition_command_list);
|
|
//
|
|
// m_backend->GetDevice()->queueWaitForCommandList(
|
|
// nvrhi::CommandQueue::Copy, nvrhi::CommandQueue::Graphics,
|
|
// transition_id);
|
|
|
|
CommandListHandle command_list = m_backend->GetDevice()->createCommandList(
|
|
CommandListParameters()
|
|
.setQueueType(CommandQueue::Graphics)
|
|
.setEnableImmediateExecution(false));
|
|
command_list->open();
|
|
|
|
{
|
|
auto diff_desc = m_sky_texture->getDesc();
|
|
for (int i = 0; i < diff_desc.arraySize; ++i) {
|
|
for (int j = 0; j < diff_desc.mipLevels; ++j) {
|
|
auto slice = nvrhi::TextureSlice()
|
|
.setArraySlice(i)
|
|
.setMipLevel(j)
|
|
.setWidth(-1)
|
|
.setHeight(-1)
|
|
.resolve(diff_desc);
|
|
command_list->copyTexture(m_sky_texture, slice,
|
|
m_sky->m_aerial_lut->m_sky_texture, slice);
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
auto diff_desc = m_aerial_lut->getDesc();
|
|
for (int i = 0; i < diff_desc.arraySize; ++i) {
|
|
for (int j = 0; j < diff_desc.mipLevels; ++j) {
|
|
auto slice = nvrhi::TextureSlice()
|
|
.setArraySlice(i)
|
|
.setMipLevel(j)
|
|
.setWidth(-1)
|
|
.setHeight(-1)
|
|
.resolve(diff_desc);
|
|
command_list->copyTexture(m_aerial_lut, slice,
|
|
m_sky->m_aerial_lut->m_lut, slice);
|
|
}
|
|
}
|
|
}
|
|
|
|
// auto diff_desc = m_dynamic_envmap_diffuse[0]->getDesc();
|
|
// for (int i = 0; i < 6; ++i) {
|
|
// for (int j = 0; j < diff_desc.mipLevels; ++j) {
|
|
// auto slice = nvrhi::TextureSlice()
|
|
// .setArraySlice(i)
|
|
// .setMipLevel(j)
|
|
// .setWidth(-1)
|
|
// .setHeight(-1)
|
|
// .resolve(diff_desc);
|
|
// command_list->copyTexture(m_dynamic_envmap_diffuse[0], slice,
|
|
// m_dynamic_envmap_diffuse[1], slice);
|
|
// }
|
|
// }
|
|
//
|
|
// auto spec_desc = m_dynamic_envmap_specular[0]->getDesc();
|
|
// for (int i = 0; i < 6; ++i) {
|
|
// for (int j = 0; j < spec_desc.mipLevels; ++j) {
|
|
// auto slice = nvrhi::TextureSlice()
|
|
// .setArraySlice(i)
|
|
// .setMipLevel(j)
|
|
// .setWidth(-1)
|
|
// .setHeight(-1)
|
|
// .resolve(spec_desc);
|
|
// command_list->copyTexture(m_dynamic_envmap_specular[0], slice,
|
|
// m_dynamic_envmap_specular[1], slice);
|
|
// }
|
|
//}
|
|
|
|
// command_list->setTextureState(m_sky_texture, nvrhi::AllSubresources,
|
|
// nvrhi::ResourceStates::Common);
|
|
// command_list->setTextureState(m_aerial_lut, nvrhi::AllSubresources,
|
|
// nvrhi::ResourceStates::Common);
|
|
command_list->close();
|
|
prev_instance = m_backend->GetDevice()->executeCommandList(
|
|
command_list, nvrhi::CommandQueue::Graphics);
|
|
// CommandListHandle transition_command_list =
|
|
// m_backend->GetDevice()->createCommandList();
|
|
// transition_command_list->open();
|
|
//
|
|
// transition_command_list->setTextureState(m_skybox, AllSubresources,
|
|
// ResourceStates::UnorderedAccess);
|
|
// transition_command_list->setTextureState(m_dynamic_skybox[target_set_index],
|
|
// AllSubresources,
|
|
// ResourceStates::UnorderedAccess);
|
|
// transition_command_list->setTextureState(
|
|
// m_dynamic_envmap_diffuse[target_set_index], AllSubresources,
|
|
// ResourceStates::UnorderedAccess);
|
|
// transition_command_list->setTextureState(
|
|
// m_dynamic_envmap_specular[target_set_index], AllSubresources,
|
|
// ResourceStates::UnorderedAccess);
|
|
// transition_command_list->setTextureState(
|
|
// m_dynamic_envmap_diffuse[source_set_index], AllSubresources,
|
|
// ResourceStates::ShaderResource);
|
|
// transition_command_list->setTextureState(
|
|
// m_dynamic_envmap_specular[source_set_index], AllSubresources,
|
|
// ResourceStates::ShaderResource);
|
|
// transition_command_list->setTextureState(gbuffer_cube->m_gbuffer_diffuse,
|
|
// AllSubresources,
|
|
// ResourceStates::ShaderResource);
|
|
// transition_command_list->setTextureState(gbuffer_cube->m_gbuffer_normal,
|
|
// AllSubresources,
|
|
// ResourceStates::ShaderResource);
|
|
// transition_command_list->setTextureState(gbuffer_cube->m_gbuffer_params,
|
|
// AllSubresources,
|
|
// ResourceStates::ShaderResource);
|
|
// transition_command_list->setTextureState(gbuffer_cube->m_gbuffer_depth,
|
|
// AllSubresources,
|
|
// ResourceStates::ShaderResource);
|
|
// transition_command_list->commitBarriers();
|
|
//
|
|
// transition_command_list->close();
|
|
// auto instance =
|
|
// m_backend->GetDevice()->executeCommandList(transition_command_list);
|
|
// m_backend->GetDevice()->queueWaitForCommandList(
|
|
// nvrhi::CommandQueue::Compute, nvrhi::CommandQueue::Graphics,
|
|
// instance);
|
|
++filter_step;
|
|
mip = 0;
|
|
return;
|
|
}
|
|
|
|
if (filter_step == 1) {
|
|
// CommandListHandle command_list_transition =
|
|
// m_backend->GetDevice()->createCommandList();
|
|
// command_list_transition->open();
|
|
//
|
|
// command_list_transition->setTextureState(
|
|
// m_sky->m_aerial_lut->m_sky_texture, nvrhi::AllSubresources,
|
|
// nvrhi::ResourceStates::ShaderResource);
|
|
//
|
|
// command_list_transition->close();
|
|
// auto instance =
|
|
// m_backend->GetDevice()->executeCommandList(command_list_transition);
|
|
|
|
if (prev_instance != -1) {
|
|
// m_backend->GetDevice()->queueWaitForCommandList(
|
|
// nvrhi::CommandQueue::Compute, nvrhi::CommandQueue::Graphics,
|
|
// prev_instance);
|
|
// prev_instance = -1;
|
|
}
|
|
CommandListHandle command_list = m_backend->GetDevice()->createCommandList(
|
|
CommandListParameters()
|
|
.setQueueType(CommandQueue::Graphics)
|
|
.setEnableImmediateExecution(false));
|
|
// m_backend->GetDevice()->queueWaitForCommandList(
|
|
// nvrhi::CommandQueue::Compute, nvrhi::CommandQueue::Graphics,
|
|
// instance);
|
|
command_list->open();
|
|
|
|
while (true) {
|
|
int target_width = std::max(
|
|
m_dynamic_skybox[target_set_index]->getDesc().width >> mip, 1u);
|
|
int target_height = std::max(
|
|
m_dynamic_skybox[target_set_index]->getDesc().height >> mip, 1u);
|
|
|
|
int pixels_x = std::min(m_pixels_per_pass, target_width - x);
|
|
int pixels_y = std::min(m_pixels_per_pass, target_height - y);
|
|
|
|
if (pixels_x * pixels_y > pixels_per_pass_sqr) {
|
|
break;
|
|
}
|
|
|
|
pixels_per_pass_sqr -= pixels_x * pixels_y;
|
|
|
|
if (mip >= m_dynamic_skybox[target_set_index]->getDesc().mipLevels) {
|
|
break;
|
|
}
|
|
if (!mip) m_sky->UpdateConstants(command_list);
|
|
ComputeState compute_state;
|
|
compute_state
|
|
.setPipeline(mip ? m_pso_generate_mip : m_pso_gbuffer_lighting)
|
|
.addBindingSet(
|
|
GetBindingSet(filter_step, mip, target_set_index, gbuffer_cube));
|
|
command_list->setComputeState(compute_state);
|
|
|
|
if (!mip) {
|
|
CubeLightingConstants filter_constants{};
|
|
const auto& daylight = Global.DayLight;
|
|
filter_constants.m_offset_x = x;
|
|
filter_constants.m_offset_y = y;
|
|
filter_constants.m_offset_z = 0;
|
|
filter_constants.m_light_direction = -daylight.direction;
|
|
filter_constants.m_height = Global.pCamera.Pos.y;
|
|
|
|
m_sky->CalcLighting(filter_constants.m_light_direction,
|
|
filter_constants.m_light_color);
|
|
|
|
filter_constants.m_light_color = glm::vec4(m_sky->CalcSunColor(), 1.f);
|
|
command_list->setPushConstants(&filter_constants,
|
|
sizeof(filter_constants));
|
|
} else {
|
|
EnvironmentFilterConstants filter_constants{};
|
|
filter_constants.m_offset_x = x;
|
|
filter_constants.m_offset_y = y;
|
|
filter_constants.m_offset_z = 0;
|
|
command_list->setPushConstants(&filter_constants,
|
|
sizeof(filter_constants));
|
|
}
|
|
|
|
command_list->dispatch((pixels_x + 31) / 32, (pixels_y + 31) / 32, 6);
|
|
x += m_pixels_per_pass;
|
|
if (x >= target_width) {
|
|
x = 0;
|
|
y += m_pixels_per_pass;
|
|
}
|
|
if (y >= target_height) {
|
|
y = 0;
|
|
++mip;
|
|
}
|
|
}
|
|
|
|
if (mip >= m_dynamic_skybox[target_set_index]->getDesc().mipLevels) {
|
|
mip = 0;
|
|
++filter_step;
|
|
}
|
|
|
|
command_list->close();
|
|
m_backend->GetDevice()->executeCommandList(command_list,
|
|
nvrhi::CommandQueue::Graphics);
|
|
}
|
|
|
|
if (filter_step == 2) {
|
|
CommandListHandle command_list = m_backend->GetDevice()->createCommandList(
|
|
CommandListParameters()
|
|
.setQueueType(CommandQueue::Graphics)
|
|
.setEnableImmediateExecution(false));
|
|
command_list->open();
|
|
|
|
ComputeState compute_state =
|
|
ComputeState()
|
|
.setPipeline(m_pso_diffuse_ibl)
|
|
.addBindingSet(
|
|
GetBindingSet(filter_step, 0, target_set_index, gbuffer_cube));
|
|
|
|
int target_width =
|
|
m_dynamic_envmap_diffuse[target_set_index]->getDesc().width;
|
|
int target_height =
|
|
m_dynamic_envmap_diffuse[target_set_index]->getDesc().height;
|
|
command_list->setComputeState(compute_state);
|
|
|
|
EnvironmentFilterConstants filter_constants{};
|
|
filter_constants.m_sample_count = 32;
|
|
filter_constants.m_source_width =
|
|
m_dynamic_skybox[target_set_index]->getDesc().width;
|
|
filter_constants.m_offset_x = 0;
|
|
filter_constants.m_offset_y = 0;
|
|
filter_constants.m_offset_z = 0;
|
|
filter_constants.m_mip_bias = 1.;
|
|
command_list->setPushConstants(&filter_constants, sizeof(filter_constants));
|
|
|
|
command_list->dispatch((target_width + 31) / 32, (target_height + 31) / 32,
|
|
6);
|
|
command_list->close();
|
|
m_backend->GetDevice()->executeCommandList(command_list,
|
|
nvrhi::CommandQueue::Graphics);
|
|
++filter_step;
|
|
}
|
|
|
|
if (filter_step == 3) {
|
|
CommandListHandle command_list = m_backend->GetDevice()->createCommandList(
|
|
CommandListParameters()
|
|
.setQueueType(CommandQueue::Graphics)
|
|
.setEnableImmediateExecution(false));
|
|
command_list->open();
|
|
|
|
while (true) {
|
|
int target_width = std::max(
|
|
1u,
|
|
m_dynamic_envmap_specular[target_set_index]->getDesc().width >> mip);
|
|
int target_height = std::max(
|
|
1u,
|
|
m_dynamic_envmap_specular[target_set_index]->getDesc().height >> mip);
|
|
|
|
int pixels_x = std::min(m_pixels_per_pass, target_width - x);
|
|
int pixels_y = std::min(m_pixels_per_pass, target_height - y);
|
|
|
|
if (pixels_x * pixels_y > pixels_per_pass_sqr) {
|
|
break;
|
|
}
|
|
|
|
if (mip >=
|
|
m_dynamic_envmap_specular[target_set_index]->getDesc().mipLevels) {
|
|
break;
|
|
}
|
|
|
|
pixels_per_pass_sqr -= pixels_x * pixels_y;
|
|
|
|
ComputeState compute_state =
|
|
ComputeState()
|
|
.setPipeline(m_pso_specular_ibl)
|
|
.addBindingSet(GetBindingSet(filter_step, mip, target_set_index,
|
|
gbuffer_cube));
|
|
|
|
EnvironmentFilterConstants filter_constants{};
|
|
filter_constants.m_sample_count = 32;
|
|
filter_constants.m_roughness =
|
|
glm::pow(static_cast<double>(mip) /
|
|
(m_dynamic_envmap_specular[target_set_index]
|
|
->getDesc()
|
|
.mipLevels -
|
|
1.),
|
|
2.);
|
|
filter_constants.m_source_width =
|
|
m_dynamic_skybox[target_set_index]->getDesc().width;
|
|
filter_constants.m_mip_bias =
|
|
mip ? 1.
|
|
: log2(target_width /
|
|
static_cast<double>(filter_constants.m_source_width));
|
|
filter_constants.m_offset_x = x;
|
|
filter_constants.m_offset_y = y;
|
|
filter_constants.m_offset_z = 0;
|
|
command_list->setComputeState(compute_state);
|
|
command_list->setPushConstants(&filter_constants,
|
|
sizeof(filter_constants));
|
|
|
|
command_list->dispatch((pixels_x + 31) / 32, (pixels_y + 31) / 32, 6);
|
|
|
|
x += m_pixels_per_pass;
|
|
if (x >= target_width) {
|
|
x = 0;
|
|
y += m_pixels_per_pass;
|
|
}
|
|
if (y >= target_height) {
|
|
y = 0;
|
|
++mip;
|
|
}
|
|
}
|
|
command_list->close();
|
|
m_backend->GetDevice()->executeCommandList(command_list,
|
|
nvrhi::CommandQueue::Graphics);
|
|
if (mip >=
|
|
m_dynamic_envmap_specular[target_set_index]->getDesc().mipLevels) {
|
|
mip = 0;
|
|
filter_step = 4;
|
|
}
|
|
}
|
|
|
|
if (filter_step == 4) {
|
|
CommandListHandle command_list = m_backend->GetDevice()->createCommandList(
|
|
CommandListParameters()
|
|
.setQueueType(CommandQueue::Graphics)
|
|
.setEnableImmediateExecution(false));
|
|
command_list->open();
|
|
|
|
auto diff_desc = m_dynamic_envmap_diffuse[0]->getDesc();
|
|
for (int i = 0; i < 6; ++i) {
|
|
for (int j = 0; j < diff_desc.mipLevels; ++j) {
|
|
auto slice = nvrhi::TextureSlice()
|
|
.setArraySlice(i)
|
|
.setMipLevel(j)
|
|
.setWidth(-1)
|
|
.setHeight(-1)
|
|
.resolve(diff_desc);
|
|
command_list->copyTexture(m_dynamic_envmap_diffuse[0], slice,
|
|
m_dynamic_envmap_diffuse[1], slice);
|
|
}
|
|
}
|
|
|
|
auto spec_desc = m_dynamic_envmap_specular[0]->getDesc();
|
|
for (int i = 0; i < 6; ++i) {
|
|
for (int j = 0; j < spec_desc.mipLevels; ++j) {
|
|
auto slice = nvrhi::TextureSlice()
|
|
.setArraySlice(i)
|
|
.setMipLevel(j)
|
|
.setWidth(-1)
|
|
.setHeight(-1)
|
|
.resolve(spec_desc);
|
|
command_list->copyTexture(m_dynamic_envmap_specular[0], slice,
|
|
m_dynamic_envmap_specular[1], slice);
|
|
}
|
|
}
|
|
|
|
command_list->close();
|
|
m_backend->GetDevice()->executeCommandList(command_list,
|
|
nvrhi::CommandQueue::Graphics);
|
|
filter_step = 0;
|
|
m_backend->GetDevice()->setEventQuery(m_ready_handle,
|
|
nvrhi::CommandQueue::Graphics);
|
|
}
|
|
}
|
|
|
|
bool MaEnvironment::IsReady() const {
|
|
return !m_ready_handle ||
|
|
m_backend->GetDevice()->pollEventQuery(m_ready_handle);
|
|
}
|
|
|
|
EnvironmentRenderPass::EnvironmentRenderPass(MaEnvironment* environment)
|
|
: FullScreenPass(environment->m_backend),
|
|
m_environment(environment),
|
|
m_gbuffer(environment->m_gbuffer),
|
|
m_skybox_texture(environment->m_skybox) {}
|
|
|
|
void EnvironmentRenderPass::Init() {
|
|
m_environment_constants = m_backend->GetDevice()->createBuffer(
|
|
nvrhi::utils::CreateVolatileConstantBufferDesc(
|
|
sizeof(EnvironmentConstants), "Skybox Draw Constants", 16)
|
|
.setInitialState(nvrhi::ResourceStates::ConstantBuffer)
|
|
.setKeepInitialState(true));
|
|
m_binding_layout = m_backend->GetDevice()->createBindingLayout(
|
|
nvrhi::BindingLayoutDesc()
|
|
.setVisibility(nvrhi::ShaderType::Pixel)
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(0))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(13))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(15))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(16))
|
|
.addItem(nvrhi::BindingLayoutItem::Sampler(0))
|
|
.addItem(nvrhi::BindingLayoutItem::Sampler(13))
|
|
.addItem(nvrhi::BindingLayoutItem::Sampler(15))
|
|
.addItem(nvrhi::BindingLayoutItem::VolatileConstantBuffer(0)));
|
|
auto sampler = m_backend->GetDevice()->createSampler(
|
|
nvrhi::SamplerDesc()
|
|
.setAllAddressModes(nvrhi::SamplerAddressMode::Clamp)
|
|
.setAllFilters(true));
|
|
|
|
for (int i = 0; i < 2; ++i) {
|
|
m_binding_set[i] = m_backend->GetDevice()->createBindingSet(
|
|
nvrhi::BindingSetDesc()
|
|
.addItem(
|
|
nvrhi::BindingSetItem::Texture_SRV(0, m_environment->m_skybox))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
13, m_environment->m_sky->m_aerial_lut->m_sky_texture))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(15, m_environment->m_clouds_texture))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(16, m_environment->m_high_clouds_texture))
|
|
.addItem(nvrhi::BindingSetItem::Sampler(
|
|
0, m_environment->m_sampler_linear_clamp))
|
|
.addItem(nvrhi::BindingSetItem::Sampler(
|
|
13, m_environment->m_sampler_linear_clamp_v_repeat_h))
|
|
.addItem(nvrhi::BindingSetItem::Sampler(
|
|
15, m_environment->m_sampler_linear_clamp))
|
|
.addItem(nvrhi::BindingSetItem::ConstantBuffer(
|
|
0, m_environment_constants)),
|
|
m_binding_layout);
|
|
}
|
|
|
|
m_pixel_shader = m_backend->CreateShader("skybox", nvrhi::ShaderType::Pixel);
|
|
FullScreenPass::Init();
|
|
}
|
|
|
|
void EnvironmentRenderPass::CreatePipelineDesc(
|
|
nvrhi::GraphicsPipelineDesc& pipeline_desc) {
|
|
FullScreenPass::CreatePipelineDesc(pipeline_desc);
|
|
pipeline_desc.addBindingLayout(m_binding_layout);
|
|
pipeline_desc.setPixelShader(m_pixel_shader);
|
|
pipeline_desc.renderState.setDepthStencilState(
|
|
nvrhi::DepthStencilState()
|
|
.enableDepthTest()
|
|
.disableDepthWrite()
|
|
.setDepthFunc(nvrhi::ComparisonFunc::GreaterOrEqual)
|
|
.disableStencil());
|
|
}
|
|
|
|
void EnvironmentRenderPass::UpdateConstants(
|
|
nvrhi::ICommandList* command_list, glm::dmat4 const& jitter,
|
|
glm::dmat4 const& projection, glm::dmat4 const& view,
|
|
glm::dmat4 const& previous_view_projection) {
|
|
EnvironmentConstants constants{};
|
|
|
|
constants.m_reproject_matrix =
|
|
glm::inverse(projection * view) * previous_view_projection;
|
|
constants.m_inverse_view_projection =
|
|
glm::inverse(jitter * projection * glm::dmat4(glm::dmat3(view)));
|
|
constants.m_sun_direction = simulation::Environment.sun().getDirection();
|
|
constants.m_moon_direction = simulation::Environment.moon().getDirection();
|
|
constants.m_height = Global.pCamera.Pos.y;
|
|
|
|
command_list->writeBuffer(m_environment_constants, &constants,
|
|
sizeof(constants));
|
|
}
|
|
|
|
void EnvironmentRenderPass::Render(nvrhi::ICommandList* command_list) {
|
|
nvrhi::GraphicsState graphics_state;
|
|
InitState(graphics_state);
|
|
graphics_state.addBindingSet(
|
|
m_binding_set[m_environment->GetCurrentSetIndex()]);
|
|
command_list->setGraphicsState(graphics_state);
|
|
Draw(command_list);
|
|
}
|
|
|
|
nvrhi::IFramebuffer* EnvironmentRenderPass::GetFramebuffer() {
|
|
return m_gbuffer->m_framebuffer;
|
|
}
|