Simplifies the code path for handling array bindings and unbounded ranges.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/command.c | 6 +----- libs/vkd3d/state.c | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 116a8a62..06d7746d 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -2674,7 +2674,6 @@ static void d3d12_command_list_update_descriptor_table(struct d3d12_command_list
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; @@ -2682,10 +2681,7 @@ static void d3d12_command_list_update_descriptor_table(struct d3d12_command_list { range = &descriptor_table->ranges[i];
- if (range->offset != D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) - { - descriptor = base_descriptor + range->offset; - } + descriptor = base_descriptor + range->offset;
for (j = 0; j < range->descriptor_count; ++j, ++descriptor) { diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index e459c998..d07212f6 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -591,6 +591,8 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo for (i = 0; i < desc->NumParameters; ++i) { const D3D12_ROOT_PARAMETER *p = &desc->pParameters[i]; + unsigned int offset = 0; + if (p->ParameterType != D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) continue;
@@ -608,6 +610,24 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo { range = &p->u.DescriptorTable.pDescriptorRanges[j];
+ if (range->OffsetInDescriptorsFromTableStart != D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + offset = range->OffsetInDescriptorsFromTableStart; + + table->ranges[j].offset = offset; + table->ranges[j].descriptor_count = range->NumDescriptors; + table->ranges[j].descriptor_magic = vkd3d_descriptor_magic_from_d3d12(range->RangeType); + table->ranges[j].register_space = range->RegisterSpace; + table->ranges[j].base_register_idx = range->BaseShaderRegister; + + TRACE("Descriptor table range %u.%u, offset %u, type %u, count %d.\n", i, j, + offset, range->RangeType, range->NumDescriptors); + + /* Validation during counting ensures this value is never used if range->NumDescriptors == UINT_MAX. */ + offset += range->NumDescriptors; + } + + for (j = 0; j < range_count; ++j) + { 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, @@ -638,12 +658,7 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo ++cur_binding; }
- table->ranges[j].offset = range->OffsetInDescriptorsFromTableStart; - table->ranges[j].descriptor_count = range->NumDescriptors; table->ranges[j].binding = vk_binding; - table->ranges[j].descriptor_magic = vkd3d_descriptor_magic_from_d3d12(range->RangeType); - table->ranges[j].register_space = range->RegisterSpace; - table->ranges[j].base_register_idx = range->BaseShaderRegister; } }
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@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;
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/command.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 06d7746d..dbbe822a 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -2592,7 +2592,7 @@ static void d3d12_command_list_prepare_descriptors(struct d3d12_command_list *li 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) + uint32_t vk_binding, unsigned int index, bool bindless) { const struct vkd3d_view *view = descriptor->u.view;
@@ -2602,8 +2602,10 @@ static bool vk_write_descriptor_set_from_d3d12_desc(VkWriteDescriptorSet *vk_des 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; + /* If bindless is true the descriptors use a single array binding. The value of + * range->descriptor_count is not necessarily UINT_MAX in this case. */ + vk_descriptor_write->dstBinding = bindless ? vk_binding : vk_binding + index; + vk_descriptor_write->dstArrayElement = bindless ? index : 0; vk_descriptor_write->descriptorCount = 1; vk_descriptor_write->descriptorType = descriptor->vk_descriptor_type; vk_descriptor_write->pImageInfo = NULL; @@ -2620,7 +2622,8 @@ static bool vk_write_descriptor_set_from_d3d12_desc(VkWriteDescriptorSet *vk_des 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 + 2 * index; + if(!bindless) + vk_descriptor_write->dstBinding = vk_binding + 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; @@ -2707,7 +2710,7 @@ static void d3d12_command_list_update_descriptor_table(struct d3d12_command_list
if (!vk_write_descriptor_set_from_d3d12_desc(current_descriptor_write, current_image_info, descriptor, range->descriptor_magic, - bindings->descriptor_set, range->binding, j)) + bindings->descriptor_set, range->binding, j, root_signature->bindless)) continue;
++descriptor_count;
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 0cdb22e0..f05cacea 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -33975,7 +33975,6 @@ static void test_resource_arrays(void) get_cpu_descriptor_handle(&context, heap, ARRAY_SIZE(input_buffers) + i)); }
- todo context.pipeline_state = create_compute_pipeline_state(device, context.root_signature, shader_bytecode(cs_code, sizeof(cs_code))); if (!context.pipeline_state)