@@ -47,6 +47,24 @@ Fog::~Fog() {
4747 singleton = nullptr ;
4848}
4949
50+ int Fog::_get_fog_variant () {
51+ RenderingDevice *rd = RD::get_singleton ();
52+ if (rd->has_feature (RD::SUPPORTS_IMAGE_ATOMIC_32_BIT)) {
53+ return 0 ;
54+ } else {
55+ return 1 ;
56+ }
57+ }
58+
59+ int Fog::_get_fog_process_variant (int p_idx) {
60+ RenderingDevice *rd = RD::get_singleton ();
61+ if (rd->has_feature (RD::SUPPORTS_IMAGE_ATOMIC_32_BIT)) {
62+ return p_idx;
63+ } else {
64+ return p_idx + VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX;
65+ }
66+ }
67+
5068/* FOG VOLUMES */
5169
5270RID Fog::fog_volume_allocate () {
@@ -143,7 +161,7 @@ Vector3 Fog::fog_volume_get_size(RID p_fog_volume) const {
143161bool Fog::FogMaterialData::update_parameters (const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
144162 uniform_set_updated = true ;
145163
146- return update_parameters_uniform_set (p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms , shader_data->ubo_offsets .ptr (), shader_data->texture_uniforms , shader_data->default_texture_params , shader_data->ubo_size , uniform_set, Fog::get_singleton ()->volumetric_fog .shader .version_get_shader (shader_data->version , 0 ), VolumetricFogShader::FogSet::FOG_SET_MATERIAL, true , true );
164+ return update_parameters_uniform_set (p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms , shader_data->ubo_offsets .ptr (), shader_data->texture_uniforms , shader_data->default_texture_params , shader_data->ubo_size , uniform_set, Fog::get_singleton ()->volumetric_fog .shader .version_get_shader (shader_data->version , _get_fog_variant () ), VolumetricFogShader::FogSet::FOG_SET_MATERIAL, true , true );
147165}
148166
149167Fog::FogMaterialData::~FogMaterialData () {
@@ -194,8 +212,26 @@ void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_lay
194212 // Initialize local fog shader
195213 Vector<String> volumetric_fog_modes;
196214 volumetric_fog_modes.push_back (" " );
215+ volumetric_fog_modes.push_back (" #define NO_IMAGE_ATOMICS\n " );
216+
197217 volumetric_fog.shader .initialize (volumetric_fog_modes, defines);
198218
219+ RenderingDevice *rd = RD::get_singleton ();
220+ if (rd->has_feature (RD::SUPPORTS_IMAGE_ATOMIC_32_BIT)) {
221+ volumetric_fog.shader .set_variant_enabled (1 , false );
222+ } else {
223+ volumetric_fog.shader .set_variant_enabled (0 , false );
224+ }
225+ // Always bake default (with image atomics) variant.
226+ volumetric_fog.shader .set_variants_bake_for (0 , " *" , true , true );
227+
228+ // Bake no "image atomics" variant for macOS/iOS (Vulkan and Metal) and visionOS (Metal).
229+ volumetric_fog.shader .set_variants_bake_for (1 , " macos_forward_clustered_vulkan" , true , false );
230+ volumetric_fog.shader .set_variants_bake_for (1 , " macos_forward_clustered_metal" , true , false );
231+ volumetric_fog.shader .set_variants_bake_for (1 , " ios_forward_clustered_vulkan" , true , false );
232+ volumetric_fog.shader .set_variants_bake_for (1 , " ios_forward_clustered_metal" , true , false );
233+ volumetric_fog.shader .set_variants_bake_for (1 , " visionos_forward_clustered_metal" , true , false );
234+
199235 material_storage->shader_set_data_request_function (RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_shader_funcs);
200236 material_storage->material_set_data_request_function (RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_material_funcs);
201237 volumetric_fog.volume_ubo = RD::get_singleton ()->uniform_buffer_create (sizeof (VolumetricFogShader::VolumeUBO));
@@ -252,7 +288,7 @@ ALBEDO = vec3(1.0);
252288 material_storage->material_set_shader (volumetric_fog.default_material , volumetric_fog.default_shader );
253289
254290 FogMaterialData *md = static_cast <FogMaterialData *>(material_storage->material_get_data (volumetric_fog.default_material , RendererRD::MaterialStorage::SHADER_TYPE_FOG));
255- volumetric_fog.default_shader_rd = volumetric_fog.shader .version_get_shader (md->shader_data ->version , 0 );
291+ volumetric_fog.default_shader_rd = volumetric_fog.shader .version_get_shader (md->shader_data ->version , _get_fog_variant () );
256292
257293 Vector<RD::Uniform> uniforms;
258294
@@ -282,10 +318,35 @@ ALBEDO = vec3(1.0);
282318 volumetric_fog_modes.push_back (" \n #define MODE_FOG\n " );
283319 volumetric_fog_modes.push_back (" \n #define MODE_COPY\n " );
284320
321+ volumetric_fog_modes.push_back (" \n #define MODE_DENSITY\n #define NO_IMAGE_ATOMICS\n " );
322+ volumetric_fog_modes.push_back (" \n #define MODE_DENSITY\n #define ENABLE_SDFGI\n #define NO_IMAGE_ATOMICS\n " );
323+ volumetric_fog_modes.push_back (" \n #define MODE_FILTER\n #define NO_IMAGE_ATOMICS\n " );
324+ volumetric_fog_modes.push_back (" \n #define MODE_FOG\n #define NO_IMAGE_ATOMICS\n " );
325+ volumetric_fog_modes.push_back (" \n #define MODE_COPY\n #define NO_IMAGE_ATOMICS\n " );
326+
285327 volumetric_fog.process_shader .initialize (volumetric_fog_modes, defines);
328+
329+ RenderingDevice *rd = RD::get_singleton ();
330+ for (int i = 0 ; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
331+ if (rd->has_feature (RD::SUPPORTS_IMAGE_ATOMIC_32_BIT)) {
332+ volumetric_fog.process_shader .set_variant_enabled (i + VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX, false );
333+ } else {
334+ volumetric_fog.process_shader .set_variant_enabled (i, false );
335+ }
336+ // Always bake default (with image atomics) variant.
337+ volumetric_fog.process_shader .set_variants_bake_for (i, " *" , true , true );
338+
339+ // Bake no "image atomics" variant for macOS/iOS (Vulkan and Metal) and visionOS (Metal) only.
340+ volumetric_fog.process_shader .set_variants_bake_for (i + VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX, " macos_forward_clustered_vulkan" , true , false );
341+ volumetric_fog.process_shader .set_variants_bake_for (i + VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX, " macos_forward_clustered_metal" , true , false );
342+ volumetric_fog.process_shader .set_variants_bake_for (i + VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX, " ios_forward_clustered_vulkan" , true , false );
343+ volumetric_fog.process_shader .set_variants_bake_for (i + VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX, " ios_forward_clustered_metal" , true , false );
344+ volumetric_fog.process_shader .set_variants_bake_for (i + VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX, " visionos_forward_clustered_metal" , true , false );
345+ }
346+
286347 volumetric_fog.process_shader_version = volumetric_fog.process_shader .version_create ();
287348 for (int i = 0 ; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
288- volumetric_fog.process_pipelines [i] = RD::get_singleton ()->compute_pipeline_create (volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , i ));
349+ volumetric_fog.process_pipelines [i] = RD::get_singleton ()->compute_pipeline_create (volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , _get_fog_process_variant (i) ));
289350 }
290351 volumetric_fog.params_ubo = RD::get_singleton ()->uniform_buffer_create (sizeof (VolumetricFogShader::ParamsUBO));
291352 }
@@ -349,7 +410,7 @@ void Fog::FogShaderData::set_code(const String &p_code) {
349410 ubo_offsets = gen_code.uniform_offsets ;
350411 texture_uniforms = gen_code.texture_uniforms ;
351412
352- pipeline = RD::get_singleton ()->compute_pipeline_create (fog_singleton->volumetric_fog .shader .version_get_shader (version, 0 ));
413+ pipeline = RD::get_singleton ()->compute_pipeline_create (fog_singleton->volumetric_fog .shader .version_get_shader (version, _get_fog_variant () ));
353414
354415 valid = true ;
355416}
@@ -941,22 +1002,22 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
9411002 if (fog->copy_uniform_set .is_valid () && RD::get_singleton ()->uniform_set_is_valid (fog->copy_uniform_set )) {
9421003 RD::get_singleton ()->free (fog->copy_uniform_set );
9431004 }
944- fog->copy_uniform_set = RD::get_singleton ()->uniform_set_create (copy_uniforms, volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0 );
1005+ fog->copy_uniform_set = RD::get_singleton ()->uniform_set_create (copy_uniforms, volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , _get_fog_process_variant ( VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY) ), 0 );
9451006
9461007 if (!gi_dependent_sets_valid) {
947- fog->gi_dependent_sets .process_uniform_set = RD::get_singleton ()->uniform_set_create (uniforms, volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0 );
1008+ fog->gi_dependent_sets .process_uniform_set = RD::get_singleton ()->uniform_set_create (uniforms, volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , _get_fog_process_variant ( VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG) ), 0 );
9481009
9491010 RID aux7 = uniforms.write [7 ].get_id (0 );
9501011 RID aux8 = uniforms.write [8 ].get_id (0 );
9511012
9521013 uniforms.write [7 ].set_id (0 , aux8);
9531014 uniforms.write [8 ].set_id (0 , aux7);
9541015
955- fog->gi_dependent_sets .process_uniform_set2 = RD::get_singleton ()->uniform_set_create (uniforms, volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0 );
1016+ fog->gi_dependent_sets .process_uniform_set2 = RD::get_singleton ()->uniform_set_create (uniforms, volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , _get_fog_process_variant ( VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG) ), 0 );
9561017
9571018 uniforms.remove_at (8 );
9581019 uniforms.write [7 ].set_id (0 , aux7);
959- fog->gi_dependent_sets .process_uniform_set_density = RD::get_singleton ()->uniform_set_create (uniforms, volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0 );
1020+ fog->gi_dependent_sets .process_uniform_set_density = RD::get_singleton ()->uniform_set_create (uniforms, volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , _get_fog_process_variant ( VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY) ), 0 );
9601021 }
9611022 }
9621023
@@ -990,7 +1051,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
9901051 uniforms.push_back (u);
9911052 }
9921053
993- fog->sdfgi_uniform_set = RD::get_singleton ()->uniform_set_create (uniforms, volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1 );
1054+ fog->sdfgi_uniform_set = RD::get_singleton ()->uniform_set_create (uniforms, volumetric_fog.process_shader .version_get_shader (volumetric_fog.process_shader_version , _get_fog_process_variant ( VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI) ), 1 );
9941055 }
9951056 }
9961057
0 commit comments