Check for Vulkan Memory Model support and make it a variant.

This commit is contained in:
Dario 2025-07-24 09:22:44 -03:00
parent 967e2d499a
commit b962b38e74
9 changed files with 87 additions and 45 deletions

View file

@ -5588,6 +5588,8 @@ bool RenderingDeviceDriverD3D12::has_feature(Features p_feature) {
return true; return true;
case SUPPORTS_IMAGE_ATOMIC_32_BIT: case SUPPORTS_IMAGE_ATOMIC_32_BIT:
return true; return true;
case SUPPORTS_VULKAN_MEMORY_MODEL:
return false;
default: default:
return false; return false;
} }

View file

@ -2743,6 +2743,8 @@ bool RenderingDeviceDriverMetal::has_feature(Features p_feature) {
return device_properties->features.metal_fx_temporal; return device_properties->features.metal_fx_temporal;
case SUPPORTS_IMAGE_ATOMIC_32_BIT: case SUPPORTS_IMAGE_ATOMIC_32_BIT:
return device_properties->features.supports_native_image_atomics; return device_properties->features.supports_native_image_atomics;
case SUPPORTS_VULKAN_MEMORY_MODEL:
return true;
default: default:
return false; return false;
} }

View file

@ -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_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false);
_register_requested_device_extension(VK_EXT_ASTC_DECODE_MODE_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_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); _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 // 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 = {}; VkPhysicalDeviceVulkan12Features device_features_vk_1_2 = {};
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {}; VkPhysicalDeviceShaderFloat16Int8FeaturesKHR shader_features = {};
VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_device_address_features = {}; VkPhysicalDeviceBufferDeviceAddressFeaturesKHR buffer_device_address_features = {};
VkPhysicalDeviceVulkanMemoryModelFeaturesKHR vulkan_memory_model_features = {};
VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsr_features = {}; VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsr_features = {};
VkPhysicalDeviceFragmentDensityMapFeaturesEXT fdm_features = {}; VkPhysicalDeviceFragmentDensityMapFeaturesEXT fdm_features = {};
VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {}; VkPhysicalDevice16BitStorageFeaturesKHR storage_feature = {};
@ -778,6 +780,11 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
buffer_device_address_features.pNext = next_features; buffer_device_address_features.pNext = next_features;
next_features = &buffer_device_address_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)) { 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)) { if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {
buffer_device_address_support = device_features_vk_1_2.bufferDeviceAddress; 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 { } else {
if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) { if (enabled_device_extension_names.has(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME)) {
shader_capabilities.shader_float16_is_supported = shader_features.shaderFloat16; 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)) { if (enabled_device_extension_names.has(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) {
buffer_device_address_support = buffer_device_address_features.bufferDeviceAddress; 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)) { if (enabled_device_extension_names.has(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {
@ -1078,6 +1093,15 @@ Error RenderingDeviceDriverVulkan::_initialize_device(const LocalVector<VkDevice
create_info_next = &buffer_device_address_features; create_info_next = &buffer_device_address_features;
} }
VkPhysicalDeviceVulkanMemoryModelFeaturesKHR vulkan_memory_model_features = {};
if (vulkan_memory_model_support && vulkan_memory_model_device_scope_support) {
vulkan_memory_model_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR;
vulkan_memory_model_features.pNext = create_info_next;
vulkan_memory_model_features.vulkanMemoryModel = vulkan_memory_model_support;
vulkan_memory_model_features.vulkanMemoryModelDeviceScope = vulkan_memory_model_device_scope_support;
create_info_next = &vulkan_memory_model_features;
}
VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsr_features = {}; VkPhysicalDeviceFragmentShadingRateFeaturesKHR fsr_features = {};
if (fsr_capabilities.pipeline_supported || fsr_capabilities.primitive_supported || fsr_capabilities.attachment_supported) { if (fsr_capabilities.pipeline_supported || fsr_capabilities.primitive_supported || fsr_capabilities.attachment_supported) {
fsr_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR; fsr_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR;
@ -5901,6 +5925,8 @@ bool RenderingDeviceDriverVulkan::has_feature(Features p_feature) {
#else #else
return true; return true;
#endif #endif
case SUPPORTS_VULKAN_MEMORY_MODEL:
return vulkan_memory_model_support && vulkan_memory_model_device_scope_support;
default: default:
return false; return false;
} }

View file

@ -133,6 +133,8 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
StorageBufferCapabilities storage_buffer_capabilities; StorageBufferCapabilities storage_buffer_capabilities;
RenderingShaderContainerFormatVulkan shader_container_format; RenderingShaderContainerFormatVulkan shader_container_format;
bool buffer_device_address_support = false; bool buffer_device_address_support = false;
bool vulkan_memory_model_support = false;
bool vulkan_memory_model_device_scope_support = false;
bool pipeline_cache_control_support = false; bool pipeline_cache_control_support = false;
bool device_fault_support = false; bool device_fault_support = false;
#if defined(VK_TRACK_DEVICE_MEMORY) #if defined(VK_TRACK_DEVICE_MEMORY)

View file

@ -47,22 +47,29 @@ Fog::~Fog() {
singleton = nullptr; singleton = nullptr;
} }
int Fog::_get_fog_shader_group() {
RenderingDevice *rd = RD::get_singleton();
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);
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() { int Fog::_get_fog_variant() {
RenderingDevice *rd = RD::get_singleton(); RenderingDevice *rd = RD::get_singleton();
if (rd->has_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT)) { bool use_32_bit_atomics = rd->has_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT);
return 0; bool use_vulkan_memory_model = rd->has_feature(RD::SUPPORTS_VULKAN_MEMORY_MODEL);
} else { return (use_vulkan_memory_model ? 2 : 0) + (use_32_bit_atomics ? 0 : 1);
return 1;
}
} }
int Fog::_get_fog_process_variant(int p_idx) { int Fog::_get_fog_process_variant(int p_idx) {
RenderingDevice *rd = RD::get_singleton(); RenderingDevice *rd = RD::get_singleton();
if (rd->has_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT)) { bool use_32_bit_atomics = rd->has_feature(RD::SUPPORTS_IMAGE_ATOMIC_32_BIT);
return p_idx; bool use_vulkan_memory_model = rd->has_feature(RD::SUPPORTS_VULKAN_MEMORY_MODEL);
} else { 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;
return p_idx + VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX;
}
} }
/* FOG VOLUMES */ /* 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"; String defines = "#define SAMPLERS_BINDING_FIRST_INDEX " + itos(SAMPLERS_BINDING_FIRST_INDEX) + "\n";
// Initialize local fog shader // Initialize local fog shader
Vector<String> volumetric_fog_modes; Vector<ShaderRD::VariantDefine> volumetric_fog_modes;
volumetric_fog_modes.push_back(""); volumetric_fog_modes.push_back(ShaderRD::VariantDefine(VolumetricFogShader::SHADER_GROUP_BASE, "", false));
volumetric_fog_modes.push_back("#define NO_IMAGE_ATOMICS\n"); 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); volumetric_fog.shader.initialize(volumetric_fog_modes, defines);
volumetric_fog.shader.enable_group(_get_fog_shader_group());
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);
}
material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_shader_funcs); 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); 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) { if (p_is_using_radiance_cubemap_array) {
defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
} }
Vector<String> volumetric_fog_modes; Vector<ShaderRD::VariantDefine> volumetric_fog_modes;
volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n"); int shader_group = 0;
volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n"); for (int vk_memory_model = 0; vk_memory_model < 2; vk_memory_model++) {
volumetric_fog_modes.push_back("\n#define MODE_FILTER\n"); for (int no_atomics = 0; no_atomics < 2; no_atomics++) {
volumetric_fog_modes.push_back("\n#define MODE_FOG\n"); String base_define = vk_memory_model ? "\n#define USE_VULKAN_MEMORY_MODEL" : "";
volumetric_fog_modes.push_back("\n#define MODE_COPY\n"); 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("\n#define MODE_DENSITY\n#define NO_IMAGE_ATOMICS\n"); 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("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n#define NO_IMAGE_ATOMICS\n"); volumetric_fog_modes.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_FILTER\n", false));
volumetric_fog_modes.push_back("\n#define MODE_FILTER\n#define NO_IMAGE_ATOMICS\n"); volumetric_fog_modes.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_FOG\n", false));
volumetric_fog_modes.push_back("\n#define MODE_FOG\n#define NO_IMAGE_ATOMICS\n"); volumetric_fog_modes.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_COPY\n", false));
volumetric_fog_modes.push_back("\n#define MODE_COPY\n#define NO_IMAGE_ATOMICS\n"); shader_group++;
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);
} }
} }
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(); volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create();
for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) { 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))); 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)));

View file

@ -48,6 +48,7 @@ class Fog : public RendererFog {
private: private:
static Fog *singleton; static Fog *singleton;
static int _get_fog_shader_group();
static int _get_fog_variant(); static int _get_fog_variant();
static int _get_fog_process_variant(int p_idx); static int _get_fog_process_variant(int p_idx);
@ -76,6 +77,13 @@ private:
/* Volumetric Fog */ /* Volumetric Fog */
struct VolumetricFogShader { 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 { enum FogSet {
FOG_SET_BASE, FOG_SET_BASE,
FOG_SET_UNIFORMS, FOG_SET_UNIFORMS,

View file

@ -2,10 +2,12 @@
#version 450 #version 450
#pragma use_vulkan_memory_model
#VERSION_DEFINES #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; layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
#define DENSITY_SCALE 1024.0 #define DENSITY_SCALE 1024.0

View file

@ -2,10 +2,12 @@
#version 450 #version 450
#pragma use_vulkan_memory_model
#VERSION_DEFINES #VERSION_DEFINES
#ifdef USE_VULKAN_MEMORY_MODEL
#pragma use_vulkan_memory_model
#endif
#ifdef MODE_DENSITY #ifdef MODE_DENSITY
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
#else #else

View file

@ -953,6 +953,7 @@ public:
SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS, SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS,
SUPPORTS_BUFFER_DEVICE_ADDRESS, SUPPORTS_BUFFER_DEVICE_ADDRESS,
SUPPORTS_IMAGE_ATOMIC_32_BIT, SUPPORTS_IMAGE_ATOMIC_32_BIT,
SUPPORTS_VULKAN_MEMORY_MODEL,
}; };
enum SubgroupOperations { enum SubgroupOperations {