[PATCH vkd3d 2/3] vkd3d: Create Vulkan descriptor sets from variable layouts.

Conor McCarthy cmccarthy at codeweavers.com
Wed May 26 03:07:53 CDT 2021


Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 libs/vkd3d/command.c       | 70 +++++++++++++++++++++++++++++++-------
 libs/vkd3d/vkd3d_private.h |  4 ++-
 2 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 116a8a62..5cb95869 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -1363,10 +1363,12 @@ static VkDescriptorPool d3d12_command_allocator_allocate_descriptor_pool(
 }
 
 static VkDescriptorSet d3d12_command_allocator_allocate_descriptor_set(
-        struct d3d12_command_allocator *allocator, VkDescriptorSetLayout vk_set_layout)
+        struct d3d12_command_allocator *allocator, VkDescriptorSetLayout vk_set_layout,
+        uint32_t variable_binding_size, bool unbounded)
 {
     struct d3d12_device *device = allocator->device;
     const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
+    VkDescriptorSetVariableDescriptorCountAllocateInfoEXT set_size;
     struct VkDescriptorSetAllocateInfo set_desc;
     VkDevice vk_device = device->vk_device;
     VkDescriptorSet vk_descriptor_set;
@@ -1382,6 +1384,14 @@ static VkDescriptorSet d3d12_command_allocator_allocate_descriptor_set(
     set_desc.descriptorPool = allocator->vk_descriptor_pool;
     set_desc.descriptorSetCount = 1;
     set_desc.pSetLayouts = &vk_set_layout;
+    if (unbounded)
+    {
+        set_desc.pNext = &set_size;
+        set_size.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT;
+        set_size.pNext = NULL;
+        set_size.descriptorSetCount = 1;
+        set_size.pDescriptorCounts = &variable_binding_size;
+    }
     if ((vr = VK_CALL(vkAllocateDescriptorSets(vk_device, &set_desc, &vk_descriptor_set))) >= 0)
         return vk_descriptor_set;
 
@@ -1881,7 +1891,7 @@ static void d3d12_command_list_invalidate_root_parameters(struct d3d12_command_l
     if (!bindings->root_signature)
         return;
 
-    bindings->descriptor_set = VK_NULL_HANDLE;
+    bindings->descriptor_set_count = 0;
     bindings->descriptor_table_dirty_mask = bindings->descriptor_table_active_mask & bindings->root_signature->descriptor_table_mask;
     bindings->push_descriptor_dirty_mask = bindings->push_descriptor_active_mask & bindings->root_signature->push_descriptor_mask;
 }
@@ -2565,8 +2575,10 @@ static void d3d12_command_list_prepare_descriptors(struct d3d12_command_list *li
 {
     struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point];
     const struct d3d12_root_signature *root_signature = bindings->root_signature;
+    struct d3d12_device *device = list->device;
+    unsigned int i;
 
-    if (bindings->descriptor_set && !bindings->in_use)
+    if (bindings->descriptor_set_count && !bindings->in_use)
         return;
 
     /* We cannot modify bound descriptor sets. We need a new descriptor set if
@@ -2581,8 +2593,41 @@ static void d3d12_command_list_prepare_descriptors(struct d3d12_command_list *li
      *   by an update command, or freed) between when the command is recorded
      *   and when the command completes executing on the queue."
      */
-    bindings->descriptor_set = d3d12_command_allocator_allocate_descriptor_set(list->allocator,
-            root_signature->vk_set_layouts[root_signature->main_set]);
+    bindings->descriptor_set_count = 0;
+    for (i = root_signature->main_set; i < root_signature->vk_set_count; ++i)
+    {
+        int unbounded_table = root_signature->vk_unbounded_set_tables[i];
+        unsigned int variable_binding_size = 0;
+        if (unbounded_table >= 0)
+        {
+            const struct d3d12_desc *base_descriptor
+                    = d3d12_desc_from_gpu_handle(bindings->descriptor_tables[unbounded_table]);
+            /* Descriptors may not be set, eg. WoW. */
+            if (base_descriptor)
+            {
+                unsigned int static_descriptor_count = root_signature->vk_set_layout_static_counts[i];
+                unsigned int heap_size;
+                int rc;
+
+                rc = pthread_mutex_lock(&device->mutex);
+                if (rc)
+                    ERR("Failed to lock mutex, error %d.\n", rc);
+                heap_size = d3d12_device_descriptor_heap_size_from_descriptor(device, base_descriptor);
+                if (!rc)
+                    pthread_mutex_unlock(&device->mutex);
+
+                if (heap_size >= static_descriptor_count)
+                    variable_binding_size = heap_size - static_descriptor_count;
+                else
+                    WARN("Descriptor heap size %u is less than the variable binding offset %u.\n", variable_binding_size,
+                            static_descriptor_count);
+            }
+        }
+        bindings->descriptor_sets[bindings->descriptor_set_count] =
+            d3d12_command_allocator_allocate_descriptor_set(list->allocator,
+                    root_signature->vk_set_layouts[i], variable_binding_size, unbounded_table >= 0);
+        ++bindings->descriptor_set_count;
+    }
     bindings->in_use = false;
 
     bindings->descriptor_table_dirty_mask |= bindings->descriptor_table_active_mask & root_signature->descriptor_table_mask;
@@ -2819,7 +2864,7 @@ static void d3d12_command_list_update_push_descriptors(struct d3d12_command_list
         }
 
         if (!vk_write_descriptor_set_from_root_descriptor(current_descriptor_write,
-                root_parameter, bindings->descriptor_set, vk_buffer_view, vk_buffer_info))
+                root_parameter, bindings->descriptor_sets[0], vk_buffer_view, vk_buffer_info))
             continue;
 
         ++descriptor_count;
@@ -2849,7 +2894,7 @@ static void d3d12_command_list_update_uav_counter_descriptors(struct d3d12_comma
     uav_counter_count = state->uav_counter_count;
     if (!(vk_descriptor_writes = vkd3d_calloc(uav_counter_count, sizeof(*vk_descriptor_writes))))
         return;
-    if (!(vk_descriptor_set = d3d12_command_allocator_allocate_descriptor_set(list->allocator, state->vk_set_layout)))
+    if (!(vk_descriptor_set = d3d12_command_allocator_allocate_descriptor_set(list->allocator, state->vk_set_layout, 0, false)))
         goto done;
 
     for (i = 0; i < uav_counter_count; ++i)
@@ -2911,10 +2956,11 @@ static void d3d12_command_list_update_descriptors(struct d3d12_command_list *lis
 
     d3d12_command_list_update_push_descriptors(list, bind_point);
 
-    if (bindings->descriptor_set)
+    if (bindings->descriptor_set_count)
     {
         VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, bindings->vk_bind_point,
-                rs->vk_pipeline_layout, rs->main_set, 1, &bindings->descriptor_set, 0, NULL));
+                rs->vk_pipeline_layout, rs->main_set, bindings->descriptor_set_count, bindings->descriptor_sets,
+                0, NULL));
         bindings->in_use = true;
     }
 
