Goes atop MR 388 (the error codes would clash otherwise). The last four commits belong to this MR.
-- v8: 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.
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..bbc1b2021 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 bbc1b2021..06faddac8 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 06faddac8..4bfebea27 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 4bfebea27..b2ef9f3f5 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);