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;