diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-e69f3da089d472b723b016ef67c04c0f954.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-e69f3da089d472b723b016ef67c04c0f954.patch index 9ace9221..0d001cc8 100644 --- a/patches/vkd3d-latest/0001-Updated-vkd3d-to-e69f3da089d472b723b016ef67c04c0f954.patch +++ b/patches/vkd3d-latest/0001-Updated-vkd3d-to-e69f3da089d472b723b016ef67c04c0f954.patch @@ -1,38 +1,40 @@ -From 6539b8d0685337b99debbe678354c3a9a58747d7 Mon Sep 17 00:00:00 2001 +From 12f8d6b72e24fcc4d9615b265012eafb9dd3d5e5 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Mon, 26 May 2025 07:03:34 +1000 Subject: [PATCH] Updated vkd3d to e69f3da089d472b723b016ef67c04c0f954fa792. --- dlls/msado15/tests/msado15.c | 2 +- - libs/vkd3d/include/private/spirv_grammar.h | 561 +------- - libs/vkd3d/include/private/vkd3d_common.h | 4 +- + libs/vkd3d/include/private/spirv_grammar.h | 561 +--- + libs/vkd3d/include/private/vkd3d_common.h | 22 +- libs/vkd3d/include/private/vkd3d_version.h | 2 +- libs/vkd3d/include/vkd3d_shader.h | 38 +- libs/vkd3d/libs/vkd3d-common/blob.c | 1 + - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 46 +- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 36 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 151 ++- + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 64 +- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 43 +- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 690 ++--- libs/vkd3d/libs/vkd3d-shader/fx.c | 2 +- libs/vkd3d/libs/vkd3d-shader/glsl.c | 74 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 70 + - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 16 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 82 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 22 +- libs/vkd3d/libs/vkd3d-shader/hlsl.l | 2 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 60 +- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 752 ++++++++--- - .../libs/vkd3d-shader/hlsl_constant_ops.c | 243 ++-- - libs/vkd3d/libs/vkd3d-shader/ir.c | 1132 ++++++++++------- - libs/vkd3d/libs/vkd3d-shader/msl.c | 45 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 161 +- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 936 +++++-- + .../libs/vkd3d-shader/hlsl_constant_ops.c | 349 ++- + libs/vkd3d/libs/vkd3d-shader/ir.c | 2320 +++++++++++------ + libs/vkd3d/libs/vkd3d-shader/msl.c | 170 +- libs/vkd3d/libs/vkd3d-shader/preproc.l | 13 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 319 ++--- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 43 +- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 222 +--- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 94 +- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 775 +++--- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 57 +- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 250 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 174 +- .../vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c | 17 +- - libs/vkd3d/libs/vkd3d/command.c | 2 +- + libs/vkd3d/libs/vkd3d/command.c | 92 +- + libs/vkd3d/libs/vkd3d/device.c | 24 +- libs/vkd3d/libs/vkd3d/state.c | 6 +- libs/vkd3d/libs/vkd3d/utils.c | 3 +- - 28 files changed, 2184 insertions(+), 1772 deletions(-) + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 5 +- + 30 files changed, 4257 insertions(+), 2700 deletions(-) diff --git a/dlls/msado15/tests/msado15.c b/dlls/msado15/tests/msado15.c index 03eaab92b39..3f4b55d2916 100644 @@ -1033,7 +1035,7 @@ index 34cadd9bd58..2aac5a6558c 100644 0x191c, "OpMaskedGatherINTEL", 6, (struct spirv_parser_instruction_operand[]) diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h -index 08341304eea..8b63acf68e1 100644 +index 08341304eea..c2e957a2fea 100644 --- a/libs/vkd3d/include/private/vkd3d_common.h +++ b/libs/vkd3d/include/private/vkd3d_common.h @@ -38,6 +38,8 @@ @@ -1054,6 +1056,31 @@ index 08341304eea..8b63acf68e1 100644 return __builtin_popcount(v); #else v -= (v >> 1) & 0x55555555; +@@ -341,6 +343,24 @@ static inline unsigned int vkd3d_log2i(unsigned int x) + #endif + } + ++static inline unsigned int vkd3d_ctz(uint32_t v) ++{ ++#ifdef HAVE_BUILTIN_CTZ ++ return __builtin_ctz(v); ++#else ++ unsigned int c = 31; ++ ++ v &= -v; ++ c = (v & 0x0000ffff) ? c - 16 : c; ++ c = (v & 0x00ff00ff) ? c - 8 : c; ++ c = (v & 0x0f0f0f0f) ? c - 4 : c; ++ c = (v & 0x33333333) ? c - 2 : c; ++ c = (v & 0x55555555) ? c - 1 : c; ++ ++ return c; ++#endif ++} ++ + static inline void *vkd3d_memmem( const void *haystack, size_t haystack_len, const void *needle, size_t needle_len) + { + const char *str = haystack; diff --git a/libs/vkd3d/include/private/vkd3d_version.h b/libs/vkd3d/include/private/vkd3d_version.h index 0edc4428022..687751d6a5f 100644 --- a/libs/vkd3d/include/private/vkd3d_version.h @@ -1137,7 +1164,7 @@ index f60ef7db769..c2c6ad67804 100644 #include "vkd3d.h" #include "vkd3d_blob.h" diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index 6425a8f62d2..e2fb8b12998 100644 +index 6425a8f62d2..6f8fbe84b90 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -390,27 +390,10 @@ static void shader_print_resource_type(struct vkd3d_d3d_asm_compiler *compiler, @@ -1171,7 +1198,39 @@ index 6425a8f62d2..e2fb8b12998 100644 else vkd3d_string_buffer_printf(&compiler->buffer, "%s%s", compiler->colours.error, type, compiler->colours.reset); -@@ -851,7 +834,7 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const +@@ -610,6 +593,18 @@ static void shader_print_uint_literal(struct vkd3d_d3d_asm_compiler *compiler, + prefix, compiler->colours.literal, i, compiler->colours.reset, suffix); + } + ++static void shader_print_int64_literal(struct vkd3d_d3d_asm_compiler *compiler, ++ const char *prefix, int64_t i, const char *suffix) ++{ ++ /* Note that we need to handle INT64_MIN here as well. */ ++ if (i < 0) ++ vkd3d_string_buffer_printf(&compiler->buffer, "%s-%s%"PRIu64"%s%s", ++ prefix, compiler->colours.literal, -(uint64_t)i, compiler->colours.reset, suffix); ++ else ++ vkd3d_string_buffer_printf(&compiler->buffer, "%s%s%"PRId64"%s%s", ++ prefix, compiler->colours.literal, i, compiler->colours.reset, suffix); ++} ++ + static void shader_print_uint64_literal(struct vkd3d_d3d_asm_compiler *compiler, + const char *prefix, uint64_t i, const char *suffix) + { +@@ -810,6 +805,12 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const + if (reg->dimension == VSIR_DIMENSION_VEC4) + shader_print_double_literal(compiler, ", ", reg->u.immconst_f64[1], ""); + } ++ else if (reg->data_type == VSIR_DATA_I64) ++ { ++ shader_print_int64_literal(compiler, "", reg->u.immconst_u64[0], ""); ++ if (reg->dimension == VSIR_DIMENSION_VEC4) ++ shader_print_int64_literal(compiler, "", reg->u.immconst_u64[1], ""); ++ } + else if (reg->data_type == VSIR_DATA_U64) + { + shader_print_uint64_literal(compiler, "", reg->u.immconst_u64[0], ""); +@@ -851,7 +852,7 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const && reg->type != VKD3DSPR_NULL && reg->type != VKD3DSPR_DEPTHOUT) { @@ -1180,7 +1239,7 @@ index 6425a8f62d2..e2fb8b12998 100644 { bool is_sm_5_1 = vkd3d_shader_ver_ge(&compiler->shader_version, 5, 1); -@@ -879,10 +862,10 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const +@@ -879,10 +880,10 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const /* For descriptors in sm < 5.1 we move the reg->idx values up one slot * to normalise with 5.1. * Here we should ignore it if it's a descriptor in sm < 5.1. */ @@ -1193,7 +1252,7 @@ index 6425a8f62d2..e2fb8b12998 100644 shader_print_subscript(compiler, reg->idx[2].offset, reg->idx[2].rel_addr); } } -@@ -974,6 +957,22 @@ static void shader_print_reg_type(struct vkd3d_d3d_asm_compiler *compiler, +@@ -974,6 +975,22 @@ static void shader_print_reg_type(struct vkd3d_d3d_asm_compiler *compiler, vkd3d_string_buffer_printf(buffer, ">%s", suffix); } @@ -1216,7 +1275,7 @@ index 6425a8f62d2..e2fb8b12998 100644 static void shader_print_write_mask(struct vkd3d_d3d_asm_compiler *compiler, const char *prefix, uint32_t mask, const char *suffix) { -@@ -1528,6 +1527,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, +@@ -1528,6 +1545,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, vkd3d_string_buffer_printf(buffer, " %sx%u%s", compiler->colours.reg, ins->declaration.indexable_temp.register_idx, compiler->colours.reset); shader_print_subscript(compiler, ins->declaration.indexable_temp.register_size, NULL); @@ -1225,7 +1284,7 @@ index 6425a8f62d2..e2fb8b12998 100644 if (ins->declaration.indexable_temp.alignment) shader_print_uint_literal(compiler, ", align ", ins->declaration.indexable_temp.alignment, ""); diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 751e5578276..a9195b3454a 100644 +index 751e5578276..fbf9de20278 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -246,6 +246,7 @@ struct vkd3d_shader_sm1_parser @@ -1369,6 +1428,17 @@ index 751e5578276..a9195b3454a 100644 sm1->ptr = sm1->start; return VKD3D_OK; +@@ -1504,8 +1506,8 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c + for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i) + program->flat_constant_count[i] = get_external_constant_count(&sm1, i); + +- if (sm1.p.failed && ret >= 0) +- ret = VKD3D_ERROR_INVALID_SHADER; ++ if (ret >= 0 && sm1.p.status < 0) ++ ret = sm1.p.status; + + if (ret < 0) + { @@ -1952,7 +1954,7 @@ static void d3dbc_write_vsir_dcl(struct d3dbc_compiler *d3dbc, const struct vkd3 reg_id = semantic->resource.reg.reg.idx[0].offset; @@ -1378,11 +1448,30 @@ index 751e5578276..a9195b3454a 100644 { vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_TYPE, "dcl instruction with register type %u.", semantic->resource.reg.reg.type); +@@ -2148,9 +2150,6 @@ int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, + if ((result = vsir_allocate_temp_registers(program, message_context))) + return result; + +- if ((result = vsir_update_dcl_temps(program, message_context))) +- return result; +- + d3dbc.program = program; + d3dbc.message_context = message_context; + switch (version->type) diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index c448e000cf9..fb2cde4501a 100644 +index c448e000cf9..f82644d4679 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -892,6 +892,8 @@ struct sm6_parser +@@ -45,6 +45,8 @@ static const unsigned int MAX_GS_OUTPUT_STREAMS = 4; + (VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(0) \ + | VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(1)) + ++#define DXIL_TYPE_SIGNED 0x1u ++ + enum bitcode_block_id + { + BLOCKINFO_BLOCK = 0, +@@ -892,6 +894,8 @@ struct sm6_parser const uint32_t *ptr, *start, *end; unsigned int bitpos; @@ -1391,7 +1480,152 @@ index c448e000cf9..fb2cde4501a 100644 struct dxil_block root_block; struct dxil_block *current_block; -@@ -2437,7 +2439,7 @@ static struct vkd3d_shader_src_param *instruction_src_params_alloc(struct vkd3d_ +@@ -915,6 +919,7 @@ struct sm6_parser + struct vkd3d_shader_dst_param *input_params; + struct vkd3d_shader_dst_param *patch_constant_params; + uint32_t io_regs_declared[VKD3D_BITMAP_SIZE(VKD3DSPR_COUNT)]; ++ struct vkd3d_shader_src_param *outpointid_param; + + struct sm6_function *functions; + size_t function_count; +@@ -976,7 +981,7 @@ static uint32_t sm6_parser_read_uint32(struct sm6_parser *sm6) + { + if (sm6_parser_is_end(sm6)) + { +- sm6->p.failed = true; ++ sm6->p.status = VKD3D_ERROR_INVALID_SHADER; + return 0; + } + return *sm6->ptr++; +@@ -994,7 +999,7 @@ static uint32_t sm6_parser_read_bits(struct sm6_parser *sm6, unsigned int length + + if (sm6_parser_is_end(sm6)) + { +- sm6->p.failed = true; ++ sm6->p.status = VKD3D_ERROR_INVALID_SHADER; + return 0; + } + +@@ -1006,7 +1011,7 @@ static uint32_t sm6_parser_read_bits(struct sm6_parser *sm6, unsigned int length + ++sm6->ptr; + if (sm6_parser_is_end(sm6) && l < length) + { +- sm6->p.failed = true; ++ sm6->p.status = VKD3D_ERROR_INVALID_SHADER; + return bits; + } + sm6->bitpos = 0; +@@ -1028,7 +1033,7 @@ static uint64_t sm6_parser_read_vbr(struct sm6_parser *sm6, unsigned int length) + + if (sm6_parser_is_end(sm6)) + { +- sm6->p.failed = true; ++ sm6->p.status = VKD3D_ERROR_INVALID_SHADER; + return 0; + } + +@@ -1039,9 +1044,10 @@ static uint64_t sm6_parser_read_vbr(struct sm6_parser *sm6, unsigned int length) + bits = sm6_parser_read_bits(sm6, length); + result |= (uint64_t)(bits & mask) << shift; + shift += length - 1; +- } while ((bits & flag) && !sm6->p.failed && shift < 64); ++ } while ((bits & flag) && (sm6->p.status >= 0) && shift < 64); + +- sm6->p.failed |= !!(bits & flag); ++ if (bits & flag) ++ sm6->p.status = VKD3D_ERROR_INVALID_SHADER; + + return result; + } +@@ -1053,7 +1059,7 @@ static void sm6_parser_align_32(struct sm6_parser *sm6) + + if (sm6_parser_is_end(sm6)) + { +- sm6->p.failed = true; ++ sm6->p.status = VKD3D_ERROR_INVALID_SHADER; + return; + } + +@@ -1144,8 +1150,8 @@ static enum vkd3d_result sm6_parser_read_unabbrev_record(struct sm6_parser *sm6) + + for (i = 0; i < count; ++i) + record->operands[i] = sm6_parser_read_vbr(sm6, 6); +- if (sm6->p.failed) +- ret = VKD3D_ERROR_INVALID_SHADER; ++ if (sm6->p.status < 0) ++ ret = sm6->p.status; + + if (ret < 0 || (ret = dxil_block_add_record(block, record)) < 0) + vkd3d_free(record); +@@ -1156,25 +1162,25 @@ static enum vkd3d_result sm6_parser_read_unabbrev_record(struct sm6_parser *sm6) + static bool sm6_parser_read_literal_operand(struct sm6_parser *sm6, uint64_t context, uint64_t *op) + { + *op = context; +- return !sm6->p.failed; ++ return sm6->p.status >= 0; + } + + static bool sm6_parser_read_fixed_operand(struct sm6_parser *sm6, uint64_t context, uint64_t *op) + { + *op = sm6_parser_read_bits(sm6, context); +- return !sm6->p.failed; ++ return sm6->p.status >= 0; + } + + static bool sm6_parser_read_vbr_operand(struct sm6_parser *sm6, uint64_t context, uint64_t *op) + { + *op = sm6_parser_read_vbr(sm6, context); +- return !sm6->p.failed; ++ return sm6->p.status >= 0; + } + + static bool sm6_parser_read_char6_operand(struct sm6_parser *sm6, uint64_t context, uint64_t *op) + { + *op = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._"[sm6_parser_read_bits(sm6, 6)]; +- return !sm6->p.failed; ++ return sm6->p.status >= 0; + } + + static bool sm6_parser_read_blob_operand(struct sm6_parser *sm6, uint64_t context, uint64_t *op) +@@ -1194,7 +1200,7 @@ static enum vkd3d_result dxil_abbrev_init(struct dxil_abbrev *abbrev, unsigned i + + abbrev->is_array = false; + +- for (i = 0, prev_type = 0; i < count && !sm6->p.failed; ++i) ++ for (i = 0, prev_type = 0; i < count && (sm6->p.status >= 0); ++i) + { + if (sm6_parser_read_bits(sm6, 1)) + { +@@ -1247,7 +1253,7 @@ static enum vkd3d_result dxil_abbrev_init(struct dxil_abbrev *abbrev, unsigned i + + abbrev->count = count; + +- return sm6->p.failed ? VKD3D_ERROR_INVALID_SHADER : VKD3D_OK; ++ return sm6->p.status; + } + + static enum vkd3d_result sm6_parser_add_global_abbrev(struct sm6_parser *sm6) +@@ -1459,7 +1465,7 @@ static enum vkd3d_result dxil_block_read(struct dxil_block *parent, struct sm6_p + } + break; + } +- } while (!sm6->p.failed); ++ } while (sm6->p.status >= 0); + + return VKD3D_ERROR_INVALID_SHADER; + } +@@ -1510,8 +1516,8 @@ static enum vkd3d_result dxil_block_init(struct dxil_block *block, const struct + block->length = sm6_parser_read_uint32(sm6); + block->start = sm6->ptr - sm6->start; + +- if (sm6->p.failed) +- return VKD3D_ERROR_INVALID_SHADER; ++ if (sm6->p.status < 0) ++ return sm6->p.status; + + if ((block->abbrev_count = sm6_parser_compute_global_abbrev_count_for_block_id(sm6, block->id))) + { +@@ -2437,7 +2443,7 @@ static struct vkd3d_shader_src_param *instruction_src_params_alloc(struct vkd3d_ { struct vkd3d_shader_src_param *params; @@ -1400,7 +1634,7 @@ index c448e000cf9..fb2cde4501a 100644 { ERR("Failed to allocate src params.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -@@ -2454,7 +2456,7 @@ static struct vkd3d_shader_dst_param *instruction_dst_params_alloc(struct vkd3d_ +@@ -2454,7 +2460,7 @@ static struct vkd3d_shader_dst_param *instruction_dst_params_alloc(struct vkd3d_ { struct vkd3d_shader_dst_param *params; @@ -1409,18 +1643,34 @@ index c448e000cf9..fb2cde4501a 100644 { ERR("Failed to allocate dst params.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -@@ -2473,7 +2475,7 @@ static void register_init_with_id(struct vkd3d_shader_register *reg, +@@ -2473,8 +2479,11 @@ static void register_init_with_id(struct vkd3d_shader_register *reg, reg->idx[0].offset = id; } -static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type) -+static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type, struct sm6_parser *dxil) ++static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type, ++ uint32_t type_flags, struct sm6_parser *dxil) { ++ bool is_signed = type_flags & DXIL_TYPE_SIGNED; ++ if (type->class == TYPE_CLASS_INTEGER) { -@@ -2490,7 +2492,8 @@ static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type) + switch (type->u.width) +@@ -2482,15 +2491,16 @@ static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type) + case 1: + return VSIR_DATA_BOOL; + case 8: +- return VSIR_DATA_U8; ++ return is_signed ? VSIR_DATA_I8 : VSIR_DATA_U8; + case 16: +- return VSIR_DATA_U16; ++ return is_signed ? VSIR_DATA_I16 : VSIR_DATA_U16; + case 32: +- return VSIR_DATA_U32; ++ return is_signed ? VSIR_DATA_I32 : VSIR_DATA_U32; case 64: - return VSIR_DATA_U64; +- return VSIR_DATA_U64; ++ return is_signed ? VSIR_DATA_I64 : VSIR_DATA_U64; default: - FIXME("Unhandled width %u.\n", type->u.width); + vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_UNSUPPORTED, @@ -1428,7 +1678,7 @@ index c448e000cf9..fb2cde4501a 100644 return VSIR_DATA_U32; } } -@@ -2505,12 +2508,14 @@ static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type) +@@ -2505,12 +2515,14 @@ static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type) case 64: return VSIR_DATA_F64; default: @@ -1445,100 +1695,399 @@ index c448e000cf9..fb2cde4501a 100644 return VSIR_DATA_U32; } -@@ -2597,7 +2602,7 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str +@@ -2572,6 +2584,16 @@ static void register_convert_to_minimum_precision(struct vkd3d_shader_register * + } + break; + ++ case VSIR_DATA_I16: ++ reg->data_type = VSIR_DATA_I32; ++ reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_INT_16; ++ if (reg->type == VKD3DSPR_IMMCONST) ++ { ++ for (i = 0; i < VSIR_DIMENSION_VEC4; ++i) ++ reg->u.immconst_u32[i] = (int16_t)reg->u.immconst_u32[i]; ++ } ++ break; ++ + case VSIR_DATA_U16: + reg->data_type = VSIR_DATA_U32; + reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_UINT_16; +@@ -2590,14 +2612,14 @@ static void register_convert_to_minimum_precision(struct vkd3d_shader_register * + static void register_index_address_init(struct vkd3d_shader_register_index *idx, const struct sm6_value *address, + struct sm6_parser *sm6); + +-static void sm6_register_from_value(struct vkd3d_shader_register *reg, const struct sm6_value *value, +- struct sm6_parser *sm6) ++static void vsir_register_from_dxil_value(struct vkd3d_shader_register *reg, ++ const struct sm6_value *value, uint32_t type_flags, struct sm6_parser *dxil) + { + const struct sm6_type *scalar_type; enum vsir_data_type data_type; scalar_type = sm6_type_get_scalar_type(value->type, 0); - data_type = vsir_data_type_from_dxil(scalar_type); -+ data_type = vsir_data_type_from_dxil(scalar_type, sm6); ++ data_type = vsir_data_type_from_dxil(scalar_type, type_flags, dxil); switch (value->value_type) { -@@ -2756,7 +2761,7 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, +@@ -2609,21 +2631,21 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str + case VALUE_TYPE_ICB: + vsir_register_init(reg, VKD3DSPR_IMMCONSTBUFFER, data_type, 2); + reg->idx[0].offset = value->u.icb.id; +- register_index_address_init(®->idx[1], value->u.icb.index.index, sm6); ++ register_index_address_init(®->idx[1], value->u.icb.index.index, dxil); + reg->idx[1].is_in_bounds = value->u.icb.index.is_in_bounds; + break; + + case VALUE_TYPE_IDXTEMP: + vsir_register_init(reg, VKD3DSPR_IDXTEMP, data_type, 2); + reg->idx[0].offset = value->u.idxtemp.id; +- register_index_address_init(®->idx[1], value->u.idxtemp.index.index, sm6); ++ register_index_address_init(®->idx[1], value->u.idxtemp.index.index, dxil); + reg->idx[1].is_in_bounds = value->u.idxtemp.index.is_in_bounds; + break; + + case VALUE_TYPE_GROUPSHAREDMEM: + vsir_register_init(reg, VKD3DSPR_GROUPSHAREDMEM, data_type, 2); + reg->idx[0].offset = value->u.groupsharedmem.id; +- register_index_address_init(®->idx[1], value->u.groupsharedmem.index.index, sm6); ++ register_index_address_init(®->idx[1], value->u.groupsharedmem.index.index, dxil); + reg->idx[1].is_in_bounds = value->u.groupsharedmem.index.is_in_bounds; + break; + +@@ -2720,11 +2742,11 @@ static void src_param_init_vector(struct vkd3d_shader_src_param *param, unsigned + param->modifiers = VKD3DSPSM_NONE; + } + +-static void src_param_init_from_value(struct vkd3d_shader_src_param *param, const struct sm6_value *src, +- struct sm6_parser *sm6) ++static void src_param_init_from_value(struct vkd3d_shader_src_param *param, ++ const struct sm6_value *src, uint32_t type_flags, struct sm6_parser *dxil) + { + src_param_init(param); +- sm6_register_from_value(¶m->reg, src, sm6); ++ vsir_register_from_dxil_value(¶m->reg, src, type_flags, dxil); + } + + static void src_param_init_vector_from_reg(struct vkd3d_shader_src_param *param, +@@ -2756,9 +2778,9 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, } else { - struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(sm6->p.program, 1); + struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(sm6->program, 1); if (rel_addr) - src_param_init_from_value(rel_addr, address, sm6); +- src_param_init_from_value(rel_addr, address, sm6); ++ src_param_init_from_value(rel_addr, address, 0, sm6); idx->offset = 0; -@@ -3224,7 +3229,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + idx->rel_addr = rel_addr; + } +@@ -2783,17 +2805,19 @@ static void src_param_init_vector_from_handle(struct sm6_parser *sm6, + src_param_init_vector_from_reg(param, ®); + } + +-static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) ++static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instruction *ins, ++ uint32_t type_flags, struct sm6_parser *dxil) + { +- struct sm6_value *dst = sm6_parser_get_current_value(sm6); ++ struct sm6_value *dst = sm6_parser_get_current_value(dxil); + struct vkd3d_shader_dst_param *param; + +- if (!(param = instruction_dst_params_alloc(ins, 1, sm6))) ++ if (!(param = instruction_dst_params_alloc(ins, 1, dxil))) + return false; + + dst_param_init(param); +- sm6_parser_init_ssa_value(sm6, dst); +- sm6_register_from_value(¶m->reg, dst, sm6); ++ sm6_parser_init_ssa_value(dxil, dst); ++ vsir_register_from_dxil_value(¶m->reg, dst, type_flags, dxil); ++ + return true; + } + +@@ -2805,7 +2829,7 @@ static void instruction_dst_param_init_ssa_vector(struct vkd3d_shader_instructio + + dst_param_init_vector(param, component_count); + sm6_parser_init_ssa_value(sm6, dst); +- sm6_register_from_value(¶m->reg, dst, sm6); ++ vsir_register_from_dxil_value(¶m->reg, dst, 0, sm6); + } + + static bool instruction_dst_param_init_uint_temp_vector(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) +@@ -2987,8 +3011,7 @@ static bool sm6_value_validate_is_backward_ref(const struct sm6_value *value, st + { + if (!value->is_back_ref) + { +- FIXME("Forward-referenced pointers are not supported.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "Forward-referenced pointer declarations are not supported."); + return false; + } +@@ -3200,8 +3223,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + /* Multidimensional arrays are emitted in flattened form. */ + if (elem_type->class != TYPE_CLASS_INTEGER && elem_type->class != TYPE_CLASS_FLOAT) + { +- FIXME("Unhandled element type %u for data array.\n", elem_type->class); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "The element data type for an immediate constant buffer is not scalar integer or floating point."); + return VKD3D_ERROR_INVALID_SHADER; + } +@@ -3224,7 +3246,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co "Out of memory allocating an immediate constant buffer of count %u.", count); return VKD3D_ERROR_OUT_OF_MEMORY; } - if (!shader_instruction_array_add_icb(&sm6->p.program->instructions, icb)) -+ if (!shader_instruction_array_add_icb(&sm6->program->instructions, icb)) ++ if (!vsir_program_add_icb(sm6->program, icb)) { ERR("Failed to store icb object.\n"); vkd3d_free(icb); -@@ -3237,7 +3242,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co +@@ -3237,7 +3259,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co dst->u.data = icb; icb->register_idx = sm6->icb_count++; - icb->data_type = vsir_data_type_from_dxil(elem_type); -+ icb->data_type = vsir_data_type_from_dxil(elem_type, sm6); ++ icb->data_type = vsir_data_type_from_dxil(elem_type, 0, sm6); icb->element_count = type->u.array.count; icb->component_count = 1; icb->is_null = !operands; -@@ -3653,7 +3658,7 @@ static bool bitcode_parse_alignment(uint64_t encoded_alignment, unsigned int *al +@@ -3254,6 +3276,12 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + icb->data_type = VSIR_DATA_F32; + break; - static struct vkd3d_shader_instruction *sm6_parser_require_space(struct sm6_parser *sm6, size_t extra) - { -- struct vkd3d_shader_instruction_array *instructions = &sm6->p.program->instructions; -+ struct vkd3d_shader_instruction_array *instructions = &sm6->program->instructions; ++ case VSIR_DATA_I16: ++ for (i = 0; i < count; ++i) ++ icb->data[i] = (int16_t)operands[i]; ++ icb->data_type = VSIR_DATA_I32; ++ break; ++ + case VSIR_DATA_U16: + for (i = 0; i < count; ++i) + icb->data[i] = (int16_t)operands[i]; +@@ -3261,12 +3289,14 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + break; - if (!shader_instruction_array_reserve(instructions, instructions->count + extra)) - { -@@ -3663,14 +3668,15 @@ static struct vkd3d_shader_instruction *sm6_parser_require_space(struct sm6_pars - return &instructions->elements[instructions->count]; + case VSIR_DATA_F32: ++ case VSIR_DATA_I32: + case VSIR_DATA_U32: + for (i = 0; i < count; ++i) + icb->data[i] = operands[i]; + break; + + case VSIR_DATA_F64: ++ case VSIR_DATA_I64: + case VSIR_DATA_U64: + data64 = (uint64_t *)icb->data; + for (i = 0; i < count; ++i) +@@ -3651,26 +3681,19 @@ static bool bitcode_parse_alignment(uint64_t encoded_alignment, unsigned int *al + return true; } --/* Space should be reserved before calling this. It is intended to require no checking of the returned pointer. */ - static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_parser *sm6, -- enum vkd3d_shader_opcode handler_idx) +-static struct vkd3d_shader_instruction *sm6_parser_require_space(struct sm6_parser *sm6, size_t extra) ++static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_parser *sm6, + enum vkd3d_shader_opcode op) { +- struct vkd3d_shader_instruction_array *instructions = &sm6->p.program->instructions; ++ struct vkd3d_shader_instruction *ins; + +- if (!shader_instruction_array_reserve(instructions, instructions->count + extra)) ++ if (!(ins = vsir_program_append(sm6->program))) + { +- ERR("Failed to allocate instruction.\n"); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ "Out of memory allocating instruction."); + return NULL; + } +- return &instructions->elements[instructions->count]; +-} ++ vsir_instruction_init(ins, &sm6->p.location, op); + +-/* Space should be reserved before calling this. It is intended to require no checking of the returned pointer. */ +-static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_parser *sm6, +- enum vkd3d_shader_opcode handler_idx) +-{ - struct vkd3d_shader_instruction *ins = sm6_parser_require_space(sm6, 1); - VKD3D_ASSERT(ins); - vsir_instruction_init(ins, &sm6->p.location, handler_idx); - ++sm6->p.program->instructions.count; -+ struct vkd3d_shader_instruction *ins; -+ -+ if (!(ins = vsir_program_append(sm6->program))) -+ return NULL; -+ vsir_instruction_init(ins, &sm6->p.location, op); -+ return ins; } -@@ -3690,7 +3696,15 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const stru +@@ -3679,7 +3702,8 @@ static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type + { + struct vkd3d_shader_instruction *ins; + +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_IMMEDIATE_CONSTANT_BUFFER); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_IMMEDIATE_CONSTANT_BUFFER))) ++ return; + /* The icb value index will be resolved later so forward references can be handled. */ + ins->declaration.icb = (void *)(intptr_t)init; + dst->value_type = VALUE_TYPE_ICB; +@@ -3690,12 +3714,22 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const stru unsigned int count, unsigned int alignment, bool has_function_scope, unsigned int init, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { - enum vsir_data_type data_type = vsir_data_type_from_dxil(elem_type); -+ enum vsir_data_type data_type = vsir_data_type_from_dxil(elem_type, sm6); ++ enum vsir_data_type data_type = vsir_data_type_from_dxil(elem_type, 0, sm6); + + if (!(sm6->program->global_flags & VKD3DSGF_FORCE_NATIVE_LOW_PRECISION)) + { + if (data_type == VSIR_DATA_F16) + data_type = VSIR_DATA_F32; ++ else if (data_type == VSIR_DATA_I16) ++ data_type = VSIR_DATA_I32; + else if (data_type == VSIR_DATA_U16) + data_type = VSIR_DATA_U32; + } if (ins) vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_DCL_INDEXABLE_TEMP); -@@ -3969,7 +3983,7 @@ static bool resolve_forward_zero_initialiser(size_t index, struct sm6_parser *sm +- else +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_INDEXABLE_TEMP); ++ else if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_INDEXABLE_TEMP))) ++ return; + ins->declaration.indexable_temp.register_idx = sm6->indexable_temp_count++; + ins->declaration.indexable_temp.register_size = count; + ins->declaration.indexable_temp.alignment = alignment; +@@ -3715,23 +3749,21 @@ static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6 + struct vkd3d_shader_instruction *ins; + unsigned int byte_count; + +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TGSM_RAW); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TGSM_RAW))) ++ return; + dst_param_init(&ins->declaration.tgsm_raw.reg); + dst->value_type = VALUE_TYPE_GROUPSHAREDMEM; + dst->u.groupsharedmem.id = sm6->tgsm_count++; + dst->structure_stride = 0; +- sm6_register_from_value(&ins->declaration.tgsm_raw.reg.reg, dst, sm6); ++ vsir_register_from_dxil_value(&ins->declaration.tgsm_raw.reg.reg, dst, 0, sm6); + ins->declaration.tgsm_raw.alignment = alignment; + byte_count = elem_type->u.width / CHAR_BIT; + /* Convert minimum precision types to their 32-bit equivalent. */ + if (byte_count == 2) + byte_count = 4; + if (byte_count != 4) +- { +- FIXME("Unsupported byte count %u.\n", byte_count); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "Raw TGSM byte count %u is not supported.", byte_count); +- } + ins->declaration.tgsm_raw.byte_count = byte_count; + /* The initialiser value index will be resolved later when forward references can be handled. */ + ins->flags = init; +@@ -3742,7 +3774,8 @@ static void sm6_parser_declare_tgsm_structured(struct sm6_parser *sm6, const str + { + struct vkd3d_shader_instruction *ins; + +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TGSM_STRUCTURED); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TGSM_STRUCTURED))) ++ return; + dst_param_init(&ins->declaration.tgsm_structured.reg); + dst->value_type = VALUE_TYPE_GROUPSHAREDMEM; + dst->u.groupsharedmem.id = sm6->tgsm_count++; +@@ -3750,13 +3783,10 @@ static void sm6_parser_declare_tgsm_structured(struct sm6_parser *sm6, const str + /* Convert minimum precision types to their 32-bit equivalent. */ + if (dst->structure_stride == 2) + dst->structure_stride = 4; +- sm6_register_from_value(&ins->declaration.tgsm_structured.reg.reg, dst, sm6); ++ vsir_register_from_dxil_value(&ins->declaration.tgsm_structured.reg.reg, dst, 0, sm6); + if (dst->structure_stride != 4) +- { +- FIXME("Unsupported structure stride %u.\n", dst->structure_stride); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "Structured TGSM byte stride %u is not supported.", dst->structure_stride); +- } + ins->declaration.tgsm_structured.alignment = alignment; + ins->declaration.tgsm_structured.byte_stride = dst->structure_stride; + ins->declaration.tgsm_structured.structure_count = count; +@@ -3781,8 +3811,7 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ + { + if (!sm6_type_is_scalar(type->u.array.elem_type)) + { +- FIXME("Unsupported nested type class %u.\n", type->u.array.elem_type->class); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "Global array variables with nested type class %u are not supported.", + type->u.array.elem_type->class); + return false; +@@ -3797,8 +3826,7 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ + } + else + { +- FIXME("Unsupported type class %u.\n", type->class); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "Global variables of type class %u are not supported.", type->class); + return false; + } +@@ -3903,14 +3931,13 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ + } + else + { +- FIXME("Unhandled address space %"PRIu64".\n", address_space); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "Global variables with address space %"PRIu64" are not supported.", address_space); + return false; + } + + ++sm6->value_count; +- return true; ++ return (sm6->p.status >= 0); + } + + static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_initialiser( +@@ -3961,17 +3988,16 @@ static bool resolve_forward_zero_initialiser(size_t index, struct sm6_parser *sm + return false; + } + +- FIXME("Non-zero initialisers are not supported.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "Non-zero TGSM initialisers are not supported."); + return false; + } static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) { - struct vsir_program_iterator it = vsir_program_iterator(&sm6->p.program->instructions); +- size_t i, count, base_value_idx = sm6->value_count; + struct vsir_program_iterator it = vsir_program_iterator(&sm6->program->instructions); - size_t i, count, base_value_idx = sm6->value_count; const struct dxil_block *block = &sm6->root_block; ++ size_t i, base_value_idx = sm6->value_count; struct vkd3d_shader_instruction *ins; -@@ -4009,8 +4023,7 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) + const struct dxil_record *record; + enum vkd3d_result ret; +@@ -3980,10 +4006,6 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) + sm6->p.location.line = block->id; + sm6->p.location.column = 0; + +- for (i = 0, count = 0; i < block->record_count; ++i) +- count += block->records[i]->code == MODULE_CODE_GLOBALVAR; +- sm6_parser_require_space(sm6, count); +- + for (i = 0; i < block->record_count; ++i) + { + sm6->p.location.column = i; +@@ -4001,7 +4023,10 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) + + case MODULE_CODE_GLOBALVAR: + if (!sm6_parser_declare_global(sm6, record)) +- return VKD3D_ERROR_INVALID_SHADER; ++ { ++ VKD3D_ASSERT(sm6->p.status < 0); ++ return sm6->p.status; ++ } + break; + + case MODULE_CODE_VERSION: +@@ -4009,8 +4034,7 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) return VKD3D_ERROR_INVALID_SHADER; if ((version = record->operands[0]) != 1) { @@ -1548,7 +2097,18 @@ index c448e000cf9..fb2cde4501a 100644 "Bitcode format version %#"PRIx64" is unsupported.", version); return VKD3D_ERROR_INVALID_SHADER; } -@@ -4125,7 +4138,7 @@ static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( +@@ -4088,7 +4112,9 @@ static void src_params_init_from_operands(struct vkd3d_shader_src_param *src_par + unsigned int i; + + for (i = 0; i < count; ++i) +- src_param_init_from_value(&src_params[i], operands[i], sm6); ++ { ++ src_param_init_from_value(&src_params[i], operands[i], 0, sm6); ++ } + } + + static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( +@@ -4125,7 +4151,7 @@ static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shader_signature *s, bool is_input, enum vkd3d_shader_register_type reg_type, struct vkd3d_shader_dst_param *params) { @@ -1557,16 +2117,19 @@ index c448e000cf9..fb2cde4501a 100644 enum vkd3d_shader_register_type io_reg_type; bool is_patch_constant, is_control_point; struct vkd3d_shader_dst_param *param; -@@ -4175,7 +4188,7 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade +@@ -4175,7 +4201,10 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade if (is_control_point) { if (reg_type == VKD3DSPR_OUTPUT) - param->reg.idx[count].rel_addr = vsir_program_create_outpointid_param(sm6->p.program); -+ param->reg.idx[count].rel_addr = vsir_program_create_outpointid_param(sm6->program); ++ { ++ VKD3D_ASSERT(sm6->outpointid_param); ++ param->reg.idx[count].rel_addr = sm6->outpointid_param; ++ } param->reg.idx[count++].offset = 0; } -@@ -4190,7 +4203,7 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade +@@ -4190,7 +4219,7 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade static int sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) { @@ -1575,7 +2138,7 @@ index c448e000cf9..fb2cde4501a 100644 { vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Failed to allocate output parameters."); -@@ -4204,7 +4217,7 @@ static int sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct +@@ -4204,7 +4233,7 @@ static int sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct static int sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct shader_signature *input_signature) { @@ -1584,7 +2147,7 @@ index c448e000cf9..fb2cde4501a 100644 { vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Failed to allocate input parameters."); -@@ -4219,9 +4232,9 @@ static int sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct +@@ -4219,9 +4248,9 @@ static int sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct static int sm6_parser_init_patch_constant_signature(struct sm6_parser *sm6, const struct shader_signature *patch_constant_signature) { @@ -1596,16 +2159,322 @@ index c448e000cf9..fb2cde4501a 100644 patch_constant_signature->element_count))) { vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -@@ -5180,7 +5193,7 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr +@@ -4310,8 +4339,7 @@ static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_rec + WARN("Ignoring in_alloca flag.\n"); + if (!(packed_operands & ALLOCA_FLAG_EXPLICIT_TYPE)) + { +- FIXME("Unhandled implicit type.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "Implicit result type for ALLOCA instructions is not supported."); + return; + } +@@ -4347,8 +4375,7 @@ static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_rec + /* A size of 1 means one instance of type[0], i.e. one array. */ + if (sm6_value_get_constant_uint(size, sm6) != 1) + { +- FIXME("Allocation size is not 1.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "ALLOCA instruction allocation sizes other than 1 are not supported."); + return; + } +@@ -4410,7 +4437,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ + || !sm6_value_validate_is_backward_ref(ptr, sm6)) + return; + +- sm6_register_from_value(®, ptr, sm6); ++ vsir_register_from_dxil_value(®, ptr, 0, sm6); + + if (reg.type != VKD3DSPR_GROUPSHAREDMEM) + { +@@ -4430,8 +4457,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ + + if ((op = map_dx_atomicrmw_op(code = record->operands[i++])) == VSIR_OP_INVALID) + { +- FIXME("Unhandled atomicrmw op %"PRIu64".\n", code); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "Operation %"PRIu64" for an atomicrmw instruction is unhandled.", code); + return; + } +@@ -4466,12 +4492,12 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ + src_param_init_vector_from_reg(&src_params[0], &coord); + else + src_param_make_constant_uint(&src_params[0], 0); +- src_param_init_from_value(&src_params[1], src, sm6); ++ src_param_init_from_value(&src_params[1], src, 0, sm6); + + sm6_parser_init_ssa_value(sm6, dst); + + dst_params = instruction_dst_params_alloc(ins, 2, sm6); +- sm6_register_from_value(&dst_params[0].reg, dst, sm6); ++ vsir_register_from_dxil_value(&dst_params[0].reg, dst, 0, sm6); + dst_param_init(&dst_params[0]); + + dst_params[1].reg = reg; +@@ -4559,8 +4585,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty + is_valid = is_int; + break; + default: +- FIXME("Unhandled binary op %#"PRIx64".\n", code); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "Binary operation %#"PRIx64" is unhandled.", code); + return VSIR_OP_INVALID; + } +@@ -4581,6 +4606,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco + struct vkd3d_shader_src_param *src_params; + enum vkd3d_shader_opcode handler_idx; + const struct sm6_value *a, *b; ++ uint32_t type_flags = 0; + uint64_t code, flags; + bool silence_warning; + unsigned int i = 0; +@@ -4622,6 +4648,8 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco + silence_warning = !(flags & ~(OB_NO_UNSIGNED_WRAP | OB_NO_SIGNED_WRAP)); + break; + case VSIR_OP_ISHR: ++ type_flags |= DXIL_TYPE_SIGNED; ++ /* fall through */ + case VSIR_OP_USHR: + case VSIR_OP_IDIV: + case VSIR_OP_UDIV_SIMPLE: +@@ -4646,8 +4674,8 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; +- src_param_init_from_value(&src_params[0], a, sm6); +- src_param_init_from_value(&src_params[1], b, sm6); ++ src_param_init_from_value(&src_params[0], a, type_flags, sm6); ++ src_param_init_from_value(&src_params[1], b, type_flags, sm6); + if (code == BINOP_SUB) + src_params[1].modifiers = VKD3DSPSM_NEG; + +@@ -4660,7 +4688,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco + * do. */ + ins->flags |= VKD3DSI_SHIFT_UNMASKED; + } +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, type_flags, sm6); + } + + static const struct sm6_block *sm6_function_get_block(const struct sm6_function *function, uint64_t index, +@@ -4710,7 +4738,7 @@ static void sm6_parser_emit_br(struct sm6_parser *sm6, const struct dxil_record + dxil_record_validate_operand_max_count(record, i, sm6); + + code_block->terminator.type = TERMINATOR_COND_BR; +- sm6_register_from_value(&code_block->terminator.conditional_reg, value, sm6); ++ vsir_register_from_dxil_value(&code_block->terminator.conditional_reg, value, 0, sm6); + code_block->terminator.true_block = sm6_function_get_block(function, record->operands[0], sm6); + code_block->terminator.false_block = sm6_function_get_block(function, record->operands[1], sm6); + } +@@ -4781,7 +4809,9 @@ static bool sm6_parser_emit_composite_construct(struct sm6_parser *sm6, const st + unsigned int i; + + for (i = 0; i < component_count; ++i) +- sm6_register_from_value(&operand_regs[i], operands[i], sm6); ++ { ++ vsir_register_from_dxil_value(&operand_regs[i], operands[i], 0, sm6); ++ } + + return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); + } +@@ -4797,11 +4827,11 @@ static bool sm6_parser_emit_coordinate_construct(struct sm6_parser *sm6, const s + { + if (!z_operand && operands[component_count]->value_type == VALUE_TYPE_UNDEFINED) + break; +- sm6_register_from_value(&operand_regs[component_count], operands[component_count], sm6); ++ vsir_register_from_dxil_value(&operand_regs[component_count], operands[component_count], 0, sm6); + } + + if (z_operand) +- sm6_register_from_value(&operand_regs[component_count++], z_operand, sm6); ++ vsir_register_from_dxil_value(&operand_regs[component_count++], z_operand, 0, sm6); + + return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); + } +@@ -4822,7 +4852,7 @@ static void sm6_parser_emit_dx_void(struct sm6_parser *sm6, enum dx_intrinsic_op + { + struct vkd3d_shader_instruction *ins = state->ins; + vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_void_op(op)); +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) +@@ -4919,13 +4949,16 @@ static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, enum dx_intrinsic_o + vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0], sm6); ++ src_param_init_from_value(src_param, operands[0], 0, sm6); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + +-static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, const struct sm6_type *type) ++static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, ++ const struct sm6_type *type, uint32_t *type_flags) + { ++ *type_flags = 0; ++ + switch (op) + { + case DX_FMAX: +@@ -4933,8 +4966,10 @@ static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, co + case DX_FMIN: + return type->u.width == 64 ? VSIR_OP_DMIN : VSIR_OP_MIN; + case DX_IMAX: ++ *type_flags |= DXIL_TYPE_SIGNED; + return VSIR_OP_IMAX; + case DX_IMIN: ++ *type_flags |= DXIL_TYPE_SIGNED; + return VSIR_OP_IMIN; + case DX_QUAD_READ_LANE_AT: + return VSIR_OP_QUAD_READ_LANE_AT; +@@ -4954,14 +4989,15 @@ static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_ + { + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_params; ++ uint32_t type_flags; + +- vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type)); ++ vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type, &type_flags)); + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; +- src_param_init_from_value(&src_params[0], operands[0], sm6); +- src_param_init_from_value(&src_params[1], operands[1], sm6); ++ src_param_init_from_value(&src_params[0], operands[0], type_flags, sm6); ++ src_param_init_from_value(&src_params[1], operands[1], type_flags, sm6); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, type_flags, sm6); + } + + static enum vkd3d_shader_opcode map_dx_atomic_binop(const struct sm6_value *operand, struct sm6_parser *sm6) +@@ -4990,8 +5026,7 @@ static enum vkd3d_shader_opcode map_dx_atomic_binop(const struct sm6_value *oper + return VSIR_OP_IMM_ATOMIC_XOR; + /* DXIL currently doesn't use SUB and NAND. */ + default: +- FIXME("Unhandled atomic binop %"PRIu64".\n", code); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "Operation %"PRIu64" for an atomic binop instruction is unhandled.", code); + return VSIR_OP_INVALID; + } +@@ -5030,7 +5065,7 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr + } + else + { +- sm6_register_from_value(®, operands[coord_idx], sm6); ++ vsir_register_from_dxil_value(®, operands[coord_idx], 0, sm6); + } + + for (i = coord_idx + coord_count; i < coord_idx + 3; ++i) +@@ -5051,14 +5086,14 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr + return; + src_param_init_vector_from_reg(&src_params[0], ®); + if (is_cmp_xchg) +- src_param_init_from_value(&src_params[1], operands[4], sm6); +- src_param_init_from_value(&src_params[1 + is_cmp_xchg], operands[5], sm6); ++ src_param_init_from_value(&src_params[1], operands[4], 0, sm6); ++ src_param_init_from_value(&src_params[1 + is_cmp_xchg], operands[5], 0, sm6); + + sm6_parser_init_ssa_value(sm6, dst); + + dst_params = instruction_dst_params_alloc(ins, 2, sm6); + dst_param_init(&dst_params[0]); +- sm6_register_from_value(&dst_params[0].reg, dst, sm6); ++ vsir_register_from_dxil_value(&dst_params[0].reg, dst, 0, sm6); + dst_param_init(&dst_params[1]); + sm6_register_from_handle(sm6, &resource->u.handle, &dst_params[1].reg); + } +@@ -5099,8 +5134,7 @@ static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enu + + if (!sm6_value_is_constant(operands[1])) + { +- FIXME("Unsupported dynamic update operand.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "A dynamic update value for a UAV counter operation is not supported."); + return; + } +@@ -5118,7 +5152,7 @@ static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enu + return; + src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5152,7 +5186,7 @@ static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_int + src_param_init_scalar(&src_params[1], !clamp); + src_param_init_vector_from_handle(sm6, &src_params[2], &sampler->u.handle); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5180,7 +5214,7 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr type = sm6_type_get_scalar_type(dst->type, 0); VKD3D_ASSERT(type); - src_param->reg.data_type = vsir_data_type_from_dxil(type); -+ src_param->reg.data_type = vsir_data_type_from_dxil(type, sm6); ++ src_param->reg.data_type = vsir_data_type_from_dxil(type, 0, sm6); if (data_type_is_64_bit(src_param->reg.data_type)) src_param->swizzle = vsir_swizzle_64_from_32(src_param->swizzle); else -@@ -5407,7 +5420,7 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri +@@ -5198,7 +5232,8 @@ static void sm6_parser_dcl_register_builtin(struct sm6_parser *sm6, enum vkd3d_s + if (!bitmap_is_set(sm6->io_regs_declared, reg_type)) + { + bitmap_set(sm6->io_regs_declared, reg_type); +- ins = sm6_parser_add_instruction(sm6, handler_idx); ++ if (!(ins = sm6_parser_add_instruction(sm6, handler_idx))) ++ return; + dst_param = &ins->declaration.dst; + vsir_register_init(&dst_param->reg, reg_type, data_type, 0); + dst_param_init_vector(dst_param, component_count); +@@ -5220,7 +5255,7 @@ static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, struct + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init(src_param); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_coverage(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5323,7 +5358,7 @@ static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_DISCARD); + + if ((src_param = instruction_src_params_alloc(ins, 1, sm6))) +- src_param_init_from_value(src_param, operands[0], sm6); ++ src_param_init_from_value(src_param, operands[0], 0, sm6); + } + + static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5350,7 +5385,7 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init_scalar(src_param, component_idx); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5392,7 +5427,7 @@ static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opc + src_param_init_vector_from_reg(&src_params[0], ®s[0]); + src_param_init_vector_from_reg(&src_params[1], ®s[1]); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5407,7 +5442,7 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri row_index = sm6_value_get_constant_uint(operands[0], sm6); column_index = sm6_value_get_constant_uint(operands[2], sm6); @@ -1614,7 +2483,78 @@ index c448e000cf9..fb2cde4501a 100644 if (row_index >= signature->element_count) { WARN("Invalid row index %u.\n", row_index); -@@ -5638,7 +5651,7 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin +@@ -5437,9 +5472,9 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri + register_index_address_init(&src_params[0].reg.idx[0], operands[1], sm6); + + if (op == DX_EVAL_SAMPLE_INDEX) +- src_param_init_from_value(&src_params[1], operands[3], sm6); ++ src_param_init_from_value(&src_params[1], operands[3], 0, sm6); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5451,10 +5486,10 @@ static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_op + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0], sm6); ++ src_param_init_from_value(src_param, operands[0], 0, sm6); + src_param->modifiers = VKD3DSPSM_ABS; + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5494,7 +5529,7 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i + component_idx = sm6_value_get_constant_uint(operands[0], sm6); + src_param_init_scalar(src_param, component_idx); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static enum vkd3d_shader_opcode sm6_dx_map_ma_op(enum dx_intrinsic_opcode op, const struct sm6_type *type) +@@ -5524,9 +5559,11 @@ static void sm6_parser_emit_dx_ma(struct sm6_parser *sm6, enum dx_intrinsic_opco + if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) + return; + for (i = 0; i < 3; ++i) +- src_param_init_from_value(&src_params[i], operands[i], sm6); ++ { ++ src_param_init_from_value(&src_params[i], operands[i], 0, sm6); ++ } + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5554,7 +5591,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in + if (is_texture) + { + ins->flags = VKD3DSI_RESINFO_UINT; +- src_param_init_from_value(&src_params[0], operands[1], sm6); ++ src_param_init_from_value(&src_params[0], operands[1], 0, sm6); + component_count = VKD3D_VEC4_SIZE; + + if (resource_kind_is_multisampled(resource_kind)) +@@ -5627,9 +5664,11 @@ static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsi + if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) + return; + for (i = 0; i < 3; ++i) +- src_param_init_from_value(&src_params[i], operands[i], sm6); ++ { ++ src_param_init_from_value(&src_params[i], operands[i], 0, sm6); ++ } + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5638,7 +5677,7 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin bool is_control_point = op == DX_LOAD_OUTPUT_CONTROL_POINT; bool is_patch_constant = op == DX_LOAD_PATCH_CONSTANT; struct vkd3d_shader_instruction *ins = state->ins; @@ -1623,7 +2563,99 @@ index c448e000cf9..fb2cde4501a 100644 unsigned int count, row_index, column_index; const struct vkd3d_shader_dst_param *params; struct vkd3d_shader_src_param *src_param; -@@ -6148,7 +6161,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ +@@ -5697,7 +5736,7 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin + register_index_address_init(&src_param->reg.idx[count], operands[3], sm6); + } + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5717,7 +5756,7 @@ static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intri + src_params[0].reg = reg; + src_param_init_vector(&src_params[0], 2); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_output_control_point_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5768,9 +5807,9 @@ static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0], sm6); ++ src_param_init_from_value(src_param, operands[0], 0, sm6); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5915,7 +5954,7 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; +- src_param_init_from_value(&src_params[0], operands[1], sm6); ++ src_param_init_from_value(&src_params[0], operands[1], 0, sm6); + if (!sm6_value_is_undef(operands[2])) + { + /* Constant zero would be ok, but is not worth checking for unless it shows up. */ +@@ -5980,7 +6019,7 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; +- src_param_init_from_value(&src_params[0], operands[1], sm6); ++ src_param_init_from_value(&src_params[0], operands[1], 0, sm6); + if (!sm6_value_is_undef(operands[2])) + { + /* Constant zero would have no effect, but is not worth checking for unless it shows up. */ +@@ -6010,7 +6049,7 @@ static void sm6_parser_emit_dx_get_sample_count(struct sm6_parser *sm6, enum dx_ + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init(src_param); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + ins->dst->reg.data_type = VSIR_DATA_U32; + } + +@@ -6035,14 +6074,14 @@ static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_in + if (op == DX_TEX2DMS_GET_SAMPLE_POS) + { + src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); +- src_param_init_from_value(&src_params[1], operands[1], sm6); ++ src_param_init_from_value(&src_params[1], operands[1], 0, sm6); + } + else + { + src_param_init_vector(&src_params[0], 2); + vsir_register_init(&src_params[0].reg, VKD3DSPR_RASTERIZER, VSIR_DATA_F32, 0); + src_params[0].reg.dimension = VSIR_DIMENSION_VEC4; +- src_param_init_from_value(&src_params[1], operands[0], sm6); ++ src_param_init_from_value(&src_params[1], operands[0], 0, sm6); + } + + instruction_dst_param_init_ssa_vector(ins, 2, sm6); +@@ -6104,7 +6143,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ + instruction_init_with_resource(ins, (op == DX_SAMPLE_B) ? VSIR_OP_SAMPLE_B : VSIR_OP_SAMPLE_LOD, + resource, sm6); + src_params = instruction_src_params_alloc(ins, 4, sm6); +- src_param_init_from_value(&src_params[3], operands[9], sm6); ++ src_param_init_from_value(&src_params[3], operands[9], 0, sm6); + break; + case DX_SAMPLE_C: + clamp_idx = 10; +@@ -6113,7 +6152,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ + instruction_init_with_resource(ins, (op == DX_SAMPLE_C_LZ) ? VSIR_OP_SAMPLE_C_LZ : VSIR_OP_SAMPLE_C, + resource, sm6); + src_params = instruction_src_params_alloc(ins, 4, sm6); +- src_param_init_from_value(&src_params[3], operands[9], sm6); ++ src_param_init_from_value(&src_params[3], operands[9], 0, sm6); + component_count = 1; + break; + case DX_SAMPLE_GRAD: +@@ -6148,7 +6187,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ static void sm6_parser_emit_dx_sample_index(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -1632,7 +2664,37 @@ index c448e000cf9..fb2cde4501a 100644 struct vkd3d_shader_instruction *ins = state->ins; struct vkd3d_shader_src_param *src_param; unsigned int element_idx; -@@ -6207,7 +6220,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr +@@ -6170,7 +6209,7 @@ static void sm6_parser_emit_dx_sample_index(struct sm6_parser *sm6, enum dx_intr + src_param->reg = sm6->input_params[element_idx].reg; + src_param_init(src_param); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -6182,9 +6221,9 @@ static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsi + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0], sm6); ++ src_param_init_from_value(src_param, operands[0], 0, sm6); + +- if (instruction_dst_param_init_ssa_scalar(ins, sm6)) ++ if (instruction_dst_param_init_ssa_scalar(ins, 0, sm6)) + ins->dst->modifiers = VKD3DSPDM_SATURATE; + } + +@@ -6197,7 +6236,7 @@ static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intr + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0], sm6); ++ src_param_init_from_value(src_param, operands[0], 0, sm6); + + instruction_dst_param_init_ssa_vector(ins, 2, sm6); + } +@@ -6207,7 +6246,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr { bool is_patch_constant = op == DX_STORE_PATCH_CONSTANT; struct vkd3d_shader_instruction *ins = state->ins; @@ -1641,7 +2703,363 @@ index c448e000cf9..fb2cde4501a 100644 struct vkd3d_shader_src_param *src_param; struct vkd3d_shader_dst_param *dst_param; const struct shader_signature *signature; -@@ -8206,7 +8219,7 @@ static enum vkd3d_result sm6_function_resolve_phi_incomings(const struct sm6_fun +@@ -6263,7 +6302,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr + } + + if ((src_param = instruction_src_params_alloc(ins, 1, sm6))) +- src_param_init_from_value(src_param, value, sm6); ++ src_param_init_from_value(src_param, value, 0, sm6); + } + + static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -6309,7 +6348,7 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in + instruction_init_with_resource(ins, extended_offset ? VSIR_OP_GATHER4_PO_C : VSIR_OP_GATHER4_C, resource, sm6); + if (!(src_params = instruction_src_params_alloc(ins, 4 + extended_offset, sm6))) + return; +- src_param_init_from_value(&src_params[3 + extended_offset], operands[9], sm6); ++ src_param_init_from_value(&src_params[3 + extended_offset], operands[9], 0, sm6); + } + + src_param_init_vector_from_reg(&src_params[0], &coord); +@@ -6372,7 +6411,7 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr + src_param_init_vector_from_reg(&src_params[0], &coord); + src_param_init_vector_from_handle(sm6, &src_params[1], &resource->u.handle); + if (is_multisample) +- src_param_init_from_value(&src_params[2], mip_level_or_sample_count, sm6); ++ src_param_init_from_value(&src_params[2], mip_level_or_sample_count, 0, sm6); + + instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); + } +@@ -6436,7 +6475,7 @@ static void sm6_parser_emit_dx_wave_active_ballot(struct sm6_parser *sm6, enum d + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_WAVE_ACTIVE_BALLOT); + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0], sm6); ++ src_param_init_from_value(src_param, operands[0], 0, sm6); + + instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); + } +@@ -6476,9 +6515,9 @@ static void sm6_parser_emit_dx_wave_active_bit(struct sm6_parser *sm6, enum dx_i + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0], sm6); ++ src_param_init_from_value(src_param, operands[0], 0, sm6); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static enum vkd3d_shader_opcode sm6_dx_map_wave_op(enum dxil_wave_op_kind op, bool is_signed, bool is_float, +@@ -6527,9 +6566,9 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0], sm6); ++ src_param_init_from_value(src_param, operands[0], 0, sm6); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -6918,14 +6957,15 @@ static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_recor + fn_value->u.function.name, &operands[1], operand_count - 1, state, dst); + } + +-static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_type *from, +- const struct sm6_type *to, struct sm6_parser *sm6) ++static enum vkd3d_shader_opcode dxil_map_cast_op(uint64_t code, const struct sm6_type *from, ++ uint32_t *src_type_flags, const struct sm6_type *to, struct sm6_parser *dxil) + { + enum vkd3d_shader_opcode op = VSIR_OP_INVALID; + bool from_int, to_int, from_fp, to_fp; + unsigned int from_width, to_width; + bool is_valid = false; + ++ *src_type_flags = 0; + from_int = sm6_type_is_integer(from); + to_int = sm6_type_is_integer(to); + from_fp = sm6_type_is_floating_point(from); +@@ -6934,15 +6974,13 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ + /* NOTE: DXIL currently doesn't use vectors here. */ + if ((!from_int && !from_fp) || (!to_int && !to_fp)) + { +- FIXME("Unhandled cast of type class %u to type class %u.\n", from->class, to->class); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast of type class %u to type class %u is not implemented.", from->class, to->class); + return VSIR_OP_INVALID; + } + if (to->u.width == 8 || from->u.width == 8) + { +- FIXME("Unhandled 8-bit value.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast to/from an 8-bit type is not implemented."); + return VSIR_OP_INVALID; + } +@@ -6982,6 +7020,7 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ + case CAST_SITOFP: + op = VSIR_OP_ITOF; + is_valid = from_int && to_fp; ++ *src_type_flags |= DXIL_TYPE_SIGNED; + break; + + case CAST_FPTRUNC: +@@ -7000,16 +7039,14 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ + break; + + default: +- FIXME("Unhandled cast op %"PRIu64".\n", code); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast operation %"PRIu64" is unhandled.", code); + return VSIR_OP_INVALID; + } + + if (!is_valid) + { +- FIXME("Invalid types %u and/or %u for op %"PRIu64".\n", from->class, to->class, code); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.", + code, from->class, from->u.width, to->class, to->u.width); + return VSIR_OP_INVALID; +@@ -7032,22 +7069,23 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ + return op; + } + +-static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_record *record, ++static void sm6_parser_emit_cast(struct sm6_parser *dxil, const struct dxil_record *record, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst) + { + struct vkd3d_shader_src_param *src_param; +- enum vkd3d_shader_opcode handler_idx; + const struct sm6_value *value; ++ enum vkd3d_shader_opcode op; + const struct sm6_type *type; ++ uint32_t src_type_flags; + unsigned int i = 0; + +- if (!(value = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))) ++ if (!(value = sm6_parser_get_value_by_ref(dxil, record, NULL, &i))) + return; + +- if (!dxil_record_validate_operand_count(record, i + 2, i + 2, sm6)) ++ if (!dxil_record_validate_operand_count(record, i + 2, i + 2, dxil)) + return; + +- if (!(type = sm6_parser_get_type(sm6, record->operands[i++]))) ++ if (!(type = sm6_parser_get_type(dxil, record->operands[i++]))) + return; + + dst->type = type; +@@ -7060,28 +7098,28 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor + return; + } + +- if ((handler_idx = sm6_map_cast_op(record->operands[i], value->type, type, sm6)) == VSIR_OP_INVALID) ++ if ((op = dxil_map_cast_op(record->operands[i], value->type, &src_type_flags, type, dxil)) == VSIR_OP_INVALID) + return; + +- vsir_instruction_init(ins, &sm6->p.location, handler_idx); ++ vsir_instruction_init(ins, &dxil->p.location, op); + +- if (handler_idx == VSIR_OP_NOP) ++ if (op == VSIR_OP_NOP) + { + *dst = *value; + dst->type = type; + return; + } + +- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil))) + return; +- src_param_init_from_value(src_param, value, sm6); ++ src_param_init_from_value(src_param, value, src_type_flags, dxil); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, dxil); + + /* VSIR bitcasts are represented by source registers with types different + * from the types they were written with, rather than with different types + * for the MOV source and destination. */ +- if (handler_idx == VSIR_OP_MOV) ++ if (op == VSIR_OP_MOV) + src_param->reg.data_type = ins->dst[0].reg.data_type; + } + +@@ -7089,6 +7127,7 @@ struct sm6_cmp_info + { + enum vkd3d_shader_opcode handler_idx; + bool src_swap; ++ uint32_t type_flags; + }; + + static const struct sm6_cmp_info *sm6_map_cmp2_op(uint64_t code) +@@ -7118,10 +7157,10 @@ static const struct sm6_cmp_info *sm6_map_cmp2_op(uint64_t code) + [ICMP_UGE] = {VSIR_OP_UGE}, + [ICMP_ULT] = {VSIR_OP_ULT}, + [ICMP_ULE] = {VSIR_OP_UGE, true}, +- [ICMP_SGT] = {VSIR_OP_ILT, true}, +- [ICMP_SGE] = {VSIR_OP_IGE}, +- [ICMP_SLT] = {VSIR_OP_ILT}, +- [ICMP_SLE] = {VSIR_OP_IGE, true}, ++ [ICMP_SGT] = {VSIR_OP_ILT, true, DXIL_TYPE_SIGNED}, ++ [ICMP_SGE] = {VSIR_OP_IGE, false, DXIL_TYPE_SIGNED}, ++ [ICMP_SLT] = {VSIR_OP_ILT, false, DXIL_TYPE_SIGNED}, ++ [ICMP_SLE] = {VSIR_OP_IGE, true, DXIL_TYPE_SIGNED}, + }; + + return (code < ARRAY_SIZE(cmp_op_table)) ? &cmp_op_table[code] : NULL; +@@ -7222,10 +7261,10 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; +- src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a, sm6); +- src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b, sm6); ++ src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a, cmp->type_flags, sm6); ++ src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b, cmp->type_flags, sm6); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_record *record, +@@ -7245,7 +7284,7 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re + || !sm6_value_validate_is_backward_ref(ptr, sm6)) + return; + +- sm6_register_from_value(®, ptr, sm6); ++ vsir_register_from_dxil_value(®, ptr, 0, sm6); + + if (reg.type != VKD3DSPR_GROUPSHAREDMEM) + { +@@ -7300,14 +7339,14 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re + if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) + return; + src_param_make_constant_uint(&src_params[0], 0); +- src_param_init_from_value(&src_params[1], cmp, sm6); +- src_param_init_from_value(&src_params[2], new, sm6); ++ src_param_init_from_value(&src_params[1], cmp, 0, sm6); ++ src_param_init_from_value(&src_params[2], new, 0, sm6); + + sm6_parser_init_ssa_value(sm6, dst); + + if (!(dst_params = instruction_dst_params_alloc(ins, 2, sm6))) + return; +- sm6_register_from_value(&dst_params[0].reg, dst, sm6); ++ vsir_register_from_dxil_value(&dst_params[0].reg, dst, 0, sm6); + dst_param_init(&dst_params[0]); + dst_params[1].reg = reg; + dst_param_init(&dst_params[1]); +@@ -7366,10 +7405,10 @@ static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- sm6_register_from_value(&src_param->reg, src, sm6); ++ vsir_register_from_dxil_value(&src_param->reg, src, 0, sm6); + src_param_init_scalar(src_param, elem_idx); + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record *record, +@@ -7515,7 +7554,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor + if (record->operands[i]) + WARN("Ignoring volatile modifier.\n"); + +- sm6_register_from_value(®, ptr, sm6); ++ vsir_register_from_dxil_value(®, ptr, 0, sm6); + + if (ptr->structure_stride) + { +@@ -7530,7 +7569,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor + src_param_make_constant_uint(&src_params[0], reg.idx[1].offset); + /* Struct offset is always zero as there is no struct, just an array. */ + src_param_make_constant_uint(&src_params[1], 0); +- src_param_init_from_value(&src_params[2], ptr, sm6); ++ src_param_init_from_value(&src_params[2], ptr, 0, sm6); + src_params[2].reg.alignment = alignment; + /* The offset is already in src_params[0]. */ + src_params[2].reg.idx_count = 1; +@@ -7544,11 +7583,11 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor + return; + if (operand_count > 1) + src_param_make_constant_uint(&src_params[0], 0); +- src_param_init_from_value(&src_params[operand_count - 1], ptr, sm6); ++ src_param_init_from_value(&src_params[operand_count - 1], ptr, 0, sm6); + src_params[operand_count - 1].reg.alignment = alignment; + } + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static int phi_incoming_compare(const void *a, const void *b) +@@ -7702,7 +7741,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco + if (record->operands[i]) + WARN("Ignoring volatile modifier.\n"); + +- sm6_register_from_value(®, ptr, sm6); ++ vsir_register_from_dxil_value(®, ptr, 0, sm6); + + if (ptr->structure_stride) + { +@@ -7717,7 +7756,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco + src_param_make_constant_uint(&src_params[0], reg.idx[1].offset); + /* Struct offset is always zero as there is no struct, just an array. */ + src_param_make_constant_uint(&src_params[1], 0); +- src_param_init_from_value(&src_params[2], src, sm6); ++ src_param_init_from_value(&src_params[2], src, 0, sm6); + } + else + { +@@ -7728,7 +7767,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco + return; + if (operand_count > 1) + src_param_make_constant_uint(&src_params[0], 0); +- src_param_init_from_value(&src_params[operand_count - 1], src, sm6); ++ src_param_init_from_value(&src_params[operand_count - 1], src, 0, sm6); + } + + dst_param = instruction_dst_params_alloc(ins, 1, sm6); +@@ -7778,7 +7817,7 @@ static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_rec + return; + } + +- sm6_register_from_value(&terminator->conditional_reg, src, sm6); ++ vsir_register_from_dxil_value(&terminator->conditional_reg, src, 0, sm6); + terminator->type = TERMINATOR_SWITCH; + + terminator->case_count = record->operand_count / 2u; +@@ -7854,9 +7893,11 @@ static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_re + if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) + return; + for (i = 0; i < 3; ++i) +- src_param_init_from_value(&src_params[i], src[i], sm6); ++ { ++ src_param_init_from_value(&src_params[i], src[i], 0, sm6); ++ } + +- instruction_dst_param_init_ssa_scalar(ins, sm6); ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static bool sm6_metadata_value_is_node(const struct sm6_metadata_value *m) +@@ -8195,7 +8236,7 @@ static enum vkd3d_result sm6_function_resolve_phi_incomings(const struct sm6_fun + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "The type of a phi incoming value does not match the result type."); + } +- sm6_register_from_value(&phi->incoming[j].reg, src, sm6); ++ vsir_register_from_dxil_value(&phi->incoming[j].reg, src, 0, sm6); + } + } + } +@@ -8206,7 +8247,7 @@ static enum vkd3d_result sm6_function_resolve_phi_incomings(const struct sm6_fun static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, struct sm6_function *function) { @@ -1650,7 +3068,119 @@ index c448e000cf9..fb2cde4501a 100644 struct vkd3d_shader_instruction *ins; size_t i, block_idx, block_count; const struct dxil_record *record; -@@ -8586,8 +8599,9 @@ static void sm6_parser_emit_label(struct sm6_parser *sm6, unsigned int label_id) +@@ -8355,8 +8396,8 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + return VKD3D_ERROR_INVALID_SHADER; + } + +- if (sm6->p.failed) +- return VKD3D_ERROR; ++ if (sm6->p.status < 0) ++ return sm6->p.status; + + if (record->attachment) + metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); +@@ -8403,18 +8444,26 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ + case TERMINATOR_UNCOND_BR: + if (!block->terminator.true_block) + return; +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_BRANCH); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_BRANCH))) ++ return; + if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } + vsir_src_param_init_label(&src_params[0], block->terminator.true_block->id); + break; + + case TERMINATOR_COND_BR: + if (!block->terminator.true_block || !block->terminator.false_block) + return; +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_BRANCH); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_BRANCH))) ++ return; + if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } + src_param_init(&src_params[0]); + src_params[0].reg = block->terminator.conditional_reg; + vsir_src_param_init_label(&src_params[1], block->terminator.true_block->id); +@@ -8422,9 +8471,13 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ + break; + + case TERMINATOR_SWITCH: +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_SWITCH_MONOLITHIC); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_SWITCH_MONOLITHIC))) ++ return; + if (!(src_params = instruction_src_params_alloc(ins, block->terminator.case_count * 2u + 1, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } + src_param_init(&src_params[0]); + src_params[0].reg = block->terminator.conditional_reg; + /* TODO: emit the merge block id. */ +@@ -8438,7 +8491,7 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ + switch_case = &block->terminator.cases[i]; + if (!(case_block = switch_case->block)) + { +- VKD3D_ASSERT(sm6->p.failed); ++ VKD3D_ASSERT(sm6->p.status < 0); + continue; + } + if (switch_case->is_default) +@@ -8491,11 +8544,18 @@ static void sm6_block_emit_phi(const struct sm6_block *block, struct sm6_parser + src_phi = &block->phi[i]; + incoming_count = src_phi->incoming_count; + +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_PHI); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_PHI))) ++ return; + if (!(src_params = instruction_src_params_alloc(ins, incoming_count * 2u, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } + if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } + + for (j = 0; j < incoming_count; ++j) + { +@@ -8507,11 +8567,11 @@ static void sm6_block_emit_phi(const struct sm6_block *block, struct sm6_parser + if (incoming_block) + vsir_src_param_init_label(&src_params[index + 1], incoming_block->id); + else +- VKD3D_ASSERT(sm6->p.failed); ++ VKD3D_ASSERT(sm6->p.status < 0); + } + + dst_param_init(dst_param); +- sm6_register_from_value(&dst_param->reg, &src_phi->value, sm6); ++ vsir_register_from_dxil_value(&dst_param->reg, &src_phi->value, 0, sm6); + } + } + +@@ -8577,42 +8637,45 @@ static void sm6_parser_emit_label(struct sm6_parser *sm6, unsigned int label_id) + struct vkd3d_shader_src_param *src_param; + struct vkd3d_shader_instruction *ins; + +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_LABEL); +- ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_LABEL))) ++ return; + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } + vsir_src_param_init_label(src_param, label_id); + } static enum vkd3d_result sm6_function_emit_blocks(const struct sm6_function *function, struct sm6_parser *sm6) { @@ -1660,9 +3190,20 @@ index c448e000cf9..fb2cde4501a 100644 + struct vkd3d_shader_instruction *ins; + unsigned int i, j; - program->block_count = function->block_count; +- program->block_count = function->block_count; ++ program->block_count = max(program->block_count, function->block_count); -@@ -8605,10 +8619,11 @@ static enum vkd3d_result sm6_function_emit_blocks(const struct sm6_function *fun + for (i = 0; i < function->block_count; ++i) + { + const struct sm6_block *block = function->blocks[i]; + +- /* Space for the label and terminator. */ +- if (!sm6_parser_require_space(sm6, block->instruction_count + block->phi_count + 2)) +- { +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, +- "Out of memory emitting shader instructions."); +- return VKD3D_ERROR_OUT_OF_MEMORY; +- } sm6_parser_emit_label(sm6, block->id); sm6_block_emit_phi(block, sm6); @@ -1672,13 +3213,23 @@ index c448e000cf9..fb2cde4501a 100644 - + for (j = 0; j < block->instruction_count; ++j) + { -+ ins = vsir_program_append(program); ++ if (!(ins = vsir_program_append(program))) ++ { ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ "Out of memory emitting block instructions."); ++ return sm6->p.status; ++ } + *ins = block->instructions[j]; + } sm6_block_emit_terminator(block, sm6); } -@@ -9510,8 +9525,8 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6, +- return VKD3D_OK; ++ return sm6->p.status; + } + + static bool sm6_parser_allocate_named_metadata(struct sm6_parser *sm6) +@@ -9510,8 +9573,8 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6, struct vkd3d_shader_instruction *ins; const struct sm6_metadata_node *node; const struct sm6_metadata_value *m; @@ -1688,20 +3239,18 @@ index c448e000cf9..fb2cde4501a 100644 unsigned int i; for (i = 0; i < descriptor_node->operand_count; ++i) -@@ -9560,9 +9575,10 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6, +@@ -9560,42 +9623,41 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6, return VKD3D_ERROR_INVALID_SHADER; } - if (!(ins = sm6_parser_require_space(sm6, 1))) -+ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_NOP))) - { +- { - ERR("Failed to allocate instruction.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ "Out of memory emitting shader instructions."); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_NOP))) return VKD3D_ERROR_OUT_OF_MEMORY; - } +- } -@@ -9570,32 +9586,34 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6, + switch (type) { case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV: if ((ret = sm6_parser_resources_load_cbv(sm6, node, d, ins)) < 0) @@ -1745,7 +3294,7 @@ index c448e000cf9..fb2cde4501a 100644 } static enum vkd3d_result sm6_parser_resources_init(struct sm6_parser *sm6) -@@ -9711,7 +9729,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const +@@ -9711,7 +9773,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const { unsigned int i, j, column_count, operand_count, index; const struct sm6_metadata_node *node, *element_node; @@ -1754,7 +3303,7 @@ index c448e000cf9..fb2cde4501a 100644 struct signature_element *elements, *e; unsigned int values[10]; bool native_16bit; -@@ -9930,7 +9948,7 @@ invalid: +@@ -9930,7 +9992,7 @@ invalid: static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, const struct sm6_metadata_value *m, enum vkd3d_tessellator_domain tessellator_domain) { @@ -1763,9 +3312,28 @@ index c448e000cf9..fb2cde4501a 100644 enum vkd3d_result ret; if (!sm6_metadata_value_is_node(m)) -@@ -9985,12 +10003,12 @@ static void sm6_parser_emit_global_flags(struct sm6_parser *sm6, const struct sm +@@ -9953,6 +10015,14 @@ static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, cons + &program->patch_constant_signature, tessellator_domain, false)) < 0) + return ret; - ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_GLOBAL_FLAGS); ++ if (sm6->program->shader_version.type == VKD3D_SHADER_TYPE_HULL ++ && !(sm6->outpointid_param = vsir_program_create_outpointid_param(sm6->program))) ++ { ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ "Failed to allocate outpointid parameter."); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ } ++ + if ((ret = sm6_parser_init_input_signature(sm6, &program->input_signature)) < 0) + return ret; + +@@ -9983,14 +10053,15 @@ static void sm6_parser_emit_global_flags(struct sm6_parser *sm6, const struct sm + rotated_flags = (rotated_flags >> 1) | ((rotated_flags & 1) << 4); + global_flags = (global_flags & ~mask) | rotated_flags; + +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_GLOBAL_FLAGS); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_GLOBAL_FLAGS))) ++ return; ins->declaration.global_flags = global_flags; - sm6->p.program->global_flags = global_flags; + sm6->program->global_flags = global_flags; @@ -1778,7 +3346,13 @@ index c448e000cf9..fb2cde4501a 100644 const struct sm6_metadata_node *node; struct vkd3d_shader_instruction *ins; unsigned int group_sizes[3]; -@@ -10044,7 +10062,7 @@ static enum vkd3d_result sm6_parser_emit_thread_group(struct sm6_parser *sm6, co +@@ -10040,11 +10111,12 @@ static enum vkd3d_result sm6_parser_emit_thread_group(struct sm6_parser *sm6, co + } + } + +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_THREAD_GROUP); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_THREAD_GROUP))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; 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]; @@ -1787,17 +3361,46 @@ index c448e000cf9..fb2cde4501a 100644 return VKD3D_OK; } -@@ -10082,7 +10100,7 @@ static void sm6_parser_emit_dcl_tessellator_domain(struct sm6_parser *sm6, +@@ -10053,7 +10125,8 @@ static void sm6_parser_emit_dcl_count(struct sm6_parser *sm6, enum vkd3d_shader_ + { + struct vkd3d_shader_instruction *ins; - ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TESSELLATOR_DOMAIN); +- ins = sm6_parser_add_instruction(sm6, handler_idx); ++ if (!(ins = sm6_parser_add_instruction(sm6, handler_idx))) ++ return; + ins->declaration.count = count; + } + +@@ -10063,7 +10136,8 @@ static void sm6_parser_emit_dcl_primitive_topology(struct sm6_parser *sm6, + { + struct vkd3d_shader_instruction *ins; + +- ins = sm6_parser_add_instruction(sm6, handler_idx); ++ if (!(ins = sm6_parser_add_instruction(sm6, handler_idx))) ++ return; + ins->declaration.primitive_type.type = primitive_type; + ins->declaration.primitive_type.patch_vertex_count = patch_vertex_count; + } +@@ -10080,9 +10154,10 @@ static void sm6_parser_emit_dcl_tessellator_domain(struct sm6_parser *sm6, + "Domain shader tessellator domain %u is unhandled.", tessellator_domain); + } + +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TESSELLATOR_DOMAIN); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TESSELLATOR_DOMAIN))) ++ return; ins->declaration.tessellator_domain = tessellator_domain; - sm6->p.program->tess_domain = tessellator_domain; + sm6->program->tess_domain = tessellator_domain; } static void sm6_parser_validate_control_point_count(struct sm6_parser *sm6, -@@ -10111,7 +10129,7 @@ static void sm6_parser_emit_dcl_tessellator_partitioning(struct sm6_parser *sm6, - ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TESSELLATOR_PARTITIONING); +@@ -10108,10 +10183,11 @@ static void sm6_parser_emit_dcl_tessellator_partitioning(struct sm6_parser *sm6, + "Hull shader tessellator partitioning %u is unhandled.", tessellator_partitioning); + } + +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TESSELLATOR_PARTITIONING); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TESSELLATOR_PARTITIONING))) ++ return; ins->declaration.tessellator_partitioning = tessellator_partitioning; - sm6->p.program->tess_partitioning = tessellator_partitioning; @@ -1805,8 +3408,13 @@ index c448e000cf9..fb2cde4501a 100644 } static void sm6_parser_emit_dcl_tessellator_output_primitive(struct sm6_parser *sm6, -@@ -10129,7 +10147,7 @@ static void sm6_parser_emit_dcl_tessellator_output_primitive(struct sm6_parser * - ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TESSELLATOR_OUTPUT_PRIMITIVE); +@@ -10126,10 +10202,11 @@ static void sm6_parser_emit_dcl_tessellator_output_primitive(struct sm6_parser * + "Hull shader tessellator output primitive %u is unhandled.", primitive); + } + +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TESSELLATOR_OUTPUT_PRIMITIVE); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_TESSELLATOR_OUTPUT_PRIMITIVE))) ++ return; ins->declaration.tessellator_output_primitive = primitive; - sm6->p.program->tess_output_primitive = primitive; @@ -1814,7 +3422,17 @@ index c448e000cf9..fb2cde4501a 100644 } static void sm6_parser_emit_dcl_max_tessellation_factor(struct sm6_parser *sm6, struct sm6_metadata_value *m) -@@ -10241,8 +10259,8 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s +@@ -10153,7 +10230,8 @@ static void sm6_parser_emit_dcl_max_tessellation_factor(struct sm6_parser *sm6, + "Hull shader max tessellation factor %f is invalid.", max_tessellation_factor); + } + +- ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_HS_MAX_TESSFACTOR); ++ if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_DCL_HS_MAX_TESSFACTOR))) ++ return; + ins->declaration.max_tessellation_factor = max_tessellation_factor; + } + +@@ -10241,8 +10319,8 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s } sm6_parser_emit_dcl_primitive_topology(sm6, VSIR_OP_DCL_INPUT_PRIMITIVE, input_primitive, patch_vertex_count); @@ -1825,7 +3443,7 @@ index c448e000cf9..fb2cde4501a 100644 i = operands[1]; /* Max total scalar count sets an upper limit. We would need to scan outputs to be more precise. */ -@@ -10253,7 +10271,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s +@@ -10253,7 +10331,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s "Geometry shader output vertex count %u is invalid.", i); } sm6_parser_emit_dcl_count(sm6, VSIR_OP_DCL_VERTICES_OUT, i); @@ -1834,7 +3452,7 @@ index c448e000cf9..fb2cde4501a 100644 if (operands[2] > 1) { -@@ -10271,7 +10289,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s +@@ -10271,7 +10349,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s output_primitive = VKD3D_PT_TRIANGLELIST; } sm6_parser_emit_dcl_primitive_topology(sm6, VSIR_OP_DCL_OUTPUT_TOPOLOGY, output_primitive, 0); @@ -1843,7 +3461,7 @@ index c448e000cf9..fb2cde4501a 100644 i = operands[4]; if (!i || i > MAX_GS_INSTANCE_COUNT) -@@ -10326,7 +10344,7 @@ static enum vkd3d_tessellator_domain sm6_parser_ds_properties_init(struct sm6_pa +@@ -10326,7 +10404,7 @@ static enum vkd3d_tessellator_domain sm6_parser_ds_properties_init(struct sm6_pa sm6_parser_emit_dcl_tessellator_domain(sm6, operands[0]); sm6_parser_validate_control_point_count(sm6, operands[1], true, "Domain shader input"); @@ -1852,7 +3470,7 @@ index c448e000cf9..fb2cde4501a 100644 return operands[0]; } -@@ -10334,7 +10352,7 @@ static enum vkd3d_tessellator_domain sm6_parser_ds_properties_init(struct sm6_pa +@@ -10334,7 +10412,7 @@ static enum vkd3d_tessellator_domain sm6_parser_ds_properties_init(struct sm6_pa static enum vkd3d_tessellator_domain sm6_parser_hs_properties_init(struct sm6_parser *sm6, const struct sm6_metadata_value *m) { @@ -1861,7 +3479,15 @@ index c448e000cf9..fb2cde4501a 100644 const struct sm6_metadata_node *node; unsigned int operands[6] = {0}; unsigned int i; -@@ -10727,9 +10745,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro +@@ -10633,7 +10711,6 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro + { + size_t count, length, function_count, expected_function_count, byte_code_size = dxbc_desc->byte_code_size; + const struct vkd3d_shader_location location = {.source_name = compile_info->source_name}; +- struct shader_signature *patch_constant_signature, *output_signature, *input_signature; + uint32_t version_token, dxil_version, token_count, magic; + const uint32_t *byte_code = dxbc_desc->byte_code; + unsigned int chunk_offset, chunk_size; +@@ -10727,9 +10804,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro if (!vsir_program_init(program, compile_info, &version, (count + (count >> 2)) / 2u + 10, VSIR_CF_BLOCKS, VSIR_NORMALISED_SM6)) return VKD3D_ERROR_OUT_OF_MEMORY; @@ -1873,6 +3499,51 @@ index c448e000cf9..fb2cde4501a 100644 switch (program->shader_version.type) { +@@ -10746,9 +10824,6 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro + break; + } + +- input_signature = &program->input_signature; +- output_signature = &program->output_signature; +- patch_constant_signature = &program->patch_constant_signature; + program->features = dxbc_desc->features; + memset(dxbc_desc, 0, sizeof(*dxbc_desc)); + +@@ -10890,15 +10965,6 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro + goto fail; + } + +- if (!sm6_parser_require_space(sm6, output_signature->element_count + input_signature->element_count +- + patch_constant_signature->element_count)) +- { +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, +- "Out of memory emitting shader signature declarations."); +- ret = VKD3D_ERROR_OUT_OF_MEMORY; +- goto fail; +- } +- + program->ssa_count = sm6->ssa_next_id; + + if (!(fn = sm6_parser_get_function(sm6, sm6->entry_point))) +@@ -10949,15 +11015,13 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro + + dxil_block_destroy(&sm6->root_block); + +- if (sm6->p.failed) +- { +- ret = VKD3D_ERROR_INVALID_SHADER; ++ if (sm6->p.status < 0) + goto fail; +- } +- + return VKD3D_OK; + + fail: ++ if (ret >= 0 && sm6->p.status < 0) ++ ret = sm6->p.status; + sm6_parser_cleanup(sm6); + vsir_program_cleanup(program); + return ret; diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c index 676c501bb08..a14346a45d2 100644 --- a/libs/vkd3d/libs/vkd3d-shader/fx.c @@ -2081,10 +3752,22 @@ index dfe0a40ddf0..b2679beff9f 100644 return VKD3D_OK; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index 62335086e20..d8eb18e39c7 100644 +index 62335086e20..ec1e27d9496 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -1809,6 +1809,76 @@ struct hlsl_ir_node *hlsl_new_null_constant(struct hlsl_ctx *ctx, const struct v +@@ -393,6 +393,11 @@ bool hlsl_type_is_signed_integer(const struct hlsl_type *type) + vkd3d_unreachable(); + } + ++bool hlsl_type_is_unsigned_integer(const struct hlsl_type *type) ++{ ++ return hlsl_type_is_integer(type) && !hlsl_type_is_signed_integer(type); ++} ++ + bool hlsl_type_is_integer(const struct hlsl_type *type) + { + VKD3D_ASSERT(hlsl_is_numeric_type(type)); +@@ -1809,6 +1814,76 @@ struct hlsl_ir_node *hlsl_new_null_constant(struct hlsl_ctx *ctx, const struct v return hlsl_new_constant(ctx, ctx->builtin_types.null, &value, loc); } @@ -2161,8 +3844,39 @@ index 62335086e20..d8eb18e39c7 100644 static struct hlsl_ir_node *hlsl_new_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS], struct hlsl_type *data_type, const struct vkd3d_shader_location *loc) +@@ -3654,8 +3729,11 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op) + [HLSL_OP1_BIT_NOT] = "~", + [HLSL_OP1_CAST] = "cast", + [HLSL_OP1_CEIL] = "ceil", ++ [HLSL_OP1_CLZ] = "clz", + [HLSL_OP1_COS] = "cos", + [HLSL_OP1_COS_REDUCED] = "cos_reduced", ++ [HLSL_OP1_COUNTBITS] = "countbits", ++ [HLSL_OP1_CTZ] = "ctz", + [HLSL_OP1_DSX] = "dsx", + [HLSL_OP1_DSX_COARSE] = "dsx_coarse", + [HLSL_OP1_DSX_FINE] = "dsx_fine", +@@ -3665,6 +3743,7 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op) + [HLSL_OP1_EXP2] = "exp2", + [HLSL_OP1_F16TOF32] = "f16tof32", + [HLSL_OP1_F32TOF16] = "f32tof16", ++ [HLSL_OP1_FIND_MSB] = "find_msb", + [HLSL_OP1_FLOOR] = "floor", + [HLSL_OP1_FRACT] = "fract", + [HLSL_OP1_ISINF] = "isinf", +@@ -3718,8 +3797,9 @@ static void dump_ir_expr(struct vkd3d_string_buffer *buffer, const struct hlsl_i + vkd3d_string_buffer_printf(buffer, "%s (", debug_hlsl_expr_op(expr->op)); + for (i = 0; i < HLSL_MAX_OPERANDS && expr->operands[i].node; ++i) + { ++ if (i) ++ vkd3d_string_buffer_printf(buffer, " "); + dump_src(buffer, &expr->operands[i]); +- vkd3d_string_buffer_printf(buffer, " "); + } + vkd3d_string_buffer_printf(buffer, ")"); + } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index d67f820fe8b..a3e8ccc1e2a 100644 +index d67f820fe8b..8dbfd062177 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -233,6 +233,9 @@ struct hlsl_type @@ -2175,7 +3889,27 @@ index d67f820fe8b..a3e8ccc1e2a 100644 bool is_typedef; uint32_t is_minimum_precision : 1; -@@ -1184,8 +1187,8 @@ struct hlsl_ctx +@@ -715,8 +718,11 @@ enum hlsl_ir_expr_op + HLSL_OP1_BIT_NOT, + HLSL_OP1_CAST, + HLSL_OP1_CEIL, ++ HLSL_OP1_CLZ, + HLSL_OP1_COS, + HLSL_OP1_COS_REDUCED, /* Reduced range [-pi, pi], writes to .x */ ++ HLSL_OP1_COUNTBITS, ++ HLSL_OP1_CTZ, + HLSL_OP1_DSX, + HLSL_OP1_DSX_COARSE, + HLSL_OP1_DSX_FINE, +@@ -726,6 +732,7 @@ enum hlsl_ir_expr_op + HLSL_OP1_EXP2, + HLSL_OP1_F16TOF32, + HLSL_OP1_F32TOF16, ++ HLSL_OP1_FIND_MSB, + HLSL_OP1_FLOOR, + HLSL_OP1_FRACT, + HLSL_OP1_ISINF, +@@ -1184,8 +1191,8 @@ struct hlsl_ctx } constant_defs; /* 'c' registers where the constants expected by SM2 sincos are stored. */ struct hlsl_reg d3dsincosconst1, d3dsincosconst2; @@ -2186,7 +3920,7 @@ index d67f820fe8b..a3e8ccc1e2a 100644 /* Number of threads to be executed (on the X, Y, and Z dimensions) in a single thread group in * compute shader profiles. It is set using the numthreads() attribute in the entry point. */ -@@ -1541,6 +1544,12 @@ static inline bool hlsl_var_has_buffer_offset_register_reservation(struct hlsl_c +@@ -1541,6 +1548,12 @@ static inline bool hlsl_var_has_buffer_offset_register_reservation(struct hlsl_c return var->reg_reservation.reg_type == 'c' && var->buffer == ctx->globals_buffer; } @@ -2199,7 +3933,7 @@ index d67f820fe8b..a3e8ccc1e2a 100644 char *hlsl_sprintf_alloc(struct hlsl_ctx *ctx, const char *fmt, ...) VKD3D_PRINTF_FUNC(2, 3); const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op); -@@ -1693,6 +1702,9 @@ struct hlsl_type *hlsl_new_stream_output_type(struct hlsl_ctx *ctx, +@@ -1693,6 +1706,9 @@ struct hlsl_type *hlsl_new_stream_output_type(struct hlsl_ctx *ctx, struct hlsl_ir_node *hlsl_new_ternary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2, struct hlsl_ir_node *arg3); @@ -2209,6 +3943,18 @@ index d67f820fe8b..a3e8ccc1e2a 100644 void hlsl_init_simple_deref_from_var(struct hlsl_deref *deref, struct hlsl_ir_var *var); struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, +@@ -1779,10 +1795,10 @@ bool hlsl_type_is_integer(const struct hlsl_type *type); + bool hlsl_type_is_floating_point(const struct hlsl_type *type); + bool hlsl_type_is_row_major(const struct hlsl_type *type); + bool hlsl_type_is_signed_integer(const struct hlsl_type *type); ++bool hlsl_type_is_unsigned_integer(const struct hlsl_type *type); + unsigned int hlsl_type_minor_size(const struct hlsl_type *type); + unsigned int hlsl_type_major_size(const struct hlsl_type *type); + unsigned int hlsl_type_element_count(const struct hlsl_type *type); +-bool hlsl_type_is_integer(const struct hlsl_type *type); + bool hlsl_type_is_minimum_precision(const struct hlsl_type *type); + bool hlsl_type_is_resource(const struct hlsl_type *type); + bool hlsl_type_is_shader(const struct hlsl_type *type); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l index 0cdebb8a657..da9f0d39136 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l @@ -2223,10 +3969,129 @@ index 0cdebb8a657..da9f0d39136 100644 %% diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 024d96c5663..d83ad9fe7d8 100644 +index 024d96c5663..d3004d7cc8a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -3983,6 +3983,53 @@ static bool intrinsic_frac(struct hlsl_ctx *ctx, +@@ -3181,6 +3181,20 @@ static bool elementwise_intrinsic_float_convert_args(struct hlsl_ctx *ctx, + return true; + } + ++static bool elementwise_intrinsic_int_convert_args(struct hlsl_ctx *ctx, ++ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_type *type; ++ ++ if (!(type = elementwise_intrinsic_get_common_type(ctx, params, loc))) ++ return false; ++ ++ type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_INT, type->e.numeric.dimx, type->e.numeric.dimy); ++ ++ convert_args(ctx, params, type, loc); ++ return true; ++} ++ + static bool elementwise_intrinsic_uint_convert_args(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +@@ -3579,6 +3593,20 @@ static bool intrinsic_cosh(struct hlsl_ctx *ctx, + return write_cosh_or_sinh(ctx, params, loc, false); + } + ++static bool intrinsic_countbits(struct hlsl_ctx *ctx, ++ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; ++ struct hlsl_type *type; ++ ++ if (!elementwise_intrinsic_uint_convert_args(ctx, params, loc)) ++ return false; ++ type = convert_numeric_type(ctx, params->args[0]->data_type, HLSL_TYPE_UINT); ++ ++ operands[0] = params->args[0]; ++ return add_expr(ctx, params->instrs, HLSL_OP1_COUNTBITS, operands, type, loc); ++} ++ + static bool intrinsic_cross(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +@@ -3925,6 +3953,76 @@ static bool intrinsic_f32tof16(struct hlsl_ctx *ctx, + return add_expr(ctx, params->instrs, HLSL_OP1_F32TOF16, operands, type, loc); + } + ++static bool intrinsic_firstbithigh(struct hlsl_ctx *ctx, ++ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; ++ struct hlsl_type *type = params->args[0]->data_type; ++ struct hlsl_ir_node *c, *clz, *eq, *xor; ++ struct hlsl_constant_value v; ++ ++ if (hlsl_version_lt(ctx, 4, 0)) ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, ++ "The 'firstbithigh' intrinsic requires shader model 4.0 or higher."); ++ ++ if (hlsl_type_is_unsigned_integer(type)) ++ { ++ if (!elementwise_intrinsic_uint_convert_args(ctx, params, loc)) ++ return false; ++ } ++ else ++ { ++ if (!elementwise_intrinsic_int_convert_args(ctx, params, loc)) ++ return false; ++ } ++ type = convert_numeric_type(ctx, type, HLSL_TYPE_UINT); ++ ++ operands[0] = params->args[0]; ++ if (hlsl_version_lt(ctx, 5, 0)) ++ return add_expr(ctx, params->instrs, HLSL_OP1_FIND_MSB, operands, type, loc); ++ ++ v.u[0].u = 0x1f; ++ if (!(c = hlsl_new_constant(ctx, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &v, loc))) ++ return false; ++ hlsl_block_add_instr(params->instrs, c); ++ ++ if (!(clz = add_expr(ctx, params->instrs, HLSL_OP1_CLZ, operands, type, loc))) ++ return false; ++ if (!(xor = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_BIT_XOR, c, clz, loc))) ++ return false; ++ ++ v.u[0].i = -1; ++ if (!(c = hlsl_new_constant(ctx, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &v, loc))) ++ return false; ++ hlsl_block_add_instr(params->instrs, c); ++ ++ if (!(eq = add_binary_comparison_expr(ctx, params->instrs, HLSL_OP2_EQUAL, clz, c, loc))) ++ return false; ++ ++ operands[0] = eq; ++ operands[1] = add_implicit_conversion(ctx, params->instrs, c, type, loc); ++ operands[2] = xor; ++ return add_expr(ctx, params->instrs, HLSL_OP3_TERNARY, operands, type, loc); ++} ++ ++static bool intrinsic_firstbitlow(struct hlsl_ctx *ctx, ++ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; ++ struct hlsl_type *type; ++ ++ if (hlsl_version_lt(ctx, 4, 0)) ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, ++ "The 'firstbitlow' intrinsic requires shader model 4.0 or higher."); ++ ++ if (!elementwise_intrinsic_uint_convert_args(ctx, params, loc)) ++ return false; ++ type = convert_numeric_type(ctx, params->args[0]->data_type, HLSL_TYPE_UINT); ++ ++ operands[0] = params->args[0]; ++ return add_expr(ctx, params->instrs, HLSL_OP1_CTZ, operands, type, loc); ++} ++ + static bool intrinsic_floor(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +@@ -3983,6 +4081,53 @@ static bool intrinsic_frac(struct hlsl_ctx *ctx, return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_FRACT, arg, loc); } @@ -2280,7 +4145,7 @@ index 024d96c5663..d83ad9fe7d8 100644 static bool intrinsic_fwidth(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { -@@ -4701,7 +4748,8 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * +@@ -4701,7 +4846,8 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * } if (!strcmp(name, "tex2Dbias") @@ -2290,7 +4155,7 @@ index 024d96c5663..d83ad9fe7d8 100644 { struct hlsl_ir_node *lod, *c; -@@ -4853,6 +4901,12 @@ static bool intrinsic_texCUBE(struct hlsl_ctx *ctx, +@@ -4853,6 +4999,12 @@ static bool intrinsic_texCUBE(struct hlsl_ctx *ctx, return intrinsic_tex(ctx, params, loc, "texCUBE", HLSL_SAMPLER_DIM_CUBE); } @@ -2303,7 +4168,20 @@ index 024d96c5663..d83ad9fe7d8 100644 static bool intrinsic_texCUBEgrad(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { -@@ -5283,6 +5337,7 @@ intrinsic_functions[] = +@@ -5263,6 +5415,7 @@ intrinsic_functions[] = + {"clip", 1, true, intrinsic_clip}, + {"cos", 1, true, intrinsic_cos}, + {"cosh", 1, true, intrinsic_cosh}, ++ {"countbits", 1, true, intrinsic_countbits}, + {"cross", 2, true, intrinsic_cross}, + {"ddx", 1, true, intrinsic_ddx}, + {"ddx_coarse", 1, true, intrinsic_ddx_coarse}, +@@ -5280,9 +5433,12 @@ intrinsic_functions[] = + {"f16tof32", 1, true, intrinsic_f16tof32}, + {"f32tof16", 1, true, intrinsic_f32tof16}, + {"faceforward", 3, true, intrinsic_faceforward}, ++ {"firstbithigh", 1, true, intrinsic_firstbithigh}, ++ {"firstbitlow", 1, true, intrinsic_firstbitlow}, {"floor", 1, true, intrinsic_floor}, {"fmod", 2, true, intrinsic_fmod}, {"frac", 1, true, intrinsic_frac}, @@ -2311,7 +4189,7 @@ index 024d96c5663..d83ad9fe7d8 100644 {"fwidth", 1, true, intrinsic_fwidth}, {"isinf", 1, true, intrinsic_isinf}, {"ldexp", 2, true, intrinsic_ldexp}, -@@ -5327,6 +5382,7 @@ intrinsic_functions[] = +@@ -5327,6 +5483,7 @@ intrinsic_functions[] = {"tex3Dgrad", 4, false, intrinsic_tex3Dgrad}, {"tex3Dproj", 2, false, intrinsic_tex3Dproj}, {"texCUBE", -1, false, intrinsic_texCUBE}, @@ -2319,7 +4197,7 @@ index 024d96c5663..d83ad9fe7d8 100644 {"texCUBEgrad", 4, false, intrinsic_texCUBEgrad}, {"texCUBEproj", 2, false, intrinsic_texCUBEproj}, {"transpose", 1, true, intrinsic_transpose}, -@@ -8059,7 +8115,7 @@ resource_format: +@@ -8059,7 +8216,7 @@ resource_format: { uint32_t modifiers = $1; @@ -2329,7 +4207,7 @@ index 024d96c5663..d83ad9fe7d8 100644 } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 0b3dee4d2ce..eaf7d7a3d63 100644 +index 0b3dee4d2ce..2138c3776a7 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -175,12 +175,29 @@ static unsigned int hlsl_type_get_packed_size(const struct hlsl_type *type) @@ -2501,10 +4379,9 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 ret.writemask = vkd3d_write_mask_from_component_count(component_count); record_allocation(ctx, allocator, allocator->reg_count, - vkd3d_write_mask_from_component_count(reg_size), first_write, last_read, mode, vip); -+ vkd3d_write_mask_from_component_count(reg_size), mode, vip); - return ret; - } - +- return ret; +-} +- -/* Allocate a register with writemask, while reserving reg_writemask. */ -static struct hlsl_reg allocate_register_with_masks(struct hlsl_ctx *ctx, - struct register_allocator *allocator, unsigned int first_write, unsigned int last_read, @@ -2529,9 +4406,10 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 - ret.allocation_size = 1; - ret.writemask = writemask; - ret.allocated = true; -- return ret; --} -- ++ vkd3d_write_mask_from_component_count(reg_size), mode, vip); + return ret; + } + -static bool is_range_available(const struct register_allocator *allocator, unsigned int first_write, - unsigned int last_read, uint32_t reg_idx, unsigned int reg_size, int mode, bool vip) +static bool is_range_available(const struct register_allocator *allocator, @@ -2706,11 +4584,11 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 + if (var->data_type->class <= HLSL_CLASS_VECTOR) + reg->writemask = vkd3d_write_mask_from_component_count(var->data_type->e.numeric.dimx); + reg->allocated = true; ++ ++ ctx->temp_count += reg->allocation_size; - TRACE("Allocated %s to %s (liveness %u-%u).\n", var->name, - debug_register(var->regs[HLSL_REGSET_NUMERIC], var->data_type), var->first_write, var->last_read); -+ ctx->temp_count += reg->allocation_size; -+ + TRACE("Allocated %s to %s.\n", var->name, + debug_register(var->regs[HLSL_REGSET_NUMERIC], var->data_type)); } @@ -3237,7 +5115,15 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 dst_param->reg.dimension = VSIR_DIMENSION_NONE; dst_param->reg.idx[0].offset = var->regs[HLSL_REGSET_SAMPLERS].index + i; dst_param->write_mask = 0; -@@ -9467,8 +9714,6 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr +@@ -8784,6 +9031,7 @@ static void vsir_src_from_hlsl_constant_value(struct vkd3d_shader_src_param *src + } + + src->reg.dimension = VSIR_DIMENSION_VEC4; ++ src->swizzle = VKD3D_SHADER_NO_SWIZZLE; + for (i = 0, j = 0; i < 4; ++i) + { + if ((map_writemask & (1u << i)) && (j < width)) +@@ -9467,8 +9715,6 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr break; case HLSL_OP3_CMP: @@ -3246,7 +5132,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_CMP, 0, 0, true); break; -@@ -9930,10 +10175,14 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_co +@@ -9930,10 +10176,14 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_co struct hlsl_ir_function_decl *func, struct list *semantic_vars, struct hlsl_block *body, uint64_t config_flags, struct vsir_program *program) { @@ -3262,7 +5148,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 if (ctx->result) return; -@@ -9944,7 +10193,19 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_co +@@ -9944,7 +10194,19 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_co sm1_generate_vsir_block(ctx, body, program); @@ -3282,7 +5168,40 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 if (ctx->result) return; -@@ -11437,6 +11698,7 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, +@@ -10795,11 +11057,32 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, + generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_ROUND_PI, 0, 0, true); + return true; + ++ case HLSL_OP1_CLZ: ++ VKD3D_ASSERT(hlsl_type_is_integer(dst_type)); ++ VKD3D_ASSERT(hlsl_version_ge(ctx, 5, 0)); ++ if (hlsl_type_is_signed_integer(src_type)) ++ generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_FIRSTBIT_SHI, 0, 0, true); ++ else ++ generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_FIRSTBIT_HI, 0, 0, true); ++ return true; ++ + case HLSL_OP1_COS: + VKD3D_ASSERT(type_is_float(dst_type)); + sm4_generate_vsir_expr_with_two_destinations(ctx, program, VSIR_OP_SINCOS, expr, 1); + return true; + ++ case HLSL_OP1_COUNTBITS: ++ VKD3D_ASSERT(hlsl_type_is_integer(dst_type)); ++ VKD3D_ASSERT(hlsl_version_ge(ctx, 5, 0)); ++ generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_COUNTBITS, 0, 0, true); ++ return true; ++ ++ case HLSL_OP1_CTZ: ++ VKD3D_ASSERT(hlsl_type_is_integer(dst_type)); ++ VKD3D_ASSERT(hlsl_version_ge(ctx, 5, 0)); ++ generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_FIRSTBIT_LO, 0, 0, true); ++ return true; ++ + case HLSL_OP1_DSX: + VKD3D_ASSERT(type_is_float(dst_type)); + generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_DSX, 0, 0, true); +@@ -11437,6 +11720,7 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, const struct vkd3d_shader_version *version = &program->shader_version; const struct hlsl_ir_node *sample_index = load->sample_index.node; const struct hlsl_ir_node *texel_offset = load->texel_offset.node; @@ -3290,7 +5209,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 const struct hlsl_ir_node *coords = load->coords.node; unsigned int coords_writemask = VKD3DSP_WRITEMASK_ALL; const struct hlsl_deref *resource = &load->resource; -@@ -11444,20 +11706,15 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, +@@ -11444,20 +11728,15 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim = load->sampling_dim; bool tgsm = load->resource.var->is_tgsm; struct vkd3d_shader_instruction *ins; @@ -3313,7 +5232,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 if (!tgsm) { -@@ -11468,15 +11725,19 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, +@@ -11468,15 +11747,19 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, hlsl_fixme(ctx, &load->node.loc, "Load from structured TGSM."); return false; } @@ -3335,7 +5254,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 return false; if (texel_offset && !sm4_generate_vsir_validate_texel_offset_aoffimmi(texel_offset)) -@@ -11504,10 +11765,15 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, +@@ -11504,10 +11787,15 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, coords_writemask); if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, @@ -3353,7 +5272,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 { if (sample_index->type == HLSL_IR_CONSTANT) vsir_src_from_hlsl_constant_value(&ins->src[2], ctx, -@@ -12093,16 +12359,15 @@ static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, struct list *se +@@ -12093,16 +12381,15 @@ static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, struct list *se struct hlsl_block block = {0}; struct hlsl_scope *scope; struct hlsl_ir_var *var; @@ -3372,7 +5291,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 hlsl_block_init(&block); -@@ -12113,8 +12378,8 @@ static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, struct list *se +@@ -12113,8 +12400,8 @@ static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, struct list *se sm4_generate_vsir_instr_dcl_semantic(ctx, program, var, &block, &var->loc); } @@ -3383,7 +5302,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 LIST_FOR_EACH_ENTRY(scope, &ctx->scopes, struct hlsl_scope, entry) { -@@ -12427,7 +12692,7 @@ static void sm4_generate_vsir_add_dcl_constant_buffer(struct hlsl_ctx *ctx, +@@ -12427,7 +12714,7 @@ static void sm4_generate_vsir_add_dcl_constant_buffer(struct hlsl_ctx *ctx, return; } @@ -3392,7 +5311,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 src_param = &ins->declaration.cb.src; vsir_src_param_init(src_param, VKD3DSPR_CONSTBUFFER, VSIR_DATA_F32, 0); -@@ -12592,6 +12857,9 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, +@@ -12592,6 +12879,9 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, { switch (component_type->sampler_dim) { @@ -3402,7 +5321,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 case HLSL_SAMPLER_DIM_RAW_BUFFER: opcode = VSIR_OP_DCL_RESOURCE_RAW; break; -@@ -12647,7 +12915,7 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, +@@ -12647,7 +12937,7 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, else if (component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) { ins->structured = true; @@ -3411,7 +5330,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 ins->declaration.structured_resource.byte_stride = ins->resource_stride; } else -@@ -12784,6 +13052,7 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, +@@ -12784,6 +13074,7 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, } program->ssa_count = 0; @@ -3419,7 +5338,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 if (version->type == VKD3D_SHADER_TYPE_HULL) generate_vsir_add_program_instruction(ctx, program, -@@ -12801,6 +13070,7 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, +@@ -12801,6 +13092,7 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, generate_vsir_scan_global_flags(ctx, program, semantic_vars, func); program->ssa_count = ctx->ssa_count; @@ -3427,7 +5346,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 } /* For some reason, for matrices, values from default value initializers end -@@ -12915,14 +13185,16 @@ static enum D3D_RESOURCE_RETURN_TYPE sm4_data_type(const struct hlsl_type *type) +@@ -12915,14 +13207,16 @@ static enum D3D_RESOURCE_RETURN_TYPE sm4_data_type(const struct hlsl_type *type) static D3D_SHADER_INPUT_TYPE sm4_resource_type(const struct hlsl_type *type) { @@ -3446,7 +5365,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 default: break; } -@@ -12998,7 +13270,8 @@ static D3D_SHADER_VARIABLE_TYPE sm4_base_type(const struct hlsl_type *type) +@@ -12998,7 +13292,8 @@ static D3D_SHADER_VARIABLE_TYPE sm4_base_type(const struct hlsl_type *type) vkd3d_unreachable(); } @@ -3456,7 +5375,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 { const struct hlsl_type *array_type = hlsl_get_multiarray_element_type(type); const char *name = array_type->name ? array_type->name : ""; -@@ -13007,7 +13280,10 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b +@@ -13007,7 +13302,10 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b size_t name_offset = 0; size_t i; @@ -3468,7 +5387,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 return; if (profile->major_version >= 5) -@@ -13029,7 +13305,7 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b +@@ -13029,7 +13327,7 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b continue; field->name_bytecode_offset = put_string(buffer, field->name); @@ -3477,7 +5396,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 ++field_count; } -@@ -13038,15 +13314,29 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b +@@ -13038,15 +13336,29 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b for (i = 0; i < array_type->e.record.field_count; ++i) { struct hlsl_struct_field *field = &array_type->e.record.fields[i]; @@ -3510,7 +5429,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 put_u32(buffer, vkd3d_make_u32(1, hlsl_type_component_count(array_type))); put_u32(buffer, vkd3d_make_u32(array_size, field_count)); put_u32(buffer, fields_offset); -@@ -13054,7 +13344,11 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b +@@ -13054,7 +13366,11 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b else { VKD3D_ASSERT(array_type->class <= HLSL_CLASS_LAST_NUMERIC); @@ -3523,7 +5442,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 put_u32(buffer, vkd3d_make_u32(array_type->e.numeric.dimy, array_type->e.numeric.dimx)); put_u32(buffer, vkd3d_make_u32(array_size, 0)); put_u32(buffer, 1); -@@ -13073,9 +13367,9 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b +@@ -13073,9 +13389,9 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rdef) { uint32_t binding_desc_size = (hlsl_version_ge(ctx, 5, 1) ? 10 : 8) * sizeof(uint32_t); @@ -3535,14 +5454,15 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 const struct hlsl_profile_info *profile = ctx->profile; struct vkd3d_bytecode_buffer buffer = {0}; struct extern_resource *extern_resources; -@@ -13097,10 +13391,20 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd +@@ -13097,10 +13413,20 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry) { if (cbuffer->reg.allocated) - ++cbuffer_count; + ++buffer_count; -+ } -+ + } + +- put_u32(&buffer, cbuffer_count); + for (i = 0; i < extern_resources_count; ++i) + { + const struct extern_resource *resource = &extern_resources[i]; @@ -3551,14 +5471,13 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 + continue; + + ++buffer_count; - } - -- put_u32(&buffer, cbuffer_count); ++ } ++ + put_u32(&buffer, buffer_count); cbuffer_position = put_u32(&buffer, 0); put_u32(&buffer, extern_resources_count); resource_position = put_u32(&buffer, 0); -@@ -13141,12 +13445,19 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd +@@ -13141,12 +13467,19 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd put_u32(&buffer, sm4_resource_type(resource->component_type)); if (resource->regset == HLSL_REGSET_TEXTURES || resource->regset == HLSL_REGSET_UAVS) { @@ -3580,7 +5499,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 } else { -@@ -13175,8 +13486,8 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd +@@ -13175,8 +13508,8 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd /* Buffers. */ @@ -3591,7 +5510,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry) { unsigned int var_count = 0; -@@ -13198,6 +13509,24 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd +@@ -13198,6 +13531,24 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd put_u32(&buffer, cbuffer->type == HLSL_BUFFER_CONSTANT ? D3D_CT_CBUFFER : D3D_CT_TBUFFER); } @@ -3616,7 +5535,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 i = 0; LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry) { -@@ -13205,7 +13534,18 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd +@@ -13205,7 +13556,18 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd continue; string_offset = put_string(&buffer, cbuffer->name); @@ -3636,7 +5555,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 } i = 0; -@@ -13216,7 +13556,7 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd +@@ -13216,7 +13578,7 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd if (!cbuffer->reg.allocated) continue; @@ -3645,7 +5564,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { -@@ -13255,7 +13595,7 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd +@@ -13255,7 +13617,7 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd string_offset = put_string(&buffer, var->name); set_u32(&buffer, var_offset, string_offset); @@ -3654,7 +5573,7 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 set_u32(&buffer, var_offset + 4 * sizeof(uint32_t), var->data_type->bytecode_offset); if (var->default_values) -@@ -13298,6 +13638,42 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd +@@ -13298,6 +13660,42 @@ static void sm4_generate_rdef(struct hlsl_ctx *ctx, struct vkd3d_shader_code *rd } } @@ -3697,14 +5616,228 @@ index 0b3dee4d2ce..eaf7d7a3d63 100644 creator_offset = put_string(&buffer, vkd3d_shader_get_version(NULL, NULL)); set_u32(&buffer, creator_position, creator_offset); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c -index d339a06e6c7..252ed51a4e4 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c -@@ -250,6 +250,36 @@ static bool fold_ceil(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, +@@ -13720,6 +14118,102 @@ static void loop_unrolling_execute(struct hlsl_ctx *ctx, struct hlsl_block *bloc + hlsl_transform_ir(ctx, resolve_loops, block, NULL); + } + ++static bool lower_countbits(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) ++{ ++ struct hlsl_ir_function_decl *func; ++ struct hlsl_ir_node *call, *rhs; ++ struct hlsl_ir_expr *expr; ++ struct hlsl_ir_var *lhs; ++ char *body; ++ ++ /* Like vkd3d_popcount(). */ ++ static const char template[] = ++ "typedef uint%u uintX;\n" ++ "uintX countbits(uintX v)\n" ++ "{\n" ++ " v -= (v >> 1) & 0x55555555;\n" ++ " v = (v & 0x33333333) + ((v >> 2) & 0x33333333);\n" ++ " return (((v + (v >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;\n" ++ "}\n"; ++ ++ if (node->type != HLSL_IR_EXPR) ++ return false; ++ ++ expr = hlsl_ir_expr(node); ++ if (expr->op != HLSL_OP1_COUNTBITS) ++ return false; ++ ++ rhs = expr->operands[0].node; ++ if (!(body = hlsl_sprintf_alloc(ctx, template, hlsl_type_component_count(rhs->data_type)))) ++ return false; ++ func = hlsl_compile_internal_function(ctx, "countbits", body); ++ vkd3d_free(body); ++ if (!func) ++ return false; ++ ++ lhs = func->parameters.vars[0]; ++ hlsl_block_add_simple_store(ctx, block, lhs, rhs); ++ ++ if (!(call = hlsl_new_call(ctx, func, &node->loc))) ++ return false; ++ hlsl_block_add_instr(block, call); ++ ++ hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); ++ ++ return true; ++} ++ ++static bool lower_ctz(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) ++{ ++ struct hlsl_ir_function_decl *func; ++ struct hlsl_ir_node *call, *rhs; ++ struct hlsl_ir_expr *expr; ++ struct hlsl_ir_var *lhs; ++ char *body; ++ ++ /* ctz() returns the bit number of the least significant 1-bit. ++ * Bit numbers count from the least significant bit. */ ++ static const char template[] = ++ "typedef uint%u uintX;\n" ++ "uintX ctz(uintX v)\n" ++ "{\n" ++ " uintX c = 31;\n" ++ " v &= -v;\n" ++ " c = (v & 0x0000ffff) ? c - 16 : c;\n" ++ " c = (v & 0x00ff00ff) ? c - 8 : c;\n" ++ " c = (v & 0x0f0f0f0f) ? c - 4 : c;\n" ++ " c = (v & 0x33333333) ? c - 2 : c;\n" ++ " c = (v & 0x55555555) ? c - 1 : c;\n" ++ " return v ? c : -1;\n" ++ "}\n"; ++ ++ if (node->type != HLSL_IR_EXPR) ++ return false; ++ ++ expr = hlsl_ir_expr(node); ++ if (expr->op != HLSL_OP1_CTZ) ++ return false; ++ ++ rhs = expr->operands[0].node; ++ if (!(body = hlsl_sprintf_alloc(ctx, template, hlsl_type_component_count(rhs->data_type)))) ++ return false; ++ func = hlsl_compile_internal_function(ctx, "ctz", body); ++ vkd3d_free(body); ++ if (!func) ++ return false; ++ ++ lhs = func->parameters.vars[0]; ++ hlsl_block_add_simple_store(ctx, block, lhs, rhs); ++ ++ if (!(call = hlsl_new_call(ctx, func, &node->loc))) ++ return false; ++ hlsl_block_add_instr(block, call); ++ ++ hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); ++ ++ return true; ++} ++ + static bool lower_f16tof32(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) + { + struct hlsl_ir_function_decl *func; +@@ -13862,6 +14356,69 @@ static bool lower_f32tof16(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, stru return true; } ++static bool lower_find_msb(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) ++{ ++ struct hlsl_ir_function_decl *func; ++ struct hlsl_ir_node *call, *rhs; ++ struct hlsl_ir_expr *expr; ++ struct hlsl_ir_var *lhs; ++ char *body; ++ ++ /* For positive numbers, find_msb() returns the bit number of the most ++ * significant 1-bit. For negative numbers, it returns the bit number of ++ * the most significant 0-bit. Bit numbers count from the least ++ * significant bit. */ ++ static const char template[] = ++ "typedef %s intX;\n" ++ "uint%u find_msb(intX v)\n" ++ "{\n" ++ " intX c, mask;\n" ++ " v = v < 0 ? ~v : v;\n" ++ " mask = v & 0xffff0000;\n" ++ " v = mask ? mask : v;\n" ++ " c = mask ? 16 : v ? 0 : -1;\n" ++ " mask = v & 0xff00ff00;\n" ++ " v = mask ? mask : v;\n" ++ " c = mask ? c + 8 : c;\n" ++ " mask = v & 0xf0f0f0f0;\n" ++ " v = mask ? mask : v;\n" ++ " c = mask ? c + 4 : c;\n" ++ " mask = v & 0xcccccccc;\n" ++ " v = mask ? mask : v;\n" ++ " c = mask ? c + 2 : c;\n" ++ " mask = v & 0xaaaaaaaa;\n" ++ " v = mask ? mask : v;\n" ++ " c = mask ? c + 1 : c;\n" ++ " return c;\n" ++ "}\n"; ++ ++ if (node->type != HLSL_IR_EXPR) ++ return false; ++ ++ expr = hlsl_ir_expr(node); ++ if (expr->op != HLSL_OP1_FIND_MSB) ++ return false; ++ ++ rhs = expr->operands[0].node; ++ if (!(body = hlsl_sprintf_alloc(ctx, template, rhs->data_type->name, hlsl_type_component_count(rhs->data_type)))) ++ return false; ++ func = hlsl_compile_internal_function(ctx, "find_msb", body); ++ vkd3d_free(body); ++ if (!func) ++ return false; ++ ++ lhs = func->parameters.vars[0]; ++ hlsl_block_add_simple_store(ctx, block, lhs, rhs); ++ ++ if (!(call = hlsl_new_call(ctx, func, &node->loc))) ++ return false; ++ hlsl_block_add_instr(block, call); ++ ++ hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); ++ ++ return true; ++} ++ + static bool lower_isinf(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) + { + struct hlsl_ir_function_decl *func; +@@ -13978,8 +14535,11 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v + + if (hlsl_version_ge(ctx, 4, 0) && hlsl_version_lt(ctx, 5, 0)) + { ++ lower_ir(ctx, lower_countbits, body); ++ lower_ir(ctx, lower_ctz, body); + lower_ir(ctx, lower_f16tof32, body); + lower_ir(ctx, lower_f32tof16, body); ++ lower_ir(ctx, lower_find_msb, body); + } + + lower_ir(ctx, lower_isinf, body); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c +index d339a06e6c7..7b3b0470d5d 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c +@@ -250,6 +250,118 @@ static bool fold_ceil(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + return true; + } + ++static bool fold_clz(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, ++ const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) ++{ ++ enum hlsl_base_type type = src->node.data_type->e.numeric.type; ++ unsigned int k, v; ++ ++ for (k = 0; k < dst_type->e.numeric.dimx; ++k) ++ { ++ switch (type) ++ { ++ case HLSL_TYPE_INT: ++ v = src->value.u[k].i < 0 ? ~src->value.u[k].u : src->value.u[k].u; ++ break; ++ ++ case HLSL_TYPE_UINT: ++ v = src->value.u[k].u; ++ break; ++ ++ default: ++ FIXME("Fold 'clz' for type %s.\n", debug_hlsl_type(ctx, dst_type)); ++ return false; ++ } ++ ++ dst->u[k].u = v ? vkd3d_log2i(v) ^ 0x1f : ~0u; ++ } ++ ++ return true; ++} ++ +static bool fold_cos(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) +{ @@ -3734,11 +5867,64 @@ index d339a06e6c7..252ed51a4e4 100644 + + return true; +} ++ ++static bool fold_countbits(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, ++ const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) ++{ ++ enum hlsl_base_type type = dst_type->e.numeric.type; ++ unsigned int k; ++ ++ VKD3D_ASSERT(type == src->node.data_type->e.numeric.type); ++ ++ for (k = 0; k < dst_type->e.numeric.dimx; ++k) ++ { ++ switch (type) ++ { ++ case HLSL_TYPE_UINT: ++ dst->u[k].u = vkd3d_popcount(src->value.u[k].u); ++ break; ++ ++ default: ++ FIXME("Fold 'countbits' for type %s.\n", debug_hlsl_type(ctx, dst_type)); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++static bool fold_ctz(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, ++ const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) ++{ ++ enum hlsl_base_type type = dst_type->e.numeric.type; ++ unsigned int k; ++ ++ VKD3D_ASSERT(type == src->node.data_type->e.numeric.type); ++ ++ for (k = 0; k < dst_type->e.numeric.dimx; ++k) ++ { ++ switch (type) ++ { ++ case HLSL_TYPE_UINT: ++ if (!src->value.u[k].u) ++ dst->u[k].u = ~0u; ++ else ++ dst->u[k].u = vkd3d_ctz(src->value.u[k].u); ++ break; ++ ++ default: ++ FIXME("Fold 'ctz' for type %s.\n", debug_hlsl_type(ctx, dst_type)); ++ return false; ++ } ++ } ++ ++ return true; ++} + static bool fold_exp2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) { -@@ -478,6 +508,48 @@ static bool fold_rcp(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons +@@ -478,6 +590,48 @@ static bool fold_rcp(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons return true; } @@ -3787,7 +5973,7 @@ index d339a06e6c7..252ed51a4e4 100644 static bool fold_rsq(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc) { -@@ -544,6 +616,36 @@ static bool fold_sat(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons +@@ -544,6 +698,36 @@ static bool fold_sat(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons return true; } @@ -3824,7 +6010,7 @@ index d339a06e6c7..252ed51a4e4 100644 static bool fold_sqrt(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc) { -@@ -974,6 +1076,44 @@ static bool fold_lshift(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c +@@ -974,6 +1158,44 @@ static bool fold_lshift(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c return true; } @@ -3869,18 +6055,30 @@ index d339a06e6c7..252ed51a4e4 100644 static bool fold_max(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2) { -@@ -1263,6 +1403,10 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, +@@ -1263,6 +1485,22 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, success = fold_ceil(ctx, &res, instr->data_type, arg1); break; ++ case HLSL_OP1_CLZ: ++ success = fold_clz(ctx, &res, instr->data_type, arg1); ++ break; ++ + case HLSL_OP1_COS: + success = fold_cos(ctx, &res, instr->data_type, arg1); + break; ++ ++ case HLSL_OP1_COUNTBITS: ++ success = fold_countbits(ctx, &res, instr->data_type, arg1); ++ break; ++ ++ case HLSL_OP1_CTZ: ++ success = fold_ctz(ctx, &res, instr->data_type, arg1); ++ break; + case HLSL_OP1_EXP2: success = fold_exp2(ctx, &res, instr->data_type, arg1); break; -@@ -1291,6 +1435,14 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, +@@ -1291,6 +1529,14 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, success = fold_rcp(ctx, &res, instr->data_type, arg1, &instr->loc); break; @@ -3895,7 +6093,7 @@ index d339a06e6c7..252ed51a4e4 100644 case HLSL_OP1_RSQ: success = fold_rsq(ctx, &res, instr->data_type, arg1, &instr->loc); break; -@@ -1299,6 +1451,10 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, +@@ -1299,6 +1545,10 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, success = fold_sat(ctx, &res, instr->data_type, arg1); break; @@ -3906,7 +6104,7 @@ index d339a06e6c7..252ed51a4e4 100644 case HLSL_OP1_SQRT: success = fold_sqrt(ctx, &res, instr->data_type, arg1, &instr->loc); break; -@@ -1373,6 +1529,10 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, +@@ -1373,6 +1623,10 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, success = fold_dp2add(ctx, &res, instr->data_type, arg1, arg2, arg3); break; @@ -3917,7 +6115,7 @@ index d339a06e6c7..252ed51a4e4 100644 case HLSL_OP3_TERNARY: success = fold_ternary(ctx, &res, instr->data_type, arg1, arg2, arg3); break; -@@ -1393,74 +1553,6 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, +@@ -1393,76 +1647,9 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, return success; } @@ -3991,8 +6189,11 @@ index d339a06e6c7..252ed51a4e4 100644 - bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) { ++ static const struct hlsl_constant_value zero; struct hlsl_ir_constant *const_arg = NULL; -@@ -1502,26 +1594,26 @@ bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + struct hlsl_ir_node *mut_arg = NULL; + struct hlsl_ir_node *res_node; +@@ -1502,29 +1689,40 @@ bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *in switch (expr->op) { case HLSL_OP2_ADD: @@ -4025,7 +6226,21 @@ index d339a06e6c7..252ed51a4e4 100644 res_node = &const_arg->node; break; -@@ -1649,6 +1741,9 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst ++ case HLSL_OP2_LESS: ++ /* x < 0 -> false, if x is unsigned. */ ++ if (!hlsl_type_is_unsigned_integer(expr->operands[0].node->data_type) ++ || expr->operands[1].node->type != HLSL_IR_CONSTANT ++ || !hlsl_constant_is_zero(hlsl_ir_constant(expr->operands[1].node))) ++ break; ++ if (!(res_node = hlsl_new_constant(ctx, instr->data_type, &zero, &instr->loc))) ++ break; ++ list_add_before(&expr->node.entry, &res_node->entry); ++ break; ++ + default: + break; + } +@@ -1649,6 +1847,9 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst if (instr->data_type->class > HLSL_CLASS_VECTOR) return false; @@ -4036,16 +6251,16 @@ index d339a06e6c7..252ed51a4e4 100644 arg1 = expr->operands[0].node; diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 23e059a3490..29bf62709eb 100644 +index 23e059a3490..453b79c75d2 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -27,8 +27,53 @@ struct vsir_transformation_context +@@ -27,8 +27,54 @@ struct vsir_transformation_context uint64_t config_flags; const struct vkd3d_shader_compile_info *compile_info; struct vkd3d_shader_message_context *message_context; + struct vkd3d_shader_location null_location; - }; - ++}; ++ +static void vsir_transformation_context_init(struct vsir_transformation_context *ctx, + struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_message_context *message_context) @@ -4059,23 +6274,24 @@ index 23e059a3490..29bf62709eb 100644 + .message_context = message_context, + .null_location = {.source_name = compile_info->source_name}, + }; -+}; -+ + }; + +const char *vsir_data_type_get_name(enum vsir_data_type t, const char *error) +{ + static const char * const names[] = + { + [VSIR_DATA_BOOL ] = "bool", -+ [VSIR_DATA_F16 ] = "half", -+ [VSIR_DATA_F32 ] = "float", -+ [VSIR_DATA_F64 ] = "double", ++ [VSIR_DATA_F16 ] = "f16", ++ [VSIR_DATA_F32 ] = "f32", ++ [VSIR_DATA_F64 ] = "f64", ++ [VSIR_DATA_I8 ] = "i8", + [VSIR_DATA_I16 ] = "i16", -+ [VSIR_DATA_I32 ] = "int", ++ [VSIR_DATA_I32 ] = "i32", + [VSIR_DATA_I64 ] = "i64", -+ [VSIR_DATA_U8 ] = "uint8", -+ [VSIR_DATA_U16 ] = "uint16", -+ [VSIR_DATA_U32 ] = "uint", -+ [VSIR_DATA_U64 ] = "uint64", ++ [VSIR_DATA_U8 ] = "u8", ++ [VSIR_DATA_U16 ] = "u16", ++ [VSIR_DATA_U32 ] = "u32", ++ [VSIR_DATA_U64 ] = "u64", + [VSIR_DATA_SNORM ] = "snorm", + [VSIR_DATA_UNORM ] = "unorm", + [VSIR_DATA_OPAQUE ] = "opaque", @@ -4093,7 +6309,7 @@ index 23e059a3490..29bf62709eb 100644 const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) { static const char * const names[] = -@@ -373,6 +418,183 @@ const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) +@@ -373,6 +419,177 @@ const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) return error; } @@ -4155,7 +6371,7 @@ index 23e059a3490..29bf62709eb 100644 + return params; +} + -+bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *array, size_t reserve) ++static bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *array, size_t reserve) +{ + if (!vkd3d_array_reserve((void **)&array->elements, &array->capacity, reserve, sizeof(*array->elements))) + { @@ -4180,22 +6396,29 @@ index 23e059a3490..29bf62709eb 100644 + return true; +} + -+bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *array, -+ struct vkd3d_shader_immediate_constant_buffer *icb) ++struct vkd3d_shader_instruction *shader_instruction_array_append(struct vkd3d_shader_instruction_array *array) +{ -+ if (!vkd3d_array_reserve((void **)&array->icbs, &array->icb_capacity, array->icb_count + 1, sizeof(*array->icbs))) ++ if (!shader_instruction_array_insert_at(array, array->count, 1)) ++ return NULL; ++ ++ return &array->elements[array->count - 1]; ++} ++ ++bool vsir_program_add_icb(struct vsir_program *program, struct vkd3d_shader_immediate_constant_buffer *icb) ++{ ++ if (!vkd3d_array_reserve((void **)&program->icbs, &program->icb_capacity, ++ program->icb_count + 1, sizeof(*program->icbs))) + return false; + -+ array->icbs[array->icb_count++] = icb; ++ program->icbs[program->icb_count++] = icb; + + return true; +} + -+static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( -+ struct vkd3d_shader_instruction_array *array, const struct vkd3d_shader_src_param *params, size_t count); ++static struct vkd3d_shader_src_param *vsir_program_clone_src_params( ++ struct vsir_program *program, const struct vkd3d_shader_src_param *params, size_t count); + -+static bool shader_register_clone_relative_addresses(struct vkd3d_shader_register *reg, -+ struct vkd3d_shader_instruction_array *array) ++static bool shader_register_clone_relative_addresses(struct vkd3d_shader_register *reg, struct vsir_program *program) +{ + size_t i; + @@ -4204,45 +6427,45 @@ index 23e059a3490..29bf62709eb 100644 + if (!reg->idx[i].rel_addr) + continue; + -+ if (!(reg->idx[i].rel_addr = shader_instruction_array_clone_src_params(array, reg->idx[i].rel_addr, 1))) ++ if (!(reg->idx[i].rel_addr = vsir_program_clone_src_params(program, reg->idx[i].rel_addr, 1))) + return false; + } + + return true; +} + -+static struct vkd3d_shader_dst_param *shader_instruction_array_clone_dst_params( -+ struct vkd3d_shader_instruction_array *array, const struct vkd3d_shader_dst_param *params, size_t count) ++static struct vkd3d_shader_dst_param *vsir_program_clone_dst_params( ++ struct vsir_program *program, const struct vkd3d_shader_dst_param *params, size_t count) +{ + struct vkd3d_shader_dst_param *dst_params; + size_t i; + -+ if (!(dst_params = shader_dst_param_allocator_get(&array->dst_params, count))) ++ if (!(dst_params = vsir_program_get_dst_params(program, count))) + return NULL; + + memcpy(dst_params, params, count * sizeof(*params)); + for (i = 0; i < count; ++i) + { -+ if (!shader_register_clone_relative_addresses(&dst_params[i].reg, array)) ++ if (!shader_register_clone_relative_addresses(&dst_params[i].reg, program)) + return NULL; + } + + return dst_params; +} + -+static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( -+ struct vkd3d_shader_instruction_array *array, const struct vkd3d_shader_src_param *params, size_t count) ++static struct vkd3d_shader_src_param *vsir_program_clone_src_params( ++ struct vsir_program *program, const struct vkd3d_shader_src_param *params, size_t count) +{ + struct vkd3d_shader_src_param *src_params; + size_t i; + -+ if (!(src_params = shader_src_param_allocator_get(&array->src_params, count))) ++ if (!(src_params = vsir_program_get_src_params(program, count))) + return NULL; + + memcpy(src_params, params, count * sizeof(*params)); + for (i = 0; i < count; ++i) + { -+ if (!shader_register_clone_relative_addresses(&src_params[i].reg, array)) ++ if (!shader_register_clone_relative_addresses(&src_params[i].reg, program)) + return NULL; + } + @@ -4251,25 +6474,12 @@ index 23e059a3490..29bf62709eb 100644 + +static void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *array) +{ -+ unsigned int i; -+ + vkd3d_free(array->elements); -+ shader_param_allocator_destroy(&array->dst_params); -+ shader_param_allocator_destroy(&array->src_params); -+ for (i = 0; i < array->icb_count; ++i) -+ { -+ vkd3d_free(array->icbs[i]); -+ } -+ vkd3d_free(array->icbs); +} + +static bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *array, size_t reserve) +{ + memset(array, 0, sizeof(*array)); -+ /* Size the parameter initial allocations so they are large enough for most shaders. The -+ * code path for chained allocations will be tested if a few shaders need to use it. */ -+ shader_param_allocator_init(&array->dst_params, reserve - reserve / 8u, sizeof(struct vkd3d_shader_dst_param)); -+ shader_param_allocator_init(&array->src_params, reserve * 2u, sizeof(struct vkd3d_shader_src_param)); + + return shader_instruction_array_reserve(array, reserve); +} @@ -4277,31 +6487,190 @@ index 23e059a3490..29bf62709eb 100644 static int convert_parameter_info(const struct vkd3d_shader_compile_info *compile_info, unsigned int *ret_count, const struct vkd3d_shader_parameter1 **ret_parameters) { -@@ -864,6 +1086,23 @@ static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *i - vsir_instruction_init(ins, &location, VSIR_OP_NOP); +@@ -444,6 +661,11 @@ bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_c + program->shader_version = *version; + program->cf_type = cf_type; + program->normalisation_level = normalisation_level; ++ ++ /* Size the parameter initial allocations so they are large enough for most shaders. The ++ * code path for chained allocations will be tested if a few shaders need to use it. */ ++ shader_param_allocator_init(&program->dst_params, reserve - reserve / 8u, sizeof(struct vkd3d_shader_dst_param)); ++ shader_param_allocator_init(&program->src_params, reserve * 2u, sizeof(struct vkd3d_shader_src_param)); + if (!shader_instruction_array_init(&program->instructions, reserve)) + { + if (program->free_parameters) +@@ -471,6 +693,13 @@ void vsir_program_cleanup(struct vsir_program *program) + shader_signature_cleanup(&program->output_signature); + shader_signature_cleanup(&program->patch_constant_signature); + vkd3d_shader_free_scan_descriptor_info1(&program->descriptors); ++ shader_param_allocator_destroy(&program->src_params); ++ shader_param_allocator_destroy(&program->dst_params); ++ for (i = 0; i < program->icb_count; ++i) ++ { ++ vkd3d_free(program->icbs[i]); ++ } ++ vkd3d_free(program->icbs); } + const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( +@@ -796,16 +1025,15 @@ static void dst_param_init_output(struct vkd3d_shader_dst_param *dst, + dst->write_mask = write_mask; + } + +-void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, +- enum vkd3d_shader_opcode opcode) ++void vsir_instruction_init(struct vkd3d_shader_instruction *ins, ++ const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode opcode) + { +- memset(ins, 0, sizeof(*ins)); +- ins->location = *location; +- ins->opcode = opcode; +- ins->resource_data_type[0] = VSIR_DATA_F32; +- ins->resource_data_type[1] = VSIR_DATA_F32; +- ins->resource_data_type[2] = VSIR_DATA_F32; +- ins->resource_data_type[3] = VSIR_DATA_F32; ++ *ins = (struct vkd3d_shader_instruction) ++ { ++ .location = *location, ++ .opcode = opcode, ++ .resource_data_type = {VSIR_DATA_F32, VSIR_DATA_F32, VSIR_DATA_F32, VSIR_DATA_F32}, ++ }; + } + + bool vsir_instruction_init_with_params(struct vsir_program *program, +@@ -857,11 +1085,19 @@ static bool vsir_instruction_is_dcl(const struct vkd3d_shader_instruction *instr + || opcode == VSIR_OP_HS_DECLS; + } + +-static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *ins) +/* NOTE: Immediate constant buffers are not cloned, so the source must not be destroyed while the + * destination is in use. This seems like a reasonable requirement given how this is currently used. */ -+static bool vsir_program_iterator_clone_instruction(struct vsir_program_iterator *dst_it, -+ const struct vkd3d_shader_instruction *src) -+{ ++static bool vsir_program_iterator_clone_instruction(struct vsir_program *program, ++ struct vsir_program_iterator *dst_it, const struct vkd3d_shader_instruction *src) + { +- struct vkd3d_shader_location location = ins->location; + struct vkd3d_shader_instruction *dst = vsir_program_iterator_current(dst_it); + + *dst = *src; + -+ if (dst->dst_count && !(dst->dst = shader_instruction_array_clone_dst_params(dst_it->array, -+ dst->dst, dst->dst_count))) ++ if (dst->dst_count && !(dst->dst = vsir_program_clone_dst_params(program, dst->dst, dst->dst_count))) + return false; + +- vsir_instruction_init(ins, &location, VSIR_OP_NOP); ++ return !dst->src_count || (dst->src = vsir_program_clone_src_params(program, dst->src, dst->src_count)); + } + + static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, +@@ -1069,6 +1305,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program + ins->src[1].reg.u.immconst_f32[1] = 0.0f; + ins->src[1].reg.u.immconst_f32[2] = 0.0f; + ins->src[1].reg.u.immconst_f32[3] = 0.0f; ++ ins->src[1].swizzle = VKD3D_SHADER_NO_SWIZZLE; + + /* tmp.x = tmp.x || tmp.y */ + /* tmp.x = tmp.x || tmp.z */ +@@ -1422,7 +1659,7 @@ static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *progr + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + +- if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 3))) ++ if (!(srcs = vsir_program_get_src_params(program, 3))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + /* Note we run before I/O normalization. */ +@@ -1498,7 +1735,7 @@ static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program, + VKD3D_ASSERT(tex->src[1].reg.idx_count == 1); + VKD3D_ASSERT(!tex->src[1].reg.idx[0].rel_addr); + +- if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 4))) ++ if (!(srcs = vsir_program_get_src_params(program, 4))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + srcs[0] = tex->src[0]; +@@ -1541,7 +1778,7 @@ static enum vkd3d_result vsir_program_lower_texldd(struct vsir_program *program, + VKD3D_ASSERT(texldd->src[1].reg.idx_count == 1); + VKD3D_ASSERT(!texldd->src[1].reg.idx[0].rel_addr); + +- if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 5))) ++ if (!(srcs = vsir_program_get_src_params(program, 5))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + srcs[0] = texldd->src[0]; +@@ -1567,7 +1804,7 @@ static enum vkd3d_result vsir_program_lower_texldl(struct vsir_program *program, + VKD3D_ASSERT(texldl->src[1].reg.idx_count == 1); + VKD3D_ASSERT(!texldl->src[1].reg.idx[0].rel_addr); + +- if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 4))) ++ if (!(srcs = vsir_program_get_src_params(program, 4))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + srcs[0] = texldl->src[0]; +@@ -1585,6 +1822,64 @@ static enum vkd3d_result vsir_program_lower_texldl(struct vsir_program *program, + return VKD3D_OK; + } + ++static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, struct vkd3d_shader_instruction *ins) ++{ ++ unsigned int idx = ins->dst[0].reg.idx[0].offset; ++ struct vkd3d_shader_src_param *srcs; + -+ return !dst->src_count || !!(dst->src = shader_instruction_array_clone_src_params(dst_it->array, -+ dst->src, dst->src_count)); ++ /* tex t# -> sample t#, t#, resource#, sampler# ++ * Note that the t# destination will subsequently be turned into a temp. */ ++ ++ /* We run before I/O normalization. */ ++ VKD3D_ASSERT(program->normalisation_level < VSIR_NORMALISED_SM6); ++ ++ if (!(srcs = vsir_program_get_src_params(program, 3))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ vsir_src_param_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); ++ srcs[0].reg.idx[0].offset = idx; ++ srcs[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ srcs[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; ++ ++ vsir_src_param_init_resource(&srcs[1], idx, idx); ++ vsir_src_param_init_sampler(&srcs[2], idx, idx); ++ ++ ins->opcode = VSIR_OP_SAMPLE; ++ ins->src = srcs; ++ ins->src_count = 3; ++ ++ return VKD3D_OK; +} + - static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, - enum vsir_data_type data_type, enum vkd3d_shader_opcode *opcode, bool *requires_swap) ++static enum vkd3d_result vsir_program_lower_texcoord(struct vsir_program *program, ++ struct vkd3d_shader_instruction *ins) ++{ ++ unsigned int idx = ins->dst[0].reg.idx[0].offset; ++ struct vkd3d_shader_src_param *srcs; ++ ++ /* texcoord t# -> mov_sat t#, t# ++ * Note that the t# destination will subsequently be turned into a temp. */ ++ ++ /* We run before I/O normalization. */ ++ VKD3D_ASSERT(program->normalisation_level < VSIR_NORMALISED_SM6); ++ ++ if (!(srcs = vsir_program_get_src_params(program, 1))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ vsir_src_param_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); ++ srcs[0].reg.idx[0].offset = idx; ++ srcs[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ srcs[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; ++ ++ ins->dst[0].modifiers |= VKD3DSPDM_SATURATE; ++ ++ ins->opcode = VSIR_OP_MOV; ++ ins->src = srcs; ++ ins->src_count = 1; ++ ++ return VKD3D_OK; ++} ++ + static enum vkd3d_result vsir_program_lower_dcl_input(struct vsir_program *program, + struct vkd3d_shader_instruction *ins, struct vsir_transformation_context *ctx) { -@@ -1669,10 +1908,22 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr +@@ -1669,10 +1964,31 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr switch (ins->opcode) { @@ -4312,6 +6681,11 @@ index 23e059a3490..29bf62709eb 100644 + case VSIR_OP_SINCOS: + ret = vsir_program_lower_sm1_sincos(program, &it); + break; ++ ++ case VSIR_OP_TEXCOORD: ++ if ((ret = vsir_program_lower_texcoord(program, ins)) < 0) ++ return ret; ++ break; + case VSIR_OP_TEXCRD: ret = vsir_program_lower_texcrd(program, ins, message_context); @@ -4320,11 +6694,15 @@ index 23e059a3490..29bf62709eb 100644 + case VSIR_OP_TEXKILL: + ret = vsir_program_lower_texkill(program, &it, &tmp_idx); + break; ++ ++ case VSIR_OP_TEX: ++ ret = vsir_program_lower_tex(program, ins); ++ break; + case VSIR_OP_TEXLD: if (program->shader_version.major == 1) ret = vsir_program_lower_texld_sm1(program, ins, message_context); -@@ -1682,6 +1933,14 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr +@@ -1682,6 +1998,34 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr ret = vsir_program_lower_texld(program, ins, message_context); break; @@ -4335,11 +6713,31 @@ index 23e059a3490..29bf62709eb 100644 + case VSIR_OP_TEXLDL: + ret = vsir_program_lower_texldl(program, ins); + break; ++ ++ case VSIR_OP_TEXBEM: ++ case VSIR_OP_TEXBEML: ++ case VSIR_OP_TEXDEPTH: ++ case VSIR_OP_TEXDP3: ++ case VSIR_OP_TEXDP3TEX: ++ case VSIR_OP_TEXM3x2PAD: ++ case VSIR_OP_TEXM3x2TEX: ++ case VSIR_OP_TEXM3x3DIFF: ++ case VSIR_OP_TEXM3x3PAD: ++ case VSIR_OP_TEXM3x3SPEC: ++ case VSIR_OP_TEXM3x3TEX: ++ case VSIR_OP_TEXM3x3VSPEC: ++ case VSIR_OP_TEXREG2AR: ++ case VSIR_OP_TEXREG2GB: ++ case VSIR_OP_TEXREG2RGB: ++ vkd3d_shader_error(ctx->message_context, &ins->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, ++ "Aborting due to unimplemented feature: Combined sampler instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(ins->opcode, ""), ins->opcode); ++ return VKD3D_ERROR_NOT_IMPLEMENTED; + default: ret = VKD3D_OK; break; -@@ -1698,7 +1957,6 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr +@@ -1698,7 +2042,6 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr struct vsir_transformation_context *ctx) { struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); @@ -4347,7 +6745,7 @@ index 23e059a3490..29bf62709eb 100644 struct vkd3d_shader_instruction *ins; unsigned int tmp_idx = ~0u; enum vkd3d_result ret; -@@ -1707,16 +1965,6 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr +@@ -1707,16 +2050,6 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr { switch (ins->opcode) { @@ -4364,7 +6762,7 @@ index 23e059a3490..29bf62709eb 100644 case VSIR_OP_MAD: if ((ret = vsir_program_lower_precise_mad(program, &it, &tmp_idx)) < 0) return ret; -@@ -1725,6 +1973,8 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr +@@ -1725,6 +2058,8 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr case VSIR_OP_DCL: case VSIR_OP_DCL_CONSTANT_BUFFER: case VSIR_OP_DCL_GLOBAL_FLAGS: @@ -4373,7 +6771,7 @@ index 23e059a3490..29bf62709eb 100644 case VSIR_OP_DCL_SAMPLER: case VSIR_OP_DCL_TEMPS: case VSIR_OP_DCL_TESSELLATOR_DOMAIN: -@@ -1765,25 +2015,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr +@@ -1765,51 +2100,67 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr break; case VSIR_OP_SINCOS: @@ -4391,16 +6789,96 @@ index 23e059a3490..29bf62709eb 100644 - - case VSIR_OP_TEXLDD: - if ((ret = vsir_program_lower_texldd(program, ins)) < 0) -- return ret; -- break; -- -- case VSIR_OP_TEXLDL: -- if ((ret = vsir_program_lower_texldl(program, ins)) < 0) + if ((ret = vsir_program_lower_sm4_sincos(program, &it, ctx)) < 0) return ret; break; -@@ -1823,16 +2055,19 @@ static enum vkd3d_result vsir_program_ensure_ret(struct vsir_program *program, +- case VSIR_OP_TEXLDL: +- if ((ret = vsir_program_lower_texldl(program, ins)) < 0) +- return ret; ++ default: + break; ++ } ++ } + +- case VSIR_OP_TEXBEM: +- case VSIR_OP_TEXBEML: +- case VSIR_OP_TEXCOORD: +- case VSIR_OP_TEXDEPTH: +- case VSIR_OP_TEXDP3: +- case VSIR_OP_TEXDP3TEX: +- case VSIR_OP_TEXM3x2PAD: +- case VSIR_OP_TEXM3x2TEX: +- case VSIR_OP_TEXM3x3DIFF: +- case VSIR_OP_TEXM3x3PAD: +- case VSIR_OP_TEXM3x3SPEC: +- case VSIR_OP_TEXM3x3TEX: +- case VSIR_OP_TEXM3x3VSPEC: +- case VSIR_OP_TEXREG2AR: +- case VSIR_OP_TEXREG2GB: +- case VSIR_OP_TEXREG2RGB: +- vkd3d_shader_error(ctx->message_context, &ins->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, +- "Aborting due to unimplemented feature: Combined sampler instruction \"%s\" (%#x).", +- vsir_opcode_get_name(ins->opcode, ""), ins->opcode); +- return VKD3D_ERROR_NOT_IMPLEMENTED; ++ return VKD3D_OK; ++} + +- default: +- break; ++/* 1.0-1.3 pixel shaders allow writing t# registers, at which point they ++ * effectively behave like normal r# temps. Convert them to r# registers. ++ * t# registers which are read before being written contain TEXCOORD varyings, ++ * just as in 1.4 and 2.x, and will later be lowered to v# registers. ++ * ++ * Registers which are partially written are rejected by the native validator, ++ * but with a "read of uninitialized component" message that suggests that once ++ * any component of a t# register is written, none of the components contain ++ * texcoord data. */ ++static enum vkd3d_result vsir_program_lower_texture_writes(struct vsir_program *program, ++ struct vsir_transformation_context *ctx) ++{ ++ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); ++ struct vkd3d_shader_instruction *ins; ++ unsigned int texture_temp_idx = ~0u; ++ uint32_t texture_written_mask = 0; ++ ++ /* We run before I/O normalization. */ ++ VKD3D_ASSERT(program->normalisation_level < VSIR_NORMALISED_SM6); ++ ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) ++ { ++ for (unsigned int i = 0; i < ins->src_count; ++i) ++ { ++ struct vkd3d_shader_src_param *src = &ins->src[i]; ++ ++ if (src->reg.type == VKD3DSPR_TEXTURE && bitmap_is_set(&texture_written_mask, src->reg.idx[0].offset)) ++ { ++ src->reg.type = VKD3DSPR_TEMP; ++ src->reg.idx[0].offset += texture_temp_idx; ++ } ++ } ++ ++ for (unsigned int i = 0; i < ins->dst_count; ++i) ++ { ++ struct vkd3d_shader_dst_param *dst = &ins->dst[i]; ++ ++ if (dst->reg.type == VKD3DSPR_TEXTURE) ++ { ++ bitmap_set(&texture_written_mask, dst->reg.idx[0].offset); ++ if (texture_temp_idx == ~0u) ++ { ++ texture_temp_idx = program->temp_count; ++ /* These versions have 4 texture registers. */ ++ program->temp_count += 4; ++ } ++ dst->reg.type = VKD3DSPR_TEMP; ++ dst->reg.idx[0].offset += texture_temp_idx; ++ } + } + } + +@@ -1823,16 +2174,19 @@ static enum vkd3d_result vsir_program_ensure_ret(struct vsir_program *program, struct vsir_transformation_context *ctx) { struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); @@ -4424,7 +6902,7 @@ index 23e059a3490..29bf62709eb 100644 return VKD3D_OK; } -@@ -1923,7 +2158,7 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra +@@ -1923,7 +2277,7 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra struct vsir_transformation_context *ctx) { struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); @@ -4433,7 +6911,7 @@ index 23e059a3490..29bf62709eb 100644 struct vkd3d_shader_instruction *ins; unsigned int i; -@@ -1937,15 +2172,16 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra +@@ -1937,21 +2291,23 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { if (!vsir_instruction_is_dcl(ins) && ins->opcode != VSIR_OP_LABEL && ins->opcode != VSIR_OP_NOP) @@ -4454,7 +6932,14 @@ index 23e059a3490..29bf62709eb 100644 vsir_dst_param_init(&ins->dst[0], VKD3DSPR_ATTROUT, VSIR_DATA_F32, 1); ins->dst[0].reg.idx[0].offset = 0; ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; -@@ -2162,10 +2398,8 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL & ~program->diffuse_written_mask; + vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; + for (i = 0; i < 4; ++i) + ins->src[0].reg.u.immconst_f32[i] = 1.0f; + return VKD3D_OK; +@@ -2162,10 +2518,8 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program continue; loc = ins->location; @@ -4466,7 +6951,15 @@ index 23e059a3490..29bf62709eb 100644 for (unsigned int j = signature->element_count - uninit_varying_count; j < signature->element_count; ++j) { -@@ -2200,8 +2434,6 @@ struct hull_flattener +@@ -2175,6 +2529,7 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program + dst_param_init_output(&ins->dst[0], VSIR_DATA_F32, e->register_index, e->mask); + vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; + ins = vsir_program_iterator_next(&it); + } + } +@@ -2200,8 +2555,6 @@ struct hull_flattener { struct vsir_program *program; @@ -4475,7 +6968,7 @@ index 23e059a3490..29bf62709eb 100644 enum vkd3d_shader_opcode phase; struct vkd3d_shader_location last_ret_location; unsigned int *ssa_map; -@@ -2213,68 +2445,6 @@ static bool flattener_is_in_fork_or_join_phase(const struct hull_flattener *flat +@@ -2213,68 +2566,6 @@ static bool flattener_is_in_fork_or_join_phase(const struct hull_flattener *flat return flattener->phase == VSIR_OP_HS_FORK_PHASE || flattener->phase == VSIR_OP_HS_JOIN_PHASE; } @@ -4544,7 +7037,7 @@ index 23e059a3490..29bf62709eb 100644 static void flattener_fixup_ssa_register(struct hull_flattener *normaliser, struct vkd3d_shader_register *reg, unsigned int instance_id) { -@@ -2337,54 +2507,109 @@ static void flattener_fixup_registers(struct hull_flattener *normaliser, +@@ -2337,54 +2628,110 @@ static void flattener_fixup_registers(struct hull_flattener *normaliser, flattener_fixup_register_indices(normaliser, &ins->dst[i].reg, instance_id); } @@ -4560,7 +7053,7 @@ index 23e059a3490..29bf62709eb 100644 - for (i = 0, count = 0; i < locations->count; ++i) - count += (locations->locations[i].instance_count - 1) * locations->locations[i].instruction_count; + struct vsir_program_iterator dst_it, src_it, first_it; -+ struct vkd3d_shader_instruction *ins; ++ struct vkd3d_shader_instruction *ins, *src_ins; + unsigned int i, j; + size_t count; @@ -4576,18 +7069,12 @@ index 23e059a3490..29bf62709eb 100644 + /* Make a copy of the non-dcl instructions for each instance. */ + dst_it = first_it; + for (i = 1; i < instance_count; ++i) - { -- loc = &locations->locations[i - 1]; -- j = loc->index + loc->instruction_count; -- memmove(&instructions->elements[j + count], &instructions->elements[j], -- (end - j) * sizeof(*instructions->elements)); -- end = j; -- count -= (loc->instance_count - 1) * loc->instruction_count; -- loc->index += count; ++ { + src_it = *it; + for (j = 0; j < instruction_count; ++j) + { -+ if (!vsir_program_iterator_clone_instruction(&dst_it, vsir_program_iterator_current(&src_it))) ++ src_ins = vsir_program_iterator_current(&src_it); ++ if (!vsir_program_iterator_clone_instruction(normaliser->program, &dst_it, src_ins)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + vsir_program_iterator_next(&dst_it); @@ -4597,7 +7084,14 @@ index 23e059a3490..29bf62709eb 100644 + /* Replace each reference to the instance id with a constant instance id. */ + *it = first_it; + for (i = 0; i < instance_count; ++i) -+ { + { +- loc = &locations->locations[i - 1]; +- j = loc->index + loc->instruction_count; +- memmove(&instructions->elements[j + count], &instructions->elements[j], +- (end - j) * sizeof(*instructions->elements)); +- end = j; +- count -= (loc->instance_count - 1) * loc->instruction_count; +- loc->index += count; + if (i) + memset(normaliser->ssa_map, 0xff, normaliser->orig_ssa_count * sizeof(*normaliser->ssa_map)); + @@ -4647,25 +7141,25 @@ index 23e059a3490..29bf62709eb 100644 + if (b) + vkd3d_shader_instruction_make_nop(ins); + continue; -+ } + } +- /* Replace each reference to the instance id with a constant instance id. */ +- for (j = 0; j < loc->instance_count; ++j) + else if (ins->opcode == VSIR_OP_DCL_HS_FORK_PHASE_INSTANCE_COUNT + || ins->opcode == VSIR_OP_DCL_HS_JOIN_PHASE_INSTANCE_COUNT) -+ { + { +- if (j != 0) +- memset(normaliser->ssa_map, 0xff, normaliser->orig_ssa_count * sizeof(*normaliser->ssa_map)); + instance_count = ins->declaration.count + !ins->declaration.count; + vkd3d_shader_instruction_make_nop(ins); + ++instruction_count; + continue; - } -- /* Replace each reference to the instance id with a constant instance id. */ -- for (j = 0; j < loc->instance_count; ++j) ++ } + + if (normaliser->phase == VSIR_OP_INVALID) + continue; + + if (!phase_body_it_valid && !vsir_instruction_is_dcl(ins)) - { -- if (j != 0) -- memset(normaliser->ssa_map, 0xff, normaliser->orig_ssa_count * sizeof(*normaliser->ssa_map)); ++ { + phase_body_it_valid = true; + phase_body_it = it; + instruction_count = 0; @@ -4690,7 +7184,7 @@ index 23e059a3490..29bf62709eb 100644 } } -@@ -2394,19 +2619,10 @@ static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normali +@@ -2394,19 +2741,10 @@ static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normali static enum vkd3d_result vsir_program_flatten_hull_shader_phases(struct vsir_program *program, struct vsir_transformation_context *ctx) { @@ -4710,7 +7204,7 @@ index 23e059a3490..29bf62709eb 100644 bitmap_clear(program->io_dcls, VKD3DSPR_FORKINSTID); bitmap_clear(program->io_dcls, VKD3DSPR_JOININSTID); -@@ -2414,8 +2630,7 @@ static enum vkd3d_result vsir_program_flatten_hull_shader_phases(struct vsir_pro +@@ -2414,8 +2752,7 @@ static enum vkd3d_result vsir_program_flatten_hull_shader_phases(struct vsir_pro if (!(flattener.ssa_map = vkd3d_calloc(flattener.orig_ssa_count, sizeof(*flattener.ssa_map)))) return VKD3D_ERROR_OUT_OF_MEMORY; @@ -4720,7 +7214,38 @@ index 23e059a3490..29bf62709eb 100644 vkd3d_free(flattener.ssa_map); flattener.ssa_map = NULL; -@@ -2481,8 +2696,8 @@ static void shader_dst_param_normalise_outpointid(struct vkd3d_shader_dst_param +@@ -2434,7 +2771,7 @@ static enum vkd3d_result vsir_program_flatten_hull_shader_phases(struct vsir_pro + + struct control_point_normaliser + { +- struct vkd3d_shader_instruction_array instructions; ++ struct vsir_program *program; + enum vkd3d_shader_opcode phase; + struct vkd3d_shader_src_param *outpointid_param; + }; +@@ -2446,20 +2783,15 @@ static bool control_point_normaliser_is_in_control_point_phase(const struct cont + + struct vkd3d_shader_src_param *vsir_program_create_outpointid_param(struct vsir_program *program) + { +- struct vkd3d_shader_instruction_array *instructions = &program->instructions; + struct vkd3d_shader_src_param *rel_addr; + +- if (instructions->outpointid_param) +- return instructions->outpointid_param; +- +- if (!(rel_addr = shader_src_param_allocator_get(&instructions->src_params, 1))) ++ if (!(rel_addr = vsir_program_get_src_params(program, 1))) + return NULL; + + vsir_register_init(&rel_addr->reg, VKD3DSPR_OUTPOINTID, VSIR_DATA_U32, 0); + rel_addr->swizzle = 0; + rel_addr->modifiers = 0; + +- instructions->outpointid_param = rel_addr; + return rel_addr; + } + +@@ -2481,8 +2813,8 @@ static void shader_dst_param_normalise_outpointid(struct vkd3d_shader_dst_param } static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_point_normaliser *normaliser, @@ -4731,7 +7256,7 @@ index 23e059a3490..29bf62709eb 100644 { struct vkd3d_shader_instruction *ins; const struct signature_element *e; -@@ -2491,17 +2706,11 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p +@@ -2491,17 +2823,11 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p for (i = 0; i < s->element_count; ++i) count += !!s->elements[i].used_mask; @@ -4751,7 +7276,28 @@ index 23e059a3490..29bf62709eb 100644 for (i = 0; i < s->element_count; ++i) { -@@ -2533,7 +2742,7 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p +@@ -2510,9 +2836,9 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p + continue; + + vsir_instruction_init(ins, location, VSIR_OP_MOV); +- ins->dst = shader_dst_param_allocator_get(&normaliser->instructions.dst_params, 1); ++ ins->dst = vsir_program_get_dst_params(normaliser->program, 1); + ins->dst_count = 1; +- ins->src = shader_src_param_allocator_get(&normaliser->instructions.src_params, 1); ++ ins->src = vsir_program_get_src_params(normaliser->program, 1); + ins->src_count = 1; + + if (!ins->dst || ! ins->src) +@@ -2521,6 +2847,8 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p + return VKD3D_ERROR_OUT_OF_MEMORY; + } + ++ VKD3D_ASSERT(normaliser->outpointid_param); ++ + vsir_dst_param_init_io(&ins->dst[0], VKD3DSPR_OUTPUT, e, 2); + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].reg.idx[0].offset = 0; +@@ -2533,7 +2861,7 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p ins->src[0].reg.idx[0].rel_addr = normaliser->outpointid_param; ins->src[0].reg.idx[1].offset = e->register_index; @@ -4760,31 +7306,322 @@ index 23e059a3490..29bf62709eb 100644 } vsir_instruction_init(ins, location, VSIR_OP_RET); -@@ -2605,8 +2814,8 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i +@@ -2565,8 +2893,8 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i + ERR("Failed to allocate src param.\n"); + return VKD3D_ERROR_OUT_OF_MEMORY; + } +- normaliser.instructions = program->instructions; +- it = vsir_program_iterator(&normaliser.instructions); ++ normaliser.program = program; ++ it = vsir_program_iterator(&normaliser.program->instructions); + normaliser.phase = VSIR_OP_INVALID; + + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) +@@ -2598,16 +2926,14 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i + input_control_point_count = ins->declaration.count; + break; + case VSIR_OP_HS_CONTROL_POINT_PHASE: +- program->instructions = normaliser.instructions; + program->normalisation_level = VSIR_NORMALISED_HULL_CONTROL_POINT_IO; + return VKD3D_OK; + case VSIR_OP_HS_FORK_PHASE: case VSIR_OP_HS_JOIN_PHASE: /* ins may be relocated if the instruction array expands. */ location = ins->location; - ret = control_point_normaliser_emit_hs_input(&normaliser, &program->input_signature, - input_control_point_count, i, &location); +- program->instructions = normaliser.instructions; + ret = control_point_normaliser_emit_hs_input(&normaliser, + &program->input_signature, input_control_point_count, &it, &location); - program->instructions = normaliser.instructions; program->normalisation_level = VSIR_NORMALISED_HULL_CONTROL_POINT_IO; return ret; -@@ -4233,9 +4442,11 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs + default: +@@ -2615,7 +2941,6 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i + } + } + +- program->instructions = normaliser.instructions; + program->normalisation_level = VSIR_NORMALISED_HULL_CONTROL_POINT_IO; + return VKD3D_OK; + } +@@ -2641,12 +2966,7 @@ struct io_normaliser + struct shader_signature *output_signature; + struct shader_signature *patch_constant_signature; + +- unsigned int instance_count; +- unsigned int phase_body_idx; + enum vkd3d_shader_opcode phase; +- unsigned int output_control_point_count; +- +- struct vkd3d_shader_src_param *outpointid_param; + + struct vkd3d_shader_dst_param *input_dcl_params[MAX_REG_OUTPUT]; + struct vkd3d_shader_dst_param *output_dcl_params[MAX_REG_OUTPUT]; +@@ -3268,9 +3588,6 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program + { + switch (ins->opcode) + { +- case VSIR_OP_DCL_OUTPUT_CONTROL_POINT_COUNT: +- normaliser.output_control_point_count = ins->declaration.count; +- break; + case VSIR_OP_DCL_INDEX_RANGE: + if ((ret = io_normaliser_add_index_range(&normaliser, ins)) < 0) + return ret; +@@ -3355,6 +3672,7 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par + { + enum vkd3d_shader_d3dbc_constant_register set; + struct vkd3d_shader_src_param *rel_addr; ++ unsigned int c; + uint32_t index; + size_t i, j; + +@@ -3369,7 +3687,11 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par + param->reg.idx_count = 0; + param->reg.dimension = VSIR_DIMENSION_VEC4; + for (j = 0; j < 4; ++j) +- param->reg.u.immconst_u32[j] = normaliser->defs[i].value[j]; ++ { ++ c = vsir_swizzle_get_component(param->swizzle, j); ++ param->reg.u.immconst_u32[j] = normaliser->defs[i].value[c]; ++ } ++ param->swizzle = VKD3D_SHADER_NO_SWIZZLE; + return; + } + } +@@ -3521,6 +3843,17 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog + return VKD3D_OK; + } + ++/* NOTE: This invalidates all iterators, since the position of the ++ * vkd3d_shader_instruction_array itself changes. */ ++static void vsir_program_replace_instructions(struct vsir_program *program, ++ struct vkd3d_shader_instruction_array *array) ++{ ++ shader_instruction_array_destroy(&program->instructions); ++ ++ program->instructions = *array; ++ memset(array, 0, sizeof(*array)); ++} ++ + struct cf_flattener_if_info + { + struct vkd3d_shader_src_param *false_param; +@@ -3544,7 +3877,7 @@ struct cf_flattener_switch_case + + struct cf_flattener_switch_info + { +- size_t ins_location; ++ struct vsir_program_iterator ins_it; + const struct vkd3d_shader_src_param *condition; + unsigned int id; + unsigned int merge_block_id; +@@ -3579,9 +3912,7 @@ struct cf_flattener + struct vkd3d_shader_location location; + enum vkd3d_result status; + +- struct vkd3d_shader_instruction *instructions; +- size_t instruction_capacity; +- size_t instruction_count; ++ struct vkd3d_shader_instruction_array instructions; + + unsigned int block_id; + const char **block_names; +@@ -3604,18 +3935,6 @@ static void cf_flattener_set_error(struct cf_flattener *flattener, enum vkd3d_re + flattener->status = error; + } + +-static struct vkd3d_shader_instruction *cf_flattener_require_space(struct cf_flattener *flattener, size_t count) +-{ +- if (!vkd3d_array_reserve((void **)&flattener->instructions, &flattener->instruction_capacity, +- flattener->instruction_count + count, sizeof(*flattener->instructions))) +- { +- ERR("Failed to allocate instructions.\n"); +- cf_flattener_set_error(flattener, VKD3D_ERROR_OUT_OF_MEMORY); +- return NULL; +- } +- return &flattener->instructions[flattener->instruction_count]; +-} +- + static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, + const struct vkd3d_shader_instruction *instruction) + { +@@ -3624,11 +3943,10 @@ static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, + if (instruction->opcode == VSIR_OP_NOP) + return true; + +- if (!(dst_ins = cf_flattener_require_space(flattener, 1))) ++ if (!(dst_ins = shader_instruction_array_append(&flattener->instructions))) + return false; + + *dst_ins = *instruction; +- ++flattener->instruction_count; + return true; + } + +@@ -3656,12 +3974,13 @@ static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int + { + struct vkd3d_shader_instruction *ins; + +- if (!(ins = cf_flattener_require_space(flattener, 1))) ++ if (!(ins = shader_instruction_array_append(&flattener->instructions))) + return; +- if (vsir_instruction_init_label(ins, &flattener->location, label_id, flattener->program)) +- ++flattener->instruction_count; +- else ++ if (!vsir_instruction_init_label(ins, &flattener->location, label_id, flattener->program)) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + cf_flattener_set_error(flattener, VKD3D_ERROR_OUT_OF_MEMORY); ++ } + } + + /* For conditional branches, this returns the false target branch parameter. */ +@@ -3673,14 +3992,17 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten + struct vkd3d_shader_src_param *src_params, *false_branch_param; + struct vkd3d_shader_instruction *ins; + +- if (!(ins = cf_flattener_require_space(flattener, 1))) ++ if (!(ins = shader_instruction_array_append(&flattener->instructions))) + return NULL; + vsir_instruction_init(ins, &flattener->location, VSIR_OP_BRANCH); + + if (condition) + { + if (!(src_params = instruction_src_params_alloc(ins, 4 + !!continue_block_id, flattener))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return NULL; ++ } + src_params[0] = *condition; + if (flags == VKD3D_SHADER_CONDITIONAL_OP_Z) + { +@@ -3701,7 +4023,10 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten + else + { + if (!(src_params = instruction_src_params_alloc(ins, merge_block_id ? 3 : 1, flattener))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return NULL; ++ } + vsir_src_param_init_label(&src_params[0], true_id); + if (merge_block_id) + { +@@ -3713,8 +4038,6 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten + false_branch_param = NULL; + } + +- ++flattener->instruction_count; +- + return false_branch_param; + } + +@@ -3820,8 +4143,12 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte + is_hull_shader = program->shader_version.type == VKD3D_SHADER_TYPE_HULL; + after_declarations_section = is_hull_shader; + +- if (!cf_flattener_require_space(flattener, instructions->count + 1)) ++ if (!shader_instruction_array_reserve(&flattener->instructions, instructions->count + 1)) ++ { ++ ERR("Failed to allocate instructions.\n"); ++ cf_flattener_set_error(flattener, VKD3D_ERROR_OUT_OF_MEMORY); + return VKD3D_ERROR_OUT_OF_MEMORY; ++ } + + it = vsir_program_iterator(instructions); + for (instruction = vsir_program_iterator_head(&it); instruction; instruction = vsir_program_iterator_next(&it)) +@@ -3961,13 +4288,14 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte + + merge_block_id = cf_flattener_alloc_block_id(flattener); + +- cf_info->u.switch_.ins_location = flattener->instruction_count; + cf_info->u.switch_.condition = src; + +- if (!(dst_ins = cf_flattener_require_space(flattener, 1))) ++ if (!(dst_ins = shader_instruction_array_append(&flattener->instructions))) + return VKD3D_ERROR_OUT_OF_MEMORY; + vsir_instruction_init(dst_ins, &instruction->location, VSIR_OP_SWITCH_MONOLITHIC); +- ++flattener->instruction_count; ++ ++ cf_info->u.switch_.ins_it = vsir_program_iterator(&flattener->instructions); ++ vsir_program_iterator_tail(&cf_info->u.switch_.ins_it); + + cf_info->u.switch_.id = flattener->switch_id; + cf_info->u.switch_.merge_block_id = merge_block_id; +@@ -4000,8 +4328,12 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte + /* The SWITCH instruction is completed when the endswitch + * instruction is processed because we do not know the number + * of case statements or the default block id in advance.*/ +- dst_ins = &flattener->instructions[cf_info->u.switch_.ins_location]; +- if (!(src_params = instruction_src_params_alloc(dst_ins, cf_info->u.switch_.cases_count * 2 + 3, flattener))) ++ /* NOTE: This relies on iterators not being invalidated ++ * when new instructions are appended to the ++ * vkd3d_shader_instruction_array. */ ++ dst_ins = vsir_program_iterator_current(&cf_info->u.switch_.ins_it); ++ if (!(src_params = instruction_src_params_alloc(dst_ins, ++ cf_info->u.switch_.cases_count * 2 + 3, flattener))) + { + vkd3d_free(cf_info->u.switch_.cases); + return VKD3D_ERROR_OUT_OF_MEMORY; +@@ -4162,18 +4494,17 @@ static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsi + + VKD3D_ASSERT(program->cf_type == VSIR_CF_STRUCTURED); + ++ shader_instruction_array_init(&flattener.instructions, 0); ++ + if ((result = cf_flattener_iterate_instruction_array(&flattener, message_context)) >= 0) + { +- vkd3d_free(program->instructions.elements); +- program->instructions.elements = flattener.instructions; +- program->instructions.capacity = flattener.instruction_capacity; +- program->instructions.count = flattener.instruction_count; ++ vsir_program_replace_instructions(program, &flattener.instructions); + program->block_count = flattener.block_id; + program->cf_type = VSIR_CF_BLOCKS; + } + else + { +- vkd3d_free(flattener.instructions); ++ shader_instruction_array_destroy(&flattener.instructions); + } + + vkd3d_free(flattener.control_flow_info); +@@ -4190,17 +4521,6 @@ static unsigned int label_from_src_param(const struct vkd3d_shader_src_param *pa + return param->reg.idx[0].offset; + } + +-static bool reserve_instructions(struct vkd3d_shader_instruction **instructions, size_t *capacity, size_t count) +-{ +- if (!vkd3d_array_reserve((void **)instructions, capacity, count, sizeof(**instructions))) +- { +- ERR("Failed to allocate instructions.\n"); +- return false; +- } +- +- return true; +-} +- + /* A record represents replacing a jump from block `switch_label' to + * block `target_label' with a jump from block `if_label' to block + * `target_label'. */ +@@ -4233,39 +4553,40 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs struct vsir_transformation_context *ctx) { unsigned int block_count = program->block_count, ssa_count = program->ssa_count, current_label = 0, if_label; - size_t ins_capacity = 0, ins_count = 0, i, map_capacity = 0, map_count = 0; +- struct vkd3d_shader_instruction *instructions = NULL; + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); -+ size_t ins_capacity = 0, ins_count = 0, map_capacity = 0, map_count = 0; - struct vkd3d_shader_instruction *instructions = NULL; struct lower_switch_to_if_ladder_block_mapping *block_map = NULL; -+ struct vkd3d_shader_instruction *ins; ++ struct vkd3d_shader_instruction_array instructions; ++ struct vkd3d_shader_instruction *ins, *dst_ins; ++ size_t map_capacity = 0, map_count = 0; VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); -@@ -4245,9 +4456,8 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +- if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count)) +- goto fail; ++ if (!shader_instruction_array_init(&instructions, program->instructions.count)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; + /* First subpass: convert SWITCH_MONOLITHIC instructions to * selection ladders, keeping a map between blocks before and * after the subpass. */ @@ -4795,7 +7632,334 @@ index 23e059a3490..29bf62709eb 100644 unsigned int case_count, j, default_label; switch (ins->opcode) -@@ -4800,8 +5010,8 @@ struct vsir_cfg + { + case VSIR_OP_LABEL: + current_label = label_from_src_param(&ins->src[0]); +- if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) ++ if (!(dst_ins = shader_instruction_array_append(&instructions))) + goto fail; +- instructions[ins_count++] = *ins; ++ *dst_ins = *ins; + continue; + + case VSIR_OP_SWITCH_MONOLITHIC: + break; + + default: +- if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) ++ if (!(dst_ins = shader_instruction_array_append(&instructions))) + goto fail; +- instructions[ins_count++] = *ins; ++ *dst_ins = *ins; + continue; + } + +@@ -4276,17 +4597,18 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs + * just have to jump to the default label. */ + if (case_count == 0) + { +- if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) ++ if (!(dst_ins = shader_instruction_array_append(&instructions))) + goto fail; + +- if (!vsir_instruction_init_with_params(program, &instructions[ins_count], +- &ins->location, VSIR_OP_BRANCH, 0, 1)) ++ if (!vsir_instruction_init_with_params(program, dst_ins, &ins->location, VSIR_OP_BRANCH, 0, 1)) ++ { ++ vkd3d_shader_instruction_make_nop(dst_ins); + goto fail; +- vsir_src_param_init_label(&instructions[ins_count].src[0], default_label); +- ++ins_count; ++ } ++ vsir_src_param_init_label(&dst_ins->src[0], default_label); + } + +- if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 3 * case_count - 1)) ++ if (!shader_instruction_array_reserve(&instructions, instructions.count + 3 * case_count - 1)) + goto fail; + + if_label = current_label; +@@ -4295,13 +4617,15 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs + { + unsigned int fallthrough_label, case_label = label_from_src_param(&ins->src[3 + 2 * j + 1]); + +- if (!vsir_instruction_init_with_params(program, +- &instructions[ins_count], &ins->location, VSIR_OP_IEQ, 1, 2)) ++ dst_ins = shader_instruction_array_append(&instructions); ++ if (!vsir_instruction_init_with_params(program, dst_ins, &ins->location, VSIR_OP_IEQ, 1, 2)) ++ { ++ vkd3d_shader_instruction_make_nop(dst_ins); + goto fail; +- dst_param_init_ssa_bool(&instructions[ins_count].dst[0], ssa_count); +- instructions[ins_count].src[0] = ins->src[0]; +- instructions[ins_count].src[1] = ins->src[3 + 2 * j]; +- ++ins_count; ++ } ++ dst_param_init_ssa_bool(&dst_ins->dst[0], ssa_count); ++ dst_ins->src[0] = ins->src[0]; ++ dst_ins->src[1] = ins->src[3 + 2 * j]; + + /* For all cases except the last one we fall through to + * the following case; the last one has to jump to the +@@ -4311,13 +4635,15 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs + else + fallthrough_label = block_count + 1; + +- if (!vsir_instruction_init_with_params(program, &instructions[ins_count], +- &ins->location, VSIR_OP_BRANCH, 0, 3)) ++ dst_ins = shader_instruction_array_append(&instructions); ++ if (!vsir_instruction_init_with_params(program, dst_ins, &ins->location, VSIR_OP_BRANCH, 0, 3)) ++ { ++ vkd3d_shader_instruction_make_nop(dst_ins); + goto fail; +- src_param_init_ssa_bool(&instructions[ins_count].src[0], ssa_count); +- vsir_src_param_init_label(&instructions[ins_count].src[1], case_label); +- vsir_src_param_init_label(&instructions[ins_count].src[2], fallthrough_label); +- ++ins_count; ++ } ++ src_param_init_ssa_bool(&dst_ins->src[0], ssa_count); ++ vsir_src_param_init_label(&dst_ins->src[1], case_label); ++ vsir_src_param_init_label(&dst_ins->src[2], fallthrough_label); + + ++ssa_count; + +@@ -4333,29 +4659,28 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs + } + else + { +- if (!vsir_instruction_init_with_params(program, +- &instructions[ins_count], &ins->location, VSIR_OP_LABEL, 0, 1)) ++ dst_ins = shader_instruction_array_append(&instructions); ++ if (!vsir_instruction_init_with_params(program, dst_ins, &ins->location, VSIR_OP_LABEL, 0, 1)) ++ { ++ vkd3d_shader_instruction_make_nop(dst_ins); + goto fail; +- vsir_src_param_init_label(&instructions[ins_count].src[0], ++block_count); +- ++ins_count; ++ } ++ vsir_src_param_init_label(&dst_ins->src[0], ++block_count); + + if_label = block_count; + } + } + } + +- vkd3d_free(program->instructions.elements); ++ vsir_program_replace_instructions(program, &instructions); + vkd3d_free(block_map); +- program->instructions.elements = instructions; +- program->instructions.capacity = ins_capacity; +- program->instructions.count = ins_count; + program->block_count = block_count; + program->ssa_count = ssa_count; + + return VKD3D_OK; + + fail: +- vkd3d_free(instructions); ++ shader_instruction_array_destroy(&instructions); + vkd3d_free(block_map); + + return VKD3D_ERROR_OUT_OF_MEMORY; +@@ -4422,15 +4747,14 @@ static void ssas_to_temps_block_info_cleanup(struct ssas_to_temps_block_info *bl + vkd3d_free(block_info); + } + +-static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_program *program, +- struct vsir_transformation_context *ctx) ++static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps_in_function( ++ struct vsir_program *program, struct vsir_program_iterator *it) + { +- struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); +- size_t ins_capacity = 0, ins_count = 0, phi_count, incoming_count; + struct ssas_to_temps_block_info *info, *block_info = NULL; +- struct vkd3d_shader_instruction *instructions = NULL; ++ struct vsir_program_iterator it_begin = *it; + struct ssas_to_temps_alloc alloc = {0}; + struct vkd3d_shader_instruction *ins; ++ size_t phi_count, incoming_count; + unsigned int current_label = 0; + + VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); +@@ -4446,14 +4770,31 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ + + phi_count = 0; + incoming_count = 0; +- for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) ++ for (ins = vsir_program_iterator_current(it); ins; ins = vsir_program_iterator_next(it)) + { + unsigned int j, temp_idx; ++ bool finish = false; + + /* Only phi src/dst SSA values need be converted here. Structurisation may + * introduce new cases of undominated SSA use, which will be handled later. */ +- if (ins->opcode != VSIR_OP_PHI) +- continue; ++ switch (ins->opcode) ++ { ++ case VSIR_OP_PHI: ++ break; ++ ++ case VSIR_OP_HS_CONTROL_POINT_PHASE: ++ case VSIR_OP_HS_FORK_PHASE: ++ case VSIR_OP_HS_JOIN_PHASE: ++ finish = true; ++ break; ++ ++ default: ++ continue; ++ } ++ ++ if (finish) ++ break; ++ + ++phi_count; + + temp_idx = alloc.next_temp_idx++; +@@ -4487,12 +4828,15 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ + if (!phi_count) + goto done; + +- if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count + incoming_count - phi_count)) ++ if (!shader_instruction_array_reserve(&program->instructions, program->instructions.count + incoming_count)) + goto fail; + +- for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) ++ *it = it_begin; ++ ++ for (ins = vsir_program_iterator_current(it); ins; ins = vsir_program_iterator_next(it)) + { + struct vkd3d_shader_instruction *mov_ins; ++ bool finish = false; + size_t j; + + for (j = 0; j < ins->dst_count; ++j) +@@ -4511,33 +4855,44 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ + case VSIR_OP_SWITCH_MONOLITHIC: + info = &block_info[current_label - 1]; + ++ mov_ins = vsir_program_iterator_insert_before_and_move(it, info->incoming_count); ++ VKD3D_ASSERT(mov_ins); ++ + for (j = 0; j < info->incoming_count; ++j) + { + struct phi_incoming_to_temp *incoming = &info->incomings[j]; + +- mov_ins = &instructions[ins_count++]; + if (!vsir_instruction_init_with_params(program, mov_ins, &ins->location, VSIR_OP_MOV, 1, 0)) ++ { ++ vkd3d_shader_instruction_make_nop(mov_ins); + goto fail; ++ } + *mov_ins->dst = *incoming->dst; + mov_ins->src = incoming->src; + mov_ins->src_count = 1; ++ ++ mov_ins = vsir_program_iterator_next(it); + } + break; + + case VSIR_OP_PHI: +- continue; ++ vkd3d_shader_instruction_make_nop(ins); ++ break; ++ ++ case VSIR_OP_HS_CONTROL_POINT_PHASE: ++ case VSIR_OP_HS_FORK_PHASE: ++ case VSIR_OP_HS_JOIN_PHASE: ++ finish = true; ++ break; + + default: + break; + } + +- instructions[ins_count++] = *ins; ++ if (finish) ++ break; + } + +- vkd3d_free(program->instructions.elements); +- program->instructions.elements = instructions; +- program->instructions.capacity = ins_capacity; +- program->instructions.count = ins_count; + program->temp_count = alloc.next_temp_idx; + done: + ssas_to_temps_block_info_cleanup(block_info, program->block_count); +@@ -4546,13 +4901,51 @@ done: + return VKD3D_OK; + + fail: +- vkd3d_free(instructions); + ssas_to_temps_block_info_cleanup(block_info, program->block_count); + vkd3d_free(alloc.table); + + return VKD3D_ERROR_OUT_OF_MEMORY; + } + ++static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_program *program, ++ struct vsir_transformation_context *ctx) ++{ ++ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); ++ struct vkd3d_shader_instruction *ins; ++ enum vkd3d_result ret; ++ ++ VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); ++ ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_current(&it)) ++ { ++ switch (ins->opcode) ++ { ++ case VSIR_OP_LABEL: ++ VKD3D_ASSERT(program->shader_version.type != VKD3D_SHADER_TYPE_HULL); ++ TRACE("Materializing undominated SSAs in a non-hull shader.\n"); ++ if ((ret = vsir_program_materialise_phi_ssas_to_temps_in_function(program, &it)) < 0) ++ return ret; ++ break; ++ ++ case VSIR_OP_HS_CONTROL_POINT_PHASE: ++ case VSIR_OP_HS_FORK_PHASE: ++ case VSIR_OP_HS_JOIN_PHASE: ++ VKD3D_ASSERT(program->shader_version.type == VKD3D_SHADER_TYPE_HULL); ++ TRACE("Materializing undominated SSAs in phase %u of a hull shader.\n", ins->opcode); ++ vsir_program_iterator_next(&it); ++ if ((ret = vsir_program_materialise_phi_ssas_to_temps_in_function(program, &it)) < 0) ++ return ret; ++ break; ++ ++ default: ++ vsir_program_iterator_next(&it); ++ break; ++ } ++ } ++ ++ return VKD3D_OK; ++} ++ + struct vsir_block_list + { + struct vsir_block **blocks; +@@ -4607,7 +5000,7 @@ struct vsir_block + * LABEL that introduces the block. `end' points to the terminator + * instruction (either BRANCH or RET). They can coincide, meaning + * that the block is empty. */ +- struct vkd3d_shader_instruction *begin, *end; ++ struct vsir_program_iterator begin, end; + struct vsir_block_list predecessors, successors; + uint32_t *dominates; + }; +@@ -4790,8 +5183,8 @@ static void vsir_cfg_structure_cleanup(struct vsir_cfg_structure *structure) + + struct vsir_cfg_emit_target + { +- struct vkd3d_shader_instruction *instructions; +- size_t ins_capacity, ins_count; ++ struct vkd3d_shader_instruction_array instructions; ++ + unsigned int jump_target_temp_idx; + unsigned int temp_count; + }; +@@ -4800,8 +5193,8 @@ struct vsir_cfg { struct vkd3d_shader_message_context *message_context; struct vsir_program *program; @@ -4806,7 +7970,31 @@ index 23e059a3490..29bf62709eb 100644 struct vsir_block *blocks; struct vsir_block *entry; size_t block_count; -@@ -5046,10 +5256,11 @@ static void vsir_cfg_dump_structured_program(struct vsir_cfg *cfg) +@@ -4926,19 +5319,21 @@ static void vsir_cfg_dump_dot(struct vsir_cfg *cfg) + for (i = 0; i < cfg->block_count; ++i) + { + struct vsir_block *block = &cfg->blocks[i]; ++ struct vkd3d_shader_instruction *end; + const char *shape; + + if (block->label == 0) + continue; + +- switch (block->end->opcode) ++ end = vsir_program_iterator_current(&block->end); ++ switch (end->opcode) + { + case VSIR_OP_RET: + shape = "trapezium"; + break; + + case VSIR_OP_BRANCH: +- shape = vsir_register_is_label(&block->end->src[0].reg) ? "ellipse" : "box"; ++ shape = vsir_register_is_label(&end->src[0].reg) ? "ellipse" : "box"; + break; + + default: +@@ -5046,19 +5441,20 @@ static void vsir_cfg_dump_structured_program(struct vsir_cfg *cfg) } static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program *program, @@ -4817,10 +8005,12 @@ index 23e059a3490..29bf62709eb 100644 { struct vsir_block *current_block = NULL; + struct vkd3d_shader_instruction *ins; ++ size_t i, defined_block_count = 0; enum vkd3d_result ret; - size_t i; +- size_t i; -@@ -5058,7 +5269,7 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program + memset(cfg, 0, sizeof(*cfg)); + cfg->message_context = message_context; cfg->program = program; cfg->block_count = program->block_count; cfg->target = target; @@ -4829,7 +8019,7 @@ index 23e059a3490..29bf62709eb 100644 vsir_block_list_init(&cfg->order); -@@ -5068,12 +5279,11 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program +@@ -5068,12 +5464,11 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program if (TRACE_ON()) vkd3d_string_buffer_init(&cfg->debug_buffer); @@ -4844,7 +8034,7 @@ index 23e059a3490..29bf62709eb 100644 { case VSIR_OP_PHI: case VSIR_OP_SWITCH_MONOLITHIC: -@@ -5081,7 +5291,7 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program +@@ -5081,7 +5476,7 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program case VSIR_OP_LABEL: { @@ -4853,36 +8043,421 @@ index 23e059a3490..29bf62709eb 100644 VKD3D_ASSERT(!current_block); VKD3D_ASSERT(label > 0); -@@ -5090,7 +5300,8 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program +@@ -5090,16 +5485,18 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program VKD3D_ASSERT(current_block->label == 0); if ((ret = vsir_block_init(current_block, label, program->block_count)) < 0) goto fail; - current_block->begin = &program->instructions.elements[i + 1]; -+ current_block->begin = vsir_program_iterator_next(it); -+ vsir_program_iterator_prev(it); ++ current_block->begin = *it; ++ vsir_program_iterator_next(¤t_block->begin); if (!cfg->entry) cfg->entry = current_block; ++ ++defined_block_count; break; -@@ -5099,7 +5310,7 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program + } + case VSIR_OP_BRANCH: case VSIR_OP_RET: VKD3D_ASSERT(current_block); - current_block->end = instruction; -+ current_block->end = ins; ++ current_block->end = *it; current_block = NULL; break; -@@ -5118,8 +5329,7 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program +@@ -5118,33 +5515,36 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program break; } - *pos = i; - cfg->function_end = *pos; + cfg->function_end = *it; ++ /* program->block_count is the max in any function. Set the count for this function. */ ++ cfg->block_count = defined_block_count; for (i = 0; i < cfg->block_count; ++i) { -@@ -6616,13 +6826,13 @@ static enum vkd3d_result vsir_cfg_emit_structured_program(struct vsir_cfg *cfg) + struct vsir_block *block = &cfg->blocks[i]; ++ struct vkd3d_shader_instruction *end; + + if (block->label == 0) + continue; + +- switch (block->end->opcode) ++ end = vsir_program_iterator_current(&block->end); ++ switch (end->opcode) + { + case VSIR_OP_RET: + break; + + case VSIR_OP_BRANCH: +- if (vsir_register_is_label(&block->end->src[0].reg)) ++ if (vsir_register_is_label(&end->src[0].reg)) + { +- if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[0])) < 0) ++ if ((ret = vsir_cfg_add_edge(cfg, block, &end->src[0])) < 0) + goto fail; + } + else + { +- if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[1])) < 0) ++ if ((ret = vsir_cfg_add_edge(cfg, block, &end->src[1])) < 0) + goto fail; + +- if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[2])) < 0) ++ if ((ret = vsir_cfg_add_edge(cfg, block, &end->src[2])) < 0) + goto fail; + } + break; +@@ -5328,8 +5728,10 @@ static enum vkd3d_result vsir_cfg_compute_loops(struct vsir_cfg *cfg) + + if (cfg->loops_by_header[header->label - 1] != SIZE_MAX) + { ++ struct vkd3d_shader_instruction *begin = vsir_program_iterator_current(&header->begin); ++ + FIXME("Block %u is header to more than one loop, this is not implemented.\n", header->label); +- vkd3d_shader_error(cfg->message_context, &header->begin->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, ++ vkd3d_shader_error(cfg->message_context, &begin->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, + "Block %u is header to more than one loop, this is not implemented.", header->label); + return VKD3D_ERROR_NOT_IMPLEMENTED; + } +@@ -5411,8 +5813,10 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg) + + if (in_degrees[i] == 0 && block != cfg->entry) + { ++ struct vkd3d_shader_instruction *begin = vsir_program_iterator_current(&block->begin); ++ + WARN("Unexpected entry point %u.\n", block->label); +- vkd3d_shader_error(cfg->message_context, &block->begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, ++ vkd3d_shader_error(cfg->message_context, &begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, + "Block %u is unreachable from the entry point.", block->label); + ret = VKD3D_ERROR_INVALID_SHADER; + goto fail; +@@ -5421,8 +5825,10 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg) + + if (in_degrees[cfg->entry->label - 1] != 0) + { ++ struct vkd3d_shader_instruction *begin = vsir_program_iterator_current(&cfg->entry->begin); ++ + WARN("Entry point has %u incoming forward edges.\n", in_degrees[cfg->entry->label - 1]); +- vkd3d_shader_error(cfg->message_context, &cfg->entry->begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, ++ vkd3d_shader_error(cfg->message_context, &begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, + "The entry point block has %u incoming forward edges.", in_degrees[cfg->entry->label - 1]); + ret = VKD3D_ERROR_INVALID_SHADER; + goto fail; +@@ -5524,9 +5930,11 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg) + + if (cfg->order.count != cfg->block_count) + { ++ struct vkd3d_shader_instruction *begin = vsir_program_iterator_current(&cfg->entry->begin); ++ + /* There is a cycle of forward edges. */ + WARN("The control flow graph is not reducible.\n"); +- vkd3d_shader_error(cfg->message_context, &cfg->entry->begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, ++ vkd3d_shader_error(cfg->message_context, &begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, + "The control flow graph is not reducible."); + ret = VKD3D_ERROR_INVALID_SHADER; + goto fail; +@@ -5785,6 +6193,7 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) + { + struct vsir_block *block = cfg->order.blocks[i]; + struct vsir_cfg_structure *structure; ++ struct vkd3d_shader_instruction *end; + + VKD3D_ASSERT(stack_depth > 0); + +@@ -5810,16 +6219,17 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) + structure->u.block = block; + + /* Generate between zero and two jump instructions. */ +- switch (block->end->opcode) ++ end = vsir_program_iterator_current(&block->end); ++ switch (end->opcode) + { + case VSIR_OP_BRANCH: + { + struct vsir_cfg_edge_action action_true, action_false; + bool invert_condition = false; + +- if (vsir_register_is_label(&block->end->src[0].reg)) ++ if (vsir_register_is_label(&end->src[0].reg)) + { +- unsigned int target = label_from_src_param(&block->end->src[0]); ++ unsigned int target = label_from_src_param(&end->src[0]); + struct vsir_block *successor = &cfg->blocks[target - 1]; + + vsir_cfg_compute_edge_action(cfg, block, successor, &action_true); +@@ -5827,12 +6237,12 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) + } + else + { +- unsigned int target = label_from_src_param(&block->end->src[1]); ++ unsigned int target = label_from_src_param(&end->src[1]); + struct vsir_block *successor = &cfg->blocks[target - 1]; + + vsir_cfg_compute_edge_action(cfg, block, successor, &action_true); + +- target = label_from_src_param(&block->end->src[2]); ++ target = label_from_src_param(&end->src[2]); + successor = &cfg->blocks[target - 1]; + + vsir_cfg_compute_edge_action(cfg, block, successor, &action_false); +@@ -5884,7 +6294,7 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) + goto fail; + structure->u.jump.type = action_true.jump_type; + structure->u.jump.target = action_true.target; +- structure->u.jump.condition = &block->end->src[0]; ++ structure->u.jump.condition = &vsir_program_iterator_current(&block->end)->src[0]; + structure->u.jump.invert_condition = invert_condition; + } + +@@ -6369,15 +6779,28 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_block(struct vsir_cfg *cfg + struct vsir_block *block) + { + struct vsir_cfg_emit_target *target = cfg->target; ++ struct vkd3d_shader_instruction *ins, *end, *dst; ++ struct vsir_program_iterator it; ++ size_t ins_count = 0; + +- if (!reserve_instructions(&target->instructions, &target->ins_capacity, +- target->ins_count + (block->end - block->begin))) +- return VKD3D_ERROR_OUT_OF_MEMORY; ++ it = block->begin; ++ end = vsir_program_iterator_current(&block->end); + +- memcpy(&target->instructions[target->ins_count], block->begin, +- (char *)block->end - (char *)block->begin); ++ for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it)) ++ { ++ ++ins_count; ++ } ++ ++ if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + ins_count)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; + +- target->ins_count += block->end - block->begin; ++ it = block->begin; ++ for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it)) ++ { ++ dst = shader_instruction_array_append(&target->instructions); ++ VKD3D_ASSERT(dst); ++ *dst = *ins; ++ } + + return VKD3D_OK; + } +@@ -6387,20 +6810,22 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, + { + struct vsir_cfg_emit_target *target = cfg->target; + const struct vkd3d_shader_location no_loc = {0}; ++ struct vkd3d_shader_instruction *ins; + enum vkd3d_result ret; + +- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) ++ if (!(ins = shader_instruction_array_append(&target->instructions))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_LOOP); ++ vsir_instruction_init(ins, &no_loc, VSIR_OP_LOOP); + + if ((ret = vsir_cfg_structure_list_emit(cfg, &loop->body, loop->idx)) < 0) + return ret; + +- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 5)) ++ if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + 5)) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_ENDLOOP); ++ ins = shader_instruction_array_append(&target->instructions); ++ vsir_instruction_init(ins, &no_loc, VSIR_OP_ENDLOOP); + + /* Add a trampoline to implement multilevel jumping depending on the stored + * jump_target value. */ +@@ -6414,44 +6839,50 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, + * we have to reach an outer loop, so we keep breaking. */ + const unsigned int inner_break_target = loop->idx << 1; + +- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], +- &no_loc, VSIR_OP_IEQ, 1, 2)) ++ ins = shader_instruction_array_append(&target->instructions); ++ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_IEQ, 1, 2)) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return VKD3D_ERROR_OUT_OF_MEMORY; ++ } + +- dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); +- src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx); +- src_param_init_const_uint(&target->instructions[target->ins_count].src[1], outer_continue_target); ++ ++target->temp_count; + +- ++target->ins_count; ++ dst_param_init_temp_bool(&ins->dst[0], target->temp_count - 1); ++ src_param_init_temp_uint(&ins->src[0], target->jump_target_temp_idx); ++ src_param_init_const_uint(&ins->src[1], outer_continue_target); + +- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], +- &no_loc, VSIR_OP_CONTINUEP, 0, 1)) ++ ins = shader_instruction_array_append(&target->instructions); ++ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_CONTINUEP, 0, 1)) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return VKD3D_ERROR_OUT_OF_MEMORY; ++ } + +- src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count); +- +- ++target->ins_count; +- ++target->temp_count; ++ src_param_init_temp_bool(&ins->src[0], target->temp_count - 1); + +- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], +- &no_loc, VSIR_OP_IEQ, 1, 2)) ++ ins = shader_instruction_array_append(&target->instructions); ++ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_IEQ, 1, 2)) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return VKD3D_ERROR_OUT_OF_MEMORY; ++ } + +- dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); +- src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx); +- src_param_init_const_uint(&target->instructions[target->ins_count].src[1], inner_break_target); ++ ++target->temp_count; + +- ++target->ins_count; ++ dst_param_init_temp_bool(&ins->dst[0], target->temp_count - 1); ++ src_param_init_temp_uint(&ins->src[0], target->jump_target_temp_idx); ++ src_param_init_const_uint(&ins->src[1], inner_break_target); + +- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], +- &no_loc, VSIR_OP_BREAKP, 0, 1)) ++ ins = shader_instruction_array_append(&target->instructions); ++ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_BREAKP, 0, 1)) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return VKD3D_ERROR_OUT_OF_MEMORY; +- target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; +- +- src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count); ++ } ++ ins->flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; + +- ++target->ins_count; +- ++target->temp_count; ++ src_param_init_temp_bool(&ins->src[0], target->temp_count - 1); + } + + return VKD3D_OK; +@@ -6462,40 +6893,40 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg + { + struct vsir_cfg_emit_target *target = cfg->target; + const struct vkd3d_shader_location no_loc = {0}; ++ struct vkd3d_shader_instruction *ins; + enum vkd3d_result ret; + +- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) ++ if (!(ins = shader_instruction_array_append(&target->instructions))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], +- &no_loc, VSIR_OP_IF, 0, 1)) ++ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_IF, 0, 1)) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return VKD3D_ERROR_OUT_OF_MEMORY; ++ } + +- target->instructions[target->ins_count].src[0] = *selection->condition; ++ ins->src[0] = *selection->condition; + + if (selection->invert_condition) +- target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; +- +- ++target->ins_count; ++ ins->flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; + + if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->if_body, loop_idx)) < 0) + return ret; + + if (selection->else_body.count != 0) + { +- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) ++ if (!(ins = shader_instruction_array_append(&target->instructions))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_ELSE); ++ vsir_instruction_init(ins, &no_loc, VSIR_OP_ELSE); + + if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->else_body, loop_idx)) < 0) + return ret; + } + +- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) ++ if (!(ins = shader_instruction_array_append(&target->instructions))) + return VKD3D_ERROR_OUT_OF_MEMORY; +- +- vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_ENDIF); ++ vsir_instruction_init(ins, &no_loc, VSIR_OP_ENDIF); + + return VKD3D_OK; + } +@@ -6508,6 +6939,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, + /* Encode the jump target as the loop index plus a bit to remember whether + * we're breaking or continue-ing. */ + unsigned int jump_target = jump->target << 1; ++ struct vkd3d_shader_instruction *ins; + enum vkd3d_shader_opcode opcode; + + switch (jump->type) +@@ -6538,32 +6970,34 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, + vkd3d_unreachable(); + } + +- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 2)) ++ if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + if (jump->needs_launcher) + { +- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], +- &no_loc, VSIR_OP_MOV, 1, 1)) ++ ins = shader_instruction_array_append(&target->instructions); ++ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_MOV, 1, 1)) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return VKD3D_ERROR_OUT_OF_MEMORY; ++ } + +- dst_param_init_temp_uint(&target->instructions[target->ins_count].dst[0], target->jump_target_temp_idx); +- src_param_init_const_uint(&target->instructions[target->ins_count].src[0], jump_target); +- +- ++target->ins_count; ++ dst_param_init_temp_uint(&ins->dst[0], target->jump_target_temp_idx); ++ src_param_init_const_uint(&ins->src[0], jump_target); + } + +- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], +- &no_loc, opcode, 0, !!jump->condition)) ++ ins = shader_instruction_array_append(&target->instructions); ++ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, opcode, 0, !!jump->condition)) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return VKD3D_ERROR_OUT_OF_MEMORY; ++ } + + if (jump->invert_condition) +- target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; ++ ins->flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; + + if (jump->condition) +- target->instructions[target->ins_count].src[0] = *jump->condition; +- +- ++target->ins_count; ++ ins->src[0] = *jump->condition; + + return VKD3D_OK; + } +@@ -6616,13 +7050,13 @@ static enum vkd3d_result vsir_cfg_emit_structured_program(struct vsir_cfg *cfg) } static enum vkd3d_result vsir_program_structurize_function(struct vsir_program *program, @@ -4899,21 +8474,24 @@ index 23e059a3490..29bf62709eb 100644 return ret; vsir_cfg_compute_dominators(&cfg); -@@ -6653,10 +6863,11 @@ out: +@@ -6653,32 +7087,31 @@ out: static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, struct vsir_transformation_context *ctx) { + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); struct vkd3d_shader_message_context *message_context = ctx->message_context; ++ struct vkd3d_shader_instruction *ins, *dst; struct vsir_cfg_emit_target target = {0}; -+ struct vkd3d_shader_instruction *ins; enum vkd3d_result ret; - size_t i; VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); -@@ -6666,19 +6877,17 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, - if (!reserve_instructions(&target.instructions, &target.ins_capacity, program->instructions.count)) + target.jump_target_temp_idx = program->temp_count; + target.temp_count = program->temp_count + 1; + +- if (!reserve_instructions(&target.instructions, &target.ins_capacity, program->instructions.count)) ++ if (!shader_instruction_array_init(&target.instructions, 0)) return VKD3D_ERROR_OUT_OF_MEMORY; - for (i = 0; i < program->instructions.count;) @@ -4936,13 +8514,18 @@ index 23e059a3490..29bf62709eb 100644 break; case VSIR_OP_HS_CONTROL_POINT_PHASE: -@@ -6687,17 +6896,17 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, +@@ -6686,33 +7119,33 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, + case VSIR_OP_HS_JOIN_PHASE: VKD3D_ASSERT(program->shader_version.type == VKD3D_SHADER_TYPE_HULL); TRACE("Structurizing phase %u of a hull shader.\n", ins->opcode); - target.instructions[target.ins_count++] = *ins; +- target.instructions[target.ins_count++] = *ins; - ++i; - if ((ret = vsir_program_structurize_function(program, message_context, - &target, &i)) < 0) ++ ++ dst = shader_instruction_array_append(&target.instructions); ++ *dst = *ins; ++ + vsir_program_iterator_next(&it); + if ((ret = vsir_program_structurize_function(program, message_context, &target, &it)) < 0) goto fail; @@ -4950,15 +8533,34 @@ index 23e059a3490..29bf62709eb 100644 break; default: - if (!reserve_instructions(&target.instructions, &target.ins_capacity, target.ins_count + 1)) +- if (!reserve_instructions(&target.instructions, &target.ins_capacity, target.ins_count + 1)) ++ if (!(dst = shader_instruction_array_append(&target.instructions))) return VKD3D_ERROR_OUT_OF_MEMORY; - target.instructions[target.ins_count++] = *ins; +- target.instructions[target.ins_count++] = *ins; - ++i; ++ *dst = *ins; + ins = vsir_program_iterator_next(&it); break; } } -@@ -6742,8 +6951,10 @@ static void register_map_undominated_use(struct vkd3d_shader_register *reg, stru + +- vkd3d_free(program->instructions.elements); +- program->instructions.elements = target.instructions; +- program->instructions.capacity = target.ins_capacity; +- program->instructions.count = target.ins_count; ++ vsir_program_replace_instructions(program, &target.instructions); + program->temp_count = target.temp_count; + program->cf_type = VSIR_CF_STRUCTURED; + + return VKD3D_OK; + + fail: +- vkd3d_free(target.instructions); ++ shader_instruction_array_destroy(&target.instructions); + + return ret; + } +@@ -6742,8 +7175,10 @@ static void register_map_undominated_use(struct vkd3d_shader_register *reg, stru static enum vkd3d_result vsir_cfg_materialize_undominated_ssas_to_temps(struct vsir_cfg *cfg) { struct vsir_program *program = cfg->program; @@ -4969,7 +8571,7 @@ index 23e059a3490..29bf62709eb 100644 unsigned int j; size_t i; -@@ -6761,7 +6972,6 @@ static enum vkd3d_result vsir_cfg_materialize_undominated_ssas_to_temps(struct v +@@ -6761,12 +7196,13 @@ static enum vkd3d_result vsir_cfg_materialize_undominated_ssas_to_temps(struct v for (i = 0; i < cfg->block_count; ++i) { struct vsir_block *block = &cfg->blocks[i]; @@ -4977,7 +8579,15 @@ index 23e059a3490..29bf62709eb 100644 if (block->label == 0) continue; -@@ -6779,7 +6989,6 @@ static enum vkd3d_result vsir_cfg_materialize_undominated_ssas_to_temps(struct v + +- for (ins = block->begin; ins <= block->end; ++ins) ++ it = block->begin; ++ end = vsir_program_iterator_current(&block->end); ++ for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it)) + { + for (j = 0; j < ins->dst_count; ++j) + { +@@ -6779,12 +7215,13 @@ static enum vkd3d_result vsir_cfg_materialize_undominated_ssas_to_temps(struct v for (i = 0; i < cfg->block_count; ++i) { struct vsir_block *block = &cfg->blocks[i]; @@ -4985,7 +8595,15 @@ index 23e059a3490..29bf62709eb 100644 if (block->label == 0) continue; -@@ -6796,10 +7005,10 @@ static enum vkd3d_result vsir_cfg_materialize_undominated_ssas_to_temps(struct v + +- for (ins = block->begin; ins <= block->end; ++ins) ++ it = block->begin; ++ end = vsir_program_iterator_current(&block->end); ++ for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it)) + { + for (j = 0; j < ins->src_count; ++j) + register_map_undominated_use(&ins->src[j].reg, &alloc, block, origin_blocks); +@@ -6796,10 +7233,10 @@ static enum vkd3d_result vsir_cfg_materialize_undominated_ssas_to_temps(struct v TRACE("Emitting temps for %u values with undominated usage.\n", alloc.next_temp_idx - program->temp_count); @@ -4999,7 +8617,7 @@ index 23e059a3490..29bf62709eb 100644 for (j = 0; j < ins->dst_count; ++j) materialize_ssas_to_temps_process_reg(program, &alloc, &ins->dst[j].reg); -@@ -6815,14 +7024,13 @@ done: +@@ -6815,14 +7252,13 @@ done: return VKD3D_OK; } @@ -5017,7 +8635,7 @@ index 23e059a3490..29bf62709eb 100644 return ret; vsir_cfg_compute_dominators(&cfg); -@@ -6837,25 +7045,25 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps_in_f +@@ -6837,25 +7273,23 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps_in_f static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(struct vsir_program *program, struct vsir_transformation_context *ctx) { @@ -5030,7 +8648,7 @@ index 23e059a3490..29bf62709eb 100644 VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); - for (i = 0; i < program->instructions.count;) -+ for (ins = vsir_program_iterator_head(&it); ins;) ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_current(&it)) { - struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - @@ -5044,12 +8662,10 @@ index 23e059a3490..29bf62709eb 100644 + program, message_context, &it)) < 0) return ret; - VKD3D_ASSERT(i == program->instructions.count); -+ ins = vsir_program_iterator_current(&it); -+ VKD3D_ASSERT(!ins); break; case VSIR_OP_HS_CONTROL_POINT_PHASE: -@@ -6863,14 +7071,15 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru +@@ -6863,14 +7297,14 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru case VSIR_OP_HS_JOIN_PHASE: VKD3D_ASSERT(program->shader_version.type == VKD3D_SHADER_TYPE_HULL); TRACE("Materializing undominated SSAs in phase %u of a hull shader.\n", ins->opcode); @@ -5059,16 +8675,15 @@ index 23e059a3490..29bf62709eb 100644 - program, message_context, &i)) < 0) + program, message_context, &it)) < 0) return ret; -+ ins = vsir_program_iterator_current(&it); break; default: - ++i; -+ ins = vsir_program_iterator_next(&it); ++ vsir_program_iterator_next(&it); break; } } -@@ -6881,7 +7090,6 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru +@@ -6881,7 +7315,6 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru static bool use_flat_interpolation(const struct vsir_program *program, struct vkd3d_shader_message_context *message_context, bool *flat) { @@ -5076,7 +8691,7 @@ index 23e059a3490..29bf62709eb 100644 const struct vkd3d_shader_parameter1 *parameter; *flat = false; -@@ -6891,13 +7099,13 @@ static bool use_flat_interpolation(const struct vsir_program *program, +@@ -6891,13 +7324,13 @@ static bool use_flat_interpolation(const struct vsir_program *program, if (parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) { @@ -5092,7 +8707,7 @@ index 23e059a3490..29bf62709eb 100644 "Invalid flat interpolation parameter data type %#x.", parameter->data_type); return false; } -@@ -6938,7 +7146,6 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr +@@ -6938,7 +7371,6 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr uint32_t colour_temp, struct vkd3d_shader_message_context *message_context) { struct vkd3d_shader_location loc = vsir_program_iterator_current(it)->location; @@ -5100,7 +8715,7 @@ index 23e059a3490..29bf62709eb 100644 struct vkd3d_shader_instruction *ins; static const struct -@@ -6959,10 +7166,8 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr +@@ -6959,10 +7391,8 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr if (compare_func == VKD3D_SHADER_COMPARISON_FUNC_NEVER) { @@ -5112,7 +8727,7 @@ index 23e059a3490..29bf62709eb 100644 vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_DISCARD, 0, 1); ins->flags = VKD3D_SHADER_CONDITIONAL_OP_Z; -@@ -6972,10 +7177,8 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr +@@ -6972,10 +7402,8 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr return VKD3D_OK; } @@ -5124,7 +8739,7 @@ index 23e059a3490..29bf62709eb 100644 switch (ref->data_type) { -@@ -6994,7 +7197,7 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr +@@ -6994,7 +7422,7 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr break; case VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4: @@ -5133,7 +8748,7 @@ index 23e059a3490..29bf62709eb 100644 "Alpha test reference data type must be a single component."); return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -7036,7 +7239,6 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro +@@ -7036,7 +7464,6 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro struct vkd3d_shader_message_context *message_context = ctx->message_context; const struct vkd3d_shader_parameter1 *func = NULL, *ref = NULL; uint32_t colour_signature_idx, colour_temp = ~0u; @@ -5141,7 +8756,7 @@ index 23e059a3490..29bf62709eb 100644 enum vkd3d_shader_comparison_func compare_func; struct vkd3d_shader_instruction *ins; int ret; -@@ -7054,13 +7256,13 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro +@@ -7054,13 +7481,13 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro if (func->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) { @@ -5157,7 +8772,7 @@ index 23e059a3490..29bf62709eb 100644 "Invalid alpha test function parameter data type %#x.", func->data_type); return VKD3D_ERROR_INVALID_ARGUMENT; } -@@ -7117,10 +7319,8 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog +@@ -7117,10 +7544,8 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog struct vkd3d_shader_instruction *ins; unsigned int output_idx = 0; @@ -5169,7 +8784,7 @@ index 23e059a3490..29bf62709eb 100644 for (unsigned int i = 0; i < 8; ++i) { -@@ -7166,7 +7366,6 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr +@@ -7166,7 +7591,6 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u; const struct vkd3d_shader_parameter1 *mask_parameter = NULL; uint32_t position_signature_idx, position_temp, mask; @@ -5177,7 +8792,7 @@ index 23e059a3490..29bf62709eb 100644 struct signature_element *clip_element; struct vkd3d_shader_instruction *ins; unsigned int plane_count; -@@ -7188,13 +7387,13 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr +@@ -7188,13 +7612,13 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr if (mask_parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) { @@ -5193,7 +8808,7 @@ index 23e059a3490..29bf62709eb 100644 "Invalid clip plane mask parameter data type %#x.", mask_parameter->data_type); return VKD3D_ERROR_INVALID_ARGUMENT; } -@@ -7207,7 +7406,7 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr +@@ -7207,7 +7631,7 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr { if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_CLIP_DISTANCE) { @@ -5202,7 +8817,7 @@ index 23e059a3490..29bf62709eb 100644 "Clip planes cannot be used if the shader writes clip distance."); return VKD3D_ERROR_INVALID_ARGUMENT; } -@@ -7215,7 +7414,7 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr +@@ -7215,7 +7639,7 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr if (!vsir_signature_find_sysval(signature, VKD3D_SHADER_SV_POSITION, 0, &position_signature_idx)) { @@ -5211,7 +8826,7 @@ index 23e059a3490..29bf62709eb 100644 "Shader does not write position."); return VKD3D_ERROR_INVALID_SHADER; } -@@ -7288,10 +7487,8 @@ static enum vkd3d_result insert_point_size_before_ret(struct vsir_program *progr +@@ -7288,10 +7712,8 @@ static enum vkd3d_result insert_point_size_before_ret(struct vsir_program *progr const struct vkd3d_shader_location loc = vsir_program_iterator_current(it)->location; struct vkd3d_shader_instruction *ins; @@ -5223,7 +8838,7 @@ index 23e059a3490..29bf62709eb 100644 vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VSIR_DATA_F32, 1); -@@ -7307,7 +7504,6 @@ static enum vkd3d_result vsir_program_insert_point_size(struct vsir_program *pro +@@ -7307,7 +7729,6 @@ static enum vkd3d_result vsir_program_insert_point_size(struct vsir_program *pro { struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); const struct vkd3d_shader_parameter1 *size_parameter = NULL; @@ -5231,7 +8846,7 @@ index 23e059a3490..29bf62709eb 100644 struct vkd3d_shader_instruction *ins; if (program->has_point_size) -@@ -7329,7 +7525,7 @@ static enum vkd3d_result vsir_program_insert_point_size(struct vsir_program *pro +@@ -7329,7 +7750,7 @@ static enum vkd3d_result vsir_program_insert_point_size(struct vsir_program *pro if (size_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32) { @@ -5240,7 +8855,7 @@ index 23e059a3490..29bf62709eb 100644 "Invalid point size parameter data type %#x.", size_parameter->data_type); return VKD3D_ERROR_INVALID_ARGUMENT; } -@@ -7356,7 +7552,6 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra +@@ -7356,7 +7777,6 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra { const struct vkd3d_shader_parameter1 *min_parameter = NULL, *max_parameter = NULL; struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); @@ -5248,7 +8863,7 @@ index 23e059a3490..29bf62709eb 100644 struct vkd3d_shader_instruction *ins; if (!program->has_point_size) -@@ -7380,14 +7575,14 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra +@@ -7380,14 +7800,14 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra if (min_parameter && min_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32) { @@ -5265,7 +8880,7 @@ index 23e059a3490..29bf62709eb 100644 "Invalid maximum point size parameter data type %#x.", max_parameter->data_type); return VKD3D_ERROR_INVALID_ARGUMENT; } -@@ -7530,7 +7725,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr +@@ -7530,7 +7950,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr { struct vsir_program_iterator it = vsir_program_iterator(&program->instructions), it2; const struct vkd3d_shader_parameter1 *sprite_parameter = NULL; @@ -5274,7 +8889,7 @@ index 23e059a3490..29bf62709eb 100644 struct vkd3d_shader_instruction *ins; bool used_texcoord = false; unsigned int coord_temp; -@@ -7552,13 +7747,13 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr +@@ -7552,13 +7972,13 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr if (sprite_parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) { @@ -5290,7 +8905,7 @@ index 23e059a3490..29bf62709eb 100644 "Invalid point sprite parameter data type %#x.", sprite_parameter->data_type); return VKD3D_ERROR_INVALID_ARGUMENT; } -@@ -7578,7 +7773,10 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr +@@ -7578,7 +7998,10 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) { if (!vsir_instruction_is_dcl(ins) && ins->opcode != VSIR_OP_LABEL && ins->opcode != VSIR_OP_NOP) @@ -5301,7 +8916,7 @@ index 23e059a3490..29bf62709eb 100644 } it2 = it; -@@ -7613,12 +7811,10 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr +@@ -7613,12 +8036,10 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr if (used_texcoord) { @@ -5316,7 +8931,7 @@ index 23e059a3490..29bf62709eb 100644 dst_param_init_temp_float4(&ins->dst[0], coord_temp); ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; vsir_src_param_init(&ins->src[0], VKD3DSPR_POINT_COORD, VSIR_DATA_F32, 0); -@@ -7626,7 +7822,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr +@@ -7626,11 +8047,12 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; ins = vsir_program_iterator_next(&it); @@ -5325,7 +8940,12 @@ index 23e059a3490..29bf62709eb 100644 dst_param_init_temp_float4(&ins->dst[0], coord_temp); ins->dst[0].write_mask = VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); -@@ -7668,15 +7864,12 @@ static enum vkd3d_result vsir_program_add_fog_input(struct vsir_program *program + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; + vsir_program_iterator_next(&it); + + program->has_point_coord = true; +@@ -7668,15 +8090,12 @@ static enum vkd3d_result vsir_program_add_fog_input(struct vsir_program *program } static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *program, @@ -5345,7 +8965,7 @@ index 23e059a3490..29bf62709eb 100644 uint32_t ssa_temp, ssa_temp2; switch (mode) -@@ -7687,16 +7880,11 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -7687,16 +8106,11 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro * add sr0, FOG_END, -vFOG.x * mul_sat srFACTOR, sr0, FOG_SCALE */ @@ -5363,7 +8983,7 @@ index 23e059a3490..29bf62709eb 100644 vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_ADD, 1, 2); dst_param_init_ssa_float(&ins->dst[0], ssa_temp); src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_END, VSIR_DATA_F32); -@@ -7705,12 +7893,15 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -7705,12 +8119,15 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); ins->src[1].modifiers = VKD3DSPSM_NEG; @@ -5380,7 +9000,7 @@ index 23e059a3490..29bf62709eb 100644 break; case VKD3D_SHADER_FOG_FRAGMENT_EXP: -@@ -7719,16 +7910,11 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -7719,16 +8136,11 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro * mul sr0, FOG_SCALE, vFOG.x * exp_sat srFACTOR, -sr0 */ @@ -5398,7 +9018,7 @@ index 23e059a3490..29bf62709eb 100644 vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MUL, 1, 2); dst_param_init_ssa_float(&ins->dst[0], ssa_temp); src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VSIR_DATA_F32); -@@ -7736,12 +7922,14 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -7736,12 +8148,14 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ins->src[1].reg.idx[0].offset = fog_signature_idx; ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); @@ -5414,7 +9034,7 @@ index 23e059a3490..29bf62709eb 100644 break; case VKD3D_SHADER_FOG_FRAGMENT_EXP2: -@@ -7751,17 +7939,12 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -7751,17 +8165,12 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro * mul sr1, sr0, sr0 * exp_sat srFACTOR, -sr1 */ @@ -5433,7 +9053,7 @@ index 23e059a3490..29bf62709eb 100644 vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MUL, 1, 2); dst_param_init_ssa_float(&ins->dst[0], ssa_temp); src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VSIR_DATA_F32); -@@ -7769,17 +7952,20 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -7769,17 +8178,20 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ins->src[1].reg.idx[0].offset = fog_signature_idx; ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); @@ -5456,7 +9076,7 @@ index 23e059a3490..29bf62709eb 100644 break; default: -@@ -7792,18 +7978,20 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -7792,18 +8204,20 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro * mad oC0, sr0, srFACTOR, FOG_COLOUR */ @@ -5479,7 +9099,7 @@ index 23e059a3490..29bf62709eb 100644 return VKD3D_OK; } -@@ -7811,14 +7999,13 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -7811,14 +8225,13 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro static enum vkd3d_result vsir_program_insert_fragment_fog(struct vsir_program *program, struct vsir_transformation_context *ctx) { @@ -5495,7 +9115,7 @@ index 23e059a3490..29bf62709eb 100644 int ret; if (program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL) -@@ -7832,13 +8019,13 @@ static enum vkd3d_result vsir_program_insert_fragment_fog(struct vsir_program *p +@@ -7832,13 +8245,13 @@ static enum vkd3d_result vsir_program_insert_fragment_fog(struct vsir_program *p if (mode_parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) { @@ -5511,7 +9131,7 @@ index 23e059a3490..29bf62709eb 100644 "Invalid fog fragment mode parameter data type %#x.", mode_parameter->data_type); return VKD3D_ERROR_INVALID_ARGUMENT; } -@@ -7859,19 +8046,16 @@ static enum vkd3d_result vsir_program_insert_fragment_fog(struct vsir_program *p +@@ -7859,19 +8272,16 @@ static enum vkd3d_result vsir_program_insert_fragment_fog(struct vsir_program *p * through the whole shader and convert it to a temp. */ colour_temp = program->temp_count++; @@ -5534,7 +9154,7 @@ index 23e059a3490..29bf62709eb 100644 continue; } -@@ -7927,21 +8111,16 @@ static enum vkd3d_result vsir_program_add_fog_output(struct vsir_program *progra +@@ -7927,21 +8337,16 @@ static enum vkd3d_result vsir_program_add_fog_output(struct vsir_program *progra return VKD3D_OK; } @@ -5560,7 +9180,7 @@ index 23e059a3490..29bf62709eb 100644 /* Write the fog output. */ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); -@@ -7951,26 +8130,26 @@ static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *progr +@@ -7951,26 +8356,26 @@ static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *progr ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z); else /* Position or specular W. */ ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W); @@ -5591,7 +9211,7 @@ index 23e059a3490..29bf62709eb 100644 enum vkd3d_shader_fog_source source; const struct signature_element *e; -@@ -7982,13 +8161,13 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro +@@ -7982,13 +8387,13 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro if (source_parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) { @@ -5607,7 +9227,7 @@ index 23e059a3490..29bf62709eb 100644 "Invalid fog source parameter data type %#x.", source_parameter->data_type); return VKD3D_ERROR_INVALID_ARGUMENT; } -@@ -8010,7 +8189,7 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro +@@ -8010,7 +8415,7 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro if (!vsir_signature_find_sysval(&program->output_signature, VKD3D_SHADER_SV_POSITION, 0, &source_signature_idx)) { @@ -5616,7 +9236,7 @@ index 23e059a3490..29bf62709eb 100644 VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC, "Shader does not write position."); return VKD3D_ERROR_INVALID_SHADER; } -@@ -8027,22 +8206,18 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro +@@ -8027,22 +8432,18 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro /* Insert a fog write before each ret, and convert either specular or * position output to a temp. */ @@ -5642,7 +9262,7 @@ index 23e059a3490..29bf62709eb 100644 continue; } -@@ -8450,7 +8625,7 @@ struct liveness_tracker +@@ -8450,7 +8851,7 @@ struct liveness_tracker bool fixed_mask; uint8_t mask; unsigned int first_write, last_access; @@ -5651,7 +9271,7 @@ index 23e059a3490..29bf62709eb 100644 }; static void liveness_track_src(struct liveness_tracker *tracker, -@@ -8464,6 +8639,8 @@ static void liveness_track_src(struct liveness_tracker *tracker, +@@ -8464,6 +8865,8 @@ static void liveness_track_src(struct liveness_tracker *tracker, if (src->reg.type == VKD3DSPR_SSA) tracker->ssa_regs[src->reg.idx[0].offset].last_access = index; @@ -5660,7 +9280,7 @@ index 23e059a3490..29bf62709eb 100644 } static void liveness_track_dst(struct liveness_tracker *tracker, struct vkd3d_shader_dst_param *dst, -@@ -8479,6 +8656,8 @@ static void liveness_track_dst(struct liveness_tracker *tracker, struct vkd3d_sh +@@ -8479,6 +8882,8 @@ static void liveness_track_dst(struct liveness_tracker *tracker, struct vkd3d_sh if (dst->reg.type == VKD3DSPR_SSA) reg = &tracker->ssa_regs[dst->reg.idx[0].offset]; @@ -5669,7 +9289,7 @@ index 23e059a3490..29bf62709eb 100644 else return; -@@ -8565,20 +8744,22 @@ static void liveness_tracker_cleanup(struct liveness_tracker *tracker) +@@ -8565,20 +8970,22 @@ static void liveness_tracker_cleanup(struct liveness_tracker *tracker) static enum vkd3d_result track_liveness(struct vsir_program *program, struct liveness_tracker *tracker) { @@ -5696,7 +9316,7 @@ index 23e059a3490..29bf62709eb 100644 if (ins->opcode == VSIR_OP_LOOP || ins->opcode == VSIR_OP_REP) { if (!loop_depth++) -@@ -8604,8 +8785,7 @@ static enum vkd3d_result track_liveness(struct vsir_program *program, struct liv +@@ -8604,8 +9011,7 @@ static enum vkd3d_result track_liveness(struct vsir_program *program, struct liv * should be illegal for an SSA value to be read in a block * containing L.) * We don't try to perform this optimization yet, in the name of @@ -5706,7 +9326,7 @@ index 23e059a3490..29bf62709eb 100644 for (unsigned int j = 0; j < program->ssa_count; ++j) { struct liveness_tracker_reg *reg = &tracker->ssa_regs[j]; -@@ -8615,6 +8795,16 @@ static enum vkd3d_result track_liveness(struct vsir_program *program, struct liv +@@ -8615,6 +9021,16 @@ static enum vkd3d_result track_liveness(struct vsir_program *program, struct liv if (reg->last_access < i) reg->last_access = i; } @@ -5723,78 +9343,93 @@ index 23e059a3490..29bf62709eb 100644 } } -@@ -8634,8 +8824,8 @@ struct temp_allocator +@@ -8632,74 +9048,19 @@ struct temp_allocator + struct vkd3d_shader_message_context *message_context; + struct temp_allocator_reg { ++ struct liveness_tracker_reg *liveness_reg; uint8_t allocated_mask; uint32_t temp_id; - } *ssa_regs; - size_t allocated_ssa_count; -+ } *ssa_regs, *temp_regs; -+ size_t allocated_ssa_count, allocated_temp_count; - enum vkd3d_result result; - }; - -@@ -8662,16 +8852,30 @@ static uint8_t get_available_writemask(const struct temp_allocator *allocator, - return writemask; - } - -+ for (size_t i = 0; i < allocator->allocated_temp_count; ++i) -+ { -+ const struct temp_allocator_reg *reg = &allocator->temp_regs[i]; -+ const struct liveness_tracker_reg *liveness_reg = &tracker->temp_regs[i]; -+ -+ if (reg->temp_id == temp_id -+ && first_write < liveness_reg->last_access -+ && last_access > liveness_reg->first_write) -+ writemask &= ~reg->allocated_mask; -+ -+ if (!writemask) -+ return writemask; -+ } -+ - return writemask; - } - - static bool temp_allocator_allocate(struct temp_allocator *allocator, struct liveness_tracker *tracker, +- enum vkd3d_result result; +-}; +- +-static uint8_t get_available_writemask(const struct temp_allocator *allocator, +- struct liveness_tracker *tracker, unsigned int first_write, unsigned int last_access, uint32_t temp_id) +-{ +- uint8_t writemask = VKD3DSP_WRITEMASK_ALL; +- +- for (size_t i = 0; i < allocator->allocated_ssa_count; ++i) +- { +- const struct temp_allocator_reg *reg = &allocator->ssa_regs[i]; +- const struct liveness_tracker_reg *liveness_reg = &tracker->ssa_regs[i]; +- +- /* We do not overlap if first write == last read: +- * this is the case where we are allocating the result of that +- * expression, e.g. "add r0, r0, r1". */ +- +- if (reg->temp_id == temp_id +- && first_write < liveness_reg->last_access +- && last_access > liveness_reg->first_write) +- writemask &= ~reg->allocated_mask; +- +- if (!writemask) +- return writemask; +- } +- +- return writemask; +-} +- +-static bool temp_allocator_allocate(struct temp_allocator *allocator, struct liveness_tracker *tracker, - struct temp_allocator_reg *reg, const struct liveness_tracker_reg *liveness_reg, uint32_t base_id) -+ struct temp_allocator_reg *reg, const struct liveness_tracker_reg *liveness_reg) - { - if (!liveness_reg->written) - return false; - +-{ +- if (!liveness_reg->written) +- return false; +- - for (uint32_t id = base_id;; ++id) -+ for (uint32_t id = 0;; ++id) - { - uint8_t available_mask = get_available_writemask(allocator, tracker, - liveness_reg->first_write, liveness_reg->last_access, id); -@@ -8688,13 +8892,21 @@ static bool temp_allocator_allocate(struct temp_allocator *allocator, struct liv - else - { - /* For SSA values the mask is always zero-based and contiguous. +- { +- uint8_t available_mask = get_available_writemask(allocator, tracker, +- liveness_reg->first_write, liveness_reg->last_access, id); +- +- if (liveness_reg->fixed_mask) +- { +- if ((available_mask & liveness_reg->mask) == liveness_reg->mask) +- { +- reg->temp_id = id; +- reg->allocated_mask = liveness_reg->mask; +- return true; +- } +- } +- else +- { +- /* For SSA values the mask is always zero-based and contiguous. - * We don't correctly handle cases where it's not, currently. */ - VKD3D_ASSERT((liveness_reg->mask | (liveness_reg->mask - 1)) == liveness_reg->mask); - - if (vkd3d_popcount(available_mask) >= vkd3d_popcount(liveness_reg->mask)) -+ * For TEMP values we assume the register was allocated that way, -+ * but it may only be partially used. -+ * We currently only handle cases where the mask is zero-based and -+ * contiguous, so we need to fill in the missing components to -+ * ensure this. */ -+ uint8_t mask = (1u << (vkd3d_log2i(liveness_reg->mask) + 1)) - 1; -+ -+ if (vkd3d_popcount(available_mask) >= vkd3d_popcount(mask)) - { -+ if (mask != liveness_reg->mask) -+ WARN("Allocating a mask %#x with used components %#x; this is not optimized.\n", -+ mask, liveness_reg->mask); -+ - reg->temp_id = id; +- { +- reg->temp_id = id; - reg->allocated_mask = vsir_combine_write_masks(available_mask, liveness_reg->mask); -+ reg->allocated_mask = vsir_combine_write_masks(available_mask, mask); - return true; - } - } -@@ -8713,6 +8925,8 @@ static void temp_allocator_set_src(struct temp_allocator *allocator, struct vkd3 +- return true; +- } +- } +- } +-} ++ enum vkd3d_shader_register_type type; ++ unsigned int idx; ++ bool force_first; ++ } *ssa_regs, *temp_regs; ++ size_t ssa_count, temp_count; ++ unsigned int new_temp_count; ++ enum vkd3d_result result; ++ uint8_t *current_allocation; ++ bool ps_1_x; ++}; + + static void temp_allocator_set_src(struct temp_allocator *allocator, struct vkd3d_shader_src_param *src) + { +@@ -8713,6 +9074,8 @@ static void temp_allocator_set_src(struct temp_allocator *allocator, struct vkd3 if (src->reg.type == VKD3DSPR_SSA) reg = &allocator->ssa_regs[src->reg.idx[0].offset]; @@ -5803,7 +9438,7 @@ index 23e059a3490..29bf62709eb 100644 else return; -@@ -8792,6 +9006,7 @@ static void temp_allocator_set_dst(struct temp_allocator *allocator, +@@ -8792,6 +9155,7 @@ static void temp_allocator_set_dst(struct temp_allocator *allocator, struct vkd3d_shader_dst_param *dst, const struct vkd3d_shader_instruction *ins) { struct temp_allocator_reg *reg; @@ -5811,7 +9446,7 @@ index 23e059a3490..29bf62709eb 100644 for (unsigned int k = 0; k < dst->reg.idx_count; ++k) { -@@ -8801,15 +9016,18 @@ static void temp_allocator_set_dst(struct temp_allocator *allocator, +@@ -8801,15 +9165,18 @@ static void temp_allocator_set_dst(struct temp_allocator *allocator, if (dst->reg.type == VKD3DSPR_SSA) reg = &allocator->ssa_regs[dst->reg.idx[0].offset]; @@ -5832,7 +9467,7 @@ index 23e059a3490..29bf62709eb 100644 if (vsir_opcode_is_double(ins->opcode)) { -@@ -8825,47 +9043,90 @@ static void temp_allocator_set_dst(struct temp_allocator *allocator, +@@ -8825,58 +9192,324 @@ static void temp_allocator_set_dst(struct temp_allocator *allocator, if (vsir_src_is_masked(ins->opcode, i)) { if (src->reg.type == VKD3DSPR_IMMCONST) @@ -5844,9 +9479,261 @@ index 23e059a3490..29bf62709eb 100644 else - src->swizzle = vsir_map_swizzle(src->swizzle, dst->write_mask); + src->swizzle = vsir_map_swizzle(src->swizzle, reg->allocated_mask); ++ } ++ } ++ } ++} ++ ++static int temp_allocate_compare_open(const void *ptr1, const void *ptr2) ++{ ++ const struct temp_allocator_reg * const *reg1 = ptr1, * const *reg2 = ptr2; ++ int ret; ++ ++ if ((ret = vkd3d_u32_compare((*reg1)->force_first, (*reg2)->force_first))) ++ return -ret; ++ if ((ret = vkd3d_u32_compare((*reg1)->liveness_reg->first_write, (*reg2)->liveness_reg->first_write))) ++ return ret; ++ if ((ret = vkd3d_u32_compare((*reg1)->liveness_reg->last_access, (*reg2)->liveness_reg->last_access))) ++ return ret; ++ return 0; ++} ++ ++static int temp_allocate_compare_close(const void *ptr1, const void *ptr2) ++{ ++ const struct temp_allocator_reg * const *reg1 = ptr1, * const *reg2 = ptr2; ++ int ret; ++ ++ if ((ret = vkd3d_u32_compare((*reg1)->liveness_reg->last_access, (*reg2)->liveness_reg->last_access))) ++ return ret; ++ return vkd3d_u32_compare((*reg1)->liveness_reg->first_write, (*reg2)->liveness_reg->first_write); ++} ++ ++static const char *debug_temp_allocator_reg(const struct temp_allocator_reg *reg) ++{ ++ return vkd3d_dbg_sprintf("%s%u", reg->type == VKD3DSPR_SSA ? "sr" : "r", reg->idx); ++} ++ ++static void temp_allocator_open_register(struct temp_allocator *allocator, struct temp_allocator_reg *reg) ++{ ++ const size_t reg_count = allocator->ssa_count + allocator->temp_count; ++ const struct liveness_tracker_reg *liveness_reg = reg->liveness_reg; ++ uint8_t *current_allocation = allocator->current_allocation; ++ size_t i; ++ ++ if (!liveness_reg->written) ++ return; ++ ++ for (i = 0; i < reg_count; ++i) ++ { ++ const uint8_t available_mask = ~current_allocation[i] & 0xf; ++ ++ if (liveness_reg->fixed_mask) ++ { ++ if ((available_mask & liveness_reg->mask) == liveness_reg->mask) ++ { ++ reg->temp_id = i; ++ reg->allocated_mask = liveness_reg->mask; ++ current_allocation[i] |= reg->allocated_mask; ++ allocator->new_temp_count = max(allocator->new_temp_count, i + 1); ++ TRACE("Allocated r%u%s for %s (liveness %u-%u).\n", ++ reg->temp_id, debug_vsir_writemask(reg->allocated_mask), ++ debug_temp_allocator_reg(reg), liveness_reg->first_write, liveness_reg->last_access); ++ break; ++ } ++ } ++ else ++ { ++ /* For SSA values the mask is always zero-based and contiguous. ++ * For TEMP values we assume the register was allocated that way, ++ * but it may only be partially used. ++ * We currently only handle cases where the mask is zero-based and ++ * contiguous, so we need to fill in the missing components to ++ * ensure this. */ ++ uint8_t mask = (1u << (vkd3d_log2i(liveness_reg->mask) + 1)) - 1; ++ ++ if (vkd3d_popcount(available_mask) >= vkd3d_popcount(mask)) ++ { ++ if (mask != liveness_reg->mask) ++ WARN("Allocating a mask %#x with used components %#x; this is not optimized.\n", ++ mask, liveness_reg->mask); ++ ++ reg->temp_id = i; ++ reg->allocated_mask = vsir_combine_write_masks(available_mask, mask); ++ current_allocation[i] |= reg->allocated_mask; ++ allocator->new_temp_count = max(allocator->new_temp_count, i + 1); ++ TRACE("Allocated r%u%s for %s (liveness %u-%u).\n", ++ reg->temp_id, debug_vsir_writemask(reg->allocated_mask), ++ debug_temp_allocator_reg(reg), liveness_reg->first_write, liveness_reg->last_access); ++ break; ++ } ++ } ++ } ++ ++ VKD3D_ASSERT(i < reg_count); ++} ++ ++static void temp_allocator_close_register(struct temp_allocator *allocator, struct temp_allocator_reg *reg) ++{ ++ const struct liveness_tracker_reg *liveness_reg = reg->liveness_reg; ++ ++ if (!liveness_reg->written) ++ return; ++ ++ TRACE("Register %s (liveness %u-%u) reaches end of life.\n", ++ debug_temp_allocator_reg(reg), liveness_reg->first_write, liveness_reg->last_access); ++ ++ allocator->current_allocation[reg->temp_id] &= ~reg->allocated_mask; ++} ++ ++/* Compute the allocation map. Each register is modeled as a time interval ++ * spanning from `first_write' to `last_access'. We simulate scanning through ++ * all the intervals in time order, keeping the set of currently allocated ++ * registers as a bit map: each time we open an interval (i.e., hit its ++ * `first_write' time) we allocate it to the first available register scanning ++ * the current state; each time we close an interval (i.e., hit its ++ * `last_access' time) we unset the corresponding bits. ++ * ++ * In general at any given time we first process all intervals to be closed and ++ * then all intervals to be opened at that time. This models the fact that an ++ * instruction can write to a register which it also reads from, and the write ++ * won't interfere with the read. In other words, first all reads are ++ * performed, then the instruction is executed, then the writes are performed. ++ * ++ * There is a corner case exception, though: the case of degenerate intervals ++ * that are opened and closed at the same time. This corresponds to registers ++ * that are written and then never read, which in principle shouldn't exist ++ * because they make no sense. However it's better to be robust, and we support ++ * them anyway. ++ * ++ * So that's what we do: ++ * - First all non-degenerate closes are processed. ++ * - Then all degenerate opens are processed, because we cannot close them ++ * before having opened them. ++ * - Then all non-degenerate opens are processed: this has to happens before ++ * the degenerate intervals are closed, because they need to be allocated to ++ * different registers. ++ * - Then all degenerate closes are processed. ++ * ++ * This is effected with a few different strategies: ++ * - In the open order, registers are primarily sorted by `first_write' and ++ * secondarily by `last_access'. This way degenerate registers are always ++ * opened before non-degenerate ones with the same `first_write' time. ++ * - In the close order, registers are primarily sorted by `last_access' and ++ * secondarily by `first_write'. This way non-degenerate registers are ++ * always closed before degenerate ones with the same `last_access' time. ++ * - There is a scheduling algorithm that decides at each iteration whether to ++ * open or close a register. See details below. ++ * ++ * TODO: the algorithm could be further optimized by keeping a few pointers to ++ * the first position in `current_allocation' that has at least one (or two, ++ * three and four) available components, so we don't always have to scan from ++ * the beginning. ++ */ ++static enum vkd3d_result temp_allocator_compute_allocation_map(struct temp_allocator *allocator, ++ const struct liveness_tracker *liveness) ++{ ++ const size_t reg_count = allocator->ssa_count + allocator->temp_count; ++ struct temp_allocator_reg **open_order = NULL, **close_order = NULL; ++ size_t i, pos_open = 0, pos_close = 0; ++ ++ /* In the worst-case scenario each of the `reg_count' registers to be ++ * processed requires its own allocation. We should never exceed that ++ * amount. */ ++ if (!(allocator->current_allocation = vkd3d_calloc(reg_count, sizeof(*allocator->current_allocation))) ++ || !(open_order = vkd3d_calloc(reg_count, sizeof(*open_order))) ++ || !(close_order = vkd3d_calloc(reg_count, sizeof(*close_order)))) ++ { ++ vkd3d_free(close_order); ++ vkd3d_free(open_order); ++ vkd3d_free(allocator->current_allocation); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ } ++ ++ for (i = 0; i < reg_count; ++i) ++ { ++ struct temp_allocator_reg *reg = &allocator->ssa_regs[i]; ++ ++ if (i < allocator->ssa_count) ++ { ++ reg->type = VKD3DSPR_SSA; ++ reg->idx = i; ++ } ++ else ++ { ++ reg->type = VKD3DSPR_TEMP; ++ reg->idx = i - allocator->ssa_count; ++ ++ /* For SM 1.x ps we need to ensure that r0 is reallocated to itself, ++ * because it doubles as the output register. To do so we ++ * artificially make it alive for the whole program and make it ++ * compare before anything else. */ ++ if (reg->idx == 0 && allocator->ps_1_x) ++ { ++ reg->force_first = true; ++ liveness->ssa_regs[i].first_write = 0; ++ liveness->ssa_regs[i].last_access = UINT_MAX; } } ++ ++ reg->liveness_reg = &liveness->ssa_regs[i]; ++ open_order[i] = reg; ++ close_order[i] = reg; ++ } ++ ++ qsort(open_order, reg_count, sizeof(*open_order), temp_allocate_compare_open); ++ qsort(close_order, reg_count, sizeof(*open_order), temp_allocate_compare_close); ++ ++ for (;;) ++ { ++ struct temp_allocator_reg *reg_open = NULL, *reg_close = NULL; ++ bool do_open; ++ ++ if (pos_open < reg_count) ++ reg_open = open_order[pos_open]; ++ if (pos_close < reg_count) ++ reg_close = close_order[pos_close]; ++ ++ /* We cannot close all the registers before we finish opening them. */ ++ VKD3D_ASSERT(!(reg_open && !reg_close)); ++ ++ /* We finished closing registers, nothing to do any more. */ ++ if (!reg_close) ++ break; ++ /* There is nothing to open, so we just close. */ ++ else if (!reg_open) ++ do_open = false; ++ /* The next open event happens before the next close event, so we open. */ ++ else if (reg_open->liveness_reg->first_write < reg_close->liveness_reg->last_access) ++ do_open = true; ++ /* The other way around, we close. */ ++ else if (reg_close->liveness_reg->last_access < reg_open->liveness_reg->first_write) ++ do_open = false; ++ /* Ok, now we have both an open and a close happening at the same time. ++ * According to the strategy above, if the interval to close is ++ * non-degenerate, then we process it. */ ++ else if (reg_close->liveness_reg->first_write < reg_close->liveness_reg->last_access) ++ do_open = false; ++ /* Otherwise the interval to close is degenerate, and therefore we first ++ * open whatever needs to be opened. */ ++ else ++ do_open = true; ++ ++ if (do_open) ++ { ++ temp_allocator_open_register(allocator, reg_open); ++ ++pos_open; ++ } ++ else ++ { ++ temp_allocator_close_register(allocator, reg_close); ++ ++pos_close; ++ } } ++ ++ vkd3d_free(close_order); ++ vkd3d_free(open_order); ++ vkd3d_free(allocator->current_allocation); ++ return VKD3D_OK; } +/* This pass does two things: @@ -5868,8 +9755,8 @@ index 23e059a3490..29bf62709eb 100644 enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, struct vkd3d_shader_message_context *message_context) { +- const unsigned int prev_temp_count = program->temp_count; + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); - const unsigned int prev_temp_count = program->temp_count; struct temp_allocator allocator = {0}; + struct vkd3d_shader_instruction *ins; struct temp_allocator_reg *regs; @@ -5877,61 +9764,45 @@ index 23e059a3490..29bf62709eb 100644 enum vkd3d_result ret; - if (!program->ssa_count) -+ if (!program->ssa_count && !prev_temp_count) ++ if (!program->ssa_count && !program->temp_count) return VKD3D_OK; if ((ret = track_liveness(program, &tracker))) return ret; - if (!(regs = vkd3d_calloc(program->ssa_count, sizeof(*regs)))) -+ if (!(regs = vkd3d_calloc(program->ssa_count + prev_temp_count, sizeof(*regs)))) ++ if (!(regs = vkd3d_calloc(program->ssa_count + program->temp_count, sizeof(*regs)))) { liveness_tracker_cleanup(&tracker); return VKD3D_ERROR_OUT_OF_MEMORY; } allocator.message_context = message_context; ++ allocator.ssa_count = program->ssa_count; ++ allocator.temp_count = program->temp_count; allocator.ssa_regs = regs; + allocator.temp_regs = regs + program->ssa_count; -+ -+ program->temp_count = 0; -+ -+ /* Reallocate temps first. We do this specifically to make sure that r0 is -+ * the first register to be allocated, and thus will be reallocated in -+ * place, and left alone. -+ * This is necessary because, in pixel shader model 1.x, r0 doubles as the -+ * output register, and needs to remain at r0. (Note that we need to already -+ * have the output in r0, rather than e.g. putting it in o0 and converting -+ * it to r0 after this pass, so that we know when r0 is live.) */ -+ for (unsigned int i = 0; i < prev_temp_count; ++i) -+ { -+ const struct liveness_tracker_reg *liveness_reg = &tracker.temp_regs[i]; -+ struct temp_allocator_reg *reg = &allocator.temp_regs[i]; -+ -+ if (temp_allocator_allocate(&allocator, &tracker, reg, liveness_reg)) -+ { -+ TRACE("Reallocated r%u%s for r%u (liveness %u-%u).\n", -+ reg->temp_id, debug_vsir_writemask(reg->allocated_mask), i, -+ liveness_reg->first_write, liveness_reg->last_access); -+ program->temp_count = max(program->temp_count, reg->temp_id + 1); -+ } -+ ++allocator.allocated_temp_count; -+ } ++ allocator.new_temp_count = 0; - for (unsigned int i = 0; i < program->ssa_count; ++i) - { - const struct liveness_tracker_reg *liveness_reg = &tracker.ssa_regs[i]; - struct temp_allocator_reg *reg = &allocator.ssa_regs[i]; +- for (unsigned int i = 0; i < program->ssa_count; ++i) +- { +- const struct liveness_tracker_reg *liveness_reg = &tracker.ssa_regs[i]; +- struct temp_allocator_reg *reg = &allocator.ssa_regs[i]; ++ if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && program->shader_version.major < 2) ++ allocator.ps_1_x = true; - if (temp_allocator_allocate(&allocator, &tracker, reg, liveness_reg, prev_temp_count)) -+ if (temp_allocator_allocate(&allocator, &tracker, reg, liveness_reg)) - { +- { - TRACE("Allocated r%u%s to sr%u (liveness %u-%u).\n", -+ TRACE("Allocated r%u%s for sr%u (liveness %u-%u).\n", - reg->temp_id, debug_vsir_writemask(reg->allocated_mask), i, - liveness_reg->first_write, liveness_reg->last_access); - program->temp_count = max(program->temp_count, reg->temp_id + 1); -@@ -8873,10 +9134,8 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, - ++allocator.allocated_ssa_count; +- reg->temp_id, debug_vsir_writemask(reg->allocated_mask), i, +- liveness_reg->first_write, liveness_reg->last_access); +- program->temp_count = max(program->temp_count, reg->temp_id + 1); +- } +- ++allocator.allocated_ssa_count; ++ if ((ret = temp_allocator_compute_allocation_map(&allocator, &tracker)) < 0) ++ { ++ liveness_tracker_cleanup(&tracker); ++ vkd3d_free(regs); ++ return ret; } - for (unsigned int i = 0; i < program->instructions.count; ++i) @@ -5942,7 +9813,19 @@ index 23e059a3490..29bf62709eb 100644 /* Make sure we do the srcs first; setting the dst writemask may need * to remap their swizzles. */ for (unsigned int j = 0; j < ins->src_count; ++j) -@@ -8902,11 +9161,14 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, +@@ -8886,9 +9519,11 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, + } + + program->ssa_count = 0; ++ program->temp_count = allocator.new_temp_count; + + vkd3d_free(regs); + liveness_tracker_cleanup(&tracker); ++ + return allocator.result; + } + +@@ -8902,11 +9537,17 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, struct vkd3d_shader_message_context *message_context) { @@ -5952,6 +9835,9 @@ index 23e059a3490..29bf62709eb 100644 unsigned int temp_count = 0; - for (int i = program->instructions.count - 1; i >= 0; --i) ++ if (program->shader_version.major < 4) ++ return VKD3D_OK; ++ + for (ins = vsir_program_iterator_tail(&it); ins; ins = vsir_program_iterator_prev(&it)) { - struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; @@ -5959,7 +9845,17 @@ index 23e059a3490..29bf62709eb 100644 if (ins->opcode == VSIR_OP_DCL_TEMPS) { -@@ -8922,11 +9184,11 @@ enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, +@@ -8915,18 +9556,17 @@ enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, + continue; + } + +- if (temp_count && program->shader_version.major >= 4 +- && (ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE +- || ins->opcode == VSIR_OP_HS_FORK_PHASE +- || ins->opcode == VSIR_OP_HS_JOIN_PHASE)) ++ if (temp_count && (ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE ++ || ins->opcode == VSIR_OP_HS_FORK_PHASE ++ || ins->opcode == VSIR_OP_HS_JOIN_PHASE)) { /* The phase didn't have a dcl_temps instruction, but we added * temps here, so we need to insert one. */ @@ -5974,9 +9870,12 @@ index 23e059a3490..29bf62709eb 100644 ins->declaration.count = temp_count; temp_count = 0; continue; -@@ -8947,13 +9209,13 @@ enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, +@@ -8945,15 +9585,15 @@ enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, + } + } - if (temp_count && program->shader_version.major >= 4) +- if (temp_count && program->shader_version.major >= 4) ++ if (temp_count) { - struct vkd3d_shader_instruction *ins; + ins = vsir_program_iterator_head(&it); @@ -5992,7 +9891,7 @@ index 23e059a3490..29bf62709eb 100644 ins->declaration.count = temp_count; } -@@ -8965,7 +9227,7 @@ struct validation_context +@@ -8965,7 +9605,7 @@ struct validation_context struct vkd3d_shader_message_context *message_context; const struct vsir_program *program; size_t instruction_idx; @@ -6001,7 +9900,7 @@ index 23e059a3490..29bf62709eb 100644 bool invalid_instruction_idx; enum vkd3d_result status; bool dcl_temps_found; -@@ -9024,13 +9286,12 @@ static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *c +@@ -9024,13 +9664,12 @@ static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *c if (ctx->invalid_instruction_idx) { @@ -6017,7 +9916,45 @@ index 23e059a3490..29bf62709eb 100644 "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer); WARN("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer); } -@@ -9459,7 +9720,8 @@ static void vsir_validate_label_register(struct validation_context *ctx, +@@ -9359,6 +9998,37 @@ static void vsir_validate_io_register(struct validation_context *ctx, const stru + reg->idx[control_point_index].offset, control_point_count, reg->type); + } + ++static void vsir_validate_texture_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg) ++{ ++ const struct vkd3d_shader_version *version = &ctx->program->shader_version; ++ uint32_t idx; ++ ++ if (version->type != VKD3D_SHADER_TYPE_PIXEL) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "TEXTURE registers cannot be used in shader type %#x.", version->type); ++ ++ if (reg->idx_count != 1) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a TEXTURE register.", reg->idx_count); ++ return; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for a TEXTURE register."); ++ ++ if (version->major >= 3) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "TEXTURE registers cannot be used in version %u.%u.", version->major, version->minor); ++ ++ idx = reg->idx[0].offset; ++ if (idx >= 8 || (vkd3d_shader_ver_le(version, 1, 4) && idx >= 6) ++ || (vkd3d_shader_ver_le(version, 1, 3) && idx >= 4)) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Register t%u exceeds limits for version %u.%u.", idx, version->major, version->minor); ++} ++ + static void vsir_validate_temp_register(struct validation_context *ctx, + const struct vkd3d_shader_register *reg) + { +@@ -9459,7 +10129,8 @@ static void vsir_validate_label_register(struct validation_context *ctx, if (reg->data_type != VSIR_DATA_UNUSED) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6027,7 +9964,7 @@ index 23e059a3490..29bf62709eb 100644 if (reg->dimension != VSIR_DIMENSION_NONE) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, -@@ -9538,7 +9800,8 @@ static void vsir_validate_sampler_register(struct validation_context *ctx, +@@ -9538,7 +10209,8 @@ static void vsir_validate_sampler_register(struct validation_context *ctx, if (reg->data_type != VSIR_DATA_UNUSED) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6037,7 +9974,7 @@ index 23e059a3490..29bf62709eb 100644 /* VEC4 is allowed in gather operations. */ if (reg->dimension == VSIR_DIMENSION_SCALAR) -@@ -9564,7 +9827,8 @@ static void vsir_validate_resource_register(struct validation_context *ctx, +@@ -9564,7 +10236,8 @@ static void vsir_validate_resource_register(struct validation_context *ctx, if (reg->data_type != VSIR_DATA_UNUSED) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6047,7 +9984,7 @@ index 23e059a3490..29bf62709eb 100644 if (reg->dimension != VSIR_DIMENSION_VEC4) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, -@@ -9590,8 +9854,8 @@ static void vsir_validate_uav_register(struct validation_context *ctx, +@@ -9590,8 +10263,8 @@ static void vsir_validate_uav_register(struct validation_context *ctx, if (reg->data_type != VSIR_DATA_UNUSED) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6058,7 +9995,7 @@ index 23e059a3490..29bf62709eb 100644 /* NONE is allowed in counter operations. */ if (reg->dimension == VSIR_DIMENSION_SCALAR) -@@ -9663,9 +9927,10 @@ static void vsir_validate_ssa_register(struct validation_context *ctx, +@@ -9663,9 +10336,10 @@ static void vsir_validate_ssa_register(struct validation_context *ctx, if (data_type_is_64_bit(data->data_type) != data_type_is_64_bit(reg->data_type)) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6072,7 +10009,27 @@ index 23e059a3490..29bf62709eb 100644 } } -@@ -9913,7 +10178,8 @@ static void vsir_validate_dst_param(struct validation_context *ctx, +@@ -9824,6 +10498,10 @@ static void vsir_validate_register(struct validation_context *ctx, + vsir_validate_register_without_indices(ctx, reg); + break; + ++ case VKD3DSPR_TEXTURE: ++ vsir_validate_texture_register(ctx, reg); ++ break; ++ + case VKD3DSPR_SSA: + vsir_validate_ssa_register(ctx, reg); + break; +@@ -9872,6 +10550,8 @@ static void vsir_validate_io_dst_param(struct validation_context *ctx, + static void vsir_validate_dst_param(struct validation_context *ctx, + const struct vkd3d_shader_dst_param *dst) + { ++ const struct vkd3d_shader_version *version = &ctx->program->shader_version; ++ + vsir_validate_register(ctx, &dst->reg); + + if (dst->write_mask & ~VKD3DSP_WRITEMASK_ALL) +@@ -9913,7 +10593,8 @@ static void vsir_validate_dst_param(struct validation_context *ctx, default: validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6082,7 +10039,7 @@ index 23e059a3490..29bf62709eb 100644 break; } -@@ -9932,7 +10198,8 @@ static void vsir_validate_dst_param(struct validation_context *ctx, +@@ -9932,7 +10613,8 @@ static void vsir_validate_dst_param(struct validation_context *ctx, case 15: if (dst->reg.data_type != VSIR_DATA_F32) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6092,7 +10049,36 @@ index 23e059a3490..29bf62709eb 100644 break; default: -@@ -10070,7 +10337,8 @@ static void vsir_validate_src_param(struct validation_context *ctx, +@@ -9999,6 +10681,11 @@ static void vsir_validate_dst_param(struct validation_context *ctx, + vsir_validate_io_dst_param(ctx, dst); + break; + ++ case VKD3DSPR_TEXTURE: ++ if (vkd3d_shader_ver_ge(version, 1, 4)) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "Texture registers cannot be written in version %u.%u.", version->major, version->minor); ++ + default: + break; + } +@@ -10062,6 +10749,16 @@ static void vsir_validate_src_param(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source of dimension %u has invalid swizzle %#x.", + src->reg.dimension, src->swizzle); + ++ if (src->reg.dimension == VSIR_DIMENSION_VEC4 && src->reg.type == VKD3DSPR_IMMCONST ++ && src->swizzle != VKD3D_SHADER_NO_SWIZZLE) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, ++ "Immediate constant source has invalid swizzle %#x.", src->swizzle); ++ ++ if (src->reg.dimension == VSIR_DIMENSION_VEC4 && src->reg.type == VKD3DSPR_IMMCONST64 ++ && src->swizzle != VKD3D_SHADER_SWIZZLE(X, Y, X, X)) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, ++ "Immediate constant source has invalid swizzle %#x.", src->swizzle); ++ + if (src->modifiers >= VKD3DSPSM_COUNT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", + src->modifiers); +@@ -10070,7 +10767,8 @@ static void vsir_validate_src_param(struct validation_context *ctx, { if (!(src_modifier_data[src->modifiers].data_type_mask & (1u << src->reg.data_type))) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, @@ -6102,7 +10088,7 @@ index 23e059a3490..29bf62709eb 100644 } switch (src->reg.type) -@@ -10722,7 +10990,7 @@ static void vsir_validate_hull_shader_phase(struct validation_context *ctx, +@@ -10722,7 +11420,7 @@ static void vsir_validate_hull_shader_phase(struct validation_context *ctx, static void vsir_validate_elementwise_operation(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction, const bool types[VSIR_DATA_TYPE_COUNT]) { @@ -6111,7 +10097,7 @@ index 23e059a3490..29bf62709eb 100644 unsigned int i; if (instruction->dst_count < 1) -@@ -10735,16 +11003,18 @@ static void vsir_validate_elementwise_operation(struct validation_context *ctx, +@@ -10735,16 +11433,18 @@ static void vsir_validate_elementwise_operation(struct validation_context *ctx, if (!types[dst_data_type]) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6135,7 +10121,34 @@ index 23e059a3490..29bf62709eb 100644 vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); } } -@@ -10801,7 +11071,7 @@ static void vsir_validate_logic_elementwise_operation(struct validation_context +@@ -10777,6 +11477,7 @@ static void vsir_validate_integer_elementwise_operation(struct validation_contex + static const bool types[VSIR_DATA_TYPE_COUNT] = + { + [VSIR_DATA_I32] = true, ++ [VSIR_DATA_I64] = true, + [VSIR_DATA_U32] = true, + [VSIR_DATA_U64] = true, + }; +@@ -10784,6 +11485,18 @@ static void vsir_validate_integer_elementwise_operation(struct validation_contex + vsir_validate_elementwise_operation(ctx, instruction, types); + } + ++static void vsir_validate_signed_integer_elementwise_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VSIR_DATA_I32] = true, ++ [VSIR_DATA_I64] = true, ++ }; ++ ++ vsir_validate_elementwise_operation(ctx, instruction, types); ++} ++ + static void vsir_validate_logic_elementwise_operation(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) + { +@@ -10801,7 +11514,7 @@ static void vsir_validate_logic_elementwise_operation(struct validation_context static void vsir_validate_comparison_operation(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction, const bool types[VSIR_DATA_TYPE_COUNT]) { @@ -6144,7 +10157,7 @@ index 23e059a3490..29bf62709eb 100644 unsigned int i; if (instruction->dst_count < 1) -@@ -10811,8 +11081,9 @@ static void vsir_validate_comparison_operation(struct validation_context *ctx, +@@ -10811,8 +11524,9 @@ static void vsir_validate_comparison_operation(struct validation_context *ctx, if (dst_data_type != VSIR_DATA_U32 && dst_data_type != VSIR_DATA_BOOL) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6156,7 +10169,7 @@ index 23e059a3490..29bf62709eb 100644 if (instruction->src_count == 0) return; -@@ -10824,16 +11095,18 @@ static void vsir_validate_comparison_operation(struct validation_context *ctx, +@@ -10824,16 +11538,18 @@ static void vsir_validate_comparison_operation(struct validation_context *ctx, if (!types[src_data_type]) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6181,7 +10194,26 @@ index 23e059a3490..29bf62709eb 100644 vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); } } -@@ -10891,19 +11164,21 @@ static void vsir_validate_cast_operation(struct validation_context *ctx, +@@ -10874,6 +11590,18 @@ static void vsir_validate_integer_comparison_operation(struct validation_context + vsir_validate_comparison_operation(ctx, instruction, types); + } + ++static void vsir_validate_signed_integer_comparison_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VSIR_DATA_I32] = true, ++ [VSIR_DATA_I64] = true, ++ }; ++ ++ vsir_validate_comparison_operation(ctx, instruction, types); ++} ++ + static void vsir_validate_cast_operation(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction, + const bool src_types[VSIR_DATA_TYPE_COUNT], const bool dst_types[VSIR_DATA_TYPE_COUNT]) +@@ -10891,45 +11619,72 @@ static void vsir_validate_cast_operation(struct validation_context *ctx, if (!src_types[src_data_type]) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6201,21 +10233,25 @@ index 23e059a3490..29bf62709eb 100644 } static void vsir_validate_shift_operation(struct validation_context *ctx, - const struct vkd3d_shader_instruction *instruction) +- const struct vkd3d_shader_instruction *instruction) ++ const struct vkd3d_shader_instruction *instruction, const bool types[VSIR_DATA_TYPE_COUNT]) { - enum vsir_data_type data_type; + enum vsir_data_type dst_data_type, src_data_type; - static const bool types[] = +- static const bool types[] = ++ static const bool shift_types[] = { -@@ -10912,24 +11187,27 @@ static void vsir_validate_shift_operation(struct validation_context *ctx, + [VSIR_DATA_I32] = true, ++ [VSIR_DATA_I64] = true, + [VSIR_DATA_U32] = true, [VSIR_DATA_U64] = true, }; - data_type = instruction->dst[0].reg.data_type; - if ((size_t)data_type >= ARRAY_SIZE(types) || !types[data_type]) + dst_data_type = instruction->dst[0].reg.data_type; -+ if ((size_t)dst_data_type >= ARRAY_SIZE(types) || !types[dst_data_type]) ++ if ((size_t)dst_data_type >= VSIR_DATA_TYPE_COUNT || !types[dst_data_type]) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, - "Invalid destination data type %#x for shift operation \"%s\" (%#x).", - data_type, vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); @@ -6237,17 +10273,80 @@ index 23e059a3490..29bf62709eb 100644 - data_type = instruction->src[1].reg.data_type; - if ((size_t)data_type >= ARRAY_SIZE(types) || !types[data_type]) + src_data_type = instruction->src[1].reg.data_type; -+ if ((size_t)src_data_type >= ARRAY_SIZE(types) || !types[src_data_type]) ++ if ((size_t)src_data_type >= ARRAY_SIZE(shift_types) || !shift_types[src_data_type]) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, - "Invalid source operand 1 data type %#x for shift operation \"%s\" (%#x).", - data_type, vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + "Invalid source operand 1 data type \"%s\" (%#x) for shift operation \"%s\" (%#x).", + vsir_data_type_get_name(src_data_type, ""), src_data_type, + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); ++} ++ ++static void vsir_validate_bem(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) ++{ ++ const struct vkd3d_shader_version *version = &ctx->program->shader_version; ++ ++ if (version->type != VKD3D_SHADER_TYPE_PIXEL) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "BEM cannot be used in shader type %#x.", version->type); ++ ++ if (version->major != 1 || version->minor != 4) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE, ++ "BEM cannot be used in version %u.%u.", version->major, version->minor); ++ ++ if (instruction->dst[0].write_mask != 0x3) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, ++ "Invalid BEM write mask %#x.", instruction->dst[0].write_mask); ++ ++ /* Strictly not an elementwise operation, but we expect all the arguments ++ * to be float. */ ++ vsir_validate_float_elementwise_operation(ctx, instruction); } static void vsir_validate_branch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) -@@ -11624,7 +11902,8 @@ static void vsir_validate_throw_invalid_dst_type_error_with_flags(struct validat +@@ -11490,14 +12245,39 @@ static void vsir_validate_ifc(struct validation_context *ctx, const struct vkd3d + vsir_validator_push_block(ctx, VSIR_OP_IF); + } + ++static void vsir_validate_ishl(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VSIR_DATA_I32] = true, ++ [VSIR_DATA_I64] = true, ++ [VSIR_DATA_U32] = true, ++ [VSIR_DATA_U64] = true, ++ }; ++ ++ vsir_validate_shift_operation(ctx, instruction, types); ++} ++ ++static void vsir_validate_ishr(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VSIR_DATA_I32] = true, ++ [VSIR_DATA_I64] = true, ++ }; ++ ++ vsir_validate_shift_operation(ctx, instruction, types); ++} ++ + static void vsir_validate_itof(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) + { + static const bool src_types[VSIR_DATA_TYPE_COUNT] = + { + [VSIR_DATA_BOOL] = true, + [VSIR_DATA_I32] = true, +- [VSIR_DATA_U32] = true, +- [VSIR_DATA_U64] = true, ++ [VSIR_DATA_I64] = true, + }; + static const bool dst_types[VSIR_DATA_TYPE_COUNT] = + { +@@ -11624,7 +12404,8 @@ static void vsir_validate_throw_invalid_dst_type_error_with_flags(struct validat enum vsir_data_type dst_data_type = instruction->dst[0].reg.data_type; validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, @@ -6257,8 +10356,62 @@ index 23e059a3490..29bf62709eb 100644 vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode, instruction->flags); } -@@ -11842,14 +12121,12 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ +@@ -11721,6 +12502,18 @@ static void vsir_validate_switch_monolithic(struct validation_context *ctx, + ctx->inside_block = false; + } + ++static void vsir_validate_ushr(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VSIR_DATA_U32] = true, ++ [VSIR_DATA_U64] = true, ++ }; ++ ++ vsir_validate_shift_operation(ctx, instruction, types); ++} ++ + struct vsir_validator_instruction_desc + { + unsigned int dst_param_count; +@@ -11736,6 +12529,7 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_AND] = {1, 2, vsir_validate_logic_elementwise_operation}, + [VSIR_OP_ASIN] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_ATAN] = {1, 1, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_BEM] = {1, 2, vsir_validate_bem}, + [VSIR_OP_BRANCH] = {0, ~0u, vsir_validate_branch}, + [VSIR_OP_DADD] = {1, 2, vsir_validate_double_elementwise_operation}, + [VSIR_OP_DCL_GS_INSTANCES] = {0, 0, vsir_validate_dcl_gs_instances}, +@@ -11800,17 +12594,17 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_IEQ] = {1, 2, vsir_validate_integer_comparison_operation}, + [VSIR_OP_IF] = {0, 1, vsir_validate_if}, + [VSIR_OP_IFC] = {0, 2, vsir_validate_ifc}, +- [VSIR_OP_IGE] = {1, 2, vsir_validate_integer_comparison_operation}, +- [VSIR_OP_ILT] = {1, 2, vsir_validate_integer_comparison_operation}, ++ [VSIR_OP_IGE] = {1, 2, vsir_validate_signed_integer_comparison_operation}, ++ [VSIR_OP_ILT] = {1, 2, vsir_validate_signed_integer_comparison_operation}, + [VSIR_OP_IMAD] = {1, 3, vsir_validate_integer_elementwise_operation}, +- [VSIR_OP_IMAX] = {1, 2, vsir_validate_integer_elementwise_operation}, +- [VSIR_OP_IMIN] = {1, 2, vsir_validate_integer_elementwise_operation}, ++ [VSIR_OP_IMAX] = {1, 2, vsir_validate_signed_integer_elementwise_operation}, ++ [VSIR_OP_IMIN] = {1, 2, vsir_validate_signed_integer_elementwise_operation}, + [VSIR_OP_INE] = {1, 2, vsir_validate_integer_comparison_operation}, + [VSIR_OP_INEG] = {1, 1, vsir_validate_integer_elementwise_operation}, + [VSIR_OP_IREM] = {1, 2, vsir_validate_integer_elementwise_operation}, + [VSIR_OP_ISFINITE] = {1, 1, vsir_validate_float_comparison_operation}, +- [VSIR_OP_ISHL] = {1, 2, vsir_validate_shift_operation}, +- [VSIR_OP_ISHR] = {1, 2, vsir_validate_shift_operation}, ++ [VSIR_OP_ISHL] = {1, 2, vsir_validate_ishl}, ++ [VSIR_OP_ISHR] = {1, 2, vsir_validate_ishr}, + [VSIR_OP_ISINF] = {1, 1, vsir_validate_float_comparison_operation}, + [VSIR_OP_ISNAN] = {1, 1, vsir_validate_float_comparison_operation}, + [VSIR_OP_ITOF] = {1, 1, vsir_validate_itof}, +@@ -11840,16 +12634,15 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_SAMPLE_INFO] = {1, 1, vsir_validate_sample_info}, + [VSIR_OP_SWITCH] = {0, 1, vsir_validate_switch}, [VSIR_OP_SWITCH_MONOLITHIC] = {0, ~0u, vsir_validate_switch_monolithic}, ++ [VSIR_OP_USHR] = {1, 2, vsir_validate_ushr}, }; -static void vsir_validate_instruction(struct validation_context *ctx) @@ -6274,7 +10427,7 @@ index 23e059a3490..29bf62709eb 100644 for (i = 0; i < instruction->dst_count; ++i) vsir_validate_dst_param(ctx, &instruction->dst[i]); -@@ -11927,7 +12204,7 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c +@@ -11927,7 +12720,7 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c { .message_context = message_context, .program = program, @@ -6283,7 +10436,7 @@ index 23e059a3490..29bf62709eb 100644 .status = VKD3D_OK, .phase = VSIR_OP_INVALID, .invalid_instruction_idx = true, -@@ -11938,6 +12215,8 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c +@@ -11938,6 +12731,8 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c .inner_tess_idxs[0] = ~0u, .inner_tess_idxs[1] = ~0u, }; @@ -6292,7 +10445,7 @@ index 23e059a3490..29bf62709eb 100644 unsigned int i; if (!(config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)) -@@ -12046,11 +12325,17 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c +@@ -12046,11 +12841,17 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c ctx.invalid_instruction_idx = false; @@ -6313,7 +10466,7 @@ index 23e059a3490..29bf62709eb 100644 if (ctx.depth != 0) validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "%zu nested blocks were not closed.", ctx.depth); -@@ -12113,14 +12398,9 @@ static void vsir_transform_( +@@ -12113,14 +12914,9 @@ static void vsir_transform_( enum vkd3d_result vsir_program_transform_early(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) { @@ -6331,7 +10484,7 @@ index 23e059a3490..29bf62709eb 100644 /* For vsir_program_ensure_diffuse(). */ if (program->shader_version.major <= 2) -@@ -12138,15 +12418,9 @@ enum vkd3d_result vsir_program_transform_early(struct vsir_program *program, uin +@@ -12138,18 +12934,18 @@ enum vkd3d_result vsir_program_transform_early(struct vsir_program *program, uin enum vkd3d_result vsir_program_lower_d3dbc(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) { @@ -6347,9 +10500,18 @@ index 23e059a3490..29bf62709eb 100644 + vsir_transformation_context_init(&ctx, program, config_flags, compile_info, message_context); vsir_transform(&ctx, vsir_program_lower_d3dbc_instructions); ++ if (program->shader_version.major == 1 && program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ++ { ++ if (program->shader_version.minor < 4) ++ vsir_transform(&ctx, vsir_program_lower_texture_writes); ++ vsir_transform(&ctx, vsir_program_normalise_ps1_output); -@@ -12160,15 +12434,9 @@ enum vkd3d_result vsir_program_lower_d3dbc(struct vsir_program *program, uint64_ ++ } + + if (TRACE_ON()) + vsir_program_trace(program); +@@ -12160,15 +12956,9 @@ enum vkd3d_result vsir_program_lower_d3dbc(struct vsir_program *program, uint64_ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) { @@ -6368,10 +10530,63 @@ index 23e059a3490..29bf62709eb 100644 if (program->shader_version.major >= 6) diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index c6e048adb20..9150e77e2c6 100644 +index c6e048adb20..8a89dcabd5e 100644 --- a/libs/vkd3d/libs/vkd3d-shader/msl.c +++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -943,8 +943,8 @@ static void msl_print_texel_offset(struct vkd3d_string_buffer *buffer, struct ms +@@ -167,6 +167,7 @@ static void msl_print_register_datatype(struct vkd3d_string_buffer *buffer, + case VSIR_DATA_F32: + vkd3d_string_buffer_printf(buffer, "f"); + break; ++ case VSIR_DATA_BOOL: + case VSIR_DATA_I32: + vkd3d_string_buffer_printf(buffer, "i"); + break; +@@ -485,6 +486,22 @@ static enum msl_data_type msl_print_register_name(struct vkd3d_string_buffer *bu + vkd3d_string_buffer_printf(buffer, "o_mask"); + return MSL_DATA_UNION; + ++ case VKD3DSPR_THREADID: ++ vkd3d_string_buffer_printf(buffer, "v_thread_id"); ++ return MSL_DATA_UNION; ++ ++ case VKD3DSPR_THREADGROUPID: ++ vkd3d_string_buffer_printf(buffer, "v_thread_group_id"); ++ return MSL_DATA_UNION; ++ ++ case VKD3DSPR_LOCALTHREADID: ++ vkd3d_string_buffer_printf(buffer, "v_local_thread_id"); ++ return MSL_DATA_UNION; ++ ++ case VKD3DSPR_LOCALTHREADINDEX: ++ vkd3d_string_buffer_printf(buffer, "v_local_thread_index"); ++ return MSL_DATA_UNION; ++ + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled register type %#x.", reg->type); +@@ -799,6 +816,7 @@ static void msl_relop(struct msl_generator *gen, const struct vkd3d_shader_instr + static void msl_cast(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *constructor) + { + unsigned int component_count; ++ const char *negate; + struct msl_src src; + struct msl_dst dst; + uint32_t mask; +@@ -806,10 +824,11 @@ static void msl_cast(struct msl_generator *gen, const struct vkd3d_shader_instru + mask = msl_dst_init(&dst, gen, ins, &ins->dst[0]); + msl_src_init(&src, gen, &ins->src[0], mask); + ++ negate = ins->opcode == VSIR_OP_UTOF && data_type_is_bool(ins->src[0].reg.data_type) ? "-" : ""; + if ((component_count = vsir_write_mask_component_count(mask)) > 1) +- msl_print_assignment(gen, &dst, "%s%u(%s)", constructor, component_count, src.str->buffer); ++ msl_print_assignment(gen, &dst, "%s%u(%s%s)", constructor, component_count, negate, src.str->buffer); + else +- msl_print_assignment(gen, &dst, "%s(%s)", constructor, src.str->buffer); ++ msl_print_assignment(gen, &dst, "%s(%s%s)", constructor, negate, src.str->buffer); + + msl_src_cleanup(&src, &gen->string_buffers); + msl_dst_cleanup(&dst, &gen->string_buffers); +@@ -943,8 +962,8 @@ static void msl_print_texel_offset(struct vkd3d_string_buffer *buffer, struct ms static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) { @@ -6381,7 +10596,7 @@ index c6e048adb20..9150e77e2c6 100644 const struct vkd3d_shader_descriptor_info1 *descriptor; const struct vkd3d_shader_descriptor_binding *binding; enum vkd3d_shader_resource_type resource_type; -@@ -969,6 +969,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct +@@ -969,6 +988,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct { resource_type = descriptor->resource_type; resource_space = descriptor->register_space; @@ -6389,7 +10604,7 @@ index c6e048adb20..9150e77e2c6 100644 data_type = descriptor->resource_data_type; } else -@@ -977,6 +978,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct +@@ -977,6 +997,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct "Internal compiler error: Undeclared resource descriptor %u.", resource_id); resource_space = 0; resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; @@ -6397,7 +10612,7 @@ index c6e048adb20..9150e77e2c6 100644 data_type = VSIR_DATA_F32; } -@@ -988,6 +990,16 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct +@@ -988,6 +1009,16 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, "Texel fetches from resource type %#x are not supported.", resource_type); @@ -6414,7 +10629,7 @@ index c6e048adb20..9150e77e2c6 100644 if (!(resource_type_info = msl_get_resource_type_info(resource_type))) { msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -@@ -1030,6 +1042,10 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct +@@ -1030,6 +1061,10 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct vkd3d_string_buffer_printf(read, ", "); if (ins->opcode != VSIR_OP_LD2DMS) msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VSIR_DATA_U32); @@ -6425,7 +10640,7 @@ index c6e048adb20..9150e77e2c6 100644 else msl_print_src_with_type(read, gen, &ins->src[2], VKD3DSP_WRITEMASK_0, VSIR_DATA_U32); } -@@ -1294,6 +1310,11 @@ static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_sh +@@ -1294,6 +1329,11 @@ static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_sh data_type = VSIR_DATA_F32; } @@ -6437,7 +10652,7 @@ index c6e048adb20..9150e77e2c6 100644 if (!(resource_type_info = msl_get_resource_type_info(resource_type))) { msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -@@ -1414,6 +1435,12 @@ static void msl_ret(struct msl_generator *gen, const struct vkd3d_shader_instruc +@@ -1414,6 +1454,12 @@ static void msl_ret(struct msl_generator *gen, const struct vkd3d_shader_instruc static void msl_dcl_indexable_temp(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) { const char *type = ins->declaration.indexable_temp.component_count == 4 ? "vkd3d_vec4" : "vkd3d_scalar"; @@ -6450,15 +10665,120 @@ index c6e048adb20..9150e77e2c6 100644 msl_print_indent(gen->buffer, gen->indent); vkd3d_string_buffer_printf(gen->buffer, "%s x%u[%u];\n", type, ins->declaration.indexable_temp.register_idx, -@@ -1516,6 +1543,7 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d +@@ -1426,6 +1472,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + + switch (ins->opcode) + { ++ case VSIR_OP_ACOS: ++ msl_intrinsic(gen, ins, "acos"); ++ break; + case VSIR_OP_ADD: + case VSIR_OP_IADD: + msl_binop(gen, ins, "+"); +@@ -1433,6 +1482,12 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + case VSIR_OP_AND: + msl_binop(gen, ins, "&"); + break; ++ case VSIR_OP_ASIN: ++ msl_intrinsic(gen, ins, "asin"); ++ break; ++ case VSIR_OP_ATAN: ++ msl_intrinsic(gen, ins, "atan"); ++ break; + case VSIR_OP_BREAK: + msl_break(gen); + break; +@@ -1442,6 +1497,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + case VSIR_OP_CONTINUE: + msl_continue(gen); + break; ++ case VSIR_OP_COS: ++ msl_intrinsic(gen, ins, "cos"); ++ break; + case VSIR_OP_DCL_INDEXABLE_TEMP: + msl_dcl_indexable_temp(gen, ins); + break; +@@ -1497,6 +1555,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + case VSIR_OP_FRC: + msl_intrinsic(gen, ins, "fract"); + break; ++ case VSIR_OP_FREM: ++ msl_intrinsic(gen, ins, "fmod"); ++ break; + case VSIR_OP_FTOI: + msl_cast(gen, ins, "int"); + break; +@@ -1516,8 +1577,18 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d break; case VSIR_OP_GEO: case VSIR_OP_IGE: + case VSIR_OP_UGE: msl_relop(gen, ins, ">="); break; ++ case VSIR_OP_HCOS: ++ msl_intrinsic(gen, ins, "cosh"); ++ break; ++ case VSIR_OP_HSIN: ++ msl_intrinsic(gen, ins, "sinh"); ++ break; ++ case VSIR_OP_HTAN: ++ msl_intrinsic(gen, ins, "tanh"); ++ break; case VSIR_OP_IF: -@@ -1995,6 +2023,7 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) + msl_if(gen, ins); + break; +@@ -1602,6 +1673,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + case VSIR_OP_RSQ: + msl_intrinsic(gen, ins, "rsqrt"); + break; ++ case VSIR_OP_SIN: ++ msl_intrinsic(gen, ins, "sin"); ++ break; + case VSIR_OP_SQRT: + msl_intrinsic(gen, ins, "sqrt"); + break; +@@ -1611,6 +1685,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + case VSIR_OP_SWITCH: + msl_switch(gen, ins); + break; ++ case VSIR_OP_TAN: ++ msl_intrinsic(gen, ins, "tan"); ++ break; + case VSIR_OP_XOR: + msl_binop(gen, ins, "^"); + break; +@@ -1951,6 +2028,30 @@ static void msl_generate_entrypoint_prologue(struct msl_generator *gen) + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, ";\n"); + } ++ ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADID)) ++ { ++ msl_print_indent(gen->buffer, 1); ++ vkd3d_string_buffer_printf(buffer, "v_thread_id.u = uint4(thread_id, 0u);\n"); ++ } ++ ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADGROUPID)) ++ { ++ msl_print_indent(gen->buffer, 1); ++ vkd3d_string_buffer_printf(buffer, "v_thread_group_id.u = uint4(thread_group_id, 0u);\n"); ++ } ++ ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_LOCALTHREADID)) ++ { ++ msl_print_indent(gen->buffer, 1); ++ vkd3d_string_buffer_printf(buffer, "v_local_thread_id.u = uint4(local_thread_id, 0u);\n"); ++ } ++ ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_LOCALTHREADINDEX)) ++ { ++ msl_print_indent(gen->buffer, 1); ++ vkd3d_string_buffer_printf(buffer, "v_local_thread_index.u = uint4(local_thread_index, 0u, 0u, 0u);\n"); ++ } + } + + static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) +@@ -1995,6 +2096,7 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) static void msl_generate_entrypoint(struct msl_generator *gen) { enum vkd3d_shader_type type = gen->program->shader_version.type; @@ -6466,7 +10786,7 @@ index c6e048adb20..9150e77e2c6 100644 switch (type) { -@@ -2006,13 +2035,21 @@ static void msl_generate_entrypoint(struct msl_generator *gen) +@@ -2006,13 +2108,21 @@ static void msl_generate_entrypoint(struct msl_generator *gen) vkd3d_string_buffer_printf(gen->buffer, "[[early_fragment_tests]]\n"); vkd3d_string_buffer_printf(gen->buffer, "fragment "); break; @@ -6489,7 +10809,67 @@ index c6e048adb20..9150e77e2c6 100644 if (gen->program->descriptors.descriptor_count) { -@@ -2054,7 +2091,9 @@ static void msl_generate_entrypoint(struct msl_generator *gen) +@@ -2028,6 +2138,30 @@ static void msl_generate_entrypoint(struct msl_generator *gen) + vkd3d_string_buffer_printf(gen->buffer, "uint vertex_id [[vertex_id]],\n"); + } + ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADID)) ++ { ++ msl_print_indent(gen->buffer, 2); ++ vkd3d_string_buffer_printf(gen->buffer, "uint3 thread_id [[thread_position_in_grid]],\n"); ++ } ++ ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADGROUPID)) ++ { ++ msl_print_indent(gen->buffer, 2); ++ vkd3d_string_buffer_printf(gen->buffer, "uint3 thread_group_id [[threadgroup_position_in_grid]],\n"); ++ } ++ ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_LOCALTHREADID)) ++ { ++ msl_print_indent(gen->buffer, 2); ++ vkd3d_string_buffer_printf(gen->buffer, "uint3 local_thread_id [[thread_position_in_threadgroup]],\n"); ++ } ++ ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_LOCALTHREADINDEX)) ++ { ++ msl_print_indent(gen->buffer, 2); ++ vkd3d_string_buffer_printf(gen->buffer, "uint local_thread_index [[thread_index_in_threadgroup]],\n"); ++ } ++ + msl_print_indent(gen->buffer, 2); + vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_in input [[stage_in]])\n{\n", gen->prefix); + +@@ -2037,6 +2171,14 @@ static void msl_generate_entrypoint(struct msl_generator *gen) + vkd3d_string_buffer_printf(gen->buffer, " vkd3d_%s_out output;\n", gen->prefix); + if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) + vkd3d_string_buffer_printf(gen->buffer, " vkd3d_scalar o_mask;\n"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADID)) ++ vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 v_thread_id;\n"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADGROUPID)) ++ vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 v_thread_group_id;\n"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_LOCALTHREADID)) ++ vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 v_local_thread_id;\n"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_LOCALTHREADINDEX)) ++ vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 v_local_thread_index;\n"); + vkd3d_string_buffer_printf(gen->buffer, "\n"); + + msl_generate_entrypoint_prologue(gen); +@@ -2048,13 +2190,23 @@ static void msl_generate_entrypoint(struct msl_generator *gen) + vkd3d_string_buffer_printf(gen->buffer, ", output.shader_out_depth"); + if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) + vkd3d_string_buffer_printf(gen->buffer, ", o_mask"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADID)) ++ vkd3d_string_buffer_printf(gen->buffer, ", v_thread_id"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADGROUPID)) ++ vkd3d_string_buffer_printf(gen->buffer, ", v_thread_group_id"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_LOCALTHREADID)) ++ vkd3d_string_buffer_printf(gen->buffer, ", v_local_thread_id"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_LOCALTHREADINDEX)) ++ vkd3d_string_buffer_printf(gen->buffer, ", v_local_thread_index"); + if (gen->program->descriptors.descriptor_count) + vkd3d_string_buffer_printf(gen->buffer, ", descriptors"); + vkd3d_string_buffer_printf(gen->buffer, ");\n\n"); msl_generate_entrypoint_epilogue(gen); @@ -6500,6 +10880,21 @@ index c6e048adb20..9150e77e2c6 100644 } static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader_code *out) +@@ -2119,6 +2271,14 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader + vkd3d_string_buffer_printf(gen->buffer, ", thread float &o_depth"); + if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) + vkd3d_string_buffer_printf(gen->buffer, ", thread vkd3d_scalar &o_mask"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADID)) ++ vkd3d_string_buffer_printf(gen->buffer, ", thread vkd3d_vec4 &v_thread_id"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADGROUPID)) ++ vkd3d_string_buffer_printf(gen->buffer, ", thread vkd3d_vec4 &v_thread_group_id"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_LOCALTHREADID)) ++ vkd3d_string_buffer_printf(gen->buffer, ", thread vkd3d_vec4 &v_local_thread_id"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_LOCALTHREADINDEX)) ++ vkd3d_string_buffer_printf(gen->buffer, ", thread vkd3d_vec4 &v_local_thread_index"); + if (gen->program->descriptors.descriptor_count) + vkd3d_string_buffer_printf(gen->buffer, ", constant descriptor *descriptors"); + vkd3d_string_buffer_printf(gen->buffer, ")\n{\n"); diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l index a8c0db358bc..f9b1d67ac36 100644 --- a/libs/vkd3d/libs/vkd3d-shader/preproc.l @@ -6540,7 +10935,7 @@ index a8c0db358bc..f9b1d67ac36 100644 fail: diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 97c0d0e73a8..8bc851f9c5b 100644 +index 97c0d0e73a8..9c5f71ee11f 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -2518,7 +2518,7 @@ static uint32_t vkd3d_spirv_build_op_glsl_std450_nclamp(struct vkd3d_spirv_build @@ -6588,47 +10983,230 @@ index 97c0d0e73a8..8bc851f9c5b 100644 } static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, -@@ -3656,7 +3657,7 @@ static uint32_t spirv_compiler_get_constant(struct spirv_compiler *compiler, +@@ -2794,7 +2795,7 @@ struct vkd3d_symbol_register_data + { + SpvStorageClass storage_class; + uint32_t member_idx; +- enum vkd3d_shader_component_type component_type; ++ enum vsir_data_type data_type; + unsigned int write_mask; + unsigned int structure_stride; + unsigned int binding_base_idx; +@@ -2804,7 +2805,7 @@ struct vkd3d_symbol_register_data + struct vkd3d_symbol_resource_data + { + struct vkd3d_shader_register_range range; +- enum vkd3d_shader_component_type sampled_type; ++ enum vsir_data_type sampled_type; + uint32_t type_id; + const struct vkd3d_spirv_resource_type *resource_type_info; + unsigned int structure_stride; +@@ -2919,15 +2920,14 @@ static void vkd3d_symbol_make_io(struct vkd3d_symbol *symbol, + symbol->key.reg.idx = index; + } + +-static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol, +- uint32_t val_id, SpvStorageClass storage_class, +- enum vkd3d_shader_component_type component_type, uint32_t write_mask) ++static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol, uint32_t val_id, ++ SpvStorageClass storage_class, enum vsir_data_type data_type, uint32_t write_mask) + { + symbol->id = val_id; + symbol->descriptor_array = NULL; + symbol->info.reg.storage_class = storage_class; + symbol->info.reg.member_idx = 0; +- symbol->info.reg.component_type = component_type; ++ symbol->info.reg.data_type = data_type; + symbol->info.reg.write_mask = write_mask; + symbol->info.reg.structure_stride = 0; + symbol->info.reg.binding_base_idx = 0; +@@ -3253,6 +3253,14 @@ static struct spirv_compiler *spirv_compiler_create(struct vsir_program *program + compiler->features = option->value; + break; + ++ case VKD3D_SHADER_COMPILE_OPTION_PACK_MATRIX_ORDER: ++ case VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY: ++ case VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT: ++ case VKD3D_SHADER_COMPILE_OPTION_WARN_IMPLICIT_TRUNCATION: ++ case VKD3D_SHADER_COMPILE_OPTION_INCLUDE_EMPTY_BUFFERS_IN_EFFECTS: ++ /* Explicitly ignored for this target. */ ++ break; ++ + default: + WARN("Ignoring unrecognised option %#x with value %#x.\n", option->name, option->value); + break; +@@ -3649,122 +3657,128 @@ static const struct vkd3d_symbol *spirv_compiler_put_symbol(struct spirv_compile + } + + static uint32_t spirv_compiler_get_constant(struct spirv_compiler *compiler, +- enum vkd3d_shader_component_type component_type, unsigned int component_count, const uint32_t *values) ++ enum vsir_data_type data_type, unsigned int component_count, const uint32_t *values) + { + uint32_t type_id, scalar_type_id, component_ids[VKD3D_VEC4_SIZE]; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; unsigned int i; VKD3D_ASSERT(0 < component_count && component_count <= VKD3D_VEC4_SIZE); - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); ++ type_id = spirv_get_type_id(builder, data_type, component_count); - switch (component_type) +- switch (component_type) ++ switch (data_type) { -@@ -3683,7 +3684,7 @@ static uint32_t spirv_compiler_get_constant(struct spirv_compiler *compiler, +- case VKD3D_SHADER_COMPONENT_UINT: +- case VKD3D_SHADER_COMPONENT_INT: +- case VKD3D_SHADER_COMPONENT_FLOAT: +- break; +- case VKD3D_SHADER_COMPONENT_BOOL: ++ case VSIR_DATA_BOOL: + if (component_count == 1) + return vkd3d_spirv_get_op_constant_bool(builder, type_id, *values); +- FIXME("Unsupported vector of bool.\n"); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, + "Vectors of bool type are not supported."); + return vkd3d_spirv_get_op_undef(builder, type_id); ++ ++ case VSIR_DATA_F16: ++ case VSIR_DATA_F32: ++ case VSIR_DATA_I32: ++ case VSIR_DATA_U16: ++ case VSIR_DATA_U32: ++ case VSIR_DATA_SNORM: ++ case VSIR_DATA_UNORM: ++ break; ++ + default: + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, +- "Unhandled component_type %#x.", component_type); ++ "Unhandled data type \"%s\" (%#x).", ++ vsir_data_type_get_name(data_type, ""), data_type); + return vkd3d_spirv_get_op_undef(builder, type_id); } - else + + if (component_count == 1) +- { + return vkd3d_spirv_get_op_constant(builder, type_id, *values); +- } +- else ++ ++ scalar_type_id = spirv_get_type_id(builder, data_type, 1); ++ for (i = 0; i < component_count; ++i) { - scalar_type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -+ scalar_type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); - for (i = 0; i < component_count; ++i) - component_ids[i] = vkd3d_spirv_get_op_constant(builder, scalar_type_id, values[i]); - return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); -@@ -3698,9 +3699,10 @@ static uint32_t spirv_compiler_get_constant64(struct spirv_compiler *compiler, +- for (i = 0; i < component_count; ++i) +- component_ids[i] = vkd3d_spirv_get_op_constant(builder, scalar_type_id, values[i]); +- return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); ++ component_ids[i] = vkd3d_spirv_get_op_constant(builder, scalar_type_id, values[i]); + } ++ ++ return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); + } + + static uint32_t spirv_compiler_get_constant64(struct spirv_compiler *compiler, +- enum vkd3d_shader_component_type component_type, unsigned int component_count, const uint64_t *values) ++ enum vsir_data_type data_type, unsigned int component_count, const uint64_t *values) + { + uint32_t type_id, scalar_type_id, component_ids[VKD3D_DVEC2_SIZE]; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; unsigned int i; VKD3D_ASSERT(0 < component_count && component_count <= VKD3D_DVEC2_SIZE); - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); ++ type_id = spirv_get_type_id(builder, data_type, component_count); - if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE && component_type != VKD3D_SHADER_COMPONENT_UINT64) -+ if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE && component_type != VKD3D_SHADER_COMPONENT_INT64 -+ && component_type != VKD3D_SHADER_COMPONENT_UINT64) ++ if (data_type != VSIR_DATA_F64 && data_type != VSIR_DATA_I64 && data_type != VSIR_DATA_U64) { - FIXME("Unhandled component_type %#x.\n", component_type); +- FIXME("Unhandled component_type %#x.\n", component_type); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, ++ "Unhandled data type \"%s\" (%#x).", ++ vsir_data_type_get_name(data_type, ""), data_type); return vkd3d_spirv_get_op_undef(builder, type_id); -@@ -3712,7 +3714,7 @@ static uint32_t spirv_compiler_get_constant64(struct spirv_compiler *compiler, } - else + + if (component_count == 1) +- { + return vkd3d_spirv_get_op_constant64(builder, type_id, *values); +- } +- else ++ ++ scalar_type_id = spirv_get_type_id(builder, data_type, 1); ++ for (i = 0; i < component_count; ++i) { - scalar_type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -+ scalar_type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); - for (i = 0; i < component_count; ++i) - component_ids[i] = vkd3d_spirv_get_op_constant64(builder, scalar_type_id, values[i]); - return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); -@@ -3772,9 +3774,7 @@ static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compil +- for (i = 0; i < component_count; ++i) +- component_ids[i] = vkd3d_spirv_get_op_constant64(builder, scalar_type_id, values[i]); +- return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); ++ component_ids[i] = vkd3d_spirv_get_op_constant64(builder, scalar_type_id, values[i]); + } ++ ++ return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); + } + +-static uint32_t spirv_compiler_get_constant_uint(struct spirv_compiler *compiler, +- uint32_t value) ++static uint32_t spirv_compiler_get_constant_uint(struct spirv_compiler *compiler, uint32_t value) + { +- return spirv_compiler_get_constant(compiler, VKD3D_SHADER_COMPONENT_UINT, 1, &value); ++ return spirv_compiler_get_constant(compiler, VSIR_DATA_U32, 1, &value); + } + +-static uint32_t spirv_compiler_get_constant_float(struct spirv_compiler *compiler, +- float value) ++static uint32_t spirv_compiler_get_constant_float(struct spirv_compiler *compiler, float value) + { +- return spirv_compiler_get_constant(compiler, VKD3D_SHADER_COMPONENT_FLOAT, 1, (uint32_t *)&value); ++ return spirv_compiler_get_constant(compiler, VSIR_DATA_F32, 1, (uint32_t *)&value); + } + + static uint32_t spirv_compiler_get_constant_vector(struct spirv_compiler *compiler, +- enum vkd3d_shader_component_type component_type, unsigned int component_count, uint32_t value) ++ enum vsir_data_type data_type, unsigned int component_count, uint32_t value) + { + const uint32_t values[] = {value, value, value, value}; +- return spirv_compiler_get_constant(compiler, component_type, component_count, values); ++ ++ return spirv_compiler_get_constant(compiler, data_type, component_count, values); + } + + static uint32_t spirv_compiler_get_constant_uint_vector(struct spirv_compiler *compiler, + uint32_t value, unsigned int component_count) + { +- return spirv_compiler_get_constant_vector(compiler, VKD3D_SHADER_COMPONENT_UINT, component_count, value); ++ return spirv_compiler_get_constant_vector(compiler, VSIR_DATA_U32, component_count, value); + } + + static uint32_t spirv_compiler_get_constant_float_vector(struct spirv_compiler *compiler, + float value, unsigned int component_count) + { + const float values[] = {value, value, value, value}; +- return spirv_compiler_get_constant(compiler, VKD3D_SHADER_COMPONENT_FLOAT, +- component_count, (const uint32_t *)values); ++ ++ return spirv_compiler_get_constant(compiler, VSIR_DATA_F32, component_count, (const uint32_t *)values); + } + + static uint32_t spirv_compiler_get_constant_double_vector(struct spirv_compiler *compiler, + double value, unsigned int component_count) + { + const double values[] = {value, value}; +- return spirv_compiler_get_constant64(compiler, VKD3D_SHADER_COMPONENT_DOUBLE, +- component_count, (const uint64_t *)values); ++ ++ return spirv_compiler_get_constant64(compiler, VSIR_DATA_F64, component_count, (const uint64_t *)values); + } + + static uint32_t spirv_compiler_get_constant_uint64_vector(struct spirv_compiler *compiler, + uint64_t value, unsigned int component_count) + { + const uint64_t values[] = {value, value}; +- return spirv_compiler_get_constant64(compiler, VKD3D_SHADER_COMPONENT_UINT64, component_count, values); ++ ++ return spirv_compiler_get_constant64(compiler, VSIR_DATA_U64, component_count, values); + } + + static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compiler, +@@ -3772,9 +3786,7 @@ static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compil { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6639,7 +11217,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 } static uint32_t spirv_compiler_get_type_id_for_dst(struct spirv_compiler *compiler, -@@ -3901,7 +3901,7 @@ static uint32_t spirv_compiler_emit_array_variable(struct spirv_compiler *compil +@@ -3901,7 +3913,7 @@ static uint32_t spirv_compiler_emit_array_variable(struct spirv_compiler *compil uint32_t type_id, length_id, ptr_type_id; unsigned int i; @@ -6648,7 +11226,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 for (i = 0; i < length_count; ++i) { if (!array_lengths[i]) -@@ -4000,8 +4000,8 @@ static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compile +@@ -4000,8 +4012,8 @@ static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compile info = get_spec_constant_info(name); default_value = info ? info->default_value.u : 0; @@ -6659,7 +11237,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 for (unsigned int i = 0; i < component_count; ++i) { -@@ -4050,7 +4050,7 @@ static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compi +@@ -4050,7 +4062,7 @@ static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compi unsigned int index = parameter - compiler->program->parameters; uint32_t type_id, ptr_id, ptr_type_id; @@ -6668,16 +11246,63 @@ index 97c0d0e73a8..8bc851f9c5b 100644 ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); ptr_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, compiler->spirv_parameter_info[index].buffer_id, -@@ -4114,7 +4114,7 @@ static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *comp +@@ -4087,8 +4099,8 @@ static uint32_t spirv_compiler_emit_shader_parameter(struct spirv_compiler *comp + type, component_count, name, parameter->data_type); + + if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) +- return spirv_compiler_get_constant(compiler, vkd3d_component_type_from_data_type(type), +- component_count, (const uint32_t *)¶meter->u.immediate_constant); ++ return spirv_compiler_get_constant(compiler, type, component_count, ++ (const uint32_t *)¶meter->u.immediate_constant); + + if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT) + return spirv_compiler_get_spec_constant(compiler, name, +@@ -4104,32 +4116,32 @@ default_parameter: + } + + static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *compiler, +- enum vkd3d_shader_component_type component_type, unsigned int component_count, +- uint32_t val_id, unsigned int val_component_idx, unsigned int val_component_count) ++ enum vsir_data_type data_type, unsigned int component_count, uint32_t val_id, ++ unsigned int val_component_idx, unsigned int val_component_count) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t components[VKD3D_VEC4_SIZE]; +- uint32_t type_id, result_id; ++ uint32_t type_id; + unsigned int i; VKD3D_ASSERT(val_component_idx < val_component_count); - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); ++ type_id = spirv_get_type_id(builder, data_type, component_count); if (val_component_count == 1) { for (i = 0; i < component_count; ++i) -@@ -4147,10 +4147,11 @@ static uint32_t spirv_compiler_emit_register_addressing(struct spirv_compiler *c ++ { + components[i] = val_id; +- result_id = vkd3d_spirv_build_op_composite_construct(builder, +- type_id, components, component_count); ++ } ++ return vkd3d_spirv_build_op_composite_construct(builder, type_id, components, component_count); + } +- else ++ ++ for (i = 0; i < component_count; ++i) + { +- for (i = 0; i < component_count; ++i) +- components[i] = val_component_idx; +- result_id = vkd3d_spirv_build_op_vector_shuffle(builder, +- type_id, val_id, val_id, components, component_count); ++ components[i] = val_component_idx; + } +- return result_id; ++ ++ return vkd3d_spirv_build_op_vector_shuffle(builder, type_id, val_id, val_id, components, component_count); + } + + static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, +@@ -4147,10 +4159,11 @@ static uint32_t spirv_compiler_emit_register_addressing(struct spirv_compiler *c addr_id = spirv_compiler_emit_load_src(compiler, reg_index->rel_addr, VKD3DSP_WRITEMASK_0); if (reg_index->offset) { @@ -6692,7 +11317,43 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return addr_id; } -@@ -4296,7 +4297,7 @@ static uint32_t spirv_compiler_get_descriptor_index(struct spirv_compiler *compi +@@ -4159,7 +4172,7 @@ struct vkd3d_shader_register_info + uint32_t id; + const struct vkd3d_symbol *descriptor_array; + SpvStorageClass storage_class; +- enum vkd3d_shader_component_type component_type; ++ enum vsir_data_type data_type; + unsigned int write_mask; + uint32_t member_idx; + unsigned int structure_stride; +@@ -4182,7 +4195,7 @@ static bool spirv_compiler_get_register_info(struct spirv_compiler *compiler, + register_info->storage_class = SpvStorageClassPrivate; + register_info->descriptor_array = NULL; + register_info->member_idx = 0; +- register_info->component_type = VKD3D_SHADER_COMPONENT_FLOAT; ++ register_info->data_type = VSIR_DATA_F32; + register_info->write_mask = VKD3DSP_WRITEMASK_ALL; + register_info->structure_stride = 0; + register_info->binding_base_idx = 0; +@@ -4203,7 +4216,7 @@ static bool spirv_compiler_get_register_info(struct spirv_compiler *compiler, + memset(register_info, 0, sizeof(*register_info)); + register_info->id = ssa->id; + register_info->storage_class = SpvStorageClassMax; +- register_info->component_type = vkd3d_component_type_from_data_type(ssa->data_type); ++ register_info->data_type = ssa->data_type; + register_info->write_mask = ssa->write_mask; + return true; + } +@@ -4222,7 +4235,7 @@ static bool spirv_compiler_get_register_info(struct spirv_compiler *compiler, + register_info->descriptor_array = symbol->descriptor_array; + register_info->storage_class = symbol->info.reg.storage_class; + register_info->member_idx = symbol->info.reg.member_idx; +- register_info->component_type = symbol->info.reg.component_type; ++ register_info->data_type = symbol->info.reg.data_type; + register_info->write_mask = symbol->info.reg.write_mask; + register_info->structure_stride = symbol->info.reg.structure_stride; + register_info->binding_base_idx = symbol->info.reg.binding_base_idx; +@@ -4296,7 +4309,7 @@ static uint32_t spirv_compiler_get_descriptor_index(struct spirv_compiler *compi struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id, ptr_type_id, ptr_id, offset_id, index_ids[2]; @@ -6701,16 +11362,16 @@ index 97c0d0e73a8..8bc851f9c5b 100644 if (!(offset_id = compiler->descriptor_offset_ids[push_constant_index])) { index_ids[0] = compiler->descriptor_offsets_member_id; -@@ -4369,7 +4370,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp +@@ -4369,7 +4382,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp if (index_count) { component_count = vsir_write_mask_component_count(register_info->write_mask); - type_id = vkd3d_spirv_get_type_id(builder, register_info->component_type, component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, register_info->component_type, component_count); ++ type_id = spirv_get_type_id(builder, register_info->data_type, component_count); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, register_info->storage_class, type_id); register_info->id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, register_info->id, indexes, index_count); -@@ -4428,7 +4429,7 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, +@@ -4428,7 +4441,7 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, && (component_count == 1 || vkd3d_swizzle_is_equal(val_write_mask, swizzle, write_mask))) return val_id; @@ -6719,7 +11380,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 if (component_count == 1) { -@@ -4479,7 +4480,7 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil +@@ -4479,7 +4492,7 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(swizzle, i); } @@ -6728,7 +11389,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return vkd3d_spirv_build_op_vector_shuffle(builder, type_id, vector1_id, vector2_id, components, component_count); } -@@ -4494,10 +4495,11 @@ static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, +@@ -4494,10 +4507,11 @@ static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, VKD3D_ASSERT(!(condition & ~(VKD3D_SHADER_CONDITIONAL_OP_NZ | VKD3D_SHADER_CONDITIONAL_OP_Z))); @@ -6742,7 +11403,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 ? spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count) : spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); } -@@ -4510,7 +4512,8 @@ static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, +@@ -4510,7 +4524,8 @@ static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, true_id = spirv_compiler_get_constant_uint_vector(compiler, signedness ? 0xffffffff : 1, component_count); false_id = spirv_compiler_get_constant_uint_vector(compiler, 0, component_count); @@ -6752,7 +11413,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); } -@@ -4523,7 +4526,8 @@ static uint32_t spirv_compiler_emit_bool_to_int64(struct spirv_compiler *compile +@@ -4523,7 +4538,8 @@ static uint32_t spirv_compiler_emit_bool_to_int64(struct spirv_compiler *compile true_id = spirv_compiler_get_constant_uint64_vector(compiler, signedness ? UINT64_MAX : 1, component_count); false_id = spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count); @@ -6762,7 +11423,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); } -@@ -4535,7 +4539,8 @@ static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compile +@@ -4535,7 +4551,8 @@ static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compile true_id = spirv_compiler_get_constant_float_vector(compiler, signedness ? -1.0f : 1.0f, component_count); false_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count); @@ -6772,7 +11433,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); } -@@ -4547,7 +4552,8 @@ static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compil +@@ -4547,7 +4564,8 @@ static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compil true_id = spirv_compiler_get_constant_double_vector(compiler, signedness ? -1.0 : 1.0, component_count); false_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count); @@ -6782,7 +11443,27 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); } -@@ -4614,7 +4620,8 @@ static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, +@@ -4574,8 +4592,7 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile + } + } + +- return spirv_compiler_get_constant(compiler, +- vkd3d_component_type_from_data_type(reg->data_type), component_count, values); ++ return spirv_compiler_get_constant(compiler, reg->data_type, component_count, values); + } + + static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compiler, +@@ -4601,8 +4618,7 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi + } + } + +- return spirv_compiler_get_constant64(compiler, +- vkd3d_component_type_from_data_type(reg->data_type), component_count, values); ++ return spirv_compiler_get_constant64(compiler, reg->data_type, component_count, values); + } + + static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, +@@ -4614,18 +4630,18 @@ static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, VKD3D_ASSERT(reg->type == VKD3DSPR_UNDEF); @@ -6792,87 +11473,215 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return vkd3d_spirv_get_op_undef(builder, type_id); } -@@ -4646,7 +4653,7 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, + static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask, +- const struct vkd3d_shader_register_info *reg_info) ++ const struct vkd3d_shader_register *reg, uint32_t swizzle, ++ uint32_t write_mask, const struct vkd3d_shader_register_info *reg_info) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, ptr_type_id, index, reg_id, val_id; + unsigned int component_idx, reg_component_count; +- enum vkd3d_shader_component_type component_type; + uint32_t skipped_component_mask; + + VKD3D_ASSERT(!register_is_constant_or_undef(reg)); +@@ -4636,7 +4652,6 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, + skipped_component_mask = ~reg_info->write_mask & ((VKD3DSP_WRITEMASK_0 << component_idx) - 1); + if (skipped_component_mask) + component_idx -= vsir_write_mask_component_count(skipped_component_mask); +- component_type = vkd3d_component_type_from_data_type(reg->data_type); + + reg_component_count = vsir_write_mask_component_count(reg_info->write_mask); + +@@ -4646,7 +4661,7 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, component_idx, reg->type, reg->idx[0].offset, reg_info->write_mask); } - type_id = vkd3d_spirv_get_type_id(builder, reg_info->component_type, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, reg_info->component_type, 1); ++ type_id = spirv_get_type_id(builder, reg_info->data_type, 1); reg_id = reg_info->id; if (reg_component_count != 1) { -@@ -4663,7 +4670,7 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, - { - if (reg_info->component_type != VKD3D_SHADER_COMPONENT_UINT) - { -- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); - val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); - } - val_id = spirv_compiler_emit_int_to_bool(compiler, -@@ -4671,7 +4678,7 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, - } - else - { -- type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); - val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); - } +@@ -4656,27 +4671,22 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, } -@@ -4691,7 +4698,7 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil - component_type = vkd3d_component_type_from_data_type(icb->data_type); + val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_id, SpvMemoryAccessMaskNone); ++ if (reg->data_type == reg_info->data_type) ++ return val_id; + +- if (component_type != reg_info->component_type) ++ if (reg->data_type != VSIR_DATA_BOOL) + { +- if (component_type == VKD3D_SHADER_COMPONENT_BOOL) +- { +- if (reg_info->component_type != VKD3D_SHADER_COMPONENT_UINT) +- { +- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); +- val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); +- } +- val_id = spirv_compiler_emit_int_to_bool(compiler, +- VKD3D_SHADER_CONDITIONAL_OP_NZ, VSIR_DATA_U32, 1, val_id); +- } +- else +- { +- type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); +- val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); +- } ++ type_id = spirv_get_type_id(builder, reg->data_type, 1); ++ return vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } + +- return val_id; ++ if (reg_info->data_type != VSIR_DATA_U32) ++ { ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); ++ } ++ ++ return spirv_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, VSIR_DATA_U32, 1, val_id); + } + + static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compiler, +@@ -4684,14 +4694,12 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil + { + 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); + elem_type_id = spirv_get_type_id(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); -@@ -4722,6 +4729,7 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil - &icb->data[component_count * i]); +@@ -4706,7 +4714,6 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil + + 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; +@@ -4718,22 +4725,27 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil + case VSIR_DATA_I32: + case VSIR_DATA_U32: + for (i = 0; i < element_count; ++i) +- elements[i] = spirv_compiler_get_constant(compiler, component_type, component_count, +- &icb->data[component_count * i]); ++ { ++ elements[i] = spirv_compiler_get_constant(compiler, icb->data_type, ++ component_count, &icb->data[component_count * i]); ++ } break; ++ case VSIR_DATA_F64: + case VSIR_DATA_I64: case VSIR_DATA_U64: { uint64_t *data = (uint64_t *)icb->data; -@@ -4777,7 +4785,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, + for (i = 0; i < element_count; ++i) +- elements[i] = spirv_compiler_get_constant64(compiler, component_type, component_count, +- &data[component_count * i]); ++ elements[i] = spirv_compiler_get_constant64(compiler, icb->data_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); ++ "Immediate constant buffer data type \"%s\" (%#x) is unhandled.", ++ vsir_data_type_get_name(icb->data_type, ""), icb->data_type); + break; + } + +@@ -4756,7 +4768,6 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, + const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- enum vkd3d_shader_component_type component_type; + struct vkd3d_shader_register_info reg_info; + unsigned int component_count; + uint32_t type_id, val_id; +@@ -4773,16 +4784,15 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, + reg->data_type, reg->dimension == VSIR_DIMENSION_VEC4 ? 4 : 1); + + component_count = vsir_write_mask_component_count(write_mask); +- component_type = vkd3d_component_type_from_data_type(reg->data_type); if (!spirv_compiler_get_register_info(compiler, reg, ®_info)) { - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); ++ type_id = spirv_get_type_id(builder, reg->data_type, component_count); return vkd3d_spirv_get_op_undef(builder, type_id); } spirv_compiler_emit_dereference_register(compiler, reg, ®_info); -@@ -4796,7 +4804,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, + +- val_write_mask = (data_type_is_64_bit(reg->data_type) && !component_type_is_64_bit(reg_info.component_type)) ++ val_write_mask = (data_type_is_64_bit(reg->data_type) && !data_type_is_64_bit(reg_info.data_type)) + ? vsir_write_mask_32_from_64(write_mask) : write_mask; + + /* Intermediate value (no storage class). */ +@@ -4796,35 +4806,31 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, } else { - type_id = vkd3d_spirv_get_type_id(builder, -+ type_id = spirv_get_type_id_for_component_type(builder, - reg_info.component_type, vsir_write_mask_component_count(reg_info.write_mask)); +- reg_info.component_type, vsir_write_mask_component_count(reg_info.write_mask)); ++ type_id = spirv_get_type_id(builder, reg_info.data_type, ++ vsir_write_mask_component_count(reg_info.write_mask)); val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_info.id, SpvMemoryAccessMaskNone); swizzle = data_type_is_64_bit(reg->data_type) ? vsir_swizzle_32_from_64(swizzle) : swizzle; -@@ -4811,7 +4819,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, - { - if (reg_info.component_type != VKD3D_SHADER_COMPONENT_UINT) - { -- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, component_count); - val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); - } - val_id = spirv_compiler_emit_int_to_bool(compiler, -@@ -4819,7 +4827,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, - } - else - { -- type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); - val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); - } } -@@ -4923,7 +4931,7 @@ static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, + +- val_id = spirv_compiler_emit_swizzle(compiler, +- val_id, reg_info.write_mask, reg_info.component_type, swizzle, val_write_mask); ++ val_id = spirv_compiler_emit_swizzle(compiler, val_id, reg_info.write_mask, ++ vkd3d_component_type_from_data_type(reg_info.data_type), swizzle, val_write_mask); ++ if (reg->data_type == reg_info.data_type) ++ return val_id; + +- if (component_type != reg_info.component_type) ++ if (reg->data_type != VSIR_DATA_BOOL) + { +- if (component_type == VKD3D_SHADER_COMPONENT_BOOL) +- { +- if (reg_info.component_type != VKD3D_SHADER_COMPONENT_UINT) +- { +- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count); +- val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); +- } +- val_id = spirv_compiler_emit_int_to_bool(compiler, +- VKD3D_SHADER_CONDITIONAL_OP_NZ, VSIR_DATA_U32, component_count, val_id); +- } +- else +- { +- type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); +- val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); +- } ++ type_id = spirv_get_type_id(builder, reg->data_type, component_count); ++ return vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } + +- return val_id; ++ if (reg_info.data_type != VSIR_DATA_U32) ++ { ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, component_count); ++ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); ++ } ++ ++ return spirv_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, ++ VSIR_DATA_U32, component_count, val_id); + } + + static void spirv_compiler_emit_execution_mode(struct spirv_compiler *compiler, +@@ -4923,7 +4929,7 @@ static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, if (vsir_write_mask_component_count(dst_write_mask) > 1) { @@ -6881,7 +11690,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); component_idx = vsir_write_mask_get_component_idx(write_mask); component_idx -= vsir_write_mask_get_component_idx(dst_write_mask); -@@ -4951,7 +4959,7 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, +@@ -4951,7 +4957,7 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, if (dst_component_count == 1 && component_count != 1) { @@ -6890,7 +11699,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 val_id = vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, vsir_write_mask_get_component_idx(dst_write_mask)); write_mask &= dst_write_mask; -@@ -4966,7 +4974,7 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, +@@ -4966,7 +4972,7 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, if (dst_component_count != component_count) { @@ -6899,16 +11708,49 @@ index 97c0d0e73a8..8bc851f9c5b 100644 dst_val_id = vkd3d_spirv_build_op_load(builder, type_id, dst_id, SpvMemoryAccessMaskNone); VKD3D_ASSERT(component_count <= ARRAY_SIZE(components)); -@@ -5018,7 +5026,7 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, - if (component_type == VKD3D_SHADER_COMPONENT_BOOL) +@@ -4993,9 +4999,9 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, + const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- enum vkd3d_shader_component_type component_type; + struct vkd3d_shader_register_info reg_info; + uint32_t src_write_mask = write_mask; ++ enum vsir_data_type data_type; + uint32_t type_id; + + VKD3D_ASSERT(!register_is_constant_or_undef(reg)); +@@ -5010,22 +5016,22 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, + return; + spirv_compiler_emit_dereference_register(compiler, reg, ®_info); + +- component_type = vkd3d_component_type_from_data_type(reg->data_type); +- if (component_type != reg_info.component_type) ++ data_type = reg->data_type; ++ if (data_type != reg_info.data_type) + { +- if (data_type_is_64_bit(reg->data_type)) ++ if (data_type_is_64_bit(data_type)) + src_write_mask = vsir_write_mask_32_from_64(write_mask); +- if (component_type == VKD3D_SHADER_COMPONENT_BOOL) ++ if (data_type == VSIR_DATA_BOOL) val_id = spirv_compiler_emit_bool_to_int(compiler, vsir_write_mask_component_count(src_write_mask), val_id, false); - type_id = vkd3d_spirv_get_type_id(builder, reg_info.component_type, -+ type_id = spirv_get_type_id_for_component_type(builder, reg_info.component_type, ++ type_id = spirv_get_type_id(builder, reg_info.data_type, vsir_write_mask_component_count(src_write_mask)); val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); - component_type = reg_info.component_type; -@@ -5101,7 +5109,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp +- component_type = reg_info.component_type; ++ data_type = reg_info.data_type; + } + +- spirv_compiler_emit_store(compiler, +- reg_info.id, reg_info.write_mask, component_type, reg_info.storage_class, src_write_mask, val_id); ++ spirv_compiler_emit_store(compiler, reg_info.id, reg_info.write_mask, ++ vkd3d_component_type_from_data_type(data_type), reg_info.storage_class, src_write_mask, val_id); + } + + static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler, +@@ -5101,7 +5107,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id, dst_type_id, val_id; @@ -6917,7 +11759,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 if (component_count > 1) { val_id = vkd3d_spirv_build_op_composite_construct(builder, -@@ -5112,7 +5120,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp +@@ -5112,7 +5118,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp val_id = *component_ids; } @@ -6926,7 +11768,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 if (dst_type_id != type_id) val_id = vkd3d_spirv_build_op_bitcast(builder, dst_type_id, val_id); -@@ -5281,9 +5289,8 @@ static uint32_t spirv_compiler_emit_draw_parameter_fixup(struct spirv_compiler * +@@ -5281,9 +5287,8 @@ static uint32_t spirv_compiler_emit_draw_parameter_fixup(struct spirv_compiler * vkd3d_spirv_add_iface_variable(builder, base_var_id); spirv_compiler_decorate_builtin(compiler, base_var_id, base); @@ -6938,7 +11780,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return vkd3d_spirv_build_op_isub(builder, type_id, index_id, base_id); } -@@ -5311,17 +5318,16 @@ static uint32_t sv_front_face_fixup(struct spirv_compiler *compiler, +@@ -5311,23 +5316,22 @@ static uint32_t sv_front_face_fixup(struct spirv_compiler *compiler, } /* frag_coord.w = 1.0f / frag_coord.w */ @@ -6961,7 +11803,127 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return vkd3d_spirv_build_op_composite_insert1(builder, type_id, w_id, frag_coord_id, 3); } -@@ -5527,7 +5533,8 @@ static uint32_t spirv_compiler_emit_load_invocation_id(struct spirv_compiler *co + struct vkd3d_spirv_builtin + { +- enum vkd3d_shader_component_type component_type; ++ enum vsir_data_type data_type; + unsigned int component_count; + SpvBuiltIn spirv_builtin; + vkd3d_spirv_builtin_fixup_pfn fixup_pfn; +@@ -5347,43 +5351,43 @@ static const struct + } + vkd3d_system_value_builtins[] = + { +- {VKD3D_SHADER_SV_VERTEX_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInVertexId}, ++ {VKD3D_SHADER_SV_VERTEX_ID, {VSIR_DATA_I32, 1, SpvBuiltInVertexId}, + VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5}, +- {VKD3D_SHADER_SV_INSTANCE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInstanceId}, ++ {VKD3D_SHADER_SV_INSTANCE_ID, {VSIR_DATA_I32, 1, SpvBuiltInInstanceId}, + VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5}, + +- {VKD3D_SHADER_SV_POSITION, {VKD3D_SHADER_COMPONENT_FLOAT, 4, SpvBuiltInPosition}}, +- {VKD3D_SHADER_SV_VERTEX_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInVertexIndex, sv_vertex_id_fixup}}, +- {VKD3D_SHADER_SV_INSTANCE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInstanceIndex, sv_instance_id_fixup}}, ++ {VKD3D_SHADER_SV_POSITION, {VSIR_DATA_F32, 4, SpvBuiltInPosition}}, ++ {VKD3D_SHADER_SV_VERTEX_ID, {VSIR_DATA_I32, 1, SpvBuiltInVertexIndex, sv_vertex_id_fixup}}, ++ {VKD3D_SHADER_SV_INSTANCE_ID, {VSIR_DATA_I32, 1, SpvBuiltInInstanceIndex, sv_instance_id_fixup}}, + +- {VKD3D_SHADER_SV_PRIMITIVE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInPrimitiveId}}, ++ {VKD3D_SHADER_SV_PRIMITIVE_ID, {VSIR_DATA_I32, 1, SpvBuiltInPrimitiveId}}, + +- {VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInLayer}}, +- {VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInViewportIndex}}, ++ {VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX, {VSIR_DATA_I32, 1, SpvBuiltInLayer}}, ++ {VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX, {VSIR_DATA_I32, 1, SpvBuiltInViewportIndex}}, + +- {VKD3D_SHADER_SV_IS_FRONT_FACE, {VKD3D_SHADER_COMPONENT_BOOL, 1, SpvBuiltInFrontFacing, sv_front_face_fixup}}, ++ {VKD3D_SHADER_SV_IS_FRONT_FACE, {VSIR_DATA_BOOL, 1, SpvBuiltInFrontFacing, sv_front_face_fixup}}, + +- {VKD3D_SHADER_SV_SAMPLE_INDEX, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSampleId}}, ++ {VKD3D_SHADER_SV_SAMPLE_INDEX, {VSIR_DATA_U32, 1, SpvBuiltInSampleId}}, + +- {VKD3D_SHADER_SV_CLIP_DISTANCE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInClipDistance, NULL, 1}}, +- {VKD3D_SHADER_SV_CULL_DISTANCE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInCullDistance, NULL, 1}}, ++ {VKD3D_SHADER_SV_CLIP_DISTANCE, {VSIR_DATA_F32, 1, SpvBuiltInClipDistance, NULL, 1}}, ++ {VKD3D_SHADER_SV_CULL_DISTANCE, {VSIR_DATA_F32, 1, SpvBuiltInCullDistance, NULL, 1}}, + +- {VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4}}, +- {VKD3D_SHADER_SV_TESS_FACTOR_QUADINT, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelInner, NULL, 2}}, ++ {VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE, {VSIR_DATA_F32, 1, SpvBuiltInTessLevelOuter, NULL, 4}}, ++ {VKD3D_SHADER_SV_TESS_FACTOR_QUADINT, {VSIR_DATA_F32, 1, SpvBuiltInTessLevelInner, NULL, 2}}, + +- {VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4}}, +- {VKD3D_SHADER_SV_TESS_FACTOR_TRIINT, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelInner, NULL, 2}}, ++ {VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE, {VSIR_DATA_F32, 1, SpvBuiltInTessLevelOuter, NULL, 4}}, ++ {VKD3D_SHADER_SV_TESS_FACTOR_TRIINT, {VSIR_DATA_F32, 1, SpvBuiltInTessLevelInner, NULL, 2}}, + +- {VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 0}}, +- {VKD3D_SHADER_SV_TESS_FACTOR_LINEDET, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 1}}, ++ {VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN, {VSIR_DATA_F32, 1, SpvBuiltInTessLevelOuter, NULL, 4, 0}}, ++ {VKD3D_SHADER_SV_TESS_FACTOR_LINEDET, {VSIR_DATA_F32, 1, SpvBuiltInTessLevelOuter, NULL, 4, 1}}, + }; + static const struct vkd3d_spirv_builtin vkd3d_pixel_shader_position_builtin = + { +- VKD3D_SHADER_COMPONENT_FLOAT, 4, SpvBuiltInFragCoord, frag_coord_fixup, ++ VSIR_DATA_F32, 4, SpvBuiltInFragCoord, frag_coord_fixup, + }; + static const struct vkd3d_spirv_builtin vkd3d_output_point_size_builtin = + { +- VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInPointSize, ++ VSIR_DATA_F32, 1, SpvBuiltInPointSize, + }; + static const struct + { +@@ -5393,31 +5397,31 @@ static const struct + } + vkd3d_register_builtins[] = + { +- {VKD3DSPR_THREADID, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_INT, 3, SpvBuiltInGlobalInvocationId}}, +- {VKD3DSPR_LOCALTHREADID, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_INT, 3, SpvBuiltInLocalInvocationId}}, +- {VKD3DSPR_LOCALTHREADINDEX, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInLocalInvocationIndex}}, +- {VKD3DSPR_THREADGROUPID, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_INT, 3, SpvBuiltInWorkgroupId}}, ++ {VKD3DSPR_THREADID, SpvStorageClassInput, {VSIR_DATA_I32, 3, SpvBuiltInGlobalInvocationId}}, ++ {VKD3DSPR_LOCALTHREADID, SpvStorageClassInput, {VSIR_DATA_I32, 3, SpvBuiltInLocalInvocationId}}, ++ {VKD3DSPR_LOCALTHREADINDEX, SpvStorageClassInput, {VSIR_DATA_I32, 1, SpvBuiltInLocalInvocationIndex}}, ++ {VKD3DSPR_THREADGROUPID, SpvStorageClassInput, {VSIR_DATA_I32, 3, SpvBuiltInWorkgroupId}}, + +- {VKD3DSPR_GSINSTID, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInvocationId}}, +- {VKD3DSPR_OUTPOINTID, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInvocationId}}, ++ {VKD3DSPR_GSINSTID, SpvStorageClassInput, {VSIR_DATA_I32, 1, SpvBuiltInInvocationId}}, ++ {VKD3DSPR_OUTPOINTID, SpvStorageClassInput, {VSIR_DATA_I32, 1, SpvBuiltInInvocationId}}, + +- {VKD3DSPR_PRIMID, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInPrimitiveId}}, ++ {VKD3DSPR_PRIMID, SpvStorageClassInput, {VSIR_DATA_I32, 1, SpvBuiltInPrimitiveId}}, + +- {VKD3DSPR_TESSCOORD, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_FLOAT, 3, SpvBuiltInTessCoord}}, ++ {VKD3DSPR_TESSCOORD, SpvStorageClassInput, {VSIR_DATA_F32, 3, SpvBuiltInTessCoord}}, + +- {VKD3DSPR_POINT_COORD, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_FLOAT, 2, SpvBuiltInPointCoord}}, ++ {VKD3DSPR_POINT_COORD, SpvStorageClassInput, {VSIR_DATA_F32, 2, SpvBuiltInPointCoord}}, + +- {VKD3DSPR_COVERAGE, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSampleMask, NULL, 1}}, +- {VKD3DSPR_SAMPLEMASK, SpvStorageClassOutput, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSampleMask, NULL, 1}}, ++ {VKD3DSPR_COVERAGE, SpvStorageClassInput, {VSIR_DATA_U32, 1, SpvBuiltInSampleMask, NULL, 1}}, ++ {VKD3DSPR_SAMPLEMASK, SpvStorageClassOutput, {VSIR_DATA_U32, 1, SpvBuiltInSampleMask, NULL, 1}}, + +- {VKD3DSPR_DEPTHOUT, SpvStorageClassOutput, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInFragDepth}}, +- {VKD3DSPR_DEPTHOUTGE, SpvStorageClassOutput, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInFragDepth}}, +- {VKD3DSPR_DEPTHOUTLE, SpvStorageClassOutput, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInFragDepth}}, ++ {VKD3DSPR_DEPTHOUT, SpvStorageClassOutput, {VSIR_DATA_F32, 1, SpvBuiltInFragDepth}}, ++ {VKD3DSPR_DEPTHOUTGE, SpvStorageClassOutput, {VSIR_DATA_F32, 1, SpvBuiltInFragDepth}}, ++ {VKD3DSPR_DEPTHOUTLE, SpvStorageClassOutput, {VSIR_DATA_F32, 1, SpvBuiltInFragDepth}}, + +- {VKD3DSPR_OUTSTENCILREF, SpvStorageClassOutput, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInFragStencilRefEXT}}, ++ {VKD3DSPR_OUTSTENCILREF, SpvStorageClassOutput, {VSIR_DATA_U32, 1, SpvBuiltInFragStencilRefEXT}}, + +- {VKD3DSPR_WAVELANECOUNT, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSubgroupSize}}, +- {VKD3DSPR_WAVELANEINDEX, SpvStorageClassInput, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSubgroupLocalInvocationId}}, ++ {VKD3DSPR_WAVELANECOUNT, SpvStorageClassInput, {VSIR_DATA_U32, 1, SpvBuiltInSubgroupSize}}, ++ {VKD3DSPR_WAVELANEINDEX, SpvStorageClassInput, {VSIR_DATA_U32, 1, SpvBuiltInSubgroupLocalInvocationId}}, + }; + + static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *compiler, +@@ -5527,7 +5531,8 @@ static uint32_t spirv_compiler_emit_load_invocation_id(struct spirv_compiler *co uint32_t type_id, id; id = spirv_compiler_get_invocation_id(compiler); @@ -6971,26 +11933,128 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return vkd3d_spirv_build_op_load(builder, type_id, id, SpvMemoryAccessMaskNone); } -@@ -5867,7 +5874,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, +@@ -5641,13 +5646,12 @@ static uint32_t spirv_compiler_emit_builtin_variable_v(struct spirv_compiler *co + sizes[0] = max(sizes[0], builtin->spirv_array_size); + + id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, storage_class, +- builtin->component_type, builtin->component_count, array_sizes, size_count); ++ vkd3d_component_type_from_data_type(builtin->data_type), builtin->component_count, array_sizes, size_count); + vkd3d_spirv_add_iface_variable(builder, id); + spirv_compiler_decorate_builtin(compiler, id, builtin->spirv_builtin); + + if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL && storage_class == SpvStorageClassInput +- && builtin->component_type != VKD3D_SHADER_COMPONENT_FLOAT +- && builtin->component_type != VKD3D_SHADER_COMPONENT_BOOL) ++ && builtin->data_type != VSIR_DATA_F32 && builtin->data_type != VSIR_DATA_BOOL) + vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationFlat, NULL, 0); + + return id; +@@ -5711,8 +5715,7 @@ static const struct vkd3d_symbol *spirv_compiler_emit_io_register(struct spirv_c + spirv_compiler_emit_register_debug_name(builder, id, reg); + + write_mask = vkd3d_write_mask_from_component_count(builtin->component_count); +- vkd3d_symbol_set_register_info(®_symbol, id, +- storage_class, builtin->component_type, write_mask); ++ vkd3d_symbol_set_register_info(®_symbol, id, storage_class, builtin->data_type, write_mask); + reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size; + + return spirv_compiler_put_symbol(compiler, ®_symbol); +@@ -5733,6 +5736,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + uint32_t val_id, input_id, var_id; + uint32_t type_id, float_type_id; + struct vkd3d_symbol reg_symbol; ++ enum vsir_data_type data_type; + SpvStorageClass storage_class; + bool use_private_var = false; + unsigned int array_sizes[2]; +@@ -5781,12 +5785,14 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + + if (builtin) + { +- component_type = builtin->component_type; ++ data_type = builtin->data_type; ++ component_type = vkd3d_component_type_from_data_type(data_type); + input_component_count = builtin->component_count; + } + else + { + component_type = signature_element->component_type; ++ data_type = vsir_data_type_from_component_type(component_type); + input_component_count = vsir_write_mask_component_count(signature_element->mask); + } + +@@ -5852,7 +5858,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + } + + vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, +- use_private_var ? VKD3D_SHADER_COMPONENT_FLOAT : component_type, ++ use_private_var ? VSIR_DATA_F32 : data_type, + use_private_var ? VKD3DSP_WRITEMASK_ALL : reg_write_mask); + reg_symbol.info.reg.is_aggregate = array_sizes[0] || array_sizes[1]; + VKD3D_ASSERT(!builtin || !builtin->spirv_array_size || use_private_var || array_sizes[0] || array_sizes[1]); +@@ -5867,16 +5873,16 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, vsir_register_init(&dst_reg, reg_type, VSIR_DATA_F32, 1); dst_reg.idx[0].offset = element_idx; - type_id = vkd3d_spirv_get_type_id(builder, component_type, input_component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, input_component_count); ++ type_id = spirv_get_type_id(builder, data_type, input_component_count); val_id = vkd3d_spirv_build_op_load(builder, type_id, input_id, SpvMemoryAccessMaskNone); -@@ -5876,7 +5883,8 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + if (builtin && builtin->fixup_pfn) + val_id = builtin->fixup_pfn(compiler, val_id); - if (component_type != VKD3D_SHADER_COMPONENT_FLOAT) +- if (component_type != VKD3D_SHADER_COMPONENT_FLOAT) ++ if (data_type != VSIR_DATA_F32) { - float_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, input_component_count); -+ float_type_id = spirv_get_type_id_for_component_type(builder, -+ VKD3D_SHADER_COMPONENT_FLOAT, input_component_count); ++ float_type_id = spirv_get_type_id(builder, VSIR_DATA_F32, input_component_count); val_id = vkd3d_spirv_build_op_bitcast(builder, float_type_id, val_id); } -@@ -6225,7 +6233,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi +@@ -6024,13 +6030,14 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + const struct shader_signature *shader_signature; + const struct vkd3d_spirv_builtin *builtin; + enum vkd3d_shader_sysval_semantic sysval; +- uint32_t write_mask; + bool use_private_variable = false; + struct vkd3d_symbol reg_symbol; ++ enum vsir_data_type data_type; + SpvStorageClass storage_class; + unsigned int array_sizes[2]; + bool is_patch_constant; + uint32_t id, var_id; ++ uint32_t write_mask; + + is_patch_constant = (reg_type == VKD3DSPR_PATCHCONST); + +@@ -6055,13 +6062,15 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + output_component_count = vsir_write_mask_component_count(write_mask); + if (builtin) + { +- component_type = builtin->component_type; ++ data_type = builtin->data_type; ++ component_type = vkd3d_component_type_from_data_type(data_type); + if (!builtin->spirv_array_size) + output_component_count = builtin->component_count; + } + else + { + component_type = signature_element->component_type; ++ data_type = vsir_data_type_from_component_type(component_type); + } + + storage_class = SpvStorageClassOutput; +@@ -6152,7 +6161,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + } + + vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, +- use_private_variable ? VKD3D_SHADER_COMPONENT_FLOAT : component_type, ++ use_private_variable ? VSIR_DATA_F32 : data_type, + use_private_variable ? VKD3DSP_WRITEMASK_ALL : write_mask); + reg_symbol.info.reg.is_aggregate = array_sizes[0] || array_sizes[1]; + VKD3D_ASSERT(!builtin || !builtin->spirv_array_size || use_private_variable || array_sizes[0] || array_sizes[1]); +@@ -6225,7 +6234,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi if (output_info->component_type != VKD3D_SHADER_COMPONENT_FLOAT) { @@ -6999,7 +12063,16 @@ index 97c0d0e73a8..8bc851f9c5b 100644 val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); } -@@ -6250,7 +6258,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi +@@ -6236,7 +6245,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + /* Set values to 0 for not initialized shader output components. */ + write_mask |= uninit_mask; + zero_id = spirv_compiler_get_constant_vector(compiler, +- output_info->component_type, VKD3D_VEC4_SIZE, 0); ++ vsir_data_type_from_component_type(output_info->component_type), VKD3D_VEC4_SIZE, 0); + val_id = spirv_compiler_emit_vector_shuffle(compiler, + zero_id, val_id, swizzle, uninit_mask, output_info->component_type, + vsir_write_mask_component_count(write_mask)); +@@ -6250,7 +6259,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi output_id = output_info->id; if (output_index_id) { @@ -7008,7 +12081,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 output_info->component_type, vsir_write_mask_component_count(dst_write_mask)); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); output_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, output_id, output_index_id); -@@ -6263,7 +6271,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi +@@ -6263,7 +6272,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi return; } @@ -7017,7 +12090,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); mask = output_info->array_element_mask; array_idx = spirv_compiler_get_output_array_index(compiler, output); -@@ -6305,7 +6313,7 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler * +@@ -6305,7 +6314,7 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler * function_id = compiler->epilogue_function_id; void_id = vkd3d_spirv_get_op_type_void(builder); @@ -7026,16 +12099,36 @@ index 97c0d0e73a8..8bc851f9c5b 100644 ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id); for (i = 0, count = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i) { -@@ -6536,7 +6544,7 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil +@@ -6514,7 +6523,6 @@ 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; +@@ -6535,8 +6543,7 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil + function_location = spirv_compiler_get_current_function_location(compiler); vkd3d_spirv_begin_function_stream_insertion(builder, function_location); - component_type = vkd3d_component_type_from_data_type(temp->data_type); +- component_type = vkd3d_component_type_from_data_type(temp->data_type); - type_id = vkd3d_spirv_get_type_id(builder, component_type, temp->component_count); + type_id = spirv_get_type_id(builder, temp->data_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); -@@ -6577,7 +6585,7 @@ static void spirv_compiler_emit_push_constant_buffers(struct spirv_compiler *com +@@ -6549,8 +6556,8 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil + vkd3d_spirv_end_function_stream_insertion(builder); + + vkd3d_symbol_make_register(®_symbol, ®); +- vkd3d_symbol_set_register_info(®_symbol, id, storage_class, +- component_type, vkd3d_write_mask_from_component_count(temp->component_count)); ++ vkd3d_symbol_set_register_info(®_symbol, id, storage_class, temp->data_type, ++ vkd3d_write_mask_from_component_count(temp->component_count)); + spirv_compiler_put_symbol(compiler, ®_symbol); + } + +@@ -6577,7 +6584,7 @@ static void spirv_compiler_emit_push_constant_buffers(struct spirv_compiler *com if (!(member_ids = vkd3d_calloc(count, sizeof(*member_ids)))) return; @@ -7044,7 +12137,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 for (i = 0, j = 0; i < compiler->shader_interface.push_constant_buffer_count; ++i) { -@@ -6594,7 +6602,7 @@ static void spirv_compiler_emit_push_constant_buffers(struct spirv_compiler *com +@@ -6594,7 +6601,7 @@ static void spirv_compiler_emit_push_constant_buffers(struct spirv_compiler *com if (compiler->offset_info.descriptor_table_count) { @@ -7053,7 +12146,17 @@ index 97c0d0e73a8..8bc851f9c5b 100644 length_id = spirv_compiler_get_constant_uint(compiler, compiler->offset_info.descriptor_table_count); member_ids[j] = vkd3d_spirv_build_op_type_array(builder, type_id, length_id); vkd3d_spirv_build_op_decorate1(builder, member_ids[j], SpvDecorationArrayStride, 4); -@@ -6788,7 +6796,7 @@ static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, +@@ -6626,8 +6633,7 @@ static void spirv_compiler_emit_push_constant_buffers(struct spirv_compiler *com + vkd3d_spirv_build_op_member_name(builder, struct_id, j, "cb%u", reg_idx); + + vkd3d_symbol_make_register(®_symbol, &cb->reg); +- vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, +- VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); ++ vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, VSIR_DATA_F32, VKD3DSP_WRITEMASK_ALL); + reg_symbol.info.reg.member_idx = j; + spirv_compiler_put_symbol(compiler, ®_symbol); + +@@ -6788,7 +6794,7 @@ static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, return; } @@ -7062,7 +12165,37 @@ index 97c0d0e73a8..8bc851f9c5b 100644 length_id = spirv_compiler_get_constant_uint(compiler, size); array_type_id = vkd3d_spirv_build_op_type_array(builder, vec4_id, length_id); vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 16); -@@ -6927,7 +6935,7 @@ static uint32_t spirv_compiler_get_image_type_id(struct spirv_compiler *compiler +@@ -6802,8 +6808,7 @@ static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, + ®, range, VKD3D_SHADER_RESOURCE_BUFFER, descriptor, false, &var_info); + + vkd3d_symbol_make_register(®_symbol, ®); +- vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, +- VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); ++ vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, VSIR_DATA_F32, VKD3DSP_WRITEMASK_ALL); + reg_symbol.descriptor_array = var_info.array_symbol; + reg_symbol.info.reg.binding_base_idx = var_info.binding_base_idx; + spirv_compiler_put_symbol(compiler, ®_symbol); +@@ -6829,8 +6834,7 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi + reg.idx[0].offset = icb->register_idx; + vkd3d_symbol_make_register(®_symbol, ®); + vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate, +- vkd3d_component_type_from_data_type(icb->data_type), +- vkd3d_write_mask_from_component_count(icb->component_count)); ++ icb->data_type, vkd3d_write_mask_from_component_count(icb->component_count)); + spirv_compiler_put_symbol(compiler, ®_symbol); + } + +@@ -6859,8 +6863,7 @@ static void spirv_compiler_emit_sampler_declaration(struct spirv_compiler *compi + ®, range, VKD3D_SHADER_RESOURCE_NONE, descriptor, false, &var_info); + + vkd3d_symbol_make_register(®_symbol, ®); +- vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, +- VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); ++ vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, VSIR_DATA_F32, VKD3DSP_WRITEMASK_ALL); + reg_symbol.descriptor_array = var_info.array_symbol; + reg_symbol.info.reg.binding_base_idx = var_info.binding_base_idx; + spirv_compiler_put_symbol(compiler, ®_symbol); +@@ -6927,7 +6930,7 @@ static uint32_t spirv_compiler_get_image_type_id(struct spirv_compiler *compiler vkd3d_spirv_enable_capability(builder, SpvCapabilityStorageImageReadWithoutFormat); } @@ -7071,7 +12204,16 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return vkd3d_spirv_get_op_type_image(builder, sampled_type_id, resource_type_info->dim, 2, resource_type_info->arrayed, resource_type_info->ms, reg->type == VKD3DSPR_UAV ? 2 : 1, format); -@@ -7053,7 +7061,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp +@@ -6996,7 +6999,7 @@ static void spirv_compiler_emit_combined_sampler_declarations(struct spirv_compi + symbol.id = var_id; + symbol.descriptor_array = NULL; + symbol.info.resource.range = *resource_range; +- symbol.info.resource.sampled_type = sampled_type; ++ symbol.info.resource.sampled_type = vsir_data_type_from_component_type(sampled_type); + symbol.info.resource.type_id = image_type_id; + symbol.info.resource.resource_type_info = resource_type_info; + symbol.info.resource.structure_stride = structure_stride; +@@ -7053,7 +7056,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp { uint32_t array_type_id, struct_id; @@ -7080,7 +12222,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 array_type_id = vkd3d_spirv_get_op_type_runtime_array(builder, type_id); vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 4); -@@ -7094,7 +7102,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp +@@ -7094,7 +7097,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp { VKD3D_ASSERT(structure_stride); /* counters are valid only for structured buffers */ @@ -7089,16 +12231,35 @@ index 97c0d0e73a8..8bc851f9c5b 100644 if (spirv_compiler_is_opengl_target(compiler)) { vkd3d_spirv_enable_capability(builder, SpvCapabilityAtomicStorage); -@@ -7158,7 +7166,7 @@ static void spirv_compiler_emit_workgroup_memory(struct spirv_compiler *compiler +@@ -7126,7 +7129,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp + resource_symbol.id = var_id; + resource_symbol.descriptor_array = var_info.array_symbol; + resource_symbol.info.resource.range = *range; +- resource_symbol.info.resource.sampled_type = sampled_type; ++ resource_symbol.info.resource.sampled_type = descriptor->resource_data_type; + resource_symbol.info.resource.type_id = type_id; + resource_symbol.info.resource.resource_type_info = resource_type_info; + resource_symbol.info.resource.structure_stride = structure_stride; +@@ -7158,7 +7161,7 @@ static void spirv_compiler_emit_workgroup_memory(struct spirv_compiler *compiler if (alignment) TRACE("Ignoring alignment %u.\n", alignment); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); length_id = spirv_compiler_get_constant_uint(compiler, size); array_type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); -@@ -7209,10 +7217,9 @@ static void spirv_compiler_emit_output_vertex_count(struct spirv_compiler *compi +@@ -7170,8 +7173,7 @@ static void spirv_compiler_emit_workgroup_memory(struct spirv_compiler *compiler + spirv_compiler_emit_register_debug_name(builder, var_id, reg); + + vkd3d_symbol_make_register(®_symbol, reg); +- vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, +- VKD3D_SHADER_COMPONENT_UINT, VKD3DSP_WRITEMASK_0); ++ vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, VSIR_DATA_U32, VKD3DSP_WRITEMASK_0); + reg_symbol.info.reg.structure_stride = structure_stride; + spirv_compiler_put_symbol(compiler, ®_symbol); + } +@@ -7209,10 +7211,9 @@ static void spirv_compiler_emit_output_vertex_count(struct spirv_compiler *compi SpvExecutionModeOutputVertices, instruction->declaration.count); } @@ -7111,7 +12272,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 SpvExecutionMode mode; switch (primitive_type) -@@ -7233,7 +7240,8 @@ static void spirv_compiler_emit_dcl_input_primitive(struct spirv_compiler *compi +@@ -7233,7 +7234,8 @@ static void spirv_compiler_emit_dcl_input_primitive(struct spirv_compiler *compi mode = SpvExecutionModeInputTrianglesAdjacency; break; default: @@ -7121,7 +12282,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return; } -@@ -7263,10 +7271,9 @@ static void spirv_compiler_emit_point_size(struct spirv_compiler *compiler) +@@ -7263,10 +7265,9 @@ static void spirv_compiler_emit_point_size(struct spirv_compiler *compiler) } } @@ -7134,7 +12295,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 SpvExecutionMode mode; switch (primitive_type) -@@ -7282,7 +7289,8 @@ static void spirv_compiler_emit_dcl_output_topology(struct spirv_compiler *compi +@@ -7282,7 +7283,8 @@ static void spirv_compiler_emit_dcl_output_topology(struct spirv_compiler *compi mode = SpvExecutionModeOutputTriangleStrip; break; default: @@ -7144,7 +12305,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 return; } -@@ -7624,11 +7632,12 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, +@@ -7624,11 +7626,12 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, /* ITOD is not supported. Frontends which emit bool casts must use ITOF for double. */ val_id = spirv_compiler_emit_bool_to_double(compiler, 1, val_id, instruction->opcode == VSIR_OP_ITOF); } @@ -7159,7 +12320,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 { val_id = spirv_compiler_emit_bool_to_int64(compiler, 1, val_id, instruction->opcode == VSIR_OP_ITOI); } -@@ -7724,7 +7733,7 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil +@@ -7724,7 +7727,7 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil condition_id = spirv_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src_ids[1]); @@ -7168,7 +12329,16 @@ index 97c0d0e73a8..8bc851f9c5b 100644 uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count); else uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT_MAX, component_count); -@@ -7839,7 +7848,7 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp +@@ -7741,7 +7744,7 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil + || instruction->opcode == VSIR_OP_ISHR || instruction->opcode == VSIR_OP_USHR)) + { + uint32_t mask_id = spirv_compiler_get_constant_vector(compiler, +- VKD3D_SHADER_COMPONENT_UINT, vsir_write_mask_component_count(dst->write_mask), 0x1f); ++ VSIR_DATA_U32, vsir_write_mask_component_count(dst->write_mask), 0x1f); + src_ids[1] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[1], mask_id); + } + +@@ -7839,7 +7842,7 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp unsigned int i, component_count; enum GLSLstd450 glsl_inst; @@ -7177,26 +12347,34 @@ index 97c0d0e73a8..8bc851f9c5b 100644 || instruction->opcode == VSIR_OP_FIRSTBIT_LO || instruction->opcode == VSIR_OP_FIRSTBIT_SHI)) { /* At least some drivers support this anyway, but if validation is enabled it will fail. */ -@@ -7878,7 +7887,8 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp +@@ -7878,7 +7881,7 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp component_count = vsir_write_mask_component_count(dst->write_mask); uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT32_MAX, component_count); condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpIEqual, - vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count), val_id, uint_max_id); -+ spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count), -+ val_id, uint_max_id); ++ spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count), val_id, uint_max_id); rev_val_id = vkd3d_spirv_build_op_isub(builder, type_id, spirv_compiler_get_constant_uint_vector(compiler, 31, component_count), val_id); val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, val_id, rev_val_id); -@@ -7928,7 +7938,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, +@@ -7905,7 +7908,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, + spirv_compiler_get_register_info(compiler, &dst->reg, &dst_reg_info); + spirv_compiler_get_register_info(compiler, &src->reg, &src_reg_info); + +- if (dst_reg_info.component_type != src_reg_info.component_type ++ if (dst_reg_info.data_type != src_reg_info.data_type + || dst_reg_info.write_mask != src_reg_info.write_mask) + goto general_implementation; + +@@ -7928,7 +7931,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, dst_id = spirv_compiler_get_register_id(compiler, &dst->reg); src_id = spirv_compiler_get_register_id(compiler, &src->reg); - type_id = vkd3d_spirv_get_type_id(builder, dst_reg_info.component_type, VKD3D_VEC4_SIZE); -+ type_id = spirv_get_type_id_for_component_type(builder, dst_reg_info.component_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(builder, dst_reg_info.data_type, VKD3D_VEC4_SIZE); val_id = vkd3d_spirv_build_op_load(builder, type_id, src_id, SpvMemoryAccessMaskNone); dst_val_id = vkd3d_spirv_build_op_load(builder, type_id, dst_id, SpvMemoryAccessMaskNone); -@@ -7957,7 +7967,7 @@ general_implementation: +@@ -7957,7 +7960,7 @@ general_implementation: val_id = spirv_compiler_emit_load_src(compiler, src, write_mask); if (dst->reg.data_type != src->reg.data_type) { @@ -7205,36 +12383,59 @@ index 97c0d0e73a8..8bc851f9c5b 100644 dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)), val_id); } spirv_compiler_emit_store_dst(compiler, dst, val_id); -@@ -7983,8 +7993,8 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, +@@ -7983,7 +7986,7 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, { if (instruction->opcode == VSIR_OP_CMP) condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpFOrdGreaterThanEqual, - vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count), condition_id, -- spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count)); -+ spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count), -+ condition_id, spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count)); ++ spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count), condition_id, + spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count)); else condition_id = spirv_compiler_emit_int_to_bool(compiler, - VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); -@@ -8010,7 +8020,7 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler, +@@ -8010,7 +8013,7 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler, src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask); component_count = vsir_write_mask_component_count(dst->write_mask); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, component_count); condition_id = spirv_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); -@@ -8046,7 +8056,7 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, +@@ -8027,13 +8030,13 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; +- enum vkd3d_shader_component_type component_type; + uint32_t type_id, val_id, src_ids[2]; + unsigned int component_count, i; ++ enum vsir_data_type data_type; + uint32_t write_mask; + + component_count = vsir_write_mask_component_count(dst->write_mask); +- component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); ++ data_type = dst->reg.data_type; + + if (instruction->opcode == VSIR_OP_DP4) + write_mask = VKD3DSP_WRITEMASK_ALL; +@@ -8046,15 +8049,12 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, for (i = 0; i < ARRAY_SIZE(src_ids); ++i) src_ids[i] = spirv_compiler_emit_load_src(compiler, &src[i], write_mask); - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); ++ type_id = spirv_get_type_id(builder, data_type, 1); val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpDot, type_id, src_ids[0], src_ids[1]); -@@ -8092,7 +8102,7 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, + if (component_count > 1) +- { +- val_id = spirv_compiler_emit_construct_vector(compiler, +- component_type, component_count, val_id, 0, 1); +- } ++ val_id = spirv_compiler_emit_construct_vector(compiler, data_type, component_count, val_id, 0, 1); + if (instruction->flags & VKD3DSI_PRECISE_XYZW) + vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); + +@@ -8092,7 +8092,7 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, unsigned int i, component_count; component_count = vsir_write_mask_component_count(dst->write_mask); @@ -7243,135 +12444,244 @@ index 97c0d0e73a8..8bc851f9c5b 100644 for (i = 0; i < ARRAY_SIZE(src_ids); ++i) src_ids[i] = spirv_compiler_emit_load_src(compiler, &src[i], dst->write_mask); -@@ -8146,7 +8156,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, - component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); +@@ -8111,7 +8111,6 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t src_type_id, dst_type_id, condition_type_id; +- enum vkd3d_shader_component_type component_type; + unsigned int component_count; + uint32_t write_mask; - int_max_id = spirv_compiler_get_constant_vector(compiler, component_type, component_count, INT_MAX); +@@ -8143,17 +8142,16 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_glsl_std450_max(builder, src_type_id, src_id, int_min_id); + + /* VSIR allows the destination of a signed conversion to be unsigned. */ +- component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); + +- int_max_id = spirv_compiler_get_constant_vector(compiler, component_type, component_count, INT_MAX); - condition_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); -+ condition_type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); ++ int_max_id = spirv_compiler_get_constant_vector(compiler, dst->reg.data_type, component_count, INT_MAX); ++ condition_type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpFOrdGreaterThanEqual, condition_type_id, val_id, float_max_id); -@@ -8199,7 +8209,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpConvertFToS, dst_type_id, val_id); + val_id = vkd3d_spirv_build_op_select(builder, dst_type_id, condition_id, int_max_id, val_id); + +- zero_id = spirv_compiler_get_constant_vector(compiler, component_type, component_count, 0); ++ zero_id = spirv_compiler_get_constant_vector(compiler, dst->reg.data_type, component_count, 0); + condition_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpIsNan, condition_type_id, src_id); + val_id = vkd3d_spirv_build_op_select(builder, dst_type_id, condition_id, zero_id, val_id); + +@@ -8199,7 +8197,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, val_id = vkd3d_spirv_build_op_glsl_std450_max(builder, src_type_id, src_id, zero_id); uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT_MAX, component_count); - condition_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); -+ condition_type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); ++ condition_type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpFOrdGreaterThanEqual, condition_type_id, val_id, float_max_id); -@@ -8224,7 +8234,7 @@ static void spirv_compiler_emit_dtof(struct spirv_compiler *compiler, +@@ -8224,7 +8222,7 @@ static void spirv_compiler_emit_dtof(struct spirv_compiler *compiler, src_id = spirv_compiler_emit_load_src(compiler, src, write_mask); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, component_count); val_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpFConvert, type_id, src_id); if (instruction->flags & VKD3DSI_PRECISE_XYZW) vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); -@@ -8248,8 +8258,8 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp +@@ -8248,8 +8246,8 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp VKD3D_ASSERT(2 <= src_count && src_count <= ARRAY_SIZE(src_ids)); component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); - size = (src[src_count - 1].reg.data_type == VSIR_DATA_U64) ? 0x40 : 0x20; -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); ++ type_id = spirv_get_type_id(builder, dst->reg.data_type, 1); + size = data_type_is_64_bit(src[src_count - 1].reg.data_type) ? 0x40 : 0x20; mask_id = spirv_compiler_get_constant_uint(compiler, size - 1); size_id = spirv_compiler_get_constant_uint(compiler, size); -@@ -8305,8 +8315,8 @@ static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler, +@@ -8305,8 +8303,8 @@ static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler, unsigned int i, j; instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); - scalar_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -+ scalar_type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); ++ scalar_type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 1); /* FIXME: Consider a single UnpackHalf2x16 instruction per 2 components. */ VKD3D_ASSERT(dst->write_mask & VKD3DSP_WRITEMASK_ALL); -@@ -8338,8 +8348,8 @@ static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler, +@@ -8338,8 +8336,8 @@ static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler, unsigned int i, j; instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); - scalar_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -+ scalar_type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); ++ scalar_type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); zero_id = spirv_compiler_get_constant_float(compiler, 0.0f); /* FIXME: Consider a single PackHalf2x16 instruction per 2 components. */ -@@ -8418,7 +8428,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co +@@ -8418,7 +8416,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co src0_id = spirv_compiler_emit_load_src(compiler, &src[0], write_mask); src1_id = spirv_compiler_emit_load_src(compiler, &src[1], write_mask); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, src0_id, src1_id); -@@ -8470,7 +8480,7 @@ static void spirv_compiler_emit_float_comparison_instruction(struct spirv_compil +@@ -8470,7 +8468,7 @@ static void spirv_compiler_emit_float_comparison_instruction(struct spirv_compil src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, src0_id, src1_id); result_id = spirv_compiler_emit_bool_to_float(compiler, component_count, result_id, false); -@@ -8999,7 +9009,7 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, +@@ -8806,7 +8804,7 @@ struct vkd3d_shader_image + uint32_t image_id; + uint32_t sampled_image_id; + +- enum vkd3d_shader_component_type sampled_type; ++ enum vsir_data_type sampled_type; + uint32_t image_type_id; + const struct vkd3d_spirv_resource_type *resource_type_info; + unsigned int structure_stride; +@@ -8926,9 +8924,9 @@ static void spirv_compiler_prepare_image(struct spirv_compiler *compiler, + image->image_id = 0; + } + +- image->image_type_id = spirv_compiler_get_image_type_id(compiler, resource_reg, +- &symbol->info.resource.range, image->resource_type_info, +- image->sampled_type, image->structure_stride || image->raw); ++ image->image_type_id = spirv_compiler_get_image_type_id(compiler, resource_reg, &symbol->info.resource.range, ++ image->resource_type_info, vkd3d_component_type_from_data_type(image->sampled_type), ++ image->structure_stride || image->raw); + + if (sampled) + { +@@ -8977,8 +8975,7 @@ static uint32_t spirv_compiler_emit_texel_offset(struct spirv_compiler *compiler + int32_t data[4] = {offset->u, offset->v, offset->w, 0}; + + VKD3D_ASSERT(resource_type_info->dim != SpvDimCube); +- return spirv_compiler_get_constant(compiler, +- VKD3D_SHADER_COMPONENT_INT, component_count, (const uint32_t *)data); ++ return spirv_compiler_get_constant(compiler, VSIR_DATA_I32, component_count, (const uint32_t *)data); + } + + static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, +@@ -8999,7 +8996,7 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, spirv_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE); - type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); -+ type_id = spirv_get_type_id_for_component_type(builder, image.sampled_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1; coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], coordinate_mask); if (image.resource_type_info->resource_type != VKD3D_SHADER_RESOURCE_BUFFER && !multisample) -@@ -9045,7 +9055,7 @@ static void spirv_compiler_emit_lod(struct spirv_compiler *compiler, +@@ -9024,8 +9021,8 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_image_fetch(builder, type_id, + image.image_id, coordinate_id, operands_mask, image_operands, image_operand_count); + +- spirv_compiler_emit_store_dst_swizzled(compiler, +- dst, val_id, image.sampled_type, src[1].swizzle); ++ spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, ++ vkd3d_component_type_from_data_type(image.sampled_type), src[1].swizzle); + } + + static void spirv_compiler_emit_lod(struct spirv_compiler *compiler, +@@ -9045,13 +9042,13 @@ static void spirv_compiler_emit_lod(struct spirv_compiler *compiler, spirv_compiler_prepare_image(compiler, &image, &resource->reg, &sampler->reg, VKD3D_IMAGE_FLAG_SAMPLED); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL); val_id = vkd3d_spirv_build_op_image_query_lod(builder, type_id, image.sampled_image_id, coordinate_id); -@@ -9115,7 +9125,7 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, + +- spirv_compiler_emit_store_dst_swizzled(compiler, +- dst, val_id, image.sampled_type, resource->swizzle); ++ spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, ++ vkd3d_component_type_from_data_type(image.sampled_type), resource->swizzle); + } + + static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, +@@ -9115,14 +9112,14 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, instruction, image.resource_type_info); } - sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); -+ sampled_type_id = spirv_get_type_id_for_component_type(builder, image.sampled_type, VKD3D_VEC4_SIZE); ++ sampled_type_id = spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL); VKD3D_ASSERT(image_operand_count <= ARRAY_SIZE(image_operands)); val_id = vkd3d_spirv_build_op_image_sample(builder, op, sampled_type_id, -@@ -9160,7 +9170,7 @@ static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, + image.sampled_image_id, coordinate_id, operands_mask, image_operands, image_operand_count); + +- spirv_compiler_emit_store_dst_swizzled(compiler, +- dst, val_id, image.sampled_type, resource->swizzle); ++ spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, ++ vkd3d_component_type_from_data_type(image.sampled_type), resource->swizzle); + } + + static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, +@@ -9160,15 +9157,15 @@ static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, instruction, image.resource_type_info); } - sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, 1); -+ sampled_type_id = spirv_get_type_id_for_component_type(builder, image.sampled_type, 1); ++ sampled_type_id = spirv_get_type_id(builder, image.sampled_type, 1); coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL); dref_id = spirv_compiler_emit_load_src(compiler, &src[3], VKD3DSP_WRITEMASK_0); val_id = vkd3d_spirv_build_op_image_sample_dref(builder, op, sampled_type_id, -@@ -9219,7 +9229,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, + image.sampled_image_id, coordinate_id, dref_id, operands_mask, + image_operands, image_operand_count); + +- spirv_compiler_emit_store_dst_scalar(compiler, +- dst, val_id, image.sampled_type, src[1].swizzle); ++ spirv_compiler_emit_store_dst_scalar(compiler, dst, val_id, ++ vkd3d_component_type_from_data_type(image.sampled_type), src[1].swizzle); + } + + static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, +@@ -9219,7 +9216,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, instruction, image.resource_type_info); } - sampled_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); -+ sampled_type_id = spirv_get_type_id_for_component_type(builder, image.sampled_type, VKD3D_VEC4_SIZE); ++ sampled_type_id = spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1; coordinate_id = spirv_compiler_emit_load_src(compiler, addr, coordinate_mask); if (image_flags & VKD3D_IMAGE_FLAG_DEPTH) -@@ -9301,10 +9311,10 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler +@@ -9234,15 +9231,14 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, + { + component_idx = vsir_swizzle_get_component(sampler->swizzle, 0); + /* Nvidia driver requires signed integer type. */ +- component_id = spirv_compiler_get_constant(compiler, +- VKD3D_SHADER_COMPONENT_INT, 1, &component_idx); ++ component_id = spirv_compiler_get_constant(compiler, VSIR_DATA_I32, 1, &component_idx); + val_id = vkd3d_spirv_build_op_image_gather(builder, sampled_type_id, + image.sampled_image_id, coordinate_id, component_id, + operands_mask, image_operands, image_operand_count); + } + +- spirv_compiler_emit_store_dst_swizzled(compiler, +- dst, val_id, image.sampled_type, resource->swizzle); ++ spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, ++ vkd3d_component_type_from_data_type(image.sampled_type), resource->swizzle); + } + + static uint32_t spirv_compiler_emit_raw_structured_addressing( +@@ -9301,10 +9297,10 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler if (storage_buffer_uav) { - texel_type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); -+ texel_type_id = spirv_get_type_id_for_component_type(builder, resource_symbol->info.resource.sampled_type, 1); ++ texel_type_id = spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, texel_type_id); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); @@ -7379,7 +12689,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, type_id, resource_symbol->info.resource.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); -@@ -9336,11 +9346,11 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler +@@ -9336,11 +9332,11 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler spirv_compiler_prepare_image(compiler, &image, &resource->reg, NULL, VKD3D_IMAGE_FLAG_NONE); @@ -7389,25 +12699,25 @@ index 97c0d0e73a8..8bc851f9c5b 100644 type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); - texel_type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); -+ texel_type_id = spirv_get_type_id_for_component_type(builder, image.sampled_type, VKD3D_VEC4_SIZE); ++ texel_type_id = spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); VKD3D_ASSERT(dst->write_mask & VKD3DSP_WRITEMASK_ALL); for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) { -@@ -9379,7 +9389,7 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, +@@ -9379,7 +9375,7 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, if (!spirv_compiler_get_register_info(compiler, &resource->reg, ®_info)) return; - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id); base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); -@@ -9438,10 +9448,10 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * +@@ -9438,10 +9434,10 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * if (spirv_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource)) { - type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, resource_symbol->info.resource.sampled_type, 1); ++ type_id = spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); @@ -7415,7 +12725,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, type_id, resource_symbol->info.resource.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); -@@ -9469,7 +9479,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * +@@ -9469,7 +9465,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * } else { @@ -7424,52 +12734,104 @@ index 97c0d0e73a8..8bc851f9c5b 100644 spirv_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE); base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); -@@ -9512,7 +9522,7 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, +@@ -9482,7 +9478,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * + for (component_idx = 0; component_idx < component_count; ++component_idx) + { + /* Mesa Vulkan drivers require the texel parameter to be a vector. */ +- data_id = spirv_compiler_emit_construct_vector(compiler, VKD3D_SHADER_COMPONENT_UINT, ++ data_id = spirv_compiler_emit_construct_vector(compiler, VSIR_DATA_U32, + VKD3D_VEC4_SIZE, val_id, component_idx, component_count); + + coordinate_id = base_coordinate_id; +@@ -9512,7 +9508,7 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, if (!spirv_compiler_get_register_info(compiler, &dst->reg, ®_info)) return; - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id); base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); -@@ -9570,7 +9580,7 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, +@@ -9570,7 +9566,7 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, if (spirv_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource)) { - type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, resource_symbol->info.resource.sampled_type, 1); ++ type_id = spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); indices[0] = spirv_compiler_get_constant_uint(compiler, 0); -@@ -9585,7 +9595,7 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, +@@ -9580,20 +9576,20 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone); + + spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, +- resource_symbol->info.resource.sampled_type, src[1].swizzle); ++ vkd3d_component_type_from_data_type(resource_symbol->info.resource.sampled_type), src[1].swizzle); + } else { spirv_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE); - type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); -+ type_id = spirv_get_type_id_for_component_type(builder, image.sampled_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1; coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], coordinate_mask); -@@ -9613,7 +9623,7 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_image_read(builder, type_id, + image.image_id, coordinate_id, SpvImageOperandsMaskNone, NULL, 0); + +- spirv_compiler_emit_store_dst_swizzled(compiler, +- dst, val_id, image.sampled_type, src[1].swizzle); ++ spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, ++ vkd3d_component_type_from_data_type(image.sampled_type), src[1].swizzle); + } + } + +@@ -9613,14 +9609,14 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler, if (spirv_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource)) { - type_id = vkd3d_spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, resource_symbol->info.resource.sampled_type, 1); ++ type_id = spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); indices[0] = spirv_compiler_get_constant_uint(compiler, 0); -@@ -9658,7 +9668,7 @@ static void spirv_compiler_emit_uav_counter_instruction(struct spirv_compiler *c + indices[1] = coordinate_id; + +- val_id = spirv_compiler_emit_load_src_with_type(compiler, &src[1], +- VKD3DSP_WRITEMASK_0, resource_symbol->info.resource.sampled_type); ++ val_id = spirv_compiler_emit_load_src_with_type(compiler, &src[1], VKD3DSP_WRITEMASK_0, ++ vkd3d_component_type_from_data_type(resource_symbol->info.resource.sampled_type)); + ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2); + vkd3d_spirv_build_op_store(builder, ptr_id, val_id, SpvMemoryAccessMaskNone); + } +@@ -9631,7 +9627,8 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler, + spirv_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE); + coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1; + coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], coordinate_mask); +- texel_id = spirv_compiler_emit_load_src_with_type(compiler, &src[1], dst->write_mask, image.sampled_type); ++ texel_id = spirv_compiler_emit_load_src_with_type(compiler, &src[1], ++ dst->write_mask, vkd3d_component_type_from_data_type(image.sampled_type)); + + vkd3d_spirv_build_op_image_write(builder, image.image_id, coordinate_id, texel_id, + SpvImageOperandsMaskNone, NULL, 0); +@@ -9658,7 +9655,7 @@ static void spirv_compiler_emit_uav_counter_instruction(struct spirv_compiler *c counter_id = resource_symbol->info.resource.uav_counter_id; VKD3D_ASSERT(counter_id); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); if (resource_symbol->info.resource.uav_counter_array) { -@@ -9820,7 +9830,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil +@@ -9772,6 +9769,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + struct vkd3d_shader_register_info reg_info; + SpvMemorySemanticsMask memory_semantic; + struct vkd3d_shader_image image; ++ enum vsir_data_type data_type; + unsigned int structure_stride; + uint32_t coordinate_mask; + uint32_t operands[6]; +@@ -9820,7 +9818,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil } } @@ -7478,57 +12840,78 @@ index 97c0d0e73a8..8bc851f9c5b 100644 if (structure_stride || raw) { VKD3D_ASSERT(!raw != !structure_stride); -@@ -9845,7 +9855,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil +@@ -9836,7 +9834,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + + if (resource->reg.type == VKD3DSPR_GROUPSHAREDMEM) + { +- component_type = VKD3D_SHADER_COMPONENT_UINT; ++ data_type = VSIR_DATA_U32; + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id); + pointer_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, reg_info.id, coordinate_id); + } +@@ -9844,8 +9842,8 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + { if (spirv_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource)) { - component_type = resource_symbol->info.resource.sampled_type; +- component_type = resource_symbol->info.resource.sampled_type; - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); ++ data_type = resource_symbol->info.resource.sampled_type; ++ type_id = spirv_get_type_id(builder, data_type, 1); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); operands[0] = spirv_compiler_get_constant_uint(compiler, 0); operands[1] = coordinate_id; -@@ -9854,7 +9864,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil +@@ -9853,8 +9851,8 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + } else { - component_type = image.sampled_type; +- component_type = image.sampled_type; - type_id = vkd3d_spirv_get_type_id(builder, image.sampled_type, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, image.sampled_type, 1); ++ data_type = image.sampled_type; ++ type_id = spirv_get_type_id(builder, data_type, 1); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassImage, type_id); sample_id = spirv_compiler_get_constant_uint(compiler, 0); pointer_id = vkd3d_spirv_build_op_image_texel_pointer(builder, -@@ -9907,7 +9917,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, +@@ -9862,6 +9860,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + } + } + ++ component_type = vkd3d_component_type_from_data_type(data_type); + val_id = spirv_compiler_emit_load_src_with_type(compiler, &src[1], VKD3DSP_WRITEMASK_0, component_type); + + if (instruction->flags & VKD3DARF_VOLATILE) +@@ -9907,7 +9906,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, { resource_symbol = spirv_compiler_find_resource(compiler, &src->reg); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); val_id = vkd3d_spirv_build_op_array_length(builder, type_id, resource_symbol->id, 0); write_mask = VKD3DSP_WRITEMASK_0; } -@@ -9917,7 +9927,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, +@@ -9917,7 +9916,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, spirv_compiler_prepare_image(compiler, &image, &src->reg, NULL, VKD3D_IMAGE_FLAG_NONE); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); val_id = vkd3d_spirv_build_op_image_query_size(builder, type_id, image.image_id); write_mask = VKD3DSP_WRITEMASK_0; } -@@ -9927,7 +9937,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, +@@ -9927,7 +9926,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, stride_id = spirv_compiler_get_constant_uint(compiler, image.structure_stride); constituents[0] = vkd3d_spirv_build_op_udiv(builder, type_id, val_id, stride_id); constituents[1] = stride_id; - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, ARRAY_SIZE(constituents)); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, ARRAY_SIZE(constituents)); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, ARRAY_SIZE(constituents)); val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, constituents, ARRAY_SIZE(constituents)); write_mask |= VKD3DSP_WRITEMASK_1; -@@ -9966,14 +9976,14 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, +@@ -9966,14 +9965,14 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, size_component_count = image.resource_type_info->coordinate_component_count; if (image.resource_type_info->dim == SpvDimCube) --size_component_count; - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, size_component_count); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, size_component_count); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, size_component_count); supports_mipmaps = src[1].reg.type != VKD3DSPR_UAV && !image.resource_type_info->ms; if (supports_mipmaps) @@ -7536,87 +12919,104 @@ index 97c0d0e73a8..8bc851f9c5b 100644 lod_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); val_id = vkd3d_spirv_build_op_image_query_size_lod(builder, type_id, image.image_id, lod_id); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); miplevel_count_id = vkd3d_spirv_build_op_image_query_levels(builder, type_id, image.image_id); } else -@@ -9987,14 +9997,14 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, +@@ -9987,14 +9986,13 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, for (i = 0; i < 3 - size_component_count; ++i) constituents[i + 1] = spirv_compiler_get_constant_uint(compiler, 0); constituents[i + 1] = miplevel_count_id; - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE); - val_id = vkd3d_spirv_build_op_composite_construct(builder, - type_id, constituents, i + 2); +- val_id = vkd3d_spirv_build_op_composite_construct(builder, +- type_id, constituents, i + 2); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, VKD3D_VEC4_SIZE); ++ val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, constituents, i + 2); if (!(instruction->flags & VKD3DSI_RESINFO_UINT)) { component_type = VKD3D_SHADER_COMPONENT_FLOAT; - type_id = vkd3d_spirv_get_type_id(builder, component_type, VKD3D_VEC4_SIZE); -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, VKD3D_VEC4_SIZE); val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id); if (instruction->flags & VKD3DSI_PRECISE_XYZW) vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); -@@ -10022,7 +10032,7 @@ static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *co +@@ -10022,7 +10020,7 @@ static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *co vkd3d_spirv_enable_capability(builder, SpvCapabilityImageQuery); spirv_compiler_prepare_image(compiler, &image, &src->reg, NULL, VKD3D_IMAGE_FLAG_NONE); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); val_id = vkd3d_spirv_build_op_image_query_samples(builder, type_id, image.image_id); } -@@ -10049,13 +10059,13 @@ static void spirv_compiler_emit_sample_info(struct spirv_compiler *compiler, +@@ -10048,14 +10046,16 @@ static void spirv_compiler_emit_sample_info(struct spirv_compiler *compiler, + constituents[0] = val_id; for (i = 1; i < VKD3D_VEC4_SIZE; ++i) ++ { constituents[i] = spirv_compiler_get_constant_uint(compiler, 0); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE); ++ } ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, VKD3D_VEC4_SIZE); val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, constituents, VKD3D_VEC4_SIZE); if (!(instruction->flags & VKD3DSI_SAMPLE_INFO_UINT)) { component_type = VKD3D_SHADER_COMPONENT_FLOAT; - type_id = vkd3d_spirv_get_type_id(builder, component_type, VKD3D_VEC4_SIZE); -+ type_id = spirv_get_type_id_for_component_type(builder, component_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, VKD3D_VEC4_SIZE); val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id); if (instruction->flags & VKD3DSI_PRECISE_XYZW) vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); -@@ -10121,13 +10131,13 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, +@@ -10121,13 +10121,12 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, sample_count_id = spirv_compiler_emit_query_sample_count(compiler, &instruction->src[0]); sample_index_id = spirv_compiler_emit_load_src(compiler, &instruction->src[1], VKD3DSP_WRITEMASK_0); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); index_id = vkd3d_spirv_build_op_iadd(builder, type_id, sample_count_id, sample_index_id); - index_id = vkd3d_spirv_build_op_isub(builder, - type_id, index_id, spirv_compiler_get_constant_uint(compiler, 1)); +- index_id = vkd3d_spirv_build_op_isub(builder, +- type_id, index_id, spirv_compiler_get_constant_uint(compiler, 1)); ++ index_id = vkd3d_spirv_build_op_isub(builder, type_id, index_id, spirv_compiler_get_constant_uint(compiler, 1)); /* Validate sample index. */ - bool_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, 1); -+ bool_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, 1); ++ bool_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, 1); id = vkd3d_spirv_build_op_logical_and(builder, bool_id, vkd3d_spirv_build_op_uless_than(builder, bool_id, sample_index_id, sample_count_id), vkd3d_spirv_build_op_uless_than_equal(builder, -@@ -10135,7 +10145,7 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, +@@ -10135,16 +10134,16 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, index_id = vkd3d_spirv_build_op_select(builder, type_id, id, index_id, spirv_compiler_get_constant_uint(compiler, 0)); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); if (!(id = compiler->sample_positions_id)) { length_id = spirv_compiler_get_constant_uint(compiler, ARRAY_SIZE(standard_sample_positions)); -@@ -10199,7 +10209,7 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, + array_type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); + +- for (i = 0; i < ARRAY_SIZE(standard_sample_positions); ++ i) ++ for (i = 0; i < ARRAY_SIZE(standard_sample_positions); ++i) + { +- constituents[i] = spirv_compiler_get_constant(compiler, +- VKD3D_SHADER_COMPONENT_FLOAT, 2, (const uint32_t *)standard_sample_positions[i]); ++ constituents[i] = spirv_compiler_get_constant(compiler, VSIR_DATA_F32, ++ 2, (const uint32_t *)standard_sample_positions[i]); + } + + id = vkd3d_spirv_build_op_constant_composite(builder, array_type_id, constituents, ARRAY_SIZE(constituents)); +@@ -10199,7 +10198,7 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, src_ids[src_count++] = spirv_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0); } - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, ++ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, vsir_write_mask_component_count(register_info.write_mask)); instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); -@@ -10334,9 +10344,8 @@ static void spirv_compiler_emit_quad_read_across(struct spirv_compiler *compiler +@@ -10334,9 +10333,8 @@ static void spirv_compiler_emit_quad_read_across(struct spirv_compiler *compiler const struct vkd3d_shader_src_param *src = instruction->src; uint32_t type_id, direction_type_id, direction_id, val_id; @@ -7628,7 +13028,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); direction_id = map_quad_read_across_direction(instruction->opcode); direction_id = vkd3d_spirv_get_op_constant(builder, direction_type_id, direction_id); -@@ -10355,14 +10364,12 @@ static void spirv_compiler_emit_quad_read_lane_at(struct spirv_compiler *compile +@@ -10355,14 +10353,12 @@ static void spirv_compiler_emit_quad_read_lane_at(struct spirv_compiler *compile if (!register_is_constant_or_undef(&src[1].reg)) { @@ -7644,16 +13044,16 @@ index 97c0d0e73a8..8bc851f9c5b 100644 val_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); lane_id = spirv_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0); val_id = vkd3d_spirv_build_op_group_nonuniform_quad_broadcast(builder, type_id, val_id, lane_id); -@@ -10411,7 +10418,7 @@ static uint32_t spirv_compiler_emit_group_nonuniform_ballot(struct spirv_compile +@@ -10411,7 +10407,7 @@ static uint32_t spirv_compiler_emit_group_nonuniform_ballot(struct spirv_compile struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id, val_id; - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, VKD3D_VEC4_SIZE); val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); val_id = vkd3d_spirv_build_op_group_nonuniform_ballot(builder, type_id, val_id); -@@ -10470,8 +10477,7 @@ static void spirv_compiler_emit_wave_alu_op(struct spirv_compiler *compiler, +@@ -10470,8 +10466,7 @@ static void spirv_compiler_emit_wave_alu_op(struct spirv_compiler *compiler, op = map_wave_alu_op(instruction->opcode, data_type_is_floating_point(src->reg.data_type)); @@ -7663,16 +13063,16 @@ index 97c0d0e73a8..8bc851f9c5b 100644 val_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); vkd3d_spirv_enable_capability(builder, SpvCapabilityGroupNonUniformArithmetic); -@@ -10495,7 +10501,7 @@ static void spirv_compiler_emit_wave_bit_count(struct spirv_compiler *compiler, +@@ -10495,7 +10490,7 @@ static void spirv_compiler_emit_wave_bit_count(struct spirv_compiler *compiler, : SpvGroupOperationReduce; val_id = spirv_compiler_emit_group_nonuniform_ballot(compiler, instruction->src); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); val_id = vkd3d_spirv_build_op_group_nonuniform_ballot_bit_count(builder, type_id, group_op, val_id); spirv_compiler_emit_store_dst(compiler, dst, val_id); -@@ -10520,8 +10526,7 @@ static void spirv_compiler_emit_wave_read_lane_at(struct spirv_compiler *compile +@@ -10520,8 +10515,7 @@ static void spirv_compiler_emit_wave_read_lane_at(struct spirv_compiler *compile const struct vkd3d_shader_src_param *src = instruction->src; uint32_t type_id, lane_id, val_id; @@ -7682,7 +13082,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 val_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); lane_id = spirv_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0); -@@ -10548,8 +10553,7 @@ static void spirv_compiler_emit_wave_read_lane_first(struct spirv_compiler *comp +@@ -10548,8 +10542,7 @@ static void spirv_compiler_emit_wave_read_lane_first(struct spirv_compiler *comp const struct vkd3d_shader_src_param *src = instruction->src; uint32_t type_id, val_id; @@ -7692,7 +13092,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); val_id = vkd3d_spirv_build_op_group_nonuniform_broadcast_first(builder, type_id, val_id); -@@ -10608,12 +10612,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, +@@ -10608,12 +10601,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VSIR_OP_DCL_VERTICES_OUT: spirv_compiler_emit_output_vertex_count(compiler, instruction); break; @@ -7705,7 +13105,7 @@ index 97c0d0e73a8..8bc851f9c5b 100644 case VSIR_OP_DCL_GS_INSTANCES: spirv_compiler_emit_dcl_gs_instances(compiler, instruction); break; -@@ -11066,7 +11064,14 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, +@@ -11066,7 +11053,14 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, if (program->ssa_count) spirv_compiler_allocate_ssa_register_ids(compiler, program->ssa_count); if (compiler->shader_type == VKD3D_SHADER_TYPE_COMPUTE) @@ -7720,17 +13120,18 @@ index 97c0d0e73a8..8bc851f9c5b 100644 spirv_compiler_emit_global_flags(compiler, program->global_flags); spirv_compiler_emit_descriptor_declarations(compiler); -@@ -11080,7 +11085,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, +@@ -11080,8 +11074,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, { uint32_t type_id, struct_id, ptr_type_id, var_id; - type_id = vkd3d_spirv_get_type_id(builder, -+ type_id = spirv_get_type_id_for_component_type(builder, - vkd3d_component_type_from_data_type(parameter_data_type_map[parameter->data_type].type), +- vkd3d_component_type_from_data_type(parameter_data_type_map[parameter->data_type].type), ++ type_id = spirv_get_type_id(builder, parameter_data_type_map[parameter->data_type].type, parameter_data_type_map[parameter->data_type].component_count); + struct_id = vkd3d_spirv_build_op_type_struct(builder, &type_id, 1); diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index ea15c1a9ad5..ec1d8b91e09 100644 +index ea15c1a9ad5..c6d239847c8 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -665,6 +665,8 @@ struct vkd3d_shader_sm4_parser @@ -7756,7 +13157,7 @@ index ea15c1a9ad5..ec1d8b91e09 100644 icb->is_null = false; memcpy(icb->data, tokens, sizeof(*tokens) * icb_size); - shader_instruction_array_add_icb(&priv->p.program->instructions, icb); -+ shader_instruction_array_add_icb(&priv->program->instructions, icb); ++ vsir_program_add_icb(priv->program, icb); ins->declaration.icb = icb; } @@ -7906,7 +13307,35 @@ index ea15c1a9ad5..ec1d8b91e09 100644 init_sm4_lookup_tables(&sm4->lookup); -@@ -3692,7 +3695,7 @@ static void write_sm4_instruction(const struct tpf_compiler *tpf, const struct s +@@ -2973,13 +2976,13 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con + } + } + if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL +- && !sm4.has_control_point_phase && !sm4.p.failed) ++ && !sm4.has_control_point_phase && sm4.p.status >= 0) + shader_sm4_validate_default_phase_index_ranges(&sm4); + +- if (sm4.p.failed) ++ if (sm4.p.status < 0) + { + vsir_program_cleanup(program); +- return VKD3D_ERROR_INVALID_SHADER; ++ return sm4.p.status; + } + + return VKD3D_OK; +@@ -3480,7 +3483,9 @@ static uint32_t sm4_encode_register(const struct tpf_compiler *tpf, const struct + switch (sm4_swizzle_type) + { + case VKD3D_SM4_SWIZZLE_NONE: +- VKD3D_ASSERT(sm4_swizzle || register_is_constant(reg)); ++ if (register_is_constant(reg)) ++ break; ++ VKD3D_ASSERT(sm4_swizzle); + token |= (sm4_swizzle << VKD3D_SM4_WRITEMASK_SHIFT) & VKD3D_SM4_WRITEMASK_MASK; + break; + +@@ -3692,7 +3697,7 @@ static void write_sm4_instruction(const struct tpf_compiler *tpf, const struct s static void tpf_dcl_constant_buffer(const struct tpf_compiler *tpf, const struct vkd3d_shader_instruction *ins) { const struct vkd3d_shader_constant_buffer *cb = &ins->declaration.cb; @@ -7915,7 +13344,7 @@ index ea15c1a9ad5..ec1d8b91e09 100644 struct sm4_instruction instr = { -@@ -4222,6 +4225,7 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ +@@ -4222,6 +4227,7 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ case VSIR_OP_DCL: case VSIR_OP_DCL_RESOURCE_RAW: @@ -7923,7 +13352,25 @@ index ea15c1a9ad5..ec1d8b91e09 100644 case VSIR_OP_DCL_UAV_RAW: case VSIR_OP_DCL_UAV_STRUCTURED: case VSIR_OP_DCL_UAV_TYPED: -@@ -4305,6 +4309,7 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ +@@ -4242,6 +4248,7 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ + case VSIR_OP_BREAK: + case VSIR_OP_CASE: + case VSIR_OP_CONTINUE: ++ case VSIR_OP_COUNTBITS: + case VSIR_OP_CUT: + case VSIR_OP_CUT_STREAM: + case VSIR_OP_DCL_STREAM: +@@ -4267,6 +4274,9 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ + case VSIR_OP_EXP: + case VSIR_OP_F16TOF32: + case VSIR_OP_F32TOF16: ++ case VSIR_OP_FIRSTBIT_HI: ++ case VSIR_OP_FIRSTBIT_LO: ++ case VSIR_OP_FIRSTBIT_SHI: + case VSIR_OP_FRC: + case VSIR_OP_FTOI: + case VSIR_OP_FTOU: +@@ -4305,6 +4315,7 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ case VSIR_OP_LD: case VSIR_OP_LD2DMS: case VSIR_OP_LD_RAW: @@ -7932,7 +13379,7 @@ index ea15c1a9ad5..ec1d8b91e09 100644 case VSIR_OP_LOG: case VSIR_OP_LOOP: diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index 5fcc836aae1..6949c1cd38f 100644 +index 5fcc836aae1..6087df80970 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 @@ @@ -7960,7 +13407,49 @@ index 5fcc836aae1..6949c1cd38f 100644 } void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser, -@@ -1683,6 +1684,7 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh +@@ -741,7 +742,32 @@ void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_error(struct vkd3d_shader_parse + vkd3d_shader_verror(parser->message_context, &parser->location, error, format, args); + va_end(args); + +- parser->failed = true; ++ if (parser->status >= 0) ++ { ++ switch (error) ++ { ++ case VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED: ++ case VKD3D_SHADER_ERROR_HLSL_NOT_IMPLEMENTED: ++ case VKD3D_SHADER_ERROR_D3DBC_NOT_IMPLEMENTED: ++ case VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED: ++ case VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED: ++ case VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED: ++ parser->status = VKD3D_ERROR_NOT_IMPLEMENTED; ++ break; ++ case VKD3D_SHADER_ERROR_DXBC_OUT_OF_MEMORY: ++ case VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY: ++ case VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY: ++ case VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY: ++ case VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY: ++ case VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY: ++ case VKD3D_SHADER_ERROR_FX_OUT_OF_MEMORY: ++ parser->status = VKD3D_ERROR_OUT_OF_MEMORY; ++ break; ++ default: ++ parser->status = VKD3D_ERROR_INVALID_SHADER; ++ break; ++ } ++ } + } + + void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser, +@@ -1523,7 +1549,6 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte + if (context->cf_info_count) + context->cf_info[context->cf_info_count - 1].inside_block = false; + break; +- case VSIR_OP_TEX: + case VSIR_OP_TEXBEM: + case VSIR_OP_TEXBEML: + case VSIR_OP_TEXDP3TEX: +@@ -1683,6 +1708,7 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info; struct vkd3d_shader_scan_hull_shader_tessellation_info *tessellation_info; @@ -7968,7 +13457,7 @@ index 5fcc836aae1..6949c1cd38f 100644 struct vkd3d_shader_scan_descriptor_info *descriptor_info; struct vkd3d_shader_scan_signature_info *signature_info; struct vkd3d_shader_scan_context context; -@@ -1704,6 +1706,7 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh +@@ -1704,6 +1730,7 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh } tessellation_info = vkd3d_find_struct(compile_info->next, SCAN_HULL_SHADER_TESSELLATION_INFO); @@ -7976,7 +13465,7 @@ index 5fcc836aae1..6949c1cd38f 100644 vkd3d_shader_scan_context_init(&context, &program->shader_version, compile_info, add_descriptor_info ? &program->descriptors : NULL, combined_sampler_info, message_context); -@@ -1756,6 +1759,13 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh +@@ -1756,6 +1783,13 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh tessellation_info->partitioning = context.partitioning; } @@ -7990,7 +13479,7 @@ index 5fcc836aae1..6949c1cd38f 100644 if (ret < 0) { if (combined_sampler_info) -@@ -2182,6 +2192,9 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( +@@ -2182,6 +2216,9 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( VKD3D_SHADER_TARGET_D3D_BYTECODE, VKD3D_SHADER_TARGET_DXBC_TPF, VKD3D_SHADER_TARGET_FX, @@ -8000,7 +13489,7 @@ index 5fcc836aae1..6949c1cd38f 100644 }; static const enum vkd3d_shader_target_type d3dbc_types[] = -@@ -2253,6 +2266,7 @@ int vkd3d_shader_preprocess(const struct vkd3d_shader_compile_info *compile_info +@@ -2253,6 +2290,7 @@ int vkd3d_shader_preprocess(const struct vkd3d_shader_compile_info *compile_info struct vkd3d_shader_code *out, char **messages) { struct vkd3d_shader_message_context message_context; @@ -8008,7 +13497,7 @@ index 5fcc836aae1..6949c1cd38f 100644 int ret; TRACE("compile_info %p, out %p, messages %p.\n", compile_info, out, messages); -@@ -2265,7 +2279,11 @@ int vkd3d_shader_preprocess(const struct vkd3d_shader_compile_info *compile_info +@@ -2265,7 +2303,11 @@ int vkd3d_shader_preprocess(const struct vkd3d_shader_compile_info *compile_info vkd3d_shader_message_context_init(&message_context, compile_info->log_level); @@ -8021,7 +13510,7 @@ index 5fcc836aae1..6949c1cd38f 100644 vkd3d_shader_message_context_trace_messages(&message_context); if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) -@@ -2279,204 +2297,6 @@ void vkd3d_shader_set_log_callback(PFN_vkd3d_log callback) +@@ -2279,204 +2321,6 @@ void vkd3d_shader_set_log_callback(PFN_vkd3d_log callback) vkd3d_dbg_set_log_callback(callback); } @@ -8227,7 +13716,7 @@ index 5fcc836aae1..6949c1cd38f 100644 const struct vkd3d_shader_signature *input_signature, unsigned int *ret_count, struct vkd3d_shader_varying_map *varyings) diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index e758c16b3d4..c00a7825610 100644 +index e758c16b3d4..3637aa4fdb9 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -213,7 +213,7 @@ enum vkd3d_shader_error @@ -8239,17 +13728,26 @@ index e758c16b3d4..c00a7825610 100644 VKD3D_SHADER_ERROR_DXIL_INVALID_FUNCTION_DCL = 8009, VKD3D_SHADER_ERROR_DXIL_INVALID_TYPE_ID = 8010, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE = 8011, -@@ -716,7 +716,9 @@ enum vsir_data_type +@@ -226,6 +226,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES = 8018, + VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE = 8019, + VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT = 8020, ++ VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED = 8021, + + VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300, + VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301, +@@ -716,7 +717,10 @@ enum vsir_data_type VSIR_DATA_F32, VSIR_DATA_F64, ++ VSIR_DATA_I8, + VSIR_DATA_I16, VSIR_DATA_I32, + VSIR_DATA_I64, VSIR_DATA_U8, VSIR_DATA_U16, -@@ -734,10 +736,13 @@ enum vsir_data_type +@@ -734,10 +738,18 @@ enum vsir_data_type VSIR_DATA_TYPE_COUNT, }; @@ -8259,13 +13757,18 @@ index e758c16b3d4..c00a7825610 100644 { - return data_type == VSIR_DATA_I32 || data_type == VSIR_DATA_U8 || data_type == VSIR_DATA_U16 - || data_type == VSIR_DATA_U32 || data_type == VSIR_DATA_U64; -+ return data_type == VSIR_DATA_I16 || data_type == VSIR_DATA_I32 || data_type == VSIR_DATA_I64 -+ || data_type == VSIR_DATA_U8 || data_type == VSIR_DATA_U16 || data_type == VSIR_DATA_U32 ++ return data_type == VSIR_DATA_I8 ++ || data_type == VSIR_DATA_I16 ++ || data_type == VSIR_DATA_I32 ++ || data_type == VSIR_DATA_I64 ++ || data_type == VSIR_DATA_U8 ++ || data_type == VSIR_DATA_U16 ++ || data_type == VSIR_DATA_U32 + || data_type == VSIR_DATA_U64; } static inline bool data_type_is_bool(enum vsir_data_type data_type) -@@ -752,7 +757,7 @@ static inline bool data_type_is_floating_point(enum vsir_data_type data_type) +@@ -752,7 +764,7 @@ static inline bool data_type_is_floating_point(enum vsir_data_type data_type) static inline bool data_type_is_64_bit(enum vsir_data_type data_type) { @@ -8274,23 +13777,78 @@ index e758c16b3d4..c00a7825610 100644 } enum vsir_dimension -@@ -1439,15 +1444,11 @@ struct vkd3d_shader_instruction_array - struct vkd3d_shader_src_param *outpointid_param; +@@ -1357,6 +1369,13 @@ static inline bool vkd3d_shader_ver_le(const struct vkd3d_shader_version *v, uns + void vsir_instruction_init(struct vkd3d_shader_instruction *ins, + const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode opcode); + ++static inline void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *ins) ++{ ++ struct vkd3d_shader_location location = ins->location; ++ ++ vsir_instruction_init(ins, &location, VSIR_OP_NOP); ++} ++ + static inline bool vkd3d_shader_instruction_has_texel_offset(const struct vkd3d_shader_instruction *ins) + { + return ins->texel_offset.u || ins->texel_offset.v || ins->texel_offset.w; +@@ -1410,44 +1429,15 @@ struct vkd3d_shader_param_allocator + + void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, size_t count); + +-static inline struct vkd3d_shader_src_param *shader_src_param_allocator_get( +- struct vkd3d_shader_param_allocator *allocator, size_t count) +-{ +- VKD3D_ASSERT(allocator->stride == sizeof(struct vkd3d_shader_src_param)); +- return shader_param_allocator_get(allocator, count); +-} +- +-static inline struct vkd3d_shader_dst_param *shader_dst_param_allocator_get( +- struct vkd3d_shader_param_allocator *allocator, size_t count) +-{ +- VKD3D_ASSERT(allocator->stride == sizeof(struct vkd3d_shader_dst_param)); +- return shader_param_allocator_get(allocator, count); +-} +- + struct vkd3d_shader_instruction_array + { + struct vkd3d_shader_instruction *elements; + size_t capacity; + size_t count; +- +- struct vkd3d_shader_param_allocator src_params; +- struct vkd3d_shader_param_allocator dst_params; +- struct vkd3d_shader_immediate_constant_buffer **icbs; +- size_t icb_capacity; +- size_t icb_count; +- +- struct vkd3d_shader_src_param *outpointid_param; }; -bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, size_t reserve); - bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, size_t reserve); - bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, - size_t idx, size_t count); - bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, - struct vkd3d_shader_immediate_constant_buffer *icb); +-bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, size_t reserve); +-bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, +- size_t idx, size_t count); +-bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, +- struct vkd3d_shader_immediate_constant_buffer *icb); -bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions, - size_t dst, size_t src); -void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions); ++struct vkd3d_shader_instruction *shader_instruction_array_append(struct vkd3d_shader_instruction_array *array); ++bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, size_t idx, size_t count); struct vsir_program_iterator { -@@ -1510,6 +1511,38 @@ static inline bool vsir_program_iterator_insert_after(struct vsir_program_iterat +@@ -1503,13 +1493,46 @@ static inline struct vkd3d_shader_instruction *vsir_program_iterator_prev( + } + + /* When insertion takes place, argument `it' is updated to point to the same +- * instruction as before the insertion, but all other iterators and pointers +- * to the same container are invalidated and cannot be used any more. */ ++ * instruction as before the insertion, but all existing pointers to the same ++ * container, as well as any iterators pointing to instructions after the ++ * insertion point should be considered invalid. */ + static inline bool vsir_program_iterator_insert_after(struct vsir_program_iterator *it, size_t count) + { return shader_instruction_array_insert_at(it->array, it->idx + 1, count); } @@ -8329,12 +13887,79 @@ index e758c16b3d4..c00a7825610 100644 enum vkd3d_shader_config_flags { VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION = 0x00000001, -@@ -1651,13 +1684,12 @@ struct vkd3d_shader_parser +@@ -1575,7 +1598,7 @@ struct vsir_program + unsigned int input_control_point_count, output_control_point_count; + struct vsir_thread_group_size thread_group_size; + unsigned int flat_constant_count[3]; +- unsigned int block_count; ++ unsigned int block_count; /* maximum block count in any function */ + unsigned int temp_count; + unsigned int ssa_count; + enum vsir_global_flags global_flags; +@@ -1599,12 +1622,21 @@ struct vsir_program + struct vkd3d_shader_source_list source_files; + const char **block_names; + size_t block_name_count; ++ ++ struct vkd3d_shader_immediate_constant_buffer **icbs; ++ size_t icb_capacity; ++ size_t icb_count; ++ ++ struct vkd3d_shader_param_allocator src_params; ++ struct vkd3d_shader_param_allocator dst_params; + }; + + enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, + struct vkd3d_shader_message_context *message_context); + enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, + struct vkd3d_shader_message_context *message_context); ++ ++bool vsir_program_add_icb(struct vsir_program *program, struct vkd3d_shader_immediate_constant_buffer *icb); + void vsir_program_cleanup(struct vsir_program *program); + const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( + const struct vsir_program *program, enum vkd3d_shader_parameter_name name); +@@ -1627,37 +1659,39 @@ bool vsir_instruction_init_with_params(struct vsir_program *program, + + static inline struct vkd3d_shader_instruction *vsir_program_append(struct vsir_program *program) + { +- struct vkd3d_shader_instruction_array *array = &program->instructions; +- +- if (!shader_instruction_array_insert_at(array, array->count, 1)) +- return NULL; +- +- return &array->elements[array->count - 1]; ++ return shader_instruction_array_append(&program->instructions); + } + + static inline struct vkd3d_shader_dst_param *vsir_program_get_dst_params( + struct vsir_program *program, unsigned int count) + { +- return shader_dst_param_allocator_get(&program->instructions.dst_params, count); ++ struct vkd3d_shader_param_allocator *allocator = &program->dst_params; ++ ++ VKD3D_ASSERT(allocator->stride == sizeof(struct vkd3d_shader_dst_param)); ++ ++ return shader_param_allocator_get(allocator, count); + } + + static inline struct vkd3d_shader_src_param *vsir_program_get_src_params( + struct vsir_program *program, unsigned int count) + { +- return shader_src_param_allocator_get(&program->instructions.src_params, count); ++ struct vkd3d_shader_param_allocator *allocator = &program->src_params; ++ ++ VKD3D_ASSERT(allocator->stride == sizeof(struct vkd3d_shader_src_param)); ++ ++ return shader_param_allocator_get(allocator, count); + } + + struct vkd3d_shader_parser { struct vkd3d_shader_message_context *message_context; struct vkd3d_shader_location location; - struct vsir_program *program; - bool failed; +- bool failed; ++ enum vkd3d_result status; }; void vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser, @@ -8344,7 +13969,7 @@ index e758c16b3d4..c00a7825610 100644 struct vkd3d_shader_message_context *message_context, const char *source_name); void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser, enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4); -@@ -1852,20 +1884,28 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty +@@ -1852,20 +1886,28 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty { case VSIR_DATA_BOOL: return VKD3D_SHADER_COMPONENT_BOOL; @@ -8375,7 +14000,7 @@ index e758c16b3d4..c00a7825610 100644 default: FIXME("Unhandled data type %#x.\n", data_type); /* fall-through */ -@@ -1878,23 +1918,41 @@ static inline enum vsir_data_type vsir_data_type_from_component_type(enum vkd3d_ +@@ -1878,23 +1920,41 @@ static inline enum vsir_data_type vsir_data_type_from_component_type(enum vkd3d_ { switch (component_type) { @@ -8487,10 +14112,44 @@ index f2967835b62..fea8c2440d1 100644 return hr; diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c -index 074d8430585..d933e7ec463 100644 +index 074d8430585..69f42280e8a 100644 --- a/libs/vkd3d/libs/vkd3d/command.c +++ b/libs/vkd3d/libs/vkd3d/command.c -@@ -3049,7 +3049,7 @@ static void d3d12_command_list_update_descriptor_table(struct d3d12_command_list +@@ -2688,32 +2688,12 @@ static void d3d12_command_list_reset_state(struct d3d12_command_list *list, + static HRESULT STDMETHODCALLTYPE d3d12_command_list_Reset(ID3D12GraphicsCommandList6 *iface, + ID3D12CommandAllocator *allocator, ID3D12PipelineState *initial_pipeline_state) + { +- struct d3d12_command_allocator *allocator_impl = unsafe_impl_from_ID3D12CommandAllocator(allocator); + struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList6(iface); +- HRESULT hr; + + TRACE("iface %p, allocator %p, initial_pipeline_state %p.\n", + iface, allocator, initial_pipeline_state); + +- if (!allocator_impl) +- { +- WARN("Command allocator is NULL.\n"); +- return E_INVALIDARG; +- } +- +- if (list->is_recording) +- { +- WARN("Command list is in the recording state.\n"); +- return E_FAIL; +- } +- +- if (SUCCEEDED(hr = d3d12_command_allocator_allocate_command_buffer(allocator_impl, list))) +- { +- list->allocator = allocator_impl; +- d3d12_command_list_reset_state(list, initial_pipeline_state); +- } +- +- return hr; ++ return d3d12_command_list_reset(list, allocator, initial_pipeline_state); + } + + static void STDMETHODCALLTYPE d3d12_command_list_ClearState(ID3D12GraphicsCommandList6 *iface, +@@ -3049,7 +3029,7 @@ static void d3d12_command_list_update_descriptor_table(struct d3d12_command_list if (descriptor_count > range->vk_binding_count) { @@ -8499,6 +14158,159 @@ index 074d8430585..d933e7ec463 100644 descriptor_count, range->vk_binding_count); descriptor_count = range->vk_binding_count; } +@@ -6405,9 +6385,8 @@ static struct d3d12_command_list *unsafe_impl_from_ID3D12CommandList(ID3D12Comma + return CONTAINING_RECORD(iface, struct d3d12_command_list, ID3D12GraphicsCommandList6_iface); + } + +-static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, struct d3d12_device *device, +- D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_allocator *allocator, +- ID3D12PipelineState *initial_pipeline_state) ++static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, ++ struct d3d12_device *device, D3D12_COMMAND_LIST_TYPE type) + { + HRESULT hr; + +@@ -6421,31 +6400,37 @@ static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, struct d + + d3d12_device_add_ref(list->device = device); + +- list->allocator = allocator; ++ return hr; ++} + +- list->descriptor_heap_count = 0; ++HRESULT d3d12_command_list_create(struct d3d12_device *device, UINT node_mask, ++ D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_list **list) ++{ ++ struct d3d12_command_list *object; ++ HRESULT hr; + +- if (SUCCEEDED(hr = d3d12_command_allocator_allocate_command_buffer(allocator, list))) +- { +- list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_GRAPHICS].vk_uav_counter_views = NULL; +- list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_COMPUTE].vk_uav_counter_views = NULL; +- d3d12_command_list_reset_state(list, initial_pipeline_state); +- } +- else ++ debug_ignored_node_mask(node_mask); ++ ++ if (!(object = vkd3d_calloc(1, sizeof(*object)))) ++ return E_OUTOFMEMORY; ++ ++ if (FAILED(hr = d3d12_command_list_init(object, device, type))) + { +- vkd3d_private_store_destroy(&list->private_store); +- d3d12_device_release(device); ++ vkd3d_free(object); ++ return hr; + } + +- return hr; ++ TRACE("Created command list %p.\n", object); ++ ++ *list = object; ++ ++ return S_OK; + } + +-HRESULT d3d12_command_list_create(struct d3d12_device *device, +- UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *allocator_iface, +- ID3D12PipelineState *initial_pipeline_state, struct d3d12_command_list **list) ++HRESULT d3d12_command_list_reset(struct d3d12_command_list *list, ID3D12CommandAllocator *allocator_iface, ++ ID3D12PipelineState *initial_pipeline_state) + { + struct d3d12_command_allocator *allocator; +- struct d3d12_command_list *object; + HRESULT hr; + + if (!(allocator = unsafe_impl_from_ID3D12CommandAllocator(allocator_iface))) +@@ -6454,29 +6439,26 @@ HRESULT d3d12_command_list_create(struct d3d12_device *device, + return E_INVALIDARG; + } + +- if (allocator->type != type) ++ if (allocator->type != list->type) + { + WARN("Command list types do not match (allocator %#x, list %#x).\n", +- allocator->type, type); ++ allocator->type, list->type); + return E_INVALIDARG; + } + +- debug_ignored_node_mask(node_mask); +- +- if (!(object = vkd3d_malloc(sizeof(*object)))) +- return E_OUTOFMEMORY; +- +- if (FAILED(hr = d3d12_command_list_init(object, device, type, allocator, initial_pipeline_state))) ++ if (list->is_recording) + { +- vkd3d_free(object); +- return hr; ++ WARN("Command list is in the recording state.\n"); ++ return E_FAIL; + } + +- TRACE("Created command list %p.\n", object); +- +- *list = object; ++ if (SUCCEEDED(hr = d3d12_command_allocator_allocate_command_buffer(allocator, list))) ++ { ++ list->allocator = allocator; ++ d3d12_command_list_reset_state(list, initial_pipeline_state); ++ } + +- return S_OK; ++ return hr; + } + + /* ID3D12CommandQueue */ +diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c +index 67f84aafa29..6af5e2a5c7d 100644 +--- a/libs/vkd3d/libs/vkd3d/device.c ++++ b/libs/vkd3d/libs/vkd3d/device.c +@@ -3271,10 +3271,15 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList(ID3D12Device9 *i + iface, node_mask, type, command_allocator, + initial_pipeline_state, debugstr_guid(riid), command_list); + +- if (FAILED(hr = d3d12_command_list_create(device, node_mask, type, command_allocator, +- initial_pipeline_state, &object))) ++ if (FAILED(hr = d3d12_command_list_create(device, node_mask, type, &object))) + return hr; + ++ if (FAILED(hr = d3d12_command_list_reset(object, command_allocator, initial_pipeline_state))) ++ { ++ ID3D12GraphicsCommandList6_Release(&object->ID3D12GraphicsCommandList6_iface); ++ return hr; ++ } ++ + return return_interface(&object->ID3D12GraphicsCommandList6_iface, + &IID_ID3D12GraphicsCommandList6, riid, command_list); + } +@@ -5082,10 +5087,21 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList1(ID3D12Device9 * + UINT node_mask, D3D12_COMMAND_LIST_TYPE type, D3D12_COMMAND_LIST_FLAGS flags, + REFIID iid, void **command_list) + { +- FIXME("iface %p, node_mask 0x%08x, type %#x, flags %#x, iid %s, command_list %p stub!\n", ++ struct d3d12_device *device = impl_from_ID3D12Device9(iface); ++ struct d3d12_command_list *object; ++ HRESULT hr; ++ ++ TRACE("iface %p, node_mask 0x%08x, type %#x, flags %#x, iid %s, command_list %p.\n", + iface, node_mask, type, flags, debugstr_guid(iid), command_list); + +- return E_NOTIMPL; ++ if (flags) ++ FIXME("Ignoring flags %#x.\n", flags); ++ ++ if (FAILED(hr = d3d12_command_list_create(device, node_mask, type, &object))) ++ return hr; ++ ++ return return_interface(&object->ID3D12GraphicsCommandList6_iface, ++ &IID_ID3D12GraphicsCommandList6, iid, command_list); + } + + static HRESULT STDMETHODCALLTYPE d3d12_device_CreateProtectedResourceSession(ID3D12Device9 *iface, diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c index 6bbd6533b74..b6055a50a99 100644 --- a/libs/vkd3d/libs/vkd3d/state.c @@ -8551,6 +14363,22 @@ index c2832a61f67..2d0510e5456 100644 #undef FLAG_TO_STR if (flags) FIXME("Unrecognized flag(s) %#x.\n", flags); +diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +index 9fb6834158f..0a8c5aef674 100644 +--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h ++++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +@@ -1327,8 +1327,9 @@ struct d3d12_command_list + }; + + HRESULT d3d12_command_list_create(struct d3d12_device *device, +- UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *allocator_iface, +- ID3D12PipelineState *initial_pipeline_state, struct d3d12_command_list **list); ++ UINT node_mask, D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_list **list); ++HRESULT d3d12_command_list_reset(struct d3d12_command_list *list, ++ ID3D12CommandAllocator *allocator_iface, ID3D12PipelineState *initial_pipeline_state); + + struct vkd3d_queue + { -- 2.51.0 diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-cd64aa69c886c7dd7148072ee69b6e70bff.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-cd64aa69c886c7dd7148072ee69b6e70bff.patch new file mode 100644 index 00000000..c6f2fc78 --- /dev/null +++ b/patches/vkd3d-latest/0002-Updated-vkd3d-to-cd64aa69c886c7dd7148072ee69b6e70bff.patch @@ -0,0 +1,1571 @@ +From 24d99375765726eaf4253baa12237035ef1f3ef2 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Tue, 7 Oct 2025 08:00:36 +1100 +Subject: [PATCH] Updated vkd3d to cd64aa69c886c7dd7148072ee69b6e70bff2f064. + +--- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 57 ++- + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 1 + + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 28 +- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 51 ++- + libs/vkd3d/libs/vkd3d-shader/ir.c | 431 +++++++++++++++++- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 171 ++++--- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 14 +- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 2 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 5 +- + 9 files changed, 616 insertions(+), 144 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index fbf9de20278..2379efd3a02 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -659,7 +659,7 @@ static unsigned int make_mask_contiguous(unsigned int mask) + + static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool output, + const char *name, unsigned int index, enum vkd3d_shader_sysval_semantic sysval, +- unsigned int register_index, bool is_dcl, unsigned int mask) ++ unsigned int register_index, bool is_dcl, unsigned int mask, uint32_t dst_modifiers) + { + struct vsir_program *program = sm1->program; + struct shader_signature *signature; +@@ -695,7 +695,8 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp + element->mask = make_mask_contiguous(mask); + element->used_mask = is_dcl ? 0 : mask; + if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output) +- element->interpolation_mode = VKD3DSIM_LINEAR; ++ element->interpolation_mode = (dst_modifiers & VKD3DSPDM_MSAMPCENTROID) ++ ? VKD3DSIM_LINEAR_CENTROID : VKD3DSIM_LINEAR; + + return true; + } +@@ -748,7 +749,7 @@ static void add_signature_mask(struct vkd3d_shader_sm1_parser *sm1, bool output, + } + + static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *sm1, +- const struct vkd3d_shader_register *reg, bool is_dcl, unsigned int mask) ++ const struct vkd3d_shader_register *reg, bool is_dcl, unsigned int mask, uint32_t dst_modifiers) + { + const struct vkd3d_shader_version *version = &sm1->program->shader_version; + unsigned int register_index = reg->idx_count > 0 ? reg->idx[0].offset : 0; +@@ -757,7 +758,8 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * + { + case VKD3DSPR_TEMP: + if (version->type == VKD3D_SHADER_TYPE_PIXEL && version->major == 1 && !register_index) +- return add_signature_element(sm1, true, "COLOR", 0, VKD3D_SHADER_SV_TARGET, 0, is_dcl, mask); ++ return add_signature_element(sm1, true, "COLOR", 0, VKD3D_SHADER_SV_TARGET, ++ 0, is_dcl, mask, dst_modifiers); + return true; + + case VKD3DSPR_INPUT: +@@ -769,15 +771,15 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * + return true; + } + return add_signature_element(sm1, false, "COLOR", register_index, +- VKD3D_SHADER_SV_NONE, SM1_COLOR_REGISTER_OFFSET + register_index, is_dcl, mask); ++ VKD3D_SHADER_SV_NONE, SM1_COLOR_REGISTER_OFFSET + register_index, is_dcl, mask, dst_modifiers); + + case VKD3DSPR_TEXTURE: + return add_signature_element(sm1, false, "TEXCOORD", register_index, +- VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask); ++ VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask, dst_modifiers); + + case VKD3DSPR_TEXCRDOUT: + return add_signature_element(sm1, true, "TEXCOORD", register_index, +- VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask); ++ VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask, dst_modifiers); + + case VKD3DSPR_OUTPUT: + if (version->type == VKD3D_SHADER_TYPE_VERTEX) +@@ -789,30 +791,30 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * + + case VKD3DSPR_ATTROUT: + return add_signature_element(sm1, true, "COLOR", register_index, +- VKD3D_SHADER_SV_NONE, SM1_COLOR_REGISTER_OFFSET + register_index, is_dcl, mask); ++ VKD3D_SHADER_SV_NONE, SM1_COLOR_REGISTER_OFFSET + register_index, is_dcl, mask, dst_modifiers); + + case VKD3DSPR_COLOROUT: + return add_signature_element(sm1, true, "COLOR", register_index, +- VKD3D_SHADER_SV_TARGET, register_index, is_dcl, mask); ++ VKD3D_SHADER_SV_TARGET, register_index, is_dcl, mask, dst_modifiers); + + case VKD3DSPR_DEPTHOUT: + return add_signature_element(sm1, true, "DEPTH", 0, +- VKD3D_SHADER_SV_DEPTH, register_index, is_dcl, 0x1); ++ VKD3D_SHADER_SV_DEPTH, register_index, is_dcl, 0x1, dst_modifiers); + + case VKD3DSPR_RASTOUT: + switch (register_index) + { + case 0: +- return add_signature_element(sm1, true, "POSITION", 0, +- VKD3D_SHADER_SV_POSITION, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, mask); ++ return add_signature_element(sm1, true, "POSITION", 0, VKD3D_SHADER_SV_POSITION, ++ SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, mask, dst_modifiers); + + case 1: +- return add_signature_element(sm1, true, "FOG", 0, +- VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1); ++ return add_signature_element(sm1, true, "FOG", 0, VKD3D_SHADER_SV_NONE, ++ SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1, dst_modifiers); + + case 2: +- return add_signature_element(sm1, true, "PSIZE", 0, +- VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1); ++ return add_signature_element(sm1, true, "PSIZE", 0, VKD3D_SHADER_SV_NONE, ++ SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1, dst_modifiers); + + default: + vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX, +@@ -825,11 +827,11 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * + { + case 0: + return add_signature_element(sm1, false, "VPOS", 0, +- VKD3D_SHADER_SV_POSITION, register_index, is_dcl, mask); ++ VKD3D_SHADER_SV_POSITION, register_index, is_dcl, mask, dst_modifiers); + + case 1: + return add_signature_element(sm1, false, "VFACE", 0, +- VKD3D_SHADER_SV_IS_FRONT_FACE, register_index, is_dcl, 0x1); ++ VKD3D_SHADER_SV_IS_FRONT_FACE, register_index, is_dcl, 0x1, dst_modifiers); + + default: + vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX, +@@ -849,6 +851,7 @@ static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser * + const struct vkd3d_shader_register *reg = &semantic->resource.reg.reg; + enum vkd3d_shader_sysval_semantic sysval = VKD3D_SHADER_SV_NONE; + unsigned int mask = semantic->resource.reg.write_mask; ++ uint32_t modifiers = semantic->resource.reg.modifiers; + bool output; + + static const char sm1_semantic_names[][13] = +@@ -874,11 +877,11 @@ static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser * + else if (reg->type == VKD3DSPR_INPUT || reg->type == VKD3DSPR_TEXTURE) + output = false; + else /* vpos and vface don't have a semantic. */ +- return add_signature_element_from_register(sm1, reg, true, mask); ++ return add_signature_element_from_register(sm1, reg, true, mask, modifiers); + + /* sm2 pixel shaders use DCL but don't provide a semantic. */ + if (version->type == VKD3D_SHADER_TYPE_PIXEL && version->major == 2) +- return add_signature_element_from_register(sm1, reg, true, mask); ++ return add_signature_element_from_register(sm1, reg, true, mask, modifiers); + + /* With the exception of vertex POSITION output, none of these are system + * values. Pixel POSITION input is not equivalent to SV_Position; the closer +@@ -887,8 +890,8 @@ static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser * + && output && semantic->usage == VKD3D_DECL_USAGE_POSITION) + sysval = VKD3D_SHADER_SV_POSITION; + +- return add_signature_element(sm1, output, sm1_semantic_names[semantic->usage], +- semantic->usage_idx, sysval, reg->idx[0].offset, true, mask); ++ return add_signature_element(sm1, output, sm1_semantic_names[semantic->usage], semantic->usage_idx, sysval, ++ reg->idx[0].offset, true, mask, modifiers); + } + + static void record_constant_register(struct vkd3d_shader_sm1_parser *sm1, +@@ -932,7 +935,7 @@ static void shader_sm1_scan_register(struct vkd3d_shader_sm1_parser *sm1, + break; + } + +- add_signature_element_from_register(sm1, reg, false, mask); ++ add_signature_element_from_register(sm1, reg, false, mask, 0); + } + + /* Read a parameter token from the input stream, and possibly a relative +@@ -1990,6 +1993,9 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str + + switch (ins->opcode) + { ++ case VSIR_OP_NOP: ++ break; ++ + case VSIR_OP_DEF: + d3dbc_write_vsir_def(d3dbc, ins); + break; +@@ -2097,6 +2103,8 @@ static void d3dbc_write_semantic_dcl(struct d3dbc_compiler *d3dbc, + put_u32(buffer, token); + + reg.write_mask = element->mask; ++ if (element->interpolation_mode == VKD3DSIM_LINEAR_CENTROID) ++ reg.modifiers |= VKD3DSPDM_MSAMPCENTROID; + write_sm1_dst_register(buffer, ®); + } + +@@ -2147,6 +2155,9 @@ int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, + struct vkd3d_bytecode_buffer *buffer = &d3dbc.buffer; + int result; + ++ if ((result = vsir_program_optimize(program, config_flags, compile_info, message_context))) ++ return result; ++ + if ((result = vsir_allocate_temp_registers(program, message_context))) + return result; + +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +index 8dbfd062177..6c6243db799 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +@@ -248,6 +248,7 @@ struct hlsl_semantic + const char *name; + uint32_t index; + uint32_t stream_index; ++ uint32_t modifiers; + + /* Name exactly as it appears in the sources. */ + const char *raw_name; +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index d3004d7cc8a..37b116bed40 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -1082,7 +1082,7 @@ static bool gen_struct_fields(struct hlsl_ctx *ctx, struct parse_fields *fields, + field->loc = v->loc; + field->name = v->name; + field->semantic = v->semantic; +- field->storage_modifiers = modifiers; ++ field->storage_modifiers = modifiers | v->semantic.modifiers; + if (v->initializer.args_count) + { + hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Illegal initializer on a struct field."); +@@ -1211,16 +1211,17 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i + static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters *parameters, + struct parse_parameter *param, const struct vkd3d_shader_location *loc) + { ++ uint32_t modifiers = param->modifiers | param->semantic.modifiers; + struct hlsl_ir_var *var; + + if (param->type->class == HLSL_CLASS_MATRIX) + VKD3D_ASSERT(param->type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK); + +- if ((param->modifiers & HLSL_STORAGE_OUT) && (param->modifiers & HLSL_STORAGE_UNIFORM)) ++ if ((modifiers & HLSL_STORAGE_OUT) && (modifiers & HLSL_STORAGE_UNIFORM)) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Parameter '%s' is declared as both \"out\" and \"uniform\".", param->name); + +- if ((param->modifiers & HLSL_STORAGE_OUT) && !(param->modifiers & HLSL_STORAGE_IN) ++ if ((modifiers & HLSL_STORAGE_OUT) && !(modifiers & HLSL_STORAGE_IN) + && (param->type->modifiers & HLSL_MODIFIER_CONST)) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Parameter '%s' is declared as both \"out\" and \"const\".", param->name); +@@ -1234,14 +1235,14 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_MISSING_INITIALIZER, + "Missing default value for parameter '%s'.", param->name); + +- if (param->initializer.args_count && (param->modifiers & HLSL_STORAGE_OUT)) ++ if (param->initializer.args_count && (modifiers & HLSL_STORAGE_OUT)) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Output parameter '%s' has a default value.", param->name); + + if (hlsl_get_stream_output_type(param->type)) + check_invalid_stream_output_object(ctx, param->type, param->name, loc); + +- if (!(var = hlsl_new_var(ctx, param->name, param->type, loc, ¶m->semantic, param->modifiers, ++ if (!(var = hlsl_new_var(ctx, param->name, param->type, loc, ¶m->semantic, modifiers, + ¶m->reg_reservation))) + return false; + var->is_param = 1; +@@ -2408,10 +2409,10 @@ static void check_invalid_object_fields(struct hlsl_ctx *ctx, const struct hlsl_ + + static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) + { ++ uint32_t modifiers = v->modifiers | v->semantic.modifiers; + struct hlsl_type *basic_type = v->basic_type; + struct hlsl_ir_function_decl *func; + struct hlsl_semantic new_semantic; +- uint32_t modifiers = v->modifiers; + bool unbounded_res_array = false; + bool constant_buffer = false; + struct hlsl_ir_var *var; +@@ -7847,15 +7848,28 @@ colon_attributes: + semantic: + ':' any_identifier + { ++ static const char *centroid_suffix = "_centroid"; ++ uint32_t modifiers = 0; ++ size_t len; + char *p; + + if (!($$.raw_name = hlsl_strdup(ctx, $2))) + YYABORT; + +- for (p = $2 + strlen($2); p > $2 && isdigit(p[-1]); --p) ++ len = strlen($2); ++ if (ascii_strncasecmp($2, "sv_", 3) ++ && len > strlen(centroid_suffix) ++ && !ascii_strcasecmp($2 + (len - strlen(centroid_suffix)), centroid_suffix)) ++ { ++ modifiers = HLSL_STORAGE_CENTROID; ++ len -= strlen(centroid_suffix); ++ } ++ ++ for (p = $2 + len; p > $2 && isdigit(p[-1]); --p) + ; + $$.name = $2; + $$.index = atoi(p); ++ $$.modifiers = modifiers; + $$.reported_missing = false; + $$.reported_duplicated_output_next_index = 0; + $$.reported_duplicated_input_incompatible_next_index = 0; +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index 2138c3776a7..d22330cedb7 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -6756,8 +6756,8 @@ static void allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_block *bod + allocate_temp_registers_recurse(ctx, body); + } + +-static enum vkd3d_shader_interpolation_mode sm4_get_interpolation_mode(struct hlsl_type *type, +- unsigned int storage_modifiers) ++static enum vkd3d_shader_interpolation_mode get_interpolation_mode(const struct vkd3d_shader_version *version, ++ struct hlsl_type *type, unsigned int storage_modifiers) + { + unsigned int i; + +@@ -6779,6 +6779,9 @@ static enum vkd3d_shader_interpolation_mode sm4_get_interpolation_mode(struct hl + + VKD3D_ASSERT(hlsl_is_numeric_type(type)); + ++ if (version->major < 4) ++ storage_modifiers &= HLSL_STORAGE_LINEAR | HLSL_STORAGE_CENTROID; ++ + if ((storage_modifiers & HLSL_STORAGE_NOINTERPOLATION) + || base_type_get_semantic_equivalent(type->e.numeric.type) == HLSL_TYPE_UINT) + return VKD3DSIM_CONSTANT; +@@ -6885,12 +6888,11 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var + { + unsigned int component_count = is_primitive + ? var->data_type->e.array.type->e.numeric.dimx : var->data_type->e.numeric.dimx; +- int mode = (ctx->profile->major_version < 4) +- ? 0 : sm4_get_interpolation_mode(var->data_type, var->storage_modifiers); + unsigned int reg_size = optimize ? component_count : 4; ++ int mode = VKD3DSIM_NONE; + +- if (special_interpolation) +- mode = VKD3DSIM_NONE; ++ if (version.major >= 4 && !special_interpolation) ++ mode = get_interpolation_mode(&version, var->data_type, var->storage_modifiers); + + var->regs[HLSL_REGSET_NUMERIC] = allocate_register(ctx, allocator, + reg_size, component_count, mode, var->force_align, vip_allocation); +@@ -8582,6 +8584,7 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog + struct shader_signature *signature, bool output, struct hlsl_ir_var *var) + { + enum vkd3d_shader_component_type component_type = VKD3D_SHADER_COMPONENT_VOID; ++ enum vkd3d_shader_interpolation_mode interpolation_mode = VKD3DSIM_NONE; + bool is_primitive = hlsl_type_is_primitive_array(var->data_type); + enum vkd3d_shader_sysval_semantic sysval = VKD3D_SHADER_SV_NONE; + unsigned int register_index, mask, use_mask; +@@ -8589,6 +8592,9 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog + enum vkd3d_shader_register_type type; + struct signature_element *element; + ++ if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output) ++ interpolation_mode = get_interpolation_mode(&program->shader_version, var->data_type, var->storage_modifiers); ++ + if (hlsl_version_ge(ctx, 4, 0)) + { + struct vkd3d_string_buffer *string; +@@ -8668,6 +8674,13 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog + || (type == VKD3DSPR_INPUT && program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL)) + register_index += SM1_COLOR_REGISTER_OFFSET; + } ++ ++ if (interpolation_mode == VKD3DSIM_LINEAR_CENTROID ++ && (vkd3d_shader_ver_ge(&program->shader_version, 3, 0) || type != VKD3DSPR_TEXTURE)) ++ { ++ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, ++ "The centroid interpolation mode is not supported by the '%s' semantic.", var->semantic.name); ++ } + } + else + { +@@ -8735,13 +8748,7 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog + element->register_count = 1; + element->mask = mask; + element->used_mask = use_mask; +- if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output) +- { +- if (program->shader_version.major >= 4) +- element->interpolation_mode = sm4_get_interpolation_mode(var->data_type, var->storage_modifiers); +- else +- element->interpolation_mode = VKD3DSIM_LINEAR; +- } ++ element->interpolation_mode = interpolation_mode; + + switch (var->data_type->e.numeric.type) + { +@@ -9133,6 +9140,8 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p + reg->type = VKD3DSPR_RESOURCE; + reg->dimension = VSIR_DIMENSION_VEC4; + reg->idx[0].offset = var->regs[HLSL_REGSET_TEXTURES].id; ++ if (vkd3d_shader_ver_le(version, 5, 0)) ++ reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref); + reg->idx[1].offset = var->regs[HLSL_REGSET_TEXTURES].index; + reg->idx[1].offset += hlsl_offset_from_deref_safe(ctx, deref); + reg->idx_count = 2; +@@ -9144,6 +9153,8 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p + reg->type = VKD3DSPR_UAV; + reg->dimension = VSIR_DIMENSION_VEC4; + reg->idx[0].offset = var->regs[HLSL_REGSET_UAVS].id; ++ if (vkd3d_shader_ver_le(version, 5, 0)) ++ reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref); + reg->idx[1].offset = var->regs[HLSL_REGSET_UAVS].index; + reg->idx[1].offset += hlsl_offset_from_deref_safe(ctx, deref); + reg->idx_count = 2; +@@ -9155,6 +9166,8 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p + reg->type = VKD3DSPR_SAMPLER; + reg->dimension = VSIR_DIMENSION_NONE; + reg->idx[0].offset = var->regs[HLSL_REGSET_SAMPLERS].id; ++ if (vkd3d_shader_ver_le(version, 5, 0)) ++ reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref); + reg->idx[1].offset = var->regs[HLSL_REGSET_SAMPLERS].index; + reg->idx[1].offset += hlsl_offset_from_deref_safe(ctx, deref); + reg->idx_count = 2; +@@ -10801,7 +10814,7 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs + dst_param->write_mask = write_mask; + + if (var->is_input_semantic && version->type == VKD3D_SHADER_TYPE_PIXEL) +- ins->flags = sm4_get_interpolation_mode(var->data_type, var->storage_modifiers); ++ ins->flags = get_interpolation_mode(version, var->data_type, var->storage_modifiers); + } + + static void sm4_generate_vsir_instr_dcl_temps(struct hlsl_ctx *ctx, struct vsir_program *program, +@@ -12530,7 +12543,7 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un + extern_resources[*count].component_type = component_type; + + extern_resources[*count].regset = regset; +- extern_resources[*count].id = var->regs[regset].id; ++ extern_resources[*count].id = var->regs[regset].id + regset_offset; + extern_resources[*count].space = var->regs[regset].space; + extern_resources[*count].index = var->regs[regset].index + regset_offset; + extern_resources[*count].bind_count = 1; +@@ -12765,7 +12778,7 @@ static void sm4_generate_vsir_add_dcl_sampler(struct hlsl_ctx *ctx, + ins->declaration.sampler.range.last = array_last; + ins->declaration.sampler.range.space = resource->space; + +- src_param->reg.idx[0].offset = resource->id; ++ src_param->reg.idx[0].offset = resource->id + i; + src_param->reg.idx[1].offset = array_first; + src_param->reg.idx[2].offset = array_last; + src_param->reg.idx_count = 3; +@@ -12923,13 +12936,11 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, + vsir_resource->range.last = array_last; + vsir_resource->range.space = resource->space; + +- vsir_resource->reg.reg.idx[0].offset = resource->id; ++ vsir_resource->reg.reg.idx[0].offset = resource->id + i; + vsir_resource->reg.reg.idx[1].offset = array_first; + vsir_resource->reg.reg.idx[2].offset = array_last; + vsir_resource->reg.reg.idx_count = 3; + +- ins->resource_type = sm4_generate_vsir_get_resource_type(resource->component_type); +- + if (component_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) + { + ins->raw = true; +@@ -12942,6 +12953,8 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, + } + else + { ++ ins->declaration.semantic.resource_type = sm4_generate_vsir_get_resource_type(resource->component_type); ++ + for (unsigned int j = 0; j < 4; ++j) + ins->declaration.semantic.resource_data_type[j] = sm4_generate_vsir_get_format_type(component_type); + +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 453b79c75d2..670f6c31cf8 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -28,6 +28,7 @@ struct vsir_transformation_context + const struct vkd3d_shader_compile_info *compile_info; + struct vkd3d_shader_message_context *message_context; + struct vkd3d_shader_location null_location; ++ bool progress; + }; + + static void vsir_transformation_context_init(struct vsir_transformation_context *ctx, +@@ -8850,7 +8851,7 @@ struct liveness_tracker + bool written; + bool fixed_mask; + uint8_t mask; +- unsigned int first_write, last_access; ++ unsigned int first_write, last_access, last_read; + } *ssa_regs, *temp_regs; + }; + +@@ -8864,9 +8865,15 @@ static void liveness_track_src(struct liveness_tracker *tracker, + } + + if (src->reg.type == VKD3DSPR_SSA) ++ { ++ tracker->ssa_regs[src->reg.idx[0].offset].last_read = index; + tracker->ssa_regs[src->reg.idx[0].offset].last_access = index; ++ } + else if (src->reg.type == VKD3DSPR_TEMP) ++ { ++ tracker->temp_regs[src->reg.idx[0].offset].last_read = index; + tracker->temp_regs[src->reg.idx[0].offset].last_access = index; ++ } + } + + static void liveness_track_dst(struct liveness_tracker *tracker, struct vkd3d_shader_dst_param *dst, +@@ -9020,6 +9027,8 @@ static enum vkd3d_result track_liveness(struct vsir_program *program, struct liv + reg->first_write = loop_start; + if (reg->last_access < i) + reg->last_access = i; ++ if (reg->last_read < i) ++ reg->last_read = i; + } + + for (unsigned int j = 0; j < program->temp_count; ++j) +@@ -9030,6 +9039,8 @@ static enum vkd3d_result track_liveness(struct vsir_program *program, struct liv + reg->first_write = loop_start; + if (reg->last_access < i) + reg->last_access = i; ++ if (reg->last_read < i) ++ reg->last_read = i; + } + } + } +@@ -12888,6 +12899,8 @@ static void vsir_transform_( + struct vsir_transformation_context *ctx, const char *step_name, + enum vkd3d_result (*step)(struct vsir_program *program, struct vsir_transformation_context *ctx)) + { ++ ctx->progress = false; ++ + if (ctx->result < 0) + return; + +@@ -12905,6 +12918,422 @@ static void vsir_transform_( + } + } + ++static bool vsir_instruction_has_side_effects(const struct vkd3d_shader_instruction *ins) ++{ ++ switch (ins->opcode) ++ { ++ case VSIR_OP_ABS: ++ case VSIR_OP_ACOS: ++ case VSIR_OP_ADD: ++ case VSIR_OP_AND: ++ case VSIR_OP_ASIN: ++ case VSIR_OP_ATAN: ++ case VSIR_OP_BEM: ++ case VSIR_OP_BFI: ++ case VSIR_OP_BFREV: ++ case VSIR_OP_BUFINFO: ++ case VSIR_OP_CHECK_ACCESS_FULLY_MAPPED: ++ case VSIR_OP_CMP: ++ case VSIR_OP_CND: ++ case VSIR_OP_COS: ++ case VSIR_OP_COUNTBITS: ++ case VSIR_OP_CRS: ++ case VSIR_OP_DADD: ++ case VSIR_OP_DDIV: ++ case VSIR_OP_DEF: ++ case VSIR_OP_DEFB: ++ case VSIR_OP_DEFI: ++ case VSIR_OP_DEQO: ++ case VSIR_OP_DFMA: ++ case VSIR_OP_DGEO: ++ case VSIR_OP_DIV: ++ case VSIR_OP_DLT: ++ case VSIR_OP_DMAX: ++ case VSIR_OP_DMIN: ++ case VSIR_OP_DMOV: ++ case VSIR_OP_DMOVC: ++ case VSIR_OP_DMUL: ++ case VSIR_OP_DNE: ++ case VSIR_OP_DP2: ++ case VSIR_OP_DP2ADD: ++ case VSIR_OP_DP3: ++ case VSIR_OP_DP4: ++ case VSIR_OP_DRCP: ++ case VSIR_OP_DST: ++ case VSIR_OP_DSX: ++ case VSIR_OP_DSX_COARSE: ++ case VSIR_OP_DSX_FINE: ++ case VSIR_OP_DSY: ++ case VSIR_OP_DSY_COARSE: ++ case VSIR_OP_DSY_FINE: ++ case VSIR_OP_DTOF: ++ case VSIR_OP_DTOI: ++ case VSIR_OP_DTOU: ++ case VSIR_OP_EQO: ++ case VSIR_OP_EQU: ++ case VSIR_OP_EVAL_CENTROID: ++ case VSIR_OP_EVAL_SAMPLE_INDEX: ++ case VSIR_OP_EXP: ++ case VSIR_OP_EXPP: ++ case VSIR_OP_F16TOF32: ++ case VSIR_OP_F32TOF16: ++ case VSIR_OP_FIRSTBIT_HI: ++ case VSIR_OP_FIRSTBIT_LO: ++ case VSIR_OP_FIRSTBIT_SHI: ++ case VSIR_OP_FRC: ++ case VSIR_OP_FREM: ++ case VSIR_OP_FTOD: ++ case VSIR_OP_FTOI: ++ case VSIR_OP_FTOU: ++ case VSIR_OP_GATHER4: ++ case VSIR_OP_GATHER4_C: ++ case VSIR_OP_GATHER4_C_S: ++ case VSIR_OP_GATHER4_PO: ++ case VSIR_OP_GATHER4_PO_C: ++ case VSIR_OP_GATHER4_PO_C_S: ++ case VSIR_OP_GATHER4_PO_S: ++ case VSIR_OP_GATHER4_S: ++ case VSIR_OP_GEO: ++ case VSIR_OP_GEU: ++ case VSIR_OP_HCOS: ++ case VSIR_OP_HSIN: ++ case VSIR_OP_HTAN: ++ case VSIR_OP_IADD: ++ case VSIR_OP_IBFE: ++ case VSIR_OP_IDIV: ++ case VSIR_OP_IEQ: ++ case VSIR_OP_IGE: ++ case VSIR_OP_ILT: ++ case VSIR_OP_IMAD: ++ case VSIR_OP_IMAX: ++ case VSIR_OP_IMIN: ++ case VSIR_OP_IMUL: ++ case VSIR_OP_IMUL_LOW: ++ case VSIR_OP_INE: ++ case VSIR_OP_INEG: ++ case VSIR_OP_IREM: ++ case VSIR_OP_ISFINITE: ++ case VSIR_OP_ISHL: ++ case VSIR_OP_ISHR: ++ case VSIR_OP_ISINF: ++ case VSIR_OP_ISNAN: ++ case VSIR_OP_ITOD: ++ case VSIR_OP_ITOF: ++ case VSIR_OP_ITOI: ++ case VSIR_OP_LD: ++ case VSIR_OP_LD2DMS: ++ case VSIR_OP_LD2DMS_S: ++ case VSIR_OP_LD_RAW: ++ case VSIR_OP_LD_RAW_S: ++ case VSIR_OP_LD_S: ++ case VSIR_OP_LD_STRUCTURED: ++ case VSIR_OP_LD_STRUCTURED_S: ++ case VSIR_OP_LD_UAV_TYPED: ++ case VSIR_OP_LD_UAV_TYPED_S: ++ case VSIR_OP_LIT: ++ case VSIR_OP_LOD: ++ case VSIR_OP_LOG: ++ case VSIR_OP_LOGP: ++ case VSIR_OP_LRP: ++ case VSIR_OP_LTO: ++ case VSIR_OP_LTU: ++ case VSIR_OP_M3x2: ++ case VSIR_OP_M3x3: ++ case VSIR_OP_M3x4: ++ case VSIR_OP_M4x3: ++ case VSIR_OP_M4x4: ++ case VSIR_OP_MAD: ++ case VSIR_OP_MAX: ++ case VSIR_OP_MIN: ++ case VSIR_OP_MOV: ++ case VSIR_OP_MOVA: ++ case VSIR_OP_MOVC: ++ case VSIR_OP_MSAD: ++ case VSIR_OP_MUL: ++ case VSIR_OP_NEO: ++ case VSIR_OP_NEU: ++ case VSIR_OP_NOP: ++ case VSIR_OP_NOT: ++ case VSIR_OP_NRM: ++ case VSIR_OP_OR: ++ case VSIR_OP_ORD: ++ case VSIR_OP_PHI: ++ case VSIR_OP_POW: ++ case VSIR_OP_QUAD_READ_ACROSS_D: ++ case VSIR_OP_QUAD_READ_ACROSS_X: ++ case VSIR_OP_QUAD_READ_ACROSS_Y: ++ case VSIR_OP_QUAD_READ_LANE_AT: ++ case VSIR_OP_RCP: ++ case VSIR_OP_RESINFO: ++ case VSIR_OP_ROUND_NE: ++ case VSIR_OP_ROUND_NI: ++ case VSIR_OP_ROUND_PI: ++ case VSIR_OP_ROUND_Z: ++ case VSIR_OP_RSQ: ++ case VSIR_OP_SAMPLE: ++ case VSIR_OP_SAMPLE_B: ++ case VSIR_OP_SAMPLE_B_CL_S: ++ case VSIR_OP_SAMPLE_C: ++ case VSIR_OP_SAMPLE_C_CL_S: ++ case VSIR_OP_SAMPLE_C_LZ: ++ case VSIR_OP_SAMPLE_C_LZ_S: ++ case VSIR_OP_SAMPLE_CL_S: ++ case VSIR_OP_SAMPLE_GRAD: ++ case VSIR_OP_SAMPLE_GRAD_CL_S: ++ case VSIR_OP_SAMPLE_INFO: ++ case VSIR_OP_SAMPLE_LOD: ++ case VSIR_OP_SAMPLE_LOD_S: ++ case VSIR_OP_SAMPLE_POS: ++ case VSIR_OP_SETP: ++ case VSIR_OP_SGE: ++ case VSIR_OP_SGN: ++ case VSIR_OP_SIN: ++ case VSIR_OP_SINCOS: ++ case VSIR_OP_SLT: ++ case VSIR_OP_SQRT: ++ case VSIR_OP_SUB: ++ case VSIR_OP_SWAPC: ++ case VSIR_OP_TAN: ++ case VSIR_OP_TEX: ++ case VSIR_OP_TEXBEM: ++ case VSIR_OP_TEXBEML: ++ case VSIR_OP_TEXCOORD: ++ case VSIR_OP_TEXCRD: ++ case VSIR_OP_TEXDEPTH: ++ case VSIR_OP_TEXDP3: ++ case VSIR_OP_TEXDP3TEX: ++ case VSIR_OP_TEXLD: ++ case VSIR_OP_TEXLDD: ++ case VSIR_OP_TEXLDL: ++ case VSIR_OP_TEXM3x2DEPTH: ++ case VSIR_OP_TEXM3x2PAD: ++ case VSIR_OP_TEXM3x2TEX: ++ case VSIR_OP_TEXM3x3: ++ case VSIR_OP_TEXM3x3DIFF: ++ case VSIR_OP_TEXM3x3PAD: ++ case VSIR_OP_TEXM3x3SPEC: ++ case VSIR_OP_TEXM3x3TEX: ++ case VSIR_OP_TEXM3x3VSPEC: ++ case VSIR_OP_TEXREG2AR: ++ case VSIR_OP_TEXREG2GB: ++ case VSIR_OP_TEXREG2RGB: ++ case VSIR_OP_UBFE: ++ case VSIR_OP_UDIV: ++ case VSIR_OP_UDIV_SIMPLE: ++ case VSIR_OP_UGE: ++ case VSIR_OP_ULT: ++ case VSIR_OP_UMAX: ++ case VSIR_OP_UMIN: ++ case VSIR_OP_UMUL: ++ case VSIR_OP_UNO: ++ case VSIR_OP_UREM: ++ case VSIR_OP_USHR: ++ case VSIR_OP_UTOD: ++ case VSIR_OP_UTOF: ++ case VSIR_OP_UTOU: ++ case VSIR_OP_WAVE_ACTIVE_ALL_EQUAL: ++ case VSIR_OP_WAVE_ACTIVE_BALLOT: ++ case VSIR_OP_WAVE_ACTIVE_BIT_AND: ++ case VSIR_OP_WAVE_ACTIVE_BIT_OR: ++ case VSIR_OP_WAVE_ACTIVE_BIT_XOR: ++ case VSIR_OP_WAVE_ALL_BIT_COUNT: ++ case VSIR_OP_WAVE_ALL_TRUE: ++ case VSIR_OP_WAVE_ANY_TRUE: ++ case VSIR_OP_WAVE_IS_FIRST_LANE: ++ case VSIR_OP_WAVE_OP_ADD: ++ case VSIR_OP_WAVE_OP_IMAX: ++ case VSIR_OP_WAVE_OP_IMIN: ++ case VSIR_OP_WAVE_OP_MAX: ++ case VSIR_OP_WAVE_OP_MIN: ++ case VSIR_OP_WAVE_OP_MUL: ++ case VSIR_OP_WAVE_OP_UMAX: ++ case VSIR_OP_WAVE_OP_UMIN: ++ case VSIR_OP_WAVE_PREFIX_BIT_COUNT: ++ case VSIR_OP_WAVE_READ_LANE_AT: ++ case VSIR_OP_WAVE_READ_LANE_FIRST: ++ case VSIR_OP_XOR: ++ return false; ++ ++ case VSIR_OP_ATOMIC_AND: ++ case VSIR_OP_ATOMIC_CMP_STORE: ++ case VSIR_OP_ATOMIC_IADD: ++ case VSIR_OP_ATOMIC_IMAX: ++ case VSIR_OP_ATOMIC_IMIN: ++ case VSIR_OP_ATOMIC_OR: ++ case VSIR_OP_ATOMIC_UMAX: ++ case VSIR_OP_ATOMIC_UMIN: ++ case VSIR_OP_ATOMIC_XOR: ++ case VSIR_OP_BRANCH: ++ case VSIR_OP_BREAK: ++ case VSIR_OP_BREAKC: ++ case VSIR_OP_BREAKP: ++ case VSIR_OP_CALL: ++ case VSIR_OP_CALLNZ: ++ case VSIR_OP_CASE: ++ case VSIR_OP_CONTINUE: ++ case VSIR_OP_CONTINUEP: ++ case VSIR_OP_CUT: ++ case VSIR_OP_CUT_STREAM: ++ case VSIR_OP_DCL: ++ case VSIR_OP_DCL_CONSTANT_BUFFER: ++ case VSIR_OP_DCL_FUNCTION_BODY: ++ case VSIR_OP_DCL_FUNCTION_TABLE: ++ case VSIR_OP_DCL_GLOBAL_FLAGS: ++ case VSIR_OP_DCL_GS_INSTANCES: ++ case VSIR_OP_DCL_HS_FORK_PHASE_INSTANCE_COUNT: ++ case VSIR_OP_DCL_HS_JOIN_PHASE_INSTANCE_COUNT: ++ case VSIR_OP_DCL_HS_MAX_TESSFACTOR: ++ case VSIR_OP_DCL_IMMEDIATE_CONSTANT_BUFFER: ++ case VSIR_OP_DCL_INDEX_RANGE: ++ case VSIR_OP_DCL_INDEXABLE_TEMP: ++ case VSIR_OP_DCL_INPUT: ++ case VSIR_OP_DCL_INPUT_CONTROL_POINT_COUNT: ++ case VSIR_OP_DCL_INPUT_PRIMITIVE: ++ case VSIR_OP_DCL_INPUT_PS: ++ case VSIR_OP_DCL_INPUT_PS_SGV: ++ case VSIR_OP_DCL_INPUT_PS_SIV: ++ case VSIR_OP_DCL_INPUT_SGV: ++ case VSIR_OP_DCL_INPUT_SIV: ++ case VSIR_OP_DCL_INTERFACE: ++ case VSIR_OP_DCL_OUTPUT: ++ case VSIR_OP_DCL_OUTPUT_CONTROL_POINT_COUNT: ++ case VSIR_OP_DCL_OUTPUT_SGV: ++ case VSIR_OP_DCL_OUTPUT_SIV: ++ case VSIR_OP_DCL_OUTPUT_TOPOLOGY: ++ case VSIR_OP_DCL_RESOURCE_RAW: ++ case VSIR_OP_DCL_RESOURCE_STRUCTURED: ++ case VSIR_OP_DCL_SAMPLER: ++ case VSIR_OP_DCL_STREAM: ++ case VSIR_OP_DCL_TEMPS: ++ case VSIR_OP_DCL_TESSELLATOR_DOMAIN: ++ case VSIR_OP_DCL_TESSELLATOR_OUTPUT_PRIMITIVE: ++ case VSIR_OP_DCL_TESSELLATOR_PARTITIONING: ++ case VSIR_OP_DCL_TGSM_RAW: ++ case VSIR_OP_DCL_TGSM_STRUCTURED: ++ case VSIR_OP_DCL_THREAD_GROUP: ++ case VSIR_OP_DCL_UAV_RAW: ++ case VSIR_OP_DCL_UAV_STRUCTURED: ++ case VSIR_OP_DCL_UAV_TYPED: ++ case VSIR_OP_DCL_VERTICES_OUT: ++ case VSIR_OP_DEFAULT: ++ case VSIR_OP_DISCARD: ++ case VSIR_OP_ELSE: ++ case VSIR_OP_EMIT: ++ case VSIR_OP_EMIT_STREAM: ++ case VSIR_OP_ENDIF: ++ case VSIR_OP_ENDLOOP: ++ case VSIR_OP_ENDREP: ++ case VSIR_OP_ENDSWITCH: ++ case VSIR_OP_FCALL: ++ case VSIR_OP_HS_CONTROL_POINT_PHASE: ++ case VSIR_OP_HS_DECLS: ++ case VSIR_OP_HS_FORK_PHASE: ++ case VSIR_OP_HS_JOIN_PHASE: ++ case VSIR_OP_IF: ++ case VSIR_OP_IFC: ++ case VSIR_OP_IMM_ATOMIC_ALLOC: ++ case VSIR_OP_IMM_ATOMIC_AND: ++ case VSIR_OP_IMM_ATOMIC_CMP_EXCH: ++ case VSIR_OP_IMM_ATOMIC_CONSUME: ++ case VSIR_OP_IMM_ATOMIC_EXCH: ++ case VSIR_OP_IMM_ATOMIC_IADD: ++ case VSIR_OP_IMM_ATOMIC_IMAX: ++ case VSIR_OP_IMM_ATOMIC_IMIN: ++ case VSIR_OP_IMM_ATOMIC_OR: ++ case VSIR_OP_IMM_ATOMIC_UMAX: ++ case VSIR_OP_IMM_ATOMIC_UMIN: ++ case VSIR_OP_IMM_ATOMIC_XOR: ++ case VSIR_OP_LABEL: ++ case VSIR_OP_LOOP: ++ case VSIR_OP_PHASE: ++ case VSIR_OP_REP: ++ case VSIR_OP_RET: ++ case VSIR_OP_RETP: ++ case VSIR_OP_STORE_RAW: ++ case VSIR_OP_STORE_STRUCTURED: ++ case VSIR_OP_STORE_UAV_TYPED: ++ case VSIR_OP_SWITCH: ++ case VSIR_OP_SWITCH_MONOLITHIC: ++ case VSIR_OP_SYNC: ++ case VSIR_OP_TEXKILL: ++ return true; ++ ++ case VSIR_OP_INVALID: ++ case VSIR_OP_COUNT: ++ break; ++ } ++ ++ vkd3d_unreachable(); ++} ++ ++static enum vkd3d_result vsir_program_dce(struct vsir_program *program, ++ struct vsir_transformation_context *ctx) ++{ ++ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); ++ struct vkd3d_shader_instruction *ins; ++ struct liveness_tracker tracker; ++ enum vkd3d_result ret; ++ unsigned int i; ++ ++ if ((ret = track_liveness(program, &tracker))) ++ return ret; ++ ++ for (ins = vsir_program_iterator_head(&it), i = 0; ins; ins = vsir_program_iterator_next(&it), ++i) ++ { ++ unsigned int used_dst_count = 0; ++ ++ /* FIXME: IMM_ATOMIC_* can still be effectively DCE'd by turning them ++ * into non-immediate ATOMIC_* instructions. */ ++ if (vsir_instruction_has_side_effects(ins)) ++ continue; ++ ++ for (unsigned int j = 0; j < ins->dst_count; ++j) ++ { ++ struct vkd3d_shader_dst_param *dst = &ins->dst[j]; ++ ++ if (dst->reg.type == VKD3DSPR_SSA && !tracker.ssa_regs[dst->reg.idx[0].offset].last_read) ++ { ++ vsir_dst_param_init_null(dst); ++ ctx->progress = true; ++ } ++ else if (dst->reg.type == VKD3DSPR_TEMP ++ && tracker.temp_regs[dst->reg.idx[0].offset].last_read <= i ++ && !(program->shader_version.major == 1 && dst->reg.idx[0].offset == 0)) ++ { ++ vsir_dst_param_init_null(dst); ++ ctx->progress = true; ++ } ++ else if (dst->reg.type != VKD3DSPR_NULL) ++ { ++ ++used_dst_count; ++ } ++ } ++ ++ if (!used_dst_count) ++ vkd3d_shader_instruction_make_nop(ins); ++ } ++ ++ liveness_tracker_cleanup(&tracker); ++ return VKD3D_OK; ++} ++ ++enum vkd3d_result vsir_program_optimize(struct vsir_program *program, uint64_t config_flags, ++ const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) ++{ ++ struct vsir_transformation_context ctx; ++ ++ vsir_transformation_context_init(&ctx, program, config_flags, compile_info, message_context); ++ ++ do ++ vsir_transform(&ctx, vsir_program_dce); ++ while (ctx.progress); ++ ++ if (TRACE_ON()) ++ vsir_program_trace(program); ++ ++ return ctx.result; ++} ++ + /* Transformations which should happen at parse time, i.e. before scan + * information is returned to the user. + * +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index 9c5f71ee11f..3deca660b00 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -3063,7 +3063,7 @@ struct spirv_compiler + struct vkd3d_shader_output_info + { + uint32_t id; +- enum vkd3d_shader_component_type component_type; ++ enum vsir_data_type data_type; + uint32_t array_element_mask; + } *output_info; + uint32_t private_output_variable[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */ +@@ -3905,15 +3905,14 @@ static void spirv_compiler_emit_register_debug_name(struct vkd3d_spirv_builder * + } + + static uint32_t spirv_compiler_emit_array_variable(struct spirv_compiler *compiler, +- struct vkd3d_spirv_stream *stream, SpvStorageClass storage_class, +- enum vkd3d_shader_component_type component_type, unsigned int component_count, +- const unsigned int *array_lengths, unsigned int length_count) ++ struct vkd3d_spirv_stream *stream, SpvStorageClass storage_class, enum vsir_data_type data_type, ++ unsigned int component_count, const unsigned int *array_lengths, unsigned int length_count) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, length_id, ptr_type_id; + unsigned int i; + +- type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); ++ type_id = spirv_get_type_id(builder, data_type, component_count); + for (i = 0; i < length_count; ++i) + { + if (!array_lengths[i]) +@@ -3921,17 +3920,16 @@ static uint32_t spirv_compiler_emit_array_variable(struct spirv_compiler *compil + length_id = spirv_compiler_get_constant_uint(compiler, array_lengths[i]); + 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); ++ + return vkd3d_spirv_build_op_variable(builder, stream, ptr_type_id, storage_class, 0); + } + +-static uint32_t spirv_compiler_emit_variable(struct spirv_compiler *compiler, +- struct vkd3d_spirv_stream *stream, SpvStorageClass storage_class, +- enum vkd3d_shader_component_type component_type, unsigned int component_count) ++static uint32_t spirv_compiler_emit_variable(struct spirv_compiler *compiler, struct vkd3d_spirv_stream *stream, ++ SpvStorageClass storage_class, enum vsir_data_type data_type, unsigned int component_count) + { +- return spirv_compiler_emit_array_variable(compiler, stream, storage_class, +- component_type, component_count, NULL, 0); ++ return spirv_compiler_emit_array_variable(compiler, stream, ++ storage_class, data_type, component_count, NULL, 0); + } + + static const struct vkd3d_spec_constant_info +@@ -4404,7 +4402,7 @@ static uint32_t spirv_compiler_get_register_id(struct spirv_compiler *compiler, + } + + return spirv_compiler_emit_variable(compiler, &builder->global_stream, +- SpvStorageClassPrivate, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); ++ SpvStorageClassPrivate, VSIR_DATA_F32, VKD3D_VEC4_SIZE); + } + + static bool vkd3d_swizzle_is_equal(uint32_t dst_write_mask, uint32_t swizzle, uint32_t write_mask) +@@ -4426,9 +4424,8 @@ static bool vkd3d_swizzle_is_scalar(uint32_t swizzle, const struct vkd3d_shader_ + && vsir_swizzle_get_component(swizzle, 3) == component_idx; + } + +-static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, +- uint32_t val_id, uint32_t val_write_mask, enum vkd3d_shader_component_type component_type, +- uint32_t swizzle, uint32_t write_mask) ++static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, uint32_t val_id, ++ uint32_t val_write_mask, enum vsir_data_type data_type, uint32_t swizzle, uint32_t write_mask) + { + unsigned int i, component_idx, component_count, val_component_count; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +@@ -4441,7 +4438,7 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, + && (component_count == 1 || vkd3d_swizzle_is_equal(val_write_mask, swizzle, write_mask))) + return val_id; + +- type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); ++ type_id = spirv_get_type_id(builder, data_type, component_count); + + if (component_count == 1) + { +@@ -4469,13 +4466,14 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, + if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) + components[component_idx++] = vsir_swizzle_get_component(swizzle, i); + } +- return vkd3d_spirv_build_op_vector_shuffle(builder, +- type_id, val_id, val_id, components, component_count); ++ ++ return vkd3d_spirv_build_op_vector_shuffle(builder, type_id, ++ val_id, val_id, components, component_count); + } + + static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compiler, + uint32_t vector1_id, uint32_t vector2_id, uint32_t swizzle, uint32_t write_mask, +- enum vkd3d_shader_component_type component_type, unsigned int component_count) ++ enum vsir_data_type data_type, unsigned int component_count) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t components[VKD3D_VEC4_SIZE]; +@@ -4491,10 +4489,10 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil + else + components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(swizzle, i); + } ++ type_id = spirv_get_type_id(builder, data_type, component_count); + +- type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); +- return vkd3d_spirv_build_op_vector_shuffle(builder, +- type_id, vector1_id, vector2_id, components, component_count); ++ return vkd3d_spirv_build_op_vector_shuffle(builder, type_id, ++ vector1_id, vector2_id, components, component_count); + } + + static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, +@@ -4812,8 +4810,8 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, + swizzle = data_type_is_64_bit(reg->data_type) ? vsir_swizzle_32_from_64(swizzle) : swizzle; + } + +- val_id = spirv_compiler_emit_swizzle(compiler, val_id, reg_info.write_mask, +- vkd3d_component_type_from_data_type(reg_info.data_type), swizzle, val_write_mask); ++ val_id = spirv_compiler_emit_swizzle(compiler, val_id, ++ reg_info.write_mask, reg_info.data_type, swizzle, val_write_mask); + if (reg->data_type == reg_info.data_type) + return val_id; + +@@ -4920,7 +4918,7 @@ static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *co + } + + static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, +- uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type, ++ uint32_t dst_id, uint32_t dst_write_mask, enum vsir_data_type data_type, + SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +@@ -4929,7 +4927,7 @@ static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, + + if (vsir_write_mask_component_count(dst_write_mask) > 1) + { +- type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); ++ type_id = spirv_get_type_id(builder, data_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); + component_idx = vsir_write_mask_get_component_idx(write_mask); + component_idx -= vsir_write_mask_get_component_idx(dst_write_mask); +@@ -4940,9 +4938,8 @@ static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, + vkd3d_spirv_build_op_store(builder, dst_id, val_id, SpvMemoryAccessMaskNone); + } + +-static void spirv_compiler_emit_store(struct spirv_compiler *compiler, +- uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type, +- SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id) ++static void spirv_compiler_emit_store(struct spirv_compiler *compiler, uint32_t dst_id, uint32_t dst_write_mask, ++ enum vsir_data_type data_type, SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + unsigned int component_count, dst_component_count; +@@ -4957,7 +4954,7 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, + + if (dst_component_count == 1 && component_count != 1) + { +- type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); ++ type_id = spirv_get_type_id(builder, data_type, 1); + val_id = vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, + vsir_write_mask_get_component_idx(dst_write_mask)); + write_mask &= dst_write_mask; +@@ -4965,14 +4962,12 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, + } + + if (component_count == 1) +- { +- return spirv_compiler_emit_store_scalar(compiler, +- dst_id, dst_write_mask, component_type, storage_class, write_mask, val_id); +- } ++ return spirv_compiler_emit_store_scalar(compiler, dst_id, ++ dst_write_mask, data_type, storage_class, write_mask, val_id); + + if (dst_component_count != component_count) + { +- type_id = spirv_get_type_id_for_component_type(builder, component_type, dst_component_count); ++ type_id = spirv_get_type_id(builder, data_type, dst_component_count); + dst_val_id = vkd3d_spirv_build_op_load(builder, type_id, dst_id, SpvMemoryAccessMaskNone); + + VKD3D_ASSERT(component_count <= ARRAY_SIZE(components)); +@@ -5031,7 +5026,7 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, + } + + spirv_compiler_emit_store(compiler, reg_info.id, reg_info.write_mask, +- vkd3d_component_type_from_data_type(data_type), reg_info.storage_class, src_write_mask, val_id); ++ data_type, reg_info.storage_class, src_write_mask, val_id); + } + + static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler, +@@ -5089,13 +5084,14 @@ static void spirv_compiler_emit_store_dst_swizzled(struct spirv_compiler *compil + const struct vkd3d_shader_dst_param *dst, uint32_t val_id, + enum vkd3d_shader_component_type component_type, uint32_t swizzle) + { ++ enum vsir_data_type data_type = vsir_data_type_from_component_type(component_type); + struct vkd3d_shader_dst_param typed_dst = *dst; +- val_id = spirv_compiler_emit_swizzle(compiler, +- val_id, VKD3DSP_WRITEMASK_ALL, component_type, swizzle, dst->write_mask); ++ ++ val_id = spirv_compiler_emit_swizzle(compiler, val_id, ++ VKD3DSP_WRITEMASK_ALL, data_type, swizzle, dst->write_mask); + /* XXX: The register data type could be fixed by the shader parser. For SM5 +- * shaders the data types are stored in instructions modifiers. +- */ +- typed_dst.reg.data_type = vsir_data_type_from_component_type(component_type); ++ * shaders the data types are stored in instructions modifiers. */ ++ typed_dst.reg.data_type = data_type; + spirv_compiler_emit_store_dst(compiler, &typed_dst, val_id); + } + +@@ -5282,8 +5278,8 @@ static uint32_t spirv_compiler_emit_draw_parameter_fixup(struct spirv_compiler * + + vkd3d_spirv_enable_capability(builder, SpvCapabilityDrawParameters); + +- base_var_id = spirv_compiler_emit_variable(compiler, &builder->global_stream, +- SpvStorageClassInput, VKD3D_SHADER_COMPONENT_INT, 1); ++ base_var_id = spirv_compiler_emit_variable(compiler, ++ &builder->global_stream, SpvStorageClassInput, VSIR_DATA_I32, 1); + vkd3d_spirv_add_iface_variable(builder, base_var_id); + spirv_compiler_decorate_builtin(compiler, base_var_id, base); + +@@ -5646,7 +5642,7 @@ static uint32_t spirv_compiler_emit_builtin_variable_v(struct spirv_compiler *co + sizes[0] = max(sizes[0], builtin->spirv_array_size); + + id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, storage_class, +- vkd3d_component_type_from_data_type(builtin->data_type), builtin->component_count, array_sizes, size_count); ++ builtin->data_type, builtin->component_count, array_sizes, size_count); + vkd3d_spirv_add_iface_variable(builder, id); + spirv_compiler_decorate_builtin(compiler, id, builtin->spirv_builtin); + +@@ -5834,7 +5830,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + unsigned int location = signature_element->target_location; + + input_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, +- storage_class, component_type, input_component_count, array_sizes, 2); ++ storage_class, data_type, input_component_count, array_sizes, 2); + vkd3d_spirv_add_iface_variable(builder, input_id); + if (reg_type == VKD3DSPR_PATCHCONST) + { +@@ -5854,7 +5850,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + { + storage_class = SpvStorageClassPrivate; + var_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, +- storage_class, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, array_sizes, 2); ++ storage_class, VSIR_DATA_F32, VKD3D_VEC4_SIZE, array_sizes, 2); + } + + vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, +@@ -5887,8 +5883,8 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + } + + val_id = spirv_compiler_emit_swizzle(compiler, val_id, +- vkd3d_write_mask_from_component_count(input_component_count), +- VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, signature_element->mask >> component_idx); ++ vkd3d_write_mask_from_component_count(input_component_count), VSIR_DATA_F32, ++ VKD3D_SHADER_NO_SWIZZLE, signature_element->mask >> component_idx); + + spirv_compiler_emit_store_reg(compiler, &dst_reg, signature_element->mask >> component_idx, val_id); + } +@@ -5979,13 +5975,13 @@ static void spirv_compiler_emit_shader_signature_outputs(struct spirv_compiler * + { + case VKD3D_SHADER_SV_CLIP_DISTANCE: + compiler->output_info[i].id = clip_distance_id; +- compiler->output_info[i].component_type = VKD3D_SHADER_COMPONENT_FLOAT; ++ compiler->output_info[i].data_type = VSIR_DATA_F32; + compiler->output_info[i].array_element_mask = clip_distance_mask; + break; + + case VKD3D_SHADER_SV_CULL_DISTANCE: + compiler->output_info[i].id = cull_distance_id; +- compiler->output_info[i].component_type = VKD3D_SHADER_COMPONENT_FLOAT; ++ compiler->output_info[i].data_type = VSIR_DATA_F32; + compiler->output_info[i].array_element_mask = cull_distance_mask; + break; + +@@ -6026,7 +6022,6 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + unsigned int component_idx, output_component_count; + const struct signature_element *signature_element; +- enum vkd3d_shader_component_type component_type; + const struct shader_signature *shader_signature; + const struct vkd3d_spirv_builtin *builtin; + enum vkd3d_shader_sysval_semantic sysval; +@@ -6063,14 +6058,12 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + if (builtin) + { + data_type = builtin->data_type; +- component_type = vkd3d_component_type_from_data_type(data_type); + if (!builtin->spirv_array_size) + output_component_count = builtin->component_count; + } + else + { +- component_type = signature_element->component_type; +- data_type = vsir_data_type_from_component_type(component_type); ++ data_type = vsir_data_type_from_component_type(signature_element->component_type); + } + + storage_class = SpvStorageClassOutput; +@@ -6111,7 +6104,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + { + storage_class = SpvStorageClassPrivate; + id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, +- storage_class, component_type, output_component_count, array_sizes, 2); ++ storage_class, data_type, output_component_count, array_sizes, 2); + } + else + { +@@ -6124,7 +6117,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + location = signature_element->semantic_index; + + id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, +- storage_class, component_type, output_component_count, array_sizes, 2); ++ storage_class, data_type, output_component_count, array_sizes, 2); + vkd3d_spirv_add_iface_variable(builder, id); + + if (is_dual_source_blending(compiler) && location < 2) +@@ -6149,7 +6142,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + if (!is_patch_constant) + { + compiler->output_info[element_idx].id = id; +- compiler->output_info[element_idx].component_type = component_type; ++ compiler->output_info[element_idx].data_type = data_type; + } + + var_id = id; +@@ -6157,7 +6150,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + { + storage_class = SpvStorageClassPrivate; + var_id = spirv_compiler_emit_variable(compiler, &builder->global_stream, +- storage_class, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); ++ storage_class, VSIR_DATA_F32, VKD3D_VEC4_SIZE); + } + + vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, +@@ -6207,6 +6200,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + uint32_t type_id, zero_id, ptr_type_id, chain_id, object_id; + const struct signature_element *element; + unsigned int i, index, array_idx; ++ enum vsir_data_type data_type; + uint32_t output_id; + + dst_write_mask = output->mask; +@@ -6232,9 +6226,11 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + if (!write_mask) + return; + +- if (output_info->component_type != VKD3D_SHADER_COMPONENT_FLOAT) ++ data_type = output_info->data_type; ++ ++ if (data_type != VSIR_DATA_F32) + { +- type_id = spirv_get_type_id_for_component_type(builder, output_info->component_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(builder, data_type, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } + +@@ -6244,35 +6240,32 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + { + /* Set values to 0 for not initialized shader output components. */ + write_mask |= uninit_mask; +- zero_id = spirv_compiler_get_constant_vector(compiler, +- vsir_data_type_from_component_type(output_info->component_type), VKD3D_VEC4_SIZE, 0); +- val_id = spirv_compiler_emit_vector_shuffle(compiler, +- zero_id, val_id, swizzle, uninit_mask, output_info->component_type, +- vsir_write_mask_component_count(write_mask)); ++ zero_id = spirv_compiler_get_constant_vector(compiler, data_type, VKD3D_VEC4_SIZE, 0); ++ val_id = spirv_compiler_emit_vector_shuffle(compiler, zero_id, val_id, swizzle, ++ uninit_mask, data_type, vsir_write_mask_component_count(write_mask)); + } + else + { +- val_id = spirv_compiler_emit_swizzle(compiler, +- val_id, VKD3DSP_WRITEMASK_ALL, output_info->component_type, swizzle, write_mask); ++ val_id = spirv_compiler_emit_swizzle(compiler, val_id, ++ VKD3DSP_WRITEMASK_ALL, data_type, swizzle, write_mask); + } + + output_id = output_info->id; + if (output_index_id) + { +- type_id = spirv_get_type_id_for_component_type(builder, +- output_info->component_type, vsir_write_mask_component_count(dst_write_mask)); ++ type_id = spirv_get_type_id(builder, data_type, vsir_write_mask_component_count(dst_write_mask)); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); + output_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, output_id, output_index_id); + } + + if (!output_info->array_element_mask) + { +- spirv_compiler_emit_store(compiler, +- output_id, dst_write_mask, output_info->component_type, SpvStorageClassOutput, write_mask, val_id); ++ spirv_compiler_emit_store(compiler, output_id, dst_write_mask, ++ data_type, SpvStorageClassOutput, write_mask, val_id); + return; + } + +- type_id = spirv_get_type_id_for_component_type(builder, output_info->component_type, 1); ++ type_id = spirv_get_type_id(builder, data_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); + mask = output_info->array_element_mask; + array_idx = spirv_compiler_get_output_array_index(compiler, output); +@@ -6285,9 +6278,9 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + chain_id = vkd3d_spirv_build_op_access_chain1(builder, + ptr_type_id, output_id, spirv_compiler_get_constant_uint(compiler, index)); + object_id = spirv_compiler_emit_swizzle(compiler, val_id, write_mask, +- output_info->component_type, VKD3D_SHADER_NO_SWIZZLE, VKD3DSP_WRITEMASK_0 << i); +- spirv_compiler_emit_store(compiler, chain_id, VKD3DSP_WRITEMASK_0, +- output_info->component_type, SpvStorageClassOutput, VKD3DSP_WRITEMASK_0 << i, object_id); ++ data_type, VKD3D_SHADER_NO_SWIZZLE, VKD3DSP_WRITEMASK_0 << i); ++ spirv_compiler_emit_store(compiler, chain_id, VKD3DSP_WRITEMASK_0, data_type, ++ SpvStorageClassOutput, VKD3DSP_WRITEMASK_0 << i, object_id); + ++index; + } + } +@@ -6494,7 +6487,7 @@ static void spirv_compiler_emit_temps(struct spirv_compiler *compiler, uint32_t + for (i = 0; i < compiler->temp_count; ++i) + { + id = spirv_compiler_emit_variable(compiler, &builder->global_stream, +- SpvStorageClassPrivate, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); ++ SpvStorageClassPrivate, VSIR_DATA_F32, VKD3D_VEC4_SIZE); + if (!i) + compiler->temp_id = id; + VKD3D_ASSERT(id == compiler->temp_id + i); +@@ -9938,18 +9931,18 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, + } + + val_id = spirv_compiler_emit_swizzle(compiler, val_id, write_mask, +- VKD3D_SHADER_COMPONENT_UINT, src->swizzle, dst->write_mask); ++ VSIR_DATA_U32, src->swizzle, dst->write_mask); + spirv_compiler_emit_store_dst(compiler, dst, val_id); + } + + static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { +- enum vkd3d_shader_component_type component_type = VKD3D_SHADER_COMPONENT_UINT; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t type_id, lod_id, val_id, miplevel_count_id; ++ enum vsir_data_type data_type = VSIR_DATA_U32; + uint32_t constituents[VKD3D_VEC4_SIZE]; + unsigned int i, size_component_count; + struct vkd3d_shader_image image; +@@ -9991,14 +9984,14 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, + + if (!(instruction->flags & VKD3DSI_RESINFO_UINT)) + { +- component_type = VKD3D_SHADER_COMPONENT_FLOAT; +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, VKD3D_VEC4_SIZE); ++ data_type = VSIR_DATA_F32; ++ type_id = spirv_get_type_id(builder, data_type, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id); + if (instruction->flags & VKD3DSI_PRECISE_XYZW) + vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); + } +- val_id = spirv_compiler_emit_swizzle(compiler, val_id, VKD3DSP_WRITEMASK_ALL, +- component_type, src[1].swizzle, dst->write_mask); ++ val_id = spirv_compiler_emit_swizzle(compiler, val_id, ++ VKD3DSP_WRITEMASK_ALL, data_type, src[1].swizzle, dst->write_mask); + + spirv_compiler_emit_store_dst(compiler, dst, val_id); + } +@@ -10030,10 +10023,10 @@ static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *co + static void spirv_compiler_emit_sample_info(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { +- enum vkd3d_shader_component_type component_type = VKD3D_SHADER_COMPONENT_UINT; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; ++ enum vsir_data_type data_type = VSIR_DATA_U32; + uint32_t constituents[VKD3D_VEC4_SIZE]; + uint32_t type_id, val_id; + unsigned int i; +@@ -10054,14 +10047,14 @@ static void spirv_compiler_emit_sample_info(struct spirv_compiler *compiler, + + if (!(instruction->flags & VKD3DSI_SAMPLE_INFO_UINT)) + { +- component_type = VKD3D_SHADER_COMPONENT_FLOAT; +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, VKD3D_VEC4_SIZE); ++ data_type = VSIR_DATA_F32; ++ type_id = spirv_get_type_id(builder, data_type, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id); + if (instruction->flags & VKD3DSI_PRECISE_XYZW) + vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); + } +- val_id = spirv_compiler_emit_swizzle(compiler, val_id, VKD3DSP_WRITEMASK_ALL, +- component_type, src->swizzle, dst->write_mask); ++ val_id = spirv_compiler_emit_swizzle(compiler, val_id, ++ VKD3DSP_WRITEMASK_ALL, data_type, src->swizzle, dst->write_mask); + + spirv_compiler_emit_store_dst(compiler, dst, val_id); + } +@@ -10158,7 +10151,7 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, + id = vkd3d_spirv_build_op_load(builder, type_id, id, SpvMemoryAccessMaskNone); + + id = spirv_compiler_emit_swizzle(compiler, id, VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1, +- VKD3D_SHADER_COMPONENT_FLOAT, instruction->src[0].swizzle, dst->write_mask); ++ VSIR_DATA_F32, instruction->src[0].swizzle, dst->write_mask); + spirv_compiler_emit_store_dst(compiler, dst, id); + } + +@@ -10205,7 +10198,7 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id, instr_set_id, op, src_ids, src_count); + + val_id = spirv_compiler_emit_swizzle(compiler, val_id, register_info.write_mask, +- VKD3D_SHADER_COMPONENT_FLOAT, src[0].swizzle, dst->write_mask); ++ VSIR_DATA_F32, src[0].swizzle, dst->write_mask); + + spirv_compiler_emit_store_dst(compiler, dst, val_id); + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index c6d239847c8..4798a75ce90 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -3874,8 +3874,11 @@ static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_s + + if (ins->opcode == VSIR_OP_DCL || ins->opcode == VSIR_OP_DCL_UAV_TYPED) + { ++ enum vkd3d_sm4_resource_type resource_type = sm4_resource_dimension(ins->declaration.semantic.resource_type); ++ + instr.idx[0] = pack_resource_data_type(ins->declaration.semantic.resource_data_type); + instr.idx_count = 1; ++ instr.extra_bits |= resource_type << VKD3D_SM4_RESOURCE_TYPE_SHIFT; + instr.extra_bits |= ins->declaration.semantic.sample_count << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; + resource = &ins->declaration.semantic.resource; + } +@@ -3910,8 +3913,6 @@ static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_s + if (uav) + instr.extra_bits |= ins->flags << VKD3D_SM5_UAV_FLAGS_SHIFT; + +- instr.extra_bits |= (sm4_resource_dimension(ins->resource_type) << VKD3D_SM4_RESOURCE_TYPE_SHIFT); +- + write_sm4_instruction(tpf, &instr); + } + +@@ -4169,6 +4170,9 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ + { + switch (ins->opcode) + { ++ case VSIR_OP_NOP: ++ break; ++ + case VSIR_OP_DCL_CONSTANT_BUFFER: + tpf_dcl_constant_buffer(tpf, ins); + break; +@@ -4519,7 +4523,8 @@ static void tpf_write_section(struct tpf_compiler *tpf, uint32_t tag, const stru + add_section(tpf, tag, &buffer); + } + +-int tpf_compile(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_code *rdef, ++int tpf_compile(struct vsir_program *program, uint64_t config_flags, ++ const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_code *rdef, + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) + { + enum vkd3d_shader_type shader_type = program->shader_version.type; +@@ -4528,6 +4533,9 @@ int tpf_compile(struct vsir_program *program, uint64_t config_flags, const struc + size_t i; + int ret; + ++ if ((ret = vsir_program_optimize(program, config_flags, compile_info, message_context))) ++ return ret; ++ + if ((ret = vsir_allocate_temp_registers(program, message_context))) + return ret; + +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index 6087df80970..2b5badb8871 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -1874,7 +1874,7 @@ static int vsir_program_compile(struct vsir_program *program, const struct vkd3d + case VKD3D_SHADER_TARGET_DXBC_TPF: + if ((ret = vsir_program_scan(program, &scan_info, message_context, true)) < 0) + return ret; +- ret = tpf_compile(program, config_flags, reflection_data, out, message_context); ++ ret = tpf_compile(program, config_flags, compile_info, reflection_data, out, message_context); + break; + + case VKD3D_SHADER_TARGET_GLSL: +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 3637aa4fdb9..df0eb2ff789 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -1645,6 +1645,8 @@ bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_c + enum vsir_normalisation_level normalisation_level); + enum vkd3d_result vsir_program_lower_d3dbc(struct vsir_program *program, uint64_t config_flags, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context); ++enum vkd3d_result vsir_program_optimize(struct vsir_program *program, uint64_t config_flags, ++ const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context); + enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t config_flags, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context); + enum vkd3d_result vsir_program_transform_early(struct vsir_program *program, uint64_t config_flags, +@@ -1860,7 +1862,8 @@ int msl_compile(struct vsir_program *program, uint64_t config_flags, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, + struct vkd3d_shader_message_context *message_context); + +-int tpf_compile(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_code *rdef, ++int tpf_compile(struct vsir_program *program, uint64_t config_flags, ++ const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_code *rdef, + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); + + enum vkd3d_md5_variant +-- +2.51.0 + diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-dddc92ccfd34f941d9b6738c4f54fac43cd.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-dddc92ccfd34f941d9b6738c4f54fac43cd.patch deleted file mode 100644 index e95c7bec..00000000 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-dddc92ccfd34f941d9b6738c4f54fac43cd.patch +++ /dev/null @@ -1,1550 +0,0 @@ -From c9111d227f6c312200cd7780eebb31ad23b069b9 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Wed, 17 Sep 2025 06:37:38 +1000 -Subject: [PATCH] Updated vkd3d to dddc92ccfd34f941d9b6738c4f54fac43cda42b3. - ---- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 18 + - libs/vkd3d/libs/vkd3d-shader/dxil.c | 294 +++++++------ - libs/vkd3d/libs/vkd3d-shader/ir.c | 409 ++++++++++++------ - .../libs/vkd3d-shader/vkd3d_shader_private.h | 10 +- - 4 files changed, 469 insertions(+), 262 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index e2fb8b12998..6f8fbe84b90 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -593,6 +593,18 @@ static void shader_print_uint_literal(struct vkd3d_d3d_asm_compiler *compiler, - prefix, compiler->colours.literal, i, compiler->colours.reset, suffix); - } - -+static void shader_print_int64_literal(struct vkd3d_d3d_asm_compiler *compiler, -+ const char *prefix, int64_t i, const char *suffix) -+{ -+ /* Note that we need to handle INT64_MIN here as well. */ -+ if (i < 0) -+ vkd3d_string_buffer_printf(&compiler->buffer, "%s-%s%"PRIu64"%s%s", -+ prefix, compiler->colours.literal, -(uint64_t)i, compiler->colours.reset, suffix); -+ else -+ vkd3d_string_buffer_printf(&compiler->buffer, "%s%s%"PRId64"%s%s", -+ prefix, compiler->colours.literal, i, compiler->colours.reset, suffix); -+} -+ - static void shader_print_uint64_literal(struct vkd3d_d3d_asm_compiler *compiler, - const char *prefix, uint64_t i, const char *suffix) - { -@@ -793,6 +805,12 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const - if (reg->dimension == VSIR_DIMENSION_VEC4) - shader_print_double_literal(compiler, ", ", reg->u.immconst_f64[1], ""); - } -+ else if (reg->data_type == VSIR_DATA_I64) -+ { -+ shader_print_int64_literal(compiler, "", reg->u.immconst_u64[0], ""); -+ if (reg->dimension == VSIR_DIMENSION_VEC4) -+ shader_print_int64_literal(compiler, "", reg->u.immconst_u64[1], ""); -+ } - else if (reg->data_type == VSIR_DATA_U64) - { - shader_print_uint64_literal(compiler, "", reg->u.immconst_u64[0], ""); -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index fb2cde4501a..44d2b8b1142 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -45,6 +45,8 @@ static const unsigned int MAX_GS_OUTPUT_STREAMS = 4; - (VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(0) \ - | VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(1)) - -+#define DXIL_TYPE_SIGNED 0x1u -+ - enum bitcode_block_id - { - BLOCKINFO_BLOCK = 0, -@@ -2475,8 +2477,11 @@ static void register_init_with_id(struct vkd3d_shader_register *reg, - reg->idx[0].offset = id; - } - --static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type, struct sm6_parser *dxil) -+static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type, -+ uint32_t type_flags, struct sm6_parser *dxil) - { -+ bool is_signed = type_flags & DXIL_TYPE_SIGNED; -+ - if (type->class == TYPE_CLASS_INTEGER) - { - switch (type->u.width) -@@ -2484,13 +2489,13 @@ static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type, - case 1: - return VSIR_DATA_BOOL; - case 8: -- return VSIR_DATA_U8; -+ return is_signed ? VSIR_DATA_I8 : VSIR_DATA_U8; - case 16: -- return VSIR_DATA_U16; -+ return is_signed ? VSIR_DATA_I16 : VSIR_DATA_U16; - case 32: -- return VSIR_DATA_U32; -+ return is_signed ? VSIR_DATA_I32 : VSIR_DATA_U32; - case 64: -- return VSIR_DATA_U64; -+ return is_signed ? VSIR_DATA_I64 : VSIR_DATA_U64; - default: - vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_UNSUPPORTED, - "Unhandled integer width %u.", type->u.width); -@@ -2577,6 +2582,16 @@ static void register_convert_to_minimum_precision(struct vkd3d_shader_register * - } - break; - -+ case VSIR_DATA_I16: -+ reg->data_type = VSIR_DATA_I32; -+ reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_INT_16; -+ if (reg->type == VKD3DSPR_IMMCONST) -+ { -+ for (i = 0; i < VSIR_DIMENSION_VEC4; ++i) -+ reg->u.immconst_u32[i] = (int16_t)reg->u.immconst_u32[i]; -+ } -+ break; -+ - case VSIR_DATA_U16: - reg->data_type = VSIR_DATA_U32; - reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_UINT_16; -@@ -2595,14 +2610,14 @@ static void register_convert_to_minimum_precision(struct vkd3d_shader_register * - static void register_index_address_init(struct vkd3d_shader_register_index *idx, const struct sm6_value *address, - struct sm6_parser *sm6); - --static void sm6_register_from_value(struct vkd3d_shader_register *reg, const struct sm6_value *value, -- struct sm6_parser *sm6) -+static void vsir_register_from_dxil_value(struct vkd3d_shader_register *reg, -+ const struct sm6_value *value, uint32_t type_flags, struct sm6_parser *dxil) - { - const struct sm6_type *scalar_type; - enum vsir_data_type data_type; - - scalar_type = sm6_type_get_scalar_type(value->type, 0); -- data_type = vsir_data_type_from_dxil(scalar_type, sm6); -+ data_type = vsir_data_type_from_dxil(scalar_type, type_flags, dxil); - - switch (value->value_type) - { -@@ -2614,21 +2629,21 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str - case VALUE_TYPE_ICB: - vsir_register_init(reg, VKD3DSPR_IMMCONSTBUFFER, data_type, 2); - reg->idx[0].offset = value->u.icb.id; -- register_index_address_init(®->idx[1], value->u.icb.index.index, sm6); -+ register_index_address_init(®->idx[1], value->u.icb.index.index, dxil); - reg->idx[1].is_in_bounds = value->u.icb.index.is_in_bounds; - break; - - case VALUE_TYPE_IDXTEMP: - vsir_register_init(reg, VKD3DSPR_IDXTEMP, data_type, 2); - reg->idx[0].offset = value->u.idxtemp.id; -- register_index_address_init(®->idx[1], value->u.idxtemp.index.index, sm6); -+ register_index_address_init(®->idx[1], value->u.idxtemp.index.index, dxil); - reg->idx[1].is_in_bounds = value->u.idxtemp.index.is_in_bounds; - break; - - case VALUE_TYPE_GROUPSHAREDMEM: - vsir_register_init(reg, VKD3DSPR_GROUPSHAREDMEM, data_type, 2); - reg->idx[0].offset = value->u.groupsharedmem.id; -- register_index_address_init(®->idx[1], value->u.groupsharedmem.index.index, sm6); -+ register_index_address_init(®->idx[1], value->u.groupsharedmem.index.index, dxil); - reg->idx[1].is_in_bounds = value->u.groupsharedmem.index.is_in_bounds; - break; - -@@ -2725,11 +2740,11 @@ static void src_param_init_vector(struct vkd3d_shader_src_param *param, unsigned - param->modifiers = VKD3DSPSM_NONE; - } - --static void src_param_init_from_value(struct vkd3d_shader_src_param *param, const struct sm6_value *src, -- struct sm6_parser *sm6) -+static void src_param_init_from_value(struct vkd3d_shader_src_param *param, -+ const struct sm6_value *src, uint32_t type_flags, struct sm6_parser *dxil) - { - src_param_init(param); -- sm6_register_from_value(¶m->reg, src, sm6); -+ vsir_register_from_dxil_value(¶m->reg, src, type_flags, dxil); - } - - static void src_param_init_vector_from_reg(struct vkd3d_shader_src_param *param, -@@ -2763,7 +2778,7 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, - { - struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(sm6->program, 1); - if (rel_addr) -- src_param_init_from_value(rel_addr, address, sm6); -+ src_param_init_from_value(rel_addr, address, 0, sm6); - idx->offset = 0; - idx->rel_addr = rel_addr; - } -@@ -2788,17 +2803,19 @@ static void src_param_init_vector_from_handle(struct sm6_parser *sm6, - src_param_init_vector_from_reg(param, ®); - } - --static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) -+static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instruction *ins, -+ uint32_t type_flags, struct sm6_parser *dxil) - { -- struct sm6_value *dst = sm6_parser_get_current_value(sm6); -+ struct sm6_value *dst = sm6_parser_get_current_value(dxil); - struct vkd3d_shader_dst_param *param; - -- if (!(param = instruction_dst_params_alloc(ins, 1, sm6))) -+ if (!(param = instruction_dst_params_alloc(ins, 1, dxil))) - return false; - - dst_param_init(param); -- sm6_parser_init_ssa_value(sm6, dst); -- sm6_register_from_value(¶m->reg, dst, sm6); -+ sm6_parser_init_ssa_value(dxil, dst); -+ vsir_register_from_dxil_value(¶m->reg, dst, type_flags, dxil); -+ - return true; - } - -@@ -2810,7 +2827,7 @@ static void instruction_dst_param_init_ssa_vector(struct vkd3d_shader_instructio - - dst_param_init_vector(param, component_count); - sm6_parser_init_ssa_value(sm6, dst); -- sm6_register_from_value(¶m->reg, dst, sm6); -+ vsir_register_from_dxil_value(¶m->reg, dst, 0, sm6); - } - - static bool instruction_dst_param_init_uint_temp_vector(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) -@@ -3242,7 +3259,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - dst->u.data = icb; - - icb->register_idx = sm6->icb_count++; -- icb->data_type = vsir_data_type_from_dxil(elem_type, sm6); -+ icb->data_type = vsir_data_type_from_dxil(elem_type, 0, sm6); - icb->element_count = type->u.array.count; - icb->component_count = 1; - icb->is_null = !operands; -@@ -3259,6 +3276,12 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - icb->data_type = VSIR_DATA_F32; - break; - -+ case VSIR_DATA_I16: -+ for (i = 0; i < count; ++i) -+ icb->data[i] = (int16_t)operands[i]; -+ icb->data_type = VSIR_DATA_I32; -+ break; -+ - case VSIR_DATA_U16: - for (i = 0; i < count; ++i) - icb->data[i] = (int16_t)operands[i]; -@@ -3266,12 +3289,14 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - break; - - case VSIR_DATA_F32: -+ case VSIR_DATA_I32: - case VSIR_DATA_U32: - for (i = 0; i < count; ++i) - icb->data[i] = operands[i]; - break; - - case VSIR_DATA_F64: -+ case VSIR_DATA_I64: - case VSIR_DATA_U64: - data64 = (uint64_t *)icb->data; - for (i = 0; i < count; ++i) -@@ -3696,12 +3721,14 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const stru - unsigned int count, unsigned int alignment, bool has_function_scope, unsigned int init, - struct vkd3d_shader_instruction *ins, struct sm6_value *dst) - { -- enum vsir_data_type data_type = vsir_data_type_from_dxil(elem_type, sm6); -+ enum vsir_data_type data_type = vsir_data_type_from_dxil(elem_type, 0, sm6); - - if (!(sm6->program->global_flags & VKD3DSGF_FORCE_NATIVE_LOW_PRECISION)) - { - if (data_type == VSIR_DATA_F16) - data_type = VSIR_DATA_F32; -+ else if (data_type == VSIR_DATA_I16) -+ data_type = VSIR_DATA_I32; - else if (data_type == VSIR_DATA_U16) - data_type = VSIR_DATA_U32; - } -@@ -3734,7 +3761,7 @@ static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6 - dst->value_type = VALUE_TYPE_GROUPSHAREDMEM; - dst->u.groupsharedmem.id = sm6->tgsm_count++; - dst->structure_stride = 0; -- sm6_register_from_value(&ins->declaration.tgsm_raw.reg.reg, dst, sm6); -+ vsir_register_from_dxil_value(&ins->declaration.tgsm_raw.reg.reg, dst, 0, sm6); - ins->declaration.tgsm_raw.alignment = alignment; - byte_count = elem_type->u.width / CHAR_BIT; - /* Convert minimum precision types to their 32-bit equivalent. */ -@@ -3764,7 +3791,7 @@ static void sm6_parser_declare_tgsm_structured(struct sm6_parser *sm6, const str - /* Convert minimum precision types to their 32-bit equivalent. */ - if (dst->structure_stride == 2) - dst->structure_stride = 4; -- sm6_register_from_value(&ins->declaration.tgsm_structured.reg.reg, dst, sm6); -+ vsir_register_from_dxil_value(&ins->declaration.tgsm_structured.reg.reg, dst, 0, sm6); - if (dst->structure_stride != 4) - { - FIXME("Unsupported structure stride %u.\n", dst->structure_stride); -@@ -4101,7 +4128,9 @@ static void src_params_init_from_operands(struct vkd3d_shader_src_param *src_par - unsigned int i; - - for (i = 0; i < count; ++i) -- src_param_init_from_value(&src_params[i], operands[i], sm6); -+ { -+ src_param_init_from_value(&src_params[i], operands[i], 0, sm6); -+ } - } - - static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( -@@ -4423,7 +4452,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ - || !sm6_value_validate_is_backward_ref(ptr, sm6)) - return; - -- sm6_register_from_value(®, ptr, sm6); -+ vsir_register_from_dxil_value(®, ptr, 0, sm6); - - if (reg.type != VKD3DSPR_GROUPSHAREDMEM) - { -@@ -4479,12 +4508,12 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ - src_param_init_vector_from_reg(&src_params[0], &coord); - else - src_param_make_constant_uint(&src_params[0], 0); -- src_param_init_from_value(&src_params[1], src, sm6); -+ src_param_init_from_value(&src_params[1], src, 0, sm6); - - sm6_parser_init_ssa_value(sm6, dst); - - dst_params = instruction_dst_params_alloc(ins, 2, sm6); -- sm6_register_from_value(&dst_params[0].reg, dst, sm6); -+ vsir_register_from_dxil_value(&dst_params[0].reg, dst, 0, sm6); - dst_param_init(&dst_params[0]); - - dst_params[1].reg = reg; -@@ -4659,8 +4688,8 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0], a, sm6); -- src_param_init_from_value(&src_params[1], b, sm6); -+ src_param_init_from_value(&src_params[0], a, 0, sm6); -+ src_param_init_from_value(&src_params[1], b, 0, sm6); - if (code == BINOP_SUB) - src_params[1].modifiers = VKD3DSPSM_NEG; - -@@ -4673,7 +4702,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - * do. */ - ins->flags |= VKD3DSI_SHIFT_UNMASKED; - } -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static const struct sm6_block *sm6_function_get_block(const struct sm6_function *function, uint64_t index, -@@ -4723,7 +4752,7 @@ static void sm6_parser_emit_br(struct sm6_parser *sm6, const struct dxil_record - dxil_record_validate_operand_max_count(record, i, sm6); - - code_block->terminator.type = TERMINATOR_COND_BR; -- sm6_register_from_value(&code_block->terminator.conditional_reg, value, sm6); -+ vsir_register_from_dxil_value(&code_block->terminator.conditional_reg, value, 0, sm6); - code_block->terminator.true_block = sm6_function_get_block(function, record->operands[0], sm6); - code_block->terminator.false_block = sm6_function_get_block(function, record->operands[1], sm6); - } -@@ -4794,7 +4823,9 @@ static bool sm6_parser_emit_composite_construct(struct sm6_parser *sm6, const st - unsigned int i; - - for (i = 0; i < component_count; ++i) -- sm6_register_from_value(&operand_regs[i], operands[i], sm6); -+ { -+ vsir_register_from_dxil_value(&operand_regs[i], operands[i], 0, sm6); -+ } - - return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); - } -@@ -4810,11 +4841,11 @@ static bool sm6_parser_emit_coordinate_construct(struct sm6_parser *sm6, const s - { - if (!z_operand && operands[component_count]->value_type == VALUE_TYPE_UNDEFINED) - break; -- sm6_register_from_value(&operand_regs[component_count], operands[component_count], sm6); -+ vsir_register_from_dxil_value(&operand_regs[component_count], operands[component_count], 0, sm6); - } - - if (z_operand) -- sm6_register_from_value(&operand_regs[component_count++], z_operand, sm6); -+ vsir_register_from_dxil_value(&operand_regs[component_count++], z_operand, 0, sm6); - - return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); - } -@@ -4835,7 +4866,7 @@ static void sm6_parser_emit_dx_void(struct sm6_parser *sm6, enum dx_intrinsic_op - { - struct vkd3d_shader_instruction *ins = state->ins; - vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_void_op(op)); -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) -@@ -4932,9 +4963,9 @@ static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, enum dx_intrinsic_o - vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0], sm6); -+ src_param_init_from_value(src_param, operands[0], 0, sm6); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, const struct sm6_type *type) -@@ -4971,10 +5002,10 @@ static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_ - vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type)); - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0], operands[0], sm6); -- src_param_init_from_value(&src_params[1], operands[1], sm6); -+ src_param_init_from_value(&src_params[0], operands[0], 0, sm6); -+ src_param_init_from_value(&src_params[1], operands[1], 0, sm6); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static enum vkd3d_shader_opcode map_dx_atomic_binop(const struct sm6_value *operand, struct sm6_parser *sm6) -@@ -5043,7 +5074,7 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr - } - else - { -- sm6_register_from_value(®, operands[coord_idx], sm6); -+ vsir_register_from_dxil_value(®, operands[coord_idx], 0, sm6); - } - - for (i = coord_idx + coord_count; i < coord_idx + 3; ++i) -@@ -5064,14 +5095,14 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr - return; - src_param_init_vector_from_reg(&src_params[0], ®); - if (is_cmp_xchg) -- src_param_init_from_value(&src_params[1], operands[4], sm6); -- src_param_init_from_value(&src_params[1 + is_cmp_xchg], operands[5], sm6); -+ src_param_init_from_value(&src_params[1], operands[4], 0, sm6); -+ src_param_init_from_value(&src_params[1 + is_cmp_xchg], operands[5], 0, sm6); - - sm6_parser_init_ssa_value(sm6, dst); - - dst_params = instruction_dst_params_alloc(ins, 2, sm6); - dst_param_init(&dst_params[0]); -- sm6_register_from_value(&dst_params[0].reg, dst, sm6); -+ vsir_register_from_dxil_value(&dst_params[0].reg, dst, 0, sm6); - dst_param_init(&dst_params[1]); - sm6_register_from_handle(sm6, &resource->u.handle, &dst_params[1].reg); - } -@@ -5131,7 +5162,7 @@ static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enu - return; - src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5165,7 +5196,7 @@ static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_int - src_param_init_scalar(&src_params[1], !clamp); - src_param_init_vector_from_handle(sm6, &src_params[2], &sampler->u.handle); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5193,7 +5224,7 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr - - type = sm6_type_get_scalar_type(dst->type, 0); - VKD3D_ASSERT(type); -- src_param->reg.data_type = vsir_data_type_from_dxil(type, sm6); -+ src_param->reg.data_type = vsir_data_type_from_dxil(type, 0, sm6); - if (data_type_is_64_bit(src_param->reg.data_type)) - src_param->swizzle = vsir_swizzle_64_from_32(src_param->swizzle); - else -@@ -5233,7 +5264,7 @@ static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, struct - src_param->reg.dimension = VSIR_DIMENSION_VEC4; - src_param_init(src_param); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_coverage(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5336,7 +5367,7 @@ static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic - vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_DISCARD); - - if ((src_param = instruction_src_params_alloc(ins, 1, sm6))) -- src_param_init_from_value(src_param, operands[0], sm6); -+ src_param_init_from_value(src_param, operands[0], 0, sm6); - } - - static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5363,7 +5394,7 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i - src_param->reg.dimension = VSIR_DIMENSION_VEC4; - src_param_init_scalar(src_param, component_idx); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5405,7 +5436,7 @@ static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opc - src_param_init_vector_from_reg(&src_params[0], ®s[0]); - src_param_init_vector_from_reg(&src_params[1], ®s[1]); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5450,9 +5481,9 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri - register_index_address_init(&src_params[0].reg.idx[0], operands[1], sm6); - - if (op == DX_EVAL_SAMPLE_INDEX) -- src_param_init_from_value(&src_params[1], operands[3], sm6); -+ src_param_init_from_value(&src_params[1], operands[3], 0, sm6); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5464,10 +5495,10 @@ static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_op - vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0], sm6); -+ src_param_init_from_value(src_param, operands[0], 0, sm6); - src_param->modifiers = VKD3DSPSM_ABS; - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5507,7 +5538,7 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i - component_idx = sm6_value_get_constant_uint(operands[0], sm6); - src_param_init_scalar(src_param, component_idx); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static enum vkd3d_shader_opcode sm6_dx_map_ma_op(enum dx_intrinsic_opcode op, const struct sm6_type *type) -@@ -5537,9 +5568,11 @@ static void sm6_parser_emit_dx_ma(struct sm6_parser *sm6, enum dx_intrinsic_opco - if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) - return; - for (i = 0; i < 3; ++i) -- src_param_init_from_value(&src_params[i], operands[i], sm6); -+ { -+ src_param_init_from_value(&src_params[i], operands[i], 0, sm6); -+ } - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5567,7 +5600,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in - if (is_texture) - { - ins->flags = VKD3DSI_RESINFO_UINT; -- src_param_init_from_value(&src_params[0], operands[1], sm6); -+ src_param_init_from_value(&src_params[0], operands[1], 0, sm6); - component_count = VKD3D_VEC4_SIZE; - - if (resource_kind_is_multisampled(resource_kind)) -@@ -5640,9 +5673,11 @@ static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsi - if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) - return; - for (i = 0; i < 3; ++i) -- src_param_init_from_value(&src_params[i], operands[i], sm6); -+ { -+ src_param_init_from_value(&src_params[i], operands[i], 0, sm6); -+ } - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5710,7 +5745,7 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin - register_index_address_init(&src_param->reg.idx[count], operands[3], sm6); - } - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5730,7 +5765,7 @@ static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intri - src_params[0].reg = reg; - src_param_init_vector(&src_params[0], 2); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_output_control_point_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5781,9 +5816,9 @@ static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic - - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0], sm6); -+ src_param_init_from_value(src_param, operands[0], 0, sm6); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5928,7 +5963,7 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri - - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0], operands[1], sm6); -+ src_param_init_from_value(&src_params[0], operands[1], 0, sm6); - if (!sm6_value_is_undef(operands[2])) - { - /* Constant zero would be ok, but is not worth checking for unless it shows up. */ -@@ -5993,7 +6028,7 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr - - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0], operands[1], sm6); -+ src_param_init_from_value(&src_params[0], operands[1], 0, sm6); - if (!sm6_value_is_undef(operands[2])) - { - /* Constant zero would have no effect, but is not worth checking for unless it shows up. */ -@@ -6023,7 +6058,7 @@ static void sm6_parser_emit_dx_get_sample_count(struct sm6_parser *sm6, enum dx_ - src_param->reg.dimension = VSIR_DIMENSION_VEC4; - src_param_init(src_param); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - ins->dst->reg.data_type = VSIR_DATA_U32; - } - -@@ -6048,14 +6083,14 @@ static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_in - if (op == DX_TEX2DMS_GET_SAMPLE_POS) - { - src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); -- src_param_init_from_value(&src_params[1], operands[1], sm6); -+ src_param_init_from_value(&src_params[1], operands[1], 0, sm6); - } - else - { - src_param_init_vector(&src_params[0], 2); - vsir_register_init(&src_params[0].reg, VKD3DSPR_RASTERIZER, VSIR_DATA_F32, 0); - src_params[0].reg.dimension = VSIR_DIMENSION_VEC4; -- src_param_init_from_value(&src_params[1], operands[0], sm6); -+ src_param_init_from_value(&src_params[1], operands[0], 0, sm6); - } - - instruction_dst_param_init_ssa_vector(ins, 2, sm6); -@@ -6117,7 +6152,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ - instruction_init_with_resource(ins, (op == DX_SAMPLE_B) ? VSIR_OP_SAMPLE_B : VSIR_OP_SAMPLE_LOD, - resource, sm6); - src_params = instruction_src_params_alloc(ins, 4, sm6); -- src_param_init_from_value(&src_params[3], operands[9], sm6); -+ src_param_init_from_value(&src_params[3], operands[9], 0, sm6); - break; - case DX_SAMPLE_C: - clamp_idx = 10; -@@ -6126,7 +6161,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ - instruction_init_with_resource(ins, (op == DX_SAMPLE_C_LZ) ? VSIR_OP_SAMPLE_C_LZ : VSIR_OP_SAMPLE_C, - resource, sm6); - src_params = instruction_src_params_alloc(ins, 4, sm6); -- src_param_init_from_value(&src_params[3], operands[9], sm6); -+ src_param_init_from_value(&src_params[3], operands[9], 0, sm6); - component_count = 1; - break; - case DX_SAMPLE_GRAD: -@@ -6183,7 +6218,7 @@ static void sm6_parser_emit_dx_sample_index(struct sm6_parser *sm6, enum dx_intr - src_param->reg = sm6->input_params[element_idx].reg; - src_param_init(src_param); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -6195,9 +6230,9 @@ static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsi - vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0], sm6); -+ src_param_init_from_value(src_param, operands[0], 0, sm6); - -- if (instruction_dst_param_init_ssa_scalar(ins, sm6)) -+ if (instruction_dst_param_init_ssa_scalar(ins, 0, sm6)) - ins->dst->modifiers = VKD3DSPDM_SATURATE; - } - -@@ -6210,7 +6245,7 @@ static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intr - vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0], sm6); -+ src_param_init_from_value(src_param, operands[0], 0, sm6); - - instruction_dst_param_init_ssa_vector(ins, 2, sm6); - } -@@ -6276,7 +6311,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr - } - - if ((src_param = instruction_src_params_alloc(ins, 1, sm6))) -- src_param_init_from_value(src_param, value, sm6); -+ src_param_init_from_value(src_param, value, 0, sm6); - } - - static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -6322,7 +6357,7 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in - instruction_init_with_resource(ins, extended_offset ? VSIR_OP_GATHER4_PO_C : VSIR_OP_GATHER4_C, resource, sm6); - if (!(src_params = instruction_src_params_alloc(ins, 4 + extended_offset, sm6))) - return; -- src_param_init_from_value(&src_params[3 + extended_offset], operands[9], sm6); -+ src_param_init_from_value(&src_params[3 + extended_offset], operands[9], 0, sm6); - } - - src_param_init_vector_from_reg(&src_params[0], &coord); -@@ -6385,7 +6420,7 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr - src_param_init_vector_from_reg(&src_params[0], &coord); - src_param_init_vector_from_handle(sm6, &src_params[1], &resource->u.handle); - if (is_multisample) -- src_param_init_from_value(&src_params[2], mip_level_or_sample_count, sm6); -+ src_param_init_from_value(&src_params[2], mip_level_or_sample_count, 0, sm6); - - instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); - } -@@ -6449,7 +6484,7 @@ static void sm6_parser_emit_dx_wave_active_ballot(struct sm6_parser *sm6, enum d - vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_WAVE_ACTIVE_BALLOT); - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0], sm6); -+ src_param_init_from_value(src_param, operands[0], 0, sm6); - - instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); - } -@@ -6489,9 +6524,9 @@ static void sm6_parser_emit_dx_wave_active_bit(struct sm6_parser *sm6, enum dx_i - - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0], sm6); -+ src_param_init_from_value(src_param, operands[0], 0, sm6); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static enum vkd3d_shader_opcode sm6_dx_map_wave_op(enum dxil_wave_op_kind op, bool is_signed, bool is_float, -@@ -6540,9 +6575,9 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic - - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0], sm6); -+ src_param_init_from_value(src_param, operands[0], 0, sm6); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -6931,14 +6966,15 @@ static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_recor - fn_value->u.function.name, &operands[1], operand_count - 1, state, dst); - } - --static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_type *from, -- const struct sm6_type *to, struct sm6_parser *sm6) -+static enum vkd3d_shader_opcode dxil_map_cast_op(uint64_t code, const struct sm6_type *from, -+ uint32_t *src_type_flags, const struct sm6_type *to, struct sm6_parser *dxil) - { - enum vkd3d_shader_opcode op = VSIR_OP_INVALID; - bool from_int, to_int, from_fp, to_fp; - unsigned int from_width, to_width; - bool is_valid = false; - -+ *src_type_flags = 0; - from_int = sm6_type_is_integer(from); - to_int = sm6_type_is_integer(to); - from_fp = sm6_type_is_floating_point(from); -@@ -6947,15 +6983,13 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ - /* NOTE: DXIL currently doesn't use vectors here. */ - if ((!from_int && !from_fp) || (!to_int && !to_fp)) - { -- FIXME("Unhandled cast of type class %u to type class %u.\n", from->class, to->class); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Cast of type class %u to type class %u is not implemented.", from->class, to->class); - return VSIR_OP_INVALID; - } - if (to->u.width == 8 || from->u.width == 8) - { -- FIXME("Unhandled 8-bit value.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Cast to/from an 8-bit type is not implemented."); - return VSIR_OP_INVALID; - } -@@ -6995,6 +7029,7 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ - case CAST_SITOFP: - op = VSIR_OP_ITOF; - is_valid = from_int && to_fp; -+ *src_type_flags |= DXIL_TYPE_SIGNED; - break; - - case CAST_FPTRUNC: -@@ -7013,16 +7048,14 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ - break; - - default: -- FIXME("Unhandled cast op %"PRIu64".\n", code); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Cast operation %"PRIu64" is unhandled.", code); - return VSIR_OP_INVALID; - } - - if (!is_valid) - { -- FIXME("Invalid types %u and/or %u for op %"PRIu64".\n", from->class, to->class, code); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.", - code, from->class, from->u.width, to->class, to->u.width); - return VSIR_OP_INVALID; -@@ -7045,22 +7078,23 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ - return op; - } - --static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_record *record, -+static void sm6_parser_emit_cast(struct sm6_parser *dxil, const struct dxil_record *record, - struct vkd3d_shader_instruction *ins, struct sm6_value *dst) - { - struct vkd3d_shader_src_param *src_param; -- enum vkd3d_shader_opcode handler_idx; - const struct sm6_value *value; -+ enum vkd3d_shader_opcode op; - const struct sm6_type *type; -+ uint32_t src_type_flags; - unsigned int i = 0; - -- if (!(value = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))) -+ if (!(value = sm6_parser_get_value_by_ref(dxil, record, NULL, &i))) - return; - -- if (!dxil_record_validate_operand_count(record, i + 2, i + 2, sm6)) -+ if (!dxil_record_validate_operand_count(record, i + 2, i + 2, dxil)) - return; - -- if (!(type = sm6_parser_get_type(sm6, record->operands[i++]))) -+ if (!(type = sm6_parser_get_type(dxil, record->operands[i++]))) - return; - - dst->type = type; -@@ -7073,28 +7107,28 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor - return; - } - -- if ((handler_idx = sm6_map_cast_op(record->operands[i], value->type, type, sm6)) == VSIR_OP_INVALID) -+ if ((op = dxil_map_cast_op(record->operands[i], value->type, &src_type_flags, type, dxil)) == VSIR_OP_INVALID) - return; - -- vsir_instruction_init(ins, &sm6->p.location, handler_idx); -+ vsir_instruction_init(ins, &dxil->p.location, op); - -- if (handler_idx == VSIR_OP_NOP) -+ if (op == VSIR_OP_NOP) - { - *dst = *value; - dst->type = type; - return; - } - -- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -+ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil))) - return; -- src_param_init_from_value(src_param, value, sm6); -+ src_param_init_from_value(src_param, value, src_type_flags, dxil); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, dxil); - - /* VSIR bitcasts are represented by source registers with types different - * from the types they were written with, rather than with different types - * for the MOV source and destination. */ -- if (handler_idx == VSIR_OP_MOV) -+ if (op == VSIR_OP_MOV) - src_param->reg.data_type = ins->dst[0].reg.data_type; - } - -@@ -7235,10 +7269,10 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor - - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a, sm6); -- src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b, sm6); -+ src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a, 0, sm6); -+ src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b, 0, sm6); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_record *record, -@@ -7258,7 +7292,7 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re - || !sm6_value_validate_is_backward_ref(ptr, sm6)) - return; - -- sm6_register_from_value(®, ptr, sm6); -+ vsir_register_from_dxil_value(®, ptr, 0, sm6); - - if (reg.type != VKD3DSPR_GROUPSHAREDMEM) - { -@@ -7313,14 +7347,14 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re - if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) - return; - src_param_make_constant_uint(&src_params[0], 0); -- src_param_init_from_value(&src_params[1], cmp, sm6); -- src_param_init_from_value(&src_params[2], new, sm6); -+ src_param_init_from_value(&src_params[1], cmp, 0, sm6); -+ src_param_init_from_value(&src_params[2], new, 0, sm6); - - sm6_parser_init_ssa_value(sm6, dst); - - if (!(dst_params = instruction_dst_params_alloc(ins, 2, sm6))) - return; -- sm6_register_from_value(&dst_params[0].reg, dst, sm6); -+ vsir_register_from_dxil_value(&dst_params[0].reg, dst, 0, sm6); - dst_param_init(&dst_params[0]); - dst_params[1].reg = reg; - dst_param_init(&dst_params[1]); -@@ -7379,10 +7413,10 @@ static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil - - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- sm6_register_from_value(&src_param->reg, src, sm6); -+ vsir_register_from_dxil_value(&src_param->reg, src, 0, sm6); - src_param_init_scalar(src_param, elem_idx); - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record *record, -@@ -7528,7 +7562,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor - if (record->operands[i]) - WARN("Ignoring volatile modifier.\n"); - -- sm6_register_from_value(®, ptr, sm6); -+ vsir_register_from_dxil_value(®, ptr, 0, sm6); - - if (ptr->structure_stride) - { -@@ -7543,7 +7577,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor - src_param_make_constant_uint(&src_params[0], reg.idx[1].offset); - /* Struct offset is always zero as there is no struct, just an array. */ - src_param_make_constant_uint(&src_params[1], 0); -- src_param_init_from_value(&src_params[2], ptr, sm6); -+ src_param_init_from_value(&src_params[2], ptr, 0, sm6); - src_params[2].reg.alignment = alignment; - /* The offset is already in src_params[0]. */ - src_params[2].reg.idx_count = 1; -@@ -7557,11 +7591,11 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor - return; - if (operand_count > 1) - src_param_make_constant_uint(&src_params[0], 0); -- src_param_init_from_value(&src_params[operand_count - 1], ptr, sm6); -+ src_param_init_from_value(&src_params[operand_count - 1], ptr, 0, sm6); - src_params[operand_count - 1].reg.alignment = alignment; - } - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static int phi_incoming_compare(const void *a, const void *b) -@@ -7715,7 +7749,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco - if (record->operands[i]) - WARN("Ignoring volatile modifier.\n"); - -- sm6_register_from_value(®, ptr, sm6); -+ vsir_register_from_dxil_value(®, ptr, 0, sm6); - - if (ptr->structure_stride) - { -@@ -7730,7 +7764,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco - src_param_make_constant_uint(&src_params[0], reg.idx[1].offset); - /* Struct offset is always zero as there is no struct, just an array. */ - src_param_make_constant_uint(&src_params[1], 0); -- src_param_init_from_value(&src_params[2], src, sm6); -+ src_param_init_from_value(&src_params[2], src, 0, sm6); - } - else - { -@@ -7741,7 +7775,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco - return; - if (operand_count > 1) - src_param_make_constant_uint(&src_params[0], 0); -- src_param_init_from_value(&src_params[operand_count - 1], src, sm6); -+ src_param_init_from_value(&src_params[operand_count - 1], src, 0, sm6); - } - - dst_param = instruction_dst_params_alloc(ins, 1, sm6); -@@ -7791,7 +7825,7 @@ static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_rec - return; - } - -- sm6_register_from_value(&terminator->conditional_reg, src, sm6); -+ vsir_register_from_dxil_value(&terminator->conditional_reg, src, 0, sm6); - terminator->type = TERMINATOR_SWITCH; - - terminator->case_count = record->operand_count / 2u; -@@ -7867,9 +7901,11 @@ static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_re - if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) - return; - for (i = 0; i < 3; ++i) -- src_param_init_from_value(&src_params[i], src[i], sm6); -+ { -+ src_param_init_from_value(&src_params[i], src[i], 0, sm6); -+ } - -- instruction_dst_param_init_ssa_scalar(ins, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - - static bool sm6_metadata_value_is_node(const struct sm6_metadata_value *m) -@@ -8208,7 +8244,7 @@ static enum vkd3d_result sm6_function_resolve_phi_incomings(const struct sm6_fun - vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, - "The type of a phi incoming value does not match the result type."); - } -- sm6_register_from_value(&phi->incoming[j].reg, src, sm6); -+ vsir_register_from_dxil_value(&phi->incoming[j].reg, src, 0, sm6); - } - } - } -@@ -8524,7 +8560,7 @@ static void sm6_block_emit_phi(const struct sm6_block *block, struct sm6_parser - } - - dst_param_init(dst_param); -- sm6_register_from_value(&dst_param->reg, &src_phi->value, sm6); -+ vsir_register_from_dxil_value(&dst_param->reg, &src_phi->value, 0, sm6); - } - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 29bf62709eb..eb50aecf8ae 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -50,16 +50,17 @@ const char *vsir_data_type_get_name(enum vsir_data_type t, const char *error) - static const char * const names[] = - { - [VSIR_DATA_BOOL ] = "bool", -- [VSIR_DATA_F16 ] = "half", -- [VSIR_DATA_F32 ] = "float", -- [VSIR_DATA_F64 ] = "double", -+ [VSIR_DATA_F16 ] = "f16", -+ [VSIR_DATA_F32 ] = "f32", -+ [VSIR_DATA_F64 ] = "f64", -+ [VSIR_DATA_I8 ] = "i8", - [VSIR_DATA_I16 ] = "i16", -- [VSIR_DATA_I32 ] = "int", -+ [VSIR_DATA_I32 ] = "i32", - [VSIR_DATA_I64 ] = "i64", -- [VSIR_DATA_U8 ] = "uint8", -- [VSIR_DATA_U16 ] = "uint16", -- [VSIR_DATA_U32 ] = "uint", -- [VSIR_DATA_U64 ] = "uint64", -+ [VSIR_DATA_U8 ] = "u8", -+ [VSIR_DATA_U16 ] = "u16", -+ [VSIR_DATA_U32 ] = "u32", -+ [VSIR_DATA_U64 ] = "u64", - [VSIR_DATA_SNORM ] = "snorm", - [VSIR_DATA_UNORM ] = "unorm", - [VSIR_DATA_OPAQUE ] = "opaque", -@@ -8822,97 +8823,18 @@ struct temp_allocator - struct vkd3d_shader_message_context *message_context; - struct temp_allocator_reg - { -+ struct liveness_tracker_reg *liveness_reg; - uint8_t allocated_mask; - uint32_t temp_id; -+ enum vkd3d_shader_register_type type; -+ unsigned int idx; - } *ssa_regs, *temp_regs; -- size_t allocated_ssa_count, allocated_temp_count; -+ size_t ssa_count, temp_count; -+ unsigned int new_temp_count; - enum vkd3d_result result; -+ uint8_t *current_allocation; - }; - --static uint8_t get_available_writemask(const struct temp_allocator *allocator, -- struct liveness_tracker *tracker, unsigned int first_write, unsigned int last_access, uint32_t temp_id) --{ -- uint8_t writemask = VKD3DSP_WRITEMASK_ALL; -- -- for (size_t i = 0; i < allocator->allocated_ssa_count; ++i) -- { -- const struct temp_allocator_reg *reg = &allocator->ssa_regs[i]; -- const struct liveness_tracker_reg *liveness_reg = &tracker->ssa_regs[i]; -- -- /* We do not overlap if first write == last read: -- * this is the case where we are allocating the result of that -- * expression, e.g. "add r0, r0, r1". */ -- -- if (reg->temp_id == temp_id -- && first_write < liveness_reg->last_access -- && last_access > liveness_reg->first_write) -- writemask &= ~reg->allocated_mask; -- -- if (!writemask) -- return writemask; -- } -- -- for (size_t i = 0; i < allocator->allocated_temp_count; ++i) -- { -- const struct temp_allocator_reg *reg = &allocator->temp_regs[i]; -- const struct liveness_tracker_reg *liveness_reg = &tracker->temp_regs[i]; -- -- if (reg->temp_id == temp_id -- && first_write < liveness_reg->last_access -- && last_access > liveness_reg->first_write) -- writemask &= ~reg->allocated_mask; -- -- if (!writemask) -- return writemask; -- } -- -- return writemask; --} -- --static bool temp_allocator_allocate(struct temp_allocator *allocator, struct liveness_tracker *tracker, -- struct temp_allocator_reg *reg, const struct liveness_tracker_reg *liveness_reg) --{ -- if (!liveness_reg->written) -- return false; -- -- for (uint32_t id = 0;; ++id) -- { -- uint8_t available_mask = get_available_writemask(allocator, tracker, -- liveness_reg->first_write, liveness_reg->last_access, id); -- -- if (liveness_reg->fixed_mask) -- { -- if ((available_mask & liveness_reg->mask) == liveness_reg->mask) -- { -- reg->temp_id = id; -- reg->allocated_mask = liveness_reg->mask; -- return true; -- } -- } -- else -- { -- /* For SSA values the mask is always zero-based and contiguous. -- * For TEMP values we assume the register was allocated that way, -- * but it may only be partially used. -- * We currently only handle cases where the mask is zero-based and -- * contiguous, so we need to fill in the missing components to -- * ensure this. */ -- uint8_t mask = (1u << (vkd3d_log2i(liveness_reg->mask) + 1)) - 1; -- -- if (vkd3d_popcount(available_mask) >= vkd3d_popcount(mask)) -- { -- if (mask != liveness_reg->mask) -- WARN("Allocating a mask %#x with used components %#x; this is not optimized.\n", -- mask, liveness_reg->mask); -- -- reg->temp_id = id; -- reg->allocated_mask = vsir_combine_write_masks(available_mask, mask); -- return true; -- } -- } -- } --} -- - static void temp_allocator_set_src(struct temp_allocator *allocator, struct vkd3d_shader_src_param *src) - { - struct temp_allocator_reg *reg; -@@ -9053,6 +8975,250 @@ static void temp_allocator_set_dst(struct temp_allocator *allocator, - } - } - -+static int temp_allocate_compare_open(const void *ptr1, const void *ptr2) -+{ -+ const struct temp_allocator_reg * const *reg1 = ptr1, * const *reg2 = ptr2; -+ int ret; -+ -+ if ((ret = vkd3d_u32_compare((*reg1)->liveness_reg->first_write, (*reg2)->liveness_reg->first_write))) -+ return ret; -+ if ((ret = vkd3d_u32_compare((*reg1)->liveness_reg->last_access, (*reg2)->liveness_reg->last_access))) -+ return ret; -+ /* r0 must compare before everything else for SM 1.x PS (see comment below). */ -+ if ((*reg1)->type == VKD3DSPR_TEMP && (*reg1)->idx == 0) -+ return -1; -+ if ((*reg2)->type == VKD3DSPR_TEMP && (*reg2)->idx == 0) -+ return 1; -+ return 0; -+} -+ -+static int temp_allocate_compare_close(const void *ptr1, const void *ptr2) -+{ -+ const struct temp_allocator_reg * const *reg1 = ptr1, * const *reg2 = ptr2; -+ int ret; -+ -+ if ((ret = vkd3d_u32_compare((*reg1)->liveness_reg->last_access, (*reg2)->liveness_reg->last_access))) -+ return ret; -+ return vkd3d_u32_compare((*reg1)->liveness_reg->first_write, (*reg2)->liveness_reg->first_write); -+} -+ -+static const char *debug_temp_allocator_reg(const struct temp_allocator_reg *reg) -+{ -+ return vkd3d_dbg_sprintf("%s%u", reg->type == VKD3DSPR_SSA ? "sr" : "r", reg->idx); -+} -+ -+static void temp_allocator_open_register(struct temp_allocator *allocator, struct temp_allocator_reg *reg) -+{ -+ const size_t reg_count = allocator->ssa_count + allocator->temp_count; -+ const struct liveness_tracker_reg *liveness_reg = reg->liveness_reg; -+ uint8_t *current_allocation = allocator->current_allocation; -+ size_t i; -+ -+ if (!liveness_reg->written) -+ return; -+ -+ for (i = 0; i < reg_count; ++i) -+ { -+ const uint8_t available_mask = ~current_allocation[i] & 0xf; -+ -+ if (liveness_reg->fixed_mask) -+ { -+ if ((available_mask & liveness_reg->mask) == liveness_reg->mask) -+ { -+ reg->temp_id = i; -+ reg->allocated_mask = liveness_reg->mask; -+ current_allocation[i] |= reg->allocated_mask; -+ allocator->new_temp_count = max(allocator->new_temp_count, i + 1); -+ TRACE("Allocated r%u%s for %s (liveness %u-%u).\n", -+ reg->temp_id, debug_vsir_writemask(reg->allocated_mask), -+ debug_temp_allocator_reg(reg), liveness_reg->first_write, liveness_reg->last_access); -+ break; -+ } -+ } -+ else -+ { -+ /* For SSA values the mask is always zero-based and contiguous. -+ * For TEMP values we assume the register was allocated that way, -+ * but it may only be partially used. -+ * We currently only handle cases where the mask is zero-based and -+ * contiguous, so we need to fill in the missing components to -+ * ensure this. */ -+ uint8_t mask = (1u << (vkd3d_log2i(liveness_reg->mask) + 1)) - 1; -+ -+ if (vkd3d_popcount(available_mask) >= vkd3d_popcount(mask)) -+ { -+ if (mask != liveness_reg->mask) -+ WARN("Allocating a mask %#x with used components %#x; this is not optimized.\n", -+ mask, liveness_reg->mask); -+ -+ reg->temp_id = i; -+ reg->allocated_mask = vsir_combine_write_masks(available_mask, mask); -+ current_allocation[i] |= reg->allocated_mask; -+ allocator->new_temp_count = max(allocator->new_temp_count, i + 1); -+ TRACE("Allocated r%u%s for %s (liveness %u-%u).\n", -+ reg->temp_id, debug_vsir_writemask(reg->allocated_mask), -+ debug_temp_allocator_reg(reg), liveness_reg->first_write, liveness_reg->last_access); -+ break; -+ } -+ } -+ } -+ -+ VKD3D_ASSERT(i < reg_count); -+} -+ -+static void temp_allocator_close_register(struct temp_allocator *allocator, struct temp_allocator_reg *reg) -+{ -+ const struct liveness_tracker_reg *liveness_reg = reg->liveness_reg; -+ -+ if (!liveness_reg->written) -+ return; -+ -+ TRACE("Register %s (liveness %u-%u) reaches end of life.\n", -+ debug_temp_allocator_reg(reg), liveness_reg->first_write, liveness_reg->last_access); -+ -+ allocator->current_allocation[reg->temp_id] &= ~reg->allocated_mask; -+} -+ -+/* Compute the allocation map. Each register is modeled as a time interval -+ * spanning from `first_write' to `last_access'. We simulate scanning through -+ * all the intervals in time order, keeping the set of currently allocated -+ * registers as a bit map: each time we open an interval (i.e., hit its -+ * `first_write' time) we allocate it to the first available register scanning -+ * the current state; each time we close an interval (i.e., hit its -+ * `last_access' time) we unset the corresponding bits. -+ * -+ * In general at any given time we first process all intervals to be closed and -+ * then all intervals to be opened at that time. This models the fact that an -+ * instruction can write to a register which it also reads from, and the write -+ * won't interfere with the read. In other words, first all reads are -+ * performed, then the instruction is executed, then the writes are performed. -+ * -+ * There is a corner case exception, though: the case of degenerate intervals -+ * that are opened and closed at the same time. This corresponds to registers -+ * that are written and then never read, which in principle shouldn't exist -+ * because they make no sense. However it's better to be robust, and we support -+ * them anyway. -+ * -+ * So that's what we do: -+ * - First all non-degenerate closes are processed. -+ * - Then all degenerate opens are processed, because we cannot close them -+ * before having opened them. -+ * - Then all non-degenerate opens are processed: this has to happens before -+ * the degenerate intervals are closed, because they need to be allocated to -+ * different registers. -+ * - Then all degenerate closes are processed. -+ * -+ * This is effected with a few different strategies: -+ * - In the open order, registers are primarily sorted by `first_write' and -+ * secondarily by `last_access'. This way degenerate registers are always -+ * opened before non-degenerate ones with the same `first_write' time. -+ * - In the close order, registers are primarily sorted by `last_access' and -+ * secondarily by `first_write'. This way non-degenerate registers are -+ * always closed before degenerate ones with the same `last_access' time. -+ * - There is a scheduling algorithm that decides at each iteration whether to -+ * open or close a register. See details below. -+ * -+ * TODO: the algorithm could be further optimized by keeping a few pointers to -+ * the first position in `current_allocation' that has at least one (or two, -+ * three and four) available components, so we don't always have to scan from -+ * the beginning. -+ */ -+static enum vkd3d_result temp_allocator_compute_allocation_map(struct temp_allocator *allocator, -+ const struct liveness_tracker *liveness) -+{ -+ const size_t reg_count = allocator->ssa_count + allocator->temp_count; -+ struct temp_allocator_reg **open_order = NULL, **close_order = NULL; -+ size_t i, pos_open = 0, pos_close = 0; -+ -+ /* In the worst-case scenario each of the `reg_count' registers to be -+ * processed requires its own allocation. We should never exceed that -+ * amount. */ -+ if (!(allocator->current_allocation = vkd3d_calloc(reg_count, sizeof(*allocator->current_allocation))) -+ || !(open_order = vkd3d_calloc(reg_count, sizeof(*open_order))) -+ || !(close_order = vkd3d_calloc(reg_count, sizeof(*close_order)))) -+ { -+ vkd3d_free(close_order); -+ vkd3d_free(open_order); -+ vkd3d_free(allocator->current_allocation); -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ } -+ -+ for (i = 0; i < reg_count; ++i) -+ { -+ struct temp_allocator_reg *reg = &allocator->ssa_regs[i]; -+ -+ if (i < allocator->ssa_count) -+ { -+ reg->type = VKD3DSPR_SSA; -+ reg->idx = i; -+ } -+ else -+ { -+ reg->type = VKD3DSPR_TEMP; -+ reg->idx = i - allocator->ssa_count; -+ } -+ -+ reg->liveness_reg = &liveness->ssa_regs[i]; -+ open_order[i] = reg; -+ close_order[i] = reg; -+ } -+ -+ qsort(open_order, reg_count, sizeof(*open_order), temp_allocate_compare_open); -+ qsort(close_order, reg_count, sizeof(*open_order), temp_allocate_compare_close); -+ -+ for (;;) -+ { -+ struct temp_allocator_reg *reg_open = NULL, *reg_close = NULL; -+ bool do_open; -+ -+ if (pos_open < reg_count) -+ reg_open = open_order[pos_open]; -+ if (pos_close < reg_count) -+ reg_close = close_order[pos_close]; -+ -+ /* We cannot close all the registers before we finish opening them. */ -+ VKD3D_ASSERT(!(reg_open && !reg_close)); -+ -+ /* We finished closing registers, nothing to do any more. */ -+ if (!reg_close) -+ break; -+ /* There is nothing to open, so we just close. */ -+ else if (!reg_open) -+ do_open = false; -+ /* The next open event happens before the next close event, so we open. */ -+ else if (reg_open->liveness_reg->first_write < reg_close->liveness_reg->last_access) -+ do_open = true; -+ /* The other way around, we close. */ -+ else if (reg_close->liveness_reg->last_access < reg_open->liveness_reg->first_write) -+ do_open = false; -+ /* Ok, now we have both an open and a close happening at the same time. -+ * According to the strategy above, if the interval to close is -+ * non-degenerate, then we process it. */ -+ else if (reg_close->liveness_reg->first_write < reg_close->liveness_reg->last_access) -+ do_open = false; -+ /* Otherwise the interval to close is degenerate, and therefore we first -+ * open whatever needs to be opened. */ -+ else -+ do_open = true; -+ -+ if (do_open) -+ { -+ temp_allocator_open_register(allocator, reg_open); -+ ++pos_open; -+ } -+ else -+ { -+ temp_allocator_close_register(allocator, reg_close); -+ ++pos_close; -+ } -+ } -+ -+ vkd3d_free(close_order); -+ vkd3d_free(open_order); -+ vkd3d_free(allocator->current_allocation); -+ return VKD3D_OK; -+} -+ - /* This pass does two things: - * - * - converts SSA registers (sr#) into temp registers (r#); -@@ -9073,65 +9239,45 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, - struct vkd3d_shader_message_context *message_context) - { - struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); -- const unsigned int prev_temp_count = program->temp_count; - struct temp_allocator allocator = {0}; - struct vkd3d_shader_instruction *ins; - struct temp_allocator_reg *regs; - struct liveness_tracker tracker; - enum vkd3d_result ret; - -- if (!program->ssa_count && !prev_temp_count) -+ if (!program->ssa_count && !program->temp_count) - return VKD3D_OK; - - if ((ret = track_liveness(program, &tracker))) - return ret; - -- if (!(regs = vkd3d_calloc(program->ssa_count + prev_temp_count, sizeof(*regs)))) -+ if (!(regs = vkd3d_calloc(program->ssa_count + program->temp_count, sizeof(*regs)))) - { - liveness_tracker_cleanup(&tracker); - return VKD3D_ERROR_OUT_OF_MEMORY; - } - allocator.message_context = message_context; -+ allocator.ssa_count = program->ssa_count; -+ allocator.temp_count = program->temp_count; - allocator.ssa_regs = regs; - allocator.temp_regs = regs + program->ssa_count; -+ allocator.new_temp_count = 0; - -- program->temp_count = 0; -- -- /* Reallocate temps first. We do this specifically to make sure that r0 is -- * the first register to be allocated, and thus will be reallocated in -- * place, and left alone. -- * This is necessary because, in pixel shader model 1.x, r0 doubles as the -- * output register, and needs to remain at r0. (Note that we need to already -- * have the output in r0, rather than e.g. putting it in o0 and converting -- * it to r0 after this pass, so that we know when r0 is live.) */ -- for (unsigned int i = 0; i < prev_temp_count; ++i) -+ /* For SM 1.x ps we need to ensure that r0 is reallocated to itself, because -+ * it doubles as the output register. To do so we artificially make it -+ * alive for the whole program. */ -+ if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL -+ && program->shader_version.major < 2 && allocator.temp_count >= 1) - { -- const struct liveness_tracker_reg *liveness_reg = &tracker.temp_regs[i]; -- struct temp_allocator_reg *reg = &allocator.temp_regs[i]; -- -- if (temp_allocator_allocate(&allocator, &tracker, reg, liveness_reg)) -- { -- TRACE("Reallocated r%u%s for r%u (liveness %u-%u).\n", -- reg->temp_id, debug_vsir_writemask(reg->allocated_mask), i, -- liveness_reg->first_write, liveness_reg->last_access); -- program->temp_count = max(program->temp_count, reg->temp_id + 1); -- } -- ++allocator.allocated_temp_count; -+ tracker.temp_regs[0].first_write = 0; -+ tracker.temp_regs[0].last_access = UINT_MAX; - } - -- for (unsigned int i = 0; i < program->ssa_count; ++i) -+ if ((ret = temp_allocator_compute_allocation_map(&allocator, &tracker)) < 0) - { -- const struct liveness_tracker_reg *liveness_reg = &tracker.ssa_regs[i]; -- struct temp_allocator_reg *reg = &allocator.ssa_regs[i]; -- -- if (temp_allocator_allocate(&allocator, &tracker, reg, liveness_reg)) -- { -- TRACE("Allocated r%u%s for sr%u (liveness %u-%u).\n", -- reg->temp_id, debug_vsir_writemask(reg->allocated_mask), i, -- liveness_reg->first_write, liveness_reg->last_access); -- program->temp_count = max(program->temp_count, reg->temp_id + 1); -- } -- ++allocator.allocated_ssa_count; -+ liveness_tracker_cleanup(&tracker); -+ vkd3d_free(regs); -+ return ret; - } - - for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) -@@ -9145,9 +9291,11 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, - } - - program->ssa_count = 0; -+ program->temp_count = allocator.new_temp_count; - - vkd3d_free(regs); - liveness_tracker_cleanup(&tracker); -+ - return allocator.result; - } - -@@ -11774,8 +11922,7 @@ static void vsir_validate_itof(struct validation_context *ctx, const struct vkd3 - { - [VSIR_DATA_BOOL] = true, - [VSIR_DATA_I32] = true, -- [VSIR_DATA_U32] = true, -- [VSIR_DATA_U64] = true, -+ [VSIR_DATA_I64] = true, - }; - static const bool dst_types[VSIR_DATA_TYPE_COUNT] = - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index c00a7825610..3f37dc6076b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -716,6 +716,7 @@ enum vsir_data_type - VSIR_DATA_F32, - VSIR_DATA_F64, - -+ VSIR_DATA_I8, - VSIR_DATA_I16, - VSIR_DATA_I32, - VSIR_DATA_I64, -@@ -740,8 +741,13 @@ const char *vsir_data_type_get_name(enum vsir_data_type t, const char *error); - - static inline bool data_type_is_integer(enum vsir_data_type data_type) - { -- return data_type == VSIR_DATA_I16 || data_type == VSIR_DATA_I32 || data_type == VSIR_DATA_I64 -- || data_type == VSIR_DATA_U8 || data_type == VSIR_DATA_U16 || data_type == VSIR_DATA_U32 -+ return data_type == VSIR_DATA_I8 -+ || data_type == VSIR_DATA_I16 -+ || data_type == VSIR_DATA_I32 -+ || data_type == VSIR_DATA_I64 -+ || data_type == VSIR_DATA_U8 -+ || data_type == VSIR_DATA_U16 -+ || data_type == VSIR_DATA_U32 - || data_type == VSIR_DATA_U64; - } - --- -2.51.0 - diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-b5b5c67b34be0c54bb4ee8a5439d65c2d1d.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-b5b5c67b34be0c54bb4ee8a5439d65c2d1d.patch new file mode 100644 index 00000000..54879280 --- /dev/null +++ b/patches/vkd3d-latest/0003-Updated-vkd3d-to-b5b5c67b34be0c54bb4ee8a5439d65c2d1d.patch @@ -0,0 +1,5282 @@ +From 4d48ac8b83085df9b1690392323665db907217b8 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Tue, 14 Oct 2025 10:43:27 +1100 +Subject: [PATCH] Updated vkd3d to b5b5c67b34be0c54bb4ee8a5439d65c2d1d6ba5d. + +--- + libs/vkd3d/include/vkd3d_shader.h | 61 ++ + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 5 - + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 92 +- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 118 ++- + libs/vkd3d/libs/vkd3d-shader/glsl.c | 54 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 4 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 4 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.l | 1 - + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 54 +- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 897 ++++++++++-------- + libs/vkd3d/libs/vkd3d-shader/ir.c | 653 +++++++++++-- + libs/vkd3d/libs/vkd3d-shader/msl.c | 26 +- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 334 ++----- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 77 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 52 +- + 15 files changed, 1455 insertions(+), 977 deletions(-) + +diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h +index 3a2f54c8f22..df1f5d5250d 100644 +--- a/libs/vkd3d/include/vkd3d_shader.h ++++ b/libs/vkd3d/include/vkd3d_shader.h +@@ -125,6 +125,11 @@ enum vkd3d_shader_structure_type + * \since 1.18 + */ + VKD3D_SHADER_STRUCTURE_TYPE_SCAN_THREAD_GROUP_SIZE_INFO, ++ /** ++ * The structure is a vkd3d_shader_d3dbc_source_info structure. ++ * \since 1.18 ++ */ ++ VKD3D_SHADER_STRUCTURE_TYPE_D3DBC_SOURCE_INFO, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE), + }; +@@ -2312,6 +2317,61 @@ struct vkd3d_shader_scan_thread_group_size_info + unsigned int x, y, z; + }; + ++/** ++ * A chained structure containing legacy Direct3D bytecode compilation parameters. ++ * This structure specifies some information about the source environment that ++ * is not specified in the source shader format, but may be necessary for the ++ * target format. ++ * ++ * This structure is optional. ++ * ++ * This structure extends vkd3d_shader_compile_info. ++ * ++ * This structure contains only input parameters. ++ * ++ * \since 1.18 ++ */ ++struct vkd3d_shader_d3dbc_source_info ++{ ++ /** Must be set to VKD3D_SHADER_STRUCTURE_TYPE_D3DBC_SOURCE_INFO. */ ++ enum vkd3d_shader_structure_type type; ++ /** Optional pointer to a structure containing further parameters. */ ++ const void *next; ++ ++ /** ++ * The dimension of each texture bound to the shader. ++ * ++ * If this structure is not specified, the dimension for all textures will ++ * be VKD3D_SHADER_RESOURCE_TEXTURE_2D. ++ * ++ * The dimension of textures in this array not used by the shader will be ++ * ignored. ++ * ++ * This field is ignored for shader models 2 and higher. ++ */ ++ enum vkd3d_shader_resource_type texture_dimensions[6]; ++ ++ /** ++ * A mask indicating which samplers should be shadow (i.e. comparison-mode) ++ * samplers. When legacy Direct3D shaders are used with the Direct3D 8 and 9 ++ * APIs, this is implied by the format of the sampled resource; e.g. a ++ * D3DFMT_D24S8 texture implies shadow sampling, while a D3DFMT_A8R8G8B8 ++ * or D3DFMT_INTZ texture does not. ++ * This information is necessary when converting to other formats ++ * (e.g. SPIR-V, GLSL) which specify this in the shader. ++ * ++ * For example, if bit 1 is set (so the value is 0x2), this indicates that ++ * the sampler at bind point 1 (and no others) should be a shadow sampler. ++ * ++ * Bits in this mask corresponding to textures not used by the shader will ++ * be ignored. ++ * ++ * If this structure is not specified, no samplers will be considered to ++ * be shadow samplers. ++ */ ++ uint32_t shadow_samplers; ++}; ++ + /** + * Data type of a shader varying, returned as part of struct + * vkd3d_shader_signature_element. +@@ -2805,6 +2865,7 @@ VKD3D_SHADER_API const enum vkd3d_shader_target_type *vkd3d_shader_get_supported + * + * Depending on the source and target types, this function may support the + * following chained structures: ++ * - vkd3d_shader_d3dbc_source_info + * - vkd3d_shader_descriptor_offset_info + * - vkd3d_shader_hlsl_source_info + * - vkd3d_shader_interface_info +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +index 6f8fbe84b90..4573cb67fb5 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +@@ -145,11 +145,6 @@ static void shader_dump_global_flags(struct vkd3d_d3d_asm_compiler *compiler, en + + static void shader_dump_atomic_op_flags(struct vkd3d_d3d_asm_compiler *compiler, uint32_t atomic_flags) + { +- if (atomic_flags & VKD3DARF_SEQ_CST) +- { +- vkd3d_string_buffer_printf(&compiler->buffer, "_seqCst"); +- atomic_flags &= ~VKD3DARF_SEQ_CST; +- } + if (atomic_flags & VKD3DARF_VOLATILE) + { + vkd3d_string_buffer_printf(&compiler->buffer, "_volatile"); +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index 2379efd3a02..b2d4ec23c6e 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -248,6 +248,10 @@ struct vkd3d_shader_sm1_parser + struct vkd3d_shader_parser p; + struct vsir_program *program; + ++ const struct vkd3d_shader_d3dbc_source_info *d3dbc_source_info; ++ ++ uint16_t texture_descriptors; ++ + struct + { + #define MAX_CONSTANT_COUNT 8192 +@@ -938,6 +942,27 @@ static void shader_sm1_scan_register(struct vkd3d_shader_sm1_parser *sm1, + add_signature_element_from_register(sm1, reg, false, mask, 0); + } + ++static void d3dbc_add_combined_sampler_descriptor(struct vkd3d_shader_sm1_parser *d3dbc, ++ unsigned int sampler_idx, enum vkd3d_shader_resource_type resource_type) ++{ ++ struct vkd3d_shader_register_range range = {.first = sampler_idx, .last = sampler_idx}; ++ const struct vkd3d_shader_d3dbc_source_info *source_info = d3dbc->d3dbc_source_info; ++ struct vsir_program *program = d3dbc->program; ++ struct vkd3d_shader_descriptor_info1 *d; ++ ++ if (!vsir_program_add_descriptor(program, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, ++ sampler_idx, &range, resource_type, VSIR_DATA_F32)) ++ vkd3d_shader_parser_error(&d3dbc->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, ++ "Failed to create SRV descriptor for combined sampler %u.", sampler_idx); ++ ++ if (!(d = vsir_program_add_descriptor(program, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, ++ sampler_idx, &range, VKD3D_SHADER_RESOURCE_NONE, VSIR_DATA_UNUSED))) ++ vkd3d_shader_parser_error(&d3dbc->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, ++ "Failed to create sampler descriptor for combined sampler %u.", sampler_idx); ++ else if (source_info && source_info->shadow_samplers & (1u << sampler_idx)) ++ d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE; ++} ++ + /* Read a parameter token from the input stream, and possibly a relative + * addressing token. */ + static void shader_sm1_read_param(struct vkd3d_shader_sm1_parser *sm1, +@@ -1102,6 +1127,11 @@ static void shader_sm1_read_semantic(struct vkd3d_shader_sm1_parser *sm1, + range->first = range->last = semantic->resource.reg.reg.idx[0].offset; + + add_signature_element_from_semantic(sm1, semantic); ++ if (semantic->resource_type) ++ { ++ d3dbc_add_combined_sampler_descriptor(sm1, range->first, semantic->resource_type); ++ sm1->texture_descriptors |= (1u << range->first); ++ } + } + + static void shader_sm1_read_immconst(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr, +@@ -1196,6 +1226,43 @@ static void shader_sm1_read_comment(struct vkd3d_shader_sm1_parser *sm1) + } + } + ++static void d3dbc_update_descriptors(struct vkd3d_shader_sm1_parser *d3dbc, ++ const struct vkd3d_shader_instruction *ins) ++{ ++ enum vkd3d_shader_resource_type type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; ++ const struct vkd3d_shader_d3dbc_source_info *source_info; ++ unsigned int sampler_idx; ++ ++ switch (ins->opcode) ++ { ++ case VSIR_OP_TEX: ++ case VSIR_OP_TEXBEM: ++ case VSIR_OP_TEXBEML: ++ case VSIR_OP_TEXDP3TEX: ++ case VSIR_OP_TEXLD: ++ case VSIR_OP_TEXM3x2TEX: ++ case VSIR_OP_TEXM3x3SPEC: ++ case VSIR_OP_TEXM3x3TEX: ++ case VSIR_OP_TEXM3x3VSPEC: ++ case VSIR_OP_TEXREG2AR: ++ case VSIR_OP_TEXREG2GB: ++ case VSIR_OP_TEXREG2RGB: ++ sampler_idx = ins->dst[0].reg.idx[0].offset; ++ if ((d3dbc->texture_descriptors & (1u << sampler_idx))) ++ break; ++ ++ if ((source_info = d3dbc->d3dbc_source_info) ++ && sampler_idx < ARRAY_SIZE(source_info->texture_dimensions)) ++ type = source_info->texture_dimensions[sampler_idx]; ++ d3dbc_add_combined_sampler_descriptor(d3dbc, sampler_idx, type); ++ d3dbc->texture_descriptors |= (1u << sampler_idx); ++ break; ++ ++ default: ++ break; ++ } ++} ++ + static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1, struct vkd3d_shader_instruction *ins) + { + if ((ins->opcode == VSIR_OP_BREAKP || ins->opcode == VSIR_OP_IF) && ins->flags) +@@ -1360,6 +1427,9 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str + goto fail; + } + ++ if (program->shader_version.major == 1) ++ d3dbc_update_descriptors(sm1, ins); ++ + shader_sm1_validate_instruction(sm1, ins); + return; + +@@ -1397,6 +1467,8 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, st + uint16_t shader_type; + size_t token_count; + ++ sm1->d3dbc_source_info = vkd3d_find_struct(compile_info->next, D3DBC_SOURCE_INFO); ++ + token_count = code_size / sizeof(*sm1->start); + + if (token_count < 2) +@@ -1478,6 +1550,7 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c + struct vkd3d_shader_message_context *message_context, struct vsir_program *program) + { + struct vkd3d_shader_sm1_parser sm1 = {0}; ++ struct vkd3d_shader_descriptor_info1 *d; + struct vkd3d_shader_instruction *ins; + unsigned int i; + int ret; +@@ -1506,8 +1579,23 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c + } + } + +- for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i) +- program->flat_constant_count[i] = get_external_constant_count(&sm1, i); ++ for (i = 0; i < 3; ++i) ++ { ++ struct vkd3d_shader_register_range range = {.space = 0, .first = i, .last = i}; ++ unsigned int size = get_external_constant_count(&sm1, i); ++ ++ if (size) ++ { ++ if (!(d = vsir_program_add_descriptor(program, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, ++ i, &range, VKD3D_SHADER_RESOURCE_BUFFER, VSIR_DATA_U32))) ++ vkd3d_shader_parser_error(&sm1.p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, ++ "Failed to create CBV descriptor."); ++ else ++ d->buffer_size = size * 16; ++ } ++ } ++ ++ program->has_descriptor_info = true; + + if (ret >= 0 && sm1.p.status < 0) + ret = sm1.p.status; +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index f82644d4679..c7af58118df 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -2430,9 +2430,9 @@ static unsigned int sm6_parser_alloc_ssa_id(struct sm6_parser *sm6) + } + + static void instruction_init_with_resource(struct vkd3d_shader_instruction *ins, +- enum vkd3d_shader_opcode handler_idx, const struct sm6_value *resource, struct sm6_parser *sm6) ++ enum vkd3d_shader_opcode opcode, const struct sm6_value *resource, struct sm6_parser *dxil) + { +- vsir_instruction_init(ins, &sm6->p.location, handler_idx); ++ vsir_instruction_init(ins, &dxil->p.location, opcode); + ins->resource_type = resource->u.handle.d->resource_type; + ins->raw = resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER; + ins->structured = resource->u.handle.d->kind == RESOURCE_KIND_STRUCTUREDBUFFER; +@@ -4467,6 +4467,8 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ + /* It's currently not possible to specify an atomic ordering in HLSL, and it defaults to seq_cst. */ + if ((code = record->operands[i++]) != ORDERING_SEQCST) + FIXME("Unhandled atomic ordering %"PRIu64".\n", code); ++ else ++ WARN("Ignoring atomic ordering %"PRIu64".\n", code); + + if ((code = record->operands[i]) != 1) + WARN("Ignoring synchronisation scope %"PRIu64".\n", code); +@@ -4484,7 +4486,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ + + ins = state->ins; + vsir_instruction_init(ins, &sm6->p.location, op); +- ins->flags = is_volatile ? VKD3DARF_SEQ_CST | VKD3DARF_VOLATILE : VKD3DARF_SEQ_CST; ++ ins->flags = is_volatile ? VKD3DARF_VOLATILE : 0; + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; +@@ -4509,7 +4511,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ + } + + static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_type *type_a, +- const struct sm6_type *type_b, struct sm6_parser *sm6) ++ const struct sm6_type *type_b, struct sm6_parser *sm6, enum vkd3d_shader_opcode *aux_opcode) + { + bool is_int = sm6_type_is_bool_i16_i32_i64(type_a); + bool is_double = sm6_type_is_double(type_a); +@@ -4532,12 +4534,17 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty + "Type mismatch in binary operation arguments."); + } + ++ *aux_opcode = VSIR_OP_NOP; ++ + switch (code) + { + case BINOP_ADD: ++ op = is_int ? VSIR_OP_IADD : (is_double ? VSIR_OP_DADD : VSIR_OP_ADD); ++ is_valid = !is_bool; ++ break; + case BINOP_SUB: +- /* NEG is applied later for subtraction. */ + op = is_int ? VSIR_OP_IADD : (is_double ? VSIR_OP_DADD : VSIR_OP_ADD); ++ *aux_opcode = is_int ? VSIR_OP_INEG : VSIR_OP_NEG; + is_valid = !is_bool; + break; + case BINOP_AND: +@@ -4601,12 +4608,13 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty + } + + static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_record *record, +- struct vkd3d_shader_instruction *ins, struct sm6_value *dst) ++ struct sm6_block *code_block, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) + { ++ enum vkd3d_shader_opcode opcode, aux_opcode; + struct vkd3d_shader_src_param *src_params; +- enum vkd3d_shader_opcode handler_idx; ++ struct vkd3d_shader_dst_param *dst_params; ++ uint32_t type_flags = 0, aux_id = 0; + const struct sm6_value *a, *b; +- uint32_t type_flags = 0; + uint64_t code, flags; + bool silence_warning; + unsigned int i = 0; +@@ -4622,15 +4630,34 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco + return; + + code = record->operands[i++]; +- if ((handler_idx = map_binary_op(code, a->type, b->type, sm6)) == VSIR_OP_INVALID) ++ if ((opcode = map_binary_op(code, a->type, b->type, sm6, &aux_opcode)) == VSIR_OP_INVALID) + return; + +- vsir_instruction_init(ins, &sm6->p.location, handler_idx); ++ if (aux_opcode != VSIR_OP_NOP) ++ { ++ vsir_instruction_init(ins, &sm6->p.location, aux_opcode); ++ ++ if (!(dst_params = instruction_dst_params_alloc(ins, 1, sm6)) ++ || !(src_params = instruction_src_params_alloc(ins, 1, sm6))) ++ return; ++ ++ aux_id = sm6_parser_alloc_ssa_id(sm6); ++ ++ src_param_init_from_value(&src_params[0], b, DXIL_TYPE_SIGNED, sm6); ++ ++ dst_param_init(&dst_params[0]); ++ register_init_with_id(&dst_params[0].reg, VKD3DSPR_SSA, src_params[0].reg.data_type, aux_id); ++ ++ ++ins; ++ ++code_block->instruction_count; ++ } ++ ++ vsir_instruction_init(ins, &sm6->p.location, opcode); + + flags = (record->operand_count > i) ? record->operands[i] : 0; + silence_warning = false; + +- switch (handler_idx) ++ switch (opcode) + { + case VSIR_OP_ADD: + case VSIR_OP_MUL: +@@ -4674,14 +4701,22 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; ++ + src_param_init_from_value(&src_params[0], a, type_flags, sm6); +- src_param_init_from_value(&src_params[1], b, type_flags, sm6); +- if (code == BINOP_SUB) +- src_params[1].modifiers = VKD3DSPSM_NEG; ++ ++ if (aux_opcode == VSIR_OP_NOP) ++ { ++ src_param_init_from_value(&src_params[1], b, type_flags, sm6); ++ } ++ else ++ { ++ src_param_init(&src_params[1]); ++ register_init_with_id(&src_params[1].reg, VKD3DSPR_SSA, src_params[0].reg.data_type, aux_id); ++ } + + dst->type = a->type; + +- if (handler_idx == VSIR_OP_ISHL || handler_idx == VSIR_OP_ISHR || handler_idx == VSIR_OP_USHR) ++ if (opcode == VSIR_OP_ISHL || opcode == VSIR_OP_ISHR || opcode == VSIR_OP_USHR) + { + /* DXC emits AND instructions where necessary to mask shift counts. + * Shift binops do not imply masking the shift as the TPF equivalents +@@ -5041,18 +5076,18 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr + unsigned int i, coord_idx, coord_count = 1; + struct vkd3d_shader_dst_param *dst_params; + struct vkd3d_shader_src_param *src_params; +- enum vkd3d_shader_opcode handler_idx; + struct vkd3d_shader_instruction *ins; + const struct sm6_value *resource; + struct vkd3d_shader_register reg; ++ enum vkd3d_shader_opcode opcode; + + resource = operands[0]; + if (!sm6_value_validate_is_handle(resource, sm6)) + return; + + if (is_cmp_xchg) +- handler_idx = VSIR_OP_IMM_ATOMIC_CMP_EXCH; +- else if ((handler_idx = map_dx_atomic_binop(operands[1], sm6)) == VSIR_OP_INVALID) ++ opcode = VSIR_OP_IMM_ATOMIC_CMP_EXCH; ++ else if ((opcode = map_dx_atomic_binop(operands[1], sm6)) == VSIR_OP_INVALID) + return; + + coord_idx = 2 - is_cmp_xchg; +@@ -5074,13 +5109,13 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr + { + WARN("Ignoring unexpected operand.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, +- "Ignoring an unexpected defined operand value for atomic instruction %u.", handler_idx); ++ "Ignoring an unexpected defined operand value for atomic instruction %u.", opcode); + break; + } + } + + ins = state->ins; +- vsir_instruction_init(ins, &sm6->p.location, handler_idx); ++ vsir_instruction_init(ins, &sm6->p.location, opcode); + + if (!(src_params = instruction_src_params_alloc(ins, 2 + is_cmp_xchg, sm6))) + return; +@@ -5223,16 +5258,16 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr + instruction_dst_param_init_ssa_vector(ins, sm6_type_max_vector_size(type), sm6); + } + +-static void sm6_parser_dcl_register_builtin(struct sm6_parser *sm6, enum vkd3d_shader_opcode handler_idx, ++static void sm6_parser_dcl_register_builtin(struct sm6_parser *dxil, enum vkd3d_shader_opcode opcode, + enum vkd3d_shader_register_type reg_type, enum vsir_data_type data_type, unsigned int component_count) + { + struct vkd3d_shader_dst_param *dst_param; + struct vkd3d_shader_instruction *ins; + +- if (!bitmap_is_set(sm6->io_regs_declared, reg_type)) ++ if (!bitmap_is_set(dxil->io_regs_declared, reg_type)) + { +- bitmap_set(sm6->io_regs_declared, reg_type); +- if (!(ins = sm6_parser_add_instruction(sm6, handler_idx))) ++ bitmap_set(dxil->io_regs_declared, reg_type); ++ if (!(ins = sm6_parser_add_instruction(dxil, opcode))) + return; + dst_param = &ins->declaration.dst; + vsir_register_init(&dst_param->reg, reg_type, data_type, 0); +@@ -5394,21 +5429,21 @@ static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opc + struct vkd3d_shader_src_param *src_params; + struct vkd3d_shader_instruction *ins; + struct vkd3d_shader_register regs[2]; +- enum vkd3d_shader_opcode handler_idx; ++ enum vkd3d_shader_opcode opcode; + unsigned int component_count; + + switch (op) + { + case DX_DOT2: +- handler_idx = VSIR_OP_DP2; ++ opcode = VSIR_OP_DP2; + component_count = 2; + break; + case DX_DOT3: +- handler_idx = VSIR_OP_DP3; ++ opcode = VSIR_OP_DP3; + component_count = 3; + break; + case DX_DOT4: +- handler_idx = VSIR_OP_DP4; ++ opcode = VSIR_OP_DP4; + component_count = 4; + break; + default: +@@ -5421,7 +5456,7 @@ static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opc + return; + + ins = state->ins; +- vsir_instruction_init(ins, &sm6->p.location, handler_idx); ++ vsir_instruction_init(ins, &sm6->p.location, opcode); + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; + src_param_init_vector_from_reg(&src_params[0], ®s[0]); +@@ -5483,11 +5518,10 @@ static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_op + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_param; + +- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); ++ vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_ABS); + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; + src_param_init_from_value(src_param, operands[0], 0, sm6); +- src_param->modifiers = VKD3DSPSM_ABS; + + instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } +@@ -7125,7 +7159,7 @@ static void sm6_parser_emit_cast(struct sm6_parser *dxil, const struct dxil_reco + + struct sm6_cmp_info + { +- enum vkd3d_shader_opcode handler_idx; ++ enum vkd3d_shader_opcode opcode; + bool src_swap; + uint32_t type_flags; + }; +@@ -7227,7 +7261,7 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor + "Type mismatch in comparison operation arguments."); + } + +- if (!(cmp = sm6_map_cmp2_op(code)) || !cmp->handler_idx || cmp->handler_idx == VSIR_OP_INVALID) ++ if (!(cmp = sm6_map_cmp2_op(code)) || !cmp->opcode || cmp->opcode == VSIR_OP_INVALID) + { + FIXME("Unhandled operation %"PRIu64".\n", code); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +@@ -7235,7 +7269,7 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor + return; + } + +- vsir_instruction_init(ins, &sm6->p.location, cmp->handler_idx); ++ vsir_instruction_init(ins, &sm6->p.location, cmp->opcode); + + flags = (record->operand_count > i) ? record->operands[i] : 0; + silence_warning = false; +@@ -7327,6 +7361,8 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re + /* It's currently not possible to specify an atomic ordering in HLSL, and it defaults to seq_cst. */ + if (success_ordering != ORDERING_SEQCST) + FIXME("Unhandled success ordering %"PRIu64".\n", success_ordering); ++ else ++ WARN("Ignoring success ordering %"PRIu64".\n", success_ordering); + if (success_ordering != failure_ordering) + FIXME("Unhandled failure ordering %"PRIu64".\n", failure_ordering); + +@@ -7334,7 +7370,7 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re + FIXME("Ignoring weak cmpxchg.\n"); + + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_IMM_ATOMIC_CMP_EXCH); +- ins->flags = is_volatile ? VKD3DARF_SEQ_CST | VKD3DARF_VOLATILE : VKD3DARF_SEQ_CST; ++ ins->flags = is_volatile ? VKD3DARF_VOLATILE : 0; + + if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) + return; +@@ -8342,7 +8378,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + break; + } + case FUNC_CODE_INST_BINOP: +- sm6_parser_emit_binop(sm6, record, ins, dst); ++ sm6_parser_emit_binop(sm6, record, code_block, ins, dst); + break; + case FUNC_CODE_INST_BR: + sm6_parser_emit_br(sm6, record, function, code_block, ins); +@@ -10121,22 +10157,22 @@ static enum vkd3d_result sm6_parser_emit_thread_group(struct sm6_parser *sm6, co + return VKD3D_OK; + } + +-static void sm6_parser_emit_dcl_count(struct sm6_parser *sm6, enum vkd3d_shader_opcode handler_idx, unsigned int count) ++static void sm6_parser_emit_dcl_count(struct sm6_parser *dxil, enum vkd3d_shader_opcode opcode, unsigned int count) + { + struct vkd3d_shader_instruction *ins; + +- if (!(ins = sm6_parser_add_instruction(sm6, handler_idx))) ++ if (!(ins = sm6_parser_add_instruction(dxil, opcode))) + return; + ins->declaration.count = count; + } + +-static void sm6_parser_emit_dcl_primitive_topology(struct sm6_parser *sm6, +- enum vkd3d_shader_opcode handler_idx, enum vkd3d_primitive_type primitive_type, ++static void sm6_parser_emit_dcl_primitive_topology(struct sm6_parser *dxil, ++ enum vkd3d_shader_opcode opcode, enum vkd3d_primitive_type primitive_type, + unsigned int patch_vertex_count) + { + struct vkd3d_shader_instruction *ins; + +- if (!(ins = sm6_parser_add_instruction(sm6, handler_idx))) ++ if (!(ins = sm6_parser_add_instruction(dxil, opcode))) + return; + ins->declaration.primitive_type.type = primitive_type; + ins->declaration.primitive_type.patch_vertex_count = patch_vertex_count; +diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c +index b2679beff9f..88c87ae33ee 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c +@@ -280,7 +280,7 @@ static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, + break; + + case VKD3DSPR_THREADID: +- vkd3d_string_buffer_printf(buffer, "gl_GlobalInvocationID"); ++ vkd3d_string_buffer_printf(buffer, "uvec4(gl_GlobalInvocationID, 0)"); + break; + + case VKD3DSPR_IDXTEMP: +@@ -419,25 +419,11 @@ static void shader_glsl_print_src(struct vkd3d_string_buffer *buffer, struct vkd + if (reg->dimension == VSIR_DIMENSION_VEC4) + shader_glsl_print_swizzle(str, vsir_src->swizzle, mask); + +- switch (vsir_src->modifiers) ++ if (vsir_src->modifiers) + { +- case VKD3DSPSM_NONE: +- break; +- case VKD3DSPSM_NEG: +- vkd3d_string_buffer_printf(buffer, "-%s", str->buffer); +- break; +- case VKD3DSPSM_ABS: +- vkd3d_string_buffer_printf(buffer, "abs(%s)", str->buffer); +- break; +- case VKD3DSPSM_ABSNEG: +- vkd3d_string_buffer_printf(buffer, "-abs(%s)", str->buffer); +- break; +- default: +- vkd3d_string_buffer_printf(buffer, "(%s)", +- vsir_src->modifiers, str->buffer); +- vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, +- "Internal compiler error: Unhandled source modifier(s) %#x.", vsir_src->modifiers); +- break; ++ vkd3d_string_buffer_printf(buffer, "(%s)", vsir_src->modifiers, str->buffer); ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled source modifier(s) %#x.", vsir_src->modifiers); + } + + if (str != buffer) +@@ -1240,25 +1226,33 @@ static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d + + static void shader_glsl_movc(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) + { ++ struct vkd3d_string_buffer *src1, *src2; + unsigned int component_count; +- struct glsl_src src[3]; ++ struct glsl_src src[1]; + struct glsl_dst dst; + uint32_t mask; + ++ /* Sadly, mix() in unextended GLSL 4.40 can only select between ++ * floating-point sources. The earliest version able to select between ++ * integer sources is version 4.50; the same functionality is also ++ * provided by the EXT_shader_integer_mix extension. */ ++ + mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); + glsl_src_init(&src[0], gen, &ins->src[0], mask); +- glsl_src_init(&src[1], gen, &ins->src[1], mask); +- glsl_src_init(&src[2], gen, &ins->src[2], mask); ++ src1 = vkd3d_string_buffer_get(&gen->string_buffers); ++ src2 = vkd3d_string_buffer_get(&gen->string_buffers); ++ shader_glsl_print_src(src1, gen, &ins->src[1], mask, VSIR_DATA_F32); ++ shader_glsl_print_src(src2, gen, &ins->src[2], mask, VSIR_DATA_F32); + + if ((component_count = vsir_write_mask_component_count(mask)) > 1) +- shader_glsl_print_assignment(gen, &dst, "mix(%s, %s, bvec%u(%s))", +- src[2].str->buffer, src[1].str->buffer, component_count, src[0].str->buffer); ++ shader_glsl_print_assignment_ext(gen, &dst, VSIR_DATA_F32, "mix(%s, %s, bvec%u(%s))", ++ src2->buffer, src1->buffer, component_count, src[0].str->buffer); + else +- shader_glsl_print_assignment(gen, &dst, "mix(%s, %s, bool(%s))", +- src[2].str->buffer, src[1].str->buffer, src[0].str->buffer); ++ shader_glsl_print_assignment_ext(gen, &dst, VSIR_DATA_F32, "mix(%s, %s, bool(%s))", ++ src2->buffer, src1->buffer, src[0].str->buffer); + +- glsl_src_cleanup(&src[2], &gen->string_buffers); +- glsl_src_cleanup(&src[1], &gen->string_buffers); ++ vkd3d_string_buffer_release(&gen->string_buffers, src2); ++ vkd3d_string_buffer_release(&gen->string_buffers, src1); + glsl_src_cleanup(&src[0], &gen->string_buffers); + glsl_dst_cleanup(&dst, &gen->string_buffers); + } +@@ -1485,6 +1479,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + + switch (ins->opcode) + { ++ case VSIR_OP_ABS: ++ shader_glsl_intrinsic(gen, ins, "abs"); ++ break; + case VSIR_OP_ADD: + case VSIR_OP_IADD: + shader_glsl_binop(gen, ins, "+"); +@@ -1597,6 +1594,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + shader_glsl_relop(gen, ins, "!=", "notEqual"); + break; + case VSIR_OP_INEG: ++ case VSIR_OP_NEG: + shader_glsl_unary_op(gen, ins, "-"); + break; + case VSIR_OP_ISHL: +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +index ec1e27d9496..3b0a7acb52a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +@@ -2205,11 +2205,11 @@ static struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, + return &store->node; + } + +-void hlsl_block_add_resource_store(struct hlsl_ctx *ctx, struct hlsl_block *block, ++struct hlsl_ir_node *hlsl_block_add_resource_store(struct hlsl_ctx *ctx, struct hlsl_block *block, + enum hlsl_resource_store_type type, const struct hlsl_deref *resource, struct hlsl_ir_node *coords, + struct hlsl_ir_node *value, uint32_t writemask, const struct vkd3d_shader_location *loc) + { +- append_new_instr(ctx, block, hlsl_new_resource_store(ctx, type, resource, coords, value, writemask, loc)); ++ return append_new_instr(ctx, block, hlsl_new_resource_store(ctx, type, resource, coords, value, writemask, loc)); + } + + struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int component_count, +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +index 6c6243db799..829fcba0aab 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +@@ -534,6 +534,8 @@ struct hlsl_ir_var + struct + { + bool used; ++ bool uav_read; ++ bool uav_atomics; + enum hlsl_sampler_dim sampler_dim; + struct vkd3d_shader_location first_sampler_dim_loc; + } *objects_usage[HLSL_REGSET_LAST_OBJECT + 1]; +@@ -1599,7 +1601,7 @@ void hlsl_block_add_loop(struct hlsl_ctx *ctx, struct hlsl_block *block, + unsigned int unroll_limit, const struct vkd3d_shader_location *loc); + struct hlsl_ir_node *hlsl_block_add_resource_load(struct hlsl_ctx *ctx, struct hlsl_block *block, + const struct hlsl_resource_load_params *params, const struct vkd3d_shader_location *loc); +-void hlsl_block_add_resource_store(struct hlsl_ctx *ctx, struct hlsl_block *block, ++struct hlsl_ir_node *hlsl_block_add_resource_store(struct hlsl_ctx *ctx, struct hlsl_block *block, + enum hlsl_resource_store_type type, const struct hlsl_deref *resource, struct hlsl_ir_node *coords, + struct hlsl_ir_node *value, uint32_t writemask, const struct vkd3d_shader_location *loc); + struct hlsl_ir_node *hlsl_block_add_simple_load(struct hlsl_ctx *ctx, struct hlsl_block *block, +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l +index da9f0d39136..c41d807cca1 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l +@@ -83,7 +83,6 @@ ComputeShader {return KW_COMPUTESHADER; } + compile {return KW_COMPILE; } + CompileShader {return KW_COMPILESHADER; } + const {return KW_CONST; } +-ConstructGSWithSO {return KW_CONSTRUCTGSWITHSO; } + continue {return KW_CONTINUE; } + DepthStencilState {return KW_DEPTHSTENCILSTATE; } + DepthStencilView {return KW_DEPTHSTENCILVIEW; } +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index 37b116bed40..27afac71320 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -5337,6 +5337,23 @@ static bool intrinsic_AllMemoryBarrierWithGroupSync(struct hlsl_ctx *ctx, + | VKD3DSSF_GROUP_SHARED_MEMORY | VKD3DSSF_THREAD_GROUP, loc); + } + ++static bool intrinsic_ConstructGSWithSO(struct hlsl_ctx *ctx, ++ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_ir_node *compile; ++ ++ if (params->args_count != 2 && params->args_count != 6) ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, ++ "Wrong number of arguments to ConstructGSWithSO(): expected 2 or 6, but got %u.", params->args_count); ++ ++ if (!(compile = hlsl_new_compile(ctx, HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO, ++ NULL, params->args, params->args_count, params->instrs, loc))) ++ return false; ++ ++ hlsl_block_add_instr(params->instrs, compile); ++ return true; ++} ++ + static bool intrinsic_DeviceMemoryBarrier(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +@@ -5386,6 +5403,7 @@ intrinsic_functions[] = + /* Note: these entries should be kept in alphabetical order. */ + {"AllMemoryBarrier", 0, true, intrinsic_AllMemoryBarrier}, + {"AllMemoryBarrierWithGroupSync", 0, true, intrinsic_AllMemoryBarrierWithGroupSync}, ++ {"ConstructGSWithSO", -1, false, intrinsic_ConstructGSWithSO}, + {"D3DCOLORtoUBYTE4", 1, true, intrinsic_d3dcolor_to_ubyte4}, + {"DeviceMemoryBarrier", 0, true, intrinsic_DeviceMemoryBarrier}, + {"DeviceMemoryBarrierWithGroupSync", 0, true, intrinsic_DeviceMemoryBarrierWithGroupSync}, +@@ -5629,36 +5647,6 @@ static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const cha + return make_block(ctx, compile); + } + +-static struct hlsl_block *add_compile_variant(struct hlsl_ctx *ctx, enum hlsl_compile_type compile_type, +- struct parse_initializer *args, const struct vkd3d_shader_location *loc) +-{ +- struct hlsl_ir_node *compile; +- +- switch (compile_type) +- { +- case HLSL_COMPILE_TYPE_COMPILE: +- vkd3d_unreachable(); +- +- case HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO: +- if (args->args_count != 2 && args->args_count != 6) +- { +- hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, +- "Wrong number of arguments to ConstructGSWithSO: expected 2 or 6, but got %u.", +- args->args_count); +- } +- break; +- } +- +- if (!(compile = hlsl_new_compile(ctx, compile_type, NULL, args->args, args->args_count, args->instrs, loc))) +- { +- free_parse_initializer(args); +- return NULL; +- } +- +- free_parse_initializer(args); +- return make_block(ctx, compile); +-} +- + static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type, + struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +@@ -6939,7 +6927,6 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, + %token KW_COMPILESHADER + %token KW_COMPUTESHADER + %token KW_CONST +-%token KW_CONSTRUCTGSWITHSO + %token KW_CONTINUE + %token KW_DEFAULT + %token KW_DEPTHSTENCILSTATE +@@ -9453,11 +9440,6 @@ primary_expr: + vkd3d_free($3); + vkd3d_free($5); + } +- | KW_CONSTRUCTGSWITHSO '(' func_arguments ')' +- { +- if (!($$ = add_compile_variant(ctx, HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO, &$3, &@1))) +- YYABORT; +- } + | var_identifier '(' func_arguments ')' + { + if (!($$ = add_call(ctx, $1, &$3, &@1))) +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index d22330cedb7..8f4e4cda73f 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -926,18 +926,17 @@ bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, + return progress; + } + +-typedef bool (*PFN_lower_func)(struct hlsl_ctx *, struct hlsl_ir_node *, struct hlsl_block *); ++typedef struct hlsl_ir_node *(*PFN_replace_func)(struct hlsl_ctx *, struct hlsl_ir_node *, struct hlsl_block *); + +-static bool call_lower_func(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) ++static bool call_replace_func(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) + { +- PFN_lower_func func = context; ++ struct hlsl_ir_node *replacement; ++ PFN_replace_func func = context; + struct hlsl_block block; + + hlsl_block_init(&block); +- if (func(ctx, instr, &block)) ++ if ((replacement = func(ctx, instr, &block))) + { +- struct hlsl_ir_node *replacement = LIST_ENTRY(list_tail(&block.instrs), struct hlsl_ir_node, entry); +- + list_move_before(&instr->entry, &block.instrs); + hlsl_replace_node(instr, replacement); + return true; +@@ -949,12 +948,17 @@ static bool call_lower_func(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, vo + } + } + +-/* Specific form of transform_ir() for passes which convert a single instruction +- * to a block of one or more instructions. This helper takes care of setting up +- * the block and calling hlsl_replace_node_with_block(). */ +-static bool lower_ir(struct hlsl_ctx *ctx, PFN_lower_func func, struct hlsl_block *block) ++/* Specific form of transform_ir() for passes which replace a single instruction ++ * with another instruction. This includes passes which lower an instruction ++ * to one or more new instructions, and passes which fold away a redundant ++ * instruction. ++ * ++ * New instructions should be added to "block", and the replacement instruction ++ * should be returned. If the instruction should be left alone, NULL should be ++ * returned instead. */ ++static bool replace_ir(struct hlsl_ctx *ctx, PFN_replace_func func, struct hlsl_block *block) + { +- return hlsl_transform_ir(ctx, call_lower_func, block, func); ++ return hlsl_transform_ir(ctx, call_replace_func, block, func); + } + + static bool transform_instr_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +@@ -1295,7 +1299,8 @@ static struct hlsl_ir_node *add_zero_mipmap_level(struct hlsl_ctx *ctx, struct h + return hlsl_block_add_simple_load(ctx, block, coords, loc); + } + +-static bool lower_complex_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_complex_casts(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + unsigned int src_comp_count, dst_comp_count; + struct hlsl_type *src_type, *dst_type; +@@ -1306,17 +1311,17 @@ static bool lower_complex_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + unsigned int dst_idx; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + + if (hlsl_ir_expr(instr)->op != HLSL_OP1_CAST) +- return false; ++ return NULL; + + arg = hlsl_ir_expr(instr)->operands[0].node; + dst_type = instr->data_type; + src_type = arg->data_type; + + if (src_type->class <= HLSL_CLASS_VECTOR && dst_type->class <= HLSL_CLASS_VECTOR) +- return false; ++ return NULL; + + src_comp_count = hlsl_type_component_count(src_type); + dst_comp_count = hlsl_type_component_count(dst_type); +@@ -1332,7 +1337,7 @@ static bool lower_complex_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + } + + if (!(var = hlsl_new_synthetic_var(ctx, "cast", dst_type, &instr->loc))) +- return false; ++ return NULL; + hlsl_init_simple_deref_from_var(&var_deref, var); + + for (dst_idx = 0; dst_idx < dst_comp_count; ++dst_idx) +@@ -1363,8 +1368,7 @@ static bool lower_complex_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + hlsl_block_add_store_component(ctx, block, &var_deref, dst_idx, cast); + } + +- hlsl_block_add_simple_load(ctx, block, var, &instr->loc); +- return true; ++ return hlsl_block_add_simple_load(ctx, block, var, &instr->loc); + } + + /* hlsl_ir_swizzle nodes that directly point to a matrix value are only a parse-time construct that +@@ -1372,7 +1376,8 @@ static bool lower_complex_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + * an assignment or as a value made from different components of the matrix. The former cases should + * have already been split into several separate assignments, but the latter are lowered by this + * pass. */ +-static bool lower_matrix_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_matrix_swizzles(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_swizzle *swizzle; + struct hlsl_deref var_deref; +@@ -1381,14 +1386,14 @@ static bool lower_matrix_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins + unsigned int k, i; + + if (instr->type != HLSL_IR_SWIZZLE) +- return false; ++ return NULL; + swizzle = hlsl_ir_swizzle(instr); + matrix_type = swizzle->val.node->data_type; + if (matrix_type->class != HLSL_CLASS_MATRIX) +- return false; ++ return NULL; + + if (!(var = hlsl_new_synthetic_var(ctx, "matrix-swizzle", instr->data_type, &instr->loc))) +- return false; ++ return NULL; + hlsl_init_simple_deref_from_var(&var_deref, var); + + for (i = 0; i < instr->data_type->e.numeric.dimx; ++i) +@@ -1401,8 +1406,7 @@ static bool lower_matrix_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins + hlsl_block_add_store_component(ctx, block, &var_deref, i, load); + } + +- hlsl_block_add_simple_load(ctx, block, var, &instr->loc); +- return true; ++ return hlsl_block_add_simple_load(ctx, block, var, &instr->loc); + } + + /* hlsl_ir_index nodes are a parse-time construct used to represent array indexing and struct +@@ -1411,7 +1415,8 @@ static bool lower_matrix_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins + * For the latter case, this pass takes care of lowering hlsl_ir_indexes into individual + * hlsl_ir_loads, or individual hlsl_ir_resource_loads, in case the indexing is a + * resource access. */ +-static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_index_loads(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_deref var_deref; + struct hlsl_ir_index *index; +@@ -1420,7 +1425,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + struct hlsl_ir_var *var; + + if (instr->type != HLSL_IR_INDEX) +- return false; ++ return NULL; + index = hlsl_ir_index(instr); + val = index->val.node; + +@@ -1435,14 +1440,13 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + VKD3D_ASSERT(coords->data_type->e.numeric.dimx == dim_count); + + if (!(coords = add_zero_mipmap_level(ctx, block, coords, &instr->loc))) +- return false; ++ return NULL; + + params.type = HLSL_RESOURCE_LOAD; + params.resource = val; + params.coords = coords; + params.format = val->data_type->e.resource.format; +- hlsl_block_add_resource_load(ctx, block, ¶ms, &instr->loc); +- return true; ++ return hlsl_block_add_resource_load(ctx, block, ¶ms, &instr->loc); + } + + if (val->type == HLSL_IR_RESOURCE_LOAD) +@@ -1459,7 +1463,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + struct hlsl_deref row_deref; + + if (!(var = hlsl_new_synthetic_var(ctx, "row", instr->data_type, &instr->loc))) +- return false; ++ return NULL; + hlsl_init_simple_deref_from_var(&row_deref, var); + + for (unsigned int i = 0; i < mat->data_type->e.numeric.dimx; ++i) +@@ -1488,7 +1492,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + hlsl_block_add_store_component(ctx, block, &row_deref, i, &column_load->node); + } + +- hlsl_block_add_simple_load(ctx, block, var, &instr->loc); ++ return hlsl_block_add_simple_load(ctx, block, var, &instr->loc); + } + else + { +@@ -1506,14 +1510,13 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + appended_load->node.data_type = type; + + hlsl_block_add_instr(block, &appended_load->node); ++ return &appended_load->node; + } +- +- return true; + } + } + + if (!(var = hlsl_new_synthetic_var(ctx, "index-val", val->data_type, &instr->loc))) +- return false; ++ return NULL; + hlsl_init_simple_deref_from_var(&var_deref, var); + + hlsl_block_add_simple_store(ctx, block, var, val); +@@ -1527,7 +1530,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + VKD3D_ASSERT(!hlsl_type_is_row_major(mat->data_type)); + + if (!(var = hlsl_new_synthetic_var(ctx, "row", instr->data_type, &instr->loc))) +- return false; ++ return NULL; + hlsl_init_simple_deref_from_var(&row_deref, var); + + for (i = 0; i < mat->data_type->e.numeric.dimx; ++i) +@@ -1537,37 +1540,34 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + c = hlsl_block_add_uint_constant(ctx, block, i, &instr->loc); + + if (!(load = hlsl_new_load_index(ctx, &var_deref, c, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, &load->node); + + if (!(load = hlsl_new_load_index(ctx, &load->src, index->idx.node, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, &load->node); + + hlsl_block_add_store_index(ctx, block, &row_deref, c, &load->node, 0, &instr->loc); + } + +- hlsl_block_add_simple_load(ctx, block, var, &instr->loc); +- } +- else +- { +- hlsl_block_add_load_index(ctx, block, &var_deref, index->idx.node, &instr->loc); ++ return hlsl_block_add_simple_load(ctx, block, var, &instr->loc); + } +- return true; ++ ++ return hlsl_block_add_load_index(ctx, block, &var_deref, index->idx.node, &instr->loc); + } + + /* Lower casts from vec1 to vecN to swizzles. */ +-static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + const struct hlsl_type *src_type, *dst_type; + struct hlsl_type *dst_scalar_type; + struct hlsl_ir_expr *cast; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + cast = hlsl_ir_expr(instr); + if (cast->op != HLSL_OP1_CAST) +- return false; ++ return NULL; + src_type = cast->operands[0].node->data_type; + dst_type = cast->node.data_type; + +@@ -1581,17 +1581,17 @@ static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, s + new_cast = hlsl_block_add_cast(ctx, block, cast->operands[0].node, dst_scalar_type, &cast->node.loc); + + if (dst_type->e.numeric.dimx != 1) +- hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(X, X, X, X), ++ return hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(X, X, X, X), + dst_type->e.numeric.dimx, new_cast, &cast->node.loc); + +- return true; ++ return new_cast; + } + +- return false; ++ return NULL; + } + + /* Lowers loads from TGSMs to resource loads. */ +-static bool lower_tgsm_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_tgsm_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_resource_load_params params = {.type = HLSL_RESOURCE_LOAD}; + const struct vkd3d_shader_location *loc = &instr->loc; +@@ -1599,29 +1599,28 @@ static bool lower_tgsm_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, s + struct hlsl_deref *deref; + + if (instr->type != HLSL_IR_LOAD || !hlsl_is_numeric_type(instr->data_type)) +- return false; ++ return NULL; + load = hlsl_ir_load(instr); + deref = &load->src; + + if (!deref->var->is_tgsm) +- return false; ++ return NULL; + + if (deref->path_len) + { + hlsl_fixme(ctx, &instr->loc, "Load from indexed TGSM."); +- return false; ++ return NULL; + } + + params.resource = hlsl_block_add_simple_load(ctx, block, deref->var, loc); + params.format = instr->data_type; + params.coords = hlsl_block_add_uint_constant(ctx, block, 0, &instr->loc); +- hlsl_block_add_resource_load(ctx, block, ¶ms, loc); +- +- return true; ++ return hlsl_block_add_resource_load(ctx, block, ¶ms, loc); + } + + /* Lowers stores to TGSMs to resource stores. */ +-static bool lower_tgsm_stores(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_tgsm_stores(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_store *store; + struct hlsl_ir_node *coords; +@@ -1629,26 +1628,24 @@ static bool lower_tgsm_stores(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + struct hlsl_deref *deref; + + if (instr->type != HLSL_IR_STORE) +- return false; ++ return NULL; + store = hlsl_ir_store(instr); + deref = &store->lhs; + + if (!deref->var->is_tgsm) +- return false; ++ return NULL; + + if (deref->path_len) + { + hlsl_fixme(ctx, &instr->loc, "Store to indexed TGSM."); +- return false; ++ return NULL; + } + + hlsl_init_simple_deref_from_var(&res_deref, deref->var); + coords = hlsl_block_add_uint_constant(ctx, block, 0, &instr->loc); + +- hlsl_block_add_resource_store(ctx, block, HLSL_RESOURCE_STORE, &res_deref, ++ return hlsl_block_add_resource_store(ctx, block, HLSL_RESOURCE_STORE, &res_deref, + coords, store->rhs.node, store->writemask, &instr->loc); +- +- return true; + } + + /* Allocate a unique, ordered index to each instruction, which will be used for +@@ -3567,7 +3564,8 @@ static bool validate_dereferences(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins + return false; + } + +-static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) ++static struct hlsl_ir_node *fold_redundant_casts(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + if (instr->type == HLSL_IR_EXPR) + { +@@ -3576,20 +3574,17 @@ static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst + const struct hlsl_type *src_type; + + if (expr->op != HLSL_OP1_CAST) +- return false; ++ return NULL; + + src_type = expr->operands[0].node->data_type; + + if (hlsl_types_are_equal(src_type, dst_type) + || (src_type->e.numeric.type == dst_type->e.numeric.type + && hlsl_is_vec1(src_type) && hlsl_is_vec1(dst_type))) +- { +- hlsl_replace_node(&expr->node, expr->operands[0].node); +- return true; +- } ++ return expr->operands[0].node; + } + +- return false; ++ return NULL; + } + + /* Copy an element of a complex variable. Helper for +@@ -3824,17 +3819,18 @@ static bool split_matrix_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + return true; + } + +-static bool lower_narrowing_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_narrowing_casts(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + const struct hlsl_type *src_type, *dst_type; + struct hlsl_type *dst_vector_type; + struct hlsl_ir_expr *cast; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + cast = hlsl_ir_expr(instr); + if (cast->op != HLSL_OP1_CAST) +- return false; ++ return NULL; + src_type = cast->operands[0].node->data_type; + dst_type = cast->node.data_type; + +@@ -3847,65 +3843,58 @@ static bool lower_narrowing_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins + /* We need to preserve the cast since it might be doing more than just + * narrowing the vector. */ + new_cast = hlsl_block_add_cast(ctx, block, cast->operands[0].node, dst_vector_type, &cast->node.loc); +- hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(X, Y, Z, W), ++ return hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(X, Y, Z, W), + dst_type->e.numeric.dimx, new_cast, &cast->node.loc); +- return true; + } + +- return false; ++ return NULL; + } + +-static bool fold_swizzle_chains(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) ++static struct hlsl_ir_node *fold_swizzle_chains(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_swizzle *swizzle; + struct hlsl_ir_node *next_instr; + + if (instr->type != HLSL_IR_SWIZZLE) +- return false; ++ return NULL; + swizzle = hlsl_ir_swizzle(instr); + + next_instr = swizzle->val.node; + + if (next_instr->type == HLSL_IR_SWIZZLE) + { +- struct hlsl_ir_node *new_swizzle; + uint32_t combined_swizzle; + + combined_swizzle = hlsl_combine_swizzles(hlsl_ir_swizzle(next_instr)->u.vector, + swizzle->u.vector, instr->data_type->e.numeric.dimx); + next_instr = hlsl_ir_swizzle(next_instr)->val.node; + +- if (!(new_swizzle = hlsl_new_swizzle(ctx, combined_swizzle, +- instr->data_type->e.numeric.dimx, next_instr, &instr->loc))) +- return false; +- +- list_add_before(&instr->entry, &new_swizzle->entry); +- hlsl_replace_node(instr, new_swizzle); +- return true; ++ return hlsl_block_add_swizzle(ctx, block, combined_swizzle, ++ instr->data_type->e.numeric.dimx, next_instr, &instr->loc); + } + +- return false; ++ return NULL; + } + +-static bool remove_trivial_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) ++static struct hlsl_ir_node *fold_trivial_swizzles(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_swizzle *swizzle; + unsigned int i; + + if (instr->type != HLSL_IR_SWIZZLE) +- return false; ++ return NULL; + swizzle = hlsl_ir_swizzle(instr); + + if (instr->data_type->e.numeric.dimx != swizzle->val.node->data_type->e.numeric.dimx) +- return false; ++ return NULL; + + for (i = 0; i < instr->data_type->e.numeric.dimx; ++i) + if (hlsl_swizzle_get_component(swizzle->u.vector, i) != i) +- return false; +- +- hlsl_replace_node(instr, swizzle->val.node); ++ return NULL; + +- return true; ++ return swizzle->val.node; + } + + static bool remove_trivial_conditional_branches(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +@@ -4028,7 +4017,8 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + return true; + } + +-static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *idx; + struct hlsl_deref *deref; +@@ -4036,13 +4026,13 @@ static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir + unsigned int i; + + if (instr->type != HLSL_IR_LOAD) +- return false; ++ return NULL; + + deref = &hlsl_ir_load(instr)->src; + VKD3D_ASSERT(deref->var); + + if (deref->path_len == 0) +- return false; ++ return NULL; + + type = deref->var->data_type; + for (i = 0; i < deref->path_len - 1; ++i) +@@ -4059,7 +4049,7 @@ static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir + enum hlsl_ir_expr_op op; + + if (!(vector_load = hlsl_new_load_parent(ctx, deref, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, &vector_load->node); + + swizzle = hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(X, X, X, X), width, idx, &instr->loc); +@@ -4069,7 +4059,7 @@ static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir + value.u[2].u = 2; + value.u[3].u = 3; + if (!(c = hlsl_new_constant(ctx, hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, width), &value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, c); + + operands[0] = swizzle; +@@ -4086,14 +4076,14 @@ static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir + * LOGIC_OR + LOGIC_AND. */ + operands[0] = &vector_load->node; + operands[1] = eq; +- hlsl_block_add_expr(ctx, block, op, operands, instr->data_type, &instr->loc); +- return true; ++ return hlsl_block_add_expr(ctx, block, op, operands, instr->data_type, &instr->loc); + } + +- return false; ++ return NULL; + } + +-static bool validate_nonconstant_vector_store_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *validate_nonconstant_vector_store_derefs(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *idx; + struct hlsl_deref *deref; +@@ -4101,13 +4091,13 @@ static bool validate_nonconstant_vector_store_derefs(struct hlsl_ctx *ctx, struc + unsigned int i; + + if (instr->type != HLSL_IR_STORE) +- return false; ++ return NULL; + + deref = &hlsl_ir_store(instr)->lhs; + VKD3D_ASSERT(deref->var); + + if (deref->path_len == 0) +- return false; ++ return NULL; + + type = deref->var->data_type; + for (i = 0; i < deref->path_len - 1; ++i) +@@ -4122,7 +4112,7 @@ static bool validate_nonconstant_vector_store_derefs(struct hlsl_ctx *ctx, struc + hlsl_fixme(ctx, &instr->loc, "Non-constant vector addressing on store. Unrolling may be missing."); + } + +- return false; ++ return NULL; + } + + static bool deref_supports_sm1_indirect_addressing(struct hlsl_ctx *ctx, const struct hlsl_deref *deref) +@@ -4136,8 +4126,8 @@ static bool deref_supports_sm1_indirect_addressing(struct hlsl_ctx *ctx, const s + * This is achieved through a synthetic variable. The non-constant index is compared for equality + * with every possible value it can have within the array bounds, and the ternary operator is used + * to update the value of the synthetic var when the equality check passes. */ +-static bool lower_nonconstant_array_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, +- struct hlsl_block *block) ++static struct hlsl_ir_node *lower_nonconstant_array_loads(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_constant_value zero_value = {0}; + struct hlsl_ir_node *cut_index, *zero; +@@ -4149,15 +4139,15 @@ static bool lower_nonconstant_array_loads(struct hlsl_ctx *ctx, struct hlsl_ir_n + bool row_major; + + if (instr->type != HLSL_IR_LOAD) +- return false; ++ return NULL; + load = hlsl_ir_load(instr); + deref = &load->src; + + if (deref->path_len == 0) +- return false; ++ return NULL; + + if (deref_supports_sm1_indirect_addressing(ctx, deref)) +- return false; ++ return NULL; + + for (i = deref->path_len - 1; ; --i) + { +@@ -4168,7 +4158,7 @@ static bool lower_nonconstant_array_loads(struct hlsl_ctx *ctx, struct hlsl_ir_n + } + + if (i == 0) +- return false; ++ return NULL; + } + + cut_index = deref->path[i_cut].node; +@@ -4180,10 +4170,10 @@ static bool lower_nonconstant_array_loads(struct hlsl_ctx *ctx, struct hlsl_ir_n + VKD3D_ASSERT(cut_type->class == HLSL_CLASS_ARRAY || row_major); + + if (!(var = hlsl_new_synthetic_var(ctx, row_major ? "row_major-load" : "array-load", instr->data_type, &instr->loc))) +- return false; ++ return NULL; + + if (!(zero = hlsl_new_constant(ctx, instr->data_type, &zero_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, zero); + + hlsl_block_add_simple_store(ctx, block, var, zero); +@@ -4209,7 +4199,7 @@ static bool lower_nonconstant_array_loads(struct hlsl_ctx *ctx, struct hlsl_ir_n + var_load = hlsl_block_add_simple_load(ctx, block, var, &cut_index->loc); + + if (!hlsl_copy_deref(ctx, &deref_copy, deref)) +- return false; ++ return NULL; + hlsl_src_remove(&deref_copy.path[i_cut]); + hlsl_src_from_node(&deref_copy.path[i_cut], const_i); + specific_load = hlsl_block_add_load_index(ctx, block, &deref_copy, NULL, &cut_index->loc); +@@ -4223,8 +4213,7 @@ static bool lower_nonconstant_array_loads(struct hlsl_ctx *ctx, struct hlsl_ir_n + hlsl_block_add_simple_store(ctx, block, var, ternary); + } + +- hlsl_block_add_simple_load(ctx, block, var, &instr->loc); +- return true; ++ return hlsl_block_add_simple_load(ctx, block, var, &instr->loc); + } + + static struct hlsl_type *clone_texture_array_as_combined_sampler_array(struct hlsl_ctx *ctx, struct hlsl_type *type) +@@ -4495,31 +4484,30 @@ static bool sort_synthetic_separated_samplers_first(struct hlsl_ctx *ctx) + } + + /* Turn CAST to int or uint into TRUNC + REINTERPRET */ +-static bool lower_casts_to_int(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_casts_to_int(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = { 0 }; + struct hlsl_ir_node *arg, *trunc; + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP1_CAST) +- return false; ++ return NULL; + + arg = expr->operands[0].node; + if (!hlsl_type_is_integer(instr->data_type) || instr->data_type->e.numeric.type == HLSL_TYPE_BOOL) +- return false; ++ return NULL; + if (!hlsl_type_is_floating_point(arg->data_type)) +- return false; ++ return NULL; + + trunc = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_TRUNC, arg, &instr->loc); + + memset(operands, 0, sizeof(operands)); + operands[0] = trunc; +- hlsl_block_add_expr(ctx, block, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc); +- +- return true; ++ return hlsl_block_add_expr(ctx, block, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc); + } + + /* Turn TRUNC into: +@@ -4533,16 +4521,16 @@ static bool lower_casts_to_int(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + * where the comparisons in the extra term are performed using CMP or SLT + * depending on whether this is a pixel or vertex shader, respectively. + */ +-static bool lower_trunc(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_trunc(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg, *res; + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP1_TRUNC) +- return false; ++ return NULL; + + arg = expr->operands[0].node; + +@@ -4553,7 +4541,7 @@ static bool lower_trunc(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct + + memset(&zero_value, 0, sizeof(zero_value)); + if (!(zero = hlsl_new_constant(ctx, arg->data_type, &zero_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, zero); + + one_value.u[0].f = 1.0; +@@ -4561,22 +4549,22 @@ static bool lower_trunc(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct + one_value.u[2].f = 1.0; + one_value.u[3].f = 1.0; + if (!(one = hlsl_new_constant(ctx, arg->data_type, &one_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, one); + + fract = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_FRACT, arg, &instr->loc); + neg_fract = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_NEG, fract, &instr->loc); + + if (!(has_fract = hlsl_new_ternary_expr(ctx, HLSL_OP3_CMP, neg_fract, zero, one))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, has_fract); + + if (!(extra = hlsl_new_ternary_expr(ctx, HLSL_OP3_CMP, arg, zero, has_fract))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, extra); + + floor = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, arg, neg_fract); +- res = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, floor, extra); ++ return hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, floor, extra); + } + else + { +@@ -4590,11 +4578,10 @@ static bool lower_trunc(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct + floor = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, arg, neg_fract); + + if (!(res = hlsl_new_ternary_expr(ctx, HLSL_OP3_MAD, is_neg, has_fract, floor))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, res); ++ return res; + } +- +- return true; + } + + /* Lower modulus using: +@@ -4602,7 +4589,8 @@ static bool lower_trunc(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct + * mod(x, y) = x - trunc(x / y) * y; + * + */ +-static bool lower_int_modulus_sm1(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_int_modulus_sm1(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *div, *trunc, *mul, *neg, *operands[2], *ret; + struct hlsl_type *float_type; +@@ -4610,15 +4598,15 @@ static bool lower_int_modulus_sm1(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins + bool is_float; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP2_MOD) +- return false; ++ return NULL; + + is_float = instr->data_type->e.numeric.type == HLSL_TYPE_FLOAT + || instr->data_type->e.numeric.type == HLSL_TYPE_HALF; + if (is_float) +- return false; ++ return NULL; + float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, instr->data_type->e.numeric.dimx); + + for (unsigned int i = 0; i < 2; ++i) +@@ -4631,13 +4619,11 @@ static bool lower_int_modulus_sm1(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins + mul = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MUL, trunc, operands[1]); + neg = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_NEG, mul, &instr->loc); + ret = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, operands[0], neg); +- hlsl_block_add_cast(ctx, block, ret, instr->data_type, &instr->loc); +- +- return true; ++ return hlsl_block_add_cast(ctx, block, ret, instr->data_type, &instr->loc); + } + + /* Lower DIV to RCP + MUL. */ +-static bool lower_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *rcp, *ret, *operands[2]; + struct hlsl_type *float_type; +@@ -4645,10 +4631,10 @@ static bool lower_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, str + bool is_float; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP2_DIV) +- return false; ++ return NULL; + + is_float = instr->data_type->e.numeric.type == HLSL_TYPE_FLOAT + || instr->data_type->e.numeric.type == HLSL_TYPE_HALF; +@@ -4665,42 +4651,40 @@ static bool lower_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, str + ret = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MUL, operands[0], rcp); + if (!is_float) + ret = hlsl_block_add_cast(ctx, block, ret, instr->data_type, &instr->loc); +- +- return true; ++ return ret; + } + + /* Lower SQRT to RSQ + RCP. */ +-static bool lower_sqrt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_sqrt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_expr *expr; + struct hlsl_ir_node *rsq; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP1_SQRT) +- return false; ++ return NULL; + + rsq = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_RSQ, expr->operands[0].node, &instr->loc); +- hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_RCP, rsq, &instr->loc); +- return true; ++ return hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_RCP, rsq, &instr->loc); + } + + /* Lower DP2 to MUL + ADD */ +-static bool lower_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg1, *arg2, *mul, *add_x, *add_y; + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + arg1 = expr->operands[0].node; + arg2 = expr->operands[1].node; + if (expr->op != HLSL_OP2_DOT) +- return false; ++ return NULL; + if (arg1->data_type->e.numeric.dimx != 2) +- return false; ++ return NULL; + + if (ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL) + { +@@ -4710,7 +4694,7 @@ static bool lower_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct h + operands[1] = arg2; + operands[2] = hlsl_block_add_float_constant(ctx, block, 0.0f, &expr->node.loc); + +- hlsl_block_add_expr(ctx, block, HLSL_OP3_DP2ADD, operands, instr->data_type, &expr->node.loc); ++ return hlsl_block_add_expr(ctx, block, HLSL_OP3_DP2ADD, operands, instr->data_type, &expr->node.loc); + } + else + { +@@ -4720,32 +4704,29 @@ static bool lower_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct h + instr->data_type->e.numeric.dimx, mul, &expr->node.loc); + add_y = hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(Y, Y, Y, Y), + instr->data_type->e.numeric.dimx, mul, &expr->node.loc); +- hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, add_x, add_y); ++ return hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, add_x, add_y); + } +- +- return true; + } + + /* Lower ABS to MAX */ +-static bool lower_abs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_abs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg, *neg; + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + arg = expr->operands[0].node; + if (expr->op != HLSL_OP1_ABS) +- return false; ++ return NULL; + + neg = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_NEG, arg, &instr->loc); +- hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MAX, neg, arg); +- return true; ++ return hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MAX, neg, arg); + } + + /* Lower ROUND using FRC, ROUND(x) -> ((x + 0.5) - FRC(x + 0.5)). */ +-static bool lower_round(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_round(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg, *neg, *sum, *frc, *half; + struct hlsl_type *type = instr->data_type; +@@ -4754,69 +4735,66 @@ static bool lower_round(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + + expr = hlsl_ir_expr(instr); + arg = expr->operands[0].node; + if (expr->op != HLSL_OP1_ROUND) +- return false; ++ return NULL; + + component_count = hlsl_type_component_count(type); + for (i = 0; i < component_count; ++i) + half_value.u[i].f = 0.5f; + if (!(half = hlsl_new_constant(ctx, type, &half_value, &expr->node.loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, half); + + sum = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, arg, half); + frc = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_FRACT, sum, &instr->loc); + neg = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_NEG, frc, &instr->loc); +- hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, sum, neg); +- return true; ++ return hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, sum, neg); + } + + /* Lower CEIL to FRC */ +-static bool lower_ceil(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_ceil(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg, *neg, *frc; + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + + expr = hlsl_ir_expr(instr); + arg = expr->operands[0].node; + if (expr->op != HLSL_OP1_CEIL) +- return false; ++ return NULL; + + neg = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_NEG, arg, &instr->loc); + frc = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_FRACT, neg, &instr->loc); +- hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, frc, arg); +- return true; ++ return hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, frc, arg); + } + + /* Lower FLOOR to FRC */ +-static bool lower_floor(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_floor(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg, *neg, *frc; + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + + expr = hlsl_ir_expr(instr); + arg = expr->operands[0].node; + if (expr->op != HLSL_OP1_FLOOR) +- return false; ++ return NULL; + + frc = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_FRACT, arg, &instr->loc); + neg = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_NEG, frc, &instr->loc); +- hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, neg, arg); +- return true; ++ return hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, neg, arg); + } + + /* Lower SIN/COS to SINCOS for SM1. */ +-static bool lower_trig(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_trig(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg, *half, *two_pi, *reciprocal_two_pi, *neg_pi; + struct hlsl_constant_value half_value, two_pi_value, reciprocal_two_pi_value, neg_pi_value; +@@ -4828,7 +4806,7 @@ static bool lower_trig(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct + int i; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + + if (expr->op == HLSL_OP1_SIN) +@@ -4836,7 +4814,7 @@ static bool lower_trig(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct + else if (expr->op == HLSL_OP1_COS) + op = HLSL_OP1_COS_REDUCED; + else +- return false; ++ return NULL; + + arg = expr->operands[0].node; + type = arg->data_type; +@@ -4854,23 +4832,23 @@ static bool lower_trig(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct + || !(two_pi = hlsl_new_constant(ctx, type, &two_pi_value, &instr->loc)) + || !(reciprocal_two_pi = hlsl_new_constant(ctx, type, &reciprocal_two_pi_value, &instr->loc)) + || !(neg_pi = hlsl_new_constant(ctx, type, &neg_pi_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, half); + hlsl_block_add_instr(block, two_pi); + hlsl_block_add_instr(block, reciprocal_two_pi); + hlsl_block_add_instr(block, neg_pi); + + if (!(mad = hlsl_new_ternary_expr(ctx, HLSL_OP3_MAD, arg, reciprocal_two_pi, half))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, mad); + frc = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_FRACT, mad, &instr->loc); + if (!(reduced = hlsl_new_ternary_expr(ctx, HLSL_OP3_MAD, frc, two_pi, neg_pi))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, reduced); + + if (type->e.numeric.dimx == 1) + { +- sincos = hlsl_block_add_unary_expr(ctx, block, op, reduced, &instr->loc); ++ return hlsl_block_add_unary_expr(ctx, block, op, reduced, &instr->loc); + } + else + { +@@ -4886,7 +4864,7 @@ static bool lower_trig(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct + } + + if (!(var = hlsl_new_synthetic_var(ctx, "sincos", type, &instr->loc))) +- return false; ++ return NULL; + hlsl_init_simple_deref_from_var(&var_deref, var); + + for (i = 0; i < type->e.numeric.dimx; ++i) +@@ -4895,13 +4873,11 @@ static bool lower_trig(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct + hlsl_block_add_store_component(ctx, block, &var_deref, i, sincos); + } + +- hlsl_block_add_load_index(ctx, block, &var_deref, NULL, &instr->loc); ++ return hlsl_block_add_load_index(ctx, block, &var_deref, NULL, &instr->loc); + } +- +- return true; + } + +-static bool lower_logic_not(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_logic_not(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg, *arg_cast, *neg, *one, *sub; + struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS]; +@@ -4910,10 +4886,10 @@ static bool lower_logic_not(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, st + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP1_LOGIC_NOT) +- return false; ++ return NULL; + + arg = expr->operands[0].node; + float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, arg->data_type->e.numeric.dimx); +@@ -4930,19 +4906,18 @@ static bool lower_logic_not(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, st + one_value.u[2].f = 1.0; + one_value.u[3].f = 1.0; + if (!(one = hlsl_new_constant(ctx, float_type, &one_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, one); + + sub = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, one, neg); + + memset(operands, 0, sizeof(operands)); + operands[0] = sub; +- hlsl_block_add_expr(ctx, block, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc); +- return true; ++ return hlsl_block_add_expr(ctx, block, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc); + } + + /* Lower TERNARY to CMP for SM1. */ +-static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *cond, *first, *second, *float_cond, *neg; + struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; +@@ -4950,11 +4925,11 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru + struct hlsl_type *type; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP3_TERNARY) +- return false; ++ return NULL; + + cond = expr->operands[0].node; + first = expr->operands[1].node; +@@ -4963,7 +4938,7 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru + if (cond->data_type->class > HLSL_CLASS_VECTOR || instr->data_type->class > HLSL_CLASS_VECTOR) + { + hlsl_fixme(ctx, &instr->loc, "Lower ternary of type other than scalar or vector."); +- return false; ++ return NULL; + } + + VKD3D_ASSERT(cond->data_type->e.numeric.type == HLSL_TYPE_BOOL); +@@ -4977,8 +4952,7 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru + operands[0] = neg; + operands[1] = second; + operands[2] = first; +- hlsl_block_add_expr(ctx, block, HLSL_OP3_CMP, operands, first->data_type, &instr->loc); +- return true; ++ return hlsl_block_add_expr(ctx, block, HLSL_OP3_CMP, operands, first->data_type, &instr->loc); + } + + static bool lower_resource_load_bias(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +@@ -5026,7 +5000,7 @@ static bool lower_resource_load_bias(struct hlsl_ctx *ctx, struct hlsl_ir_node * + return true; + } + +-static bool lower_comparison_operators(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, ++static struct hlsl_ir_node *lower_comparison_operators(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + struct hlsl_block *block) + { + struct hlsl_ir_node *arg1, *arg1_cast, *arg2, *arg2_cast, *slt, *res; +@@ -5036,10 +5010,10 @@ static bool lower_comparison_operators(struct hlsl_ctx *ctx, struct hlsl_ir_node + bool negate = false; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + if (!hlsl_is_comparison_op(expr->op)) +- return false; ++ return NULL; + + arg1 = expr->operands[0].node; + arg2 = expr->operands[1].node; +@@ -5096,7 +5070,7 @@ static bool lower_comparison_operators(struct hlsl_ctx *ctx, struct hlsl_ir_node + one_value.u[2].f = 1.0; + one_value.u[3].f = 1.0; + if (!(one = hlsl_new_constant(ctx, float_type, &one_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, one); + + slt_neg = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_NEG, slt, &instr->loc); +@@ -5111,8 +5085,7 @@ static bool lower_comparison_operators(struct hlsl_ctx *ctx, struct hlsl_ir_node + * and casts to BOOL have already been lowered to "!= 0". */ + memset(operands, 0, sizeof(operands)); + operands[0] = res; +- hlsl_block_add_expr(ctx, block, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc); +- return true; ++ return hlsl_block_add_expr(ctx, block, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc); + } + + /* Intended to be used for SM1-SM3, lowers SLT instructions (only available in vertex shaders) to +@@ -5123,7 +5096,7 @@ static bool lower_comparison_operators(struct hlsl_ctx *ctx, struct hlsl_ir_node + * = ((x - y) >= 0) ? 0.0 : 1.0 + * = CMP(x - y, 0.0, 1.0) + */ +-static bool lower_slt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_slt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg1, *arg2, *arg1_cast, *arg2_cast, *neg, *sub, *zero, *one, *cmp; + struct hlsl_constant_value zero_value, one_value; +@@ -5131,10 +5104,10 @@ static bool lower_slt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct h + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP2_SLT) +- return false; ++ return NULL; + + arg1 = expr->operands[0].node; + arg2 = expr->operands[1].node; +@@ -5147,7 +5120,7 @@ static bool lower_slt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct h + + memset(&zero_value, 0, sizeof(zero_value)); + if (!(zero = hlsl_new_constant(ctx, float_type, &zero_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, zero); + + one_value.u[0].f = 1.0; +@@ -5155,14 +5128,13 @@ static bool lower_slt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct h + one_value.u[2].f = 1.0; + one_value.u[3].f = 1.0; + if (!(one = hlsl_new_constant(ctx, float_type, &one_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, one); + + if (!(cmp = hlsl_new_ternary_expr(ctx, HLSL_OP3_CMP, sub, zero, one))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, cmp); +- +- return true; ++ return cmp; + } + + /* Intended to be used for SM1-SM3, lowers CMP instructions (only available in pixel shaders) to +@@ -5173,7 +5145,7 @@ static bool lower_slt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct h + * = z * ((x < 0) ? 1.0 : 0.0) + y * ((x < 0) ? 0.0 : 1.0) + * = z * SLT(x, 0.0) + y * (1 - SLT(x, 0.0)) + */ +-static bool lower_cmp(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_cmp(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *args[3], *args_cast[3], *slt, *neg_slt, *sub, *zero, *one, *mul1, *mul2; + struct hlsl_constant_value zero_value, one_value; +@@ -5182,10 +5154,10 @@ static bool lower_cmp(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct h + unsigned int i; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP3_CMP) +- return false; ++ return NULL; + + float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, instr->data_type->e.numeric.dimx); + +@@ -5197,7 +5169,7 @@ static bool lower_cmp(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct h + + memset(&zero_value, 0, sizeof(zero_value)); + if (!(zero = hlsl_new_constant(ctx, float_type, &zero_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, zero); + + one_value.u[0].f = 1.0; +@@ -5205,7 +5177,7 @@ static bool lower_cmp(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct h + one_value.u[2].f = 1.0; + one_value.u[3].f = 1.0; + if (!(one = hlsl_new_constant(ctx, float_type, &one_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, one); + + slt = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_SLT, args_cast[0], zero); +@@ -5213,11 +5185,11 @@ static bool lower_cmp(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct h + neg_slt = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_NEG, slt, &instr->loc); + sub = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, one, neg_slt); + mul2 = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MUL, args_cast[1], sub); +- hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, mul1, mul2); +- return true; ++ return hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, mul1, mul2); + } + +-static bool lower_casts_to_bool(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_casts_to_bool(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_type *type = instr->data_type, *arg_type; + static const struct hlsl_constant_value zero_value; +@@ -5225,28 +5197,27 @@ static bool lower_casts_to_bool(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP1_CAST) +- return false; ++ return NULL; + arg_type = expr->operands[0].node->data_type; + if (type->class > HLSL_CLASS_VECTOR || arg_type->class > HLSL_CLASS_VECTOR) +- return false; ++ return NULL; + if (type->e.numeric.type != HLSL_TYPE_BOOL) +- return false; ++ return NULL; + + /* Narrowing casts should have already been lowered. */ + VKD3D_ASSERT(type->e.numeric.dimx == arg_type->e.numeric.dimx); + + zero = hlsl_new_constant(ctx, arg_type, &zero_value, &instr->loc); + if (!zero) +- return false; ++ return NULL; + hlsl_block_add_instr(block, zero); + + neq = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_NEQUAL, expr->operands[0].node, zero); + neq->data_type = expr->node.data_type; +- +- return true; ++ return neq; + } + + struct hlsl_ir_node *hlsl_add_conditional(struct hlsl_ctx *ctx, struct hlsl_block *instrs, +@@ -5270,7 +5241,8 @@ struct hlsl_ir_node *hlsl_add_conditional(struct hlsl_ctx *ctx, struct hlsl_bloc + return hlsl_block_add_expr(ctx, instrs, HLSL_OP3_TERNARY, operands, if_true->data_type, &condition->loc); + } + +-static bool lower_int_division_sm4(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_int_division_sm4(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg1, *arg2, *xor, *and, *abs1, *abs2, *div, *neg, *cast1, *cast2, *cast3, *high_bit; + struct hlsl_type *type = instr->data_type, *utype; +@@ -5279,16 +5251,16 @@ static bool lower_int_division_sm4(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + unsigned int i; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + arg1 = expr->operands[0].node; + arg2 = expr->operands[1].node; + if (expr->op != HLSL_OP2_DIV) +- return false; ++ return NULL; + if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR) +- return false; ++ return NULL; + if (type->e.numeric.type != HLSL_TYPE_INT) +- return false; ++ return NULL; + utype = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_UINT, type->e.numeric.dimx, type->e.numeric.dimy); + + xor = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_BIT_XOR, arg1, arg2); +@@ -5296,7 +5268,7 @@ static bool lower_int_division_sm4(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + for (i = 0; i < type->e.numeric.dimx; ++i) + high_bit_value.u[i].u = 0x80000000; + if (!(high_bit = hlsl_new_constant(ctx, type, &high_bit_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, high_bit); + + and = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_BIT_AND, xor, high_bit); +@@ -5310,7 +5282,8 @@ static bool lower_int_division_sm4(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + return hlsl_add_conditional(ctx, block, and, neg, cast3); + } + +-static bool lower_int_modulus_sm4(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_int_modulus_sm4(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg1, *arg2, *and, *abs1, *abs2, *div, *neg, *cast1, *cast2, *cast3, *high_bit; + struct hlsl_type *type = instr->data_type, *utype; +@@ -5319,22 +5292,22 @@ static bool lower_int_modulus_sm4(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins + unsigned int i; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + arg1 = expr->operands[0].node; + arg2 = expr->operands[1].node; + if (expr->op != HLSL_OP2_MOD) +- return false; ++ return NULL; + if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR) +- return false; ++ return NULL; + if (type->e.numeric.type != HLSL_TYPE_INT) +- return false; ++ return NULL; + utype = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_UINT, type->e.numeric.dimx, type->e.numeric.dimy); + + for (i = 0; i < type->e.numeric.dimx; ++i) + high_bit_value.u[i].u = 0x80000000; + if (!(high_bit = hlsl_new_constant(ctx, type, &high_bit_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, high_bit); + + and = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_BIT_AND, arg1, high_bit); +@@ -5348,31 +5321,30 @@ static bool lower_int_modulus_sm4(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins + return hlsl_add_conditional(ctx, block, and, neg, cast3); + } + +-static bool lower_int_abs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_int_abs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_type *type = instr->data_type; + struct hlsl_ir_node *arg, *neg; + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + + if (expr->op != HLSL_OP1_ABS) +- return false; ++ return NULL; + if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR) +- return false; ++ return NULL; + if (type->e.numeric.type != HLSL_TYPE_INT) +- return false; ++ return NULL; + + arg = expr->operands[0].node; + + neg = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_NEG, arg, &instr->loc); +- hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MAX, arg, neg); +- return true; ++ return hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MAX, arg, neg); + } + +-static bool lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg1, *arg2, *mult, *comps[4] = {0}, *res; + struct hlsl_type *type = instr->data_type; +@@ -5381,11 +5353,11 @@ static bool lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru + bool is_bool; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + + if (expr->op != HLSL_OP2_DOT) +- return false; ++ return NULL; + + if (hlsl_type_is_integer(type)) + { +@@ -5407,14 +5379,14 @@ static bool lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru + res = comps[0]; + for (i = 1; i < dimx; ++i) + res = hlsl_block_add_binary_expr(ctx, block, is_bool ? HLSL_OP2_LOGIC_OR : HLSL_OP2_ADD, res, comps[i]); +- +- return true; ++ return res; + } + +- return false; ++ return NULL; + } + +-static bool lower_float_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_float_modulus(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *arg1, *arg2, *mul1, *neg1, *ge, *neg2, *div, *mul2, *frc, *cond, *one; + struct hlsl_type *type = instr->data_type, *btype; +@@ -5423,16 +5395,16 @@ static bool lower_float_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + unsigned int i; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + arg1 = expr->operands[0].node; + arg2 = expr->operands[1].node; + if (expr->op != HLSL_OP2_MOD) +- return false; ++ return NULL; + if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR) +- return false; ++ return NULL; + if (type->e.numeric.type != HLSL_TYPE_FLOAT) +- return false; ++ return NULL; + btype = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_BOOL, type->e.numeric.dimx, type->e.numeric.dimy); + + mul1 = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MUL, arg2, arg1); +@@ -5447,14 +5419,13 @@ static bool lower_float_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + for (i = 0; i < type->e.numeric.dimx; ++i) + one_value.u[i].f = 1.0f; + if (!(one = hlsl_new_constant(ctx, type, &one_value, &instr->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, one); + + div = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_DIV, one, cond); + mul2 = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MUL, div, arg1); + frc = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_FRACT, mul2, &instr->loc); +- hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MUL, frc, cond); +- return true; ++ return hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MUL, frc, cond); + } + + static bool lower_discard_neg(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +@@ -6167,7 +6138,7 @@ static bool track_object_components_sampler_dim(struct hlsl_ctx *ctx, struct hls + return false; + } + +-static void register_deref_usage(struct hlsl_ctx *ctx, struct hlsl_deref *deref) ++static void register_deref_usage(struct hlsl_ctx *ctx, const struct hlsl_deref *deref) + { + struct hlsl_ir_var *var = deref->var; + enum hlsl_regset regset = hlsl_deref_get_regset(ctx, deref); +@@ -6215,18 +6186,43 @@ static bool track_components_usage(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + } + + case HLSL_IR_RESOURCE_LOAD: +- register_deref_usage(ctx, &hlsl_ir_resource_load(instr)->resource); +- if (hlsl_ir_resource_load(instr)->sampler.var) +- register_deref_usage(ctx, &hlsl_ir_resource_load(instr)->sampler); ++ { ++ const struct hlsl_ir_resource_load *load = hlsl_ir_resource_load(instr); ++ ++ register_deref_usage(ctx, &load->resource); ++ if (load->sampler.var) ++ register_deref_usage(ctx, &load->sampler); ++ ++ if (hlsl_deref_get_regset(ctx, &load->resource) == HLSL_REGSET_UAVS) ++ { ++ unsigned int index; ++ ++ hlsl_regset_index_from_deref(ctx, &load->resource, HLSL_REGSET_UAVS, &index); ++ load->resource.var->objects_usage[HLSL_REGSET_UAVS][index].uav_read = true; ++ } + break; ++ } + + case HLSL_IR_RESOURCE_STORE: + register_deref_usage(ctx, &hlsl_ir_resource_store(instr)->resource); + break; + + case HLSL_IR_INTERLOCKED: +- register_deref_usage(ctx, &hlsl_ir_interlocked(instr)->dst); ++ { ++ const struct hlsl_ir_interlocked *interlocked = hlsl_ir_interlocked(instr); ++ ++ register_deref_usage(ctx, &interlocked->dst); ++ ++ if (hlsl_deref_get_regset(ctx, &interlocked->dst) == HLSL_REGSET_UAVS) ++ { ++ unsigned int index; ++ ++ hlsl_regset_index_from_deref(ctx, &interlocked->dst, HLSL_REGSET_UAVS, &index); ++ interlocked->dst.var->objects_usage[HLSL_REGSET_UAVS][index].uav_read = true; ++ interlocked->dst.var->objects_usage[HLSL_REGSET_UAVS][index].uav_atomics = true; ++ } + break; ++ } + + default: + break; +@@ -8234,7 +8230,7 @@ static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *bod + + void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body) + { +- lower_ir(ctx, lower_index_loads, body); ++ replace_ir(ctx, lower_index_loads, body); + } + + static enum hlsl_ir_expr_op invert_comparison_op(enum hlsl_ir_expr_op op) +@@ -8537,27 +8533,27 @@ static void hlsl_run_folding_passes(struct hlsl_ctx *ctx, struct hlsl_block *bod + { + bool progress; + +- hlsl_transform_ir(ctx, fold_redundant_casts, body, NULL); ++ replace_ir(ctx, fold_redundant_casts, body); + do + { + progress = simplify_exprs(ctx, body); + progress |= hlsl_copy_propagation_execute(ctx, body); +- progress |= hlsl_transform_ir(ctx, fold_swizzle_chains, body, NULL); +- progress |= hlsl_transform_ir(ctx, remove_trivial_swizzles, body, NULL); ++ progress |= replace_ir(ctx, fold_swizzle_chains, body); ++ progress |= replace_ir(ctx, fold_trivial_swizzles, body); + progress |= hlsl_transform_ir(ctx, remove_trivial_conditional_branches, body, NULL); + } while (progress); +- hlsl_transform_ir(ctx, fold_redundant_casts, body, NULL); ++ replace_ir(ctx, fold_redundant_casts, body); + } + + void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body) + { + bool progress; + +- lower_ir(ctx, lower_complex_casts, body); +- lower_ir(ctx, lower_matrix_swizzles, body); ++ replace_ir(ctx, lower_complex_casts, body); ++ replace_ir(ctx, lower_matrix_swizzles, body); + +- lower_ir(ctx, lower_broadcasts, body); +- while (hlsl_transform_ir(ctx, fold_redundant_casts, body, NULL)); ++ replace_ir(ctx, lower_broadcasts, body); ++ while (replace_ir(ctx, fold_redundant_casts, body)); + do + { + progress = hlsl_transform_ir(ctx, split_array_copies, body, NULL); +@@ -8566,16 +8562,16 @@ void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body) + while (progress); + hlsl_transform_ir(ctx, split_matrix_copies, body, NULL); + +- lower_ir(ctx, lower_narrowing_casts, body); +- lower_ir(ctx, lower_int_dot, body); ++ replace_ir(ctx, lower_narrowing_casts, body); ++ replace_ir(ctx, lower_int_dot, body); + if (hlsl_version_ge(ctx, 4, 0)) + { +- lower_ir(ctx, lower_int_modulus_sm4, body); +- lower_ir(ctx, lower_int_division_sm4, body); ++ replace_ir(ctx, lower_int_modulus_sm4, body); ++ replace_ir(ctx, lower_int_division_sm4, body); + } +- lower_ir(ctx, lower_int_abs, body); +- lower_ir(ctx, lower_casts_to_bool, body); +- lower_ir(ctx, lower_float_modulus, body); ++ replace_ir(ctx, lower_int_abs, body); ++ replace_ir(ctx, lower_casts_to_bool, body); ++ replace_ir(ctx, lower_float_modulus, body); + + hlsl_run_folding_passes(ctx, body); + } +@@ -10189,10 +10185,7 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_co + struct hlsl_ir_function_decl *func, struct list *semantic_vars, + struct hlsl_block *body, uint64_t config_flags, struct vsir_program *program) + { +- struct hlsl_ir_var *var; + struct hlsl_block block; +- struct hlsl_reg *reg; +- unsigned int *count; + + program->ssa_count = 0; + program->temp_count = 0; +@@ -10207,17 +10200,6 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_co + + sm1_generate_vsir_block(ctx, body, program); + +- count = &program->flat_constant_count[VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER]; +- LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) +- { +- if (!var->is_uniform) +- continue; +- +- if (!(reg = &var->regs[HLSL_REGSET_NUMERIC])->allocation_size) +- continue; +- +- *count = max(*count, reg->id + reg->allocation_size); +- } + program->ssa_count = ctx->ssa_count; + program->temp_count = ctx->temp_count; + +@@ -12785,9 +12767,9 @@ static void sm4_generate_vsir_add_dcl_sampler(struct hlsl_ctx *ctx, + } + } + +-static enum vkd3d_shader_resource_type sm4_generate_vsir_get_resource_type(const struct hlsl_type *type) ++static enum vkd3d_shader_resource_type get_vsir_resource_type(enum hlsl_sampler_dim sampler_dim) + { +- switch (type->sampler_dim) ++ switch (sampler_dim) + { + case HLSL_SAMPLER_DIM_1D: + return VKD3D_SHADER_RESOURCE_TEXTURE_1D; +@@ -12816,7 +12798,7 @@ static enum vkd3d_shader_resource_type sm4_generate_vsir_get_resource_type(const + } + } + +-static enum vsir_data_type sm4_generate_vsir_get_format_type(const struct hlsl_type *type) ++static enum vsir_data_type get_vsir_resource_data_type(const struct hlsl_type *type) + { + const struct hlsl_type *format = type->e.resource.format; + +@@ -12953,10 +12935,10 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, + } + else + { +- ins->declaration.semantic.resource_type = sm4_generate_vsir_get_resource_type(resource->component_type); ++ ins->declaration.semantic.resource_type = get_vsir_resource_type(resource->component_type->sampler_dim); + + for (unsigned int j = 0; j < 4; ++j) +- ins->declaration.semantic.resource_data_type[j] = sm4_generate_vsir_get_format_type(component_type); ++ ins->declaration.semantic.resource_data_type[j] = get_vsir_resource_data_type(component_type); + + if (multisampled) + ins->declaration.semantic.sample_count = component_type->sample_count; +@@ -13108,6 +13090,140 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, + program->temp_count = ctx->temp_count; + } + ++static void generate_vsir_descriptors_for_var(struct hlsl_ctx *ctx, struct vsir_program *program, ++ const struct hlsl_ir_var *var, enum hlsl_regset r, enum vkd3d_shader_descriptor_type type) ++{ ++ unsigned int component_count = hlsl_type_component_count(var->data_type); ++ ++ for (unsigned int k = 0; k < component_count; ++k) ++ { ++ const struct hlsl_type *component_type = hlsl_type_get_component_type(ctx, var->data_type, k); ++ struct vkd3d_shader_register_range range; ++ struct vkd3d_shader_descriptor_info1 *d; ++ unsigned int regset_offset; ++ enum hlsl_regset regset; ++ uint32_t id; ++ ++ if (!hlsl_type_is_resource(component_type)) ++ continue; ++ regset_offset = hlsl_type_get_component_offset(ctx, var->data_type, k, ®set); ++ if (regset != r) ++ continue; ++ if (regset_offset > var->regs[r].allocation_size) ++ continue; ++ ++ if (!var->objects_usage[r][regset_offset].used) ++ continue; ++ ++ id = var->regs[r].id + regset_offset; ++ range.space = var->regs[r].space; ++ range.first = var->regs[r].index + regset_offset; ++ /* FIXME: 5.1 arrays. */ ++ range.last = var->regs[r].index + regset_offset; ++ ++ if (type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) ++ { ++ if (!(d = vsir_program_add_descriptor(program, type, id, ++ &range, VKD3D_SHADER_RESOURCE_NONE, VSIR_DATA_UNUSED))) ++ return; ++ if (component_type->sampler_dim == HLSL_SAMPLER_DIM_COMPARISON) ++ d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE; ++ } ++ else ++ { ++ if (component_type->class == HLSL_CLASS_SAMPLER) ++ d = vsir_program_add_descriptor(program, type, id, &range, ++ get_vsir_resource_type(var->objects_usage[r][regset_offset].sampler_dim), VSIR_DATA_F32); ++ else ++ d = vsir_program_add_descriptor(program, type, id, &range, ++ get_vsir_resource_type(component_type->sampler_dim), ++ get_vsir_resource_data_type(component_type)); ++ if (!d) ++ return; ++ ++ if (component_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) ++ d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_RAW_BUFFER; ++ else if (component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) ++ d->structure_stride = hlsl_type_get_packed_size(component_type->e.resource.format); ++ else if (component_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS ++ || component_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) ++ d->sample_count = component_type->sample_count; ++ ++ if (type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV && component_type->e.resource.rasteriser_ordered) ++ d->uav_flags |= VKD3DSUF_RASTERISER_ORDERED_VIEW; ++ ++ if (var->objects_usage[r][regset_offset].uav_read) ++ d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ; ++ if (var->objects_usage[r][regset_offset].uav_atomics) ++ d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_ATOMICS; ++ } ++ } ++} ++ ++static void generate_vsir_descriptors(struct hlsl_ctx *ctx, struct vsir_program *program) ++{ ++ struct vkd3d_shader_register_range range; ++ struct vkd3d_shader_descriptor_info1 *d; ++ const struct hlsl_ir_var *var; ++ ++ if (program->shader_version.major < 4) ++ { ++ uint32_t flat_constant_count = 0; ++ ++ LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) ++ { ++ const struct hlsl_reg *reg = &var->regs[HLSL_REGSET_NUMERIC]; ++ ++ if (var->is_uniform && reg->allocation_size) ++ flat_constant_count = max(flat_constant_count, reg->id + reg->allocation_size); ++ ++ generate_vsir_descriptors_for_var(ctx, program, var, ++ HLSL_REGSET_SAMPLERS, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER); ++ generate_vsir_descriptors_for_var(ctx, program, var, ++ HLSL_REGSET_SAMPLERS, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV); ++ } ++ ++ if (flat_constant_count) ++ { ++ range.space = 0; ++ range.first = range.last = VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER; ++ if ((d = vsir_program_add_descriptor(program, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, ++ range.first, &range, VKD3D_SHADER_RESOURCE_BUFFER, VSIR_DATA_U32))) ++ d->buffer_size = flat_constant_count * 16; ++ } ++ } ++ else ++ { ++ struct hlsl_buffer *buffer; ++ ++ LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) ++ { ++ generate_vsir_descriptors_for_var(ctx, program, var, ++ HLSL_REGSET_SAMPLERS, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER); ++ generate_vsir_descriptors_for_var(ctx, program, var, ++ HLSL_REGSET_TEXTURES, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV); ++ generate_vsir_descriptors_for_var(ctx, program, var, ++ HLSL_REGSET_UAVS, VKD3D_SHADER_DESCRIPTOR_TYPE_UAV); ++ } ++ ++ LIST_FOR_EACH_ENTRY(buffer, &ctx->buffers, struct hlsl_buffer, entry) ++ { ++ if (!buffer->reg.allocated) ++ continue; ++ ++ range.space = buffer->reg.space; ++ range.first = buffer->reg.index; ++ /* FIXME: 5.1 arrays. */ ++ range.last = buffer->reg.index; ++ if ((d = vsir_program_add_descriptor(program, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, ++ buffer->reg.id, &range, VKD3D_SHADER_RESOURCE_BUFFER, VSIR_DATA_U32))) ++ d->buffer_size = align(buffer->size, 4) * sizeof(float); ++ } ++ } ++ ++ program->has_descriptor_info = true; ++} ++ + /* For some reason, for matrices, values from default value initializers end + * up in different components than from regular initializers. Default value + * initializers fill the matrix in vertical reading order +@@ -13877,8 +13993,8 @@ static void loop_unrolling_simplify(struct hlsl_ctx *ctx, struct hlsl_block *blo + current_index = index_instructions(block, *index); + progress |= copy_propagation_transform_block(ctx, block, state); + +- progress |= hlsl_transform_ir(ctx, fold_swizzle_chains, block, NULL); +- progress |= hlsl_transform_ir(ctx, remove_trivial_swizzles, block, NULL); ++ progress |= replace_ir(ctx, fold_swizzle_chains, block); ++ progress |= replace_ir(ctx, fold_trivial_swizzles, block); + progress |= hlsl_transform_ir(ctx, remove_trivial_conditional_branches, block, NULL); + } while (progress); + +@@ -14131,7 +14247,7 @@ static void loop_unrolling_execute(struct hlsl_ctx *ctx, struct hlsl_block *bloc + hlsl_transform_ir(ctx, resolve_loops, block, NULL); + } + +-static bool lower_countbits(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_countbits(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) + { + struct hlsl_ir_function_decl *func; + struct hlsl_ir_node *call, *rhs; +@@ -14150,33 +14266,31 @@ static bool lower_countbits(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, str + "}\n"; + + if (node->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + + expr = hlsl_ir_expr(node); + if (expr->op != HLSL_OP1_COUNTBITS) +- return false; ++ return NULL; + + rhs = expr->operands[0].node; + if (!(body = hlsl_sprintf_alloc(ctx, template, hlsl_type_component_count(rhs->data_type)))) +- return false; ++ return NULL; + func = hlsl_compile_internal_function(ctx, "countbits", body); + vkd3d_free(body); + if (!func) +- return false; ++ return NULL; + + lhs = func->parameters.vars[0]; + hlsl_block_add_simple_store(ctx, block, lhs, rhs); + + if (!(call = hlsl_new_call(ctx, func, &node->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, call); + +- hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); +- +- return true; ++ return hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); + } + +-static bool lower_ctz(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_ctz(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) + { + struct hlsl_ir_function_decl *func; + struct hlsl_ir_node *call, *rhs; +@@ -14201,11 +14315,11 @@ static bool lower_ctz(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hl + "}\n"; + + if (node->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + + expr = hlsl_ir_expr(node); + if (expr->op != HLSL_OP1_CTZ) +- return false; ++ return NULL; + + rhs = expr->operands[0].node; + if (!(body = hlsl_sprintf_alloc(ctx, template, hlsl_type_component_count(rhs->data_type)))) +@@ -14213,21 +14327,19 @@ static bool lower_ctz(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hl + func = hlsl_compile_internal_function(ctx, "ctz", body); + vkd3d_free(body); + if (!func) +- return false; ++ return NULL; + + lhs = func->parameters.vars[0]; + hlsl_block_add_simple_store(ctx, block, lhs, rhs); + + if (!(call = hlsl_new_call(ctx, func, &node->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, call); + +- hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); +- +- return true; ++ return hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); + } + +-static bool lower_f16tof32(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_f16tof32(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) + { + struct hlsl_ir_function_decl *func; + struct hlsl_ir_node *call, *rhs; +@@ -14282,29 +14394,28 @@ static bool lower_f16tof32(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, stru + expr = hlsl_ir_expr(node); + + if (expr->op != HLSL_OP1_F16TOF32) +- return false; ++ return NULL; + + rhs = expr->operands[0].node; + component_count = hlsl_type_component_count(rhs->data_type); + + if (!(body = hlsl_sprintf_alloc(ctx, template, component_count, component_count))) +- return false; ++ return NULL; + + if (!(func = hlsl_compile_internal_function(ctx, "soft_f16tof32", body))) +- return false; ++ return NULL; + + lhs = func->parameters.vars[0]; + hlsl_block_add_simple_store(ctx, block, lhs, rhs); + + if (!(call = hlsl_new_call(ctx, func, &node->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, call); + +- hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); +- return true; ++ return hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); + } + +-static bool lower_f32tof16(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_f32tof16(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) + { + struct hlsl_ir_function_decl *func; + struct hlsl_ir_node *call, *rhs; +@@ -14342,34 +14453,33 @@ static bool lower_f32tof16(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, stru + "}\n"; + + if (node->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + + expr = hlsl_ir_expr(node); + + if (expr->op != HLSL_OP1_F32TOF16) +- return false; ++ return NULL; + + rhs = expr->operands[0].node; + component_count = hlsl_type_component_count(rhs->data_type); + + if (!(body = hlsl_sprintf_alloc(ctx, template, component_count, component_count))) +- return false; ++ return NULL; + + if (!(func = hlsl_compile_internal_function(ctx, "soft_f32tof16", body))) +- return false; ++ return NULL; + + lhs = func->parameters.vars[0]; + hlsl_block_add_simple_store(ctx, block, lhs, rhs); + + if (!(call = hlsl_new_call(ctx, func, &node->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, call); + +- hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); +- return true; ++ return hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); + } + +-static bool lower_find_msb(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_find_msb(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) + { + struct hlsl_ir_function_decl *func; + struct hlsl_ir_node *call, *rhs; +@@ -14406,33 +14516,31 @@ static bool lower_find_msb(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, stru + "}\n"; + + if (node->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + + expr = hlsl_ir_expr(node); + if (expr->op != HLSL_OP1_FIND_MSB) +- return false; ++ return NULL; + + rhs = expr->operands[0].node; + if (!(body = hlsl_sprintf_alloc(ctx, template, rhs->data_type->name, hlsl_type_component_count(rhs->data_type)))) +- return false; ++ return NULL; + func = hlsl_compile_internal_function(ctx, "find_msb", body); + vkd3d_free(body); + if (!func) +- return false; ++ return NULL; + + lhs = func->parameters.vars[0]; + hlsl_block_add_simple_store(ctx, block, lhs, rhs); + + if (!(call = hlsl_new_call(ctx, func, &node->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, call); + +- hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); +- +- return true; ++ return hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); + } + +-static bool lower_isinf(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) ++static struct hlsl_ir_node *lower_isinf(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) + { + struct hlsl_ir_function_decl *func; + struct hlsl_ir_node *call, *rhs; +@@ -14477,12 +14585,12 @@ static bool lower_isinf(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct + "}"; + + if (node->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + + expr = hlsl_ir_expr(node); + + if (expr->op != HLSL_OP1_ISINF) +- return false; ++ return NULL; + + rhs = expr->operands[0].node; + +@@ -14497,19 +14605,18 @@ static bool lower_isinf(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct + + component_count = hlsl_type_component_count(rhs->data_type); + if (!(body = hlsl_sprintf_alloc(ctx, template, component_count, component_count))) +- return false; ++ return NULL; + + if (!(func = hlsl_compile_internal_function(ctx, "isinf", body))) +- return false; ++ return NULL; + + hlsl_block_add_simple_store(ctx, block, func->parameters.vars[0], rhs); + + if (!(call = hlsl_new_call(ctx, func, &node->loc))) +- return false; ++ return NULL; + hlsl_block_add_instr(block, call); + +- hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); +- return true; ++ return hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); + } + + static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_vars, struct hlsl_block *body, +@@ -14548,25 +14655,25 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v + + if (hlsl_version_ge(ctx, 4, 0) && hlsl_version_lt(ctx, 5, 0)) + { +- lower_ir(ctx, lower_countbits, body); +- lower_ir(ctx, lower_ctz, body); +- lower_ir(ctx, lower_f16tof32, body); +- lower_ir(ctx, lower_f32tof16, body); +- lower_ir(ctx, lower_find_msb, body); ++ replace_ir(ctx, lower_countbits, body); ++ replace_ir(ctx, lower_ctz, body); ++ replace_ir(ctx, lower_f16tof32, body); ++ replace_ir(ctx, lower_f32tof16, body); ++ replace_ir(ctx, lower_find_msb, body); + } + +- lower_ir(ctx, lower_isinf, body); ++ replace_ir(ctx, lower_isinf, body); + + lower_return(ctx, entry_func, body, false); + + while (hlsl_transform_ir(ctx, lower_calls, body, NULL)); + +- lower_ir(ctx, lower_complex_casts, body); +- lower_ir(ctx, lower_matrix_swizzles, body); +- lower_ir(ctx, lower_index_loads, body); ++ replace_ir(ctx, lower_complex_casts, body); ++ replace_ir(ctx, lower_matrix_swizzles, body); ++ replace_ir(ctx, lower_index_loads, body); + +- lower_ir(ctx, lower_tgsm_loads, body); +- lower_ir(ctx, lower_tgsm_stores, body); ++ replace_ir(ctx, lower_tgsm_loads, body); ++ replace_ir(ctx, lower_tgsm_stores, body); + + if (entry_func->return_var) + { +@@ -14739,9 +14846,9 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v + remove_unreachable_code(ctx, body); + hlsl_transform_ir(ctx, normalize_switch_cases, body, NULL); + +- lower_ir(ctx, lower_nonconstant_vector_derefs, body); +- lower_ir(ctx, lower_casts_to_bool, body); +- lower_ir(ctx, lower_int_dot, body); ++ replace_ir(ctx, lower_nonconstant_vector_derefs, body); ++ replace_ir(ctx, lower_casts_to_bool, body); ++ replace_ir(ctx, lower_int_dot, body); + + if (hlsl_version_lt(ctx, 4, 0)) + hlsl_transform_ir(ctx, lower_separate_samples, body, NULL); +@@ -14753,8 +14860,8 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v + progress = vectorize_exprs(ctx, body); + compute_liveness(ctx, body); + progress |= hlsl_transform_ir(ctx, dce, body, NULL); +- progress |= hlsl_transform_ir(ctx, fold_swizzle_chains, body, NULL); +- progress |= hlsl_transform_ir(ctx, remove_trivial_swizzles, body, NULL); ++ progress |= replace_ir(ctx, fold_swizzle_chains, body); ++ progress |= replace_ir(ctx, fold_trivial_swizzles, body); + progress |= vectorize_stores(ctx, body); + } while (progress); + +@@ -14782,37 +14889,37 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v + + if (profile->major_version < 4) + { +- while (lower_ir(ctx, lower_nonconstant_array_loads, body)); ++ while (replace_ir(ctx, lower_nonconstant_array_loads, body)); + +- lower_ir(ctx, lower_ternary, body); +- lower_ir(ctx, lower_int_modulus_sm1, body); +- lower_ir(ctx, lower_division, body); ++ replace_ir(ctx, lower_ternary, body); ++ replace_ir(ctx, lower_int_modulus_sm1, body); ++ replace_ir(ctx, lower_division, body); + /* Constants casted to float must be folded, and new casts to bool also need to be lowered. */ + hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL); +- lower_ir(ctx, lower_casts_to_bool, body); +- +- lower_ir(ctx, lower_casts_to_int, body); +- lower_ir(ctx, lower_trunc, body); +- lower_ir(ctx, lower_sqrt, body); +- lower_ir(ctx, lower_dot, body); +- lower_ir(ctx, lower_round, body); +- lower_ir(ctx, lower_ceil, body); +- lower_ir(ctx, lower_floor, body); +- lower_ir(ctx, lower_trig, body); +- lower_ir(ctx, lower_comparison_operators, body); +- lower_ir(ctx, lower_logic_not, body); ++ replace_ir(ctx, lower_casts_to_bool, body); ++ ++ replace_ir(ctx, lower_casts_to_int, body); ++ replace_ir(ctx, lower_trunc, body); ++ replace_ir(ctx, lower_sqrt, body); ++ replace_ir(ctx, lower_dot, body); ++ replace_ir(ctx, lower_round, body); ++ replace_ir(ctx, lower_ceil, body); ++ replace_ir(ctx, lower_floor, body); ++ replace_ir(ctx, lower_trig, body); ++ replace_ir(ctx, lower_comparison_operators, body); ++ replace_ir(ctx, lower_logic_not, body); + if (ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL) +- lower_ir(ctx, lower_slt, body); ++ replace_ir(ctx, lower_slt, body); + else +- lower_ir(ctx, lower_cmp, body); ++ replace_ir(ctx, lower_cmp, body); + } + + if (profile->major_version < 2) + { +- lower_ir(ctx, lower_abs, body); ++ replace_ir(ctx, lower_abs, body); + } + +- lower_ir(ctx, validate_nonconstant_vector_store_derefs, body); ++ replace_ir(ctx, validate_nonconstant_vector_store_derefs, body); + + hlsl_run_folding_passes(ctx, body); + +@@ -14930,6 +15037,8 @@ int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info + if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL) + generate_vsir_signature(ctx, program, ctx->patch_constant_func, &patch_semantic_vars); + ++ generate_vsir_descriptors(ctx, program); ++ + if (program->shader_version.major < 4) + sm1_generate_ctab(ctx, reflection_data); + else +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 670f6c31cf8..13ea8a433a6 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -299,6 +299,7 @@ const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) + [VSIR_OP_MOVC ] = "movc", + [VSIR_OP_MSAD ] = "msad", + [VSIR_OP_MUL ] = "mul", ++ [VSIR_OP_NEG ] = "neg", + [VSIR_OP_NEO ] = "ne_ord", + [VSIR_OP_NEU ] = "ne", + [VSIR_OP_NOP ] = "nop", +@@ -747,6 +748,38 @@ bool vsir_signature_find_sysval(const struct shader_signature *signature, + return false; + } + ++struct vkd3d_shader_descriptor_info1 *vsir_program_add_descriptor(struct vsir_program *program, ++ enum vkd3d_shader_descriptor_type type, unsigned int register_id, ++ const struct vkd3d_shader_register_range *range, ++ enum vkd3d_shader_resource_type resource_type, enum vsir_data_type resource_data_type) ++{ ++ struct vkd3d_shader_scan_descriptor_info1 *info = &program->descriptors; ++ struct vkd3d_shader_descriptor_info1 *d; ++ ++ if (!info) ++ return NULL; ++ ++ if (!vkd3d_array_reserve((void **)&info->descriptors, &program->descriptors_size, ++ info->descriptor_count + 1, sizeof(*info->descriptors))) ++ { ++ ERR("Failed to allocate descriptor info.\n"); ++ return NULL; ++ } ++ ++ d = &info->descriptors[info->descriptor_count]; ++ memset(d, 0, sizeof(*d)); ++ d->type = type; ++ d->register_id = register_id; ++ d->register_space = range->space; ++ d->register_index = range->first; ++ d->resource_type = resource_type; ++ d->resource_data_type = resource_data_type; ++ d->count = (range->last == ~0u) ? ~0u : range->last - range->first + 1; ++ ++info->descriptor_count; ++ ++ return d; ++} ++ + const char *debug_vsir_writemask(unsigned int writemask) + { + static const char components[] = {'x', 'y', 'z', 'w'}; +@@ -1422,8 +1455,8 @@ static enum vkd3d_result vsir_program_lower_imul(struct vsir_program *program, + static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, + struct vsir_program_iterator *it, struct vsir_transformation_context *ctx) + { ++ unsigned int count = 3, src0_id, src1_id, divisor_id; + struct vkd3d_shader_instruction *udiv, *ins, *mov; +- unsigned int count = 2; + + udiv = vsir_program_iterator_current(it); + +@@ -1437,9 +1470,9 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, + } + + if (udiv->dst[0].reg.type != VKD3DSPR_NULL) +- ++count; ++ count += 2; + if (udiv->dst[1].reg.type != VKD3DSPR_NULL) +- ++count; ++ count += 2; + + if (!vsir_program_iterator_insert_after(it, count)) + return VKD3D_ERROR_OUT_OF_MEMORY; +@@ -1451,14 +1484,33 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, + return VKD3D_ERROR_OUT_OF_MEMORY; + + mov->src[0] = udiv->src[0]; +- dst_param_init_ssa(&mov->dst[0], program->ssa_count, udiv->src[0].reg.data_type, udiv->src[0].reg.dimension); ++ src0_id = program->ssa_count++; ++ dst_param_init_ssa(&mov->dst[0], src0_id, udiv->src[0].reg.data_type, udiv->src[0].reg.dimension); + + mov = vsir_program_iterator_next(it); + if (!(vsir_instruction_init_with_params(program, mov, &udiv->location, VSIR_OP_MOV, 1, 1))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + mov->src[0] = udiv->src[1]; +- dst_param_init_ssa(&mov->dst[0], program->ssa_count + 1, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ src1_id = program->ssa_count++; ++ dst_param_init_ssa(&mov->dst[0], src1_id, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ ++ mov = vsir_program_iterator_next(it); ++ if (!(vsir_instruction_init_with_params(program, mov, &udiv->location, VSIR_OP_MOVC, 1, 3))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ src_param_init_ssa(&mov->src[0], src1_id, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ src_param_init_ssa(&mov->src[1], src1_id, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ vsir_register_init(&mov->src[2].reg, VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); ++ mov->src[2].reg.dimension = udiv->src[1].reg.dimension; ++ mov->src[2].reg.u.immconst_u32[0] = 1; ++ mov->src[2].reg.u.immconst_u32[1] = 1; ++ mov->src[2].reg.u.immconst_u32[2] = 1; ++ mov->src[2].reg.u.immconst_u32[3] = 1; ++ if (mov->src[2].reg.dimension == VSIR_DIMENSION_VEC4) ++ mov->src[2].swizzle = VKD3D_SHADER_NO_SWIZZLE; ++ divisor_id = program->ssa_count++; ++ dst_param_init_ssa(&mov->dst[0], divisor_id, mov->src[1].reg.data_type, mov->src[1].reg.dimension); + + if (udiv->dst[0].reg.type != VKD3DSPR_NULL) + { +@@ -1469,11 +1521,30 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, + + ins->flags = udiv->flags; + +- src_param_init_ssa(&ins->src[0], program->ssa_count, +- udiv->src[0].reg.data_type, udiv->src[0].reg.dimension); +- src_param_init_ssa(&ins->src[1], program->ssa_count + 1, +- udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ src_param_init_ssa(&ins->src[0], src0_id, udiv->src[0].reg.data_type, udiv->src[0].reg.dimension); ++ src_param_init_ssa(&ins->src[1], divisor_id, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ dst_param_init_ssa(&ins->dst[0], program->ssa_count, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ ++ /* Like its TPF equivalent, division by zero is well-defined for ++ * VSIR_OP_UDIV, and returns UINT_MAX. Division by zero is undefined ++ * for VSIR_OP_UDIV_SIMPLE and VSIR_OP_UREM, so handle it here. */ ++ ins = vsir_program_iterator_next(it); ++ if (!(vsir_instruction_init_with_params(program, ins, &udiv->location, VSIR_OP_MOVC, 1, 3))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ src_param_init_ssa(&ins->src[0], src1_id, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ src_param_init_ssa(&ins->src[1], program->ssa_count, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ vsir_register_init(&ins->src[2].reg, VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); ++ ins->src[2].reg.dimension = udiv->src[1].reg.dimension; ++ ins->src[2].reg.u.immconst_u32[0] = UINT_MAX; ++ ins->src[2].reg.u.immconst_u32[1] = UINT_MAX; ++ ins->src[2].reg.u.immconst_u32[2] = UINT_MAX; ++ ins->src[2].reg.u.immconst_u32[3] = UINT_MAX; ++ if (ins->src[2].reg.dimension == VSIR_DIMENSION_VEC4) ++ ins->src[2].swizzle = VKD3D_SHADER_NO_SWIZZLE; + ins->dst[0] = udiv->dst[0]; ++ ++ ++program->ssa_count; + } + + if (udiv->dst[1].reg.type != VKD3DSPR_NULL) +@@ -1485,15 +1556,30 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, + + ins->flags = udiv->flags; + +- src_param_init_ssa(&ins->src[0], program->ssa_count, +- udiv->src[0].reg.data_type, udiv->src[0].reg.dimension); +- src_param_init_ssa(&ins->src[1], program->ssa_count + 1, +- udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ src_param_init_ssa(&ins->src[0], src0_id, udiv->src[0].reg.data_type, udiv->src[0].reg.dimension); ++ src_param_init_ssa(&ins->src[1], divisor_id, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ dst_param_init_ssa(&ins->dst[0], program->ssa_count, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ ++ ins = vsir_program_iterator_next(it); ++ if (!(vsir_instruction_init_with_params(program, ins, &udiv->location, VSIR_OP_MOVC, 1, 3))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ src_param_init_ssa(&ins->src[0], src1_id, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ src_param_init_ssa(&ins->src[1], program->ssa_count, udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); ++ vsir_register_init(&ins->src[2].reg, VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); ++ ins->src[2].reg.dimension = udiv->src[1].reg.dimension; ++ ins->src[2].reg.u.immconst_u32[0] = UINT_MAX; ++ ins->src[2].reg.u.immconst_u32[1] = UINT_MAX; ++ ins->src[2].reg.u.immconst_u32[2] = UINT_MAX; ++ ins->src[2].reg.u.immconst_u32[3] = UINT_MAX; ++ if (ins->src[2].reg.dimension == VSIR_DIMENSION_VEC4) ++ ins->src[2].swizzle = VKD3D_SHADER_NO_SWIZZLE; + ins->dst[0] = udiv->dst[1]; ++ ++ ++program->ssa_count; + } + + vkd3d_shader_instruction_make_nop(udiv); +- program->ssa_count += 2; + + return VKD3D_OK; + } +@@ -1648,6 +1734,7 @@ static enum vkd3d_result vsir_program_lower_texcrd(struct vsir_program *program, + static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *program, + struct vkd3d_shader_instruction *ins, struct vkd3d_shader_message_context *message_context) + { ++ const struct vkd3d_shader_descriptor_info1 *sampler; + unsigned int idx = ins->src[0].reg.idx[0].offset; + struct vkd3d_shader_src_param *srcs; + +@@ -1660,7 +1747,7 @@ static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *progr + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + +- if (!(srcs = vsir_program_get_src_params(program, 3))) ++ if (!(srcs = vsir_program_get_src_params(program, 4))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + /* Note we run before I/O normalization. */ +@@ -1668,9 +1755,26 @@ static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *progr + vsir_src_param_init_resource(&srcs[1], idx, idx); + vsir_src_param_init_sampler(&srcs[2], idx, idx); + +- ins->opcode = VSIR_OP_SAMPLE; +- ins->src = srcs; +- ins->src_count = 3; ++ sampler = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx); ++ if (sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE) ++ { ++ enum vkd3d_shader_swizzle_component ref = vsir_swizzle_get_component(srcs[0].swizzle, 2); ++ ++ ins->opcode = VSIR_OP_SAMPLE_C; ++ ins->src = srcs; ++ ins->src_count = 4; ++ ++ srcs[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); ++ ++ srcs[3] = srcs[0]; ++ srcs[3].swizzle = vkd3d_shader_create_swizzle(ref, ref, ref, ref); ++ } ++ else ++ { ++ ins->opcode = VSIR_OP_SAMPLE; ++ ins->src = srcs; ++ ins->src_count = 3; ++ } + + return VKD3D_OK; + } +@@ -1730,6 +1834,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, + static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program, + struct vkd3d_shader_instruction *tex, struct vkd3d_shader_message_context *message_context) + { ++ const struct vkd3d_shader_descriptor_info1 *sampler; + unsigned int idx = tex->src[1].reg.idx[0].offset; + struct vkd3d_shader_src_param *srcs; + +@@ -1743,7 +1848,21 @@ static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program, + vsir_src_param_init_resource(&srcs[1], idx, idx); + vsir_src_param_init_sampler(&srcs[2], idx, idx); + +- if (!tex->flags) ++ sampler = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx); ++ if (sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE) ++ { ++ enum vkd3d_shader_swizzle_component ref = vsir_swizzle_get_component(srcs[0].swizzle, 2); ++ ++ tex->opcode = VSIR_OP_SAMPLE_C; ++ tex->src = srcs; ++ tex->src_count = 4; ++ ++ srcs[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); ++ ++ srcs[3] = srcs[0]; ++ srcs[3].swizzle = vkd3d_shader_create_swizzle(ref, ref, ref, ref); ++ } ++ else if (!tex->flags) + { + tex->opcode = VSIR_OP_SAMPLE; + tex->src = srcs; +@@ -1825,6 +1944,7 @@ static enum vkd3d_result vsir_program_lower_texldl(struct vsir_program *program, + + static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, struct vkd3d_shader_instruction *ins) + { ++ const struct vkd3d_shader_descriptor_info1 *sampler; + unsigned int idx = ins->dst[0].reg.idx[0].offset; + struct vkd3d_shader_src_param *srcs; + +@@ -1834,7 +1954,7 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, st + /* We run before I/O normalization. */ + VKD3D_ASSERT(program->normalisation_level < VSIR_NORMALISED_SM6); + +- if (!(srcs = vsir_program_get_src_params(program, 3))) ++ if (!(srcs = vsir_program_get_src_params(program, 4))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + vsir_src_param_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); +@@ -1845,9 +1965,24 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, st + vsir_src_param_init_resource(&srcs[1], idx, idx); + vsir_src_param_init_sampler(&srcs[2], idx, idx); + +- ins->opcode = VSIR_OP_SAMPLE; +- ins->src = srcs; +- ins->src_count = 3; ++ sampler = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx); ++ if (sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE) ++ { ++ ins->opcode = VSIR_OP_SAMPLE_C; ++ ins->src = srcs; ++ ins->src_count = 4; ++ ++ srcs[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); ++ ++ srcs[3] = srcs[0]; ++ srcs[3].swizzle = VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z); ++ } ++ else ++ { ++ ins->opcode = VSIR_OP_SAMPLE; ++ ins->src = srcs; ++ ins->src_count = 3; ++ } + + return VKD3D_OK; + } +@@ -2039,6 +2174,72 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr + return VKD3D_OK; + } + ++static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *program, ++ struct vsir_transformation_context *ctx) ++{ ++ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions), new_it; ++ struct vkd3d_shader_instruction *ins, *new_ins; ++ unsigned int i, j; ++ ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) ++ { ++ for (i = 0; i < ins->src_count; ++i) ++ { ++ enum vkd3d_shader_opcode new_opcodes[2] = {VSIR_OP_NOP, VSIR_OP_NOP}; ++ struct vkd3d_shader_src_param *src = &ins->src[i]; ++ ++ /* TODO: support other modifiers, including destination modifiers. */ ++ switch (src->modifiers) ++ { ++ case VKD3DSPSM_ABS: ++ new_opcodes[0] = VSIR_OP_ABS; ++ break; ++ ++ case VKD3DSPSM_NEG: ++ new_opcodes[0] = data_type_is_integer(src->reg.data_type) ? VSIR_OP_INEG : VSIR_OP_NEG; ++ break; ++ ++ case VKD3DSPSM_ABSNEG: ++ new_opcodes[0] = VSIR_OP_ABS; ++ new_opcodes[1] = VSIR_OP_NEG; ++ break; ++ ++ default: ++ continue; ++ } ++ ++ for (j = 0; j < 2 && new_opcodes[j] != VSIR_OP_NOP; ++j) ++ { ++ if (!(new_ins = vsir_program_iterator_insert_before(&it, &new_it, 1))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ins = vsir_program_iterator_current(&it); ++ ++ if (!vsir_instruction_init_with_params(program, new_ins, &ins->location, new_opcodes[j], 1, 1)) ++ { ++ vkd3d_shader_instruction_make_nop(new_ins); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ } ++ ++ new_ins->src[0] = *src; ++ new_ins->src[0].modifiers = VKD3DSPSM_NONE; ++ ++ dst_param_init_ssa(&new_ins->dst[0], program->ssa_count, src->reg.data_type, src->reg.dimension); ++ src_param_init_ssa(src, program->ssa_count, src->reg.data_type, src->reg.dimension); ++ ++ if (data_type_is_64_bit(src->reg.data_type)) ++ { ++ new_ins->dst[0].write_mask = vsir_write_mask_64_from_32(new_ins->dst[0].write_mask); ++ src->swizzle = vsir_swizzle_64_from_32(src->swizzle); ++ } ++ ++ ++program->ssa_count; ++ } ++ } ++ } ++ ++ return VKD3D_OK; ++} ++ + static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *program, + struct vsir_transformation_context *ctx) + { +@@ -3936,6 +4137,19 @@ static void cf_flattener_set_error(struct cf_flattener *flattener, enum vkd3d_re + flattener->status = error; + } + ++static struct vkd3d_shader_instruction *cf_flattener_instruction_append(struct cf_flattener *flattener) ++{ ++ struct vkd3d_shader_instruction *ins; ++ ++ if (!(ins = shader_instruction_array_append(&flattener->instructions))) ++ { ++ ERR("Failed to allocate instructions.\n"); ++ cf_flattener_set_error(flattener, VKD3D_ERROR_OUT_OF_MEMORY); ++ return NULL; ++ } ++ return ins; ++} ++ + static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, + const struct vkd3d_shader_instruction *instruction) + { +@@ -3944,7 +4158,7 @@ static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, + if (instruction->opcode == VSIR_OP_NOP) + return true; + +- if (!(dst_ins = shader_instruction_array_append(&flattener->instructions))) ++ if (!(dst_ins = cf_flattener_instruction_append(flattener))) + return false; + + *dst_ins = *instruction; +@@ -3975,7 +4189,7 @@ static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int + { + struct vkd3d_shader_instruction *ins; + +- if (!(ins = shader_instruction_array_append(&flattener->instructions))) ++ if (!(ins = cf_flattener_instruction_append(flattener))) + return; + if (!vsir_instruction_init_label(ins, &flattener->location, label_id, flattener->program)) + { +@@ -3993,7 +4207,7 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten + struct vkd3d_shader_src_param *src_params, *false_branch_param; + struct vkd3d_shader_instruction *ins; + +- if (!(ins = shader_instruction_array_append(&flattener->instructions))) ++ if (!(ins = cf_flattener_instruction_append(flattener))) + return NULL; + vsir_instruction_init(ins, &flattener->location, VSIR_OP_BRANCH); + +@@ -4144,13 +4358,6 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte + is_hull_shader = program->shader_version.type == VKD3D_SHADER_TYPE_HULL; + after_declarations_section = is_hull_shader; + +- if (!shader_instruction_array_reserve(&flattener->instructions, instructions->count + 1)) +- { +- ERR("Failed to allocate instructions.\n"); +- cf_flattener_set_error(flattener, VKD3D_ERROR_OUT_OF_MEMORY); +- return VKD3D_ERROR_OUT_OF_MEMORY; +- } +- + it = vsir_program_iterator(instructions); + for (instruction = vsir_program_iterator_head(&it); instruction; instruction = vsir_program_iterator_next(&it)) + { +@@ -4609,16 +4816,14 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs + vsir_src_param_init_label(&dst_ins->src[0], default_label); + } + +- if (!shader_instruction_array_reserve(&instructions, instructions.count + 3 * case_count - 1)) +- goto fail; +- + if_label = current_label; + + for (j = 0; j < case_count; ++j) + { + unsigned int fallthrough_label, case_label = label_from_src_param(&ins->src[3 + 2 * j + 1]); + +- dst_ins = shader_instruction_array_append(&instructions); ++ if (!(dst_ins = shader_instruction_array_append(&instructions))) ++ goto fail; + if (!vsir_instruction_init_with_params(program, dst_ins, &ins->location, VSIR_OP_IEQ, 1, 2)) + { + vkd3d_shader_instruction_make_nop(dst_ins); +@@ -4636,7 +4841,8 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs + else + fallthrough_label = block_count + 1; + +- dst_ins = shader_instruction_array_append(&instructions); ++ if (!(dst_ins = shader_instruction_array_append(&instructions))) ++ goto fail; + if (!vsir_instruction_init_with_params(program, dst_ins, &ins->location, VSIR_OP_BRANCH, 0, 3)) + { + vkd3d_shader_instruction_make_nop(dst_ins); +@@ -4660,7 +4866,8 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs + } + else + { +- dst_ins = shader_instruction_array_append(&instructions); ++ if (!(dst_ins = shader_instruction_array_append(&instructions))) ++ goto fail; + if (!vsir_instruction_init_with_params(program, dst_ins, &ins->location, VSIR_OP_LABEL, 0, 1)) + { + vkd3d_shader_instruction_make_nop(dst_ins); +@@ -4755,8 +4962,8 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps_in_function( + struct vsir_program_iterator it_begin = *it; + struct ssas_to_temps_alloc alloc = {0}; + struct vkd3d_shader_instruction *ins; +- size_t phi_count, incoming_count; + unsigned int current_label = 0; ++ size_t phi_count; + + VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); + +@@ -4770,7 +4977,6 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps_in_function( + goto fail; + + phi_count = 0; +- incoming_count = 0; + for (ins = vsir_program_iterator_current(it); ins; ins = vsir_program_iterator_next(it)) + { + unsigned int j, temp_idx; +@@ -4819,8 +5025,6 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps_in_function( + incoming->dst = ins->dst; + + alloc.table[ins->dst->reg.idx[0].offset] = temp_idx; +- +- ++incoming_count; + } + + materialize_ssas_to_temps_process_reg(program, &alloc, &ins->dst->reg); +@@ -4829,9 +5033,6 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps_in_function( + if (!phi_count) + goto done; + +- if (!shader_instruction_array_reserve(&program->instructions, program->instructions.count + incoming_count)) +- goto fail; +- + *it = it_begin; + + for (ins = vsir_program_iterator_current(it); ins; ins = vsir_program_iterator_next(it)) +@@ -4856,7 +5057,8 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps_in_function( + case VSIR_OP_SWITCH_MONOLITHIC: + info = &block_info[current_label - 1]; + +- mov_ins = vsir_program_iterator_insert_before_and_move(it, info->incoming_count); ++ if (!(mov_ins = vsir_program_iterator_insert_before_and_move(it, info->incoming_count))) ++ goto fail; + VKD3D_ASSERT(mov_ins); + + for (j = 0; j < info->incoming_count; ++j) +@@ -6782,23 +6984,14 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_block(struct vsir_cfg *cfg + struct vsir_cfg_emit_target *target = cfg->target; + struct vkd3d_shader_instruction *ins, *end, *dst; + struct vsir_program_iterator it; +- size_t ins_count = 0; + + it = block->begin; + end = vsir_program_iterator_current(&block->end); + + for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it)) + { +- ++ins_count; +- } +- +- if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + ins_count)) +- return VKD3D_ERROR_OUT_OF_MEMORY; +- +- it = block->begin; +- for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it)) +- { +- dst = shader_instruction_array_append(&target->instructions); ++ if (!(dst = shader_instruction_array_append(&target->instructions))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; + VKD3D_ASSERT(dst); + *dst = *ins; + } +@@ -6822,10 +7015,8 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, + if ((ret = vsir_cfg_structure_list_emit(cfg, &loop->body, loop->idx)) < 0) + return ret; + +- if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + 5)) ++ if (!(ins = shader_instruction_array_append(&target->instructions))) + return VKD3D_ERROR_OUT_OF_MEMORY; +- +- ins = shader_instruction_array_append(&target->instructions); + vsir_instruction_init(ins, &no_loc, VSIR_OP_ENDLOOP); + + /* Add a trampoline to implement multilevel jumping depending on the stored +@@ -6840,7 +7031,8 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, + * we have to reach an outer loop, so we keep breaking. */ + const unsigned int inner_break_target = loop->idx << 1; + +- ins = shader_instruction_array_append(&target->instructions); ++ if (!(ins = shader_instruction_array_append(&target->instructions))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; + if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_IEQ, 1, 2)) + { + vkd3d_shader_instruction_make_nop(ins); +@@ -6853,7 +7045,8 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, + src_param_init_temp_uint(&ins->src[0], target->jump_target_temp_idx); + src_param_init_const_uint(&ins->src[1], outer_continue_target); + +- ins = shader_instruction_array_append(&target->instructions); ++ if (!(ins = shader_instruction_array_append(&target->instructions))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; + if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_CONTINUEP, 0, 1)) + { + vkd3d_shader_instruction_make_nop(ins); +@@ -6875,7 +7068,8 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, + src_param_init_temp_uint(&ins->src[0], target->jump_target_temp_idx); + src_param_init_const_uint(&ins->src[1], inner_break_target); + +- ins = shader_instruction_array_append(&target->instructions); ++ if (!(ins = shader_instruction_array_append(&target->instructions))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; + if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_BREAKP, 0, 1)) + { + vkd3d_shader_instruction_make_nop(ins); +@@ -6971,12 +7165,10 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, + vkd3d_unreachable(); + } + +- if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + 2)) +- return VKD3D_ERROR_OUT_OF_MEMORY; +- + if (jump->needs_launcher) + { +- ins = shader_instruction_array_append(&target->instructions); ++ if (!(ins = shader_instruction_array_append(&target->instructions))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; + if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_MOV, 1, 1)) + { + vkd3d_shader_instruction_make_nop(ins); +@@ -6987,7 +7179,8 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, + src_param_init_const_uint(&ins->src[0], jump_target); + } + +- ins = shader_instruction_array_append(&target->instructions); ++ if (!(ins = shader_instruction_array_append(&target->instructions))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; + if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, opcode, 0, !!jump->condition)) + { + vkd3d_shader_instruction_make_nop(ins); +@@ -8097,35 +8290,41 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(it); + struct vkd3d_shader_location loc = ins->location; + uint32_t ssa_factor = program->ssa_count++; +- uint32_t ssa_temp, ssa_temp2; ++ uint32_t ssa_temp, ssa_temp2, ssa_temp3; + + switch (mode) + { + case VKD3D_SHADER_FOG_FRAGMENT_LINEAR: + /* We generate the following code: + * +- * add sr0, FOG_END, -vFOG.x +- * mul_sat srFACTOR, sr0, FOG_SCALE ++ * neg sr0, vFOG.x ++ * add sr1, FOG_END, sr0 ++ * mul_sat srFACTOR, sr1, FOG_SCALE + */ +- if (!(ins = vsir_program_iterator_insert_before_and_move(it, 4))) ++ if (!(ins = vsir_program_iterator_insert_before_and_move(it, 6))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + ssa_temp = program->ssa_count++; ++ ssa_temp2 = program->ssa_count++; + +- vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_ADD, 1, 2); ++ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_NEG, 1, 1); + dst_param_init_ssa_float(&ins->dst[0], ssa_temp); ++ vsir_src_param_init(&ins->src[0], VKD3DSPR_INPUT, VSIR_DATA_F32, 1); ++ ins->src[0].reg.idx[0].offset = fog_signature_idx; ++ ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); ++ ins = vsir_program_iterator_next(it); ++ ++ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_ADD, 1, 2); ++ dst_param_init_ssa_float(&ins->dst[0], ssa_temp2); + src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_END, VSIR_DATA_F32); +- vsir_src_param_init(&ins->src[1], VKD3DSPR_INPUT, VSIR_DATA_F32, 1); +- ins->src[1].reg.idx[0].offset = fog_signature_idx; +- ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; +- ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); +- ins->src[1].modifiers = VKD3DSPSM_NEG; ++ src_param_init_ssa_float(&ins->src[1], ssa_temp); + ins = vsir_program_iterator_next(it); + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MUL, 1, 2); + dst_param_init_ssa_float(&ins->dst[0], ssa_factor); + ins->dst[0].modifiers = VKD3DSPDM_SATURATE; +- src_param_init_ssa_float(&ins->src[0], ssa_temp); ++ src_param_init_ssa_float(&ins->src[0], ssa_temp2); + src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VSIR_DATA_F32); + ins = vsir_program_iterator_next(it); + +@@ -8135,12 +8334,14 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + /* We generate the following code: + * + * mul sr0, FOG_SCALE, vFOG.x +- * exp_sat srFACTOR, -sr0 ++ * neg sr1, sr0 ++ * exp_sat srFACTOR, sr1 + */ +- if (!(ins = vsir_program_iterator_insert_before_and_move(it, 4))) ++ if (!(ins = vsir_program_iterator_insert_before_and_move(it, 6))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + ssa_temp = program->ssa_count++; ++ ssa_temp2 = program->ssa_count++; + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MUL, 1, 2); + dst_param_init_ssa_float(&ins->dst[0], ssa_temp); +@@ -8151,11 +8352,15 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); + ins = vsir_program_iterator_next(it); + ++ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_NEG, 1, 1); ++ dst_param_init_ssa_float(&ins->dst[0], ssa_temp2); ++ src_param_init_ssa_float(&ins->src[0], ssa_temp); ++ ins = vsir_program_iterator_next(it); ++ + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_EXP, 1, 1); + dst_param_init_ssa_float(&ins->dst[0], ssa_factor); + ins->dst[0].modifiers = VKD3DSPDM_SATURATE; +- src_param_init_ssa_float(&ins->src[0], ssa_temp); +- ins->src[0].modifiers = VKD3DSPSM_NEG; ++ src_param_init_ssa_float(&ins->src[0], ssa_temp2); + ins = vsir_program_iterator_next(it); + break; + +@@ -8164,13 +8369,15 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + * + * mul sr0, FOG_SCALE, vFOG.x + * mul sr1, sr0, sr0 +- * exp_sat srFACTOR, -sr1 ++ * neg sr2, sr1 ++ * exp_sat srFACTOR, sr2 + */ +- if (!(ins = vsir_program_iterator_insert_before_and_move(it, 5))) ++ if (!(ins = vsir_program_iterator_insert_before_and_move(it, 7))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + ssa_temp = program->ssa_count++; + ssa_temp2 = program->ssa_count++; ++ ssa_temp3 = program->ssa_count++; + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MUL, 1, 2); + dst_param_init_ssa_float(&ins->dst[0], ssa_temp); +@@ -8187,11 +8394,15 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + src_param_init_ssa_float(&ins->src[1], ssa_temp); + ins = vsir_program_iterator_next(it); + ++ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_NEG, 1, 1); ++ dst_param_init_ssa_float(&ins->dst[0], ssa_temp3); ++ src_param_init_ssa_float(&ins->src[0], ssa_temp2); ++ ins = vsir_program_iterator_next(it); ++ + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_EXP, 1, 1); + dst_param_init_ssa_float(&ins->dst[0], ssa_factor); + ins->dst[0].modifiers = VKD3DSPDM_SATURATE; +- src_param_init_ssa_float(&ins->src[0], ssa_temp2); +- ins->src[0].modifiers = VKD3DSPSM_NEG; ++ src_param_init_ssa_float(&ins->src[0], ssa_temp3); + ins = vsir_program_iterator_next(it); + break; + +@@ -8201,21 +8412,28 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + + /* We generate the following code: + * +- * add sr0, FRAG_COLOUR, -FOG_COLOUR +- * mad oC0, sr0, srFACTOR, FOG_COLOUR ++ * neg sr0, FOG_COLOUR ++ * add sr1, FRAG_COLOUR, sr0 ++ * mad oC0, sr1, srFACTOR, FOG_COLOUR + */ ++ ssa_temp = program->ssa_count++; ++ ssa_temp2 = program->ssa_count++; ++ ++ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_NEG, 1, 1); ++ dst_param_init_ssa_float4(&ins->dst[0], ssa_temp); ++ src_param_init_parameter_vec4(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_COLOUR, VSIR_DATA_F32); ++ ins = vsir_program_iterator_next(it); + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_ADD, 1, 2); +- dst_param_init_ssa_float4(&ins->dst[0], program->ssa_count++); ++ dst_param_init_ssa_float4(&ins->dst[0], ssa_temp2); + src_param_init_temp_float4(&ins->src[0], colour_temp); +- src_param_init_parameter_vec4(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_FOG_COLOUR, VSIR_DATA_F32); +- ins->src[1].modifiers = VKD3DSPSM_NEG; ++ src_param_init_ssa_float4(&ins->src[1], ssa_temp); + ins = vsir_program_iterator_next(it); + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MAD, 1, 3); + dst_param_init_output(&ins->dst[0], VSIR_DATA_F32, colour_signature_idx, + program->output_signature.elements[colour_signature_idx].mask); +- src_param_init_ssa_float4(&ins->src[0], program->ssa_count - 1); ++ src_param_init_ssa_float4(&ins->src[0], ssa_temp2); + src_param_init_ssa_float(&ins->src[1], ssa_factor); + src_param_init_parameter_vec4(&ins->src[2], VKD3D_SHADER_PARAMETER_NAME_FOG_COLOUR, VSIR_DATA_F32); + ins = vsir_program_iterator_next(it); +@@ -8560,6 +8778,7 @@ static bool vsir_src_is_masked(enum vkd3d_shader_opcode opcode, unsigned int src + case VSIR_OP_MOVC: + case VSIR_OP_MSAD: /* FIXME: Is this correct? */ + case VSIR_OP_MUL: ++ case VSIR_OP_NEG: + case VSIR_OP_NEO: + case VSIR_OP_NEU: + case VSIR_OP_NOT: +@@ -11482,6 +11701,18 @@ static void vsir_validate_float_elementwise_operation(struct validation_context + vsir_validate_elementwise_operation(ctx, instruction, types); + } + ++static void vsir_validate_float_or_double_elementwise_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VSIR_DATA_F32] = true, ++ [VSIR_DATA_F64] = true, ++ }; ++ ++ vsir_validate_elementwise_operation(ctx, instruction, types); ++} ++ + static void vsir_validate_integer_elementwise_operation(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) + { +@@ -12534,7 +12765,7 @@ struct vsir_validator_instruction_desc + + static const struct vsir_validator_instruction_desc vsir_validator_instructions[] = + { +- [VSIR_OP_ABS] = {1, 1, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_ABS] = {1, 1, vsir_validate_float_or_double_elementwise_operation}, + [VSIR_OP_ACOS] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_ADD] = {1, 2, vsir_validate_float_elementwise_operation}, + [VSIR_OP_AND] = {1, 2, vsir_validate_logic_elementwise_operation}, +@@ -12629,6 +12860,7 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_MAX] = {1, 2, vsir_validate_float_elementwise_operation}, + [VSIR_OP_MIN] = {1, 2, vsir_validate_float_elementwise_operation}, + [VSIR_OP_MUL] = {1, 2, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_NEG] = {1, 1, vsir_validate_float_or_double_elementwise_operation}, + [VSIR_OP_NEO] = {1, 2, vsir_validate_float_comparison_operation}, + [VSIR_OP_NEU] = {1, 2, vsir_validate_float_comparison_operation}, + [VSIR_OP_NOP] = {0, 0, vsir_validate_nop}, +@@ -12899,8 +13131,6 @@ static void vsir_transform_( + struct vsir_transformation_context *ctx, const char *step_name, + enum vkd3d_result (*step)(struct vsir_program *program, struct vsir_transformation_context *ctx)) + { +- ctx->progress = false; +- + if (ctx->result < 0) + return; + +@@ -13050,6 +13280,7 @@ static bool vsir_instruction_has_side_effects(const struct vkd3d_shader_instruct + case VSIR_OP_MOVC: + case VSIR_OP_MSAD: + case VSIR_OP_MUL: ++ case VSIR_OP_NEG: + case VSIR_OP_NEO: + case VSIR_OP_NEU: + case VSIR_OP_NOP: +@@ -13317,6 +13548,229 @@ static enum vkd3d_result vsir_program_dce(struct vsir_program *program, + return VKD3D_OK; + } + ++/* ++ * This pass attempts to reduce redundant MOVs (copies) by combining them with ++ * adjacent instructions. The resulting MOVs will subsequently be removed by ++ * DCE if no longer used. ++ * ++ * We attempt to combine two instructions, not necessarily consecutive, ++ * of the form ++ * ++ * mov aaa.bbb, ccc ++ * XXX ..., aaa.ddd ++ * ++ * into ++ * ++ * XXX ..., ccc ++ * ++ * There are many constraints, including: ++ * ++ * - The ddd components of aaa must not have been modified between the ++ * two instructions. ++ * Currently, only SSA is supported, so this is trivial. ++ * ++ * - The relevant components of ccc must not have been modified between the ++ * two instructions. ++ * Currently, we require ccc to be a read-only register, so this is trivial. ++ * ++ * - ddd must be a subset of bbb. This is again trivial for SSA. ++ */ ++ ++struct vsir_copy_propagation_state ++{ ++ /* The sources for each SSA register, if it was written by a ++ * MOV instruction, or NULL if not. ++ * ++ * We do not add or remove instructions in this pass, only modifying their ++ * content, so these pointers are safe to store. ++ */ ++ const struct vkd3d_shader_instruction **ssa_sources; ++}; ++ ++static bool is_read_only(const struct vsir_program *program, enum vkd3d_shader_register_type type) ++{ ++ switch (type) ++ { ++ case VKD3DSPR_ADDR: ++ case VKD3DSPR_IDXTEMP: ++ case VKD3DSPR_LOOP: ++ case VKD3DSPR_TEMP: ++ case VKD3DSPR_TEMPFLOAT16: ++ return false; ++ ++ case VKD3DSPR_TEXTURE: ++ return vkd3d_shader_ver_ge(&program->shader_version, 1, 4); ++ ++ /* Not applicable since they're not numeric or can't be sources. */ ++ case VKD3DSPR_ATTROUT: ++ case VKD3DSPR_COLOROUT: ++ case VKD3DSPR_COMBINED_SAMPLER: ++ case VKD3DSPR_COUNT: ++ case VKD3DSPR_DEPTHOUT: ++ case VKD3DSPR_DEPTHOUTGE: ++ case VKD3DSPR_DEPTHOUTLE: ++ case VKD3DSPR_FUNCTIONBODY: ++ case VKD3DSPR_FUNCTIONPOINTER: ++ case VKD3DSPR_GROUPSHAREDMEM: ++ case VKD3DSPR_INVALID: ++ case VKD3DSPR_LABEL: ++ case VKD3DSPR_NULL: ++ case VKD3DSPR_OUTPUT: ++ case VKD3DSPR_OUTSTENCILREF: ++ case VKD3DSPR_PREDICATE: ++ case VKD3DSPR_RASTERIZER: ++ case VKD3DSPR_RASTOUT: ++ case VKD3DSPR_RESOURCE: ++ case VKD3DSPR_SAMPLER: ++ case VKD3DSPR_STREAM: ++ case VKD3DSPR_TEXCRDOUT: ++ case VKD3DSPR_UAV: ++ return false; ++ ++ case VKD3DSPR_CONST: ++ case VKD3DSPR_CONSTBOOL: ++ case VKD3DSPR_CONSTBUFFER: ++ case VKD3DSPR_CONSTINT: ++ case VKD3DSPR_COVERAGE: ++ case VKD3DSPR_FORKINSTID: ++ case VKD3DSPR_GSINSTID: ++ case VKD3DSPR_IMMCONST: ++ case VKD3DSPR_IMMCONST64: ++ case VKD3DSPR_IMMCONSTBUFFER: ++ case VKD3DSPR_INCONTROLPOINT: ++ case VKD3DSPR_INPUT: ++ case VKD3DSPR_JOININSTID: ++ case VKD3DSPR_LOCALTHREADID: ++ case VKD3DSPR_LOCALTHREADINDEX: ++ case VKD3DSPR_MISCTYPE: ++ case VKD3DSPR_OUTCONTROLPOINT: ++ case VKD3DSPR_OUTPOINTID: ++ case VKD3DSPR_PARAMETER: ++ case VKD3DSPR_PATCHCONST: ++ case VKD3DSPR_POINT_COORD: ++ case VKD3DSPR_PRIMID: ++ case VKD3DSPR_SAMPLEMASK: ++ case VKD3DSPR_SSA: ++ case VKD3DSPR_TESSCOORD: ++ case VKD3DSPR_THREADGROUPID: ++ case VKD3DSPR_THREADID: ++ case VKD3DSPR_UNDEF: ++ case VKD3DSPR_WAVELANECOUNT: ++ case VKD3DSPR_WAVELANEINDEX: ++ return true; ++ } ++ ++ vkd3d_unreachable(); ++} ++ ++static bool can_propagate_ssa_source(const struct vsir_program *program, const struct vkd3d_shader_instruction *ins) ++{ ++ if (ins->opcode != VSIR_OP_MOV) ++ return false; ++ /* TODO: Propagate copies for other register types. */ ++ if (ins->dst[0].reg.type != VKD3DSPR_SSA) ++ return false; ++ if (ins->dst[0].modifiers || ins->dst[0].shift) ++ return false; ++ ++ /* TODO: We can perform copy-prop for read-write register types, but we ++ * have to be sure that the register wasn't modified between the two ++ * instructions. */ ++ if (!is_read_only(program, ins->src[0].reg.type)) ++ return false; ++ for (unsigned int k = 0; k < ins->src[0].reg.idx_count; ++k) ++ { ++ if (ins->src[0].reg.idx[k].rel_addr && !is_read_only(program, ins->src[0].reg.idx[k].rel_addr->reg.type)) ++ return false; ++ } ++ ++ /* Don't bother with other source modifiers for now; the HLSL compiler ++ * doesn't emit them. */ ++ switch (ins->src[0].modifiers) ++ { ++ case VKD3DSPSM_ABS: ++ case VKD3DSPSM_ABSNEG: ++ case VKD3DSPSM_NEG: ++ case VKD3DSPSM_NONE: ++ break; ++ ++ default: ++ return false; ++ } ++ return true; ++} ++ ++static enum vkd3d_result vsir_program_copy_propagation(struct vsir_program *program, ++ struct vsir_transformation_context *ctx) ++{ ++ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); ++ struct vsir_copy_propagation_state state = {0}; ++ struct vkd3d_shader_instruction *ins; ++ ++ if (!(state.ssa_sources = vkd3d_calloc(program->ssa_count, sizeof(*state.ssa_sources)))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) ++ { ++ for (unsigned int j = 0; j < ins->src_count; ++j) ++ { ++ struct vkd3d_shader_src_param *src = &ins->src[j]; ++ const struct vkd3d_shader_src_param *mov_src; ++ const struct vkd3d_shader_instruction *mov; ++ enum vsir_data_type data_type; ++ uint32_t new_swizzle = 0; ++ ++ if (src->reg.type != VKD3DSPR_SSA) ++ continue; ++ if (data_type_is_64_bit(src->reg.data_type)) ++ continue; ++ if (!(mov = state.ssa_sources[src->reg.idx[0].offset])) ++ continue; ++ mov_src = &mov->src[0]; ++ data_type = src->reg.data_type; ++ ++ src->reg = mov_src->reg; ++ src->reg.data_type = data_type; ++ ++ if (!shader_register_clone_relative_addresses(&src->reg, program)) ++ { ++ vkd3d_free(state.ssa_sources); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ } ++ ++ for (unsigned int k = 0; k < 4; ++k) ++ { ++ unsigned int s = vsir_swizzle_get_component(src->swizzle, k); ++ ++ if (mov_src->reg.type == VKD3DSPR_IMMCONST) ++ src->reg.u.immconst_u32[k] = mov_src->reg.u.immconst_u32[s]; ++ else ++ vsir_swizzle_set_component(&new_swizzle, k, vsir_swizzle_get_component(mov_src->swizzle, s)); ++ } ++ if (mov_src->reg.type != VKD3DSPR_IMMCONST) ++ src->swizzle = new_swizzle; ++ ++ if (src->modifiers == VKD3DSPSM_NONE) ++ src->modifiers = mov_src->modifiers; ++ else if (src->modifiers == VKD3DSPSM_NEG && mov_src->modifiers == VKD3DSPSM_ABS) ++ src->modifiers = VKD3DSPSM_ABSNEG; ++ else if (src->modifiers == VKD3DSPSM_NEG && mov_src->modifiers == VKD3DSPSM_ABSNEG) ++ src->modifiers = VKD3DSPSM_ABS; ++ else if (src->modifiers == VKD3DSPSM_NEG && mov_src->modifiers == VKD3DSPSM_NEG) ++ src->modifiers = VKD3DSPSM_NONE; ++ /* Otherwise no change is necessary. */ ++ ++ ctx->progress = true; ++ } ++ ++ if (can_propagate_ssa_source(program, ins)) ++ state.ssa_sources[ins->dst[0].reg.idx[0].offset] = ins; ++ } ++ ++ vkd3d_free(state.ssa_sources); ++ return VKD3D_OK; ++} ++ + enum vkd3d_result vsir_program_optimize(struct vsir_program *program, uint64_t config_flags, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) + { +@@ -13325,7 +13779,11 @@ enum vkd3d_result vsir_program_optimize(struct vsir_program *program, uint64_t c + vsir_transformation_context_init(&ctx, program, config_flags, compile_info, message_context); + + do ++ { ++ ctx.progress = false; ++ vsir_transform(&ctx, vsir_program_copy_propagation); + vsir_transform(&ctx, vsir_program_dce); ++ } + while (ctx.progress); + + if (TRACE_ON()) +@@ -13388,6 +13846,7 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t + struct vsir_transformation_context ctx; + + vsir_transformation_context_init(&ctx, program, config_flags, compile_info, message_context); ++ vsir_transform(&ctx, vsir_program_lower_modifiers); + vsir_transform(&ctx, vsir_program_lower_instructions); + + if (program->shader_version.major >= 6) +diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c +index 8a89dcabd5e..fc136e3ac98 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/msl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/msl.c +@@ -602,25 +602,11 @@ static void msl_print_src_with_type(struct vkd3d_string_buffer *buffer, struct m + if (reg->dimension == VSIR_DIMENSION_VEC4) + msl_print_swizzle(str, vsir_src->swizzle, mask); + +- switch (vsir_src->modifiers) ++ if (vsir_src->modifiers) + { +- case VKD3DSPSM_NONE: +- break; +- case VKD3DSPSM_NEG: +- vkd3d_string_buffer_printf(buffer, "-%s", str->buffer); +- break; +- case VKD3DSPSM_ABS: +- vkd3d_string_buffer_printf(buffer, "abs(%s)", str->buffer); +- break; +- case VKD3DSPSM_ABSNEG: +- vkd3d_string_buffer_printf(buffer, "-abs(%s)", str->buffer); +- break; +- default: +- vkd3d_string_buffer_printf(buffer, "(%s)", +- vsir_src->modifiers, str->buffer); +- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, +- "Internal compiler error: Unhandled source modifier(s) %#x.", vsir_src->modifiers); +- break; ++ vkd3d_string_buffer_printf(buffer, "(%s)", vsir_src->modifiers, str->buffer); ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled source modifier(s) %#x.", vsir_src->modifiers); + } + + if (str != buffer) +@@ -1472,6 +1458,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + + switch (ins->opcode) + { ++ case VSIR_OP_ABS: ++ msl_intrinsic(gen, ins, "abs"); ++ break; + case VSIR_OP_ACOS: + msl_intrinsic(gen, ins, "acos"); + break; +@@ -1624,6 +1613,7 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + msl_relop(gen, ins, "!="); + break; + case VSIR_OP_INEG: ++ case VSIR_OP_NEG: + msl_unary_op(gen, ins, "-"); + break; + case VSIR_OP_ITOF: +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index 3deca660b00..31271660e4f 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -989,7 +989,7 @@ struct vkd3d_spirv_builder + uint32_t type_bool_id; + uint32_t type_void_id; + uint32_t scope_subgroup_id; +- uint32_t numeric_type_ids[VKD3D_SHADER_COMPONENT_TYPE_COUNT][VKD3D_VEC4_SIZE]; ++ uint32_t numeric_type_ids[VSIR_DATA_TYPE_COUNT][VKD3D_VEC4_SIZE]; + + struct vkd3d_spirv_stream debug_stream; /* debug instructions */ + struct vkd3d_spirv_stream annotation_stream; /* decoration instructions */ +@@ -2116,20 +2116,6 @@ static uint32_t vkd3d_spirv_build_op_fdiv(struct vkd3d_spirv_builder *builder, + SpvOpFDiv, result_type, operand0, operand1); + } + +-static uint32_t vkd3d_spirv_build_op_fnegate(struct vkd3d_spirv_builder *builder, +- uint32_t result_type, uint32_t operand) +-{ +- return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, +- SpvOpFNegate, result_type, operand); +-} +- +-static uint32_t vkd3d_spirv_build_op_snegate(struct vkd3d_spirv_builder *builder, +- uint32_t result_type, uint32_t operand) +-{ +- return vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, +- SpvOpSNegate, result_type, operand); +-} +- + static uint32_t vkd3d_spirv_build_op_and(struct vkd3d_spirv_builder *builder, + uint32_t result_type, uint32_t operand0, uint32_t operand1) + { +@@ -2478,19 +2464,6 @@ static uint32_t vkd3d_spirv_build_op_group_nonuniform_broadcast_first(struct vkd + result_type, vkd3d_spirv_get_op_scope_subgroup(builder), val_id); + } + +-static uint32_t vkd3d_spirv_build_op_glsl_std450_tr1(struct vkd3d_spirv_builder *builder, +- enum GLSLstd450 op, uint32_t result_type, uint32_t operand) +-{ +- uint32_t id = vkd3d_spirv_get_glsl_std450_instr_set(builder); +- return vkd3d_spirv_build_op_ext_inst(builder, result_type, id, op, &operand, 1); +-} +- +-static uint32_t vkd3d_spirv_build_op_glsl_std450_fabs(struct vkd3d_spirv_builder *builder, +- uint32_t result_type, uint32_t operand) +-{ +- return vkd3d_spirv_build_op_glsl_std450_tr1(builder, GLSLstd450FAbs, result_type, operand); +-} +- + static uint32_t vkd3d_spirv_build_op_glsl_std450_max(struct vkd3d_spirv_builder *builder, + uint32_t result_type, uint32_t x, uint32_t y) + { +@@ -2518,71 +2491,69 @@ static uint32_t vkd3d_spirv_build_op_glsl_std450_nclamp(struct vkd3d_spirv_build + GLSLstd450NClamp, operands, ARRAY_SIZE(operands)); + } + +-static uint32_t spirv_get_type_id_for_component_type(struct vkd3d_spirv_builder *builder, +- enum vkd3d_shader_component_type component_type, unsigned int component_count) ++static uint32_t spirv_get_type_id(struct vkd3d_spirv_builder *builder, ++ enum vsir_data_type data_type, unsigned int component_count) + { + uint32_t scalar_id, type_id; + +- VKD3D_ASSERT(component_type < VKD3D_SHADER_COMPONENT_TYPE_COUNT); ++ VKD3D_ASSERT(data_type < VSIR_DATA_TYPE_COUNT); + if (!component_count || component_count > VKD3D_VEC4_SIZE) + { + ERR("Invalid component count %u.\n", component_count); + return 0; + } + +- if ((type_id = builder->numeric_type_ids[component_type][component_count - 1])) ++ if ((type_id = builder->numeric_type_ids[data_type][component_count - 1])) + return type_id; + + if (component_count == 1) + { +- switch (component_type) ++ switch (data_type) + { +- case VKD3D_SHADER_COMPONENT_VOID: +- type_id = vkd3d_spirv_get_op_type_void(builder); ++ case VSIR_DATA_BOOL: ++ type_id = vkd3d_spirv_get_op_type_bool(builder); + break; +- case VKD3D_SHADER_COMPONENT_FLOAT: ++ ++ case VSIR_DATA_F32: + type_id = vkd3d_spirv_get_op_type_float(builder, 32); + break; +- case VKD3D_SHADER_COMPONENT_INT: +- case VKD3D_SHADER_COMPONENT_UINT: +- type_id = vkd3d_spirv_get_op_type_int(builder, 32, component_type == VKD3D_SHADER_COMPONENT_INT); ++ ++ case VSIR_DATA_F64: ++ type_id = vkd3d_spirv_get_op_type_float(builder, 64); + break; +- case VKD3D_SHADER_COMPONENT_BOOL: +- type_id = vkd3d_spirv_get_op_type_bool(builder); ++ ++ case VSIR_DATA_I32: ++ case VSIR_DATA_U32: ++ type_id = vkd3d_spirv_get_op_type_int(builder, 32, data_type == VSIR_DATA_I32); + break; +- case VKD3D_SHADER_COMPONENT_DOUBLE: +- type_id = vkd3d_spirv_get_op_type_float(builder, 64); ++ ++ case VSIR_DATA_I64: ++ case VSIR_DATA_U64: ++ type_id = vkd3d_spirv_get_op_type_int(builder, 64, data_type == VSIR_DATA_I64); + break; +- case VKD3D_SHADER_COMPONENT_INT64: +- case VKD3D_SHADER_COMPONENT_UINT64: +- type_id = vkd3d_spirv_get_op_type_int(builder, 64, component_type == VKD3D_SHADER_COMPONENT_INT64); ++ ++ case VSIR_DATA_UNUSED: ++ type_id = vkd3d_spirv_get_op_type_void(builder); + break; ++ + default: +- FIXME("Unhandled component type %#x.\n", component_type); ++ FIXME("Unhandled data type \"%s\" (%#x).\n", ++ vsir_data_type_get_name(data_type, ""), data_type); + return 0; + } + } + else + { +- VKD3D_ASSERT(component_type != VKD3D_SHADER_COMPONENT_VOID); +- scalar_id = spirv_get_type_id_for_component_type(builder, component_type, 1); ++ VKD3D_ASSERT(data_type != VSIR_DATA_UNUSED); ++ scalar_id = spirv_get_type_id(builder, data_type, 1); + type_id = vkd3d_spirv_get_op_type_vector(builder, scalar_id, component_count); + } + +- builder->numeric_type_ids[component_type][component_count - 1] = type_id; ++ builder->numeric_type_ids[data_type][component_count - 1] = type_id; + + return type_id; + } + +-static uint32_t spirv_get_type_id(struct vkd3d_spirv_builder *builder, +- enum vsir_data_type data_type, unsigned int component_count) +-{ +- enum vkd3d_shader_component_type component_type; +- +- component_type = vkd3d_component_type_from_data_type(data_type); +- return spirv_get_type_id_for_component_type(builder, component_type, component_count); +-} +- + static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, + const char *entry_point, const char *source_name) + { +@@ -4846,74 +4817,23 @@ static void spirv_compiler_emit_execution_mode1(struct spirv_compiler *compiler, + spirv_compiler_emit_execution_mode(compiler, mode, &literal, 1); + } + +-static uint32_t spirv_compiler_emit_abs(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) +-{ +- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- uint32_t type_id; +- +- type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask); +- if (data_type_is_floating_point(reg->data_type)) +- return vkd3d_spirv_build_op_glsl_std450_fabs(builder, type_id, val_id); +- +- FIXME("Unhandled data type %#x.\n", reg->data_type); +- return val_id; +-} +- +-static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) +-{ +- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- uint32_t type_id; +- +- type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask); +- if (data_type_is_floating_point(reg->data_type)) +- return vkd3d_spirv_build_op_fnegate(builder, type_id, val_id); +- else if (data_type_is_integer(reg->data_type)) +- return vkd3d_spirv_build_op_snegate(builder, type_id, val_id); +- +- FIXME("Unhandled data type %#x.\n", reg->data_type); +- return val_id; +-} +- +-static uint32_t spirv_compiler_emit_src_modifier(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, uint32_t write_mask, +- enum vkd3d_shader_src_modifier modifier, uint32_t val_id) +-{ +- switch (modifier) +- { +- case VKD3DSPSM_NONE: +- break; +- case VKD3DSPSM_NEG: +- return spirv_compiler_emit_neg(compiler, reg, write_mask, val_id); +- case VKD3DSPSM_ABS: +- return spirv_compiler_emit_abs(compiler, reg, write_mask, val_id); +- case VKD3DSPSM_ABSNEG: +- val_id = spirv_compiler_emit_abs(compiler, reg, write_mask, val_id); +- return spirv_compiler_emit_neg(compiler, reg, write_mask, val_id); +- default: +- FIXME("Unhandled src modifier %#x.\n", modifier); +- break; +- } +- +- return val_id; +-} +- + static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, + const struct vkd3d_shader_src_param *src, uint32_t write_mask) + { +- uint32_t val_id; ++ if (src->modifiers) ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, ++ "Unhandled source modifier(s) %#x.", src->modifiers); + +- val_id = spirv_compiler_emit_load_reg(compiler, &src->reg, src->swizzle, write_mask); +- return spirv_compiler_emit_src_modifier(compiler, &src->reg, write_mask, src->modifiers, val_id); ++ return spirv_compiler_emit_load_reg(compiler, &src->reg, src->swizzle, write_mask); + } + + static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *compiler, +- const struct vkd3d_shader_src_param *src, uint32_t write_mask, enum vkd3d_shader_component_type component_type) ++ const struct vkd3d_shader_src_param *src, uint32_t write_mask, enum vsir_data_type data_type) + { + struct vkd3d_shader_src_param src_param = *src; + +- src_param.reg.data_type = vsir_data_type_from_component_type(component_type); ++ src_param.reg.data_type = data_type; ++ + return spirv_compiler_emit_load_src(compiler, &src_param, write_mask); + } + +@@ -5081,10 +5001,8 @@ static void spirv_compiler_emit_store_dst(struct spirv_compiler *compiler, + } + + static void spirv_compiler_emit_store_dst_swizzled(struct spirv_compiler *compiler, +- const struct vkd3d_shader_dst_param *dst, uint32_t val_id, +- enum vkd3d_shader_component_type component_type, uint32_t swizzle) ++ const struct vkd3d_shader_dst_param *dst, uint32_t val_id, enum vsir_data_type data_type, uint32_t swizzle) + { +- enum vsir_data_type data_type = vsir_data_type_from_component_type(component_type); + struct vkd3d_shader_dst_param typed_dst = *dst; + + val_id = spirv_compiler_emit_swizzle(compiler, val_id, +@@ -5096,23 +5014,17 @@ static void spirv_compiler_emit_store_dst_swizzled(struct spirv_compiler *compil + } + + static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *compiler, +- const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_component_type component_type, +- uint32_t *component_ids) ++ const struct vkd3d_shader_dst_param *dst, enum vsir_data_type data_type, uint32_t *component_ids) + { + unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, dst_type_id, val_id; + +- type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); ++ type_id = spirv_get_type_id(builder, data_type, component_count); + if (component_count > 1) +- { +- val_id = vkd3d_spirv_build_op_composite_construct(builder, +- type_id, component_ids, component_count); +- } ++ val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, component_ids, component_count); + else +- { + val_id = *component_ids; +- } + + dst_type_id = spirv_get_type_id(builder, dst->reg.data_type, component_count); + if (dst_type_id != type_id) +@@ -5122,8 +5034,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp + } + + static void spirv_compiler_emit_store_dst_scalar(struct spirv_compiler *compiler, +- const struct vkd3d_shader_dst_param *dst, uint32_t val_id, +- enum vkd3d_shader_component_type component_type, uint32_t swizzle) ++ const struct vkd3d_shader_dst_param *dst, uint32_t val_id, enum vsir_data_type data_type, uint32_t swizzle) + { + unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); + uint32_t component_ids[VKD3D_VEC4_SIZE]; +@@ -5137,7 +5048,7 @@ static void spirv_compiler_emit_store_dst_scalar(struct spirv_compiler *compiler + + component_ids[i] = val_id; + } +- spirv_compiler_emit_store_dst_components(compiler, dst, component_type, component_ids); ++ spirv_compiler_emit_store_dst_components(compiler, dst, data_type, component_ids); + } + + static void spirv_compiler_decorate_builtin(struct spirv_compiler *compiler, +@@ -5229,7 +5140,7 @@ static void spirv_compiler_decorate_builtin(struct spirv_compiler *compiler, + } + + static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler *compiler, +- enum vkd3d_shader_component_type component_type, uint32_t id, enum vkd3d_shader_interpolation_mode mode) ++ enum vsir_data_type data_type, uint32_t id, enum vkd3d_shader_interpolation_mode mode) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + +@@ -5238,7 +5149,7 @@ static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler + case VKD3DSIM_NONE: + /* VUID-StandaloneSpirv-Flat-04744: integer or double types must be + * decorated 'Flat' for fragment shaders. */ +- if (compiler->shader_type != VKD3D_SHADER_TYPE_PIXEL || component_type == VKD3D_SHADER_COMPONENT_FLOAT) ++ if (compiler->shader_type != VKD3D_SHADER_TYPE_PIXEL || data_type == VSIR_DATA_F32) + break; + /* fall through */ + case VKD3DSIM_CONSTANT: +@@ -5724,7 +5635,6 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + unsigned int component_idx, input_component_count; + const struct signature_element *signature_element; + const struct shader_signature *shader_signature; +- enum vkd3d_shader_component_type component_type; + enum vkd3d_shader_register_type sysval_reg_type; + const struct vkd3d_spirv_builtin *builtin; + enum vkd3d_shader_sysval_semantic sysval; +@@ -5782,13 +5692,11 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + if (builtin) + { + data_type = builtin->data_type; +- component_type = vkd3d_component_type_from_data_type(data_type); + input_component_count = builtin->component_count; + } + else + { +- component_type = signature_element->component_type; +- data_type = vsir_data_type_from_component_type(component_type); ++ data_type = vsir_data_type_from_component_type(signature_element->component_type); + input_component_count = vsir_write_mask_component_count(signature_element->mask); + } + +@@ -5841,8 +5749,8 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + if (component_idx) + vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationComponent, component_idx); + +- spirv_compiler_emit_interpolation_decorations(compiler, component_type, input_id, +- signature_element->interpolation_mode); ++ spirv_compiler_emit_interpolation_decorations(compiler, data_type, ++ input_id, signature_element->interpolation_mode); + } + + var_id = input_id; +@@ -6879,7 +6787,7 @@ static const struct vkd3d_spirv_resource_type *spirv_compiler_enable_resource_ty + return resource_type_info; + } + +-static SpvImageFormat image_format_for_image_read(enum vkd3d_shader_component_type data_type) ++static SpvImageFormat image_format_for_image_read(enum vsir_data_type data_type) + { + /* The following formats are supported by Direct3D 11 hardware for UAV + * typed loads. A newer hardware may support more formats for UAV typed +@@ -6887,11 +6795,11 @@ static SpvImageFormat image_format_for_image_read(enum vkd3d_shader_component_ty + */ + switch (data_type) + { +- case VKD3D_SHADER_COMPONENT_FLOAT: ++ case VSIR_DATA_F32: + return SpvImageFormatR32f; +- case VKD3D_SHADER_COMPONENT_INT: ++ case VSIR_DATA_I32: + return SpvImageFormatR32i; +- case VKD3D_SHADER_COMPONENT_UINT: ++ case VSIR_DATA_U32: + return SpvImageFormatR32ui; + default: + FIXME("Unhandled type %#x.\n", data_type); +@@ -6901,8 +6809,7 @@ static SpvImageFormat image_format_for_image_read(enum vkd3d_shader_component_ty + + static uint32_t spirv_compiler_get_image_type_id(struct spirv_compiler *compiler, + const struct vkd3d_shader_register *reg, const struct vkd3d_shader_register_range *range, +- const struct vkd3d_spirv_resource_type *resource_type_info, enum vkd3d_shader_component_type data_type, +- bool raw_structured) ++ const struct vkd3d_spirv_resource_type *resource_type_info, enum vsir_data_type data_type, bool raw_structured) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_descriptor_info1 *d; +@@ -6923,15 +6830,15 @@ static uint32_t spirv_compiler_get_image_type_id(struct spirv_compiler *compiler + vkd3d_spirv_enable_capability(builder, SpvCapabilityStorageImageReadWithoutFormat); + } + +- sampled_type_id = spirv_get_type_id_for_component_type(builder, data_type, 1); +- return vkd3d_spirv_get_op_type_image(builder, sampled_type_id, resource_type_info->dim, +- 2, resource_type_info->arrayed, resource_type_info->ms, +- reg->type == VKD3DSPR_UAV ? 2 : 1, format); ++ sampled_type_id = spirv_get_type_id(builder, data_type, 1); ++ ++ return vkd3d_spirv_get_op_type_image(builder, sampled_type_id, resource_type_info->dim, 2, ++ resource_type_info->arrayed, resource_type_info->ms, reg->type == VKD3DSPR_UAV ? 2 : 1, format); + } + + static void spirv_compiler_emit_combined_sampler_declarations(struct spirv_compiler *compiler, + const struct vkd3d_shader_register *resource, const struct vkd3d_shader_register_range *resource_range, +- enum vkd3d_shader_resource_type resource_type, enum vkd3d_shader_component_type sampled_type, ++ enum vkd3d_shader_resource_type resource_type, enum vsir_data_type sampled_type, + unsigned int structure_stride, bool raw, const struct vkd3d_spirv_resource_type *resource_type_info) + { + const struct vkd3d_shader_interface_info *shader_interface = &compiler->shader_interface; +@@ -6992,7 +6899,7 @@ static void spirv_compiler_emit_combined_sampler_declarations(struct spirv_compi + symbol.id = var_id; + symbol.descriptor_array = NULL; + symbol.info.resource.range = *resource_range; +- symbol.info.resource.sampled_type = vsir_data_type_from_component_type(sampled_type); ++ symbol.info.resource.sampled_type = sampled_type; + symbol.info.resource.type_id = image_type_id; + symbol.info.resource.resource_type_info = resource_type_info; + symbol.info.resource.structure_stride = structure_stride; +@@ -7017,9 +6924,9 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp + uint32_t counter_type_id, type_id, var_id, counter_var_id = 0; + const struct vkd3d_spirv_resource_type *resource_type_info; + unsigned int sample_count = descriptor->sample_count; +- enum vkd3d_shader_component_type sampled_type; + struct vkd3d_symbol resource_symbol; + struct vkd3d_shader_register reg; ++ enum vsir_data_type sampled_type; + + vsir_register_init(®, is_uav ? VKD3DSPR_UAV : VKD3DSPR_RESOURCE, VSIR_DATA_F32, 1); + reg.idx[0].offset = descriptor->register_id; +@@ -7036,7 +6943,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp + return; + } + +- sampled_type = vkd3d_component_type_from_data_type(descriptor->resource_data_type); ++ sampled_type = descriptor->resource_data_type; + + if (!is_uav && spirv_compiler_has_combined_sampler_for_resource(compiler, range)) + { +@@ -7049,7 +6956,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp + { + uint32_t array_type_id, struct_id; + +- type_id = spirv_get_type_id(builder, descriptor->resource_data_type, 1); ++ type_id = spirv_get_type_id(builder, sampled_type, 1); + + array_type_id = vkd3d_spirv_get_op_type_runtime_array(builder, type_id); + vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 4); +@@ -7122,7 +7029,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp + resource_symbol.id = var_id; + resource_symbol.descriptor_array = var_info.array_symbol; + resource_symbol.info.resource.range = *range; +- resource_symbol.info.resource.sampled_type = descriptor->resource_data_type; ++ resource_symbol.info.resource.sampled_type = sampled_type; + resource_symbol.info.resource.type_id = type_id; + resource_symbol.info.resource.resource_type_info = resource_type_info; + resource_symbol.info.resource.structure_stride = structure_stride; +@@ -7564,6 +7471,7 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru + {VSIR_OP_ITOF, SpvOpConvertSToF}, + {VSIR_OP_ITOI, SpvOpSConvert}, + {VSIR_OP_MUL, SpvOpFMul}, ++ {VSIR_OP_NEG, SpvOpFNegate}, + {VSIR_OP_NOT, SpvOpNot}, + {VSIR_OP_OR, SpvOpBitwiseOr}, + {VSIR_OP_UDIV_SIMPLE, SpvOpUDiv}, +@@ -7641,14 +7549,13 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, + static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { +- uint32_t src_ids[SPIRV_MAX_SRC_COUNT], condition_id = 0, uint_max_id = 0; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; +- unsigned int i, component_count; ++ uint32_t src_ids[SPIRV_MAX_SRC_COUNT]; + uint32_t type_id, val_id; + SpvOp op = SpvOpMax; +- bool check_zero; ++ unsigned int i; + + if (src->reg.data_type == VSIR_DATA_U64 && instruction->opcode == VSIR_OP_COUNTBITS) + { +@@ -7688,44 +7595,14 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil + return VKD3D_ERROR_INVALID_SHADER; + } + +- /* SPIR-V doesn't mandate a behaviour when a denominator is zero, +- * so we have an explicit check. */ +- switch (instruction->opcode) +- { +- case VSIR_OP_IDIV: +- case VSIR_OP_IREM: +- case VSIR_OP_UDIV_SIMPLE: +- case VSIR_OP_UREM: +- check_zero = true; +- break; +- +- default: +- check_zero = false; +- break; +- } +- + VKD3D_ASSERT(instruction->dst_count == 1); + VKD3D_ASSERT(instruction->src_count <= SPIRV_MAX_SRC_COUNT); +- if (check_zero) +- VKD3D_ASSERT(instruction->src_count == 2); + +- component_count = vsir_write_mask_component_count(dst[0].write_mask); + type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); + + for (i = 0; i < instruction->src_count; ++i) + src_ids[i] = spirv_compiler_emit_load_src(compiler, &src[i], dst->write_mask); + +- if (check_zero) +- { +- condition_id = spirv_compiler_emit_int_to_bool(compiler, +- VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src_ids[1]); +- +- if (data_type_is_64_bit(dst[0].reg.data_type)) +- uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count); +- else +- uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT_MAX, component_count); +- } +- + /* The SPIR-V specification states, "The resulting value is undefined if + * Shift is greater than or equal to the bit width of the components of + * Base." Direct3D applies only the lowest 5 bits of the shift. +@@ -7746,9 +7623,6 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil + if (instruction->flags & VKD3DSI_PRECISE_XYZW) + vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); + +- if (check_zero) +- val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, val_id, uint_max_id); +- + spirv_compiler_emit_store_dst(compiler, dst, val_id); + return VKD3D_OK; + } +@@ -8230,16 +8104,16 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; +- enum vkd3d_shader_component_type component_type; + unsigned int i, j, k, src_count, size; ++ enum vsir_data_type data_type; + uint32_t write_mask; + SpvOp op; + + src_count = instruction->src_count; + VKD3D_ASSERT(2 <= src_count && src_count <= ARRAY_SIZE(src_ids)); + +- component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); +- type_id = spirv_get_type_id(builder, dst->reg.data_type, 1); ++ data_type = dst->reg.data_type; ++ type_id = spirv_get_type_id(builder, data_type, 1); + size = data_type_is_64_bit(src[src_count - 1].reg.data_type) ? 0x40 : 0x20; + mask_id = spirv_compiler_get_constant_uint(compiler, size - 1); + size_id = spirv_compiler_get_constant_uint(compiler, size); +@@ -8265,7 +8139,7 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp + for (j = 0; j < src_count; ++j) + { + src_ids[src_count - j - 1] = spirv_compiler_emit_load_src_with_type(compiler, +- &src[j], write_mask, component_type); ++ &src[j], write_mask, data_type); + } + + /* In SPIR-V, the last two operands are Offset and Count. */ +@@ -8281,7 +8155,7 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp + op, type_id, src_ids, src_count); + } + +- spirv_compiler_emit_store_dst_components(compiler, dst, component_type, constituents); ++ spirv_compiler_emit_store_dst_components(compiler, dst, data_type, constituents); + } + + static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler, +@@ -8313,8 +8187,7 @@ static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler, + scalar_type_id, result_id, 0); + } + +- spirv_compiler_emit_store_dst_components(compiler, +- dst, vkd3d_component_type_from_data_type(dst->reg.data_type), components); ++ spirv_compiler_emit_store_dst_components(compiler, dst, dst->reg.data_type, components); + } + + static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler, +@@ -8349,8 +8222,7 @@ static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler, + instr_set_id, GLSLstd450PackHalf2x16, &src_id, 1); + } + +- spirv_compiler_emit_store_dst_components(compiler, +- dst, vkd3d_component_type_from_data_type(dst->reg.data_type), components); ++ spirv_compiler_emit_store_dst_components(compiler, dst, dst->reg.data_type, components); + } + + static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *compiler, +@@ -8918,8 +8790,7 @@ static void spirv_compiler_prepare_image(struct spirv_compiler *compiler, + } + + image->image_type_id = spirv_compiler_get_image_type_id(compiler, resource_reg, &symbol->info.resource.range, +- image->resource_type_info, vkd3d_component_type_from_data_type(image->sampled_type), +- image->structure_stride || image->raw); ++ image->resource_type_info, image->sampled_type, image->structure_stride || image->raw); + + if (sampled) + { +@@ -9014,8 +8885,7 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_image_fetch(builder, type_id, + image.image_id, coordinate_id, operands_mask, image_operands, image_operand_count); + +- spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, +- vkd3d_component_type_from_data_type(image.sampled_type), src[1].swizzle); ++ spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, image.sampled_type, src[1].swizzle); + } + + static void spirv_compiler_emit_lod(struct spirv_compiler *compiler, +@@ -9040,8 +8910,7 @@ static void spirv_compiler_emit_lod(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_image_query_lod(builder, + type_id, image.sampled_image_id, coordinate_id); + +- spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, +- vkd3d_component_type_from_data_type(image.sampled_type), resource->swizzle); ++ spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, image.sampled_type, resource->swizzle); + } + + static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, +@@ -9111,8 +8980,7 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_image_sample(builder, op, sampled_type_id, + image.sampled_image_id, coordinate_id, operands_mask, image_operands, image_operand_count); + +- spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, +- vkd3d_component_type_from_data_type(image.sampled_type), resource->swizzle); ++ spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, image.sampled_type, resource->swizzle); + } + + static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, +@@ -9157,8 +9025,7 @@ static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, + image.sampled_image_id, coordinate_id, dref_id, operands_mask, + image_operands, image_operand_count); + +- spirv_compiler_emit_store_dst_scalar(compiler, dst, val_id, +- vkd3d_component_type_from_data_type(image.sampled_type), src[1].swizzle); ++ spirv_compiler_emit_store_dst_scalar(compiler, dst, val_id, image.sampled_type, src[1].swizzle); + } + + static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, +@@ -9230,8 +9097,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, + operands_mask, image_operands, image_operand_count); + } + +- spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, +- vkd3d_component_type_from_data_type(image.sampled_type), resource->swizzle); ++ spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, image.sampled_type, resource->swizzle); + } + + static uint32_t spirv_compiler_emit_raw_structured_addressing( +@@ -9293,7 +9159,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler + texel_type_id = spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, texel_type_id); + +- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); + base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, + type_id, resource_symbol->info.resource.structure_stride, + &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); +@@ -9325,7 +9191,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler + + spirv_compiler_prepare_image(compiler, &image, &resource->reg, NULL, VKD3D_IMAGE_FLAG_NONE); + +- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); + base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, + type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); + +@@ -9348,7 +9214,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler + type_id, val_id, 0); + } + } +- spirv_compiler_emit_store_dst_components(compiler, dst, VKD3D_SHADER_COMPONENT_UINT, constituents); ++ spirv_compiler_emit_store_dst_components(compiler, dst, VSIR_DATA_U32, constituents); + } + + static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, +@@ -9388,7 +9254,7 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, + ptr_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, reg_info.id, coordinate_id); + constituents[j++] = vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone); + } +- spirv_compiler_emit_store_dst_components(compiler, dst, VKD3D_SHADER_COMPONENT_UINT, constituents); ++ spirv_compiler_emit_store_dst_components(compiler, dst, VSIR_DATA_U32, constituents); + } + + static void spirv_compiler_emit_ld_raw_structured(struct spirv_compiler *compiler, +@@ -9430,7 +9296,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * + type_id = spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); + +- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); + base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, + type_id, resource_symbol->info.resource.structure_stride, + &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); +@@ -9458,7 +9324,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * + } + else + { +- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); + spirv_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE); + base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, + type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); +@@ -9569,7 +9435,7 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone); + + spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, +- vkd3d_component_type_from_data_type(resource_symbol->info.resource.sampled_type), src[1].swizzle); ++ resource_symbol->info.resource.sampled_type, src[1].swizzle); + } + else + { +@@ -9581,8 +9447,7 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_image_read(builder, type_id, + image.image_id, coordinate_id, SpvImageOperandsMaskNone, NULL, 0); + +- spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, +- vkd3d_component_type_from_data_type(image.sampled_type), src[1].swizzle); ++ spirv_compiler_emit_store_dst_swizzled(compiler, dst, val_id, image.sampled_type, src[1].swizzle); + } + } + +@@ -9608,8 +9473,8 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler, + indices[0] = spirv_compiler_get_constant_uint(compiler, 0); + indices[1] = coordinate_id; + +- val_id = spirv_compiler_emit_load_src_with_type(compiler, &src[1], VKD3DSP_WRITEMASK_0, +- vkd3d_component_type_from_data_type(resource_symbol->info.resource.sampled_type)); ++ val_id = spirv_compiler_emit_load_src_with_type(compiler, &src[1], ++ VKD3DSP_WRITEMASK_0, resource_symbol->info.resource.sampled_type); + ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2); + vkd3d_spirv_build_op_store(builder, ptr_id, val_id, SpvMemoryAccessMaskNone); + } +@@ -9620,8 +9485,7 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler, + spirv_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE); + coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1; + coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], coordinate_mask); +- texel_id = spirv_compiler_emit_load_src_with_type(compiler, &src[1], +- dst->write_mask, vkd3d_component_type_from_data_type(image.sampled_type)); ++ texel_id = spirv_compiler_emit_load_src_with_type(compiler, &src[1], dst->write_mask, image.sampled_type); + + vkd3d_spirv_build_op_image_write(builder, image.image_id, coordinate_id, texel_id, + SpvImageOperandsMaskNone, NULL, 0); +@@ -9756,11 +9620,9 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + const struct vkd3d_shader_src_param *src = instruction->src; + const struct vkd3d_symbol *resource_symbol = NULL; + uint32_t ptr_type_id, type_id, val_id, result_id; +- enum vkd3d_shader_component_type component_type; + const struct vkd3d_shader_dst_param *resource; + uint32_t coordinate_id, sample_id, pointer_id; + struct vkd3d_shader_register_info reg_info; +- SpvMemorySemanticsMask memory_semantic; + struct vkd3d_shader_image image; + enum vsir_data_type data_type; + unsigned int structure_stride; +@@ -9811,7 +9673,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + } + } + +- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); + if (structure_stride || raw) + { + VKD3D_ASSERT(!raw != !structure_stride); +@@ -9853,8 +9715,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + } + } + +- component_type = vkd3d_component_type_from_data_type(data_type); +- val_id = spirv_compiler_emit_load_src_with_type(compiler, &src[1], VKD3DSP_WRITEMASK_0, component_type); ++ val_id = spirv_compiler_emit_load_src_with_type(compiler, &src[1], VKD3DSP_WRITEMASK_0, data_type); + + if (instruction->flags & VKD3DARF_VOLATILE) + { +@@ -9863,17 +9724,13 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + } + +- memory_semantic = (instruction->flags & VKD3DARF_SEQ_CST) +- ? SpvMemorySemanticsSequentiallyConsistentMask +- : SpvMemorySemanticsMaskNone; +- + operands[i++] = pointer_id; + operands[i++] = spirv_compiler_get_constant_uint(compiler, scope); +- operands[i++] = spirv_compiler_get_constant_uint(compiler, memory_semantic); ++ operands[i++] = spirv_compiler_get_constant_uint(compiler, SpvMemorySemanticsMaskNone); + if (instruction->src_count >= 3) + { +- operands[i++] = spirv_compiler_get_constant_uint(compiler, memory_semantic); +- operands[i++] = spirv_compiler_emit_load_src_with_type(compiler, &src[2], VKD3DSP_WRITEMASK_0, component_type); ++ operands[i++] = spirv_compiler_get_constant_uint(compiler, SpvMemorySemanticsMaskNone); ++ operands[i++] = spirv_compiler_emit_load_src_with_type(compiler, &src[2], VKD3DSP_WRITEMASK_0, data_type); + } + operands[i++] = val_id; + result_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream, +@@ -10648,6 +10505,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, + case VSIR_OP_ITOF: + case VSIR_OP_ITOI: + case VSIR_OP_MUL: ++ case VSIR_OP_NEG: + case VSIR_OP_NOT: + case VSIR_OP_OR: + case VSIR_OP_UDIV_SIMPLE: +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index 2b5badb8871..821c639ee16 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -950,6 +950,7 @@ static bool vkd3d_shader_signature_from_shader_signature(struct vkd3d_shader_sig + struct vkd3d_shader_scan_context + { + const struct vkd3d_shader_version *version; ++ const struct vkd3d_shader_d3dbc_source_info *d3dbc_source_info; + + struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info; + size_t descriptors_size; +@@ -1017,6 +1018,7 @@ static void vkd3d_shader_scan_context_init(struct vkd3d_shader_scan_context *con + context->location.line = 2; /* Line 1 is the version token. */ + context->api_version = VKD3D_SHADER_API_VERSION_1_2; + context->combined_sampler_info = combined_sampler_info; ++ context->d3dbc_source_info = vkd3d_find_struct(compile_info->next, D3DBC_SOURCE_INFO); + + for (i = 0; i < compile_info->option_count; ++i) + { +@@ -1218,15 +1220,6 @@ static void vkd3d_shader_scan_sampler_declaration(struct vkd3d_shader_scan_conte + d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE; + } + +-static void vkd3d_shader_scan_combined_sampler_declaration( +- struct vkd3d_shader_scan_context *context, const struct vkd3d_shader_semantic *semantic) +-{ +- vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, &semantic->resource.reg.reg, +- &semantic->resource.range, VKD3D_SHADER_RESOURCE_NONE, VSIR_DATA_UNUSED); +- vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, &semantic->resource.reg.reg, +- &semantic->resource.range, semantic->resource_type, VSIR_DATA_F32); +-} +- + const struct vkd3d_shader_descriptor_info1 *vkd3d_shader_find_descriptor( + const struct vkd3d_shader_scan_descriptor_info1 *info, + enum vkd3d_shader_descriptor_type type, unsigned int register_id) +@@ -1312,40 +1305,6 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co + s->sampler_index = sampler_idx; + } + +-static void vkd3d_shader_scan_sample_instruction(struct vkd3d_shader_scan_context *context, +- const struct vkd3d_shader_register *resource, const struct vkd3d_shader_register *sampler) +-{ +- unsigned int resource_idx = resource->idx[0].offset; +- unsigned int sampler_idx = sampler->idx[0].offset; +- +- vkd3d_shader_scan_combined_sampler_usage(context, resource, sampler); +- +- if (!context->scan_descriptor_info) +- return; +- +- /* Sample instructions lowered from 1.x texture instructions have no +- * DCL, so we need to add the resource if it didn't already exist. +- * Such descriptors have a fixed count, type, etc. */ +- +- if (!vkd3d_shader_find_descriptor(context->scan_descriptor_info, +- VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_idx)) +- { +- struct vkd3d_shader_register_range range = {.first = resource_idx, .last = resource_idx}; +- +- vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource, +- &range, VKD3D_SHADER_RESOURCE_TEXTURE_2D, VSIR_DATA_F32); +- } +- +- if (!vkd3d_shader_find_descriptor(context->scan_descriptor_info, +- VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler_idx)) +- { +- struct vkd3d_shader_register_range range = {.first = sampler_idx, .last = sampler_idx}; +- +- vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, resource, +- &range, VKD3D_SHADER_RESOURCE_NONE, VSIR_DATA_UNUSED); +- } +-} +- + static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_context *context, + const struct vkd3d_shader_resource *resource, enum vkd3d_shader_resource_type resource_type, + enum vsir_data_type resource_data_type, unsigned int sample_count, +@@ -1403,14 +1362,9 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte + vkd3d_shader_scan_sampler_declaration(context, instruction); + break; + case VSIR_OP_DCL: +- if (instruction->declaration.semantic.resource_type == VKD3D_SHADER_RESOURCE_NONE) +- break; +- +- if (instruction->declaration.semantic.resource.reg.reg.type == VKD3DSPR_COMBINED_SAMPLER) +- { +- vkd3d_shader_scan_combined_sampler_declaration(context, &instruction->declaration.semantic); ++ if (instruction->declaration.semantic.resource_type == VKD3D_SHADER_RESOURCE_NONE ++ || instruction->declaration.semantic.resource.reg.reg.type == VKD3DSPR_COMBINED_SAMPLER) + break; +- } + /* fall through */ + case VSIR_OP_DCL_UAV_TYPED: + vkd3d_shader_scan_typed_resource_declaration(context, instruction); +@@ -1564,6 +1518,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte + break; + case VSIR_OP_GATHER4: + case VSIR_OP_GATHER4_C: ++ case VSIR_OP_SAMPLE: + case VSIR_OP_SAMPLE_B: + case VSIR_OP_SAMPLE_C: + case VSIR_OP_SAMPLE_C_LZ: +@@ -1571,9 +1526,6 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte + case VSIR_OP_SAMPLE_LOD: + vkd3d_shader_scan_combined_sampler_usage(context, &instruction->src[1].reg, &instruction->src[2].reg); + break; +- case VSIR_OP_SAMPLE: +- vkd3d_shader_scan_sample_instruction(context, &instruction->src[1].reg, &instruction->src[2].reg); +- break; + case VSIR_OP_GATHER4_PO: + case VSIR_OP_GATHER4_PO_C: + vkd3d_shader_scan_combined_sampler_usage(context, &instruction->src[2].reg, &instruction->src[3].reg); +@@ -1714,7 +1666,6 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh + struct vkd3d_shader_scan_context context; + struct vkd3d_shader_instruction *ins; + int ret = VKD3D_OK; +- unsigned int i; + + descriptor_info = vkd3d_find_struct(compile_info->next, SCAN_DESCRIPTOR_INFO); + if (descriptor_info) +@@ -1729,6 +1680,9 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh + add_descriptor_info = true; + } + ++ if (program->has_descriptor_info) ++ add_descriptor_info = false; ++ + tessellation_info = vkd3d_find_struct(compile_info->next, SCAN_HULL_SHADER_TESSELLATION_INFO); + thread_group_size_info = vkd3d_find_struct(compile_info->next, SCAN_THREAD_GROUP_SIZE_INFO); + +@@ -1747,21 +1701,6 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh + break; + } + +- for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i) +- { +- struct vkd3d_shader_register_range range = {.space = 0, .first = i, .last = i}; +- struct vkd3d_shader_register reg = {.idx[0].offset = i, .idx_count = 1}; +- unsigned int size = program->flat_constant_count[i]; +- struct vkd3d_shader_descriptor_info1 *d; +- +- if (size) +- { +- if ((d = vkd3d_shader_scan_add_descriptor(&context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, +- ®, &range, VKD3D_SHADER_RESOURCE_BUFFER, VSIR_DATA_U32))) +- d->buffer_size = size * 16; +- } +- } +- + if (!ret && signature_info) + { + if (!vkd3d_shader_signature_from_shader_signature(&signature_info->input, &program->input_signature) +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index df0eb2ff789..c70096f1f75 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -503,6 +503,7 @@ enum vkd3d_shader_opcode + VSIR_OP_MOVC, + VSIR_OP_MSAD, + VSIR_OP_MUL, ++ VSIR_OP_NEG, + VSIR_OP_NEO, + VSIR_OP_NEU, + VSIR_OP_NOP, +@@ -878,8 +879,7 @@ enum vkd3d_shader_uav_flags + + enum vkd3d_shader_atomic_rmw_flags + { +- VKD3DARF_SEQ_CST = 0x1, +- VKD3DARF_VOLATILE = 0x2, ++ VKD3DARF_VOLATILE = 0x1, + }; + + enum vkd3d_tessellator_domain +@@ -1590,6 +1590,7 @@ struct vsir_program + + struct vkd3d_shader_scan_descriptor_info1 descriptors; + bool has_descriptor_info; ++ size_t descriptors_size; + + unsigned int parameter_count; + const struct vkd3d_shader_parameter1 *parameters; +@@ -1597,7 +1598,6 @@ struct vsir_program + + unsigned int input_control_point_count, output_control_point_count; + struct vsir_thread_group_size thread_group_size; +- unsigned int flat_constant_count[3]; + unsigned int block_count; /* maximum block count in any function */ + unsigned int temp_count; + unsigned int ssa_count; +@@ -1636,6 +1636,10 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, + enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, + struct vkd3d_shader_message_context *message_context); + ++struct vkd3d_shader_descriptor_info1 *vsir_program_add_descriptor(struct vsir_program *program, ++ enum vkd3d_shader_descriptor_type type, unsigned int register_id, ++ const struct vkd3d_shader_register_range *range, ++ enum vkd3d_shader_resource_type resource_type, enum vsir_data_type resource_data_type); + bool vsir_program_add_icb(struct vsir_program *program, struct vkd3d_shader_immediate_constant_buffer *icb); + void vsir_program_cleanup(struct vsir_program *program); + const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( +@@ -1883,42 +1887,6 @@ int hlsl_parse(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_message_context *message_context, + struct vsir_program *program, struct vkd3d_shader_code *reflection_data); + +-static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type( enum vsir_data_type data_type) +-{ +- switch (data_type) +- { +- case VSIR_DATA_BOOL: +- return VKD3D_SHADER_COMPONENT_BOOL; +- case VSIR_DATA_F16: +- return VKD3D_SHADER_COMPONENT_FLOAT16; +- case VSIR_DATA_F32: +- case VSIR_DATA_SNORM: +- case VSIR_DATA_UNORM: +- return VKD3D_SHADER_COMPONENT_FLOAT; +- case VSIR_DATA_F64: +- return VKD3D_SHADER_COMPONENT_DOUBLE; +- case VSIR_DATA_I16: +- return VKD3D_SHADER_COMPONENT_INT16; +- case VSIR_DATA_I32: +- return VKD3D_SHADER_COMPONENT_INT; +- case VSIR_DATA_I64: +- return VKD3D_SHADER_COMPONENT_INT64; +- case VSIR_DATA_U16: +- return VKD3D_SHADER_COMPONENT_UINT16; +- case VSIR_DATA_U32: +- return VKD3D_SHADER_COMPONENT_UINT; +- case VSIR_DATA_U64: +- return VKD3D_SHADER_COMPONENT_UINT64; +- case VSIR_DATA_UNUSED: +- return VKD3D_SHADER_COMPONENT_VOID; +- default: +- FIXME("Unhandled data type %#x.\n", data_type); +- /* fall-through */ +- case VSIR_DATA_MIXED: +- return VKD3D_SHADER_COMPONENT_UINT; +- } +-} +- + static inline enum vsir_data_type vsir_data_type_from_component_type(enum vkd3d_shader_component_type component_type) + { + switch (component_type) +@@ -1954,12 +1922,6 @@ static inline enum vsir_data_type vsir_data_type_from_component_type(enum vkd3d_ + return VSIR_DATA_UNUSED; + } + +-static inline bool component_type_is_64_bit(enum vkd3d_shader_component_type component_type) +-{ +- return component_type == VKD3D_SHADER_COMPONENT_DOUBLE || component_type == VKD3D_SHADER_COMPONENT_INT64 +- || component_type == VKD3D_SHADER_COMPONENT_UINT64; +-} +- + static inline unsigned int vsir_write_mask_get_component_idx(uint32_t write_mask) + { + unsigned int i; +-- +2.51.0 + diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-c48141457203d4cdfcd8315c0735748ba3b.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-c48141457203d4cdfcd8315c0735748ba3b.patch deleted file mode 100644 index 7f7bd903..00000000 --- a/patches/vkd3d-latest/0003-Updated-vkd3d-to-c48141457203d4cdfcd8315c0735748ba3b.patch +++ /dev/null @@ -1,1009 +0,0 @@ -From 49e8d491e80fcff8c686524e746d956770bec0aa Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Thu, 18 Sep 2025 06:55:52 +1000 -Subject: [PATCH] Updated vkd3d to c48141457203d4cdfcd8315c0735748ba3b9fda2. - ---- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 16 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 3 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 280 ++++++++++++------ - libs/vkd3d/libs/vkd3d-shader/spirv.c | 13 +- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 2 +- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 1 - - .../libs/vkd3d-shader/vkd3d_shader_private.h | 45 ++- - libs/vkd3d/libs/vkd3d/command.c | 90 +++--- - libs/vkd3d/libs/vkd3d/device.c | 24 +- - libs/vkd3d/libs/vkd3d/vkd3d_private.h | 5 +- - 10 files changed, 296 insertions(+), 183 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 44d2b8b1142..63dcbd3c08a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -919,6 +919,7 @@ struct sm6_parser - struct vkd3d_shader_dst_param *input_params; - struct vkd3d_shader_dst_param *patch_constant_params; - uint32_t io_regs_declared[VKD3D_BITMAP_SIZE(VKD3DSPR_COUNT)]; -+ struct vkd3d_shader_src_param *outpointid_param; - - struct sm6_function *functions; - size_t function_count; -@@ -3246,7 +3247,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - "Out of memory allocating an immediate constant buffer of count %u.", count); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -- if (!shader_instruction_array_add_icb(&sm6->program->instructions, icb)) -+ if (!vsir_program_add_icb(sm6->program, icb)) - { - ERR("Failed to store icb object.\n"); - vkd3d_free(icb); -@@ -4217,7 +4218,10 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade - if (is_control_point) - { - if (reg_type == VKD3DSPR_OUTPUT) -- param->reg.idx[count].rel_addr = vsir_program_create_outpointid_param(sm6->program); -+ { -+ VKD3D_ASSERT(sm6->outpointid_param); -+ param->reg.idx[count].rel_addr = sm6->outpointid_param; -+ } - param->reg.idx[count++].offset = 0; - } - -@@ -10007,6 +10011,14 @@ static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, cons - &program->patch_constant_signature, tessellator_domain, false)) < 0) - return ret; - -+ if (sm6->program->shader_version.type == VKD3D_SHADER_TYPE_HULL -+ && !(sm6->outpointid_param = vsir_program_create_outpointid_param(sm6->program))) -+ { -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ "Failed to allocate outpointid parameter."); -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ } -+ - if ((ret = sm6_parser_init_input_signature(sm6, &program->input_signature)) < 0) - return ret; - -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index d8eb18e39c7..5a25efdee75 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -3788,8 +3788,9 @@ static void dump_ir_expr(struct vkd3d_string_buffer *buffer, const struct hlsl_i - vkd3d_string_buffer_printf(buffer, "%s (", debug_hlsl_expr_op(expr->op)); - for (i = 0; i < HLSL_MAX_OPERANDS && expr->operands[i].node; ++i) - { -+ if (i) -+ vkd3d_string_buffer_printf(buffer, " "); - dump_src(buffer, &expr->operands[i]); -- vkd3d_string_buffer_printf(buffer, " "); - } - vkd3d_string_buffer_printf(buffer, ")"); - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index eb50aecf8ae..506b397fb02 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -502,22 +502,21 @@ bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *a - return true; - } - --bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *array, -- struct vkd3d_shader_immediate_constant_buffer *icb) -+bool vsir_program_add_icb(struct vsir_program *program, struct vkd3d_shader_immediate_constant_buffer *icb) - { -- if (!vkd3d_array_reserve((void **)&array->icbs, &array->icb_capacity, array->icb_count + 1, sizeof(*array->icbs))) -+ if (!vkd3d_array_reserve((void **)&program->icbs, &program->icb_capacity, -+ program->icb_count + 1, sizeof(*program->icbs))) - return false; - -- array->icbs[array->icb_count++] = icb; -+ program->icbs[program->icb_count++] = icb; - - return true; - } - --static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( -- struct vkd3d_shader_instruction_array *array, const struct vkd3d_shader_src_param *params, size_t count); -+static struct vkd3d_shader_src_param *vsir_program_clone_src_params( -+ struct vsir_program *program, const struct vkd3d_shader_src_param *params, size_t count); - --static bool shader_register_clone_relative_addresses(struct vkd3d_shader_register *reg, -- struct vkd3d_shader_instruction_array *array) -+static bool shader_register_clone_relative_addresses(struct vkd3d_shader_register *reg, struct vsir_program *program) - { - size_t i; - -@@ -526,45 +525,45 @@ static bool shader_register_clone_relative_addresses(struct vkd3d_shader_registe - if (!reg->idx[i].rel_addr) - continue; - -- if (!(reg->idx[i].rel_addr = shader_instruction_array_clone_src_params(array, reg->idx[i].rel_addr, 1))) -+ if (!(reg->idx[i].rel_addr = vsir_program_clone_src_params(program, reg->idx[i].rel_addr, 1))) - return false; - } - - return true; - } - --static struct vkd3d_shader_dst_param *shader_instruction_array_clone_dst_params( -- struct vkd3d_shader_instruction_array *array, const struct vkd3d_shader_dst_param *params, size_t count) -+static struct vkd3d_shader_dst_param *vsir_program_clone_dst_params( -+ struct vsir_program *program, const struct vkd3d_shader_dst_param *params, size_t count) - { - struct vkd3d_shader_dst_param *dst_params; - size_t i; - -- if (!(dst_params = shader_dst_param_allocator_get(&array->dst_params, count))) -+ if (!(dst_params = vsir_program_get_dst_params(program, count))) - return NULL; - - memcpy(dst_params, params, count * sizeof(*params)); - for (i = 0; i < count; ++i) - { -- if (!shader_register_clone_relative_addresses(&dst_params[i].reg, array)) -+ if (!shader_register_clone_relative_addresses(&dst_params[i].reg, program)) - return NULL; - } - - return dst_params; - } - --static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( -- struct vkd3d_shader_instruction_array *array, const struct vkd3d_shader_src_param *params, size_t count) -+static struct vkd3d_shader_src_param *vsir_program_clone_src_params( -+ struct vsir_program *program, const struct vkd3d_shader_src_param *params, size_t count) - { - struct vkd3d_shader_src_param *src_params; - size_t i; - -- if (!(src_params = shader_src_param_allocator_get(&array->src_params, count))) -+ if (!(src_params = vsir_program_get_src_params(program, count))) - return NULL; - - memcpy(src_params, params, count * sizeof(*params)); - for (i = 0; i < count; ++i) - { -- if (!shader_register_clone_relative_addresses(&src_params[i].reg, array)) -+ if (!shader_register_clone_relative_addresses(&src_params[i].reg, program)) - return NULL; - } - -@@ -573,25 +572,12 @@ static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( - - static void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *array) - { -- unsigned int i; -- - vkd3d_free(array->elements); -- shader_param_allocator_destroy(&array->dst_params); -- shader_param_allocator_destroy(&array->src_params); -- for (i = 0; i < array->icb_count; ++i) -- { -- vkd3d_free(array->icbs[i]); -- } -- vkd3d_free(array->icbs); - } - - static bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *array, size_t reserve) - { - memset(array, 0, sizeof(*array)); -- /* Size the parameter initial allocations so they are large enough for most shaders. The -- * code path for chained allocations will be tested if a few shaders need to use it. */ -- shader_param_allocator_init(&array->dst_params, reserve - reserve / 8u, sizeof(struct vkd3d_shader_dst_param)); -- shader_param_allocator_init(&array->src_params, reserve * 2u, sizeof(struct vkd3d_shader_src_param)); - - return shader_instruction_array_reserve(array, reserve); - } -@@ -667,6 +653,11 @@ bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_c - program->shader_version = *version; - program->cf_type = cf_type; - program->normalisation_level = normalisation_level; -+ -+ /* Size the parameter initial allocations so they are large enough for most shaders. The -+ * code path for chained allocations will be tested if a few shaders need to use it. */ -+ shader_param_allocator_init(&program->dst_params, reserve - reserve / 8u, sizeof(struct vkd3d_shader_dst_param)); -+ shader_param_allocator_init(&program->src_params, reserve * 2u, sizeof(struct vkd3d_shader_src_param)); - if (!shader_instruction_array_init(&program->instructions, reserve)) - { - if (program->free_parameters) -@@ -694,6 +685,13 @@ void vsir_program_cleanup(struct vsir_program *program) - shader_signature_cleanup(&program->output_signature); - shader_signature_cleanup(&program->patch_constant_signature); - vkd3d_shader_free_scan_descriptor_info1(&program->descriptors); -+ shader_param_allocator_destroy(&program->src_params); -+ shader_param_allocator_destroy(&program->dst_params); -+ for (i = 0; i < program->icb_count; ++i) -+ { -+ vkd3d_free(program->icbs[i]); -+ } -+ vkd3d_free(program->icbs); - } - - const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( -@@ -1089,19 +1087,17 @@ static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *i - - /* NOTE: Immediate constant buffers are not cloned, so the source must not be destroyed while the - * destination is in use. This seems like a reasonable requirement given how this is currently used. */ --static bool vsir_program_iterator_clone_instruction(struct vsir_program_iterator *dst_it, -- const struct vkd3d_shader_instruction *src) -+static bool vsir_program_iterator_clone_instruction(struct vsir_program *program, -+ struct vsir_program_iterator *dst_it, const struct vkd3d_shader_instruction *src) - { - struct vkd3d_shader_instruction *dst = vsir_program_iterator_current(dst_it); - - *dst = *src; - -- if (dst->dst_count && !(dst->dst = shader_instruction_array_clone_dst_params(dst_it->array, -- dst->dst, dst->dst_count))) -+ if (dst->dst_count && !(dst->dst = vsir_program_clone_dst_params(program, dst->dst, dst->dst_count))) - return false; - -- return !dst->src_count || !!(dst->src = shader_instruction_array_clone_src_params(dst_it->array, -- dst->src, dst->src_count)); -+ return !dst->src_count || (dst->src = vsir_program_clone_src_params(program, dst->src, dst->src_count)); - } - - static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, -@@ -1662,7 +1658,7 @@ static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *progr - return VKD3D_ERROR_NOT_IMPLEMENTED; - } - -- if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 3))) -+ if (!(srcs = vsir_program_get_src_params(program, 3))) - return VKD3D_ERROR_OUT_OF_MEMORY; - - /* Note we run before I/O normalization. */ -@@ -1738,7 +1734,7 @@ static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program, - VKD3D_ASSERT(tex->src[1].reg.idx_count == 1); - VKD3D_ASSERT(!tex->src[1].reg.idx[0].rel_addr); - -- if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 4))) -+ if (!(srcs = vsir_program_get_src_params(program, 4))) - return VKD3D_ERROR_OUT_OF_MEMORY; - - srcs[0] = tex->src[0]; -@@ -1781,7 +1777,7 @@ static enum vkd3d_result vsir_program_lower_texldd(struct vsir_program *program, - VKD3D_ASSERT(texldd->src[1].reg.idx_count == 1); - VKD3D_ASSERT(!texldd->src[1].reg.idx[0].rel_addr); - -- if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 5))) -+ if (!(srcs = vsir_program_get_src_params(program, 5))) - return VKD3D_ERROR_OUT_OF_MEMORY; - - srcs[0] = texldd->src[0]; -@@ -1807,7 +1803,7 @@ static enum vkd3d_result vsir_program_lower_texldl(struct vsir_program *program, - VKD3D_ASSERT(texldl->src[1].reg.idx_count == 1); - VKD3D_ASSERT(!texldl->src[1].reg.idx[0].rel_addr); - -- if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 4))) -+ if (!(srcs = vsir_program_get_src_params(program, 4))) - return VKD3D_ERROR_OUT_OF_MEMORY; - - srcs[0] = texldl->src[0]; -@@ -1825,6 +1821,64 @@ static enum vkd3d_result vsir_program_lower_texldl(struct vsir_program *program, - return VKD3D_OK; - } - -+static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, struct vkd3d_shader_instruction *ins) -+{ -+ unsigned int idx = ins->dst[0].reg.idx[0].offset; -+ struct vkd3d_shader_src_param *srcs; -+ -+ /* tex t# -> sample t#, t#, resource#, sampler# -+ * Note that the t# destination will subsequently be turned into a temp. */ -+ -+ /* We run before I/O normalization. */ -+ VKD3D_ASSERT(program->normalisation_level < VSIR_NORMALISED_SM6); -+ -+ if (!(srcs = vsir_program_get_src_params(program, 3))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ vsir_src_param_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); -+ srcs[0].reg.idx[0].offset = idx; -+ srcs[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ srcs[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; -+ -+ vsir_src_param_init_resource(&srcs[1], idx, idx); -+ vsir_src_param_init_sampler(&srcs[2], idx, idx); -+ -+ ins->opcode = VSIR_OP_SAMPLE; -+ ins->src = srcs; -+ ins->src_count = 3; -+ -+ return VKD3D_OK; -+} -+ -+static enum vkd3d_result vsir_program_lower_texcoord(struct vsir_program *program, -+ struct vkd3d_shader_instruction *ins) -+{ -+ unsigned int idx = ins->dst[0].reg.idx[0].offset; -+ struct vkd3d_shader_src_param *srcs; -+ -+ /* texcoord t# -> mov_sat t#, t# -+ * Note that the t# destination will subsequently be turned into a temp. */ -+ -+ /* We run before I/O normalization. */ -+ VKD3D_ASSERT(program->normalisation_level < VSIR_NORMALISED_SM6); -+ -+ if (!(srcs = vsir_program_get_src_params(program, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ vsir_src_param_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); -+ srcs[0].reg.idx[0].offset = idx; -+ srcs[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ srcs[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; -+ -+ ins->dst[0].modifiers |= VKD3DSPDM_SATURATE; -+ -+ ins->opcode = VSIR_OP_MOV; -+ ins->src = srcs; -+ ins->src_count = 1; -+ -+ return VKD3D_OK; -+} -+ - static enum vkd3d_result vsir_program_lower_dcl_input(struct vsir_program *program, - struct vkd3d_shader_instruction *ins, struct vsir_transformation_context *ctx) - { -@@ -1917,6 +1971,11 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr - ret = vsir_program_lower_sm1_sincos(program, &it); - break; - -+ case VSIR_OP_TEXCOORD: -+ if ((ret = vsir_program_lower_texcoord(program, ins)) < 0) -+ return ret; -+ break; -+ - case VSIR_OP_TEXCRD: - ret = vsir_program_lower_texcrd(program, ins, message_context); - break; -@@ -1925,6 +1984,10 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr - ret = vsir_program_lower_texkill(program, &it, &tmp_idx); - break; - -+ case VSIR_OP_TEX: -+ ret = vsir_program_lower_tex(program, ins); -+ break; -+ - case VSIR_OP_TEXLD: - if (program->shader_version.major == 1) - ret = vsir_program_lower_texld_sm1(program, ins, message_context); -@@ -1942,6 +2005,26 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr - ret = vsir_program_lower_texldl(program, ins); - break; - -+ case VSIR_OP_TEXBEM: -+ case VSIR_OP_TEXBEML: -+ case VSIR_OP_TEXDEPTH: -+ case VSIR_OP_TEXDP3: -+ case VSIR_OP_TEXDP3TEX: -+ case VSIR_OP_TEXM3x2PAD: -+ case VSIR_OP_TEXM3x2TEX: -+ case VSIR_OP_TEXM3x3DIFF: -+ case VSIR_OP_TEXM3x3PAD: -+ case VSIR_OP_TEXM3x3SPEC: -+ case VSIR_OP_TEXM3x3TEX: -+ case VSIR_OP_TEXM3x3VSPEC: -+ case VSIR_OP_TEXREG2AR: -+ case VSIR_OP_TEXREG2GB: -+ case VSIR_OP_TEXREG2RGB: -+ vkd3d_shader_error(ctx->message_context, &ins->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, -+ "Aborting due to unimplemented feature: Combined sampler instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(ins->opcode, ""), ins->opcode); -+ return VKD3D_ERROR_NOT_IMPLEMENTED; -+ - default: - ret = VKD3D_OK; - break; -@@ -2020,27 +2103,6 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr - return ret; - break; - -- case VSIR_OP_TEXBEM: -- case VSIR_OP_TEXBEML: -- case VSIR_OP_TEXCOORD: -- case VSIR_OP_TEXDEPTH: -- case VSIR_OP_TEXDP3: -- case VSIR_OP_TEXDP3TEX: -- case VSIR_OP_TEXM3x2PAD: -- case VSIR_OP_TEXM3x2TEX: -- case VSIR_OP_TEXM3x3DIFF: -- case VSIR_OP_TEXM3x3PAD: -- case VSIR_OP_TEXM3x3SPEC: -- case VSIR_OP_TEXM3x3TEX: -- case VSIR_OP_TEXM3x3VSPEC: -- case VSIR_OP_TEXREG2AR: -- case VSIR_OP_TEXREG2GB: -- case VSIR_OP_TEXREG2RGB: -- vkd3d_shader_error(ctx->message_context, &ins->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, -- "Aborting due to unimplemented feature: Combined sampler instruction \"%s\" (%#x).", -- vsir_opcode_get_name(ins->opcode, ""), ins->opcode); -- return VKD3D_ERROR_NOT_IMPLEMENTED; -- - default: - break; - } -@@ -2049,6 +2111,61 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr - return VKD3D_OK; - } - -+/* 1.0-1.3 pixel shaders allow writing t# registers, at which point they -+ * effectively behave like normal r# temps. Convert them to r# registers. -+ * t# registers which are read before being written contain TEXCOORD varyings, -+ * just as in 1.4 and 2.x, and will later be lowered to v# registers. -+ * -+ * Registers which are partially written are rejected by the native validator, -+ * but with a "read of uninitialized component" message that suggests that once -+ * any component of a t# register is written, none of the components contain -+ * texcoord data. */ -+static enum vkd3d_result vsir_program_lower_texture_writes(struct vsir_program *program, -+ struct vsir_transformation_context *ctx) -+{ -+ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); -+ struct vkd3d_shader_instruction *ins; -+ unsigned int texture_temp_idx = ~0u; -+ uint32_t texture_written_mask = 0; -+ -+ /* We run before I/O normalization. */ -+ VKD3D_ASSERT(program->normalisation_level < VSIR_NORMALISED_SM6); -+ -+ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) -+ { -+ for (unsigned int i = 0; i < ins->src_count; ++i) -+ { -+ struct vkd3d_shader_src_param *src = &ins->src[i]; -+ -+ if (src->reg.type == VKD3DSPR_TEXTURE && bitmap_is_set(&texture_written_mask, src->reg.idx[0].offset)) -+ { -+ src->reg.type = VKD3DSPR_TEMP; -+ src->reg.idx[0].offset += texture_temp_idx; -+ } -+ } -+ -+ for (unsigned int i = 0; i < ins->dst_count; ++i) -+ { -+ struct vkd3d_shader_dst_param *dst = &ins->dst[i]; -+ -+ if (dst->reg.type == VKD3DSPR_TEXTURE) -+ { -+ bitmap_set(&texture_written_mask, dst->reg.idx[0].offset); -+ if (texture_temp_idx == ~0u) -+ { -+ texture_temp_idx = program->temp_count; -+ /* These versions have 4 texture registers. */ -+ program->temp_count += 4; -+ } -+ dst->reg.type = VKD3DSPR_TEMP; -+ dst->reg.idx[0].offset += texture_temp_idx; -+ } -+ } -+ } -+ -+ return VKD3D_OK; -+} -+ - /* Ensure that the program closes with a ret. sm1 programs do not, by default. - * Many of our IR passes rely on this in order to insert instructions at the - * end of execution. */ -@@ -2512,7 +2629,7 @@ static enum vkd3d_result flattener_replicate_location(struct hull_flattener *nor - struct vsir_program_iterator *it, size_t instance_count, size_t instruction_count) - { - struct vsir_program_iterator dst_it, src_it, first_it; -- struct vkd3d_shader_instruction *ins; -+ struct vkd3d_shader_instruction *ins, *src_ins; - unsigned int i, j; - size_t count; - -@@ -2528,7 +2645,8 @@ static enum vkd3d_result flattener_replicate_location(struct hull_flattener *nor - src_it = *it; - for (j = 0; j < instruction_count; ++j) - { -- if (!vsir_program_iterator_clone_instruction(&dst_it, vsir_program_iterator_current(&src_it))) -+ src_ins = vsir_program_iterator_current(&src_it); -+ if (!vsir_program_iterator_clone_instruction(normaliser->program, &dst_it, src_ins)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - vsir_program_iterator_next(&dst_it); -@@ -2650,7 +2768,7 @@ static enum vkd3d_result vsir_program_flatten_hull_shader_phases(struct vsir_pro - - struct control_point_normaliser - { -- struct vkd3d_shader_instruction_array instructions; -+ struct vsir_program *program; - enum vkd3d_shader_opcode phase; - struct vkd3d_shader_src_param *outpointid_param; - }; -@@ -2662,20 +2780,15 @@ static bool control_point_normaliser_is_in_control_point_phase(const struct cont - - struct vkd3d_shader_src_param *vsir_program_create_outpointid_param(struct vsir_program *program) - { -- struct vkd3d_shader_instruction_array *instructions = &program->instructions; - struct vkd3d_shader_src_param *rel_addr; - -- if (instructions->outpointid_param) -- return instructions->outpointid_param; -- -- if (!(rel_addr = shader_src_param_allocator_get(&instructions->src_params, 1))) -+ if (!(rel_addr = vsir_program_get_src_params(program, 1))) - return NULL; - - vsir_register_init(&rel_addr->reg, VKD3DSPR_OUTPOINTID, VSIR_DATA_U32, 0); - rel_addr->swizzle = 0; - rel_addr->modifiers = 0; - -- instructions->outpointid_param = rel_addr; - return rel_addr; - } - -@@ -2720,9 +2833,9 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p - continue; - - vsir_instruction_init(ins, location, VSIR_OP_MOV); -- ins->dst = shader_dst_param_allocator_get(&normaliser->instructions.dst_params, 1); -+ ins->dst = vsir_program_get_dst_params(normaliser->program, 1); - ins->dst_count = 1; -- ins->src = shader_src_param_allocator_get(&normaliser->instructions.src_params, 1); -+ ins->src = vsir_program_get_src_params(normaliser->program, 1); - ins->src_count = 1; - - if (!ins->dst || ! ins->src) -@@ -2731,6 +2844,8 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p - return VKD3D_ERROR_OUT_OF_MEMORY; - } - -+ VKD3D_ASSERT(normaliser->outpointid_param); -+ - vsir_dst_param_init_io(&ins->dst[0], VKD3DSPR_OUTPUT, e, 2); - ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; - ins->dst[0].reg.idx[0].offset = 0; -@@ -2775,8 +2890,8 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i - ERR("Failed to allocate src param.\n"); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -- normaliser.instructions = program->instructions; -- it = vsir_program_iterator(&normaliser.instructions); -+ normaliser.program = program; -+ it = vsir_program_iterator(&normaliser.program->instructions); - normaliser.phase = VSIR_OP_INVALID; - - for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) -@@ -2808,7 +2923,6 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i - input_control_point_count = ins->declaration.count; - break; - case VSIR_OP_HS_CONTROL_POINT_PHASE: -- program->instructions = normaliser.instructions; - program->normalisation_level = VSIR_NORMALISED_HULL_CONTROL_POINT_IO; - return VKD3D_OK; - case VSIR_OP_HS_FORK_PHASE: -@@ -2817,7 +2931,6 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i - location = ins->location; - ret = control_point_normaliser_emit_hs_input(&normaliser, - &program->input_signature, input_control_point_count, &it, &location); -- program->instructions = normaliser.instructions; - program->normalisation_level = VSIR_NORMALISED_HULL_CONTROL_POINT_IO; - return ret; - default: -@@ -2825,7 +2938,6 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i - } - } - -- program->instructions = normaliser.instructions; - program->normalisation_level = VSIR_NORMALISED_HULL_CONTROL_POINT_IO; - return VKD3D_OK; - } -@@ -2851,12 +2963,7 @@ struct io_normaliser - struct shader_signature *output_signature; - struct shader_signature *patch_constant_signature; - -- unsigned int instance_count; -- unsigned int phase_body_idx; - enum vkd3d_shader_opcode phase; -- unsigned int output_control_point_count; -- -- struct vkd3d_shader_src_param *outpointid_param; - - struct vkd3d_shader_dst_param *input_dcl_params[MAX_REG_OUTPUT]; - struct vkd3d_shader_dst_param *output_dcl_params[MAX_REG_OUTPUT]; -@@ -3478,9 +3585,6 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program - { - switch (ins->opcode) - { -- case VSIR_OP_DCL_OUTPUT_CONTROL_POINT_COUNT: -- normaliser.output_control_point_count = ins->declaration.count; -- break; - case VSIR_OP_DCL_INDEX_RANGE: - if ((ret = io_normaliser_add_index_range(&normaliser, ins)) < 0) - return ret; -@@ -12569,8 +12673,14 @@ enum vkd3d_result vsir_program_lower_d3dbc(struct vsir_program *program, uint64_ - - vsir_transformation_context_init(&ctx, program, config_flags, compile_info, message_context); - vsir_transform(&ctx, vsir_program_lower_d3dbc_instructions); -+ - if (program->shader_version.major == 1 && program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL) -+ { -+ if (program->shader_version.minor < 4) -+ vsir_transform(&ctx, vsir_program_lower_texture_writes); -+ - vsir_transform(&ctx, vsir_program_normalise_ps1_output); -+ } - - if (TRACE_ON()) - vsir_program_trace(program); -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 8bc851f9c5b..8ffc68935f3 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -7166,7 +7166,7 @@ static void spirv_compiler_emit_workgroup_memory(struct spirv_compiler *compiler - if (alignment) - TRACE("Ignoring alignment %u.\n", alignment); - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); - length_id = spirv_compiler_get_constant_uint(compiler, size); - array_type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); - -@@ -7887,8 +7887,7 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp - component_count = vsir_write_mask_component_count(dst->write_mask); - uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT32_MAX, component_count); - condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpIEqual, -- spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count), -- val_id, uint_max_id); -+ spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count), val_id, uint_max_id); - rev_val_id = vkd3d_spirv_build_op_isub(builder, type_id, - spirv_compiler_get_constant_uint_vector(compiler, 31, component_count), val_id); - val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, val_id, rev_val_id); -@@ -7993,8 +7992,8 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, - { - if (instruction->opcode == VSIR_OP_CMP) - condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpFOrdGreaterThanEqual, -- spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count), -- condition_id, spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count)); -+ spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count), condition_id, -+ spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count)); - else - condition_id = spirv_compiler_emit_int_to_bool(compiler, - VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); -@@ -8020,7 +8019,7 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler, - src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask); - - component_count = vsir_write_mask_component_count(dst->write_mask); -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, component_count); - - condition_id = spirv_compiler_emit_int_to_bool(compiler, - VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); -@@ -8056,7 +8055,7 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, - for (i = 0; i < ARRAY_SIZE(src_ids); ++i) - src_ids[i] = spirv_compiler_emit_load_src(compiler, &src[i], write_mask); - -- type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); -+ type_id = spirv_get_type_id(builder, dst->reg.data_type, 1); - - val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, - SpvOpDot, type_id, src_ids[0], src_ids[1]); -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index ec1d8b91e09..2541aef1314 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -851,7 +851,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui - 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->program->instructions, icb); -+ vsir_program_add_icb(priv->program, icb); - ins->declaration.icb = icb; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index 6949c1cd38f..f536a8ee08f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -1524,7 +1524,6 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte - if (context->cf_info_count) - context->cf_info[context->cf_info_count - 1].inside_block = false; - break; -- case VSIR_OP_TEX: - case VSIR_OP_TEXBEM: - case VSIR_OP_TEXBEML: - case VSIR_OP_TEXDP3TEX: -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 3f37dc6076b..6037f7179e7 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -1421,40 +1421,16 @@ struct vkd3d_shader_param_allocator - - void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, size_t count); - --static inline struct vkd3d_shader_src_param *shader_src_param_allocator_get( -- struct vkd3d_shader_param_allocator *allocator, size_t count) --{ -- VKD3D_ASSERT(allocator->stride == sizeof(struct vkd3d_shader_src_param)); -- return shader_param_allocator_get(allocator, count); --} -- --static inline struct vkd3d_shader_dst_param *shader_dst_param_allocator_get( -- struct vkd3d_shader_param_allocator *allocator, size_t count) --{ -- VKD3D_ASSERT(allocator->stride == sizeof(struct vkd3d_shader_dst_param)); -- return shader_param_allocator_get(allocator, count); --} -- - struct vkd3d_shader_instruction_array - { - struct vkd3d_shader_instruction *elements; - size_t capacity; - size_t count; -- -- struct vkd3d_shader_param_allocator src_params; -- struct vkd3d_shader_param_allocator dst_params; -- struct vkd3d_shader_immediate_constant_buffer **icbs; -- size_t icb_capacity; -- size_t icb_count; -- -- struct vkd3d_shader_src_param *outpointid_param; - }; - - bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, size_t reserve); - bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, - size_t idx, size_t count); --bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, -- struct vkd3d_shader_immediate_constant_buffer *icb); - - struct vsir_program_iterator - { -@@ -1638,12 +1614,21 @@ struct vsir_program - struct vkd3d_shader_source_list source_files; - const char **block_names; - size_t block_name_count; -+ -+ struct vkd3d_shader_immediate_constant_buffer **icbs; -+ size_t icb_capacity; -+ size_t icb_count; -+ -+ struct vkd3d_shader_param_allocator src_params; -+ struct vkd3d_shader_param_allocator dst_params; - }; - - enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, - struct vkd3d_shader_message_context *message_context); - enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, - struct vkd3d_shader_message_context *message_context); -+ -+bool vsir_program_add_icb(struct vsir_program *program, struct vkd3d_shader_immediate_constant_buffer *icb); - void vsir_program_cleanup(struct vsir_program *program); - const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( - const struct vsir_program *program, enum vkd3d_shader_parameter_name name); -@@ -1677,13 +1662,21 @@ static inline struct vkd3d_shader_instruction *vsir_program_append(struct vsir_p - static inline struct vkd3d_shader_dst_param *vsir_program_get_dst_params( - struct vsir_program *program, unsigned int count) - { -- return shader_dst_param_allocator_get(&program->instructions.dst_params, count); -+ struct vkd3d_shader_param_allocator *allocator = &program->dst_params; -+ -+ VKD3D_ASSERT(allocator->stride == sizeof(struct vkd3d_shader_dst_param)); -+ -+ return shader_param_allocator_get(allocator, count); - } - - static inline struct vkd3d_shader_src_param *vsir_program_get_src_params( - struct vsir_program *program, unsigned int count) - { -- return shader_src_param_allocator_get(&program->instructions.src_params, count); -+ struct vkd3d_shader_param_allocator *allocator = &program->src_params; -+ -+ VKD3D_ASSERT(allocator->stride == sizeof(struct vkd3d_shader_src_param)); -+ -+ return shader_param_allocator_get(allocator, count); - } - - struct vkd3d_shader_parser -diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c -index d933e7ec463..69f42280e8a 100644 ---- a/libs/vkd3d/libs/vkd3d/command.c -+++ b/libs/vkd3d/libs/vkd3d/command.c -@@ -2688,32 +2688,12 @@ static void d3d12_command_list_reset_state(struct d3d12_command_list *list, - static HRESULT STDMETHODCALLTYPE d3d12_command_list_Reset(ID3D12GraphicsCommandList6 *iface, - ID3D12CommandAllocator *allocator, ID3D12PipelineState *initial_pipeline_state) - { -- struct d3d12_command_allocator *allocator_impl = unsafe_impl_from_ID3D12CommandAllocator(allocator); - struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList6(iface); -- HRESULT hr; - - TRACE("iface %p, allocator %p, initial_pipeline_state %p.\n", - iface, allocator, initial_pipeline_state); - -- if (!allocator_impl) -- { -- WARN("Command allocator is NULL.\n"); -- return E_INVALIDARG; -- } -- -- if (list->is_recording) -- { -- WARN("Command list is in the recording state.\n"); -- return E_FAIL; -- } -- -- if (SUCCEEDED(hr = d3d12_command_allocator_allocate_command_buffer(allocator_impl, list))) -- { -- list->allocator = allocator_impl; -- d3d12_command_list_reset_state(list, initial_pipeline_state); -- } -- -- return hr; -+ return d3d12_command_list_reset(list, allocator, initial_pipeline_state); - } - - static void STDMETHODCALLTYPE d3d12_command_list_ClearState(ID3D12GraphicsCommandList6 *iface, -@@ -6405,9 +6385,8 @@ static struct d3d12_command_list *unsafe_impl_from_ID3D12CommandList(ID3D12Comma - return CONTAINING_RECORD(iface, struct d3d12_command_list, ID3D12GraphicsCommandList6_iface); - } - --static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, struct d3d12_device *device, -- D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_allocator *allocator, -- ID3D12PipelineState *initial_pipeline_state) -+static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, -+ struct d3d12_device *device, D3D12_COMMAND_LIST_TYPE type) - { - HRESULT hr; - -@@ -6421,31 +6400,37 @@ static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, struct d - - d3d12_device_add_ref(list->device = device); - -- list->allocator = allocator; -+ return hr; -+} - -- list->descriptor_heap_count = 0; -+HRESULT d3d12_command_list_create(struct d3d12_device *device, UINT node_mask, -+ D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_list **list) -+{ -+ struct d3d12_command_list *object; -+ HRESULT hr; - -- if (SUCCEEDED(hr = d3d12_command_allocator_allocate_command_buffer(allocator, list))) -- { -- list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_GRAPHICS].vk_uav_counter_views = NULL; -- list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_COMPUTE].vk_uav_counter_views = NULL; -- d3d12_command_list_reset_state(list, initial_pipeline_state); -- } -- else -+ debug_ignored_node_mask(node_mask); -+ -+ if (!(object = vkd3d_calloc(1, sizeof(*object)))) -+ return E_OUTOFMEMORY; -+ -+ if (FAILED(hr = d3d12_command_list_init(object, device, type))) - { -- vkd3d_private_store_destroy(&list->private_store); -- d3d12_device_release(device); -+ vkd3d_free(object); -+ return hr; - } - -- return hr; -+ TRACE("Created command list %p.\n", object); -+ -+ *list = object; -+ -+ return S_OK; - } - --HRESULT d3d12_command_list_create(struct d3d12_device *device, -- UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *allocator_iface, -- ID3D12PipelineState *initial_pipeline_state, struct d3d12_command_list **list) -+HRESULT d3d12_command_list_reset(struct d3d12_command_list *list, ID3D12CommandAllocator *allocator_iface, -+ ID3D12PipelineState *initial_pipeline_state) - { - struct d3d12_command_allocator *allocator; -- struct d3d12_command_list *object; - HRESULT hr; - - if (!(allocator = unsafe_impl_from_ID3D12CommandAllocator(allocator_iface))) -@@ -6454,29 +6439,26 @@ HRESULT d3d12_command_list_create(struct d3d12_device *device, - return E_INVALIDARG; - } - -- if (allocator->type != type) -+ if (allocator->type != list->type) - { - WARN("Command list types do not match (allocator %#x, list %#x).\n", -- allocator->type, type); -+ allocator->type, list->type); - return E_INVALIDARG; - } - -- debug_ignored_node_mask(node_mask); -- -- if (!(object = vkd3d_malloc(sizeof(*object)))) -- return E_OUTOFMEMORY; -- -- if (FAILED(hr = d3d12_command_list_init(object, device, type, allocator, initial_pipeline_state))) -+ if (list->is_recording) - { -- vkd3d_free(object); -- return hr; -+ WARN("Command list is in the recording state.\n"); -+ return E_FAIL; - } - -- TRACE("Created command list %p.\n", object); -- -- *list = object; -+ if (SUCCEEDED(hr = d3d12_command_allocator_allocate_command_buffer(allocator, list))) -+ { -+ list->allocator = allocator; -+ d3d12_command_list_reset_state(list, initial_pipeline_state); -+ } - -- return S_OK; -+ return hr; - } - - /* ID3D12CommandQueue */ -diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c -index 67f84aafa29..6af5e2a5c7d 100644 ---- a/libs/vkd3d/libs/vkd3d/device.c -+++ b/libs/vkd3d/libs/vkd3d/device.c -@@ -3271,10 +3271,15 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList(ID3D12Device9 *i - iface, node_mask, type, command_allocator, - initial_pipeline_state, debugstr_guid(riid), command_list); - -- if (FAILED(hr = d3d12_command_list_create(device, node_mask, type, command_allocator, -- initial_pipeline_state, &object))) -+ if (FAILED(hr = d3d12_command_list_create(device, node_mask, type, &object))) - return hr; - -+ if (FAILED(hr = d3d12_command_list_reset(object, command_allocator, initial_pipeline_state))) -+ { -+ ID3D12GraphicsCommandList6_Release(&object->ID3D12GraphicsCommandList6_iface); -+ return hr; -+ } -+ - return return_interface(&object->ID3D12GraphicsCommandList6_iface, - &IID_ID3D12GraphicsCommandList6, riid, command_list); - } -@@ -5082,10 +5087,21 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommandList1(ID3D12Device9 * - UINT node_mask, D3D12_COMMAND_LIST_TYPE type, D3D12_COMMAND_LIST_FLAGS flags, - REFIID iid, void **command_list) - { -- FIXME("iface %p, node_mask 0x%08x, type %#x, flags %#x, iid %s, command_list %p stub!\n", -+ struct d3d12_device *device = impl_from_ID3D12Device9(iface); -+ struct d3d12_command_list *object; -+ HRESULT hr; -+ -+ TRACE("iface %p, node_mask 0x%08x, type %#x, flags %#x, iid %s, command_list %p.\n", - iface, node_mask, type, flags, debugstr_guid(iid), command_list); - -- return E_NOTIMPL; -+ if (flags) -+ FIXME("Ignoring flags %#x.\n", flags); -+ -+ if (FAILED(hr = d3d12_command_list_create(device, node_mask, type, &object))) -+ return hr; -+ -+ return return_interface(&object->ID3D12GraphicsCommandList6_iface, -+ &IID_ID3D12GraphicsCommandList6, iid, command_list); - } - - static HRESULT STDMETHODCALLTYPE d3d12_device_CreateProtectedResourceSession(ID3D12Device9 *iface, -diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -index 9fb6834158f..0a8c5aef674 100644 ---- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h -+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -@@ -1327,8 +1327,9 @@ struct d3d12_command_list - }; - - HRESULT d3d12_command_list_create(struct d3d12_device *device, -- UINT node_mask, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator *allocator_iface, -- ID3D12PipelineState *initial_pipeline_state, struct d3d12_command_list **list); -+ UINT node_mask, D3D12_COMMAND_LIST_TYPE type, struct d3d12_command_list **list); -+HRESULT d3d12_command_list_reset(struct d3d12_command_list *list, -+ ID3D12CommandAllocator *allocator_iface, ID3D12PipelineState *initial_pipeline_state); - - struct vkd3d_queue - { --- -2.51.0 - diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-40bdaa43af3414d25e43b477bf813b81827.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-40bdaa43af3414d25e43b477bf813b81827.patch new file mode 100644 index 00000000..313f4225 --- /dev/null +++ b/patches/vkd3d-latest/0004-Updated-vkd3d-to-40bdaa43af3414d25e43b477bf813b81827.patch @@ -0,0 +1,330 @@ +From 9f47509c12b50d2d39f192dfc66b8a711ca70b27 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Wed, 15 Oct 2025 07:43:18 +1100 +Subject: [PATCH] Updated vkd3d to 40bdaa43af3414d25e43b477bf813b81827633b3. + +--- + libs/vkd3d/Makefile.in | 4 +- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 9 ++--- + libs/vkd3d/libs/vkd3d-shader/glsl.c | 18 +++++++++ + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 4 -- + libs/vkd3d/libs/vkd3d-shader/ir.c | 40 ++++++++++++++++++- + libs/vkd3d/libs/vkd3d-shader/msl.c | 11 +++++ + libs/vkd3d/libs/vkd3d-shader/spirv.c | 16 ++++++++ + .../libs/vkd3d-shader/vkd3d_shader_private.h | 7 ++-- + libs/vkd3d/libs/vkd3d/state.c | 2 +- + 9 files changed, 95 insertions(+), 16 deletions(-) + +diff --git a/libs/vkd3d/Makefile.in b/libs/vkd3d/Makefile.in +index 9ad9ed850b6..868f4582380 100644 +--- a/libs/vkd3d/Makefile.in ++++ b/libs/vkd3d/Makefile.in +@@ -7,7 +7,6 @@ EXTRADEFS = \ + -DLIBVKD3D_UTILS_SOURCE + + SOURCES = \ +- config.h \ + libs/vkd3d-common/blob.c \ + libs/vkd3d-common/debug.c \ + libs/vkd3d-common/error.c \ +@@ -40,4 +39,5 @@ SOURCES = \ + libs/vkd3d/resource.c \ + libs/vkd3d/state.c \ + libs/vkd3d/utils.c \ +- libs/vkd3d/vkd3d_main.c ++ libs/vkd3d/vkd3d_main.c \ ++ config.h +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index c7af58118df..7861efc16d2 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -4674,13 +4674,13 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco + case VSIR_OP_ISHL: + silence_warning = !(flags & ~(OB_NO_UNSIGNED_WRAP | OB_NO_SIGNED_WRAP)); + break; ++ case VSIR_OP_IDIV: ++ case VSIR_OP_IREM: + case VSIR_OP_ISHR: + type_flags |= DXIL_TYPE_SIGNED; + /* fall through */ + case VSIR_OP_USHR: +- case VSIR_OP_IDIV: + case VSIR_OP_UDIV_SIMPLE: +- case VSIR_OP_IREM: + case VSIR_OP_UREM: + silence_warning = !(flags & ~PEB_EXACT); + break; +@@ -6252,13 +6252,12 @@ static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsi + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_param; + +- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); ++ vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_SATURATE); + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; + src_param_init_from_value(src_param, operands[0], 0, sm6); + +- if (instruction_dst_param_init_ssa_scalar(ins, 0, sm6)) +- ins->dst->modifiers = VKD3DSPDM_SATURATE; ++ instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + + static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c +index 88c87ae33ee..91a96a5547e 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c +@@ -605,6 +605,21 @@ static void shader_glsl_dot(struct vkd3d_glsl_generator *gen, + glsl_dst_cleanup(&dst, &gen->string_buffers); + } + ++static void shader_glsl_saturate(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ struct glsl_src src; ++ struct glsl_dst dst; ++ uint32_t mask; ++ ++ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); ++ glsl_src_init(&src, gen, &ins->src[0], mask); ++ ++ shader_glsl_print_assignment(gen, &dst, "clamp(%s, 0.0, 1.0)", src.str->buffer); ++ ++ glsl_src_cleanup(&src, &gen->string_buffers); ++ glsl_dst_cleanup(&dst, &gen->string_buffers); ++} ++ + static void shader_glsl_intrinsic(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_instruction *ins, const char *op) + { +@@ -1654,6 +1669,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + case VSIR_OP_RSQ: + shader_glsl_intrinsic(gen, ins, "inversesqrt"); + break; ++ case VSIR_OP_SATURATE: ++ shader_glsl_saturate(gen, ins); ++ break; + case VSIR_OP_SIN: + shader_glsl_intrinsic(gen, ins, "sin"); + break; +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index 27afac71320..759dadf8a58 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -614,10 +614,6 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx + if (!(ret.string = vkd3d_strdup(string->string))) + return ret; + } +- else if (node->type == HLSL_IR_STRING_CONSTANT) +- { +- hlsl_fixme(ctx, &node->loc, "Evaluate string constants as static expressions."); +- } + else + { + hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 13ea8a433a6..c013c9e61bd 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -338,6 +338,7 @@ const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) + [VSIR_OP_SAMPLE_LOD ] = "sample_l", + [VSIR_OP_SAMPLE_LOD_S ] = "sample_l_s", + [VSIR_OP_SAMPLE_POS ] = "sample_pos", ++ [VSIR_OP_SATURATE ] = "saturate", + [VSIR_OP_SETP ] = "setp", + [VSIR_OP_SGE ] = "sge", + [VSIR_OP_SGN ] = "sgn", +@@ -2235,6 +2236,39 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr + ++program->ssa_count; + } + } ++ ++ for (i = 0; i < ins->dst_count; ++i) ++ { ++ struct vkd3d_shader_dst_param *dst = &ins->dst[i]; ++ ++ if (dst->modifiers & VKD3DSPDM_SATURATE) ++ { ++ if (!vsir_program_iterator_insert_after(&it, 1)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ins = vsir_program_iterator_current(&it); ++ new_ins = vsir_program_iterator_next(&it); ++ ++ if (!vsir_instruction_init_with_params(program, new_ins, &ins->location, VSIR_OP_SATURATE, 1, 1)) ++ { ++ vkd3d_shader_instruction_make_nop(new_ins); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ } ++ ++ new_ins->dst[0] = *dst; ++ new_ins->dst[0].modifiers &= ~VKD3DSPDM_NONE; ++ ++ dst_param_init_ssa(dst, program->ssa_count, dst->reg.data_type, dst->reg.dimension); ++ src_param_init_ssa(&new_ins->src[0], program->ssa_count, dst->reg.data_type, dst->reg.dimension); ++ ++ if (data_type_is_64_bit(dst->reg.data_type)) ++ { ++ dst->write_mask = vsir_write_mask_64_from_32(dst->write_mask); ++ new_ins->src[0].swizzle = vsir_swizzle_64_from_32(new_ins->src[0].swizzle); ++ } ++ ++ ++program->ssa_count; ++ } ++ } + } + + return VKD3D_OK; +@@ -8795,6 +8829,7 @@ static bool vsir_src_is_masked(enum vkd3d_shader_opcode opcode, unsigned int src + case VSIR_OP_ROUND_PI: + case VSIR_OP_ROUND_Z: + case VSIR_OP_RSQ: ++ case VSIR_OP_SATURATE: + case VSIR_OP_SETP: + case VSIR_OP_SGE: + case VSIR_OP_SGN: +@@ -12833,6 +12868,7 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_HS_JOIN_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, + [VSIR_OP_HTAN] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_IADD] = {1, 2, vsir_validate_integer_elementwise_operation}, ++ [VSIR_OP_IDIV] = {1, 2, vsir_validate_signed_integer_elementwise_operation}, + [VSIR_OP_IEQ] = {1, 2, vsir_validate_integer_comparison_operation}, + [VSIR_OP_IF] = {0, 1, vsir_validate_if}, + [VSIR_OP_IFC] = {0, 2, vsir_validate_ifc}, +@@ -12843,7 +12879,7 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_IMIN] = {1, 2, vsir_validate_signed_integer_elementwise_operation}, + [VSIR_OP_INE] = {1, 2, vsir_validate_integer_comparison_operation}, + [VSIR_OP_INEG] = {1, 1, vsir_validate_integer_elementwise_operation}, +- [VSIR_OP_IREM] = {1, 2, vsir_validate_integer_elementwise_operation}, ++ [VSIR_OP_IREM] = {1, 2, vsir_validate_signed_integer_elementwise_operation}, + [VSIR_OP_ISFINITE] = {1, 1, vsir_validate_float_comparison_operation}, + [VSIR_OP_ISHL] = {1, 2, vsir_validate_ishl}, + [VSIR_OP_ISHR] = {1, 2, vsir_validate_ishr}, +@@ -12875,6 +12911,7 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_ROUND_NE] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_ROUND_NI] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_SAMPLE_INFO] = {1, 1, vsir_validate_sample_info}, ++ [VSIR_OP_SATURATE] = {1, 1, vsir_validate_float_or_double_elementwise_operation}, + [VSIR_OP_SWITCH] = {0, 1, vsir_validate_switch}, + [VSIR_OP_SWITCH_MONOLITHIC] = {0, ~0u, vsir_validate_switch_monolithic}, + [VSIR_OP_USHR] = {1, 2, vsir_validate_ushr}, +@@ -13315,6 +13352,7 @@ static bool vsir_instruction_has_side_effects(const struct vkd3d_shader_instruct + case VSIR_OP_SAMPLE_LOD: + case VSIR_OP_SAMPLE_LOD_S: + case VSIR_OP_SAMPLE_POS: ++ case VSIR_OP_SATURATE: + case VSIR_OP_SETP: + case VSIR_OP_SGE: + case VSIR_OP_SGN: +diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c +index fc136e3ac98..f2d28acbe38 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/msl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/msl.c +@@ -1578,9 +1578,17 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + case VSIR_OP_HTAN: + msl_intrinsic(gen, ins, "tanh"); + break; ++ case VSIR_OP_IDIV: ++ case VSIR_OP_UDIV_SIMPLE: ++ msl_binop(gen, ins, "/"); ++ break; + case VSIR_OP_IF: + msl_if(gen, ins); + break; ++ case VSIR_OP_IREM: ++ case VSIR_OP_UREM: ++ msl_binop(gen, ins, "%"); ++ break; + case VSIR_OP_ISHL: + msl_binop(gen, ins, "<<"); + break; +@@ -1663,6 +1671,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + case VSIR_OP_RSQ: + msl_intrinsic(gen, ins, "rsqrt"); + break; ++ case VSIR_OP_SATURATE: ++ msl_intrinsic(gen, ins, "saturate"); ++ break; + case VSIR_OP_SIN: + msl_intrinsic(gen, ins, "sin"); + break; +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index 31271660e4f..8ff46759fb6 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -2524,6 +2524,7 @@ static uint32_t spirv_get_type_id(struct vkd3d_spirv_builder *builder, + + case VSIR_DATA_I32: + case VSIR_DATA_U32: ++ case VSIR_DATA_MIXED: + type_id = vkd3d_spirv_get_op_type_int(builder, 32, data_type == VSIR_DATA_I32); + break; + +@@ -7627,6 +7628,18 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil + return VKD3D_OK; + } + ++static void spirv_compiler_emit_saturate(struct spirv_compiler *compiler, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ const struct vkd3d_shader_dst_param *dst = instruction->dst; ++ const struct vkd3d_shader_src_param *src = instruction->src; ++ uint32_t val_id; ++ ++ val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); ++ val_id = spirv_compiler_emit_sat(compiler, &dst->reg, dst->write_mask, val_id); ++ spirv_compiler_emit_store_dst(compiler, dst, val_id); ++} ++ + static void spirv_compiler_emit_isfinite(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { +@@ -10520,6 +10533,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, + case VSIR_OP_ISFINITE: + spirv_compiler_emit_isfinite(compiler, instruction); + break; ++ case VSIR_OP_SATURATE: ++ spirv_compiler_emit_saturate(compiler, instruction); ++ break; + case VSIR_OP_ABS: + case VSIR_OP_ACOS: + case VSIR_OP_ASIN: +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index c70096f1f75..346c74ff698 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -542,6 +542,7 @@ enum vkd3d_shader_opcode + VSIR_OP_SAMPLE_LOD, + VSIR_OP_SAMPLE_LOD_S, + VSIR_OP_SAMPLE_POS, ++ VSIR_OP_SATURATE, + VSIR_OP_SETP, + VSIR_OP_SGE, + VSIR_OP_SGN, +@@ -1502,9 +1503,9 @@ static inline bool vsir_program_iterator_insert_after(struct vsir_program_iterat + } + + /* When insertion takes place, argument `it' is updated to point to the same +- * instruction as before the insertion, and the optional argument `ins_it' is +- * initialized to point to the first inserted instruction. +- * A pointer to the first inserted instruction is returned. */ ++ * instruction as before the insertion, and argument `ins_it' is initialized ++ * to point to the first inserted instruction. A pointer to the first inserted ++ * instruction is returned. */ + static inline struct vkd3d_shader_instruction *vsir_program_iterator_insert_before( + struct vsir_program_iterator *it, struct vsir_program_iterator *ins_it, size_t count) + { +diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c +index b6055a50a99..4bd97fd599f 100644 +--- a/libs/vkd3d/libs/vkd3d/state.c ++++ b/libs/vkd3d/libs/vkd3d/state.c +@@ -843,7 +843,7 @@ static struct vk_binding_array *d3d12_root_signature_vk_binding_array_for_type( + { + if (!context->static_samplers_descriptor_set) + { +- if (!context->push_descriptor && context->root_descriptor_set) ++ if (!root_signature->device->vk_info.KHR_push_descriptor && context->root_descriptor_set) + context->static_samplers_descriptor_set = context->root_descriptor_set; + else + /* The descriptor type is irrelevant here, it will never be used. */ +-- +2.51.0 + diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-52b9aa416bb4e8be2fb6e28ffd1234cc10d.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-52b9aa416bb4e8be2fb6e28ffd1234cc10d.patch deleted file mode 100644 index a2376854..00000000 --- a/patches/vkd3d-latest/0004-Updated-vkd3d-to-52b9aa416bb4e8be2fb6e28ffd1234cc10d.patch +++ /dev/null @@ -1,626 +0,0 @@ -From b36e73b23646553bf2b9976a888b74a7122dc784 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Sat, 20 Sep 2025 07:06:08 +1000 -Subject: [PATCH] Updated vkd3d to 52b9aa416bb4e8be2fb6e28ffd1234cc10db96c6. - ---- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 3 - - libs/vkd3d/libs/vkd3d-shader/dxil.c | 38 +++-- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 1 + - libs/vkd3d/libs/vkd3d-shader/ir.c | 166 +++++++++++++++----- - libs/vkd3d/libs/vkd3d-shader/msl.c | 7 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 12 +- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 4 +- - 7 files changed, 166 insertions(+), 65 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index a9195b3454a..b4e079f507e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -2150,9 +2150,6 @@ int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, - if ((result = vsir_allocate_temp_registers(program, message_context))) - return result; - -- if ((result = vsir_update_dcl_temps(program, message_context))) -- return result; -- - d3dbc.program = program; - d3dbc.message_context = message_context; - switch (version->type) -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 63dcbd3c08a..5d8ab701cc0 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -4627,6 +4627,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - struct vkd3d_shader_src_param *src_params; - enum vkd3d_shader_opcode handler_idx; - const struct sm6_value *a, *b; -+ uint32_t type_flags = 0; - uint64_t code, flags; - bool silence_warning; - unsigned int i = 0; -@@ -4668,6 +4669,8 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - silence_warning = !(flags & ~(OB_NO_UNSIGNED_WRAP | OB_NO_SIGNED_WRAP)); - break; - case VSIR_OP_ISHR: -+ type_flags |= DXIL_TYPE_SIGNED; -+ /* fall through */ - case VSIR_OP_USHR: - case VSIR_OP_IDIV: - case VSIR_OP_UDIV_SIMPLE: -@@ -4692,8 +4695,8 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0], a, 0, sm6); -- src_param_init_from_value(&src_params[1], b, 0, sm6); -+ src_param_init_from_value(&src_params[0], a, type_flags, sm6); -+ src_param_init_from_value(&src_params[1], b, type_flags, sm6); - if (code == BINOP_SUB) - src_params[1].modifiers = VKD3DSPSM_NEG; - -@@ -4706,7 +4709,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - * do. */ - ins->flags |= VKD3DSI_SHIFT_UNMASKED; - } -- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, type_flags, sm6); - } - - static const struct sm6_block *sm6_function_get_block(const struct sm6_function *function, uint64_t index, -@@ -4972,8 +4975,11 @@ static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, enum dx_intrinsic_o - instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } - --static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, const struct sm6_type *type) -+static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, -+ const struct sm6_type *type, uint32_t *type_flags) - { -+ *type_flags = 0; -+ - switch (op) - { - case DX_FMAX: -@@ -4981,8 +4987,10 @@ static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, co - case DX_FMIN: - return type->u.width == 64 ? VSIR_OP_DMIN : VSIR_OP_MIN; - case DX_IMAX: -+ *type_flags |= DXIL_TYPE_SIGNED; - return VSIR_OP_IMAX; - case DX_IMIN: -+ *type_flags |= DXIL_TYPE_SIGNED; - return VSIR_OP_IMIN; - case DX_QUAD_READ_LANE_AT: - return VSIR_OP_QUAD_READ_LANE_AT; -@@ -5002,14 +5010,15 @@ static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_ - { - struct vkd3d_shader_instruction *ins = state->ins; - struct vkd3d_shader_src_param *src_params; -+ uint32_t type_flags; - -- vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type)); -+ vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type, &type_flags)); - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0], operands[0], 0, sm6); -- src_param_init_from_value(&src_params[1], operands[1], 0, sm6); -+ src_param_init_from_value(&src_params[0], operands[0], type_flags, sm6); -+ src_param_init_from_value(&src_params[1], operands[1], type_flags, sm6); - -- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); -+ instruction_dst_param_init_ssa_scalar(ins, type_flags, sm6); - } - - static enum vkd3d_shader_opcode map_dx_atomic_binop(const struct sm6_value *operand, struct sm6_parser *sm6) -@@ -7140,6 +7149,7 @@ struct sm6_cmp_info - { - enum vkd3d_shader_opcode handler_idx; - bool src_swap; -+ uint32_t type_flags; - }; - - static const struct sm6_cmp_info *sm6_map_cmp2_op(uint64_t code) -@@ -7169,10 +7179,10 @@ static const struct sm6_cmp_info *sm6_map_cmp2_op(uint64_t code) - [ICMP_UGE] = {VSIR_OP_UGE}, - [ICMP_ULT] = {VSIR_OP_ULT}, - [ICMP_ULE] = {VSIR_OP_UGE, true}, -- [ICMP_SGT] = {VSIR_OP_ILT, true}, -- [ICMP_SGE] = {VSIR_OP_IGE}, -- [ICMP_SLT] = {VSIR_OP_ILT}, -- [ICMP_SLE] = {VSIR_OP_IGE, true}, -+ [ICMP_SGT] = {VSIR_OP_ILT, true, DXIL_TYPE_SIGNED}, -+ [ICMP_SGE] = {VSIR_OP_IGE, false, DXIL_TYPE_SIGNED}, -+ [ICMP_SLT] = {VSIR_OP_ILT, false, DXIL_TYPE_SIGNED}, -+ [ICMP_SLE] = {VSIR_OP_IGE, true, DXIL_TYPE_SIGNED}, - }; - - return (code < ARRAY_SIZE(cmp_op_table)) ? &cmp_op_table[code] : NULL; -@@ -7273,8 +7283,8 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor - - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a, 0, sm6); -- src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b, 0, sm6); -+ src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a, cmp->type_flags, sm6); -+ src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b, cmp->type_flags, sm6); - - instruction_dst_param_init_ssa_scalar(ins, 0, sm6); - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index eaf7d7a3d63..bb8fdb8bd60 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -9031,6 +9031,7 @@ static void vsir_src_from_hlsl_constant_value(struct vkd3d_shader_src_param *src - } - - src->reg.dimension = VSIR_DIMENSION_VEC4; -+ src->swizzle = VKD3D_SHADER_NO_SWIZZLE; - for (i = 0, j = 0; i < 4; ++i) - { - if ((map_writemask & (1u << i)) && (j < width)) -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 506b397fb02..a242f32d824 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -1017,16 +1017,15 @@ static void dst_param_init_output(struct vkd3d_shader_dst_param *dst, - dst->write_mask = write_mask; - } - --void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, -- enum vkd3d_shader_opcode opcode) -+void vsir_instruction_init(struct vkd3d_shader_instruction *ins, -+ const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode opcode) - { -- memset(ins, 0, sizeof(*ins)); -- ins->location = *location; -- ins->opcode = opcode; -- ins->resource_data_type[0] = VSIR_DATA_F32; -- ins->resource_data_type[1] = VSIR_DATA_F32; -- ins->resource_data_type[2] = VSIR_DATA_F32; -- ins->resource_data_type[3] = VSIR_DATA_F32; -+ *ins = (struct vkd3d_shader_instruction) -+ { -+ .location = *location, -+ .opcode = opcode, -+ .resource_data_type = {VSIR_DATA_F32, VSIR_DATA_F32, VSIR_DATA_F32, VSIR_DATA_F32}, -+ }; - } - - bool vsir_instruction_init_with_params(struct vsir_program *program, -@@ -1305,6 +1304,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program - ins->src[1].reg.u.immconst_f32[1] = 0.0f; - ins->src[1].reg.u.immconst_f32[2] = 0.0f; - ins->src[1].reg.u.immconst_f32[3] = 0.0f; -+ ins->src[1].swizzle = VKD3D_SHADER_NO_SWIZZLE; - - /* tmp.x = tmp.x || tmp.y */ - /* tmp.x = tmp.x || tmp.z */ -@@ -2306,6 +2306,7 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra - ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL & ~program->diffuse_written_mask; - vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); - ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; - for (i = 0; i < 4; ++i) - ins->src[0].reg.u.immconst_f32[i] = 1.0f; - return VKD3D_OK; -@@ -2527,6 +2528,7 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program - dst_param_init_output(&ins->dst[0], VSIR_DATA_F32, e->register_index, e->mask); - vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); - ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; - ins = vsir_program_iterator_next(&it); - } - } -@@ -3669,6 +3671,7 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par - { - enum vkd3d_shader_d3dbc_constant_register set; - struct vkd3d_shader_src_param *rel_addr; -+ unsigned int c; - uint32_t index; - size_t i, j; - -@@ -3683,7 +3686,11 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par - param->reg.idx_count = 0; - param->reg.dimension = VSIR_DIMENSION_VEC4; - for (j = 0; j < 4; ++j) -- param->reg.u.immconst_u32[j] = normaliser->defs[i].value[j]; -+ { -+ c = vsir_swizzle_get_component(param->swizzle, j); -+ param->reg.u.immconst_u32[j] = normaliser->defs[i].value[c]; -+ } -+ param->swizzle = VKD3D_SHADER_NO_SWIZZLE; - return; - } - } -@@ -7932,6 +7939,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr - ins->dst[0].write_mask = VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; - vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); - ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; - vsir_program_iterator_next(&it); - - program->has_point_coord = true; -@@ -8932,11 +8940,13 @@ struct temp_allocator - uint32_t temp_id; - enum vkd3d_shader_register_type type; - unsigned int idx; -+ bool force_first; - } *ssa_regs, *temp_regs; - size_t ssa_count, temp_count; - unsigned int new_temp_count; - enum vkd3d_result result; - uint8_t *current_allocation; -+ bool ps_1_x; - }; - - static void temp_allocator_set_src(struct temp_allocator *allocator, struct vkd3d_shader_src_param *src) -@@ -9084,15 +9094,12 @@ static int temp_allocate_compare_open(const void *ptr1, const void *ptr2) - const struct temp_allocator_reg * const *reg1 = ptr1, * const *reg2 = ptr2; - int ret; - -+ if ((ret = vkd3d_u32_compare((*reg1)->force_first, (*reg2)->force_first))) -+ return -ret; - if ((ret = vkd3d_u32_compare((*reg1)->liveness_reg->first_write, (*reg2)->liveness_reg->first_write))) - return ret; - if ((ret = vkd3d_u32_compare((*reg1)->liveness_reg->last_access, (*reg2)->liveness_reg->last_access))) - return ret; -- /* r0 must compare before everything else for SM 1.x PS (see comment below). */ -- if ((*reg1)->type == VKD3DSPR_TEMP && (*reg1)->idx == 0) -- return -1; -- if ((*reg2)->type == VKD3DSPR_TEMP && (*reg2)->idx == 0) -- return 1; - return 0; - } - -@@ -9260,6 +9267,17 @@ static enum vkd3d_result temp_allocator_compute_allocation_map(struct temp_alloc - { - reg->type = VKD3DSPR_TEMP; - reg->idx = i - allocator->ssa_count; -+ -+ /* For SM 1.x ps we need to ensure that r0 is reallocated to itself, -+ * because it doubles as the output register. To do so we -+ * artificially make it alive for the whole program and make it -+ * compare before anything else. */ -+ if (reg->idx == 0 && allocator->ps_1_x) -+ { -+ reg->force_first = true; -+ liveness->ssa_regs[i].first_write = 0; -+ liveness->ssa_regs[i].last_access = UINT_MAX; -+ } - } - - reg->liveness_reg = &liveness->ssa_regs[i]; -@@ -9367,15 +9385,8 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, - allocator.temp_regs = regs + program->ssa_count; - allocator.new_temp_count = 0; - -- /* For SM 1.x ps we need to ensure that r0 is reallocated to itself, because -- * it doubles as the output register. To do so we artificially make it -- * alive for the whole program. */ -- if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL -- && program->shader_version.major < 2 && allocator.temp_count >= 1) -- { -- tracker.temp_regs[0].first_write = 0; -- tracker.temp_regs[0].last_access = UINT_MAX; -- } -+ if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && program->shader_version.major < 2) -+ allocator.ps_1_x = true; - - if ((ret = temp_allocator_compute_allocation_map(&allocator, &tracker)) < 0) - { -@@ -9418,6 +9429,9 @@ enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, - struct vkd3d_shader_instruction *ins; - unsigned int temp_count = 0; - -+ if (program->shader_version.major < 4) -+ return VKD3D_OK; -+ - for (ins = vsir_program_iterator_tail(&it); ins; ins = vsir_program_iterator_prev(&it)) - { - location = ins->location; -@@ -9429,10 +9443,9 @@ enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, - continue; - } - -- if (temp_count && program->shader_version.major >= 4 -- && (ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE -- || ins->opcode == VSIR_OP_HS_FORK_PHASE -- || ins->opcode == VSIR_OP_HS_JOIN_PHASE)) -+ if (temp_count && (ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE -+ || ins->opcode == VSIR_OP_HS_FORK_PHASE -+ || ins->opcode == VSIR_OP_HS_JOIN_PHASE)) - { - /* The phase didn't have a dcl_temps instruction, but we added - * temps here, so we need to insert one. */ -@@ -9459,7 +9472,7 @@ enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, - } - } - -- if (temp_count && program->shader_version.major >= 4) -+ if (temp_count) - { - ins = vsir_program_iterator_head(&it); - location = ins->location; -@@ -10581,6 +10594,16 @@ static void vsir_validate_src_param(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source of dimension %u has invalid swizzle %#x.", - src->reg.dimension, src->swizzle); - -+ if (src->reg.dimension == VSIR_DIMENSION_VEC4 && src->reg.type == VKD3DSPR_IMMCONST -+ && src->swizzle != VKD3D_SHADER_NO_SWIZZLE) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, -+ "Immediate constant source has invalid swizzle %#x.", src->swizzle); -+ -+ if (src->reg.dimension == VSIR_DIMENSION_VEC4 && src->reg.type == VKD3DSPR_IMMCONST64 -+ && src->swizzle != VKD3D_SHADER_SWIZZLE(X, Y, X, X)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, -+ "Immediate constant source has invalid swizzle %#x.", src->swizzle); -+ - if (src->modifiers >= VKD3DSPSM_COUNT) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", - src->modifiers); -@@ -11299,6 +11322,7 @@ static void vsir_validate_integer_elementwise_operation(struct validation_contex - static const bool types[VSIR_DATA_TYPE_COUNT] = - { - [VSIR_DATA_I32] = true, -+ [VSIR_DATA_I64] = true, - [VSIR_DATA_U32] = true, - [VSIR_DATA_U64] = true, - }; -@@ -11306,6 +11330,18 @@ static void vsir_validate_integer_elementwise_operation(struct validation_contex - vsir_validate_elementwise_operation(ctx, instruction, types); - } - -+static void vsir_validate_signed_integer_elementwise_operation(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ static const bool types[VSIR_DATA_TYPE_COUNT] = -+ { -+ [VSIR_DATA_I32] = true, -+ [VSIR_DATA_I64] = true, -+ }; -+ -+ vsir_validate_elementwise_operation(ctx, instruction, types); -+} -+ - static void vsir_validate_logic_elementwise_operation(struct validation_context *ctx, - const struct vkd3d_shader_instruction *instruction) - { -@@ -11399,6 +11435,18 @@ static void vsir_validate_integer_comparison_operation(struct validation_context - vsir_validate_comparison_operation(ctx, instruction, types); - } - -+static void vsir_validate_signed_integer_comparison_operation(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ static const bool types[VSIR_DATA_TYPE_COUNT] = -+ { -+ [VSIR_DATA_I32] = true, -+ [VSIR_DATA_I64] = true, -+ }; -+ -+ vsir_validate_comparison_operation(ctx, instruction, types); -+} -+ - static void vsir_validate_cast_operation(struct validation_context *ctx, - const struct vkd3d_shader_instruction *instruction, - const bool src_types[VSIR_DATA_TYPE_COUNT], const bool dst_types[VSIR_DATA_TYPE_COUNT]) -@@ -11428,19 +11476,20 @@ static void vsir_validate_cast_operation(struct validation_context *ctx, - } - - static void vsir_validate_shift_operation(struct validation_context *ctx, -- const struct vkd3d_shader_instruction *instruction) -+ const struct vkd3d_shader_instruction *instruction, const bool types[VSIR_DATA_TYPE_COUNT]) - { - enum vsir_data_type dst_data_type, src_data_type; - -- static const bool types[] = -+ static const bool shift_types[] = - { - [VSIR_DATA_I32] = true, -+ [VSIR_DATA_I64] = true, - [VSIR_DATA_U32] = true, - [VSIR_DATA_U64] = true, - }; - - dst_data_type = instruction->dst[0].reg.data_type; -- if ((size_t)dst_data_type >= ARRAY_SIZE(types) || !types[dst_data_type]) -+ if ((size_t)dst_data_type >= VSIR_DATA_TYPE_COUNT || !types[dst_data_type]) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, - "Invalid destination data type \"%s\" (%#x) for shift operation \"%s\" (%#x).", - vsir_data_type_get_name(dst_data_type, ""), dst_data_type, -@@ -11455,7 +11504,7 @@ static void vsir_validate_shift_operation(struct validation_context *ctx, - vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - - src_data_type = instruction->src[1].reg.data_type; -- if ((size_t)src_data_type >= ARRAY_SIZE(types) || !types[src_data_type]) -+ if ((size_t)src_data_type >= ARRAY_SIZE(shift_types) || !shift_types[src_data_type]) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, - "Invalid source operand 1 data type \"%s\" (%#x) for shift operation \"%s\" (%#x).", - vsir_data_type_get_name(src_data_type, ""), src_data_type, -@@ -12020,6 +12069,32 @@ static void vsir_validate_ifc(struct validation_context *ctx, const struct vkd3d - vsir_validator_push_block(ctx, VSIR_OP_IF); - } - -+static void vsir_validate_ishl(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ static const bool types[VSIR_DATA_TYPE_COUNT] = -+ { -+ [VSIR_DATA_I32] = true, -+ [VSIR_DATA_I64] = true, -+ [VSIR_DATA_U32] = true, -+ [VSIR_DATA_U64] = true, -+ }; -+ -+ vsir_validate_shift_operation(ctx, instruction, types); -+} -+ -+static void vsir_validate_ishr(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ static const bool types[VSIR_DATA_TYPE_COUNT] = -+ { -+ [VSIR_DATA_I32] = true, -+ [VSIR_DATA_I64] = true, -+ }; -+ -+ vsir_validate_shift_operation(ctx, instruction, types); -+} -+ - static void vsir_validate_itof(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) - { - static const bool src_types[VSIR_DATA_TYPE_COUNT] = -@@ -12251,6 +12326,18 @@ static void vsir_validate_switch_monolithic(struct validation_context *ctx, - ctx->inside_block = false; - } - -+static void vsir_validate_ushr(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ static const bool types[VSIR_DATA_TYPE_COUNT] = -+ { -+ [VSIR_DATA_U32] = true, -+ [VSIR_DATA_U64] = true, -+ }; -+ -+ vsir_validate_shift_operation(ctx, instruction, types); -+} -+ - struct vsir_validator_instruction_desc - { - unsigned int dst_param_count; -@@ -12330,17 +12417,17 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ - [VSIR_OP_IEQ] = {1, 2, vsir_validate_integer_comparison_operation}, - [VSIR_OP_IF] = {0, 1, vsir_validate_if}, - [VSIR_OP_IFC] = {0, 2, vsir_validate_ifc}, -- [VSIR_OP_IGE] = {1, 2, vsir_validate_integer_comparison_operation}, -- [VSIR_OP_ILT] = {1, 2, vsir_validate_integer_comparison_operation}, -+ [VSIR_OP_IGE] = {1, 2, vsir_validate_signed_integer_comparison_operation}, -+ [VSIR_OP_ILT] = {1, 2, vsir_validate_signed_integer_comparison_operation}, - [VSIR_OP_IMAD] = {1, 3, vsir_validate_integer_elementwise_operation}, -- [VSIR_OP_IMAX] = {1, 2, vsir_validate_integer_elementwise_operation}, -- [VSIR_OP_IMIN] = {1, 2, vsir_validate_integer_elementwise_operation}, -+ [VSIR_OP_IMAX] = {1, 2, vsir_validate_signed_integer_elementwise_operation}, -+ [VSIR_OP_IMIN] = {1, 2, vsir_validate_signed_integer_elementwise_operation}, - [VSIR_OP_INE] = {1, 2, vsir_validate_integer_comparison_operation}, - [VSIR_OP_INEG] = {1, 1, vsir_validate_integer_elementwise_operation}, - [VSIR_OP_IREM] = {1, 2, vsir_validate_integer_elementwise_operation}, - [VSIR_OP_ISFINITE] = {1, 1, vsir_validate_float_comparison_operation}, -- [VSIR_OP_ISHL] = {1, 2, vsir_validate_shift_operation}, -- [VSIR_OP_ISHR] = {1, 2, vsir_validate_shift_operation}, -+ [VSIR_OP_ISHL] = {1, 2, vsir_validate_ishl}, -+ [VSIR_OP_ISHR] = {1, 2, vsir_validate_ishr}, - [VSIR_OP_ISINF] = {1, 1, vsir_validate_float_comparison_operation}, - [VSIR_OP_ISNAN] = {1, 1, vsir_validate_float_comparison_operation}, - [VSIR_OP_ITOF] = {1, 1, vsir_validate_itof}, -@@ -12370,6 +12457,7 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ - [VSIR_OP_SAMPLE_INFO] = {1, 1, vsir_validate_sample_info}, - [VSIR_OP_SWITCH] = {0, 1, vsir_validate_switch}, - [VSIR_OP_SWITCH_MONOLITHIC] = {0, ~0u, vsir_validate_switch_monolithic}, -+ [VSIR_OP_USHR] = {1, 2, vsir_validate_ushr}, - }; - - static void vsir_validate_instruction(struct validation_context *ctx, -diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index 9150e77e2c6..2005e842201 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -167,6 +167,7 @@ static void msl_print_register_datatype(struct vkd3d_string_buffer *buffer, - case VSIR_DATA_F32: - vkd3d_string_buffer_printf(buffer, "f"); - break; -+ case VSIR_DATA_BOOL: - case VSIR_DATA_I32: - vkd3d_string_buffer_printf(buffer, "i"); - break; -@@ -799,6 +800,7 @@ static void msl_relop(struct msl_generator *gen, const struct vkd3d_shader_instr - static void msl_cast(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *constructor) - { - unsigned int component_count; -+ const char *negate; - struct msl_src src; - struct msl_dst dst; - uint32_t mask; -@@ -806,10 +808,11 @@ static void msl_cast(struct msl_generator *gen, const struct vkd3d_shader_instru - mask = msl_dst_init(&dst, gen, ins, &ins->dst[0]); - msl_src_init(&src, gen, &ins->src[0], mask); - -+ negate = ins->opcode == VSIR_OP_UTOF && data_type_is_bool(ins->src[0].reg.data_type) ? "-" : ""; - if ((component_count = vsir_write_mask_component_count(mask)) > 1) -- msl_print_assignment(gen, &dst, "%s%u(%s)", constructor, component_count, src.str->buffer); -+ msl_print_assignment(gen, &dst, "%s%u(%s%s)", constructor, component_count, negate, src.str->buffer); - else -- msl_print_assignment(gen, &dst, "%s(%s)", constructor, src.str->buffer); -+ msl_print_assignment(gen, &dst, "%s(%s%s)", constructor, negate, src.str->buffer); - - msl_src_cleanup(&src, &gen->string_buffers); - msl_dst_cleanup(&dst, &gen->string_buffers); -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 8ffc68935f3..0fdeba75c58 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -8155,7 +8155,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, - component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); - - int_max_id = spirv_compiler_get_constant_vector(compiler, component_type, component_count, INT_MAX); -- condition_type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); -+ condition_type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); - condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, - SpvOpFOrdGreaterThanEqual, condition_type_id, val_id, float_max_id); - -@@ -8208,7 +8208,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, - val_id = vkd3d_spirv_build_op_glsl_std450_max(builder, src_type_id, src_id, zero_id); - - uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT_MAX, component_count); -- condition_type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); -+ condition_type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); - condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, - SpvOpFOrdGreaterThanEqual, condition_type_id, val_id, float_max_id); - -@@ -8233,7 +8233,7 @@ static void spirv_compiler_emit_dtof(struct spirv_compiler *compiler, - - src_id = spirv_compiler_emit_load_src(compiler, src, write_mask); - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, component_count); - val_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpFConvert, type_id, src_id); - if (instruction->flags & VKD3DSI_PRECISE_XYZW) - vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); -@@ -8257,7 +8257,7 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp - VKD3D_ASSERT(2 <= src_count && src_count <= ARRAY_SIZE(src_ids)); - - component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); -- type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); -+ type_id = spirv_get_type_id(builder, dst->reg.data_type, 1); - size = data_type_is_64_bit(src[src_count - 1].reg.data_type) ? 0x40 : 0x20; - mask_id = spirv_compiler_get_constant_uint(compiler, size - 1); - size_id = spirv_compiler_get_constant_uint(compiler, size); -@@ -8314,8 +8314,8 @@ static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler, - unsigned int i, j; - - instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -- scalar_type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); -+ scalar_type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 1); - - /* FIXME: Consider a single UnpackHalf2x16 instruction per 2 components. */ - VKD3D_ASSERT(dst->write_mask & VKD3DSP_WRITEMASK_ALL); -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 2541aef1314..7ff2a305cfa 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -3483,7 +3483,9 @@ static uint32_t sm4_encode_register(const struct tpf_compiler *tpf, const struct - switch (sm4_swizzle_type) - { - case VKD3D_SM4_SWIZZLE_NONE: -- VKD3D_ASSERT(sm4_swizzle || register_is_constant(reg)); -+ if (register_is_constant(reg)) -+ break; -+ VKD3D_ASSERT(sm4_swizzle); - token |= (sm4_swizzle << VKD3D_SM4_WRITEMASK_SHIFT) & VKD3D_SM4_WRITEMASK_MASK; - break; - --- -2.51.0 - diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-507990d3c5a7b61ad5df63a17bbd122d8dc.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-507990d3c5a7b61ad5df63a17bbd122d8dc.patch new file mode 100644 index 00000000..58c9444e --- /dev/null +++ b/patches/vkd3d-latest/0005-Updated-vkd3d-to-507990d3c5a7b61ad5df63a17bbd122d8dc.patch @@ -0,0 +1,1263 @@ +From 7deb0d9351a2645eb2828fb177e1bc3f46bfc688 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Thu, 16 Oct 2025 06:52:58 +1100 +Subject: [PATCH] Updated vkd3d to 507990d3c5a7b61ad5df63a17bbd122d8dc7e2e3. + +--- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 9 +- + libs/vkd3d/libs/vkd3d-shader/glsl.c | 2 + + libs/vkd3d/libs/vkd3d-shader/ir.c | 22 +- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 364 ++++++++++++++------------- + 4 files changed, 199 insertions(+), 198 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index b2d4ec23c6e..87a7d48acca 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -1597,6 +1597,9 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c + + program->has_descriptor_info = true; + ++ if (TRACE_ON()) ++ vsir_program_trace(program); ++ + if (ret >= 0 && sm1.p.status < 0) + ret = sm1.p.status; + +@@ -2171,11 +2174,11 @@ static void d3dbc_write_semantic_dcl(struct d3dbc_compiler *d3dbc, + VKD3D_ASSERT(ret); + reg.reg.type = output ? VKD3DSPR_OUTPUT : VKD3DSPR_INPUT; + reg.reg.idx[0].offset = element->register_index; +- if (!vkd3d_shader_ver_ge(version, 3, 0)) ++ if ((version->type == VKD3D_SHADER_TYPE_PIXEL || output) && !vkd3d_shader_ver_ge(version, 3, 0)) + { +- if (reg.reg.idx[0].offset > SM1_RASTOUT_REGISTER_OFFSET) ++ if (reg.reg.idx[0].offset >= SM1_RASTOUT_REGISTER_OFFSET) + reg.reg.idx[0].offset -= SM1_RASTOUT_REGISTER_OFFSET; +- else if (reg.reg.idx[0].offset > SM1_COLOR_REGISTER_OFFSET) ++ else if (reg.reg.idx[0].offset >= SM1_COLOR_REGISTER_OFFSET) + reg.reg.idx[0].offset -= SM1_COLOR_REGISTER_OFFSET; + } + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c +index 91a96a5547e..ab45c4d1e73 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c +@@ -514,6 +514,8 @@ static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_g + "Internal compiler error: Unhandled destination register data type %#x.", data_type); + /* fall through */ + case VSIR_DATA_F32: ++ case VSIR_DATA_SNORM: ++ case VSIR_DATA_UNORM: + close = false; + break; + case VSIR_DATA_I32: +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index c013c9e61bd..82901c6fb34 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -1223,11 +1223,12 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra + ins2->dst[0].reg.idx[0].offset = tmp_idx; + ins2->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins2->dst[0].write_mask = ins->dst[0].write_mask; ++ ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; + + vsir_register_init(&ins2->src[0].reg, VKD3DSPR_TEMP, VSIR_DATA_F32, 1); + ins2->src[0].reg.idx[0].offset = tmp_idx; + ins2->src[0].reg.dimension = VSIR_DIMENSION_VEC4; +- ins2->src[0].swizzle = vsir_swizzle_from_writemask(ins2->dst[0].write_mask); ++ ins2->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; + } + + for (k = 0; k < ins->src_count; ++k) +@@ -1392,7 +1393,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program + * not fused for "precise" operations." + * Windows drivers seem to conform with the latter, for SM 4-5 and SM 6. */ + static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *program, +- struct vsir_program_iterator *it, unsigned int *tmp_idx) ++ struct vsir_program_iterator *it) + { + struct vkd3d_shader_instruction *mad, *mul_ins, *add_ins; + struct vkd3d_shader_dst_param *mul_dst; +@@ -1405,9 +1406,6 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro + if (!vsir_program_iterator_insert_after(it, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- if (*tmp_idx == ~0u) +- *tmp_idx = program->temp_count++; +- + mul_ins = vsir_program_iterator_current(it); + add_ins = vsir_program_iterator_next(it); + +@@ -1422,14 +1420,9 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro + mul_dst = mul_ins->dst; + *add_ins->dst = *mul_dst; + +- mul_dst->modifiers = 0; +- vsir_register_init(&mul_dst->reg, VKD3DSPR_TEMP, mul_ins->src[0].reg.data_type, 1); +- mul_dst->reg.dimension = add_ins->dst->reg.dimension; +- mul_dst->reg.idx[0].offset = *tmp_idx; ++ dst_param_init_ssa(mul_dst, program->ssa_count, mul_ins->src[0].reg.data_type, VSIR_DIMENSION_VEC4); ++ src_param_init_ssa(&add_ins->src[0], program->ssa_count++, mul_ins->src[0].reg.data_type, VSIR_DIMENSION_VEC4); + +- add_ins->src[0].reg = mul_dst->reg; +- add_ins->src[0].swizzle = vsir_swizzle_from_writemask(mul_dst->write_mask); +- add_ins->src[0].modifiers = 0; + add_ins->src[1] = mul_ins->src[2]; + + return VKD3D_OK; +@@ -1736,7 +1729,7 @@ static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *progr + struct vkd3d_shader_instruction *ins, struct vkd3d_shader_message_context *message_context) + { + const struct vkd3d_shader_descriptor_info1 *sampler; +- unsigned int idx = ins->src[0].reg.idx[0].offset; ++ unsigned int idx = ins->dst[0].reg.idx[0].offset; + struct vkd3d_shader_src_param *srcs; + + /* texld DST, t# -> sample DST, t#, resource#, sampler# */ +@@ -2279,7 +2272,6 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr + { + struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); + struct vkd3d_shader_instruction *ins; +- unsigned int tmp_idx = ~0u; + enum vkd3d_result ret; + + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) +@@ -2287,7 +2279,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr + switch (ins->opcode) + { + case VSIR_OP_MAD: +- if ((ret = vsir_program_lower_precise_mad(program, &it, &tmp_idx)) < 0) ++ if ((ret = vsir_program_lower_precise_mad(program, &it)) < 0) + return ret; + break; + +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index 8ff46759fb6..a1572f69438 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -2491,70 +2491,6 @@ static uint32_t vkd3d_spirv_build_op_glsl_std450_nclamp(struct vkd3d_spirv_build + GLSLstd450NClamp, operands, ARRAY_SIZE(operands)); + } + +-static uint32_t spirv_get_type_id(struct vkd3d_spirv_builder *builder, +- enum vsir_data_type data_type, unsigned int component_count) +-{ +- uint32_t scalar_id, type_id; +- +- VKD3D_ASSERT(data_type < VSIR_DATA_TYPE_COUNT); +- if (!component_count || component_count > VKD3D_VEC4_SIZE) +- { +- ERR("Invalid component count %u.\n", component_count); +- return 0; +- } +- +- if ((type_id = builder->numeric_type_ids[data_type][component_count - 1])) +- return type_id; +- +- if (component_count == 1) +- { +- switch (data_type) +- { +- case VSIR_DATA_BOOL: +- type_id = vkd3d_spirv_get_op_type_bool(builder); +- break; +- +- case VSIR_DATA_F32: +- type_id = vkd3d_spirv_get_op_type_float(builder, 32); +- break; +- +- case VSIR_DATA_F64: +- type_id = vkd3d_spirv_get_op_type_float(builder, 64); +- break; +- +- case VSIR_DATA_I32: +- case VSIR_DATA_U32: +- case VSIR_DATA_MIXED: +- type_id = vkd3d_spirv_get_op_type_int(builder, 32, data_type == VSIR_DATA_I32); +- break; +- +- case VSIR_DATA_I64: +- case VSIR_DATA_U64: +- type_id = vkd3d_spirv_get_op_type_int(builder, 64, data_type == VSIR_DATA_I64); +- break; +- +- case VSIR_DATA_UNUSED: +- type_id = vkd3d_spirv_get_op_type_void(builder); +- break; +- +- default: +- FIXME("Unhandled data type \"%s\" (%#x).\n", +- vsir_data_type_get_name(data_type, ""), data_type); +- return 0; +- } +- } +- else +- { +- VKD3D_ASSERT(data_type != VSIR_DATA_UNUSED); +- scalar_id = spirv_get_type_id(builder, data_type, 1); +- type_id = vkd3d_spirv_get_op_type_vector(builder, scalar_id, component_count); +- } +- +- builder->numeric_type_ids[data_type][component_count - 1] = type_id; +- +- return type_id; +-} +- + static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, + const char *entry_point, const char *source_name) + { +@@ -3471,6 +3407,74 @@ static struct vkd3d_string_buffer *vkd3d_shader_register_range_string(struct spi + return buffer; + } + ++static uint32_t spirv_get_type_id(struct spirv_compiler *compiler, ++ enum vsir_data_type data_type, unsigned int component_count) ++{ ++ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ uint32_t scalar_id, type_id; ++ ++ VKD3D_ASSERT(data_type < VSIR_DATA_TYPE_COUNT); ++ if (!component_count || component_count > VKD3D_VEC4_SIZE) ++ { ++ ERR("Invalid component count %u.\n", component_count); ++ return 0; ++ } ++ ++ if ((type_id = builder->numeric_type_ids[data_type][component_count - 1])) ++ return type_id; ++ ++ if (component_count == 1) ++ { ++ switch (data_type) ++ { ++ case VSIR_DATA_BOOL: ++ type_id = vkd3d_spirv_get_op_type_bool(builder); ++ break; ++ ++ case VSIR_DATA_F32: ++ case VSIR_DATA_SNORM: ++ case VSIR_DATA_UNORM: ++ type_id = vkd3d_spirv_get_op_type_float(builder, 32); ++ break; ++ ++ case VSIR_DATA_F64: ++ type_id = vkd3d_spirv_get_op_type_float(builder, 64); ++ break; ++ ++ case VSIR_DATA_I32: ++ case VSIR_DATA_U32: ++ case VSIR_DATA_MIXED: ++ type_id = vkd3d_spirv_get_op_type_int(builder, 32, data_type == VSIR_DATA_I32); ++ break; ++ ++ case VSIR_DATA_I64: ++ case VSIR_DATA_U64: ++ type_id = vkd3d_spirv_get_op_type_int(builder, 64, data_type == VSIR_DATA_I64); ++ break; ++ ++ case VSIR_DATA_UNUSED: ++ type_id = vkd3d_spirv_get_op_type_void(builder); ++ break; ++ ++ default: ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, ++ "Unhandled data type \"%s\" (%#x).", ++ vsir_data_type_get_name(data_type, ""), data_type); ++ return 0; ++ } ++ } ++ else ++ { ++ VKD3D_ASSERT(data_type != VSIR_DATA_UNUSED); ++ scalar_id = spirv_get_type_id(compiler, data_type, 1); ++ type_id = vkd3d_spirv_get_op_type_vector(builder, scalar_id, component_count); ++ } ++ ++ builder->numeric_type_ids[data_type][component_count - 1] = type_id; ++ ++ return type_id; ++} ++ + static uint32_t spirv_compiler_get_label_id(struct spirv_compiler *compiler, unsigned int block_id) + { + --block_id; +@@ -3636,7 +3640,7 @@ static uint32_t spirv_compiler_get_constant(struct spirv_compiler *compiler, + unsigned int i; + + VKD3D_ASSERT(0 < component_count && component_count <= VKD3D_VEC4_SIZE); +- type_id = spirv_get_type_id(builder, data_type, component_count); ++ type_id = spirv_get_type_id(compiler, data_type, component_count); + + switch (data_type) + { +@@ -3666,7 +3670,7 @@ static uint32_t spirv_compiler_get_constant(struct spirv_compiler *compiler, + if (component_count == 1) + return vkd3d_spirv_get_op_constant(builder, type_id, *values); + +- scalar_type_id = spirv_get_type_id(builder, data_type, 1); ++ scalar_type_id = spirv_get_type_id(compiler, data_type, 1); + for (i = 0; i < component_count; ++i) + { + component_ids[i] = vkd3d_spirv_get_op_constant(builder, scalar_type_id, values[i]); +@@ -3683,7 +3687,7 @@ static uint32_t spirv_compiler_get_constant64(struct spirv_compiler *compiler, + unsigned int i; + + VKD3D_ASSERT(0 < component_count && component_count <= VKD3D_DVEC2_SIZE); +- type_id = spirv_get_type_id(builder, data_type, component_count); ++ type_id = spirv_get_type_id(compiler, data_type, component_count); + + if (data_type != VSIR_DATA_F64 && data_type != VSIR_DATA_I64 && data_type != VSIR_DATA_U64) + { +@@ -3696,7 +3700,7 @@ static uint32_t spirv_compiler_get_constant64(struct spirv_compiler *compiler, + if (component_count == 1) + return vkd3d_spirv_get_op_constant64(builder, type_id, *values); + +- scalar_type_id = spirv_get_type_id(builder, data_type, 1); ++ scalar_type_id = spirv_get_type_id(compiler, data_type, 1); + for (i = 0; i < component_count; ++i) + { + component_ids[i] = vkd3d_spirv_get_op_constant64(builder, scalar_type_id, values[i]); +@@ -3756,9 +3760,7 @@ static uint32_t spirv_compiler_get_constant_uint64_vector(struct spirv_compiler + static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compiler, + const struct vkd3d_shader_register *reg, uint32_t write_mask) + { +- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- +- return spirv_get_type_id(builder, reg->data_type, vsir_write_mask_component_count(write_mask)); ++ return spirv_get_type_id(compiler, reg->data_type, vsir_write_mask_component_count(write_mask)); + } + + static uint32_t spirv_compiler_get_type_id_for_dst(struct spirv_compiler *compiler, +@@ -3884,7 +3886,7 @@ static uint32_t spirv_compiler_emit_array_variable(struct spirv_compiler *compil + uint32_t type_id, length_id, ptr_type_id; + unsigned int i; + +- type_id = spirv_get_type_id(builder, data_type, component_count); ++ type_id = spirv_get_type_id(compiler, data_type, component_count); + for (i = 0; i < length_count; ++i) + { + if (!array_lengths[i]) +@@ -3982,8 +3984,8 @@ static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compile + info = get_spec_constant_info(name); + default_value = info ? info->default_value.u : 0; + +- scalar_type_id = spirv_get_type_id(builder, type, 1); +- vector_type_id = spirv_get_type_id(builder, type, component_count); ++ scalar_type_id = spirv_get_type_id(compiler, type, 1); ++ vector_type_id = spirv_get_type_id(compiler, type, component_count); + + for (unsigned int i = 0; i < component_count; ++i) + { +@@ -4032,7 +4034,7 @@ static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compi + unsigned int index = parameter - compiler->program->parameters; + uint32_t type_id, ptr_id, ptr_type_id; + +- type_id = spirv_get_type_id(builder, type, component_count); ++ type_id = spirv_get_type_id(compiler, type, component_count); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); + ptr_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, + compiler->spirv_parameter_info[index].buffer_id, +@@ -4096,7 +4098,7 @@ static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *comp + + VKD3D_ASSERT(val_component_idx < val_component_count); + +- type_id = spirv_get_type_id(builder, data_type, component_count); ++ type_id = spirv_get_type_id(compiler, data_type, component_count); + if (val_component_count == 1) + { + for (i = 0; i < component_count; ++i) +@@ -4129,7 +4131,7 @@ static uint32_t spirv_compiler_emit_register_addressing(struct spirv_compiler *c + addr_id = spirv_compiler_emit_load_src(compiler, reg_index->rel_addr, VKD3DSP_WRITEMASK_0); + if (reg_index->offset) + { +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + addr_id = vkd3d_spirv_build_op_iadd(builder, type_id, addr_id, + spirv_compiler_get_constant_uint(compiler, reg_index->offset)); + } +@@ -4279,7 +4281,7 @@ static uint32_t spirv_compiler_get_descriptor_index(struct spirv_compiler *compi + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, ptr_type_id, ptr_id, offset_id, index_ids[2]; + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + if (!(offset_id = compiler->descriptor_offset_ids[push_constant_index])) + { + index_ids[0] = compiler->descriptor_offsets_member_id; +@@ -4352,7 +4354,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp + if (index_count) + { + component_count = vsir_write_mask_component_count(register_info->write_mask); +- type_id = spirv_get_type_id(builder, register_info->data_type, component_count); ++ type_id = spirv_get_type_id(compiler, register_info->data_type, component_count); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, register_info->storage_class, type_id); + register_info->id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, + register_info->id, indexes, index_count); +@@ -4410,7 +4412,7 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, uin + && (component_count == 1 || vkd3d_swizzle_is_equal(val_write_mask, swizzle, write_mask))) + return val_id; + +- type_id = spirv_get_type_id(builder, data_type, component_count); ++ type_id = spirv_get_type_id(compiler, data_type, component_count); + + if (component_count == 1) + { +@@ -4461,7 +4463,7 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil + else + components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(swizzle, i); + } +- type_id = spirv_get_type_id(builder, data_type, component_count); ++ type_id = spirv_get_type_id(compiler, data_type, component_count); + + return vkd3d_spirv_build_op_vector_shuffle(builder, type_id, + vector1_id, vector2_id, components, component_count); +@@ -4477,7 +4479,7 @@ static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, + + VKD3D_ASSERT(!(condition & ~(VKD3D_SHADER_CONDITIONAL_OP_NZ | VKD3D_SHADER_CONDITIONAL_OP_Z))); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_BOOL, component_count); + op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual; + + return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, val_id, +@@ -4494,7 +4496,7 @@ static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, + + true_id = spirv_compiler_get_constant_uint_vector(compiler, signedness ? 0xffffffff : 1, component_count); + false_id = spirv_compiler_get_constant_uint_vector(compiler, 0, component_count); +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, component_count); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, component_count); + + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); + } +@@ -4508,7 +4510,7 @@ static uint32_t spirv_compiler_emit_bool_to_int64(struct spirv_compiler *compile + true_id = spirv_compiler_get_constant_uint64_vector(compiler, signedness ? UINT64_MAX : 1, + component_count); + false_id = spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count); +- type_id = spirv_get_type_id(builder, VSIR_DATA_U64, component_count); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U64, component_count); + + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); + } +@@ -4521,7 +4523,7 @@ static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compile + + true_id = spirv_compiler_get_constant_float_vector(compiler, signedness ? -1.0f : 1.0f, component_count); + false_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count); +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, component_count); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, component_count); + + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); + } +@@ -4534,7 +4536,7 @@ static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compil + + true_id = spirv_compiler_get_constant_double_vector(compiler, signedness ? -1.0 : 1.0, component_count); + false_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count); +- type_id = spirv_get_type_id(builder, VSIR_DATA_F64, component_count); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F64, component_count); + + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); + } +@@ -4600,7 +4602,7 @@ static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, + + VKD3D_ASSERT(reg->type == VKD3DSPR_UNDEF); + +- type_id = spirv_get_type_id(builder, reg->data_type, component_count); ++ type_id = spirv_get_type_id(compiler, reg->data_type, component_count); + + return vkd3d_spirv_get_op_undef(builder, type_id); + } +@@ -4631,7 +4633,7 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, + component_idx, reg->type, reg->idx[0].offset, reg_info->write_mask); + } + +- type_id = spirv_get_type_id(builder, reg_info->data_type, 1); ++ type_id = spirv_get_type_id(compiler, reg_info->data_type, 1); + reg_id = reg_info->id; + if (reg_component_count != 1) + { +@@ -4646,13 +4648,13 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, + + if (reg->data_type != VSIR_DATA_BOOL) + { +- type_id = spirv_get_type_id(builder, reg->data_type, 1); ++ type_id = spirv_get_type_id(compiler, reg->data_type, 1); + return vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } + + if (reg_info->data_type != VSIR_DATA_U32) + { +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } + +@@ -4669,7 +4671,7 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil + element_count = icb->element_count; + + component_count = icb->component_count; +- elem_type_id = spirv_get_type_id(builder, icb->data_type, component_count); ++ elem_type_id = spirv_get_type_id(compiler, 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); + +@@ -4757,7 +4759,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, + + if (!spirv_compiler_get_register_info(compiler, reg, ®_info)) + { +- type_id = spirv_get_type_id(builder, reg->data_type, component_count); ++ type_id = spirv_get_type_id(compiler, reg->data_type, component_count); + return vkd3d_spirv_get_op_undef(builder, type_id); + } + spirv_compiler_emit_dereference_register(compiler, reg, ®_info); +@@ -4776,7 +4778,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, + } + else + { +- type_id = spirv_get_type_id(builder, reg_info.data_type, ++ type_id = spirv_get_type_id(compiler, reg_info.data_type, + vsir_write_mask_component_count(reg_info.write_mask)); + val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_info.id, SpvMemoryAccessMaskNone); + swizzle = data_type_is_64_bit(reg->data_type) ? vsir_swizzle_32_from_64(swizzle) : swizzle; +@@ -4789,13 +4791,13 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, + + if (reg->data_type != VSIR_DATA_BOOL) + { +- type_id = spirv_get_type_id(builder, reg->data_type, component_count); ++ type_id = spirv_get_type_id(compiler, reg->data_type, component_count); + return vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } + + if (reg_info.data_type != VSIR_DATA_U32) + { +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, component_count); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, component_count); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } + +@@ -4848,7 +4850,7 @@ static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, + + if (vsir_write_mask_component_count(dst_write_mask) > 1) + { +- type_id = spirv_get_type_id(builder, data_type, 1); ++ type_id = spirv_get_type_id(compiler, data_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); + component_idx = vsir_write_mask_get_component_idx(write_mask); + component_idx -= vsir_write_mask_get_component_idx(dst_write_mask); +@@ -4875,7 +4877,7 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, uint32_t + + if (dst_component_count == 1 && component_count != 1) + { +- type_id = spirv_get_type_id(builder, data_type, 1); ++ type_id = spirv_get_type_id(compiler, data_type, 1); + val_id = vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, + vsir_write_mask_get_component_idx(dst_write_mask)); + write_mask &= dst_write_mask; +@@ -4888,7 +4890,7 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, uint32_t + + if (dst_component_count != component_count) + { +- type_id = spirv_get_type_id(builder, data_type, dst_component_count); ++ type_id = spirv_get_type_id(compiler, data_type, dst_component_count); + dst_val_id = vkd3d_spirv_build_op_load(builder, type_id, dst_id, SpvMemoryAccessMaskNone); + + VKD3D_ASSERT(component_count <= ARRAY_SIZE(components)); +@@ -4940,7 +4942,7 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, + if (data_type == VSIR_DATA_BOOL) + val_id = spirv_compiler_emit_bool_to_int(compiler, + vsir_write_mask_component_count(src_write_mask), val_id, false); +- type_id = spirv_get_type_id(builder, reg_info.data_type, ++ type_id = spirv_get_type_id(compiler, reg_info.data_type, + vsir_write_mask_component_count(src_write_mask)); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + data_type = reg_info.data_type; +@@ -5021,13 +5023,13 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, dst_type_id, val_id; + +- type_id = spirv_get_type_id(builder, data_type, component_count); ++ type_id = spirv_get_type_id(compiler, data_type, component_count); + if (component_count > 1) + val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, component_ids, component_count); + else + val_id = *component_ids; + +- dst_type_id = spirv_get_type_id(builder, dst->reg.data_type, component_count); ++ dst_type_id = spirv_get_type_id(compiler, dst->reg.data_type, component_count); + if (dst_type_id != type_id) + val_id = vkd3d_spirv_build_op_bitcast(builder, dst_type_id, val_id); + +@@ -5195,7 +5197,7 @@ static uint32_t spirv_compiler_emit_draw_parameter_fixup(struct spirv_compiler * + vkd3d_spirv_add_iface_variable(builder, base_var_id); + spirv_compiler_decorate_builtin(compiler, base_var_id, base); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_I32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_I32, 1); + base_id = vkd3d_spirv_build_op_load(builder, type_id, base_var_id, SpvMemoryAccessMaskNone); + + return vkd3d_spirv_build_op_isub(builder, type_id, index_id, base_id); +@@ -5229,10 +5231,10 @@ static uint32_t frag_coord_fixup(struct spirv_compiler *compiler, uint32_t frag_ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, w_id; + +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, 1); + w_id = vkd3d_spirv_build_op_composite_extract1(builder, type_id, frag_coord_id, 3); + w_id = vkd3d_spirv_build_op_fdiv(builder, type_id, spirv_compiler_get_constant_float(compiler, 1.0f), w_id); +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, VKD3D_VEC4_SIZE); + + return vkd3d_spirv_build_op_composite_insert1(builder, type_id, w_id, frag_coord_id, 3); + } +@@ -5439,7 +5441,7 @@ static uint32_t spirv_compiler_emit_load_invocation_id(struct spirv_compiler *co + uint32_t type_id, id; + + id = spirv_compiler_get_invocation_id(compiler); +- type_id = spirv_get_type_id(builder, VSIR_DATA_I32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_I32, 1); + + return vkd3d_spirv_build_op_load(builder, type_id, id, SpvMemoryAccessMaskNone); + } +@@ -5778,7 +5780,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + vsir_register_init(&dst_reg, reg_type, VSIR_DATA_F32, 1); + dst_reg.idx[0].offset = element_idx; + +- type_id = spirv_get_type_id(builder, data_type, input_component_count); ++ type_id = spirv_get_type_id(compiler, data_type, input_component_count); + + val_id = vkd3d_spirv_build_op_load(builder, type_id, input_id, SpvMemoryAccessMaskNone); + +@@ -5787,7 +5789,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + + if (data_type != VSIR_DATA_F32) + { +- float_type_id = spirv_get_type_id(builder, VSIR_DATA_F32, input_component_count); ++ float_type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, input_component_count); + val_id = vkd3d_spirv_build_op_bitcast(builder, float_type_id, val_id); + } + +@@ -6139,7 +6141,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + + if (data_type != VSIR_DATA_F32) + { +- type_id = spirv_get_type_id(builder, data_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(compiler, data_type, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } + +@@ -6162,7 +6164,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + output_id = output_info->id; + if (output_index_id) + { +- type_id = spirv_get_type_id(builder, data_type, vsir_write_mask_component_count(dst_write_mask)); ++ type_id = spirv_get_type_id(compiler, data_type, vsir_write_mask_component_count(dst_write_mask)); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); + output_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, output_id, output_index_id); + } +@@ -6174,7 +6176,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + return; + } + +- type_id = spirv_get_type_id(builder, data_type, 1); ++ type_id = spirv_get_type_id(compiler, data_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); + mask = output_info->array_element_mask; + array_idx = spirv_compiler_get_output_array_index(compiler, output); +@@ -6216,7 +6218,7 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler * + function_id = compiler->epilogue_function_id; + + void_id = vkd3d_spirv_get_op_type_void(builder); +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 4); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, 4); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id); + for (i = 0, count = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i) + { +@@ -6445,7 +6447,7 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil + function_location = spirv_compiler_get_current_function_location(compiler); + vkd3d_spirv_begin_function_stream_insertion(builder, function_location); + +- type_id = spirv_get_type_id(builder, temp->data_type, temp->component_count); ++ type_id = spirv_get_type_id(compiler, temp->data_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); +@@ -6486,7 +6488,7 @@ static void spirv_compiler_emit_push_constant_buffers(struct spirv_compiler *com + if (!(member_ids = vkd3d_calloc(count, sizeof(*member_ids)))) + return; + +- vec4_id = spirv_get_type_id(builder, VSIR_DATA_F32, VKD3D_VEC4_SIZE); ++ vec4_id = spirv_get_type_id(compiler, VSIR_DATA_F32, VKD3D_VEC4_SIZE); + + for (i = 0, j = 0; i < compiler->shader_interface.push_constant_buffer_count; ++i) + { +@@ -6503,7 +6505,7 @@ static void spirv_compiler_emit_push_constant_buffers(struct spirv_compiler *com + + if (compiler->offset_info.descriptor_table_count) + { +- uint32_t type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ uint32_t type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + length_id = spirv_compiler_get_constant_uint(compiler, compiler->offset_info.descriptor_table_count); + member_ids[j] = vkd3d_spirv_build_op_type_array(builder, type_id, length_id); + vkd3d_spirv_build_op_decorate1(builder, member_ids[j], SpvDecorationArrayStride, 4); +@@ -6696,7 +6698,7 @@ static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, + return; + } + +- vec4_id = spirv_get_type_id(builder, VSIR_DATA_F32, VKD3D_VEC4_SIZE); ++ vec4_id = spirv_get_type_id(compiler, VSIR_DATA_F32, VKD3D_VEC4_SIZE); + length_id = spirv_compiler_get_constant_uint(compiler, size); + array_type_id = vkd3d_spirv_build_op_type_array(builder, vec4_id, length_id); + vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 16); +@@ -6797,6 +6799,8 @@ static SpvImageFormat image_format_for_image_read(enum vsir_data_type data_type) + switch (data_type) + { + case VSIR_DATA_F32: ++ case VSIR_DATA_SNORM: ++ case VSIR_DATA_UNORM: + return SpvImageFormatR32f; + case VSIR_DATA_I32: + return SpvImageFormatR32i; +@@ -6831,7 +6835,7 @@ static uint32_t spirv_compiler_get_image_type_id(struct spirv_compiler *compiler + vkd3d_spirv_enable_capability(builder, SpvCapabilityStorageImageReadWithoutFormat); + } + +- sampled_type_id = spirv_get_type_id(builder, data_type, 1); ++ sampled_type_id = spirv_get_type_id(compiler, data_type, 1); + + return vkd3d_spirv_get_op_type_image(builder, sampled_type_id, resource_type_info->dim, 2, + resource_type_info->arrayed, resource_type_info->ms, reg->type == VKD3DSPR_UAV ? 2 : 1, format); +@@ -6957,7 +6961,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp + { + uint32_t array_type_id, struct_id; + +- type_id = spirv_get_type_id(builder, sampled_type, 1); ++ type_id = spirv_get_type_id(compiler, sampled_type, 1); + + array_type_id = vkd3d_spirv_get_op_type_runtime_array(builder, type_id); + vkd3d_spirv_build_op_decorate1(builder, array_type_id, SpvDecorationArrayStride, 4); +@@ -6998,7 +7002,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp + { + VKD3D_ASSERT(structure_stride); /* counters are valid only for structured buffers */ + +- counter_type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ counter_type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + if (spirv_compiler_is_opengl_target(compiler)) + { + vkd3d_spirv_enable_capability(builder, SpvCapabilityAtomicStorage); +@@ -7062,7 +7066,7 @@ static void spirv_compiler_emit_workgroup_memory(struct spirv_compiler *compiler + if (alignment) + TRACE("Ignoring alignment %u.\n", alignment); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + length_id = spirv_compiler_get_constant_uint(compiler, size); + array_type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); + +@@ -7761,7 +7765,7 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp + component_count = vsir_write_mask_component_count(dst->write_mask); + uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT32_MAX, component_count); + condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpIEqual, +- spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count), val_id, uint_max_id); ++ spirv_get_type_id(compiler, VSIR_DATA_BOOL, component_count), val_id, uint_max_id); + rev_val_id = vkd3d_spirv_build_op_isub(builder, type_id, + spirv_compiler_get_constant_uint_vector(compiler, 31, component_count), val_id); + val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, val_id, rev_val_id); +@@ -7811,7 +7815,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, + dst_id = spirv_compiler_get_register_id(compiler, &dst->reg); + src_id = spirv_compiler_get_register_id(compiler, &src->reg); + +- type_id = spirv_get_type_id(builder, dst_reg_info.data_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(compiler, dst_reg_info.data_type, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_load(builder, type_id, src_id, SpvMemoryAccessMaskNone); + dst_val_id = vkd3d_spirv_build_op_load(builder, type_id, dst_id, SpvMemoryAccessMaskNone); + +@@ -7840,7 +7844,7 @@ general_implementation: + val_id = spirv_compiler_emit_load_src(compiler, src, write_mask); + if (dst->reg.data_type != src->reg.data_type) + { +- val_id = vkd3d_spirv_build_op_bitcast(builder, spirv_get_type_id(builder, ++ val_id = vkd3d_spirv_build_op_bitcast(builder, spirv_get_type_id(compiler, + dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)), val_id); + } + spirv_compiler_emit_store_dst(compiler, dst, val_id); +@@ -7866,7 +7870,7 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, + { + if (instruction->opcode == VSIR_OP_CMP) + condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpFOrdGreaterThanEqual, +- spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count), condition_id, ++ spirv_get_type_id(compiler, VSIR_DATA_BOOL, component_count), condition_id, + spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count)); + else + condition_id = spirv_compiler_emit_int_to_bool(compiler, +@@ -7893,7 +7897,7 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler, + src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask); + + component_count = vsir_write_mask_component_count(dst->write_mask); +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, component_count); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, component_count); + + condition_id = spirv_compiler_emit_int_to_bool(compiler, + VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); +@@ -7929,7 +7933,7 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, + for (i = 0; i < ARRAY_SIZE(src_ids); ++i) + src_ids[i] = spirv_compiler_emit_load_src(compiler, &src[i], write_mask); + +- type_id = spirv_get_type_id(builder, data_type, 1); ++ type_id = spirv_get_type_id(compiler, data_type, 1); + + val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, + SpvOpDot, type_id, src_ids[0], src_ids[1]); +@@ -7972,7 +7976,7 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, + unsigned int i, component_count; + + component_count = vsir_write_mask_component_count(dst->write_mask); +- type_id = spirv_get_type_id(builder, dst->reg.data_type, component_count); ++ type_id = spirv_get_type_id(compiler, dst->reg.data_type, component_count); + + for (i = 0; i < ARRAY_SIZE(src_ids); ++i) + src_ids[i] = spirv_compiler_emit_load_src(compiler, &src[i], dst->write_mask); +@@ -8024,7 +8028,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, + /* VSIR allows the destination of a signed conversion to be unsigned. */ + + int_max_id = spirv_compiler_get_constant_vector(compiler, dst->reg.data_type, component_count, INT_MAX); +- condition_type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); ++ condition_type_id = spirv_get_type_id(compiler, VSIR_DATA_BOOL, component_count); + condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, + SpvOpFOrdGreaterThanEqual, condition_type_id, val_id, float_max_id); + +@@ -8077,7 +8081,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_glsl_std450_max(builder, src_type_id, src_id, zero_id); + + uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT_MAX, component_count); +- condition_type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); ++ condition_type_id = spirv_get_type_id(compiler, VSIR_DATA_BOOL, component_count); + condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, + SpvOpFOrdGreaterThanEqual, condition_type_id, val_id, float_max_id); + +@@ -8102,7 +8106,7 @@ static void spirv_compiler_emit_dtof(struct spirv_compiler *compiler, + + src_id = spirv_compiler_emit_load_src(compiler, src, write_mask); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, component_count); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, component_count); + val_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpFConvert, type_id, src_id); + if (instruction->flags & VKD3DSI_PRECISE_XYZW) + vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); +@@ -8126,7 +8130,7 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp + VKD3D_ASSERT(2 <= src_count && src_count <= ARRAY_SIZE(src_ids)); + + data_type = dst->reg.data_type; +- type_id = spirv_get_type_id(builder, data_type, 1); ++ type_id = spirv_get_type_id(compiler, data_type, 1); + size = data_type_is_64_bit(src[src_count - 1].reg.data_type) ? 0x40 : 0x20; + mask_id = spirv_compiler_get_constant_uint(compiler, size - 1); + size_id = spirv_compiler_get_constant_uint(compiler, size); +@@ -8183,8 +8187,8 @@ static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler, + unsigned int i, j; + + instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); +- scalar_type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, 2); ++ scalar_type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, 1); + + /* FIXME: Consider a single UnpackHalf2x16 instruction per 2 components. */ + VKD3D_ASSERT(dst->write_mask & VKD3DSP_WRITEMASK_ALL); +@@ -8215,8 +8219,8 @@ static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler, + unsigned int i, j; + + instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); +- scalar_type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, 2); ++ scalar_type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + zero_id = spirv_compiler_get_constant_float(compiler, 0.0f); + + /* FIXME: Consider a single PackHalf2x16 instruction per 2 components. */ +@@ -8294,7 +8298,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co + src0_id = spirv_compiler_emit_load_src(compiler, &src[0], write_mask); + src1_id = spirv_compiler_emit_load_src(compiler, &src[1], write_mask); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_BOOL, component_count); + result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, + op, type_id, src0_id, src1_id); + +@@ -8346,7 +8350,7 @@ static void spirv_compiler_emit_float_comparison_instruction(struct spirv_compil + src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); + src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_BOOL, component_count); + result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, src0_id, src1_id); + + result_id = spirv_compiler_emit_bool_to_float(compiler, component_count, result_id, false); +@@ -8873,7 +8877,7 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, + + spirv_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE); + +- type_id = spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(compiler, image.sampled_type, VKD3D_VEC4_SIZE); + coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1; + coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], coordinate_mask); + if (image.resource_type_info->resource_type != VKD3D_SHADER_RESOURCE_BUFFER && !multisample) +@@ -8918,7 +8922,7 @@ static void spirv_compiler_emit_lod(struct spirv_compiler *compiler, + spirv_compiler_prepare_image(compiler, &image, + &resource->reg, &sampler->reg, VKD3D_IMAGE_FLAG_SAMPLED); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, 2); + coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL); + val_id = vkd3d_spirv_build_op_image_query_lod(builder, + type_id, image.sampled_image_id, coordinate_id); +@@ -8987,7 +8991,7 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, + instruction, image.resource_type_info); + } + +- sampled_type_id = spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); ++ sampled_type_id = spirv_get_type_id(compiler, image.sampled_type, VKD3D_VEC4_SIZE); + coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL); + VKD3D_ASSERT(image_operand_count <= ARRAY_SIZE(image_operands)); + val_id = vkd3d_spirv_build_op_image_sample(builder, op, sampled_type_id, +@@ -9031,7 +9035,7 @@ static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, + instruction, image.resource_type_info); + } + +- sampled_type_id = spirv_get_type_id(builder, image.sampled_type, 1); ++ sampled_type_id = spirv_get_type_id(compiler, image.sampled_type, 1); + coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL); + dref_id = spirv_compiler_emit_load_src(compiler, &src[3], VKD3DSP_WRITEMASK_0); + val_id = vkd3d_spirv_build_op_image_sample_dref(builder, op, sampled_type_id, +@@ -9089,7 +9093,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, + instruction, image.resource_type_info); + } + +- sampled_type_id = spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); ++ sampled_type_id = spirv_get_type_id(compiler, image.sampled_type, VKD3D_VEC4_SIZE); + coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1; + coordinate_id = spirv_compiler_emit_load_src(compiler, addr, coordinate_mask); + if (image_flags & VKD3D_IMAGE_FLAG_DEPTH) +@@ -9169,10 +9173,10 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler + + if (storage_buffer_uav) + { +- texel_type_id = spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); ++ texel_type_id = spirv_get_type_id(compiler, resource_symbol->info.resource.sampled_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, texel_type_id); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, + type_id, resource_symbol->info.resource.structure_stride, + &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); +@@ -9204,11 +9208,11 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler + + spirv_compiler_prepare_image(compiler, &image, &resource->reg, NULL, VKD3D_IMAGE_FLAG_NONE); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, + type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); + +- texel_type_id = spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); ++ texel_type_id = spirv_get_type_id(compiler, image.sampled_type, VKD3D_VEC4_SIZE); + VKD3D_ASSERT(dst->write_mask & VKD3DSP_WRITEMASK_ALL); + for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) + { +@@ -9247,7 +9251,7 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, + if (!spirv_compiler_get_register_info(compiler, &resource->reg, ®_info)) + return; + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id); + base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, + type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); +@@ -9306,10 +9310,10 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * + + if (spirv_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource)) + { +- type_id = spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); ++ type_id = spirv_get_type_id(compiler, resource_symbol->info.resource.sampled_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, + type_id, resource_symbol->info.resource.structure_stride, + &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); +@@ -9337,7 +9341,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * + } + else + { +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + spirv_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE); + base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, + type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); +@@ -9380,7 +9384,7 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, + if (!spirv_compiler_get_register_info(compiler, &dst->reg, ®_info)) + return; + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id); + base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, + type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); +@@ -9438,7 +9442,7 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, + + if (spirv_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource)) + { +- type_id = spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); ++ type_id = spirv_get_type_id(compiler, resource_symbol->info.resource.sampled_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); + coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); + indices[0] = spirv_compiler_get_constant_uint(compiler, 0); +@@ -9453,7 +9457,7 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, + else + { + spirv_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE); +- type_id = spirv_get_type_id(builder, image.sampled_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(compiler, image.sampled_type, VKD3D_VEC4_SIZE); + coordinate_mask = (1u << image.resource_type_info->coordinate_component_count) - 1; + coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], coordinate_mask); + +@@ -9480,7 +9484,7 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler, + + if (spirv_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource)) + { +- type_id = spirv_get_type_id(builder, resource_symbol->info.resource.sampled_type, 1); ++ type_id = spirv_get_type_id(compiler, resource_symbol->info.resource.sampled_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); + coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); + indices[0] = spirv_compiler_get_constant_uint(compiler, 0); +@@ -9525,7 +9529,7 @@ static void spirv_compiler_emit_uav_counter_instruction(struct spirv_compiler *c + counter_id = resource_symbol->info.resource.uav_counter_id; + VKD3D_ASSERT(counter_id); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + + if (resource_symbol->info.resource.uav_counter_array) + { +@@ -9686,7 +9690,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + } + } + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + if (structure_stride || raw) + { + VKD3D_ASSERT(!raw != !structure_stride); +@@ -9711,7 +9715,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + if (spirv_compiler_use_storage_buffer(compiler, &resource_symbol->info.resource)) + { + data_type = resource_symbol->info.resource.sampled_type; +- type_id = spirv_get_type_id(builder, data_type, 1); ++ type_id = spirv_get_type_id(compiler, data_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); + operands[0] = spirv_compiler_get_constant_uint(compiler, 0); + operands[1] = coordinate_id; +@@ -9720,7 +9724,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + else + { + data_type = image.sampled_type; +- type_id = spirv_get_type_id(builder, data_type, 1); ++ type_id = spirv_get_type_id(compiler, data_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassImage, type_id); + sample_id = spirv_compiler_get_constant_uint(compiler, 0); + pointer_id = vkd3d_spirv_build_op_image_texel_pointer(builder, +@@ -9769,7 +9773,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, + { + resource_symbol = spirv_compiler_find_resource(compiler, &src->reg); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + val_id = vkd3d_spirv_build_op_array_length(builder, type_id, resource_symbol->id, 0); + write_mask = VKD3DSP_WRITEMASK_0; + } +@@ -9779,7 +9783,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, + + spirv_compiler_prepare_image(compiler, &image, &src->reg, NULL, VKD3D_IMAGE_FLAG_NONE); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + val_id = vkd3d_spirv_build_op_image_query_size(builder, type_id, image.image_id); + write_mask = VKD3DSP_WRITEMASK_0; + } +@@ -9789,7 +9793,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, + stride_id = spirv_compiler_get_constant_uint(compiler, image.structure_stride); + constituents[0] = vkd3d_spirv_build_op_udiv(builder, type_id, val_id, stride_id); + constituents[1] = stride_id; +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, ARRAY_SIZE(constituents)); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, ARRAY_SIZE(constituents)); + val_id = vkd3d_spirv_build_op_composite_construct(builder, + type_id, constituents, ARRAY_SIZE(constituents)); + write_mask |= VKD3DSP_WRITEMASK_1; +@@ -9828,14 +9832,14 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, + size_component_count = image.resource_type_info->coordinate_component_count; + if (image.resource_type_info->dim == SpvDimCube) + --size_component_count; +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, size_component_count); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, size_component_count); + + supports_mipmaps = src[1].reg.type != VKD3DSPR_UAV && !image.resource_type_info->ms; + if (supports_mipmaps) + { + lod_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); + val_id = vkd3d_spirv_build_op_image_query_size_lod(builder, type_id, image.image_id, lod_id); +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + miplevel_count_id = vkd3d_spirv_build_op_image_query_levels(builder, type_id, image.image_id); + } + else +@@ -9849,13 +9853,13 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, + for (i = 0; i < 3 - size_component_count; ++i) + constituents[i + 1] = spirv_compiler_get_constant_uint(compiler, 0); + constituents[i + 1] = miplevel_count_id; +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, constituents, i + 2); + + if (!(instruction->flags & VKD3DSI_RESINFO_UINT)) + { + data_type = VSIR_DATA_F32; +- type_id = spirv_get_type_id(builder, data_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(compiler, data_type, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id); + if (instruction->flags & VKD3DSI_PRECISE_XYZW) + vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); +@@ -9883,7 +9887,7 @@ static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *co + vkd3d_spirv_enable_capability(builder, SpvCapabilityImageQuery); + + spirv_compiler_prepare_image(compiler, &image, &src->reg, NULL, VKD3D_IMAGE_FLAG_NONE); +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + val_id = vkd3d_spirv_build_op_image_query_samples(builder, type_id, image.image_id); + } + +@@ -9912,13 +9916,13 @@ static void spirv_compiler_emit_sample_info(struct spirv_compiler *compiler, + { + constituents[i] = spirv_compiler_get_constant_uint(compiler, 0); + } +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, constituents, VKD3D_VEC4_SIZE); + + if (!(instruction->flags & VKD3DSI_SAMPLE_INFO_UINT)) + { + data_type = VSIR_DATA_F32; +- type_id = spirv_get_type_id(builder, data_type, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(compiler, data_type, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id); + if (instruction->flags & VKD3DSI_PRECISE_XYZW) + vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); +@@ -9984,12 +9988,12 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, + sample_count_id = spirv_compiler_emit_query_sample_count(compiler, &instruction->src[0]); + sample_index_id = spirv_compiler_emit_load_src(compiler, &instruction->src[1], VKD3DSP_WRITEMASK_0); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + index_id = vkd3d_spirv_build_op_iadd(builder, type_id, sample_count_id, sample_index_id); + index_id = vkd3d_spirv_build_op_isub(builder, type_id, index_id, spirv_compiler_get_constant_uint(compiler, 1)); + + /* Validate sample index. */ +- bool_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, 1); ++ bool_id = spirv_get_type_id(compiler, VSIR_DATA_BOOL, 1); + id = vkd3d_spirv_build_op_logical_and(builder, bool_id, + vkd3d_spirv_build_op_uless_than(builder, bool_id, sample_index_id, sample_count_id), + vkd3d_spirv_build_op_uless_than_equal(builder, +@@ -9997,7 +10001,7 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, + index_id = vkd3d_spirv_build_op_select(builder, type_id, + id, index_id, spirv_compiler_get_constant_uint(compiler, 0)); + +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, 2); + if (!(id = compiler->sample_positions_id)) + { + length_id = spirv_compiler_get_constant_uint(compiler, ARRAY_SIZE(standard_sample_positions)); +@@ -10061,7 +10065,7 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, + src_ids[src_count++] = spirv_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0); + } + +- type_id = spirv_get_type_id(builder, VSIR_DATA_F32, ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_F32, + vsir_write_mask_component_count(register_info.write_mask)); + + instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); +@@ -10196,8 +10200,8 @@ static void spirv_compiler_emit_quad_read_across(struct spirv_compiler *compiler + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t type_id, direction_type_id, direction_id, val_id; + +- type_id = spirv_get_type_id(builder, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); +- direction_type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); ++ direction_type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); + direction_id = map_quad_read_across_direction(instruction->opcode); + direction_id = vkd3d_spirv_get_op_constant(builder, direction_type_id, direction_id); +@@ -10221,7 +10225,7 @@ static void spirv_compiler_emit_quad_read_lane_at(struct spirv_compiler *compile + return; + } + +- type_id = spirv_get_type_id(builder, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); ++ type_id = spirv_get_type_id(compiler, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); + val_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); + lane_id = spirv_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0); + val_id = vkd3d_spirv_build_op_group_nonuniform_quad_broadcast(builder, type_id, val_id, lane_id); +@@ -10270,7 +10274,7 @@ static uint32_t spirv_compiler_emit_group_nonuniform_ballot(struct spirv_compile + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, val_id; + +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, VKD3D_VEC4_SIZE); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, VKD3D_VEC4_SIZE); + val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); + val_id = vkd3d_spirv_build_op_group_nonuniform_ballot(builder, type_id, val_id); + +@@ -10329,7 +10333,7 @@ static void spirv_compiler_emit_wave_alu_op(struct spirv_compiler *compiler, + + op = map_wave_alu_op(instruction->opcode, data_type_is_floating_point(src->reg.data_type)); + +- type_id = spirv_get_type_id(builder, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); ++ type_id = spirv_get_type_id(compiler, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); + val_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); + + vkd3d_spirv_enable_capability(builder, SpvCapabilityGroupNonUniformArithmetic); +@@ -10353,7 +10357,7 @@ static void spirv_compiler_emit_wave_bit_count(struct spirv_compiler *compiler, + : SpvGroupOperationReduce; + + val_id = spirv_compiler_emit_group_nonuniform_ballot(compiler, instruction->src); +- type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); ++ type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); + val_id = vkd3d_spirv_build_op_group_nonuniform_ballot_bit_count(builder, type_id, group_op, val_id); + + spirv_compiler_emit_store_dst(compiler, dst, val_id); +@@ -10378,7 +10382,7 @@ static void spirv_compiler_emit_wave_read_lane_at(struct spirv_compiler *compile + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t type_id, lane_id, val_id; + +- type_id = spirv_get_type_id(builder, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); ++ type_id = spirv_get_type_id(compiler, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); + val_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); + lane_id = spirv_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0); + +@@ -10405,7 +10409,7 @@ static void spirv_compiler_emit_wave_read_lane_first(struct spirv_compiler *comp + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t type_id, val_id; + +- type_id = spirv_get_type_id(builder, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); ++ type_id = spirv_get_type_id(compiler, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); + val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); + val_id = vkd3d_spirv_build_op_group_nonuniform_broadcast_first(builder, type_id, val_id); + +@@ -10941,7 +10945,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + { + uint32_t type_id, struct_id, ptr_type_id, var_id; + +- type_id = spirv_get_type_id(builder, parameter_data_type_map[parameter->data_type].type, ++ type_id = spirv_get_type_id(compiler, parameter_data_type_map[parameter->data_type].type, + parameter_data_type_map[parameter->data_type].component_count); + + struct_id = vkd3d_spirv_build_op_type_struct(builder, &type_id, 1); +-- +2.51.0 + diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-cb8c851bec08a9483ce52f57c71922c9b14.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-cb8c851bec08a9483ce52f57c71922c9b14.patch deleted file mode 100644 index 5d71cd67..00000000 --- a/patches/vkd3d-latest/0005-Updated-vkd3d-to-cb8c851bec08a9483ce52f57c71922c9b14.patch +++ /dev/null @@ -1,830 +0,0 @@ -From e19754650a2fae6ebfb0a471026cc5e9683a8237 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 23 Sep 2025 07:11:30 +1000 -Subject: [PATCH] Updated vkd3d to cb8c851bec08a9483ce52f57c71922c9b145b9d3. - ---- - libs/vkd3d/include/private/vkd3d_common.h | 18 ++ - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 9 + - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 6 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 101 ++++++++++ - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 183 ++++++++++++++++++ - .../libs/vkd3d-shader/hlsl_constant_ops.c | 106 ++++++++++ - libs/vkd3d/libs/vkd3d-shader/ir.c | 64 ++++++ - libs/vkd3d/libs/vkd3d-shader/spirv.c | 20 +- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 4 + - 9 files changed, 504 insertions(+), 7 deletions(-) - -diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h -index 8b63acf68e1..c2e957a2fea 100644 ---- a/libs/vkd3d/include/private/vkd3d_common.h -+++ b/libs/vkd3d/include/private/vkd3d_common.h -@@ -343,6 +343,24 @@ static inline unsigned int vkd3d_log2i(unsigned int x) - #endif - } - -+static inline unsigned int vkd3d_ctz(uint32_t v) -+{ -+#ifdef HAVE_BUILTIN_CTZ -+ return __builtin_ctz(v); -+#else -+ unsigned int c = 31; -+ -+ v &= -v; -+ c = (v & 0x0000ffff) ? c - 16 : c; -+ c = (v & 0x00ff00ff) ? c - 8 : c; -+ c = (v & 0x0f0f0f0f) ? c - 4 : c; -+ c = (v & 0x33333333) ? c - 2 : c; -+ c = (v & 0x55555555) ? c - 1 : c; -+ -+ return c; -+#endif -+} -+ - static inline void *vkd3d_memmem( const void *haystack, size_t haystack_len, const void *needle, size_t needle_len) - { - const char *str = haystack; -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index 5a25efdee75..ec1e27d9496 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -393,6 +393,11 @@ bool hlsl_type_is_signed_integer(const struct hlsl_type *type) - vkd3d_unreachable(); - } - -+bool hlsl_type_is_unsigned_integer(const struct hlsl_type *type) -+{ -+ return hlsl_type_is_integer(type) && !hlsl_type_is_signed_integer(type); -+} -+ - bool hlsl_type_is_integer(const struct hlsl_type *type) - { - VKD3D_ASSERT(hlsl_is_numeric_type(type)); -@@ -3724,8 +3729,11 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op) - [HLSL_OP1_BIT_NOT] = "~", - [HLSL_OP1_CAST] = "cast", - [HLSL_OP1_CEIL] = "ceil", -+ [HLSL_OP1_CLZ] = "clz", - [HLSL_OP1_COS] = "cos", - [HLSL_OP1_COS_REDUCED] = "cos_reduced", -+ [HLSL_OP1_COUNTBITS] = "countbits", -+ [HLSL_OP1_CTZ] = "ctz", - [HLSL_OP1_DSX] = "dsx", - [HLSL_OP1_DSX_COARSE] = "dsx_coarse", - [HLSL_OP1_DSX_FINE] = "dsx_fine", -@@ -3735,6 +3743,7 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op) - [HLSL_OP1_EXP2] = "exp2", - [HLSL_OP1_F16TOF32] = "f16tof32", - [HLSL_OP1_F32TOF16] = "f32tof16", -+ [HLSL_OP1_FIND_MSB] = "find_msb", - [HLSL_OP1_FLOOR] = "floor", - [HLSL_OP1_FRACT] = "fract", - [HLSL_OP1_ISINF] = "isinf", -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index a3e8ccc1e2a..8dbfd062177 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -718,8 +718,11 @@ enum hlsl_ir_expr_op - HLSL_OP1_BIT_NOT, - HLSL_OP1_CAST, - HLSL_OP1_CEIL, -+ HLSL_OP1_CLZ, - HLSL_OP1_COS, - HLSL_OP1_COS_REDUCED, /* Reduced range [-pi, pi], writes to .x */ -+ HLSL_OP1_COUNTBITS, -+ HLSL_OP1_CTZ, - HLSL_OP1_DSX, - HLSL_OP1_DSX_COARSE, - HLSL_OP1_DSX_FINE, -@@ -729,6 +732,7 @@ enum hlsl_ir_expr_op - HLSL_OP1_EXP2, - HLSL_OP1_F16TOF32, - HLSL_OP1_F32TOF16, -+ HLSL_OP1_FIND_MSB, - HLSL_OP1_FLOOR, - HLSL_OP1_FRACT, - HLSL_OP1_ISINF, -@@ -1791,10 +1795,10 @@ bool hlsl_type_is_integer(const struct hlsl_type *type); - bool hlsl_type_is_floating_point(const struct hlsl_type *type); - bool hlsl_type_is_row_major(const struct hlsl_type *type); - bool hlsl_type_is_signed_integer(const struct hlsl_type *type); -+bool hlsl_type_is_unsigned_integer(const struct hlsl_type *type); - unsigned int hlsl_type_minor_size(const struct hlsl_type *type); - unsigned int hlsl_type_major_size(const struct hlsl_type *type); - unsigned int hlsl_type_element_count(const struct hlsl_type *type); --bool hlsl_type_is_integer(const struct hlsl_type *type); - bool hlsl_type_is_minimum_precision(const struct hlsl_type *type); - bool hlsl_type_is_resource(const struct hlsl_type *type); - bool hlsl_type_is_shader(const struct hlsl_type *type); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index d83ad9fe7d8..d3004d7cc8a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -3181,6 +3181,20 @@ static bool elementwise_intrinsic_float_convert_args(struct hlsl_ctx *ctx, - return true; - } - -+static bool elementwise_intrinsic_int_convert_args(struct hlsl_ctx *ctx, -+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_type *type; -+ -+ if (!(type = elementwise_intrinsic_get_common_type(ctx, params, loc))) -+ return false; -+ -+ type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_INT, type->e.numeric.dimx, type->e.numeric.dimy); -+ -+ convert_args(ctx, params, type, loc); -+ return true; -+} -+ - static bool elementwise_intrinsic_uint_convert_args(struct hlsl_ctx *ctx, - const struct parse_initializer *params, const struct vkd3d_shader_location *loc) - { -@@ -3579,6 +3593,20 @@ static bool intrinsic_cosh(struct hlsl_ctx *ctx, - return write_cosh_or_sinh(ctx, params, loc, false); - } - -+static bool intrinsic_countbits(struct hlsl_ctx *ctx, -+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; -+ struct hlsl_type *type; -+ -+ if (!elementwise_intrinsic_uint_convert_args(ctx, params, loc)) -+ return false; -+ type = convert_numeric_type(ctx, params->args[0]->data_type, HLSL_TYPE_UINT); -+ -+ operands[0] = params->args[0]; -+ return add_expr(ctx, params->instrs, HLSL_OP1_COUNTBITS, operands, type, loc); -+} -+ - static bool intrinsic_cross(struct hlsl_ctx *ctx, - const struct parse_initializer *params, const struct vkd3d_shader_location *loc) - { -@@ -3925,6 +3953,76 @@ static bool intrinsic_f32tof16(struct hlsl_ctx *ctx, - return add_expr(ctx, params->instrs, HLSL_OP1_F32TOF16, operands, type, loc); - } - -+static bool intrinsic_firstbithigh(struct hlsl_ctx *ctx, -+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; -+ struct hlsl_type *type = params->args[0]->data_type; -+ struct hlsl_ir_node *c, *clz, *eq, *xor; -+ struct hlsl_constant_value v; -+ -+ if (hlsl_version_lt(ctx, 4, 0)) -+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, -+ "The 'firstbithigh' intrinsic requires shader model 4.0 or higher."); -+ -+ if (hlsl_type_is_unsigned_integer(type)) -+ { -+ if (!elementwise_intrinsic_uint_convert_args(ctx, params, loc)) -+ return false; -+ } -+ else -+ { -+ if (!elementwise_intrinsic_int_convert_args(ctx, params, loc)) -+ return false; -+ } -+ type = convert_numeric_type(ctx, type, HLSL_TYPE_UINT); -+ -+ operands[0] = params->args[0]; -+ if (hlsl_version_lt(ctx, 5, 0)) -+ return add_expr(ctx, params->instrs, HLSL_OP1_FIND_MSB, operands, type, loc); -+ -+ v.u[0].u = 0x1f; -+ if (!(c = hlsl_new_constant(ctx, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &v, loc))) -+ return false; -+ hlsl_block_add_instr(params->instrs, c); -+ -+ if (!(clz = add_expr(ctx, params->instrs, HLSL_OP1_CLZ, operands, type, loc))) -+ return false; -+ if (!(xor = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_BIT_XOR, c, clz, loc))) -+ return false; -+ -+ v.u[0].i = -1; -+ if (!(c = hlsl_new_constant(ctx, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &v, loc))) -+ return false; -+ hlsl_block_add_instr(params->instrs, c); -+ -+ if (!(eq = add_binary_comparison_expr(ctx, params->instrs, HLSL_OP2_EQUAL, clz, c, loc))) -+ return false; -+ -+ operands[0] = eq; -+ operands[1] = add_implicit_conversion(ctx, params->instrs, c, type, loc); -+ operands[2] = xor; -+ return add_expr(ctx, params->instrs, HLSL_OP3_TERNARY, operands, type, loc); -+} -+ -+static bool intrinsic_firstbitlow(struct hlsl_ctx *ctx, -+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; -+ struct hlsl_type *type; -+ -+ if (hlsl_version_lt(ctx, 4, 0)) -+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, -+ "The 'firstbitlow' intrinsic requires shader model 4.0 or higher."); -+ -+ if (!elementwise_intrinsic_uint_convert_args(ctx, params, loc)) -+ return false; -+ type = convert_numeric_type(ctx, params->args[0]->data_type, HLSL_TYPE_UINT); -+ -+ operands[0] = params->args[0]; -+ return add_expr(ctx, params->instrs, HLSL_OP1_CTZ, operands, type, loc); -+} -+ - static bool intrinsic_floor(struct hlsl_ctx *ctx, - const struct parse_initializer *params, const struct vkd3d_shader_location *loc) - { -@@ -5317,6 +5415,7 @@ intrinsic_functions[] = - {"clip", 1, true, intrinsic_clip}, - {"cos", 1, true, intrinsic_cos}, - {"cosh", 1, true, intrinsic_cosh}, -+ {"countbits", 1, true, intrinsic_countbits}, - {"cross", 2, true, intrinsic_cross}, - {"ddx", 1, true, intrinsic_ddx}, - {"ddx_coarse", 1, true, intrinsic_ddx_coarse}, -@@ -5334,6 +5433,8 @@ intrinsic_functions[] = - {"f16tof32", 1, true, intrinsic_f16tof32}, - {"f32tof16", 1, true, intrinsic_f32tof16}, - {"faceforward", 3, true, intrinsic_faceforward}, -+ {"firstbithigh", 1, true, intrinsic_firstbithigh}, -+ {"firstbitlow", 1, true, intrinsic_firstbitlow}, - {"floor", 1, true, intrinsic_floor}, - {"fmod", 2, true, intrinsic_fmod}, - {"frac", 1, true, intrinsic_frac}, -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index bb8fdb8bd60..2138c3776a7 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -11057,11 +11057,32 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, - generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_ROUND_PI, 0, 0, true); - return true; - -+ case HLSL_OP1_CLZ: -+ VKD3D_ASSERT(hlsl_type_is_integer(dst_type)); -+ VKD3D_ASSERT(hlsl_version_ge(ctx, 5, 0)); -+ if (hlsl_type_is_signed_integer(src_type)) -+ generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_FIRSTBIT_SHI, 0, 0, true); -+ else -+ generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_FIRSTBIT_HI, 0, 0, true); -+ return true; -+ - case HLSL_OP1_COS: - VKD3D_ASSERT(type_is_float(dst_type)); - sm4_generate_vsir_expr_with_two_destinations(ctx, program, VSIR_OP_SINCOS, expr, 1); - return true; - -+ case HLSL_OP1_COUNTBITS: -+ VKD3D_ASSERT(hlsl_type_is_integer(dst_type)); -+ VKD3D_ASSERT(hlsl_version_ge(ctx, 5, 0)); -+ generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_COUNTBITS, 0, 0, true); -+ return true; -+ -+ case HLSL_OP1_CTZ: -+ VKD3D_ASSERT(hlsl_type_is_integer(dst_type)); -+ VKD3D_ASSERT(hlsl_version_ge(ctx, 5, 0)); -+ generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_FIRSTBIT_LO, 0, 0, true); -+ return true; -+ - case HLSL_OP1_DSX: - VKD3D_ASSERT(type_is_float(dst_type)); - generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VSIR_OP_DSX, 0, 0, true); -@@ -14097,6 +14118,102 @@ static void loop_unrolling_execute(struct hlsl_ctx *ctx, struct hlsl_block *bloc - hlsl_transform_ir(ctx, resolve_loops, block, NULL); - } - -+static bool lower_countbits(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) -+{ -+ struct hlsl_ir_function_decl *func; -+ struct hlsl_ir_node *call, *rhs; -+ struct hlsl_ir_expr *expr; -+ struct hlsl_ir_var *lhs; -+ char *body; -+ -+ /* Like vkd3d_popcount(). */ -+ static const char template[] = -+ "typedef uint%u uintX;\n" -+ "uintX countbits(uintX v)\n" -+ "{\n" -+ " v -= (v >> 1) & 0x55555555;\n" -+ " v = (v & 0x33333333) + ((v >> 2) & 0x33333333);\n" -+ " return (((v + (v >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;\n" -+ "}\n"; -+ -+ if (node->type != HLSL_IR_EXPR) -+ return false; -+ -+ expr = hlsl_ir_expr(node); -+ if (expr->op != HLSL_OP1_COUNTBITS) -+ return false; -+ -+ rhs = expr->operands[0].node; -+ if (!(body = hlsl_sprintf_alloc(ctx, template, hlsl_type_component_count(rhs->data_type)))) -+ return false; -+ func = hlsl_compile_internal_function(ctx, "countbits", body); -+ vkd3d_free(body); -+ if (!func) -+ return false; -+ -+ lhs = func->parameters.vars[0]; -+ hlsl_block_add_simple_store(ctx, block, lhs, rhs); -+ -+ if (!(call = hlsl_new_call(ctx, func, &node->loc))) -+ return false; -+ hlsl_block_add_instr(block, call); -+ -+ hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); -+ -+ return true; -+} -+ -+static bool lower_ctz(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) -+{ -+ struct hlsl_ir_function_decl *func; -+ struct hlsl_ir_node *call, *rhs; -+ struct hlsl_ir_expr *expr; -+ struct hlsl_ir_var *lhs; -+ char *body; -+ -+ /* ctz() returns the bit number of the least significant 1-bit. -+ * Bit numbers count from the least significant bit. */ -+ static const char template[] = -+ "typedef uint%u uintX;\n" -+ "uintX ctz(uintX v)\n" -+ "{\n" -+ " uintX c = 31;\n" -+ " v &= -v;\n" -+ " c = (v & 0x0000ffff) ? c - 16 : c;\n" -+ " c = (v & 0x00ff00ff) ? c - 8 : c;\n" -+ " c = (v & 0x0f0f0f0f) ? c - 4 : c;\n" -+ " c = (v & 0x33333333) ? c - 2 : c;\n" -+ " c = (v & 0x55555555) ? c - 1 : c;\n" -+ " return v ? c : -1;\n" -+ "}\n"; -+ -+ if (node->type != HLSL_IR_EXPR) -+ return false; -+ -+ expr = hlsl_ir_expr(node); -+ if (expr->op != HLSL_OP1_CTZ) -+ return false; -+ -+ rhs = expr->operands[0].node; -+ if (!(body = hlsl_sprintf_alloc(ctx, template, hlsl_type_component_count(rhs->data_type)))) -+ return false; -+ func = hlsl_compile_internal_function(ctx, "ctz", body); -+ vkd3d_free(body); -+ if (!func) -+ return false; -+ -+ lhs = func->parameters.vars[0]; -+ hlsl_block_add_simple_store(ctx, block, lhs, rhs); -+ -+ if (!(call = hlsl_new_call(ctx, func, &node->loc))) -+ return false; -+ hlsl_block_add_instr(block, call); -+ -+ hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); -+ -+ return true; -+} -+ - static bool lower_f16tof32(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) - { - struct hlsl_ir_function_decl *func; -@@ -14239,6 +14356,69 @@ static bool lower_f32tof16(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, stru - return true; - } - -+static bool lower_find_msb(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) -+{ -+ struct hlsl_ir_function_decl *func; -+ struct hlsl_ir_node *call, *rhs; -+ struct hlsl_ir_expr *expr; -+ struct hlsl_ir_var *lhs; -+ char *body; -+ -+ /* For positive numbers, find_msb() returns the bit number of the most -+ * significant 1-bit. For negative numbers, it returns the bit number of -+ * the most significant 0-bit. Bit numbers count from the least -+ * significant bit. */ -+ static const char template[] = -+ "typedef %s intX;\n" -+ "uint%u find_msb(intX v)\n" -+ "{\n" -+ " intX c, mask;\n" -+ " v = v < 0 ? ~v : v;\n" -+ " mask = v & 0xffff0000;\n" -+ " v = mask ? mask : v;\n" -+ " c = mask ? 16 : v ? 0 : -1;\n" -+ " mask = v & 0xff00ff00;\n" -+ " v = mask ? mask : v;\n" -+ " c = mask ? c + 8 : c;\n" -+ " mask = v & 0xf0f0f0f0;\n" -+ " v = mask ? mask : v;\n" -+ " c = mask ? c + 4 : c;\n" -+ " mask = v & 0xcccccccc;\n" -+ " v = mask ? mask : v;\n" -+ " c = mask ? c + 2 : c;\n" -+ " mask = v & 0xaaaaaaaa;\n" -+ " v = mask ? mask : v;\n" -+ " c = mask ? c + 1 : c;\n" -+ " return c;\n" -+ "}\n"; -+ -+ if (node->type != HLSL_IR_EXPR) -+ return false; -+ -+ expr = hlsl_ir_expr(node); -+ if (expr->op != HLSL_OP1_FIND_MSB) -+ return false; -+ -+ rhs = expr->operands[0].node; -+ if (!(body = hlsl_sprintf_alloc(ctx, template, rhs->data_type->name, hlsl_type_component_count(rhs->data_type)))) -+ return false; -+ func = hlsl_compile_internal_function(ctx, "find_msb", body); -+ vkd3d_free(body); -+ if (!func) -+ return false; -+ -+ lhs = func->parameters.vars[0]; -+ hlsl_block_add_simple_store(ctx, block, lhs, rhs); -+ -+ if (!(call = hlsl_new_call(ctx, func, &node->loc))) -+ return false; -+ hlsl_block_add_instr(block, call); -+ -+ hlsl_block_add_simple_load(ctx, block, func->return_var, &node->loc); -+ -+ return true; -+} -+ - static bool lower_isinf(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block) - { - struct hlsl_ir_function_decl *func; -@@ -14355,8 +14535,11 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v - - if (hlsl_version_ge(ctx, 4, 0) && hlsl_version_lt(ctx, 5, 0)) - { -+ lower_ir(ctx, lower_countbits, body); -+ lower_ir(ctx, lower_ctz, body); - lower_ir(ctx, lower_f16tof32, body); - lower_ir(ctx, lower_f32tof16, body); -+ lower_ir(ctx, lower_find_msb, body); - } - - lower_ir(ctx, lower_isinf, body); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c -index 252ed51a4e4..7b3b0470d5d 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c -@@ -250,6 +250,35 @@ static bool fold_ceil(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, - return true; - } - -+static bool fold_clz(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, -+ const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) -+{ -+ enum hlsl_base_type type = src->node.data_type->e.numeric.type; -+ unsigned int k, v; -+ -+ for (k = 0; k < dst_type->e.numeric.dimx; ++k) -+ { -+ switch (type) -+ { -+ case HLSL_TYPE_INT: -+ v = src->value.u[k].i < 0 ? ~src->value.u[k].u : src->value.u[k].u; -+ break; -+ -+ case HLSL_TYPE_UINT: -+ v = src->value.u[k].u; -+ break; -+ -+ default: -+ FIXME("Fold 'clz' for type %s.\n", debug_hlsl_type(ctx, dst_type)); -+ return false; -+ } -+ -+ dst->u[k].u = v ? vkd3d_log2i(v) ^ 0x1f : ~0u; -+ } -+ -+ return true; -+} -+ - static bool fold_cos(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, - const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) - { -@@ -280,6 +309,59 @@ static bool fold_cos(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, - return true; - } - -+static bool fold_countbits(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, -+ const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) -+{ -+ enum hlsl_base_type type = dst_type->e.numeric.type; -+ unsigned int k; -+ -+ VKD3D_ASSERT(type == src->node.data_type->e.numeric.type); -+ -+ for (k = 0; k < dst_type->e.numeric.dimx; ++k) -+ { -+ switch (type) -+ { -+ case HLSL_TYPE_UINT: -+ dst->u[k].u = vkd3d_popcount(src->value.u[k].u); -+ break; -+ -+ default: -+ FIXME("Fold 'countbits' for type %s.\n", debug_hlsl_type(ctx, dst_type)); -+ return false; -+ } -+ } -+ -+ return true; -+} -+ -+static bool fold_ctz(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, -+ const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) -+{ -+ enum hlsl_base_type type = dst_type->e.numeric.type; -+ unsigned int k; -+ -+ VKD3D_ASSERT(type == src->node.data_type->e.numeric.type); -+ -+ for (k = 0; k < dst_type->e.numeric.dimx; ++k) -+ { -+ switch (type) -+ { -+ case HLSL_TYPE_UINT: -+ if (!src->value.u[k].u) -+ dst->u[k].u = ~0u; -+ else -+ dst->u[k].u = vkd3d_ctz(src->value.u[k].u); -+ break; -+ -+ default: -+ FIXME("Fold 'ctz' for type %s.\n", debug_hlsl_type(ctx, dst_type)); -+ return false; -+ } -+ } -+ -+ return true; -+} -+ - static bool fold_exp2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, - const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) - { -@@ -1403,10 +1485,22 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, - success = fold_ceil(ctx, &res, instr->data_type, arg1); - break; - -+ case HLSL_OP1_CLZ: -+ success = fold_clz(ctx, &res, instr->data_type, arg1); -+ break; -+ - case HLSL_OP1_COS: - success = fold_cos(ctx, &res, instr->data_type, arg1); - break; - -+ case HLSL_OP1_COUNTBITS: -+ success = fold_countbits(ctx, &res, instr->data_type, arg1); -+ break; -+ -+ case HLSL_OP1_CTZ: -+ success = fold_ctz(ctx, &res, instr->data_type, arg1); -+ break; -+ - case HLSL_OP1_EXP2: - success = fold_exp2(ctx, &res, instr->data_type, arg1); - break; -@@ -1555,6 +1649,7 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, - - bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) - { -+ static const struct hlsl_constant_value zero; - struct hlsl_ir_constant *const_arg = NULL; - struct hlsl_ir_node *mut_arg = NULL; - struct hlsl_ir_node *res_node; -@@ -1617,6 +1712,17 @@ bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *in - res_node = &const_arg->node; - break; - -+ case HLSL_OP2_LESS: -+ /* x < 0 -> false, if x is unsigned. */ -+ if (!hlsl_type_is_unsigned_integer(expr->operands[0].node->data_type) -+ || expr->operands[1].node->type != HLSL_IR_CONSTANT -+ || !hlsl_constant_is_zero(hlsl_ir_constant(expr->operands[1].node))) -+ break; -+ if (!(res_node = hlsl_new_constant(ctx, instr->data_type, &zero, &instr->loc))) -+ break; -+ list_add_before(&expr->node.entry, &res_node->entry); -+ break; -+ - default: - break; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index a242f32d824..d765b5acccd 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -9885,6 +9885,37 @@ static void vsir_validate_io_register(struct validation_context *ctx, const stru - reg->idx[control_point_index].offset, control_point_count, reg->type); - } - -+static void vsir_validate_texture_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg) -+{ -+ const struct vkd3d_shader_version *version = &ctx->program->shader_version; -+ uint32_t idx; -+ -+ if (version->type != VKD3D_SHADER_TYPE_PIXEL) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "TEXTURE registers cannot be used in shader type %#x.", version->type); -+ -+ if (reg->idx_count != 1) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, -+ "Invalid index count %u for a TEXTURE register.", reg->idx_count); -+ return; -+ } -+ -+ if (reg->idx[0].rel_addr) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "Non-NULL relative address for a TEXTURE register."); -+ -+ if (version->major >= 3) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "TEXTURE registers cannot be used in version %u.%u.", version->major, version->minor); -+ -+ idx = reg->idx[0].offset; -+ if (idx >= 8 || (vkd3d_shader_ver_le(version, 1, 4) && idx >= 6) -+ || (vkd3d_shader_ver_le(version, 1, 3) && idx >= 4)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "Register t%u exceeds limits for version %u.%u.", idx, version->major, version->minor); -+} -+ - static void vsir_validate_temp_register(struct validation_context *ctx, - const struct vkd3d_shader_register *reg) - { -@@ -10354,6 +10385,10 @@ static void vsir_validate_register(struct validation_context *ctx, - vsir_validate_register_without_indices(ctx, reg); - break; - -+ case VKD3DSPR_TEXTURE: -+ vsir_validate_texture_register(ctx, reg); -+ break; -+ - case VKD3DSPR_SSA: - vsir_validate_ssa_register(ctx, reg); - break; -@@ -10402,6 +10437,8 @@ static void vsir_validate_io_dst_param(struct validation_context *ctx, - static void vsir_validate_dst_param(struct validation_context *ctx, - const struct vkd3d_shader_dst_param *dst) - { -+ const struct vkd3d_shader_version *version = &ctx->program->shader_version; -+ - vsir_validate_register(ctx, &dst->reg); - - if (dst->write_mask & ~VKD3DSP_WRITEMASK_ALL) -@@ -10531,6 +10568,11 @@ static void vsir_validate_dst_param(struct validation_context *ctx, - vsir_validate_io_dst_param(ctx, dst); - break; - -+ case VKD3DSPR_TEXTURE: -+ if (vkd3d_shader_ver_ge(version, 1, 4)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Texture registers cannot be written in version %u.%u.", version->major, version->minor); -+ - default: - break; - } -@@ -11511,6 +11553,27 @@ static void vsir_validate_shift_operation(struct validation_context *ctx, - vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - } - -+static void vsir_validate_bem(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) -+{ -+ const struct vkd3d_shader_version *version = &ctx->program->shader_version; -+ -+ if (version->type != VKD3D_SHADER_TYPE_PIXEL) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "BEM cannot be used in shader type %#x.", version->type); -+ -+ if (version->major != 1 || version->minor != 4) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE, -+ "BEM cannot be used in version %u.%u.", version->major, version->minor); -+ -+ if (instruction->dst[0].write_mask != 0x3) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, -+ "Invalid BEM write mask %#x.", instruction->dst[0].write_mask); -+ -+ /* Strictly not an elementwise operation, but we expect all the arguments -+ * to be float. */ -+ vsir_validate_float_elementwise_operation(ctx, instruction); -+} -+ - static void vsir_validate_branch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) - { - size_t i; -@@ -12353,6 +12416,7 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ - [VSIR_OP_AND] = {1, 2, vsir_validate_logic_elementwise_operation}, - [VSIR_OP_ASIN] = {1, 1, vsir_validate_float_elementwise_operation}, - [VSIR_OP_ATAN] = {1, 1, vsir_validate_float_elementwise_operation}, -+ [VSIR_OP_BEM] = {1, 2, vsir_validate_bem}, - [VSIR_OP_BRANCH] = {0, ~0u, vsir_validate_branch}, - [VSIR_OP_DADD] = {1, 2, vsir_validate_double_elementwise_operation}, - [VSIR_OP_DCL_GS_INSTANCES] = {0, 0, vsir_validate_dcl_gs_instances}, -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 0fdeba75c58..434be05e786 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -3254,6 +3254,14 @@ static struct spirv_compiler *spirv_compiler_create(struct vsir_program *program - compiler->features = option->value; - break; - -+ case VKD3D_SHADER_COMPILE_OPTION_PACK_MATRIX_ORDER: -+ case VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY: -+ case VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT: -+ case VKD3D_SHADER_COMPILE_OPTION_WARN_IMPLICIT_TRUNCATION: -+ case VKD3D_SHADER_COMPILE_OPTION_INCLUDE_EMPTY_BUFFERS_IN_EFFECTS: -+ /* Explicitly ignored for this target. */ -+ break; -+ - default: - WARN("Ignoring unrecognised option %#x with value %#x.\n", option->name, option->value); - break; -@@ -8347,8 +8355,8 @@ static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler, - unsigned int i, j; - - instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -- scalar_type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); -+ scalar_type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); - zero_id = spirv_compiler_get_constant_float(compiler, 0.0f); - - /* FIXME: Consider a single PackHalf2x16 instruction per 2 components. */ -@@ -8427,7 +8435,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co - src0_id = spirv_compiler_emit_load_src(compiler, &src[0], write_mask); - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], write_mask); - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); - result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, - op, type_id, src0_id, src1_id); - -@@ -8479,7 +8487,7 @@ static void spirv_compiler_emit_float_comparison_instruction(struct spirv_compil - src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); - result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, src0_id, src1_id); - - result_id = spirv_compiler_emit_bool_to_float(compiler, component_count, result_id, false); -@@ -9054,7 +9062,7 @@ static void spirv_compiler_emit_lod(struct spirv_compiler *compiler, - spirv_compiler_prepare_image(compiler, &image, - &resource->reg, &sampler->reg, VKD3D_IMAGE_FLAG_SAMPLED); - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); - coordinate_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_ALL); - val_id = vkd3d_spirv_build_op_image_query_lod(builder, - type_id, image.sampled_image_id, coordinate_id); -@@ -9388,7 +9396,7 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, - if (!spirv_compiler_get_register_info(compiler, &resource->reg, ®_info)) - return; - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id); - base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, - type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 7ff2a305cfa..8f2d3dd48ca 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -4248,6 +4248,7 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ - case VSIR_OP_BREAK: - case VSIR_OP_CASE: - case VSIR_OP_CONTINUE: -+ case VSIR_OP_COUNTBITS: - case VSIR_OP_CUT: - case VSIR_OP_CUT_STREAM: - case VSIR_OP_DCL_STREAM: -@@ -4273,6 +4274,9 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ - case VSIR_OP_EXP: - case VSIR_OP_F16TOF32: - case VSIR_OP_F32TOF16: -+ case VSIR_OP_FIRSTBIT_HI: -+ case VSIR_OP_FIRSTBIT_LO: -+ case VSIR_OP_FIRSTBIT_SHI: - case VSIR_OP_FRC: - case VSIR_OP_FTOI: - case VSIR_OP_FTOU: --- -2.51.0 - diff --git a/patches/vkd3d-latest/0006-Updated-vkd3d-to-b4174f52521fa4921babad6f1c374d5e9c2.patch b/patches/vkd3d-latest/0006-Updated-vkd3d-to-b4174f52521fa4921babad6f1c374d5e9c2.patch deleted file mode 100644 index 9c3befcd..00000000 --- a/patches/vkd3d-latest/0006-Updated-vkd3d-to-b4174f52521fa4921babad6f1c374d5e9c2.patch +++ /dev/null @@ -1,1243 +0,0 @@ -From 29ba3145cd22f1e29bb71b166cedfa8aedf95a4a Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 30 Sep 2025 07:43:05 +1000 -Subject: [PATCH] Updated vkd3d to b4174f52521fa4921babad6f1c374d5e9c218c95. - ---- - libs/vkd3d/libs/vkd3d-shader/ir.c | 427 ++++++++++-------- - libs/vkd3d/libs/vkd3d-shader/msl.c | 15 + - libs/vkd3d/libs/vkd3d-shader/spirv.c | 44 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 16 +- - 4 files changed, 282 insertions(+), 220 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index d765b5acccd..43bd799d2eb 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -502,6 +502,14 @@ bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *a - return true; - } - -+struct vkd3d_shader_instruction *shader_instruction_array_append(struct vkd3d_shader_instruction_array *array) -+{ -+ if (!shader_instruction_array_insert_at(array, array->count, 1)) -+ return NULL; -+ -+ return &array->elements[array->count - 1]; -+} -+ - bool vsir_program_add_icb(struct vsir_program *program, struct vkd3d_shader_immediate_constant_buffer *icb) - { - if (!vkd3d_array_reserve((void **)&program->icbs, &program->icb_capacity, -@@ -3842,6 +3850,17 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog - return VKD3D_OK; - } - -+/* NOTE: This invalidates all iterators, since the position of the -+ * vkd3d_shader_instruction_array itself changes. */ -+static void vsir_program_replace_instructions(struct vsir_program *program, -+ struct vkd3d_shader_instruction_array *array) -+{ -+ shader_instruction_array_destroy(&program->instructions); -+ -+ program->instructions = *array; -+ memset(array, 0, sizeof(*array)); -+} -+ - struct cf_flattener_if_info - { - struct vkd3d_shader_src_param *false_param; -@@ -3865,7 +3884,7 @@ struct cf_flattener_switch_case - - struct cf_flattener_switch_info - { -- size_t ins_location; -+ struct vsir_program_iterator ins_it; - const struct vkd3d_shader_src_param *condition; - unsigned int id; - unsigned int merge_block_id; -@@ -3900,9 +3919,7 @@ struct cf_flattener - struct vkd3d_shader_location location; - enum vkd3d_result status; - -- struct vkd3d_shader_instruction *instructions; -- size_t instruction_capacity; -- size_t instruction_count; -+ struct vkd3d_shader_instruction_array instructions; - - unsigned int block_id; - const char **block_names; -@@ -3925,18 +3942,6 @@ static void cf_flattener_set_error(struct cf_flattener *flattener, enum vkd3d_re - flattener->status = error; - } - --static struct vkd3d_shader_instruction *cf_flattener_require_space(struct cf_flattener *flattener, size_t count) --{ -- if (!vkd3d_array_reserve((void **)&flattener->instructions, &flattener->instruction_capacity, -- flattener->instruction_count + count, sizeof(*flattener->instructions))) -- { -- ERR("Failed to allocate instructions.\n"); -- cf_flattener_set_error(flattener, VKD3D_ERROR_OUT_OF_MEMORY); -- return NULL; -- } -- return &flattener->instructions[flattener->instruction_count]; --} -- - static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, - const struct vkd3d_shader_instruction *instruction) - { -@@ -3945,11 +3950,10 @@ static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, - if (instruction->opcode == VSIR_OP_NOP) - return true; - -- if (!(dst_ins = cf_flattener_require_space(flattener, 1))) -+ if (!(dst_ins = shader_instruction_array_append(&flattener->instructions))) - return false; - - *dst_ins = *instruction; -- ++flattener->instruction_count; - return true; - } - -@@ -3977,12 +3981,13 @@ static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int - { - struct vkd3d_shader_instruction *ins; - -- if (!(ins = cf_flattener_require_space(flattener, 1))) -+ if (!(ins = shader_instruction_array_append(&flattener->instructions))) - return; -- if (vsir_instruction_init_label(ins, &flattener->location, label_id, flattener->program)) -- ++flattener->instruction_count; -- else -+ if (!vsir_instruction_init_label(ins, &flattener->location, label_id, flattener->program)) -+ { -+ vkd3d_shader_instruction_make_nop(ins); - cf_flattener_set_error(flattener, VKD3D_ERROR_OUT_OF_MEMORY); -+ } - } - - /* For conditional branches, this returns the false target branch parameter. */ -@@ -3994,14 +3999,17 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten - struct vkd3d_shader_src_param *src_params, *false_branch_param; - struct vkd3d_shader_instruction *ins; - -- if (!(ins = cf_flattener_require_space(flattener, 1))) -+ if (!(ins = shader_instruction_array_append(&flattener->instructions))) - return NULL; - vsir_instruction_init(ins, &flattener->location, VSIR_OP_BRANCH); - - if (condition) - { - if (!(src_params = instruction_src_params_alloc(ins, 4 + !!continue_block_id, flattener))) -+ { -+ vkd3d_shader_instruction_make_nop(ins); - return NULL; -+ } - src_params[0] = *condition; - if (flags == VKD3D_SHADER_CONDITIONAL_OP_Z) - { -@@ -4022,7 +4030,10 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten - else - { - if (!(src_params = instruction_src_params_alloc(ins, merge_block_id ? 3 : 1, flattener))) -+ { -+ vkd3d_shader_instruction_make_nop(ins); - return NULL; -+ } - vsir_src_param_init_label(&src_params[0], true_id); - if (merge_block_id) - { -@@ -4034,8 +4045,6 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten - false_branch_param = NULL; - } - -- ++flattener->instruction_count; -- - return false_branch_param; - } - -@@ -4141,8 +4150,12 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte - is_hull_shader = program->shader_version.type == VKD3D_SHADER_TYPE_HULL; - after_declarations_section = is_hull_shader; - -- if (!cf_flattener_require_space(flattener, instructions->count + 1)) -+ if (!shader_instruction_array_reserve(&flattener->instructions, instructions->count + 1)) -+ { -+ ERR("Failed to allocate instructions.\n"); -+ cf_flattener_set_error(flattener, VKD3D_ERROR_OUT_OF_MEMORY); - return VKD3D_ERROR_OUT_OF_MEMORY; -+ } - - it = vsir_program_iterator(instructions); - for (instruction = vsir_program_iterator_head(&it); instruction; instruction = vsir_program_iterator_next(&it)) -@@ -4282,13 +4295,14 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte - - merge_block_id = cf_flattener_alloc_block_id(flattener); - -- cf_info->u.switch_.ins_location = flattener->instruction_count; - cf_info->u.switch_.condition = src; - -- if (!(dst_ins = cf_flattener_require_space(flattener, 1))) -+ if (!(dst_ins = shader_instruction_array_append(&flattener->instructions))) - return VKD3D_ERROR_OUT_OF_MEMORY; - vsir_instruction_init(dst_ins, &instruction->location, VSIR_OP_SWITCH_MONOLITHIC); -- ++flattener->instruction_count; -+ -+ cf_info->u.switch_.ins_it = vsir_program_iterator(&flattener->instructions); -+ vsir_program_iterator_tail(&cf_info->u.switch_.ins_it); - - cf_info->u.switch_.id = flattener->switch_id; - cf_info->u.switch_.merge_block_id = merge_block_id; -@@ -4321,8 +4335,12 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte - /* The SWITCH instruction is completed when the endswitch - * instruction is processed because we do not know the number - * of case statements or the default block id in advance.*/ -- dst_ins = &flattener->instructions[cf_info->u.switch_.ins_location]; -- if (!(src_params = instruction_src_params_alloc(dst_ins, cf_info->u.switch_.cases_count * 2 + 3, flattener))) -+ /* NOTE: This relies on iterators not being invalidated -+ * when new instructions are appended to the -+ * vkd3d_shader_instruction_array. */ -+ dst_ins = vsir_program_iterator_current(&cf_info->u.switch_.ins_it); -+ if (!(src_params = instruction_src_params_alloc(dst_ins, -+ cf_info->u.switch_.cases_count * 2 + 3, flattener))) - { - vkd3d_free(cf_info->u.switch_.cases); - return VKD3D_ERROR_OUT_OF_MEMORY; -@@ -4485,16 +4503,13 @@ static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsi - - if ((result = cf_flattener_iterate_instruction_array(&flattener, message_context)) >= 0) - { -- vkd3d_free(program->instructions.elements); -- program->instructions.elements = flattener.instructions; -- program->instructions.capacity = flattener.instruction_capacity; -- program->instructions.count = flattener.instruction_count; -+ vsir_program_replace_instructions(program, &flattener.instructions); - program->block_count = flattener.block_id; - program->cf_type = VSIR_CF_BLOCKS; - } - else - { -- vkd3d_free(flattener.instructions); -+ shader_instruction_array_destroy(&flattener.instructions); - } - - vkd3d_free(flattener.control_flow_info); -@@ -4511,17 +4526,6 @@ static unsigned int label_from_src_param(const struct vkd3d_shader_src_param *pa - return param->reg.idx[0].offset; - } - --static bool reserve_instructions(struct vkd3d_shader_instruction **instructions, size_t *capacity, size_t count) --{ -- if (!vkd3d_array_reserve((void **)instructions, capacity, count, sizeof(**instructions))) -- { -- ERR("Failed to allocate instructions.\n"); -- return false; -- } -- -- return true; --} -- - /* A record represents replacing a jump from block `switch_label' to - * block `target_label' with a jump from block `if_label' to block - * `target_label'. */ -@@ -4555,14 +4559,14 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs - { - unsigned int block_count = program->block_count, ssa_count = program->ssa_count, current_label = 0, if_label; - struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); -- size_t ins_capacity = 0, ins_count = 0, map_capacity = 0, map_count = 0; -- struct vkd3d_shader_instruction *instructions = NULL; - struct lower_switch_to_if_ladder_block_mapping *block_map = NULL; -- struct vkd3d_shader_instruction *ins; -+ struct vkd3d_shader_instruction_array instructions = {0}; -+ struct vkd3d_shader_instruction *ins, *dst_ins; -+ size_t map_capacity = 0, map_count = 0; - - VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); - -- if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count)) -+ if (!shader_instruction_array_reserve(&instructions, program->instructions.count)) - goto fail; - - /* First subpass: convert SWITCH_MONOLITHIC instructions to -@@ -4576,18 +4580,18 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs - { - case VSIR_OP_LABEL: - current_label = label_from_src_param(&ins->src[0]); -- if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) -+ if (!(dst_ins = shader_instruction_array_append(&instructions))) - goto fail; -- instructions[ins_count++] = *ins; -+ *dst_ins = *ins; - continue; - - case VSIR_OP_SWITCH_MONOLITHIC: - break; - - default: -- if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) -+ if (!(dst_ins = shader_instruction_array_append(&instructions))) - goto fail; -- instructions[ins_count++] = *ins; -+ *dst_ins = *ins; - continue; - } - -@@ -4598,17 +4602,18 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs - * just have to jump to the default label. */ - if (case_count == 0) - { -- if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) -+ if (!(dst_ins = shader_instruction_array_append(&instructions))) - goto fail; - -- if (!vsir_instruction_init_with_params(program, &instructions[ins_count], -- &ins->location, VSIR_OP_BRANCH, 0, 1)) -+ if (!vsir_instruction_init_with_params(program, dst_ins, &ins->location, VSIR_OP_BRANCH, 0, 1)) -+ { -+ vkd3d_shader_instruction_make_nop(dst_ins); - goto fail; -- vsir_src_param_init_label(&instructions[ins_count].src[0], default_label); -- ++ins_count; -+ } -+ vsir_src_param_init_label(&dst_ins->src[0], default_label); - } - -- if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 3 * case_count - 1)) -+ if (!shader_instruction_array_reserve(&instructions, instructions.count + 3 * case_count - 1)) - goto fail; - - if_label = current_label; -@@ -4617,13 +4622,15 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs - { - unsigned int fallthrough_label, case_label = label_from_src_param(&ins->src[3 + 2 * j + 1]); - -- if (!vsir_instruction_init_with_params(program, -- &instructions[ins_count], &ins->location, VSIR_OP_IEQ, 1, 2)) -+ dst_ins = shader_instruction_array_append(&instructions); -+ if (!vsir_instruction_init_with_params(program, dst_ins, &ins->location, VSIR_OP_IEQ, 1, 2)) -+ { -+ vkd3d_shader_instruction_make_nop(dst_ins); - goto fail; -- dst_param_init_ssa_bool(&instructions[ins_count].dst[0], ssa_count); -- instructions[ins_count].src[0] = ins->src[0]; -- instructions[ins_count].src[1] = ins->src[3 + 2 * j]; -- ++ins_count; -+ } -+ dst_param_init_ssa_bool(&dst_ins->dst[0], ssa_count); -+ dst_ins->src[0] = ins->src[0]; -+ dst_ins->src[1] = ins->src[3 + 2 * j]; - - /* For all cases except the last one we fall through to - * the following case; the last one has to jump to the -@@ -4633,13 +4640,15 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs - else - fallthrough_label = block_count + 1; - -- if (!vsir_instruction_init_with_params(program, &instructions[ins_count], -- &ins->location, VSIR_OP_BRANCH, 0, 3)) -+ dst_ins = shader_instruction_array_append(&instructions); -+ if (!vsir_instruction_init_with_params(program, dst_ins, &ins->location, VSIR_OP_BRANCH, 0, 3)) -+ { -+ vkd3d_shader_instruction_make_nop(dst_ins); - goto fail; -- src_param_init_ssa_bool(&instructions[ins_count].src[0], ssa_count); -- vsir_src_param_init_label(&instructions[ins_count].src[1], case_label); -- vsir_src_param_init_label(&instructions[ins_count].src[2], fallthrough_label); -- ++ins_count; -+ } -+ src_param_init_ssa_bool(&dst_ins->src[0], ssa_count); -+ vsir_src_param_init_label(&dst_ins->src[1], case_label); -+ vsir_src_param_init_label(&dst_ins->src[2], fallthrough_label); - - ++ssa_count; - -@@ -4655,29 +4664,28 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs - } - else - { -- if (!vsir_instruction_init_with_params(program, -- &instructions[ins_count], &ins->location, VSIR_OP_LABEL, 0, 1)) -+ dst_ins = shader_instruction_array_append(&instructions); -+ if (!vsir_instruction_init_with_params(program, dst_ins, &ins->location, VSIR_OP_LABEL, 0, 1)) -+ { -+ vkd3d_shader_instruction_make_nop(dst_ins); - goto fail; -- vsir_src_param_init_label(&instructions[ins_count].src[0], ++block_count); -- ++ins_count; -+ } -+ vsir_src_param_init_label(&dst_ins->src[0], ++block_count); - - if_label = block_count; - } - } - } - -- vkd3d_free(program->instructions.elements); -+ vsir_program_replace_instructions(program, &instructions); - vkd3d_free(block_map); -- program->instructions.elements = instructions; -- program->instructions.capacity = ins_capacity; -- program->instructions.count = ins_count; - program->block_count = block_count; - program->ssa_count = ssa_count; - - return VKD3D_OK; - - fail: -- vkd3d_free(instructions); -+ shader_instruction_array_destroy(&instructions); - vkd3d_free(block_map); - - return VKD3D_ERROR_OUT_OF_MEMORY; -@@ -4748,11 +4756,11 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ - struct vsir_transformation_context *ctx) - { - struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); -- size_t ins_capacity = 0, ins_count = 0, phi_count, incoming_count; - struct ssas_to_temps_block_info *info, *block_info = NULL; -- struct vkd3d_shader_instruction *instructions = NULL; -+ struct vkd3d_shader_instruction_array instructions = {0}; -+ struct vkd3d_shader_instruction *ins, *dst_ins; - struct ssas_to_temps_alloc alloc = {0}; -- struct vkd3d_shader_instruction *ins; -+ size_t phi_count, incoming_count; - unsigned int current_label = 0; - - VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); -@@ -4809,7 +4817,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ - if (!phi_count) - goto done; - -- if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count + incoming_count - phi_count)) -+ if (!shader_instruction_array_reserve(&instructions, program->instructions.count + incoming_count - phi_count)) - goto fail; - - for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) -@@ -4837,9 +4845,12 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ - { - struct phi_incoming_to_temp *incoming = &info->incomings[j]; - -- mov_ins = &instructions[ins_count++]; -+ mov_ins = shader_instruction_array_append(&instructions); - if (!vsir_instruction_init_with_params(program, mov_ins, &ins->location, VSIR_OP_MOV, 1, 0)) -+ { -+ vkd3d_shader_instruction_make_nop(mov_ins); - goto fail; -+ } - *mov_ins->dst = *incoming->dst; - mov_ins->src = incoming->src; - mov_ins->src_count = 1; -@@ -4853,13 +4864,11 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ - break; - } - -- instructions[ins_count++] = *ins; -+ dst_ins = shader_instruction_array_append(&instructions); -+ *dst_ins = *ins; - } - -- vkd3d_free(program->instructions.elements); -- program->instructions.elements = instructions; -- program->instructions.capacity = ins_capacity; -- program->instructions.count = ins_count; -+ vsir_program_replace_instructions(program, &instructions); - program->temp_count = alloc.next_temp_idx; - done: - ssas_to_temps_block_info_cleanup(block_info, program->block_count); -@@ -4868,7 +4877,7 @@ done: - return VKD3D_OK; - - fail: -- vkd3d_free(instructions); -+ shader_instruction_array_destroy(&instructions); - ssas_to_temps_block_info_cleanup(block_info, program->block_count); - vkd3d_free(alloc.table); - -@@ -4929,7 +4938,7 @@ struct vsir_block - * LABEL that introduces the block. `end' points to the terminator - * instruction (either BRANCH or RET). They can coincide, meaning - * that the block is empty. */ -- struct vkd3d_shader_instruction *begin, *end; -+ struct vsir_program_iterator begin, end; - struct vsir_block_list predecessors, successors; - uint32_t *dominates; - }; -@@ -5112,8 +5121,8 @@ static void vsir_cfg_structure_cleanup(struct vsir_cfg_structure *structure) - - struct vsir_cfg_emit_target - { -- struct vkd3d_shader_instruction *instructions; -- size_t ins_capacity, ins_count; -+ struct vkd3d_shader_instruction_array instructions; -+ - unsigned int jump_target_temp_idx; - unsigned int temp_count; - }; -@@ -5248,19 +5257,21 @@ static void vsir_cfg_dump_dot(struct vsir_cfg *cfg) - for (i = 0; i < cfg->block_count; ++i) - { - struct vsir_block *block = &cfg->blocks[i]; -+ struct vkd3d_shader_instruction *end; - const char *shape; - - if (block->label == 0) - continue; - -- switch (block->end->opcode) -+ end = vsir_program_iterator_current(&block->end); -+ switch (end->opcode) - { - case VSIR_OP_RET: - shape = "trapezium"; - break; - - case VSIR_OP_BRANCH: -- shape = vsir_register_is_label(&block->end->src[0].reg) ? "ellipse" : "box"; -+ shape = vsir_register_is_label(&end->src[0].reg) ? "ellipse" : "box"; - break; - - default: -@@ -5412,8 +5423,8 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program - VKD3D_ASSERT(current_block->label == 0); - if ((ret = vsir_block_init(current_block, label, program->block_count)) < 0) - goto fail; -- current_block->begin = vsir_program_iterator_next(it); -- vsir_program_iterator_prev(it); -+ current_block->begin = *it; -+ vsir_program_iterator_next(¤t_block->begin); - if (!cfg->entry) - cfg->entry = current_block; - break; -@@ -5422,7 +5433,7 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program - case VSIR_OP_BRANCH: - case VSIR_OP_RET: - VKD3D_ASSERT(current_block); -- current_block->end = ins; -+ current_block->end = *it; - current_block = NULL; - break; - -@@ -5446,27 +5457,29 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program - for (i = 0; i < cfg->block_count; ++i) - { - struct vsir_block *block = &cfg->blocks[i]; -+ struct vkd3d_shader_instruction *end; - - if (block->label == 0) - continue; - -- switch (block->end->opcode) -+ end = vsir_program_iterator_current(&block->end); -+ switch (end->opcode) - { - case VSIR_OP_RET: - break; - - case VSIR_OP_BRANCH: -- if (vsir_register_is_label(&block->end->src[0].reg)) -+ if (vsir_register_is_label(&end->src[0].reg)) - { -- if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[0])) < 0) -+ if ((ret = vsir_cfg_add_edge(cfg, block, &end->src[0])) < 0) - goto fail; - } - else - { -- if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[1])) < 0) -+ if ((ret = vsir_cfg_add_edge(cfg, block, &end->src[1])) < 0) - goto fail; - -- if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[2])) < 0) -+ if ((ret = vsir_cfg_add_edge(cfg, block, &end->src[2])) < 0) - goto fail; - } - break; -@@ -5650,8 +5663,10 @@ static enum vkd3d_result vsir_cfg_compute_loops(struct vsir_cfg *cfg) - - if (cfg->loops_by_header[header->label - 1] != SIZE_MAX) - { -+ struct vkd3d_shader_instruction *begin = vsir_program_iterator_current(&header->begin); -+ - FIXME("Block %u is header to more than one loop, this is not implemented.\n", header->label); -- vkd3d_shader_error(cfg->message_context, &header->begin->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, -+ vkd3d_shader_error(cfg->message_context, &begin->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, - "Block %u is header to more than one loop, this is not implemented.", header->label); - return VKD3D_ERROR_NOT_IMPLEMENTED; - } -@@ -5733,8 +5748,10 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg) - - if (in_degrees[i] == 0 && block != cfg->entry) - { -+ struct vkd3d_shader_instruction *begin = vsir_program_iterator_current(&block->begin); -+ - WARN("Unexpected entry point %u.\n", block->label); -- vkd3d_shader_error(cfg->message_context, &block->begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, -+ vkd3d_shader_error(cfg->message_context, &begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, - "Block %u is unreachable from the entry point.", block->label); - ret = VKD3D_ERROR_INVALID_SHADER; - goto fail; -@@ -5743,8 +5760,10 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg) - - if (in_degrees[cfg->entry->label - 1] != 0) - { -+ struct vkd3d_shader_instruction *begin = vsir_program_iterator_current(&cfg->entry->begin); -+ - WARN("Entry point has %u incoming forward edges.\n", in_degrees[cfg->entry->label - 1]); -- vkd3d_shader_error(cfg->message_context, &cfg->entry->begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, -+ vkd3d_shader_error(cfg->message_context, &begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, - "The entry point block has %u incoming forward edges.", in_degrees[cfg->entry->label - 1]); - ret = VKD3D_ERROR_INVALID_SHADER; - goto fail; -@@ -5846,9 +5865,11 @@ static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg) - - if (cfg->order.count != cfg->block_count) - { -+ struct vkd3d_shader_instruction *begin = vsir_program_iterator_current(&cfg->entry->begin); -+ - /* There is a cycle of forward edges. */ - WARN("The control flow graph is not reducible.\n"); -- vkd3d_shader_error(cfg->message_context, &cfg->entry->begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, -+ vkd3d_shader_error(cfg->message_context, &begin->location, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, - "The control flow graph is not reducible."); - ret = VKD3D_ERROR_INVALID_SHADER; - goto fail; -@@ -6107,6 +6128,7 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) - { - struct vsir_block *block = cfg->order.blocks[i]; - struct vsir_cfg_structure *structure; -+ struct vkd3d_shader_instruction *end; - - VKD3D_ASSERT(stack_depth > 0); - -@@ -6132,16 +6154,17 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) - structure->u.block = block; - - /* Generate between zero and two jump instructions. */ -- switch (block->end->opcode) -+ end = vsir_program_iterator_current(&block->end); -+ switch (end->opcode) - { - case VSIR_OP_BRANCH: - { - struct vsir_cfg_edge_action action_true, action_false; - bool invert_condition = false; - -- if (vsir_register_is_label(&block->end->src[0].reg)) -+ if (vsir_register_is_label(&end->src[0].reg)) - { -- unsigned int target = label_from_src_param(&block->end->src[0]); -+ unsigned int target = label_from_src_param(&end->src[0]); - struct vsir_block *successor = &cfg->blocks[target - 1]; - - vsir_cfg_compute_edge_action(cfg, block, successor, &action_true); -@@ -6149,12 +6172,12 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) - } - else - { -- unsigned int target = label_from_src_param(&block->end->src[1]); -+ unsigned int target = label_from_src_param(&end->src[1]); - struct vsir_block *successor = &cfg->blocks[target - 1]; - - vsir_cfg_compute_edge_action(cfg, block, successor, &action_true); - -- target = label_from_src_param(&block->end->src[2]); -+ target = label_from_src_param(&end->src[2]); - successor = &cfg->blocks[target - 1]; - - vsir_cfg_compute_edge_action(cfg, block, successor, &action_false); -@@ -6206,7 +6229,7 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) - goto fail; - structure->u.jump.type = action_true.jump_type; - structure->u.jump.target = action_true.target; -- structure->u.jump.condition = &block->end->src[0]; -+ structure->u.jump.condition = &vsir_program_iterator_current(&block->end)->src[0]; - structure->u.jump.invert_condition = invert_condition; - } - -@@ -6691,15 +6714,28 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_block(struct vsir_cfg *cfg - struct vsir_block *block) - { - struct vsir_cfg_emit_target *target = cfg->target; -+ struct vkd3d_shader_instruction *ins, *end, *dst; -+ struct vsir_program_iterator it; -+ size_t ins_count = 0; - -- if (!reserve_instructions(&target->instructions, &target->ins_capacity, -- target->ins_count + (block->end - block->begin))) -- return VKD3D_ERROR_OUT_OF_MEMORY; -+ it = block->begin; -+ end = vsir_program_iterator_current(&block->end); -+ -+ for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it)) -+ { -+ ++ins_count; -+ } - -- memcpy(&target->instructions[target->ins_count], block->begin, -- (char *)block->end - (char *)block->begin); -+ if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + ins_count)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; - -- target->ins_count += block->end - block->begin; -+ it = block->begin; -+ for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it)) -+ { -+ dst = shader_instruction_array_append(&target->instructions); -+ VKD3D_ASSERT(dst); -+ *dst = *ins; -+ } - - return VKD3D_OK; - } -@@ -6709,20 +6745,22 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, - { - struct vsir_cfg_emit_target *target = cfg->target; - const struct vkd3d_shader_location no_loc = {0}; -+ struct vkd3d_shader_instruction *ins; - enum vkd3d_result ret; - -- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) -+ if (!(ins = shader_instruction_array_append(&target->instructions))) - return VKD3D_ERROR_OUT_OF_MEMORY; - -- vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_LOOP); -+ vsir_instruction_init(ins, &no_loc, VSIR_OP_LOOP); - - if ((ret = vsir_cfg_structure_list_emit(cfg, &loop->body, loop->idx)) < 0) - return ret; - -- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 5)) -+ if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + 5)) - return VKD3D_ERROR_OUT_OF_MEMORY; - -- vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_ENDLOOP); -+ ins = shader_instruction_array_append(&target->instructions); -+ vsir_instruction_init(ins, &no_loc, VSIR_OP_ENDLOOP); - - /* Add a trampoline to implement multilevel jumping depending on the stored - * jump_target value. */ -@@ -6736,44 +6774,50 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, - * we have to reach an outer loop, so we keep breaking. */ - const unsigned int inner_break_target = loop->idx << 1; - -- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], -- &no_loc, VSIR_OP_IEQ, 1, 2)) -+ ins = shader_instruction_array_append(&target->instructions); -+ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_IEQ, 1, 2)) -+ { -+ vkd3d_shader_instruction_make_nop(ins); - return VKD3D_ERROR_OUT_OF_MEMORY; -+ } - -- dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); -- src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx); -- src_param_init_const_uint(&target->instructions[target->ins_count].src[1], outer_continue_target); -+ ++target->temp_count; - -- ++target->ins_count; -+ dst_param_init_temp_bool(&ins->dst[0], target->temp_count - 1); -+ src_param_init_temp_uint(&ins->src[0], target->jump_target_temp_idx); -+ src_param_init_const_uint(&ins->src[1], outer_continue_target); - -- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], -- &no_loc, VSIR_OP_CONTINUEP, 0, 1)) -+ ins = shader_instruction_array_append(&target->instructions); -+ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_CONTINUEP, 0, 1)) -+ { -+ vkd3d_shader_instruction_make_nop(ins); - return VKD3D_ERROR_OUT_OF_MEMORY; -+ } - -- src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count); -- -- ++target->ins_count; -- ++target->temp_count; -+ src_param_init_temp_bool(&ins->src[0], target->temp_count - 1); - -- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], -- &no_loc, VSIR_OP_IEQ, 1, 2)) -+ ins = shader_instruction_array_append(&target->instructions); -+ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_IEQ, 1, 2)) -+ { -+ vkd3d_shader_instruction_make_nop(ins); - return VKD3D_ERROR_OUT_OF_MEMORY; -+ } - -- dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); -- src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx); -- src_param_init_const_uint(&target->instructions[target->ins_count].src[1], inner_break_target); -+ ++target->temp_count; - -- ++target->ins_count; -+ dst_param_init_temp_bool(&ins->dst[0], target->temp_count - 1); -+ src_param_init_temp_uint(&ins->src[0], target->jump_target_temp_idx); -+ src_param_init_const_uint(&ins->src[1], inner_break_target); - -- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], -- &no_loc, VSIR_OP_BREAKP, 0, 1)) -+ ins = shader_instruction_array_append(&target->instructions); -+ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_BREAKP, 0, 1)) -+ { -+ vkd3d_shader_instruction_make_nop(ins); - return VKD3D_ERROR_OUT_OF_MEMORY; -- target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; -- -- src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count); -+ } -+ ins->flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; - -- ++target->ins_count; -- ++target->temp_count; -+ src_param_init_temp_bool(&ins->src[0], target->temp_count - 1); - } - - return VKD3D_OK; -@@ -6784,40 +6828,40 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg - { - struct vsir_cfg_emit_target *target = cfg->target; - const struct vkd3d_shader_location no_loc = {0}; -+ struct vkd3d_shader_instruction *ins; - enum vkd3d_result ret; - -- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) -+ if (!(ins = shader_instruction_array_append(&target->instructions))) - return VKD3D_ERROR_OUT_OF_MEMORY; - -- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], -- &no_loc, VSIR_OP_IF, 0, 1)) -+ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_IF, 0, 1)) -+ { -+ vkd3d_shader_instruction_make_nop(ins); - return VKD3D_ERROR_OUT_OF_MEMORY; -+ } - -- target->instructions[target->ins_count].src[0] = *selection->condition; -+ ins->src[0] = *selection->condition; - - if (selection->invert_condition) -- target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; -- -- ++target->ins_count; -+ ins->flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; - - if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->if_body, loop_idx)) < 0) - return ret; - - if (selection->else_body.count != 0) - { -- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) -+ if (!(ins = shader_instruction_array_append(&target->instructions))) - return VKD3D_ERROR_OUT_OF_MEMORY; - -- vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_ELSE); -+ vsir_instruction_init(ins, &no_loc, VSIR_OP_ELSE); - - if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->else_body, loop_idx)) < 0) - return ret; - } - -- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) -+ if (!(ins = shader_instruction_array_append(&target->instructions))) - return VKD3D_ERROR_OUT_OF_MEMORY; -- -- vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VSIR_OP_ENDIF); -+ vsir_instruction_init(ins, &no_loc, VSIR_OP_ENDIF); - - return VKD3D_OK; - } -@@ -6830,6 +6874,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, - /* Encode the jump target as the loop index plus a bit to remember whether - * we're breaking or continue-ing. */ - unsigned int jump_target = jump->target << 1; -+ struct vkd3d_shader_instruction *ins; - enum vkd3d_shader_opcode opcode; - - switch (jump->type) -@@ -6860,32 +6905,34 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, - vkd3d_unreachable(); - } - -- if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 2)) -+ if (!shader_instruction_array_reserve(&target->instructions, target->instructions.count + 2)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - if (jump->needs_launcher) - { -- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], -- &no_loc, VSIR_OP_MOV, 1, 1)) -+ ins = shader_instruction_array_append(&target->instructions); -+ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_MOV, 1, 1)) -+ { -+ vkd3d_shader_instruction_make_nop(ins); - return VKD3D_ERROR_OUT_OF_MEMORY; -+ } - -- dst_param_init_temp_uint(&target->instructions[target->ins_count].dst[0], target->jump_target_temp_idx); -- src_param_init_const_uint(&target->instructions[target->ins_count].src[0], jump_target); -- -- ++target->ins_count; -+ dst_param_init_temp_uint(&ins->dst[0], target->jump_target_temp_idx); -+ src_param_init_const_uint(&ins->src[0], jump_target); - } - -- if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], -- &no_loc, opcode, 0, !!jump->condition)) -+ ins = shader_instruction_array_append(&target->instructions); -+ if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, opcode, 0, !!jump->condition)) -+ { -+ vkd3d_shader_instruction_make_nop(ins); - return VKD3D_ERROR_OUT_OF_MEMORY; -+ } - - if (jump->invert_condition) -- target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; -+ ins->flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; - - if (jump->condition) -- target->instructions[target->ins_count].src[0] = *jump->condition; -- -- ++target->ins_count; -+ ins->src[0] = *jump->condition; - - return VKD3D_OK; - } -@@ -6977,8 +7024,8 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, - { - struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); - struct vkd3d_shader_message_context *message_context = ctx->message_context; -+ struct vkd3d_shader_instruction *ins, *dst; - struct vsir_cfg_emit_target target = {0}; -- struct vkd3d_shader_instruction *ins; - enum vkd3d_result ret; - - VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); -@@ -6986,7 +7033,7 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, - target.jump_target_temp_idx = program->temp_count; - target.temp_count = program->temp_count + 1; - -- if (!reserve_instructions(&target.instructions, &target.ins_capacity, program->instructions.count)) -+ if (!shader_instruction_array_reserve(&target.instructions, target.instructions.count)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - for (ins = vsir_program_iterator_head(&it); ins;) -@@ -7007,7 +7054,10 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, - case VSIR_OP_HS_JOIN_PHASE: - VKD3D_ASSERT(program->shader_version.type == VKD3D_SHADER_TYPE_HULL); - TRACE("Structurizing phase %u of a hull shader.\n", ins->opcode); -- target.instructions[target.ins_count++] = *ins; -+ -+ dst = shader_instruction_array_append(&target.instructions); -+ *dst = *ins; -+ - vsir_program_iterator_next(&it); - if ((ret = vsir_program_structurize_function(program, message_context, &target, &it)) < 0) - goto fail; -@@ -7015,25 +7065,22 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, - break; - - default: -- if (!reserve_instructions(&target.instructions, &target.ins_capacity, target.ins_count + 1)) -+ if (!(dst = shader_instruction_array_append(&target.instructions))) - return VKD3D_ERROR_OUT_OF_MEMORY; -- target.instructions[target.ins_count++] = *ins; -+ *dst = *ins; - ins = vsir_program_iterator_next(&it); - break; - } - } - -- vkd3d_free(program->instructions.elements); -- program->instructions.elements = target.instructions; -- program->instructions.capacity = target.ins_capacity; -- program->instructions.count = target.ins_count; -+ vsir_program_replace_instructions(program, &target.instructions); - program->temp_count = target.temp_count; - program->cf_type = VSIR_CF_STRUCTURED; - - return VKD3D_OK; - - fail: -- vkd3d_free(target.instructions); -+ shader_instruction_array_destroy(&target.instructions); - - return ret; - } -@@ -7088,7 +7135,9 @@ static enum vkd3d_result vsir_cfg_materialize_undominated_ssas_to_temps(struct v - if (block->label == 0) - continue; - -- for (ins = block->begin; ins <= block->end; ++ins) -+ it = block->begin; -+ end = vsir_program_iterator_current(&block->end); -+ for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it)) - { - for (j = 0; j < ins->dst_count; ++j) - { -@@ -7105,7 +7154,9 @@ static enum vkd3d_result vsir_cfg_materialize_undominated_ssas_to_temps(struct v - if (block->label == 0) - continue; - -- for (ins = block->begin; ins <= block->end; ++ins) -+ it = block->begin; -+ end = vsir_program_iterator_current(&block->end); -+ for (ins = vsir_program_iterator_current(&it); ins != end; ins = vsir_program_iterator_next(&it)) - { - for (j = 0; j < ins->src_count; ++j) - register_map_undominated_use(&ins->src[j].reg, &alloc, block, origin_blocks); -diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index 2005e842201..2acb31ed6d6 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -1472,6 +1472,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VSIR_OP_CONTINUE: - msl_continue(gen); - break; -+ case VSIR_OP_COS: -+ msl_intrinsic(gen, ins, "cos"); -+ break; - case VSIR_OP_DCL_INDEXABLE_TEMP: - msl_dcl_indexable_temp(gen, ins); - break; -@@ -1549,6 +1552,12 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VSIR_OP_UGE: - msl_relop(gen, ins, ">="); - break; -+ case VSIR_OP_HCOS: -+ msl_intrinsic(gen, ins, "cosh"); -+ break; -+ case VSIR_OP_HSIN: -+ msl_intrinsic(gen, ins, "sinh"); -+ break; - case VSIR_OP_IF: - msl_if(gen, ins); - break; -@@ -1633,6 +1642,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VSIR_OP_RSQ: - msl_intrinsic(gen, ins, "rsqrt"); - break; -+ case VSIR_OP_SIN: -+ msl_intrinsic(gen, ins, "sin"); -+ break; - case VSIR_OP_SQRT: - msl_intrinsic(gen, ins, "sqrt"); - break; -@@ -1642,6 +1654,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VSIR_OP_SWITCH: - msl_switch(gen, ins); - break; -+ case VSIR_OP_TAN: -+ msl_intrinsic(gen, ins, "tan"); -+ break; - case VSIR_OP_XOR: - msl_binop(gen, ins, "^"); - break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 434be05e786..41ab6114ffc 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -9529,7 +9529,7 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, - if (!spirv_compiler_get_register_info(compiler, &dst->reg, ®_info)) - return; - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id); - base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, - type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); -@@ -9675,7 +9675,7 @@ static void spirv_compiler_emit_uav_counter_instruction(struct spirv_compiler *c - counter_id = resource_symbol->info.resource.uav_counter_id; - VKD3D_ASSERT(counter_id); - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); - - if (resource_symbol->info.resource.uav_counter_array) - { -@@ -9924,7 +9924,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, - { - resource_symbol = spirv_compiler_find_resource(compiler, &src->reg); - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); - val_id = vkd3d_spirv_build_op_array_length(builder, type_id, resource_symbol->id, 0); - write_mask = VKD3DSP_WRITEMASK_0; - } -@@ -9934,7 +9934,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, - - spirv_compiler_prepare_image(compiler, &image, &src->reg, NULL, VKD3D_IMAGE_FLAG_NONE); - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); - val_id = vkd3d_spirv_build_op_image_query_size(builder, type_id, image.image_id); - write_mask = VKD3DSP_WRITEMASK_0; - } -@@ -9944,7 +9944,7 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, - stride_id = spirv_compiler_get_constant_uint(compiler, image.structure_stride); - constituents[0] = vkd3d_spirv_build_op_udiv(builder, type_id, val_id, stride_id); - constituents[1] = stride_id; -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, ARRAY_SIZE(constituents)); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, ARRAY_SIZE(constituents)); - val_id = vkd3d_spirv_build_op_composite_construct(builder, - type_id, constituents, ARRAY_SIZE(constituents)); - write_mask |= VKD3DSP_WRITEMASK_1; -@@ -9983,14 +9983,14 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, - size_component_count = image.resource_type_info->coordinate_component_count; - if (image.resource_type_info->dim == SpvDimCube) - --size_component_count; -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, size_component_count); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, size_component_count); - - supports_mipmaps = src[1].reg.type != VKD3DSPR_UAV && !image.resource_type_info->ms; - if (supports_mipmaps) - { - lod_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); - val_id = vkd3d_spirv_build_op_image_query_size_lod(builder, type_id, image.image_id, lod_id); -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); - miplevel_count_id = vkd3d_spirv_build_op_image_query_levels(builder, type_id, image.image_id); - } - else -@@ -10004,14 +10004,13 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, - for (i = 0; i < 3 - size_component_count; ++i) - constituents[i + 1] = spirv_compiler_get_constant_uint(compiler, 0); - constituents[i + 1] = miplevel_count_id; -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE); -- val_id = vkd3d_spirv_build_op_composite_construct(builder, -- type_id, constituents, i + 2); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, VKD3D_VEC4_SIZE); -+ val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, constituents, i + 2); - - if (!(instruction->flags & VKD3DSI_RESINFO_UINT)) - { - component_type = VKD3D_SHADER_COMPONENT_FLOAT; -- type_id = spirv_get_type_id_for_component_type(builder, component_type, VKD3D_VEC4_SIZE); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, VKD3D_VEC4_SIZE); - val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id); - if (instruction->flags & VKD3DSI_PRECISE_XYZW) - vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); -@@ -10039,7 +10038,7 @@ static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *co - vkd3d_spirv_enable_capability(builder, SpvCapabilityImageQuery); - - spirv_compiler_prepare_image(compiler, &image, &src->reg, NULL, VKD3D_IMAGE_FLAG_NONE); -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); - val_id = vkd3d_spirv_build_op_image_query_samples(builder, type_id, image.image_id); - } - -@@ -10065,14 +10064,16 @@ static void spirv_compiler_emit_sample_info(struct spirv_compiler *compiler, - - constituents[0] = val_id; - for (i = 1; i < VKD3D_VEC4_SIZE; ++i) -+ { - constituents[i] = spirv_compiler_get_constant_uint(compiler, 0); -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE); -+ } -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, VKD3D_VEC4_SIZE); - val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, constituents, VKD3D_VEC4_SIZE); - - if (!(instruction->flags & VKD3DSI_SAMPLE_INFO_UINT)) - { - component_type = VKD3D_SHADER_COMPONENT_FLOAT; -- type_id = spirv_get_type_id_for_component_type(builder, component_type, VKD3D_VEC4_SIZE); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, VKD3D_VEC4_SIZE); - val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id); - if (instruction->flags & VKD3DSI_PRECISE_XYZW) - vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); -@@ -10138,13 +10139,12 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, - sample_count_id = spirv_compiler_emit_query_sample_count(compiler, &instruction->src[0]); - sample_index_id = spirv_compiler_emit_load_src(compiler, &instruction->src[1], VKD3DSP_WRITEMASK_0); - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); - index_id = vkd3d_spirv_build_op_iadd(builder, type_id, sample_count_id, sample_index_id); -- index_id = vkd3d_spirv_build_op_isub(builder, -- type_id, index_id, spirv_compiler_get_constant_uint(compiler, 1)); -+ index_id = vkd3d_spirv_build_op_isub(builder, type_id, index_id, spirv_compiler_get_constant_uint(compiler, 1)); - - /* Validate sample index. */ -- bool_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_BOOL, 1); -+ bool_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, 1); - id = vkd3d_spirv_build_op_logical_and(builder, bool_id, - vkd3d_spirv_build_op_uless_than(builder, bool_id, sample_index_id, sample_count_id), - vkd3d_spirv_build_op_uless_than_equal(builder, -@@ -10152,7 +10152,7 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, - index_id = vkd3d_spirv_build_op_select(builder, type_id, - id, index_id, spirv_compiler_get_constant_uint(compiler, 0)); - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, 2); - if (!(id = compiler->sample_positions_id)) - { - length_id = spirv_compiler_get_constant_uint(compiler, ARRAY_SIZE(standard_sample_positions)); -@@ -10216,7 +10216,7 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, - src_ids[src_count++] = spirv_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0); - } - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_FLOAT, -+ type_id = spirv_get_type_id(builder, VSIR_DATA_F32, - vsir_write_mask_component_count(register_info.write_mask)); - - instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); -@@ -10425,7 +10425,7 @@ static uint32_t spirv_compiler_emit_group_nonuniform_ballot(struct spirv_compile - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, val_id; - -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, VKD3D_VEC4_SIZE); - val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); - val_id = vkd3d_spirv_build_op_group_nonuniform_ballot(builder, type_id, val_id); - -@@ -10508,7 +10508,7 @@ static void spirv_compiler_emit_wave_bit_count(struct spirv_compiler *compiler, - : SpvGroupOperationReduce; - - val_id = spirv_compiler_emit_group_nonuniform_ballot(compiler, instruction->src); -- type_id = spirv_get_type_id_for_component_type(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = spirv_get_type_id(builder, VSIR_DATA_U32, 1); - val_id = vkd3d_spirv_build_op_group_nonuniform_ballot_bit_count(builder, type_id, group_op, val_id); - - spirv_compiler_emit_store_dst(compiler, dst, val_id); -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 6037f7179e7..896c97a7a64 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -1428,9 +1428,9 @@ struct vkd3d_shader_instruction_array - size_t count; - }; - -+struct vkd3d_shader_instruction *shader_instruction_array_append(struct vkd3d_shader_instruction_array *array); -+bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, size_t idx, size_t count); - bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, size_t reserve); --bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, -- size_t idx, size_t count); - - struct vsir_program_iterator - { -@@ -1486,8 +1486,9 @@ static inline struct vkd3d_shader_instruction *vsir_program_iterator_prev( - } - - /* When insertion takes place, argument `it' is updated to point to the same -- * instruction as before the insertion, but all other iterators and pointers -- * to the same container are invalidated and cannot be used any more. */ -+ * instruction as before the insertion, but all existing pointers to the same -+ * container, as well as any iterators pointing to instructions after the -+ * insertion point should be considered invalid. */ - static inline bool vsir_program_iterator_insert_after(struct vsir_program_iterator *it, size_t count) - { - return shader_instruction_array_insert_at(it->array, it->idx + 1, count); -@@ -1651,12 +1652,7 @@ bool vsir_instruction_init_with_params(struct vsir_program *program, - - static inline struct vkd3d_shader_instruction *vsir_program_append(struct vsir_program *program) - { -- struct vkd3d_shader_instruction_array *array = &program->instructions; -- -- if (!shader_instruction_array_insert_at(array, array->count, 1)) -- return NULL; -- -- return &array->elements[array->count - 1]; -+ return shader_instruction_array_append(&program->instructions); - } - - static inline struct vkd3d_shader_dst_param *vsir_program_get_dst_params( --- -2.51.0 - diff --git a/patches/vkd3d-latest/0007-Updated-vkd3d-to-f9c71d5775dd7e3be19911c8bf77fac563b.patch b/patches/vkd3d-latest/0007-Updated-vkd3d-to-f9c71d5775dd7e3be19911c8bf77fac563b.patch deleted file mode 100644 index 45c004c9..00000000 --- a/patches/vkd3d-latest/0007-Updated-vkd3d-to-f9c71d5775dd7e3be19911c8bf77fac563b.patch +++ /dev/null @@ -1,705 +0,0 @@ -From 9d3b75631464e8d87d74bcbb8d1776a1aa07014e Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Wed, 1 Oct 2025 07:35:50 +1000 -Subject: [PATCH] Updated vkd3d to f9c71d5775dd7e3be19911c8bf77fac563bfce85. - ---- - libs/vkd3d/libs/vkd3d-shader/ir.c | 36 +++--- - libs/vkd3d/libs/vkd3d-shader/msl.c | 37 ++++++ - libs/vkd3d/libs/vkd3d-shader/spirv.c | 182 +++++++++++++-------------- - 3 files changed, 143 insertions(+), 112 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 43bd799d2eb..315ee522e9e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -4501,6 +4501,8 @@ static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsi - - VKD3D_ASSERT(program->cf_type == VSIR_CF_STRUCTURED); - -+ shader_instruction_array_init(&flattener.instructions, 0); -+ - if ((result = cf_flattener_iterate_instruction_array(&flattener, message_context)) >= 0) - { - vsir_program_replace_instructions(program, &flattener.instructions); -@@ -4560,14 +4562,14 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs - unsigned int block_count = program->block_count, ssa_count = program->ssa_count, current_label = 0, if_label; - struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); - struct lower_switch_to_if_ladder_block_mapping *block_map = NULL; -- struct vkd3d_shader_instruction_array instructions = {0}; -+ struct vkd3d_shader_instruction_array instructions; - struct vkd3d_shader_instruction *ins, *dst_ins; - size_t map_capacity = 0, map_count = 0; - - VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); - -- if (!shader_instruction_array_reserve(&instructions, program->instructions.count)) -- goto fail; -+ if (!shader_instruction_array_init(&instructions, program->instructions.count)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; - - /* First subpass: convert SWITCH_MONOLITHIC instructions to - * selection ladders, keeping a map between blocks before and -@@ -4757,9 +4759,8 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ - { - struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); - struct ssas_to_temps_block_info *info, *block_info = NULL; -- struct vkd3d_shader_instruction_array instructions = {0}; -- struct vkd3d_shader_instruction *ins, *dst_ins; - struct ssas_to_temps_alloc alloc = {0}; -+ struct vkd3d_shader_instruction *ins; - size_t phi_count, incoming_count; - unsigned int current_label = 0; - -@@ -4817,7 +4818,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ - if (!phi_count) - goto done; - -- if (!shader_instruction_array_reserve(&instructions, program->instructions.count + incoming_count - phi_count)) -+ if (!shader_instruction_array_reserve(&program->instructions, program->instructions.count + incoming_count)) - goto fail; - - for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) -@@ -4841,11 +4842,13 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ - case VSIR_OP_SWITCH_MONOLITHIC: - info = &block_info[current_label - 1]; - -+ mov_ins = vsir_program_iterator_insert_before_and_move(&it, info->incoming_count); -+ VKD3D_ASSERT(mov_ins); -+ - for (j = 0; j < info->incoming_count; ++j) - { - struct phi_incoming_to_temp *incoming = &info->incomings[j]; - -- mov_ins = shader_instruction_array_append(&instructions); - if (!vsir_instruction_init_with_params(program, mov_ins, &ins->location, VSIR_OP_MOV, 1, 0)) - { - vkd3d_shader_instruction_make_nop(mov_ins); -@@ -4854,21 +4857,20 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ - *mov_ins->dst = *incoming->dst; - mov_ins->src = incoming->src; - mov_ins->src_count = 1; -+ -+ mov_ins = vsir_program_iterator_next(&it); - } - break; - - case VSIR_OP_PHI: -- continue; -+ vkd3d_shader_instruction_make_nop(ins); -+ break; - - default: - break; - } -- -- dst_ins = shader_instruction_array_append(&instructions); -- *dst_ins = *ins; - } - -- vsir_program_replace_instructions(program, &instructions); - program->temp_count = alloc.next_temp_idx; - done: - ssas_to_temps_block_info_cleanup(block_info, program->block_count); -@@ -4877,7 +4879,6 @@ done: - return VKD3D_OK; - - fail: -- shader_instruction_array_destroy(&instructions); - ssas_to_temps_block_info_cleanup(block_info, program->block_count); - vkd3d_free(alloc.table); - -@@ -7033,7 +7034,7 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, - target.jump_target_temp_idx = program->temp_count; - target.temp_count = program->temp_count + 1; - -- if (!shader_instruction_array_reserve(&target.instructions, target.instructions.count)) -+ if (!shader_instruction_array_init(&target.instructions, 0)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - for (ins = vsir_program_iterator_head(&it); ins;) -@@ -7215,7 +7216,7 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru - - VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS); - -- for (ins = vsir_program_iterator_head(&it); ins;) -+ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_current(&it)) - { - switch (ins->opcode) - { -@@ -7225,8 +7226,6 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru - if ((ret = vsir_program_materialize_undominated_ssas_to_temps_in_function( - program, message_context, &it)) < 0) - return ret; -- ins = vsir_program_iterator_current(&it); -- VKD3D_ASSERT(!ins); - break; - - case VSIR_OP_HS_CONTROL_POINT_PHASE: -@@ -7238,11 +7237,10 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru - if ((ret = vsir_program_materialize_undominated_ssas_to_temps_in_function( - program, message_context, &it)) < 0) - return ret; -- ins = vsir_program_iterator_current(&it); - break; - - default: -- ins = vsir_program_iterator_next(&it); -+ vsir_program_iterator_next(&it); - break; - } - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index 2acb31ed6d6..906392870ed 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -486,6 +486,10 @@ static enum msl_data_type msl_print_register_name(struct vkd3d_string_buffer *bu - vkd3d_string_buffer_printf(buffer, "o_mask"); - return MSL_DATA_UNION; - -+ case VKD3DSPR_THREADID: -+ vkd3d_string_buffer_printf(buffer, "v_thread_id"); -+ return MSL_DATA_UNION; -+ - default: - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled register type %#x.", reg->type); -@@ -1456,6 +1460,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - - switch (ins->opcode) - { -+ case VSIR_OP_ACOS: -+ msl_intrinsic(gen, ins, "acos"); -+ break; - case VSIR_OP_ADD: - case VSIR_OP_IADD: - msl_binop(gen, ins, "+"); -@@ -1463,6 +1470,12 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VSIR_OP_AND: - msl_binop(gen, ins, "&"); - break; -+ case VSIR_OP_ASIN: -+ msl_intrinsic(gen, ins, "asin"); -+ break; -+ case VSIR_OP_ATAN: -+ msl_intrinsic(gen, ins, "atan"); -+ break; - case VSIR_OP_BREAK: - msl_break(gen); - break; -@@ -1530,6 +1543,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VSIR_OP_FRC: - msl_intrinsic(gen, ins, "fract"); - break; -+ case VSIR_OP_FREM: -+ msl_intrinsic(gen, ins, "fmod"); -+ break; - case VSIR_OP_FTOI: - msl_cast(gen, ins, "int"); - break; -@@ -1558,6 +1574,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VSIR_OP_HSIN: - msl_intrinsic(gen, ins, "sinh"); - break; -+ case VSIR_OP_HTAN: -+ msl_intrinsic(gen, ins, "tanh"); -+ break; - case VSIR_OP_IF: - msl_if(gen, ins); - break; -@@ -1997,6 +2016,12 @@ static void msl_generate_entrypoint_prologue(struct msl_generator *gen) - msl_print_write_mask(buffer, e->mask); - vkd3d_string_buffer_printf(buffer, ";\n"); - } -+ -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADID)) -+ { -+ msl_print_indent(gen->buffer, 1); -+ vkd3d_string_buffer_printf(buffer, "v_thread_id.u = uint4(thread_id, 0u);\n"); -+ } - } - - static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) -@@ -2083,6 +2108,12 @@ static void msl_generate_entrypoint(struct msl_generator *gen) - vkd3d_string_buffer_printf(gen->buffer, "uint vertex_id [[vertex_id]],\n"); - } - -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADID)) -+ { -+ msl_print_indent(gen->buffer, 2); -+ vkd3d_string_buffer_printf(gen->buffer, "uint3 thread_id [[thread_position_in_grid]],\n"); -+ } -+ - msl_print_indent(gen->buffer, 2); - vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_in input [[stage_in]])\n{\n", gen->prefix); - -@@ -2092,6 +2123,8 @@ static void msl_generate_entrypoint(struct msl_generator *gen) - vkd3d_string_buffer_printf(gen->buffer, " vkd3d_%s_out output;\n", gen->prefix); - if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) - vkd3d_string_buffer_printf(gen->buffer, " vkd3d_scalar o_mask;\n"); -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADID)) -+ vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 v_thread_id;\n"); - vkd3d_string_buffer_printf(gen->buffer, "\n"); - - msl_generate_entrypoint_prologue(gen); -@@ -2103,6 +2136,8 @@ static void msl_generate_entrypoint(struct msl_generator *gen) - vkd3d_string_buffer_printf(gen->buffer, ", output.shader_out_depth"); - if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) - vkd3d_string_buffer_printf(gen->buffer, ", o_mask"); -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADID)) -+ vkd3d_string_buffer_printf(gen->buffer, ", v_thread_id"); - if (gen->program->descriptors.descriptor_count) - vkd3d_string_buffer_printf(gen->buffer, ", descriptors"); - vkd3d_string_buffer_printf(gen->buffer, ");\n\n"); -@@ -2176,6 +2211,8 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader - vkd3d_string_buffer_printf(gen->buffer, ", thread float &o_depth"); - if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) - vkd3d_string_buffer_printf(gen->buffer, ", thread vkd3d_scalar &o_mask"); -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_THREADID)) -+ vkd3d_string_buffer_printf(gen->buffer, ", thread vkd3d_vec4 &v_thread_id"); - if (gen->program->descriptors.descriptor_count) - vkd3d_string_buffer_printf(gen->buffer, ", constant descriptor *descriptors"); - vkd3d_string_buffer_printf(gen->buffer, ")\n{\n"); -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 41ab6114ffc..1bad74b06bc 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -3658,123 +3658,128 @@ static const struct vkd3d_symbol *spirv_compiler_put_symbol(struct spirv_compile - } - - static uint32_t spirv_compiler_get_constant(struct spirv_compiler *compiler, -- enum vkd3d_shader_component_type component_type, unsigned int component_count, const uint32_t *values) -+ enum vsir_data_type data_type, unsigned int component_count, const uint32_t *values) - { - uint32_t type_id, scalar_type_id, component_ids[VKD3D_VEC4_SIZE]; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - unsigned int i; - - VKD3D_ASSERT(0 < component_count && component_count <= VKD3D_VEC4_SIZE); -- type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); -+ type_id = spirv_get_type_id(builder, data_type, component_count); - -- switch (component_type) -+ switch (data_type) - { -- case VKD3D_SHADER_COMPONENT_UINT: -- case VKD3D_SHADER_COMPONENT_INT: -- case VKD3D_SHADER_COMPONENT_FLOAT: -- break; -- case VKD3D_SHADER_COMPONENT_BOOL: -+ case VSIR_DATA_BOOL: - if (component_count == 1) - return vkd3d_spirv_get_op_constant_bool(builder, type_id, *values); -- FIXME("Unsupported vector of bool.\n"); - spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, - "Vectors of bool type are not supported."); - return vkd3d_spirv_get_op_undef(builder, type_id); -+ -+ case VSIR_DATA_F16: -+ case VSIR_DATA_F32: -+ case VSIR_DATA_I32: -+ case VSIR_DATA_U16: -+ case VSIR_DATA_U32: -+ case VSIR_DATA_SNORM: -+ case VSIR_DATA_UNORM: -+ break; -+ - default: - spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, -- "Unhandled component_type %#x.", component_type); -+ "Unhandled data type \"%s\" (%#x).", -+ vsir_data_type_get_name(data_type, ""), data_type); - return vkd3d_spirv_get_op_undef(builder, type_id); - } - - if (component_count == 1) -- { - return vkd3d_spirv_get_op_constant(builder, type_id, *values); -- } -- else -+ -+ scalar_type_id = spirv_get_type_id(builder, data_type, 1); -+ for (i = 0; i < component_count; ++i) - { -- scalar_type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); -- for (i = 0; i < component_count; ++i) -- component_ids[i] = vkd3d_spirv_get_op_constant(builder, scalar_type_id, values[i]); -- return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); -+ component_ids[i] = vkd3d_spirv_get_op_constant(builder, scalar_type_id, values[i]); - } -+ -+ return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); - } - - static uint32_t spirv_compiler_get_constant64(struct spirv_compiler *compiler, -- enum vkd3d_shader_component_type component_type, unsigned int component_count, const uint64_t *values) -+ enum vsir_data_type data_type, unsigned int component_count, const uint64_t *values) - { - uint32_t type_id, scalar_type_id, component_ids[VKD3D_DVEC2_SIZE]; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - unsigned int i; - - VKD3D_ASSERT(0 < component_count && component_count <= VKD3D_DVEC2_SIZE); -- type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); -+ type_id = spirv_get_type_id(builder, data_type, component_count); - -- if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE && component_type != VKD3D_SHADER_COMPONENT_INT64 -- && component_type != VKD3D_SHADER_COMPONENT_UINT64) -+ if (data_type != VSIR_DATA_F64 && data_type != VSIR_DATA_I64 && data_type != VSIR_DATA_U64) - { -- FIXME("Unhandled component_type %#x.\n", component_type); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, -+ "Unhandled data type \"%s\" (%#x).", -+ vsir_data_type_get_name(data_type, ""), data_type); - return vkd3d_spirv_get_op_undef(builder, type_id); - } - - if (component_count == 1) -- { - return vkd3d_spirv_get_op_constant64(builder, type_id, *values); -- } -- else -+ -+ scalar_type_id = spirv_get_type_id(builder, data_type, 1); -+ for (i = 0; i < component_count; ++i) - { -- scalar_type_id = spirv_get_type_id_for_component_type(builder, component_type, 1); -- for (i = 0; i < component_count; ++i) -- component_ids[i] = vkd3d_spirv_get_op_constant64(builder, scalar_type_id, values[i]); -- return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); -+ component_ids[i] = vkd3d_spirv_get_op_constant64(builder, scalar_type_id, values[i]); - } -+ -+ return vkd3d_spirv_get_op_constant_composite(builder, type_id, component_ids, component_count); - } - --static uint32_t spirv_compiler_get_constant_uint(struct spirv_compiler *compiler, -- uint32_t value) -+static uint32_t spirv_compiler_get_constant_uint(struct spirv_compiler *compiler, uint32_t value) - { -- return spirv_compiler_get_constant(compiler, VKD3D_SHADER_COMPONENT_UINT, 1, &value); -+ return spirv_compiler_get_constant(compiler, VSIR_DATA_U32, 1, &value); - } - --static uint32_t spirv_compiler_get_constant_float(struct spirv_compiler *compiler, -- float value) -+static uint32_t spirv_compiler_get_constant_float(struct spirv_compiler *compiler, float value) - { -- return spirv_compiler_get_constant(compiler, VKD3D_SHADER_COMPONENT_FLOAT, 1, (uint32_t *)&value); -+ return spirv_compiler_get_constant(compiler, VSIR_DATA_F32, 1, (uint32_t *)&value); - } - - static uint32_t spirv_compiler_get_constant_vector(struct spirv_compiler *compiler, -- enum vkd3d_shader_component_type component_type, unsigned int component_count, uint32_t value) -+ enum vsir_data_type data_type, unsigned int component_count, uint32_t value) - { - const uint32_t values[] = {value, value, value, value}; -- return spirv_compiler_get_constant(compiler, component_type, component_count, values); -+ -+ return spirv_compiler_get_constant(compiler, data_type, component_count, values); - } - - static uint32_t spirv_compiler_get_constant_uint_vector(struct spirv_compiler *compiler, - uint32_t value, unsigned int component_count) - { -- return spirv_compiler_get_constant_vector(compiler, VKD3D_SHADER_COMPONENT_UINT, component_count, value); -+ return spirv_compiler_get_constant_vector(compiler, VSIR_DATA_U32, component_count, value); - } - - static uint32_t spirv_compiler_get_constant_float_vector(struct spirv_compiler *compiler, - float value, unsigned int component_count) - { - const float values[] = {value, value, value, value}; -- return spirv_compiler_get_constant(compiler, VKD3D_SHADER_COMPONENT_FLOAT, -- component_count, (const uint32_t *)values); -+ -+ return spirv_compiler_get_constant(compiler, VSIR_DATA_F32, component_count, (const uint32_t *)values); - } - - static uint32_t spirv_compiler_get_constant_double_vector(struct spirv_compiler *compiler, - double value, unsigned int component_count) - { - const double values[] = {value, value}; -- return spirv_compiler_get_constant64(compiler, VKD3D_SHADER_COMPONENT_DOUBLE, -- component_count, (const uint64_t *)values); -+ -+ return spirv_compiler_get_constant64(compiler, VSIR_DATA_F64, component_count, (const uint64_t *)values); - } - - static uint32_t spirv_compiler_get_constant_uint64_vector(struct spirv_compiler *compiler, - uint64_t value, unsigned int component_count) - { - const uint64_t values[] = {value, value}; -- return spirv_compiler_get_constant64(compiler, VKD3D_SHADER_COMPONENT_UINT64, component_count, values); -+ -+ return spirv_compiler_get_constant64(compiler, VSIR_DATA_U64, component_count, values); - } - - static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compiler, -@@ -4095,8 +4100,8 @@ static uint32_t spirv_compiler_emit_shader_parameter(struct spirv_compiler *comp - type, component_count, name, parameter->data_type); - - if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) -- return spirv_compiler_get_constant(compiler, vkd3d_component_type_from_data_type(type), -- component_count, (const uint32_t *)¶meter->u.immediate_constant); -+ return spirv_compiler_get_constant(compiler, type, component_count, -+ (const uint32_t *)¶meter->u.immediate_constant); - - if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT) - return spirv_compiler_get_spec_constant(compiler, name, -@@ -4112,32 +4117,32 @@ default_parameter: - } - - static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *compiler, -- enum vkd3d_shader_component_type component_type, unsigned int component_count, -- uint32_t val_id, unsigned int val_component_idx, unsigned int val_component_count) -+ enum vsir_data_type data_type, unsigned int component_count, uint32_t val_id, -+ unsigned int val_component_idx, unsigned int val_component_count) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t components[VKD3D_VEC4_SIZE]; -- uint32_t type_id, result_id; -+ uint32_t type_id; - unsigned int i; - - VKD3D_ASSERT(val_component_idx < val_component_count); - -- type_id = spirv_get_type_id_for_component_type(builder, component_type, component_count); -+ type_id = spirv_get_type_id(builder, data_type, component_count); - if (val_component_count == 1) - { - for (i = 0; i < component_count; ++i) -+ { - components[i] = val_id; -- result_id = vkd3d_spirv_build_op_composite_construct(builder, -- type_id, components, component_count); -+ } -+ return vkd3d_spirv_build_op_composite_construct(builder, type_id, components, component_count); - } -- else -+ -+ for (i = 0; i < component_count; ++i) - { -- for (i = 0; i < component_count; ++i) -- components[i] = val_component_idx; -- result_id = vkd3d_spirv_build_op_vector_shuffle(builder, -- type_id, val_id, val_id, components, component_count); -+ components[i] = val_component_idx; - } -- return result_id; -+ -+ return vkd3d_spirv_build_op_vector_shuffle(builder, type_id, val_id, val_id, components, component_count); - } - - static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, -@@ -4588,8 +4593,7 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile - } - } - -- return spirv_compiler_get_constant(compiler, -- vkd3d_component_type_from_data_type(reg->data_type), component_count, values); -+ return spirv_compiler_get_constant(compiler, reg->data_type, component_count, values); - } - - static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compiler, -@@ -4615,8 +4619,7 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi - } - } - -- return spirv_compiler_get_constant64(compiler, -- vkd3d_component_type_from_data_type(reg->data_type), component_count, values); -+ return spirv_compiler_get_constant64(compiler, reg->data_type, component_count, values); - } - - static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, -@@ -4699,12 +4702,10 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil - { - 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 = spirv_get_type_id(builder, icb->data_type, component_count); - length_id = spirv_compiler_get_constant_uint(compiler, element_count); -@@ -4721,7 +4722,6 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil - - 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; -@@ -4733,23 +4733,27 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil - case VSIR_DATA_I32: - case VSIR_DATA_U32: - for (i = 0; i < element_count; ++i) -- elements[i] = spirv_compiler_get_constant(compiler, component_type, component_count, -- &icb->data[component_count * i]); -+ { -+ elements[i] = spirv_compiler_get_constant(compiler, icb->data_type, -+ component_count, &icb->data[component_count * i]); -+ } - break; -+ - case VSIR_DATA_F64: - case VSIR_DATA_I64: - case VSIR_DATA_U64: - { - 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]); -+ elements[i] = spirv_compiler_get_constant64(compiler, icb->data_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); -+ "Immediate constant buffer data type \"%s\" (%#x) is unhandled.", -+ vsir_data_type_get_name(icb->data_type, ""), icb->data_type); - break; - } - -@@ -6252,7 +6256,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi - /* Set values to 0 for not initialized shader output components. */ - write_mask |= uninit_mask; - zero_id = spirv_compiler_get_constant_vector(compiler, -- output_info->component_type, VKD3D_VEC4_SIZE, 0); -+ vsir_data_type_from_component_type(output_info->component_type), VKD3D_VEC4_SIZE, 0); - val_id = spirv_compiler_emit_vector_shuffle(compiler, - zero_id, val_id, swizzle, uninit_mask, output_info->component_type, - vsir_write_mask_component_count(write_mask)); -@@ -7758,7 +7762,7 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil - || instruction->opcode == VSIR_OP_ISHR || instruction->opcode == VSIR_OP_USHR)) - { - uint32_t mask_id = spirv_compiler_get_constant_vector(compiler, -- VKD3D_SHADER_COMPONENT_UINT, vsir_write_mask_component_count(dst->write_mask), 0x1f); -+ VSIR_DATA_U32, vsir_write_mask_component_count(dst->write_mask), 0x1f); - src_ids[1] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[1], mask_id); - } - -@@ -8044,13 +8048,13 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_dst_param *dst = instruction->dst; - const struct vkd3d_shader_src_param *src = instruction->src; -- enum vkd3d_shader_component_type component_type; - uint32_t type_id, val_id, src_ids[2]; - unsigned int component_count, i; -+ enum vsir_data_type data_type; - uint32_t write_mask; - - component_count = vsir_write_mask_component_count(dst->write_mask); -- component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); -+ data_type = dst->reg.data_type; - - if (instruction->opcode == VSIR_OP_DP4) - write_mask = VKD3DSP_WRITEMASK_ALL; -@@ -8063,15 +8067,12 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, - for (i = 0; i < ARRAY_SIZE(src_ids); ++i) - src_ids[i] = spirv_compiler_emit_load_src(compiler, &src[i], write_mask); - -- type_id = spirv_get_type_id(builder, dst->reg.data_type, 1); -+ type_id = spirv_get_type_id(builder, data_type, 1); - - val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, - SpvOpDot, type_id, src_ids[0], src_ids[1]); - if (component_count > 1) -- { -- val_id = spirv_compiler_emit_construct_vector(compiler, -- component_type, component_count, val_id, 0, 1); -- } -+ val_id = spirv_compiler_emit_construct_vector(compiler, data_type, component_count, val_id, 0, 1); - if (instruction->flags & VKD3DSI_PRECISE_XYZW) - vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); - -@@ -8128,7 +8129,6 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst = instruction->dst; - const struct vkd3d_shader_src_param *src = instruction->src; - uint32_t src_type_id, dst_type_id, condition_type_id; -- enum vkd3d_shader_component_type component_type; - unsigned int component_count; - uint32_t write_mask; - -@@ -8160,9 +8160,8 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, - val_id = vkd3d_spirv_build_op_glsl_std450_max(builder, src_type_id, src_id, int_min_id); - - /* VSIR allows the destination of a signed conversion to be unsigned. */ -- component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); - -- int_max_id = spirv_compiler_get_constant_vector(compiler, component_type, component_count, INT_MAX); -+ int_max_id = spirv_compiler_get_constant_vector(compiler, dst->reg.data_type, component_count, INT_MAX); - condition_type_id = spirv_get_type_id(builder, VSIR_DATA_BOOL, component_count); - condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, - SpvOpFOrdGreaterThanEqual, condition_type_id, val_id, float_max_id); -@@ -8170,7 +8169,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, - val_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpConvertFToS, dst_type_id, val_id); - val_id = vkd3d_spirv_build_op_select(builder, dst_type_id, condition_id, int_max_id, val_id); - -- zero_id = spirv_compiler_get_constant_vector(compiler, component_type, component_count, 0); -+ zero_id = spirv_compiler_get_constant_vector(compiler, dst->reg.data_type, component_count, 0); - condition_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpIsNan, condition_type_id, src_id); - val_id = vkd3d_spirv_build_op_select(builder, dst_type_id, condition_id, zero_id, val_id); - -@@ -8994,8 +8993,7 @@ static uint32_t spirv_compiler_emit_texel_offset(struct spirv_compiler *compiler - int32_t data[4] = {offset->u, offset->v, offset->w, 0}; - - VKD3D_ASSERT(resource_type_info->dim != SpvDimCube); -- return spirv_compiler_get_constant(compiler, -- VKD3D_SHADER_COMPONENT_INT, component_count, (const uint32_t *)data); -+ return spirv_compiler_get_constant(compiler, VSIR_DATA_I32, component_count, (const uint32_t *)data); - } - - static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, -@@ -9251,8 +9249,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, - { - component_idx = vsir_swizzle_get_component(sampler->swizzle, 0); - /* Nvidia driver requires signed integer type. */ -- component_id = spirv_compiler_get_constant(compiler, -- VKD3D_SHADER_COMPONENT_INT, 1, &component_idx); -+ component_id = spirv_compiler_get_constant(compiler, VSIR_DATA_I32, 1, &component_idx); - val_id = vkd3d_spirv_build_op_image_gather(builder, sampled_type_id, - image.sampled_image_id, coordinate_id, component_id, - operands_mask, image_operands, image_operand_count); -@@ -9499,7 +9496,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * - for (component_idx = 0; component_idx < component_count; ++component_idx) - { - /* Mesa Vulkan drivers require the texel parameter to be a vector. */ -- data_id = spirv_compiler_emit_construct_vector(compiler, VKD3D_SHADER_COMPONENT_UINT, -+ data_id = spirv_compiler_emit_construct_vector(compiler, VSIR_DATA_U32, - VKD3D_VEC4_SIZE, val_id, component_idx, component_count); - - coordinate_id = base_coordinate_id; -@@ -10158,10 +10155,10 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, - length_id = spirv_compiler_get_constant_uint(compiler, ARRAY_SIZE(standard_sample_positions)); - array_type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); - -- for (i = 0; i < ARRAY_SIZE(standard_sample_positions); ++ i) -+ for (i = 0; i < ARRAY_SIZE(standard_sample_positions); ++i) - { -- constituents[i] = spirv_compiler_get_constant(compiler, -- VKD3D_SHADER_COMPONENT_FLOAT, 2, (const uint32_t *)standard_sample_positions[i]); -+ constituents[i] = spirv_compiler_get_constant(compiler, VSIR_DATA_F32, -+ 2, (const uint32_t *)standard_sample_positions[i]); - } - - id = vkd3d_spirv_build_op_constant_composite(builder, array_type_id, constituents, ARRAY_SIZE(constituents)); -@@ -11092,8 +11089,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - { - uint32_t type_id, struct_id, ptr_type_id, var_id; - -- type_id = spirv_get_type_id_for_component_type(builder, -- vkd3d_component_type_from_data_type(parameter_data_type_map[parameter->data_type].type), -+ type_id = spirv_get_type_id(builder, parameter_data_type_map[parameter->data_type].type, - parameter_data_type_map[parameter->data_type].component_count); - - struct_id = vkd3d_spirv_build_op_type_struct(builder, &type_id, 1); --- -2.51.0 -