Does not cover every case for SM 6.0, but it's a useful start.
Signed-off-by: Hans-Kristian Arntzen post@arntzen-software.no --- libs/vkd3d/device.c | 47 +++++++++++++++++++++++++++++++++++--- libs/vkd3d/vkd3d_private.h | 1 + 2 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 28430fb..82355f1 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -699,6 +699,7 @@ struct vkd3d_physical_device_info VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties; VkPhysicalDeviceTransformFeedbackPropertiesEXT xfb_properties; VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT vertex_divisor_properties; + VkPhysicalDeviceSubgroupProperties subgroup_properties;
VkPhysicalDeviceProperties2KHR properties2;
@@ -730,6 +731,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb_properties; VkPhysicalDevice physical_device = device->vk_physical_device; VkPhysicalDeviceTransformFeedbackFeaturesEXT *xfb_features; + VkPhysicalDeviceSubgroupProperties *subgroup_properties; struct vkd3d_vulkan_info *vulkan_info = &device->vk_info;
memset(info, 0, sizeof(*info)); @@ -745,6 +747,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i vertex_divisor_properties = &info->vertex_divisor_properties; xfb_features = &info->xfb_features; xfb_properties = &info->xfb_properties; + subgroup_properties = &info->subgroup_properties;
info->features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
@@ -780,6 +783,8 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i vk_prepend_struct(&info->properties2, xfb_properties); vertex_divisor_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT; vk_prepend_struct(&info->properties2, vertex_divisor_properties); + subgroup_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; + vk_prepend_struct(&info->properties2, subgroup_properties);
if (vulkan_info->KHR_get_physical_device_properties2) VK_CALL(vkGetPhysicalDeviceProperties2KHR(physical_device, &info->properties2)); @@ -1293,6 +1298,42 @@ static void vkd3d_init_feature_level(struct vkd3d_vulkan_info *vk_info, TRACE("Max feature level: %#x.\n", vk_info->max_feature_level); }
+static void vkd3d_init_shader_model(uint32_t api_version, + struct vkd3d_vulkan_info *vulkan_info, + struct vkd3d_physical_device_info *physical_device_info) +{ + /* SHUFFLE is required to implement WaveReadLaneAt with dynamically uniform index before SPIR-V 1.5 / Vulkan 1.2. */ + static const VkSubgroupFeatureFlags required = + VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | + VK_SUBGROUP_FEATURE_BASIC_BIT | + VK_SUBGROUP_FEATURE_BALLOT_BIT | + VK_SUBGROUP_FEATURE_SHUFFLE_BIT | + VK_SUBGROUP_FEATURE_QUAD_BIT | + VK_SUBGROUP_FEATURE_VOTE_BIT; + + static const VkSubgroupFeatureFlags required_stages = + VK_SHADER_STAGE_COMPUTE_BIT | + VK_SHADER_STAGE_FRAGMENT_BIT; + + if (api_version >= VK_API_VERSION_1_1 && + vkd3d_shader_supports_dxil() && + physical_device_info->subgroup_properties.subgroupSize >= 4 && + (physical_device_info->subgroup_properties.supportedOperations & required) == required && + (physical_device_info->subgroup_properties.supportedStages & required_stages) == required_stages) + { + /* TODO: Add checks for all the other features which are required to implement SM 6.0. + * - 16-bit arithmetic / storage. + */ + vulkan_info->max_shader_model = D3D_SHADER_MODEL_6_0; + TRACE("Enabling support for SM 6.0.\n"); + } + else + { + vulkan_info->max_shader_model = D3D_SHADER_MODEL_5_1; + TRACE("Enabling support for SM 5.1.\n"); + } +} + static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, const struct vkd3d_device_create_info *create_info, struct vkd3d_physical_device_info *physical_device_info, @@ -1481,6 +1522,8 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, features->robustBufferAccess = VK_FALSE; }
+ vkd3d_init_shader_model(device->api_version, vulkan_info, physical_device_info); + return S_OK; }
@@ -2703,9 +2746,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device * }
TRACE("Request shader model %#x.\n", data->HighestShaderModel); - - data->HighestShaderModel = D3D_SHADER_MODEL_5_1; - + data->HighestShaderModel = min(data->HighestShaderModel, device->vk_info.max_shader_model); TRACE("Shader model %#x.\n", data->HighestShaderModel); return S_OK; } diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 29386c5..c032e05 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -126,6 +126,7 @@ struct vkd3d_vulkan_info enum vkd3d_shader_target_extension shader_extensions[VKD3D_MAX_SHADER_EXTENSIONS];
D3D_FEATURE_LEVEL max_feature_level; + D3D_SHADER_MODEL max_shader_model; };
enum vkd3d_config_flags