vkd3d: Check the entire root signature for register conflicts.

Not just each descriptor table individually.
This commit is contained in:
Giovanni Mascellani 2024-08-02 23:38:52 +02:00 committed by Henri Verbeet
parent a3f4785720
commit 784e69a366
Notes: Henri Verbeet 2024-08-06 16:59:03 +02:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/981
2 changed files with 130 additions and 45 deletions

View File

@ -345,15 +345,93 @@ struct d3d12_root_signature_info
unsigned int sampler_unbounded_range_count;
size_t cost;
struct d3d12_root_signature_info_range
{
enum vkd3d_shader_descriptor_type type;
unsigned int space;
unsigned int base_idx;
unsigned int count;
D3D12_SHADER_VISIBILITY visibility;
} *ranges;
size_t range_count, range_capacity;
};
static HRESULT d3d12_root_signature_info_add_range(struct d3d12_root_signature_info *info,
enum vkd3d_shader_descriptor_type type, D3D12_SHADER_VISIBILITY visibility,
unsigned int space, unsigned int base_idx, unsigned int count)
{
struct d3d12_root_signature_info_range *range;
if (!vkd3d_array_reserve((void **)&info->ranges, &info->range_capacity, info->range_count + 1,
sizeof(*info->ranges)))
return E_OUTOFMEMORY;
range = &info->ranges[info->range_count++];
range->type = type;
range->space = space;
range->base_idx = base_idx;
range->count = count;
range->visibility = visibility;
return S_OK;
}
static int d3d12_root_signature_info_range_compare(const void *a, const void *b)
{
const struct d3d12_root_signature_info_range *range_a = a, *range_b = b;
int ret;
if ((ret = vkd3d_u32_compare(range_a->type, range_b->type)))
return ret;
if ((ret = vkd3d_u32_compare(range_a->space, range_b->space)))
return ret;
return vkd3d_u32_compare(range_a->base_idx, range_b->base_idx);
}
static HRESULT d3d12_root_signature_info_range_validate(const struct d3d12_root_signature_info_range *ranges,
unsigned int count, D3D12_SHADER_VISIBILITY visibility)
{
const struct d3d12_root_signature_info_range *range, *next;
unsigned int i = 0, j;
while (i < count)
{
range = &ranges[i];
for (j = i + 1; j < count; ++j)
{
next = &ranges[j];
if (range->visibility != D3D12_SHADER_VISIBILITY_ALL
&& next->visibility != D3D12_SHADER_VISIBILITY_ALL
&& range->visibility != next->visibility)
continue;
if (range->type == next->type && range->space == next->space
&& range->base_idx + range->count > next->base_idx)
return E_INVALIDARG;
break;
}
i = j;
}
return S_OK;
}
static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_signature_info *info,
const D3D12_ROOT_DESCRIPTOR_TABLE *table, bool use_array)
const D3D12_ROOT_PARAMETER *param, bool use_array)
{
bool cbv_unbounded_range = false, srv_unbounded_range = false, uav_unbounded_range = false;
const D3D12_ROOT_DESCRIPTOR_TABLE *table = &param->u.DescriptorTable;
bool sampler_unbounded_range = false;
bool unbounded = false;
unsigned int i, count;
HRESULT hr;
for (i = 0; i < table->NumDescriptorRanges; ++i)
{
@ -381,6 +459,12 @@ static HRESULT d3d12_root_signature_info_count_descriptors(struct d3d12_root_sig
}
count = range->NumDescriptors;
if (FAILED(hr = d3d12_root_signature_info_add_range(info,
vkd3d_descriptor_type_from_d3d12_range_type(range->RangeType),
param->ShaderVisibility, range->RegisterSpace, range->BaseShaderRegister, count)))
return hr;
if (range->NumDescriptors == UINT_MAX)
{
unbounded = true;
@ -453,7 +537,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, use_array)))
p, use_array)))
return hr;
++info->cost;
break;
@ -463,23 +547,41 @@ static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_i
++info->cbv_count;
++info->binding_count;
info->cost += 2;
if (FAILED(hr = d3d12_root_signature_info_add_range(info,
VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, p->ShaderVisibility,
p->u.Descriptor.RegisterSpace, p->u.Descriptor.ShaderRegister, 1)))
return hr;
break;
case D3D12_ROOT_PARAMETER_TYPE_SRV:
++info->root_descriptor_count;
++info->srv_count;
++info->binding_count;
info->cost += 2;
if (FAILED(hr = d3d12_root_signature_info_add_range(info,
VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, p->ShaderVisibility,
p->u.Descriptor.RegisterSpace, p->u.Descriptor.ShaderRegister, 1)))
return hr;
break;
case D3D12_ROOT_PARAMETER_TYPE_UAV:
++info->root_descriptor_count;
++info->uav_count;
++info->binding_count;
info->cost += 2;
if (FAILED(hr = d3d12_root_signature_info_add_range(info,
VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, p->ShaderVisibility,
p->u.Descriptor.RegisterSpace, p->u.Descriptor.ShaderRegister, 1)))
return hr;
break;
case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS:
++info->root_constant_count;
info->cost += p->u.Constants.Num32BitValues;
if (FAILED(hr = d3d12_root_signature_info_add_range(info,
VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, p->ShaderVisibility,
p->u.Constants.RegisterSpace, p->u.Constants.ShaderRegister, 1)))
return hr;
break;
default:
@ -491,6 +593,30 @@ static HRESULT d3d12_root_signature_info_from_desc(struct d3d12_root_signature_i
info->binding_count += desc->NumStaticSamplers;
info->sampler_count += desc->NumStaticSamplers;
for (i = 0; i < desc->NumStaticSamplers; ++i)
{
const D3D12_STATIC_SAMPLER_DESC *s = &desc->pStaticSamplers[i];
if (FAILED(hr = d3d12_root_signature_info_add_range(info,
VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, s->ShaderVisibility,
s->RegisterSpace, s->ShaderRegister, 1)))
return hr;
}
qsort(info->ranges, info->range_count, sizeof(*info->ranges),
d3d12_root_signature_info_range_compare);
for (i = D3D12_SHADER_VISIBILITY_VERTEX; i <= D3D12_SHADER_VISIBILITY_MESH; ++i)
{
if (FAILED(hr = d3d12_root_signature_info_range_validate(info->ranges, info->range_count, i)))
return hr;
}
vkd3d_free(info->ranges);
info->ranges = NULL;
info->range_count = 0;
info->range_capacity = 0;
return S_OK;
}
@ -963,20 +1089,6 @@ static void d3d12_root_signature_map_descriptor_unbounded_binding(struct d3d12_r
descriptor_offset, is_buffer, shader_visibility, context);
}
static int compare_register_range(const void *a, const void *b)
{
const struct d3d12_root_descriptor_table_range *range_a = a, *range_b = b;
int ret;
if ((ret = vkd3d_u32_compare(range_a->type, range_b->type)))
return ret;
if ((ret = vkd3d_u32_compare(range_a->register_space, range_b->register_space)))
return ret;
return vkd3d_u32_compare(range_a->base_register_idx, range_b->base_register_idx);
}
static int compare_descriptor_range(const void *a, const void *b)
{
const struct d3d12_root_descriptor_table_range *range_a = a, *range_b = b;
@ -991,25 +1103,6 @@ static int compare_descriptor_range(const void *a, const void *b)
return (range_a->descriptor_count == UINT_MAX) - (range_b->descriptor_count == UINT_MAX);
}
static HRESULT validate_descriptor_register_ranges(const struct d3d12_root_descriptor_table_range *ranges,
unsigned int count)
{
const struct d3d12_root_descriptor_table_range *range, *prev;
unsigned int i;
for (i = 1; i < count; ++i)
{
range = &ranges[i];
prev = &ranges[i - 1];
if (range->type == prev->type && range->register_space == prev->register_space
&& range->base_register_idx - prev->base_register_idx < prev->descriptor_count)
return E_INVALIDARG;
}
return S_OK;
}
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)
@ -1070,10 +1163,6 @@ static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_roo
offset += range->NumDescriptors;
}
qsort(table->ranges, range_count, sizeof(*table->ranges), compare_register_range);
if (FAILED(hr = validate_descriptor_register_ranges(table->ranges, range_count)))
return hr;
qsort(table->ranges, range_count, sizeof(*table->ranges), compare_descriptor_range);
for (j = 0; j < range_count; ++j)

