[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