|
|
|
@ -366,11 +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; |
|
|
|
|
|
|
|
|
|
/* Map 1:1 with VkShaderModule. */ |
|
|
|
|
struct vkd3d_shader_library_entry_point *entry_points; |
|
|
|
|
size_t entry_points_size; |
|
|
|
@ -456,41 +451,28 @@ static HRESULT d3d12_state_object_add_collection( |
|
|
|
|
return E_OUTOFMEMORY; |
|
|
|
|
|
|
|
|
|
if (!vkd3d_array_reserve((void **)&data->associations, &data->associations_size, |
|
|
|
|
data->associations_count + 1, sizeof(*data->associations))) |
|
|
|
|
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 we end up with mismatches. */ |
|
|
|
|
* 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; |
|
|
|
@ -506,6 +488,59 @@ 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_subobjects(struct d3d12_state_object *object, |
|
|
|
|
const D3D12_STATE_OBJECT_DESC *desc, |
|
|
|
|
struct d3d12_state_object *parent, |
|
|
|
@ -547,9 +582,10 @@ static HRESULT d3d12_state_object_parse_subobjects(struct d3d12_state_object *ob |
|
|
|
|
* 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, |
|
|
|
|
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; |
|
|
|
@ -592,46 +628,51 @@ static HRESULT d3d12_state_object_parse_subobjects(struct d3d12_state_object *ob |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
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 = 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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG: |
|
|
|
|
{ |
|
|
|
|
const D3D12_RAYTRACING_PIPELINE_CONFIG *pipeline_config; |
|
|
|
|
D3D12_RAYTRACING_PIPELINE_CONFIG1 config1; |
|
|
|
|
const D3D12_RAYTRACING_PIPELINE_CONFIG *pipeline_config = obj->pDesc; |
|
|
|
|
|
|
|
|
|
pipeline_config = obj->pDesc; |
|
|
|
|
config1.Flags = 0; |
|
|
|
|
config1.MaxTraceRecursionDepth = pipeline_config->MaxTraceRecursionDepth; |
|
|
|
|
vkd3d_array_reserve((void **)&data->associations, &data->associations_size, |
|
|
|
|
data->associations_count + 1, |
|
|
|
|
sizeof(*data->associations)); |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
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_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; |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -639,54 +680,39 @@ static HRESULT d3d12_state_object_parse_subobjects(struct d3d12_state_object *ob |
|
|
|
|
{ |
|
|
|
|
const D3D12_SUBOBJECT_TO_EXPORTS_ASSOCIATION *association = obj->pDesc; |
|
|
|
|
|
|
|
|
|
/* This aliases trivially with GLOBAL_ROOT_SIGNATURE. */ |
|
|
|
|
const D3D12_LOCAL_ROOT_SIGNATURE *root_signature; |
|
|
|
|
|
|
|
|
|
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: |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG1: |
|
|
|
|
case D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE: |
|
|
|
|
case D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE: |
|
|
|
|
{ |
|
|
|
|
root_signature = association->pSubobjectToAssociate->pDesc; |
|
|
|
|
if (association->NumExports) |
|
|
|
|
{ |
|
|
|
|
vkd3d_array_reserve((void **) &data->associations, &data->associations_size, |
|
|
|
|
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].kind = |
|
|
|
|
association->pSubobjectToAssociate->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(root_signature->pLocalRootSignature); |
|
|
|
|
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, |
|
|
|
|
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; |
|
|
|
|
data->associations[data->associations_count].kind = |
|
|
|
|
association->pSubobjectToAssociate->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(root_signature->pLocalRootSignature); |
|
|
|
|
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++; |
|
|
|
|
} |
|
|
|
@ -723,18 +749,6 @@ static HRESULT d3d12_state_object_parse_subobjects(struct d3d12_state_object *ob |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!data->has_pipeline_config) |
|
|
|
|
{ |
|
|
|
|
ERR("Must have pipeline config.\n"); |
|
|
|
|
return E_INVALIDARG; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!data->shader_config) |
|
|
|
|
{ |
|
|
|
|
ERR("Must have shader config.\n"); |
|
|
|
|
return E_INVALIDARG; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return S_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -897,6 +911,33 @@ static VkDeviceSize d3d12_state_object_pipeline_data_compute_default_stack_size( |
|
|
|
|
return pipeline_stack_size; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool d3d12_state_object_association_data_equal(const struct d3d12_state_object_association *a, |
|
|
|
|
const struct d3d12_state_object_association *b) |
|
|
|
|
{ |
|
|
|
|
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, |
|
|
|
@ -932,8 +973,7 @@ static struct d3d12_state_object_association *d3d12_state_object_find_associatio |
|
|
|
|
association = &data->associations[i]; |
|
|
|
|
conflict = false; |
|
|
|
|
} |
|
|
|
|
else if (association->root_signature->compatibility_hash != |
|
|
|
|
data->associations[i].root_signature->compatibility_hash) |
|
|
|
|
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; |
|
|
|
@ -1119,72 +1159,96 @@ 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_root_signature( |
|
|
|
|
struct d3d12_state_object_pipeline_data *data, struct d3d12_root_signature **out_root_signature) |
|
|
|
|
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) |
|
|
|
|
{ |
|
|
|
|
struct d3d12_state_object_association *association; |
|
|
|
|
struct d3d12_root_signature *root_signature; |
|
|
|
|
const struct d3d12_state_object_association *association = NULL; |
|
|
|
|
const struct d3d12_state_object_association *candidate; |
|
|
|
|
size_t i; |
|
|
|
|
|
|
|
|
|
root_signature = NULL; |
|
|
|
|
/* 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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* All exports must conform to the same global root signature. */ |
|
|
|
|
for (i = 0; i < data->entry_points_count; i++) |
|
|
|
|
{ |
|
|
|
|
association = d3d12_state_object_find_association( |
|
|
|
|
VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE, data, |
|
|
|
|
candidate = d3d12_state_object_find_association(kind, data, |
|
|
|
|
&data->entry_points[i], NULL); |
|
|
|
|
|
|
|
|
|
if (!root_signature) |
|
|
|
|
if (!association) |
|
|
|
|
{ |
|
|
|
|
root_signature = association ? association->root_signature : NULL; |
|
|
|
|
association = candidate; |
|
|
|
|
} |
|
|
|
|
else if (!association || !association->root_signature || |
|
|
|
|
root_signature->compatibility_hash != association->root_signature->compatibility_hash) |
|
|
|
|
else if (!d3d12_state_object_association_data_equal(association, candidate)) |
|
|
|
|
{ |
|
|
|
|
/* To hypothetically support this, we'd have to partition any RTPSO into N VkPipelines and select
|
|
|
|
|
/* 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. */ |
|
|
|
|
FIXME("Two entry points declare different global root signatures. This is currently unsupported.\n"); |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* If every entry point declares no root signature, this is still okay. */ |
|
|
|
|
*out_root_signature = association ? association->root_signature : NULL; |
|
|
|
|
*out_association = association; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool d3d12_state_object_pipeline_data_validate_global_root_signature( |
|
|
|
|
struct d3d12_state_object_pipeline_data *data, |
|
|
|
|
struct d3d12_root_signature *global_signature) |
|
|
|
|
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) |
|
|
|
|
{ |
|
|
|
|
/* Validate that all imported collections share the same global root signature. */ |
|
|
|
|
bool mismatch; |
|
|
|
|
size_t i; |
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < data->collections_count; i++) |
|
|
|
|
{ |
|
|
|
|
mismatch = false; |
|
|
|
|
if (!d3d12_state_object_pipeline_data_find_global_state_object(data, |
|
|
|
|
VKD3D_SHADER_SUBOBJECT_KIND_GLOBAL_ROOT_SIGNATURE, &root_signature)) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
if (!global_signature && data->collections[i].object->global_root_signature->compatibility_hash != 0) |
|
|
|
|
{ |
|
|
|
|
/* We can match against default root signature. */ |
|
|
|
|
mismatch = true; |
|
|
|
|
} |
|
|
|
|
else if (global_signature && global_signature->compatibility_hash != |
|
|
|
|
data->collections[i].object->global_root_signature->compatibility_hash) |
|
|
|
|
{ |
|
|
|
|
mismatch = true; |
|
|
|
|
} |
|
|
|
|
if (!d3d12_state_object_pipeline_data_find_global_state_object(data, |
|
|
|
|
VKD3D_SHADER_SUBOBJECT_KIND_RAYTRACING_PIPELINE_CONFIG1, &pipeline_config)) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
if (mismatch) |
|
|
|
|
{ |
|
|
|
|
FIXME("Mismatch in global root signatures for export and collection. This is currently unsupported.\n"); |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1200,11 +1264,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; |
|
|
|
@ -1235,9 +1301,8 @@ 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; |
|
|
|
|
|
|
|
|
|
if (!d3d12_state_object_pipeline_data_find_global_root_signature(data, &global_signature)) |
|
|
|
|
return E_INVALIDARG; |
|
|
|
|
if (!d3d12_state_object_pipeline_data_validate_global_root_signature(data, global_signature)) |
|
|
|
|
if (!d3d12_state_object_pipeline_data_find_global_state_objects(data, |
|
|
|
|
&global_signature, &shader_config, &pipeline_config)) |
|
|
|
|
return E_INVALIDARG; |
|
|
|
|
|
|
|
|
|
if (global_signature) |
|
|
|
@ -1594,11 +1659,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; |
|
|
|
@ -1608,16 +1673,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; |
|
|
|
|
} |
|
|
|
@ -1673,8 +1738,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. */ |
|
|
|
|