From 6e15ad20b43b7427d03da04a5cda9ad3963ee081 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 5 Mar 2020 11:23:42 +0100 Subject: [PATCH] vkd3d: Rework descriptor table binding. Uses the new data structures to iterate over descriptor tables and populate the packed descriptor set. Signed-off-by: Philip Rebohle --- libs/vkd3d/command.c | 313 ++++++++++++++++++------------------- libs/vkd3d/state.c | 37 +---- libs/vkd3d/vkd3d_private.h | 27 ++-- 3 files changed, 167 insertions(+), 210 deletions(-) diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 1747908a..e254ffe4 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -1867,8 +1867,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_table_dirty_mask = bindings->descriptor_table_active_mask & bindings->root_signature->descriptor_table_mask; + bindings->descriptor_table_dirty_mask = bindings->root_signature->descriptor_table_mask; bindings->root_descriptor_dirty_mask = bindings->root_signature->root_descriptor_mask; bindings->root_constant_dirty_mask = bindings->root_signature->root_constant_mask; @@ -2188,6 +2187,7 @@ static ULONG STDMETHODCALLTYPE d3d12_command_list_Release(ID3D12GraphicsCommandL { struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList2(iface); ULONG refcount = InterlockedDecrement(&list->refcount); + unsigned int i; TRACE("%p decreasing refcount to %u.\n", list, refcount); @@ -2201,6 +2201,12 @@ static ULONG STDMETHODCALLTYPE d3d12_command_list_Release(ID3D12GraphicsCommandL if (list->allocator) d3d12_command_allocator_free_command_buffer(list->allocator, list); + for (i = 0; i < ARRAY_SIZE(list->packed_descriptors); i++) + { + struct vkd3d_descriptor_updates *updates = &list->packed_descriptors[i]; + vkd3d_free(updates->descriptors); + vkd3d_free(updates->descriptor_writes); + } vkd3d_free(list); d3d12_device_release(device); @@ -2538,176 +2544,186 @@ static bool d3d12_command_list_update_graphics_pipeline(struct d3d12_command_lis return true; } -static void d3d12_command_list_prepare_descriptors(struct d3d12_command_list *list, - VkPipelineBindPoint bind_point) +static bool vkd3d_descriptor_info_from_d3d12_desc(struct d3d12_device *device, + const struct d3d12_desc *desc, const struct vkd3d_shader_resource_binding *binding, + union vkd3d_descriptor_info *vk_descriptor) { - struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point]; - const struct d3d12_root_signature *root_signature = bindings->root_signature; - - if (bindings->descriptor_set && !bindings->in_use) - return; - - /* We cannot modify bound descriptor sets. We need a new descriptor set if - * we are about to update resource bindings. - * - * The Vulkan spec says: - * - * "The descriptor set contents bound by a call to - * vkCmdBindDescriptorSets may be consumed during host execution of the - * command, or during shader execution of the resulting draws, or any - * time in between. Thus, the contents must not be altered (overwritten - * 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_packed_descriptor_layout); - bindings->in_use = false; - - bindings->descriptor_table_dirty_mask |= bindings->descriptor_table_active_mask & root_signature->descriptor_table_mask; -} - -static bool vk_write_descriptor_set_from_d3d12_desc(VkWriteDescriptorSet *vk_descriptor_write, - VkDescriptorImageInfo *vk_image_info, const struct d3d12_desc *descriptor, - uint32_t descriptor_range_magic, VkDescriptorSet vk_descriptor_set, - uint32_t vk_binding, unsigned int index, bool uav_counter) -{ - const struct vkd3d_view *view = descriptor->u.view; - bool is_uav = descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_UAV; - - if (descriptor->magic != descriptor_range_magic || (uav_counter && !is_uav)) - return false; - - vk_descriptor_write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - vk_descriptor_write->pNext = NULL; - vk_descriptor_write->dstSet = vk_descriptor_set; - vk_descriptor_write->dstBinding = vk_binding + index; - vk_descriptor_write->dstArrayElement = 0; - vk_descriptor_write->descriptorCount = 1; - vk_descriptor_write->descriptorType = descriptor->vk_descriptor_type; - vk_descriptor_write->pImageInfo = NULL; - vk_descriptor_write->pBufferInfo = NULL; - vk_descriptor_write->pTexelBufferView = NULL; - - switch (descriptor->magic) + switch (binding->type) { - case VKD3D_DESCRIPTOR_MAGIC_CBV: - vk_descriptor_write->pBufferInfo = &descriptor->u.vk_cbv_info; - break; + case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV: + if (desc->magic != VKD3D_DESCRIPTOR_MAGIC_CBV) + return false; - case VKD3D_DESCRIPTOR_MAGIC_SRV: - case VKD3D_DESCRIPTOR_MAGIC_UAV: - /* We use separate bindings for buffer and texture SRVs/UAVs. - * See d3d12_root_signature_init(). */ - vk_descriptor_write->dstBinding = vk_binding + (is_uav ? 3 : 2) * index; - if (descriptor->vk_descriptor_type != VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER - && descriptor->vk_descriptor_type != VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) - ++vk_descriptor_write->dstBinding; + vk_descriptor->buffer = desc->u.vk_cbv_info; + return true; - if (descriptor->vk_descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER - || descriptor->vk_descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) + case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV: + if (desc->magic != VKD3D_DESCRIPTOR_MAGIC_SRV) + return false; + + if ((binding->flags & VKD3D_SHADER_BINDING_FLAG_IMAGE) + && (desc->u.view->type == VKD3D_VIEW_TYPE_IMAGE)) { - if (uav_counter) - { - vk_descriptor_write->dstBinding += 2; - vk_descriptor_write->pTexelBufferView = &view->vk_counter_view; - - if (!view->vk_counter_view) - return false; - } - else - { - vk_descriptor_write->pTexelBufferView = &view->u.vk_buffer_view; - } + vk_descriptor->image.imageView = desc->u.view->u.vk_image_view; + vk_descriptor->image.sampler = VK_NULL_HANDLE; + vk_descriptor->image.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + return true; } - else + else if ((binding->flags & VKD3D_SHADER_BINDING_FLAG_BUFFER) + && (desc->u.view->type == VKD3D_VIEW_TYPE_BUFFER)) { - vk_image_info->sampler = VK_NULL_HANDLE; - vk_image_info->imageView = view->u.vk_image_view; - vk_image_info->imageLayout = descriptor->magic == VKD3D_DESCRIPTOR_MAGIC_SRV - ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL; - - vk_descriptor_write->pImageInfo = vk_image_info; + vk_descriptor->buffer_view = desc->u.view->u.vk_buffer_view; + return true; } break; - case VKD3D_DESCRIPTOR_MAGIC_SAMPLER: - vk_image_info->sampler = view->u.vk_sampler; - vk_image_info->imageView = VK_NULL_HANDLE; - vk_image_info->imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + case VKD3D_SHADER_DESCRIPTOR_TYPE_UAV: + if (desc->magic != VKD3D_DESCRIPTOR_MAGIC_UAV) + return false; - vk_descriptor_write->pImageInfo = vk_image_info; + if ((binding->flags & VKD3D_SHADER_BINDING_FLAG_IMAGE) + && (desc->u.view->type == VKD3D_VIEW_TYPE_IMAGE)) + { + vk_descriptor->image.imageView = desc->u.view->u.vk_image_view; + vk_descriptor->image.sampler = VK_NULL_HANDLE; + vk_descriptor->image.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + return true; + } + else if ((binding->flags & VKD3D_SHADER_BINDING_FLAG_BUFFER) + && (desc->u.view->type == VKD3D_VIEW_TYPE_BUFFER)) + { + vk_descriptor->buffer_view = desc->u.view->u.vk_buffer_view; + return true; + } + else if ((binding->flags & VKD3D_SHADER_BINDING_FLAG_COUNTER) + && desc->u.view->vk_counter_view) + { + vk_descriptor->buffer_view = desc->u.view->vk_counter_view; + return true; + } break; + case VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER: + if (desc->magic != VKD3D_DESCRIPTOR_MAGIC_SAMPLER) + return false; + + vk_descriptor->image.sampler = desc->u.view->u.vk_sampler; + vk_descriptor->image.imageView = VK_NULL_HANDLE; + vk_descriptor->image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + return true; + default: - ERR("Invalid descriptor %#x.\n", descriptor->magic); - return false; + ERR("Unhandled descriptor type %d.\n", binding->type); } + return false; +} + +static bool vkd3d_descriptor_updates_resize_arrays(struct vkd3d_descriptor_updates *updates, + unsigned int descriptor_count) +{ + /* This should grow over time to the point where no further allocations are necessary */ + if (!vkd3d_array_reserve((void **)&updates->descriptors, &updates->descriptors_size, + descriptor_count, sizeof(*updates->descriptors))) + return false; + + if (!vkd3d_array_reserve((void **)&updates->descriptor_writes, &updates->descriptor_writes_size, + descriptor_count, sizeof(*updates->descriptor_writes))) + return false; + return true; } -static void d3d12_command_list_update_descriptor_table(struct d3d12_command_list *list, - VkPipelineBindPoint bind_point, unsigned int index, struct d3d12_desc *base_descriptor) +static void vk_write_descriptor_set_for_descriptor_info(VkDescriptorSet vk_descriptor_set, uint32_t vk_binding, + VkDescriptorType vk_descriptor_type, union vkd3d_descriptor_info *vk_descriptor, VkWriteDescriptorSet *vk_write) { + vk_write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + vk_write->pNext = NULL; + vk_write->dstSet = vk_descriptor_set; + vk_write->dstBinding = vk_binding; + vk_write->dstArrayElement = 0; + vk_write->descriptorCount = 1; + vk_write->descriptorType = vk_descriptor_type; + vk_write->pImageInfo = &vk_descriptor->image; + vk_write->pBufferInfo = &vk_descriptor->buffer; + vk_write->pTexelBufferView = &vk_descriptor->buffer_view; +} + +static void d3d12_command_list_update_packed_descriptors(struct d3d12_command_list *list, + VkPipelineBindPoint bind_point) +{ + struct vkd3d_descriptor_updates *updates = &list->packed_descriptors[bind_point]; struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point]; - struct VkWriteDescriptorSet descriptor_writes[24], *current_descriptor_write; const struct d3d12_root_signature *root_signature = bindings->root_signature; const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; - struct VkDescriptorImageInfo image_infos[24], *current_image_info; - const struct d3d12_root_descriptor_table *descriptor_table; - const struct d3d12_root_descriptor_table_range *range; - VkDevice vk_device = list->device->vk_device; - unsigned int i, j, descriptor_count; - struct d3d12_desc *descriptor; + const struct d3d12_root_descriptor_table *table; + VkDescriptorSet descriptor_set = VK_NULL_HANDLE; + union vkd3d_descriptor_info *vk_descriptor; + const struct d3d12_desc *base_descriptor; + unsigned int root_parameter_index, i, j; + unsigned int write_count = 0; - descriptor_table = root_signature_get_descriptor_table(root_signature, index); - - descriptor = base_descriptor; - descriptor_count = 0; - current_descriptor_write = descriptor_writes; - current_image_info = image_infos; - for (i = 0; i < descriptor_table->range_count; ++i) + if (!vkd3d_descriptor_updates_resize_arrays(updates, root_signature->packed_descriptor_count)) { - range = &descriptor_table->ranges[i]; + ERR("Failed to resize descriptor update arrays.\n"); + return; + } - if (range->offset != D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) - { - descriptor = base_descriptor + range->offset; - } + /* Update packed descriptor set for all active descriptor tables */ + bindings->descriptor_table_dirty_mask |= root_signature->descriptor_table_mask; + bindings->descriptor_table_dirty_mask &= bindings->descriptor_table_active_mask; - for (j = 0; j < range->descriptor_count; ++j, ++descriptor) + if (root_signature->vk_packed_descriptor_layout) + { + descriptor_set = d3d12_command_allocator_allocate_descriptor_set( + list->allocator, root_signature->vk_packed_descriptor_layout); + } + + while (bindings->descriptor_table_dirty_mask) + { + root_parameter_index = vkd3d_bitmask_iter64(&bindings->descriptor_table_dirty_mask); + base_descriptor = d3d12_desc_from_gpu_handle(bindings->descriptor_tables[root_parameter_index]); + + table = root_signature_get_descriptor_table(root_signature, root_parameter_index); + vk_descriptor = &updates->descriptors[table->first_packed_descriptor]; + + for (i = 0; i < table->binding_count; i++) { - if (!vk_write_descriptor_set_from_d3d12_desc(current_descriptor_write, - current_image_info, descriptor, range->descriptor_magic, - bindings->descriptor_set, range->binding, j, false)) + const struct vkd3d_shader_resource_binding *binding = &table->first_binding[i]; + + if (binding->flags & VKD3D_SHADER_BINDING_FLAG_BINDLESS) continue; - ++descriptor_count; - ++current_descriptor_write; - ++current_image_info; - - if (vk_write_descriptor_set_from_d3d12_desc(current_descriptor_write, - current_image_info, descriptor, range->descriptor_magic, - bindings->descriptor_set, range->binding, j, true)) + for (j = 0; j < binding->register_count; j++) { - ++descriptor_count; - ++current_descriptor_write; - ++current_image_info; - } + const struct d3d12_desc *desc = &base_descriptor[binding->descriptor_offset + j]; - /* We may write up to two descriptors per iteration, so - * make sure there's enough space left in the array. */ - if (descriptor_count >= ARRAY_SIZE(descriptor_writes) - 1) - { - VK_CALL(vkUpdateDescriptorSets(vk_device, descriptor_count, descriptor_writes, 0, NULL)); - descriptor_count = 0; - current_descriptor_write = descriptor_writes; - current_image_info = image_infos; + /* Skip invalid descriptors */ + if (vkd3d_descriptor_info_from_d3d12_desc(list->device, desc, binding, vk_descriptor)) + { + vk_write_descriptor_set_for_descriptor_info(descriptor_set, binding->binding.binding, + desc->vk_descriptor_type, vk_descriptor, &updates->descriptor_writes[write_count++]); + } + + vk_descriptor++; } } } - VK_CALL(vkUpdateDescriptorSets(vk_device, descriptor_count, descriptor_writes, 0, NULL)); + /* Populate and bind descriptor set */ + if (write_count) + { + VK_CALL(vkUpdateDescriptorSets(list->device->vk_device, + write_count, updates->descriptor_writes, 0, NULL)); + } + + if (descriptor_set) + { + VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, bind_point, + root_signature->vk_pipeline_layout, + root_signature->packed_descriptor_set, + 1, &descriptor_set, 0, NULL)); + } } static bool vk_write_descriptor_set_from_root_descriptor(VkWriteDescriptorSet *vk_descriptor_write, @@ -2843,10 +2859,7 @@ static void d3d12_command_list_update_descriptors(struct d3d12_command_list *lis VkPipelineBindPoint bind_point) { struct vkd3d_pipeline_bindings *bindings = &list->pipeline_bindings[bind_point]; - const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; const struct d3d12_root_signature *rs = bindings->root_signature; - struct d3d12_desc *base_descriptor; - unsigned int i; if (!rs) return; @@ -2855,30 +2868,11 @@ static void d3d12_command_list_update_descriptors(struct d3d12_command_list *lis d3d12_command_list_update_static_samplers(list, bind_point); if (bindings->descriptor_table_dirty_mask) - d3d12_command_list_prepare_descriptors(list, bind_point); - - for (i = 0; i < ARRAY_SIZE(bindings->descriptor_tables); ++i) - { - if (bindings->descriptor_table_dirty_mask & ((uint64_t)1 << i)) - { - if ((base_descriptor = d3d12_desc_from_gpu_handle(bindings->descriptor_tables[i]))) - d3d12_command_list_update_descriptor_table(list, bind_point, i, base_descriptor); - else - WARN("Descriptor table %u is not set.\n", i); - } - } - bindings->descriptor_table_dirty_mask = 0; + d3d12_command_list_update_packed_descriptors(list, bind_point); if (bindings->root_descriptor_dirty_mask) d3d12_command_list_update_root_descriptors(list, bind_point); - if (bindings->descriptor_set) - { - VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, bind_point, - rs->vk_pipeline_layout, rs->packed_descriptor_set, 1, &bindings->descriptor_set, 0, NULL)); - bindings->in_use = true; - } - if (bindings->root_constant_dirty_mask) d3d12_command_list_update_root_constants(list, bind_point); } @@ -5543,6 +5537,7 @@ static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, struct d { HRESULT hr; + memset(list, 0, sizeof(*list)); list->ID3D12GraphicsCommandList2_iface.lpVtbl = &d3d12_command_list_vtbl; list->refcount = 1; diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index a9cf06f9..21f93191 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -71,12 +71,6 @@ static void d3d12_root_signature_cleanup(struct d3d12_root_signature *root_signa for (i = 0; i < root_signature->static_sampler_count; ++i) VK_CALL(vkDestroySampler(device->vk_device, root_signature->static_samplers[i], NULL)); - for (i = 0; i < root_signature->parameter_count; ++i) - { - if (root_signature->parameters[i].parameter_type == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) - vkd3d_free(root_signature->parameters[i].u.descriptor_table.ranges); - } - vkd3d_free(root_signature->parameters); vkd3d_free(root_signature->bindings); vkd3d_free(root_signature->root_constants); @@ -474,24 +468,6 @@ struct vkd3d_descriptor_set_context uint32_t vk_binding; }; -static uint32_t vkd3d_descriptor_magic_from_d3d12(D3D12_DESCRIPTOR_RANGE_TYPE type) -{ - switch (type) - { - case D3D12_DESCRIPTOR_RANGE_TYPE_SRV: - return VKD3D_DESCRIPTOR_MAGIC_SRV; - case D3D12_DESCRIPTOR_RANGE_TYPE_UAV: - return VKD3D_DESCRIPTOR_MAGIC_UAV; - case D3D12_DESCRIPTOR_RANGE_TYPE_CBV: - return VKD3D_DESCRIPTOR_MAGIC_CBV; - case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER: - return VKD3D_DESCRIPTOR_MAGIC_SAMPLER; - default: - ERR("Invalid range type %#x.\n", type); - return VKD3D_DESCRIPTOR_MAGIC_FREE; - } -} - static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_root_signature *root_signature, const D3D12_ROOT_SIGNATURE_DESC *desc, const struct d3d12_root_signature_info *info, struct vkd3d_descriptor_set_context *context, VkDescriptorSetLayout *vk_set_layout) @@ -519,15 +495,12 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo range_descriptor_offset = 0; root_signature->parameters[i].parameter_type = p->ParameterType; - table->range_count = range_count; + table->table_index = t++; table->binding_count = 0; table->first_binding = &root_signature->bindings[context->binding_index]; table->first_packed_descriptor = context->packed_descriptor_index; - if (!(table->ranges = vkd3d_calloc(table->range_count, sizeof(*table->ranges)))) - return E_OUTOFMEMORY; - for (j = 0; j < range_count; ++j) { const D3D12_DESCRIPTOR_RANGE *range = &p->u.DescriptorTable.pDescriptorRanges[j]; @@ -535,13 +508,6 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo bool is_srv = range->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV; bool is_uav = range->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV; - table->ranges[j].offset = range->OffsetInDescriptorsFromTableStart; - table->ranges[j].descriptor_count = range->NumDescriptors; - table->ranges[j].binding = context->vk_binding; - table->ranges[j].descriptor_magic = vkd3d_descriptor_magic_from_d3d12(range->RangeType); - table->ranges[j].base_register_idx = range->BaseShaderRegister; - table->ranges[j].register_space = range->RegisterSpace; - if (range->OffsetInDescriptorsFromTableStart != D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) range_descriptor_offset = range->OffsetInDescriptorsFromTableStart; @@ -764,6 +730,7 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa root_signature->device = device; root_signature->binding_count = info.binding_count; root_signature->static_sampler_count = desc->NumStaticSamplers; + root_signature->packed_descriptor_count = info.descriptor_count; root_signature->root_descriptor_count = info.root_descriptor_count; hr = E_OUTOFMEMORY; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 2a000d22..ec8bdd48 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -656,22 +656,8 @@ static inline void d3d12_query_heap_mark_result_as_available(struct d3d12_query_ heap->availability_mask[index] |= (uint64_t)1 << shift; } -struct d3d12_root_descriptor_table_range -{ - unsigned int offset; - unsigned int descriptor_count; - uint32_t binding; - - uint32_t descriptor_magic; - unsigned int base_register_idx; - unsigned int register_space; -}; - struct d3d12_root_descriptor_table { - unsigned int range_count; - struct d3d12_root_descriptor_table_range *ranges; - uint32_t table_index; uint32_t binding_count; uint32_t first_packed_descriptor; @@ -731,6 +717,7 @@ struct d3d12_root_signature unsigned int root_constant_count; struct vkd3d_shader_push_constant_buffer *root_constants; + unsigned int packed_descriptor_count; unsigned int root_descriptor_count; /* Use one global push constant range */ @@ -914,14 +901,21 @@ union vkd3d_descriptor_info VkDescriptorImageInfo image; }; +struct vkd3d_descriptor_updates +{ + VkWriteDescriptorSet *descriptor_writes; + size_t descriptor_writes_size; + + union vkd3d_descriptor_info *descriptors; + size_t descriptors_size; +}; + struct vkd3d_pipeline_bindings { const struct d3d12_root_signature *root_signature; VkDescriptorSet static_sampler_set; - VkDescriptorSet descriptor_set; bool static_sampler_set_dirty; - bool in_use; D3D12_GPU_DESCRIPTOR_HANDLE descriptor_tables[D3D12_MAX_ROOT_COST]; uint64_t descriptor_table_dirty_mask; @@ -970,6 +964,7 @@ struct d3d12_command_list VkRenderPass pso_render_pass; VkRenderPass current_render_pass; struct vkd3d_pipeline_bindings pipeline_bindings[VK_PIPELINE_BIND_POINT_RANGE_SIZE]; + struct vkd3d_descriptor_updates packed_descriptors[VK_PIPELINE_BIND_POINT_RANGE_SIZE]; struct d3d12_pipeline_state *state;