@@ -4229,7 +4275,7 @@ static void d3d12_command_list_set_root_cbv(struct d3d12_command_list *list,
     {
         d3d12_command_list_prepare_descriptors(list, bind_point);
         vk_write_descriptor_set_from_root_descriptor(&descriptor_write,
-                root_parameter, bindings->descriptor_set, NULL, &buffer_info);
+                root_parameter, bindings->descriptor_sets[0], NULL, &buffer_info);
         VK_CALL(vkUpdateDescriptorSets(list->device->vk_device, 1, &descriptor_write, 0, NULL));
 
         assert(index < ARRAY_SIZE(bindings->push_descriptors));
@@ -4302,7 +4348,7 @@ static void d3d12_command_list_set_root_descriptor(struct d3d12_command_list *li
     {
         d3d12_command_list_prepare_descriptors(list, bind_point);
         vk_write_descriptor_set_from_root_descriptor(&descriptor_write,
-                root_parameter, bindings->descriptor_set, &vk_buffer_view,  NULL);
+                root_parameter, bindings->descriptor_sets[0], &vk_buffer_view,  NULL);
         VK_CALL(vkUpdateDescriptorSets(list->device->vk_device, 1, &descriptor_write, 0, NULL));
 
         assert(index < ARRAY_SIZE(bindings->push_descriptors));
@@ -4949,7 +4995,7 @@ static void d3d12_command_list_clear_uav(struct d3d12_command_list *list,
     }
 
     if (!(write_set.dstSet = d3d12_command_allocator_allocate_descriptor_set(
-            list->allocator, pipeline.vk_set_layout)))
+            list->allocator, pipeline.vk_set_layout, 0, false)))
     {
         ERR("Failed to allocate descriptor set.\n");
         return;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 28742a8b..d0275062 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -924,7 +924,9 @@ struct vkd3d_pipeline_bindings
     const struct d3d12_root_signature *root_signature;
 
     VkPipelineBindPoint vk_bind_point;
-    VkDescriptorSet descriptor_set;
+    /* All descriptor sets at index > 1 are for unbounded D3D12 ranges. Set 0 or 1 may be unbounded too. */
+    size_t descriptor_set_count;
+    VkDescriptorSet descriptor_sets[VKD3D_MAX_DESCRIPTOR_SETS];
     bool in_use;
 
     D3D12_GPU_DESCRIPTOR_HANDLE descriptor_tables[D3D12_MAX_ROOT_COST];
-- 
2.31.1




More information about the wine-devel mailing list