diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-e69f3da089d472b723b016ef67c04c0f954.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-e69f3da089d472b723b016ef67c04c0f954.patch index bf0c30ec..a95bbe37 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 45ec4834e0dc9c581ad36f702f0b46344599451b Mon Sep 17 00:00:00 2001 +From cbe5d8ece42a672f12b79eccf708428eddfcdcb4 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. @@ -37,10 +37,10 @@ Subject: [PATCH] Updated vkd3d to e69f3da089d472b723b016ef67c04c0f954fa792. 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 +index d81ab7da6cf..6529571a60e 100644 --- a/dlls/msado15/tests/msado15.c +++ b/dlls/msado15/tests/msado15.c -@@ -2023,8 +2023,8 @@ START_TEST(msado15) +@@ -2046,8 +2046,8 @@ START_TEST(msado15) setup_database(); test_Connection(); diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-cd64aa69c886c7dd7148072ee69b6e70bff.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-cd64aa69c886c7dd7148072ee69b6e70bff.patch index 43ae63be..d933fe97 100644 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-cd64aa69c886c7dd7148072ee69b6e70bff.patch +++ b/patches/vkd3d-latest/0002-Updated-vkd3d-to-cd64aa69c886c7dd7148072ee69b6e70bff.patch @@ -1,4 +1,4 @@ -From 9b60d920c564bef944c2e4becd92dd61775ea468 Mon Sep 17 00:00:00 2001 +From a42f0f57fe9b61c4591efe5fd148ee2e0e1752a4 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. diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-b5b5c67b34be0c54bb4ee8a5439d65c2d1d.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-b5b5c67b34be0c54bb4ee8a5439d65c2d1d.patch index 6a85730c..6f6b493d 100644 --- a/patches/vkd3d-latest/0003-Updated-vkd3d-to-b5b5c67b34be0c54bb4ee8a5439d65c2d1d.patch +++ b/patches/vkd3d-latest/0003-Updated-vkd3d-to-b5b5c67b34be0c54bb4ee8a5439d65c2d1d.patch @@ -1,4 +1,4 @@ -From 55e98ca5107db1afba25205f66972abed9ff9f1c Mon Sep 17 00:00:00 2001 +From 4d87ad9ccaeae715096c6248fe60ddaacc182575 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. diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-40bdaa43af3414d25e43b477bf813b81827.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-40bdaa43af3414d25e43b477bf813b81827.patch index c221ca3b..3deb31ca 100644 --- a/patches/vkd3d-latest/0004-Updated-vkd3d-to-40bdaa43af3414d25e43b477bf813b81827.patch +++ b/patches/vkd3d-latest/0004-Updated-vkd3d-to-40bdaa43af3414d25e43b477bf813b81827.patch @@ -1,4 +1,4 @@ -From c2d961c5158c255d753f41664c8aa2a5ec04f7e0 Mon Sep 17 00:00:00 2001 +From 5866455f54b6310fdc5e7e3c8f3503aa55118657 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. diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-507990d3c5a7b61ad5df63a17bbd122d8dc.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-507990d3c5a7b61ad5df63a17bbd122d8dc.patch index fff8c28e..5497462b 100644 --- a/patches/vkd3d-latest/0005-Updated-vkd3d-to-507990d3c5a7b61ad5df63a17bbd122d8dc.patch +++ b/patches/vkd3d-latest/0005-Updated-vkd3d-to-507990d3c5a7b61ad5df63a17bbd122d8dc.patch @@ -1,4 +1,4 @@ -From 84eb0cbafd4a64b81f4da5c0dbdc38242baf2ce5 Mon Sep 17 00:00:00 2001 +From 653731fd7468dc26bc87777a24d8b4ae26a3d93e 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. diff --git a/patches/vkd3d-latest/0006-Updated-vkd3d-to-86b8f2de3546603c67e1f2828a68b1cd0aa.patch b/patches/vkd3d-latest/0006-Updated-vkd3d-to-86b8f2de3546603c67e1f2828a68b1cd0aa.patch index 9063f251..70c64c28 100644 --- a/patches/vkd3d-latest/0006-Updated-vkd3d-to-86b8f2de3546603c67e1f2828a68b1cd0aa.patch +++ b/patches/vkd3d-latest/0006-Updated-vkd3d-to-86b8f2de3546603c67e1f2828a68b1cd0aa.patch @@ -1,4 +1,4 @@ -From f59dd7827d7a6d436fecc303aea3a4241802d869 Mon Sep 17 00:00:00 2001 +From f6ccbf9518ca22514548ca078947750430f8ada7 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Sat, 18 Oct 2025 15:15:36 +1100 Subject: [PATCH] Updated vkd3d to 86b8f2de3546603c67e1f2828a68b1cd0aa049df. diff --git a/patches/vkd3d-latest/0007-Updated-vkd3d-to-d3f658d410c42d739bdb3513bfdbd3f4e78.patch b/patches/vkd3d-latest/0007-Updated-vkd3d-to-d3f658d410c42d739bdb3513bfdbd3f4e78.patch new file mode 100644 index 00000000..0e405e50 --- /dev/null +++ b/patches/vkd3d-latest/0007-Updated-vkd3d-to-d3f658d410c42d739bdb3513bfdbd3f4e78.patch @@ -0,0 +1,1527 @@ +From 65b2564bc2e373169e5de6198d42600dd8a44273 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Thu, 30 Oct 2025 06:55:00 +1100 +Subject: [PATCH] Updated vkd3d to d3f658d410c42d739bdb3513bfdbd3f4e787c528. + +--- + libs/vkd3d/include/vkd3d_shader.h | 77 ++++++ + libs/vkd3d/libs/vkd3d-shader/glsl.c | 1 + + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 6 + + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 11 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 25 +- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 172 ++++---------- + .../libs/vkd3d-shader/hlsl_constant_ops.c | 66 ++---- + libs/vkd3d/libs/vkd3d-shader/ir.c | 223 ++++++++++++++++-- + libs/vkd3d/libs/vkd3d-shader/msl.c | 216 ++++++----------- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 9 +- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 2 - + .../libs/vkd3d-shader/vkd3d_shader_private.h | 1 + + 12 files changed, 451 insertions(+), 358 deletions(-) + +diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h +index df1f5d5250d..50bcf6b292b 100644 +--- a/libs/vkd3d/include/vkd3d_shader.h ++++ b/libs/vkd3d/include/vkd3d_shader.h +@@ -961,6 +961,83 @@ enum vkd3d_shader_parameter_name + * \since 1.15 + */ + VKD3D_SHADER_PARAMETER_NAME_FOG_SOURCE, ++ /** ++ * Bump-mapping matrix. This parameter is used in the evaluation of the ++ * Shader Model 1.x instructions BEM, TEXBEM, and TEXBEML. ++ * ++ * This parameter specifies a 2x2 matrix, packed into a vector in the order ++ * [00, 01, 10, 11], where "01" specifies the component at column 0 and row ++ * 1. These coordinates correspond to the Direct3D notation. ++ * ++ * To use this parameter to implement Direct3D bump mapping, pass the values ++ * of the texture stage states D3DTSS_BUMPENVMAT00, D3DTSS_BUMPENVMAT01, ++ * D3DTSS_BUMPENVMAT10, and D3DTSS_BUMPENVMAT11, in that order. ++ * ++ * These enum values are contiguous and arithmetic may safely be performed ++ * on them. That is, VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_[n] is ++ * VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_0 plus n. ++ * ++ * The data type for each parameter must be ++ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4. ++ * ++ * The default value for each parameter is the zero matrix [0, 0; 0, 0]. ++ * ++ * \since 1.18 ++ */ ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_0, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_1, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_2, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_3, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_4, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_5, ++ /** ++ * Bump-mapping luminance scale factor. This parameter is used in the ++ * evaluation of the Shader Model 1.x instruction TEXBEML. ++ * ++ * To use this parameter to implement Direct3D bump mapping, pass the value ++ * of the texture stage state D3DTSS_BUMPENVLSCALE. ++ * ++ * These enum values are contiguous and arithmetic may safely be performed ++ * on them. That is, VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_SCALE_[n] is ++ * VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_SCALE_0 plus n. ++ * ++ * The data type for each parameter must be ++ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32. ++ * ++ * The default value for each parameter is 0.0. ++ * ++ * \since 1.18 ++ */ ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_SCALE_0, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_SCALE_1, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_SCALE_2, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_SCALE_3, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_SCALE_4, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_SCALE_5, ++ /** ++ * Bump-mapping luminance offset. This parameter is used in the ++ * evaluation of the Shader Model 1.x instruction TEXBEML. ++ * ++ * To use this parameter to implement Direct3D bump mapping, pass the value ++ * of the texture stage state D3DTSS_BUMPENVLOFFSET. ++ * ++ * These enum values are contiguous and arithmetic may safely be performed ++ * on them. That is, VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_[n] is ++ * VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_0 plus n. ++ * ++ * The data type for each parameter must be ++ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32. ++ * ++ * The default value for each parameter is 0.0. ++ * ++ * \since 1.18 ++ */ ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_0, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_1, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_2, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_3, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_4, ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_5, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME), + }; +diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c +index 073282db129..4d7505d8740 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c +@@ -2482,6 +2482,7 @@ int glsl_compile(struct vsir_program *program, uint64_t config_flags, + + VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_SM6); + VKD3D_ASSERT(program->has_descriptor_info); ++ VKD3D_ASSERT(program->has_no_modifiers); + + vkd3d_glsl_generator_init(&generator, program, compile_info, + combined_sampler_info, message_context); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +index 3b0a7acb52a..1de17e2b551 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +@@ -1737,6 +1737,12 @@ struct hlsl_ir_node *hlsl_new_constant(struct hlsl_ctx *ctx, struct hlsl_type *t + return &c->node; + } + ++struct hlsl_ir_node *hlsl_block_add_constant(struct hlsl_ctx *ctx, struct hlsl_block *block, ++ struct hlsl_type *type, const struct hlsl_constant_value *value, const struct vkd3d_shader_location *loc) ++{ ++ return append_new_instr(ctx, block, hlsl_new_constant(ctx, type, value, loc)); ++} ++ + struct hlsl_ir_node *hlsl_new_bool_constant(struct hlsl_ctx *ctx, bool b, const struct vkd3d_shader_location *loc) + { + struct hlsl_constant_value value; +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +index 829fcba0aab..75027f83e33 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +@@ -1579,6 +1579,8 @@ struct hlsl_ir_node *hlsl_block_add_binary_expr(struct hlsl_ctx *ctx, struct hls + enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2); + struct hlsl_ir_node *hlsl_block_add_cast(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_ir_node *arg, struct hlsl_type *type, const struct vkd3d_shader_location *loc); ++struct hlsl_ir_node *hlsl_block_add_constant(struct hlsl_ctx *ctx, struct hlsl_block *block, ++ struct hlsl_type *type, const struct hlsl_constant_value *value, const struct vkd3d_shader_location *loc); + struct hlsl_ir_node *hlsl_block_add_expr(struct hlsl_ctx *ctx, struct hlsl_block *block, + 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); +@@ -1833,10 +1835,13 @@ unsigned int hlsl_offset_from_deref_safe(struct hlsl_ctx *ctx, const struct hlsl + struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref); + + bool hlsl_copy_propagation_execute(struct hlsl_ctx *ctx, struct hlsl_block *block); +-bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context); +-bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context); ++struct hlsl_ir_node *hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block); ++struct hlsl_ir_node *hlsl_fold_constant_identities(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block); + bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context); +-bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context); ++struct hlsl_ir_node *hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block); + bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), + struct hlsl_block *block, void *context); + +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index 759dadf8a58..8ec963c8656 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -3038,10 +3038,7 @@ static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx, + if (!param->default_values[j].string) + { + value.u[0] = param->default_values[j].number; +- if (!(comp = hlsl_new_constant(ctx, type, &value, loc))) +- return NULL; +- hlsl_block_add_instr(args->instrs, comp); +- ++ comp = hlsl_block_add_constant(ctx, args->instrs, type, &value, loc); + hlsl_block_add_store_component(ctx, args->instrs, ¶m_deref, j, comp); + } + } +@@ -3956,7 +3953,6 @@ static bool intrinsic_firstbithigh(struct hlsl_ctx *ctx, + 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, +@@ -3978,20 +3974,14 @@ static bool intrinsic_firstbithigh(struct hlsl_ctx *ctx, + 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); ++ c = hlsl_block_add_uint_constant(ctx, params->instrs, 0x1f, loc); + + 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); ++ c = hlsl_block_add_uint_constant(ctx, params->instrs, ~0u, loc); + + if (!(eq = add_binary_comparison_expr(ctx, params->instrs, HLSL_OP2_EQUAL, clz, c, loc))) + return false; +@@ -4043,9 +4033,7 @@ static bool intrinsic_fmod(struct hlsl_ctx *ctx, const struct parse_initializer + if (!(div = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_DIV, x, y, loc))) + return false; + +- if (!(zero = hlsl_new_constant(ctx, div->data_type, &zero_value, loc))) +- return false; +- hlsl_block_add_instr(params->instrs, zero); ++ zero = hlsl_block_add_constant(ctx, params->instrs, div->data_type, &zero_value, loc); + + if (!(abs = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_ABS, div, loc))) + return false; +@@ -4641,9 +4629,8 @@ static bool intrinsic_sign(struct hlsl_ctx *ctx, + struct hlsl_type *int_type = hlsl_get_numeric_type(ctx, arg->data_type->class, HLSL_TYPE_INT, + arg->data_type->e.numeric.dimx, arg->data_type->e.numeric.dimy); + +- if (!(zero = hlsl_new_constant(ctx, hlsl_get_scalar_type(ctx, arg->data_type->e.numeric.type), &zero_value, loc))) +- return false; +- hlsl_block_add_instr(params->instrs, zero); ++ zero = hlsl_block_add_constant(ctx, params->instrs, ++ hlsl_get_scalar_type(ctx, arg->data_type->e.numeric.type), &zero_value, loc); + + /* Check if 0 < arg, cast bool to int */ + +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index 8f4e4cda73f..9048214923b 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -4058,9 +4058,7 @@ static struct hlsl_ir_node *lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx + value.u[1].u = 1; + 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 NULL; +- hlsl_block_add_instr(block, c); ++ c = hlsl_block_add_constant(ctx, block, hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, width), &value, &instr->loc); + + operands[0] = swizzle; + operands[1] = c; +@@ -4172,10 +4170,7 @@ static struct hlsl_ir_node *lower_nonconstant_array_loads(struct hlsl_ctx *ctx, + if (!(var = hlsl_new_synthetic_var(ctx, row_major ? "row_major-load" : "array-load", instr->data_type, &instr->loc))) + return NULL; + +- if (!(zero = hlsl_new_constant(ctx, instr->data_type, &zero_value, &instr->loc))) +- return NULL; +- hlsl_block_add_instr(block, zero); +- ++ zero = hlsl_block_add_constant(ctx, block, instr->data_type, &zero_value, &instr->loc); + hlsl_block_add_simple_store(ctx, block, var, zero); + + TRACE("Lowering non-constant %s load on variable '%s'.\n", row_major ? "row_major" : "array", deref->var->name); +@@ -4540,17 +4535,13 @@ static struct hlsl_ir_node *lower_trunc(struct hlsl_ctx *ctx, struct hlsl_ir_nod + struct hlsl_constant_value zero_value, one_value; + + memset(&zero_value, 0, sizeof(zero_value)); +- if (!(zero = hlsl_new_constant(ctx, arg->data_type, &zero_value, &instr->loc))) +- return NULL; +- hlsl_block_add_instr(block, zero); ++ zero = hlsl_block_add_constant(ctx, block, arg->data_type, &zero_value, &instr->loc); + + one_value.u[0].f = 1.0; + one_value.u[1].f = 1.0; + 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 NULL; +- hlsl_block_add_instr(block, one); ++ one = hlsl_block_add_constant(ctx, block, arg->data_type, &one_value, &instr->loc); + + 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); +@@ -4745,9 +4736,7 @@ static struct hlsl_ir_node *lower_round(struct hlsl_ctx *ctx, struct hlsl_ir_nod + 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 NULL; +- hlsl_block_add_instr(block, half); ++ half = hlsl_block_add_constant(ctx, block, type, &half_value, &expr->node.loc); + + 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); +@@ -4828,15 +4817,10 @@ static struct hlsl_ir_node *lower_trig(struct hlsl_ctx *ctx, struct hlsl_ir_node + neg_pi_value.u[i].f = -M_PI; + } + +- if (!(half = hlsl_new_constant(ctx, type, &half_value, &instr->loc)) +- || !(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 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); ++ half = hlsl_block_add_constant(ctx, block, type, &half_value, &instr->loc); ++ two_pi = hlsl_block_add_constant(ctx, block, type, &two_pi_value, &instr->loc); ++ reciprocal_two_pi = hlsl_block_add_constant(ctx, block, type, &reciprocal_two_pi_value, &instr->loc); ++ neg_pi = hlsl_block_add_constant(ctx, block, type, &neg_pi_value, &instr->loc); + + if (!(mad = hlsl_new_ternary_expr(ctx, HLSL_OP3_MAD, arg, reciprocal_two_pi, half))) + return NULL; +@@ -4905,10 +4889,7 @@ static struct hlsl_ir_node *lower_logic_not(struct hlsl_ctx *ctx, struct hlsl_ir + one_value.u[1].f = 1.0; + 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 NULL; +- hlsl_block_add_instr(block, one); +- ++ one = hlsl_block_add_constant(ctx, block, float_type, &one_value, &instr->loc); + sub = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, one, neg); + + memset(operands, 0, sizeof(operands)); +@@ -5069,10 +5050,7 @@ static struct hlsl_ir_node *lower_comparison_operators(struct hlsl_ctx *ctx, str + one_value.u[1].f = 1.0; + 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 NULL; +- hlsl_block_add_instr(block, one); +- ++ one = hlsl_block_add_constant(ctx, block, float_type, &one_value, &instr->loc); + slt_neg = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_NEG, slt, &instr->loc); + res = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, one, slt_neg); + } +@@ -5119,17 +5097,13 @@ static struct hlsl_ir_node *lower_slt(struct hlsl_ctx *ctx, struct hlsl_ir_node + sub = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, arg1_cast, neg); + + memset(&zero_value, 0, sizeof(zero_value)); +- if (!(zero = hlsl_new_constant(ctx, float_type, &zero_value, &instr->loc))) +- return NULL; +- hlsl_block_add_instr(block, zero); ++ zero = hlsl_block_add_constant(ctx, block, float_type, &zero_value, &instr->loc); + + one_value.u[0].f = 1.0; + one_value.u[1].f = 1.0; + 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 NULL; +- hlsl_block_add_instr(block, one); ++ one = hlsl_block_add_constant(ctx, block, float_type, &one_value, &instr->loc); + + if (!(cmp = hlsl_new_ternary_expr(ctx, HLSL_OP3_CMP, sub, zero, one))) + return NULL; +@@ -5168,17 +5142,13 @@ static struct hlsl_ir_node *lower_cmp(struct hlsl_ctx *ctx, struct hlsl_ir_node + } + + memset(&zero_value, 0, sizeof(zero_value)); +- if (!(zero = hlsl_new_constant(ctx, float_type, &zero_value, &instr->loc))) +- return NULL; +- hlsl_block_add_instr(block, zero); ++ zero = hlsl_block_add_constant(ctx, block, float_type, &zero_value, &instr->loc); + + one_value.u[0].f = 1.0; + one_value.u[1].f = 1.0; + 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 NULL; +- hlsl_block_add_instr(block, one); ++ one = hlsl_block_add_constant(ctx, block, float_type, &one_value, &instr->loc); + + slt = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_SLT, args_cast[0], zero); + mul1 = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MUL, args_cast[2], slt); +@@ -5210,11 +5180,7 @@ static struct hlsl_ir_node *lower_casts_to_bool(struct hlsl_ctx *ctx, + /* 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 NULL; +- hlsl_block_add_instr(block, zero); +- ++ zero = hlsl_block_add_constant(ctx, block, arg_type, &zero_value, &instr->loc); + neq = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_NEQUAL, expr->operands[0].node, zero); + neq->data_type = expr->node.data_type; + return neq; +@@ -5267,10 +5233,7 @@ static struct hlsl_ir_node *lower_int_division_sm4(struct hlsl_ctx *ctx, + + 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 NULL; +- hlsl_block_add_instr(block, high_bit); +- ++ high_bit = hlsl_block_add_constant(ctx, block, type, &high_bit_value, &instr->loc); + and = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_BIT_AND, xor, high_bit); + abs1 = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_ABS, arg1, &instr->loc); + cast1 = hlsl_block_add_cast(ctx, block, abs1, utype, &instr->loc); +@@ -5306,10 +5269,7 @@ static struct hlsl_ir_node *lower_int_modulus_sm4(struct hlsl_ctx *ctx, + + 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 NULL; +- hlsl_block_add_instr(block, high_bit); +- ++ high_bit = hlsl_block_add_constant(ctx, block, type, &high_bit_value, &instr->loc); + and = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_BIT_AND, arg1, high_bit); + abs1 = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_ABS, arg1, &instr->loc); + cast1 = hlsl_block_add_cast(ctx, block, abs1, utype, &instr->loc); +@@ -5418,10 +5378,7 @@ static struct hlsl_ir_node *lower_float_modulus(struct hlsl_ctx *ctx, + + 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 NULL; +- hlsl_block_add_instr(block, one); +- ++ one = hlsl_block_add_constant(ctx, block, type, &one_value, &instr->loc); + 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); +@@ -5447,9 +5404,7 @@ static bool lower_discard_neg(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + hlsl_block_init(&block); + + arg_type = jump->condition.node->data_type; +- if (!(zero = hlsl_new_constant(ctx, arg_type, &zero_value, &instr->loc))) +- return false; +- hlsl_block_add_instr(&block, zero); ++ zero = hlsl_block_add_constant(ctx, &block, arg_type, &zero_value, &instr->loc); + + operands[0] = jump->condition.node; + operands[1] = zero; +@@ -5457,9 +5412,8 @@ static bool lower_discard_neg(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + arg_type->e.numeric.dimx, arg_type->e.numeric.dimy); + cmp = hlsl_block_add_expr(ctx, &block, HLSL_OP2_LESS, operands, cmp_type, &instr->loc); + +- if (!(bool_false = hlsl_new_constant(ctx, hlsl_get_scalar_type(ctx, HLSL_TYPE_BOOL), &zero_value, &instr->loc))) +- return false; +- hlsl_block_add_instr(&block, bool_false); ++ bool_false = hlsl_block_add_constant(ctx, &block, ++ hlsl_get_scalar_type(ctx, HLSL_TYPE_BOOL), &zero_value, &instr->loc); + + or = bool_false; + +@@ -8417,22 +8371,21 @@ static struct hlsl_ir_node *evaluate_conditionals_recurse(struct hlsl_ctx *ctx, + return NULL; + } + +-static bool fold_conditional_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) ++static struct hlsl_ir_node *fold_conditional_identities(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_node *c, *x, *y, *res_x, *res_y; +- struct hlsl_ir_node *res = NULL; + struct hlsl_ir_expr *expr, *ec; +- struct hlsl_block block; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + + if (instr->data_type->class > HLSL_CLASS_VECTOR) +- return false; ++ return NULL; + + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP3_TERNARY) +- return false; ++ return NULL; + + c = expr->operands[0].node; + x = expr->operands[1].node; +@@ -8440,74 +8393,45 @@ static bool fold_conditional_identities(struct hlsl_ctx *ctx, struct hlsl_ir_nod + + VKD3D_ASSERT(c->data_type->e.numeric.type == HLSL_TYPE_BOOL); + ++ /* c ? x : x -> x */ + if (nodes_are_equivalent(x, y)) +- { +- /* c ? x : x -> x */ +- hlsl_replace_node(instr, x); +- return true; +- } ++ return x; + + if (c->type == HLSL_IR_CONSTANT) + { ++ /* false ? x : y -> y */ + if (hlsl_constant_is_zero(hlsl_ir_constant(c))) +- { +- /* false ? x : y -> y */ +- hlsl_replace_node(instr, y); +- return true; +- } ++ return y; + ++ /* true ? x : y -> x */ + if (hlsl_constant_is_one(hlsl_ir_constant(c))) +- { +- /* true ? x : y -> x */ +- hlsl_replace_node(instr, x); +- return true; +- } ++ return x; + } + +- hlsl_block_init(&block); +- + if (x->type == HLSL_IR_CONSTANT && y->type == HLSL_IR_CONSTANT + && hlsl_types_are_equal(c->data_type, x->data_type) + && hlsl_types_are_equal(c->data_type, y->data_type)) + { ++ /* c ? true : false -> c */ + if (hlsl_constant_is_one(hlsl_ir_constant(x)) && hlsl_constant_is_zero(hlsl_ir_constant(y))) +- { +- /* c ? true : false -> c */ +- res = c; +- goto done; +- } ++ return c; + ++ /* c ? false : true -> !c */ + if (hlsl_constant_is_zero(hlsl_ir_constant(x)) && hlsl_constant_is_one(hlsl_ir_constant(y))) +- { +- /* c ? false : true -> !c */ +- res = hlsl_block_add_unary_expr(ctx, &block, HLSL_OP1_LOGIC_NOT, c, &instr->loc); +- goto done; +- } ++ return hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_LOGIC_NOT, c, &instr->loc); + } + ++ /* !c ? x : y -> c ? y : x */ + ec = c->type == HLSL_IR_EXPR ? hlsl_ir_expr(c) : NULL; + if (ec && ec->op == HLSL_OP1_LOGIC_NOT) +- { +- /* !c ? x : y -> c ? y : x */ +- res = hlsl_add_conditional(ctx, &block, ec->operands[0].node, y, x); +- goto done; +- } ++ return hlsl_add_conditional(ctx, block, ec->operands[0].node, y, x); + +- res_x = evaluate_conditionals_recurse(ctx, &block, c, true, x, &instr->loc); +- res_y = evaluate_conditionals_recurse(ctx, &block, c, false, y, &instr->loc); ++ res_x = evaluate_conditionals_recurse(ctx, block, c, true, x, &instr->loc); ++ res_y = evaluate_conditionals_recurse(ctx, block, c, false, y, &instr->loc); + if (res_x || res_y) +- res = hlsl_add_conditional(ctx, &block, c, res_x ? res_x : x, res_y ? res_y : y); ++ return hlsl_add_conditional(ctx, block, c, res_x ? res_x : x, res_y ? res_y : y); + +-done: +- if (res) +- { +- list_move_before(&instr->entry, &block.instrs); +- hlsl_replace_node(instr, res); +- return true; +- } +- +- hlsl_block_cleanup(&block); +- return false; ++ return NULL; + } + + static bool simplify_exprs(struct hlsl_ctx *ctx, struct hlsl_block *block) +@@ -8516,12 +8440,12 @@ static bool simplify_exprs(struct hlsl_ctx *ctx, struct hlsl_block *block) + + do + { +- progress = hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, block, NULL); ++ progress = replace_ir(ctx, hlsl_fold_constant_exprs, block); + progress |= hlsl_transform_ir(ctx, hlsl_normalize_binary_exprs, block, NULL); + progress |= hlsl_transform_ir(ctx, fold_unary_identities, block, NULL); +- progress |= hlsl_transform_ir(ctx, fold_conditional_identities, block, NULL); +- progress |= hlsl_transform_ir(ctx, hlsl_fold_constant_identities, block, NULL); +- progress |= hlsl_transform_ir(ctx, hlsl_fold_constant_swizzles, block, NULL); ++ progress |= replace_ir(ctx, fold_conditional_identities, block); ++ progress |= replace_ir(ctx, hlsl_fold_constant_identities, block); ++ progress |= replace_ir(ctx, hlsl_fold_constant_swizzles, block); + + any_progress |= progress; + } while (progress); +@@ -14895,7 +14819,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v + 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); ++ replace_ir(ctx, hlsl_fold_constant_exprs, body); + replace_ir(ctx, lower_casts_to_bool, body); + + replace_ir(ctx, lower_casts_to_int, body); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c +index 7b3b0470d5d..1c44e5fa37a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c +@@ -1434,11 +1434,11 @@ static bool fold_rshift(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c + return true; + } + +-bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) ++struct hlsl_ir_node *hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_ir_constant *arg1, *arg2 = NULL, *arg3 = NULL; + struct hlsl_constant_value res = {0}; +- struct hlsl_ir_node *res_node; + struct hlsl_ir_expr *expr; + unsigned int i; + bool success; +@@ -1638,36 +1638,32 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + } + + if (success) +- { +- if (!(res_node = hlsl_new_constant(ctx, instr->data_type, &res, &instr->loc))) +- return false; +- list_add_before(&expr->node.entry, &res_node->entry); +- hlsl_replace_node(&expr->node, res_node); +- } +- return success; ++ return hlsl_block_add_constant(ctx, block, instr->data_type, &res, &instr->loc); ++ ++ return NULL; + } + +-bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) ++struct hlsl_ir_node *hlsl_fold_constant_identities(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + 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; + struct hlsl_ir_expr *expr; + unsigned int i; + + if (instr->type != HLSL_IR_EXPR) +- return false; ++ return NULL; + expr = hlsl_ir_expr(instr); + + if (instr->data_type->class > HLSL_CLASS_VECTOR) +- return false; ++ return NULL; + + /* Verify that the expression has two operands. */ + for (i = 0; i < ARRAY_SIZE(expr->operands); ++i) + { + if (!!expr->operands[i].node != (i < 2)) +- return false; ++ return NULL; + } + + if (expr->operands[0].node->type == HLSL_IR_CONSTANT) +@@ -1682,34 +1678,33 @@ bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + } + else + { +- return false; ++ return NULL; + } + +- res_node = NULL; + switch (expr->op) + { + case HLSL_OP2_ADD: + if (hlsl_constant_is_zero(const_arg)) +- res_node = mut_arg; ++ return mut_arg; + break; + + case HLSL_OP2_MUL: + if (hlsl_constant_is_one(const_arg)) +- res_node = mut_arg; ++ return mut_arg; + break; + + case HLSL_OP2_LOGIC_AND: + if (hlsl_constant_is_zero(const_arg)) +- res_node = &const_arg->node; ++ return &const_arg->node; + else if (hlsl_constant_is_one(const_arg)) +- res_node = mut_arg; ++ return mut_arg; + break; + + case HLSL_OP2_LOGIC_OR: + if (hlsl_constant_is_zero(const_arg)) +- res_node = mut_arg; ++ return mut_arg; + else if (hlsl_constant_is_one(const_arg)) +- res_node = &const_arg->node; ++ return &const_arg->node; + break; + + case HLSL_OP2_LESS: +@@ -1718,21 +1713,13 @@ bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + || 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; ++ return hlsl_block_add_constant(ctx, block, instr->data_type, &zero, &instr->loc); + + default: + break; + } + +- if (res_node) +- { +- hlsl_replace_node(&expr->node, res_node); +- return true; +- } +- return false; ++ return NULL; + } + + static bool is_op_associative(enum hlsl_ir_expr_op op, enum hlsl_base_type type) +@@ -1961,28 +1948,23 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst + return progress; + } + +-bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) ++struct hlsl_ir_node *hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, ++ struct hlsl_ir_node *instr, struct hlsl_block *block) + { + struct hlsl_constant_value value; + struct hlsl_ir_swizzle *swizzle; + struct hlsl_ir_constant *src; +- struct hlsl_ir_node *dst; + unsigned int i; + + if (instr->type != HLSL_IR_SWIZZLE) +- return false; ++ return NULL; + swizzle = hlsl_ir_swizzle(instr); + if (swizzle->val.node->type != HLSL_IR_CONSTANT) +- return false; ++ return NULL; + src = hlsl_ir_constant(swizzle->val.node); + + for (i = 0; i < swizzle->node.data_type->e.numeric.dimx; ++i) + value.u[i] = src->value.u[hlsl_swizzle_get_component(swizzle->u.vector, i)]; + +- if (!(dst = hlsl_new_constant(ctx, instr->data_type, &value, &instr->loc))) +- return false; +- +- list_add_before(&swizzle->node.entry, &dst->entry); +- hlsl_replace_node(&swizzle->node, dst); +- return true; ++ return hlsl_block_add_constant(ctx, block, instr->data_type, &value, &instr->loc); + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 000c78aeed3..a566d65d8cd 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -1987,7 +1987,7 @@ static enum vkd3d_result vsir_program_lower_texcoord(struct vsir_program *progra + unsigned int idx = ins->dst[0].reg.idx[0].offset; + struct vkd3d_shader_src_param *srcs; + +- /* texcoord t# -> mov_sat t#, t# ++ /* texcoord t# -> saturate t#, t# + * Note that the t# destination will subsequently be turned into a temp. */ + + /* We run before I/O normalization. */ +@@ -2001,15 +2001,180 @@ static enum vkd3d_result vsir_program_lower_texcoord(struct vsir_program *progra + 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->opcode = VSIR_OP_SATURATE; + ins->src = srcs; + ins->src_count = 1; + + return VKD3D_OK; + } + ++static struct vkd3d_shader_instruction *generate_bump_coords(struct vsir_program *program, ++ struct vsir_program_iterator *it, uint32_t idx, const struct vkd3d_shader_src_param *coords, ++ const struct vkd3d_shader_src_param *perturbation, const struct vkd3d_shader_location *loc) ++{ ++ struct vkd3d_shader_instruction *ins; ++ uint32_t ssa_temp, ssa_coords; ++ ++ /* We generate the following code: ++ * ++ * mad srTMP.xy, PERTURBATION.xx, BUMP_MATRIX#.xy, COORDS.xy ++ * mad srCOORDS.xy, PERTURBATION.yy, BUMP_MATRIX#.zw, srTMP.xy ++ */ ++ ++ ssa_temp = program->ssa_count++; ++ ssa_coords = program->ssa_count++; ++ ++ ins = vsir_program_iterator_current(it); ++ if (!vsir_instruction_init_with_params(program, ins, loc, VSIR_OP_MAD, 1, 3)) ++ return false; ++ dst_param_init_ssa_float4(&ins->dst[0], ssa_temp); ++ ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; ++ ins->src[0] = *perturbation; ++ ins->src[0].swizzle = vsir_combine_swizzles(perturbation->swizzle, VKD3D_SHADER_SWIZZLE(X, X, X, X)); ++ src_param_init_parameter_vec4(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_0 + idx, VSIR_DATA_F32); ++ ins->src[2] = *coords; ++ ++ ins = vsir_program_iterator_next(it); ++ if (!vsir_instruction_init_with_params(program, ins, loc, VSIR_OP_MAD, 1, 3)) ++ return false; ++ dst_param_init_ssa_float4(&ins->dst[0], ssa_coords); ++ ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; ++ ins->src[0] = *perturbation; ++ ins->src[0].swizzle = vsir_combine_swizzles(perturbation->swizzle, VKD3D_SHADER_SWIZZLE(Y, Y, Y, Y)); ++ src_param_init_parameter_vec4(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_0 + idx, VSIR_DATA_F32); ++ ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(Z, W, W, W); ++ src_param_init_ssa_float4(&ins->src[2], ssa_temp); ++ ins->src[2].swizzle = VKD3D_SHADER_SWIZZLE(X, Y, Y, Y); ++ ++ return ins; ++} ++ ++static enum vkd3d_result vsir_program_lower_bem(struct vsir_program *program, struct vsir_program_iterator *it) ++{ ++ struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(it); ++ const struct vkd3d_shader_location location = ins->location; ++ const struct vkd3d_shader_src_param *src = ins->src; ++ const struct vkd3d_shader_dst_param *dst = ins->dst; ++ ++ /* bem DST.xy, SRC0, SRC1 ++ * -> ++ * mad srTMP.xy, SRC1.xx, BUMP_MATRIX#.xy, SRC0.xy ++ * mad DST.xy, SRC1.yy, BUMP_MATRIX#.zw, srTMP.xy */ ++ ++ if (!vsir_program_iterator_insert_after(it, 1)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ if (!(ins = generate_bump_coords(program, it, dst[0].reg.idx[0].offset, &src[0], &src[1], &location))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ ins->dst[0] = dst[0]; ++ return VKD3D_OK; ++} ++ ++static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, ++ struct vsir_program_iterator *it, struct vkd3d_shader_message_context *message_context) ++{ ++ struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(it); ++ const struct vkd3d_shader_location location = ins->location; ++ const struct vkd3d_shader_descriptor_info1 *descriptor; ++ const struct vkd3d_shader_src_param *src = ins->src; ++ bool is_texbeml = (ins->opcode == VSIR_OP_TEXBEML); ++ unsigned int idx = ins->dst[0].reg.idx[0].offset; ++ uint32_t ssa_coords, ssa_luminance, ssa_sample; ++ struct vkd3d_shader_src_param orig_coords; ++ ++ /* texbem t#, SRC ++ * -> ++ * bem srCOORDS.xy, t#, SRC ++ * texld t#, srCOORDS ++ * -> ++ * mad srTMP.xy, SRC.xx, BUMP_MATRIX#.xy, t#.xy ++ * mad srCOORDS.xy, SRC.yy, BUMP_MATRIX#.zw, srTMP.xy ++ * sample t#, srCOORDS, resource#, sampler# ++ * ++ * Luminance then adds: ++ * ++ * mad srLUM.x, SRC.z, BUMP_LUMINANCE_SCALE#, BUMP_LUMINANCE_OFFSET# ++ * mul t#, t#, srLUM.xxxx ++ * ++ * Note that the t# destination will subsequently be turned into a temp. */ ++ ++ descriptor = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx); ++ if (descriptor->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE) ++ { ++ vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, ++ "Unhandled TEXBEM(L) with a comparison sampler."); ++ return VKD3D_ERROR_NOT_IMPLEMENTED; ++ } ++ ++ descriptor = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, idx); ++ if (descriptor->resource_type != VKD3D_SHADER_RESOURCE_TEXTURE_2D) ++ { ++ vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, ++ "Unhandled TEXBEM(L) with resource dimension %#x.", descriptor->resource_type); ++ return VKD3D_ERROR_NOT_IMPLEMENTED; ++ } ++ ++ if (!vsir_program_iterator_insert_after(it, is_texbeml ? 4 : 2)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ vsir_src_param_init(&orig_coords, VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); ++ orig_coords.reg.idx[0].offset = idx; ++ orig_coords.reg.dimension = VSIR_DIMENSION_VEC4; ++ orig_coords.swizzle = VKD3D_SHADER_NO_SWIZZLE; ++ ++ if (!(ins = generate_bump_coords(program, it, idx, &orig_coords, &src[0], &location))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ssa_coords = ins->dst[0].reg.idx[0].offset; ++ ++ ins = vsir_program_iterator_next(it); ++ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_SAMPLE, 1, 3)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); ++ ins->dst[0].reg.idx[0].offset = idx; ++ ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; ++ src_param_init_ssa_float4(&ins->src[0], ssa_coords); ++ ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, Y, Y, Y); ++ vsir_src_param_init_resource(&ins->src[1], idx, idx); ++ vsir_src_param_init_sampler(&ins->src[2], idx, idx); ++ ++ if (is_texbeml) ++ { ++ enum vkd3d_shader_swizzle_component z = vsir_swizzle_get_component(src[0].swizzle, 2); ++ ++ ssa_sample = program->ssa_count++; ++ ssa_luminance = program->ssa_count++; ++ ++ /* Replace t# destination of the SAMPLE instruction with an SSA value. */ ++ dst_param_init_ssa_float4(&ins->dst[0], ssa_sample); ++ ++ ins = vsir_program_iterator_next(it); ++ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_MAD, 1, 3)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ dst_param_init_ssa_float4(&ins->dst[0], ssa_luminance); ++ ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; ++ ins->src[0] = src[0]; ++ ins->src[0].swizzle = vkd3d_shader_create_swizzle(z, z, z, z); ++ src_param_init_parameter(&ins->src[1], ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_SCALE_0 + idx, VSIR_DATA_F32); ++ src_param_init_parameter(&ins->src[2], ++ VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_0 + idx, VSIR_DATA_F32); ++ ++ ins = vsir_program_iterator_next(it); ++ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_MUL, 1, 2)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); ++ ins->dst[0].reg.idx[0].offset = idx; ++ ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; ++ src_param_init_ssa_float4(&ins->src[0], ssa_sample); ++ src_param_init_ssa_float4(&ins->src[1], ssa_luminance); ++ ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); ++ } ++ 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) + { +@@ -2094,6 +2259,10 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr + + switch (ins->opcode) + { ++ case VSIR_OP_BEM: ++ ret = vsir_program_lower_bem(program, &it); ++ break; ++ + case VSIR_OP_IFC: + ret = vsir_program_lower_ifc(program, &it, &tmp_idx, message_context); + break; +@@ -2102,6 +2271,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_TEXBEM: ++ case VSIR_OP_TEXBEML: ++ ret = vsir_program_lower_texbem(program, &it, message_context); ++ break; ++ + case VSIR_OP_TEXCOORD: + if ((ret = vsir_program_lower_texcoord(program, ins)) < 0) + return ret; +@@ -2136,8 +2310,6 @@ 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: +@@ -2281,6 +2453,8 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr + } + } + ++ program->has_no_modifiers = true; ++ + return ret; + } + +@@ -2445,13 +2619,16 @@ static enum vkd3d_result vsir_program_normalise_ps1_output(struct vsir_program * + struct vkd3d_shader_instruction *ins; + struct vkd3d_shader_location loc; + ++ /* Note we run before I/O normalization. */ ++ VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_SM4); ++ + if (!(ins = vsir_program_iterator_tail(&it))) + return VKD3D_OK; + loc = ins->location; + + if (!(ins = vsir_program_append(program))) + return VKD3D_ERROR_OUT_OF_MEMORY; +- if (!vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1)) ++ if (!vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_SATURATE, 1, 1)) + { + vsir_instruction_init(ins, &loc, VSIR_OP_NOP); + return VKD3D_ERROR_OUT_OF_MEMORY; +@@ -2459,12 +2636,10 @@ static enum vkd3d_result vsir_program_normalise_ps1_output(struct vsir_program * + + src_param_init_temp_float4(&ins->src[0], 0); + ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; +- /* Note we run before I/O normalization. */ + vsir_dst_param_init(&ins->dst[0], VKD3DSPR_COLOROUT, VSIR_DATA_F32, 1); + ins->dst[0].reg.idx[0].offset = 0; + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; +- ins->dst[0].modifiers = VKD3DSPDM_SATURATE; + + return VKD3D_OK; + } +@@ -8344,9 +8519,9 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + * + * neg sr0, vFOG.x + * add sr1, FOG_END, sr0 +- * mul_sat srFACTOR, sr1, FOG_SCALE ++ * mul srFACTOR, sr1, FOG_SCALE + */ +- if (!(ins = vsir_program_iterator_insert_before_and_move(it, 6))) ++ if (!(ins = vsir_program_iterator_insert_before_and_move(it, 7))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + ssa_temp = program->ssa_count++; +@@ -8368,7 +8543,6 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + + 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_temp2); + src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VSIR_DATA_F32); + ins = vsir_program_iterator_next(it); +@@ -8380,9 +8554,9 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + * + * mul sr0, FOG_SCALE, vFOG.x + * neg sr1, sr0 +- * exp_sat srFACTOR, sr1 ++ * exp srFACTOR, sr1 + */ +- if (!(ins = vsir_program_iterator_insert_before_and_move(it, 6))) ++ if (!(ins = vsir_program_iterator_insert_before_and_move(it, 7))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + ssa_temp = program->ssa_count++; +@@ -8404,7 +8578,6 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + + 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 = vsir_program_iterator_next(it); + break; +@@ -8415,9 +8588,9 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + * mul sr0, FOG_SCALE, vFOG.x + * mul sr1, sr0, sr0 + * neg sr2, sr1 +- * exp_sat srFACTOR, sr2 ++ * exp srFACTOR, sr2 + */ +- if (!(ins = vsir_program_iterator_insert_before_and_move(it, 7))) ++ if (!(ins = vsir_program_iterator_insert_before_and_move(it, 8))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + ssa_temp = program->ssa_count++; +@@ -8446,7 +8619,6 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + + 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_temp3); + ins = vsir_program_iterator_next(it); + break; +@@ -8459,10 +8631,12 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + * + * neg sr0, FOG_COLOUR + * add sr1, FRAG_COLOUR, sr0 +- * mad oC0, sr1, srFACTOR, FOG_COLOUR ++ * saturate sr2, srFACTOR ++ * mad oC0, sr1, sr2, FOG_COLOUR + */ + 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_NEG, 1, 1); + dst_param_init_ssa_float4(&ins->dst[0], ssa_temp); +@@ -8475,11 +8649,16 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + 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_SATURATE, 1, 1); ++ dst_param_init_ssa_float(&ins->dst[0], ssa_temp3); ++ src_param_init_ssa_float(&ins->src[0], ssa_factor); ++ 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], ssa_temp2); +- src_param_init_ssa_float(&ins->src[1], ssa_factor); ++ src_param_init_ssa_float(&ins->src[1], ssa_temp3); + src_param_init_parameter_vec4(&ins->src[2], VKD3D_SHADER_PARAMETER_NAME_FOG_COLOUR, VSIR_DATA_F32); + ins = vsir_program_iterator_next(it); + +@@ -10869,7 +11048,7 @@ static void vsir_validate_dst_param(struct validation_context *ctx, + break; + } + +- if (dst->modifiers & ~VKD3DSPDM_MASK) ++ if (dst->modifiers & ~VKD3DSPDM_MASK || (ctx->program->has_no_modifiers && dst->modifiers)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Destination has invalid modifiers %#x.", + dst->modifiers); + +@@ -11050,7 +11229,7 @@ static void vsir_validate_src_param(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, + "Immediate constant source has invalid swizzle %#x.", src->swizzle); + +- if (src->modifiers >= VKD3DSPSM_COUNT) ++ if (src->modifiers >= VKD3DSPSM_COUNT || (ctx->program->has_no_modifiers && src->modifiers)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", + src->modifiers); + +diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c +index 3e7bf831e48..7b4804e8036 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/msl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/msl.c +@@ -209,20 +209,20 @@ static bool msl_check_shader_visibility(const struct msl_generator *gen, + } + } + +-static const struct vkd3d_shader_descriptor_binding *msl_get_cbv_binding(const struct msl_generator *gen, +- unsigned int register_space, unsigned int register_idx) ++static bool msl_get_binding(const struct msl_generator *gen, unsigned int register_space, unsigned int register_idx, ++ enum vkd3d_shader_descriptor_type type, enum vkd3d_shader_binding_flag flags, unsigned int *idx) + { + const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; + unsigned int i; + + if (!interface_info) +- return NULL; ++ return false; + + for (i = 0; i < interface_info->binding_count; ++i) + { + const struct vkd3d_shader_resource_binding *binding = &interface_info->bindings[i]; + +- if (binding->type != VKD3D_SHADER_DESCRIPTOR_TYPE_CBV) ++ if (binding->type != type) + continue; + if (binding->register_space != register_space) + continue; +@@ -230,111 +230,43 @@ static const struct vkd3d_shader_descriptor_binding *msl_get_cbv_binding(const s + continue; + if (!msl_check_shader_visibility(gen, binding->shader_visibility)) + continue; +- if (!(binding->flags & VKD3D_SHADER_BINDING_FLAG_BUFFER)) ++ if ((binding->flags & flags) != flags) + continue; + +- return &binding->binding; ++ *idx = binding->binding.binding; ++ return true; + } + +- return NULL; ++ return false; + } + +-static const struct vkd3d_shader_descriptor_binding *msl_get_sampler_binding(const struct msl_generator *gen, +- unsigned int register_space, unsigned int register_idx) ++static bool msl_get_cbv_binding(const struct msl_generator *gen, ++ unsigned int register_space, unsigned int register_idx, unsigned int *idx) + { +- const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; +- const struct vkd3d_shader_resource_binding *binding; +- unsigned int i; +- +- if (!interface_info) +- return NULL; +- +- for (i = 0; i < interface_info->binding_count; ++i) +- { +- binding = &interface_info->bindings[i]; +- +- if (binding->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) +- continue; +- if (binding->register_space != register_space) +- continue; +- if (binding->register_index != register_idx) +- continue; +- if (!msl_check_shader_visibility(gen, binding->shader_visibility)) +- continue; +- +- return &binding->binding; +- } +- +- return NULL; ++ return msl_get_binding(gen, register_space, register_idx, ++ VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, VKD3D_SHADER_BINDING_FLAG_BUFFER, idx); + } + +-static const struct vkd3d_shader_descriptor_binding *msl_get_srv_binding(const struct msl_generator *gen, +- unsigned int register_space, unsigned int register_idx, enum vkd3d_shader_resource_type resource_type) ++static bool msl_get_sampler_binding(const struct msl_generator *gen, ++ unsigned int register_space, unsigned int register_idx, unsigned int *idx) + { +- const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; +- enum vkd3d_shader_binding_flag resource_type_flag; +- unsigned int i; +- +- if (!interface_info) +- return NULL; +- +- resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER +- ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE; +- +- for (i = 0; i < interface_info->binding_count; ++i) +- { +- const struct vkd3d_shader_resource_binding *binding = &interface_info->bindings[i]; +- +- if (binding->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SRV) +- continue; +- if (binding->register_space != register_space) +- continue; +- if (binding->register_index != register_idx) +- continue; +- if (!msl_check_shader_visibility(gen, binding->shader_visibility)) +- continue; +- if (!(binding->flags & resource_type_flag)) +- continue; +- +- return &binding->binding; +- } +- +- return NULL; ++ return msl_get_binding(gen, register_space, register_idx, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, 0, idx); + } + +-static const struct vkd3d_shader_descriptor_binding *msl_get_uav_binding(const struct msl_generator *gen, +- unsigned int register_space, unsigned int register_idx, enum vkd3d_shader_resource_type resource_type) ++static bool msl_get_srv_binding(const struct msl_generator *gen, unsigned int register_space, ++ unsigned int register_idx, enum vkd3d_shader_resource_type resource_type, unsigned int *idx) + { +- const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; +- const struct vkd3d_shader_resource_binding *binding; +- enum vkd3d_shader_binding_flag resource_type_flag; +- unsigned int i; +- +- if (!interface_info) +- return NULL; +- +- resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER +- ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE; +- +- for (i = 0; i < interface_info->binding_count; ++i) +- { +- binding = &interface_info->bindings[i]; +- +- if (binding->type != VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) +- continue; +- if (binding->register_space != register_space) +- continue; +- if (binding->register_index != register_idx) +- continue; +- if (!msl_check_shader_visibility(gen, binding->shader_visibility)) +- continue; +- if (!(binding->flags & resource_type_flag)) +- continue; +- +- return &binding->binding; +- } ++ return msl_get_binding(gen, register_space, register_idx, ++ VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_type == VKD3D_SHADER_RESOURCE_BUFFER ++ ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE, idx); ++} + +- return NULL; ++static bool msl_get_uav_binding(const struct msl_generator *gen, unsigned int register_space, ++ unsigned int register_idx, enum vkd3d_shader_resource_type resource_type, unsigned int *idx) ++{ ++ return msl_get_binding(gen, register_space, register_idx, ++ VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, resource_type == VKD3D_SHADER_RESOURCE_BUFFER ++ ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE, idx); + } + + static void msl_print_cbv_name(struct vkd3d_string_buffer *buffer, unsigned int binding) +@@ -370,6 +302,9 @@ static void msl_print_uav_name(struct vkd3d_string_buffer *buffer, struct msl_ge + static enum msl_data_type msl_print_register_name(struct vkd3d_string_buffer *buffer, + struct msl_generator *gen, const struct vkd3d_shader_register *reg) + { ++ const struct vkd3d_shader_descriptor_info1 *descriptor; ++ unsigned int binding, cbv_id, cbv_idx; ++ + switch (reg->type) + { + case VKD3DSPR_TEMP: +@@ -441,38 +376,47 @@ static enum msl_data_type msl_print_register_name(struct vkd3d_string_buffer *bu + } + + case VKD3DSPR_CONSTBUFFER: ++ if (reg->idx_count != 3) + { +- const struct vkd3d_shader_descriptor_binding *binding; ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled constant buffer register index count %u.", ++ reg->idx_count); ++ vkd3d_string_buffer_printf(buffer, "", reg->type); ++ return MSL_DATA_UNION; ++ } + +- if (reg->idx_count != 3) +- { +- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, +- "Internal compiler error: Unhandled constant buffer register index count %u.", +- reg->idx_count); +- vkd3d_string_buffer_printf(buffer, "", reg->type); +- return MSL_DATA_UNION; +- } +- if (reg->idx[0].rel_addr || reg->idx[1].rel_addr) +- { +- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, +- "Internal compiler error: Unhandled constant buffer register indirect addressing."); +- vkd3d_string_buffer_printf(buffer, "", reg->type); +- return MSL_DATA_UNION; +- } +- /* FIXME: This should use vkd3d_shader_find_descriptor() to +- * find the resource index/space from the resource ID. */ +- if (!(binding = msl_get_cbv_binding(gen, 0, reg->idx[1].offset))) +- { +- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, +- "No descriptor binding specified for CBV %u.", reg->idx[0].offset); +- vkd3d_string_buffer_printf(buffer, "", reg->type); +- return MSL_DATA_UNION; +- } +- msl_print_cbv_name(buffer, binding->binding); +- msl_print_subscript(buffer, gen, reg->idx[2].rel_addr, reg->idx[2].offset); ++ if (reg->idx[0].rel_addr || reg->idx[1].rel_addr) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled constant buffer register indirect addressing."); ++ vkd3d_string_buffer_printf(buffer, "", reg->type); ++ return MSL_DATA_UNION; ++ } ++ ++ cbv_id = reg->idx[0].offset; ++ cbv_idx = reg->idx[1].offset; ++ ++ if (!(descriptor = vkd3d_shader_find_descriptor(&gen->program->descriptors, ++ VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, cbv_id))) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Undeclared CBV descriptor %u.", cbv_id); ++ vkd3d_string_buffer_printf(buffer, "", reg->type); + return MSL_DATA_UNION; + } + ++ if (!msl_get_cbv_binding(gen, descriptor->register_space, cbv_idx, &binding)) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, ++ "No descriptor binding specified for CBV %u.", cbv_id); ++ vkd3d_string_buffer_printf(buffer, "", reg->type); ++ return MSL_DATA_UNION; ++ } ++ ++ msl_print_cbv_name(buffer, binding); ++ msl_print_subscript(buffer, gen, reg->idx[2].rel_addr, reg->idx[2].offset); ++ return MSL_DATA_UNION; ++ + case VKD3DSPR_IDXTEMP: + vkd3d_string_buffer_printf(buffer, "x%u", reg->idx[0].offset); + msl_print_subscript(buffer, gen, reg->idx[1].rel_addr, reg->idx[1].offset); +@@ -923,7 +867,6 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct + unsigned int resource_id, resource_idx, resource_space, sample_count; + const struct msl_resource_type_info *resource_type_info; + const struct vkd3d_shader_descriptor_info1 *descriptor; +- const struct vkd3d_shader_descriptor_binding *binding; + enum vkd3d_shader_resource_type resource_type; + uint32_t coord_mask, write_mask_size; + struct vkd3d_string_buffer *read; +@@ -985,11 +928,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct + } + coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); + +- if ((binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) +- { +- srv_binding = binding->binding; +- } +- else ++ if (!msl_get_srv_binding(gen, resource_space, resource_idx, resource_type, &srv_binding)) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, + "No descriptor binding specified for SRV %u (index %u, space %u).", +@@ -1042,7 +981,6 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + const struct msl_resource_type_info *resource_type_info; + const struct vkd3d_shader_src_param *resource, *sampler; + unsigned int resource_id, resource_idx, resource_space; +- const struct vkd3d_shader_descriptor_binding *binding; + unsigned int sampler_id, sampler_idx, sampler_space; + const struct vkd3d_shader_descriptor_info1 *d; + enum vkd3d_shader_resource_type resource_type; +@@ -1114,11 +1052,7 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + } + coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); + +- if ((binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) +- { +- srv_binding = binding->binding; +- } +- else ++ if (!msl_get_srv_binding(gen, resource_space, resource_idx, resource_type, &srv_binding)) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, + "No descriptor binding specified for SRV %u (index %u, space %u).", +@@ -1154,11 +1088,7 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + sampler_space = 0; + } + +- if ((binding = msl_get_sampler_binding(gen, sampler_space, sampler_idx))) +- { +- sampler_binding = binding->binding; +- } +- else ++ if (!msl_get_sampler_binding(gen, sampler_space, sampler_idx, &sampler_binding)) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, + "No descriptor binding specified for sampler %u (index %u, space %u).", +@@ -1256,7 +1186,6 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) + { + const struct msl_resource_type_info *resource_type_info; +- const struct vkd3d_shader_descriptor_binding *binding; + const struct vkd3d_shader_descriptor_info1 *d; + enum vkd3d_shader_resource_type resource_type; + unsigned int uav_id, uav_idx, uav_space; +@@ -1300,11 +1229,7 @@ static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_sh + } + coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); + +- if ((binding = msl_get_uav_binding(gen, uav_space, uav_idx, resource_type))) +- { +- uav_binding = binding->binding; +- } +- else ++ if (!msl_get_uav_binding(gen, uav_space, uav_idx, resource_type, &uav_binding)) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, + "No descriptor binding specified for UAV %u (index %u, space %u).", +@@ -2334,6 +2259,7 @@ int msl_compile(struct vsir_program *program, uint64_t config_flags, + + VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_SM6); + VKD3D_ASSERT(program->has_descriptor_info); ++ VKD3D_ASSERT(program->has_no_modifiers); + + if ((ret = msl_generator_init(&generator, program, compile_info, message_context)) < 0) + return ret; +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index 0f5df228121..aae5f6b5534 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -4752,8 +4752,14 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, + else if (reg->type == VKD3DSPR_UNDEF) + return spirv_compiler_emit_load_undef(compiler, reg, write_mask); + else if (reg->type == VKD3DSPR_PARAMETER) +- return spirv_compiler_emit_shader_parameter(compiler, reg->idx[0].offset, ++ { ++ val_id = spirv_compiler_emit_shader_parameter(compiler, reg->idx[0].offset, + reg->data_type, reg->dimension == VSIR_DIMENSION_VEC4 ? 4 : 1); ++ if (reg->dimension != VSIR_DIMENSION_VEC4) ++ return val_id; ++ return spirv_compiler_emit_swizzle(compiler, val_id, ++ VKD3DSP_WRITEMASK_ALL, reg->data_type, swizzle, write_mask); ++ } + + component_count = vsir_write_mask_component_count(write_mask); + +@@ -11060,6 +11066,7 @@ int spirv_compile(struct vsir_program *program, uint64_t config_flags, + + VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_SM6); + VKD3D_ASSERT(program->has_descriptor_info); ++ VKD3D_ASSERT(program->has_no_modifiers); + + if (!(spirv_compiler = spirv_compiler_create(program, compile_info, + message_context, config_flags))) +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index 821c639ee16..c0faa30f14a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -1503,8 +1503,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_TEXBEM: +- case VSIR_OP_TEXBEML: + case VSIR_OP_TEXDP3TEX: + case VSIR_OP_TEXM3x2TEX: + case VSIR_OP_TEXM3x3SPEC: +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 346c74ff698..404e7cec6ea 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -1610,6 +1610,7 @@ struct vsir_program + uint8_t diffuse_written_mask; + enum vsir_control_flow_type cf_type; + enum vsir_normalisation_level normalisation_level; ++ bool has_no_modifiers; + enum vkd3d_tessellator_domain tess_domain; + enum vkd3d_shader_tessellator_partitioning tess_partitioning; + enum vkd3d_shader_tessellator_output_primitive tess_output_primitive; +-- +2.51.0 + diff --git a/patches/vkd3d-latest/0008-Updated-vkd3d-to-39391230d27d58f4e7e8786ba32a0ca133b.patch b/patches/vkd3d-latest/0008-Updated-vkd3d-to-39391230d27d58f4e7e8786ba32a0ca133b.patch new file mode 100644 index 00000000..6d9fef92 --- /dev/null +++ b/patches/vkd3d-latest/0008-Updated-vkd3d-to-39391230d27d58f4e7e8786ba32a0ca133b.patch @@ -0,0 +1,743 @@ +From 94dda6de862380f5d527ebd1690a3be3aac2fba8 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Thu, 30 Oct 2025 06:55:15 +1100 +Subject: [PATCH] Updated vkd3d to 39391230d27d58f4e7e8786ba32a0ca133b28fc0. + +--- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 264 ++++++++++++++------------- + libs/vkd3d/libs/vkd3d-shader/ir.c | 25 +++ + libs/vkd3d/libs/vkd3d-shader/msl.c | 61 +++---- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 65 +++---- + 4 files changed, 221 insertions(+), 194 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index 7861efc16d2..8d803b91f7a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -647,13 +647,13 @@ enum sm6_value_type + { + VALUE_TYPE_INVALID, + VALUE_TYPE_FUNCTION, +- VALUE_TYPE_DATA, + VALUE_TYPE_HANDLE, + VALUE_TYPE_SSA, + VALUE_TYPE_ICB, + VALUE_TYPE_IDXTEMP, + VALUE_TYPE_GROUPSHAREDMEM, + VALUE_TYPE_CONSTANT, ++ VALUE_TYPE_CONSTANT_ARRAY, + VALUE_TYPE_UNDEFINED, + }; + +@@ -706,6 +706,12 @@ struct sm6_constant_data + union vsir_immediate_constant immconst; + }; + ++struct sm6_constant_array_data ++{ ++ const struct vkd3d_shader_immediate_constant_buffer *icb; ++ const uint64_t *elements; ++}; ++ + struct sm6_value + { + const struct sm6_type *type; +@@ -716,13 +722,13 @@ struct sm6_value + union + { + struct sm6_function_data function; +- const struct vkd3d_shader_immediate_constant_buffer *data; + struct sm6_handle_data handle; + struct sm6_ssa_data ssa; + struct sm6_icb_data icb; + struct sm6_idxtemp_data idxtemp; + struct sm6_groupsharedmem_data groupsharedmem; + struct sm6_constant_data constant; ++ struct sm6_constant_array_data constant_array; + } u; + }; + +@@ -2280,6 +2286,11 @@ static inline bool sm6_value_is_constant(const struct sm6_value *value) + return value->value_type == VALUE_TYPE_CONSTANT; + } + ++static bool sm6_value_is_constant_array(const struct sm6_value *value) ++{ ++ return value->value_type == VALUE_TYPE_CONSTANT_ARRAY; ++} ++ + static bool sm6_value_is_constant_zero(const struct sm6_value *value) + { + if (value->value_type != VALUE_TYPE_CONSTANT) +@@ -2323,11 +2334,6 @@ static bool sm6_value_vector_is_constant_or_undef(const struct sm6_value **value + return true; + } + +-static bool sm6_value_is_data(const struct sm6_value *value) +-{ +- return value->value_type == VALUE_TYPE_DATA; +-} +- + static bool sm6_value_is_ssa(const struct sm6_value *value) + { + return value->value_type == VALUE_TYPE_SSA; +@@ -2662,7 +2668,7 @@ static void vsir_register_from_dxil_value(struct vkd3d_shader_register *reg, + + case VALUE_TYPE_FUNCTION: + case VALUE_TYPE_HANDLE: +- case VALUE_TYPE_DATA: ++ case VALUE_TYPE_CONSTANT_ARRAY: + vkd3d_unreachable(); + } + +@@ -3067,7 +3073,7 @@ static bool sm6_value_validate_is_i32(const struct sm6_value *value, struct sm6_ + return true; + } + +-static const struct sm6_value *sm6_parser_get_value_safe(struct sm6_parser *sm6, unsigned int idx) ++static struct sm6_value *sm6_parser_get_value_safe(struct sm6_parser *sm6, unsigned int idx) + { + if (idx < sm6->value_count) + return &sm6->values[idx]; +@@ -3211,107 +3217,6 @@ static inline uint64_t decode_rotated_signed_value(uint64_t value) + return value << 63; + } + +-static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, const struct sm6_type *type, +- const uint64_t *operands, struct sm6_parser *sm6) +-{ +- struct vkd3d_shader_immediate_constant_buffer *icb; +- const struct sm6_type *elem_type; +- unsigned int i, size, count; +- uint64_t *data64; +- +- elem_type = type->u.array.elem_type; +- /* Multidimensional arrays are emitted in flattened form. */ +- if (elem_type->class != TYPE_CLASS_INTEGER && elem_type->class != TYPE_CLASS_FLOAT) +- { +- 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; +- } +- +- /* Arrays of bool are not used in DXIL. dxc will emit an array of int32 instead if necessary. */ +- if (!(size = elem_type->u.width / CHAR_BIT)) +- { +- WARN("Invalid data type width %u.\n", elem_type->u.width); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +- "An immediate constant buffer is declared with boolean elements."); +- return VKD3D_ERROR_INVALID_SHADER; +- } +- size = max(size, sizeof(icb->data[0])); +- count = operands ? type->u.array.count * size / sizeof(icb->data[0]) : 0; +- +- if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[count])))) +- { +- ERR("Failed to allocate buffer, count %u.\n", count); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, +- "Out of memory allocating an immediate constant buffer of count %u.", count); +- return VKD3D_ERROR_OUT_OF_MEMORY; +- } +- if (!vsir_program_add_icb(sm6->program, icb)) +- { +- ERR("Failed to store icb object.\n"); +- vkd3d_free(icb); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, +- "Out of memory storing an immediate constant buffer object."); +- return VKD3D_ERROR_OUT_OF_MEMORY; +- } +- +- dst->value_type = VALUE_TYPE_DATA; +- dst->u.data = icb; +- +- icb->register_idx = sm6->icb_count++; +- 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; +- +- if (!operands) +- return VKD3D_OK; +- +- count = type->u.array.count; +- switch (icb->data_type) +- { +- case VSIR_DATA_F16: +- for (i = 0; i < count; ++i) +- icb->data[i] = half_to_float(operands[i]); +- 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]; +- icb->data_type = VSIR_DATA_U32; +- 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) +- data64[i] = operands[i]; +- break; +- +- default: +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +- "Invalid array of type %u.", icb->data_type); +- return VKD3D_ERROR_INVALID_SHADER; +- } +- +- return VKD3D_OK; +-} +- + static struct sm6_index *sm6_get_value_index(struct sm6_parser *sm6, struct sm6_value *value) + { + switch (value->value_type) +@@ -3498,8 +3403,8 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + case CST_CODE_NULL: + if (sm6_type_is_array(type)) + { +- if ((ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) +- return ret; ++ dst->value_type = VALUE_TYPE_CONSTANT_ARRAY; ++ dst->u.constant_array.elements = NULL; + } + else + { +@@ -3559,8 +3464,8 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + if (!dxil_record_validate_operand_count(record, type->u.array.count, type->u.array.count, sm6)) + return VKD3D_ERROR_INVALID_SHADER; + +- if ((ret = value_allocate_constant_array(dst, type, record->operands, sm6)) < 0) +- return ret; ++ dst->value_type = VALUE_TYPE_CONSTANT_ARRAY; ++ dst->u.constant_array.elements = record->operands; + + break; + +@@ -3943,20 +3848,129 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ + static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_initialiser( + size_t index, struct sm6_parser *sm6) + { +- const struct sm6_value *value; ++ struct sm6_value *value; + + VKD3D_ASSERT(index); + --index; +- if (!(value = sm6_parser_get_value_safe(sm6, index)) || (!sm6_value_is_data(value) && !sm6_value_is_undef(value))) ++ if (!(value = sm6_parser_get_value_safe(sm6, index)) ++ || (!sm6_value_is_constant_array(value) && !sm6_value_is_undef(value))) + { + WARN("Invalid initialiser index %zu.\n", index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Global variable initialiser value index %zu is invalid.", index); + return NULL; + } +- else if (sm6_value_is_data(value)) ++ else if (sm6_value_is_constant_array(value)) + { +- return value->u.data; ++ const uint64_t *elements = value->u.constant_array.elements; ++ struct vkd3d_shader_immediate_constant_buffer *icb; ++ const struct sm6_array_info *array; ++ const struct sm6_type *elem_type; ++ unsigned int i, size, count; ++ uint64_t *data64; ++ ++ if (value->u.constant_array.icb) ++ return value->u.constant_array.icb; ++ ++ array = &value->type->u.array; ++ elem_type = array->elem_type; ++ /* Multidimensional arrays are emitted in flattened form. */ ++ if (elem_type->class != TYPE_CLASS_INTEGER && elem_type->class != TYPE_CLASS_FLOAT) ++ { ++ 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 NULL; ++ } ++ ++ /* Arrays of bool are not used in DXIL. dxc will emit an array of int32 instead if necessary. */ ++ if (!(size = elem_type->u.width / CHAR_BIT)) ++ { ++ WARN("Invalid data type width %u.\n", elem_type->u.width); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "An immediate constant buffer is declared with boolean elements."); ++ return NULL; ++ } ++ size = max(size, sizeof(icb->data[0])); ++ count = elements ? array->count * size / sizeof(icb->data[0]) : 0; ++ ++ if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[count])))) ++ { ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ "Out of memory allocating an immediate constant buffer of count %u.", count); ++ return NULL; ++ } ++ ++ if (!vsir_program_add_icb(sm6->program, icb)) ++ { ++ vkd3d_free(icb); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ "Out of memory storing an immediate constant buffer object."); ++ return NULL; ++ } ++ ++ count = array->count; ++ icb->register_idx = sm6->icb_count++; ++ icb->data_type = vsir_data_type_from_dxil(elem_type, 0, sm6); ++ icb->element_count = count; ++ icb->component_count = 1; ++ icb->is_null = !elements; ++ value->u.constant_array.icb = icb; ++ ++ if (!elements) ++ return icb; ++ ++ switch (icb->data_type) ++ { ++ case VSIR_DATA_F16: ++ icb->data_type = VSIR_DATA_F32; ++ for (i = 0; i < count; ++i) ++ { ++ icb->data[i] = half_to_float(elements[i]); ++ } ++ break; ++ ++ case VSIR_DATA_I16: ++ icb->data_type = VSIR_DATA_I32; ++ for (i = 0; i < count; ++i) ++ { ++ icb->data[i] = (int16_t)elements[i]; ++ } ++ break; ++ ++ case VSIR_DATA_U16: ++ icb->data_type = VSIR_DATA_U32; ++ for (i = 0; i < count; ++i) ++ { ++ icb->data[i] = (int16_t)elements[i]; ++ } ++ break; ++ ++ case VSIR_DATA_F32: ++ case VSIR_DATA_I32: ++ case VSIR_DATA_U32: ++ for (i = 0; i < count; ++i) ++ { ++ icb->data[i] = elements[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) ++ { ++ data64[i] = elements[i]; ++ } ++ break; ++ ++ default: ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Invalid array of type %u.", icb->data_type); ++ return NULL; ++ } ++ ++ return icb; + } + /* In VSIR, initialisation with undefined values of objects is implied, not explicit. */ + return NULL; +@@ -3970,15 +3984,16 @@ static bool resolve_forward_zero_initialiser(size_t index, struct sm6_parser *sm + return false; + + --index; +- if (!(value = sm6_parser_get_value_safe(sm6, index)) +- || (!sm6_value_is_data(value) && !sm6_value_is_constant(value) && !sm6_value_is_undef(value))) ++ if (!(value = sm6_parser_get_value_safe(sm6, index)) || (!sm6_value_is_constant_array(value) ++ && !sm6_value_is_constant(value) && !sm6_value_is_undef(value))) + { + WARN("Invalid initialiser index %zu.\n", index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "TGSM initialiser value index %zu is invalid.", index); + return false; + } +- else if ((sm6_value_is_data(value) && value->u.data->is_null) || sm6_value_is_constant_zero(value)) ++ else if ((sm6_value_is_constant_array(value) && !value->u.constant_array.elements) ++ || sm6_value_is_constant_zero(value)) + { + return true; + } +@@ -6299,8 +6314,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr + return; + } + e = &signature->elements[row_index]; +- if (!e->sysval_semantic) +- column_index += vsir_write_mask_get_component_idx(e->mask); ++ column_index += vsir_write_mask_get_component_idx(e->mask); + + if (column_index >= VKD3D_VEC4_SIZE) + { +@@ -8911,8 +8925,8 @@ static enum vkd3d_result sm6_parser_metadata_init(struct sm6_parser *sm6, const + if (!(value = sm6_parser_get_value_safe(sm6, value_idx))) + return VKD3D_ERROR_INVALID_SHADER; + +- if (!sm6_value_is_constant(value) && !sm6_value_is_undef(value) && !sm6_value_is_data(value) +- && !sm6_value_is_function_dcl(value)) ++ if (!sm6_value_is_constant(value) && !sm6_value_is_undef(value) ++ && !sm6_value_is_constant_array(value) && !sm6_value_is_function_dcl(value)) + { + WARN("Value at index %u is not a constant or a function declaration.\n", value_idx); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA, +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index a566d65d8cd..5b1d0449a64 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -2477,6 +2477,7 @@ 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: ++ case VSIR_OP_DCL_IMMEDIATE_CONSTANT_BUFFER: + case VSIR_OP_DCL_INPUT_PRIMITIVE: + case VSIR_OP_DCL_OUTPUT_TOPOLOGY: + case VSIR_OP_DCL_SAMPLER: +@@ -11011,10 +11012,34 @@ static void vsir_validate_io_dst_param(struct validation_context *ctx, + const struct vkd3d_shader_dst_param *dst) + { + struct vsir_io_register_data io_reg_data; ++ const struct signature_element *e; ++ unsigned int idx; + + if (!vsir_get_io_register_data(ctx, dst->reg.type, &io_reg_data) || !(io_reg_data.flags & OUTPUT_BIT)) ++ { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, + "Invalid register type %#x used as destination parameter.", dst->reg.type); ++ return; ++ } ++ ++ if (ctx->program->normalisation_level >= VSIR_NORMALISED_SM6) ++ { ++ if (!dst->reg.idx_count) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "Invalid index count %u for a register of type %#x.", ++ dst->reg.idx_count, dst->reg.type); ++ return; ++ } ++ ++ idx = dst->reg.idx[dst->reg.idx_count - 1].offset; ++ e = &io_reg_data.signature->elements[idx]; ++ ++ if (dst->write_mask & ~e->mask) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "Invalid destination write mask %#x for signature element with mask %#x.", ++ dst->write_mask, e->mask); ++ } + } + + static void vsir_validate_dst_param(struct validation_context *ctx, +diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c +index 7b4804e8036..c974c9e532b 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/msl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/msl.c +@@ -209,8 +209,8 @@ static bool msl_check_shader_visibility(const struct msl_generator *gen, + } + } + +-static bool msl_get_binding(const struct msl_generator *gen, unsigned int register_space, unsigned int register_idx, +- enum vkd3d_shader_descriptor_type type, enum vkd3d_shader_binding_flag flags, unsigned int *idx) ++static bool msl_get_binding(const struct msl_generator *gen, const struct vkd3d_shader_descriptor_info1 *descriptor, ++ unsigned int register_idx, enum vkd3d_shader_binding_flag flags, unsigned int *idx) + { + const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; + unsigned int i; +@@ -222,9 +222,9 @@ static bool msl_get_binding(const struct msl_generator *gen, unsigned int regist + { + const struct vkd3d_shader_resource_binding *binding = &interface_info->bindings[i]; + +- if (binding->type != type) ++ if (binding->type != descriptor->type) + continue; +- if (binding->register_space != register_space) ++ if (binding->register_space != descriptor->register_space) + continue; + if (binding->register_index != register_idx) + continue; +@@ -241,31 +241,30 @@ static bool msl_get_binding(const struct msl_generator *gen, unsigned int regist + } + + static bool msl_get_cbv_binding(const struct msl_generator *gen, +- unsigned int register_space, unsigned int register_idx, unsigned int *idx) ++ const struct vkd3d_shader_descriptor_info1 *descriptor, unsigned int register_idx, unsigned int *idx) + { +- return msl_get_binding(gen, register_space, register_idx, +- VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, VKD3D_SHADER_BINDING_FLAG_BUFFER, idx); ++ return msl_get_binding(gen, descriptor, register_idx, VKD3D_SHADER_BINDING_FLAG_BUFFER, idx); + } + + static bool msl_get_sampler_binding(const struct msl_generator *gen, +- unsigned int register_space, unsigned int register_idx, unsigned int *idx) ++ const struct vkd3d_shader_descriptor_info1 *descriptor, unsigned int register_idx, unsigned int *idx) + { +- return msl_get_binding(gen, register_space, register_idx, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, 0, idx); ++ return msl_get_binding(gen, descriptor, register_idx, 0, idx); + } + +-static bool msl_get_srv_binding(const struct msl_generator *gen, unsigned int register_space, +- unsigned int register_idx, enum vkd3d_shader_resource_type resource_type, unsigned int *idx) ++static bool msl_get_srv_binding(const struct msl_generator *gen, ++ const struct vkd3d_shader_descriptor_info1 *descriptor, unsigned int register_idx, unsigned int *idx) + { +- return msl_get_binding(gen, register_space, register_idx, +- VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_type == VKD3D_SHADER_RESOURCE_BUFFER ++ return msl_get_binding(gen, descriptor, register_idx, ++ descriptor->resource_type == VKD3D_SHADER_RESOURCE_BUFFER + ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE, idx); + } + +-static bool msl_get_uav_binding(const struct msl_generator *gen, unsigned int register_space, +- unsigned int register_idx, enum vkd3d_shader_resource_type resource_type, unsigned int *idx) ++static bool msl_get_uav_binding(const struct msl_generator *gen, ++ const struct vkd3d_shader_descriptor_info1 *descriptor, unsigned int register_idx, unsigned int *idx) + { +- return msl_get_binding(gen, register_space, register_idx, +- VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, resource_type == VKD3D_SHADER_RESOURCE_BUFFER ++ return msl_get_binding(gen, descriptor, register_idx, ++ descriptor->resource_type == VKD3D_SHADER_RESOURCE_BUFFER + ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE, idx); + } + +@@ -405,7 +404,7 @@ static enum msl_data_type msl_print_register_name(struct vkd3d_string_buffer *bu + return MSL_DATA_UNION; + } + +- if (!msl_get_cbv_binding(gen, descriptor->register_space, cbv_idx, &binding)) ++ if (!msl_get_cbv_binding(gen, descriptor, cbv_idx, &binding)) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, + "No descriptor binding specified for CBV %u.", cbv_id); +@@ -871,7 +870,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct + uint32_t coord_mask, write_mask_size; + struct vkd3d_string_buffer *read; + enum vsir_data_type data_type; +- unsigned int srv_binding; ++ unsigned int srv_binding = 0; + struct msl_dst dst; + + if (vkd3d_shader_instruction_has_texel_offset(ins)) +@@ -928,13 +927,10 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct + } + coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); + +- if (!msl_get_srv_binding(gen, resource_space, resource_idx, resource_type, &srv_binding)) +- { ++ if (descriptor && !msl_get_srv_binding(gen, descriptor, resource_idx, &srv_binding)) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, + "No descriptor binding specified for SRV %u (index %u, space %u).", + resource_id, resource_idx, resource_space); +- srv_binding = 0; +- } + + msl_dst_init(&dst, gen, ins, &ins->dst[0]); + read = vkd3d_string_buffer_get(&gen->string_buffers); +@@ -982,9 +978,9 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + const struct vkd3d_shader_src_param *resource, *sampler; + unsigned int resource_id, resource_idx, resource_space; + unsigned int sampler_id, sampler_idx, sampler_space; ++ unsigned int srv_binding = 0, sampler_binding = 0; + const struct vkd3d_shader_descriptor_info1 *d; + enum vkd3d_shader_resource_type resource_type; +- unsigned int srv_binding, sampler_binding; + uint32_t coord_mask, write_mask_size; + struct vkd3d_string_buffer *sample; + enum vsir_data_type data_type; +@@ -1052,13 +1048,10 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + } + coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); + +- if (!msl_get_srv_binding(gen, resource_space, resource_idx, resource_type, &srv_binding)) +- { ++ if (d && !msl_get_srv_binding(gen, d, resource_idx, &srv_binding)) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, + "No descriptor binding specified for SRV %u (index %u, space %u).", + resource_id, resource_idx, resource_space); +- srv_binding = 0; +- } + + sampler_id = sampler->reg.idx[0].offset; + sampler_idx = sampler->reg.idx[1].offset; +@@ -1088,13 +1081,10 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + sampler_space = 0; + } + +- if (!msl_get_sampler_binding(gen, sampler_space, sampler_idx, &sampler_binding)) +- { ++ if (d && !msl_get_sampler_binding(gen, d, sampler_idx, &sampler_binding)) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, + "No descriptor binding specified for sampler %u (index %u, space %u).", + sampler_id, sampler_idx, sampler_space); +- sampler_binding = 0; +- } + + msl_dst_init(&dst, gen, ins, &ins->dst[0]); + sample = vkd3d_string_buffer_get(&gen->string_buffers); +@@ -1191,7 +1181,7 @@ static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_sh + unsigned int uav_id, uav_idx, uav_space; + struct vkd3d_string_buffer *image_data; + enum vsir_data_type data_type; +- unsigned int uav_binding; ++ unsigned int uav_binding = 0; + uint32_t coord_mask; + + if (ins->dst[0].reg.idx[0].rel_addr || ins->dst[0].reg.idx[1].rel_addr) +@@ -1229,13 +1219,10 @@ static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_sh + } + coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); + +- if (!msl_get_uav_binding(gen, uav_space, uav_idx, resource_type, &uav_binding)) +- { ++ if (d && !msl_get_uav_binding(gen, d, uav_idx, &uav_binding)) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, + "No descriptor binding specified for UAV %u (index %u, space %u).", + uav_id, uav_idx, uav_space); +- uav_binding = 0; +- } + + image_data = vkd3d_string_buffer_get(&gen->string_buffers); + +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index aae5f6b5534..3950021a2ef 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -5813,7 +5813,7 @@ static void calculate_clip_or_cull_distance_mask(const struct signature_element + return; + } + +- write_mask = e->mask >> vsir_write_mask_get_component_idx(e->mask); ++ write_mask = e->mask; + *mask |= (write_mask & VKD3DSP_WRITEMASK_ALL) << (VKD3D_VEC4_SIZE * e->semantic_index); + } + +@@ -6060,7 +6060,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + if (use_private_variable) + { + compiler->private_output_variable[element_idx] = var_id; +- compiler->private_output_variable_write_mask[element_idx] |= write_mask >> component_idx; ++ compiler->private_output_variable_write_mask[element_idx] |= write_mask; + if (!compiler->epilogue_function_id) + compiler->epilogue_function_id = vkd3d_spirv_alloc_id(builder); + } +@@ -6112,9 +6112,6 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + use_mask |= element->used_mask; + } + } +- index = vsir_write_mask_get_component_idx(output->mask); +- dst_write_mask >>= index; +- use_mask >>= index; + write_mask &= dst_write_mask; + + if (!write_mask) +@@ -6701,30 +6698,6 @@ static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, + spirv_compiler_put_symbol(compiler, ®_symbol); + } + +-static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compiler *compiler, +- const struct vkd3d_shader_instruction *instruction) +-{ +- const struct vkd3d_shader_immediate_constant_buffer *icb = instruction->declaration.icb; +- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- uint32_t type_id, const_id, ptr_type_id, icb_id; +- struct vkd3d_shader_register reg; +- struct vkd3d_symbol reg_symbol; +- +- const_id = spirv_compiler_emit_constant_array(compiler, icb, &type_id); +- ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id); +- icb_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, +- ptr_type_id, SpvStorageClassPrivate, const_id); +- vkd3d_spirv_build_op_name(builder, icb_id, "icb"); +- +- /* Set an index count of 2 so vkd3d_symbol_make_register() uses idx[0] as a buffer id. */ +- vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VSIR_DATA_F32, 2); +- reg.idx[0].offset = icb->register_idx; +- vkd3d_symbol_make_register(®_symbol, ®); +- vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate, +- icb->data_type, vkd3d_write_mask_from_component_count(icb->component_count)); +- spirv_compiler_put_symbol(compiler, ®_symbol); +-} +- + static void spirv_compiler_emit_sampler_declaration(struct spirv_compiler *compiler, + const struct vkd3d_shader_register_range *range, const struct vkd3d_shader_descriptor_info1 *descriptor) + { +@@ -10436,9 +10409,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, + case VSIR_OP_DCL_INDEXABLE_TEMP: + spirv_compiler_emit_dcl_indexable_temp(compiler, instruction); + break; +- case VSIR_OP_DCL_IMMEDIATE_CONSTANT_BUFFER: +- spirv_compiler_emit_dcl_immediate_constant_buffer(compiler, instruction); +- break; + case VSIR_OP_DCL_TGSM_RAW: + spirv_compiler_emit_dcl_tgsm_raw(compiler, instruction); + break; +@@ -10885,6 +10855,36 @@ static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *c + } + } + ++static void spirv_compiler_emit_immediate_constant_buffers(struct spirv_compiler *compiler) ++{ ++ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ const struct vkd3d_shader_immediate_constant_buffer *icb; ++ const struct vsir_program *program = compiler->program; ++ uint32_t type_id, const_id, ptr_type_id, icb_id; ++ struct vkd3d_shader_register reg; ++ struct vkd3d_symbol reg_symbol; ++ size_t i; ++ ++ for (i = 0; i < program->icb_count; ++i) ++ { ++ icb = program->icbs[i]; ++ ++ const_id = spirv_compiler_emit_constant_array(compiler, icb, &type_id); ++ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id); ++ icb_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, ++ ptr_type_id, SpvStorageClassPrivate, const_id); ++ vkd3d_spirv_build_op_name(builder, icb_id, "icb%zu", icb->register_idx); ++ ++ /* Set an index count of 2 so vkd3d_symbol_make_register() uses idx[0] as a buffer id. */ ++ vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VSIR_DATA_F32, 2); ++ reg.idx[0].offset = icb->register_idx; ++ vkd3d_symbol_make_register(®_symbol, ®); ++ vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate, ++ icb->data_type, vkd3d_write_mask_from_component_count(icb->component_count)); ++ spirv_compiler_put_symbol(compiler, ®_symbol); ++ } ++} ++ + static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *spirv) + { +@@ -10918,6 +10918,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + spirv_compiler_emit_global_flags(compiler, program->global_flags); + + spirv_compiler_emit_descriptor_declarations(compiler); ++ spirv_compiler_emit_immediate_constant_buffers(compiler); + + compiler->spirv_parameter_info = vkd3d_calloc(program->parameter_count, sizeof(*compiler->spirv_parameter_info)); + for (i = 0; i < program->parameter_count; ++i) +-- +2.51.0 +