Add ubershader support to material and SDF variants in Forward+.

This commit is contained in:
Dario 2025-08-07 14:40:14 -03:00
parent b1792e5fb5
commit 517b42e7dd
3 changed files with 13 additions and 19 deletions

View file

@ -489,11 +489,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RID vertex_array_rd; RID vertex_array_rd;
RID index_array_rd; RID index_array_rd;
RID pipeline_rd; RID pipeline_rd;
uint32_t ubershader_iterations = 2; const uint32_t ubershader_iterations = 2;
if constexpr (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || p_pass_mode == PASS_MODE_SDF) {
ubershader_iterations = 1;
}
bool pipeline_valid = false; bool pipeline_valid = false;
while (pipeline_key.ubershader < ubershader_iterations) { while (pipeline_key.ubershader < ubershader_iterations) {
// Skeleton and blend shape. // Skeleton and blend shape.
@ -519,9 +515,8 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
pipeline_hash = pipeline_key.hash(); pipeline_hash = pipeline_key.hash();
if (shader != prev_shader || pipeline_hash != prev_pipeline_hash) { if (shader != prev_shader || pipeline_hash != prev_pipeline_hash) {
bool wait_for_compilation = (ubershader_iterations == 1) || pipeline_key.ubershader; RS::PipelineSource pipeline_source = pipeline_key.ubershader ? RS::PIPELINE_SOURCE_DRAW : RS::PIPELINE_SOURCE_SPECIALIZATION;
RS::PipelineSource pipeline_source = wait_for_compilation ? RS::PIPELINE_SOURCE_DRAW : RS::PIPELINE_SOURCE_SPECIALIZATION; pipeline_rd = shader->pipeline_hash_map.get_pipeline(pipeline_key, pipeline_hash, pipeline_key.ubershader, pipeline_source);
pipeline_rd = shader->pipeline_hash_map.get_pipeline(pipeline_key, pipeline_hash, wait_for_compilation, pipeline_source);
if (pipeline_rd.is_valid()) { if (pipeline_rd.is_valid()) {
pipeline_valid = true; pipeline_valid = true;
@ -3778,7 +3773,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
// The variant for SDF from the default material should only be retrieved when SDFGI is required. // The variant for SDF from the default material should only be retrieved when SDFGI is required.
ERR_FAIL_NULL_V(scene_shader.default_material_shader_ptr, RID()); ERR_FAIL_NULL_V(scene_shader.default_material_shader_ptr, RID());
scene_shader.enable_advanced_shader_group(); scene_shader.enable_advanced_shader_group();
scene_shader.default_shader_sdfgi_rd = scene_shader.default_material_shader_ptr->get_shader_variant(SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF, 0, false); scene_shader.default_shader_sdfgi_rd = scene_shader.default_material_shader_ptr->get_shader_variant(SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF, 0, true);
ERR_FAIL_COND_V(scene_shader.default_shader_sdfgi_rd.is_null(), RID()); ERR_FAIL_COND_V(scene_shader.default_shader_sdfgi_rd.is_null(), RID());
} }
@ -4570,11 +4565,11 @@ void RenderForwardClustered::_mesh_compile_pipelines_for_surface(const SurfacePi
// Depth pass with SDFGI support. // Depth pass with SDFGI support.
pipeline_key.version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF; pipeline_key.version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF;
pipeline_key.framebuffer_format_id = _get_depth_framebuffer_format_for_pipeline(buffers_can_be_storage, RD::TextureSamples(p_global.texture_samples), false, false); pipeline_key.framebuffer_format_id = _get_depth_framebuffer_format_for_pipeline(buffers_can_be_storage, RD::TextureSamples(p_global.texture_samples), false, false);
_mesh_compile_pipeline_for_surface(p_surface.shader, p_surface.mesh_surface, false, p_surface.instanced, p_source, pipeline_key, r_pipeline_pairs); _mesh_compile_pipeline_for_surface(p_surface.shader, p_surface.mesh_surface, true, p_surface.instanced, p_source, pipeline_key, r_pipeline_pairs);
// Depth pass with SDFGI support for an empty framebuffer. // Depth pass with SDFGI support for an empty framebuffer.
pipeline_key.framebuffer_format_id = RD::get_singleton()->framebuffer_format_create_empty(); pipeline_key.framebuffer_format_id = RD::get_singleton()->framebuffer_format_create_empty();
_mesh_compile_pipeline_for_surface(p_surface.shader, p_surface.mesh_surface, false, p_surface.instanced, p_source, pipeline_key, r_pipeline_pairs); _mesh_compile_pipeline_for_surface(p_surface.shader, p_surface.mesh_surface, true, p_surface.instanced, p_source, pipeline_key, r_pipeline_pairs);
} }
// The dedicated depth passes use a different version of the surface and the shader. // The dedicated depth passes use a different version of the surface and the shader.

View file

@ -272,7 +272,7 @@ Pair<ShaderRD *, RID> SceneShaderForwardClustered::ShaderData::get_native_shader
} }
uint16_t SceneShaderForwardClustered::ShaderData::_get_shader_version(PipelineVersion p_pipeline_version, uint32_t p_color_pass_flags, bool p_ubershader) const { uint16_t SceneShaderForwardClustered::ShaderData::_get_shader_version(PipelineVersion p_pipeline_version, uint32_t p_color_pass_flags, bool p_ubershader) const {
uint32_t ubershader_base = p_ubershader ? ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL : 0; uint32_t ubershader_base = p_ubershader ? ShaderVersion::SHADER_VERSION_COLOR_PASS : 0;
switch (p_pipeline_version) { switch (p_pipeline_version) {
case PIPELINE_VERSION_DEPTH_PASS: case PIPELINE_VERSION_DEPTH_PASS:
return ShaderVersion::SHADER_VERSION_DEPTH_PASS + ubershader_base; return ShaderVersion::SHADER_VERSION_DEPTH_PASS + ubershader_base;
@ -289,9 +289,9 @@ uint16_t SceneShaderForwardClustered::ShaderData::_get_shader_version(PipelineVe
case PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW: case PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW:
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW + ubershader_base; return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW + ubershader_base;
case PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL: case PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL:
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL + ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL; return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL + ubershader_base;
case PIPELINE_VERSION_DEPTH_PASS_WITH_SDF: case PIPELINE_VERSION_DEPTH_PASS_WITH_SDF:
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL + ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_SDF; return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_SDF + ubershader_base;
case PIPELINE_VERSION_COLOR_PASS: { case PIPELINE_VERSION_COLOR_PASS: {
int shader_flags = 0; int shader_flags = 0;
@ -315,7 +315,7 @@ uint16_t SceneShaderForwardClustered::ShaderData::_get_shader_version(PipelineVe
shader_flags |= SHADER_COLOR_PASS_FLAG_MULTIVIEW; shader_flags |= SHADER_COLOR_PASS_FLAG_MULTIVIEW;
} }
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL + ShaderVersion::SHADER_VERSION_COLOR_PASS + shader_flags; return ShaderVersion::SHADER_VERSION_COLOR_PASS * 2 + shader_flags;
} break; } break;
default: { default: {
DEV_ASSERT(false && "Unknown pipeline version."); DEV_ASSERT(false && "Unknown pipeline version.");
@ -632,11 +632,10 @@ void SceneShaderForwardClustered::init(const String p_defines) {
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n", false)); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n", false)); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
} }
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
Vector<String> color_pass_flags = { Vector<String> color_pass_flags = {
"\n#define UBERSHADER\n", // SHADER_COLOR_PASS_FLAG_UBERSHADER "\n#define UBERSHADER\n", // SHADER_COLOR_PASS_FLAG_UBERSHADER
"\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR "\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR

View file

@ -217,7 +217,7 @@ public:
RID version; RID version;
static const uint32_t VERTEX_INPUT_MASKS_SIZE = ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL + ShaderVersion::SHADER_VERSION_COLOR_PASS + SHADER_COLOR_PASS_FLAG_COUNT; static const uint32_t VERTEX_INPUT_MASKS_SIZE = ShaderVersion::SHADER_VERSION_COLOR_PASS * 2 + SHADER_COLOR_PASS_FLAG_COUNT;
std::atomic<uint64_t> vertex_input_masks[VERTEX_INPUT_MASKS_SIZE] = {}; std::atomic<uint64_t> vertex_input_masks[VERTEX_INPUT_MASKS_SIZE] = {};
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;