Signed-off-by: Conor McCarthy cmccarthy@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];