vkd3d: Use mutable descriptors if available.

The mutable descriptor type allows six descriptor sets to be replaced
with one set for CBV/SRV/UAV heaps.
This commit is contained in:
Conor McCarthy 2023-12-14 14:58:19 +10:00 committed by Alexandre Julliard
parent bb64bfff63
commit b0d1fb7d98
Notes: Alexandre Julliard 2024-01-09 23:37:22 +01:00
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/523
7 changed files with 83 additions and 10 deletions

2
README
View File

@ -9,7 +9,7 @@ similar, but not identical, to Direct3D 12.
Building vkd3d Building vkd3d
============== ==============
Vkd3d depends on SPIRV-Headers and Vulkan-Headers (>= 1.2.148). Vkd3d depends on SPIRV-Headers and Vulkan-Headers (>= 1.3.228).
Vkd3d generates some of its headers from IDL files. If you are using the Vkd3d generates some of its headers from IDL files. If you are using the
release tarballs, then these headers are pre-generated and are included. If release tarballs, then these headers are pre-generated and are included. If

View File

@ -86,7 +86,7 @@ AS_IF([test "x$ac_cv_header_spirv_unified1_GLSL_std_450_h" != "xyes" \
-a "x$ac_cv_header_vulkan_GLSL_std_450_h" != "xyes"], -a "x$ac_cv_header_vulkan_GLSL_std_450_h" != "xyes"],
[AC_MSG_ERROR([GLSL.std.450.h not found.])]) [AC_MSG_ERROR([GLSL.std.450.h not found.])])
VKD3D_CHECK_VULKAN_HEADER_VERSION([148], [AC_MSG_ERROR([Vulkan headers are too old, 1.2.148 is required.])]) VKD3D_CHECK_VULKAN_HEADER_VERSION([228], [AC_MSG_ERROR([Vulkan headers are too old, 1.3.228 is required.])])
AC_CHECK_DECL([SpvCapabilityDemoteToHelperInvocationEXT],, [AC_MSG_ERROR([SPIR-V headers are too old.])], [ AC_CHECK_DECL([SpvCapabilityDemoteToHelperInvocationEXT],, [AC_MSG_ERROR([SPIR-V headers are too old.])], [
#ifdef HAVE_SPIRV_UNIFIED1_SPIRV_H #ifdef HAVE_SPIRV_UNIFIED1_SPIRV_H

View File

@ -3270,7 +3270,8 @@ static void d3d12_command_list_bind_descriptor_heap(struct d3d12_command_list *l
{ {
VkDescriptorSet vk_descriptor_set = heap->vk_descriptor_sets[set].vk_set; VkDescriptorSet vk_descriptor_set = heap->vk_descriptor_sets[set].vk_set;
if (!vk_descriptor_set) /* Null vk_set_layout means set 0 uses mutable descriptors, and this set is unused. */
if (!vk_descriptor_set || !list->device->vk_descriptor_heap_layouts[set].vk_set_layout)
continue; continue;
VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, bindings->vk_bind_point, rs->vk_pipeline_layout, VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, bindings->vk_bind_point, rs->vk_pipeline_layout,

View File

@ -94,6 +94,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] =
VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker), VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker),
VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable), VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable),
VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing), VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing),
VK_EXTENSION(EXT_MUTABLE_DESCRIPTOR_TYPE, EXT_mutable_descriptor_type),
VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2), VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2),
VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation), VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation),
VK_EXTENSION(EXT_SHADER_STENCIL_EXPORT, EXT_shader_stencil_export), VK_EXTENSION(EXT_SHADER_STENCIL_EXPORT, EXT_shader_stencil_export),
@ -106,13 +107,32 @@ static HRESULT vkd3d_create_vk_descriptor_heap_layout(struct d3d12_device *devic
{ {
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
VkDescriptorSetLayoutBindingFlagsCreateInfoEXT flags_info; VkDescriptorSetLayoutBindingFlagsCreateInfoEXT flags_info;
VkMutableDescriptorTypeCreateInfoEXT mutable_info;
VkMutableDescriptorTypeListEXT type_list;
VkDescriptorSetLayoutCreateInfo set_desc; VkDescriptorSetLayoutCreateInfo set_desc;
VkDescriptorBindingFlagsEXT set_flags; VkDescriptorBindingFlagsEXT set_flags;
VkDescriptorSetLayoutBinding binding; VkDescriptorSetLayoutBinding binding;
VkResult vr; VkResult vr;
static const VkDescriptorType descriptor_types[] =
{
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
};
if (device->vk_info.EXT_mutable_descriptor_type && index && index != VKD3D_SET_INDEX_UAV_COUNTER
&& device->vk_descriptor_heap_layouts[index].applicable_heap_type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
{
device->vk_descriptor_heap_layouts[index].vk_set_layout = VK_NULL_HANDLE;
return S_OK;
}
binding.binding = 0; binding.binding = 0;
binding.descriptorType = device->vk_descriptor_heap_layouts[index].type; binding.descriptorType = (device->vk_info.EXT_mutable_descriptor_type && !index)
? VK_DESCRIPTOR_TYPE_MUTABLE_EXT : device->vk_descriptor_heap_layouts[index].type;
binding.descriptorCount = device->vk_descriptor_heap_layouts[index].count; binding.descriptorCount = device->vk_descriptor_heap_layouts[index].count;
binding.stageFlags = VK_SHADER_STAGE_ALL; binding.stageFlags = VK_SHADER_STAGE_ALL;
binding.pImmutableSamplers = NULL; binding.pImmutableSamplers = NULL;
@ -132,6 +152,17 @@ static HRESULT vkd3d_create_vk_descriptor_heap_layout(struct d3d12_device *devic
flags_info.bindingCount = 1; flags_info.bindingCount = 1;
flags_info.pBindingFlags = &set_flags; flags_info.pBindingFlags = &set_flags;
if (binding.descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_EXT)
{
type_list.descriptorTypeCount = ARRAY_SIZE(descriptor_types);
type_list.pDescriptorTypes = descriptor_types;
mutable_info.sType = VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT;
mutable_info.pNext = NULL;
mutable_info.mutableDescriptorTypeListCount = 1;
mutable_info.pMutableDescriptorTypeLists = &type_list;
flags_info.pNext = &mutable_info;
}
if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device->vk_device, &set_desc, NULL, if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device->vk_device, &set_desc, NULL,
&device->vk_descriptor_heap_layouts[index].vk_set_layout))) < 0) &device->vk_descriptor_heap_layouts[index].vk_set_layout))) < 0)
{ {
@ -763,6 +794,7 @@ struct vkd3d_physical_device_info
VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features; VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features;
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features; VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features;
VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timeline_semaphore_features; VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timeline_semaphore_features;
VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT mutable_features;
VkPhysicalDeviceFeatures2 features2; VkPhysicalDeviceFeatures2 features2;
}; };
@ -780,6 +812,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features; VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features;
VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features; VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features;
VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *timeline_semaphore_features; VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *timeline_semaphore_features;
VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT *mutable_features;
VkPhysicalDeviceDepthClipEnableFeaturesEXT *depth_clip_features; VkPhysicalDeviceDepthClipEnableFeaturesEXT *depth_clip_features;
VkPhysicalDeviceMaintenance3Properties *maintenance3_properties; VkPhysicalDeviceMaintenance3Properties *maintenance3_properties;
VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb_properties; VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb_properties;
@ -800,6 +833,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
vertex_divisor_features = &info->vertex_divisor_features; vertex_divisor_features = &info->vertex_divisor_features;
vertex_divisor_properties = &info->vertex_divisor_properties; vertex_divisor_properties = &info->vertex_divisor_properties;
timeline_semaphore_features = &info->timeline_semaphore_features; timeline_semaphore_features = &info->timeline_semaphore_features;
mutable_features = &info->mutable_features;
xfb_features = &info->xfb_features; xfb_features = &info->xfb_features;
xfb_properties = &info->xfb_properties; xfb_properties = &info->xfb_properties;
@ -823,6 +857,8 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
vk_prepend_struct(&info->features2, vertex_divisor_features); vk_prepend_struct(&info->features2, vertex_divisor_features);
timeline_semaphore_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR; timeline_semaphore_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR;
vk_prepend_struct(&info->features2, timeline_semaphore_features); vk_prepend_struct(&info->features2, timeline_semaphore_features);
mutable_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT;
vk_prepend_struct(&info->features2, mutable_features);
if (vulkan_info->KHR_get_physical_device_properties2) if (vulkan_info->KHR_get_physical_device_properties2)
VK_CALL(vkGetPhysicalDeviceFeatures2KHR(physical_device, &info->features2)); VK_CALL(vkGetPhysicalDeviceFeatures2KHR(physical_device, &info->features2));
@ -1594,6 +1630,8 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
vulkan_info->EXT_shader_demote_to_helper_invocation = false; vulkan_info->EXT_shader_demote_to_helper_invocation = false;
if (!physical_device_info->texel_buffer_alignment_features.texelBufferAlignment) if (!physical_device_info->texel_buffer_alignment_features.texelBufferAlignment)
vulkan_info->EXT_texel_buffer_alignment = false; vulkan_info->EXT_texel_buffer_alignment = false;
if (!physical_device_info->mutable_features.mutableDescriptorType)
vulkan_info->EXT_mutable_descriptor_type = false;
if (!physical_device_info->timeline_semaphore_features.timelineSemaphore) if (!physical_device_info->timeline_semaphore_features.timelineSemaphore)
vulkan_info->KHR_timeline_semaphore = false; vulkan_info->KHR_timeline_semaphore = false;

