From ea30d819230045130e8ab67fa66dad4ad15b1968 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Tue, 30 Sep 2025 07:58:05 +1000 Subject: [PATCH] Updated vkd3d-latest patchset --- ...-e69f3da089d472b723b016ef67c04c0f954.patch | 2 +- ...-dddc92ccfd34f941d9b6738c4f54fac43cd.patch | 2 +- ...-c48141457203d4cdfcd8315c0735748ba3b.patch | 2 +- ...-52b9aa416bb4e8be2fb6e28ffd1234cc10d.patch | 2 +- ...-cb8c851bec08a9483ce52f57c71922c9b14.patch | 830 +++++++++++ ...-b4174f52521fa4921babad6f1c374d5e9c2.patch | 1243 +++++++++++++++++ 6 files changed, 2077 insertions(+), 4 deletions(-) create mode 100644 patches/vkd3d-latest/0005-Updated-vkd3d-to-cb8c851bec08a9483ce52f57c71922c9b14.patch create mode 100644 patches/vkd3d-latest/0006-Updated-vkd3d-to-b4174f52521fa4921babad6f1c374d5e9c2.patch diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-e69f3da089d472b723b016ef67c04c0f954.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-e69f3da089d472b723b016ef67c04c0f954.patch index e356f4a3..efcde841 100644 --- a/patches/vkd3d-latest/0001-Updated-vkd3d-to-e69f3da089d472b723b016ef67c04c0f954.patch +++ b/patches/vkd3d-latest/0001-Updated-vkd3d-to-e69f3da089d472b723b016ef67c04c0f954.patch @@ -1,4 +1,4 @@ -From 758a3c4c4d478bb14d7a582f0f5d919f1d0606d7 Mon Sep 17 00:00:00 2001 +From ec7698b55e7cc60eb81efb26e2b3547a0a12d4c7 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. diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-dddc92ccfd34f941d9b6738c4f54fac43cd.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-dddc92ccfd34f941d9b6738c4f54fac43cd.patch index 634a1995..aa59972a 100644 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-dddc92ccfd34f941d9b6738c4f54fac43cd.patch +++ b/patches/vkd3d-latest/0002-Updated-vkd3d-to-dddc92ccfd34f941d9b6738c4f54fac43cd.patch @@ -1,4 +1,4 @@ -From 608249d59683030152ffef768265bb0e2627da2a Mon Sep 17 00:00:00 2001 +From 85aa4e5435ca545806c463e7f52b4fe641b987a2 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. diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-c48141457203d4cdfcd8315c0735748ba3b.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-c48141457203d4cdfcd8315c0735748ba3b.patch index c49d18c1..6fa1d704 100644 --- a/patches/vkd3d-latest/0003-Updated-vkd3d-to-c48141457203d4cdfcd8315c0735748ba3b.patch +++ b/patches/vkd3d-latest/0003-Updated-vkd3d-to-c48141457203d4cdfcd8315c0735748ba3b.patch @@ -1,4 +1,4 @@ -From 31a8d5149c3489fa51bad8aa9880eb201f4513bd Mon Sep 17 00:00:00 2001 +From 52bc48b25e81de94fbd83de567967a234855633d 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. diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-52b9aa416bb4e8be2fb6e28ffd1234cc10d.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-52b9aa416bb4e8be2fb6e28ffd1234cc10d.patch index 1bd01353..6990295e 100644 --- a/patches/vkd3d-latest/0004-Updated-vkd3d-to-52b9aa416bb4e8be2fb6e28ffd1234cc10d.patch +++ b/patches/vkd3d-latest/0004-Updated-vkd3d-to-52b9aa416bb4e8be2fb6e28ffd1234cc10d.patch @@ -1,4 +1,4 @@ -From e962b7b825187b410bb18a20c2cd80be39adde17 Mon Sep 17 00:00:00 2001 +From 610c33ccfaabe19a0b07f48bd52597e7d3194260 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. diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-cb8c851bec08a9483ce52f57c71922c9b14.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-cb8c851bec08a9483ce52f57c71922c9b14.patch new file mode 100644 index 00000000..42dcbf8c --- /dev/null +++ b/patches/vkd3d-latest/0005-Updated-vkd3d-to-cb8c851bec08a9483ce52f57c71922c9b14.patch @@ -0,0 +1,830 @@ +From 2d5f778bb2ca586980b7974b07d37fedd35d69fd 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 new file mode 100644 index 00000000..88eaae2a --- /dev/null +++ b/patches/vkd3d-latest/0006-Updated-vkd3d-to-b4174f52521fa4921babad6f1c374d5e9c2.patch @@ -0,0 +1,1243 @@ +From 673dd99db756087e48ebef26464eea89ff5e63c2 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 +