[PATCH vkd3d v2 2/4] vkd3d: Use arrayed Vulkan bindings if descriptor indexing is available.

Conor McCarthy cmccarthy at codeweavers.com
Thu Jun 3 00:04:05 CDT 2021


The partial binding feature enables bindings with count > 1 even for
SRV and UAV descriptors, for which both buffer and image bindings
must be created to accomodate D3D12 heap flexibility. This patch
depends on shader model 5.1 support.

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 libs/vkd3d/state.c         | 91 +++++++++++++++++++++++++++++++-------
 libs/vkd3d/vkd3d_private.h |  1 +
 2 files changed, 75 insertions(+), 17 deletions(-)

diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c
index d07212f6..f676ab88 100644
--- a/libs/vkd3d/state.c
+++ b/libs/vkd3d/state.c
@@ -300,12 +300,12 @@ static enum vkd3d_shader_descriptor_type vkd3d_descriptor_type_from_d3d12_root_p
 
 static bool vk_binding_from_d3d12_descriptor_range(struct VkDescriptorSetLayoutBinding *binding_desc,
         const D3D12_DESCRIPTOR_RANGE *descriptor_range, D3D12_SHADER_VISIBILITY shader_visibility,
-        bool is_buffer, uint32_t vk_binding)
+        bool is_buffer, unsigned int descriptor_count, uint32_t vk_binding)
 {
     binding_desc->binding = vk_binding;
     binding_desc->descriptorType
             = vk_descriptor_type_from_d3d12_range_type(descriptor_range->RangeType, is_buffer);
-    binding_desc->descriptorCount = 1;
+    binding_desc->descriptorCount = descriptor_count;
     binding_desc->stageFlags = stage_flags_from_visibility(shader_visibility);
     binding_desc->pImmutableSamplers = NULL;
 
@@ -323,13 +323,14 @@ struct d3d12_root_signature_info
 };
 
 static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_signature_info *info,
-        const D3D12_ROOT_DESCRIPTOR_TABLE *table)
+        const D3D12_ROOT_DESCRIPTOR_TABLE *table, bool bindless)
 {
     unsigned int i;
 
     for (i = 0; i < table->NumDescriptorRanges; ++i)
     {
         const D3D12_DESCRIPTOR_RANGE *range = &table->pDescriptorRanges[i];
+        unsigned int binding_count;
 
         if (range->NumDescriptors == 0xffffffff)
         {
@@ -337,6 +338,8 @@ static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_sig
             return E_NOTIMPL;
         }
 
+        binding_count = bindless ? 1 : range->NumDescriptors;
+
         switch (range->RangeType)
         {
             case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
@@ -344,11 +347,11 @@ static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_sig
                 * to preserve compatibility between Vulkan resource bindings for the same
                 * root signature, we create descriptor set layouts with two bindings for
                 * each SRV and UAV. */
-                info->binding_count += range->NumDescriptors;
+                info->binding_count += binding_count;
                 break;
             case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
                 /* As above. */
-                info->binding_count += range->NumDescriptors;
+                info->binding_count += binding_count;
                 break;
             case D3D12_DESCRIPTOR_RANGE_TYPE_CBV:
                 break;
@@ -359,14 +362,14 @@ static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_sig
                 return E_NOTIMPL;
         }
 
-        info->binding_count += range->NumDescriptors;
+        info->binding_count += binding_count;
     }
 
     return S_OK;
 }
 
 static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_info *info,
-        const D3D12_ROOT_SIGNATURE_DESC *desc)
+        const D3D12_ROOT_SIGNATURE_DESC *desc, bool bindless)
 {
     unsigned int i;
     HRESULT hr;
@@ -381,7 +384,7 @@ static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_i
         {
             case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
                 if (FAILED(hr = d3d12_root_signature_info_count_descriptors(info,
-                        &p->u.DescriptorTable)))
+                        &p->u.DescriptorTable, bindless)))
                     return hr;
                 ++info->cost;
                 break;
@@ -517,7 +520,7 @@ struct vkd3d_descriptor_set_context
 
 static void d3d12_root_signature_append_vk_binding(struct d3d12_root_signature *root_signature,
         enum vkd3d_shader_descriptor_type descriptor_type, unsigned int register_space, unsigned int register_idx,
-        bool buffer_descriptor, enum vkd3d_shader_visibility shader_visibility,
+        bool buffer_descriptor, unsigned int descriptor_count, enum vkd3d_shader_visibility shader_visibility,
         struct vkd3d_descriptor_set_context *context)
 {
     struct vkd3d_shader_resource_binding *mapping
@@ -530,7 +533,7 @@ static void d3d12_root_signature_append_vk_binding(struct d3d12_root_signature *
     mapping->flags = buffer_descriptor ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE;
     mapping->binding.set = root_signature->vk_set_count;
     mapping->binding.binding = context->descriptor_binding++;
-    mapping->binding.count = 1;
+    mapping->binding.count = descriptor_count;
 }
 
 static uint32_t d3d12_root_signature_assign_vk_bindings(struct d3d12_root_signature *root_signature,
@@ -551,10 +554,11 @@ static uint32_t d3d12_root_signature_assign_vk_bindings(struct d3d12_root_signat
     {
         if (duplicate_descriptors)
             d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, register_space,
-                    base_register_idx + i, true, shader_visibility, context);
+                    base_register_idx + i, true, 1, shader_visibility, context);
 
         d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, register_space,
-                base_register_idx + i, is_buffer_descriptor, shader_visibility, context);
+                base_register_idx + i, is_buffer_descriptor, 1, shader_visibility,
+                context);
     }
     return first_binding;
 }
