add depth prepass in preparation for moving from deferred back to forward renderer

This commit is contained in:
Wls50
2025-11-23 09:19:44 +01:00
committed by Hirek
parent 915e4c769e
commit 593a8a288f
10 changed files with 201 additions and 53 deletions

View File

@@ -424,6 +424,7 @@ class NvRenderer : public gfx_renderer, public MaResourceRegistry {
float m_opacity;
float m_selfillum;
glm::vec3 m_diffuse;
std::string_view m_name = "";
};
struct SpotLight {
glm::vec3 m_color;
@@ -610,16 +611,21 @@ class NvRenderer : public gfx_renderer, public MaResourceRegistry {
nvrhi::BufferHandle m_cubedrawconstant_buffer;
nvrhi::BufferHandle m_drawconstant_buffer;
std::array<nvrhi::ShaderHandle, Constants::NumDrawTypes()> m_vertex_shader;
std::array<nvrhi::ShaderHandle, Constants::NumDrawTypes()> m_vertex_shader_prepass;
std::array<nvrhi::ShaderHandle, Constants::NumDrawTypes()>
m_vertex_shader_cubemap;
std::array<nvrhi::ShaderHandle, Constants::NumDrawTypes()>
m_vertex_shader_shadow;
nvrhi::BindingLayoutHandle m_binding_layout_shadow_masked;
nvrhi::BindingLayoutHandle m_binding_layout_prepass;
nvrhi::ShaderHandle m_pixel_shader_shadow_masked;
nvrhi::ShaderHandle m_pixel_shader_prepass_masked;
std::array<nvrhi::InputLayoutHandle, Constants::NumDrawTypes()>
m_input_layout;
m_input_layout;
std::array<nvrhi::GraphicsPipelineHandle, Constants::NumShadowPipelines()>
m_pso_shadow;
std::array<nvrhi::GraphicsPipelineHandle, Constants::NumShadowPipelines()>
m_pso_prepass;
nvrhi::GraphicsPipelineHandle m_pso_line;
std::condition_variable m_cv_next_frame;

View File

@@ -3,6 +3,7 @@
namespace RendererEnums {
enum class RenderPassType {
DepthOnly,
Deferred,
Forward,
CubeMap,

View File

@@ -94,6 +94,10 @@ nvrhi::IGraphicsPipeline *NvRenderer::MaterialTemplate::GetPipeline(
return m_renderer->m_pso_shadow[Constants::GetDefaultShadowPipelineIndex(
draw_type, alpha_masked)];
}
if (pass_type == RenderPassType::DepthOnly) {
return m_renderer->m_pso_prepass[Constants::GetDefaultShadowPipelineIndex(
draw_type, alpha_masked)];
}
return nullptr;
}
@@ -169,6 +173,14 @@ void NvRenderer::MaterialTemplate::Init(const YAML::Node &conf) {
.Add(texture_mapping_shadow)
.Add(sampler_mapping_shadow);
}
if (pass == RenderPassType::DepthOnly) {
mappings
.Add(MaResourceMapping::ConstantBuffer(
0, "cb_draw_constants_static"))
.Add(MaResourceMapping::PushConstants<PushConstantsDraw>(1))
.Add(texture_mapping_shadow)
.Add(sampler_mapping_shadow);
}
continue;
}
pipeline_desc.setPixelShader(pixel_shader)
@@ -181,6 +193,7 @@ void NvRenderer::MaterialTemplate::Init(const YAML::Node &conf) {
pipeline_desc.setInputLayout(
m_renderer->m_input_layout[static_cast<size_t>(draw)]);
switch (pass) {
case RenderPassType::DepthOnly:
case RenderPassType::Deferred:
case RenderPassType::Forward:
pipeline_desc.setVertexShader(
@@ -193,6 +206,7 @@ void NvRenderer::MaterialTemplate::Init(const YAML::Node &conf) {
default:;
}
switch (pass) {
case RenderPassType::DepthOnly:
case RenderPassType::Deferred:
case RenderPassType::Forward:
mappings.Add(MaResourceMapping::PushConstants<PushConstantsDraw>(1))
@@ -220,12 +234,16 @@ void NvRenderer::MaterialTemplate::Init(const YAML::Node &conf) {
.Add(MaResourceMapping::Texture_SRV(11, "shadow_depths"))
.Add(MaResourceMapping::Texture_SRV(12, "gbuffer_depth"))
.Add(MaResourceMapping::Texture_SRV(14, "sky_aerial_lut"))
.Add(MaResourceMapping::Texture_SRV(16, "forwardplus_index_grid_transparent"))
.Add(MaResourceMapping::StructuredBuffer_SRV(17, "forwardplus_index_buffer_transparent"))
.Add(MaResourceMapping::StructuredBuffer_SRV(18, "forwardplus_light_buffer"))
.Add(MaResourceMapping::Texture_SRV(
16, "forwardplus_index_grid_transparent"))
.Add(MaResourceMapping::StructuredBuffer_SRV(
17, "forwardplus_index_buffer_transparent"))
.Add(MaResourceMapping::StructuredBuffer_SRV(
18, "forwardplus_light_buffer"))
.Add(MaResourceMapping::Sampler(8, "sampler_linear_wrap"))
.Add(MaResourceMapping::Sampler(11, "shadow_sampler_comp"))
.Add(MaResourceMapping::Sampler(13, "sampler_linear_clamp_v_repeat_h"));
.Add(MaResourceMapping::Sampler(
13, "sampler_linear_clamp_v_repeat_h"));
break;
default:;
}
@@ -243,7 +261,22 @@ void NvRenderer::MaterialTemplate::Init(const YAML::Node &conf) {
}
switch (pass) {
case RenderPassType::Deferred:
case RenderPassType::CubeMap:
pipeline_desc.setRenderState(
nvrhi::RenderState()
.setDepthStencilState(
nvrhi::DepthStencilState()
.enableDepthTest()
.disableStencil()
.setDepthFunc(nvrhi::ComparisonFunc::Equal))
.setRasterState(nvrhi::RasterState()
.setFillSolid()
.enableDepthClip()
.disableScissor()
.setCullFront())
.setBlendState(nvrhi::BlendState().setRenderTarget(
0, nvrhi::BlendState::RenderTarget().disableBlend())));
break;
case RenderPassType::CubeMap:
pipeline_desc.setRenderState(
nvrhi::RenderState()
.setDepthStencilState(
@@ -419,8 +452,14 @@ bool NvRenderer::InitMaterials() {
m_vertex_shader[static_cast<size_t>(DrawType::Model)] =
m_backend->CreateShader("default_vertex", nvrhi::ShaderType::Vertex);
m_vertex_shader_prepass[static_cast<size_t>(DrawType::Model)] =
m_backend->CreateShader("default_prepass_vertex",
nvrhi::ShaderType::Vertex);
m_vertex_shader[static_cast<size_t>(DrawType::InstancedModel)] =
m_backend->CreateShader("instanced_vertex", nvrhi::ShaderType::Vertex);
m_vertex_shader_prepass[static_cast<size_t>(DrawType::InstancedModel)] =
m_backend->CreateShader("instanced_prepass_vertex",
nvrhi::ShaderType::Vertex);
m_vertex_shader_shadow[static_cast<size_t>(DrawType::Model)] =
m_backend->CreateShader("shadow_vertex", nvrhi::ShaderType::Vertex);
m_vertex_shader_shadow[static_cast<size_t>(DrawType::InstancedModel)] =
@@ -433,6 +472,8 @@ bool NvRenderer::InitMaterials() {
nvrhi::ShaderType::Vertex);
m_pixel_shader_shadow_masked =
m_backend->CreateShader("shadow_masked", nvrhi::ShaderType::Pixel);
m_pixel_shader_prepass_masked =
m_backend->CreateShader("prepass_masked", nvrhi::ShaderType::Pixel);
nvrhi::VertexAttributeDesc desc[]{
nvrhi::VertexAttributeDesc()
@@ -481,55 +522,82 @@ bool NvRenderer::InitMaterials() {
m_vertex_shader[static_cast<size_t>(DrawType::InstancedModel)]);
{
m_binding_layout_shadow_masked =
m_backend->GetDevice()->createBindingLayout(
nvrhi::BindingLayoutDesc()
.setVisibility(nvrhi::ShaderType::Pixel)
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(0))
.addItem(nvrhi::BindingLayoutItem::Sampler(0)));
auto constexpr render_state_shadow =
nvrhi::RenderState()
.setDepthStencilState(
nvrhi::DepthStencilState()
.enableDepthTest()
.enableDepthWrite()
.disableStencil()
.setDepthFunc(nvrhi::ComparisonFunc::Greater))
.setRasterState(nvrhi::RasterState()
.setFillSolid()
.disableDepthClip()
.disableScissor()
.setCullBack()
.setDepthBias(1)
.setSlopeScaleDepthBias(-4.f))
.setBlendState(nvrhi::BlendState().setRenderTarget(
0, nvrhi::BlendState::RenderTarget().disableBlend()));
auto constexpr render_state_depthonly =
nvrhi::RenderState()
.setDepthStencilState(
nvrhi::DepthStencilState()
.enableDepthTest()
.enableDepthWrite()
.disableStencil()
.setDepthFunc(nvrhi::ComparisonFunc::Greater))
.setRasterState(nvrhi::RasterState()
.setFillSolid()
.enableDepthClip()
.disableScissor()
.setCullFront())
.setBlendState(nvrhi::BlendState().setRenderTarget(
0, nvrhi::BlendState::RenderTarget().disableBlend()));
for (int i = 0; i < Constants::NumDrawTypes(); ++i) {
for (int j = 0; j < 2; ++j) {
DrawType draw = static_cast<DrawType>(i);
bool masked = j;
nvrhi::BindingLayoutDesc desc =
nvrhi::BindingLayoutDesc desc_shadow =
*m_binding_layout_shadowdrawconstants->getDesc();
desc.visibility = nvrhi::ShaderType::All;
if (masked)
desc.addItem(nvrhi::BindingLayoutItem::Texture_SRV(0))
.addItem(nvrhi::BindingLayoutItem::Sampler(0));
auto binding_layout =
GetBackend()->GetDevice()->createBindingLayout(desc);
auto pipeline_desc =
nvrhi::GraphicsPipelineDesc()
.setRenderState(
nvrhi::RenderState()
.setDepthStencilState(
nvrhi::DepthStencilState()
.enableDepthTest()
.enableDepthWrite()
.disableStencil()
.setDepthFunc(nvrhi::ComparisonFunc::Greater))
.setRasterState(nvrhi::RasterState()
.setFillSolid()
.disableDepthClip()
.disableScissor()
.setCullBack()
.setDepthBias(1)
.setSlopeScaleDepthBias(-4.f))
.setBlendState(nvrhi::BlendState().setRenderTarget(
0,
nvrhi::BlendState::RenderTarget().disableBlend())))
.setVertexShader(
m_vertex_shader_shadow[static_cast<size_t>(draw)])
.setInputLayout(m_input_layout[static_cast<size_t>(draw)]);
nvrhi::BindingLayoutDesc desc_prepass =
*m_binding_layout_drawconstants->getDesc();
desc_shadow.visibility = nvrhi::ShaderType::All;
desc_prepass.visibility = nvrhi::ShaderType::All;
if (masked) {
pipeline_desc.setPixelShader(m_pixel_shader_shadow_masked);
desc_shadow.addItem(nvrhi::BindingLayoutItem::Texture_SRV(0))
.addItem(nvrhi::BindingLayoutItem::Sampler(0));
desc_prepass.addItem(nvrhi::BindingLayoutItem::Texture_SRV(0))
.addItem(nvrhi::BindingLayoutItem::Sampler(0));
}
pipeline_desc.addBindingLayout(binding_layout);
auto binding_layout_shadow =
GetBackend()->GetDevice()->createBindingLayout(desc_shadow);
auto binding_layout_prepass =
GetBackend()->GetDevice()->createBindingLayout(desc_prepass);
auto pipeline_desc = nvrhi::GraphicsPipelineDesc().setInputLayout(
m_input_layout[static_cast<size_t>(draw)]);
m_pso_shadow[Constants::GetDefaultShadowPipelineIndex(draw, masked)] =
GetBackend()->GetDevice()->createGraphicsPipeline(
pipeline_desc, m_gbuffer_shadow->m_framebuffer);
nvrhi::GraphicsPipelineDesc(pipeline_desc)
.setRenderState(render_state_shadow)
.setVertexShader(
m_vertex_shader_shadow[static_cast<size_t>(draw)])
.setPixelShader(masked ? m_pixel_shader_shadow_masked
: nullptr)
.addBindingLayout(binding_layout_shadow),
m_gbuffer_shadow->m_framebuffer);
m_pso_prepass[Constants::GetDefaultShadowPipelineIndex(draw, masked)] =
GetBackend()->GetDevice()->createGraphicsPipeline(
nvrhi::GraphicsPipelineDesc(pipeline_desc)
.setVertexShader(
m_vertex_shader_prepass[static_cast<size_t>(draw)])
.setPixelShader(masked ? m_pixel_shader_prepass_masked
: nullptr)
.setRenderState(render_state_depthonly)
.addBindingLayout(binding_layout_prepass),
m_gbuffer->m_framebuffer);
}
}
}

View File

@@ -413,6 +413,18 @@ bool NvRenderer::Render() {
pass.m_history_transform =
std::exchange(m_previous_view, pass.m_transform);
command_list->beginMarker("Depth only");
pass.m_type = RenderPassType::DepthOnly;
RenderKabina(pass);
RenderShapes(pass);
RenderBatches(pass);
RenderTracks(pass);
RenderAnimateds(pass);
RenderLines(pass);
command_list->endMarker();
command_list->beginMarker("Gbuffer fill");
pass.m_type = RenderPassType::Deferred;
Timer::subsystem.gfx_color.start();
RenderKabina(pass);
RenderShapes(pass);
@@ -420,6 +432,7 @@ bool NvRenderer::Render() {
RenderTracks(pass);
RenderAnimateds(pass);
RenderLines(pass);
command_list->endMarker();
GatherSpotLights(pass);
@@ -1495,6 +1508,7 @@ void NvRenderer::UpdateDrawData(const RenderPass &pass,
pass.m_command_list_draw->setPushConstants(&data, sizeof(data));
break;
}
case RenderPassType::DepthOnly:
case RenderPassType::Deferred:
case RenderPassType::Forward: {
PushConstantsDraw data{};
@@ -1967,6 +1981,8 @@ void NvRenderer::Animate(Renderable &renderable, TSubModel *Submodel,
m_batched_instances.end()) {
auto &item = renderable.m_items.emplace_back();
item.m_name = Submodel->pName.c_str();
auto &motion_cache = m_motion_cache->Get(Submodel);
motion_cache.m_history_transform =

View File

@@ -959,13 +959,19 @@ void NvRenderer::RenderAnimateds(const RenderPass& pass) {
switch (command.m_type) {
case RenderCommand::ObjectType_Animated:
m_drawcall_counter = &m_drawcalls_tanimobj;
pass.m_command_list_draw->beginMarker(
m_animateds[command.m_index].m_model->name().c_str());
Render(m_animateds[command.m_index].m_renderable, pass, history_origin,
m_animateds[command.m_index].m_distance);
pass.m_command_list_draw->endMarker();
break;
case RenderCommand::ObjectType_Dynamic:
m_drawcall_counter = &m_drawcalls_dynamic;
pass.m_command_list_draw->beginMarker(
m_dynamics[command.m_index].m_dynamic->name().c_str());
Render(m_dynamics[command.m_index].m_renderable, pass, history_origin,
m_dynamics[command.m_index].m_distance);
pass.m_command_list_draw->endMarker();
break;
}
}
@@ -989,7 +995,9 @@ void NvRenderer::RenderKabina(const RenderPass& pass) {
default:
if (!dynamic.m_renderable_kabina.m_render_in_deferred) return;
}
pass.m_command_list_draw->beginMarker("Render cab");
Render(dynamic.m_renderable_kabina, pass, history_origin, dynamic.m_distance);
pass.m_command_list_draw->endMarker();
}
void NvRenderer::Render(const Renderable& renderable, const RenderPass& pass,
@@ -1009,13 +1017,15 @@ void NvRenderer::Render(const Renderable& renderable, const RenderPass& pass,
float alpha_threshold;
if (!BindGeometry(item.m_geometry, pass, gfx_state, draw_arguments,
indexed))
return;
continue;
if (!BindMaterial(item.m_material, DrawType::Model, pass, gfx_state,
alpha_threshold))
return;
continue;
BindConstants(pass, gfx_state);
pass.m_command_list_draw->beginMarker(item.m_name.data());
pass.m_command_list_draw->setGraphicsState(gfx_state);
auto transform = item.m_transform;
@@ -1034,6 +1044,8 @@ void NvRenderer::Render(const Renderable& renderable, const RenderPass& pass,
else
pass.m_command_list_draw->draw(draw_arguments);
m_drawcall_counter->Draw(draw_arguments);
pass.m_command_list_draw->endMarker();
}
}

View File

@@ -7,6 +7,12 @@ struct VertexInput {
float4 m_Tangent : Tangent;
};
#ifdef PREPASS
struct VertexOutput {
float2 m_TexCoord : TexCoord;
float4 m_PositionSV : SV_Position;
};
#else
struct VertexOutput {
float3 m_Position : Position;
float3 m_Normal : Normal;
@@ -16,6 +22,7 @@ struct VertexOutput {
float4 m_PositionCS : PositionCS;
float4 m_HistoryPositionCS : HistoryPositionCS;
};
#endif
cbuffer VertexConstants : register(b0) {
float4x4 g_JitteredProjection;
@@ -29,14 +36,17 @@ VertexOutput main(in VertexInput vs_in) {
VertexOutput result;
float4x3 model_view = GetModelView();
float4x3 model_view_history = GetModelViewHistory();
result.m_Position = mul(float4(vs_in.m_Position, 1.), model_view).xyz;
result.m_Normal = mul(float4(vs_in.m_Normal, 0.), model_view).xyz;
float3 view_space_position = mul(float4(vs_in.m_Position, 1.), model_view).xyz;
result.m_TexCoord = vs_in.m_TexCoord;
result.m_PositionSV = mul(g_JitteredProjection, float4(view_space_position, 1.));
#ifndef PREPASS
result.m_Normal = mul(float4(vs_in.m_Normal, 0.), model_view).xyz;
result.m_Position = view_space_position;
result.m_Tangent.xyz = mul(float4(vs_in.m_Tangent.xyz, 0.), model_view).xyz;
result.m_Tangent.w = vs_in.m_Tangent.w;
result.m_PositionSV = mul(g_JitteredProjection, float4(result.m_Position, 1.));
result.m_PositionCS = mul(g_Projection, float4(result.m_Position, 1.));
float3 history_position = mul(float4(vs_in.m_Position, 1.), model_view_history);
result.m_HistoryPositionCS = mul(g_ProjectionHistory, float4(history_position, 1.));
#endif
return result;
}

View File

@@ -8,6 +8,12 @@ struct VertexInput {
float4 m_InstanceTransform[3] : InstanceTransform;
};
#ifdef PREPASS
struct VertexOutput {
float2 m_TexCoord : TexCoord;
float4 m_PositionSV : SV_Position;
};
#else
struct VertexOutput {
float3 m_Position : Position;
float3 m_Normal : Normal;
@@ -17,6 +23,7 @@ struct VertexOutput {
float4 m_PositionCS : PositionCS;
float4 m_HistoryPositionCS : HistoryPositionCS;
};
#endif
cbuffer VertexConstants : register(b0) {
float4x4 g_JitteredProjection;
@@ -32,14 +39,17 @@ VertexOutput main(in VertexInput vs_in) {
float4x3 model_view_history = GetModelViewHistory();
float4x4 instance_transform = transpose(float4x4(vs_in.m_InstanceTransform[0], vs_in.m_InstanceTransform[1], vs_in.m_InstanceTransform[2], float4(0., 0., 0., 1.)));
float3 position = mul(float4(vs_in.m_Position, 1.), instance_transform).xyz;
result.m_Position = mul(float4(position, 1.), model_view).xyz;
result.m_Normal = mul(mul(float4(vs_in.m_Normal, 0.), instance_transform), model_view);
float3 view_space_position = mul(float4(position, 1.), model_view).xyz;
result.m_PositionSV = mul(g_JitteredProjection, float4(view_space_position, 1.));
result.m_TexCoord = vs_in.m_TexCoord;
#ifndef PREPASS
result.m_Position = view_space_position;
result.m_Normal = mul(mul(float4(vs_in.m_Normal, 0.), instance_transform), model_view);
result.m_Tangent.xyz = mul(mul(float4(vs_in.m_Tangent.xyz, 0.), instance_transform), model_view);
result.m_Tangent.w = vs_in.m_Tangent.w;
result.m_PositionSV = mul(g_JitteredProjection, float4(result.m_Position, 1.));
result.m_PositionCS = mul(g_Projection, float4(result.m_Position, 1.));
float3 history_position = mul(float4(position, 1.), model_view_history).xyz;
result.m_HistoryPositionCS = mul(g_ProjectionHistory, float4(history_position, 1.));
#endif
return result;
}

View File

@@ -2,7 +2,9 @@
#define ALPHA_MASK_HLSLI
void AlphaMask(in float alpha) {
#if (PASS & FORWARD_LIGHTING) || defined (SHADOW)
if(g_DrawConstants.m_AlphaThreshold >= 0. ? (alpha < g_DrawConstants.m_AlphaThreshold) : (alpha >= -g_DrawConstants.m_AlphaThreshold)) discard;
#endif
}
#endif

View File

@@ -157,6 +157,12 @@ shaders:
source: ps_shadow_masked
target: pixel
entrypoint: main
prepass_masked:
source: ps_shadow_masked
target: pixel
entrypoint: main
definitions:
PREPASS: 1
# Contact shadows
# TODO Depth conversion is broken since converting to reversed depth buffer
contact_shadows:
@@ -173,6 +179,12 @@ shaders:
source: default_vertex
target: vertex
entrypoint: main
default_prepass_vertex:
source: default_vertex
target: vertex
entrypoint: main
definitions:
PREPASS: 1
shadow_vertex:
source: shadow_vertex
target: vertex
@@ -185,6 +197,12 @@ shaders:
source: instanced_vertex
target: vertex
entrypoint: main
instanced_prepass_vertex:
source: instanced_vertex
target: vertex
entrypoint: main
definitions:
PREPASS: 1
instanced_shadow_vertex:
source: instanced_shadow_vertex
target: vertex

View File

@@ -3,8 +3,13 @@
sampler diffuse_sampler : register(s0);
Texture2D diffuse : register(t0);
#ifdef PREPASS
#include "manul/draw_constants.hlsli"
#else
#include "manul/draw_constants_shadow.hlsli"
#endif
#define SHADOW
#include "manul/alpha_mask.hlsli"
struct VertexOutput {