From a8873727ac23b56f29b9c5a64b5d875a8d185b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Fri, 20 Jun 2025 13:03:47 +0300 Subject: [PATCH] [macOS] Selectively bake specific shader variants for MoltenVK. --- editor/export/shader_baker_export_plugin.cpp | 10 ++++- .../renderer_rd/cluster_builder_rd.cpp | 40 +++++++++++++++++++ .../renderer_rd/cluster_builder_rd.h | 2 + servers/rendering/renderer_rd/shader_rd.cpp | 15 +++---- servers/rendering/renderer_rd/shader_rd.h | 21 ++++++++++ .../renderer_rd/shaders/cluster_render.glsl | 8 ++++ 6 files changed, 87 insertions(+), 9 deletions(-) diff --git a/editor/export/shader_baker_export_plugin.cpp b/editor/export/shader_baker_export_plugin.cpp index 5d0c633d426..90cc9bf6a88 100644 --- a/editor/export/shader_baker_export_plugin.cpp +++ b/editor/export/shader_baker_export_plugin.cpp @@ -397,8 +397,14 @@ void ShaderBakerExportPlugin::_customize_shader_version(ShaderRD *p_shader, RID for (int64_t i = 0; i < variant_count; i++) { int group = p_shader->get_variant_to_group(i); - if (!p_shader->is_variant_enabled(i) || !groups_to_compile.has(group)) { - continue; + if (p_shader->has_variant_bake_for(i)) { + if (!p_shader->get_variant_bake_for(i, shader_cache_platform_name + "_" + shader_cache_renderer_name + "_" + shader_container_driver) || !groups_to_compile.has(group)) { + continue; + } + } else { + if (!p_shader->is_variant_enabled(i) || !groups_to_compile.has(group)) { + continue; + } } WorkItem work_item; diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index f47ed35dc64..adaf52f994c 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -57,22 +57,62 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() { Vector variants; variants.push_back(""); variants.push_back("\n#define USE_ATTACHMENT\n"); + variants.push_back("\n#define MOLTENVK_USED\n"); + variants.push_back("\n#define USE_ATTACHMENT\n#define MOLTENVK_USED\n"); ClusterRender::ShaderVariant shader_variant; if (RD::get_singleton()->has_feature(RD::SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS)) { fb_format = RD::get_singleton()->framebuffer_format_create_empty(); blend_state = RD::PipelineColorBlendState::create_disabled(); +#if (defined(MACOS_ENABLED) || defined(APPLE_EMBEDDED_ENABLED)) + if (RD::get_singleton()->get_device_capabilities().device_family == RDD::DEVICE_VULKAN) { + shader_variant = ClusterRender::SHADER_NORMAL_MOLTENVK; + } else { + shader_variant = ClusterRender::SHADER_NORMAL; + } +#else shader_variant = ClusterRender::SHADER_NORMAL; +#endif } else { Vector afs; afs.push_back(RD::AttachmentFormat()); afs.write[0].usage_flags = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; fb_format = RD::get_singleton()->framebuffer_format_create(afs); blend_state = RD::PipelineColorBlendState::create_blend(); +#if (defined(MACOS_ENABLED) || defined(APPLE_EMBEDDED_ENABLED)) + if (RD::get_singleton()->get_device_capabilities().device_family == RDD::DEVICE_VULKAN) { + shader_variant = ClusterRender::SHADER_USE_ATTACHMENT_MOLTENVK; + } else { + shader_variant = ClusterRender::SHADER_USE_ATTACHMENT; + } +#else shader_variant = ClusterRender::SHADER_USE_ATTACHMENT; +#endif } cluster_render.cluster_render_shader.initialize(variants); +#if (defined(MACOS_ENABLED) || defined(APPLE_EMBEDDED_ENABLED)) + if (RD::get_singleton()->get_device_capabilities().device_family == RDD::DEVICE_VULKAN) { + cluster_render.cluster_render_shader.set_variant_enabled(ClusterRender::SHADER_NORMAL, false); + cluster_render.cluster_render_shader.set_variant_enabled(ClusterRender::SHADER_USE_ATTACHMENT, false); + } else { + cluster_render.cluster_render_shader.set_variant_enabled(ClusterRender::SHADER_NORMAL_MOLTENVK, false); + cluster_render.cluster_render_shader.set_variant_enabled(ClusterRender::SHADER_USE_ATTACHMENT_MOLTENVK, false); + } +#else + cluster_render.cluster_render_shader.set_variant_enabled(ClusterRender::SHADER_NORMAL_MOLTENVK, false); + cluster_render.cluster_render_shader.set_variant_enabled(ClusterRender::SHADER_USE_ATTACHMENT_MOLTENVK, false); +#endif + cluster_render.cluster_render_shader.set_variants_bake_for(ClusterRender::SHADER_NORMAL, "macos_forward_clustered_vulkan", false, true); + cluster_render.cluster_render_shader.set_variants_bake_for(ClusterRender::SHADER_USE_ATTACHMENT, "macos_forward_clustered_vulkan", false, true); + cluster_render.cluster_render_shader.set_variants_bake_for(ClusterRender::SHADER_NORMAL_MOLTENVK, "macos_forward_clustered_vulkan", true, false); + cluster_render.cluster_render_shader.set_variants_bake_for(ClusterRender::SHADER_USE_ATTACHMENT_MOLTENVK, "macos_forward_clustered_vulkan", true, false); + + cluster_render.cluster_render_shader.set_variants_bake_for(ClusterRender::SHADER_NORMAL, "ios_forward_clustered_vulkan", false, true); + cluster_render.cluster_render_shader.set_variants_bake_for(ClusterRender::SHADER_USE_ATTACHMENT, "ios_forward_clustered_vulkan", false, true); + cluster_render.cluster_render_shader.set_variants_bake_for(ClusterRender::SHADER_NORMAL_MOLTENVK, "ios_forward_clustered_vulkan", true, false); + cluster_render.cluster_render_shader.set_variants_bake_for(ClusterRender::SHADER_USE_ATTACHMENT_MOLTENVK, "ios_forward_clustered_vulkan", true, false); + cluster_render.shader_version = cluster_render.cluster_render_shader.version_create(); cluster_render.shader = cluster_render.cluster_render_shader.version_get_shader(cluster_render.shader_version, shader_variant); cluster_render.shader_pipelines[ClusterRender::PIPELINE_NORMAL] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, fb_format, vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rasterization_state, RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h index 3b852b8c67a..ac4e6a8d409 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.h +++ b/servers/rendering/renderer_rd/cluster_builder_rd.h @@ -76,6 +76,8 @@ class ClusterBuilderSharedDataRD { enum ShaderVariant { SHADER_NORMAL, SHADER_USE_ATTACHMENT, + SHADER_NORMAL_MOLTENVK, + SHADER_USE_ATTACHMENT_MOLTENVK, }; enum PipelineVersion { diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index ed8ecdc4b12..b90be987d11 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -235,9 +235,6 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c } #if (defined(MACOS_ENABLED) || defined(APPLE_EMBEDDED_ENABLED)) RenderingDevice *rd = RD::get_singleton(); - if (rd->get_device_capabilities().device_family == RDD::DEVICE_VULKAN) { - builder.append("#define MOLTENVK_USED\n"); - } if (!rd->has_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT)) { builder.append("#define NO_IMAGE_ATOMICS\n"); } @@ -272,7 +269,7 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c } Vector ShaderRD::_build_variant_stage_sources(uint32_t p_variant, CompileData p_data) { - if (!variants_enabled[p_variant]) { + if (!variants_enabled[p_variant] && !variants_bake_for.has(p_variant)) { return Vector(); // Variant is disabled, return. } @@ -474,7 +471,10 @@ bool ShaderRD::_load_from_cache(Version *p_version, int p_group) { int variant_id = group_to_variant_map[p_group][i]; uint32_t variant_size = f->get_32(); ERR_FAIL_COND_V(variant_size == 0 && variants_enabled[variant_id], false); - if (!variants_enabled[variant_id]) { + if (!variants_enabled[variant_id] && !variants_bake_for.has(variant_id)) { + continue; + } + if (variant_size == 0) { continue; } Vector variant_bytes; @@ -489,10 +489,11 @@ bool ShaderRD::_load_from_cache(Version *p_version, int p_group) { for (uint32_t i = 0; i < variant_count; i++) { int variant_id = group_to_variant_map[p_group][i]; - if (!variants_enabled[variant_id]) { + if ((!variants_enabled[variant_id] && !variants_bake_for.has(variant_id)) || p_version->variant_data[variant_id].is_empty()) { p_version->variants.write[variant_id] = RID(); continue; } + print_verbose(vformat("Loading cache for shader %s, variant %d", name, i)); { RID shader = RD::get_singleton()->shader_create_from_bytecode_with_samplers(p_version->variant_data[variant_id], p_version->variants[variant_id], immutable_samplers); if (shader.is_null()) { @@ -581,7 +582,7 @@ void ShaderRD::_compile_version_end(Version *p_version, int p_group) { if (!all_valid) { // Clear versions if they exist. for (int i = 0; i < variant_defines.size(); i++) { - if (!variants_enabled[i] || !group_enabled[variant_defines[i].group]) { + if ((!variants_enabled[i] && !variants_bake_for.has(i)) || !group_enabled[variant_defines[i].group]) { continue; // Disabled. } if (!p_version->variants[i].is_null()) { diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h index 2a38e27886a..3ed5a0194ee 100644 --- a/servers/rendering/renderer_rd/shader_rd.h +++ b/servers/rendering/renderer_rd/shader_rd.h @@ -60,6 +60,8 @@ private: CharString general_defines; Vector variant_defines; Vector variants_enabled; + HashMap> variants_bake_for; + HashMap variants_bake_for_def; Vector variant_to_group; HashMap> group_to_variant_map; Vector group_enabled; @@ -216,6 +218,25 @@ public: int64_t get_variant_count() const; int get_variant_to_group(int p_variant) const; + bool has_variant_bake_for(int p_variant) const { + return variants_bake_for.has(p_variant); + } + + bool get_variant_bake_for(int p_variant, const String &p_name) const { + if (!variants_bake_for.has(p_variant)) { + return is_variant_enabled(p_variant); + } + if (!variants_bake_for[p_variant].has(p_name.to_lower())) { + return variants_bake_for_def[p_variant]; + } + return variants_bake_for[p_variant][p_name.to_lower()]; + } + + void set_variants_bake_for(int p_variant, const String &p_name, bool p_enable, bool p_default) { + variants_bake_for[p_variant][p_name.to_lower()] = p_enable; + variants_bake_for_def[p_variant] = p_default; + } + // Enable/disable groups for things that might be enabled at run time. void enable_group(int p_group); bool is_group_enabled(int p_group) const; diff --git a/servers/rendering/renderer_rd/shaders/cluster_render.glsl b/servers/rendering/renderer_rd/shaders/cluster_render.glsl index 4a4299080fb..91ab7488358 100644 --- a/servers/rendering/renderer_rd/shaders/cluster_render.glsl +++ b/servers/rendering/renderer_rd/shaders/cluster_render.glsl @@ -114,7 +114,11 @@ void main() { uint aux = 0; uint cluster_thread_group_index; +#ifndef MOLTENVK_USED if (!gl_HelperInvocation) { +#else + { +#endif //https://advances.realtimerendering.com/s2017/2017_Sig_Improved_Culling_final.pdf uvec4 mask; @@ -147,7 +151,11 @@ void main() { uint z_write_offset = cluster_offset + state.cluster_depth_offset + element_index; uint z_write_bit = 1 << z_bit; +#ifndef MOLTENVK_USED if (!gl_HelperInvocation) { +#else + { +#endif z_write_bit = subgroupOr(z_write_bit); //merge all Zs if (cluster_thread_group_index == 0) { aux = atomicOr(cluster_render.data[z_write_offset], z_write_bit);