@@ -577,10 +581,40 @@ static uint32_t vkd3d_descriptor_magic_from_d3d12(D3D12_DESCRIPTOR_RANGE_TYPE ty
     }
 }
 
+static HRESULT d3d12_root_signature_init_bindless_descriptor_range(struct d3d12_root_signature *root_signature,
+        const D3D12_DESCRIPTOR_RANGE *range, D3D12_SHADER_VISIBILITY visibility,
+        struct vkd3d_descriptor_set_context *context)
+{
+    enum vkd3d_shader_descriptor_type descriptor_type = vkd3d_descriptor_type_from_d3d12_range_type(range->RangeType);
+    enum vkd3d_shader_visibility shader_visibility = vkd3d_shader_visibility_from_d3d12(visibility);
+    bool is_buffer = descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_CBV;
+
+    if (descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_SRV
+            || descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV)
+    {
+        if (!vk_binding_from_d3d12_descriptor_range(context->current_binding,
+                range, visibility, true, range->NumDescriptors, context->descriptor_binding))
+            return E_NOTIMPL;
+        ++context->current_binding;
+
+        d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, range->RegisterSpace,
+                range->BaseShaderRegister, true, range->NumDescriptors, shader_visibility, context);
+    }
+
+    if (!vk_binding_from_d3d12_descriptor_range(context->current_binding,
+            range, visibility, is_buffer, range->NumDescriptors, context->descriptor_binding))
+        return E_NOTIMPL;
+    ++context->current_binding;
+
+    d3d12_root_signature_append_vk_binding(root_signature, descriptor_type, range->RegisterSpace,
+            range->BaseShaderRegister, is_buffer, range->NumDescriptors, shader_visibility, context);
+
+    return S_OK;
+}
+
 static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_root_signature *root_signature,
         const D3D12_ROOT_SIGNATURE_DESC *desc, struct vkd3d_descriptor_set_context *context)
 {
-    VkDescriptorSetLayoutBinding *cur_binding = context->current_binding;
     struct d3d12_root_descriptor_table *table;
     const D3D12_DESCRIPTOR_RANGE *range;
     unsigned int i, j, k, range_count;
@@ -628,6 +662,24 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo
 
         for (j = 0; j < range_count; ++j)
         {
+            VkDescriptorSetLayoutBinding *cur_binding;
+
+            range = &p->u.DescriptorTable.pDescriptorRanges[j];
+
+            if (root_signature->bindless)
+            {
+                HRESULT hr;
+
+                table->ranges[j].binding = context->descriptor_binding;
+                if (FAILED(hr = d3d12_root_signature_init_bindless_descriptor_range(root_signature,
+                        range, p->ShaderVisibility, context)))
+                    return hr;
+
+                continue;
+            }
+
+            cur_binding = context->current_binding;
+
             vk_binding = d3d12_root_signature_assign_vk_bindings(root_signature,
                     vkd3d_descriptor_type_from_d3d12_range_type(range->RangeType),
                     range->RegisterSpace, range->BaseShaderRegister, range->NumDescriptors, false, true,
@@ -645,24 +697,25 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo
 
                     /* Assign binding for image view. */
                     if (!vk_binding_from_d3d12_descriptor_range(cur_binding,
-                            range, p->ShaderVisibility, false, vk_current_binding + 1))
+                            range, p->ShaderVisibility, false, 1, vk_current_binding + 1))
                         return E_NOTIMPL;
 
                     ++cur_binding;
                 }
 
                 if (!vk_binding_from_d3d12_descriptor_range(cur_binding,
-                        range, p->ShaderVisibility, true, vk_current_binding))
+                        range, p->ShaderVisibility, true, 1, vk_current_binding))
                     return E_NOTIMPL;
 
                 ++cur_binding;
             }
 
             table->ranges[j].binding = vk_binding;
+
+            context->current_binding = cur_binding;
         }
     }
 
-    context->current_binding = cur_binding;
     return S_OK;
 }
 
@@ -809,7 +862,7 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa
             | D3D12_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT))
         FIXME("Ignoring root signature flags %#x.\n", desc->Flags);
 
-    if (FAILED(hr = d3d12_root_signature_info_from_desc(&info, desc)))
+    if (FAILED(hr = d3d12_root_signature_info_from_desc(&info, desc, device->vk_info.EXT_descriptor_indexing)))
         return hr;
     if (info.cost > D3D12_MAX_ROOT_COST)
     {
@@ -820,6 +873,7 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa
     root_signature->binding_count = info.binding_count;
     root_signature->static_sampler_count = desc->NumStaticSamplers;
     root_signature->root_descriptor_count = info.root_descriptor_count;
+    root_signature->bindless = device->vk_info.EXT_descriptor_indexing;
 
     hr = E_OUTOFMEMORY;
     root_signature->parameter_count = desc->NumParameters;
@@ -1474,6 +1528,9 @@ static HRESULT d3d12_pipeline_state_init_compute_uav_counters(struct d3d12_pipel
                 || !(d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER))
             continue;
 
+        if (d->count != 1)
+            FIXME("UAV counter arrays are not supported.\n");
+
         state->uav_counters[j].register_space = d->register_space;
         state->uav_counters[j].register_index = d->register_index;
         state->uav_counters[j].shader_visibility = VKD3D_SHADER_VISIBILITY_COMPUTE;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 8dbb05b5..d86bf9a3 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -702,6 +702,7 @@ struct d3d12_root_signature
     VkPipelineLayout vk_pipeline_layout;
     uint32_t vk_set_count;
     VkDescriptorSetLayout vk_set_layouts[VKD3D_MAX_DESCRIPTOR_SETS];
+    bool bindless;
 
     struct d3d12_root_parameter *parameters;
     unsigned int parameter_count;
-- 
2.31.1




More information about the wine-devel mailing list