diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp index f454291a1ba..3a184db8bfd 100644 --- a/drivers/d3d12/rendering_device_driver_d3d12.cpp +++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp @@ -5588,6 +5588,8 @@ bool RenderingDeviceDriverD3D12::has_feature(Features p_feature) { return true; case SUPPORTS_IMAGE_ATOMIC_32_BIT: return true; + case SUPPORTS_VULKAN_MEMORY_MODEL: + return false; default: return false; } diff --git a/drivers/metal/rendering_device_driver_metal.mm b/drivers/metal/rendering_device_driver_metal.mm index 3bdc7a8a425..9cf85db0511 100644 --- a/drivers/metal/rendering_device_driver_metal.mm +++ b/drivers/metal/rendering_device_driver_metal.mm @@ -2743,6 +2743,8 @@ bool RenderingDeviceDriverMetal::has_feature(Features p_feature) { return device_properties->features.metal_fx_temporal; case SUPPORTS_IMAGE_ATOMIC_32_BIT: return device_properties->features.supports_native_image_atomics; + case SUPPORTS_VULKAN_MEMORY_MODEL: + return true; default: return false; } diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp index 542322a738d..5c0ddef65e6 100644 --- a/drivers/vulkan/rendering_device_driver_vulkan.cpp +++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp @@ -533,6 +533,7 @@ Error RenderingDeviceDriverVulkan::_initialize_device_extensions() { _register_requested_device_extension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false); _register_requested_device_extension(VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME, false); _register_requested_device_extension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, false); + _register_requested_device_extension(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME, false); _register_requested_device_extension(VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME, false); // We don't actually use this extension, but some runtime components on some platforms @@ -756,6 +757,7 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() { VkPhysicalDeviceVulkan12Features device_features_vk_1_2 = {}; VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {}; VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_device_address_features = {}; + VkPhysicalDeviceVulkanMemoryModelFeaturesKHR vulkan_memory_model_features = {}; VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsr_features = {}; VkPhysicalDeviceFragmentDensityMapFeaturesEXT fdm_features = {}; VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {}; @@ -778,6 +780,11 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() { buffer_device_address_features.pNext = next_features; next_features = &buffer_device_address_features; } + if (enabled_device_extension_names.has(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME)) { + vulkan_memory_model_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR; + vulkan_memory_model_features.pNext = next_features; + next_features = &vulkan_memory_model_features; + } } if (enabled_device_extension_names.has(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) { @@ -826,6 +833,10 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() { if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) { buffer_device_address_support = device_features_vk_1_2.bufferDeviceAddress; } + if (enabled_device_extension_names.has(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME)) { + vulkan_memory_model_support = device_features_vk_1_2.vulkanMemoryModel; + vulkan_memory_model_device_scope_support = device_features_vk_1_2.vulkanMemoryModelDeviceScope; + } } else { if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) { shader_capabilities.shader_float16_is_supported = shader_features.shaderFloat16; @@ -834,6 +845,10 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() { if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) { buffer_device_address_support = buffer_device_address_features.bufferDeviceAddress; } + if (enabled_device_extension_names.has(VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME)) { + vulkan_memory_model_support = vulkan_memory_model_features.vulkanMemoryModel; + vulkan_memory_model_device_scope_support = vulkan_memory_model_features.vulkanMemoryModelDeviceScope; + } } if (enabled_device_extension_names.has(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) { @@ -1078,6 +1093,15 @@ Error RenderingDeviceDriverVulkan::_initialize_device(const LocalVectorhas_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT); + bool use_vulkan_memory_model = rd->has_feature(RD::SUPPORTS_VULKAN_MEMORY_MODEL); + if (use_vulkan_memory_model) { + return use_32_bit_atomics ? VolumetricFogShader::SHADER_GROUP_VULKAN_MEMORY_MODEL : VolumetricFogShader::SHADER_GROUP_VULKAN_MEMORY_MODEL_NO_ATOMICS; + } else { + return use_32_bit_atomics ? VolumetricFogShader::SHADER_GROUP_BASE : VolumetricFogShader::SHADER_GROUP_NO_ATOMICS; + } +} + int Fog::_get_fog_variant() { RenderingDevice *rd = RD::get_singleton(); - if (rd->has_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT)) { - return 0; - } else { - return 1; - } + bool use_32_bit_atomics = rd->has_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT); + bool use_vulkan_memory_model = rd->has_feature(RD::SUPPORTS_VULKAN_MEMORY_MODEL); + return (use_vulkan_memory_model ? 2 : 0) + (use_32_bit_atomics ? 0 : 1); } int Fog::_get_fog_process_variant(int p_idx) { RenderingDevice *rd = RD::get_singleton(); - if (rd->has_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT)) { - return p_idx; - } else { - return p_idx + VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; - } + bool use_32_bit_atomics = rd->has_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT); + bool use_vulkan_memory_model = rd->has_feature(RD::SUPPORTS_VULKAN_MEMORY_MODEL); + return (use_vulkan_memory_model ? (VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX * 2) : 0) + (use_32_bit_atomics ? 0 : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX) + p_idx; } /* FOG VOLUMES */ @@ -210,18 +217,14 @@ void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_lay { String defines = "#define SAMPLERS_BINDING_FIRST_INDEX " + itos(SAMPLERS_BINDING_FIRST_INDEX) + "\n"; // Initialize local fog shader - Vector volumetric_fog_modes; - volumetric_fog_modes.push_back(""); - volumetric_fog_modes.push_back("#define NO_IMAGE_ATOMICS\n"); + Vector volumetric_fog_modes; + volumetric_fog_modes.push_back(ShaderRD::VariantDefine(VolumetricFogShader::SHADER_GROUP_BASE, "", false)); + volumetric_fog_modes.push_back(ShaderRD::VariantDefine(VolumetricFogShader::SHADER_GROUP_NO_ATOMICS, "#define NO_IMAGE_ATOMICS\n", false)); + volumetric_fog_modes.push_back(ShaderRD::VariantDefine(VolumetricFogShader::SHADER_GROUP_VULKAN_MEMORY_MODEL, "#define USE_VULKAN_MEMORY_MODEL\n", false)); + volumetric_fog_modes.push_back(ShaderRD::VariantDefine(VolumetricFogShader::SHADER_GROUP_VULKAN_MEMORY_MODEL_NO_ATOMICS, "#define USE_VULKAN_MEMORY_MODEL\n#define NO_IMAGE_ATOMICS\n", false)); volumetric_fog.shader.initialize(volumetric_fog_modes, defines); - - RenderingDevice *rd = RD::get_singleton(); - if (rd->has_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT)) { - volumetric_fog.shader.set_variant_enabled(1, false); - } else { - volumetric_fog.shader.set_variant_enabled(0, false); - } + volumetric_fog.shader.enable_group(_get_fog_shader_group()); material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_shader_funcs); material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_material_funcs); @@ -302,30 +305,24 @@ ALBEDO = vec3(1.0); if (p_is_using_radiance_cubemap_array) { defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; } - Vector volumetric_fog_modes; - volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n"); - volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n"); - volumetric_fog_modes.push_back("\n#define MODE_FILTER\n"); - volumetric_fog_modes.push_back("\n#define MODE_FOG\n"); - volumetric_fog_modes.push_back("\n#define MODE_COPY\n"); - - volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define NO_IMAGE_ATOMICS\n"); - volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n#define NO_IMAGE_ATOMICS\n"); - volumetric_fog_modes.push_back("\n#define MODE_FILTER\n#define NO_IMAGE_ATOMICS\n"); - volumetric_fog_modes.push_back("\n#define MODE_FOG\n#define NO_IMAGE_ATOMICS\n"); - volumetric_fog_modes.push_back("\n#define MODE_COPY\n#define NO_IMAGE_ATOMICS\n"); - - volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines); - - RenderingDevice *rd = RD::get_singleton(); - for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) { - if (rd->has_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT)) { - volumetric_fog.process_shader.set_variant_enabled(i + VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX, false); - } else { - volumetric_fog.process_shader.set_variant_enabled(i, false); + Vector volumetric_fog_modes; + int shader_group = 0; + for (int vk_memory_model = 0; vk_memory_model < 2; vk_memory_model++) { + for (int no_atomics = 0; no_atomics < 2; no_atomics++) { + String base_define = vk_memory_model ? "\n#define USE_VULKAN_MEMORY_MODEL" : ""; + base_define += no_atomics ? "\n#define NO_IMAGE_ATOMICS" : ""; + volumetric_fog_modes.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_DENSITY\n", false)); + volumetric_fog_modes.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n", false)); + volumetric_fog_modes.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_FILTER\n", false)); + volumetric_fog_modes.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_FOG\n", false)); + volumetric_fog_modes.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_COPY\n", false)); + shader_group++; } } + volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines); + volumetric_fog.process_shader.enable_group(_get_fog_shader_group()); + volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create(); for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) { 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))); diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index 353ec539414..052deb7b9cd 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -48,6 +48,7 @@ class Fog : public RendererFog { private: static Fog *singleton; + static int _get_fog_shader_group(); static int _get_fog_variant(); static int _get_fog_process_variant(int p_idx); @@ -76,6 +77,13 @@ private: /* Volumetric Fog */ struct VolumetricFogShader { + enum ShaderGroup { + SHADER_GROUP_BASE, + SHADER_GROUP_NO_ATOMICS, + SHADER_GROUP_VULKAN_MEMORY_MODEL, + SHADER_GROUP_VULKAN_MEMORY_MODEL_NO_ATOMICS, + }; + enum FogSet { FOG_SET_BASE, FOG_SET_UNIFORMS, diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl index 4ca666019ac..e6d28e33e04 100644 --- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl @@ -2,10 +2,12 @@ #version 450 -#pragma use_vulkan_memory_model - #VERSION_DEFINES +#ifdef USE_VULKAN_MEMORY_MODEL +#pragma use_vulkan_memory_model +#endif + layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; #define DENSITY_SCALE 1024.0 diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl index 17ee5ced28d..d2122e0a348 100644 --- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl @@ -2,10 +2,12 @@ #version 450 -#pragma use_vulkan_memory_model - #VERSION_DEFINES +#ifdef USE_VULKAN_MEMORY_MODEL +#pragma use_vulkan_memory_model +#endif + #ifdef MODE_DENSITY layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; #else diff --git a/servers/rendering/rendering_device_commons.h b/servers/rendering/rendering_device_commons.h index 960233e3aba..c8124a1d972 100644 --- a/servers/rendering/rendering_device_commons.h +++ b/servers/rendering/rendering_device_commons.h @@ -953,6 +953,7 @@ public: SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS, SUPPORTS_BUFFER_DEVICE_ADDRESS, SUPPORTS_IMAGE_ATOMIC_32_BIT, + SUPPORTS_VULKAN_MEMORY_MODEL, }; enum SubgroupOperations {