From b88b04e4f1f2c3a4af657150f79c114fbb0a1253 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Mon, 9 May 2022 20:02:09 +0200 Subject: [PATCH] vkd3d: Rewrite how submodules are associated with exports. Handle embedded DXIL subobjects and fix various issues exposed by the upcoming new tests. Associating with global root signatures, shader config and pipeline config needs to be rewritten so that we validate uniqueness late. The strategy here is to look at all exports we care about and find an association. There are many priority levels which are implied by how I understand the DXR docs. State objects in the API win over embedded DXIL state objects. Any DXIL state object wins over a collection. Hit group associations can trump an entry point. It's not entirely clear how this works, but we let it win if it has higher priority, i.e. an explicit association directed at the hit group. There's also cases where explicit assignment trumps explicit default assignment, which then trumps just declaring a state object. Collection state is inherited in some cases like AddToStateObject() even if this seems to be undocumented behavior. Signed-off-by: Hans-Kristian Arntzen --- libs/vkd3d/raytracing_pipeline.c | 1011 +++++++++++++++++++++--------- 1 file changed, 711 insertions(+), 300 deletions(-) diff --git a/libs/vkd3d/raytracing_pipeline.c b/libs/vkd3d/raytracing_pipeline.c index 8da85c63..a9f1c1cc 100644 --- a/libs/vkd3d/raytracing_pipeline.c +++ b/libs/vkd3d/raytracing_pipeline.c @@ -343,9 +343,17 @@ static CONST_VTBL struct ID3D12StateObjectPropertiesVtbl d3d12_state_object_prop d3d12_state_object_properties_SetPipelineStackSize, }; -struct d3d12_state_object_root_signature_association +struct d3d12_state_object_association { - struct d3d12_root_signature *root_signature; + enum vkd3d_shader_subobject_kind kind; + unsigned int priority; /* Different priorities can tie-break. */ + union + { + struct d3d12_root_signature *root_signature; + D3D12_STATE_OBJECT_CONFIG object_config; + D3D12_RAYTRACING_PIPELINE_CONFIG1 pipeline_config; + D3D12_RAYTRACING_SHADER_CONFIG shader_config; + }; const WCHAR *export; }; @@ -358,14 +366,6 @@ struct d3d12_state_object_collection struct d3d12_state_object_pipeline_data { - D3D12_RAYTRACING_PIPELINE_CONFIG1 pipeline_config; - bool has_pipeline_config; - - const D3D12_RAYTRACING_SHADER_CONFIG *shader_config; - struct d3d12_root_signature *global_root_signature; - struct d3d12_root_signature *high_priority_local_root_signature; - struct d3d12_root_signature *low_priority_local_root_signature; - /* Map 1:1 with VkShaderModule. */ struct vkd3d_shader_library_entry_point *entry_points; size_t entry_points_size; @@ -375,6 +375,10 @@ struct d3d12_state_object_pipeline_data size_t subobjects_size; size_t subobjects_count; + struct d3d12_root_signature **subobject_root_signatures; + size_t subobject_root_signatures_size; + size_t subobject_root_signatures_count; + /* Resolve these to group + export name later. */ const struct D3D12_HIT_GROUP_DESC **hit_groups; size_t hit_groups_size; @@ -395,7 +399,7 @@ struct d3d12_state_object_pipeline_data size_t groups_size; size_t groups_count; - struct d3d12_state_object_root_signature_association *associations; + struct d3d12_state_object_association *associations; size_t associations_size; size_t associations_count; @@ -423,6 +427,10 @@ static void d3d12_state_object_pipeline_data_cleanup(struct d3d12_state_object_p vkd3d_free((void*)data->hit_groups); vkd3d_free((void*)data->dxil_libraries); + for (i = 0; i < data->subobject_root_signatures_count; i++) + d3d12_root_signature_dec_ref(data->subobject_root_signatures[i]); + vkd3d_free(data->subobject_root_signatures); + for (i = 0; i < data->exports_count; i++) { vkd3d_free(data->exports[i].mangled_export); @@ -440,6 +448,14 @@ static void d3d12_state_object_pipeline_data_cleanup(struct d3d12_state_object_p vkd3d_free(data->vk_libraries); } +#define VKD3D_ASSOCIATION_PRIORITY_INHERITED_COLLECTION 0 +#define VKD3D_ASSOCIATION_PRIORITY_DXIL_SUBOBJECT 1 +#define VKD3D_ASSOCIATION_PRIORITY_DXIL_SUBOBJECT_ASSIGNMENT_DEFAULT 2 +#define VKD3D_ASSOCIATION_PRIORITY_DXIL_SUBOBJECT_ASSIGNMENT_EXPLICIT 3 +#define VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT 4 +#define VKD3D_ASSOCIATION_PRIORITY_EXPLICIT_DEFAULT 5 +#define VKD3D_ASSOCIATION_PRIORITY_EXPLICIT 6 + static HRESULT d3d12_state_object_add_collection( struct d3d12_state_object *collection, struct d3d12_state_object_pipeline_data *data, @@ -449,44 +465,29 @@ static HRESULT d3d12_state_object_add_collection( data->collections_count + 1, sizeof(*data->collections))) return E_OUTOFMEMORY; + if (!vkd3d_array_reserve((void **)&data->associations, &data->associations_size, + data->associations_count + 3, sizeof(*data->associations))) + return E_OUTOFMEMORY; + /* If a PSO only declares collections, but no pipelines, just inherit various state. - * Also, validates that we have a match across different PSOs. */ - if (data->global_root_signature) - { - if (!collection->global_root_signature || - data->global_root_signature->compatibility_hash != collection->global_root_signature->compatibility_hash) - { - FIXME("Mismatch in global root signature state for PSO and collection.\n"); - return E_INVALIDARG; - } - } - else - data->global_root_signature = collection->global_root_signature; + * Also, validates later that we have a match across different PSOs if we end up with mismatches. */ + data->associations[data->associations_count].kind = VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE; + data->associations[data->associations_count].root_signature = collection->global_root_signature; + data->associations[data->associations_count].priority = VKD3D_ASSOCIATION_PRIORITY_INHERITED_COLLECTION; + data->associations[data->associations_count].export = NULL; + data->associations_count++; - if (data->has_pipeline_config) - { - if (memcmp(&data->pipeline_config, &collection->pipeline_config, sizeof(data->pipeline_config)) != 0) - { - FIXME("Mismatch in pipeline config state for collection and PSO.\n"); - return E_INVALIDARG; - } - } - else - { - data->pipeline_config = collection->pipeline_config; - data->has_pipeline_config = true; - } + data->associations[data->associations_count].kind = VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1; + data->associations[data->associations_count].pipeline_config = collection->pipeline_config; + data->associations[data->associations_count].priority = VKD3D_ASSOCIATION_PRIORITY_INHERITED_COLLECTION; + data->associations[data->associations_count].export = NULL; + data->associations_count++; - if (data->shader_config) - { - if (memcmp(data->shader_config, &collection->shader_config, sizeof(*data->shader_config)) != 0) - { - FIXME("Mismatch in shader config state for collection and PSO.\n"); - return E_INVALIDARG; - } - } - else - data->shader_config = &collection->shader_config; + data->associations[data->associations_count].kind = VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_SHADER_CONFIG; + data->associations[data->associations_count].shader_config = collection->shader_config; + data->associations[data->associations_count].priority = VKD3D_ASSOCIATION_PRIORITY_INHERITED_COLLECTION; + data->associations[data->associations_count].export = NULL; + data->associations_count++; data->collections[data->collections_count].object = collection; data->collections[data->collections_count].num_exports = num_exports; @@ -502,222 +503,449 @@ static HRESULT d3d12_state_object_add_collection( return S_OK; } +static void d3d12_state_object_set_association_data(struct d3d12_state_object_association *association, + const D3D12_STATE_SUBOBJECT *object) +{ + union + { + const D3D12_RAYTRACING_PIPELINE_CONFIG1 *pipeline_config1; + const D3D12_GLOBAL_ROOT_SIGNATURE *global_root_signature; + const D3D12_RAYTRACING_PIPELINE_CONFIG *pipeline_config; + const D3D12_LOCAL_ROOT_SIGNATURE *local_root_signature; + const D3D12_RAYTRACING_SHADER_CONFIG *shader_config; + } types; + + switch (object->Type) + { + case D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE: + association->kind = VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE; + types.global_root_signature = object->pDesc; + association->root_signature = + impl_from_ID3D12RootSignature(types.global_root_signature->pGlobalRootSignature); + break; + + case D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE: + association->kind = VKD3D_SHADER_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE; + types.local_root_signature = object->pDesc; + association->root_signature = + impl_from_ID3D12RootSignature(types.local_root_signature->pLocalRootSignature); + break; + + case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG: + association->kind = VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_SHADER_CONFIG; + types.shader_config = object->pDesc; + association->shader_config = *types.shader_config; + break; + + case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG1: + association->kind = VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1; + types.pipeline_config1 = object->pDesc; + association->pipeline_config = *types.pipeline_config1; + break; + + case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG: + association->kind = VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1; + types.pipeline_config = object->pDesc; + association->pipeline_config.MaxTraceRecursionDepth = types.pipeline_config->MaxTraceRecursionDepth; + association->pipeline_config.Flags = 0; + break; + + default: + assert(0 && "Unreachable."); + break; + } +} + +static HRESULT d3d12_state_object_parse_subobject(struct d3d12_state_object *object, + const D3D12_STATE_SUBOBJECT *obj, + struct d3d12_state_object_pipeline_data *data, + unsigned int association_priority) +{ + unsigned int i; + HRESULT hr; + + switch (obj->Type) + { + case D3D12_STATE_SUBOBJECT_TYPE_STATE_OBJECT_CONFIG: + { + /* TODO: We might have to do global object assignment similar to SHADER_CONFIG / PIPELINE_CONFIG, + * but STATE_OBJECT_CONFIG doesn't change any functionality or compatibility rules really, + * so just append flags. */ + const uint32_t supported_flags = + D3D12_STATE_OBJECT_FLAG_ALLOW_EXTERNAL_DEPENDENCIES_ON_LOCAL_DEFINITIONS | + D3D12_STATE_OBJECT_FLAG_ALLOW_STATE_OBJECT_ADDITIONS; + const D3D12_STATE_OBJECT_CONFIG *object_config = obj->pDesc; + object->flags |= object_config->Flags; + if (object->flags & ~supported_flags) + { + FIXME("Object config flag #%x is not supported.\n", object->flags); + return E_INVALIDARG; + } + break; + } + + case D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE: + case D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE: + { + /* LOCAL_ROOT_SIGNATURE and GLOBAL_ROOT_SIGNATURE alias. */ + const D3D12_LOCAL_ROOT_SIGNATURE *rs = obj->pDesc; + + /* 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. */ + vkd3d_array_reserve((void **)&data->associations, &data->associations_size, + data->associations_count + 1, + sizeof(*data->associations)); + + /* Root signatures being exported to NULL takes priority as the default local RS. + * They do however, take precedence over DXIL exported subobjects ... */ + data->associations[data->associations_count].export = NULL; + data->associations[data->associations_count].kind = + obj->Type == D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE ? + VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE : + VKD3D_SHADER_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE; + data->associations[data->associations_count].root_signature = + impl_from_ID3D12RootSignature(rs->pLocalRootSignature); + data->associations[data->associations_count].priority = association_priority; + data->associations_count++; + break; + } + + case D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY: + { + const D3D12_DXIL_LIBRARY_DESC *lib = obj->pDesc; + if (vkd3d_shader_dxil_append_library_entry_points_and_subobjects(lib, data->dxil_libraries_count, + &data->entry_points, &data->entry_points_size, + &data->entry_points_count, + &data->subobjects, &data->subobjects_size, + &data->subobjects_count) != VKD3D_OK) + { + ERR("Failed to parse DXIL library.\n"); + return E_OUTOFMEMORY; + } + vkd3d_array_reserve((void**)&data->dxil_libraries, &data->dxil_libraries_size, + data->dxil_libraries_count + 1, sizeof(*data->dxil_libraries)); + data->dxil_libraries[data->dxil_libraries_count++] = lib; + break; + } + + case D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP: + { + const D3D12_HIT_GROUP_DESC *group = obj->pDesc; + vkd3d_array_reserve((void**)&data->hit_groups, &data->hit_groups_size, + data->hit_groups_count + 1, sizeof(*data->hit_groups)); + data->hit_groups[data->hit_groups_count++] = group; + break; + } + + case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG: + { + const D3D12_RAYTRACING_SHADER_CONFIG *config = obj->pDesc; + + vkd3d_array_reserve((void **)&data->associations, &data->associations_size, + data->associations_count + 1, + sizeof(*data->associations)); + + data->associations[data->associations_count].kind = VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_SHADER_CONFIG; + data->associations[data->associations_count].priority = association_priority; + data->associations[data->associations_count].shader_config = *config; + data->associations[data->associations_count].export = NULL; + data->associations_count++; + break; + } + + case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG: + { + const D3D12_RAYTRACING_PIPELINE_CONFIG *pipeline_config = obj->pDesc; + + vkd3d_array_reserve((void **)&data->associations, &data->associations_size, + data->associations_count + 1, + sizeof(*data->associations)); + + data->associations[data->associations_count].kind = VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1; + data->associations[data->associations_count].priority = association_priority; + data->associations[data->associations_count].pipeline_config.MaxTraceRecursionDepth = + pipeline_config->MaxTraceRecursionDepth; + data->associations[data->associations_count].pipeline_config.Flags = 0; + data->associations[data->associations_count].export = NULL; + data->associations_count++; + break; + } + + case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG1: + { + const D3D12_RAYTRACING_PIPELINE_CONFIG1 *pipeline_config = obj->pDesc; + + vkd3d_array_reserve((void **)&data->associations, &data->associations_size, + data->associations_count + 1, + sizeof(*data->associations)); + + data->associations[data->associations_count].kind = VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1; + data->associations[data->associations_count].priority = association_priority; + data->associations[data->associations_count].pipeline_config = *pipeline_config; + data->associations[data->associations_count].export = NULL; + data->associations_count++; + break; + } + + case D3D12_STATE_SUBOBJECT_TYPE_DXIL_SUBOBJECT_TO_EXPORTS_ASSOCIATION: + { + const D3D12_DXIL_SUBOBJECT_TO_EXPORTS_ASSOCIATION *association = obj->pDesc; + unsigned int num_associations = max(association->NumExports, 1); + const struct vkd3d_shader_library_subobject *subobject; + unsigned int root_signature_index = 0; + + for (i = 0; i < data->subobjects_count; i++) + { + if (vkd3d_export_strequal_mixed(association->SubobjectToAssociate, data->subobjects[i].name)) + break; + + if (data->subobjects[i].kind == VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE || + data->subobjects[i].kind == VKD3D_SHADER_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE) + { + root_signature_index++; + } + } + + if (i == data->subobjects_count) + { + ERR("Cannot find subobject %s.\n", debugstr_w(association->SubobjectToAssociate)); + return E_INVALIDARG; + } + + subobject = &data->subobjects[i]; + + vkd3d_array_reserve((void **)&data->associations, &data->associations_size, + data->associations_count + num_associations, + sizeof(*data->associations)); + + for (i = 0; i < num_associations; i++) + { + switch (subobject->kind) + { + case VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE: + case VKD3D_SHADER_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE: + data->associations[data->associations_count].root_signature = + data->subobject_root_signatures[root_signature_index]; + break; + + case VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1: + data->associations[data->associations_count].pipeline_config = subobject->data.pipeline_config; + break; + + case VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_SHADER_CONFIG: + data->associations[data->associations_count].shader_config = subobject->data.shader_config; + break; + + default: + ERR("Unexpected type %u for DXIL -> object association.\n", subobject->kind); + return E_INVALIDARG; + } + + data->associations[data->associations_count].kind = subobject->kind; + data->associations[data->associations_count].export = + association->NumExports ? association->pExports[i] : NULL; + + if (association_priority == VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT && + association->NumExports) + { + data->associations[data->associations_count].priority = VKD3D_ASSOCIATION_PRIORITY_EXPLICIT; + } + else if (association_priority == VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT) + { + data->associations[data->associations_count].priority = VKD3D_ASSOCIATION_PRIORITY_EXPLICIT_DEFAULT; + } + else if (association->NumExports) + { + data->associations[data->associations_count].priority = + VKD3D_ASSOCIATION_PRIORITY_DXIL_SUBOBJECT_ASSIGNMENT_EXPLICIT; + } + else + { + data->associations[data->associations_count].priority = + VKD3D_ASSOCIATION_PRIORITY_DXIL_SUBOBJECT_ASSIGNMENT_DEFAULT; + } + + data->associations_count++; + } + + break; + } + + case D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION: + { + const D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION *association = obj->pDesc; + unsigned int num_associations = max(association->NumExports, 1); + + vkd3d_array_reserve((void **)&data->associations, &data->associations_size, + data->associations_count + num_associations, + sizeof(*data->associations)); + + switch (association->pSubobjectToAssociate->Type) + { + case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG: + case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG: + case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG1: + case D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE: + case D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE: + { + for (i = 0; i < num_associations; i++) + { + data->associations[data->associations_count].export = + association->NumExports ? association->pExports[i] : NULL; + d3d12_state_object_set_association_data(&data->associations[data->associations_count], + association->pSubobjectToAssociate); + data->associations[data->associations_count].priority = association->NumExports ? + VKD3D_ASSOCIATION_PRIORITY_EXPLICIT : + VKD3D_ASSOCIATION_PRIORITY_EXPLICIT_DEFAULT; + data->associations_count++; + } + break; + } + + default: + FIXME("Got unsupported subobject association type %u.\n", association->pSubobjectToAssociate->Type); + return E_INVALIDARG; + } + break; + } + + case D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION: + { + const D3D12_EXISTING_COLLECTION_DESC *collection = obj->pDesc; + struct d3d12_state_object *library_state; + library_state = impl_from_ID3D12StateObject(collection->pExistingCollection); + if (FAILED(hr = d3d12_state_object_add_collection(library_state, data, + collection->pExports, collection->NumExports))) + { + return hr; + } + break; + } + + case D3D12_STATE_SUBOBJECT_TYPE_NODE_MASK: + /* Just ignore this. It's irrelevant for us. */ + break; + + default: + FIXME("Unrecognized subobject type: %u.\n", obj->Type); + return E_INVALIDARG; + } + + return S_OK; +} + static HRESULT d3d12_state_object_parse_subobjects(struct d3d12_state_object *object, const D3D12_STATE_OBJECT_DESC *desc, struct d3d12_state_object *parent, struct d3d12_state_object_pipeline_data *data) { - unsigned int i, j; + struct d3d12_root_signature *root_signature; + unsigned int i; HRESULT hr; if (parent && FAILED(hr = d3d12_state_object_add_collection(parent, data, NULL, 0))) return hr; + /* Make sure all state has been parsed. Ignore DXIL subobject associations for now. + * We'll have to parse subobjects first. */ for (i = 0; i < desc->NumSubobjects; i++) { const D3D12_STATE_SUBOBJECT *obj = &desc->pSubobjects[i]; - switch (obj->Type) + if (obj->Type != D3D12_STATE_SUBOBJECT_TYPE_DXIL_SUBOBJECT_TO_EXPORTS_ASSOCIATION && + obj->Type != D3D12_STATE_SUBOBJECT_TYPE_NODE_MASK) { - case D3D12_STATE_SUBOBJECT_TYPE_STATE_OBJECT_CONFIG: - { - const uint32_t supported_flags = - D3D12_STATE_OBJECT_FLAG_ALLOW_EXTERNAL_DEPENDENCIES_ON_LOCAL_DEFINITIONS | - D3D12_STATE_OBJECT_FLAG_ALLOW_STATE_OBJECT_ADDITIONS; - const D3D12_STATE_OBJECT_CONFIG *object_config = obj->pDesc; - object->flags = object_config->Flags; - if (object->flags & ~supported_flags) - { - FIXME("Object config flag #%x is not supported.\n", object->flags); - return E_INVALIDARG; - } - break; - } - - case D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE: - { - const D3D12_GLOBAL_ROOT_SIGNATURE *rs = obj->pDesc; - struct d3d12_root_signature *new_rs; - struct d3d12_root_signature *old_rs; - - new_rs = impl_from_ID3D12RootSignature(rs->pGlobalRootSignature); - old_rs = data->global_root_signature; - - if (new_rs && old_rs && new_rs->compatibility_hash != old_rs->compatibility_hash) - { - /* Simplicity for now. */ - FIXME("More than one unique global root signature is used.\n"); - return E_INVALIDARG; - } - - if (!data->global_root_signature) - data->global_root_signature = new_rs; - break; - } - - case D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE: - { - const D3D12_LOCAL_ROOT_SIGNATURE *rs = obj->pDesc; - /* 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 = impl_from_ID3D12RootSignature(rs->pLocalRootSignature); - break; - } - - case D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY: - { - const D3D12_DXIL_LIBRARY_DESC *lib = obj->pDesc; - if (vkd3d_shader_dxil_append_library_entry_points_and_subobjects(lib, data->dxil_libraries_count, - &data->entry_points, &data->entry_points_size, - &data->entry_points_count, - &data->subobjects, &data->subobjects_size, - &data->subobjects_count) != VKD3D_OK) - { - ERR("Failed to parse DXIL library.\n"); - return E_OUTOFMEMORY; - } - vkd3d_array_reserve((void**)&data->dxil_libraries, &data->dxil_libraries_size, - data->dxil_libraries_count + 1, sizeof(*data->dxil_libraries)); - data->dxil_libraries[data->dxil_libraries_count++] = lib; - break; - } - - case D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP: - { - const D3D12_HIT_GROUP_DESC *group = obj->pDesc; - vkd3d_array_reserve((void**)&data->hit_groups, &data->hit_groups_size, - data->hit_groups_count + 1, sizeof(*data->hit_groups)); - data->hit_groups[data->hit_groups_count++] = group; - break; - } - - case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG: - { - if (data->shader_config && memcmp(data->shader_config, obj->pDesc, sizeof(*data->shader_config)) != 0) - { - ERR("RAYTRACING_SHADER_CONFIG must match if multiple objects are present.\n"); - return E_INVALIDARG; - } - data->shader_config = obj->pDesc; - break; - } - - case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG: - { - const D3D12_RAYTRACING_PIPELINE_CONFIG *pipeline_config; - D3D12_RAYTRACING_PIPELINE_CONFIG1 config1; - - pipeline_config = obj->pDesc; - config1.Flags = 0; - config1.MaxTraceRecursionDepth = pipeline_config->MaxTraceRecursionDepth; - - if (data->has_pipeline_config && - memcmp(&data->pipeline_config, &config1, sizeof(config1)) != 0) - { - ERR("RAYTRACING_PIPELINE_CONFIG must match if multiple objects are present.\n"); - return E_INVALIDARG; - } - data->has_pipeline_config = true; - data->pipeline_config = config1; - break; - } - - case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG1: - { - const D3D12_RAYTRACING_PIPELINE_CONFIG1 *pipeline_config = obj->pDesc; - if (data->has_pipeline_config && - memcmp(&data->pipeline_config, pipeline_config, sizeof(*pipeline_config)) != 0) - { - ERR("RAYTRACING_PIPELINE_CONFIG1 must match if multiple objects are present.\n"); - return E_INVALIDARG; - } - data->has_pipeline_config = true; - data->pipeline_config = *pipeline_config; - 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; - - switch (association->pSubobjectToAssociate->Type) - { - /* These are irrelevant. There can only be one unique config, - * and what can happen here is that app redundantly assigns the same config. - * The associated object must be part of the PSO anyways, so it should be safe to ignore - * here. */ - case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG: - case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG: - case D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE: - break; - - case D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE: - { - 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 = - 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 = - impl_from_ID3D12RootSignature(local_rs->pLocalRootSignature); - } - break; - } - - default: - FIXME("Got unsupported subobject association type %u.\n", association->pSubobjectToAssociate->Type); - return E_INVALIDARG; - } - break; - } - - case D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION: - { - const D3D12_EXISTING_COLLECTION_DESC *collection = obj->pDesc; - struct d3d12_state_object *library_state; - library_state = impl_from_ID3D12StateObject(collection->pExistingCollection); - if (FAILED(hr = d3d12_state_object_add_collection(library_state, data, - collection->pExports, collection->NumExports))) - { - return hr; - } - break; - } - - case D3D12_STATE_SUBOBJECT_TYPE_NODE_MASK: - /* Just ignore this. It's irrelevant for us. */ - break; - - default: - FIXME("Unrecognized subobject type: %u.\n", obj->Type); - return E_INVALIDARG; + if (FAILED(hr = d3d12_state_object_parse_subobject(object, obj, data, + VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT))) + return hr; } } - if (!data->has_pipeline_config) + /* Make sure all child state has been parsed. */ + for (i = 0; i < data->subobjects_count; i++) { - ERR("Must have pipeline config.\n"); - return E_INVALIDARG; + D3D12_GLOBAL_ROOT_SIGNATURE obj_root_signature; + D3D12_STATE_SUBOBJECT obj; + obj.pDesc = NULL; + + switch (data->subobjects[i].kind) + { + case VKD3D_SHADER_SUBOBJECT_KIND_STATE_OBJECT_CONFIG: + obj.Type = D3D12_STATE_SUBOBJECT_TYPE_STATE_OBJECT_CONFIG; + obj.pDesc = &data->subobjects[i].data.object_config; + break; + + case VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_SHADER_CONFIG: + obj.Type = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG; + obj.pDesc = &data->subobjects[i].data.shader_config; + break; + + case VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1: + obj.Type = D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG1; + obj.pDesc = &data->subobjects[i].data.pipeline_config; + break; + + case VKD3D_SHADER_SUBOBJECT_KIND_HIT_GROUP: + obj.Type = D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP; + obj.pDesc = &data->subobjects[i].data.hit_group; + break; + + case VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE: + case VKD3D_SHADER_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE: + /* No DXBC header here, just raw root signature binary. */ + if (FAILED(hr = d3d12_root_signature_create_raw(object->device, + data->subobjects[i].data.payload.data, + data->subobjects[i].data.payload.size, &root_signature))) + return hr; + + d3d12_root_signature_inc_ref(root_signature); + ID3D12RootSignature_Release(&root_signature->ID3D12RootSignature_iface); + + obj_root_signature.pGlobalRootSignature = &root_signature->ID3D12RootSignature_iface; + obj.Type = data->subobjects[i].kind == VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE ? + D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE : + D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE; + obj.pDesc = &obj_root_signature; + + vkd3d_array_reserve((void**)&data->subobject_root_signatures, &data->subobject_root_signatures_size, + data->subobject_root_signatures_count + 1, sizeof(*data->subobject_root_signatures)); + data->subobject_root_signatures[data->subobject_root_signatures_count++] = root_signature; + break; + + default: + break; + } + + if (obj.pDesc && FAILED(hr = d3d12_state_object_parse_subobject( + object, &obj, data, VKD3D_ASSOCIATION_PRIORITY_DXIL_SUBOBJECT))) + return hr; } - if (!data->shader_config) + for (i = 0; i < desc->NumSubobjects; i++) { - ERR("Must have shader config.\n"); - return E_INVALIDARG; + const D3D12_STATE_SUBOBJECT *obj = &desc->pSubobjects[i]; + /* Now we can parse DXIL subobject -> export associations. */ + if (obj->Type == D3D12_STATE_SUBOBJECT_TYPE_DXIL_SUBOBJECT_TO_EXPORTS_ASSOCIATION) + { + if (FAILED(hr = d3d12_state_object_parse_subobject(object, obj, data, + VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT))) + return hr; + } + } + + /* Finally, parse subobject version of DXIL subobject to export. */ + for (i = 0; i < data->subobjects_count; i++) + { + if (data->subobjects[i].kind == VKD3D_SHADER_SUBOBJECT_KIND_SUBOBJECT_TO_EXPORTS_ASSOCIATION) + { + D3D12_STATE_SUBOBJECT obj; + obj.Type = D3D12_STATE_SUBOBJECT_TYPE_DXIL_SUBOBJECT_TO_EXPORTS_ASSOCIATION; + obj.pDesc = &data->subobjects[i].data.association; + if (FAILED(hr = d3d12_state_object_parse_subobject(object, &obj, data, + VKD3D_ASSOCIATION_PRIORITY_DXIL_SUBOBJECT))) + return hr; + } } return S_OK; @@ -882,63 +1110,149 @@ static VkDeviceSize d3d12_state_object_pipeline_data_compute_default_stack_size( return pipeline_stack_size; } -static struct d3d12_root_signature *d3d12_state_object_find_associated_root_signature_entry( - struct d3d12_state_object_pipeline_data *data, - const struct vkd3d_shader_library_entry_point *entry) +static bool d3d12_state_object_association_data_equal(const struct d3d12_state_object_association *a, + const struct d3d12_state_object_association *b) { - size_t i; - for (i = 0; i < data->associations_count; i++) - if (vkd3d_export_equal(data->associations[i].export, entry)) - return data->associations[i].root_signature; - return NULL; -} - -static struct d3d12_root_signature *d3d12_state_object_find_associated_root_signature_export( - struct d3d12_state_object_pipeline_data *data, LPCWSTR export) -{ - size_t i; - for (i = 0; i < data->associations_count; i++) - if (vkd3d_export_strequal(data->associations[i].export, export)) - return data->associations[i].root_signature; - return NULL; -} - -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) -{ - const D3D12_HIT_GROUP_DESC *hit_group; - struct d3d12_root_signature *rs; - size_t i; - - rs = d3d12_state_object_find_associated_root_signature_entry(data, entry); - - /* If we didn't find an association for this entry point, we might have an association - * in a hit group export. - * FIXME: Is it possible to have multiple hit groups, all referring to same entry point, while using - * different root signatures for the different instances of the entry point? :| */ - for (i = 0; i < data->hit_groups_count && !rs; i++) + /* Normalize dummy root signatures. */ + if (a && (a->kind == VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE || + a->kind == VKD3D_SHADER_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE)) { - hit_group = data->hit_groups[i]; - if (vkd3d_export_equal(hit_group->ClosestHitShaderImport, entry) || - vkd3d_export_equal(hit_group->AnyHitShaderImport, entry) || - vkd3d_export_equal(hit_group->IntersectionShaderImport, entry)) + if (!a->root_signature || a->root_signature->compatibility_hash == 0) + a = NULL; + } + + if (b && (b->kind == VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE || + b->kind == VKD3D_SHADER_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE)) + { + if (!b->root_signature || b->root_signature->compatibility_hash == 0) + b = NULL; + } + + if (!a && !b) + return true; + if ((!!a) != (!!b)) + return false; + if (a->kind != b->kind) + return false; + + switch (a->kind) + { + case VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1: + return memcmp(&a->pipeline_config, &b->pipeline_config, sizeof(a->pipeline_config)) == 0; + case VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_SHADER_CONFIG: + return memcmp(&a->shader_config, &b->shader_config, sizeof(a->shader_config)) == 0; + case VKD3D_SHADER_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE: + case VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE: + if (!a->root_signature && !b->root_signature) + return true; + if ((!!a->root_signature) != (!!b->root_signature)) + return false; + return a->root_signature->compatibility_hash == b->root_signature->compatibility_hash; + + default: + break; + } + + return false; +} + +static struct d3d12_state_object_association *d3d12_state_object_find_association( + enum vkd3d_shader_subobject_kind kind, + struct d3d12_state_object_pipeline_data *data, + const struct vkd3d_shader_library_entry_point *entry, + LPCWSTR export) +{ + struct d3d12_state_object_association *hit_group_association = NULL; + struct d3d12_state_object_association *association = NULL; + const D3D12_HIT_GROUP_DESC *hit_group; + bool conflict = false; + bool match; + size_t i; + + for (i = 0; i < data->associations_count; i++) + { + if (data->associations[i].kind != kind) + continue; + if (association && data->associations[i].priority < association->priority) + continue; + + if (data->associations[i].export) { - rs = d3d12_state_object_find_associated_root_signature_export(data, hit_group->HitGroupExport); + if (entry) + match = vkd3d_export_equal(data->associations[i].export, entry); + else + match = vkd3d_export_strequal(data->associations[i].export, export); + } + else + match = true; + + if (match) + { + if (!association || data->associations[i].priority > association->priority) + { + association = &data->associations[i]; + conflict = false; + } + else if (!d3d12_state_object_association_data_equal(association, &data->associations[i])) + { + /* We might get a higher priority match later that makes this conflict irrelevant. */ + conflict = true; + } } } - if (!rs) + hit_group_association = NULL; + + /* If we didn't find an association for this entry point, we might have an association + * in a hit group export. Alternatively, we might have a higher priority association which is only + * set for the hit group. + * FIXME: Is it possible to have multiple hit groups, all referring to same entry point, while using + * different root signatures for the different instances of the entry point? :| */ + if (entry && (entry->stage == VK_SHADER_STAGE_ANY_HIT_BIT_KHR || + entry->stage == VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR || + entry->stage == VK_SHADER_STAGE_INTERSECTION_BIT_KHR)) { - if (data->high_priority_local_root_signature) - rs = data->high_priority_local_root_signature; - else if (data->low_priority_local_root_signature) - rs = data->low_priority_local_root_signature; - else - rs = NULL; + for (i = 0; i < data->hit_groups_count; i++) + { + hit_group = data->hit_groups[i]; + + match = vkd3d_export_equal(hit_group->ClosestHitShaderImport, entry) || + vkd3d_export_equal(hit_group->AnyHitShaderImport, entry) || + vkd3d_export_equal(hit_group->IntersectionShaderImport, entry); + + if (match) + { + hit_group_association = d3d12_state_object_find_association( + kind, data, NULL, hit_group->HitGroupExport); + + /* Accept hit group association if it has a higher priority, otherwise tie-break to the export itself. */ + if (hit_group_association && hit_group_association->priority > association->priority) + { + association = hit_group_association; + conflict = false; + break; + } + } + } } - return rs; + if (conflict) + { + ERR("Conflicting root signatures defined for same export.\n"); + return NULL; + } + + return association; +} + +static struct d3d12_root_signature *d3d12_state_object_pipeline_data_get_root_signature( + enum vkd3d_shader_subobject_kind kind, + struct d3d12_state_object_pipeline_data *data, + const struct vkd3d_shader_library_entry_point *entry) +{ + struct d3d12_state_object_association *association; + association = d3d12_state_object_find_association(kind, data, entry, NULL); + return association ? association->root_signature : NULL; } static HRESULT d3d12_state_object_get_group_handles(struct d3d12_state_object *object, @@ -1073,6 +1387,98 @@ static void d3d12_state_object_append_local_static_samplers( *out_vk_bindings_count = vk_bindings_count; } +static bool d3d12_state_object_pipeline_data_find_global_state_object( + struct d3d12_state_object_pipeline_data *data, + enum vkd3d_shader_subobject_kind kind, + const struct d3d12_state_object_association **out_association) +{ + const struct d3d12_state_object_association *association = NULL; + const struct d3d12_state_object_association *candidate; + size_t i; + + /* All inherited associations have to agree. */ + for (i = 0; i < data->associations_count; i++) + { + if (data->associations[i].kind == kind && + data->associations[i].priority == VKD3D_ASSOCIATION_PRIORITY_INHERITED_COLLECTION) + { + if (!association) + association = &data->associations[i]; + else if (!d3d12_state_object_association_data_equal(association, &data->associations[i])) + { + ERR("Mismatch in inherited associations for kind %u.\n", kind); + return false; + } + } + } + + for (i = 0; i < data->entry_points_count; i++) + { + candidate = d3d12_state_object_find_association(kind, data, &data->entry_points[i], NULL); + + if (!association) + { + association = candidate; + } + else if (!d3d12_state_object_association_data_equal(association, candidate)) + { + /* To hypothetically support this for global root signatures, + * we'd have to partition any RTPSO into N VkPipelines and select + * the appropriate pipeline at DispatchRays() time based on the currently bound root signature ... + * Leave this as a TODO until we observe that applications rely on this esoteric behavior. */ + if (kind == VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE) + FIXME("Two entry points declare different global root signatures. This is currently unsupported.\n"); + else + ERR("Mismatch in inherited associations for kind %u.\n", kind); + return false; + } + } + + *out_association = association; + return true; +} + +static bool d3d12_state_object_pipeline_data_find_global_state_objects( + struct d3d12_state_object_pipeline_data *data, struct d3d12_root_signature **out_root_signature, + D3D12_RAYTRACING_SHADER_CONFIG *out_shader_config, + D3D12_RAYTRACING_PIPELINE_CONFIG1 *out_pipeline_config) +{ + const struct d3d12_state_object_association *pipeline_config = NULL; + const struct d3d12_state_object_association *root_signature = NULL; + const struct d3d12_state_object_association *shader_config = NULL; + + if (!d3d12_state_object_pipeline_data_find_global_state_object(data, + VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE, &root_signature)) + return false; + + if (!d3d12_state_object_pipeline_data_find_global_state_object(data, + VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1, &pipeline_config)) + return false; + + if (!d3d12_state_object_pipeline_data_find_global_state_object(data, + VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_SHADER_CONFIG, &shader_config)) + return false; + + if (!pipeline_config) + { + ERR("No pipeline config was declared or inherited. This is required state.\n"); + return false; + } + + if (!shader_config) + { + ERR("No shader config was declared or inherited. This is required state.\n"); + return false; + } + + /* If every entry point declares no root signature, this is still okay. */ + *out_root_signature = root_signature ? root_signature->root_signature : NULL; + *out_pipeline_config = pipeline_config->pipeline_config; + *out_shader_config = shader_config->shader_config; + + return true; +} + static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *object, struct d3d12_state_object_pipeline_data *data) { @@ -1085,11 +1491,13 @@ static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *ob VkRayTracingPipelineCreateInfoKHR pipeline_create_info; struct vkd3d_shader_resource_binding *local_bindings; struct vkd3d_shader_compile_arguments compile_args; + D3D12_RAYTRACING_PIPELINE_CONFIG1 pipeline_config; struct d3d12_state_object_collection *collection; VkPipelineDynamicStateCreateInfo dynamic_state; struct vkd3d_shader_library_entry_point *entry; struct d3d12_root_signature *global_signature; struct d3d12_root_signature *local_signature; + D3D12_RAYTRACING_SHADER_CONFIG shader_config; const struct D3D12_HIT_GROUP_DESC *hit_group; struct d3d12_state_object_identifier *export; VkPipelineLibraryCreateInfoKHR library_info; @@ -1120,7 +1528,9 @@ static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *ob shader_interface_info.stage = VK_SHADER_STAGE_ALL; shader_interface_info.xfb_info = NULL; - global_signature = data->global_root_signature; + if (!d3d12_state_object_pipeline_data_find_global_state_objects(data, + &global_signature, &shader_config, &pipeline_config)) + return E_INVALIDARG; if (global_signature) { @@ -1163,7 +1573,8 @@ static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *ob { entry = &data->entry_points[i]; - local_signature = d3d12_state_object_pipeline_data_get_local_root_signature(data, entry); + local_signature = d3d12_state_object_pipeline_data_get_root_signature( + VKD3D_SHADER_SUBOBJECT_KIND_LOCAL_ROOT_SIGNATURE, data, entry); local_bindings = NULL; if (local_signature) @@ -1475,11 +1886,11 @@ static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *ob pipeline_create_info.pLibraryInfo = &library_info; pipeline_create_info.pLibraryInterface = &interface_create_info; pipeline_create_info.pDynamicState = &dynamic_state; - pipeline_create_info.maxPipelineRayRecursionDepth = data->pipeline_config.MaxTraceRecursionDepth; + pipeline_create_info.maxPipelineRayRecursionDepth = pipeline_config.MaxTraceRecursionDepth; - if (data->pipeline_config.Flags & D3D12_RAYTRACING_PIPELINE_FLAG_SKIP_TRIANGLES) + if (pipeline_config.Flags & D3D12_RAYTRACING_PIPELINE_FLAG_SKIP_TRIANGLES) pipeline_create_info.flags |= VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR; - if (data->pipeline_config.Flags & D3D12_RAYTRACING_PIPELINE_FLAG_SKIP_PROCEDURAL_PRIMITIVES) + if (pipeline_config.Flags & D3D12_RAYTRACING_PIPELINE_FLAG_SKIP_PROCEDURAL_PRIMITIVES) pipeline_create_info.flags |= VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR; library_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR; @@ -1489,16 +1900,16 @@ static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *ob interface_create_info.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR; interface_create_info.pNext = NULL; - interface_create_info.maxPipelineRayPayloadSize = data->shader_config->MaxPayloadSizeInBytes; - interface_create_info.maxPipelineRayHitAttributeSize = data->shader_config->MaxAttributeSizeInBytes; + interface_create_info.maxPipelineRayPayloadSize = shader_config.MaxPayloadSizeInBytes; + interface_create_info.maxPipelineRayHitAttributeSize = shader_config.MaxAttributeSizeInBytes; - if (data->pipeline_config.MaxTraceRecursionDepth > + if (pipeline_config.MaxTraceRecursionDepth > object->device->device_info.ray_tracing_pipeline_properties.maxRayRecursionDepth) { /* We cannot do anything about this, since we let sub-minspec devices through, * and this content actually tries to use recursion. */ ERR("MaxTraceRecursionDepth %u exceeds device limit of %u.\n", - data->pipeline_config.MaxTraceRecursionDepth, + pipeline_config.MaxTraceRecursionDepth, object->device->device_info.ray_tracing_pipeline_properties.maxRayRecursionDepth); return E_INVALIDARG; } @@ -1554,8 +1965,8 @@ static HRESULT d3d12_state_object_compile_pipeline(struct d3d12_state_object *ob data->exports_size = 0; data->exports_count = 0; - object->shader_config = *data->shader_config; - object->pipeline_config = data->pipeline_config; + object->shader_config = shader_config; + object->pipeline_config = pipeline_config; /* Spec says we need to hold a reference to the collection object, but it doesn't show up in API, * so we must assume private reference. */