diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-45679a966c73669bdb7fa371569dcc34a44.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-45679a966c73669bdb7fa371569dcc34a44.patch new file mode 100644 index 00000000..2dd4c639 --- /dev/null +++ b/patches/vkd3d-latest/0001-Updated-vkd3d-to-45679a966c73669bdb7fa371569dcc34a44.patch @@ -0,0 +1,1227 @@ +From 87d00abec6d4ea8946e1a9dcf79640a3bdac6ea2 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Fri, 8 Dec 2023 13:21:19 +1100 +Subject: [PATCH] Updated vkd3d to 45679a966c73669bdb7fa371569dcc34a448d8d4. + +--- + libs/vkd3d/include/private/vkd3d_common.h | 4 +- + libs/vkd3d/libs/vkd3d-common/blob.c | 1 + + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 4 +- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 423 +++++++++++++++++- + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 2 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 20 +- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 12 +- + libs/vkd3d/libs/vkd3d-shader/ir.c | 5 +- + libs/vkd3d/libs/vkd3d-shader/preproc.h | 2 +- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 129 ++++-- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 11 + + .../libs/vkd3d-shader/vkd3d_shader_main.c | 45 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 5 +- + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 4 +- + 14 files changed, 570 insertions(+), 97 deletions(-) + +diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h +index 34fde1a2aa0..e9bff2fbba3 100644 +--- a/libs/vkd3d/include/private/vkd3d_common.h ++++ b/libs/vkd3d/include/private/vkd3d_common.h +@@ -80,7 +80,7 @@ static inline size_t align(size_t addr, size_t alignment) + # ifdef __MINGW_PRINTF_FORMAT + # define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, args))) + # else +-# define VKD3D_PRINTF_FUNC(fmt, args) /* __attribute__((format(printf, fmt, args))) */ ++# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args))) + # endif + # define VKD3D_UNUSED __attribute__((unused)) + # define VKD3D_UNREACHABLE __builtin_unreachable() +@@ -107,7 +107,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v) + { + #ifdef _MSC_VER + return __popcnt(v); +-#elif defined(__MINGW32__) ++#elif defined(HAVE_BUILTIN_POPCOUNT) + return __builtin_popcount(v); + #else + v -= (v >> 1) & 0x55555555; +diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c +index 71ab9a2c51e..fa2812619ac 100644 +--- a/libs/vkd3d/libs/vkd3d-common/blob.c ++++ b/libs/vkd3d/libs/vkd3d-common/blob.c +@@ -17,6 +17,7 @@ + */ + + #define COBJMACROS ++ + #define CONST_VTABLE + #include "vkd3d.h" + #include "vkd3d_blob.h" +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index 3d139416b61..c78ffebac69 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -2253,7 +2253,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b + { + struct hlsl_reg *reg = &jump->condition.node->reg; + +- struct sm1_instruction instr = ++ struct sm1_instruction sm1_instr = + { + .opcode = D3DSIO_TEXKILL, + +@@ -2263,7 +2263,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b + .has_dst = 1, + }; + +- write_sm1_instruction(ctx, buffer, &instr); ++ write_sm1_instruction(ctx, buffer, &sm1_instr); + break; + } + +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index beb9ae574dc..a1065c8bc45 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -296,8 +296,28 @@ enum dx_intrinsic_opcode + { + DX_LOAD_INPUT = 4, + DX_STORE_OUTPUT = 5, ++ DX_EXP = 21, ++ DX_FRC = 22, ++ DX_LOG = 23, ++ DX_SQRT = 24, ++ DX_RSQRT = 25, ++ DX_ROUND_NE = 26, ++ DX_ROUND_NI = 27, ++ DX_ROUND_PI = 28, ++ DX_ROUND_Z = 29, ++ DX_BFREV = 30, ++ DX_COUNT_BITS = 31, ++ DX_FIRST_BIT_LO = 32, ++ DX_FIRST_BIT_HI = 33, ++ DX_FIRST_BIT_SHI = 34, + DX_CREATE_HANDLE = 57, + DX_CBUFFER_LOAD_LEGACY = 59, ++ DX_DERIV_COARSEX = 83, ++ DX_DERIV_COARSEY = 84, ++ DX_DERIV_FINEX = 85, ++ DX_DERIV_FINEY = 86, ++ DX_LEGACY_F32TOF16 = 130, ++ DX_LEGACY_F16TOF32 = 131, + }; + + enum dxil_cast_code +@@ -439,6 +459,7 @@ struct dxil_record + { + unsigned int code; + unsigned int operand_count; ++ const struct dxil_record *attachment; + uint64_t operands[]; + }; + +@@ -581,6 +602,7 @@ struct sm6_parser + size_t descriptor_count; + + unsigned int indexable_temp_count; ++ unsigned int icb_count; + + struct sm6_value *values; + size_t value_count; +@@ -796,6 +818,7 @@ static enum vkd3d_result sm6_parser_read_unabbrev_record(struct sm6_parser *sm6) + + record->code = code; + record->operand_count = count; ++ record->attachment = NULL; + + for (i = 0; i < count; ++i) + record->operands[i] = sm6_parser_read_vbr(sm6, 6); +@@ -1012,6 +1035,7 @@ static enum vkd3d_result sm6_parser_read_abbrev_record(struct sm6_parser *sm6, u + if (!abbrev->operands[i + 1].read_operand(sm6, abbrev->operands[i + 1].context, &record->operands[i])) + goto fail; + record->operand_count = count; ++ record->attachment = NULL; + + /* An array can occur only as the last operand. */ + if (abbrev->is_array) +@@ -1572,6 +1596,11 @@ static bool sm6_type_is_bool_i16_i32_i64(const struct sm6_type *type) + return type->class == TYPE_CLASS_INTEGER && (type->u.width == 1 || type->u.width >= 16); + } + ++static bool sm6_type_is_i16_i32_i64(const struct sm6_type *type) ++{ ++ return type->class == TYPE_CLASS_INTEGER && type->u.width >= 16; ++} ++ + static bool sm6_type_is_bool(const struct sm6_type *type) + { + return type->class == TYPE_CLASS_INTEGER && type->u.width == 1; +@@ -1587,6 +1616,16 @@ static inline bool sm6_type_is_i32(const struct sm6_type *type) + return type->class == TYPE_CLASS_INTEGER && type->u.width == 32; + } + ++static bool sm6_type_is_float(const struct sm6_type *type) ++{ ++ return type->class == TYPE_CLASS_FLOAT && type->u.width == 32; ++} ++ ++static bool sm6_type_is_f16_f32(const struct sm6_type *type) ++{ ++ return type->class == TYPE_CLASS_FLOAT && (type->u.width == 16 || type->u.width == 32); ++} ++ + static inline bool sm6_type_is_floating_point(const struct sm6_type *type) + { + return type->class == TYPE_CLASS_FLOAT; +@@ -2412,7 +2451,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + return VKD3D_ERROR_INVALID_SHADER; + } + size = max(size, sizeof(icb->data[0])); +- count = type->u.array.count * size / sizeof(icb->data[0]); ++ count = operands ? type->u.array.count * size / sizeof(icb->data[0]) : 0; + + if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[count])))) + { +@@ -2433,9 +2472,14 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + dst->value_type = VALUE_TYPE_ICB; + dst->u.icb = icb; + ++ icb->register_idx = sm6->icb_count++; + icb->data_type = vkd3d_data_type_from_sm6_type(elem_type); + icb->element_count = type->u.array.count; + icb->component_count = 1; ++ icb->is_null = !operands; ++ ++ if (!operands) ++ return VKD3D_OK; + + count = type->u.array.count; + if (size > sizeof(icb->data[0])) +@@ -2510,12 +2554,10 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + switch (record->code) + { + case CST_CODE_NULL: +- if (sm6_type_is_array(type)) ++ if (sm6_type_is_array(type) ++ && (ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) + { +- FIXME("Constant null arrays are not supported.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +- "Constant null arrays are not supported."); +- return VKD3D_ERROR_INVALID_SHADER; ++ return ret; + } + /* For non-aggregates, register constant data is already zero-filled. */ + break; +@@ -2588,6 +2630,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + break; + } + ++ if (record->attachment) ++ { ++ WARN("Ignoring metadata attachment.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring a metadata attachment for a constant."); ++ } ++ + ++sm6->value_count; + } + +@@ -2626,6 +2675,18 @@ static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_pa + return ins; + } + ++static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type *elem_type, unsigned int count, ++ unsigned int alignment, unsigned int init, struct sm6_value *dst) ++{ ++ enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); ++ struct vkd3d_shader_instruction *ins; ++ ++ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER); ++ /* The icb value index will be resolved later so forward references can be handled. */ ++ ins->declaration.icb = (void *)(intptr_t)init; ++ register_init_with_id(&dst->u.reg, VKD3DSPR_IMMCONSTBUFFER, data_type, init); ++} ++ + static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, + unsigned int count, unsigned int alignment, unsigned int init, struct sm6_value *dst) + { +@@ -2762,7 +2823,10 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ + + if (address_space == ADDRESS_SPACE_DEFAULT) + { +- sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst); ++ if (is_constant) ++ sm6_parser_declare_icb(sm6, scalar_type, count, alignment, init, dst); ++ else ++ sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst); + } + else if (address_space == ADDRESS_SPACE_GROUPSHARED) + { +@@ -2806,11 +2870,11 @@ static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_init + static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) + { + const struct dxil_block *block = &sm6->root_block; ++ size_t i, base_value_idx = sm6->value_count; + struct vkd3d_shader_instruction *ins; + const struct dxil_record *record; + enum vkd3d_result ret; + uint64_t version; +- size_t i; + + sm6->p.location.line = block->id; + sm6->p.location.column = 0; +@@ -2868,6 +2932,21 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) + ins->declaration.indexable_temp.initialiser = resolve_forward_initialiser( + (uintptr_t)ins->declaration.indexable_temp.initialiser, sm6); + } ++ else if (ins->handler_idx == VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER) ++ { ++ ins->declaration.icb = resolve_forward_initialiser((uintptr_t)ins->declaration.icb, sm6); ++ } ++ } ++ for (i = base_value_idx; i < sm6->value_count; ++i) ++ { ++ const struct vkd3d_shader_immediate_constant_buffer *icb; ++ struct sm6_value *value = &sm6->values[i]; ++ ++ if (!sm6_value_is_register(value) || value->u.reg.type != VKD3DSPR_IMMCONSTBUFFER) ++ continue; ++ ++ if ((icb = resolve_forward_initialiser(value->u.reg.idx[0].offset, sm6))) ++ value->u.reg.idx[0].offset = icb->register_idx; + } + + return VKD3D_OK; +@@ -3171,6 +3250,67 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco + } + } + ++static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) ++{ ++ switch (op) ++ { ++ case DX_EXP: ++ return VKD3DSIH_EXP; ++ case DX_FRC: ++ return VKD3DSIH_FRC; ++ case DX_LOG: ++ return VKD3DSIH_LOG; ++ case DX_SQRT: ++ return VKD3DSIH_SQRT; ++ case DX_RSQRT: ++ return VKD3DSIH_RSQ; ++ case DX_ROUND_NE: ++ return VKD3DSIH_ROUND_NE; ++ case DX_ROUND_NI: ++ return VKD3DSIH_ROUND_NI; ++ case DX_ROUND_PI: ++ return VKD3DSIH_ROUND_PI; ++ case DX_ROUND_Z: ++ return VKD3DSIH_ROUND_Z; ++ case DX_BFREV: ++ return VKD3DSIH_BFREV; ++ case DX_COUNT_BITS: ++ return VKD3DSIH_COUNTBITS; ++ case DX_FIRST_BIT_LO: ++ return VKD3DSIH_FIRSTBIT_LO; ++ case DX_FIRST_BIT_HI: ++ return VKD3DSIH_FIRSTBIT_HI; ++ case DX_FIRST_BIT_SHI: ++ return VKD3DSIH_FIRSTBIT_SHI; ++ case DX_DERIV_COARSEX: ++ return VKD3DSIH_DSX_COARSE; ++ case DX_DERIV_COARSEY: ++ return VKD3DSIH_DSY_COARSE; ++ case DX_DERIV_FINEX: ++ return VKD3DSIH_DSX_FINE; ++ case DX_DERIV_FINEY: ++ return VKD3DSIH_DSY_FINE; ++ case DX_LEGACY_F32TOF16: ++ return VKD3DSIH_F32TOF16; ++ case DX_LEGACY_F16TOF32: ++ return VKD3DSIH_F16TOF32; ++ default: ++ vkd3d_unreachable(); ++ } ++} ++ ++static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, struct sm6_block *code_block, ++ enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) ++{ ++ struct vkd3d_shader_src_param *src_param; ++ ++ vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); ++ src_param = instruction_src_params_alloc(ins, 1, sm6); ++ src_param_init_from_value(src_param, operands[0]); ++ ++ instruction_dst_param_init_ssa_scalar(ins, sm6); ++} ++ + static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, struct sm6_block *code_block, + enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) + { +@@ -3344,7 +3484,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, struct sm6_b + + struct sm6_dx_opcode_info + { +- const char ret_type; ++ const char *ret_type; + const char *operand_info; + void (*handler)(struct sm6_parser *, struct sm6_block *, enum dx_intrinsic_opcode, + const struct sm6_value **, struct vkd3d_shader_instruction *); +@@ -3355,16 +3495,40 @@ struct sm6_dx_opcode_info + b -> constant int1 + c -> constant int8/16/32 + i -> int32 ++ m -> int16/32/64 ++ f -> float ++ e -> half/float ++ g -> half/float/double + H -> handle + v -> void + o -> overloaded + */ + static const struct sm6_dx_opcode_info sm6_dx_op_table[] = + { +- [DX_CBUFFER_LOAD_LEGACY ] = {'o', "Hi", sm6_parser_emit_dx_cbuffer_load}, +- [DX_CREATE_HANDLE ] = {'H', "ccib", sm6_parser_emit_dx_create_handle}, +- [DX_LOAD_INPUT ] = {'o', "ii8i", sm6_parser_emit_dx_load_input}, +- [DX_STORE_OUTPUT ] = {'v', "ii8o", sm6_parser_emit_dx_store_output}, ++ [DX_BFREV ] = {"m0", "m", sm6_parser_emit_dx_unary}, ++ [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, ++ [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, ++ [DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle}, ++ [DX_DERIV_COARSEX ] = {"e0", "e", sm6_parser_emit_dx_unary}, ++ [DX_DERIV_COARSEY ] = {"e0", "e", sm6_parser_emit_dx_unary}, ++ [DX_DERIV_FINEX ] = {"e0", "e", sm6_parser_emit_dx_unary}, ++ [DX_DERIV_FINEY ] = {"e0", "e", sm6_parser_emit_dx_unary}, ++ [DX_EXP ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_FIRST_BIT_HI ] = {"i", "m", sm6_parser_emit_dx_unary}, ++ [DX_FIRST_BIT_LO ] = {"i", "m", sm6_parser_emit_dx_unary}, ++ [DX_FIRST_BIT_SHI ] = {"i", "m", sm6_parser_emit_dx_unary}, ++ [DX_FRC ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_LEGACY_F16TOF32 ] = {"f", "i", sm6_parser_emit_dx_unary}, ++ [DX_LEGACY_F32TOF16 ] = {"i", "f", sm6_parser_emit_dx_unary}, ++ [DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input}, ++ [DX_LOG ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_ROUND_NE ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_ROUND_NI ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_ROUND_PI ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_ROUND_Z ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_RSQRT ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_SQRT ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, + }; + + static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type, +@@ -3389,6 +3553,14 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc + && type->u.width <= 32; + case 'i': + return sm6_type_is_i32(type); ++ case 'm': ++ return sm6_type_is_i16_i32_i64(type); ++ case 'f': ++ return sm6_type_is_float(type); ++ case 'e': ++ return sm6_type_is_f16_f32(type); ++ case 'g': ++ return sm6_type_is_floating_point(type); + case 'H': + return (is_return || sm6_value_is_handle(value)) && type == sm6->handle_type; + case 'v': +@@ -3402,6 +3574,17 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc + } + } + ++static bool operand_types_match(struct sm6_value *dst, const struct sm6_value **operands, unsigned int operand_count, ++ char index_char) ++{ ++ unsigned int i = index_char - '0'; ++ ++ assert(i < 10); ++ if (i >= operand_count) ++ return false; ++ return dst->type == operands[i]->type; ++} ++ + static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const char *name, + const struct sm6_value **operands, unsigned int operand_count, struct sm6_value *dst) + { +@@ -3410,7 +3593,9 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ + + info = &sm6_dx_op_table[op]; + +- if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type, true)) ++ assert(info->ret_type[0]); ++ if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type[0], true) ++ || (info->ret_type[1] && !operand_types_match(dst, operands, operand_count, info->ret_type[1]))) + { + WARN("Failed to validate return type for dx intrinsic id %u, '%s'.\n", op, name); + /* Return type validation failure is not so critical. We only need to set +@@ -3700,6 +3885,9 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor + if (handler_idx == VKD3DSIH_NOP) + { + dst->u.reg = value->u.reg; ++ /* Set the result type for casts from 16-bit min precision. */ ++ if (type->u.width != 16) ++ dst->u.reg.data_type = vkd3d_data_type_from_sm6_type(type); + return; + } + +@@ -4153,6 +4341,208 @@ static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, + return true; + } + ++static void sm6_parser_metadata_attachment_block_init(struct sm6_parser *sm6, const struct dxil_block *target_block, ++ const struct dxil_block *block) ++{ ++ struct dxil_record *target_record; ++ const struct dxil_record *record; ++ unsigned int i; ++ uint64_t index; ++ ++ for (i = 0; i < block->record_count; ++i) ++ { ++ record = block->records[i]; ++ if (record->code != METADATA_ATTACHMENT) ++ { ++ WARN("Ignoring record with code %u.\n", record->code); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring a metadata attachment record with code %u.", record->code); ++ continue; ++ } ++ if (!(record->operand_count & 1)) ++ { ++ WARN("Ignoring function attachment.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring a metadata function attachment."); ++ continue; ++ } ++ ++ index = record->operands[0]; ++ if (!target_block->record_count || index >= target_block->record_count - 1) ++ { ++ WARN("Invalid record index %"PRIu64".\n", index); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Invalid record index %"PRIu64" for a metadata attachment.", index); ++ continue; ++ } ++ /* 'index' is an instruction index, but records[0] is DECLAREBLOCKS, not an instruction. */ ++ target_record = target_block->records[index + 1]; ++ if (target_record->attachment) ++ { ++ WARN("Overwriting record attachment.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "The target record for a metadata attachment already has an attachment."); ++ } ++ target_record->attachment = record; ++ } ++} ++ ++static void sm6_parser_metadata_attachments_init(struct sm6_parser *sm6, const struct dxil_block *block) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < block->child_block_count; ++i) ++ { ++ if (block->child_blocks[i]->id == METADATA_ATTACHMENT_BLOCK) ++ sm6_parser_metadata_attachment_block_init(sm6, block, block->child_blocks[i]); ++ } ++} ++ ++static const struct sm6_metadata_value *sm6_parser_find_metadata_kind(const struct sm6_parser *sm6, uint64_t id) ++{ ++ unsigned int i, j; ++ ++ for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) ++ { ++ for (j = 0; j < sm6->metadata_tables[i].count; ++j) ++ { ++ if (sm6->metadata_tables[i].values[j].type == VKD3D_METADATA_KIND ++ && sm6->metadata_tables[i].values[j].u.kind.id == id) ++ return &sm6->metadata_tables[i].values[j]; ++ } ++ } ++ ++ return NULL; ++} ++ ++static const struct sm6_metadata_value *sm6_parser_metadata_get_value(const struct sm6_parser *sm6, uint64_t index) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) ++ { ++ if (sm6->metadata_tables[i].count > index) ++ break; ++ index -= sm6->metadata_tables[i].count; ++ } ++ ++ return (index < sm6->metadata_tables[i].count) ? &sm6->metadata_tables[i].values[index] : NULL; ++} ++ ++static bool metadata_node_get_unary_uint(const struct sm6_metadata_node *node, unsigned int *operand, ++ struct sm6_parser *sm6) ++{ ++ if (node->operand_count != 1) ++ { ++ FIXME("Ignoring node with %u operands.\n", node->operand_count); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring metadata attachment node with %u operands; expected unary.", node->operand_count); ++ return false; ++ } ++ if (!sm6_metadata_value_is_value(node->operands[0]) ++ || !sm6_metadata_get_uint_value(sm6, node->operands[0], operand)) ++ { ++ WARN("Failed to get operand value.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Failed to get a metadata attachment operand value; ignoring the attachment."); ++ return false; ++ } ++ ++ return true; ++} ++ ++static void metadata_attachment_record_apply(const struct dxil_record *record, enum bitcode_function_code func_code, ++ struct vkd3d_shader_instruction *ins, struct sm6_value *dst, struct sm6_parser *sm6) ++{ ++ static const char *ignored_names[] = ++ { ++ "alias.scope", ++ "dx.controlflow.hints", ++ "llvm.loop", ++ "noalias", ++ "tbaa", ++ "range", ++ }; ++ const struct sm6_metadata_node *node; ++ const struct sm6_metadata_value *m; ++ unsigned int i, j, operand; ++ bool ignored = false; ++ const char *name; ++ ++ if (record->attachment) ++ { ++ WARN("Ignoring nested metadata attachment.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring a nested metadata attachment."); ++ } ++ ++ assert(record->operand_count & 1); ++ for (i = 1; i < record->operand_count; i += 2) ++ { ++ if (!(m = sm6_parser_find_metadata_kind(sm6, record->operands[i]))) ++ { ++ WARN("Failed to find metadata kind %"PRIx64".\n", record->operands[i]); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Failed to find metadata kind %"PRIx64" for an attachment.", record->operands[i]); ++ continue; ++ } ++ name = m->u.kind.name; ++ ++ m = sm6_parser_metadata_get_value(sm6, record->operands[i + 1]); ++ if (!m || !sm6_metadata_value_is_node(m)) ++ { ++ WARN("Failed to retrieve metadata attachment node.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Failed to retrieve a metadata attachment node."); ++ continue; ++ } ++ node = m->u.node; ++ ++ if (!strcmp(name, "dx.precise")) ++ { ++ if (!sm6_value_is_register(dst)) ++ { ++ WARN("Precise value is not a register.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "A value marked as precise is not a register."); ++ } ++ else if (metadata_node_get_unary_uint(node, &operand, sm6) && operand) ++ { ++ ins->flags |= sm6_type_is_scalar(dst->type) ? VKD3DSI_PRECISE_X : VKD3DSI_PRECISE_XYZW; ++ } ++ } ++ else if (!strcmp(name, "dx.nonuniform")) ++ { ++ if (!sm6_value_is_register(dst)) ++ { ++ WARN("Non-uniform value is not a register.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "A value marked as non-uniform is not a register."); ++ } ++ else if (metadata_node_get_unary_uint(node, &operand, sm6)) ++ { ++ dst->u.reg.non_uniform = !!operand; ++ } ++ } ++ else ++ { ++ for (j = 0; j < ARRAY_SIZE(ignored_names); ++j) ++ if (!strcmp(name, ignored_names[j])) ++ break; ++ if (j == ARRAY_SIZE(ignored_names)) ++ { ++ WARN("Ignoring metadata attachment '%s'.\n", name); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring a metadata attachment named '%s'.", name); ++ } ++ ignored = true; ++ } ++ ++ if (func_code != FUNC_CODE_INST_CALL && !ignored) ++ WARN("Metadata attachment target is not a function call.\n"); ++ } ++} ++ + static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, + struct sm6_function *function) + { +@@ -4278,6 +4668,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + return VKD3D_ERROR; + assert(ins->handler_idx != VKD3DSIH_INVALID); + ++ if (record->attachment) ++ metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); ++ + if (is_terminator) + { + ++block_idx; +@@ -4331,6 +4724,8 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st + sm6->p.location.line = block->id; + sm6->p.location.column = 0; + ++ sm6_parser_metadata_attachments_init(sm6, block); ++ + switch (block->id) + { + case CONSTANTS_BLOCK: +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +index ca75a1936f1..bd6682be6ac 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +@@ -21,7 +21,7 @@ + #define __VKD3D_SHADER_HLSL_H + + #include "vkd3d_shader_private.h" +-#include "wine/rbtree.h" ++#include "rbtree.h" + #include "d3dcommon.h" + #include "d3dx9shader.h" + +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index 0dde4c18587..ed053f16312 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -487,27 +487,27 @@ static void resolve_loop_continue(struct hlsl_ctx *ctx, struct hlsl_block *block + else if (instr->type == HLSL_IR_JUMP) + { + struct hlsl_ir_jump *jump = hlsl_ir_jump(instr); +- struct hlsl_block block; ++ struct hlsl_block cond_block; + + if (jump->type != HLSL_IR_JUMP_UNRESOLVED_CONTINUE) + continue; + + if (type == LOOP_DO_WHILE) + { +- if (!hlsl_clone_block(ctx, &block, cond)) ++ if (!hlsl_clone_block(ctx, &cond_block, cond)) + return; +- if (!append_conditional_break(ctx, &block)) ++ if (!append_conditional_break(ctx, &cond_block)) + { +- hlsl_block_cleanup(&block); ++ hlsl_block_cleanup(&cond_block); + return; + } +- list_move_before(&instr->entry, &block.instrs); ++ list_move_before(&instr->entry, &cond_block.instrs); + } + else if (type == LOOP_FOR) + { +- if (!hlsl_clone_block(ctx, &block, iter)) ++ if (!hlsl_clone_block(ctx, &cond_block, iter)) + return; +- list_move_before(&instr->entry, &block.instrs); ++ list_move_before(&instr->entry, &cond_block.instrs); + } + jump->type = HLSL_IR_JUMP_CONTINUE; + } +@@ -3553,7 +3553,7 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * + { + struct hlsl_resource_load_params load_params = { 0 }; + const struct hlsl_type *sampler_type; +- struct hlsl_ir_node *coords, *load; ++ struct hlsl_ir_node *coords, *sample; + + if (params->args_count != 2 && params->args_count != 4) + { +@@ -3688,9 +3688,9 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * + load_params.format = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4); + load_params.sampling_dim = dim; + +- if (!(load = hlsl_new_resource_load(ctx, &load_params, loc))) ++ if (!(sample = hlsl_new_resource_load(ctx, &load_params, loc))) + return false; +- hlsl_block_add_instr(params->instrs, load); ++ hlsl_block_add_instr(params->instrs, sample); + return true; + } + +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index 4a622185741..88cbef61d5f 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -1090,7 +1090,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + unsigned int dim_count = hlsl_sampler_dim_count(val->data_type->sampler_dim); + struct hlsl_ir_node *coords = index->idx.node; + struct hlsl_resource_load_params params = {0}; +- struct hlsl_ir_node *load; ++ struct hlsl_ir_node *resource_load; + + assert(coords->data_type->class == HLSL_CLASS_VECTOR); + assert(coords->data_type->base_type == HLSL_TYPE_UINT); +@@ -1104,9 +1104,9 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + params.coords = coords; + params.format = val->data_type->e.resource_format; + +- if (!(load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) ++ if (!(resource_load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) + return false; +- hlsl_block_add_instr(block, load); ++ hlsl_block_add_instr(block, resource_load); + return true; + } + +@@ -2301,7 +2301,6 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + struct hlsl_ir_switch_case *c, *def = NULL; + bool missing_terminal_break = false; + struct hlsl_ir_node *node; +- struct hlsl_ir_jump *jump; + struct hlsl_ir_switch *s; + + if (instr->type != HLSL_IR_SWITCH) +@@ -2320,10 +2319,7 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + { + node = LIST_ENTRY(list_tail(&c->body.instrs), struct hlsl_ir_node, entry); + if (node->type == HLSL_IR_JUMP) +- { +- jump = hlsl_ir_jump(node); +- terminal_break = jump->type == HLSL_IR_JUMP_BREAK; +- } ++ terminal_break = (hlsl_ir_jump(node)->type == HLSL_IR_JUMP_BREAK); + } + + missing_terminal_break |= !terminal_break; +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 710811c6761..a35ef862096 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -463,6 +463,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i + struct vkd3d_shader_instruction_array *instructions; + struct control_point_normaliser normaliser; + unsigned int input_control_point_count; ++ struct vkd3d_shader_location location; + struct vkd3d_shader_instruction *ins; + enum vkd3d_result ret; + unsigned int i, j; +@@ -513,8 +514,10 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i + return VKD3D_OK; + case VKD3DSIH_HS_FORK_PHASE: + case VKD3DSIH_HS_JOIN_PHASE: ++ /* ins may be relocated if the instruction array expands. */ ++ location = ins->location; + ret = control_point_normaliser_emit_hs_input(&normaliser, input_signature, +- input_control_point_count, i, &ins->location); ++ input_control_point_count, i, &location); + *src_instructions = normaliser.instructions; + return ret; + default: +diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.h b/libs/vkd3d/libs/vkd3d-shader/preproc.h +index 4860cf5f90e..e1cb75e177c 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/preproc.h ++++ b/libs/vkd3d/libs/vkd3d-shader/preproc.h +@@ -22,7 +22,7 @@ + #define __VKD3D_SHADER_PREPROC_H + + #include "vkd3d_shader_private.h" +-#include "wine/rbtree.h" ++#include "rbtree.h" + + struct preproc_if_state + { +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index c8a43adbe03..dc3d9631302 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -18,7 +18,7 @@ + */ + + #include "vkd3d_shader_private.h" +-#include "wine/rbtree.h" ++#include "rbtree.h" + + #include + #include +@@ -1194,6 +1194,16 @@ static uint32_t vkd3d_spirv_get_op_constant64(struct vkd3d_spirv_builder *builde + (const uint32_t *)&value, 2, vkd3d_spirv_build_op_constant64); + } + ++static uint32_t vkd3d_spirv_build_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) ++{ ++ return vkd3d_spirv_build_op_tr(builder, &builder->global_stream, SpvOpConstantNull, result_type); ++} ++ ++static uint32_t vkd3d_spirv_get_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) ++{ ++ return vkd3d_spirv_build_once1(builder, SpvOpConstantNull, result_type, vkd3d_spirv_build_op_constant_null); ++} ++ + static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_builder *builder, + uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) + { +@@ -2152,6 +2162,7 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol, + break; + + case VKD3DSPR_IMMCONSTBUFFER: ++ symbol->key.reg.idx = reg->idx_count > 1 ? reg->idx[0].offset : 0; + break; + + default: +@@ -3498,7 +3509,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp + } + else if (reg->type == VKD3DSPR_IMMCONSTBUFFER) + { +- indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[0]); ++ indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[reg->idx_count - 1]); + } + else if (reg->type == VKD3DSPR_IDXTEMP) + { +@@ -3756,6 +3767,69 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, + return val_id; + } + ++static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compiler, ++ const struct vkd3d_shader_immediate_constant_buffer *icb, uint32_t *type_id_out) ++{ ++ uint32_t *elements, elem_type_id, length_id, type_id, const_id; ++ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ enum vkd3d_shader_component_type component_type; ++ unsigned int i, element_count, component_count; ++ ++ element_count = icb->element_count; ++ ++ component_type = vkd3d_component_type_from_data_type(icb->data_type); ++ component_count = icb->component_count; ++ elem_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, icb->data_type, component_count); ++ length_id = spirv_compiler_get_constant_uint(compiler, element_count); ++ type_id = vkd3d_spirv_get_op_type_array(builder, elem_type_id, length_id); ++ ++ if (type_id_out) ++ *type_id_out = type_id; ++ ++ if (icb->is_null) ++ { ++ /* All values are null. Workgroup memory initialisers require OpConstantNull. */ ++ return vkd3d_spirv_get_op_constant_null(builder, type_id); ++ } ++ ++ if (!(elements = vkd3d_calloc(element_count, sizeof(*elements)))) ++ { ++ ERR("Failed to allocate %u elements.", element_count); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY, ++ "Failed to allocate %u constant array elements.", element_count); ++ return 0; ++ } ++ ++ switch (icb->data_type) ++ { ++ case VKD3D_DATA_FLOAT: ++ case VKD3D_DATA_INT: ++ case VKD3D_DATA_UINT: ++ for (i = 0; i < element_count; ++i) ++ elements[i] = spirv_compiler_get_constant(compiler, component_type, component_count, ++ &icb->data[component_count * i]); ++ break; ++ case VKD3D_DATA_DOUBLE: ++ case VKD3D_DATA_UINT64: ++ { ++ uint64_t *data = (uint64_t *)icb->data; ++ for (i = 0; i < element_count; ++i) ++ elements[i] = spirv_compiler_get_constant64(compiler, component_type, component_count, ++ &data[component_count * i]); ++ break; ++ } ++ default: ++ FIXME("Unhandled data type %u.\n", icb->data_type); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, ++ "Immediate constant buffer data type %u is unhandled.", icb->data_type); ++ break; ++ } ++ ++ const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, element_count); ++ vkd3d_free(elements); ++ return const_id; ++} ++ + static const struct ssa_register_info *spirv_compiler_get_ssa_register_info(const struct spirv_compiler *compiler, + const struct vkd3d_shader_register *reg) + { +@@ -5493,39 +5567,40 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil + { + const struct vkd3d_shader_indexable_temp *temp = &instruction->declaration.indexable_temp; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ uint32_t id, type_id, length_id, ptr_type_id, init_id = 0; ++ enum vkd3d_shader_component_type component_type; + struct vkd3d_shader_register reg; + struct vkd3d_symbol reg_symbol; ++ SpvStorageClass storage_class; + size_t function_location; +- uint32_t id; + +- if (temp->component_count != 4) +- FIXME("Unhandled component count %u.\n", temp->component_count); ++ storage_class = SpvStorageClassFunction; + + vsir_register_init(®, VKD3DSPR_IDXTEMP, VKD3D_DATA_FLOAT, 1); + reg.idx[0].offset = temp->register_idx; + + if (temp->alignment) + WARN("Ignoring alignment %u.\n", temp->alignment); +- if (temp->initialiser) +- { +- FIXME("Initialisers are not supported.\n"); +- spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, +- "Initialisers for indexable temps are not supported."); +- } + + function_location = spirv_compiler_get_current_function_location(compiler); + vkd3d_spirv_begin_function_stream_insertion(builder, function_location); + +- id = spirv_compiler_emit_array_variable(compiler, &builder->function_stream, +- SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &temp->register_size, 1); ++ component_type = vkd3d_component_type_from_data_type(temp->data_type); ++ type_id = vkd3d_spirv_get_type_id(builder, component_type, temp->component_count); ++ length_id = spirv_compiler_get_constant_uint(compiler, temp->register_size); ++ type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); ++ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); ++ if (temp->initialiser) ++ init_id = spirv_compiler_emit_constant_array(compiler, temp->initialiser, NULL); ++ id = vkd3d_spirv_build_op_variable(builder, &builder->function_stream, ptr_type_id, storage_class, init_id); + + spirv_compiler_emit_register_debug_name(builder, id, ®); + + vkd3d_spirv_end_function_stream_insertion(builder); + + vkd3d_symbol_make_register(®_symbol, ®); +- vkd3d_symbol_set_register_info(®_symbol, id, +- SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); ++ vkd3d_symbol_set_register_info(®_symbol, id, storage_class, ++ component_type, vkd3d_write_mask_from_component_count(temp->component_count)); + spirv_compiler_put_symbol(compiler, ®_symbol); + } + +@@ -5743,34 +5818,24 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi + const struct vkd3d_shader_instruction *instruction) + { + const struct vkd3d_shader_immediate_constant_buffer *icb = instruction->declaration.icb; +- uint32_t *elements, length_id, type_id, const_id, ptr_type_id, icb_id; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ uint32_t type_id, const_id, ptr_type_id, icb_id; + struct vkd3d_shader_register reg; + struct vkd3d_symbol reg_symbol; +- unsigned int i; + +- assert(icb->data_type == VKD3D_DATA_FLOAT); +- assert(icb->component_count == VKD3D_VEC4_SIZE); +- +- if (!(elements = vkd3d_calloc(icb->element_count, sizeof(*elements)))) +- return; +- for (i = 0; i < icb->element_count; ++i) +- elements[i] = spirv_compiler_get_constant(compiler, +- VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &icb->data[4 * i]); +- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); +- length_id = spirv_compiler_get_constant_uint(compiler, icb->element_count); +- type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); +- const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, icb->element_count); ++ const_id = spirv_compiler_emit_constant_array(compiler, icb, &type_id); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id); + icb_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, + ptr_type_id, SpvStorageClassPrivate, const_id); + vkd3d_spirv_build_op_name(builder, icb_id, "icb"); +- vkd3d_free(elements); + +- vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 0); ++ /* Set an index count of 2 so vkd3d_symbol_make_register() uses idx[0] as a buffer id. */ ++ vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 2); ++ reg.idx[0].offset = icb->register_idx; + vkd3d_symbol_make_register(®_symbol, ®); + vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate, +- VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); ++ vkd3d_component_type_from_data_type(icb->data_type), ++ vkd3d_write_mask_from_component_count(icb->component_count)); + spirv_compiler_put_symbol(compiler, ®_symbol); + } + +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index 80f8ab98c08..163cd90ee13 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -792,9 +792,11 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui + ins->handler_idx = VKD3DSIH_INVALID; + return; + } ++ icb->register_idx = 0; + icb->data_type = VKD3D_DATA_FLOAT; + icb->component_count = VKD3D_VEC4_SIZE; + icb->element_count = icb_size / VKD3D_VEC4_SIZE; ++ icb->is_null = false; + memcpy(icb->data, tokens, sizeof(*tokens) * icb_size); + shader_instruction_array_add_icb(&priv->p.instructions, icb); + ins->declaration.icb = icb; +@@ -1930,6 +1932,15 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui + break; + } + } ++ else if (register_type == VKD3D_SM4_RT_IMMCONSTBUFFER) ++ { ++ if (param->idx_count != 1) ++ { ++ WARN("Unexpected idx count %u.\n", param->idx_count); ++ vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_INDEX_COUNT, ++ "Invalid index count %u for immediate const buffer register; expected count 1.", param->idx_count); ++ } ++ } + else if (!shader_is_sm_5_1(priv) && vsir_register_is_descriptor(param)) + { + /* SM5.1 places a symbol identifier in idx[0] and moves +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index 8fd8945151f..d4a9d391477 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -23,6 +23,8 @@ + #include + #include + ++/* VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG"); */ ++ + static inline int char_to_int(char c) + { + if ('0' <= c && c <= '9') +@@ -888,6 +890,21 @@ static void vkd3d_shader_scan_combined_sampler_declaration( + &semantic->resource.range, semantic->resource_type, VKD3D_SHADER_RESOURCE_DATA_FLOAT); + } + ++static const struct vkd3d_shader_descriptor_info1 *find_descriptor( ++ const struct vkd3d_shader_scan_descriptor_info1 *info, ++ enum vkd3d_shader_descriptor_type type, unsigned int register_id) ++{ ++ for (unsigned int i = 0; i < info->descriptor_count; ++i) ++ { ++ const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i]; ++ ++ if (d->type == type && d->register_id == register_id) ++ return d; ++ } ++ ++ return NULL; ++} ++ + static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_context *context, + const struct vkd3d_shader_register *resource, const struct vkd3d_shader_register *sampler) + { +@@ -913,7 +930,6 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co + + if (vkd3d_shader_ver_ge(context->version, 5, 1)) + { +- const struct vkd3d_shader_scan_descriptor_info1 *info = context->scan_descriptor_info; + const struct vkd3d_shader_descriptor_info1 *d; + bool dynamic_resource, dynamic_sampler; + +@@ -928,30 +944,13 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co + if (dynamic_resource || dynamic_sampler) + return; + +- for (i = 0; i < info->descriptor_count; ++i) +- { +- d = &info->descriptors[i]; +- if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SRV) +- continue; +- if (d->register_id != resource->idx[0].offset) +- continue; ++ if ((d = find_descriptor(context->scan_descriptor_info, ++ VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource->idx[0].offset))) + resource_space = d->register_space; +- break; +- } + +- if (sampler) +- { +- for (i = 0; i < info->descriptor_count; ++i) +- { +- d = &info->descriptors[i]; +- if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) +- continue; +- if (d->register_id != sampler->idx[0].offset) +- continue; +- sampler_space = d->register_space; +- break; +- } +- } ++ if (sampler && (d = find_descriptor(context->scan_descriptor_info, ++ VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler->idx[0].offset))) ++ sampler_space = d->register_space; + } + + for (i = 0; i < info->combined_sampler_count; ++i) +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index a93fa7160f7..102d49a38e0 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -49,7 +49,7 @@ + #include "vkd3d_common.h" + #include "vkd3d_memory.h" + #include "vkd3d_shader.h" +-#include "wine/list.h" ++#include "list.h" + + #include + #include +@@ -196,6 +196,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH = 8306, + VKD3D_SHADER_WARNING_DXIL_INVALID_MASK = 8307, + VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308, ++ VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT = 8309, + + VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, + VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001, +@@ -793,10 +794,12 @@ struct vkd3d_shader_version + + struct vkd3d_shader_immediate_constant_buffer + { ++ unsigned int register_idx; + enum vkd3d_data_type data_type; + /* total count is element_count * component_count */ + unsigned int element_count; + unsigned int component_count; ++ bool is_null; + uint32_t data[]; + }; + +diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +index f06f564d6ea..e0eb9f3d3fe 100644 +--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h ++++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +@@ -32,8 +32,8 @@ + #include "vkd3d_blob.h" + #include "vkd3d_memory.h" + #include "vkd3d_utf8.h" +-#include "wine/list.h" +-#include "wine/rbtree.h" ++#include "list.h" ++#include "rbtree.h" + + #include "vkd3d.h" + #include "vkd3d_shader.h" +-- +2.43.0 +