View File

@ -2470,12 +2470,14 @@ static void d3d12_desc_write_vk_heap_null_descriptor(struct d3d12_descriptor_hea
{ {
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
struct d3d12_descriptor_heap_vk_set *descriptor_set; struct d3d12_descriptor_heap_vk_set *descriptor_set;
enum vkd3d_vk_descriptor_set_index set; enum vkd3d_vk_descriptor_set_index set, end;
unsigned int i = writes->count; unsigned int i = writes->count;
end = device->vk_info.EXT_mutable_descriptor_type ? VKD3D_SET_INDEX_UNIFORM_BUFFER
: VKD3D_SET_INDEX_STORAGE_IMAGE;
/* Binding a shader with the wrong null descriptor type works in Windows. /* Binding a shader with the wrong null descriptor type works in Windows.
* To support that here we must write one to all applicable Vulkan sets. */ * To support that here we must write one to all applicable Vulkan sets. */
for (set = VKD3D_SET_INDEX_UNIFORM_BUFFER; set <= VKD3D_SET_INDEX_STORAGE_IMAGE; ++set) for (set = VKD3D_SET_INDEX_UNIFORM_BUFFER; set <= end; ++set)
{ {
descriptor_set = &descriptor_heap->vk_descriptor_sets[set]; descriptor_set = &descriptor_heap->vk_descriptor_sets[set];
writes->vk_descriptor_writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writes->vk_descriptor_writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
@ -4220,9 +4222,11 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_pool(struct d3d12_descrip
for (set = 0, pool_desc.poolSizeCount = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set) for (set = 0, pool_desc.poolSizeCount = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set)
{ {
if (device->vk_descriptor_heap_layouts[set].applicable_heap_type == desc->Type) if (device->vk_descriptor_heap_layouts[set].applicable_heap_type == desc->Type
&& device->vk_descriptor_heap_layouts[set].vk_set_layout)
{ {
pool_sizes[pool_desc.poolSizeCount].type = device->vk_descriptor_heap_layouts[set].type; pool_sizes[pool_desc.poolSizeCount].type = (device->vk_info.EXT_mutable_descriptor_type && !set)
? VK_DESCRIPTOR_TYPE_MUTABLE_EXT : device->vk_descriptor_heap_layouts[set].type;
pool_sizes[pool_desc.poolSizeCount++].descriptorCount = desc->NumDescriptors; pool_sizes[pool_desc.poolSizeCount++].descriptorCount = desc->NumDescriptors;
} }
} }
@ -4248,6 +4252,16 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_set(struct d3d12_descript
VkDescriptorSetAllocateInfo set_desc; VkDescriptorSetAllocateInfo set_desc;
VkResult vr; VkResult vr;
if (!device->vk_descriptor_heap_layouts[set].vk_set_layout)
{
/* Set 0 uses mutable descriptors, and this set is unused. */
if (!descriptor_heap->vk_descriptor_sets[0].vk_set)
d3d12_descriptor_heap_create_descriptor_set(descriptor_heap, device, 0);
descriptor_set->vk_set = descriptor_heap->vk_descriptor_sets[0].vk_set;
descriptor_set->vk_type = device->vk_descriptor_heap_layouts[set].type;
return S_OK;
}
set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
set_desc.pNext = &set_size; set_desc.pNext = &set_size;
set_desc.descriptorPool = descriptor_heap->vk_descriptor_pool; set_desc.descriptorPool = descriptor_heap->vk_descriptor_pool;

View File

@ -848,7 +848,20 @@ static void vkd3d_descriptor_heap_binding_from_descriptor_range(const struct d3d
const struct vkd3d_device_descriptor_limits *descriptor_limits = &root_signature->device->vk_info.descriptor_limits; const struct vkd3d_device_descriptor_limits *descriptor_limits = &root_signature->device->vk_info.descriptor_limits;
unsigned int descriptor_set_size; unsigned int descriptor_set_size;
switch (range->type) if (root_signature->device->vk_info.EXT_mutable_descriptor_type)
{
if (range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER)
{
binding->set = VKD3D_SET_INDEX_SAMPLER;
descriptor_set_size = descriptor_limits->sampler_max_descriptors;
}
else
{
binding->set = 0;
descriptor_set_size = descriptor_limits->sampled_image_max_descriptors;
}
}
else switch (range->type)
{ {
case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV: case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV:
binding->set = is_buffer ? VKD3D_SET_INDEX_UNIFORM_TEXEL_BUFFER : VKD3D_SET_INDEX_SAMPLED_IMAGE; binding->set = is_buffer ? VKD3D_SET_INDEX_UNIFORM_TEXEL_BUFFER : VKD3D_SET_INDEX_SAMPLED_IMAGE;
@ -1368,8 +1381,14 @@ static unsigned int d3d12_root_signature_copy_descriptor_set_layouts(const struc
if (device->use_vk_heaps) if (device->use_vk_heaps)
{ {
VkDescriptorSetLayout mutable_layout = device->vk_descriptor_heap_layouts[0].vk_set_layout;
for (set = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set) for (set = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set)
vk_set_layouts[i++] = device->vk_descriptor_heap_layouts[set].vk_set_layout; {
VkDescriptorSetLayout vk_set_layout = device->vk_descriptor_heap_layouts[set].vk_set_layout;
/* All layouts must be valid, so if null, just set it to the mutable one. */
vk_set_layouts[i++] = vk_set_layout ? vk_set_layout : mutable_layout;
}
} }
return i; return i;

View File

@ -133,6 +133,7 @@ struct vkd3d_vulkan_info
bool EXT_debug_marker; bool EXT_debug_marker;
bool EXT_depth_clip_enable; bool EXT_depth_clip_enable;
bool EXT_descriptor_indexing; bool EXT_descriptor_indexing;
bool EXT_mutable_descriptor_type;
bool EXT_robustness2; bool EXT_robustness2;
bool EXT_shader_demote_to_helper_invocation; bool EXT_shader_demote_to_helper_invocation;
bool EXT_shader_stencil_export; bool EXT_shader_stencil_export;