[PATCH vkd3d 3/4] vkd3d: Count unbounded ranges and per-stage bound descriptors.
Conor McCarthy
cmccarthy at codeweavers.com
Wed May 26 03:04:36 CDT 2021
Enables calculation of upper bounds for variable Vulkan bindings. The
alternative is to use an arbitrary count value. The counting is complex, and
can be simplified slightly if/when update-after-bind is used, as total counts
will no longer be required.
Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
libs/vkd3d/state.c | 188 +++++++++++++++++++++++++++++++++++--
libs/vkd3d/vkd3d_private.h | 2 +-
2 files changed, 181 insertions(+), 9 deletions(-)
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c
index e459c998..749d3763 100644
--- a/libs/vkd3d/state.c
+++ b/libs/vkd3d/state.c
@@ -314,6 +314,19 @@ static bool vk_binding_from_d3d12_descriptor_range(struct VkDescriptorSetLayoutB
struct d3d12_root_signature_info
{
+ uint32_t cbv_stage_count[5];
+ uint32_t uav_stage_count[5];
+ uint32_t srv_stage_count[5];
+ uint32_t sampler_stage_count[5];
+ uint32_t total_stage_count[5];
+
+ uint32_t cbv_unbounded_set_count;
+ uint32_t uav_unbounded_set_count;
+ uint32_t srv_unbounded_set_count;
+ uint32_t sampler_unbounded_set_count;
+ uint32_t total_unbounded_set_count;
+
+ size_t mapping_count;
size_t binding_count;
size_t root_constant_count;
@@ -362,11 +375,149 @@ static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_sig
info->binding_count += range->NumDescriptors;
}
+ /* Without descriptor indexing these are always equal. */
+ info->mapping_count = info->binding_count;
+
+ return S_OK;
+}
+
+static void d3d12_count_shader_stages(D3D12_SHADER_VISIBILITY visibility,
+ uint32_t stage_count[5], unsigned int count)
+{
+ unsigned int i;
+
+ switch (visibility)
+ {
+ case D3D12_SHADER_VISIBILITY_ALL:
+ for (i = 0; i < 5; ++i)
+ stage_count[i] += count;
+ break;
+ case D3D12_SHADER_VISIBILITY_VERTEX:
+ stage_count[0] += count;
+ break;
+ case D3D12_SHADER_VISIBILITY_HULL:
+ stage_count[1] += count;
+ break;
+ case D3D12_SHADER_VISIBILITY_DOMAIN:
+ stage_count[2] += count;
+ break;
+ case D3D12_SHADER_VISIBILITY_GEOMETRY:
+ stage_count[3] += count;
+ break;
+ case D3D12_SHADER_VISIBILITY_PIXEL:
+ stage_count[4] += count;
+ break;
+ default:
+ break;
+ }
+}
+
+static HRESULT d3d12_root_signature_info_count_bindless_descriptors(struct d3d12_root_signature_info *info,
+ const D3D12_ROOT_DESCRIPTOR_TABLE *table, D3D12_SHADER_VISIBILITY visibility,
+ const struct d3d12_device *device)
+{
+ /* XXX: Vulkan buffer and image descriptors have different types. In order
+ * 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. Space must be allowed for UAV counters too. */
+ static const uint32_t multiplier[] = { 2, 3, 1, 1};
+ uint32_t *const stage_count[] = {
+ info->srv_stage_count,
+ info->uav_stage_count,
+ info->cbv_stage_count,
+ info->sampler_stage_count
+ };
+ uint32_t *const unbounded_set_count[] = {
+ &info->srv_unbounded_set_count,
+ &info->uav_unbounded_set_count,
+ &info->cbv_unbounded_set_count,
+ &info->sampler_unbounded_set_count
+ };
+ unsigned int min_offset[4], max_offset[4];
+ unsigned int i, offset = 0;
+
+ memset(min_offset, 0xFF, sizeof(min_offset));
+ memset(max_offset, 0, sizeof(max_offset));
+
+ for (i = 0; i < table->NumDescriptorRanges; ++i)
+ {
+ const D3D12_DESCRIPTOR_RANGE *range = &table->pDescriptorRanges[i];
+ unsigned int j;
+
+ if (range->OffsetInDescriptorsFromTableStart != D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
+ offset = range->OffsetInDescriptorsFromTableStart;
+
+ switch (range->RangeType)
+ {
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
+ info->mapping_count += 2;
+ j = 0;
+ break;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
+ info->mapping_count += 2;
+ j = 1;
+ break;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_CBV:
+ ++info->mapping_count;
+ j = 2;
+ break;
+ case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER:
+ ++info->mapping_count;
+ j = 3;
+ break;
+ default:
+ FIXME("Unhandled descriptor type %#x.\n", range->RangeType);
+ return E_NOTIMPL;
+ }
+
+ min_offset[j] = min(min_offset[j], offset);
+ if (range->NumDescriptors == ~0u)
+ {
+ if (offset == ~0u && range->OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND)
+ {
+ ERR("Unbounded range with offset D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND occurs after "
+ "another unbounded range.\n");
+ return E_INVALIDARG;
+ }
+ max_offset[j] = ~0u;
+ offset = ~0u;
+ }
+ else
+ {
+ if (offset == ~0u)
+ {
+ ERR("Static range occurs after unbounded range.\n");
+ return E_INVALIDARG;
+ }
+ offset += range->NumDescriptors;
+ max_offset[j] = max(max_offset[j], offset);
+ }
+ }
+
+ for (i = 0; i < 4; ++i)
+ {
+ if (min_offset[i] != ~0u)
+ {
+ /* Count descriptors bound to each stage to enable calculation of upper bounds for
+ * variable Vulkan bindings. */
+ if (max_offset[i] != ~0u)
+ d3d12_count_shader_stages(visibility, stage_count[i], (max_offset[i] - min_offset[i]) * multiplier[i]);
+ /* One Vulkan variable binding for each descriptor type, plus possible UAV counters. */
+ if (max_offset[i] == ~0u)
+ {
+ *unbounded_set_count[i] += multiplier[i];
+ info->total_unbounded_set_count += multiplier[i];
+ }
+ /* UAV counter bindings are not counted here as they are created later in separate set layouts. */
+ info->binding_count += (multiplier[i] > 1) ? 2 : 1;
+ }
+ }
+
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, const struct d3d12_device *device)
{
unsigned int i;
HRESULT hr;
@@ -380,8 +531,12 @@ static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_i
switch (p->ParameterType)
{
case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
- if (FAILED(hr = d3d12_root_signature_info_count_descriptors(info,
- &p->u.DescriptorTable)))
+ if (device->vk_info.EXT_descriptor_indexing)
+ hr = d3d12_root_signature_info_count_bindless_descriptors(info,
+ &p->u.DescriptorTable, p->ShaderVisibility, device);
+ else
+ hr = d3d12_root_signature_info_count_descriptors(info, &p->u.DescriptorTable);
+ if (FAILED(hr))
return hr;
++info->cost;
break;
@@ -389,16 +544,22 @@ static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_i
case D3D12_ROOT_PARAMETER_TYPE_CBV:
++info->root_descriptor_count;
++info->binding_count;
+ ++info->mapping_count;
+ d3d12_count_shader_stages(p->ShaderVisibility, info->cbv_stage_count, 1);
info->cost += 2;
break;
case D3D12_ROOT_PARAMETER_TYPE_SRV:
++info->root_descriptor_count;
++info->binding_count;
+ ++info->mapping_count;
+ d3d12_count_shader_stages(p->ShaderVisibility, info->srv_stage_count, 1);
info->cost += 2;
break;
case D3D12_ROOT_PARAMETER_TYPE_UAV:
++info->root_descriptor_count;
++info->binding_count;
+ ++info->mapping_count;
+ d3d12_count_shader_stages(p->ShaderVisibility, info->uav_stage_count, 1);
info->cost += 2;
break;
@@ -414,6 +575,17 @@ static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_i
}
info->binding_count += desc->NumStaticSamplers;
+ info->mapping_count += desc->NumStaticSamplers;
+ for (i = 0; i < desc->NumStaticSamplers; ++i)
+ d3d12_count_shader_stages(desc->pStaticSamplers[i].ShaderVisibility, info->sampler_stage_count, 1);
+
+ for (i = 0; i < ARRAY_SIZE(info->total_stage_count); ++i)
+ {
+ info->total_stage_count[i] += info->cbv_stage_count[i];
+ info->total_stage_count[i] += info->uav_stage_count[i];
+ info->total_stage_count[i] += info->srv_stage_count[i];
+ info->total_stage_count[i] += info->sampler_stage_count[i];
+ }
return S_OK;
}
@@ -794,7 +966,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)))
return hr;
if (info.cost > D3D12_MAX_ROOT_COST)
{
@@ -802,7 +974,7 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa
return E_INVALIDARG;
}
- root_signature->binding_count = info.binding_count;
+ root_signature->mapping_count = info.mapping_count;
root_signature->static_sampler_count = desc->NumStaticSamplers;
root_signature->root_descriptor_count = info.root_descriptor_count;
@@ -811,7 +983,7 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa
if (!(root_signature->parameters = vkd3d_calloc(root_signature->parameter_count,
sizeof(*root_signature->parameters))))
goto fail;
- if (!(root_signature->descriptor_mapping = vkd3d_calloc(root_signature->binding_count,
+ if (!(root_signature->descriptor_mapping = vkd3d_calloc(root_signature->mapping_count,
sizeof(*root_signature->descriptor_mapping))))
goto fail;
root_signature->root_constant_count = info.root_constant_count;
@@ -1549,7 +1721,7 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st
shader_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO;
shader_interface.next = NULL;
shader_interface.bindings = root_signature->descriptor_mapping;
- shader_interface.binding_count = root_signature->binding_count;
+ shader_interface.binding_count = root_signature->mapping_count;
shader_interface.push_constant_buffers = root_signature->root_constants;
shader_interface.push_constant_buffer_count = root_signature->root_constant_count;
shader_interface.combined_samplers = NULL;
@@ -2258,7 +2430,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
shader_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO;
shader_interface.next = NULL;
shader_interface.bindings = root_signature->descriptor_mapping;
- shader_interface.binding_count = root_signature->binding_count;
+ shader_interface.binding_count = root_signature->mapping_count;
shader_interface.push_constant_buffers = root_signature->root_constants;
shader_interface.push_constant_buffer_count = root_signature->root_constant_count;
shader_interface.combined_samplers = NULL;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index b30e38e9..79cd3f4f 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -712,7 +712,7 @@ struct d3d12_root_signature
D3D12_ROOT_SIGNATURE_FLAGS flags;
- unsigned int binding_count;
+ unsigned int mapping_count;
struct vkd3d_shader_resource_binding *descriptor_mapping;
unsigned int root_constant_count;
--
2.31.1
More information about the wine-devel
mailing list