From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxbc.c | 1 + libs/vkd3d-shader/dxil.c | 158 ++++++++++++++++++++++- libs/vkd3d-shader/vkd3d_shader_private.h | 3 + 3 files changed, 161 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index a9a7aefe..6f47560f 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -550,6 +550,7 @@ void free_shader_desc(struct vkd3d_shader_desc *desc) shader_signature_cleanup(&desc->input_signature); shader_signature_cleanup(&desc->output_signature); shader_signature_cleanup(&desc->patch_constant_signature); + vkd3d_free(desc->descriptors); }
int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc, diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 4bfebea2..4d127515 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -2821,6 +2821,11 @@ static bool sm6_metadata_value_is_node(const struct sm6_metadata_value *m) return m && m->type == VKD3D_METADATA_NODE; }
+static bool sm6_metadata_value_is_value(const struct sm6_metadata_value *m) +{ + return m && m->type == VKD3D_METADATA_VALUE; +} + static bool sm6_metadata_value_is_string(const struct sm6_metadata_value *m) { return m && m->type == VKD3D_METADATA_STRING; @@ -3375,11 +3380,161 @@ static const struct sm6_metadata_value *sm6_parser_find_named_metadata(struct sm return NULL; }
+static bool sm6_parser_resources_load_register_range(struct sm6_parser *sm6, + const struct sm6_metadata_node *node, struct vkd3d_shader_register_range *range) +{ + unsigned int size; + + if (!sm6_metadata_value_is_value(node->operands[1])) + { + WARN("Resource data type is not a value.\n"); + return false; + } + if (!sm6_type_is_pointer(node->operands[1]->value_type)) + { + WARN("Resource type is not a pointer.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "Resource metadata value type is not a pointer."); + } + + if (!sm6_metadata_get_uint_value(sm6, node->operands[3], &range->space)) + { + WARN("Failed to load register space.\n"); + return false; + } + if (!sm6_metadata_get_uint_value(sm6, node->operands[4], &range->first)) + { + WARN("Failed to load register first.\n"); + return false; + } + if (!sm6_metadata_get_uint_value(sm6, node->operands[5], &size)) + { + WARN("Failed to load register range size.\n"); + return false; + } + if (!size || (size != UINT_MAX && !vkd3d_bound_range(range->first, size, UINT_MAX))) + { + WARN("Invalid register range, first %u, size %u.\n", range->first, size); + return false; + } + range->last = (size == UINT_MAX) ? UINT_MAX : range->first + size - 1; + + return true; +} + +static enum vkd3d_result sm6_parser_resources_load_cbv(struct sm6_parser *sm6, + const struct sm6_metadata_node *node, struct vkd3d_shader_descriptor_info1 *d) +{ + if (node->operand_count < 7) + { + WARN("Invalid operand count %u.\n", node->operand_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, + "Invalid operand count %u for a CBV descriptor.", node->operand_count); + return VKD3D_ERROR_INVALID_SHADER; + } + if (node->operand_count > 7 && node->operands[7]) + { + WARN("Ignoring %u extra operands.\n", node->operand_count - 7); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Ignoring %u extra operands for a CBV descriptor.", node->operand_count - 7); + } + + d->resource_type = VKD3D_SHADER_RESOURCE_BUFFER; + d->resource_data_type = VKD3D_SHADER_RESOURCE_DATA_UINT; + + if (!sm6_metadata_get_uint_value(sm6, node->operands[6], &d->buffer_size)) + { + WARN("Failed to load buffer size.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "Constant buffer size metadata value is not an integer."); + return VKD3D_ERROR_INVALID_SHADER; + } + + return VKD3D_OK; +} + +static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6, + enum vkd3d_shader_descriptor_type type, const struct sm6_metadata_node *descriptor_node, + size_t *descriptor_capacity) +{ + struct vkd3d_shader_desc *desc = &sm6->p.shader_desc; + struct vkd3d_shader_register_range range; + struct vkd3d_shader_descriptor_info1 *d; + const struct sm6_metadata_node *node; + const struct sm6_metadata_value *m; + enum vkd3d_result ret; + unsigned int i; + + for (i = 0; i < descriptor_node->operand_count; ++i) + { + m = descriptor_node->operands[i]; + if (!sm6_metadata_value_is_node(m)) + { + WARN("Resource descriptor is not a node.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "Resource descriptor is not a metadata node."); + return VKD3D_ERROR_INVALID_SHADER; + } + + if (!vkd3d_array_reserve((void **)&desc->descriptors, descriptor_capacity, + desc->descriptor_count + 1, sizeof(*desc->descriptors))) + { + ERR("Failed to allocate descriptor array.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory allocating the descriptor array."); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + + d = &desc->descriptors[desc->descriptor_count]; + memset(d, 0, sizeof(*d)); + d->type = type; + + node = m->u.node; + + switch (type) + { + case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV: + if ((ret = sm6_parser_resources_load_cbv(sm6, node, d)) < 0) + return ret; + break; + default: + FIXME("Unsupported descriptor type %u.\n", type); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "Resource descriptor type %u is unsupported.", type); + return VKD3D_ERROR_INVALID_SHADER; + } + + if (!sm6_metadata_get_uint_value(sm6, node->operands[0], &d->register_id)) + { + WARN("Failed to load resource id.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "Resource id metadata value is not an integer."); + return VKD3D_ERROR_INVALID_SHADER; + } + + if (!sm6_parser_resources_load_register_range(sm6, node, &range)) + { + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "Resource register range is invalid."); + return VKD3D_ERROR_INVALID_SHADER; + } + d->register_space = range.space; + d->register_index = range.first; + d->count = (range.last == UINT_MAX) ? UINT_MAX : range.last - range.first + 1; + + ++desc->descriptor_count; + } + + return VKD3D_OK; +} + static enum vkd3d_result sm6_parser_resources_init(struct sm6_parser *sm6) { const struct sm6_metadata_value *m = sm6_parser_find_named_metadata(sm6, "dx.resources"); enum vkd3d_shader_descriptor_type type; const struct sm6_metadata_node *node; + size_t descriptor_capacity = 0; + enum vkd3d_result ret;
if (!m) return VKD3D_OK; @@ -3406,7 +3561,8 @@ static enum vkd3d_result sm6_parser_resources_init(struct sm6_parser *sm6) return VKD3D_ERROR_INVALID_SHADER; }
- FIXME("Descriptor info is unhandled.\n"); + if ((ret = sm6_parser_descriptor_type_init(sm6, type, m->u.node, &descriptor_capacity)) < 0) + return ret; }
return VKD3D_OK; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index cd5cc593..1305e4af 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -932,6 +932,9 @@ struct vkd3d_shader_desc { uint32_t used, external; } flat_constant_count[3]; + + struct vkd3d_shader_descriptor_info1 *descriptors; + size_t descriptor_count; };
struct vkd3d_shader_register_semantic