Goes atop MR 403 and 388. The last four commits belong to this MR.
-- v7: vkd3d-shader: Clone descriptor scan info from struct vkd3d_shader_desc. vkd3d-shader/dxil: Read CBV descriptors. vkd3d-shader/dxil: Validate the descriptor list metadata nodes. vkd3d-shader/spirv: Align constant buffer sizes to 16 bytes. vkd3d-shader/dxil: Read DXIL compute shader thread group dimensions. vkd3d-shader/dxil: Read DXIL global flags. vkd3d-shader: Define more global flags. vkd3d-shader/dxil: Handle multi-row signature elements. vkd3d-shader/dxil: Handle signature element additional tag/value pairs. vkd3d-shader/dxil: Read the DXIL input and output signatures. vkd3d-shader/dxil: Validate the entry point info.
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 112 +++++++++++++++++++++-- libs/vkd3d-shader/vkd3d_shader_private.h | 2 + 2 files changed, 105 insertions(+), 9 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 9e591af25..fdcb84013 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -358,6 +358,8 @@ struct sm6_parser struct sm6_symbol *global_symbols; size_t global_symbol_count;
+ const char *entry_point; + struct vkd3d_shader_dst_param *output_params; struct vkd3d_shader_dst_param *input_params;
@@ -2710,6 +2712,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_string(const struct sm6_metadata_value *m) +{ + return m && m->type == VKD3D_METADATA_STRING; +} + static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, struct sm6_function *function) { @@ -3135,6 +3142,77 @@ static enum vkd3d_result sm6_parser_metadata_init(struct sm6_parser *sm6, const return VKD3D_OK; }
+static const struct sm6_metadata_value *sm6_parser_find_named_metadata(struct sm6_parser *sm6, const char *name) +{ + const struct sm6_metadata_node *node; + unsigned int i; + + for (i = 0; i < sm6->named_metadata_count; ++i) + { + if (strcmp(sm6->named_metadata[i].name, name)) + continue; + + node = sm6->named_metadata[i].value.u.node; + if (!node->operand_count) + return NULL; + if (node->operand_count > 1) + { + FIXME("Ignoring %u extra operands for %s.\n", node->operand_count - 1, name); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Ignoring %u extra operands for metadata node %s.", node->operand_count - 1, name); + } + return node->operands[0]; + } + + return NULL; +} + +static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6) +{ + const struct sm6_metadata_value *m = sm6_parser_find_named_metadata(sm6, "dx.entryPoints"); + const struct sm6_metadata_node *entry_node = m ? m->u.node : NULL; + const struct sm6_value *value; + + if (!entry_node || entry_node->operand_count < 2 || !(m = entry_node->operands[0])) + { + WARN("No entry point definition found.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_ENTRY_POINT, + "No entry point definition found in the metadata."); + return VKD3D_ERROR_INVALID_SHADER; + } + + if (m->type != VKD3D_METADATA_VALUE) + { + WARN("Entry point definition is not a value.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_ENTRY_POINT, + "Entry point definition is not a metadata value."); + return VKD3D_ERROR_INVALID_SHADER; + } + + value = m->u.value; + if (!sm6_value_is_function_dcl(value)) + { + WARN("Entry point value is not a function definition.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_ENTRY_POINT, + "Entry point metadata value does not contain a function definition."); + return VKD3D_ERROR_INVALID_SHADER; + } + + sm6->entry_point = value->u.function.name; + if (!sm6_metadata_value_is_string(entry_node->operands[1]) + || ascii_strcasecmp(sm6->entry_point, entry_node->operands[1]->u.string_value)) + { + WARN("Entry point function name %s mismatch.\n", sm6->entry_point); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH, + "Entry point function name %s does not match the name in metadata.", sm6->entry_point); + } + + sm6_parser_init_input_signature(sm6, &sm6->p.shader_desc.input_signature); + sm6_parser_init_output_signature(sm6, &sm6->p.shader_desc.output_signature); + + return VKD3D_OK; +} + static void sm6_metadata_value_destroy(struct sm6_metadata_value *m) { switch (m->type) @@ -3245,6 +3323,15 @@ static const struct vkd3d_shader_parser_ops sm6_parser_ops = .parser_destroy = sm6_parser_destroy, };
+static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6, const char *name) +{ + size_t i; + for (i = 0; i < sm6->function_count; ++i) + if (!ascii_strcasecmp(sm6->functions[i].declaration->u.function.name, name)) + return &sm6->functions[i]; + return NULL; +} + static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t *byte_code, size_t byte_code_size, const char *source_name, struct vkd3d_shader_message_context *message_context) { @@ -3257,6 +3344,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t enum bitcode_block_abbreviation abbr; struct vkd3d_shader_version version; struct dxil_block *block; + struct sm6_function *fn; enum vkd3d_result ret; unsigned int i, j;
@@ -3469,8 +3557,8 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t return ret; }
- sm6_parser_init_output_signature(sm6, output_signature); - sm6_parser_init_input_signature(sm6, input_signature); + if ((ret = sm6_parser_entry_point_init(sm6)) < 0) + return ret;
if ((ret = sm6_parser_module_init(sm6, &sm6->root_block, 0)) < 0) { @@ -3494,14 +3582,20 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
sm6->p.shader_desc.ssa_count = sm6->ssa_next_id;
- for (i = 0; i < sm6->function_count; ++i) + if (!(fn = sm6_parser_get_function(sm6, sm6->entry_point))) { - if (!sm6_block_emit_instructions(sm6->functions[i].blocks[0], sm6)) - { - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory emitting shader instructions."); - return VKD3D_ERROR_OUT_OF_MEMORY; - } + WARN("Failed to find entry point %s.\n", sm6->entry_point); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_ENTRY_POINT, + "The definition of the entry point function '%s' was not found.", sm6->entry_point); + return VKD3D_ERROR_INVALID_SHADER; + } + + assert(sm6->function_count == 1); + if (!sm6_block_emit_instructions(fn->blocks[0], sm6)) + { + vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory emitting shader instructions."); + return VKD3D_ERROR_OUT_OF_MEMORY; }
dxil_block_destroy(&sm6->root_block); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 060647a68..a0140c674 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -177,6 +177,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND = 8012, VKD3D_SHADER_ERROR_DXIL_UNHANDLED_INTRINSIC = 8013, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA = 8014, + VKD3D_SHADER_ERROR_DXIL_INVALID_ENTRY_POINT = 8015,
VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301, @@ -184,6 +185,7 @@ enum vkd3d_shader_error VKD3D_SHADER_WARNING_DXIL_INVALID_MODULE_LENGTH = 8303, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS = 8304, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH = 8305, + VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH = 8306,
VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001,
From: Conor McCarthy cmccarthy@codeweavers.com
These can differ from the DXBC signatures by having multiple rows, and load/store instructions reference them by id instead of register index. --- libs/vkd3d-shader/dxbc.c | 2 + libs/vkd3d-shader/dxil.c | 358 ++++++++++++++++++++++- libs/vkd3d-shader/vkd3d_shader_private.h | 4 + 3 files changed, 360 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index dbbf8a5c4..a9a7aefe8 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -435,6 +435,8 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s else e[i].min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE;
+ e[i].interpolation_mode = VKD3DSIM_NONE; + TRACE("Stream: %u, semantic: %s, semantic idx: %u, sysval_semantic %#x, " "type %u, register idx: %u, use_mask %#x, input_mask %#x, precision %u.\n", e[i].stream_index, debugstr_a(e[i].semantic_name), e[i].semantic_index, e[i].sysval_semantic, diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index fdcb84013..48fbcaf13 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -154,6 +154,66 @@ enum bitcode_value_symtab_code VST_CODE_BBENTRY = 2, };
+enum dxil_component_type +{ + COMPONENT_TYPE_INVALID = 0, + COMPONENT_TYPE_I1 = 1, + COMPONENT_TYPE_I16 = 2, + COMPONENT_TYPE_U16 = 3, + COMPONENT_TYPE_I32 = 4, + COMPONENT_TYPE_U32 = 5, + COMPONENT_TYPE_I64 = 6, + COMPONENT_TYPE_U64 = 7, + COMPONENT_TYPE_F16 = 8, + COMPONENT_TYPE_F32 = 9, + COMPONENT_TYPE_F64 = 10, + COMPONENT_TYPE_SNORMF16 = 11, + COMPONENT_TYPE_UNORMF16 = 12, + COMPONENT_TYPE_SNORMF32 = 13, + COMPONENT_TYPE_UNORMF32 = 14, + COMPONENT_TYPE_SNORMF64 = 15, + COMPONENT_TYPE_UNORMF64 = 16, + COMPONENT_TYPE_PACKEDS8X32 = 17, + COMPONENT_TYPE_PACKEDU8X32 = 18, +}; + +enum dxil_semantic_kind +{ + SEMANTIC_KIND_ARBITRARY = 0, + SEMANTIC_KIND_VERTEXID = 1, + SEMANTIC_KIND_INSTANCEID = 2, + SEMANTIC_KIND_POSITION = 3, + SEMANTIC_KIND_RTARRAYINDEX = 4, + SEMANTIC_KIND_VIEWPORTARRAYINDEX = 5, + SEMANTIC_KIND_CLIPDISTANCE = 6, + SEMANTIC_KIND_CULLDISTANCE = 7, + SEMANTIC_KIND_OUTPUTCONTROLPOINTID = 8, + SEMANTIC_KIND_DOMAINLOCATION = 9, + SEMANTIC_KIND_PRIMITIVEID = 10, + SEMANTIC_KIND_GSINSTANCEID = 11, + SEMANTIC_KIND_SAMPLEINDEX = 12, + SEMANTIC_KIND_ISFRONTFACE = 13, + SEMANTIC_KIND_COVERAGE = 14, + SEMANTIC_KIND_INNERCOVERAGE = 15, + SEMANTIC_KIND_TARGET = 16, + SEMANTIC_KIND_DEPTH = 17, + SEMANTIC_KIND_DEPTHLESSEQUAL = 18, + SEMANTIC_KIND_DEPTHGREATEREQUAL = 19, + SEMANTIC_KIND_STENCILREF = 20, + SEMANTIC_KIND_DISPATCHTHREADID = 21, + SEMANTIC_KIND_GROUPID = 22, + SEMANTIC_KIND_GROUPINDEX = 23, + SEMANTIC_KIND_GROUPTHREADID = 24, + SEMANTIC_KIND_TESSFACTOR = 25, + SEMANTIC_KIND_INSIDETESSFACTOR = 26, + SEMANTIC_KIND_VIEWID = 27, + SEMANTIC_KIND_BARYCENTRICS = 28, + SEMANTIC_KIND_SHADINGRATE = 29, + SEMANTIC_KIND_CULLPRIMITIVE = 30, + SEMANTIC_KIND_COUNT = 31, + SEMANTIC_KIND_INVALID = SEMANTIC_KIND_COUNT, +}; + enum dx_intrinsic_opcode { DX_LOAD_INPUT = 4, @@ -2357,8 +2417,7 @@ static void sm6_parser_emit_signature(struct sm6_parser *sm6, const struct shade param = &ins->declaration.dst; }
- /* TODO: set the interpolation mode when signatures are loaded from DXIL metadata. */ - ins->flags = (handler_idx == VKD3DSIH_DCL_INPUT_PS) ? VKD3DSIM_LINEAR_NOPERSPECTIVE : 0; + ins->flags = e->interpolation_mode; *param = params[i]; } } @@ -2717,6 +2776,25 @@ static bool sm6_metadata_value_is_string(const struct sm6_metadata_value *m) return m && m->type == VKD3D_METADATA_STRING; }
+static bool sm6_metadata_get_uint_value(const struct sm6_parser *sm6, + const struct sm6_metadata_value *m, unsigned int *u) +{ + const struct sm6_value *value; + + if (!m || m->type != VKD3D_METADATA_VALUE) + return false; + + value = m->u.value; + if (!sm6_value_is_constant(value)) + return false; + if (!sm6_type_is_integer(value->type)) + return false; + + *u = register_get_uint_value(&value->u.reg); + + return true; +} + static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, struct sm6_function *function) { @@ -3142,6 +3220,67 @@ static enum vkd3d_result sm6_parser_metadata_init(struct sm6_parser *sm6, const return VKD3D_OK; }
+static enum vkd3d_shader_component_type vkd3d_component_type_from_dxil_component_type(enum dxil_component_type type) +{ + switch (type) + { + case COMPONENT_TYPE_I1: + return VKD3D_SHADER_COMPONENT_BOOL; + case COMPONENT_TYPE_I16: + case COMPONENT_TYPE_I32: + return VKD3D_SHADER_COMPONENT_INT; + case COMPONENT_TYPE_U16: + case COMPONENT_TYPE_U32: + return VKD3D_SHADER_COMPONENT_UINT; + case COMPONENT_TYPE_F16: + case COMPONENT_TYPE_F32: + case COMPONENT_TYPE_SNORMF32: + case COMPONENT_TYPE_UNORMF32: + return VKD3D_SHADER_COMPONENT_FLOAT; + case COMPONENT_TYPE_F64: + case COMPONENT_TYPE_SNORMF64: + case COMPONENT_TYPE_UNORMF64: + return VKD3D_SHADER_COMPONENT_DOUBLE; + default: + FIXME("Unhandled component type %u.\n", type); + return VKD3D_SHADER_COMPONENT_UINT; + } +} + +static enum vkd3d_shader_minimum_precision minimum_precision_from_dxil_component_type(enum dxil_component_type type) +{ + switch (type) + { + case COMPONENT_TYPE_F16: + return VKD3D_SHADER_MINIMUM_PRECISION_FLOAT_16; + case COMPONENT_TYPE_I16: + return VKD3D_SHADER_MINIMUM_PRECISION_INT_16; + case COMPONENT_TYPE_U16: + return VKD3D_SHADER_MINIMUM_PRECISION_UINT_16; + default: + return VKD3D_SHADER_MINIMUM_PRECISION_NONE; + } +} + +static const enum vkd3d_shader_sysval_semantic sysval_semantic_table[] = +{ + [SEMANTIC_KIND_ARBITRARY] = VKD3D_SHADER_SV_NONE, + [SEMANTIC_KIND_POSITION] = VKD3D_SHADER_SV_POSITION, + [SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_NONE, +}; + +static enum vkd3d_shader_sysval_semantic sysval_semantic_from_dxil_semantic_kind(enum dxil_semantic_kind kind) +{ + if (kind < ARRAY_SIZE(sysval_semantic_table)) + { + return sysval_semantic_table[kind]; + } + else + { + return VKD3D_SHADER_SV_NONE; + } +} + static const struct sm6_metadata_value *sm6_parser_find_named_metadata(struct sm6_parser *sm6, const char *name) { const struct sm6_metadata_node *node; @@ -3167,11 +3306,219 @@ static const struct sm6_metadata_value *sm6_parser_find_named_metadata(struct sm return NULL; }
+static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const struct sm6_metadata_value *m, + struct shader_signature *s) +{ + unsigned int i, j, column_count, operand_count, index; + const struct sm6_metadata_node *node, *element_node; + struct signature_element *elements, *e; + unsigned int values[10]; + + if (!m) + return VKD3D_OK; + + if (!sm6_metadata_value_is_node(m)) + { + WARN("Signature element list is not a node.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element list is not a metadata node."); + return VKD3D_ERROR_INVALID_SHADER; + } + + node = m->u.node; + operand_count = node->operand_count; + + if (!(elements = vkd3d_calloc(operand_count, sizeof(*elements)))) + { + ERR("Failed to allocate %u signature elements.\n", operand_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory allocating %u signature elements.", operand_count); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + + for (i = 0; i < operand_count; ++i) + { + m = node->operands[i]; + + if (!sm6_metadata_value_is_node(m)) + { + WARN("Signature element is not a node.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element is not a metadata node."); + return VKD3D_ERROR_INVALID_SHADER; + } + + element_node = m->u.node; + if (element_node->operand_count < 10) + { + WARN("Invalid operand count %u.\n", element_node->operand_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Invalid signature element operand count %u.", element_node->operand_count); + return VKD3D_ERROR_INVALID_SHADER; + } + if (element_node->operand_count > 11) + { + WARN("Ignoring %u extra operands.\n", element_node->operand_count - 11); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Ignoring %u extra operands for a signature element.", element_node->operand_count - 11); + } + + for (j = 0; j < 10; ++j) + { + /* 1 is the semantic name, 4 is semantic index metadata. */ + if (j == 1 || j == 4) + continue; + if (!sm6_metadata_get_uint_value(sm6, element_node->operands[j], &values[j])) + { + WARN("Failed to load uint value at index %u.\n", j); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element value at index %u is not an integer.", j); + return VKD3D_ERROR_INVALID_SHADER; + } + } + + e = &elements[i]; + + if (values[0] != i) + { + FIXME("Unsupported element id %u not equal to its index %u.\n", values[0], i); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "A non-sequential and non-zero-based element id is not supported."); + return VKD3D_ERROR_INVALID_SHADER; + } + + if (!sm6_metadata_value_is_string(element_node->operands[1])) + { + WARN("Element name is not a string.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element name is not a metadata string."); + return VKD3D_ERROR_INVALID_SHADER; + } + e->semantic_name = element_node->operands[1]->u.string_value; + + /* TODO: load from additional tag/value pairs. */ + e->stream_index = 0; + + e->component_type = vkd3d_component_type_from_dxil_component_type(values[2]); + e->min_precision = minimum_precision_from_dxil_component_type(values[2]); + + j = values[3]; + e->sysval_semantic = sysval_semantic_from_dxil_semantic_kind(j); + if (j != SEMANTIC_KIND_ARBITRARY && j != SEMANTIC_KIND_TARGET && e->sysval_semantic == VKD3D_SHADER_SV_NONE) + { + WARN("Unhandled semantic kind %u.\n", j); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "DXIL semantic kind %u is unhandled.", j); + return VKD3D_ERROR_INVALID_SHADER; + } + + if ((e->interpolation_mode = values[5]) >= VKD3DSIM_COUNT) + { + WARN("Unhandled interpolation mode %u.\n", e->interpolation_mode); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Interpolation mode %u is unhandled.", e->interpolation_mode); + return VKD3D_ERROR_INVALID_SHADER; + } + + e->register_count = values[6]; + column_count = values[7]; + e->register_index = values[8]; + e->target_location = e->register_index; + if (e->register_index > MAX_REG_OUTPUT || e->register_count > MAX_REG_OUTPUT - e->register_index) + { + WARN("Invalid row start %u with row count %u.\n", e->register_index, e->register_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "A signature element starting row of %u with count %u is invalid.", + e->register_index, e->register_count); + return VKD3D_ERROR_INVALID_SHADER; + } + index = values[9]; + if (index >= VKD3D_VEC4_SIZE || column_count > VKD3D_VEC4_SIZE - index) + { + WARN("Invalid column start %u with count %u.\n", index, column_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "A signature element starting column %u with count %u is invalid.", index, column_count); + return VKD3D_ERROR_INVALID_SHADER; + } + + e->mask = vkd3d_write_mask_from_component_count(column_count) << index; + /* TODO: load from additional tag/value pairs. */ + e->used_mask = e->mask; + + m = element_node->operands[4]; + if (!sm6_metadata_value_is_node(m)) + { + WARN("Semantic index list is not a node.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element semantic index list is not a metadata node."); + return VKD3D_ERROR_INVALID_SHADER; + } + + element_node = m->u.node; + for (j = 0; j < element_node->operand_count; ++j) + { + if (!sm6_metadata_get_uint_value(sm6, element_node->operands[j], &index)) + { + WARN("Failed to get semantic index for row %u.\n", j); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element semantic index for row %u is not an integer.", j); + } + else if (!j) + { + e->semantic_index = index; + } + else if (index != e->semantic_index + j) + { + WARN("Semantic index %u for row %u is not of an incrementing sequence.\n", index, j); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element semantic index %u for row %u is not of an incrementing sequence.", index, j); + } + } + } + + vkd3d_free(s->elements); + s->elements = elements; + s->element_count = operand_count; + + return VKD3D_OK; +} + +static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, const struct sm6_metadata_value *m) +{ + enum vkd3d_result ret; + + if (!sm6_metadata_value_is_node(m)) + { + WARN("Signature table is not a node.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature table is not a metadata node."); + return VKD3D_ERROR_INVALID_SHADER; + } + + if (m->u.node->operand_count && (ret = sm6_parser_read_signature(sm6, m->u.node->operands[0], + &sm6->p.shader_desc.input_signature)) < 0) + { + return ret; + } + if (m->u.node->operand_count > 1 && (ret = sm6_parser_read_signature(sm6, m->u.node->operands[1], + &sm6->p.shader_desc.output_signature)) < 0) + { + return ret; + } + /* TODO: patch constant signature in operand 2. */ + + sm6_parser_init_input_signature(sm6, &sm6->p.shader_desc.input_signature); + sm6_parser_init_output_signature(sm6, &sm6->p.shader_desc.output_signature); + + return VKD3D_OK; +} + static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6) { const struct sm6_metadata_value *m = sm6_parser_find_named_metadata(sm6, "dx.entryPoints"); const struct sm6_metadata_node *entry_node = m ? m->u.node : NULL; const struct sm6_value *value; + enum vkd3d_result ret;
if (!entry_node || entry_node->operand_count < 2 || !(m = entry_node->operands[0])) { @@ -3207,8 +3554,11 @@ static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6) "Entry point function name %s does not match the name in metadata.", sm6->entry_point); }
- sm6_parser_init_input_signature(sm6, &sm6->p.shader_desc.input_signature); - sm6_parser_init_output_signature(sm6, &sm6->p.shader_desc.output_signature); + if (entry_node->operand_count >= 3 && (m = entry_node->operands[2]) + && (ret = sm6_parser_signatures_init(sm6, m)) < 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 a0140c674..b5171ba66 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -178,6 +178,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_DXIL_UNHANDLED_INTRINSIC = 8013, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA = 8014, VKD3D_SHADER_ERROR_DXIL_INVALID_ENTRY_POINT = 8015, + VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE = 8016,
VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301, @@ -627,6 +628,8 @@ enum vkd3d_shader_interpolation_mode VKD3DSIM_LINEAR_NOPERSPECTIVE_CENTROID = 5, VKD3DSIM_LINEAR_SAMPLE = 6, VKD3DSIM_LINEAR_NOPERSPECTIVE_SAMPLE = 7, + + VKD3DSIM_COUNT = 8, };
enum vkd3d_shader_global_flags @@ -867,6 +870,7 @@ struct signature_element unsigned int mask; unsigned int used_mask; enum vkd3d_shader_minimum_precision min_precision; + enum vkd3d_shader_interpolation_mode interpolation_mode; /* Register index / location in the target shader. * If SIGNATURE_TARGET_LOCATION_UNUSED, this element should not be written. */ unsigned int target_location;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 84 ++++++++++++++++++++++-- libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 81 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 48fbcaf13..7e3a1257b 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -214,6 +214,14 @@ enum dxil_semantic_kind SEMANTIC_KIND_INVALID = SEMANTIC_KIND_COUNT, };
+enum dxil_element_additional_tag +{ + ADDITIONAL_TAG_STREAM_INDEX = 0, + ADDITIONAL_TAG_GLOBAL_SYMBOL = 1, /* not used */ + ADDITIONAL_TAG_RELADDR_MASK = 2, + ADDITIONAL_TAG_USED_MASK = 3, +}; + enum dx_intrinsic_opcode { DX_LOAD_INPUT = 4, @@ -3306,6 +3314,76 @@ static const struct sm6_metadata_value *sm6_parser_find_named_metadata(struct sm return NULL; }
+static void signature_element_read_additional_element_values(struct signature_element *e, + const struct sm6_metadata_node *node, struct sm6_parser *sm6) +{ + unsigned int i, operand_count, value; + enum dxil_element_additional_tag tag; + + if (node->operand_count < 11 || !node->operands[10]) + return; + + if (!sm6_metadata_value_is_node(node->operands[10])) + { + WARN("Additional values list is not a node.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element additional values list is not a metadata node."); + return; + } + + node = node->operands[10]->u.node; + if (node->operand_count & 1) + { + WARN("Operand count is not even.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Operand count for signature element additional tag/value pairs is not even."); + } + operand_count = node->operand_count & ~1u; + + for (i = 0; i < operand_count; i += 2) + { + if (!sm6_metadata_get_uint_value(sm6, node->operands[i], &tag) + || !sm6_metadata_get_uint_value(sm6, node->operands[i + 1], &value)) + { + WARN("Failed to extract tag/value pair.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element tag/value pair at index %u is not an integer pair.", i); + continue; + } + + switch (tag) + { + case ADDITIONAL_TAG_STREAM_INDEX: + e->stream_index = value; + break; + case ADDITIONAL_TAG_RELADDR_MASK: + /* A mask of components accessed via relative addressing. Seems to replace TPF 'dcl_index_range'. */ + if (value > VKD3DSP_WRITEMASK_ALL) + { + WARN("Invalid relative addressed mask %#x.\n", value); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_INVALID_MASK, + "Mask %#x of relative-addressed components is invalid.", value); + } + break; + case ADDITIONAL_TAG_USED_MASK: + if (value > VKD3DSP_WRITEMASK_ALL) + { + WARN("Invalid used mask %#x.\n", value); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_INVALID_MASK, + "Mask %#x of used components is invalid.", value); + value &= VKD3DSP_WRITEMASK_ALL; + } + e->used_mask = value; + break; + default: + FIXME("Unhandled tag %u, value %u.\n", tag, value); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Tag %#x for signature element additional value %#x is unhandled.", tag, value); + break; + } + } +} + static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const struct sm6_metadata_value *m, struct shader_signature *s) { @@ -3396,9 +3474,6 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const } e->semantic_name = element_node->operands[1]->u.string_value;
- /* TODO: load from additional tag/value pairs. */ - e->stream_index = 0; - e->component_type = vkd3d_component_type_from_dxil_component_type(values[2]); e->min_precision = minimum_precision_from_dxil_component_type(values[2]);
@@ -3442,9 +3517,10 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const }
e->mask = vkd3d_write_mask_from_component_count(column_count) << index; - /* TODO: load from additional tag/value pairs. */ e->used_mask = e->mask;
+ signature_element_read_additional_element_values(e, element_node, sm6); + m = element_node->operands[4]; if (!sm6_metadata_value_is_node(m)) { diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index b5171ba66..2c84cb104 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -187,6 +187,7 @@ enum vkd3d_shader_error VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS = 8304, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH = 8305, VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH = 8306, + VKD3D_SHADER_WARNING_DXIL_INVALID_MASK = 8307,
VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001,
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 15 ++++++++++++--- tests/hlsl/entry-point-semantics.shader_test | 17 +++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 7e3a1257b..47b261949 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -2384,7 +2384,7 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade { struct vkd3d_shader_dst_param *param; const struct signature_element *e; - unsigned int i; + unsigned int i, count;
for (i = 0; i < s->element_count; ++i) { @@ -2392,8 +2392,11 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade
param = ¶ms[i]; dst_param_io_init(param, e, reg_type); - param->reg.idx[0].offset = i; - param->reg.idx_count = 1; + count = 0; + if (e->register_count > 1) + param->reg.idx[count++].offset = 0; + param->reg.idx[count++].offset = i; + param->reg.idx_count = count; } }
@@ -2427,6 +2430,12 @@ static void sm6_parser_emit_signature(struct sm6_parser *sm6, const struct shade
ins->flags = e->interpolation_mode; *param = params[i]; + + if (e->register_count > 1) + { + param->reg.idx[0].rel_addr = NULL; + param->reg.idx[0].offset = e->register_count; + } } }
diff --git a/tests/hlsl/entry-point-semantics.shader_test b/tests/hlsl/entry-point-semantics.shader_test index 6d355ab5c..d177b0376 100644 --- a/tests/hlsl/entry-point-semantics.shader_test +++ b/tests/hlsl/entry-point-semantics.shader_test @@ -84,7 +84,7 @@ float4 main(in apple a) : sv_target
[test] draw quad -todo(sm>=6) probe (0, 0) rgba (10.0, 20.0, 30.0, 40.0) +probe (0, 0) rgba (10.0, 20.0, 30.0, 40.0)
% Arrays of matrices get successive indexes. @@ -101,7 +101,12 @@ float4 main(in apple a) : sv_target
[test] draw quad -todo(sm>=6) probe (0, 0) rgba (10.0, 11.0, 30.0, 31.0) +probe (0, 0) rgba (10.0, 11.0, 30.0, 31.0) + + +% dxcompiler emits correct array addressing. +[require] +shader model < 6.0
% Arrays (even multi-dimensional) of struct elements are allowed. The fields in the different struct @@ -145,6 +150,10 @@ draw quad todo(sm>=6) probe (0, 0) rgba (10.0, 11.0, 20.0, 21.0)
+[require] +% reset requirements + + [pixel shader fail] struct apple { @@ -201,7 +210,7 @@ float4 main(in float4 tex0 : TEXCOORD0, in float4 tex1 : TEXCOORD1) : sv_target
[test] draw quad -todo(sm>=6) probe (0, 0) rgba (1.0, 2.0, 10.0, 20.0) +probe (0, 0) rgba (1.0, 2.0, 10.0, 20.0)
% Output semantics cannot be mapped to more than one value. @@ -272,7 +281,7 @@ float4 main(in float4 a : TEXCOORD0, in float3 b : TEXCOORD1) : sv_target
[test] draw quad -todo(sm>=6) probe (0, 0) rgba (10.0, 11.0, 20.0, 21.0) +probe (0, 0) rgba (10.0, 11.0, 20.0, 21.0)
% In SM4, duplicated input semantics can only have different types if they have the same layout and
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/d3d_asm.c | 9 ++++---- libs/vkd3d-shader/spirv.c | 6 +++--- libs/vkd3d-shader/tpf.c | 2 +- libs/vkd3d-shader/vkd3d_shader_private.h | 27 ++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 566680be7..5a75cf25e 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -391,13 +391,14 @@ static unsigned int shader_get_float_offset(enum vkd3d_shader_register_type regi } }
-static void shader_dump_global_flags(struct vkd3d_d3d_asm_compiler *compiler, uint32_t global_flags) +static void shader_dump_global_flags(struct vkd3d_d3d_asm_compiler *compiler, + enum vkd3d_shader_global_flags global_flags) { unsigned int i;
static const struct { - unsigned int flag; + enum vkd3d_shader_global_flags flag; const char *name; } global_flag_info[] = @@ -423,7 +424,7 @@ static void shader_dump_global_flags(struct vkd3d_d3d_asm_compiler *compiler, ui }
if (global_flags) - vkd3d_string_buffer_printf(&compiler->buffer, "unknown_flags(%#x)", global_flags); + vkd3d_string_buffer_printf(&compiler->buffer, "unknown_flags(%#"PRIx64")", global_flags); }
static void shader_dump_sync_flags(struct vkd3d_d3d_asm_compiler *compiler, uint32_t sync_flags) @@ -1637,7 +1638,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler,
case VKD3DSIH_DCL_GLOBAL_FLAGS: vkd3d_string_buffer_printf(buffer, " "); - shader_dump_global_flags(compiler, ins->flags); + shader_dump_global_flags(compiler, ins->declaration.global_flags); break;
case VKD3DSIH_DCL_HS_MAX_TESSFACTOR: diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 738016029..90f1adeb7 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -5378,7 +5378,7 @@ static size_t spirv_compiler_get_current_function_location(struct spirv_compiler static void spirv_compiler_emit_dcl_global_flags(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { - unsigned int flags = instruction->flags; + enum vkd3d_shader_global_flags flags = instruction->declaration.global_flags;
if (flags & VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL) { @@ -5393,9 +5393,9 @@ static void spirv_compiler_emit_dcl_global_flags(struct spirv_compiler *compiler }
if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS)) - FIXME("Unhandled global flags %#x.\n", flags); + FIXME("Unhandled global flags %#"PRIx64".\n", flags); else - WARN("Unhandled global flags %#x.\n", flags); + WARN("Unhandled global flags %#"PRIx64".\n", flags); }
static void spirv_compiler_emit_temps(struct spirv_compiler *compiler, uint32_t count) diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 5c42a5886..bf4c03c05 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -1092,7 +1092,7 @@ static void shader_sm4_read_dcl_indexable_temp(struct vkd3d_shader_instruction * static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) { - ins->flags = (opcode_token & VKD3D_SM4_GLOBAL_FLAGS_MASK) >> VKD3D_SM4_GLOBAL_FLAGS_SHIFT; + ins->declaration.global_flags = (opcode_token & VKD3D_SM4_GLOBAL_FLAGS_MASK) >> VKD3D_SM4_GLOBAL_FLAGS_SHIFT; }
static void shader_sm5_read_fcall(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 2c84cb104..ab148b3be 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -642,6 +642,32 @@ enum vkd3d_shader_global_flags VKD3DSGF_SKIP_OPTIMIZATION = 0x10, VKD3DSGF_ENABLE_MINIMUM_PRECISION = 0x20, VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS = 0x40, + VKD3DSGF_ENABLE_SHADER_EXTENSIONS = 0x80, /* never emitted? */ + VKD3DSGF_BIND_FOR_DURATION = 0x100, + VKD3DSGF_ENABLE_VP_AND_RT_ARRAY_INDEX = 0x200, + VKD3DSGF_ENABLE_INNER_COVERAGE = 0x400, + VKD3DSGF_ENABLE_STENCIL_REF = 0x800, + VKD3DSGF_ENABLE_TILED_RESOURCE_INTRINSICS = 0x1000, + VKD3DSGF_ENABLE_RELAXED_TYPED_UAV_FORMATS = 0x2000, + VKD3DSGF_ENABLE_LVL_9_COMPARISON_FILTERING = 0x4000, + VKD3DSGF_ENABLE_UP_TO_64_UAVS = 0x8000, + VKD3DSGF_ENABLE_UAVS_AT_EVERY_STAGE = 0x10000, + VKD3DSGF_ENABLE_CS4_RAW_STRUCTURED_BUFFERS = 0x20000, + VKD3DSGF_ENABLE_RASTERIZER_ORDERED_VIEWS = 0x40000, + VKD3DSGF_ENABLE_WAVE_INTRINSICS = 0x80000, + VKD3DSGF_ENABLE_INT64 = 0x100000, + VKD3DSGF_ENABLE_VIEWID = 0x200000, + VKD3DSGF_ENABLE_BARYCENTRICS = 0x400000, + VKD3DSGF_FORCE_NATIVE_LOW_PRECISION = 0x800000, + VKD3DSGF_ENABLE_SHADINGRATE = 0x1000000, + VKD3DSGF_ENABLE_RAYTRACING_TIER_1_1 = 0x2000000, + VKD3DSGF_ENABLE_SAMPLER_FEEDBACK = 0x4000000, + VKD3DSGF_ENABLE_ATOMIC_INT64_ON_TYPED_RESOURCE = 0x8000000, + VKD3DSGF_ENABLE_ATOMIC_INT64_ON_GROUP_SHARED = 0x10000000, + VKD3DSGF_ENABLE_DERIVATIVES_IN_MESH_AND_AMPLIFICATION_SHADERS = 0x20000000, + VKD3DSGF_ENABLE_RESOURCE_DESCRIPTOR_HEAP_INDEXING = 0x40000000, + VKD3DSGF_ENABLE_SAMPLER_DESCRIPTOR_HEAP_INDEXING = 0x80000000, + VKD3DSGF_ENABLE_ATOMIC_INT64_ON_DESCRIPTOR_HEAP_RESOURCE = 0x100000000ull, };
enum vkd3d_shader_sync_flags @@ -1016,6 +1042,7 @@ struct vkd3d_shader_instruction const struct vkd3d_shader_src_param *predicate; union { + enum vkd3d_shader_global_flags global_flags; struct vkd3d_shader_semantic semantic; struct vkd3d_shader_register_semantic register_semantic; struct vkd3d_shader_primitive_type primitive_type;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 118 ++++++++++++++++++++++- libs/vkd3d-shader/vkd3d_shader_private.h | 5 +- 2 files changed, 121 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 47b261949..e24f01324 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -222,6 +222,23 @@ enum dxil_element_additional_tag ADDITIONAL_TAG_USED_MASK = 3, };
+enum dxil_shader_properties_tag +{ + SHADER_PROPERTIES_FLAGS = 0, + SHADER_PROPERTIES_GEOMETRY = 1, + SHADER_PROPERTIES_DOMAIN = 2, + SHADER_PROPERTIES_HULL = 3, + SHADER_PROPERTIES_COMPUTE = 4, + SHADER_PROPERTIES_AUTO_BINDING_SPACE = 5, + SHADER_PROPERTIES_RAY_PAYLOAD_SIZE = 6, + SHADER_PROPERTIES_RAY_ATTRIB_SIZE = 7, + SHADER_PROPERTIES_SHADER_KIND = 8, + SHADER_PROPERTIES_MESH = 9, + SHADER_PROPERTIES_AMPLIFICATION = 10, + SHADER_PROPERTIES_WAVE_SIZE = 11, + SHADER_PROPERTIES_ENTRY_ROOT_SIG = 12, +}; + enum dx_intrinsic_opcode { DX_LOAD_INPUT = 4, @@ -1657,6 +1674,17 @@ static unsigned int register_get_uint_value(const struct vkd3d_shader_register * return reg->u.immconst_uint[0]; }
+static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *reg) +{ + if (!register_is_constant(reg) || !data_type_is_integer(reg->data_type)) + return UINT64_MAX; + + if (reg->dimension == VSIR_DIMENSION_VEC4) + WARN("Returning vec4.x.\n"); + + return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_uint64[0] : reg->u.immconst_uint[0]; +} + static inline bool sm6_value_is_function_dcl(const struct sm6_value *value) { return value->value_type == VALUE_TYPE_FUNCTION; @@ -1755,6 +1783,8 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type return VKD3D_DATA_UINT8; case 32: return VKD3D_DATA_UINT; + case 64: + return VKD3D_DATA_UINT64; default: FIXME("Unhandled width %u.\n", type->u.width); return VKD3D_DATA_UINT; @@ -2812,6 +2842,25 @@ static bool sm6_metadata_get_uint_value(const struct sm6_parser *sm6, return true; }
+static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, + const struct sm6_metadata_value *m, uint64_t *u) +{ + const struct sm6_value *value; + + if (!m || m->type != VKD3D_METADATA_VALUE) + return false; + + value = m->u.value; + if (!sm6_value_is_constant(value)) + return false; + if (!sm6_type_is_integer(value->type)) + return false; + + *u = register_get_uint64_value(&value->u.reg); + + return true; +} + static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, struct sm6_function *function) { @@ -3598,10 +3647,34 @@ static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, cons return VKD3D_OK; }
+static void sm6_parser_emit_global_flags(struct sm6_parser *sm6, const struct sm6_metadata_value *m) +{ + enum vkd3d_shader_global_flags global_flags, mask, rotated_flags; + struct vkd3d_shader_instruction *ins; + + if (!sm6_metadata_get_uint64_value(sm6, m, &global_flags)) + { + WARN("Failed to load global flags.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, + "Global flags metadata value is not an integer."); + return; + } + /* Rotate SKIP_OPTIMIZATION from bit 0 to bit 4 to match vkd3d_shader_global_flags.. */ + mask = (VKD3DSGF_SKIP_OPTIMIZATION << 1) - 1; + rotated_flags = global_flags & mask; + rotated_flags = (rotated_flags >> 1) | ((rotated_flags & 1) << 4); + global_flags = (global_flags & ~mask) | rotated_flags; + + ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_GLOBAL_FLAGS); + ins->declaration.global_flags = global_flags; +} + static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6) { const struct sm6_metadata_value *m = sm6_parser_find_named_metadata(sm6, "dx.entryPoints"); - const struct sm6_metadata_node *entry_node = m ? m->u.node : NULL; + const struct sm6_metadata_node *node, *entry_node = m ? m->u.node : NULL; + enum dxil_shader_properties_tag tag; + unsigned int i, operand_count; const struct sm6_value *value; enum vkd3d_result ret;
@@ -3645,6 +3718,49 @@ static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6) return ret; }
+ if (entry_node->operand_count >= 5 && (m = entry_node->operands[4])) + { + if (!sm6_metadata_value_is_node(m)) + { + WARN("Shader properties list is not a node.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, + "Shader properties tag/value list is not a metadata node."); + return VKD3D_ERROR_INVALID_SHADER; + } + + node = m->u.node; + if (node->operand_count & 1) + { + WARN("Operand count is not even.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Operand count for shader properties tag/value pairs is not even."); + } + operand_count = node->operand_count & ~1u; + + for (i = 0; i < operand_count; i += 2) + { + if (!sm6_metadata_get_uint_value(sm6, node->operands[i], &tag)) + { + WARN("Tag is not an integer value.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, + "Shader properties tag at index %u is not an integer.", i); + return VKD3D_ERROR_INVALID_SHADER; + } + + switch (tag) + { + case SHADER_PROPERTIES_FLAGS: + sm6_parser_emit_global_flags(sm6, node->operands[i + 1]); + break; + default: + FIXME("Unhandled tag %#x.\n", tag); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, + "Shader properties tag %#x is unhandled.", tag); + break; + } + } + } + return VKD3D_OK; }
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index ab148b3be..85041f2a5 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -179,6 +179,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA = 8014, VKD3D_SHADER_ERROR_DXIL_INVALID_ENTRY_POINT = 8015, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE = 8016, + VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES = 8017,
VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301, @@ -571,11 +572,13 @@ enum vkd3d_data_type VKD3D_DATA_CONTINUED, VKD3D_DATA_UNUSED, VKD3D_DATA_UINT8, + VKD3D_DATA_UINT64, };
static inline bool data_type_is_integer(enum vkd3d_data_type data_type) { - return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT; + return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT + || data_type == VKD3D_DATA_UINT64; }
enum vsir_dimension
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index e24f01324..57e2885de 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -26,6 +26,8 @@ #define BITCODE_MAGIC VKD3D_MAKE_TAG('B', 'C', 0xc0, 0xde) #define DXIL_OP_MAX_OPERANDS 17
+static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64}; + enum bitcode_block_id { BLOCKINFO_BLOCK = 0, @@ -3669,6 +3671,65 @@ static void sm6_parser_emit_global_flags(struct sm6_parser *sm6, const struct sm ins->declaration.global_flags = global_flags; }
+static enum vkd3d_result sm6_parser_emit_thread_group(struct sm6_parser *sm6, const struct sm6_metadata_value *m) +{ + const struct sm6_metadata_node *node; + struct vkd3d_shader_instruction *ins; + unsigned int group_sizes[3]; + unsigned int i; + + if (sm6->p.shader_version.type != VKD3D_SHADER_TYPE_COMPUTE) + { + WARN("Shader of type %#x has thread group dimensions.\n", sm6->p.shader_version.type); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, + "Shader has thread group dimensions but is not a compute shader."); + return VKD3D_ERROR_INVALID_SHADER; + } + + if (!m || !sm6_metadata_value_is_node(m)) + { + WARN("Thread group dimension value is not a node.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, + "Thread group dimension metadata value is not a node."); + return VKD3D_ERROR_INVALID_SHADER; + } + + node = m->u.node; + if (node->operand_count != 3) + { + WARN("Invalid operand count %u.\n", node->operand_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, + "Thread group dimension operand count %u is invalid.", node->operand_count); + return VKD3D_ERROR_INVALID_SHADER; + } + + for (i = 0; i < 3; ++i) + { + if (!sm6_metadata_get_uint_value(sm6, node->operands[i], &group_sizes[i])) + { + WARN("Thread group dimension is not an integer value.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, + "Thread group dimension metadata value is not an integer."); + return VKD3D_ERROR_INVALID_SHADER; + } + if (!group_sizes[i] || group_sizes[i] > dx_max_thread_group_size[i]) + { + char dim = "XYZ"[i]; + WARN("Invalid thread group %c dimension %u.\n", dim, group_sizes[i]); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, + "Thread group %c dimension %u is invalid.", dim, group_sizes[i]); + return VKD3D_ERROR_INVALID_SHADER; + } + } + + ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_THREAD_GROUP); + ins->declaration.thread_group_size.x = group_sizes[0]; + ins->declaration.thread_group_size.y = group_sizes[1]; + ins->declaration.thread_group_size.z = group_sizes[2]; + + return VKD3D_OK; +} + static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6) { const struct sm6_metadata_value *m = sm6_parser_find_named_metadata(sm6, "dx.entryPoints"); @@ -3752,6 +3813,10 @@ static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6) case SHADER_PROPERTIES_FLAGS: sm6_parser_emit_global_flags(sm6, node->operands[i + 1]); break; + case SHADER_PROPERTIES_COMPUTE: + if ((ret = sm6_parser_emit_thread_group(sm6, node->operands[i + 1])) < 0) + return ret; + break; default: FIXME("Unhandled tag %#x.\n", tag); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
From: Conor McCarthy cmccarthy@codeweavers.com
DXIL constant buffer sizes can be 32-bit scalar aligned. --- libs/vkd3d-shader/spirv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 90f1adeb7..86a7010ae 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -5639,7 +5639,8 @@ static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, reg.idx[1].offset = range->first; reg.idx[2].offset = range->last;
- size = size_in_bytes / (VKD3D_VEC4_SIZE * sizeof(uint32_t)); + size = align(size_in_bytes, VKD3D_VEC4_SIZE * sizeof(uint32_t)); + size /= VKD3D_VEC4_SIZE * sizeof(uint32_t);
if ((push_cb = spirv_compiler_find_push_constant_buffer(compiler, range))) {
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 41 ++++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 42 insertions(+)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 57e2885de..4206c37f5 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -25,6 +25,7 @@
#define BITCODE_MAGIC VKD3D_MAKE_TAG('B', 'C', 0xc0, 0xde) #define DXIL_OP_MAX_OPERANDS 17 +static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4;
static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64};
@@ -3374,6 +3375,43 @@ static const struct sm6_metadata_value *sm6_parser_find_named_metadata(struct sm return NULL; }
+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; + + if (!m) + return VKD3D_OK; + + node = m->u.node; + if (node->operand_count != SHADER_DESCRIPTOR_TYPE_COUNT) + { + WARN("Unexpected descriptor type count %u.\n", node->operand_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "Descriptor type count %u is invalid.", node->operand_count); + return VKD3D_ERROR_INVALID_SHADER; + } + + for (type = 0; type < SHADER_DESCRIPTOR_TYPE_COUNT; ++type) + { + if (!(m = node->operands[type])) + continue; + + if (!sm6_metadata_value_is_node(m)) + { + WARN("Resource list is not a node.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "Resource list is not a metadata node."); + return VKD3D_ERROR_INVALID_SHADER; + } + + FIXME("Descriptor info is unhandled.\n"); + } + + return VKD3D_OK; +} + static void signature_element_read_additional_element_values(struct signature_element *e, const struct sm6_metadata_node *node, struct sm6_parser *sm6) { @@ -4176,6 +4214,9 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t if ((ret = sm6_parser_entry_point_init(sm6)) < 0) return ret;
+ if ((ret = sm6_parser_resources_init(sm6)) < 0) + return ret; + if ((ret = sm6_parser_module_init(sm6, &sm6->root_block, 0)) < 0) { if (ret == VKD3D_ERROR_OUT_OF_MEMORY) diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 85041f2a5..cd5cc593d 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -180,6 +180,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_DXIL_INVALID_ENTRY_POINT = 8015, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE = 8016, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES = 8017, + VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES = 8018,
VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301,
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 a9a7aefe8..6f47560fc 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 4206c37f5..b31f4e72f 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; + + 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; + + 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; + } + + ++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 cd5cc593d..1305e4aff 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
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/vkd3d_shader_main.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 052edeb50..310932d9e 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1150,6 +1150,22 @@ static enum vkd3d_result convert_descriptor_info(struct vkd3d_shader_scan_descri return VKD3D_OK; }
+static bool clone_descriptor_info1_safe(struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info, + struct vkd3d_shader_descriptor_info1 *descriptors, unsigned int descriptor_count) +{ + if (!scan_descriptor_info || !descriptor_count) + return true; + + if (!(scan_descriptor_info->descriptors = vkd3d_calloc(descriptor_count, + sizeof(*scan_descriptor_info->descriptors)))) + return false; + memcpy(scan_descriptor_info->descriptors, descriptors, + descriptor_count * sizeof(*scan_descriptor_info->descriptors)); + scan_descriptor_info->descriptor_count = descriptor_count; + + return true; +} + static void vkd3d_shader_free_scan_descriptor_info1(struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info) { TRACE("scan_descriptor_info %p.\n", scan_descriptor_info); @@ -1179,6 +1195,8 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info { descriptor_info1 = &local_descriptor_info1; } + clone_descriptor_info1_safe(descriptor_info1, parser->shader_desc.descriptors, parser->shader_desc.descriptor_count); + signature_info = vkd3d_find_struct(compile_info->next, SCAN_SIGNATURE_INFO);
vkd3d_shader_scan_context_init(&context, compile_info, descriptor_info1, message_context);
Giovanni Mascellani (@giomasce) commented about libs/vkd3d-shader/dxil.c:
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;
if (!sm6_metadata_get_uint_value(sm6, node->operands[0], &d->register_id))
I don't think you're checking the number of operands available in this node, are you? You do the check in `sm6_parser_resources_load_cbv()`, but that's only for CBV and it's too late anyway.