Parse DXIL subobjects.

Hans-Kristian Arntzen 2 months ago
parent df2be95553
commit 0ac32b5f3c
  1. 2
      include/vkd3d_shader.h
  2. 429
      libs/vkd3d/raytracing_pipeline.c

@ -811,6 +811,8 @@ struct vkd3d_shader_library_subobject
D3D12_RAYTRACING_PIPELINE_CONFIG1 pipeline_config;
D3D12_RAYTRACING_SHADER_CONFIG shader_config;
D3D12_STATE_OBJECT_CONFIG object_config;
/* Duped strings because API wants wide strings for no good reason. */
D3D12_HIT_GROUP_DESC hit_group;
struct

@ -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;
@ -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);
@ -442,9 +450,10 @@ static void d3d12_state_object_pipeline_data_cleanup(struct d3d12_state_object_p
#define VKD3D_ASSOCIATION_PRIORITY_INHERITED_COLLECTION 0
#define VKD3D_ASSOCIATION_PRIORITY_DXIL_SUBOBJECT 1
#define VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT 2
#define VKD3D_ASSOCIATION_PRIORITY_EXPLICIT_DEFAULT 3
#define VKD3D_ASSOCIATION_PRIORITY_EXPLICIT 4
#define VKD3D_ASSOCIATION_PRIORITY_DXIL_SUBOBJECT_ASSIGNMENT 2
#define VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT 3
#define VKD3D_ASSOCIATION_PRIORITY_EXPLICIT_DEFAULT 4
#define VKD3D_ASSOCIATION_PRIORITY_EXPLICIT 5
static HRESULT d3d12_state_object_add_collection(
struct d3d12_state_object *collection,
@ -546,214 +555,290 @@ static void d3d12_state_object_set_association_data(struct d3d12_state_object_as
}
}
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)
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, j;
unsigned int i;
HRESULT hr;
if (parent && FAILED(hr = d3d12_state_object_add_collection(parent, data, NULL, 0)))
return hr;
for (i = 0; i < desc->NumSubobjects; i++)
switch (obj->Type)
{
const D3D12_STATE_SUBOBJECT *obj = &desc->pSubobjects[i];
switch (obj->Type)
case D3D12_STATE_SUBOBJECT_TYPE_STATE_OBJECT_CONFIG:
{
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)
{
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;
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 =
VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT;
data->associations_count++;
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:
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)
{
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;
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_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;
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));
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 = VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT;
data->associations[data->associations_count].shader_config = *config;
data->associations[data->associations_count].export = NULL;
data->associations_count++;
break;
}
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 = VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT;
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_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;
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));
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 = VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT;
data->associations[data->associations_count].pipeline_config = *pipeline_config;
data->associations[data->associations_count].export = NULL;
data->associations_count++;
break;
}
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_SUBOBJECT_TO_EXPORTS_ASSOCIATION:
{
const D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION *association = obj->pDesc;
case D3D12_STATE_SUBOBJECT_TYPE_SUBOBJECT_TO_EXPORTS_ASSOCIATION:
{
const D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION *association = obj->pDesc;
switch (association->pSubobjectToAssociate->Type)
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:
{
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:
if (association->NumExports)
{
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];
d3d12_state_object_set_association_data(&data->associations[data->associations_count],
association->pSubobjectToAssociate);
data->associations[data->associations_count].priority = VKD3D_ASSOCIATION_PRIORITY_EXPLICIT;
data->associations_count++;
}
}
else
{
vkd3d_array_reserve((void **)&data->associations, &data->associations_size,
data->associations_count + 1,
sizeof(*data->associations));
vkd3d_array_reserve((void **)&data->associations, &data->associations_size,
data->associations_count + association->NumExports,
sizeof(*data->associations));
/* Local root signatures being exported to NULL takes priority as the default local RS. */
data->associations[data->associations_count].export = NULL;
for (i = 0; i < association->NumExports; i++)
{
data->associations[data->associations_count].export = association->pExports[i];
d3d12_state_object_set_association_data(&data->associations[data->associations_count],
association->pSubobjectToAssociate);
data->associations[data->associations_count].priority = VKD3D_ASSOCIATION_PRIORITY_EXPLICIT_DEFAULT;
data->associations[data->associations_count].priority = VKD3D_ASSOCIATION_PRIORITY_EXPLICIT;
data->associations_count++;
}
break;
}
default:
FIXME("Got unsupported subobject association type %u.\n", association->pSubobjectToAssociate->Type);
return E_INVALIDARG;
else
{
vkd3d_array_reserve((void **)&data->associations, &data->associations_size,
data->associations_count + 1,
sizeof(*data->associations));
/* Local root signatures being exported to NULL takes priority as the default local RS. */
data->associations[data->associations_count].export = NULL;
d3d12_state_object_set_association_data(&data->associations[data->associations_count],
association->pSubobjectToAssociate);
data->associations[data->associations_count].priority = VKD3D_ASSOCIATION_PRIORITY_EXPLICIT_DEFAULT;
data->associations_count++;
}
break;
}
break;
default:
FIXME("Got unsupported subobject association type %u.\n", association->pSubobjectToAssociate->Type);
return E_INVALIDARG;
}
break;
}
case D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION:
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)))
{
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;
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)
{
struct d3d12_root_signature *root_signature;
unsigned int i;
HRESULT hr;
case D3D12_STATE_SUBOBJECT_TYPE_NODE_MASK:
/* Just ignore this. It's irrelevant for us. */
if (parent && FAILED(hr = d3d12_state_object_add_collection(parent, data, NULL, 0)))
return hr;
/* First, parse the DXIL libraries so every subobject is parsed. */
for (i = 0; i < desc->NumSubobjects; i++)
{
const D3D12_STATE_SUBOBJECT *obj = &desc->pSubobjects[i];
if (obj->Type == D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY)
if (FAILED(hr = d3d12_state_object_parse_subobject(object, obj, data, VKD3D_ASSOCIATION_PRIORITY_DECLARED_STATE_OBJECT)))
return hr;
}
/* Make sure all child state has been parsed. */
for (i = 0; i < data->subobjects_count; i++)
{
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:
if (FAILED(hr = d3d12_root_signature_create(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:
FIXME("Unrecognized subobject type: %u.\n", obj->Type);
return E_INVALIDARG;
break;
}
if (obj.pDesc && FAILED(hr = d3d12_state_object_parse_subobject(
object, &obj, data, VKD3D_ASSOCIATION_PRIORITY_DXIL_SUBOBJECT)))
return hr;
}
return S_OK;

Loading…
Cancel
Save