You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-11 13:10:58 +00:00
Add Shader compile groups to RD Shader system
This allows us to specify a subset of variants to compile at load time and conditionally other variants later. This works seamlessly with shader caching. Needed to ensure that users only pay the cost for variants they use
This commit is contained in:
@@ -802,6 +802,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
|
||||
scene_state.used_screen_texture = false;
|
||||
scene_state.used_normal_texture = false;
|
||||
scene_state.used_depth_texture = false;
|
||||
scene_state.used_lightmap = false;
|
||||
}
|
||||
uint32_t lightmap_captures_used = 0;
|
||||
|
||||
@@ -1015,6 +1016,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
|
||||
|
||||
if (uses_lightmap) {
|
||||
surf->sort.uses_lightmap = 1;
|
||||
scene_state.used_lightmap = true;
|
||||
}
|
||||
|
||||
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING) {
|
||||
@@ -1649,6 +1651,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||
|
||||
if (rb->get_use_taa() || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
|
||||
color_pass_flags |= COLOR_PASS_FLAG_MOTION_VECTORS;
|
||||
scene_shader.enable_advanced_shader_group();
|
||||
}
|
||||
|
||||
if (p_render_data->voxel_gi_instances->size() > 0) {
|
||||
@@ -1668,6 +1671,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||
|
||||
if (p_render_data->scene_data->view_count > 1) {
|
||||
color_pass_flags |= COLOR_PASS_FLAG_MULTIVIEW;
|
||||
// Try enabling here in case is_xr_enabled() returns false.
|
||||
scene_shader.shader.enable_group(SceneShaderForwardClustered::SHADER_GROUP_MULTIVIEW);
|
||||
}
|
||||
|
||||
color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
|
||||
@@ -1733,6 +1738,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||
color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
|
||||
color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
|
||||
}
|
||||
|
||||
if (using_sss || using_separate_specular || scene_state.used_lightmap || using_voxelgi) {
|
||||
scene_shader.enable_advanced_shader_group(p_render_data->scene_data->view_count > 1);
|
||||
}
|
||||
|
||||
RID radiance_texture;
|
||||
bool draw_sky = false;
|
||||
bool draw_sky_fog_only = false;
|
||||
@@ -2505,6 +2515,8 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
|
||||
render_data.cluster_max_elements = 32;
|
||||
render_data.instances = &p_instances;
|
||||
|
||||
scene_shader.enable_advanced_shader_group();
|
||||
|
||||
_update_render_base_uniform_set();
|
||||
|
||||
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
|
||||
@@ -2554,6 +2566,8 @@ void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance
|
||||
render_data.cluster_max_elements = 32;
|
||||
render_data.instances = &p_instances;
|
||||
|
||||
scene_shader.enable_advanced_shader_group();
|
||||
|
||||
_update_render_base_uniform_set();
|
||||
|
||||
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
|
||||
@@ -3342,6 +3356,10 @@ void RenderForwardClustered::sdfgi_update(const Ref<RenderSceneBuffers> &p_rende
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure advanced shaders are available if SDFGI is used.
|
||||
// Call here as this is the first entry point for SDFGI.
|
||||
scene_shader.enable_advanced_shader_group();
|
||||
|
||||
static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 };
|
||||
uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge];
|
||||
|
||||
|
||||
@@ -328,6 +328,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
||||
bool used_normal_texture = false;
|
||||
bool used_depth_texture = false;
|
||||
bool used_sss = false;
|
||||
bool used_lightmap = false;
|
||||
|
||||
struct ShadowPass {
|
||||
uint32_t element_from;
|
||||
|
||||
@@ -301,7 +301,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
||||
|
||||
if (k == PIPELINE_VERSION_COLOR_PASS) {
|
||||
for (int l = 0; l < PIPELINE_COLOR_PASS_FLAG_COUNT; l++) {
|
||||
if (!shader_singleton->valid_color_pass_pipelines.has(l)) {
|
||||
if (!shader_singleton->valid_color_pass_pipelines[l]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -476,16 +476,16 @@ void SceneShaderForwardClustered::init(const String p_defines) {
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
|
||||
{
|
||||
Vector<String> shader_versions;
|
||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS
|
||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_DEPTH_PASS_DP
|
||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS
|
||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI
|
||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
|
||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
|
||||
shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW
|
||||
shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW
|
||||
shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW
|
||||
Vector<ShaderRD::VariantDefine> shader_versions;
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, "\n#define MODE_RENDER_DEPTH\n", true)); // SHADER_VERSION_DEPTH_PASS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n", true)); // SHADER_VERSION_DEPTH_PASS_DP
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n", true)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, "\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
|
||||
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
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, "\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, "\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, "\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
|
||||
|
||||
Vector<String> color_pass_flags = {
|
||||
"\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR
|
||||
@@ -501,54 +501,38 @@ void SceneShaderForwardClustered::init(const String p_defines) {
|
||||
version += color_pass_flags[j];
|
||||
}
|
||||
}
|
||||
shader_versions.push_back(version);
|
||||
|
||||
// Assign a group based on what features this pass contains.
|
||||
ShaderGroup group = SHADER_GROUP_BASE;
|
||||
bool advanced_group = (i & SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR) || (i & SHADER_COLOR_PASS_FLAG_LIGHTMAP) || (i & SHADER_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
bool multiview_group = i & SHADER_COLOR_PASS_FLAG_MULTIVIEW;
|
||||
if (advanced_group && multiview_group) {
|
||||
group = SHADER_GROUP_ADVANCED_MULTIVIEW;
|
||||
} else if (advanced_group) {
|
||||
group = SHADER_GROUP_ADVANCED;
|
||||
} else if (multiview_group) {
|
||||
group = SHADER_GROUP_MULTIVIEW;
|
||||
}
|
||||
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(group, version, false));
|
||||
}
|
||||
|
||||
shader.initialize(shader_versions, p_defines);
|
||||
|
||||
if (!RendererCompositorRD::get_singleton()->is_xr_enabled()) {
|
||||
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false);
|
||||
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW, false);
|
||||
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW, false);
|
||||
|
||||
// Disable Color Passes
|
||||
for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) {
|
||||
// Selectively disable any shader pass that includes Multiview.
|
||||
if ((i & SHADER_COLOR_PASS_FLAG_MULTIVIEW)) {
|
||||
shader.set_variant_enabled(i + SHADER_VERSION_COLOR_PASS, false);
|
||||
}
|
||||
}
|
||||
if (RendererCompositorRD::get_singleton()->is_xr_enabled()) {
|
||||
shader.enable_group(SHADER_GROUP_MULTIVIEW);
|
||||
}
|
||||
}
|
||||
|
||||
valid_color_pass_pipelines.insert(0);
|
||||
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
|
||||
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
|
||||
// Set flag to true if a combination is valid.
|
||||
// The only invalid combinations are those that include both TRANSPARENT and SEPARATE_SPECULAR.
|
||||
for (int i = 0; i < PIPELINE_COLOR_PASS_FLAG_COUNT; i++) {
|
||||
if ((i & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) && (i & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR)) {
|
||||
valid_color_pass_pipelines[i] = false;
|
||||
} else {
|
||||
valid_color_pass_pipelines[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs);
|
||||
material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs);
|
||||
@@ -854,3 +838,11 @@ void SceneShaderForwardClustered::set_default_specialization_constants(const Vec
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardClustered::enable_advanced_shader_group(bool p_needs_multiview) {
|
||||
if (p_needs_multiview || RendererCompositorRD::get_singleton()->is_xr_enabled()) {
|
||||
shader.enable_group(SHADER_GROUP_ADVANCED_MULTIVIEW);
|
||||
} else {
|
||||
shader.enable_group(SHADER_GROUP_ADVANCED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,13 @@ private:
|
||||
static SceneShaderForwardClustered *singleton;
|
||||
|
||||
public:
|
||||
enum ShaderGroup {
|
||||
SHADER_GROUP_BASE, // Always compiled at the beginning.
|
||||
SHADER_GROUP_ADVANCED,
|
||||
SHADER_GROUP_MULTIVIEW,
|
||||
SHADER_GROUP_ADVANCED_MULTIVIEW,
|
||||
};
|
||||
|
||||
enum ShaderVersion {
|
||||
SHADER_VERSION_DEPTH_PASS,
|
||||
SHADER_VERSION_DEPTH_PASS_DP,
|
||||
@@ -78,8 +85,8 @@ public:
|
||||
};
|
||||
|
||||
enum PipelineColorPassFlags {
|
||||
PIPELINE_COLOR_PASS_FLAG_TRANSPARENT = 1 << 0,
|
||||
PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1,
|
||||
PIPELINE_COLOR_PASS_FLAG_TRANSPARENT = 1 << 0, // Can't combine with SEPARATE_SPECULAR.
|
||||
PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1, // Can't combine with TRANSPARENT.
|
||||
PIPELINE_COLOR_PASS_FLAG_LIGHTMAP = 1 << 2,
|
||||
PIPELINE_COLOR_PASS_FLAG_MULTIVIEW = 1 << 3,
|
||||
PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS = 1 << 4,
|
||||
@@ -242,12 +249,13 @@ public:
|
||||
ShaderData *debug_shadow_splits_material_shader_ptr = nullptr;
|
||||
|
||||
Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
|
||||
HashSet<uint32_t> valid_color_pass_pipelines;
|
||||
bool valid_color_pass_pipelines[PIPELINE_COLOR_PASS_FLAG_COUNT];
|
||||
SceneShaderForwardClustered();
|
||||
~SceneShaderForwardClustered();
|
||||
|
||||
void init(const String p_defines);
|
||||
void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants);
|
||||
void enable_advanced_shader_group(bool p_needs_multiview = false);
|
||||
};
|
||||
|
||||
} // namespace RendererSceneRenderImplementation
|
||||
|
||||
Reference in New Issue
Block a user