vkd3d: Implement local root signature association.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2021-03-11 11:40:45 +01:00
parent 028b87ab61
commit 3358fca922
1 changed files with 95 additions and 28 deletions

View File

@ -283,12 +283,19 @@ static CONST_VTBL struct ID3D12StateObjectPropertiesVtbl d3d12_state_object_prop
d3d12_state_object_properties_SetPipelineStackSize,
};
struct d3d12_state_object_root_signature_association
{
struct d3d12_root_signature *root_signature;
const WCHAR *export;
};
struct d3d12_state_object_pipeline_data
{
const D3D12_RAYTRACING_PIPELINE_CONFIG *pipeline_config;
const D3D12_RAYTRACING_SHADER_CONFIG *shader_config;
ID3D12RootSignature *global_root_signature;
ID3D12RootSignature *local_root_signature;
ID3D12RootSignature *high_priority_local_root_signature;
ID3D12RootSignature *low_priority_local_root_signature;
/* Map 1:1 with VkShaderModule. */
struct vkd3d_shader_library_entry_point *entry_points;
@ -315,6 +322,10 @@ struct d3d12_state_object_pipeline_data
size_t groups_size;
size_t groups_count;
struct d3d12_state_object_root_signature_association *associations;
size_t associations_size;
size_t associations_count;
VkPipelineShaderStageCreateInfo *stages;
size_t stages_size;
size_t stages_count;
@ -341,12 +352,14 @@ static void d3d12_state_object_pipeline_data_cleanup(struct d3d12_state_object_p
for (i = 0; i < data->stages_count; i++)
VK_CALL(vkDestroyShaderModule(device->vk_device, data->stages[i].module, NULL));
vkd3d_free(data->stages);
vkd3d_free(data->associations);
}
static HRESULT d3d12_state_object_parse_subobjects(struct d3d12_state_object *object,
const D3D12_STATE_OBJECT_DESC *desc, struct d3d12_state_object_pipeline_data *data)
{
unsigned int i;
unsigned int i, j;
for (i = 0; i < desc->NumSubobjects; i++)
{
@ -380,13 +393,11 @@ static HRESULT d3d12_state_object_parse_subobjects(struct d3d12_state_object *ob
case D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE:
{
const D3D12_LOCAL_ROOT_SIGNATURE *rs = obj->pDesc;
if (data->local_root_signature)
{
/* Simplicity for now. */
FIXME("More than one local root signature is used.\n");
return E_INVALIDARG;
}
data->local_root_signature = rs->pLocalRootSignature;
/* This is only chosen as default if there is nothing else.
* Conflicting definitions seem to cause runtime to choose something
* arbitrary. Just override the low priority default.
* A high priority default association takes precedence if it exists. */
data->low_priority_local_root_signature = rs->pLocalRootSignature;
break;
}
@ -437,6 +448,39 @@ static HRESULT d3d12_state_object_parse_subobjects(struct d3d12_state_object *ob
break;
}
case D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION:
{
const D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION *association = obj->pDesc;
const D3D12_LOCAL_ROOT_SIGNATURE *local_rs;
if (association->pSubobjectToAssociate->Type != D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE)
{
FIXME("Can only associate local root signatures to exports.\n");
return E_INVALIDARG;
}
local_rs = association->pSubobjectToAssociate->pDesc;
if (association->NumExports)
{
vkd3d_array_reserve((void **)&data->associations, &data->associations_size,
data->associations_count + association->NumExports,
sizeof(*data->associations));
for (j = 0; j < association->NumExports; j++)
{
data->associations[data->associations_count].export = association->pExports[j];
data->associations[data->associations_count].root_signature =
unsafe_impl_from_ID3D12RootSignature(local_rs->pLocalRootSignature);
data->associations_count++;
}
}
else
{
/* Local root signatures being exported to NULL takes priority as the default local RS. */
data->high_priority_local_root_signature = local_rs->pLocalRootSignature;
}
break;
}
default:
FIXME("Unrecognized subobject type: %u.\n", obj->Type);
return E_INVALIDARG;
@ -561,6 +605,29 @@ static VkDeviceSize d3d12_state_object_pipeline_data_compute_default_stack_size(
return pipeline_stack_size;
}
static struct d3d12_root_signature *d3d12_state_object_pipeline_data_get_local_root_signature(
struct d3d12_state_object_pipeline_data *data,
const struct vkd3d_shader_library_entry_point *entry)
{
size_t i;
for (i = 0; i < data->associations_count; i++)
{
if (vkd3d_export_strequal(data->associations[i].export, entry->mangled_entry_point) ||
vkd3d_export_strequal(data->associations[i].export, entry->plain_entry_point))
{
return data->associations[i].root_signature;
}
}
if (data->high_priority_local_root_signature)
return unsafe_impl_from_ID3D12RootSignature(data->high_priority_local_root_signature);
else if (data->low_priority_local_root_signature)
return unsafe_impl_from_ID3D12RootSignature(data->low_priority_local_root_signature);
else
return NULL;
}
static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *object,
struct d3d12_state_object_pipeline_data *data)
{
@ -595,7 +662,6 @@ static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *ob
shader_interface_info.min_ssbo_alignment = d3d12_device_get_ssbo_alignment(object->device);
global_signature = unsafe_impl_from_ID3D12RootSignature(data->global_root_signature);
local_signature = unsafe_impl_from_ID3D12RootSignature(data->local_root_signature);
if (global_signature)
{
@ -610,28 +676,30 @@ static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *ob
shader_interface_info.offset_buffer_binding = &global_signature->offset_buffer_binding;
}
if (local_signature)
{
shader_interface_local_info.local_root_parameters = local_signature->parameters;
shader_interface_local_info.local_root_parameter_count = local_signature->parameter_count;
shader_interface_local_info.shader_record_constant_buffers = local_signature->root_constants;
shader_interface_local_info.shader_record_buffer_count = local_signature->root_constant_count;
shader_interface_local_info.bindings = local_signature->bindings;
shader_interface_local_info.binding_count = local_signature->binding_count;
/* Promote state which might only be active in local root signature. */
shader_interface_info.flags |= local_signature->flags;
if (local_signature->flags & (VKD3D_ROOT_SIGNATURE_USE_SSBO_OFFSET_BUFFER | VKD3D_ROOT_SIGNATURE_USE_TYPED_OFFSET_BUFFER))
shader_interface_info.offset_buffer_binding = &local_signature->offset_buffer_binding;
}
else
memset(&shader_interface_local_info, 0, sizeof(shader_interface_local_info));
shader_interface_local_info.descriptor_size = sizeof(struct d3d12_desc);
for (i = 0; i < data->entry_points_count; i++)
{
entry = &data->entry_points[i];
local_signature = d3d12_state_object_pipeline_data_get_local_root_signature(data, entry);
if (local_signature)
{
shader_interface_local_info.local_root_parameters = local_signature->parameters;
shader_interface_local_info.local_root_parameter_count = local_signature->parameter_count;
shader_interface_local_info.shader_record_constant_buffers = local_signature->root_constants;
shader_interface_local_info.shader_record_buffer_count = local_signature->root_constant_count;
shader_interface_local_info.bindings = local_signature->bindings;
shader_interface_local_info.binding_count = local_signature->binding_count;
/* Promote state which might only be active in local root signature. */
shader_interface_info.flags |= local_signature->flags;
if (local_signature->flags & (VKD3D_ROOT_SIGNATURE_USE_SSBO_OFFSET_BUFFER | VKD3D_ROOT_SIGNATURE_USE_TYPED_OFFSET_BUFFER))
shader_interface_info.offset_buffer_binding = &local_signature->offset_buffer_binding;
}
else
memset(&shader_interface_local_info, 0, sizeof(shader_interface_local_info));
if (vkd3d_stage_is_global_group(entry->stage))
{
/* Directly export this as a group. */
@ -851,7 +919,6 @@ HRESULT d3d12_state_object_create(struct d3d12_device *device, const D3D12_STATE
return hr;
}
FIXME("Created stub state_object %p.\n", object);
*state_object = object;
return S_OK;
}