View File

@ -2913,7 +2913,7 @@ static void test_create_root_signature(void)
root_signature_desc.pStaticSamplers = NULL;
root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
hr = create_root_signature(device, &root_signature_desc, &root_signature);
todo ok(hr == E_FAIL || hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
ok(hr == E_FAIL || hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
if (SUCCEEDED(hr))
ID3D12RootSignature_Release(root_signature);
root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
@ -2948,7 +2948,7 @@ static void test_create_root_signature(void)
root_signature_desc.pStaticSamplers = NULL;
root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
hr = create_root_signature(device, &root_signature_desc, &root_signature);
todo ok(hr == E_FAIL || hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
ok(hr == E_FAIL || hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
if (SUCCEEDED(hr))
ID3D12RootSignature_Release(root_signature);
root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_GEOMETRY;
@ -2984,7 +2984,6 @@ static void test_create_root_signature(void)
root_parameters[1].DescriptorTable.pDescriptorRanges = &descriptor_ranges[1];
root_signature_desc.NumParameters = 2;
hr = create_root_signature(device, &root_signature_desc, &root_signature);
todo
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
if (SUCCEEDED(hr))
ID3D12RootSignature_Release(root_signature);
@ -2995,7 +2994,6 @@ static void test_create_root_signature(void)
root_parameters[1].Descriptor.ShaderRegister = 0;
root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
hr = create_root_signature(device, &root_signature_desc, &root_signature);
todo
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
if (SUCCEEDED(hr))
ID3D12RootSignature_Release(root_signature);
@ -3008,7 +3006,6 @@ static void test_create_root_signature(void)
root_parameters[1].Constants.Num32BitValues = 1;
root_parameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
hr = create_root_signature(device, &root_signature_desc, &root_signature);
todo
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
if (SUCCEEDED(hr))
ID3D12RootSignature_Release(root_signature);
@ -3032,7 +3029,6 @@ static void test_create_root_signature(void)
root_signature_desc.NumStaticSamplers = 1;
root_signature_desc.pStaticSamplers = static_samplers;
hr = create_root_signature(device, &root_signature_desc, &root_signature);
todo
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
if (SUCCEEDED(hr))
ID3D12RootSignature_Release(root_signature);