From 81492f71560e0574179251be0e766d2dd5ea1167 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Tue, 15 Oct 2024 09:23:52 +1100 Subject: [PATCH] Updated vkd3d-latest patchset --- ...25232f2b2b35bcf1c265bc380c31cd1d32e.patch} | 5754 +++++++++++++++-- ...-a2aeb3a1421c5540b7f4d0e68ec3ff211e1.patch | 949 --- ...-cd74461d6dabae4e702de61a90533d811aa.patch | 1718 +++++ ...-9cb4207c92ec3ee05fce15580c89f2e5146.patch | 386 ++ ...-e8b14d765dbebae32d83aa5d2a7521932d9.patch | 303 - ...-cd249a47b86545fe0b3a4b477f854965e85.patch | 1533 +++++ ...-f28d39b609036ce9bc3a4baaf6cda012fc2.patch | 1233 ---- ...-9dd42d15ddca66458042b5e4b7775fa054b.patch | 1465 +++++ ...-ae27fded1a039fda84b526cd9bd7b64aeb5.patch | 1977 ------ ...-25232f2b2b35bcf1c265bc380c31cd1d32e.patch | 893 --- 10 files changed, 10167 insertions(+), 6044 deletions(-) rename patches/vkd3d-latest/{0001-Updated-vkd3d-to-2ac7f650a196e47a18ea1957eac5953255c.patch => 0001-Updated-vkd3d-to-25232f2b2b35bcf1c265bc380c31cd1d32e.patch} (65%) delete mode 100644 patches/vkd3d-latest/0002-Updated-vkd3d-to-a2aeb3a1421c5540b7f4d0e68ec3ff211e1.patch create mode 100644 patches/vkd3d-latest/0002-Updated-vkd3d-to-cd74461d6dabae4e702de61a90533d811aa.patch create mode 100644 patches/vkd3d-latest/0003-Updated-vkd3d-to-9cb4207c92ec3ee05fce15580c89f2e5146.patch delete mode 100644 patches/vkd3d-latest/0003-Updated-vkd3d-to-e8b14d765dbebae32d83aa5d2a7521932d9.patch create mode 100644 patches/vkd3d-latest/0004-Updated-vkd3d-to-cd249a47b86545fe0b3a4b477f854965e85.patch delete mode 100644 patches/vkd3d-latest/0004-Updated-vkd3d-to-f28d39b609036ce9bc3a4baaf6cda012fc2.patch create mode 100644 patches/vkd3d-latest/0005-Updated-vkd3d-to-9dd42d15ddca66458042b5e4b7775fa054b.patch delete mode 100644 patches/vkd3d-latest/0005-Updated-vkd3d-to-ae27fded1a039fda84b526cd9bd7b64aeb5.patch delete mode 100644 patches/vkd3d-latest/0006-Updated-vkd3d-to-25232f2b2b35bcf1c265bc380c31cd1d32e.patch diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-2ac7f650a196e47a18ea1957eac5953255c.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-25232f2b2b35bcf1c265bc380c31cd1d32e.patch similarity index 65% rename from patches/vkd3d-latest/0001-Updated-vkd3d-to-2ac7f650a196e47a18ea1957eac5953255c.patch rename to patches/vkd3d-latest/0001-Updated-vkd3d-to-25232f2b2b35bcf1c265bc380c31cd1d32e.patch index 5282141c..146bf532 100644 --- a/patches/vkd3d-latest/0001-Updated-vkd3d-to-2ac7f650a196e47a18ea1957eac5953255c.patch +++ b/patches/vkd3d-latest/0001-Updated-vkd3d-to-25232f2b2b35bcf1c265bc380c31cd1d32e.patch @@ -1,39 +1,40 @@ -From 77787c434c8a936f72753bf770273d39316c9917 Mon Sep 17 00:00:00 2001 +From 21b9bad56830f461f19e19dc3c81030500610728 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Tue, 3 Sep 2024 07:18:49 +1000 -Subject: [PATCH] Updated vkd3d to 2ac7f650a196e47a18ea1957eac5953255cf424d. +Subject: [PATCH] Updated vkd3d to 25232f2b2b35bcf1c265bc380c31cd1d32e4f4a6. --- libs/vkd3d/Makefile.in | 1 + libs/vkd3d/include/private/vkd3d_common.h | 4 +- - libs/vkd3d/include/vkd3d_shader.h | 13 +- + libs/vkd3d/include/vkd3d_shader.h | 102 +- libs/vkd3d/libs/vkd3d-common/blob.c | 1 + libs/vkd3d/libs/vkd3d-shader/checksum.c | 49 +- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 6 +- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 1183 ++++-------- + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 35 +- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 1249 +++------- libs/vkd3d/libs/vkd3d-shader/dxbc.c | 19 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 4 +- - libs/vkd3d/libs/vkd3d-shader/fx.c | 106 +- - libs/vkd3d/libs/vkd3d-shader/glsl.c | 755 +++++++- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 198 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 70 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.l | 2 + - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 509 ++++-- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 1382 +++++++++++++- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 90 +- + libs/vkd3d/libs/vkd3d-shader/fx.c | 423 +++- + libs/vkd3d/libs/vkd3d-shader/glsl.c | 1479 +++++++++++- + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 347 ++- + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 107 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.l | 3 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 778 +++++-- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 1452 +++++++++++- .../libs/vkd3d-shader/hlsl_constant_ops.c | 20 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 1605 +++++++++-------- - libs/vkd3d/libs/vkd3d-shader/msl.c | 275 +++ - libs/vkd3d/libs/vkd3d-shader/preproc.l | 1 + - libs/vkd3d/libs/vkd3d-shader/spirv.c | 134 +- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 554 +++++- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 119 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 53 +- + libs/vkd3d/libs/vkd3d-shader/ir.c | 2050 ++++++++++------- + libs/vkd3d/libs/vkd3d-shader/msl.c | 319 +++ + libs/vkd3d/libs/vkd3d-shader/preproc.l | 3 +- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 354 +-- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 752 ++++-- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 124 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 64 +- libs/vkd3d/libs/vkd3d/command.c | 50 +- libs/vkd3d/libs/vkd3d/device.c | 1 + - libs/vkd3d/libs/vkd3d/state.c | 3 +- + libs/vkd3d/libs/vkd3d/state.c | 7 +- libs/vkd3d/libs/vkd3d/utils.c | 3 +- + libs/vkd3d/libs/vkd3d/vkd3d_main.c | 1 + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 4 +- - 29 files changed, 4987 insertions(+), 2137 deletions(-) + 30 files changed, 7256 insertions(+), 2635 deletions(-) create mode 100644 libs/vkd3d/libs/vkd3d-shader/msl.c diff --git a/libs/vkd3d/Makefile.in b/libs/vkd3d/Makefile.in @@ -71,10 +72,141 @@ index 39145a97df1..fd62730f948 100644 #else v -= (v >> 1) & 0x55555555; diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h -index d9a355d3bc9..46feff35138 100644 +index d9a355d3bc9..d08ee74a3a0 100644 --- a/libs/vkd3d/include/vkd3d_shader.h +++ b/libs/vkd3d/include/vkd3d_shader.h -@@ -1087,6 +1087,10 @@ enum vkd3d_shader_target_type +@@ -190,6 +190,17 @@ enum vkd3d_shader_compile_option_backward_compatibility + * - DEPTH to SV_Depth for pixel shader outputs. + */ + VKD3D_SHADER_COMPILE_OPTION_BACKCOMPAT_MAP_SEMANTIC_NAMES = 0x00000001, ++ /** ++ * Causes 'double' to behave as an alias for 'float'. This option only ++ * applies to HLSL sources with shader model 1-3 target profiles. Without ++ * this option using the 'double' type produces compilation errors in ++ * these target profiles. ++ * ++ * This option is disabled by default. ++ * ++ * \since 1.14 ++ */ ++ VKD3D_SHADER_COMPILE_OPTION_DOUBLE_AS_FLOAT_ALIAS = 0x00000002, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY), + }; +@@ -469,8 +480,8 @@ enum vkd3d_shader_parameter_type + /** The parameter value is embedded directly in the shader. */ + VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT, + /** +- * The parameter value is provided to the shader via a specialization +- * constant. This value is only supported for the SPIR-V target type. ++ * The parameter value is provided to the shader via specialization ++ * constants. This value is only supported for the SPIR-V target type. + */ + VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT, + /** +@@ -495,6 +506,13 @@ enum vkd3d_shader_parameter_data_type + VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32, + /** The parameter is provided as a 32-bit float. \since 1.13 */ + VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32, ++ /** ++ * The parameter is provided as a 4-dimensional vector of 32-bit floats. ++ * This parameter must be used with struct vkd3d_shader_parameter1; ++ * it cannot be used with struct vkd3d_shader_parameter. ++ * \since 1.14 ++ */ ++ VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_DATA_TYPE), + }; +@@ -578,6 +596,58 @@ enum vkd3d_shader_parameter_name + * \since 1.13 + */ + VKD3D_SHADER_PARAMETER_NAME_FLAT_INTERPOLATION, ++ /** ++ * A mask of enabled clip planes. ++ * ++ * When this parameter is provided to a vertex shader, for each nonzero bit ++ * of this mask, a user clip distance will be generated from vertex position ++ * in clip space, and the clip plane defined by the indexed vector, taken ++ * from the VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_# parameter. ++ * ++ * Regardless of the specific clip planes which are enabled, the clip ++ * distances which are output are a contiguous array starting from clip ++ * distance 0. This affects the interface of OpenGL. For example, if only ++ * clip planes 1 and 3 are enabled (and so the value of the mask is 0xa), ++ * the user should enable only GL_CLIP_DISTANCE0 and GL_CLIP_DISTANCE1. ++ * ++ * The default value is zero, i.e. do not enable any clip planes. ++ * ++ * The data type for this parameter must be ++ * VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32. ++ * ++ * Only VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT is supported in this ++ * version of vkd3d-shader. ++ * ++ * If the source shader writes clip distances and this parameter is nonzero, ++ * compilation fails. ++ * ++ * \since 1.14 ++ */ ++ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK, ++ /** ++ * Clip plane values. ++ * See VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK for documentation of ++ * clip planes. ++ * ++ * These enum values are contiguous and arithmetic may safely be performed ++ * on them. That is, VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_[n] is ++ * VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 plus n. ++ * ++ * The data type for each parameter must be ++ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4. ++ * ++ * The default value for each plane is a (0, 0, 0, 0) vector. ++ * ++ * \since 1.14 ++ */ ++ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0, ++ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_1, ++ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_2, ++ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_3, ++ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_4, ++ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_5, ++ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_6, ++ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_7, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME), + }; +@@ -625,6 +695,13 @@ struct vkd3d_shader_parameter_immediate_constant1 + * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32. + */ + float f32; ++ /** ++ * A pointer to the value if the parameter's data type is ++ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4. ++ * ++ * \since 1.14 ++ */ ++ float f32_vec4[4]; + void *_pointer_pad; + uint32_t _pad[4]; + } u; +@@ -636,7 +713,13 @@ struct vkd3d_shader_parameter_immediate_constant1 + */ + struct vkd3d_shader_parameter_specialization_constant + { +- /** The ID of the specialization constant. */ ++ /** ++ * The ID of the specialization constant. ++ * If the type comprises more than one constant, such as ++ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4, then a contiguous ++ * array of specialization constants should be used, one for each component, ++ * and this ID should point to the first component. ++ */ + uint32_t id; + }; + +@@ -1087,6 +1170,10 @@ enum vkd3d_shader_target_type * Output is a raw FX section without container. \since 1.11 */ VKD3D_SHADER_TARGET_FX, @@ -85,7 +217,7 @@ index d9a355d3bc9..46feff35138 100644 VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TARGET_TYPE), }; -@@ -1292,7 +1296,8 @@ typedef int (*PFN_vkd3d_shader_open_include)(const char *filename, bool local, +@@ -1292,7 +1379,8 @@ typedef int (*PFN_vkd3d_shader_open_include)(const char *filename, bool local, * vkd3d_shader_preprocess_info. * * \param code Contents of the included file, which were allocated by the @@ -95,7 +227,7 @@ index d9a355d3bc9..46feff35138 100644 * * \param context The user-defined pointer passed to struct * vkd3d_shader_preprocess_info. -@@ -1319,8 +1324,8 @@ struct vkd3d_shader_preprocess_info +@@ -1319,8 +1407,8 @@ struct vkd3d_shader_preprocess_info /** * Pointer to an array of predefined macros. Each macro in this array will @@ -106,7 +238,7 @@ index d9a355d3bc9..46feff35138 100644 * * If the same macro is specified multiple times, only the last value is * used. -@@ -2798,7 +2803,7 @@ VKD3D_SHADER_API void vkd3d_shader_free_scan_signature_info(struct vkd3d_shader_ +@@ -2798,7 +2886,7 @@ VKD3D_SHADER_API void vkd3d_shader_free_scan_signature_info(struct vkd3d_shader_ * \param input_signature The input signature of the second shader. * * \param count On output, contains the number of entries written into @@ -224,7 +356,7 @@ index d9560628c77..45de1c92513 100644 memcpy(checksum, ctx.digest, sizeof(ctx.digest)); } diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index 77e9711300f..cfee053d49c 100644 +index 77e9711300f..9fe4b74486a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -79,7 +79,7 @@ static const char * const shader_opcode_names[] = @@ -254,8 +386,74 @@ index 77e9711300f..cfee053d49c 100644 [VKD3DSIH_DDIV ] = "ddiv", [VKD3DSIH_DEF ] = "def", [VKD3DSIH_DEFAULT ] = "default", +@@ -675,9 +675,6 @@ static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum + { + [VKD3D_DATA_FLOAT ] = "float", + [VKD3D_DATA_INT ] = "int", +- [VKD3D_DATA_RESOURCE ] = "resource", +- [VKD3D_DATA_SAMPLER ] = "sampler", +- [VKD3D_DATA_UAV ] = "uav", + [VKD3D_DATA_UINT ] = "uint", + [VKD3D_DATA_UNORM ] = "unorm", + [VKD3D_DATA_SNORM ] = "snorm", +@@ -1229,8 +1226,6 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const + case VKD3D_DATA_INT: + shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); + break; +- case VKD3D_DATA_RESOURCE: +- case VKD3D_DATA_SAMPLER: + case VKD3D_DATA_UINT: + shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); + break; +@@ -1266,8 +1261,6 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const + shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[2], ""); + shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[3], ""); + break; +- case VKD3D_DATA_RESOURCE: +- case VKD3D_DATA_SAMPLER: + case VKD3D_DATA_UINT: + shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); + shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[1], ""); +@@ -1319,6 +1312,23 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const + } + vkd3d_string_buffer_printf(buffer, ")"); + } ++ else if (compiler->flags & VSIR_ASM_FLAG_DUMP_ALL_INDICES) ++ { ++ unsigned int i = 0; ++ ++ if (reg->idx_count == 0 || reg->idx[0].rel_addr) ++ { ++ vkd3d_string_buffer_printf(buffer, "%s", compiler->colours.reset); ++ } ++ else ++ { ++ vkd3d_string_buffer_printf(buffer, "%u%s", offset, compiler->colours.reset); ++ i = 1; ++ } ++ ++ for (; i < reg->idx_count; ++i) ++ shader_print_subscript(compiler, reg->idx[i].offset, reg->idx[i].rel_addr); ++ } + else if (reg->type != VKD3DSPR_RASTOUT + && reg->type != VKD3DSPR_MISCTYPE + && reg->type != VKD3DSPR_NULL +@@ -2491,10 +2501,11 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, + + void vkd3d_shader_trace(const struct vsir_program *program) + { +- const char *p, *q, *end; ++ const unsigned int flags = VSIR_ASM_FLAG_DUMP_TYPES | VSIR_ASM_FLAG_DUMP_ALL_INDICES; + struct vkd3d_shader_code code; ++ const char *p, *q, *end; + +- if (d3d_asm_compile(program, NULL, &code, VSIR_ASM_FLAG_DUMP_TYPES) != VKD3D_OK) ++ if (d3d_asm_compile(program, NULL, &code, flags) != VKD3D_OK) + return; + + end = (const char *)code.code + code.size; diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index d05394c3ab7..10f2e5e5e6d 100644 +index d05394c3ab7..267cf410cbe 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -104,6 +104,19 @@ enum vkd3d_sm1_resource_type @@ -278,7 +476,76 @@ index d05394c3ab7..10f2e5e5e6d 100644 enum vkd3d_sm1_opcode { VKD3D_SM1_OP_NOP = 0x00, -@@ -1272,7 +1285,8 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, st +@@ -444,17 +457,36 @@ static uint32_t swizzle_from_sm1(uint32_t swizzle) + shader_sm1_get_swizzle_component(swizzle, 3)); + } + ++/* D3DBC doesn't have the concept of index count. All registers implicitly have ++ * exactly one index. However for some register types the index doesn't make ++ * sense, so we remove it. */ ++static unsigned int idx_count_from_reg_type(enum vkd3d_shader_register_type reg_type) ++{ ++ switch (reg_type) ++ { ++ case VKD3DSPR_DEPTHOUT: ++ return 0; ++ ++ default: ++ return 1; ++ } ++} ++ + static void shader_sm1_parse_src_param(uint32_t param, struct vkd3d_shader_src_param *rel_addr, + struct vkd3d_shader_src_param *src) + { + enum vkd3d_shader_register_type reg_type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT) + | ((param & VKD3D_SM1_REGISTER_TYPE_MASK2) >> VKD3D_SM1_REGISTER_TYPE_SHIFT2); ++ unsigned int idx_count = idx_count_from_reg_type(reg_type); + +- vsir_register_init(&src->reg, reg_type, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&src->reg, reg_type, VKD3D_DATA_FLOAT, idx_count); + src->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT; + src->reg.non_uniform = false; +- src->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK; +- src->reg.idx[0].rel_addr = rel_addr; ++ if (idx_count == 1) ++ { ++ src->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK; ++ src->reg.idx[0].rel_addr = rel_addr; ++ } + if (src->reg.type == VKD3DSPR_SAMPLER) + src->reg.dimension = VSIR_DIMENSION_NONE; + else if (src->reg.type == VKD3DSPR_DEPTHOUT) +@@ -470,12 +502,16 @@ static void shader_sm1_parse_dst_param(uint32_t param, struct vkd3d_shader_src_p + { + enum vkd3d_shader_register_type reg_type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT) + | ((param & VKD3D_SM1_REGISTER_TYPE_MASK2) >> VKD3D_SM1_REGISTER_TYPE_SHIFT2); ++ unsigned int idx_count = idx_count_from_reg_type(reg_type); + +- vsir_register_init(&dst->reg, reg_type, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&dst->reg, reg_type, VKD3D_DATA_FLOAT, idx_count); + dst->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT; + dst->reg.non_uniform = false; +- dst->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK; +- dst->reg.idx[0].rel_addr = rel_addr; ++ if (idx_count == 1) ++ { ++ dst->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK; ++ dst->reg.idx[0].rel_addr = rel_addr; ++ } + if (dst->reg.type == VKD3DSPR_SAMPLER) + dst->reg.dimension = VSIR_DIMENSION_NONE; + else if (dst->reg.type == VKD3DSPR_DEPTHOUT) +@@ -601,7 +637,7 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * + const struct vkd3d_shader_register *reg, bool is_dcl, unsigned int mask) + { + const struct vkd3d_shader_version *version = &sm1->p.program->shader_version; +- unsigned int register_index = reg->idx[0].offset; ++ unsigned int register_index = reg->idx_count > 0 ? reg->idx[0].offset : 0; + + switch (reg->type) + { +@@ -1272,7 +1308,8 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, st sm1->end = &code[token_count]; /* Estimate instruction count to avoid reallocation in most shaders. */ @@ -288,7 +555,37 @@ index d05394c3ab7..10f2e5e5e6d 100644 return VKD3D_ERROR_OUT_OF_MEMORY; vkd3d_shader_parser_init(&sm1->p, program, message_context, compile_info->source_name); -@@ -1384,22 +1398,22 @@ bool hlsl_sm1_register_from_semantic(const struct vkd3d_shader_version *version, +@@ -1338,9 +1375,6 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c + for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i) + program->flat_constant_count[i] = get_external_constant_count(&sm1, i); + +- if (!sm1.p.failed) +- ret = vkd3d_shader_parser_validate(&sm1.p, config_flags); +- + if (sm1.p.failed && ret >= 0) + ret = VKD3D_ERROR_INVALID_SHADER; + +@@ -1351,7 +1385,18 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c + return ret; + } + +- return ret; ++ if ((ret = vkd3d_shader_parser_validate(&sm1.p, config_flags)) < 0) ++ { ++ WARN("Failed to validate shader after parsing, ret %d.\n", ret); ++ ++ if (TRACE_ON()) ++ vkd3d_shader_trace(program); ++ ++ vsir_program_cleanup(program); ++ return ret; ++ } ++ ++ return VKD3D_OK; + } + + bool hlsl_sm1_register_from_semantic(const struct vkd3d_shader_version *version, const char *semantic_name, +@@ -1384,22 +1429,22 @@ bool hlsl_sm1_register_from_semantic(const struct vkd3d_shader_version *version, {"depth", true, VKD3D_SHADER_TYPE_PIXEL, 3, VKD3DSPR_DEPTHOUT}, {"sv_depth", true, VKD3D_SHADER_TYPE_PIXEL, 3, VKD3DSPR_DEPTHOUT}, {"sv_target", true, VKD3D_SHADER_TYPE_PIXEL, 3, VKD3DSPR_COLOROUT}, @@ -322,7 +619,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 {"texcoord", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_TEXCRDOUT}, }; -@@ -1423,32 +1437,32 @@ bool hlsl_sm1_register_from_semantic(const struct vkd3d_shader_version *version, +@@ -1423,32 +1468,32 @@ bool hlsl_sm1_register_from_semantic(const struct vkd3d_shader_version *version, } bool hlsl_sm1_usage_from_semantic(const char *semantic_name, @@ -374,7 +671,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 }; unsigned int i; -@@ -1468,21 +1482,17 @@ bool hlsl_sm1_usage_from_semantic(const char *semantic_name, +@@ -1468,21 +1513,17 @@ bool hlsl_sm1_usage_from_semantic(const char *semantic_name, struct d3dbc_compiler { @@ -400,7 +697,59 @@ index d05394c3ab7..10f2e5e5e6d 100644 } D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) -@@ -1860,24 +1870,24 @@ void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buff +@@ -1512,6 +1553,7 @@ D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) + case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: ++ case HLSL_CLASS_ERROR: + case HLSL_CLASS_PASS: + case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: +@@ -1617,6 +1659,7 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type) + case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: ++ case HLSL_CLASS_ERROR: + case HLSL_CLASS_PASS: + case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: +@@ -1709,7 +1752,7 @@ static void sm1_sort_externs(struct hlsl_ctx *ctx) + + void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer) + { +- size_t ctab_offset, ctab_start, ctab_end, vars_start, size_offset, creator_offset, offset; ++ size_t ctab_offset, ctab_start, ctab_end, vars_offset, vars_start, size_offset, creator_offset, offset; + unsigned int uniform_count = 0; + struct hlsl_ir_var *var; + +@@ -1745,11 +1788,12 @@ void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buff + creator_offset = put_u32(buffer, 0); + put_u32(buffer, sm1_version(ctx->profile->type, ctx->profile->major_version, ctx->profile->minor_version)); + put_u32(buffer, uniform_count); +- put_u32(buffer, sizeof(D3DXSHADER_CONSTANTTABLE)); /* offset of constants */ ++ vars_offset = put_u32(buffer, 0); + put_u32(buffer, 0); /* FIXME: flags */ + put_u32(buffer, 0); /* FIXME: target string */ + + vars_start = bytecode_align(buffer); ++ set_u32(buffer, vars_offset, vars_start - ctab_start); + + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { +@@ -1825,8 +1869,10 @@ void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buff + switch (comp_type->e.numeric.type) + { + case HLSL_TYPE_DOUBLE: +- hlsl_fixme(ctx, &var->loc, "Write double default values."); +- uni.u = 0; ++ if (ctx->double_as_float_alias) ++ uni.u = var->default_values[k].number.u; ++ else ++ uni.u = 0; + break; + + case HLSL_TYPE_INT: +@@ -1860,24 +1906,24 @@ void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buff set_u32(buffer, creator_offset, offset - ctab_start); ctab_end = bytecode_align(buffer); @@ -430,7 +779,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 unsigned int writemask; uint32_t reg; } dst; -@@ -1885,7 +1895,7 @@ struct sm1_instruction +@@ -1885,7 +1931,7 @@ struct sm1_instruction struct sm1_src_register { enum vkd3d_shader_register_type type; @@ -439,7 +788,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 unsigned int swizzle; uint32_t reg; } srcs[4]; -@@ -1900,11 +1910,11 @@ static bool is_inconsequential_instr(const struct sm1_instruction *instr) +@@ -1900,11 +1946,11 @@ static bool is_inconsequential_instr(const struct sm1_instruction *instr) const struct sm1_dst_register *dst = &instr->dst; unsigned int i; @@ -454,7 +803,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 return false; if (src->type != dst->type) return false; -@@ -1923,13 +1933,19 @@ static bool is_inconsequential_instr(const struct sm1_instruction *instr) +@@ -1923,13 +1969,19 @@ static bool is_inconsequential_instr(const struct sm1_instruction *instr) static void write_sm1_dst_register(struct vkd3d_bytecode_buffer *buffer, const struct sm1_dst_register *reg) { VKD3D_ASSERT(reg->writemask); @@ -476,7 +825,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 } static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct sm1_instruction *instr) -@@ -1945,7 +1961,7 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct s +@@ -1945,7 +1997,7 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct s token |= VKD3D_SM1_INSTRUCTION_FLAGS_MASK & (instr->flags << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT); if (version->major > 1) @@ -485,7 +834,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 put_u32(buffer, token); if (instr->has_dst) -@@ -1955,346 +1971,112 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct s +@@ -1955,346 +2007,112 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct s write_sm1_src_register(buffer, &instr->srcs[i]); }; @@ -496,9 +845,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 - -static void d3dbc_write_dp2add(struct d3dbc_compiler *d3dbc, const struct hlsl_reg *dst, - const struct hlsl_reg *src1, const struct hlsl_reg *src2, const struct hlsl_reg *src3) -+static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir( -+ struct d3dbc_compiler *d3dbc, enum vkd3d_shader_opcode vkd3d_opcode) - { +-{ - struct sm1_instruction instr = - { - .opcode = D3DSIO_DP2ADD, @@ -556,7 +903,9 @@ index d05394c3ab7..10f2e5e5e6d 100644 - -static void d3dbc_write_binary_op(struct d3dbc_compiler *d3dbc, D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode, - const struct hlsl_reg *dst, const struct hlsl_reg *src1, const struct hlsl_reg *src2) --{ ++static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir( ++ struct d3dbc_compiler *d3dbc, enum vkd3d_shader_opcode vkd3d_opcode) + { - struct sm1_instruction instr = - { - .opcode = opcode, @@ -625,16 +974,18 @@ index d05394c3ab7..10f2e5e5e6d 100644 - struct sm1_instruction instr = - { - .opcode = opcode, -- ++ uint32_t x = vsir_swizzle_get_component(swizzle, 0); ++ uint32_t y = vsir_swizzle_get_component(swizzle, 1); ++ uint32_t z = vsir_swizzle_get_component(swizzle, 2); ++ uint32_t w = vsir_swizzle_get_component(swizzle, 3); + - .dst.type = VKD3DSPR_TEMP, - .dst.mod = dst_mod, - .dst.writemask = dst->writemask, - .dst.reg = dst->id, - .has_dst = 1, -+ uint32_t x = vsir_swizzle_get_component(swizzle, 0); -+ uint32_t y = vsir_swizzle_get_component(swizzle, 1); -+ uint32_t z = vsir_swizzle_get_component(swizzle, 2); -+ uint32_t w = vsir_swizzle_get_component(swizzle, 3); ++ if (x & ~0x3u || y & ~0x3u || z & ~0x3u || w & ~0x3u) ++ ERR("Unexpected vsir swizzle: 0x%08x.\n", swizzle); - .srcs[0].type = VKD3DSPR_TEMP, - .srcs[0].swizzle = hlsl_swizzle_from_writemask(src->writemask), @@ -642,9 +993,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 - .srcs[0].mod = src_mod, - .src_count = 1, - }; -+ if (x & ~0x3u || y & ~0x3u || z & ~0x3u || w & ~0x3u) -+ ERR("Unexpected vsir swizzle: 0x%08x.\n", swizzle); - +- - sm1_map_src_swizzle(&instr.srcs[0], instr.dst.writemask); - d3dbc_write_instruction(d3dbc, &instr); + return ((x & 0x3u) << VKD3D_SM1_SWIZZLE_COMPONENT_SHIFT(0)) @@ -662,14 +1011,14 @@ index d05394c3ab7..10f2e5e5e6d 100644 - const struct hlsl_type *dst_type = expr->node.data_type; - const struct hlsl_type *src_type = arg1->data_type; - struct hlsl_ctx *ctx = d3dbc->ctx; +- +- /* Narrowing casts were already lowered. */ +- VKD3D_ASSERT(src_type->dimx == dst_type->dimx); + src->mod = param->modifiers; + src->reg = param->reg.idx[0].offset; + src->type = param->reg.type; + src->swizzle = swizzle_from_vsir(param->swizzle); -- /* Narrowing casts were already lowered. */ -- VKD3D_ASSERT(src_type->dimx == dst_type->dimx); -- - switch (dst_type->e.numeric.type) + if (param->reg.idx[0].rel_addr) { @@ -791,13 +1140,13 @@ index d05394c3ab7..10f2e5e5e6d 100644 - if (hlsl_sm1_register_from_semantic(version, element->semantic_name, - element->semantic_index, output, ®.type, ®.reg)) -- { ++ const struct sm1_dst_register reg = + { - usage = 0; - usage_idx = 0; - } - else -+ const struct sm1_dst_register reg = - { +- { - ret = hlsl_sm1_usage_from_semantic(element->semantic_name, element->semantic_index, &usage, &usage_idx); - VKD3D_ASSERT(ret); - reg.type = output ? VKD3DSPR_OUTPUT : VKD3DSPR_INPUT; @@ -895,7 +1244,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 token |= res_type << VKD3D_SM1_RESOURCE_TYPE_SHIFT; put_u32(buffer, token); -@@ -2305,618 +2087,283 @@ static void d3dbc_write_sampler_dcl(struct d3dbc_compiler *d3dbc, +@@ -2305,618 +2123,283 @@ static void d3dbc_write_sampler_dcl(struct d3dbc_compiler *d3dbc, write_sm1_dst_register(buffer, ®); } @@ -919,8 +1268,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 - continue; - - count = var->bind_count[HLSL_REGSET_SAMPLERS]; -+ reg_id = semantic->resource.reg.reg.idx[0].offset; - +- - for (i = 0; i < count; ++i) - { - if (var->objects_usage[HLSL_REGSET_SAMPLERS][i].used) @@ -944,8 +1292,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 -{ - const struct hlsl_ir_constant *constant = hlsl_ir_constant(instr); - struct sm1_instruction sm1_instr = -+ if (semantic->resource.reg.reg.type != VKD3DSPR_SAMPLER) - { +- { - .opcode = D3DSIO_MOV, - - .dst.type = VKD3DSPR_TEMP, @@ -1041,22 +1388,24 @@ index d05394c3ab7..10f2e5e5e6d 100644 - if (expr->op == HLSL_OP1_CAST) - { - d3dbc_write_cast(d3dbc, instr); +- return; +- } ++ reg_id = semantic->resource.reg.reg.idx[0].offset; + +- if (instr->data_type->e.numeric.type != HLSL_TYPE_FLOAT) ++ if (semantic->resource.reg.reg.type != VKD3DSPR_SAMPLER) + { +- /* These need to be lowered. */ +- hlsl_fixme(ctx, &instr->loc, "SM1 non-float expression."); + vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_TYPE, + "dcl instruction with register type %u.", semantic->resource.reg.reg.type); + d3dbc->failed = true; return; } -- if (instr->data_type->e.numeric.type != HLSL_TYPE_FLOAT) +- switch (expr->op) + switch (semantic->resource_type) { -- /* These need to be lowered. */ -- hlsl_fixme(ctx, &instr->loc, "SM1 non-float expression."); -- return; -- } -- -- switch (expr->op) -- { - case HLSL_OP1_ABS: - d3dbc_write_unary_op(d3dbc, D3DSIO_ABS, &instr->reg, &arg1->reg, 0, 0); - break; @@ -1083,12 +1432,16 @@ index d05394c3ab7..10f2e5e5e6d 100644 - - case HLSL_OP1_SAT: - d3dbc_write_unary_op(d3dbc, D3DSIO_MOV, &instr->reg, &arg1->reg, 0, D3DSPDM_SATURATE); -- break; -- ++ case VKD3D_SHADER_RESOURCE_TEXTURE_2D: ++ d3dbc_write_vsir_sampler_dcl(d3dbc, reg_id, VKD3D_SM1_RESOURCE_TEXTURE_2D); + break; + - case HLSL_OP1_RCP: - d3dbc_write_per_component_unary_op(d3dbc, instr, D3DSIO_RCP); -- break; -- ++ case VKD3D_SHADER_RESOURCE_TEXTURE_CUBE: ++ d3dbc_write_vsir_sampler_dcl(d3dbc, reg_id, VKD3D_SM1_RESOURCE_TEXTURE_CUBE); + break; + - case HLSL_OP1_RSQ: - d3dbc_write_per_component_unary_op(d3dbc, instr, D3DSIO_RSQ); - break; @@ -1132,16 +1485,12 @@ index d05394c3ab7..10f2e5e5e6d 100644 - default: - vkd3d_unreachable(); - } -+ case VKD3D_SHADER_RESOURCE_TEXTURE_2D: -+ d3dbc_write_vsir_sampler_dcl(d3dbc, reg_id, VKD3D_SM1_RESOURCE_TEXTURE_2D); - break; - +- break; +- - case HLSL_OP2_LOGIC_AND: - d3dbc_write_binary_op(d3dbc, D3DSIO_MIN, &instr->reg, &arg1->reg, &arg2->reg); -+ case VKD3D_SHADER_RESOURCE_TEXTURE_CUBE: -+ d3dbc_write_vsir_sampler_dcl(d3dbc, reg_id, VKD3D_SM1_RESOURCE_TEXTURE_CUBE); - break; - +- break; +- - case HLSL_OP2_LOGIC_OR: - d3dbc_write_binary_op(d3dbc, D3DSIO_MAX, &instr->reg, &arg1->reg, &arg2->reg); - break; @@ -1171,19 +1520,13 @@ index d05394c3ab7..10f2e5e5e6d 100644 default: - hlsl_fixme(ctx, &instr->loc, "SM1 \"%s\" expression.", debug_hlsl_expr_op(expr->op)); - break; -+ vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_RESOURCE_TYPE, -+ "dcl instruction with resource_type %u.", semantic->resource_type); -+ d3dbc->failed = true; -+ return; - } - } - +- } +-} +- -static void d3dbc_write_block(struct d3dbc_compiler *d3dbc, const struct hlsl_block *block); - -static void d3dbc_write_if(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_node *instr) -+static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir_instruction( -+ struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_instruction *ins) - { +-{ - const struct hlsl_ir_if *iff = hlsl_ir_if(instr); - const struct hlsl_ir_node *condition; - struct sm1_instruction sm1_ifc, sm1_else, sm1_endif; @@ -1210,30 +1553,31 @@ index d05394c3ab7..10f2e5e5e6d 100644 - }; - d3dbc_write_instruction(d3dbc, &sm1_ifc); - d3dbc_write_block(d3dbc, &iff->then_block); -+ const struct vkd3d_sm1_opcode_info *info; - +- - if (!list_empty(&iff->else_block.instrs)) -+ if (!(info = shader_sm1_get_opcode_info_from_vsir(d3dbc, ins->opcode))) - { +- { - sm1_else = (struct sm1_instruction){.opcode = D3DSIO_ELSE}; - d3dbc_write_instruction(d3dbc, &sm1_else); - d3dbc_write_block(d3dbc, &iff->else_block); -+ vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, -+ "Opcode %#x not supported for shader profile.", ins->opcode); -+ d3dbc->failed = true; -+ return NULL; ++ vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_RESOURCE_TYPE, ++ "dcl instruction with resource_type %u.", semantic->resource_type); ++ d3dbc->failed = true; ++ return; } - +- - sm1_endif = (struct sm1_instruction){.opcode = D3DSIO_ENDIF}; - d3dbc_write_instruction(d3dbc, &sm1_endif); --} -- + } + -static void d3dbc_write_jump(struct d3dbc_compiler *d3dbc, const struct hlsl_ir_node *instr) --{ ++static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir_instruction( ++ struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_instruction *ins) + { - const struct hlsl_ir_jump *jump = hlsl_ir_jump(instr); -- ++ const struct vkd3d_sm1_opcode_info *info; + - switch (jump->type) -+ if (ins->dst_count != info->dst_count) ++ if (!(info = shader_sm1_get_opcode_info_from_vsir(d3dbc, ins->opcode))) { - case HLSL_IR_JUMP_DISCARD_NEG: - { @@ -1255,9 +1599,8 @@ index d05394c3ab7..10f2e5e5e6d 100644 - - default: - hlsl_fixme(d3dbc->ctx, &jump->node.loc, "Jump type %s.", hlsl_jump_type_to_string(jump->type)); -+ vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, -+ "Invalid destination count %u for vsir instruction %#x (expected %u).", -+ ins->dst_count, ins->opcode, info->dst_count); ++ vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, ++ "Opcode %#x not supported for shader profile.", ins->opcode); + d3dbc->failed = true; + return NULL; } @@ -1271,7 +1614,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 - struct sm1_instruction sm1_instr = - { - .opcode = D3DSIO_MOV, -- + - .dst.type = VKD3DSPR_TEMP, - .dst.reg = instr->reg.id, - .dst.writemask = instr->reg.writemask, @@ -1286,13 +1629,19 @@ index d05394c3ab7..10f2e5e5e6d 100644 - VKD3D_ASSERT(instr->reg.allocated); - - if (load->src.var->is_uniform) -+ if (ins->src_count != info->src_count) ++ if (ins->dst_count != info->dst_count) { - VKD3D_ASSERT(reg.allocated); - sm1_instr.srcs[0].type = VKD3DSPR_CONST; -- } ++ vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, ++ "Invalid destination count %u for vsir instruction %#x (expected %u).", ++ ins->dst_count, ins->opcode, info->dst_count); ++ d3dbc->failed = true; ++ return NULL; + } - else if (load->src.var->is_input_semantic) -- { ++ if (ins->src_count != info->src_count) + { - if (!hlsl_sm1_register_from_semantic(&d3dbc->program->shader_version, load->src.var->semantic.name, - load->src.var->semantic.index, false, &sm1_instr.srcs[0].type, &sm1_instr.srcs[0].reg)) - { @@ -1698,7 +2047,7 @@ index d05394c3ab7..10f2e5e5e6d 100644 { out->code = buffer->data; out->size = buffer->size; -@@ -2925,5 +2372,5 @@ int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, +@@ -2925,5 +2408,5 @@ int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, { vkd3d_free(buffer->data); } @@ -1757,7 +2106,7 @@ index 184788dc57e..93fc993e0d1 100644 set_u32(&context.buffer, (i + 1) * sizeof(uint32_t), checksum[i]); diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 4a17c62292b..ee78b6251f9 100644 +index 4a17c62292b..d4296ef4bc5 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -3888,7 +3888,7 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade @@ -1769,7 +2118,215 @@ index 4a17c62292b..ee78b6251f9 100644 param->reg.idx[count++].offset = 0; } -@@ -10303,7 +10303,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro +@@ -4161,8 +4161,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ + dst_param_init(&dst_params[0]); + + dst_params[1].reg = ptr->u.reg; +- /* The groupshared register has data type UAV when accessed. */ +- dst_params[1].reg.data_type = VKD3D_DATA_UAV; ++ dst_params[1].reg.data_type = VKD3D_DATA_UNUSED; + dst_params[1].reg.idx[1].rel_addr = NULL; + dst_params[1].reg.idx[1].offset = ~0u; + dst_params[1].reg.idx_count = 1; +@@ -4865,8 +4864,10 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; + src_param_init_vector_from_reg(src_param, &buffer->u.handle.reg); ++ /* Differently from other descriptors, constant buffers require an ++ * additional index, used to index within the constant buffer itself. */ ++ src_param->reg.idx_count = 3; + register_index_address_init(&src_param->reg.idx[2], operands[1], sm6); +- VKD3D_ASSERT(src_param->reg.idx_count == 3); + + type = sm6_type_get_scalar_type(dst->type, 0); + VKD3D_ASSERT(type); +@@ -4965,8 +4966,7 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int + dst->u.handle.d = d; + + reg = &dst->u.handle.reg; +- /* Set idx_count to 3 for use with load/store instructions. */ +- vsir_register_init(reg, d->reg_type, d->reg_data_type, 3); ++ vsir_register_init(reg, d->reg_type, d->reg_data_type, 2); + reg->dimension = VSIR_DIMENSION_VEC4; + reg->idx[0].offset = id; + register_index_address_init(®->idx[1], operands[2], sm6); +@@ -6861,7 +6861,6 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re + struct vkd3d_shader_dst_param *dst_params; + struct vkd3d_shader_src_param *src_params; + const struct sm6_value *ptr, *cmp, *new; +- const struct sm6_type *type; + unsigned int i = 0; + bool is_volatile; + uint64_t code; +@@ -6887,9 +6886,10 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re + return; + } + +- type = ptr->type->u.pointer.type; +- cmp = sm6_parser_get_value_by_ref(sm6, record, type, &i); +- new = sm6_parser_get_value_by_ref(sm6, record, type, &i); ++ /* Forward-referenced comparands are stored as value/type pairs, even ++ * though in principle we could use the destination type. */ ++ cmp = sm6_parser_get_value_by_ref(sm6, record, NULL, &i); ++ new = sm6_parser_get_value_by_ref(sm6, record, ptr->type->u.pointer.type, &i); + if (!cmp || !new) + return; + +@@ -7287,7 +7287,6 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco + unsigned int i = 0, alignment, operand_count; + struct vkd3d_shader_src_param *src_params; + struct vkd3d_shader_dst_param *dst_param; +- const struct sm6_type *pointee_type; + const struct sm6_value *ptr, *src; + uint64_t alignment_code; + +@@ -7299,13 +7298,14 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco + return; + } + +- pointee_type = ptr->type->u.pointer.type; +- if (!(src = sm6_parser_get_value_by_ref(sm6, record, pointee_type, &i))) ++ /* Forward-referenced sources are stored as value/type pairs, even ++ * though in principle we could use the destination type. */ ++ if (!(src = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))) + return; + if (!sm6_value_validate_is_numeric(src, sm6)) + return; + +- if (pointee_type != src->type) ++ if (ptr->type->u.pointer.type != src->type) + { + WARN("Type mismatch.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, +@@ -8908,7 +8908,7 @@ static enum vkd3d_result sm6_parser_resources_load_srv(struct sm6_parser *sm6, + d->resource_type = ins->resource_type; + d->kind = kind; + d->reg_type = VKD3DSPR_RESOURCE; +- d->reg_data_type = (ins->resource_type == VKD3D_SHADER_RESOURCE_BUFFER) ? VKD3D_DATA_UINT : VKD3D_DATA_RESOURCE; ++ d->reg_data_type = VKD3D_DATA_UNUSED; + d->resource_data_type = (ins->opcode == VKD3DSIH_DCL) + ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; + +@@ -8982,7 +8982,7 @@ static enum vkd3d_result sm6_parser_resources_load_uav(struct sm6_parser *sm6, + d->resource_type = ins->resource_type; + d->kind = values[0]; + d->reg_type = VKD3DSPR_UAV; +- d->reg_data_type = (ins->resource_type == VKD3D_SHADER_RESOURCE_BUFFER) ? VKD3D_DATA_UINT : VKD3D_DATA_UAV; ++ d->reg_data_type = VKD3D_DATA_UNUSED; + d->resource_data_type = (ins->opcode == VKD3DSIH_DCL_UAV_TYPED) + ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; + +@@ -9346,7 +9346,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + WARN("Signature element is not a node.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element is not a metadata node."); +- return VKD3D_ERROR_INVALID_SHADER; ++ goto invalid; + } + + element_node = m->u.node; +@@ -9355,7 +9355,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + WARN("Invalid operand count %u.\n", element_node->operand_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Invalid signature element operand count %u.", element_node->operand_count); +- return VKD3D_ERROR_INVALID_SHADER; ++ goto invalid; + } + if (element_node->operand_count > 11) + { +@@ -9374,7 +9374,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + WARN("Failed to load uint value at index %u.\n", j); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element value at index %u is not an integer.", j); +- return VKD3D_ERROR_INVALID_SHADER; ++ goto invalid; + } + } + +@@ -9385,7 +9385,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + FIXME("Unsupported element id %u not equal to its index %u.\n", values[0], i); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "A non-sequential and non-zero-based element id is not supported."); +- return VKD3D_ERROR_INVALID_SHADER; ++ goto invalid; + } + + if (!sm6_metadata_value_is_string(element_node->operands[1])) +@@ -9393,7 +9393,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + WARN("Element name is not a string.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element name is not a metadata string."); +- return VKD3D_ERROR_INVALID_SHADER; ++ goto invalid; + } + e->semantic_name = element_node->operands[1]->u.string_value; + +@@ -9407,7 +9407,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + WARN("Unhandled semantic kind %u.\n", j); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "DXIL semantic kind %u is unhandled.", j); +- return VKD3D_ERROR_INVALID_SHADER; ++ goto invalid; + } + + if ((e->interpolation_mode = values[5]) >= VKD3DSIM_COUNT) +@@ -9415,7 +9415,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + WARN("Unhandled interpolation mode %u.\n", e->interpolation_mode); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Interpolation mode %u is unhandled.", e->interpolation_mode); +- return VKD3D_ERROR_INVALID_SHADER; ++ goto invalid; + } + + e->register_count = values[6]; +@@ -9430,7 +9430,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + WARN("Unhandled I/O register semantic kind %u.\n", j); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "DXIL semantic kind %u is unhandled for an I/O register.", j); +- return VKD3D_ERROR_INVALID_SHADER; ++ goto invalid; + } + } + else if (e->register_index > MAX_REG_OUTPUT || e->register_count > MAX_REG_OUTPUT - e->register_index) +@@ -9439,7 +9439,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "A signature element starting row of %u with count %u is invalid.", + e->register_index, e->register_count); +- return VKD3D_ERROR_INVALID_SHADER; ++ goto invalid; + } + + index = values[9]; +@@ -9448,7 +9448,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + WARN("Invalid column start %u with count %u.\n", index, column_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "A signature element starting column %u with count %u is invalid.", index, column_count); +- return VKD3D_ERROR_INVALID_SHADER; ++ goto invalid; + } + + e->mask = vkd3d_write_mask_from_component_count(column_count); +@@ -9471,7 +9471,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + WARN("Semantic index list is not a node.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, + "Signature element semantic index list is not a metadata node."); +- return VKD3D_ERROR_INVALID_SHADER; ++ goto invalid; + } + + element_node = m->u.node; +@@ -9516,6 +9516,10 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + s->element_count = operand_count; + + return VKD3D_OK; ++ ++invalid: ++ vkd3d_free(elements); ++ return VKD3D_ERROR_INVALID_SHADER; + } + + static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, const struct sm6_metadata_value *m, +@@ -10303,7 +10307,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro /* Estimate instruction count to avoid reallocation in most shaders. */ count = max(token_count, 400) - 400; @@ -1778,8 +2335,59 @@ index 4a17c62292b..ee78b6251f9 100644 return VKD3D_ERROR_OUT_OF_MEMORY; vkd3d_shader_parser_init(&sm6->p, program, message_context, compile_info->source_name); sm6->ptr = &sm6->start[1]; +@@ -10526,9 +10530,16 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro + + dxil_block_destroy(&sm6->root_block); + ++ if (sm6->p.failed) ++ { ++ ret = VKD3D_ERROR_INVALID_SHADER; ++ goto fail; ++ } ++ + return VKD3D_OK; + + fail: ++ sm6_parser_cleanup(sm6); + vsir_program_cleanup(program); + return ret; + } +@@ -10570,18 +10581,25 @@ int dxil_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t co + free_dxbc_shader_desc(&dxbc_desc); + vkd3d_free(byte_code); + +- if (!sm6.p.failed && ret >= 0) +- ret = vkd3d_shader_parser_validate(&sm6.p, config_flags); +- +- if (sm6.p.failed && ret >= 0) +- ret = VKD3D_ERROR_INVALID_SHADER; +- +- sm6_parser_cleanup(&sm6); + if (ret < 0) + { + WARN("Failed to parse shader.\n"); + return ret; + } + +- return ret; ++ if ((ret = vkd3d_shader_parser_validate(&sm6.p, config_flags)) < 0) ++ { ++ WARN("Failed to validate shader after parsing, ret %d.\n", ret); ++ ++ if (TRACE_ON()) ++ vkd3d_shader_trace(program); ++ ++ sm6_parser_cleanup(&sm6); ++ vsir_program_cleanup(program); ++ return ret; ++ } ++ ++ sm6_parser_cleanup(&sm6); ++ ++ return VKD3D_OK; + } diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index a1d1fd6572f..1314bc09e73 100644 +index a1d1fd6572f..cc18857a010 100644 --- a/libs/vkd3d/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d/libs/vkd3d-shader/fx.c @@ -38,6 +38,7 @@ struct type_entry @@ -1790,7 +2398,27 @@ index a1d1fd6572f..1314bc09e73 100644 uint32_t offset; }; -@@ -278,9 +279,9 @@ static void write_fx_4_state_block(struct hlsl_ir_var *var, unsigned int block_i +@@ -181,6 +182,7 @@ struct fx_write_context + + struct vkd3d_bytecode_buffer unstructured; + struct vkd3d_bytecode_buffer structured; ++ struct vkd3d_bytecode_buffer objects; + + struct rb_tree strings; + struct list types; +@@ -223,11 +225,6 @@ static void set_status(struct fx_write_context *fx, int status) + fx->status = status; + } + +-static bool has_annotations(const struct hlsl_ir_var *var) +-{ +- return var->annotations && !list_empty(&var->annotations->vars); +-} +- + static uint32_t write_string(const char *string, struct fx_write_context *fx) + { + return fx->ops->write_string(string, fx); +@@ -278,9 +275,9 @@ static void write_fx_4_state_block(struct hlsl_ir_var *var, unsigned int block_i static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context *fx) { @@ -1801,7 +2429,7 @@ index a1d1fd6572f..1314bc09e73 100644 const char *name; VKD3D_ASSERT(fx->ctx->profile->major_version >= 4); -@@ -297,6 +298,7 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context +@@ -297,6 +294,7 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context } name = get_fx_4_type_name(element_type); @@ -1809,7 +2437,7 @@ index a1d1fd6572f..1314bc09e73 100644 LIST_FOR_EACH_ENTRY(type_entry, &fx->types, struct type_entry, entry) { -@@ -306,6 +308,9 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context +@@ -306,6 +304,9 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context if (type_entry->elements_count != elements_count) continue; @@ -1819,7 +2447,7 @@ index a1d1fd6572f..1314bc09e73 100644 return type_entry->offset; } -@@ -315,6 +320,7 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context +@@ -315,6 +316,7 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context type_entry->offset = write_fx_4_type(type, fx); type_entry->name = name; type_entry->elements_count = elements_count; @@ -1827,7 +2455,53 @@ index a1d1fd6572f..1314bc09e73 100644 list_add_tail(&fx->types, &type_entry->entry); -@@ -564,6 +570,9 @@ static const char * get_fx_4_type_name(const struct hlsl_type *type) +@@ -429,17 +431,26 @@ static void write_fx_4_pass(struct hlsl_ir_var *var, struct fx_write_context *fx + write_fx_4_state_block(var, 0, count_offset, fx); + } + ++static void write_fx_2_annotations(struct hlsl_ir_var *var, uint32_t count_offset, struct fx_write_context *fx) ++{ ++ struct vkd3d_bytecode_buffer *buffer = &fx->structured; ++ uint32_t count; ++ ++ count = write_annotations(var->annotations, fx); ++ set_u32(buffer, count_offset, count); ++} ++ + static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) + { + struct vkd3d_bytecode_buffer *buffer = &fx->structured; +- uint32_t name_offset; ++ uint32_t name_offset, annotation_count_offset; + + name_offset = write_string(var->name, fx); + put_u32(buffer, name_offset); +- put_u32(buffer, 0); /* Annotation count. */ ++ annotation_count_offset = put_u32(buffer, 0); + put_u32(buffer, 0); /* Assignment count. */ + +- /* TODO: annotations */ ++ write_fx_2_annotations(var, annotation_count_offset, fx); + /* TODO: assignments */ + + if (var->state_block_count && var->state_blocks[0]->count) +@@ -461,6 +472,7 @@ static uint32_t get_fx_4_type_size(const struct hlsl_type *type) + + static const uint32_t fx_4_numeric_base_type[] = + { ++ [HLSL_TYPE_HALF] = 1, + [HLSL_TYPE_FLOAT] = 1, + [HLSL_TYPE_INT ] = 2, + [HLSL_TYPE_UINT ] = 3, +@@ -497,6 +509,7 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, + switch (type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: ++ case HLSL_TYPE_HALF: + case HLSL_TYPE_INT: + case HLSL_TYPE_UINT: + case HLSL_TYPE_BOOL: +@@ -564,17 +577,32 @@ static const char * get_fx_4_type_name(const struct hlsl_type *type) case HLSL_CLASS_VERTEX_SHADER: return "VertexShader"; @@ -1837,7 +2511,17 @@ index a1d1fd6572f..1314bc09e73 100644 case HLSL_CLASS_PIXEL_SHADER: return "PixelShader"; -@@ -575,6 +584,12 @@ static const char * get_fx_4_type_name(const struct hlsl_type *type) + case HLSL_CLASS_STRING: + return "String"; + ++ case HLSL_CLASS_SCALAR: ++ case HLSL_CLASS_VECTOR: ++ case HLSL_CLASS_MATRIX: ++ if (type->e.numeric.type == HLSL_TYPE_HALF) ++ return "float"; ++ /* fall-through */ + default: + return type->name; } } @@ -1850,7 +2534,7 @@ index a1d1fd6572f..1314bc09e73 100644 static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx) { struct field_offsets -@@ -584,43 +599,41 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co +@@ -584,43 +612,41 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co uint32_t offset; uint32_t type; }; @@ -1904,7 +2588,15 @@ index a1d1fd6572f..1314bc09e73 100644 { case HLSL_CLASS_SCALAR: case HLSL_CLASS_VECTOR: -@@ -659,32 +672,32 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co +@@ -652,6 +678,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + + case HLSL_CLASS_ARRAY: + case HLSL_CLASS_EFFECT_GROUP: ++ case HLSL_CLASS_ERROR: + case HLSL_CLASS_PASS: + case HLSL_CLASS_TECHNIQUE: + case HLSL_CLASS_CONSTANT_BUFFER: +@@ -659,32 +686,32 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co vkd3d_unreachable(); case HLSL_CLASS_VOID: @@ -1948,7 +2640,7 @@ index a1d1fd6572f..1314bc09e73 100644 { const struct field_offsets *field = &field_offsets[i]; -@@ -700,7 +713,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co +@@ -700,7 +727,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co put_u32_unaligned(buffer, 0); /* Interface count */ } } @@ -1957,7 +2649,7 @@ index a1d1fd6572f..1314bc09e73 100644 { static const uint32_t texture_type[] = { -@@ -716,13 +729,13 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co +@@ -716,13 +743,13 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co [HLSL_SAMPLER_DIM_CUBEARRAY] = 23, }; @@ -1974,7 +2666,7 @@ index a1d1fd6572f..1314bc09e73 100644 { static const uint32_t uav_type[] = { -@@ -735,60 +748,60 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co +@@ -735,60 +762,60 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co [HLSL_SAMPLER_DIM_STRUCTURED_BUFFER] = 40, }; @@ -2050,7 +2742,449 @@ index a1d1fd6572f..1314bc09e73 100644 set_status(fx, VKD3D_ERROR_NOT_IMPLEMENTED); } -@@ -2126,7 +2139,7 @@ static unsigned int decompose_fx_4_state_function_call(struct hlsl_ir_var *var, +@@ -963,16 +990,16 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n + + static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) + { ++ uint32_t name_offset, pass_count_offset, annotation_count_offset, count = 0; + struct vkd3d_bytecode_buffer *buffer = &fx->structured; +- uint32_t name_offset, count_offset, count = 0; + struct hlsl_ir_var *pass; + + name_offset = write_string(var->name, fx); + put_u32(buffer, name_offset); +- put_u32(buffer, 0); /* Annotation count. */ +- count_offset = put_u32(buffer, 0); /* Pass count. */ ++ annotation_count_offset = put_u32(buffer, 0); ++ pass_count_offset = put_u32(buffer, 0); + +- /* FIXME: annotations */ ++ write_fx_2_annotations(var, annotation_count_offset, fx); + + LIST_FOR_EACH_ENTRY(pass, &var->scope->vars, struct hlsl_ir_var, scope_entry) + { +@@ -980,47 +1007,128 @@ static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_contex + ++count; + } + +- set_u32(buffer, count_offset, count); ++ set_u32(buffer, pass_count_offset, count); + } + +-static uint32_t get_fx_2_type_size(const struct hlsl_type *type) ++static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hlsl_default_value *value, ++ struct fx_write_context *fx) + { +- uint32_t size = 0, elements_count; +- size_t i; ++ const struct hlsl_type *type = hlsl_get_multiarray_element_type(value_type); ++ uint32_t elements_count = hlsl_get_multiarray_size(value_type), i, j; ++ struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; ++ struct hlsl_ctx *ctx = fx->ctx; ++ uint32_t offset = buffer->size; ++ unsigned int comp_count; + +- if (type->class == HLSL_CLASS_ARRAY) ++ if (!value) ++ return 0; ++ ++ comp_count = hlsl_type_component_count(type); ++ ++ for (i = 0; i < elements_count; ++i) + { +- elements_count = hlsl_get_multiarray_size(type); +- type = hlsl_get_multiarray_element_type(type); +- return get_fx_2_type_size(type) * elements_count; ++ switch (type->class) ++ { ++ case HLSL_CLASS_SCALAR: ++ case HLSL_CLASS_VECTOR: ++ case HLSL_CLASS_MATRIX: ++ { ++ switch (type->e.numeric.type) ++ { ++ case HLSL_TYPE_FLOAT: ++ case HLSL_TYPE_HALF: ++ case HLSL_TYPE_INT: ++ case HLSL_TYPE_UINT: ++ case HLSL_TYPE_BOOL: ++ ++ for (j = 0; j < comp_count; ++j) ++ { ++ put_u32(buffer, value->number.u); ++ value++; ++ } ++ break; ++ default: ++ hlsl_fixme(ctx, &ctx->location, "Writing default values for numeric type %u is not implemented.", ++ type->e.numeric.type); ++ } ++ ++ break; ++ } ++ case HLSL_CLASS_STRUCT: ++ { ++ struct hlsl_struct_field *fields = type->e.record.fields; ++ ++ for (j = 0; j < type->e.record.field_count; ++j) ++ { ++ write_fx_2_default_value(fields[i].type, value, fx); ++ value += hlsl_type_component_count(fields[i].type); ++ } ++ break; ++ } ++ default: ++ hlsl_fixme(ctx, &ctx->location, "Writing default values for class %u is not implemented.", type->class); ++ } + } +- else if (type->class == HLSL_CLASS_STRUCT) ++ ++ return offset; ++} ++ ++static uint32_t write_fx_2_object_initializer(const struct hlsl_ir_var *var, struct fx_write_context *fx) ++{ ++ const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); ++ unsigned int i, elements_count = hlsl_get_multiarray_size(var->data_type); ++ struct vkd3d_bytecode_buffer *buffer = &fx->objects; ++ uint32_t offset = fx->unstructured.size, id, size; ++ struct hlsl_ctx *ctx = fx->ctx; ++ const void *data; ++ ++ for (i = 0; i < elements_count; ++i) + { +- for (i = 0; i < type->e.record.field_count; ++i) ++ if (type->class == HLSL_CLASS_SAMPLER) + { +- const struct hlsl_struct_field *field = &type->e.record.fields[i]; +- size += get_fx_2_type_size(field->type); ++ hlsl_fixme(ctx, &var->loc, "Writing fx_2_0 sampler objects initializers is not implemented."); + } ++ else ++ { ++ switch (type->class) ++ { ++ case HLSL_CLASS_STRING: ++ { ++ const char *string = var->default_values[i].string ? var->default_values[i].string : ""; ++ size = strlen(string) + 1; ++ data = string; ++ break; ++ } ++ case HLSL_CLASS_TEXTURE: ++ size = 0; ++ break; ++ case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_VERTEX_SHADER: ++ size = 0; ++ hlsl_fixme(ctx, &var->loc, "Writing fx_2_0 shader objects initializers is not implemented."); ++ break; ++ default: ++ vkd3d_unreachable(); ++ } ++ id = fx->object_variable_count++; ++ ++ put_u32(&fx->unstructured, id); + +- return size; ++ put_u32(buffer, id); ++ put_u32(buffer, size); ++ if (size) ++ bytecode_put_bytes(buffer, data, size); ++ } + } + +- return type->dimx * type->dimy * sizeof(float); ++ return offset; + } + + static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct fx_write_context *fx) + { +- struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; +- const struct hlsl_type *type = var->data_type; +- uint32_t offset, size, elements_count = 1; +- +- size = get_fx_2_type_size(type); +- +- if (type->class == HLSL_CLASS_ARRAY) +- { +- elements_count = hlsl_get_multiarray_size(type); +- type = hlsl_get_multiarray_element_type(type); +- } ++ const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); ++ struct hlsl_ctx *ctx = fx->ctx; ++ uint32_t offset; + + /* Note that struct fields must all be numeric; + * this was validated in check_invalid_object_fields(). */ +@@ -1030,21 +1138,20 @@ static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct f + case HLSL_CLASS_VECTOR: + case HLSL_CLASS_MATRIX: + case HLSL_CLASS_STRUCT: +- /* FIXME: write actual initial value */ +- if (var->default_values) +- hlsl_fixme(fx->ctx, &var->loc, "Write default values.\n"); +- +- offset = put_u32(buffer, 0); ++ offset = write_fx_2_default_value(var->data_type, var->default_values, fx); ++ break; + +- for (uint32_t i = 1; i < size / sizeof(uint32_t); ++i) +- put_u32(buffer, 0); ++ case HLSL_CLASS_SAMPLER: ++ case HLSL_CLASS_TEXTURE: ++ case HLSL_CLASS_STRING: ++ case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_VERTEX_SHADER: ++ offset = write_fx_2_object_initializer(var, fx); + break; + + default: +- /* Objects are given sequential ids. */ +- offset = put_u32(buffer, fx->object_variable_count++); +- for (uint32_t i = 1; i < elements_count; ++i) +- put_u32(buffer, fx->object_variable_count++); ++ offset = 0; ++ hlsl_fixme(ctx, &var->loc, "Writing initializer not implemented for parameter class %#x.", type->class); + break; + } + +@@ -1070,6 +1177,7 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type + return is_type_supported_fx_2(ctx, type->e.array.type, loc); + + case HLSL_CLASS_TEXTURE: ++ case HLSL_CLASS_SAMPLER: + switch (type->sampler_dim) + { + case HLSL_SAMPLER_DIM_1D: +@@ -1083,9 +1191,10 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type + } + break; + +- case HLSL_CLASS_PIXEL_SHADER: +- case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: ++ return true; ++ ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_VERTEX_SHADER: + hlsl_fixme(ctx, loc, "Write fx 2.0 parameter class %#x.", type->class); + return false; +@@ -1104,6 +1213,7 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type + return false; + + case HLSL_CLASS_EFFECT_GROUP: ++ case HLSL_CLASS_ERROR: + case HLSL_CLASS_PASS: + case HLSL_CLASS_TECHNIQUE: + case HLSL_CLASS_CONSTANT_BUFFER: +@@ -1117,8 +1227,8 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type + + static void write_fx_2_parameters(struct fx_write_context *fx) + { ++ uint32_t desc_offset, value_offset, flags, annotation_count_offset; + struct vkd3d_bytecode_buffer *buffer = &fx->structured; +- uint32_t desc_offset, value_offset, flags; + struct hlsl_ctx *ctx = fx->ctx; + struct hlsl_ir_var *var; + enum fx_2_parameter_flags +@@ -1138,23 +1248,35 @@ static void write_fx_2_parameters(struct fx_write_context *fx) + if (var->storage_modifiers & HLSL_STORAGE_SHARED) + flags |= IS_SHARED; + +- put_u32(buffer, desc_offset); /* Parameter description */ +- put_u32(buffer, value_offset); /* Value */ +- put_u32(buffer, flags); /* Flags */ ++ put_u32(buffer, desc_offset); ++ put_u32(buffer, value_offset); ++ put_u32(buffer, flags); + +- put_u32(buffer, 0); /* Annotations count */ +- if (has_annotations(var)) +- hlsl_fixme(ctx, &ctx->location, "Writing annotations for parameters is not implemented."); ++ annotation_count_offset = put_u32(buffer, 0); ++ write_fx_2_annotations(var, annotation_count_offset, fx); + + ++fx->parameter_count; + } + } + ++static void write_fx_2_annotation(struct hlsl_ir_var *var, struct fx_write_context *fx) ++{ ++ struct vkd3d_bytecode_buffer *buffer = &fx->structured; ++ uint32_t desc_offset, value_offset; ++ ++ desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, fx); ++ value_offset = write_fx_2_initial_value(var, fx); ++ ++ put_u32(buffer, desc_offset); ++ put_u32(buffer, value_offset); ++} ++ + static const struct fx_write_context_ops fx_2_ops = + { + .write_string = write_fx_2_string, + .write_technique = write_fx_2_technique, + .write_pass = write_fx_2_pass, ++ .write_annotation = write_fx_2_annotation, + }; + + static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) +@@ -1180,19 +1302,18 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) + object_count = put_u32(structured, 0); + + write_fx_2_parameters(&fx); +- set_u32(structured, parameter_count, fx.parameter_count); +- set_u32(structured, object_count, fx.object_variable_count); +- + write_techniques(ctx->globals, &fx); +- set_u32(structured, technique_count, fx.technique_count); +- set_u32(structured, shader_count, fx.shader_count); +- +- put_u32(structured, 0); /* String count */ ++ put_u32(structured, fx.object_variable_count - 1); + put_u32(structured, 0); /* Resource count */ + +- /* TODO: strings */ ++ bytecode_put_bytes(structured, fx.objects.data, fx.objects.size); + /* TODO: resources */ + ++ set_u32(structured, parameter_count, fx.parameter_count); ++ set_u32(structured, object_count, fx.object_variable_count); ++ set_u32(structured, technique_count, fx.technique_count); ++ set_u32(structured, shader_count, fx.shader_count); ++ + size = align(fx.unstructured.size, 4); + set_u32(&buffer, offset, size); + +@@ -1201,6 +1322,7 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) + + vkd3d_free(fx.unstructured.data); + vkd3d_free(fx.structured.data); ++ vkd3d_free(fx.objects.data); + + if (!fx.technique_count) + hlsl_error(ctx, &ctx->location, VKD3D_SHADER_ERROR_HLSL_MISSING_TECHNIQUE, "No techniques found."); +@@ -1252,6 +1374,7 @@ static uint32_t write_fx_4_default_value(struct hlsl_type *value_type, struct hl + switch (type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: ++ case HLSL_TYPE_HALF: + case HLSL_TYPE_INT: + case HLSL_TYPE_UINT: + case HLSL_TYPE_BOOL: +@@ -1438,11 +1561,14 @@ static uint32_t write_fx_4_state_numeric_value(struct hlsl_ir_constant *value, s + static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry, + struct fx_write_context *fx) + { +- uint32_t value_offset = 0, assignment_type = 0, rhs_offset; +- uint32_t type_offset; ++ uint32_t value_offset = 0, assignment_type = 0, rhs_offset, type_offset, offset; ++ struct vkd3d_bytecode_buffer *unstructured = &fx->unstructured; + struct vkd3d_bytecode_buffer *buffer = &fx->structured; +- struct hlsl_ctx *ctx = fx->ctx; + struct hlsl_ir_node *value = entry->args->node; ++ struct hlsl_ctx *ctx = fx->ctx; ++ struct hlsl_ir_var *index_var; ++ struct hlsl_ir_constant *c; ++ struct hlsl_ir_load *load; + + put_u32(buffer, entry->name_id); + put_u32(buffer, entry->lhs_index); +@@ -1453,7 +1579,7 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl + { + case HLSL_IR_CONSTANT: + { +- struct hlsl_ir_constant *c = hlsl_ir_constant(value); ++ c = hlsl_ir_constant(value); + + value_offset = write_fx_4_state_numeric_value(c, fx); + assignment_type = 1; +@@ -1461,15 +1587,71 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl + } + case HLSL_IR_LOAD: + { +- struct hlsl_ir_load *l = hlsl_ir_load(value); ++ load = hlsl_ir_load(value); + +- if (l->src.path_len) ++ if (load->src.path_len) + hlsl_fixme(ctx, &var->loc, "Indexed access in RHS values is not implemented."); + +- value_offset = write_fx_4_string(l->src.var->name, fx); ++ value_offset = write_fx_4_string(load->src.var->name, fx); + assignment_type = 2; + break; + } ++ case HLSL_IR_INDEX: ++ { ++ struct hlsl_ir_index *index = hlsl_ir_index(value); ++ struct hlsl_ir_node *val = index->val.node; ++ struct hlsl_ir_node *idx = index->idx.node; ++ struct hlsl_type *type; ++ ++ if (val->type != HLSL_IR_LOAD) ++ { ++ hlsl_fixme(ctx, &var->loc, "Unexpected indexed RHS value type."); ++ break; ++ } ++ ++ load = hlsl_ir_load(val); ++ value_offset = write_fx_4_string(load->src.var->name, fx); ++ type = load->src.var->data_type; ++ ++ switch (idx->type) ++ { ++ case HLSL_IR_CONSTANT: ++ { ++ c = hlsl_ir_constant(idx); ++ value_offset = put_u32(unstructured, value_offset); ++ put_u32(unstructured, c->value.u[0].u); ++ assignment_type = 3; ++ ++ if (c->value.u[0].u >= type->e.array.elements_count) ++ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS, ++ "Array index %u exceeds array size %u.", c->value.u[0].u, type->e.array.elements_count); ++ break; ++ } ++ ++ case HLSL_IR_LOAD: ++ { ++ load = hlsl_ir_load(idx); ++ index_var = load->src.var; ++ ++ /* Special case for uint index variables, for anything more complex use an expression. */ ++ if (hlsl_types_are_equal(index_var->data_type, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT)) ++ && !load->src.path_len) ++ { ++ offset = write_fx_4_string(index_var->name, fx); ++ ++ value_offset = put_u32(unstructured, value_offset); ++ put_u32(unstructured, offset); ++ assignment_type = 4; ++ break; ++ } ++ } ++ /* fall through */ ++ ++ default: ++ hlsl_fixme(ctx, &var->loc, "Complex array index expressions in RHS values are not implemented."); ++ } ++ break; ++ } + default: + hlsl_fixme(ctx, &var->loc, "Unsupported assignment type for state %s.", entry->name); + } +@@ -2118,7 +2300,7 @@ static unsigned int decompose_fx_4_state_function_call(struct hlsl_ir_var *var, + const struct function_component *comp = &components[i]; + unsigned int arg_index = (i + 1) % entry->args_count; + block->entries[entry_index + i] = clone_stateblock_entry(ctx, entry, comp->name, +- comp->lhs_has_index, comp->lhs_index, arg_index); ++ comp->lhs_has_index, comp->lhs_index, true, arg_index); + } + hlsl_free_state_block_entry(entry); + +@@ -2126,7 +2308,7 @@ static unsigned int decompose_fx_4_state_function_call(struct hlsl_ir_var *var, } /* For some states assignment sets all of the elements. This behaviour is limited to certain states of BlendState @@ -2059,7 +3193,7 @@ index a1d1fd6572f..1314bc09e73 100644 static unsigned int decompose_fx_4_state_block_expand_array(struct hlsl_ir_var *var, struct hlsl_state_block *block, unsigned int entry_index, struct fx_write_context *fx) { -@@ -2140,7 +2153,7 @@ static unsigned int decompose_fx_4_state_block_expand_array(struct hlsl_ir_var * +@@ -2140,7 +2322,7 @@ static unsigned int decompose_fx_4_state_block_expand_array(struct hlsl_ir_var * if (type->class != HLSL_CLASS_BLEND_STATE) return 1; @@ -2068,7 +3202,16 @@ index a1d1fd6572f..1314bc09e73 100644 return 1; if (entry->lhs_has_index) return 1; -@@ -2401,6 +2414,9 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx +@@ -2164,7 +2346,7 @@ static unsigned int decompose_fx_4_state_block_expand_array(struct hlsl_ir_var * + for (i = 1; i < array_size; ++i) + { + block->entries[entry_index + i] = clone_stateblock_entry(ctx, entry, +- entry->name, true, i, 0); ++ entry->name, true, i, true, 0); + } + + return array_size; +@@ -2401,6 +2583,9 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx size = 0; LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { @@ -2079,10 +3222,24 @@ index a1d1fd6572f..1314bc09e73 100644 continue; diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index d1f02ab568b..dd1c121d5a8 100644 +index d1f02ab568b..c2fb58c55e6 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -38,7 +38,20 @@ struct vkd3d_glsl_generator +@@ -18,6 +18,13 @@ + + #include "vkd3d_shader_private.h" + ++struct glsl_resource_type_info ++{ ++ size_t coord_size; ++ bool shadow; ++ const char *sampler_type; ++}; ++ + struct glsl_src + { + struct vkd3d_string_buffer *str; +@@ -38,7 +45,21 @@ struct vkd3d_glsl_generator struct vkd3d_shader_location location; struct vkd3d_shader_message_context *message_context; unsigned int indent; @@ -2100,10 +3257,11 @@ index d1f02ab568b..dd1c121d5a8 100644 + const struct vkd3d_shader_interface_info *interface_info; + const struct vkd3d_shader_descriptor_offset_info *offset_info; + const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info; ++ const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info; }; static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error( -@@ -53,6 +66,27 @@ static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error( +@@ -53,11 +74,102 @@ static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error( generator->failed = true; } @@ -2127,11 +3285,86 @@ index d1f02ab568b..dd1c121d5a8 100644 + return NULL; + } +} ++ ++static const struct glsl_resource_type_info *shader_glsl_get_resource_type_info(enum vkd3d_shader_resource_type t) ++{ ++ static const struct glsl_resource_type_info info[] = ++ { ++ {0, 0, "samplerNone"}, /* VKD3D_SHADER_RESOURCE_NONE */ ++ {1, 0, "samplerBuffer"}, /* VKD3D_SHADER_RESOURCE_BUFFER */ ++ {1, 1, "sampler1D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1D */ ++ {2, 1, "sampler2D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2D */ ++ {2, 0, "sampler2DMS"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMS */ ++ {3, 0, "sampler3D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_3D */ ++ {3, 1, "samplerCube"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBE */ ++ {2, 1, "sampler1DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY */ ++ {3, 1, "sampler2DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY */ ++ {3, 0, "sampler2DMSArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY */ ++ {4, 1, "samplerCubeArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY */ ++ }; ++ ++ if (!t || t >= ARRAY_SIZE(info)) ++ return NULL; ++ ++ return &info[t]; ++} ++ ++static const struct vkd3d_shader_descriptor_info1 *shader_glsl_get_descriptor(struct vkd3d_glsl_generator *gen, ++ enum vkd3d_shader_descriptor_type type, unsigned int idx, unsigned int space) ++{ ++ const struct vkd3d_shader_scan_descriptor_info1 *info = gen->descriptor_info; ++ ++ for (unsigned int i = 0; i < info->descriptor_count; ++i) ++ { ++ const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i]; ++ ++ if (d->type == type && d->register_space == space && d->register_index == idx) ++ return d; ++ } ++ ++ return NULL; ++} ++ ++static const struct vkd3d_shader_descriptor_info1 *shader_glsl_get_descriptor_by_id( ++ struct vkd3d_glsl_generator *gen, enum vkd3d_shader_descriptor_type type, unsigned int id) ++{ ++ const struct vkd3d_shader_scan_descriptor_info1 *info = gen->descriptor_info; ++ ++ for (unsigned int i = 0; i < info->descriptor_count; ++i) ++ { ++ const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i]; ++ ++ if (d->type == type && d->register_id == id) ++ return d; ++ } ++ ++ return NULL; ++} + static void shader_glsl_print_indent(struct vkd3d_string_buffer *buffer, unsigned int indent) { vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, ""); -@@ -67,6 +101,82 @@ static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, + } + ++static void shader_glsl_print_combined_sampler_name(struct vkd3d_string_buffer *buffer, ++ struct vkd3d_glsl_generator *gen, unsigned int resource_index, ++ unsigned int resource_space, unsigned int sampler_index, unsigned int sampler_space) ++{ ++ vkd3d_string_buffer_printf(buffer, "%s_t_%u", gen->prefix, resource_index); ++ if (resource_space) ++ vkd3d_string_buffer_printf(buffer, "_%u", resource_space); ++ if (sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX) ++ { ++ vkd3d_string_buffer_printf(buffer, "_s_%u", sampler_index); ++ if (sampler_space) ++ vkd3d_string_buffer_printf(buffer, "_%u", sampler_space); ++ } ++} ++ + static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, + struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_register *reg) + { +@@ -67,6 +179,90 @@ static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, vkd3d_string_buffer_printf(buffer, "r[%u]", reg->idx[0].offset); break; @@ -2171,6 +3404,14 @@ index d1f02ab568b..dd1c121d5a8 100644 + vkd3d_string_buffer_printf(buffer, "%s_out[%u]", gen->prefix, reg->idx[0].offset); + break; + ++ case VKD3DSPR_DEPTHOUT: ++ if (gen->program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL) ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled depth output in shader type #%x.", ++ gen->program->shader_version.type); ++ vkd3d_string_buffer_printf(buffer, "gl_FragDepth"); ++ break; ++ + case VKD3DSPR_IMMCONST: + switch (reg->dimension) + { @@ -2214,7 +3455,7 @@ index d1f02ab568b..dd1c121d5a8 100644 default: vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, "Internal compiler error: Unhandled register type %#x.", reg->type); -@@ -106,23 +216,109 @@ static void glsl_src_cleanup(struct glsl_src *src, struct vkd3d_string_buffer_ca +@@ -106,23 +302,112 @@ static void glsl_src_cleanup(struct glsl_src *src, struct vkd3d_string_buffer_ca vkd3d_string_buffer_release(cache, src->str); } @@ -2312,6 +3553,9 @@ index d1f02ab568b..dd1c121d5a8 100644 + { + case VKD3DSPSM_NONE: + break; ++ case VKD3DSPSM_NEG: ++ vkd3d_string_buffer_printf(glsl_src->str, "-%s", str->buffer); ++ break; + case VKD3DSPSM_ABS: + vkd3d_string_buffer_printf(glsl_src->str, "abs(%s)", str->buffer); + break; @@ -2329,50 +3573,86 @@ index d1f02ab568b..dd1c121d5a8 100644 } static void glsl_dst_cleanup(struct glsl_dst *dst, struct vkd3d_string_buffer_cache *cache) -@@ -156,6 +352,9 @@ static uint32_t glsl_dst_init(struct glsl_dst *glsl_dst, struct vkd3d_glsl_gener - static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( - struct vkd3d_glsl_generator *gen, struct glsl_dst *dst, const char *format, ...) +@@ -153,26 +438,69 @@ static uint32_t glsl_dst_init(struct glsl_dst *glsl_dst, struct vkd3d_glsl_gener + return write_mask; + } + +-static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( +- struct vkd3d_glsl_generator *gen, struct glsl_dst *dst, const char *format, ...) ++static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_glsl_generator *gen, ++ struct glsl_dst *dst, enum vkd3d_data_type data_type, const char *format, va_list args) { -+ const struct vkd3d_shader_register *dst_reg = &dst->vsir->reg; +- va_list args; + struct vkd3d_string_buffer *buffer = gen->buffer; ++ uint32_t modifiers = dst->vsir->modifiers; + bool close = true; - va_list args; if (dst->vsir->shift) -@@ -165,14 +364,28 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled destination modifier(s) %#x.", dst->vsir->modifiers); + "Internal compiler error: Unhandled destination shift %#x.", dst->vsir->shift); +- if (dst->vsir->modifiers) ++ if (modifiers & ~VKD3DSPDM_SATURATE) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, +- "Internal compiler error: Unhandled destination modifier(s) %#x.", dst->vsir->modifiers); ++ "Internal compiler error: Unhandled destination modifier(s) %#x.", modifiers); - shader_glsl_print_indent(gen->buffer, gen->indent); - vkd3d_string_buffer_printf(gen->buffer, "%s%s = ", dst->register_name->buffer, dst->mask->buffer); + shader_glsl_print_indent(buffer, gen->indent); + vkd3d_string_buffer_printf(buffer, "%s%s = ", dst->register_name->buffer, dst->mask->buffer); ++ if (modifiers & VKD3DSPDM_SATURATE) ++ vkd3d_string_buffer_printf(buffer, "clamp("); + -+ switch (dst_reg->data_type) ++ switch (data_type) + { + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Unhandled destination register data type %#x.", dst_reg->data_type); ++ "Internal compiler error: Unhandled destination register data type %#x.", data_type); + /* fall through */ + case VKD3D_DATA_FLOAT: + close = false; + break; ++ case VKD3D_DATA_INT: ++ vkd3d_string_buffer_printf(buffer, "intBitsToFloat("); ++ break; + case VKD3D_DATA_UINT: + vkd3d_string_buffer_printf(buffer, "uintBitsToFloat("); + break; + } ++ ++ vkd3d_string_buffer_vprintf(buffer, format, args); ++ ++ if (close) ++ vkd3d_string_buffer_printf(buffer, ")"); ++ if (modifiers & VKD3DSPDM_SATURATE) ++ vkd3d_string_buffer_printf(buffer, ", 0.0, 1.0)"); ++ vkd3d_string_buffer_printf(buffer, ";\n"); ++} ++ ++static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( ++ struct vkd3d_glsl_generator *gen, struct glsl_dst *dst, const char *format, ...) ++{ ++ va_list args; va_start(args, format); - vkd3d_string_buffer_vprintf(gen->buffer, format, args); -+ vkd3d_string_buffer_vprintf(buffer, format, args); ++ shader_glsl_vprint_assignment(gen, dst, dst->vsir->reg.data_type, format, args); va_end(args); ++} ++ ++static void VKD3D_PRINTF_FUNC(4, 5) shader_glsl_print_assignment_ext(struct vkd3d_glsl_generator *gen, ++ struct glsl_dst *dst, enum vkd3d_data_type data_type, const char *format, ...) ++{ ++ va_list args; - vkd3d_string_buffer_printf(gen->buffer, ";\n"); -+ vkd3d_string_buffer_printf(buffer, "%s;\n", close ? ")" : ""); ++ va_start(args, format); ++ shader_glsl_vprint_assignment(gen, dst, data_type, format, args); ++ va_end(args); } static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) -@@ -183,6 +396,48 @@ static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct +@@ -183,6 +511,319 @@ static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct "Internal compiler error: Unhandled instruction %#x.", ins->opcode); } @@ -2394,6 +3674,54 @@ index d1f02ab568b..dd1c121d5a8 100644 + glsl_dst_cleanup(&dst, &gen->string_buffers); +} + ++static void shader_glsl_dot(struct vkd3d_glsl_generator *gen, ++ const struct vkd3d_shader_instruction *ins, uint32_t src_mask) ++{ ++ unsigned int component_count; ++ struct glsl_src src[2]; ++ struct glsl_dst dst; ++ uint32_t dst_mask; ++ ++ dst_mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); ++ glsl_src_init(&src[0], gen, &ins->src[0], src_mask); ++ glsl_src_init(&src[1], gen, &ins->src[1], src_mask); ++ ++ if ((component_count = vsir_write_mask_component_count(dst_mask)) > 1) ++ shader_glsl_print_assignment(gen, &dst, "vec%d(dot(%s, %s))", ++ component_count, src[0].str->buffer, src[1].str->buffer); ++ else ++ shader_glsl_print_assignment(gen, &dst, "dot(%s, %s)", ++ src[0].str->buffer, src[1].str->buffer); ++ ++ glsl_src_cleanup(&src[1], &gen->string_buffers); ++ glsl_src_cleanup(&src[0], &gen->string_buffers); ++ glsl_dst_cleanup(&dst, &gen->string_buffers); ++} ++ ++static void shader_glsl_intrinsic(struct vkd3d_glsl_generator *gen, ++ const struct vkd3d_shader_instruction *ins, const char *op) ++{ ++ struct vkd3d_string_buffer *args; ++ struct glsl_src src; ++ struct glsl_dst dst; ++ unsigned int i; ++ uint32_t mask; ++ ++ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); ++ args = vkd3d_string_buffer_get(&gen->string_buffers); ++ ++ for (i = 0; i < ins->src_count; ++i) ++ { ++ glsl_src_init(&src, gen, &ins->src[i], mask); ++ vkd3d_string_buffer_printf(args, "%s%s", i ? ", " : "", src.str->buffer); ++ glsl_src_cleanup(&src, &gen->string_buffers); ++ } ++ shader_glsl_print_assignment(gen, &dst, "%s(%s)", op, args->buffer); ++ ++ vkd3d_string_buffer_release(&gen->string_buffers, args); ++ glsl_dst_cleanup(&dst, &gen->string_buffers); ++} ++ +static void shader_glsl_relop(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_instruction *ins, const char *scalar_op, const char *vector_op) +{ @@ -2417,14 +3745,293 @@ index d1f02ab568b..dd1c121d5a8 100644 + glsl_src_cleanup(&src[0], &gen->string_buffers); + glsl_dst_cleanup(&dst, &gen->string_buffers); +} ++ ++static void shader_glsl_cast(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins, ++ const char *scalar_constructor, const char *vector_constructor) ++{ ++ unsigned int component_count; ++ struct glsl_src src; ++ struct glsl_dst dst; ++ uint32_t mask; ++ ++ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); ++ glsl_src_init(&src, gen, &ins->src[0], mask); ++ ++ if ((component_count = vsir_write_mask_component_count(mask)) > 1) ++ shader_glsl_print_assignment(gen, &dst, "%s%u(%s)", ++ vector_constructor, component_count, src.str->buffer); ++ else ++ shader_glsl_print_assignment(gen, &dst, "%s(%s)", ++ scalar_constructor, src.str->buffer); ++ ++ glsl_src_cleanup(&src, &gen->string_buffers); ++ glsl_dst_cleanup(&dst, &gen->string_buffers); ++} ++ ++static void shader_glsl_if(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ const char *condition; ++ struct glsl_src src; ++ ++ glsl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); ++ ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ condition = ins->flags == VKD3D_SHADER_CONDITIONAL_OP_NZ ? "bool" : "!bool"; ++ vkd3d_string_buffer_printf(gen->buffer, "if (%s(%s))\n", condition, src.str->buffer); ++ ++ glsl_src_cleanup(&src, &gen->string_buffers); ++ ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "{\n"); ++ ++gen->indent; ++} ++ ++static void shader_glsl_else(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ unsigned int i = 4 * (gen->indent - 1); ++ ++ vkd3d_string_buffer_printf(gen->buffer, "%*s}\n%*selse\n%*s{\n", i, "", i, "", i, ""); ++} ++ ++static void shader_glsl_endif(struct vkd3d_glsl_generator *gen) ++{ ++ --gen->indent; ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "}\n"); ++} ++ ++static void shader_glsl_ld(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ const struct glsl_resource_type_info *resource_type_info; ++ unsigned int resource_id, resource_idx, resource_space; ++ const struct vkd3d_shader_descriptor_info1 *d; ++ enum vkd3d_shader_component_type sampled_type; ++ enum vkd3d_shader_resource_type resource_type; ++ struct vkd3d_string_buffer *fetch; ++ enum vkd3d_data_type data_type; ++ struct glsl_src coord, lod; ++ struct glsl_dst dst; ++ uint32_t coord_mask; ++ ++ if (vkd3d_shader_instruction_has_texel_offset(ins)) ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled texel fetch offset."); ++ ++ if (ins->src[1].reg.idx[0].rel_addr || ins->src[1].reg.idx[1].rel_addr) ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, ++ "Descriptor indexing is not supported."); ++ ++ resource_id = ins->src[1].reg.idx[0].offset; ++ resource_idx = ins->src[1].reg.idx[1].offset; ++ if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_id))) ++ { ++ resource_type = d->resource_type; ++ resource_space = d->register_space; ++ sampled_type = vkd3d_component_type_from_resource_data_type(d->resource_data_type); ++ data_type = vkd3d_data_type_from_component_type(sampled_type); ++ } ++ else ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Undeclared resource descriptor %u.", resource_id); ++ resource_space = 0; ++ resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; ++ data_type = VKD3D_DATA_FLOAT; ++ } ++ ++ if ((resource_type_info = shader_glsl_get_resource_type_info(resource_type))) ++ { ++ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); ++ } ++ else ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled resource type %#x.", resource_type); ++ coord_mask = vkd3d_write_mask_from_component_count(2); ++ } ++ ++ glsl_dst_init(&dst, gen, ins, &ins->dst[0]); ++ glsl_src_init(&coord, gen, &ins->src[0], coord_mask); ++ glsl_src_init(&lod, gen, &ins->src[0], VKD3DSP_WRITEMASK_3); ++ fetch = vkd3d_string_buffer_get(&gen->string_buffers); ++ ++ vkd3d_string_buffer_printf(fetch, "texelFetch("); ++ shader_glsl_print_combined_sampler_name(fetch, gen, resource_idx, ++ resource_space, VKD3D_SHADER_DUMMY_SAMPLER_INDEX, 0); ++ vkd3d_string_buffer_printf(fetch, ", %s", coord.str->buffer); ++ if (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) ++ vkd3d_string_buffer_printf(fetch, ", %s", lod.str->buffer); ++ vkd3d_string_buffer_printf(fetch, ")"); ++ shader_glsl_print_swizzle(fetch, ins->src[1].swizzle, ins->dst[0].write_mask); ++ ++ shader_glsl_print_assignment_ext(gen, &dst, data_type, "%s", fetch->buffer); ++ ++ vkd3d_string_buffer_release(&gen->string_buffers, fetch); ++ glsl_src_cleanup(&lod, &gen->string_buffers); ++ glsl_src_cleanup(&coord, &gen->string_buffers); ++ glsl_dst_cleanup(&dst, &gen->string_buffers); ++} ++ ++static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ const struct glsl_resource_type_info *resource_type_info; ++ unsigned int resource_id, resource_idx, resource_space; ++ unsigned int sampler_id, sampler_idx, sampler_space; ++ const struct vkd3d_shader_descriptor_info1 *d; ++ enum vkd3d_shader_component_type sampled_type; ++ enum vkd3d_shader_resource_type resource_type; ++ struct vkd3d_string_buffer *sample; ++ enum vkd3d_data_type data_type; ++ struct glsl_src coord; ++ struct glsl_dst dst; ++ uint32_t coord_mask; ++ ++ if (vkd3d_shader_instruction_has_texel_offset(ins)) ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled texel sample offset."); ++ ++ if (ins->src[1].reg.idx[0].rel_addr || ins->src[1].reg.idx[1].rel_addr ++ || ins->src[2].reg.idx[0].rel_addr || ins->src[2].reg.idx[1].rel_addr) ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, ++ "Descriptor indexing is not supported."); ++ ++ resource_id = ins->src[1].reg.idx[0].offset; ++ resource_idx = ins->src[1].reg.idx[1].offset; ++ if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_id))) ++ { ++ resource_type = d->resource_type; ++ resource_space = d->register_space; ++ sampled_type = vkd3d_component_type_from_resource_data_type(d->resource_data_type); ++ data_type = vkd3d_data_type_from_component_type(sampled_type); ++ } ++ else ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Undeclared resource descriptor %u.", resource_id); ++ resource_space = 0; ++ resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; ++ data_type = VKD3D_DATA_FLOAT; ++ } ++ ++ if ((resource_type_info = shader_glsl_get_resource_type_info(resource_type))) ++ { ++ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); ++ } ++ else ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled resource type %#x.", resource_type); ++ coord_mask = vkd3d_write_mask_from_component_count(2); ++ } ++ ++ sampler_id = ins->src[2].reg.idx[0].offset; ++ sampler_idx = ins->src[2].reg.idx[1].offset; ++ if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler_id))) ++ { ++ sampler_space = d->register_space; ++ } ++ else ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Undeclared sampler descriptor %u.", sampler_id); ++ sampler_space = 0; ++ } ++ ++ glsl_dst_init(&dst, gen, ins, &ins->dst[0]); ++ glsl_src_init(&coord, gen, &ins->src[0], coord_mask); ++ sample = vkd3d_string_buffer_get(&gen->string_buffers); ++ ++ vkd3d_string_buffer_printf(sample, "texture("); ++ shader_glsl_print_combined_sampler_name(sample, gen, resource_idx, resource_space, sampler_idx, sampler_space); ++ vkd3d_string_buffer_printf(sample, ", %s)", coord.str->buffer); ++ shader_glsl_print_swizzle(sample, ins->src[1].swizzle, ins->dst[0].write_mask); ++ ++ shader_glsl_print_assignment_ext(gen, &dst, data_type, "%s", sample->buffer); ++ ++ vkd3d_string_buffer_release(&gen->string_buffers, sample); ++ glsl_src_cleanup(&coord, &gen->string_buffers); ++ glsl_dst_cleanup(&dst, &gen->string_buffers); ++} ++ ++static void shader_glsl_unary_op(struct vkd3d_glsl_generator *gen, ++ const struct vkd3d_shader_instruction *ins, const char *op) ++{ ++ struct glsl_src src; ++ struct glsl_dst dst; ++ uint32_t mask; ++ ++ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); ++ glsl_src_init(&src, gen, &ins->src[0], mask); ++ ++ shader_glsl_print_assignment(gen, &dst, "%s%s", op, src.str->buffer); ++ ++ glsl_src_cleanup(&src, &gen->string_buffers); ++ glsl_dst_cleanup(&dst, &gen->string_buffers); ++} + static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) { struct glsl_src src; -@@ -198,16 +453,138 @@ static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d +@@ -198,16 +839,203 @@ static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d glsl_dst_cleanup(&dst, &gen->string_buffers); } ++static void shader_glsl_movc(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ unsigned int component_count; ++ struct glsl_src src[3]; ++ struct glsl_dst dst; ++ uint32_t mask; ++ ++ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); ++ glsl_src_init(&src[0], gen, &ins->src[0], mask); ++ glsl_src_init(&src[1], gen, &ins->src[1], mask); ++ glsl_src_init(&src[2], gen, &ins->src[2], mask); ++ ++ if ((component_count = vsir_write_mask_component_count(mask)) > 1) ++ shader_glsl_print_assignment(gen, &dst, "mix(%s, %s, bvec%u(%s))", ++ src[2].str->buffer, src[1].str->buffer, component_count, src[0].str->buffer); ++ else ++ shader_glsl_print_assignment(gen, &dst, "mix(%s, %s, bool(%s))", ++ src[2].str->buffer, src[1].str->buffer, src[0].str->buffer); ++ ++ glsl_src_cleanup(&src[2], &gen->string_buffers); ++ glsl_src_cleanup(&src[1], &gen->string_buffers); ++ glsl_src_cleanup(&src[0], &gen->string_buffers); ++ glsl_dst_cleanup(&dst, &gen->string_buffers); ++} ++ ++static void shader_glsl_mul_extended(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ struct glsl_src src[2]; ++ struct glsl_dst dst; ++ uint32_t mask; ++ ++ if (ins->dst[0].reg.type != VKD3DSPR_NULL) ++ { ++ /* FIXME: imulExtended()/umulExtended() from ARB_gpu_shader5/GLSL 4.00+. */ ++ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); ++ shader_glsl_print_assignment(gen, &dst, ""); ++ glsl_dst_cleanup(&dst, &gen->string_buffers); ++ ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled 64-bit integer multiplication."); ++ } ++ ++ if (ins->dst[1].reg.type != VKD3DSPR_NULL) ++ { ++ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[1]); ++ glsl_src_init(&src[0], gen, &ins->src[0], mask); ++ glsl_src_init(&src[1], gen, &ins->src[1], mask); ++ ++ shader_glsl_print_assignment(gen, &dst, "%s * %s", src[0].str->buffer, src[1].str->buffer); ++ ++ glsl_src_cleanup(&src[1], &gen->string_buffers); ++ glsl_src_cleanup(&src[0], &gen->string_buffers); ++ glsl_dst_cleanup(&dst, &gen->string_buffers); ++ } ++} ++ +static void shader_glsl_print_sysval_name(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, + enum vkd3d_shader_sysval_semantic sysval, unsigned int idx) +{ @@ -2448,6 +4055,15 @@ index d1f02ab568b..dd1c121d5a8 100644 + } + break; + ++ case VKD3D_SHADER_SV_IS_FRONT_FACE: ++ if (version->type != VKD3D_SHADER_TYPE_PIXEL) ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled SV_IS_FRONT_FACE in shader type #%x.", version->type); ++ vkd3d_string_buffer_printf(buffer, ++ "uintBitsToFloat(uvec4(gl_FrontFacing ? 0xffffffffu : 0u, 0u, 0u, 0u))"); ++ ++ break; ++ + case VKD3D_SHADER_SV_TARGET: + if (version->type != VKD3D_SHADER_TYPE_PIXEL) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, @@ -2564,7 +4180,7 @@ index d1f02ab568b..dd1c121d5a8 100644 shader_glsl_print_indent(gen->buffer, gen->indent); vkd3d_string_buffer_printf(gen->buffer, "return;\n"); } -@@ -220,14 +597,30 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, +@@ -220,30 +1048,582 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, switch (ins->opcode) { @@ -2575,27 +4191,131 @@ index d1f02ab568b..dd1c121d5a8 100644 + shader_glsl_binop(gen, ins, "&"); + break; case VKD3DSIH_DCL_INPUT: ++ case VKD3DSIH_DCL_INPUT_PS: ++ case VKD3DSIH_DCL_INPUT_PS_SIV: case VKD3DSIH_DCL_OUTPUT: case VKD3DSIH_DCL_OUTPUT_SIV: case VKD3DSIH_NOP: break; ++ case VKD3DSIH_DIV: ++ shader_glsl_binop(gen, ins, "/"); ++ break; ++ case VKD3DSIH_DP2: ++ shader_glsl_dot(gen, ins, vkd3d_write_mask_from_component_count(2)); ++ break; ++ case VKD3DSIH_DP3: ++ shader_glsl_dot(gen, ins, vkd3d_write_mask_from_component_count(3)); ++ break; ++ case VKD3DSIH_DP4: ++ shader_glsl_dot(gen, ins, VKD3DSP_WRITEMASK_ALL); ++ break; ++ case VKD3DSIH_ELSE: ++ shader_glsl_else(gen, ins); ++ break; ++ case VKD3DSIH_ENDIF: ++ shader_glsl_endif(gen); ++ break; ++ case VKD3DSIH_IEQ: ++ shader_glsl_relop(gen, ins, "==", "equal"); ++ break; ++ case VKD3DSIH_EXP: ++ shader_glsl_intrinsic(gen, ins, "exp2"); ++ break; ++ case VKD3DSIH_FRC: ++ shader_glsl_intrinsic(gen, ins, "fract"); ++ break; ++ case VKD3DSIH_FTOI: ++ shader_glsl_cast(gen, ins, "int", "ivec"); ++ break; ++ case VKD3DSIH_FTOU: ++ shader_glsl_cast(gen, ins, "uint", "uvec"); ++ break; ++ case VKD3DSIH_GEO: ++ case VKD3DSIH_IGE: ++ shader_glsl_relop(gen, ins, ">=", "greaterThanEqual"); ++ break; ++ case VKD3DSIH_IF: ++ shader_glsl_if(gen, ins); ++ break; ++ case VKD3DSIH_MAD: ++ shader_glsl_intrinsic(gen, ins, "fma"); ++ break; ++ case VKD3DSIH_ILT: ++ case VKD3DSIH_LTO: ++ shader_glsl_relop(gen, ins, "<", "lessThan"); ++ break; ++ case VKD3DSIH_IMUL: ++ shader_glsl_mul_extended(gen, ins); ++ break; ++ case VKD3DSIH_ISHL: ++ shader_glsl_binop(gen, ins, "<<"); ++ break; ++ case VKD3DSIH_ISHR: ++ case VKD3DSIH_USHR: ++ shader_glsl_binop(gen, ins, ">>"); ++ break; ++ case VKD3DSIH_MAX: ++ shader_glsl_intrinsic(gen, ins, "max"); ++ break; ++ case VKD3DSIH_MIN: ++ shader_glsl_intrinsic(gen, ins, "min"); ++ break; + case VKD3DSIH_INE: + case VKD3DSIH_NEU: + shader_glsl_relop(gen, ins, "!=", "notEqual"); ++ break; ++ case VKD3DSIH_ITOF: ++ case VKD3DSIH_UTOF: ++ shader_glsl_cast(gen, ins, "float", "vec"); ++ break; ++ case VKD3DSIH_LD: ++ shader_glsl_ld(gen, ins); ++ break; ++ case VKD3DSIH_LOG: ++ shader_glsl_intrinsic(gen, ins, "log2"); + break; case VKD3DSIH_MOV: shader_glsl_mov(gen, ins); break; ++ case VKD3DSIH_MOVC: ++ shader_glsl_movc(gen, ins); ++ break; + case VKD3DSIH_MUL: + shader_glsl_binop(gen, ins, "*"); + break; ++ case VKD3DSIH_NOT: ++ shader_glsl_unary_op(gen, ins, "~"); ++ break; + case VKD3DSIH_OR: + shader_glsl_binop(gen, ins, "|"); + break; case VKD3DSIH_RET: shader_glsl_ret(gen, ins); break; -@@ -237,13 +630,290 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, ++ case VKD3DSIH_ROUND_NE: ++ shader_glsl_intrinsic(gen, ins, "roundEven"); ++ break; ++ case VKD3DSIH_ROUND_NI: ++ shader_glsl_intrinsic(gen, ins, "floor"); ++ break; ++ case VKD3DSIH_ROUND_PI: ++ shader_glsl_intrinsic(gen, ins, "ceil"); ++ break; ++ case VKD3DSIH_ROUND_Z: ++ shader_glsl_intrinsic(gen, ins, "trunc"); ++ break; ++ case VKD3DSIH_RSQ: ++ shader_glsl_intrinsic(gen, ins, "inversesqrt"); ++ break; ++ case VKD3DSIH_SAMPLE: ++ shader_glsl_sample(gen, ins); ++ break; ++ case VKD3DSIH_SQRT: ++ shader_glsl_intrinsic(gen, ins, "sqrt"); ++ break; + default: + shader_glsl_unhandled(gen, ins); + break; } } @@ -2717,8 +4437,156 @@ index d1f02ab568b..dd1c121d5a8 100644 + binding->binding, prefix, cbv->register_id, prefix, cbv->register_id, size); +} + ++static bool shader_glsl_get_combined_sampler_binding(const struct vkd3d_glsl_generator *gen, ++ const struct vkd3d_shader_combined_resource_sampler_info *crs, ++ enum vkd3d_shader_resource_type resource_type, unsigned int *binding_idx) ++{ ++ const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; ++ const struct vkd3d_shader_combined_resource_sampler *s; ++ enum vkd3d_shader_binding_flag resource_type_flag; ++ unsigned int i; ++ ++ if (!interface_info) ++ return false; ++ ++ 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->combined_sampler_count; ++i) ++ { ++ s = &interface_info->combined_samplers[i]; ++ ++ if (s->resource_space != crs->resource_space) ++ continue; ++ if (s->resource_index != crs->resource_index) ++ continue; ++ if (crs->sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX) ++ { ++ if (s->sampler_space != crs->sampler_space) ++ continue; ++ if (s->sampler_index != crs->sampler_index) ++ continue; ++ } ++ if (!shader_glsl_check_shader_visibility(gen, s->shader_visibility)) ++ continue; ++ if (!(s->flags & resource_type_flag)) ++ continue; ++ *binding_idx = i; ++ return true; ++ } ++ ++ return false; ++} ++ ++static void shader_glsl_generate_sampler_declaration(struct vkd3d_glsl_generator *gen, ++ const struct vkd3d_shader_combined_resource_sampler_info *crs) ++{ ++ const struct vkd3d_shader_descriptor_info1 *sampler, *srv; ++ const struct glsl_resource_type_info *resource_type_info; ++ const struct vkd3d_shader_descriptor_binding *binding; ++ struct vkd3d_string_buffer *buffer = gen->buffer; ++ enum vkd3d_shader_component_type component_type; ++ const char *sampler_type, *sampler_type_prefix; ++ unsigned int binding_idx; ++ bool shadow = false; ++ ++ if (crs->sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX) ++ { ++ if (!(sampler = shader_glsl_get_descriptor(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, ++ crs->sampler_index, crs->sampler_space))) ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: No descriptor found for sampler %u, space %u.", ++ crs->sampler_index, crs->sampler_space); ++ return; ++ } ++ shadow = sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE; ++ } ++ ++ if (!(srv = shader_glsl_get_descriptor(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, ++ crs->resource_index, crs->resource_space))) ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: No descriptor found for resource %u, space %u.", ++ crs->resource_index, crs->resource_space); ++ return; ++ } ++ ++ if ((resource_type_info = shader_glsl_get_resource_type_info(srv->resource_type))) ++ { ++ sampler_type = resource_type_info->sampler_type; ++ if (shadow && !resource_type_info->shadow) ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, ++ "Comparison samplers are not supported with resource type %#x.", srv->resource_type); ++ } ++ else ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled resource type %#x for combined resource/sampler " ++ "for resource %u, space %u and sampler %u, space %u.", srv->resource_type, ++ crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); ++ sampler_type = ""; ++ } ++ ++ switch ((component_type = vkd3d_component_type_from_resource_data_type(srv->resource_data_type))) ++ { ++ case VKD3D_SHADER_COMPONENT_UINT: ++ sampler_type_prefix = "u"; ++ break; ++ case VKD3D_SHADER_COMPONENT_INT: ++ sampler_type_prefix = "i"; ++ break; ++ case VKD3D_SHADER_COMPONENT_FLOAT: ++ sampler_type_prefix = ""; ++ break; ++ default: ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled component type %#x for combined resource/sampler " ++ "for resource %u, space %u and sampler %u, space %u.", component_type, ++ crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); ++ sampler_type_prefix = ""; ++ break; ++ } ++ ++ if (!shader_glsl_get_combined_sampler_binding(gen, crs, srv->resource_type, &binding_idx)) ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, ++ "No descriptor binding specified for combined resource/sampler " ++ "for resource %u, space %u and sampler %u, space %u.", ++ crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); ++ return; ++ } ++ ++ binding = &gen->interface_info->combined_samplers[binding_idx].binding; ++ ++ if (binding->set != 0) ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, ++ "Unsupported binding set %u specified for combined resource/sampler " ++ "for resource %u, space %u and sampler %u, space %u.", binding->set, ++ crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); ++ return; ++ } ++ ++ if (binding->count != 1) ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, ++ "Unsupported binding count %u specified for combined resource/sampler " ++ "for resource %u, space %u and sampler %u, space %u.", binding->count, ++ crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); ++ return; ++ } ++ ++ vkd3d_string_buffer_printf(buffer, "layout(binding = %u) uniform %s%s%s ", ++ binding->binding, sampler_type_prefix, sampler_type, shadow ? "Shadow" : ""); ++ shader_glsl_print_combined_sampler_name(buffer, gen, crs->resource_index, ++ crs->resource_space, crs->sampler_index, crs->sampler_space); ++ vkd3d_string_buffer_printf(buffer, ";\n"); ++} ++ +static void shader_glsl_generate_descriptor_declarations(struct vkd3d_glsl_generator *gen) +{ ++ const struct vkd3d_shader_scan_combined_resource_sampler_info *sampler_info = gen->combined_sampler_info; + const struct vkd3d_shader_scan_descriptor_info1 *info = gen->descriptor_info; + const struct vkd3d_shader_descriptor_info1 *descriptor; + unsigned int i; @@ -2729,6 +4597,11 @@ index d1f02ab568b..dd1c121d5a8 100644 + + switch (descriptor->type) + { ++ case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV: ++ case VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER: ++ /* GLSL uses combined resource/sampler descriptors.*/ ++ break; ++ + case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV: + shader_glsl_generate_cbv_declaration(gen, descriptor); + break; @@ -2740,6 +4613,10 @@ index d1f02ab568b..dd1c121d5a8 100644 + break; + } + } ++ for (i = 0; i < sampler_info->combined_sampler_count; ++i) ++ { ++ shader_glsl_generate_sampler_declaration(gen, &sampler_info->combined_samplers[i]); ++ } + if (info->descriptor_count) + vkd3d_string_buffer_printf(gen->buffer, "\n"); +} @@ -2887,7 +4764,7 @@ index d1f02ab568b..dd1c121d5a8 100644 } static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *gen, struct vkd3d_shader_code *out) -@@ -264,6 +934,7 @@ static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *gen, struc +@@ -264,6 +1644,7 @@ static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *gen, struc vkd3d_string_buffer_printf(buffer, "void main()\n{\n"); ++gen->indent; @@ -2895,7 +4772,7 @@ index d1f02ab568b..dd1c121d5a8 100644 for (i = 0; i < instructions->count; ++i) { vkd3d_glsl_handle_instruction(gen, &instructions->elements[i]); -@@ -294,27 +965,73 @@ static void vkd3d_glsl_generator_cleanup(struct vkd3d_glsl_generator *gen) +@@ -294,27 +1675,77 @@ static void vkd3d_glsl_generator_cleanup(struct vkd3d_glsl_generator *gen) vkd3d_string_buffer_cache_cleanup(&gen->string_buffers); } @@ -2930,6 +4807,7 @@ index d1f02ab568b..dd1c121d5a8 100644 - struct vsir_program *program, struct vkd3d_shader_message_context *message_context) + struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, + const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, ++ const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info, + struct vkd3d_shader_message_context *message_context) { + enum vkd3d_shader_type type = program->shader_version.type; @@ -2953,12 +4831,14 @@ index d1f02ab568b..dd1c121d5a8 100644 + gen->interface_info = vkd3d_find_struct(compile_info->next, INTERFACE_INFO); + gen->offset_info = vkd3d_find_struct(compile_info->next, DESCRIPTOR_OFFSET_INFO); + gen->descriptor_info = descriptor_info; ++ gen->combined_sampler_info = combined_sampler_info; } int glsl_compile(struct vsir_program *program, uint64_t config_flags, - const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, - struct vkd3d_shader_message_context *message_context) + const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, ++ const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info, + const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) { @@ -2970,15 +4850,16 @@ index d1f02ab568b..dd1c121d5a8 100644 return ret; - vkd3d_glsl_generator_init(&generator, program, message_context); -+ vkd3d_glsl_generator_init(&generator, program, compile_info, descriptor_info, message_context); ++ vkd3d_glsl_generator_init(&generator, program, compile_info, ++ descriptor_info, combined_sampler_info, message_context); ret = vkd3d_glsl_generator_generate(&generator, out); vkd3d_glsl_generator_cleanup(&generator); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index bd5baacd83d..6323260eab7 100644 +index bd5baacd83d..9ace1930c1b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -254,6 +254,45 @@ bool hlsl_type_is_resource(const struct hlsl_type *type) +@@ -254,6 +254,46 @@ bool hlsl_type_is_resource(const struct hlsl_type *type) } } @@ -3004,6 +4885,7 @@ index bd5baacd83d..6323260eab7 100644 + case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: ++ case HLSL_CLASS_ERROR: + case HLSL_CLASS_PASS: + case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: @@ -3024,7 +4906,31 @@ index bd5baacd83d..6323260eab7 100644 /* Only intended to be used for derefs (after copies have been lowered to components or vectors) or * resources, since for both their data types span across a single regset. */ static enum hlsl_regset type_get_regset(const struct hlsl_type *type) -@@ -930,6 +969,7 @@ static const char * get_case_insensitive_typename(const char *name) +@@ -379,6 +419,7 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type + case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: ++ case HLSL_CLASS_ERROR: + case HLSL_CLASS_PASS: + case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_RASTERIZER_STATE: +@@ -455,6 +496,7 @@ static bool type_is_single_component(const struct hlsl_type *type) + { + case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: ++ case HLSL_CLASS_ERROR: + case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_SCALAR: + case HLSL_CLASS_SAMPLER: +@@ -631,6 +673,7 @@ unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_ty + break; + + case HLSL_CLASS_EFFECT_GROUP: ++ case HLSL_CLASS_ERROR: + case HLSL_CLASS_PASS: + case HLSL_CLASS_TECHNIQUE: + case HLSL_CLASS_VOID: +@@ -930,6 +973,7 @@ static const char * get_case_insensitive_typename(const char *name) { "dword", "float", @@ -3032,7 +4938,40 @@ index bd5baacd83d..6323260eab7 100644 "matrix", "pixelshader", "texture", -@@ -1792,6 +1832,65 @@ struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned +@@ -1021,6 +1065,7 @@ unsigned int hlsl_type_component_count(const struct hlsl_type *type) + + case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: ++ case HLSL_CLASS_ERROR: + case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_RASTERIZER_STATE: + case HLSL_CLASS_RENDER_TARGET_VIEW: +@@ -1115,6 +1160,7 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 + case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: ++ case HLSL_CLASS_ERROR: + case HLSL_CLASS_PASS: + case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_RASTERIZER_STATE: +@@ -1589,6 +1635,16 @@ struct hlsl_ir_node *hlsl_new_ternary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_ex + return hlsl_new_expr(ctx, op, operands, arg1->data_type, &arg1->loc); + } + ++static struct hlsl_ir_node *hlsl_new_error_expr(struct hlsl_ctx *ctx) ++{ ++ static const struct vkd3d_shader_location loc = {.source_name = ""}; ++ struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; ++ ++ /* Use a dummy location; we should never report any messages related to ++ * this expression. */ ++ return hlsl_new_expr(ctx, HLSL_OP0_ERROR, operands, ctx->builtin_types.error, &loc); ++} ++ + struct hlsl_ir_node *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *condition, + struct hlsl_block *then_block, struct hlsl_block *else_block, const struct vkd3d_shader_location *loc) + { +@@ -1792,6 +1848,118 @@ struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned return &swizzle->node; } @@ -3094,11 +5033,64 @@ index bd5baacd83d..6323260eab7 100644 + + return &compile->node; +} ++ ++bool hlsl_state_block_add_entry(struct hlsl_state_block *state_block, ++ struct hlsl_state_block_entry *entry) ++{ ++ if (!vkd3d_array_reserve((void **)&state_block->entries, ++ &state_block->capacity, state_block->count + 1, ++ sizeof(*state_block->entries))) ++ return false; ++ ++ state_block->entries[state_block->count++] = entry; ++ return true; ++} ++ ++struct hlsl_ir_node *hlsl_new_sampler_state(struct hlsl_ctx *ctx, ++ const struct hlsl_state_block *state_block, struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_ir_sampler_state *sampler_state; ++ struct hlsl_type *type = ctx->builtin_types.sampler[HLSL_SAMPLER_DIM_GENERIC]; ++ ++ if (!(sampler_state = hlsl_alloc(ctx, sizeof(*sampler_state)))) ++ return NULL; ++ ++ init_node(&sampler_state->node, HLSL_IR_SAMPLER_STATE, type, loc); ++ ++ if (!(sampler_state->state_block = hlsl_alloc(ctx, sizeof(*sampler_state->state_block)))) ++ { ++ vkd3d_free(sampler_state); ++ return NULL; ++ } ++ ++ if (state_block) ++ { ++ for (unsigned int i = 0; i < state_block->count; ++i) ++ { ++ const struct hlsl_state_block_entry *src = state_block->entries[i]; ++ struct hlsl_state_block_entry *entry; ++ ++ if (!(entry = clone_stateblock_entry(ctx, src, src->name, src->lhs_has_index, src->lhs_index, false, 0))) ++ { ++ hlsl_free_instr(&sampler_state->node); ++ return NULL; ++ } ++ ++ if (!hlsl_state_block_add_entry(sampler_state->state_block, entry)) ++ { ++ hlsl_free_instr(&sampler_state->node); ++ return NULL; ++ } ++ } ++ } ++ ++ return &sampler_state->node; ++} + struct hlsl_ir_node *hlsl_new_stateblock_constant(struct hlsl_ctx *ctx, const char *name, struct vkd3d_shader_location *loc) { -@@ -2142,6 +2241,44 @@ static struct hlsl_ir_node *clone_index(struct hlsl_ctx *ctx, struct clone_instr +@@ -2142,6 +2310,51 @@ static struct hlsl_ir_node *clone_index(struct hlsl_ctx *ctx, struct clone_instr return dst; } @@ -3139,30 +5131,102 @@ index bd5baacd83d..6323260eab7 100644 + vkd3d_free(args); + return node; +} ++ ++static struct hlsl_ir_node *clone_sampler_state(struct hlsl_ctx *ctx, ++ struct clone_instr_map *map, struct hlsl_ir_sampler_state *sampler_state) ++{ ++ return hlsl_new_sampler_state(ctx, sampler_state->state_block, ++ &sampler_state->node.loc); ++} + static struct hlsl_ir_node *clone_stateblock_constant(struct hlsl_ctx *ctx, struct clone_instr_map *map, struct hlsl_ir_stateblock_constant *constant) { -@@ -2284,6 +2421,9 @@ static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx, +@@ -2149,8 +2362,8 @@ static struct hlsl_ir_node *clone_stateblock_constant(struct hlsl_ctx *ctx, + } + + struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx, +- struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index, +- unsigned int lhs_index, unsigned int arg_index) ++ const struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index, ++ unsigned int lhs_index, bool single_arg, unsigned int arg_index) + { + struct hlsl_state_block_entry *entry; + struct clone_instr_map map = { 0 }; +@@ -2166,7 +2379,11 @@ struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx, + return NULL; + } + +- entry->args_count = 1; ++ if (single_arg) ++ entry->args_count = 1; ++ else ++ entry->args_count = src->args_count; ++ + if (!(entry->args = hlsl_alloc(ctx, sizeof(*entry->args) * entry->args_count))) + { + hlsl_free_state_block_entry(entry); +@@ -2179,7 +2396,16 @@ struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx, + hlsl_free_state_block_entry(entry); + return NULL; + } +- clone_src(&map, entry->args, &src->args[arg_index]); ++ ++ if (single_arg) ++ { ++ clone_src(&map, entry->args, &src->args[arg_index]); ++ } ++ else ++ { ++ for (unsigned int i = 0; i < src->args_count; ++i) ++ clone_src(&map, &entry->args[i], &src->args[i]); ++ } + vkd3d_free(map.instrs); + + return entry; +@@ -2284,6 +2510,12 @@ static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx, case HLSL_IR_SWIZZLE: return clone_swizzle(ctx, map, hlsl_ir_swizzle(instr)); + case HLSL_IR_COMPILE: + return clone_compile(ctx, map, hlsl_ir_compile(instr)); ++ ++ case HLSL_IR_SAMPLER_STATE: ++ return clone_sampler_state(ctx, map, hlsl_ir_sampler_state(instr)); + case HLSL_IR_STATEBLOCK_CONSTANT: return clone_stateblock_constant(ctx, map, hlsl_ir_stateblock_constant(instr)); } -@@ -2698,6 +2838,8 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type) +@@ -2570,6 +2802,10 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru + } + return string; + ++ case HLSL_CLASS_ERROR: ++ vkd3d_string_buffer_printf(string, ""); ++ return string; ++ + case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: +@@ -2698,6 +2934,9 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type) [HLSL_IR_STORE ] = "HLSL_IR_STORE", [HLSL_IR_SWITCH ] = "HLSL_IR_SWITCH", [HLSL_IR_SWIZZLE ] = "HLSL_IR_SWIZZLE", + + [HLSL_IR_COMPILE] = "HLSL_IR_COMPILE", ++ [HLSL_IR_SAMPLER_STATE] = "HLSL_IR_SAMPLER_STATE", [HLSL_IR_STATEBLOCK_CONSTANT] = "HLSL_IR_STATEBLOCK_CONSTANT", }; -@@ -3146,6 +3288,34 @@ static void dump_ir_index(struct vkd3d_string_buffer *buffer, const struct hlsl_ +@@ -2907,6 +3146,7 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op) + { + static const char *const op_names[] = + { ++ [HLSL_OP0_ERROR] = "error", + [HLSL_OP0_VOID] = "void", + [HLSL_OP0_RASTERIZER_SAMPLE_COUNT] = "GetRenderTargetSampleCount", + +@@ -3146,6 +3386,40 @@ static void dump_ir_index(struct vkd3d_string_buffer *buffer, const struct hlsl_ vkd3d_string_buffer_printf(buffer, "]"); } @@ -3193,22 +5257,32 @@ index bd5baacd83d..6323260eab7 100644 + } + vkd3d_string_buffer_printf(buffer, ")"); +} ++ ++static void dump_ir_sampler_state(struct vkd3d_string_buffer *buffer, ++ const struct hlsl_ir_sampler_state *sampler_state) ++{ ++ vkd3d_string_buffer_printf(buffer, "sampler_state {...}"); ++} + static void dump_ir_stateblock_constant(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_stateblock_constant *constant) { -@@ -3245,6 +3415,10 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, +@@ -3245,6 +3519,14 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, dump_ir_swizzle(buffer, hlsl_ir_swizzle(instr)); break; + case HLSL_IR_COMPILE: + dump_ir_compile(ctx, buffer, hlsl_ir_compile(instr)); + break; ++ ++ case HLSL_IR_SAMPLER_STATE: ++ dump_ir_sampler_state(buffer, hlsl_ir_sampler_state(instr)); ++ break; + case HLSL_IR_STATEBLOCK_CONSTANT: dump_ir_stateblock_constant(buffer, hlsl_ir_stateblock_constant(instr)); break; -@@ -3308,8 +3482,8 @@ void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new) +@@ -3308,8 +3590,8 @@ void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new) { struct hlsl_src *src, *next; @@ -3219,7 +5293,7 @@ index bd5baacd83d..6323260eab7 100644 LIST_FOR_EACH_ENTRY_SAFE(src, next, &old->uses, struct hlsl_src, entry) { -@@ -3459,6 +3633,17 @@ static void free_ir_index(struct hlsl_ir_index *index) +@@ -3459,6 +3741,24 @@ static void free_ir_index(struct hlsl_ir_index *index) vkd3d_free(index); } @@ -3233,25 +5307,75 @@ index bd5baacd83d..6323260eab7 100644 + hlsl_block_cleanup(&compile->instrs); + vkd3d_free(compile); +} ++ ++static void free_ir_sampler_state(struct hlsl_ir_sampler_state *sampler_state) ++{ ++ if (sampler_state->state_block) ++ hlsl_free_state_block(sampler_state->state_block); ++ vkd3d_free(sampler_state); ++} + static void free_ir_stateblock_constant(struct hlsl_ir_stateblock_constant *constant) { vkd3d_free(constant->name); -@@ -3527,6 +3712,10 @@ void hlsl_free_instr(struct hlsl_ir_node *node) +@@ -3527,6 +3827,14 @@ void hlsl_free_instr(struct hlsl_ir_node *node) free_ir_switch(hlsl_ir_switch(node)); break; + case HLSL_IR_COMPILE: + free_ir_compile(hlsl_ir_compile(node)); + break; ++ ++ case HLSL_IR_SAMPLER_STATE: ++ free_ir_sampler_state(hlsl_ir_sampler_state(node)); ++ break; + case HLSL_IR_STATEBLOCK_CONSTANT: free_ir_stateblock_constant(hlsl_ir_stateblock_constant(node)); break; -@@ -4078,6 +4267,11 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil +@@ -3801,12 +4109,12 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) + + static const char * const names[] = + { +- "float", +- "half", +- "double", +- "int", +- "uint", +- "bool", ++ [HLSL_TYPE_FLOAT] = "float", ++ [HLSL_TYPE_HALF] = "half", ++ [HLSL_TYPE_DOUBLE] = "double", ++ [HLSL_TYPE_INT] = "int", ++ [HLSL_TYPE_UINT] = "uint", ++ [HLSL_TYPE_BOOL] = "bool", + }; + + static const char *const variants_float[] = {"min10float", "min16float"}; +@@ -3957,6 +4265,7 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) + ctx->builtin_types.Void = hlsl_new_simple_type(ctx, "void", HLSL_CLASS_VOID); + ctx->builtin_types.null = hlsl_new_type(ctx, "NULL", HLSL_CLASS_NULL, HLSL_TYPE_UINT, 1, 1); + ctx->builtin_types.string = hlsl_new_simple_type(ctx, "string", HLSL_CLASS_STRING); ++ ctx->builtin_types.error = hlsl_new_simple_type(ctx, "", HLSL_CLASS_ERROR); + hlsl_scope_add_type(ctx->globals, ctx->builtin_types.string); + hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "DepthStencilView", HLSL_CLASS_DEPTH_STENCIL_VIEW)); + hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "DepthStencilState", HLSL_CLASS_DEPTH_STENCIL_STATE)); +@@ -4059,6 +4368,7 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil + + case VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY: + ctx->semantic_compat_mapping = option->value & VKD3D_SHADER_COMPILE_OPTION_BACKCOMPAT_MAP_SEMANTIC_NAMES; ++ ctx->double_as_float_alias = option->value & VKD3D_SHADER_COMPILE_OPTION_DOUBLE_AS_FLOAT_ALIAS; + break; + + case VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT: +@@ -4078,6 +4388,15 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil } } ++ if (!(ctx->error_instr = hlsl_new_error_expr(ctx))) ++ return false; ++ hlsl_block_add_instr(&ctx->static_initializers, ctx->error_instr); ++ + ctx->domain = VKD3D_TESSELLATOR_DOMAIN_INVALID; + ctx->output_control_point_count = UINT_MAX; + ctx->output_primitive = 0; @@ -3260,8 +5384,26 @@ index bd5baacd83d..6323260eab7 100644 return true; } +@@ -4089,8 +4408,6 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) + struct hlsl_type *type, *next_type; + unsigned int i; + +- hlsl_block_cleanup(&ctx->static_initializers); +- + for (i = 0; i < ctx->source_files_count; ++i) + vkd3d_free((void *)ctx->source_files[i]); + vkd3d_free(ctx->source_files); +@@ -4098,6 +4415,8 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) + + rb_destroy(&ctx->functions, free_function_rb, NULL); + ++ hlsl_block_cleanup(&ctx->static_initializers); ++ + /* State blocks must be free before the variables, because they contain instructions that may + * refer to them. */ + LIST_FOR_EACH_ENTRY_SAFE(scope, next_scope, &ctx->scopes, struct hlsl_scope, entry) diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index 22e25b23988..20a96692a48 100644 +index 22e25b23988..4082b14fe04 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -22,7 +22,6 @@ @@ -3287,16 +5429,35 @@ index 22e25b23988..20a96692a48 100644 enum hlsl_type_class { HLSL_CLASS_SCALAR, -@@ -316,6 +323,8 @@ enum hlsl_ir_node_type +@@ -99,6 +106,7 @@ enum hlsl_type_class + HLSL_CLASS_BLEND_STATE, + HLSL_CLASS_VOID, + HLSL_CLASS_NULL, ++ HLSL_CLASS_ERROR, + }; + + enum hlsl_base_type +@@ -316,6 +324,9 @@ enum hlsl_ir_node_type HLSL_IR_STORE, HLSL_IR_SWIZZLE, HLSL_IR_SWITCH, + + HLSL_IR_COMPILE, ++ HLSL_IR_SAMPLER_STATE, HLSL_IR_STATEBLOCK_CONSTANT, }; -@@ -591,6 +600,8 @@ struct hlsl_ir_function_decl +@@ -352,6 +363,9 @@ struct hlsl_block + { + /* List containing instruction nodes; linked by the hlsl_ir_node.entry fields. */ + struct list instrs; ++ /* Instruction representing the "value" of this block, if applicable. ++ * This may point to an instruction outside of this block! */ ++ struct hlsl_ir_node *value; + }; + + /* A reference to an instruction node (struct hlsl_ir_node), usable as a field in other structs. +@@ -591,6 +605,8 @@ struct hlsl_ir_function_decl unsigned int attr_count; const struct hlsl_attribute *const *attrs; @@ -3305,7 +5466,15 @@ index 22e25b23988..20a96692a48 100644 /* Synthetic boolean variable marking whether a return statement has been * executed. Needed to deal with return statements in non-uniform control * flow, since some backends can't handle them. */ -@@ -703,7 +714,7 @@ enum hlsl_ir_expr_op +@@ -646,6 +662,7 @@ struct hlsl_ir_switch + + enum hlsl_ir_expr_op + { ++ HLSL_OP0_ERROR, + HLSL_OP0_VOID, + HLSL_OP0_RASTERIZER_SAMPLE_COUNT, + +@@ -703,7 +720,7 @@ enum hlsl_ir_expr_op HLSL_OP2_SLT, /* DP2ADD(a, b, c) computes the scalar product of a.xy and b.xy, @@ -3314,7 +5483,7 @@ index 22e25b23988..20a96692a48 100644 HLSL_OP3_DP2ADD, /* TERNARY(a, b, c) returns 'b' if 'a' is true and 'c' otherwise. 'a' must always be boolean. * CMP(a, b, c) returns 'b' if 'a' >= 0, and 'c' otherwise. It's used only for SM1-SM3 targets. */ -@@ -854,6 +865,35 @@ struct hlsl_ir_string_constant +@@ -854,6 +871,43 @@ struct hlsl_ir_string_constant char *string; }; @@ -3346,11 +5515,32 @@ index 22e25b23988..20a96692a48 100644 + struct hlsl_src *args; + unsigned int args_count; +}; ++ ++/* Represents a state block initialized with the "sampler_state" keyword. */ ++struct hlsl_ir_sampler_state ++{ ++ struct hlsl_ir_node node; ++ ++ struct hlsl_state_block *state_block; ++}; + /* Stateblock constants are undeclared values found on state blocks or technique passes descriptions, * that do not concern regular pixel, vertex, or compute shaders, except for parsing. */ struct hlsl_ir_stateblock_constant -@@ -1016,6 +1056,7 @@ struct hlsl_ctx +@@ -1003,8 +1057,12 @@ struct hlsl_ctx + struct hlsl_type *string; + struct hlsl_type *Void; + struct hlsl_type *null; ++ struct hlsl_type *error; + } builtin_types; + ++ /* Pre-allocated "error" expression. */ ++ struct hlsl_ir_node *error_instr; ++ + /* List of the instruction nodes for initializing static variables. */ + struct hlsl_block static_initializers; + +@@ -1016,6 +1074,7 @@ struct hlsl_ctx { uint32_t index; struct hlsl_vec4 value; @@ -3358,7 +5548,7 @@ index 22e25b23988..20a96692a48 100644 } *regs; size_t count, size; } constant_defs; -@@ -1029,6 +1070,12 @@ struct hlsl_ctx +@@ -1029,6 +1088,12 @@ struct hlsl_ctx * compute shader profiles. It is set using the numthreads() attribute in the entry point. */ uint32_t thread_count[3]; @@ -3371,7 +5561,15 @@ index 22e25b23988..20a96692a48 100644 /* In some cases we generate opcodes by parsing an HLSL function and then * invoking it. If not NULL, this field is the name of the function that we * are currently parsing, "mangled" with an internal prefix to avoid -@@ -1149,6 +1196,12 @@ static inline struct hlsl_ir_switch *hlsl_ir_switch(const struct hlsl_ir_node *n +@@ -1044,6 +1109,7 @@ struct hlsl_ctx + bool child_effect; + bool include_empty_buffers; + bool warn_implicit_truncation; ++ bool double_as_float_alias; + }; + + static inline bool hlsl_version_ge(const struct hlsl_ctx *ctx, unsigned int major, unsigned int minor) +@@ -1149,6 +1215,18 @@ static inline struct hlsl_ir_switch *hlsl_ir_switch(const struct hlsl_ir_node *n return CONTAINING_RECORD(node, struct hlsl_ir_switch, node); } @@ -3380,11 +5578,55 @@ index 22e25b23988..20a96692a48 100644 + VKD3D_ASSERT(node->type == HLSL_IR_COMPILE); + return CONTAINING_RECORD(node, struct hlsl_ir_compile, node); +} ++ ++static inline struct hlsl_ir_sampler_state *hlsl_ir_sampler_state(const struct hlsl_ir_node *node) ++{ ++ VKD3D_ASSERT(node->type == HLSL_IR_SAMPLER_STATE); ++ return CONTAINING_RECORD(node, struct hlsl_ir_sampler_state, node); ++}; + static inline struct hlsl_ir_stateblock_constant *hlsl_ir_stateblock_constant(const struct hlsl_ir_node *node) { VKD3D_ASSERT(node->type == HLSL_IR_STATEBLOCK_CONSTANT); -@@ -1428,6 +1481,9 @@ bool hlsl_index_is_noncontiguous(struct hlsl_ir_index *index); +@@ -1158,16 +1236,19 @@ static inline struct hlsl_ir_stateblock_constant *hlsl_ir_stateblock_constant(co + static inline void hlsl_block_init(struct hlsl_block *block) + { + list_init(&block->instrs); ++ block->value = NULL; + } + + static inline void hlsl_block_add_instr(struct hlsl_block *block, struct hlsl_ir_node *instr) + { + list_add_tail(&block->instrs, &instr->entry); ++ block->value = (instr->data_type ? instr : NULL); + } + + static inline void hlsl_block_add_block(struct hlsl_block *block, struct hlsl_block *add) + { + list_move_tail(&block->instrs, &add->instrs); ++ block->value = add->value; + } + + static inline void hlsl_src_from_node(struct hlsl_src *src, struct hlsl_ir_node *node) +@@ -1330,12 +1411,15 @@ bool hlsl_clone_block(struct hlsl_ctx *ctx, struct hlsl_block *dst_block, const + void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func); + void hlsl_dump_var_default_values(const struct hlsl_ir_var *var); + ++bool hlsl_state_block_add_entry(struct hlsl_state_block *state_block, ++ struct hlsl_state_block_entry *entry); + bool hlsl_validate_state_block_entry(struct hlsl_ctx *ctx, struct hlsl_state_block_entry *entry, + const struct vkd3d_shader_location *loc); + struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx, +- struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index, +- unsigned int lhs_index, unsigned int arg_index); ++ const struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index, ++ unsigned int lhs_index, bool single_arg, unsigned int arg_index); + ++void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body); + void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body); + int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, + enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out); +@@ -1428,6 +1512,9 @@ bool hlsl_index_is_noncontiguous(struct hlsl_ir_index *index); bool hlsl_index_is_resource_access(struct hlsl_ir_index *index); bool hlsl_index_chain_has_resource_access(struct hlsl_ir_index *index); @@ -3394,7 +5636,16 @@ index 22e25b23988..20a96692a48 100644 struct hlsl_ir_node *hlsl_new_index(struct hlsl_ctx *ctx, struct hlsl_ir_node *val, struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_new_loop(struct hlsl_ctx *ctx, -@@ -1493,6 +1549,7 @@ unsigned int hlsl_type_minor_size(const struct hlsl_type *type); +@@ -1440,6 +1527,8 @@ struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name, + struct hlsl_struct_field *fields, size_t field_count); + struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int components, + struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc); ++struct hlsl_ir_node *hlsl_new_sampler_state(struct hlsl_ctx *ctx, ++ const struct hlsl_state_block *state_block, struct vkd3d_shader_location *loc); + struct hlsl_ir_node *hlsl_new_stateblock_constant(struct hlsl_ctx *ctx, const char *name, + struct vkd3d_shader_location *loc); + struct hlsl_ir_node *hlsl_new_string_constant(struct hlsl_ctx *ctx, const char *str, +@@ -1493,6 +1582,7 @@ unsigned int hlsl_type_minor_size(const struct hlsl_type *type); unsigned int hlsl_type_major_size(const struct hlsl_type *type); unsigned int hlsl_type_element_count(const struct hlsl_type *type); bool hlsl_type_is_resource(const struct hlsl_type *type); @@ -3402,7 +5653,7 @@ index 22e25b23988..20a96692a48 100644 unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset); bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2); -@@ -1528,16 +1585,15 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type); +@@ -1528,16 +1618,15 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type); bool hlsl_sm1_register_from_semantic(const struct vkd3d_shader_version *version, const char *semantic_name, unsigned int semantic_index, bool output, enum vkd3d_shader_register_type *type, unsigned int *reg); bool hlsl_sm1_usage_from_semantic(const char *semantic_name, @@ -3424,7 +5675,7 @@ index 22e25b23988..20a96692a48 100644 bool output, enum vkd3d_shader_register_type *type, bool *has_idx); int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l -index 0c02b27817e..b7c242661e3 100644 +index 0c02b27817e..97d8b13772b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l @@ -80,7 +80,9 @@ centroid {return KW_CENTROID; } @@ -3437,11 +5688,51 @@ index 0c02b27817e..b7c242661e3 100644 continue {return KW_CONTINUE; } DepthStencilState {return KW_DEPTHSTENCILSTATE; } DepthStencilView {return KW_DEPTHSTENCILVIEW; } +@@ -88,7 +90,6 @@ default {return KW_DEFAULT; } + discard {return KW_DISCARD; } + DomainShader {return KW_DOMAINSHADER; } + do {return KW_DO; } +-double {return KW_DOUBLE; } + else {return KW_ELSE; } + export {return KW_EXPORT; } + extern {return KW_EXTERN; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 3f319dea0d8..67262c2ccfd 100644 +index 3f319dea0d8..ef37eb75f03 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -516,7 +516,7 @@ enum loop_type +@@ -147,7 +147,7 @@ static void yyerror(YYLTYPE *loc, void *scanner, struct hlsl_ctx *ctx, const cha + + static struct hlsl_ir_node *node_from_block(struct hlsl_block *block) + { +- return LIST_ENTRY(list_tail(&block->instrs), struct hlsl_ir_node, entry); ++ return block->value; + } + + static struct hlsl_block *make_empty_block(struct hlsl_ctx *ctx) +@@ -437,6 +437,9 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct + if (hlsl_types_are_equal(src_type, dst_type)) + return node; + ++ if (node->type == HLSL_IR_SAMPLER_STATE && dst_type->class == HLSL_CLASS_SAMPLER) ++ return node; ++ + if (!implicit_compatible_data_types(ctx, src_type, dst_type)) + { + struct vkd3d_string_buffer *src_string, *dst_string; +@@ -489,9 +492,10 @@ static bool append_conditional_break(struct hlsl_ctx *ctx, struct hlsl_block *co + check_condition_type(ctx, condition); + + bool_type = hlsl_get_scalar_type(ctx, HLSL_TYPE_BOOL); +- if (!(cast = hlsl_new_cast(ctx, condition, bool_type, &condition->loc))) ++ /* We already checked for a 1-component numeric type, so ++ * add_implicit_conversion() is equivalent to add_cast() here. */ ++ if (!(cast = add_cast(ctx, cond_block, condition, bool_type, &condition->loc))) + return false; +- hlsl_block_add_instr(cond_block, cast); + + if (!(not = hlsl_new_unary_expr(ctx, HLSL_OP1_LOGIC_NOT, cast, &condition->loc))) + return false; +@@ -516,7 +520,7 @@ enum loop_type LOOP_DO_WHILE }; @@ -3450,7 +5741,7 @@ index 3f319dea0d8..67262c2ccfd 100644 { unsigned int i, j; -@@ -525,11 +525,10 @@ static bool attribute_list_has_duplicates(const struct parse_attribute_list *att +@@ -525,11 +529,10 @@ static bool attribute_list_has_duplicates(const struct parse_attribute_list *att for (j = i + 1; j < attrs->count; ++j) { if (!strcmp(attrs->attrs[i]->name, attrs->attrs[j]->name)) @@ -3464,15 +5755,36 @@ index 3f319dea0d8..67262c2ccfd 100644 } static void resolve_loop_continue(struct hlsl_ctx *ctx, struct hlsl_block *block, enum loop_type type, -@@ -610,6 +609,7 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx +@@ -610,8 +613,10 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx { switch (node->type) { + case HLSL_IR_COMPILE: case HLSL_IR_CONSTANT: case HLSL_IR_EXPR: ++ case HLSL_IR_SAMPLER_STATE: case HLSL_IR_STRING_CONSTANT: -@@ -697,9 +697,7 @@ static struct hlsl_block *create_loop(struct hlsl_ctx *ctx, enum loop_type type, + case HLSL_IR_SWIZZLE: + case HLSL_IR_LOAD: +@@ -639,14 +644,15 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx + return ret; + hlsl_block_add_block(&expr, block); + +- if (!add_implicit_conversion(ctx, &expr, node_from_block(&expr), dst_type, loc)) ++ if (!(node = add_implicit_conversion(ctx, &expr, node_from_block(&expr), dst_type, loc))) + { + hlsl_block_cleanup(&expr); + return ret; + } + + /* Wrap the node into a src to allow the reference to survive the multiple const passes. */ +- hlsl_src_from_node(&src, node_from_block(&expr)); ++ hlsl_src_from_node(&src, node); ++ hlsl_lower_index_loads(ctx, &expr); + hlsl_run_const_passes(ctx, &expr); + node = src.node; + hlsl_src_remove(&src); +@@ -697,9 +703,7 @@ static struct hlsl_block *create_loop(struct hlsl_ctx *ctx, enum loop_type type, unsigned int i, unroll_limit = 0; struct hlsl_ir_node *loop; @@ -3483,7 +5795,7 @@ index 3f319dea0d8..67262c2ccfd 100644 check_loop_attributes(ctx, attributes, loc); /* Ignore unroll(0) attribute, and any invalid attribute. */ -@@ -1227,7 +1225,8 @@ static bool add_typedef(struct hlsl_ctx *ctx, struct hlsl_type *const orig_type, +@@ -1227,7 +1231,8 @@ static bool add_typedef(struct hlsl_ctx *ctx, struct hlsl_type *const orig_type, } static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *instrs, @@ -3493,7 +5805,7 @@ index 3f319dea0d8..67262c2ccfd 100644 static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters *parameters, struct parse_parameter *param, const struct vkd3d_shader_location *loc) -@@ -1285,7 +1284,8 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters +@@ -1285,7 +1290,8 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters for (i = 0; i < param->initializer.args_count; ++i) { @@ -3503,7 +5815,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } free_parse_initializer(¶m->initializer); -@@ -1673,25 +1673,36 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct hlsl_block *bl +@@ -1673,25 +1679,36 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct hlsl_block *bl return expr; } @@ -3552,9 +5864,303 @@ index 3f319dea0d8..67262c2ccfd 100644 } static struct hlsl_ir_node *add_unary_arithmetic_expr(struct hlsl_ctx *ctx, struct hlsl_block *block, -@@ -2357,7 +2368,8 @@ static unsigned int get_component_index_from_default_initializer_index(struct hl +@@ -1699,12 +1716,18 @@ static struct hlsl_ir_node *add_unary_arithmetic_expr(struct hlsl_ctx *ctx, stru + { + struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {arg}; + ++ if (arg->data_type->class == HLSL_CLASS_ERROR) ++ return arg; ++ + return add_expr(ctx, block, op, args, arg->data_type, loc); } + static struct hlsl_ir_node *add_unary_bitwise_expr(struct hlsl_ctx *ctx, struct hlsl_block *block, + enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, const struct vkd3d_shader_location *loc) + { ++ if (arg->data_type->class == HLSL_CLASS_ERROR) ++ return arg; ++ + check_integer_type(ctx, arg); + + return add_unary_arithmetic_expr(ctx, block, op, arg, loc); +@@ -1716,6 +1739,9 @@ static struct hlsl_ir_node *add_unary_logical_expr(struct hlsl_ctx *ctx, struct + struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; + struct hlsl_type *bool_type; + ++ if (arg->data_type->class == HLSL_CLASS_ERROR) ++ return arg; ++ + bool_type = hlsl_get_numeric_type(ctx, arg->data_type->class, HLSL_TYPE_BOOL, + arg->data_type->dimx, arg->data_type->dimy); + +@@ -1745,7 +1771,11 @@ static struct hlsl_ir_node *add_binary_arithmetic_expr(struct hlsl_ctx *ctx, str + struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; + struct hlsl_type *common_type; + +- common_type = get_common_numeric_type(ctx, arg1, arg2, loc); ++ if (!(common_type = get_common_numeric_type(ctx, arg1, arg2, loc))) ++ { ++ block->value = ctx->error_instr; ++ return block->value; ++ } + + if (!(args[0] = add_implicit_conversion(ctx, block, arg1, common_type, loc))) + return NULL; +@@ -1942,6 +1972,12 @@ static struct hlsl_block *add_binary_expr_merge(struct hlsl_ctx *ctx, struct hls + hlsl_block_add_block(block1, block2); + destroy_block(block2); + ++ if (arg1->data_type->class == HLSL_CLASS_ERROR || arg2->data_type->class == HLSL_CLASS_ERROR) ++ { ++ block1->value = ctx->error_instr; ++ return block1; ++ } ++ + if (add_binary_expr(ctx, block1, op, arg1, arg2, loc) == NULL) + return NULL; + +@@ -2048,18 +2084,23 @@ static bool invert_swizzle_matrix(uint32_t *swizzle, unsigned int *writemask, un + return true; + } + +-static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *lhs, ++static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *lhs, + enum parse_assign_op assign_op, struct hlsl_ir_node *rhs) + { + struct hlsl_type *lhs_type = lhs->data_type; +- struct hlsl_ir_node *copy; + unsigned int writemask = 0, width = 0; + bool matrix_writemask = false; + ++ if (lhs->data_type->class == HLSL_CLASS_ERROR || rhs->data_type->class == HLSL_CLASS_ERROR) ++ { ++ block->value = ctx->error_instr; ++ return true; ++ } ++ + if (assign_op == ASSIGN_OP_SUB) + { + if (!(rhs = add_unary_arithmetic_expr(ctx, block, HLSL_OP1_NEG, rhs, &rhs->loc))) +- return NULL; ++ return false; + assign_op = ASSIGN_OP_ADD; + } + if (assign_op != ASSIGN_OP_ASSIGN) +@@ -2068,7 +2109,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo + + VKD3D_ASSERT(op); + if (!(rhs = add_binary_expr(ctx, block, op, lhs, rhs, &rhs->loc))) +- return NULL; ++ return false; + } + + if (hlsl_is_numeric_type(lhs_type)) +@@ -2078,14 +2119,14 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo + } + + if (!(rhs = add_implicit_conversion(ctx, block, rhs, lhs_type, &rhs->loc))) +- return NULL; ++ return false; + + while (lhs->type != HLSL_IR_LOAD && lhs->type != HLSL_IR_INDEX) + { + if (lhs->type == HLSL_IR_EXPR && hlsl_ir_expr(lhs)->op == HLSL_OP1_CAST) + { + hlsl_fixme(ctx, &lhs->loc, "Cast on the LHS."); +- return NULL; ++ return false; + } + else if (lhs->type == HLSL_IR_SWIZZLE) + { +@@ -2100,25 +2141,23 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo + if (swizzle->val.node->type != HLSL_IR_LOAD && swizzle->val.node->type != HLSL_IR_INDEX) + { + hlsl_fixme(ctx, &lhs->loc, "Unhandled source of matrix swizzle."); +- return NULL; ++ return false; + } + if (!invert_swizzle_matrix(&s, &writemask, &width)) + { + hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask for matrix."); +- return NULL; ++ return false; + } + matrix_writemask = true; + } + else if (!invert_swizzle(&s, &writemask, &width)) + { + hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask."); +- return NULL; ++ return false; + } + + if (!(new_swizzle = hlsl_new_swizzle(ctx, s, width, rhs, &swizzle->node.loc))) +- { +- return NULL; +- } ++ return false; + hlsl_block_add_instr(block, new_swizzle); + + lhs = swizzle->val.node; +@@ -2127,7 +2166,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo + else + { + hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_LVALUE, "Invalid lvalue."); +- return NULL; ++ return false; + } + } + +@@ -2142,11 +2181,11 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo + if (!hlsl_index_is_resource_access(hlsl_ir_index(lhs))) + { + hlsl_fixme(ctx, &lhs->loc, "Non-direct structured resource store."); +- return NULL; ++ return false; + } + + if (!hlsl_init_deref_from_index_chain(ctx, &resource_deref, hlsl_ir_index(lhs)->val.node)) +- return NULL; ++ return false; + + resource_type = hlsl_deref_get_type(ctx, &resource_deref); + VKD3D_ASSERT(resource_type->class == HLSL_CLASS_TEXTURE || resource_type->class == HLSL_CLASS_UAV); +@@ -2168,7 +2207,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo + if (!(store = hlsl_new_resource_store(ctx, &resource_deref, coords, rhs, &lhs->loc))) + { + hlsl_cleanup_deref(&resource_deref); +- return NULL; ++ return false; + } + hlsl_block_add_instr(block, store); + hlsl_cleanup_deref(&resource_deref); +@@ -2195,13 +2234,13 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo + if (!(load = hlsl_add_load_component(ctx, block, rhs, k++, &rhs->loc))) + { + hlsl_cleanup_deref(&deref); +- return NULL; ++ return false; + } + + if (!hlsl_new_store_component(ctx, &store_block, &deref, component, load)) + { + hlsl_cleanup_deref(&deref); +- return NULL; ++ return false; + } + hlsl_block_add_block(block, &store_block); + } +@@ -2226,23 +2265,23 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo + continue; + + if (!(c = hlsl_new_uint_constant(ctx, i, &lhs->loc))) +- return NULL; ++ return false; + hlsl_block_add_instr(block, c); + + if (!(cell = hlsl_new_index(ctx, &row->node, c, &lhs->loc))) +- return NULL; ++ return false; + hlsl_block_add_instr(block, cell); + + if (!(load = hlsl_add_load_component(ctx, block, rhs, k++, &rhs->loc))) +- return NULL; ++ return false; + + if (!hlsl_init_deref_from_index_chain(ctx, &deref, cell)) +- return NULL; ++ return false; + + if (!(store = hlsl_new_store_index(ctx, &deref, NULL, load, 0, &rhs->loc))) + { + hlsl_cleanup_deref(&deref); +- return NULL; ++ return false; + } + hlsl_block_add_instr(block, store); + hlsl_cleanup_deref(&deref); +@@ -2254,24 +2293,19 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo + struct hlsl_deref deref; + + if (!hlsl_init_deref_from_index_chain(ctx, &deref, lhs)) +- return NULL; ++ return false; + + if (!(store = hlsl_new_store_index(ctx, &deref, NULL, rhs, writemask, &rhs->loc))) + { + hlsl_cleanup_deref(&deref); +- return NULL; ++ return false; + } + hlsl_block_add_instr(block, store); + hlsl_cleanup_deref(&deref); + } + +- /* Don't use the instruction itself as a source, as this makes structure +- * splitting easier. Instead copy it here. Since we retrieve sources from +- * the last instruction in the list, we do need to copy. */ +- if (!(copy = hlsl_new_copy(ctx, rhs))) +- return NULL; +- hlsl_block_add_instr(block, copy); +- return copy; ++ block->value = rhs; ++ return true; + } + + static bool add_increment(struct hlsl_ctx *ctx, struct hlsl_block *block, bool decrement, bool post, +@@ -2307,57 +2341,9 @@ static bool add_increment(struct hlsl_ctx *ctx, struct hlsl_block *block, bool d + return true; + } + +-/* For some reason, for matrices, values from default value initializers end up in different +- * components than from regular initializers. Default value initializers fill the matrix in +- * vertical reading order (left-to-right top-to-bottom) instead of regular reading order +- * (top-to-bottom left-to-right), so they have to be adjusted. +- * An exception is that the order of matrix initializers for function parameters are row-major +- * (top-to-bottom left-to-right). */ +-static unsigned int get_component_index_from_default_initializer_index(struct hlsl_ctx *ctx, +- struct hlsl_type *type, unsigned int index) +-{ +- unsigned int element_comp_count, element, x, y, i; +- unsigned int base = 0; +- +- if (ctx->profile->major_version < 4) +- return index; +- +- if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT) +- return index; +- +- switch (type->class) +- { +- case HLSL_CLASS_MATRIX: +- x = index / type->dimy; +- y = index % type->dimy; +- return y * type->dimx + x; +- +- case HLSL_CLASS_ARRAY: +- element_comp_count = hlsl_type_component_count(type->e.array.type); +- element = index / element_comp_count; +- base = element * element_comp_count; +- return base + get_component_index_from_default_initializer_index(ctx, type->e.array.type, index - base); +- +- case HLSL_CLASS_STRUCT: +- for (i = 0; i < type->e.record.field_count; ++i) +- { +- struct hlsl_type *field_type = type->e.record.fields[i].type; +- +- element_comp_count = hlsl_type_component_count(field_type); +- if (index - base < element_comp_count) +- return base + get_component_index_from_default_initializer_index(ctx, field_type, index - base); +- base += element_comp_count; +- } +- break; +- +- default: +- return index; +- } +- vkd3d_unreachable(); +-} +- static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *instrs, - struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src) + struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src, @@ -3562,7 +6168,7 @@ index 3f319dea0d8..67262c2ccfd 100644 { unsigned int src_comp_count = hlsl_type_component_count(src->data_type); struct hlsl_deref dst_deref; -@@ -2376,23 +2388,43 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i +@@ -2376,32 +2362,75 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i dst_comp_type = hlsl_type_get_component_type(ctx, dst->data_type, *store_index); @@ -3570,14 +6176,19 @@ index 3f319dea0d8..67262c2ccfd 100644 + if (is_default_values_initializer) { struct hlsl_default_value default_value = {0}; - unsigned int dst_index; +- unsigned int dst_index; - if (!hlsl_clone_block(ctx, &block, instrs)) - return; - default_value = evaluate_static_expression(ctx, &block, dst_comp_type, &src->loc); +- +- if (dst->is_param) +- dst_index = *store_index; +- else +- dst_index = get_component_index_from_default_initializer_index(ctx, dst->data_type, *store_index); + if (hlsl_is_numeric_type(dst_comp_type)) + { -+ if (src->type == HLSL_IR_COMPILE) ++ if (src->type == HLSL_IR_COMPILE || src->type == HLSL_IR_SAMPLER_STATE) + { + /* Default values are discarded if they contain an object + * literal expression for a numeric component. */ @@ -3596,18 +6207,9 @@ index 3f319dea0d8..67262c2ccfd 100644 + return; + default_value = evaluate_static_expression(ctx, &block, dst_comp_type, &src->loc); -- if (dst->is_param) -- dst_index = *store_index; -- else -- dst_index = get_component_index_from_default_initializer_index(ctx, dst->data_type, *store_index); -+ if (dst->is_param) -+ dst_index = *store_index; -+ else -+ dst_index = get_component_index_from_default_initializer_index(ctx, dst->data_type, *store_index); - - dst->default_values[dst_index] = default_value; + if (dst->default_values) -+ dst->default_values[dst_index] = default_value; ++ dst->default_values[*store_index] = default_value; - hlsl_block_cleanup(&block); + hlsl_block_cleanup(&block); @@ -3616,7 +6218,50 @@ index 3f319dea0d8..67262c2ccfd 100644 } else { -@@ -2733,13 +2765,15 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var +- if (!(conv = add_implicit_conversion(ctx, instrs, load, dst_comp_type, &src->loc))) +- return; ++ if (src->type == HLSL_IR_SAMPLER_STATE) ++ { ++ /* Sampler states end up in the variable's state_blocks instead of ++ * being used to initialize its value. */ ++ struct hlsl_ir_sampler_state *sampler_state = hlsl_ir_sampler_state(src); ++ ++ if (dst_comp_type->class != HLSL_CLASS_SAMPLER) ++ { ++ struct vkd3d_string_buffer *dst_string; + +- if (!hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv)) +- return; +- hlsl_block_add_block(instrs, &block); ++ dst_string = hlsl_type_to_string(ctx, dst_comp_type); ++ if (dst_string) ++ hlsl_error(ctx, &src->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, ++ "Cannot assign sampler_state to %s.", dst_string->buffer); ++ hlsl_release_string_buffer(ctx, dst_string); ++ return; ++ } ++ ++ if (!hlsl_array_reserve(ctx, (void **)&dst->state_blocks, &dst->state_block_capacity, ++ dst->state_block_count + 1, sizeof(*dst->state_blocks))) ++ return; ++ ++ dst->state_blocks[dst->state_block_count] = sampler_state->state_block; ++ sampler_state->state_block = NULL; ++ ++dst->state_block_count; ++ } ++ else ++ { ++ if (!(conv = add_implicit_conversion(ctx, instrs, load, dst_comp_type, &src->loc))) ++ return; ++ ++ if (!hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv)) ++ return; ++ hlsl_block_add_block(instrs, &block); ++ } + } + + ++*store_index; +@@ -2733,13 +2762,17 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var if (v->initializer.args_count) { @@ -3628,12 +6273,14 @@ index 3f319dea0d8..67262c2ccfd 100644 is_default_values_initializer = (ctx->cur_buffer != ctx->globals_buffer) || (var->storage_modifiers & HLSL_STORAGE_UNIFORM) || ctx->cur_scope->annotations; ++ if (hlsl_get_multiarray_element_type(type)->class == HLSL_CLASS_SAMPLER) ++ is_default_values_initializer = false; + if (hlsl_type_is_shader(type)) + is_default_values_initializer = false; if (is_default_values_initializer) { -@@ -2780,7 +2814,8 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var +@@ -2780,7 +2813,8 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var for (k = 0; k < v->initializer.args_count; ++k) { @@ -3643,7 +6290,17 @@ index 3f319dea0d8..67262c2ccfd 100644 } if (is_default_values_initializer) -@@ -2835,28 +2870,36 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var +@@ -2795,6 +2829,9 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var + { + hlsl_block_add_block(initializers, v->initializer.instrs); + } ++ ++ if (var->state_blocks) ++ TRACE("Variable %s has %u state blocks.\n", var->name, var->state_block_count); + } + else if (var->storage_modifiers & HLSL_STORAGE_STATIC) + { +@@ -2835,28 +2872,36 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var return initializers; } @@ -3692,7 +6349,7 @@ index 3f319dea0d8..67262c2ccfd 100644 const struct vkd3d_shader_location *loc) { struct hlsl_ir_function_decl *decl, *compatible_match = NULL; -@@ -2869,7 +2912,7 @@ static struct hlsl_ir_function_decl *find_function_call(struct hlsl_ctx *ctx, +@@ -2869,7 +2914,7 @@ static struct hlsl_ir_function_decl *find_function_call(struct hlsl_ctx *ctx, LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry) { @@ -3701,7 +6358,7 @@ index 3f319dea0d8..67262c2ccfd 100644 { if (compatible_match) { -@@ -2890,26 +2933,35 @@ static struct hlsl_ir_node *hlsl_new_void_expr(struct hlsl_ctx *ctx, const struc +@@ -2890,26 +2935,35 @@ static struct hlsl_ir_node *hlsl_new_void_expr(struct hlsl_ctx *ctx, const struc return hlsl_new_expr(ctx, HLSL_OP0_VOID, operands, ctx->builtin_types.Void, loc); } @@ -3744,7 +6401,7 @@ index 3f319dea0d8..67262c2ccfd 100644 arg = cast; } -@@ -2918,13 +2970,15 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu +@@ -2918,13 +2972,15 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu struct hlsl_ir_node *store; if (!(store = hlsl_new_simple_store(ctx, param, arg))) @@ -3762,7 +6419,7 @@ index 3f319dea0d8..67262c2ccfd 100644 { struct hlsl_ir_var *param = func->parameters.vars[i]; unsigned int comp_count = hlsl_type_component_count(param->data_type); -@@ -2932,6 +2986,9 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu +@@ -2932,6 +2988,9 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu VKD3D_ASSERT(param->default_values); @@ -3772,7 +6429,7 @@ index 3f319dea0d8..67262c2ccfd 100644 hlsl_init_simple_deref_from_var(¶m_deref, param); for (j = 0; j < comp_count; ++j) -@@ -2945,20 +3002,23 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu +@@ -2945,20 +3004,23 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu { value.u[0] = param->default_values[j].number; if (!(comp = hlsl_new_constant(ctx, type, &value, loc))) @@ -3799,7 +6456,7 @@ index 3f319dea0d8..67262c2ccfd 100644 for (i = 0; i < args->args_count; ++i) { struct hlsl_ir_var *param = func->parameters.vars[i]; -@@ -2973,11 +3033,11 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu +@@ -2973,11 +3035,11 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu "Output argument to \"%s\" is const.", func->func->name); if (!(load = hlsl_new_var_load(ctx, param, &arg->loc))) @@ -3813,7 +6470,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } } -@@ -2998,7 +3058,7 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu +@@ -2998,7 +3060,7 @@ static bool add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fu hlsl_block_add_instr(args->instrs, expr); } @@ -3822,7 +6479,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } static struct hlsl_ir_node *intrinsic_float_convert_arg(struct hlsl_ctx *ctx, -@@ -3006,7 +3066,7 @@ static struct hlsl_ir_node *intrinsic_float_convert_arg(struct hlsl_ctx *ctx, +@@ -3006,7 +3068,7 @@ static struct hlsl_ir_node *intrinsic_float_convert_arg(struct hlsl_ctx *ctx, { struct hlsl_type *type = arg->data_type; @@ -3831,7 +6488,7 @@ index 3f319dea0d8..67262c2ccfd 100644 return arg; type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_FLOAT, type->dimx, type->dimy); -@@ -3094,14 +3154,12 @@ static bool elementwise_intrinsic_convert_args(struct hlsl_ctx *ctx, +@@ -3094,14 +3156,12 @@ static bool elementwise_intrinsic_convert_args(struct hlsl_ctx *ctx, static bool elementwise_intrinsic_float_convert_args(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { @@ -3848,7 +6505,7 @@ index 3f319dea0d8..67262c2ccfd 100644 return convert_args(ctx, params, type, loc); } -@@ -3129,6 +3187,7 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx, +@@ -3129,6 +3189,7 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc, bool asin_mode) { struct hlsl_ir_function_decl *func; @@ -3856,7 +6513,7 @@ index 3f319dea0d8..67262c2ccfd 100644 struct hlsl_type *type; char *body; -@@ -3152,8 +3211,9 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx, +@@ -3152,8 +3213,9 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx, const char *fn_name = asin_mode ? fn_name_asin : fn_name_acos; @@ -3868,7 +6525,7 @@ index 3f319dea0d8..67262c2ccfd 100644 if (!(body = hlsl_sprintf_alloc(ctx, template, type->name, fn_name, type->name, -@@ -3165,7 +3225,7 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx, +@@ -3165,7 +3227,7 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx, if (!func) return false; @@ -3877,7 +6534,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } static bool intrinsic_acos(struct hlsl_ctx *ctx, -@@ -3282,9 +3342,9 @@ static bool write_atan_or_atan2(struct hlsl_ctx *ctx, +@@ -3282,9 +3344,9 @@ static bool write_atan_or_atan2(struct hlsl_ctx *ctx, " : poly_approx;\n" "}"; @@ -3889,7 +6546,7 @@ index 3f319dea0d8..67262c2ccfd 100644 if (!(buf = hlsl_get_string_buffer(ctx))) return false; -@@ -3314,7 +3374,7 @@ static bool write_atan_or_atan2(struct hlsl_ctx *ctx, +@@ -3314,7 +3376,7 @@ static bool write_atan_or_atan2(struct hlsl_ctx *ctx, if (!func) return false; @@ -3898,7 +6555,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } static bool intrinsic_atan(struct hlsl_ctx *ctx, -@@ -3507,7 +3567,7 @@ static bool write_cosh_or_sinh(struct hlsl_ctx *ctx, +@@ -3507,7 +3569,7 @@ static bool write_cosh_or_sinh(struct hlsl_ctx *ctx, if (!func) return false; @@ -3907,7 +6564,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } static bool intrinsic_cosh(struct hlsl_ctx *ctx, -@@ -3525,9 +3585,8 @@ static bool intrinsic_cross(struct hlsl_ctx *ctx, +@@ -3525,9 +3587,8 @@ static bool intrinsic_cross(struct hlsl_ctx *ctx, struct hlsl_type *cast_type; enum hlsl_base_type base; @@ -3919,7 +6576,7 @@ index 3f319dea0d8..67262c2ccfd 100644 base = HLSL_TYPE_FLOAT; cast_type = hlsl_get_vector_type(ctx, base, 3); -@@ -3698,15 +3757,14 @@ static bool intrinsic_determinant(struct hlsl_ctx *ctx, +@@ -3698,15 +3759,14 @@ static bool intrinsic_determinant(struct hlsl_ctx *ctx, return false; } @@ -3939,7 +6596,7 @@ index 3f319dea0d8..67262c2ccfd 100644 template = templates[dim]; switch (dim) -@@ -3734,7 +3792,7 @@ static bool intrinsic_determinant(struct hlsl_ctx *ctx, +@@ -3734,7 +3794,7 @@ static bool intrinsic_determinant(struct hlsl_ctx *ctx, if (!func) return false; @@ -3948,7 +6605,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } static bool intrinsic_distance(struct hlsl_ctx *ctx, -@@ -3766,6 +3824,50 @@ static bool intrinsic_dot(struct hlsl_ctx *ctx, +@@ -3766,6 +3826,50 @@ static bool intrinsic_dot(struct hlsl_ctx *ctx, return !!add_binary_dot_expr(ctx, params->instrs, params->args[0], params->args[1], loc); } @@ -3999,7 +6656,7 @@ index 3f319dea0d8..67262c2ccfd 100644 static bool intrinsic_exp(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { -@@ -3809,9 +3911,9 @@ static bool intrinsic_faceforward(struct hlsl_ctx *ctx, +@@ -3809,9 +3913,9 @@ static bool intrinsic_faceforward(struct hlsl_ctx *ctx, " return dot(i, ng) < 0 ? n : -n;\n" "}\n"; @@ -4011,7 +6668,7 @@ index 3f319dea0d8..67262c2ccfd 100644 if (!(body = hlsl_sprintf_alloc(ctx, template, type->name, type->name, type->name, type->name))) -@@ -3821,7 +3923,7 @@ static bool intrinsic_faceforward(struct hlsl_ctx *ctx, +@@ -3821,7 +3925,7 @@ static bool intrinsic_faceforward(struct hlsl_ctx *ctx, if (!func) return false; @@ -4020,7 +6677,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } static bool intrinsic_f16tof32(struct hlsl_ctx *ctx, -@@ -3926,7 +4028,7 @@ static bool intrinsic_fwidth(struct hlsl_ctx *ctx, +@@ -3926,7 +4030,7 @@ static bool intrinsic_fwidth(struct hlsl_ctx *ctx, if (!func) return false; @@ -4029,7 +6686,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } static bool intrinsic_ldexp(struct hlsl_ctx *ctx, -@@ -4029,7 +4131,7 @@ static bool intrinsic_lit(struct hlsl_ctx *ctx, +@@ -4029,7 +4133,7 @@ static bool intrinsic_lit(struct hlsl_ctx *ctx, if (!(func = hlsl_compile_internal_function(ctx, "lit", body))) return false; @@ -4038,7 +6695,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } static bool intrinsic_log(struct hlsl_ctx *ctx, -@@ -4081,6 +4183,20 @@ static bool intrinsic_log2(struct hlsl_ctx *ctx, +@@ -4081,6 +4185,20 @@ static bool intrinsic_log2(struct hlsl_ctx *ctx, return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_LOG2, arg, loc); } @@ -4059,7 +6716,7 @@ index 3f319dea0d8..67262c2ccfd 100644 static bool intrinsic_max(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { -@@ -4285,13 +4401,9 @@ static bool intrinsic_reflect(struct hlsl_ctx *ctx, +@@ -4285,13 +4403,9 @@ static bool intrinsic_reflect(struct hlsl_ctx *ctx, static bool intrinsic_refract(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { @@ -4075,7 +6732,7 @@ index 3f319dea0d8..67262c2ccfd 100644 char *body; static const char template[] = -@@ -4303,28 +4415,34 @@ static bool intrinsic_refract(struct hlsl_ctx *ctx, +@@ -4303,28 +4417,34 @@ static bool intrinsic_refract(struct hlsl_ctx *ctx, " return t >= 0.0 ? i.x * r - (i.x * d + sqrt(t)) * n : 0;\n" "}"; @@ -4124,7 +6781,7 @@ index 3f319dea0d8..67262c2ccfd 100644 return false; func = hlsl_compile_internal_function(ctx, "refract", body); -@@ -4332,7 +4450,7 @@ static bool intrinsic_refract(struct hlsl_ctx *ctx, +@@ -4332,7 +4452,7 @@ static bool intrinsic_refract(struct hlsl_ctx *ctx, if (!func) return false; @@ -4133,7 +6790,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } static bool intrinsic_round(struct hlsl_ctx *ctx, -@@ -4415,6 +4533,35 @@ static bool intrinsic_sin(struct hlsl_ctx *ctx, +@@ -4415,6 +4535,35 @@ static bool intrinsic_sin(struct hlsl_ctx *ctx, return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_SIN, arg, loc); } @@ -4169,7 +6826,7 @@ index 3f319dea0d8..67262c2ccfd 100644 static bool intrinsic_sinh(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { -@@ -4436,9 +4583,9 @@ static bool intrinsic_smoothstep(struct hlsl_ctx *ctx, +@@ -4436,9 +4585,9 @@ static bool intrinsic_smoothstep(struct hlsl_ctx *ctx, " return (p * p) * (3 - 2 * p);\n" "}"; @@ -4181,7 +6838,7 @@ index 3f319dea0d8..67262c2ccfd 100644 if (!(body = hlsl_sprintf_alloc(ctx, template, type->name, type->name, type->name, type->name, type->name))) return false; -@@ -4447,7 +4594,7 @@ static bool intrinsic_smoothstep(struct hlsl_ctx *ctx, +@@ -4447,7 +4596,7 @@ static bool intrinsic_smoothstep(struct hlsl_ctx *ctx, if (!func) return false; @@ -4190,7 +6847,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } static bool intrinsic_sqrt(struct hlsl_ctx *ctx, -@@ -4469,13 +4616,12 @@ static bool intrinsic_step(struct hlsl_ctx *ctx, +@@ -4469,13 +4618,12 @@ static bool intrinsic_step(struct hlsl_ctx *ctx, if (!elementwise_intrinsic_float_convert_args(ctx, params, loc)) return false; @@ -4205,7 +6862,7 @@ index 3f319dea0d8..67262c2ccfd 100644 return !!add_implicit_conversion(ctx, params->instrs, ge, type, loc); } -@@ -4523,7 +4669,7 @@ static bool intrinsic_tanh(struct hlsl_ctx *ctx, +@@ -4523,7 +4671,7 @@ static bool intrinsic_tanh(struct hlsl_ctx *ctx, if (!func) return false; @@ -4214,7 +6871,7 @@ index 3f319dea0d8..67262c2ccfd 100644 } static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *params, -@@ -4661,17 +4807,17 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * +@@ -4661,17 +4809,17 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * if (!(var = hlsl_new_synthetic_var(ctx, "coords", hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 2), loc))) return false; @@ -4235,7 +6892,7 @@ index 3f319dea0d8..67262c2ccfd 100644 if (!(load = hlsl_new_var_load(ctx, var, loc))) return false; -@@ -4937,6 +5083,7 @@ intrinsic_functions[] = +@@ -4937,6 +5085,7 @@ intrinsic_functions[] = {"determinant", 1, true, intrinsic_determinant}, {"distance", 2, true, intrinsic_distance}, {"dot", 2, true, intrinsic_dot}, @@ -4243,7 +6900,7 @@ index 3f319dea0d8..67262c2ccfd 100644 {"exp", 1, true, intrinsic_exp}, {"exp2", 1, true, intrinsic_exp2}, {"f16tof32", 1, true, intrinsic_f16tof32}, -@@ -4952,6 +5099,7 @@ intrinsic_functions[] = +@@ -4952,6 +5101,7 @@ intrinsic_functions[] = {"log", 1, true, intrinsic_log}, {"log10", 1, true, intrinsic_log10}, {"log2", 1, true, intrinsic_log2}, @@ -4251,7 +6908,7 @@ index 3f319dea0d8..67262c2ccfd 100644 {"max", 2, true, intrinsic_max}, {"min", 2, true, intrinsic_min}, {"mul", 2, true, intrinsic_mul}, -@@ -4966,6 +5114,7 @@ intrinsic_functions[] = +@@ -4966,6 +5116,7 @@ intrinsic_functions[] = {"saturate", 1, true, intrinsic_saturate}, {"sign", 1, true, intrinsic_sign}, {"sin", 1, true, intrinsic_sin}, @@ -4259,11 +6916,20 @@ index 3f319dea0d8..67262c2ccfd 100644 {"sinh", 1, true, intrinsic_sinh}, {"smoothstep", 3, true, intrinsic_smoothstep}, {"sqrt", 1, true, intrinsic_sqrt}, -@@ -5002,9 +5151,9 @@ static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name, +@@ -5002,9 +5153,18 @@ static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name, struct intrinsic_function *intrinsic; struct hlsl_ir_function_decl *decl; - if ((decl = find_function_call(ctx, name, args, loc))) ++ for (unsigned int i = 0; i < args->args_count; ++i) ++ { ++ if (args->args[i]->data_type->class == HLSL_CLASS_ERROR) ++ { ++ args->instrs->value = ctx->error_instr; ++ return args->instrs; ++ } ++ } ++ + if ((decl = find_function_call(ctx, name, args, false, loc))) { - if (!add_user_call(ctx, decl, args, loc)) @@ -4271,7 +6937,7 @@ index 3f319dea0d8..67262c2ccfd 100644 goto fail; } else if ((intrinsic = bsearch(name, intrinsic_functions, ARRAY_SIZE(intrinsic_functions), -@@ -5060,6 +5209,84 @@ fail: +@@ -5060,6 +5220,84 @@ fail: return NULL; } @@ -4356,7 +7022,7 @@ index 3f319dea0d8..67262c2ccfd 100644 static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type, struct parse_initializer *params, const struct vkd3d_shader_location *loc) { -@@ -5071,7 +5298,7 @@ static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type +@@ -5071,7 +5309,7 @@ static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type return NULL; for (i = 0; i < params->args_count; ++i) @@ -4365,7 +7031,70 @@ index 3f319dea0d8..67262c2ccfd 100644 if (!(load = hlsl_new_var_load(ctx, var, loc))) return NULL; -@@ -6058,8 +6285,10 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h +@@ -5113,11 +5351,6 @@ static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, + } + else + { +- cond_type = hlsl_get_numeric_type(ctx, cond_type->class, HLSL_TYPE_BOOL, +- cond_type->dimx, cond_type->dimy); +- if (!(cond = add_implicit_conversion(ctx, block, cond, cond_type, &cond->loc))) +- return false; +- + if (common_type->dimx == 1 && common_type->dimy == 1) + { + common_type = hlsl_get_numeric_type(ctx, cond_type->class, +@@ -5139,6 +5372,11 @@ static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, + hlsl_release_string_buffer(ctx, cond_string); + hlsl_release_string_buffer(ctx, value_string); + } ++ ++ cond_type = hlsl_get_numeric_type(ctx, common_type->class, HLSL_TYPE_BOOL, ++ common_type->dimx, common_type->dimy); ++ if (!(cond = add_implicit_conversion(ctx, block, cond, cond_type, &cond->loc))) ++ return false; + } + + if (!(first = add_implicit_conversion(ctx, block, first, common_type, &first->loc))) +@@ -5854,6 +6092,21 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, stru + const struct hlsl_type *object_type = object->data_type; + const struct method_function *method; + ++ if (object_type->class == HLSL_CLASS_ERROR) ++ { ++ block->value = ctx->error_instr; ++ return true; ++ } ++ ++ for (unsigned int i = 0; i < params->args_count; ++i) ++ { ++ if (params->args[i]->data_type->class == HLSL_CLASS_ERROR) ++ { ++ block->value = ctx->error_instr; ++ return true; ++ } ++ } ++ + if (object_type->class != HLSL_CLASS_TEXTURE || object_type->sampler_dim == HLSL_SAMPLER_DIM_GENERIC) + { + struct vkd3d_string_buffer *string; +@@ -5995,16 +6248,6 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, + hlsl_release_string_buffer(ctx, string); + } + +-static bool state_block_add_entry(struct hlsl_state_block *state_block, struct hlsl_state_block_entry *entry) +-{ +- if (!vkd3d_array_reserve((void **)&state_block->entries, &state_block->capacity, state_block->count + 1, +- sizeof(*state_block->entries))) +- return false; +- +- state_block->entries[state_block->count++] = entry; +- return true; +-} +- + } + + %locations +@@ -6058,8 +6301,10 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h %token KW_CENTROID %token KW_COLUMN_MAJOR %token KW_COMPILE @@ -4376,7 +7105,15 @@ index 3f319dea0d8..67262c2ccfd 100644 %token KW_CONTINUE %token KW_DEFAULT %token KW_DEPTHSTENCILSTATE -@@ -6827,6 +7056,8 @@ func_prototype: +@@ -6067,7 +6312,6 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h + %token KW_DISCARD + %token KW_DO + %token KW_DOMAINSHADER +-%token KW_DOUBLE + %token KW_ELSE + %token KW_EXPORT + %token KW_EXTERN +@@ -6827,6 +7071,8 @@ func_prototype: func_prototype_no_attrs | attribute_list func_prototype_no_attrs { @@ -4385,7 +7122,17 @@ index 3f319dea0d8..67262c2ccfd 100644 if ($2.first) { $2.decl->attr_count = $1.count; -@@ -7619,6 +7850,11 @@ stateblock_lhs_identifier: +@@ -7614,11 +7860,21 @@ stateblock_lhs_identifier: + if (!($$ = hlsl_strdup(ctx, "pixelshader"))) + YYABORT; + } ++ | KW_TEXTURE ++ { ++ if (!($$ = hlsl_strdup(ctx, "texture"))) ++ YYABORT; ++ } + | KW_VERTEXSHADER + { if (!($$ = hlsl_strdup(ctx, "vertexshader"))) YYABORT; } @@ -4397,7 +7144,25 @@ index 3f319dea0d8..67262c2ccfd 100644 state_block_index_opt: %empty -@@ -8092,8 +8328,7 @@ selection_statement: +@@ -7666,7 +7922,7 @@ state_block: + vkd3d_free($5.args); + + $$ = $1; +- state_block_add_entry($$, entry); ++ hlsl_state_block_add_entry($$, entry); + } + | state_block any_identifier '(' func_arguments ')' ';' + { +@@ -7694,7 +7950,7 @@ state_block: + hlsl_validate_state_block_entry(ctx, entry, &@4); + + $$ = $1; +- state_block_add_entry($$, entry); ++ hlsl_state_block_add_entry($$, entry); + } + + state_block_list: +@@ -8092,8 +8348,7 @@ selection_statement: struct hlsl_ir_node *instr; unsigned int i; @@ -4407,7 +7172,7 @@ index 3f319dea0d8..67262c2ccfd 100644 for (i = 0; i < attributes->count; ++i) { -@@ -8391,6 +8626,34 @@ primary_expr: +@@ -8391,6 +8646,34 @@ primary_expr: { $$ = $2; } @@ -4442,11 +7207,70 @@ index 3f319dea0d8..67262c2ccfd 100644 | var_identifier '(' func_arguments ')' { if (!($$ = add_call(ctx, $1, &$3, &@1))) +@@ -8400,6 +8683,25 @@ primary_expr: + } + vkd3d_free($1); + } ++ | KW_SAMPLER_STATE '{' state_block_start state_block '}' ++ { ++ struct hlsl_ir_node *sampler_state; ++ ctx->in_state_block = 0; ++ ++ if (!ctx->in_state_block && ctx->cur_scope != ctx->globals) ++ hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_MISPLACED_SAMPLER_STATE, ++ "sampler_state must be in global scope or a state block."); ++ ++ if (!(sampler_state = hlsl_new_sampler_state(ctx, $4, &@1))) ++ { ++ hlsl_free_state_block($4); ++ YYABORT; ++ } ++ hlsl_free_state_block($4); ++ ++ if (!($$ = make_block(ctx, sampler_state))) ++ YYABORT; ++ } + | NEW_IDENTIFIER + { + if (ctx->in_state_block) +@@ -8416,7 +8718,11 @@ primary_expr: + else + { + hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Identifier \"%s\" is not declared.", $1); +- YYABORT; ++ vkd3d_free($1); ++ ++ if (!($$ = make_empty_block(ctx))) ++ YYABORT; ++ $$->value = ctx->error_instr; + } + } + diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 92b5c71c43f..6cae0e3b5c9 100644 +index 92b5c71c43f..c5dd5e71e02 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -4050,6 +4050,7 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +@@ -1655,11 +1655,16 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, + case HLSL_CLASS_MATRIX: + case HLSL_CLASS_ARRAY: + case HLSL_CLASS_STRUCT: +- case HLSL_CLASS_CONSTANT_BUFFER: +- /* FIXME: Actually we shouldn't even get here, but we don't split +- * matrices yet. */ ++ /* We can't handle complex types here. ++ * They should have been already split anyway by earlier passes, ++ * but they may not have been deleted yet. We can't rely on DCE to ++ * solve that problem for us, since we may be called on a partial ++ * block, but DCE deletes dead stores, so it needs to be able to ++ * see the whole program. */ ++ case HLSL_CLASS_ERROR: + return false; + ++ case HLSL_CLASS_CONSTANT_BUFFER: + case HLSL_CLASS_EFFECT_GROUP: + case HLSL_CLASS_PASS: + case HLSL_CLASS_TECHNIQUE: +@@ -4050,12 +4055,14 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) switch (instr->type) { case HLSL_IR_CONSTANT: @@ -4454,17 +7278,25 @@ index 92b5c71c43f..6cae0e3b5c9 100644 case HLSL_IR_EXPR: case HLSL_IR_INDEX: case HLSL_IR_LOAD: -@@ -4337,6 +4338,9 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop + case HLSL_IR_RESOURCE_LOAD: + case HLSL_IR_STRING_CONSTANT: + case HLSL_IR_SWIZZLE: ++ case HLSL_IR_SAMPLER_STATE: + if (list_empty(&instr->uses)) + { + list_remove(&instr->entry); +@@ -4337,6 +4344,10 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop case HLSL_IR_CONSTANT: case HLSL_IR_STRING_CONSTANT: break; + case HLSL_IR_COMPILE: -+ /* Compile calls are skipped as they are only relevent to effects. */ ++ case HLSL_IR_SAMPLER_STATE: ++ /* These types are skipped as they are only relevant to effects. */ + break; } } } -@@ -4816,7 +4820,8 @@ static void allocate_temp_registers_recurse(struct hlsl_ctx *ctx, +@@ -4816,7 +4827,8 @@ static void allocate_temp_registers_recurse(struct hlsl_ctx *ctx, } } @@ -4474,7 +7306,7 @@ index 92b5c71c43f..6cae0e3b5c9 100644 { struct hlsl_constant_defs *defs = &ctx->constant_defs; struct hlsl_constant_register *reg; -@@ -4838,6 +4843,7 @@ static void record_constant(struct hlsl_ctx *ctx, unsigned int component_index, +@@ -4838,6 +4850,7 @@ static void record_constant(struct hlsl_ctx *ctx, unsigned int component_index, memset(reg, 0, sizeof(*reg)); reg->index = component_index / 4; reg->value.f[component_index % 4] = f; @@ -4482,7 +7314,7 @@ index 92b5c71c43f..6cae0e3b5c9 100644 } static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, -@@ -4898,7 +4904,7 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, +@@ -4898,7 +4911,7 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, vkd3d_unreachable(); } @@ -4491,7 +7323,7 @@ index 92b5c71c43f..6cae0e3b5c9 100644 } break; -@@ -4991,17 +4997,17 @@ static void allocate_sincos_const_registers(struct hlsl_ctx *ctx, struct hlsl_bl +@@ -4991,17 +5004,17 @@ static void allocate_sincos_const_registers(struct hlsl_ctx *ctx, struct hlsl_bl ctx->d3dsincosconst1 = allocate_numeric_registers_for_type(ctx, allocator, 1, UINT_MAX, type); TRACE("Allocated D3DSINCOSCONST1 to %s.\n", debug_register('c', ctx->d3dsincosconst1, type)); @@ -4517,7 +7349,7 @@ index 92b5c71c43f..6cae0e3b5c9 100644 return; } -@@ -5128,7 +5134,7 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var +@@ -5128,7 +5141,7 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var if (ctx->profile->major_version < 4) { struct vkd3d_shader_version version; @@ -4526,7 +7358,7 @@ index 92b5c71c43f..6cae0e3b5c9 100644 uint32_t usage_idx; /* ps_1_* outputs are special and go in temp register 0. */ -@@ -5152,10 +5158,10 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var +@@ -5152,10 +5165,10 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var } else { @@ -4539,7 +7371,74 @@ index 92b5c71c43f..6cae0e3b5c9 100644 { hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC, "Invalid semantic '%s'.", var->semantic.name); -@@ -5786,6 +5792,26 @@ struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_dere +@@ -5195,7 +5208,8 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx) + } + } + +-static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint32_t space, uint32_t index) ++static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, ++ uint32_t space, uint32_t index, bool allocated_only) + { + const struct hlsl_buffer *buffer; + +@@ -5203,7 +5217,12 @@ static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint3 + { + if (buffer->reservation.reg_type == 'b' + && buffer->reservation.reg_space == space && buffer->reservation.reg_index == index) ++ { ++ if (allocated_only && !buffer->reg.allocated) ++ continue; ++ + return buffer; ++ } + } + return NULL; + } +@@ -5386,8 +5405,8 @@ static void allocate_buffers(struct hlsl_ctx *ctx) + + if (reservation->reg_type == 'b') + { +- const struct hlsl_buffer *reserved_buffer = get_reserved_buffer(ctx, +- reservation->reg_space, reservation->reg_index); ++ const struct hlsl_buffer *allocated_buffer = get_reserved_buffer(ctx, ++ reservation->reg_space, reservation->reg_index, true); + unsigned int max_index = get_max_cbuffer_reg_index(ctx); + + if (buffer->reservation.reg_index > max_index) +@@ -5395,14 +5414,14 @@ static void allocate_buffers(struct hlsl_ctx *ctx) + "Buffer reservation cb%u exceeds target's maximum (cb%u).", + buffer->reservation.reg_index, max_index); + +- if (reserved_buffer && reserved_buffer != buffer) ++ if (allocated_buffer && allocated_buffer != buffer) + { + hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_OVERLAPPING_RESERVATIONS, + "Multiple buffers bound to space %u, index %u.", + reservation->reg_space, reservation->reg_index); +- hlsl_note(ctx, &reserved_buffer->loc, VKD3D_SHADER_LOG_ERROR, ++ hlsl_note(ctx, &allocated_buffer->loc, VKD3D_SHADER_LOG_ERROR, + "Buffer %s is already bound to space %u, index %u.", +- reserved_buffer->name, reservation->reg_space, reservation->reg_index); ++ allocated_buffer->name, reservation->reg_space, reservation->reg_index); + } + + buffer->reg.space = reservation->reg_space; +@@ -5419,12 +5438,12 @@ static void allocate_buffers(struct hlsl_ctx *ctx) + else if (!reservation->reg_type) + { + unsigned int max_index = get_max_cbuffer_reg_index(ctx); +- while (get_reserved_buffer(ctx, 0, index)) ++ while (get_reserved_buffer(ctx, 0, index, false)) + ++index; + + if (index > max_index) + hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, +- "Too many buffers allocated, target's maximum is %u.", max_index); ++ "Too many buffers reserved, target's maximum is %u.", max_index); + + buffer->reg.space = 0; + buffer->reg.index = index; +@@ -5786,6 +5805,26 @@ struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_dere return ret; } @@ -4566,7 +7465,7 @@ index 92b5c71c43f..6cae0e3b5c9 100644 static void parse_numthreads_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr) { unsigned int i; -@@ -5834,6 +5860,263 @@ static void parse_numthreads_attribute(struct hlsl_ctx *ctx, const struct hlsl_a +@@ -5834,6 +5873,263 @@ static void parse_numthreads_attribute(struct hlsl_ctx *ctx, const struct hlsl_a } } @@ -4830,7 +7729,25 @@ index 92b5c71c43f..6cae0e3b5c9 100644 static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *body) { struct hlsl_ir_node *instr, *next; -@@ -5956,8 +6239,8 @@ static void sm1_generate_vsir_signature_entry(struct hlsl_ctx *ctx, +@@ -5890,12 +6186,16 @@ static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *bod + } + } + ++void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body) ++{ ++ lower_ir(ctx, lower_index_loads, body); ++} ++ + void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body) + { + bool progress; + + lower_ir(ctx, lower_matrix_swizzles, body); +- lower_ir(ctx, lower_index_loads, body); + + lower_ir(ctx, lower_broadcasts, body); + while (hlsl_transform_ir(ctx, fold_redundant_casts, body, NULL)); +@@ -5956,8 +6256,8 @@ static void sm1_generate_vsir_signature_entry(struct hlsl_ctx *ctx, if (!hlsl_sm1_register_from_semantic(&program->shader_version, var->semantic.name, var->semantic.index, output, &type, ®ister_index)) { @@ -4840,7 +7757,7 @@ index 92b5c71c43f..6cae0e3b5c9 100644 bool ret; register_index = var->regs[HLSL_REGSET_NUMERIC].id; -@@ -5969,7 +6252,7 @@ static void sm1_generate_vsir_signature_entry(struct hlsl_ctx *ctx, +@@ -5969,7 +6269,7 @@ static void sm1_generate_vsir_signature_entry(struct hlsl_ctx *ctx, * SV_Position; the closer equivalent is VPOS, which is not declared * as a semantic. */ if (program->shader_version.type == VKD3D_SHADER_TYPE_VERTEX @@ -4849,7 +7766,7 @@ index 92b5c71c43f..6cae0e3b5c9 100644 sysval = VKD3D_SHADER_SV_POSITION; } mask = (1 << var->data_type->dimx) - 1; -@@ -6006,104 +6289,1018 @@ static void sm1_generate_vsir_signature(struct hlsl_ctx *ctx, struct vsir_progra +@@ -6006,101 +6306,1036 @@ static void sm1_generate_vsir_signature(struct hlsl_ctx *ctx, struct vsir_progra } } @@ -4871,8 +7788,7 @@ index 92b5c71c43f..6cae0e3b5c9 100644 - ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; - return; - } -+ uint32_t swizzle; - +- - write_sm1_uniforms(ctx, &buffer); - if (buffer.status) - { @@ -4882,7 +7798,8 @@ index 92b5c71c43f..6cae0e3b5c9 100644 - } - ctab->code = buffer.data; - ctab->size = buffer.size; -- ++ uint32_t swizzle; + - sm1_generate_vsir_signature(ctx, program); + swizzle = hlsl_swizzle_from_writemask(src_writemask); + swizzle = hlsl_map_swizzle(swizzle, dst_writemask); @@ -4978,27 +7895,45 @@ index 92b5c71c43f..6cae0e3b5c9 100644 { - *found_block = block; - return jump; +- } +- } +- } + sampler_dim = var->objects_usage[HLSL_REGSET_SAMPLERS][i].sampler_dim; -+ + +- return NULL; +-} + switch (sampler_dim) + { + case HLSL_SAMPLER_DIM_2D: + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; + break; -+ + +-static unsigned int loop_unrolling_get_max_iterations(struct hlsl_ctx *ctx, struct hlsl_ir_loop *loop) +-{ +- /* Always use the explicit limit if it has been passed. */ +- if (loop->unroll_limit) +- return loop->unroll_limit; + case HLSL_SAMPLER_DIM_CUBE: + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_CUBE; + break; -+ + +- /* All SMs will default to 1024 if [unroll] has been specified without an explicit limit. */ +- if (loop->unroll_type == HLSL_IR_LOOP_FORCE_UNROLL) +- return 1024; + case HLSL_SAMPLER_DIM_3D: + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_3D; + break; -+ + +- /* SM4 limits implicit unrolling to 254 iterations. */ +- if (hlsl_version_ge(ctx, 4, 0)) +- return 254; + case HLSL_SAMPLER_DIM_GENERIC: + /* These can appear in sm4-style combined sample instructions. */ + hlsl_fixme(ctx, &var->loc, "Generic samplers need to be lowered."); + continue; -+ + +- /* SM<3 implicitly unrolls up to 1024 iterations. */ +- return 1024; + default: + vkd3d_unreachable(); + break; @@ -5029,22 +7964,29 @@ index 92b5c71c43f..6cae0e3b5c9 100644 + range = &semantic->resource.range; + range->space = 0; + range->first = range->last = dst_param->reg.idx[0].offset; - } - } - } -+} ++ } ++ } ++ } + } -- return NULL; +-static bool loop_unrolling_unroll_loop(struct hlsl_ctx *ctx, struct hlsl_block *block, +- struct hlsl_block *loop_parent, struct hlsl_ir_loop *loop) +static struct vkd3d_shader_instruction *generate_vsir_add_program_instruction( + struct hlsl_ctx *ctx, struct vsir_program *program, + const struct vkd3d_shader_location *loc, enum vkd3d_shader_opcode opcode, + unsigned int dst_count, unsigned int src_count) -+{ + { +- unsigned int max_iterations, i; +- +- max_iterations = loop_unrolling_get_max_iterations(ctx, loop); + struct vkd3d_shader_instruction_array *instructions = &program->instructions; + struct vkd3d_shader_instruction *ins; -+ + +- for (i = 0; i < max_iterations; ++i) + if (!shader_instruction_array_reserve(instructions, instructions->count + 1)) -+ { + { +- struct hlsl_block tmp_dst, *jump_block; +- struct hlsl_ir_jump *jump = NULL; + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + return NULL; + } @@ -5056,34 +7998,22 @@ index 92b5c71c43f..6cae0e3b5c9 100644 + } + ++instructions->count; + return ins; - } - --static unsigned int loop_unrolling_get_max_iterations(struct hlsl_ctx *ctx, struct hlsl_ir_loop *loop) ++} ++ +static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, + struct vsir_program *program, struct hlsl_ir_constant *constant) - { -- /* Always use the explicit limit if it has been passed. */ -- if (loop->unroll_limit) -- return loop->unroll_limit; ++{ + struct hlsl_ir_node *instr = &constant->node; + struct vkd3d_shader_dst_param *dst_param; + struct vkd3d_shader_src_param *src_param; + struct vkd3d_shader_instruction *ins; - -- /* All SMs will default to 1024 if [unroll] has been specified without an explicit limit. */ -- if (loop->unroll_type == HLSL_IR_LOOP_FORCE_UNROLL) -- return 1024; ++ + VKD3D_ASSERT(instr->reg.allocated); + VKD3D_ASSERT(constant->reg.allocated); - -- /* SM4 limits implicit unrolling to 254 iterations. */ -- if (hlsl_version_ge(ctx, 4, 0)) -- return 254; ++ + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_MOV, 1, 1))) + return; - -- /* SM<3 implicitly unrolls up to 1024 iterations. */ -- return 1024; ++ + src_param = &ins->src[0]; + vsir_register_init(&src_param->reg, VKD3DSPR_CONST, VKD3D_DATA_FLOAT, 1); + src_param->reg.idx[0].offset = constant->reg.id; @@ -5093,37 +8023,28 @@ index 92b5c71c43f..6cae0e3b5c9 100644 + vsir_register_init(&dst_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); + dst_param->reg.idx[0].offset = instr->reg.id; + dst_param->write_mask = instr->reg.writemask; - } - --static bool loop_unrolling_unroll_loop(struct hlsl_ctx *ctx, struct hlsl_block *block, -- struct hlsl_block *loop_parent, struct hlsl_ir_loop *loop) ++} ++ +/* Translate ops that can be mapped to a single vsir instruction with only one dst register. */ +static void sm1_generate_vsir_instr_expr_single_instr_op(struct hlsl_ctx *ctx, struct vsir_program *program, + struct hlsl_ir_expr *expr, enum vkd3d_shader_opcode opcode, uint32_t src_mod, uint32_t dst_mod, + bool map_src_swizzles) - { -- unsigned int max_iterations, i; ++{ + struct hlsl_ir_node *instr = &expr->node; + struct vkd3d_shader_dst_param *dst_param; + struct vkd3d_shader_src_param *src_param; + struct vkd3d_shader_instruction *ins; + unsigned int i, src_count = 0; - -- max_iterations = loop_unrolling_get_max_iterations(ctx, loop); ++ + VKD3D_ASSERT(instr->reg.allocated); - -- for (i = 0; i < max_iterations; ++i) ++ + for (i = 0; i < HLSL_MAX_OPERANDS; ++i) - { -- struct hlsl_block tmp_dst, *jump_block; -- struct hlsl_ir_jump *jump = NULL; ++ { + if (expr->operands[i].node) + src_count = i + 1; + } + VKD3D_ASSERT(!src_mod || src_count == 1); - -- if (!hlsl_clone_block(ctx, &tmp_dst, &loop->body)) -- return false; ++ + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, src_count))) + return; + @@ -5254,7 +8175,13 @@ index 92b5c71c43f..6cae0e3b5c9 100644 + return true; + + case HLSL_TYPE_DOUBLE: -+ hlsl_fixme(ctx, &instr->loc, "SM1 cast from double to float."); ++ if (ctx->double_as_float_alias) ++ { ++ sm1_generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOV, 0, 0, true); ++ return true; ++ } ++ hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, ++ "The 'double' type is not supported for the %s profile.", ctx->profile->name); + break; + + default: @@ -5292,7 +8219,22 @@ index 92b5c71c43f..6cae0e3b5c9 100644 + break; + + case HLSL_TYPE_DOUBLE: -+ hlsl_fixme(ctx, &instr->loc, "SM1 cast to double."); ++ switch (src_type->e.numeric.type) ++ { ++ case HLSL_TYPE_FLOAT: ++ if (ctx->double_as_float_alias) ++ { ++ sm1_generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOV, 0, 0, true); ++ return true; ++ } ++ hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, ++ "The 'double' type is not supported for the %s profile.", ctx->profile->name); ++ break; ++ ++ default: ++ hlsl_fixme(ctx, &instr->loc, "SM1 cast to double."); ++ break; ++ } + break; + + case HLSL_TYPE_BOOL: @@ -5930,13 +8872,10 @@ index 92b5c71c43f..6cae0e3b5c9 100644 + { + struct hlsl_block tmp_dst, *jump_block; + struct hlsl_ir_jump *jump = NULL; -+ -+ if (!hlsl_clone_block(ctx, &tmp_dst, &loop->body)) -+ return false; - list_move_before(&loop->node.entry, &tmp_dst.instrs); - hlsl_block_cleanup(&tmp_dst); -@@ -6406,18 +7603,13 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry + if (!hlsl_clone_block(ctx, &tmp_dst, &loop->body)) + return false; +@@ -6406,18 +7641,13 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry append_output_var_copy(ctx, body, entry_func->return_var); } @@ -5961,7 +8900,7 @@ index 92b5c71c43f..6cae0e3b5c9 100644 hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE, "Entry point \"%s\" is missing a [numthreads] attribute.", entry_func->func->name); -@@ -6540,7 +7732,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry +@@ -6540,7 +7770,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry return ctx->result; } @@ -6013,7 +8952,7 @@ index db4913b7c62..716adb15f08 100644 break; } diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 747238e2fee..db9992d9715 100644 +index 747238e2fee..6a74e2eb8de 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -19,6 +19,15 @@ @@ -6049,7 +8988,7 @@ index 747238e2fee..db9992d9715 100644 return shader_instruction_array_init(&program->instructions, reserve); } -@@ -117,26 +127,137 @@ const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( +@@ -117,26 +127,145 @@ const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( return NULL; } @@ -6115,7 +9054,7 @@ index 747238e2fee..db9992d9715 100644 + +static void vsir_src_param_init_resource(struct vkd3d_shader_src_param *src, unsigned int id, unsigned int idx) +{ -+ vsir_src_param_init(src, VKD3DSPR_RESOURCE, VKD3D_DATA_RESOURCE, 2); ++ vsir_src_param_init(src, VKD3DSPR_RESOURCE, VKD3D_DATA_UNUSED, 2); + src->reg.idx[0].offset = id; + src->reg.idx[1].offset = idx; + src->reg.dimension = VSIR_DIMENSION_VEC4; @@ -6124,7 +9063,7 @@ index 747238e2fee..db9992d9715 100644 + +static void vsir_src_param_init_sampler(struct vkd3d_shader_src_param *src, unsigned int id, unsigned int idx) +{ -+ vsir_src_param_init(src, VKD3DSPR_SAMPLER, VKD3D_DATA_SAMPLER, 2); ++ vsir_src_param_init(src, VKD3DSPR_SAMPLER, VKD3D_DATA_UNUSED, 2); + src->reg.idx[0].offset = id; + src->reg.idx[1].offset = idx; + src->reg.dimension = VSIR_DIMENSION_NONE; @@ -6148,6 +9087,14 @@ index 747238e2fee..db9992d9715 100644 + src->reg.idx[0].offset = idx; +} + ++static void src_param_init_temp_float4(struct vkd3d_shader_src_param *src, unsigned int idx) ++{ ++ vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); ++ src->reg.dimension = VSIR_DIMENSION_VEC4; ++ src->swizzle = VKD3D_SHADER_NO_SWIZZLE; ++ src->reg.idx[0].offset = idx; ++} ++ +static void src_param_init_temp_uint(struct vkd3d_shader_src_param *src, unsigned int idx) +{ + vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); @@ -6180,22 +9127,22 @@ index 747238e2fee..db9992d9715 100644 + vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); + dst->reg.idx[0].offset = idx; + dst->write_mask = VKD3DSP_WRITEMASK_0; - } - --static bool vsir_instruction_init_with_params(struct vsir_program *program, ++} ++ +void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, + enum vkd3d_shader_opcode opcode) +{ + memset(ins, 0, sizeof(*ins)); + ins->location = *location; + ins->opcode = opcode; -+} -+ + } + +-static bool vsir_instruction_init_with_params(struct vsir_program *program, +bool vsir_instruction_init_with_params(struct vsir_program *program, struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode opcode, unsigned int dst_count, unsigned int src_count) { -@@ -161,6 +282,37 @@ static bool vsir_instruction_init_with_params(struct vsir_program *program, +@@ -161,6 +290,37 @@ static bool vsir_instruction_init_with_params(struct vsir_program *program, return true; } @@ -6233,7 +9180,7 @@ index 747238e2fee..db9992d9715 100644 static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_data_type data_type, enum vkd3d_shader_opcode *opcode, bool *requires_swap) { -@@ -441,10 +593,58 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog +@@ -441,10 +601,58 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog return VKD3D_OK; } @@ -6293,7 +9240,7 @@ index 747238e2fee..db9992d9715 100644 unsigned int tmp_idx = ~0u, i; enum vkd3d_result ret; -@@ -481,6 +681,38 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr +@@ -481,6 +689,38 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr return ret; break; @@ -6332,7 +9279,7 @@ index 747238e2fee..db9992d9715 100644 default: break; } -@@ -541,9 +773,11 @@ static const struct vkd3d_shader_varying_map *find_varying_map( +@@ -541,9 +781,11 @@ static const struct vkd3d_shader_varying_map *find_varying_map( } static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program *program, @@ -6346,7 +9293,7 @@ index 747238e2fee..db9992d9715 100644 struct shader_signature *signature = &program->output_signature; const struct vkd3d_shader_varying_map_info *varying_map; unsigned int i; -@@ -727,174 +961,50 @@ static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normali +@@ -727,147 +969,23 @@ static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normali return VKD3D_OK; } @@ -6371,48 +9318,21 @@ index 747238e2fee..db9992d9715 100644 - reg->idx_count = idx_count; - reg->dimension = VSIR_DIMENSION_SCALAR; - reg->alignment = 0; +-} + struct hull_flattener flattener = {program->instructions}; + struct vkd3d_shader_instruction_array *instructions; + struct shader_phase_location_array locations; + enum vkd3d_result result = VKD3D_OK; + unsigned int i; -+ -+ instructions = &flattener.instructions; -+ -+ flattener.phase = VKD3DSIH_INVALID; -+ for (i = 0, locations.count = 0; i < instructions->count; ++i) -+ flattener_eliminate_phase_related_dcls(&flattener, i, &locations); -+ -+ if ((result = flattener_flatten_phases(&flattener, &locations)) < 0) -+ return result; -+ -+ if (flattener.phase != VKD3DSIH_INVALID) -+ { -+ if (!shader_instruction_array_reserve(&flattener.instructions, flattener.instructions.count + 1)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ vsir_instruction_init(&instructions->elements[instructions->count++], &flattener.last_ret_location, VKD3DSIH_RET); -+ } -+ -+ program->instructions = flattener.instructions; -+ return result; - } -void vsir_src_param_init(struct vkd3d_shader_src_param *param, enum vkd3d_shader_register_type reg_type, - enum vkd3d_data_type data_type, unsigned int idx_count) -+struct control_point_normaliser - { +-{ - vsir_register_init(¶m->reg, reg_type, data_type, idx_count); - param->swizzle = 0; - param->modifiers = VKD3DSPSM_NONE; -+ struct vkd3d_shader_instruction_array instructions; -+ enum vkd3d_shader_opcode phase; -+ struct vkd3d_shader_src_param *outpointid_param; -+}; -+ -+static bool control_point_normaliser_is_in_control_point_phase(const struct control_point_normaliser *normaliser) -+{ -+ return normaliser->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE; - } +-} ++ instructions = &flattener.instructions; -void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, - enum vkd3d_data_type data_type, unsigned int idx_count) @@ -6422,7 +9342,10 @@ index 747238e2fee..db9992d9715 100644 - param->modifiers = VKD3DSPDM_NONE; - param->shift = 0; -} -- ++ flattener.phase = VKD3DSIH_INVALID; ++ for (i = 0, locations.count = 0; i < instructions->count; ++i) ++ flattener_eliminate_phase_related_dcls(&flattener, i, &locations); + -void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id) -{ - vsir_src_param_init(param, VKD3DSPR_LABEL, VKD3D_DATA_UNUSED, 1); @@ -6526,30 +9449,24 @@ index 747238e2fee..db9992d9715 100644 - - if ((result = flattener_flatten_phases(&flattener, &locations)) < 0) - return result; -- -- if (flattener.phase != VKD3DSIH_INVALID) -- { -- if (!shader_instruction_array_reserve(&flattener.instructions, flattener.instructions.count + 1)) -- return VKD3D_ERROR_OUT_OF_MEMORY; -- vsir_instruction_init(&instructions->elements[instructions->count++], &flattener.last_ret_location, VKD3DSIH_RET); -- } -- ++ if ((result = flattener_flatten_phases(&flattener, &locations)) < 0) ++ return result; + + if (flattener.phase != VKD3DSIH_INVALID) + { +@@ -876,7 +994,7 @@ static enum vkd3d_result instruction_array_flatten_hull_shader_phases(struct vkd + vsir_instruction_init(&instructions->elements[instructions->count++], &flattener.last_ret_location, VKD3DSIH_RET); + } + - *src_instructions = flattener.instructions; -- return result; --} -- --struct control_point_normaliser --{ -- struct vkd3d_shader_instruction_array instructions; -- enum vkd3d_shader_opcode phase; -- struct vkd3d_shader_src_param *outpointid_param; --}; -- --static bool control_point_normaliser_is_in_control_point_phase(const struct control_point_normaliser *normaliser) --{ -- return normaliser->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE; --} -- ++ program->instructions = flattener.instructions; + return result; + } + +@@ -892,9 +1010,9 @@ static bool control_point_normaliser_is_in_control_point_phase(const struct cont + return normaliser->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE; + } + -struct vkd3d_shader_src_param *instruction_array_create_outpointid_param( - struct vkd3d_shader_instruction_array *instructions) +struct vkd3d_shader_src_param *vsir_program_create_outpointid_param(struct vsir_program *program) @@ -6558,7 +9475,7 @@ index 747238e2fee..db9992d9715 100644 struct vkd3d_shader_src_param *rel_addr; if (instructions->outpointid_param) -@@ -991,7 +1101,7 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p +@@ -991,7 +1109,7 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p } static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_io( @@ -6567,7 +9484,7 @@ index 747238e2fee..db9992d9715 100644 { struct vkd3d_shader_instruction_array *instructions; struct control_point_normaliser normaliser; -@@ -1001,12 +1111,12 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i +@@ -1001,12 +1119,12 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i enum vkd3d_result ret; unsigned int i, j; @@ -6582,7 +9499,7 @@ index 747238e2fee..db9992d9715 100644 instructions = &normaliser.instructions; normaliser.phase = VKD3DSIH_INVALID; -@@ -1043,22 +1153,22 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i +@@ -1043,22 +1161,22 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i input_control_point_count = ins->declaration.count; break; case VKD3DSIH_HS_CONTROL_POINT_PHASE: @@ -6609,7 +9526,7 @@ index 747238e2fee..db9992d9715 100644 return VKD3D_OK; } -@@ -1098,8 +1208,8 @@ static bool io_normaliser_is_in_control_point_phase(const struct io_normaliser * +@@ -1098,18 +1216,20 @@ static bool io_normaliser_is_in_control_point_phase(const struct io_normaliser * return normaliser->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE; } @@ -6618,10 +9535,15 @@ index 747238e2fee..db9992d9715 100644 +static bool shader_signature_find_element_for_reg(const struct shader_signature *signature, + unsigned int reg_idx, unsigned int write_mask, unsigned int *element_idx) { ++ const struct signature_element *e; unsigned int i, base_write_mask; -@@ -1109,7 +1219,8 @@ static unsigned int shader_signature_find_element_for_reg(const struct shader_si - if (e->register_index <= reg_idx && e->register_index + e->register_count > reg_idx + for (i = 0; i < signature->element_count; ++i) + { +- struct signature_element *e = &signature->elements[i]; +- if (e->register_index <= reg_idx && e->register_index + e->register_count > reg_idx ++ e = &signature->elements[i]; ++ if (e->register_index <= reg_idx && e->register_count > reg_idx - e->register_index && (e->mask & write_mask) == write_mask) { - return i; @@ -6630,7 +9552,7 @@ index 747238e2fee..db9992d9715 100644 } } -@@ -1119,15 +1230,20 @@ static unsigned int shader_signature_find_element_for_reg(const struct shader_si +@@ -1119,15 +1239,20 @@ static unsigned int shader_signature_find_element_for_reg(const struct shader_si reg_idx, write_mask); base_write_mask = 1u << vsir_write_mask_get_component_idx(write_mask); if (base_write_mask != write_mask) @@ -6654,7 +9576,7 @@ index 747238e2fee..db9992d9715 100644 } static unsigned int range_map_get_register_count(uint8_t range_map[][VKD3D_VEC4_SIZE], -@@ -1181,9 +1297,10 @@ static void io_normaliser_add_index_range(struct io_normaliser *normaliser, +@@ -1181,9 +1306,10 @@ static void io_normaliser_add_index_range(struct io_normaliser *normaliser, { const struct vkd3d_shader_index_range *range = &ins->declaration.index_range; const struct vkd3d_shader_register *reg = &range->dst.reg; @@ -6666,7 +9588,7 @@ index 747238e2fee..db9992d9715 100644 switch (reg->type) { -@@ -1215,9 +1332,8 @@ static void io_normaliser_add_index_range(struct io_normaliser *normaliser, +@@ -1215,9 +1341,8 @@ static void io_normaliser_add_index_range(struct io_normaliser *normaliser, reg_idx = reg->idx[reg->idx_count - 1].offset; write_mask = range->dst.write_mask; @@ -6678,7 +9600,7 @@ index 747238e2fee..db9992d9715 100644 } static int signature_element_mask_compare(const void *a, const void *b) -@@ -1388,6 +1504,8 @@ static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map +@@ -1388,6 +1513,8 @@ static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map else e->interpolation_mode = f->interpolation_mode; } @@ -6687,7 +9609,7 @@ index 747238e2fee..db9992d9715 100644 } } element_count = new_count; -@@ -1415,6 +1533,12 @@ static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map +@@ -1415,6 +1542,12 @@ static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map TRACE("Merging %s, base reg %u, count %u.\n", e->semantic_name, e->register_index, register_count); e->register_count = register_count; e->mask = signature_element_range_expand_mask(e, register_count, range_map); @@ -6700,7 +9622,7 @@ index 747238e2fee..db9992d9715 100644 } } element_count = new_count; -@@ -1530,7 +1654,8 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par +@@ -1530,7 +1663,8 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par id_idx = reg->idx_count - 1; write_mask = dst_param->write_mask; @@ -6710,7 +9632,7 @@ index 747238e2fee..db9992d9715 100644 e = &signature->elements[element_idx]; dst_param->write_mask >>= vsir_write_mask_get_component_idx(e->mask); -@@ -1653,7 +1778,8 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par +@@ -1653,7 +1787,8 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par id_idx = reg->idx_count - 1; write_mask = VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(src_param->swizzle, 0); @@ -6720,7 +9642,23 @@ index 747238e2fee..db9992d9715 100644 e = &signature->elements[element_idx]; if ((e->register_count > 1 || vsir_sysval_semantic_is_tess_factor(e->sysval_semantic))) -@@ -1751,12 +1877,12 @@ static bool use_flat_interpolation(const struct vsir_program *program, +@@ -1737,13 +1872,13 @@ static bool use_flat_interpolation(const struct vsir_program *program, + if (parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) + { + vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, +- "Unsupported flat interpolation parameter type %#x.\n", parameter->type); ++ "Unsupported flat interpolation parameter type %#x.", parameter->type); + return false; + } + if (parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) + { + vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, +- "Invalid flat interpolation parameter data type %#x.\n", parameter->data_type); ++ "Invalid flat interpolation parameter data type %#x.", parameter->data_type); + return false; + } + +@@ -1751,12 +1886,12 @@ static bool use_flat_interpolation(const struct vsir_program *program, } static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program *program, @@ -6736,7 +9674,7 @@ index 747238e2fee..db9992d9715 100644 normaliser.phase = VKD3DSIH_INVALID; normaliser.shader_type = program->shader_version.type; -@@ -1765,7 +1891,7 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program +@@ -1765,7 +1900,7 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program normaliser.output_signature = &program->output_signature; normaliser.patch_constant_signature = &program->patch_constant_signature; @@ -6745,7 +9683,7 @@ index 747238e2fee..db9992d9715 100644 { ins = &program->instructions.elements[i]; -@@ -1779,8 +1905,6 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program +@@ -1779,8 +1914,6 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program vkd3d_shader_instruction_make_nop(ins); break; case VKD3DSIH_HS_CONTROL_POINT_PHASE: @@ -6754,7 +9692,7 @@ index 747238e2fee..db9992d9715 100644 case VKD3DSIH_HS_FORK_PHASE: case VKD3DSIH_HS_JOIN_PHASE: normaliser.phase = ins->opcode; -@@ -1790,22 +1914,6 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program +@@ -1790,22 +1923,6 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program } } @@ -6777,7 +9715,7 @@ index 747238e2fee..db9992d9715 100644 if (!shader_signature_merge(&program->input_signature, normaliser.input_range_map, false) || !shader_signature_merge(&program->output_signature, normaliser.output_range_map, false) || !shader_signature_merge(&program->patch_constant_signature, normaliser.pc_range_map, true)) -@@ -1918,7 +2026,8 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par +@@ -1918,7 +2035,8 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par param->reg.idx_count = 3; } @@ -6787,7 +9725,7 @@ index 747238e2fee..db9992d9715 100644 { struct flat_constants_normaliser normaliser = {0}; unsigned int i, j; -@@ -1957,7 +2066,8 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vsir_ +@@ -1957,7 +2075,8 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vsir_ return VKD3D_OK; } @@ -6797,7 +9735,7 @@ index 747238e2fee..db9992d9715 100644 { size_t i, depth = 0; bool dead = false; -@@ -2045,103 +2155,6 @@ static void remove_dead_code(struct vsir_program *program) +@@ -2045,103 +2164,6 @@ static void remove_dead_code(struct vsir_program *program) break; } } @@ -6901,7 +9839,7 @@ index 747238e2fee..db9992d9715 100644 return VKD3D_OK; } -@@ -2789,11 +2802,14 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -2789,11 +2811,14 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte } static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsir_program *program, @@ -6917,7 +9855,7 @@ index 747238e2fee..db9992d9715 100644 if ((result = cf_flattener_iterate_instruction_array(&flattener, message_context)) >= 0) { vkd3d_free(program->instructions.elements); -@@ -2801,6 +2817,7 @@ static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsi +@@ -2801,6 +2826,7 @@ static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsi program->instructions.capacity = flattener.instruction_capacity; program->instructions.count = flattener.instruction_count; program->block_count = flattener.block_id; @@ -6925,7 +9863,7 @@ index 747238e2fee..db9992d9715 100644 } else { -@@ -2860,13 +2877,16 @@ static bool lower_switch_to_if_ladder_add_block_mapping(struct lower_switch_to_i +@@ -2860,13 +2886,16 @@ static bool lower_switch_to_if_ladder_add_block_mapping(struct lower_switch_to_i return true; } @@ -6943,7 +9881,7 @@ index 747238e2fee..db9992d9715 100644 if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count)) goto fail; -@@ -3050,7 +3070,8 @@ static void ssas_to_temps_block_info_cleanup(struct ssas_to_temps_block_info *bl +@@ -3050,7 +3079,8 @@ static void ssas_to_temps_block_info_cleanup(struct ssas_to_temps_block_info *bl vkd3d_free(block_info); } @@ -6953,7 +9891,7 @@ index 747238e2fee..db9992d9715 100644 { size_t ins_capacity = 0, ins_count = 0, phi_count, incoming_count, i; struct ssas_to_temps_block_info *info, *block_info = NULL; -@@ -3058,6 +3079,8 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ +@@ -3058,6 +3088,8 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ struct ssas_to_temps_alloc alloc = {0}; unsigned int current_label = 0; @@ -6962,7 +9900,7 @@ index 747238e2fee..db9992d9715 100644 if (!(block_info = vkd3d_calloc(program->block_count, sizeof(*block_info)))) { ERR("Failed to allocate block info array.\n"); -@@ -5271,12 +5294,15 @@ out: +@@ -5271,12 +5303,15 @@ out: } static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, @@ -6979,7 +9917,7 @@ index 747238e2fee..db9992d9715 100644 target.jump_target_temp_idx = program->temp_count; target.temp_count = program->temp_count + 1; -@@ -5324,6 +5350,7 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, +@@ -5324,6 +5359,7 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, program->instructions.capacity = target.ins_capacity; program->instructions.count = target.ins_count; program->temp_count = target.temp_count; @@ -6987,7 +9925,7 @@ index 747238e2fee..db9992d9715 100644 return VKD3D_OK; -@@ -5451,11 +5478,14 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps_in_f +@@ -5451,11 +5487,14 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps_in_f } static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(struct vsir_program *program, @@ -7003,7 +9941,32 @@ index 747238e2fee..db9992d9715 100644 for (i = 0; i < program->instructions.count;) { struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; -@@ -5596,8 +5626,9 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr +@@ -5508,9 +5547,11 @@ static bool find_colour_signature_idx(const struct shader_signature *signature, + + static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *program, + const struct vkd3d_shader_instruction *ret, enum vkd3d_shader_comparison_func compare_func, +- const struct vkd3d_shader_parameter1 *ref, uint32_t colour_signature_idx, uint32_t colour_temp, size_t *ret_pos) ++ const struct vkd3d_shader_parameter1 *ref, uint32_t colour_signature_idx, ++ uint32_t colour_temp, size_t *ret_pos, struct vkd3d_shader_message_context *message_context) + { + struct vkd3d_shader_instruction_array *instructions = &program->instructions; ++ static const struct vkd3d_shader_location no_loc; + size_t pos = ret - instructions->elements; + struct vkd3d_shader_instruction *ins; + +@@ -5565,6 +5606,11 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr + VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF, VKD3D_DATA_UINT); + break; + ++ case VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4: ++ vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER, ++ "Alpha test reference data type must be a single component."); ++ return VKD3D_ERROR_INVALID_ARGUMENT; ++ + default: + FIXME("Unhandled parameter data type %#x.\n", ref->data_type); + return VKD3D_ERROR_NOT_IMPLEMENTED; +@@ -5596,8 +5642,9 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr } static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *program, @@ -7014,37 +9977,542 @@ index 747238e2fee..db9992d9715 100644 const struct vkd3d_shader_parameter1 *func = NULL, *ref = NULL; static const struct vkd3d_shader_location no_loc; enum vkd3d_shader_comparison_func compare_func; -@@ -5687,12 +5718,6 @@ struct validation_context - enum vkd3d_result status; - bool dcl_temps_found; - enum vkd3d_shader_opcode phase; +@@ -5620,13 +5667,13 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro + if (func->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) + { + vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, +- "Unsupported alpha test function parameter type %#x.\n", func->type); ++ "Unsupported alpha test function parameter type %#x.", func->type); + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + if (func->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) + { + vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, +- "Invalid alpha test function parameter data type %#x.\n", func->data_type); ++ "Invalid alpha test function parameter data type %#x.", func->data_type); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + compare_func = func->u.immediate_constant.u.u32; +@@ -5650,7 +5697,7 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro + if (ins->opcode == VKD3DSIH_RET) + { + if ((ret = insert_alpha_test_before_ret(program, ins, compare_func, +- ref, colour_signature_idx, colour_temp, &new_pos)) < 0) ++ ref, colour_signature_idx, colour_temp, &new_pos, message_context)) < 0) + return ret; + i = new_pos; + continue; +@@ -5677,78 +5724,268 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro + return VKD3D_OK; + } + +-struct validation_context ++static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *program, ++ const struct vkd3d_shader_instruction *ret, uint32_t mask, uint32_t position_signature_idx, ++ uint32_t position_temp, uint32_t low_signature_idx, uint32_t high_signature_idx, size_t *ret_pos) + { +- struct vkd3d_shader_message_context *message_context; +- const struct vsir_program *program; +- size_t instruction_idx; +- struct vkd3d_shader_location null_location; +- bool invalid_instruction_idx; +- enum vkd3d_result status; +- bool dcl_temps_found; +- enum vkd3d_shader_opcode phase; - enum cf_type - { - CF_TYPE_UNKNOWN = 0, - CF_TYPE_STRUCTURED, - CF_TYPE_BLOCKS, - } cf_type; - bool inside_block; +- bool inside_block; +- +- struct validation_context_temp_data +- { +- enum vsir_dimension dimension; +- size_t first_seen; +- } *temps; ++ struct vkd3d_shader_instruction_array *instructions = &program->instructions; ++ size_t pos = ret - instructions->elements; ++ struct vkd3d_shader_instruction *ins; ++ unsigned int output_idx = 0; - struct validation_context_temp_data -@@ -5731,14 +5756,14 @@ static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *c - if (ctx->invalid_instruction_idx) - { - vkd3d_shader_error(ctx->message_context, &ctx->null_location, error, "%s", buf.buffer); +- struct validation_context_ssa_data +- { +- enum vsir_dimension dimension; +- enum vkd3d_data_type data_type; +- size_t first_seen; +- uint32_t write_mask; +- uint32_t read_mask; +- size_t first_assigned; +- } *ssas; ++ if (!shader_instruction_array_insert_at(&program->instructions, pos, vkd3d_popcount(mask) + 1)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; + +- enum vkd3d_shader_opcode *blocks; +- size_t depth; +- size_t blocks_capacity; +-}; ++ ins = &program->instructions.elements[pos]; + +-static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *ctx, +- enum vkd3d_shader_error error, const char *format, ...) +-{ +- struct vkd3d_string_buffer buf; +- va_list args; ++ for (unsigned int i = 0; i < 8; ++i) ++ { ++ if (!(mask & (1u << i))) ++ continue; + +- vkd3d_string_buffer_init(&buf); ++ vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_DP4, 1, 2); ++ src_param_init_temp_float4(&ins->src[0], position_temp); ++ src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 + i, VKD3D_DATA_FLOAT); ++ ins->src[1].swizzle = VKD3D_SHADER_NO_SWIZZLE; ++ ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; + +- va_start(args, format); +- vkd3d_string_buffer_vprintf(&buf, format, args); +- va_end(args); ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); ++ if (output_idx < 4) ++ ins->dst[0].reg.idx[0].offset = low_signature_idx; ++ else ++ ins->dst[0].reg.idx[0].offset = high_signature_idx; ++ ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ins->dst[0].write_mask = (1u << (output_idx % 4)); ++ ++output_idx; + +- if (ctx->invalid_instruction_idx) +- { +- vkd3d_shader_error(ctx->message_context, &ctx->null_location, error, "%s", buf.buffer); - ERR("VSIR validation error: %s\n", buf.buffer); -+ WARN("VSIR validation error: %s\n", buf.buffer); - } - else - { - const struct vkd3d_shader_instruction *ins = &ctx->program->instructions.elements[ctx->instruction_idx]; - vkd3d_shader_error(ctx->message_context, &ins->location, error, - "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer); +- } +- else +- { +- const struct vkd3d_shader_instruction *ins = &ctx->program->instructions.elements[ctx->instruction_idx]; +- vkd3d_shader_error(ctx->message_context, &ins->location, error, +- "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer); - ERR("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer); -+ WARN("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer); ++ ++ins; } - vkd3d_string_buffer_cleanup(&buf); -@@ -6105,13 +6130,13 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx, +- vkd3d_string_buffer_cleanup(&buf); ++ vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_MOV, 1, 1); ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); ++ ins->dst[0].reg.idx[0].offset = position_signature_idx; ++ ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ins->dst[0].write_mask = program->output_signature.elements[position_signature_idx].mask; ++ src_param_init_temp_float(&ins->src[0], position_temp); ++ ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; + +- if (!ctx->status) +- ctx->status = VKD3D_ERROR_INVALID_SHADER; ++ *ret_pos = pos + vkd3d_popcount(mask) + 1; ++ return VKD3D_OK; + } + +-static void vsir_validate_src_param(struct validation_context *ctx, +- const struct vkd3d_shader_src_param *src); ++static bool find_position_signature_idx(const struct shader_signature *signature, uint32_t *idx) ++{ ++ for (unsigned int i = 0; i < signature->element_count; ++i) ++ { ++ if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_POSITION) ++ { ++ *idx = i; ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *program, ++ struct vsir_transformation_context *ctx) ++{ ++ struct shader_signature *signature = &program->output_signature; ++ unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u; ++ const struct vkd3d_shader_parameter1 *mask_parameter = NULL; ++ struct signature_element *new_elements, *clip_element; ++ uint32_t position_signature_idx, position_temp, mask; ++ static const struct vkd3d_shader_location no_loc; ++ struct vkd3d_shader_instruction *ins; ++ unsigned int plane_count; ++ size_t new_pos; ++ int ret; ++ ++ if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX) ++ return VKD3D_OK; ++ ++ for (unsigned int i = 0; i < program->parameter_count; ++i) ++ { ++ const struct vkd3d_shader_parameter1 *parameter = &program->parameters[i]; ++ ++ if (parameter->name == VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK) ++ mask_parameter = parameter; ++ } ++ ++ if (!mask_parameter) ++ return VKD3D_OK; ++ ++ if (mask_parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) ++ { ++ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, ++ "Unsupported clip plane mask parameter type %#x.", mask_parameter->type); ++ return VKD3D_ERROR_NOT_IMPLEMENTED; ++ } ++ if (mask_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) ++ { ++ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid clip plane mask parameter data type %#x.", mask_parameter->data_type); ++ return VKD3D_ERROR_INVALID_ARGUMENT; ++ } ++ mask = mask_parameter->u.immediate_constant.u.u32; ++ ++ if (!mask) ++ return VKD3D_OK; ++ ++ for (unsigned int i = 0; i < signature->element_count; ++i) ++ { ++ if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_CLIP_DISTANCE) ++ { ++ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER, ++ "Clip planes cannot be used if the shader writes clip distance."); ++ return VKD3D_ERROR_INVALID_ARGUMENT; ++ } ++ } ++ ++ if (!find_position_signature_idx(signature, &position_signature_idx)) ++ { ++ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC, ++ "Shader does not write position."); ++ return VKD3D_ERROR_INVALID_SHADER; ++ } ++ ++ /* Append the clip plane signature indices. */ ++ ++ plane_count = vkd3d_popcount(mask); ++ ++ if (!(new_elements = vkd3d_realloc(signature->elements, ++ (signature->element_count + 2) * sizeof(*signature->elements)))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ signature->elements = new_elements; ++ ++ low_signature_idx = signature->element_count; ++ clip_element = &signature->elements[signature->element_count++]; ++ memset(clip_element, 0, sizeof(*clip_element)); ++ clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; ++ clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; ++ clip_element->register_count = 1; ++ clip_element->mask = vkd3d_write_mask_from_component_count(min(plane_count, 4)); ++ clip_element->used_mask = clip_element->mask; ++ clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; ++ ++ if (plane_count > 4) ++ { ++ high_signature_idx = signature->element_count; ++ clip_element = &signature->elements[signature->element_count++]; ++ memset(clip_element, 0, sizeof(*clip_element)); ++ clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; ++ clip_element->semantic_index = 1; ++ clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; ++ clip_element->register_count = 1; ++ clip_element->mask = vkd3d_write_mask_from_component_count(plane_count - 4); ++ clip_element->used_mask = clip_element->mask; ++ clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; ++ } ++ ++ /* We're going to be reading from the output position, so we need to go ++ * through the whole shader and convert it to a temp. */ ++ ++ position_temp = program->temp_count++; ++ ++ for (size_t i = 0; i < program->instructions.count; ++i) ++ { ++ ins = &program->instructions.elements[i]; ++ ++ if (vsir_instruction_is_dcl(ins)) ++ continue; ++ ++ if (ins->opcode == VKD3DSIH_RET) ++ { ++ if ((ret = insert_clip_planes_before_ret(program, ins, mask, position_signature_idx, ++ position_temp, low_signature_idx, high_signature_idx, &new_pos)) < 0) ++ return ret; ++ i = new_pos; ++ continue; ++ } ++ ++ for (size_t j = 0; j < ins->dst_count; ++j) ++ { ++ struct vkd3d_shader_dst_param *dst = &ins->dst[j]; ++ ++ /* Note we run after I/O normalization. */ ++ if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == position_signature_idx) ++ { ++ dst->reg.type = VKD3DSPR_TEMP; ++ dst->reg.idx[0].offset = position_temp; ++ } ++ } ++ } ++ ++ return VKD3D_OK; ++} ++ ++struct validation_context ++{ ++ struct vkd3d_shader_message_context *message_context; ++ const struct vsir_program *program; ++ size_t instruction_idx; ++ struct vkd3d_shader_location null_location; ++ bool invalid_instruction_idx; ++ enum vkd3d_result status; ++ bool dcl_temps_found; ++ enum vkd3d_shader_opcode phase; ++ bool inside_block; ++ ++ struct validation_context_temp_data ++ { ++ enum vsir_dimension dimension; ++ size_t first_seen; ++ } *temps; ++ ++ struct validation_context_ssa_data ++ { ++ enum vsir_dimension dimension; ++ enum vkd3d_data_type data_type; ++ size_t first_seen; ++ uint32_t write_mask; ++ uint32_t read_mask; ++ size_t first_assigned; ++ } *ssas; ++ ++ enum vkd3d_shader_opcode *blocks; ++ size_t depth; ++ size_t blocks_capacity; ++}; ++ ++static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *ctx, ++ enum vkd3d_shader_error error, const char *format, ...) ++{ ++ struct vkd3d_string_buffer buf; ++ va_list args; ++ ++ vkd3d_string_buffer_init(&buf); ++ ++ va_start(args, format); ++ vkd3d_string_buffer_vprintf(&buf, format, args); ++ va_end(args); ++ ++ if (ctx->invalid_instruction_idx) ++ { ++ vkd3d_shader_error(ctx->message_context, &ctx->null_location, error, "%s", buf.buffer); ++ WARN("VSIR validation error: %s\n", buf.buffer); ++ } ++ else ++ { ++ const struct vkd3d_shader_instruction *ins = &ctx->program->instructions.elements[ctx->instruction_idx]; ++ vkd3d_shader_error(ctx->message_context, &ins->location, error, ++ "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer); ++ WARN("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer); ++ } ++ ++ vkd3d_string_buffer_cleanup(&buf); ++ ++ if (!ctx->status) ++ ctx->status = VKD3D_ERROR_INVALID_SHADER; ++} ++ ++static void vsir_validate_src_param(struct validation_context *ctx, ++ const struct vkd3d_shader_src_param *src); + + static void vsir_validate_register(struct validation_context *ctx, + const struct vkd3d_shader_register *reg) +@@ -5934,6 +6171,151 @@ static void vsir_validate_register(struct validation_context *ctx, + reg->idx_count); + break; + ++ case VKD3DSPR_SAMPLER: ++ if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, ++ "Invalid precision %#x for a SAMPLER register.", ++ reg->precision); ++ ++ if (reg->data_type != VKD3D_DATA_UNUSED) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for a SAMPLER register.", ++ reg->data_type); ++ ++ /* VEC4 is allowed in gather operations. */ ++ if (reg->dimension == VSIR_DIMENSION_SCALAR) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, ++ "Invalid dimension SCALAR for a SAMPLER register."); ++ ++ if (reg->idx_count != 2) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a SAMPLER register.", ++ reg->idx_count); ++ break; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for the descriptor index of a SAMPLER register."); ++ break; ++ ++ case VKD3DSPR_RESOURCE: ++ if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, ++ "Invalid precision %#x for a RESOURCE register.", ++ reg->precision); ++ ++ if (reg->data_type != VKD3D_DATA_UNUSED) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for a RESOURCE register.", ++ reg->data_type); ++ ++ if (reg->dimension != VSIR_DIMENSION_VEC4) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, ++ "Invalid dimension %#x for a RESOURCE register.", ++ reg->dimension); ++ ++ if (reg->idx_count != 2) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a RESOURCE register.", ++ reg->idx_count); ++ break; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for the descriptor index of a RESOURCE register."); ++ break; ++ ++ case VKD3DSPR_UAV: ++ if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, ++ "Invalid precision %#x for a UAV register.", ++ reg->precision); ++ ++ if (reg->data_type != VKD3D_DATA_UNUSED) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for a UAV register.", ++ reg->data_type); ++ ++ /* NONE is allowed in counter operations. */ ++ if (reg->dimension == VSIR_DIMENSION_SCALAR) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, ++ "Invalid dimension %#x for a UAV register.", ++ reg->dimension); ++ ++ if (reg->idx_count != 2) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a UAV register.", ++ reg->idx_count); ++ break; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for the descriptor index of a UAV register."); ++ break; ++ ++ case VKD3DSPR_DEPTHOUT: ++ if (reg->idx_count != 0) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a DEPTHOUT register.", ++ reg->idx_count); ++ break; ++ ++ case VKD3DSPR_DEPTHOUTGE: ++ if (reg->idx_count != 0) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a DEPTHOUTGE register.", ++ reg->idx_count); ++ break; ++ ++ case VKD3DSPR_DEPTHOUTLE: ++ if (reg->idx_count != 0) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a DEPTHOUTLE register.", ++ reg->idx_count); ++ break; ++ ++ case VKD3DSPR_RASTOUT: ++ if (reg->idx_count != 1) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a RASTOUT register.", ++ reg->idx_count); ++ break; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for a RASTOUT register."); ++ ++ if (reg->idx[0].offset >= 3) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Invalid offset for a RASTOUT register."); ++ break; ++ ++ case VKD3DSPR_MISCTYPE: ++ if (reg->idx_count != 1) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a MISCTYPE register.", ++ reg->idx_count); ++ break; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for a MISCTYPE register."); ++ ++ if (reg->idx[0].offset >= 2) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Invalid offset for a MISCTYPE register."); ++ break; ++ + default: + break; + } +@@ -6019,6 +6401,16 @@ static void vsir_validate_dst_param(struct validation_context *ctx, + "Invalid IMMCONST64 register used as destination parameter."); + break; + ++ case VKD3DSPR_SAMPLER: ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "Invalid SAMPLER register used as destination parameter."); ++ break; ++ ++ case VKD3DSPR_RESOURCE: ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "Invalid RESOURCE register used as destination parameter."); ++ break; ++ + default: + break; + } +@@ -6054,6 +6446,11 @@ static void vsir_validate_src_param(struct validation_context *ctx, + } + break; + ++ case VKD3DSPR_NULL: ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "Invalid NULL register used as source parameter."); ++ break; ++ + default: + break; + } +@@ -6105,13 +6502,13 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx, return true; } @@ -7061,7 +10529,7 @@ index 747238e2fee..db9992d9715 100644 return "block-based"; default: vkd3d_unreachable(); -@@ -6119,437 +6144,510 @@ static const char *name_from_cf_type(enum cf_type type) +@@ -6119,437 +6516,510 @@ static const char *name_from_cf_type(enum cf_type type) } static void vsir_validate_cf_type(struct validation_context *ctx, @@ -7085,26 +10553,64 @@ index 747238e2fee..db9992d9715 100644 - size_t i; - - instruction = &ctx->program->instructions.elements[ctx->instruction_idx]; -- -- for (i = 0; i < instruction->dst_count; ++i) -- vsir_validate_dst_param(ctx, &instruction->dst[i]); -- -- for (i = 0; i < instruction->src_count; ++i) -- vsir_validate_src_param(ctx, &instruction->src[i]); -- -- if (instruction->opcode >= VKD3DSIH_INVALID) + if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks))) - { -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Invalid instruction handler %#x.", -- instruction->opcode); ++ { + ctx->status = VKD3D_ERROR_OUT_OF_MEMORY; + return; - } ++ } + ctx->blocks[ctx->depth++] = opcode; +} +- for (i = 0; i < instruction->dst_count; ++i) +- vsir_validate_dst_param(ctx, &instruction->dst[i]); ++static void vsir_validate_hull_shader_phase(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, ++ "Phase instruction %#x is only valid in a hull shader.", ++ instruction->opcode); ++ if (ctx->depth != 0) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, ++ "Phase instruction %#x must appear to top level.", ++ instruction->opcode); ++ ctx->phase = instruction->opcode; ++ ctx->dcl_temps_found = false; ++} + +- for (i = 0; i < instruction->src_count; ++i) +- vsir_validate_src_param(ctx, &instruction->src[i]); ++static void vsir_validate_branch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) ++{ ++ size_t i; + +- if (instruction->opcode >= VKD3DSIH_INVALID) ++ vsir_validate_cf_type(ctx, instruction, VSIR_CF_BLOCKS); ++ vsir_validate_dst_count(ctx, instruction, 0); ++ ++ if (!vsir_validate_src_min_count(ctx, instruction, 1)) ++ return; ++ ++ if (vsir_register_is_label(&instruction->src[0].reg)) + { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Invalid instruction handler %#x.", +- instruction->opcode); +- } ++ /* Unconditional branch: parameters are jump label, ++ * optional merge label, optional continue label. */ ++ vsir_validate_src_max_count(ctx, instruction, 3); + - switch (instruction->opcode) -- { ++ for (i = 0; i < instruction->src_count; ++i) ++ { ++ if (!vsir_register_is_label(&instruction->src[i].reg)) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "Invalid register of type %#x in unconditional BRANCH instruction, expected LABEL.", ++ instruction->src[i].reg.type); ++ } ++ } ++ else + { - case VKD3DSIH_HS_DECLS: - case VKD3DSIH_HS_CONTROL_POINT_PHASE: - case VKD3DSIH_HS_FORK_PHASE: @@ -7122,20 +10628,11 @@ index 747238e2fee..db9992d9715 100644 - ctx->phase = instruction->opcode; - ctx->dcl_temps_found = false; - return; -+static void vsir_validate_hull_shader_phase(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, -+ "Phase instruction %#x is only valid in a hull shader.", -+ instruction->opcode); -+ if (ctx->depth != 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, -+ "Phase instruction %#x must appear to top level.", -+ instruction->opcode); -+ ctx->phase = instruction->opcode; -+ ctx->dcl_temps_found = false; -+} ++ /* Conditional branch: parameters are condition, true ++ * jump label, false jump label, optional merge label, ++ * optional continue label. */ ++ vsir_validate_src_min_count(ctx, instruction, 3); ++ vsir_validate_src_max_count(ctx, instruction, 5); - case VKD3DSIH_DCL_HS_MAX_TESSFACTOR: - /* Exclude non-finite values. */ @@ -7144,65 +10641,6 @@ index 747238e2fee..db9992d9715 100644 - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, "Max tessellation factor %f is invalid.", - instruction->declaration.max_tessellation_factor); - return; -+static void vsir_validate_branch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) -+{ -+ size_t i; - -- case VKD3DSIH_DCL_INPUT_PRIMITIVE: -- if (instruction->declaration.primitive_type.type == VKD3D_PT_UNDEFINED -- || instruction->declaration.primitive_type.type >= VKD3D_PT_COUNT) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS input primitive %u is invalid.", -- instruction->declaration.primitive_type.type); -- return; -+ vsir_validate_cf_type(ctx, instruction, VSIR_CF_BLOCKS); -+ vsir_validate_dst_count(ctx, instruction, 0); - -- case VKD3DSIH_DCL_VERTICES_OUT: -- if (instruction->declaration.count > 1024) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS output vertex count %u is invalid.", -- instruction->declaration.count); -- return; -+ if (!vsir_validate_src_min_count(ctx, instruction, 1)) -+ return; - -- case VKD3DSIH_DCL_OUTPUT_TOPOLOGY: -- if (instruction->declaration.primitive_type.type == VKD3D_PT_UNDEFINED -- || instruction->declaration.primitive_type.type >= VKD3D_PT_COUNT) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS output primitive %u is invalid.", -- instruction->declaration.primitive_type.type); -- return; -+ if (vsir_register_is_label(&instruction->src[0].reg)) -+ { -+ /* Unconditional branch: parameters are jump label, -+ * optional merge label, optional continue label. */ -+ vsir_validate_src_max_count(ctx, instruction, 3); - -- case VKD3DSIH_DCL_GS_INSTANCES: -- if (!instruction->declaration.count || instruction->declaration.count > 32) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS instance count %u is invalid.", -- instruction->declaration.count); -- return; -+ for (i = 0; i < instruction->src_count; ++i) -+ { -+ if (!vsir_register_is_label(&instruction->src[i].reg)) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid register of type %#x in unconditional BRANCH instruction, expected LABEL.", -+ instruction->src[i].reg.type); -+ } -+ } -+ else -+ { -+ /* Conditional branch: parameters are condition, true -+ * jump label, false jump label, optional merge label, -+ * optional continue label. */ -+ vsir_validate_src_min_count(ctx, instruction, 3); -+ vsir_validate_src_max_count(ctx, instruction, 5); - -- case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT: -- if (!instruction->declaration.count || instruction->declaration.count > 32) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, "Output control point count %u is invalid.", -- instruction->declaration.count); -- return; + for (i = 1; i < instruction->src_count; ++i) + { + if (!vsir_register_is_label(&instruction->src[i].reg)) @@ -7212,20 +10650,19 @@ index 747238e2fee..db9992d9715 100644 + } + } -- case VKD3DSIH_DCL_TESSELLATOR_DOMAIN: -- if (instruction->declaration.tessellator_domain == VKD3D_TESSELLATOR_DOMAIN_INVALID -- || instruction->declaration.tessellator_domain >= VKD3D_TESSELLATOR_DOMAIN_COUNT) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, -- "Tessellator domain %#x is invalid.", instruction->declaration.tessellator_domain); +- case VKD3DSIH_DCL_INPUT_PRIMITIVE: +- if (instruction->declaration.primitive_type.type == VKD3D_PT_UNDEFINED +- || instruction->declaration.primitive_type.type >= VKD3D_PT_COUNT) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS input primitive %u is invalid.", +- instruction->declaration.primitive_type.type); - return; + ctx->inside_block = false; +} -- case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE: -- if (!instruction->declaration.tessellator_output_primitive -- || instruction->declaration.tessellator_output_primitive > VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, -- "Tessellator output primitive %#x is invalid.", instruction->declaration.tessellator_output_primitive); +- case VKD3DSIH_DCL_VERTICES_OUT: +- if (instruction->declaration.count > 1024) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS output vertex count %u is invalid.", +- instruction->declaration.count); - return; +static void vsir_validate_dcl_gs_instances(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) @@ -7235,11 +10672,11 @@ index 747238e2fee..db9992d9715 100644 + instruction->declaration.count); +} -- case VKD3DSIH_DCL_TESSELLATOR_PARTITIONING: -- if (!instruction->declaration.tessellator_partitioning -- || instruction->declaration.tessellator_partitioning > VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, -- "Tessellator partitioning %#x is invalid.", instruction->declaration.tessellator_partitioning); +- case VKD3DSIH_DCL_OUTPUT_TOPOLOGY: +- if (instruction->declaration.primitive_type.type == VKD3D_PT_UNDEFINED +- || instruction->declaration.primitive_type.type >= VKD3D_PT_COUNT) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS output primitive %u is invalid.", +- instruction->declaration.primitive_type.type); - return; +static void vsir_validate_dcl_hs_max_tessfactor(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) @@ -7252,9 +10689,11 @@ index 747238e2fee..db9992d9715 100644 + instruction->declaration.max_tessellation_factor); +} -- default: -- break; -- } +- case VKD3DSIH_DCL_GS_INSTANCES: +- if (!instruction->declaration.count || instruction->declaration.count > 32) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS instance count %u is invalid.", +- instruction->declaration.count); +- return; +static void vsir_validate_dcl_input_primitive(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) +{ @@ -7264,12 +10703,11 @@ index 747238e2fee..db9992d9715 100644 + instruction->declaration.primitive_type.type); +} -- /* Only DCL instructions may occur outside hull shader phases. */ -- if (!vsir_instruction_is_dcl(instruction) && version->type == VKD3D_SHADER_TYPE_HULL -- && ctx->phase == VKD3DSIH_INVALID) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, -- "Instruction %#x appear before any phase instruction in a hull shader.", -- instruction->opcode); +- case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT: +- if (!instruction->declaration.count || instruction->declaration.count > 32) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, "Output control point count %u is invalid.", +- instruction->declaration.count); +- return; +static void vsir_validate_dcl_output_control_point_count(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) +{ @@ -7279,6 +10717,86 @@ index 747238e2fee..db9992d9715 100644 + instruction->declaration.count); +} +- case VKD3DSIH_DCL_TESSELLATOR_DOMAIN: +- if (instruction->declaration.tessellator_domain == VKD3D_TESSELLATOR_DOMAIN_INVALID +- || instruction->declaration.tessellator_domain >= VKD3D_TESSELLATOR_DOMAIN_COUNT) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, +- "Tessellator domain %#x is invalid.", instruction->declaration.tessellator_domain); +- return; ++static void vsir_validate_dcl_output_topology(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ if (instruction->declaration.primitive_type.type == VKD3D_PT_UNDEFINED ++ || instruction->declaration.primitive_type.type >= VKD3D_PT_COUNT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS output primitive %u is invalid.", ++ instruction->declaration.primitive_type.type); ++} + +- case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE: +- if (!instruction->declaration.tessellator_output_primitive +- || instruction->declaration.tessellator_output_primitive > VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, +- "Tessellator output primitive %#x is invalid.", instruction->declaration.tessellator_output_primitive); +- return; ++static void vsir_validate_dcl_temps(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ if (ctx->dcl_temps_found) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS, ++ "Duplicate DCL_TEMPS instruction."); ++ if (instruction->declaration.count > ctx->program->temp_count) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS, ++ "Invalid DCL_TEMPS count %u, expected at most %u.", ++ instruction->declaration.count, ctx->program->temp_count); ++ ctx->dcl_temps_found = true; ++} + +- case VKD3DSIH_DCL_TESSELLATOR_PARTITIONING: +- if (!instruction->declaration.tessellator_partitioning +- || instruction->declaration.tessellator_partitioning > VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, +- "Tessellator partitioning %#x is invalid.", instruction->declaration.tessellator_partitioning); +- return; ++static void vsir_validate_dcl_tessellator_domain(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ if (instruction->declaration.tessellator_domain == VKD3D_TESSELLATOR_DOMAIN_INVALID ++ || instruction->declaration.tessellator_domain >= VKD3D_TESSELLATOR_DOMAIN_COUNT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, ++ "Tessellator domain %#x is invalid.", instruction->declaration.tessellator_domain); ++} + +- default: +- break; +- } ++static void vsir_validate_dcl_tessellator_output_primitive(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ if (!instruction->declaration.tessellator_output_primitive ++ || instruction->declaration.tessellator_output_primitive ++ > VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, ++ "Tessellator output primitive %#x is invalid.", ++ instruction->declaration.tessellator_output_primitive); ++} + +- /* Only DCL instructions may occur outside hull shader phases. */ +- if (!vsir_instruction_is_dcl(instruction) && version->type == VKD3D_SHADER_TYPE_HULL +- && ctx->phase == VKD3DSIH_INVALID) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, +- "Instruction %#x appear before any phase instruction in a hull shader.", +- instruction->opcode); ++static void vsir_validate_dcl_tessellator_partitioning(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ if (!instruction->declaration.tessellator_partitioning ++ || instruction->declaration.tessellator_partitioning ++ > VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, ++ "Tessellator partitioning %#x is invalid.", ++ instruction->declaration.tessellator_partitioning); ++} + - /* We support two different control flow types in shaders: - * block-based, like DXIL and SPIR-V, and structured, like D3DBC - * and TPF. The shader is detected as block-based when its first @@ -7294,60 +10812,6 @@ index 747238e2fee..db9992d9715 100644 - else - ctx->cf_type = CF_TYPE_STRUCTURED; - } -+static void vsir_validate_dcl_output_topology(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ if (instruction->declaration.primitive_type.type == VKD3D_PT_UNDEFINED -+ || instruction->declaration.primitive_type.type >= VKD3D_PT_COUNT) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS output primitive %u is invalid.", -+ instruction->declaration.primitive_type.type); -+} -+ -+static void vsir_validate_dcl_temps(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ if (ctx->dcl_temps_found) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS, -+ "Duplicate DCL_TEMPS instruction."); -+ if (instruction->declaration.count > ctx->program->temp_count) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS, -+ "Invalid DCL_TEMPS count %u, expected at most %u.", -+ instruction->declaration.count, ctx->program->temp_count); -+ ctx->dcl_temps_found = true; -+} -+ -+static void vsir_validate_dcl_tessellator_domain(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ if (instruction->declaration.tessellator_domain == VKD3D_TESSELLATOR_DOMAIN_INVALID -+ || instruction->declaration.tessellator_domain >= VKD3D_TESSELLATOR_DOMAIN_COUNT) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, -+ "Tessellator domain %#x is invalid.", instruction->declaration.tessellator_domain); -+} -+ -+static void vsir_validate_dcl_tessellator_output_primitive(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ if (!instruction->declaration.tessellator_output_primitive -+ || instruction->declaration.tessellator_output_primitive -+ > VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, -+ "Tessellator output primitive %#x is invalid.", -+ instruction->declaration.tessellator_output_primitive); -+} -+ -+static void vsir_validate_dcl_tessellator_partitioning(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ if (!instruction->declaration.tessellator_partitioning -+ || instruction->declaration.tessellator_partitioning -+ > VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, -+ "Tessellator partitioning %#x is invalid.", -+ instruction->declaration.tessellator_partitioning); -+} - -- if (ctx->cf_type == CF_TYPE_BLOCKS && !vsir_instruction_is_dcl(instruction)) +static void vsir_validate_dcl_vertices_out(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) +{ @@ -7457,7 +10921,8 @@ index 747238e2fee..db9992d9715 100644 + "Invalid source count %u for a PHI instruction, it must be an even number.", + instruction->src_count); + incoming_count = instruction->src_count / 2; -+ + +- if (ctx->cf_type == CF_TYPE_BLOCKS && !vsir_instruction_is_dcl(instruction)) + for (i = 0; i < incoming_count; ++i) { - switch (instruction->opcode) @@ -7948,7 +11413,7 @@ index 747238e2fee..db9992d9715 100644 } } -@@ -6575,7 +6673,8 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c +@@ -6575,7 +7045,8 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c if (!(ctx.ssas = vkd3d_calloc(ctx.program->ssa_count, sizeof(*ctx.ssas)))) goto fail; @@ -7958,7 +11423,7 @@ index 747238e2fee..db9992d9715 100644 vsir_validate_instruction(&ctx); ctx.invalid_instruction_idx = true; -@@ -6610,74 +6709,74 @@ fail: +@@ -6610,74 +7081,75 @@ fail: return VKD3D_ERROR_OUT_OF_MEMORY; } @@ -8068,6 +11533,7 @@ index 747238e2fee..db9992d9715 100644 - if ((result = vsir_program_insert_alpha_test(program, message_context)) < 0) - return result; + vsir_transform(&ctx, vsir_program_insert_alpha_test); ++ vsir_transform(&ctx, vsir_program_insert_clip_planes); if (TRACE_ON()) vkd3d_shader_trace(program); @@ -8081,10 +11547,10 @@ index 747238e2fee..db9992d9715 100644 } diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c new file mode 100644 -index 00000000000..7d2e713cddc +index 00000000000..6b41363d60e --- /dev/null +++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -0,0 +1,275 @@ +@@ -0,0 +1,319 @@ +/* + * Copyright 2024 Feifan He for CodeWeavers + * @@ -8142,12 +11608,44 @@ index 00000000000..7d2e713cddc + vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, ""); +} + ++static void msl_print_register_datatype(struct vkd3d_string_buffer *buffer, ++ struct msl_generator *gen, const struct vkd3d_shader_register *reg) ++{ ++ vkd3d_string_buffer_printf(buffer, "."); ++ switch (reg->data_type) ++ { ++ case VKD3D_DATA_FLOAT: ++ vkd3d_string_buffer_printf(buffer, "f"); ++ break; ++ case VKD3D_DATA_INT: ++ vkd3d_string_buffer_printf(buffer, "i"); ++ break; ++ case VKD3D_DATA_UINT: ++ vkd3d_string_buffer_printf(buffer, "u"); ++ break; ++ default: ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled register datatype %#x.", reg->data_type); ++ vkd3d_string_buffer_printf(buffer, "", reg->data_type); ++ break; ++ } ++} ++ +static void msl_print_register_name(struct vkd3d_string_buffer *buffer, + struct msl_generator *gen, const struct vkd3d_shader_register *reg) +{ -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled register type %#x.", reg->type); -+ vkd3d_string_buffer_printf(buffer, "", reg->type); ++ switch (reg->type) ++ { ++ case VKD3DSPR_TEMP: ++ vkd3d_string_buffer_printf(buffer, "r[%u]", reg->idx[0].offset); ++ msl_print_register_datatype(buffer, gen, reg); ++ break; ++ default: ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled register type %#x.", reg->type); ++ vkd3d_string_buffer_printf(buffer, "", reg->type); ++ break; ++ } +} + +static void msl_print_swizzle(struct vkd3d_string_buffer *buffer, uint32_t swizzle, uint32_t mask) @@ -8308,9 +11806,21 @@ index 00000000000..7d2e713cddc + + vkd3d_string_buffer_printf(gen->buffer, "/* Generated by %s. */\n\n", vkd3d_shader_get_version(NULL, NULL)); + ++ vkd3d_string_buffer_printf(gen->buffer, "union vkd3d_vec4\n{\n"); ++ vkd3d_string_buffer_printf(gen->buffer, " uint4 u;\n"); ++ vkd3d_string_buffer_printf(gen->buffer, " int4 i;\n"); ++ vkd3d_string_buffer_printf(gen->buffer, " float4 f;\n};\n\n"); ++ + vkd3d_string_buffer_printf(gen->buffer, "void shader_main()\n{\n"); + + ++gen->indent; ++ ++ if (gen->program->temp_count) ++ { ++ msl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "vkd3d_vec4 r[%u];\n\n", gen->program->temp_count); ++ } ++ + for (i = 0; i < instructions->count; ++i) + { + msl_handle_instruction(gen, &instructions->elements[i]); @@ -8361,7 +11871,7 @@ index 00000000000..7d2e713cddc + return VKD3D_ERROR_INVALID_SHADER; +} diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l -index 2b7455a5c30..7fc963192cf 100644 +index 2b7455a5c30..41c21cca1f5 100644 --- a/libs/vkd3d/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l @@ -20,6 +20,7 @@ @@ -8372,8 +11882,17 @@ index 2b7455a5c30..7fc963192cf 100644 #include "preproc.tab.h" #undef ERROR /* defined in wingdi.h */ +@@ -66,7 +67,7 @@ static void update_location(struct preproc_ctx *ctx); + + NEWLINE \r?\n + WS [ \t\r] +-IDENTIFIER [A-Za-z_][A-Za-z0-9_]* ++IDENTIFIER (::)?[A-Za-z_]((::)?[A-Za-z0-9_]+)* + INT_SUFFIX [uUlL]{0,2} + + %% diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 49979ab2491..7f1e0fea2c3 100644 +index 49979ab2491..11c054a28f5 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -97,15 +97,37 @@ static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_co @@ -8438,7 +11957,129 @@ index 49979ab2491..7f1e0fea2c3 100644 static size_t vkd3d_spirv_stream_current_location(struct vkd3d_spirv_stream *stream) { return stream->word_count; -@@ -1996,9 +2028,7 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, +@@ -362,6 +394,7 @@ struct vkd3d_spirv_builder + uint32_t type_bool_id; + uint32_t type_void_id; + uint32_t scope_subgroup_id; ++ uint32_t numeric_type_ids[VKD3D_SHADER_COMPONENT_TYPE_COUNT][VKD3D_VEC4_SIZE]; + + struct vkd3d_spirv_stream debug_stream; /* debug instructions */ + struct vkd3d_spirv_stream annotation_stream; /* decoration instructions */ +@@ -1195,6 +1228,13 @@ static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_build + SpvOpConstantComposite, result_type, constituents, constituent_count); + } + ++static uint32_t vkd3d_spirv_build_op_spec_constant_composite(struct vkd3d_spirv_builder *builder, ++ uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) ++{ ++ return vkd3d_spirv_build_op_trv(builder, &builder->global_stream, ++ SpvOpSpecConstantComposite, result_type, constituents, constituent_count); ++} ++ + static uint32_t vkd3d_spirv_get_op_constant_composite(struct vkd3d_spirv_builder *builder, + uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) + { +@@ -1870,29 +1910,37 @@ static uint32_t vkd3d_spirv_build_op_glsl_std450_nclamp(struct vkd3d_spirv_build + static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder, + enum vkd3d_shader_component_type component_type, unsigned int component_count) + { +- uint32_t scalar_id; ++ uint32_t scalar_id, type_id; ++ ++ VKD3D_ASSERT(component_type < VKD3D_SHADER_COMPONENT_TYPE_COUNT); ++ VKD3D_ASSERT(1 <= component_count && component_count <= VKD3D_VEC4_SIZE); ++ ++ if ((type_id = builder->numeric_type_ids[component_type][component_count - 1])) ++ return type_id; + + if (component_count == 1) + { + switch (component_type) + { + case VKD3D_SHADER_COMPONENT_VOID: +- return vkd3d_spirv_get_op_type_void(builder); ++ type_id = vkd3d_spirv_get_op_type_void(builder); + break; + case VKD3D_SHADER_COMPONENT_FLOAT: +- return vkd3d_spirv_get_op_type_float(builder, 32); ++ type_id = vkd3d_spirv_get_op_type_float(builder, 32); + break; + case VKD3D_SHADER_COMPONENT_INT: + case VKD3D_SHADER_COMPONENT_UINT: +- return vkd3d_spirv_get_op_type_int(builder, 32, component_type == VKD3D_SHADER_COMPONENT_INT); ++ type_id = vkd3d_spirv_get_op_type_int(builder, 32, component_type == VKD3D_SHADER_COMPONENT_INT); + break; + case VKD3D_SHADER_COMPONENT_BOOL: +- return vkd3d_spirv_get_op_type_bool(builder); ++ type_id = vkd3d_spirv_get_op_type_bool(builder); + break; + case VKD3D_SHADER_COMPONENT_DOUBLE: +- return vkd3d_spirv_get_op_type_float(builder, 64); ++ type_id = vkd3d_spirv_get_op_type_float(builder, 64); ++ break; + case VKD3D_SHADER_COMPONENT_UINT64: +- return vkd3d_spirv_get_op_type_int(builder, 64, 0); ++ type_id = vkd3d_spirv_get_op_type_int(builder, 64, 0); ++ break; + default: + FIXME("Unhandled component type %#x.\n", component_type); + return 0; +@@ -1902,46 +1950,21 @@ static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder, + { + VKD3D_ASSERT(component_type != VKD3D_SHADER_COMPONENT_VOID); + scalar_id = vkd3d_spirv_get_type_id(builder, component_type, 1); +- return vkd3d_spirv_get_op_type_vector(builder, scalar_id, component_count); ++ type_id = vkd3d_spirv_get_op_type_vector(builder, scalar_id, component_count); + } ++ ++ builder->numeric_type_ids[component_type][component_count - 1] = type_id; ++ ++ return type_id; + } + + static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder *builder, + enum vkd3d_data_type data_type, unsigned int component_count) + { +- uint32_t scalar_id; ++ enum vkd3d_shader_component_type component_type; + +- if (component_count == 1) +- { +- switch (data_type) +- { +- case VKD3D_DATA_HALF: /* Minimum precision. TODO: native 16-bit */ +- case VKD3D_DATA_FLOAT: +- case VKD3D_DATA_SNORM: +- case VKD3D_DATA_UNORM: +- return vkd3d_spirv_get_op_type_float(builder, 32); +- break; +- case VKD3D_DATA_INT: +- case VKD3D_DATA_UINT: +- case VKD3D_DATA_UINT16: /* Minimum precision. TODO: native 16-bit */ +- return vkd3d_spirv_get_op_type_int(builder, 32, data_type == VKD3D_DATA_INT); +- break; +- case VKD3D_DATA_DOUBLE: +- return vkd3d_spirv_get_op_type_float(builder, 64); +- case VKD3D_DATA_UINT64: +- return vkd3d_spirv_get_op_type_int(builder, 64, 0); +- case VKD3D_DATA_BOOL: +- return vkd3d_spirv_get_op_type_bool(builder); +- default: +- FIXME("Unhandled data type %#x.\n", data_type); +- return 0; +- } +- } +- else +- { +- scalar_id = vkd3d_spirv_get_type_id_for_data_type(builder, data_type, 1); +- return vkd3d_spirv_get_op_type_vector(builder, scalar_id, component_count); +- } ++ component_type = vkd3d_component_type_from_data_type(data_type); ++ return vkd3d_spirv_get_type_id(builder, component_type, component_count); + } + + static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, const char *entry_point) +@@ -1996,9 +2019,7 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, { uint64_t capability_mask = builder->capability_mask; struct vkd3d_spirv_stream stream; @@ -8448,7 +12089,7 @@ index 49979ab2491..7f1e0fea2c3 100644 vkd3d_spirv_stream_init(&stream); -@@ -2053,26 +2083,20 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, +@@ -2053,26 +2074,20 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, if (builder->invocation_count) vkd3d_spirv_build_op_execution_mode(&builder->execution_mode_stream, builder->main_function_id, SpvExecutionModeInvocations, &builder->invocation_count, 1); @@ -8481,7 +12122,219 @@ index 49979ab2491..7f1e0fea2c3 100644 return true; } -@@ -6120,12 +6144,12 @@ static void spirv_compiler_decorate_descriptor(struct spirv_compiler *compiler, +@@ -3316,8 +3331,10 @@ static const struct vkd3d_spec_constant_info *get_spec_constant_info(enum vkd3d_ + return NULL; + } + +-static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *compiler) ++static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *compiler, unsigned int count) + { ++ uint32_t ret; ++ + if (!compiler->current_spec_constant_id) + { + unsigned int i, id = 0; +@@ -3327,28 +3344,52 @@ static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *com + const struct vkd3d_shader_parameter1 *current = &compiler->program->parameters[i]; + + if (current->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT) +- id = max(current->u.specialization_constant.id + 1, id); ++ { ++ switch (current->data_type) ++ { ++ case VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4: ++ id = max(current->u.specialization_constant.id + 4, id); ++ break; ++ ++ default: ++ id = max(current->u.specialization_constant.id + 1, id); ++ break; ++ } ++ } + } + + compiler->current_spec_constant_id = id; + } + +- return compiler->current_spec_constant_id++; ++ ret = compiler->current_spec_constant_id; ++ compiler->current_spec_constant_id += count; ++ return ret; + } + + static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compiler, +- enum vkd3d_shader_parameter_name name, uint32_t spec_id, enum vkd3d_data_type type) ++ enum vkd3d_shader_parameter_name name, uint32_t spec_id, ++ enum vkd3d_data_type type, unsigned int component_count) + { ++ uint32_t scalar_type_id, vector_type_id, id, default_value, components[4]; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_spec_constant_info *info; +- uint32_t type_id, id, default_value; + + info = get_spec_constant_info(name); + default_value = info ? info->default_value : 0; + +- type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1); +- id = vkd3d_spirv_build_op_spec_constant(builder, type_id, default_value); +- vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationSpecId, spec_id); ++ scalar_type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1); ++ vector_type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), component_count); ++ ++ for (unsigned int i = 0; i < component_count; ++i) ++ { ++ components[i] = vkd3d_spirv_build_op_spec_constant(builder, scalar_type_id, default_value); ++ vkd3d_spirv_build_op_decorate1(builder, components[i], SpvDecorationSpecId, spec_id + i); ++ } ++ ++ if (component_count == 1) ++ id = components[0]; ++ else ++ id = vkd3d_spirv_build_op_spec_constant_composite(builder, vector_type_id, components, component_count); + + if (info) + vkd3d_spirv_build_op_name(builder, id, "%s", info->debug_name); +@@ -3365,7 +3406,8 @@ static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compile + } + + static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler, +- enum vkd3d_shader_parameter_name name, uint32_t spec_id, enum vkd3d_data_type type) ++ enum vkd3d_shader_parameter_name name, uint32_t spec_id, ++ enum vkd3d_data_type type, unsigned int component_count) + { + unsigned int i; + +@@ -3375,17 +3417,17 @@ static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler + return compiler->spec_constants[i].id; + } + +- return spirv_compiler_emit_spec_constant(compiler, name, spec_id, type); ++ return spirv_compiler_emit_spec_constant(compiler, name, spec_id, type, component_count); + } + + static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compiler, +- const struct vkd3d_shader_parameter1 *parameter, enum vkd3d_data_type type) ++ const struct vkd3d_shader_parameter1 *parameter, enum vkd3d_data_type type, unsigned int component_count) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + unsigned int index = parameter - compiler->program->parameters; + uint32_t type_id, ptr_id, ptr_type_id; + +- type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1); ++ type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), component_count); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); + ptr_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, + compiler->spirv_parameter_info[index].buffer_id, +@@ -3393,48 +3435,49 @@ static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compi + return vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone); + } + ++static const struct ++{ ++ enum vkd3d_data_type type; ++ unsigned int component_count; ++} ++parameter_data_type_map[] = ++{ ++ [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32] = {VKD3D_DATA_FLOAT, 1}, ++ [VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32] = {VKD3D_DATA_UINT, 1}, ++ [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4] = {VKD3D_DATA_FLOAT, 4}, ++}; ++ + static uint32_t spirv_compiler_emit_shader_parameter(struct spirv_compiler *compiler, +- enum vkd3d_shader_parameter_name name, enum vkd3d_data_type type) ++ enum vkd3d_shader_parameter_name name, enum vkd3d_data_type type, unsigned int component_count) + { + const struct vkd3d_shader_parameter1 *parameter; + +- static const struct +- { +- enum vkd3d_data_type type; +- } +- type_map[] = +- { +- [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32] = {VKD3D_DATA_FLOAT}, +- [VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32] = {VKD3D_DATA_UINT}, +- }; +- + if (!(parameter = vsir_program_get_parameter(compiler->program, name))) + { + WARN("Unresolved shader parameter %#x.\n", name); + goto default_parameter; + } + +- if (type_map[parameter->data_type].type != type) +- ERR("Expected data type %#x for parameter %#x, got %#x.\n", type, name, parameter->data_type); ++ if (parameter_data_type_map[parameter->data_type].type != type ++ || parameter_data_type_map[parameter->data_type].component_count != component_count) ++ ERR("Expected type %#x, count %u for parameter %#x, got %#x.\n", ++ type, component_count, name, parameter->data_type); + + if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) +- { +- if (parameter->data_type == VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32) +- return spirv_compiler_get_constant_float(compiler, parameter->u.immediate_constant.u.f32); +- else +- return spirv_compiler_get_constant_uint(compiler, parameter->u.immediate_constant.u.u32); +- } ++ return spirv_compiler_get_constant(compiler, vkd3d_component_type_from_data_type(type), ++ component_count, (const uint32_t *)¶meter->u.immediate_constant); + + if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT) +- return spirv_compiler_get_spec_constant(compiler, name, parameter->u.specialization_constant.id, type); ++ return spirv_compiler_get_spec_constant(compiler, name, ++ parameter->u.specialization_constant.id, type, component_count); + if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_BUFFER) +- return spirv_compiler_get_buffer_parameter(compiler, parameter, type); ++ return spirv_compiler_get_buffer_parameter(compiler, parameter, type, component_count); + + FIXME("Unhandled parameter type %#x.\n", parameter->type); + + default_parameter: + return spirv_compiler_get_spec_constant(compiler, +- name, spirv_compiler_alloc_spec_constant_id(compiler), type); ++ name, spirv_compiler_alloc_spec_constant_id(compiler, component_count), type, component_count); + } + + static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *compiler, +@@ -4210,7 +4253,8 @@ 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, reg->data_type); ++ return spirv_compiler_emit_shader_parameter(compiler, reg->idx[0].offset, ++ reg->data_type, reg->dimension == VSIR_DIMENSION_VEC4 ? 4 : 1); + + component_count = vsir_write_mask_component_count(write_mask); + component_type = vkd3d_component_type_from_data_type(reg->data_type); +@@ -4500,9 +4544,24 @@ static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler, + static void spirv_compiler_emit_store_dst(struct spirv_compiler *compiler, + const struct vkd3d_shader_dst_param *dst, uint32_t val_id) + { +- VKD3D_ASSERT(!(dst->modifiers & ~VKD3DSPDM_SATURATE)); +- if (dst->modifiers & VKD3DSPDM_SATURATE) ++ uint32_t modifiers = dst->modifiers; ++ ++ /* It is always legitimate to ignore _pp. */ ++ modifiers &= ~VKD3DSPDM_PARTIALPRECISION; ++ ++ if (modifiers & VKD3DSPDM_SATURATE) ++ { + val_id = spirv_compiler_emit_sat(compiler, &dst->reg, dst->write_mask, val_id); ++ modifiers &= ~VKD3DSPDM_SATURATE; ++ } ++ ++ if (dst->modifiers & VKD3DSPDM_MSAMPCENTROID) ++ { ++ FIXME("Ignoring _centroid modifier.\n"); ++ modifiers &= ~VKD3DSPDM_MSAMPCENTROID; ++ } ++ ++ VKD3D_ASSERT(!modifiers); + + spirv_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, val_id); + } +@@ -6120,12 +6179,12 @@ static void spirv_compiler_decorate_descriptor(struct spirv_compiler *compiler, static uint32_t spirv_compiler_build_descriptor_variable(struct spirv_compiler *compiler, SpvStorageClass storage_class, uint32_t type_id, const struct vkd3d_shader_register *reg, const struct vkd3d_shader_register_range *range, enum vkd3d_shader_resource_type resource_type, @@ -8496,7 +12349,7 @@ index 49979ab2491..7f1e0fea2c3 100644 uint32_t array_type_id, ptr_type_id, var_id; bool write_only = false, coherent = false; struct vkd3d_symbol symbol; -@@ -6135,12 +6159,11 @@ static uint32_t spirv_compiler_build_descriptor_variable(struct spirv_compiler * +@@ -6135,12 +6194,11 @@ static uint32_t spirv_compiler_build_descriptor_variable(struct spirv_compiler * resource_type, is_uav_counter, &binding_address); var_info->binding_base_idx = binding_address.binding_base_idx; @@ -8512,7 +12365,7 @@ index 49979ab2491..7f1e0fea2c3 100644 } if (binding.count == 1 && range->first == binding_address.binding_base_idx && range->last != ~0u -@@ -6194,11 +6217,12 @@ static uint32_t spirv_compiler_build_descriptor_variable(struct spirv_compiler * +@@ -6194,11 +6252,12 @@ static uint32_t spirv_compiler_build_descriptor_variable(struct spirv_compiler * } static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, @@ -8526,7 +12379,7 @@ index 49979ab2491..7f1e0fea2c3 100644 struct vkd3d_push_constant_buffer_binding *push_cb; struct vkd3d_descriptor_variable_info var_info; struct vkd3d_shader_register reg; -@@ -6206,7 +6230,7 @@ static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, +@@ -6206,7 +6265,7 @@ static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, unsigned int size; vsir_register_init(®, VKD3DSPR_CONSTBUFFER, VKD3D_DATA_FLOAT, 3); @@ -8535,7 +12388,7 @@ index 49979ab2491..7f1e0fea2c3 100644 reg.idx[1].offset = range->first; reg.idx[2].offset = range->last; -@@ -6239,7 +6263,7 @@ static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, +@@ -6239,7 +6298,7 @@ static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, vkd3d_spirv_build_op_name(builder, struct_id, "cb%u_struct", size); var_id = spirv_compiler_build_descriptor_variable(compiler, storage_class, struct_id, @@ -8544,7 +12397,7 @@ index 49979ab2491..7f1e0fea2c3 100644 vkd3d_symbol_make_register(®_symbol, ®); vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, -@@ -6275,7 +6299,7 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi +@@ -6275,7 +6334,7 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi } static void spirv_compiler_emit_sampler_declaration(struct spirv_compiler *compiler, @@ -8553,7 +12406,7 @@ index 49979ab2491..7f1e0fea2c3 100644 { const SpvStorageClass storage_class = SpvStorageClassUniformConstant; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -@@ -6285,7 +6309,7 @@ static void spirv_compiler_emit_sampler_declaration(struct spirv_compiler *compi +@@ -6285,7 +6344,7 @@ static void spirv_compiler_emit_sampler_declaration(struct spirv_compiler *compi uint32_t type_id, var_id; vsir_register_init(®, VKD3DSPR_SAMPLER, VKD3D_DATA_FLOAT, 1); @@ -8562,7 +12415,7 @@ index 49979ab2491..7f1e0fea2c3 100644 vkd3d_symbol_make_sampler(®_symbol, ®); reg_symbol.info.sampler.range = *range; -@@ -6295,8 +6319,8 @@ static void spirv_compiler_emit_sampler_declaration(struct spirv_compiler *compi +@@ -6295,8 +6354,8 @@ static void spirv_compiler_emit_sampler_declaration(struct spirv_compiler *compi return; type_id = vkd3d_spirv_get_op_type_sampler(builder); @@ -8573,7 +12426,62 @@ index 49979ab2491..7f1e0fea2c3 100644 vkd3d_symbol_make_register(®_symbol, ®); vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, -@@ -6461,21 +6485,24 @@ static void spirv_compiler_emit_combined_sampler_declarations(struct spirv_compi +@@ -6346,7 +6405,7 @@ static SpvImageFormat image_format_for_image_read(enum vkd3d_shader_component_ty + static uint32_t spirv_compiler_get_image_type_id(struct spirv_compiler *compiler, + const struct vkd3d_shader_register *reg, const struct vkd3d_shader_register_range *range, + const struct vkd3d_spirv_resource_type *resource_type_info, enum vkd3d_shader_component_type data_type, +- bool raw_structured, uint32_t depth) ++ bool raw_structured) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_descriptor_info1 *d; +@@ -6369,7 +6428,7 @@ static uint32_t spirv_compiler_get_image_type_id(struct spirv_compiler *compiler + + sampled_type_id = vkd3d_spirv_get_type_id(builder, data_type, 1); + return vkd3d_spirv_get_op_type_image(builder, sampled_type_id, resource_type_info->dim, +- depth, resource_type_info->arrayed, resource_type_info->ms, ++ 2, resource_type_info->arrayed, resource_type_info->ms, + reg->type == VKD3DSPR_UAV ? 2 : 1, format); + } + +@@ -6384,18 +6443,14 @@ static void spirv_compiler_emit_combined_sampler_declarations(struct spirv_compi + const struct vkd3d_shader_combined_resource_sampler *current; + uint32_t image_type_id, type_id, ptr_type_id, var_id; + enum vkd3d_shader_binding_flag resource_type_flag; +- const struct vkd3d_shader_descriptor_info1 *d; + struct vkd3d_symbol symbol; + unsigned int i; +- bool depth; + + resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER + ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE; + + for (i = 0; i < shader_interface->combined_sampler_count; ++i) + { +- struct vkd3d_shader_register_range sampler_range; +- + current = &shader_interface->combined_samplers[i]; + + if (current->resource_space != resource_range->space || current->resource_index != resource_range->first) +@@ -6417,16 +6472,8 @@ static void spirv_compiler_emit_combined_sampler_declarations(struct spirv_compi + current->sampler_space, current->binding.count); + } + +- sampler_range.space = current->sampler_space; +- sampler_range.first = current->sampler_index; +- sampler_range.last = current->sampler_index; +- d = spirv_compiler_get_descriptor_info(compiler, +- VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, &sampler_range); +- depth = current->sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX +- && (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE); +- + image_type_id = spirv_compiler_get_image_type_id(compiler, resource, resource_range, +- resource_type_info, sampled_type, structure_stride || raw, depth); ++ resource_type_info, sampled_type, structure_stride || raw); + type_id = vkd3d_spirv_get_op_type_sampled_image(builder, image_type_id); + + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); +@@ -6461,21 +6508,24 @@ static void spirv_compiler_emit_combined_sampler_declarations(struct spirv_compi } static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *compiler, @@ -8602,7 +12510,7 @@ index 49979ab2491..7f1e0fea2c3 100644 if (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS && sample_count == 1) resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; -@@ -6489,7 +6516,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp +@@ -6489,7 +6539,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp return; } @@ -8611,8 +12519,12 @@ index 49979ab2491..7f1e0fea2c3 100644 if (!is_uav && spirv_compiler_has_combined_sampler_for_resource(compiler, range)) { -@@ -6520,16 +6547,12 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp - resource_type_info, sampled_type, structure_stride || raw, 0); +@@ -6517,19 +6567,15 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp + else + { + type_id = spirv_compiler_get_image_type_id(compiler, ®, range, +- resource_type_info, sampled_type, structure_stride || raw, 0); ++ resource_type_info, sampled_type, structure_stride || raw); } - var_id = spirv_compiler_build_descriptor_variable(compiler, storage_class, type_id, ®, @@ -8631,7 +12543,7 @@ index 49979ab2491..7f1e0fea2c3 100644 { if (compiler->shader_type != VKD3D_SHADER_TYPE_PIXEL) spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, -@@ -6543,7 +6566,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp +@@ -6543,7 +6589,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp compiler->use_invocation_interlock = true; } @@ -8640,7 +12552,7 @@ index 49979ab2491..7f1e0fea2c3 100644 { VKD3D_ASSERT(structure_stride); /* counters are valid only for structured buffers */ -@@ -6571,7 +6594,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp +@@ -6571,7 +6617,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp } counter_var_id = spirv_compiler_build_descriptor_variable(compiler, storage_class, @@ -8649,7 +12561,38 @@ index 49979ab2491..7f1e0fea2c3 100644 } } -@@ -10564,23 +10587,16 @@ static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *c +@@ -8433,11 +8479,10 @@ static void spirv_compiler_prepare_image(struct spirv_compiler *compiler, + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t sampler_var_id, sampler_id, sampled_image_type_id; + const struct vkd3d_symbol *symbol = NULL; +- bool load, sampled, depth_comparison; ++ bool load, sampled; + + load = !(flags & VKD3D_IMAGE_FLAG_NO_LOAD); + sampled = flags & VKD3D_IMAGE_FLAG_SAMPLED; +- depth_comparison = flags & VKD3D_IMAGE_FLAG_DEPTH; + + if (resource_reg->type == VKD3DSPR_RESOURCE) + symbol = spirv_compiler_find_combined_sampler(compiler, resource_reg, sampler_reg); +@@ -8491,7 +8536,7 @@ static void spirv_compiler_prepare_image(struct spirv_compiler *compiler, + + image->image_type_id = spirv_compiler_get_image_type_id(compiler, resource_reg, + &symbol->info.resource.range, image->resource_type_info, +- image->sampled_type, image->structure_stride || image->raw, depth_comparison); ++ image->sampled_type, image->structure_stride || image->raw); + + if (sampled) + { +@@ -9569,7 +9614,7 @@ static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *co + if (src->reg.type == VKD3DSPR_RASTERIZER) + { + val_id = spirv_compiler_emit_shader_parameter(compiler, +- VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, VKD3D_DATA_UINT); ++ VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, VKD3D_DATA_UINT, 1); + } + else + { +@@ -10564,23 +10609,16 @@ static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *c switch (descriptor->type) { case VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER: @@ -8676,7 +12619,7 @@ index 49979ab2491..7f1e0fea2c3 100644 break; default: -@@ -10600,7 +10616,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct +@@ -10600,7 +10638,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct enum vkd3d_result result = VKD3D_OK; unsigned int i, max_element_count; @@ -8685,8 +12628,19 @@ index 49979ab2491..7f1e0fea2c3 100644 compile_info, compiler->message_context)) < 0) return result; +@@ -10624,7 +10662,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct + { + uint32_t type_id, struct_id, ptr_type_id, var_id; + +- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ++ type_id = vkd3d_spirv_get_type_id(builder, ++ vkd3d_component_type_from_data_type(parameter_data_type_map[parameter->data_type].type), ++ parameter_data_type_map[parameter->data_type].component_count); + + struct_id = vkd3d_spirv_build_op_type_struct(builder, &type_id, 1); + vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBlock, NULL, 0); diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 84f641cc316..884a2998d5b 100644 +index 84f641cc316..00a525c9ac3 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -23,6 +23,7 @@ @@ -8753,6 +12707,33 @@ index 84f641cc316..884a2998d5b 100644 }; struct vkd3d_shader_sm4_parser +@@ -853,7 +896,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u + >> VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; + } + +- reg_data_type = opcode == VKD3D_SM4_OP_DCL_RESOURCE ? VKD3D_DATA_RESOURCE : VKD3D_DATA_UAV; ++ reg_data_type = VKD3D_DATA_UNUSED; + shader_sm4_read_dst_param(priv, &tokens, end, reg_data_type, &semantic->resource.reg); + shader_sm4_set_descriptor_register_range(priv, &semantic->resource.reg.reg, &semantic->resource.range); + +@@ -873,7 +916,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u + } + } + +- if (reg_data_type == VKD3D_DATA_UAV) ++ if (opcode != VKD3D_SM4_OP_DCL_RESOURCE) + ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT; + + shader_sm4_read_register_space(priv, &tokens, end, &semantic->resource.range.space); +@@ -915,7 +958,7 @@ static void shader_sm4_read_dcl_sampler(struct vkd3d_shader_instruction *ins, ui + ins->flags = (opcode_token & VKD3D_SM4_SAMPLER_MODE_MASK) >> VKD3D_SM4_SAMPLER_MODE_SHIFT; + if (ins->flags & ~VKD3D_SM4_SAMPLER_COMPARISON) + FIXME("Unhandled sampler mode %#x.\n", ins->flags); +- shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_SAMPLER, &ins->declaration.sampler.src); ++ shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &ins->declaration.sampler.src); + shader_sm4_set_descriptor_register_range(priv, &ins->declaration.sampler.src.reg, &ins->declaration.sampler.range); + shader_sm4_read_register_space(priv, &tokens, end, &ins->declaration.sampler.range.space); + } @@ -1115,7 +1158,18 @@ static void shader_sm4_read_dcl_input_ps(struct vkd3d_shader_instruction *ins, u struct signature_element *e = vsir_signature_find_element_for_reg( &priv->p.program->input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); @@ -8793,6 +12774,42 @@ index 84f641cc316..884a2998d5b 100644 } ins->declaration.register_semantic.sysval_semantic = *tokens; } +@@ -1237,7 +1302,7 @@ static void shader_sm5_read_dcl_uav_raw(struct vkd3d_shader_instruction *ins, ui + struct vkd3d_shader_raw_resource *resource = &ins->declaration.raw_resource; + const uint32_t *end = &tokens[token_count]; + +- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UAV, &resource->resource.reg); ++ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); + shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); + ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT; + shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.range.space); +@@ -1249,7 +1314,7 @@ static void shader_sm5_read_dcl_uav_structured(struct vkd3d_shader_instruction * + struct vkd3d_shader_structured_resource *resource = &ins->declaration.structured_resource; + const uint32_t *end = &tokens[token_count]; + +- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UAV, &resource->resource.reg); ++ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); + shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); + ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT; + resource->byte_stride = *tokens++; +@@ -1286,7 +1351,7 @@ static void shader_sm5_read_dcl_resource_structured(struct vkd3d_shader_instruct + struct vkd3d_shader_structured_resource *resource = &ins->declaration.structured_resource; + const uint32_t *end = &tokens[token_count]; + +- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_RESOURCE, &resource->resource.reg); ++ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); + shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); + resource->byte_stride = *tokens++; + if (resource->byte_stride % 4) +@@ -1300,7 +1365,7 @@ static void shader_sm5_read_dcl_resource_raw(struct vkd3d_shader_instruction *in + struct vkd3d_shader_raw_resource *resource = &ins->declaration.raw_resource; + const uint32_t *end = &tokens[token_count]; + +- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_RESOURCE, &resource->resource.reg); ++ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); + shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); + shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.range.space); + } @@ -1330,11 +1395,17 @@ static const enum vkd3d_shader_register_precision register_precision_table[] = /* VKD3D_SM4_REGISTER_PRECISION_MIN_UINT_16 */ VKD3D_SHADER_REGISTER_PRECISION_MIN_UINT_16, }; @@ -8811,6 +12828,175 @@ index 84f641cc316..884a2998d5b 100644 }; static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) +@@ -1400,8 +1471,8 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + {VKD3D_SM4_OP_ISHR, VKD3DSIH_ISHR, "i", "ii"}, + {VKD3D_SM4_OP_ITOF, VKD3DSIH_ITOF, "f", "i"}, + {VKD3D_SM4_OP_LABEL, VKD3DSIH_LABEL, "", "O"}, +- {VKD3D_SM4_OP_LD, VKD3DSIH_LD, "u", "iR"}, +- {VKD3D_SM4_OP_LD2DMS, VKD3DSIH_LD2DMS, "u", "iRi"}, ++ {VKD3D_SM4_OP_LD, VKD3DSIH_LD, "u", "i*"}, ++ {VKD3D_SM4_OP_LD2DMS, VKD3DSIH_LD2DMS, "u", "i*i"}, + {VKD3D_SM4_OP_LOG, VKD3DSIH_LOG, "f", "f"}, + {VKD3D_SM4_OP_LOOP, VKD3DSIH_LOOP, "", ""}, + {VKD3D_SM4_OP_LT, VKD3DSIH_LTO, "u", "ff"}, +@@ -1417,7 +1488,7 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + {VKD3D_SM4_OP_NOP, VKD3DSIH_NOP, "", ""}, + {VKD3D_SM4_OP_NOT, VKD3DSIH_NOT, "u", "u"}, + {VKD3D_SM4_OP_OR, VKD3DSIH_OR, "u", "uu"}, +- {VKD3D_SM4_OP_RESINFO, VKD3DSIH_RESINFO, "f", "iR"}, ++ {VKD3D_SM4_OP_RESINFO, VKD3DSIH_RESINFO, "f", "i*"}, + {VKD3D_SM4_OP_RET, VKD3DSIH_RET, "", ""}, + {VKD3D_SM4_OP_RETC, VKD3DSIH_RETP, "", "u", + shader_sm4_read_conditional_op}, +@@ -1426,12 +1497,12 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + {VKD3D_SM4_OP_ROUND_PI, VKD3DSIH_ROUND_PI, "f", "f"}, + {VKD3D_SM4_OP_ROUND_Z, VKD3DSIH_ROUND_Z, "f", "f"}, + {VKD3D_SM4_OP_RSQ, VKD3DSIH_RSQ, "f", "f"}, +- {VKD3D_SM4_OP_SAMPLE, VKD3DSIH_SAMPLE, "u", "fRS"}, +- {VKD3D_SM4_OP_SAMPLE_C, VKD3DSIH_SAMPLE_C, "f", "fRSf"}, +- {VKD3D_SM4_OP_SAMPLE_C_LZ, VKD3DSIH_SAMPLE_C_LZ, "f", "fRSf"}, +- {VKD3D_SM4_OP_SAMPLE_LOD, VKD3DSIH_SAMPLE_LOD, "u", "fRSf"}, +- {VKD3D_SM4_OP_SAMPLE_GRAD, VKD3DSIH_SAMPLE_GRAD, "u", "fRSff"}, +- {VKD3D_SM4_OP_SAMPLE_B, VKD3DSIH_SAMPLE_B, "u", "fRSf"}, ++ {VKD3D_SM4_OP_SAMPLE, VKD3DSIH_SAMPLE, "u", "f**"}, ++ {VKD3D_SM4_OP_SAMPLE_C, VKD3DSIH_SAMPLE_C, "f", "f**f"}, ++ {VKD3D_SM4_OP_SAMPLE_C_LZ, VKD3DSIH_SAMPLE_C_LZ, "f", "f**f"}, ++ {VKD3D_SM4_OP_SAMPLE_LOD, VKD3DSIH_SAMPLE_LOD, "u", "f**f"}, ++ {VKD3D_SM4_OP_SAMPLE_GRAD, VKD3DSIH_SAMPLE_GRAD, "u", "f**ff"}, ++ {VKD3D_SM4_OP_SAMPLE_B, VKD3DSIH_SAMPLE_B, "u", "f**f"}, + {VKD3D_SM4_OP_SQRT, VKD3DSIH_SQRT, "f", "f"}, + {VKD3D_SM4_OP_SWITCH, VKD3DSIH_SWITCH, "", "i"}, + {VKD3D_SM4_OP_SINCOS, VKD3DSIH_SINCOS, "ff", "f"}, +@@ -1480,10 +1551,10 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + shader_sm4_read_dcl_indexable_temp}, + {VKD3D_SM4_OP_DCL_GLOBAL_FLAGS, VKD3DSIH_DCL_GLOBAL_FLAGS, "", "", + shader_sm4_read_dcl_global_flags}, +- {VKD3D_SM4_OP_LOD, VKD3DSIH_LOD, "f", "fRS"}, +- {VKD3D_SM4_OP_GATHER4, VKD3DSIH_GATHER4, "u", "fRS"}, +- {VKD3D_SM4_OP_SAMPLE_POS, VKD3DSIH_SAMPLE_POS, "f", "Ru"}, +- {VKD3D_SM4_OP_SAMPLE_INFO, VKD3DSIH_SAMPLE_INFO, "f", "R"}, ++ {VKD3D_SM4_OP_LOD, VKD3DSIH_LOD, "f", "f**"}, ++ {VKD3D_SM4_OP_GATHER4, VKD3DSIH_GATHER4, "u", "f**"}, ++ {VKD3D_SM4_OP_SAMPLE_POS, VKD3DSIH_SAMPLE_POS, "f", "*u"}, ++ {VKD3D_SM4_OP_SAMPLE_INFO, VKD3DSIH_SAMPLE_INFO, "f", "*"}, + {VKD3D_SM5_OP_HS_DECLS, VKD3DSIH_HS_DECLS, "", ""}, + {VKD3D_SM5_OP_HS_CONTROL_POINT_PHASE, VKD3DSIH_HS_CONTROL_POINT_PHASE, "", ""}, + {VKD3D_SM5_OP_HS_FORK_PHASE, VKD3DSIH_HS_FORK_PHASE, "", ""}, +@@ -1492,14 +1563,14 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + {VKD3D_SM5_OP_CUT_STREAM, VKD3DSIH_CUT_STREAM, "", "f"}, + {VKD3D_SM5_OP_FCALL, VKD3DSIH_FCALL, "", "O", + shader_sm5_read_fcall}, +- {VKD3D_SM5_OP_BUFINFO, VKD3DSIH_BUFINFO, "i", "U"}, ++ {VKD3D_SM5_OP_BUFINFO, VKD3DSIH_BUFINFO, "i", "*"}, + {VKD3D_SM5_OP_DERIV_RTX_COARSE, VKD3DSIH_DSX_COARSE, "f", "f"}, + {VKD3D_SM5_OP_DERIV_RTX_FINE, VKD3DSIH_DSX_FINE, "f", "f"}, + {VKD3D_SM5_OP_DERIV_RTY_COARSE, VKD3DSIH_DSY_COARSE, "f", "f"}, + {VKD3D_SM5_OP_DERIV_RTY_FINE, VKD3DSIH_DSY_FINE, "f", "f"}, +- {VKD3D_SM5_OP_GATHER4_C, VKD3DSIH_GATHER4_C, "f", "fRSf"}, +- {VKD3D_SM5_OP_GATHER4_PO, VKD3DSIH_GATHER4_PO, "f", "fiRS"}, +- {VKD3D_SM5_OP_GATHER4_PO_C, VKD3DSIH_GATHER4_PO_C, "f", "fiRSf"}, ++ {VKD3D_SM5_OP_GATHER4_C, VKD3DSIH_GATHER4_C, "f", "f**f"}, ++ {VKD3D_SM5_OP_GATHER4_PO, VKD3DSIH_GATHER4_PO, "f", "fi**"}, ++ {VKD3D_SM5_OP_GATHER4_PO_C, VKD3DSIH_GATHER4_PO_C, "f", "fi**f"}, + {VKD3D_SM5_OP_RCP, VKD3DSIH_RCP, "f", "f"}, + {VKD3D_SM5_OP_F32TOF16, VKD3DSIH_F32TOF16, "u", "f"}, + {VKD3D_SM5_OP_F16TOF32, VKD3DSIH_F16TOF32, "f", "u"}, +@@ -1551,33 +1622,33 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + shader_sm5_read_dcl_resource_raw}, + {VKD3D_SM5_OP_DCL_RESOURCE_STRUCTURED, VKD3DSIH_DCL_RESOURCE_STRUCTURED, "", "", + shader_sm5_read_dcl_resource_structured}, +- {VKD3D_SM5_OP_LD_UAV_TYPED, VKD3DSIH_LD_UAV_TYPED, "u", "iU"}, +- {VKD3D_SM5_OP_STORE_UAV_TYPED, VKD3DSIH_STORE_UAV_TYPED, "U", "iu"}, +- {VKD3D_SM5_OP_LD_RAW, VKD3DSIH_LD_RAW, "u", "iU"}, +- {VKD3D_SM5_OP_STORE_RAW, VKD3DSIH_STORE_RAW, "U", "uu"}, +- {VKD3D_SM5_OP_LD_STRUCTURED, VKD3DSIH_LD_STRUCTURED, "u", "iiR"}, +- {VKD3D_SM5_OP_STORE_STRUCTURED, VKD3DSIH_STORE_STRUCTURED, "U", "iiu"}, +- {VKD3D_SM5_OP_ATOMIC_AND, VKD3DSIH_ATOMIC_AND, "U", "iu"}, +- {VKD3D_SM5_OP_ATOMIC_OR, VKD3DSIH_ATOMIC_OR, "U", "iu"}, +- {VKD3D_SM5_OP_ATOMIC_XOR, VKD3DSIH_ATOMIC_XOR, "U", "iu"}, +- {VKD3D_SM5_OP_ATOMIC_CMP_STORE, VKD3DSIH_ATOMIC_CMP_STORE, "U", "iuu"}, +- {VKD3D_SM5_OP_ATOMIC_IADD, VKD3DSIH_ATOMIC_IADD, "U", "ii"}, +- {VKD3D_SM5_OP_ATOMIC_IMAX, VKD3DSIH_ATOMIC_IMAX, "U", "ii"}, +- {VKD3D_SM5_OP_ATOMIC_IMIN, VKD3DSIH_ATOMIC_IMIN, "U", "ii"}, +- {VKD3D_SM5_OP_ATOMIC_UMAX, VKD3DSIH_ATOMIC_UMAX, "U", "iu"}, +- {VKD3D_SM5_OP_ATOMIC_UMIN, VKD3DSIH_ATOMIC_UMIN, "U", "iu"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_ALLOC, VKD3DSIH_IMM_ATOMIC_ALLOC, "u", "U"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_CONSUME, VKD3DSIH_IMM_ATOMIC_CONSUME, "u", "U"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_IADD, VKD3DSIH_IMM_ATOMIC_IADD, "uU", "ii"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_AND, VKD3DSIH_IMM_ATOMIC_AND, "uU", "iu"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_OR, VKD3DSIH_IMM_ATOMIC_OR, "uU", "iu"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_XOR, VKD3DSIH_IMM_ATOMIC_XOR, "uU", "iu"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_EXCH, VKD3DSIH_IMM_ATOMIC_EXCH, "uU", "iu"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_CMP_EXCH, VKD3DSIH_IMM_ATOMIC_CMP_EXCH, "uU", "iuu"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_IMAX, VKD3DSIH_IMM_ATOMIC_IMAX, "iU", "ii"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_IMIN, VKD3DSIH_IMM_ATOMIC_IMIN, "iU", "ii"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_UMAX, VKD3DSIH_IMM_ATOMIC_UMAX, "uU", "iu"}, +- {VKD3D_SM5_OP_IMM_ATOMIC_UMIN, VKD3DSIH_IMM_ATOMIC_UMIN, "uU", "iu"}, ++ {VKD3D_SM5_OP_LD_UAV_TYPED, VKD3DSIH_LD_UAV_TYPED, "u", "i*"}, ++ {VKD3D_SM5_OP_STORE_UAV_TYPED, VKD3DSIH_STORE_UAV_TYPED, "*", "iu"}, ++ {VKD3D_SM5_OP_LD_RAW, VKD3DSIH_LD_RAW, "u", "i*"}, ++ {VKD3D_SM5_OP_STORE_RAW, VKD3DSIH_STORE_RAW, "*", "uu"}, ++ {VKD3D_SM5_OP_LD_STRUCTURED, VKD3DSIH_LD_STRUCTURED, "u", "ii*"}, ++ {VKD3D_SM5_OP_STORE_STRUCTURED, VKD3DSIH_STORE_STRUCTURED, "*", "iiu"}, ++ {VKD3D_SM5_OP_ATOMIC_AND, VKD3DSIH_ATOMIC_AND, "*", "iu"}, ++ {VKD3D_SM5_OP_ATOMIC_OR, VKD3DSIH_ATOMIC_OR, "*", "iu"}, ++ {VKD3D_SM5_OP_ATOMIC_XOR, VKD3DSIH_ATOMIC_XOR, "*", "iu"}, ++ {VKD3D_SM5_OP_ATOMIC_CMP_STORE, VKD3DSIH_ATOMIC_CMP_STORE, "*", "iuu"}, ++ {VKD3D_SM5_OP_ATOMIC_IADD, VKD3DSIH_ATOMIC_IADD, "*", "ii"}, ++ {VKD3D_SM5_OP_ATOMIC_IMAX, VKD3DSIH_ATOMIC_IMAX, "*", "ii"}, ++ {VKD3D_SM5_OP_ATOMIC_IMIN, VKD3DSIH_ATOMIC_IMIN, "*", "ii"}, ++ {VKD3D_SM5_OP_ATOMIC_UMAX, VKD3DSIH_ATOMIC_UMAX, "*", "iu"}, ++ {VKD3D_SM5_OP_ATOMIC_UMIN, VKD3DSIH_ATOMIC_UMIN, "*", "iu"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_ALLOC, VKD3DSIH_IMM_ATOMIC_ALLOC, "u", "*"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_CONSUME, VKD3DSIH_IMM_ATOMIC_CONSUME, "u", "*"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_IADD, VKD3DSIH_IMM_ATOMIC_IADD, "u*", "ii"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_AND, VKD3DSIH_IMM_ATOMIC_AND, "u*", "iu"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_OR, VKD3DSIH_IMM_ATOMIC_OR, "u*", "iu"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_XOR, VKD3DSIH_IMM_ATOMIC_XOR, "u*", "iu"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_EXCH, VKD3DSIH_IMM_ATOMIC_EXCH, "u*", "iu"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_CMP_EXCH, VKD3DSIH_IMM_ATOMIC_CMP_EXCH, "u*", "iuu"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_IMAX, VKD3DSIH_IMM_ATOMIC_IMAX, "i*", "ii"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_IMIN, VKD3DSIH_IMM_ATOMIC_IMIN, "i*", "ii"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_UMAX, VKD3DSIH_IMM_ATOMIC_UMAX, "u*", "iu"}, ++ {VKD3D_SM5_OP_IMM_ATOMIC_UMIN, VKD3DSIH_IMM_ATOMIC_UMIN, "u*", "iu"}, + {VKD3D_SM5_OP_SYNC, VKD3DSIH_SYNC, "", "", + shader_sm5_read_sync}, + {VKD3D_SM5_OP_DADD, VKD3DSIH_DADD, "d", "dd"}, +@@ -1604,21 +1675,21 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + {VKD3D_SM5_OP_DTOU, VKD3DSIH_DTOU, "u", "d"}, + {VKD3D_SM5_OP_ITOD, VKD3DSIH_ITOD, "d", "i"}, + {VKD3D_SM5_OP_UTOD, VKD3DSIH_UTOD, "d", "u"}, +- {VKD3D_SM5_OP_GATHER4_S, VKD3DSIH_GATHER4_S, "uu", "fRS"}, +- {VKD3D_SM5_OP_GATHER4_C_S, VKD3DSIH_GATHER4_C_S, "fu", "fRSf"}, +- {VKD3D_SM5_OP_GATHER4_PO_S, VKD3DSIH_GATHER4_PO_S, "fu", "fiRS"}, +- {VKD3D_SM5_OP_GATHER4_PO_C_S, VKD3DSIH_GATHER4_PO_C_S, "fu", "fiRSf"}, +- {VKD3D_SM5_OP_LD_S, VKD3DSIH_LD_S, "uu", "iR"}, +- {VKD3D_SM5_OP_LD2DMS_S, VKD3DSIH_LD2DMS_S, "uu", "iRi"}, ++ {VKD3D_SM5_OP_GATHER4_S, VKD3DSIH_GATHER4_S, "uu", "f**"}, ++ {VKD3D_SM5_OP_GATHER4_C_S, VKD3DSIH_GATHER4_C_S, "fu", "f**f"}, ++ {VKD3D_SM5_OP_GATHER4_PO_S, VKD3DSIH_GATHER4_PO_S, "fu", "fi**"}, ++ {VKD3D_SM5_OP_GATHER4_PO_C_S, VKD3DSIH_GATHER4_PO_C_S, "fu", "fi**f"}, ++ {VKD3D_SM5_OP_LD_S, VKD3DSIH_LD_S, "uu", "i*"}, ++ {VKD3D_SM5_OP_LD2DMS_S, VKD3DSIH_LD2DMS_S, "uu", "i*i"}, + {VKD3D_SM5_OP_LD_UAV_TYPED_S, VKD3DSIH_LD_UAV_TYPED_S, "uu", "iU"}, + {VKD3D_SM5_OP_LD_RAW_S, VKD3DSIH_LD_RAW_S, "uu", "iU"}, +- {VKD3D_SM5_OP_LD_STRUCTURED_S, VKD3DSIH_LD_STRUCTURED_S, "uu", "iiR"}, +- {VKD3D_SM5_OP_SAMPLE_LOD_S, VKD3DSIH_SAMPLE_LOD_S, "uu", "fRSf"}, +- {VKD3D_SM5_OP_SAMPLE_C_LZ_S, VKD3DSIH_SAMPLE_C_LZ_S, "fu", "fRSf"}, +- {VKD3D_SM5_OP_SAMPLE_CL_S, VKD3DSIH_SAMPLE_CL_S, "uu", "fRSf"}, +- {VKD3D_SM5_OP_SAMPLE_B_CL_S, VKD3DSIH_SAMPLE_B_CL_S, "uu", "fRSff"}, +- {VKD3D_SM5_OP_SAMPLE_GRAD_CL_S, VKD3DSIH_SAMPLE_GRAD_CL_S, "uu", "fRSfff"}, +- {VKD3D_SM5_OP_SAMPLE_C_CL_S, VKD3DSIH_SAMPLE_C_CL_S, "fu", "fRSff"}, ++ {VKD3D_SM5_OP_LD_STRUCTURED_S, VKD3DSIH_LD_STRUCTURED_S, "uu", "ii*"}, ++ {VKD3D_SM5_OP_SAMPLE_LOD_S, VKD3DSIH_SAMPLE_LOD_S, "uu", "f**f"}, ++ {VKD3D_SM5_OP_SAMPLE_C_LZ_S, VKD3DSIH_SAMPLE_C_LZ_S, "fu", "f**f"}, ++ {VKD3D_SM5_OP_SAMPLE_CL_S, VKD3DSIH_SAMPLE_CL_S, "uu", "f**f"}, ++ {VKD3D_SM5_OP_SAMPLE_B_CL_S, VKD3DSIH_SAMPLE_B_CL_S, "uu", "f**ff"}, ++ {VKD3D_SM5_OP_SAMPLE_GRAD_CL_S, VKD3DSIH_SAMPLE_GRAD_CL_S, "uu", "f**fff"}, ++ {VKD3D_SM5_OP_SAMPLE_C_CL_S, VKD3DSIH_SAMPLE_C_CL_S, "fu", "f**ff"}, + {VKD3D_SM5_OP_CHECK_ACCESS_FULLY_MAPPED, VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED, "u", "u"}, + }; + @@ -1662,6 +1733,161 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) {VKD3D_SM5_RT_OUTPUT_STENCIL_REF, VKD3DSPR_OUTSTENCILREF, VKD3D_SM4_SWIZZLE_VEC4}, }; @@ -9013,7 +13199,22 @@ index 84f641cc316..884a2998d5b 100644 static enum vkd3d_data_type map_data_type(char t) { switch (t) -@@ -2553,7 +2798,7 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_pro +@@ -1735,12 +1980,8 @@ static enum vkd3d_data_type map_data_type(char t) + return VKD3D_DATA_UINT; + case 'O': + return VKD3D_DATA_OPAQUE; +- case 'R': +- return VKD3D_DATA_RESOURCE; +- case 'S': +- return VKD3D_DATA_SAMPLER; +- case 'U': +- return VKD3D_DATA_UAV; ++ case '*': ++ return VKD3D_DATA_UNUSED; + default: + ERR("Invalid data type '%c'.\n", t); + return VKD3D_DATA_FLOAT; +@@ -2553,7 +2794,7 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_pro version.minor = VKD3D_SM4_VERSION_MINOR(version_token); /* Estimate instruction count to avoid reallocation in most shaders. */ @@ -9022,7 +13223,35 @@ index 84f641cc316..884a2998d5b 100644 return false; vkd3d_shader_parser_init(&sm4->p, program, message_context, compile_info->source_name); sm4->ptr = sm4->start; -@@ -2782,8 +3027,8 @@ bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_sem +@@ -2706,9 +2947,6 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con + && !sm4.has_control_point_phase && !sm4.p.failed) + shader_sm4_validate_default_phase_index_ranges(&sm4); + +- if (!sm4.p.failed) +- vkd3d_shader_parser_validate(&sm4.p, config_flags); +- + if (sm4.p.failed) + { + WARN("Failed to parse shader.\n"); +@@ -2716,6 +2954,17 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con + return VKD3D_ERROR_INVALID_SHADER; + } + ++ if ((ret = vkd3d_shader_parser_validate(&sm4.p, config_flags)) < 0) ++ { ++ WARN("Failed to validate shader after parsing, ret %d.\n", ret); ++ ++ if (TRACE_ON()) ++ vkd3d_shader_trace(program); ++ ++ vsir_program_cleanup(program); ++ return ret; ++ } ++ + return VKD3D_OK; + } + +@@ -2782,8 +3031,8 @@ bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_sem return false; } @@ -9033,7 +13262,7 @@ index 84f641cc316..884a2998d5b 100644 { unsigned int i; -@@ -2792,7 +3037,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant +@@ -2792,7 +3041,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant const char *name; bool output; enum vkd3d_shader_type shader_type; @@ -9042,7 +13271,7 @@ index 84f641cc316..884a2998d5b 100644 } semantics[] = { -@@ -2800,46 +3045,47 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant +@@ -2800,46 +3049,47 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant {"sv_groupid", false, VKD3D_SHADER_TYPE_COMPUTE, ~0u}, {"sv_groupthreadid", false, VKD3D_SHADER_TYPE_COMPUTE, ~0u}, @@ -9122,7 +13351,7 @@ index 84f641cc316..884a2998d5b 100644 return true; } } -@@ -2847,7 +3093,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant +@@ -2847,7 +3097,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semant if (!needs_compat_mapping) return false; @@ -9131,7 +13360,7 @@ index 84f641cc316..884a2998d5b 100644 return true; } -@@ -2880,16 +3126,16 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, +@@ -2880,16 +3130,16 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { unsigned int width = (1u << var->data_type->dimx) - 1, use_mask; @@ -9151,7 +13380,7 @@ index 84f641cc316..884a2998d5b 100644 continue; usage_idx = var->semantic.index; -@@ -2908,26 +3154,26 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, +@@ -2908,26 +3158,26 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, use_mask = 0xf ^ use_mask; /* Special pixel shader semantics (TARGET, DEPTH, COVERAGE). */ @@ -9184,7 +13413,7 @@ index 84f641cc316..884a2998d5b 100644 break; default: -@@ -2935,7 +3181,7 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, +@@ -2935,7 +3185,7 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Invalid data type %s for semantic variable %s.", string->buffer, var->name); hlsl_release_string_buffer(ctx, string); @@ -9193,7 +13422,7 @@ index 84f641cc316..884a2998d5b 100644 } put_u32(&buffer, reg_idx); put_u32(&buffer, vkd3d_make_u16(width, use_mask)); -@@ -2944,25 +3190,25 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, +@@ -2944,25 +3194,25 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, i = 0; LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { @@ -9227,7 +13456,15 @@ index 84f641cc316..884a2998d5b 100644 set_u32(&buffer, (2 + i++ * 6) * sizeof(uint32_t), string_offset); } -@@ -3123,24 +3369,24 @@ static D3D_SHADER_INPUT_TYPE sm4_resource_type(const struct hlsl_type *type) +@@ -2990,6 +3240,7 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type) + case HLSL_CLASS_DEPTH_STENCIL_STATE: + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: ++ case HLSL_CLASS_ERROR: + case HLSL_CLASS_STRUCT: + case HLSL_CLASS_PASS: + case HLSL_CLASS_PIXEL_SHADER: +@@ -3123,24 +3374,24 @@ static D3D_SHADER_INPUT_TYPE sm4_resource_type(const struct hlsl_type *type) vkd3d_unreachable(); } @@ -9257,7 +13494,56 @@ index 84f641cc316..884a2998d5b 100644 default: vkd3d_unreachable(); -@@ -3471,7 +3717,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) +@@ -3398,6 +3649,48 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un + return extern_resources; + } + ++/* For some reason, for matrices, values from default value initializers end up in different ++ * components than from regular initializers. Default value initializers fill the matrix in ++ * vertical reading order (left-to-right top-to-bottom) instead of regular reading order ++ * (top-to-bottom left-to-right), so they have to be adjusted. ++ * An exception is that the order of matrix initializers for function parameters are row-major ++ * (top-to-bottom left-to-right). */ ++static unsigned int get_component_index_from_default_initializer_index(struct hlsl_type *type, unsigned int index) ++{ ++ unsigned int element_comp_count, element, x, y, i; ++ unsigned int base = 0; ++ ++ switch (type->class) ++ { ++ case HLSL_CLASS_MATRIX: ++ x = index / type->dimy; ++ y = index % type->dimy; ++ return y * type->dimx + x; ++ ++ case HLSL_CLASS_ARRAY: ++ element_comp_count = hlsl_type_component_count(type->e.array.type); ++ element = index / element_comp_count; ++ base = element * element_comp_count; ++ return base + get_component_index_from_default_initializer_index(type->e.array.type, index - base); ++ ++ case HLSL_CLASS_STRUCT: ++ for (i = 0; i < type->e.record.field_count; ++i) ++ { ++ struct hlsl_type *field_type = type->e.record.fields[i].type; ++ ++ element_comp_count = hlsl_type_component_count(field_type); ++ if (index - base < element_comp_count) ++ return base + get_component_index_from_default_initializer_index(field_type, index - base); ++ base += element_comp_count; ++ } ++ break; ++ ++ default: ++ return index; ++ } ++ vkd3d_unreachable(); ++} ++ + static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) + { + uint32_t binding_desc_size = (hlsl_version_ge(ctx, 5, 1) ? 10 : 8) * sizeof(uint32_t); +@@ -3471,7 +3764,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) { unsigned int dimx = resource->component_type->e.resource.format->dimx; @@ -9266,7 +13552,26 @@ index 84f641cc316..884a2998d5b 100644 put_u32(&buffer, sm4_rdef_resource_dimension(resource->component_type)); put_u32(&buffer, ~0u); /* FIXME: multisample count */ flags |= (dimx - 1) << VKD3D_SM4_SIF_TEXTURE_COMPONENTS_SHIFT; -@@ -4182,10 +4428,55 @@ static void sm4_write_src_register(const struct tpf_writer *tpf, const struct vk +@@ -3598,7 +3891,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) + for (k = 0; k < comp_count; ++k) + { + struct hlsl_type *comp_type = hlsl_type_get_component_type(ctx, var->data_type, k); +- unsigned int comp_offset; ++ unsigned int comp_offset, comp_index; + enum hlsl_regset regset; + + if (comp_type->class == HLSL_CLASS_STRING) +@@ -3608,7 +3901,8 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) + continue; + } + +- comp_offset = hlsl_type_get_component_offset(ctx, var->data_type, k, ®set); ++ comp_index = get_component_index_from_default_initializer_index(var->data_type, k); ++ comp_offset = hlsl_type_get_component_offset(ctx, var->data_type, comp_index, ®set); + if (regset == HLSL_REGSET_NUMERIC) + { + if (comp_type->e.numeric.type == HLSL_TYPE_DOUBLE) +@@ -4182,10 +4476,55 @@ static void sm4_write_src_register(const struct tpf_writer *tpf, const struct vk } } @@ -9323,7 +13628,7 @@ index 84f641cc316..884a2998d5b 100644 unsigned int size, i, j; size_t token_position; -@@ -4218,6 +4509,8 @@ static void write_sm4_instruction(const struct tpf_writer *tpf, const struct sm4 +@@ -4218,6 +4557,8 @@ static void write_sm4_instruction(const struct tpf_writer *tpf, const struct sm4 size = (bytecode_get_size(buffer) - token_position) / sizeof(uint32_t); token |= (size << VKD3D_SM4_INSTRUCTION_LENGTH_SHIFT); set_u32(buffer, token_position, token); @@ -9332,7 +13637,7 @@ index 84f641cc316..884a2998d5b 100644 } static bool encode_texel_offset_as_aoffimmi(struct sm4_instruction *instr, -@@ -4348,7 +4641,7 @@ static void write_sm4_dcl_textures(const struct tpf_writer *tpf, const struct ex +@@ -4348,7 +4689,7 @@ static void write_sm4_dcl_textures(const struct tpf_writer *tpf, const struct ex .dsts[0].reg.idx_count = 1, .dst_count = 1, @@ -9341,7 +13646,7 @@ index 84f641cc316..884a2998d5b 100644 .idx_count = 1, }; -@@ -4412,7 +4705,7 @@ static void write_sm4_dcl_semantic(const struct tpf_writer *tpf, const struct hl +@@ -4412,7 +4753,7 @@ static void write_sm4_dcl_semantic(const struct tpf_writer *tpf, const struct hl { const struct hlsl_profile_info *profile = tpf->ctx->profile; const bool output = var->is_output_semantic; @@ -9350,7 +13655,7 @@ index 84f641cc316..884a2998d5b 100644 bool has_idx; struct sm4_instruction instr = -@@ -4445,22 +4738,23 @@ static void write_sm4_dcl_semantic(const struct tpf_writer *tpf, const struct hl +@@ -4445,22 +4786,23 @@ static void write_sm4_dcl_semantic(const struct tpf_writer *tpf, const struct hl if (instr.dsts[0].reg.type == VKD3DSPR_DEPTHOUT) instr.dsts[0].reg.dimension = VSIR_DIMENSION_SCALAR; @@ -9382,7 +13687,7 @@ index 84f641cc316..884a2998d5b 100644 instr.opcode = (profile->type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3D_SM4_OP_DCL_INPUT_PS_SGV : VKD3D_SM4_OP_DCL_INPUT_SGV; break; -@@ -4510,25 +4804,25 @@ static void write_sm4_dcl_semantic(const struct tpf_writer *tpf, const struct hl +@@ -4510,25 +4852,25 @@ static void write_sm4_dcl_semantic(const struct tpf_writer *tpf, const struct hl } else { @@ -9417,7 +13722,7 @@ index 84f641cc316..884a2998d5b 100644 break; } -@@ -4577,6 +4871,17 @@ static void write_sm4_dcl_thread_group(const struct tpf_writer *tpf, const uint3 +@@ -4577,6 +4919,17 @@ static void write_sm4_dcl_thread_group(const struct tpf_writer *tpf, const uint3 write_sm4_instruction(tpf, &instr); } @@ -9435,7 +13740,7 @@ index 84f641cc316..884a2998d5b 100644 static void write_sm4_ret(const struct tpf_writer *tpf) { struct sm4_instruction instr = -@@ -5578,6 +5883,23 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex +@@ -5578,6 +5931,23 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex write_sm4_ternary_op(tpf, VKD3D_SM4_OP_MOVC, &expr->node, arg1, arg2, arg3); break; @@ -9459,7 +13764,7 @@ index 84f641cc316..884a2998d5b 100644 default: hlsl_fixme(tpf->ctx, &expr->node.loc, "SM4 %s expression.", debug_hlsl_expr_op(expr->op)); } -@@ -5998,8 +6320,8 @@ static void write_sm4_block(const struct tpf_writer *tpf, const struct hlsl_bloc +@@ -5998,8 +6368,8 @@ static void write_sm4_block(const struct tpf_writer *tpf, const struct hlsl_bloc } } @@ -9470,7 +13775,7 @@ index 84f641cc316..884a2998d5b 100644 { const struct hlsl_profile_info *profile = ctx->profile; struct vkd3d_bytecode_buffer buffer = {0}; -@@ -6024,7 +6346,7 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, +@@ -6024,7 +6394,7 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, VKD3D_SM4_LIB, }; @@ -9479,7 +13784,7 @@ index 84f641cc316..884a2998d5b 100644 extern_resources = sm4_get_extern_resources(ctx, &extern_resources_count); -@@ -6049,6 +6371,9 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, +@@ -6049,6 +6419,9 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, write_sm4_dcl_textures(&tpf, resource, true); } @@ -9489,7 +13794,7 @@ index 84f641cc316..884a2998d5b 100644 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { if ((var->is_input_semantic && var->last_read) || (var->is_output_semantic && var->first_write)) -@@ -6110,14 +6435,64 @@ static void write_sm4_sfi0(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) +@@ -6110,14 +6483,64 @@ static void write_sm4_sfi0(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) /* FIXME: We also emit code that should require UAVS_AT_EVERY_STAGE, * STENCIL_REF, and TYPED_UAV_LOAD_ADDITIONAL_FORMATS. */ @@ -9555,7 +13860,7 @@ index 84f641cc316..884a2998d5b 100644 struct dxbc_writer dxbc; size_t i; int ret; -@@ -6127,8 +6502,9 @@ int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun +@@ -6127,8 +6550,9 @@ int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun write_sm4_signature(ctx, &dxbc, false); write_sm4_signature(ctx, &dxbc, true); write_sm4_rdef(ctx, &dxbc); @@ -9567,7 +13872,7 @@ index 84f641cc316..884a2998d5b 100644 if (!(ret = ctx->result)) ret = dxbc_writer_write(&dxbc, out); diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index 306c1ca0dd8..fc217860403 100644 +index 306c1ca0dd8..ee8a633431a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c @@ -23,6 +23,8 @@ @@ -9617,14 +13922,14 @@ index 306c1ca0dd8..fc217860403 100644 + str_checksum[2 * i + 1] = hexadecimal_digits[checksum[i] & 0xf]; + } + str_checksum[32] = '\0'; - -- if (profile) -- snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%u-%s.%s", path, id, profile, suffix); ++ + pos = snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%s", dump_data->path, str_checksum); + + if (dump_data->profile) + pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-%s", dump_data->profile); -+ + +- if (profile) +- snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%u-%s.%s", path, id, profile, suffix); + if (source) + pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-source.%s", dump_data->source_suffix); else @@ -9693,11 +13998,11 @@ index 306c1ca0dd8..fc217860403 100644 { - if (!(hlsl_source_info = vkd3d_find_struct(compile_info->next, HLSL_SOURCE_INFO))) - return; -+ const struct vkd3d_shader_hlsl_source_info *hlsl_source_info; - +- - if (!(profile = hlsl_get_target_info(hlsl_source_info->profile))) - return; -- ++ const struct vkd3d_shader_hlsl_source_info *hlsl_source_info; + - profile_name = profile->name; + if ((hlsl_source_info = vkd3d_find_struct(compile_info->next, HLSL_SOURCE_INFO))) + data->profile = hlsl_source_info->profile; @@ -9730,17 +14035,31 @@ index 306c1ca0dd8..fc217860403 100644 if (compile_info->source_type == VKD3D_SHADER_SOURCE_HLSL) { -@@ -1580,7 +1635,8 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, +@@ -1565,6 +1620,7 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, + struct vkd3d_shader_message_context *message_context) + { ++ struct vkd3d_shader_scan_combined_resource_sampler_info combined_sampler_info; + struct vkd3d_shader_scan_descriptor_info1 scan_descriptor_info; + struct vkd3d_shader_compile_info scan_info; + int ret; +@@ -1578,9 +1634,14 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, + break; + case VKD3D_SHADER_TARGET_GLSL: ++ combined_sampler_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_COMBINED_RESOURCE_SAMPLER_INFO; ++ combined_sampler_info.next = scan_info.next; ++ scan_info.next = &combined_sampler_info; if ((ret = vsir_program_scan(program, &scan_info, message_context, &scan_descriptor_info)) < 0) return ret; - ret = glsl_compile(program, config_flags, compile_info, out, message_context); + ret = glsl_compile(program, config_flags, &scan_descriptor_info, -+ compile_info, out, message_context); ++ &combined_sampler_info, compile_info, out, message_context); ++ vkd3d_shader_free_scan_combined_resource_sampler_info(&combined_sampler_info); vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); break; -@@ -1593,6 +1649,10 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, +@@ -1593,6 +1654,10 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); break; @@ -9751,7 +14070,7 @@ index 306c1ca0dd8..fc217860403 100644 default: /* Validation should prevent us from reaching this. */ vkd3d_unreachable(); -@@ -1620,6 +1680,7 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, +@@ -1620,6 +1685,7 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, char **messages) { struct vkd3d_shader_message_context message_context; @@ -9759,7 +14078,7 @@ index 306c1ca0dd8..fc217860403 100644 int ret; TRACE("compile_info %p, out %p, messages %p.\n", compile_info, out, messages); -@@ -1634,7 +1695,8 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, +@@ -1634,7 +1700,8 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, vkd3d_shader_message_context_init(&message_context, compile_info->log_level); @@ -9769,7 +14088,7 @@ index 306c1ca0dd8..fc217860403 100644 if (compile_info->source_type == VKD3D_SHADER_SOURCE_HLSL) { -@@ -1676,6 +1738,8 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, +@@ -1676,6 +1743,8 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, } } @@ -9778,7 +14097,7 @@ index 306c1ca0dd8..fc217860403 100644 vkd3d_shader_message_context_trace_messages(&message_context); if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) ret = VKD3D_ERROR_OUT_OF_MEMORY; -@@ -1888,6 +1952,9 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( +@@ -1888,6 +1957,9 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( VKD3D_SHADER_TARGET_D3D_ASM, #ifdef VKD3D_SHADER_UNSUPPORTED_GLSL VKD3D_SHADER_TARGET_GLSL, @@ -9789,10 +14108,19 @@ index 306c1ca0dd8..fc217860403 100644 }; diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index ef66a8ca07a..447210449da 100644 +index ef66a8ca07a..eab164cc848 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -80,6 +80,7 @@ enum vkd3d_shader_error +@@ -59,6 +59,8 @@ + #define VKD3D_VEC4_SIZE 4 + #define VKD3D_DVEC2_SIZE 2 + ++#define VKD3D_SHADER_COMPONENT_TYPE_COUNT (VKD3D_SHADER_COMPONENT_UINT64 + 1) ++ + enum vkd3d_shader_error + { + VKD3D_SHADER_ERROR_DXBC_INVALID_SIZE = 1, +@@ -80,6 +82,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_TPF_INVALID_CASE_VALUE = 1007, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_DIMENSION = 1008, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_SWIZZLE = 1009, @@ -9800,7 +14128,7 @@ index ef66a8ca07a..447210449da 100644 VKD3D_SHADER_WARNING_TPF_MASK_NOT_CONTIGUOUS = 1300, VKD3D_SHADER_WARNING_TPF_UNHANDLED_INDEX_RANGE_MASK = 1301, -@@ -152,6 +153,12 @@ enum vkd3d_shader_error +@@ -152,6 +155,13 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_HLSL_UNKNOWN_MODIFIER = 5030, VKD3D_SHADER_ERROR_HLSL_INVALID_STATE_BLOCK_ENTRY = 5031, VKD3D_SHADER_ERROR_HLSL_FAILED_FORCED_UNROLL = 5032, @@ -9810,10 +14138,11 @@ index ef66a8ca07a..447210449da 100644 + VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT = 5036, + VKD3D_SHADER_ERROR_HLSL_INVALID_OUTPUT_PRIMITIVE = 5037, + VKD3D_SHADER_ERROR_HLSL_INVALID_PARTITIONING = 5038, ++ VKD3D_SHADER_ERROR_HLSL_MISPLACED_SAMPLER_STATE = 5039, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, -@@ -159,8 +166,10 @@ enum vkd3d_shader_error +@@ -159,8 +169,11 @@ enum vkd3d_shader_error VKD3D_SHADER_WARNING_HLSL_IMAGINARY_NUMERIC_RESULT = 5303, VKD3D_SHADER_WARNING_HLSL_NON_FINITE_RESULT = 5304, VKD3D_SHADER_WARNING_HLSL_IGNORED_ATTRIBUTE = 5305, @@ -9821,10 +14150,11 @@ index ef66a8ca07a..447210449da 100644 VKD3D_SHADER_ERROR_GLSL_INTERNAL = 6000, + VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND = 6001, ++ VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED = 6002, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF = 7000, VKD3D_SHADER_ERROR_D3DBC_INVALID_VERSION_TOKEN = 7001, -@@ -169,6 +178,11 @@ enum vkd3d_shader_error +@@ -169,6 +182,11 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY = 7004, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX = 7005, VKD3D_SHADER_ERROR_D3DBC_UNDECLARED_SEMANTIC = 7006, @@ -9836,8 +14166,12 @@ index ef66a8ca07a..447210449da 100644 VKD3D_SHADER_WARNING_D3DBC_IGNORED_INSTRUCTION_FLAGS= 7300, -@@ -227,6 +241,8 @@ enum vkd3d_shader_error +@@ -225,8 +243,12 @@ enum vkd3d_shader_error + VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE = 9017, + VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION = 9018, VKD3D_SHADER_ERROR_VSIR_INVALID_GS = 9019, ++ VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER = 9020, ++ VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC = 9021, VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300, + @@ -9845,7 +14179,17 @@ index ef66a8ca07a..447210449da 100644 }; enum vkd3d_shader_opcode -@@ -1344,8 +1360,6 @@ bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *ins +@@ -642,9 +664,6 @@ enum vkd3d_data_type + { + VKD3D_DATA_FLOAT, + VKD3D_DATA_INT, +- VKD3D_DATA_RESOURCE, +- VKD3D_DATA_SAMPLER, +- VKD3D_DATA_UAV, + VKD3D_DATA_UINT, + VKD3D_DATA_UNORM, + VKD3D_DATA_SNORM, +@@ -1344,8 +1363,6 @@ bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *ins struct vkd3d_shader_immediate_constant_buffer *icb); bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions, unsigned int dst, unsigned int src); @@ -9854,7 +14198,7 @@ index ef66a8ca07a..447210449da 100644 void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions); enum vkd3d_shader_config_flags -@@ -1353,6 +1367,12 @@ enum vkd3d_shader_config_flags +@@ -1353,6 +1370,12 @@ enum vkd3d_shader_config_flags VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION = 0x00000001, }; @@ -9867,7 +14211,7 @@ index ef66a8ca07a..447210449da 100644 struct vsir_program { struct vkd3d_shader_version shader_version; -@@ -1372,6 +1392,7 @@ struct vsir_program +@@ -1372,6 +1395,7 @@ struct vsir_program unsigned int temp_count; unsigned int ssa_count; bool use_vocp; @@ -9875,7 +14219,7 @@ index ef66a8ca07a..447210449da 100644 const char **block_names; size_t block_name_count; -@@ -1384,11 +1405,16 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, +@@ -1384,11 +1408,16 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( const struct vsir_program *program, enum vkd3d_shader_parameter_name name); bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, @@ -9894,7 +14238,15 @@ index ef66a8ca07a..447210449da 100644 static inline struct vkd3d_shader_dst_param *vsir_program_get_dst_params( struct vsir_program *program, unsigned int count) -@@ -1549,7 +1575,6 @@ void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const st +@@ -1465,6 +1494,7 @@ enum vsir_asm_flags + { + VSIR_ASM_FLAG_NONE = 0, + VSIR_ASM_FLAG_DUMP_TYPES = 0x1, ++ VSIR_ASM_FLAG_DUMP_ALL_INDICES = 0x2, + }; + + enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, +@@ -1549,7 +1579,6 @@ void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const st void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, enum vkd3d_shader_error error, const char *format, va_list args); @@ -9902,19 +14254,20 @@ index ef66a8ca07a..447210449da 100644 uint64_t vkd3d_shader_init_config_flags(void); void vkd3d_shader_trace_text_(const char *text, size_t size, const char *function); #define vkd3d_shader_trace_text(text, size) \ -@@ -1570,8 +1595,9 @@ int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, +@@ -1570,8 +1599,10 @@ int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context, struct shader_signature *signature); int glsl_compile(struct vsir_program *program, uint64_t config_flags, - const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, - struct vkd3d_shader_message_context *message_context); + const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, ++ const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info, + const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); #define SPIRV_MAX_SRC_COUNT 6 -@@ -1580,7 +1606,16 @@ int spirv_compile(struct vsir_program *program, uint64_t config_flags, +@@ -1580,7 +1611,16 @@ int spirv_compile(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); @@ -9932,7 +14285,7 @@ index ef66a8ca07a..447210449da 100644 int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); -@@ -1853,7 +1888,7 @@ static inline void *vkd3d_find_struct_(const struct vkd3d_struct *chain, +@@ -1853,7 +1893,7 @@ static inline void *vkd3d_find_struct_(const struct vkd3d_struct *chain, #define VKD3D_DXBC_HEADER_SIZE (8 * sizeof(uint32_t)) #define VKD3D_DXBC_CHUNK_ALIGNMENT sizeof(uint32_t) @@ -10085,7 +14438,7 @@ index 01841c89692..65339c7ba5d 100644 VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing), VK_EXTENSION(EXT_FRAGMENT_SHADER_INTERLOCK, EXT_fragment_shader_interlock), diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c -index 682d488faa8..ea7d8f040b5 100644 +index 682d488faa8..fb377177403 100644 --- a/libs/vkd3d/libs/vkd3d/state.c +++ b/libs/vkd3d/libs/vkd3d/state.c @@ -738,7 +738,7 @@ static bool vkd3d_validate_descriptor_set_count(struct d3d12_device *device, uns @@ -10097,7 +14450,18 @@ index 682d488faa8..ea7d8f040b5 100644 return false; } -@@ -3867,6 +3867,7 @@ VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_sta +@@ -1107,7 +1107,9 @@ static int compare_descriptor_range(const void *a, const void *b) + if ((ret = vkd3d_u32_compare(range_a->offset, range_b->offset))) + return ret; + +- return (range_a->descriptor_count == UINT_MAX) - (range_b->descriptor_count == UINT_MAX); ++ /* Place bounded ranges after unbounded ones of equal offset, ++ * so the bounded range can be mapped to the unbounded one. */ ++ return (range_b->descriptor_count == UINT_MAX) - (range_a->descriptor_count == UINT_MAX); + } + + static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_root_signature *root_signature, +@@ -3867,6 +3869,7 @@ VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_sta VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_BLEND_CONSTANTS, VK_DYNAMIC_STATE_STENCIL_REFERENCE, @@ -10126,6 +14490,18 @@ index 831dc07af56..839bb173854 100644 #undef FLAG_TO_STR if (flags) FIXME("Unrecognized flag(s) %#x.\n", flags); +diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_main.c b/libs/vkd3d/libs/vkd3d/vkd3d_main.c +index 9eccec111c7..5215cf8ef86 100644 +--- a/libs/vkd3d/libs/vkd3d/vkd3d_main.c ++++ b/libs/vkd3d/libs/vkd3d/vkd3d_main.c +@@ -415,6 +415,7 @@ HRESULT vkd3d_create_versioned_root_signature_deserializer(const void *data, SIZ + if (FAILED(hr = d3d12_versioned_root_signature_deserializer_init(object, &dxbc))) + { + vkd3d_free(object); ++ *deserializer = NULL; + return hr; + } + diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h index ba4e2e8488d..e6d477a5c12 100644 --- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-a2aeb3a1421c5540b7f4d0e68ec3ff211e1.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-a2aeb3a1421c5540b7f4d0e68ec3ff211e1.patch deleted file mode 100644 index ae4242aa..00000000 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-a2aeb3a1421c5540b7f4d0e68ec3ff211e1.patch +++ /dev/null @@ -1,949 +0,0 @@ -From 1b1edbf05da10281bbb9b0ef228752ec9c21ab28 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 24 Sep 2024 08:29:40 +1000 -Subject: [PATCH] Updated vkd3d to a2aeb3a1421c5540b7f4d0e68ec3ff211e15f646. - ---- - libs/vkd3d/include/vkd3d_shader.h | 11 +++ - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 13 ++- - libs/vkd3d/libs/vkd3d-shader/fx.c | 2 + - libs/vkd3d/libs/vkd3d-shader/glsl.c | 56 +++++++++++ - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 39 ++++++-- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 13 +++ - libs/vkd3d/libs/vkd3d-shader/hlsl.l | 1 - - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 93 ++++++++++--------- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 36 ++++++- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 64 +++++-------- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 1 + - .../libs/vkd3d-shader/vkd3d_shader_private.h | 2 + - libs/vkd3d/libs/vkd3d/state.c | 4 +- - 13 files changed, 234 insertions(+), 101 deletions(-) - -diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h -index 46feff35138..115bb21b932 100644 ---- a/libs/vkd3d/include/vkd3d_shader.h -+++ b/libs/vkd3d/include/vkd3d_shader.h -@@ -190,6 +190,17 @@ enum vkd3d_shader_compile_option_backward_compatibility - * - DEPTH to SV_Depth for pixel shader outputs. - */ - VKD3D_SHADER_COMPILE_OPTION_BACKCOMPAT_MAP_SEMANTIC_NAMES = 0x00000001, -+ /** -+ * Causes 'double' to behave as an alias for 'float'. This option only -+ * applies to HLSL sources with shader model 1-3 target profiles. Without -+ * this option using the 'double' type produces compilation errors in -+ * these target profiles. -+ * -+ * This option is disabled by default. -+ * -+ * \since 1.14 -+ */ -+ VKD3D_SHADER_COMPILE_OPTION_DOUBLE_AS_FLOAT_ALIAS = 0x00000002, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY), - }; -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 10f2e5e5e6d..34752a1ab89 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -1522,6 +1522,7 @@ D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) - case HLSL_CLASS_DEPTH_STENCIL_STATE: - case HLSL_CLASS_DEPTH_STENCIL_VIEW: - case HLSL_CLASS_EFFECT_GROUP: -+ case HLSL_CLASS_ERROR: - case HLSL_CLASS_PASS: - case HLSL_CLASS_RASTERIZER_STATE: - case HLSL_CLASS_RENDER_TARGET_VIEW: -@@ -1627,6 +1628,7 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type) - case HLSL_CLASS_DEPTH_STENCIL_STATE: - case HLSL_CLASS_DEPTH_STENCIL_VIEW: - case HLSL_CLASS_EFFECT_GROUP: -+ case HLSL_CLASS_ERROR: - case HLSL_CLASS_PASS: - case HLSL_CLASS_RASTERIZER_STATE: - case HLSL_CLASS_RENDER_TARGET_VIEW: -@@ -1719,7 +1721,7 @@ static void sm1_sort_externs(struct hlsl_ctx *ctx) - - void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer) - { -- size_t ctab_offset, ctab_start, ctab_end, vars_start, size_offset, creator_offset, offset; -+ size_t ctab_offset, ctab_start, ctab_end, vars_offset, vars_start, size_offset, creator_offset, offset; - unsigned int uniform_count = 0; - struct hlsl_ir_var *var; - -@@ -1755,11 +1757,12 @@ void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buff - creator_offset = put_u32(buffer, 0); - put_u32(buffer, sm1_version(ctx->profile->type, ctx->profile->major_version, ctx->profile->minor_version)); - put_u32(buffer, uniform_count); -- put_u32(buffer, sizeof(D3DXSHADER_CONSTANTTABLE)); /* offset of constants */ -+ vars_offset = put_u32(buffer, 0); - put_u32(buffer, 0); /* FIXME: flags */ - put_u32(buffer, 0); /* FIXME: target string */ - - vars_start = bytecode_align(buffer); -+ set_u32(buffer, vars_offset, vars_start - ctab_start); - - LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) - { -@@ -1835,8 +1838,10 @@ void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buff - switch (comp_type->e.numeric.type) - { - case HLSL_TYPE_DOUBLE: -- hlsl_fixme(ctx, &var->loc, "Write double default values."); -- uni.u = 0; -+ if (ctx->double_as_float_alias) -+ uni.u = var->default_values[k].number.u; -+ else -+ uni.u = 0; - break; - - case HLSL_TYPE_INT: -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index 1314bc09e73..7d4a9d2e2ff 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -665,6 +665,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co - - case HLSL_CLASS_ARRAY: - case HLSL_CLASS_EFFECT_GROUP: -+ case HLSL_CLASS_ERROR: - case HLSL_CLASS_PASS: - case HLSL_CLASS_TECHNIQUE: - case HLSL_CLASS_CONSTANT_BUFFER: -@@ -1117,6 +1118,7 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type - return false; - - case HLSL_CLASS_EFFECT_GROUP: -+ case HLSL_CLASS_ERROR: - case HLSL_CLASS_PASS: - case HLSL_CLASS_TECHNIQUE: - case HLSL_CLASS_CONSTANT_BUFFER: -diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index dd1c121d5a8..b29f13f2b19 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/glsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -305,6 +305,9 @@ static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator - { - case VKD3DSPSM_NONE: - break; -+ case VKD3DSPSM_NEG: -+ vkd3d_string_buffer_printf(glsl_src->str, "-%s", str->buffer); -+ break; - case VKD3DSPSM_ABS: - vkd3d_string_buffer_printf(glsl_src->str, "abs(%s)", str->buffer); - break; -@@ -414,6 +417,22 @@ static void shader_glsl_binop(struct vkd3d_glsl_generator *gen, - glsl_dst_cleanup(&dst, &gen->string_buffers); - } - -+static void shader_glsl_intrinsic(struct vkd3d_glsl_generator *gen, -+ const struct vkd3d_shader_instruction *ins, const char *op) -+{ -+ struct glsl_src src; -+ struct glsl_dst dst; -+ uint32_t mask; -+ -+ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); -+ glsl_src_init(&src, gen, &ins->src[0], mask); -+ -+ shader_glsl_print_assignment(gen, &dst, "%s(%s)", op, src.str->buffer); -+ -+ glsl_src_cleanup(&src, &gen->string_buffers); -+ glsl_dst_cleanup(&dst, &gen->string_buffers); -+} -+ - static void shader_glsl_relop(struct vkd3d_glsl_generator *gen, - const struct vkd3d_shader_instruction *ins, const char *scalar_op, const char *vector_op) - { -@@ -453,6 +472,31 @@ static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d - glsl_dst_cleanup(&dst, &gen->string_buffers); - } - -+static void shader_glsl_movc(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ unsigned int component_count; -+ struct glsl_src src[3]; -+ struct glsl_dst dst; -+ uint32_t mask; -+ -+ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); -+ glsl_src_init(&src[0], gen, &ins->src[0], mask); -+ glsl_src_init(&src[1], gen, &ins->src[1], mask); -+ glsl_src_init(&src[2], gen, &ins->src[2], mask); -+ -+ if ((component_count = vsir_write_mask_component_count(mask)) > 1) -+ shader_glsl_print_assignment(gen, &dst, "mix(%s, %s, bvec%u(%s))", -+ src[2].str->buffer, src[1].str->buffer, component_count, src[0].str->buffer); -+ else -+ shader_glsl_print_assignment(gen, &dst, "mix(%s, %s, bool(%s))", -+ src[2].str->buffer, src[1].str->buffer, src[0].str->buffer); -+ -+ glsl_src_cleanup(&src[2], &gen->string_buffers); -+ glsl_src_cleanup(&src[1], &gen->string_buffers); -+ glsl_src_cleanup(&src[0], &gen->string_buffers); -+ glsl_dst_cleanup(&dst, &gen->string_buffers); -+} -+ - static void shader_glsl_print_sysval_name(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, - enum vkd3d_shader_sysval_semantic sysval, unsigned int idx) - { -@@ -608,6 +652,15 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_DCL_OUTPUT_SIV: - case VKD3DSIH_NOP: - break; -+ case VKD3DSIH_DIV: -+ shader_glsl_binop(gen, ins, "/"); -+ break; -+ case VKD3DSIH_FRC: -+ shader_glsl_intrinsic(gen, ins, "fract"); -+ break; -+ case VKD3DSIH_GEO: -+ shader_glsl_relop(gen, ins, ">=", "greaterThanEqual"); -+ break; - case VKD3DSIH_INE: - case VKD3DSIH_NEU: - shader_glsl_relop(gen, ins, "!=", "notEqual"); -@@ -615,6 +668,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_MOV: - shader_glsl_mov(gen, ins); - break; -+ case VKD3DSIH_MOVC: -+ shader_glsl_movc(gen, ins); -+ break; - case VKD3DSIH_MUL: - shader_glsl_binop(gen, ins, "*"); - break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index 6323260eab7..f4401bc5d89 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -276,6 +276,7 @@ bool hlsl_type_is_shader(const struct hlsl_type *type) - case HLSL_CLASS_DEPTH_STENCIL_STATE: - case HLSL_CLASS_DEPTH_STENCIL_VIEW: - case HLSL_CLASS_EFFECT_GROUP: -+ case HLSL_CLASS_ERROR: - case HLSL_CLASS_PASS: - case HLSL_CLASS_RASTERIZER_STATE: - case HLSL_CLASS_RENDER_TARGET_VIEW: -@@ -418,6 +419,7 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type - case HLSL_CLASS_DEPTH_STENCIL_STATE: - case HLSL_CLASS_DEPTH_STENCIL_VIEW: - case HLSL_CLASS_EFFECT_GROUP: -+ case HLSL_CLASS_ERROR: - case HLSL_CLASS_PASS: - case HLSL_CLASS_PIXEL_SHADER: - case HLSL_CLASS_RASTERIZER_STATE: -@@ -494,6 +496,7 @@ static bool type_is_single_component(const struct hlsl_type *type) - { - case HLSL_CLASS_DEPTH_STENCIL_STATE: - case HLSL_CLASS_DEPTH_STENCIL_VIEW: -+ case HLSL_CLASS_ERROR: - case HLSL_CLASS_PIXEL_SHADER: - case HLSL_CLASS_SCALAR: - case HLSL_CLASS_SAMPLER: -@@ -670,6 +673,7 @@ unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_ty - break; - - case HLSL_CLASS_EFFECT_GROUP: -+ case HLSL_CLASS_ERROR: - case HLSL_CLASS_PASS: - case HLSL_CLASS_TECHNIQUE: - case HLSL_CLASS_VOID: -@@ -1061,6 +1065,7 @@ unsigned int hlsl_type_component_count(const struct hlsl_type *type) - - case HLSL_CLASS_DEPTH_STENCIL_STATE: - case HLSL_CLASS_DEPTH_STENCIL_VIEW: -+ case HLSL_CLASS_ERROR: - case HLSL_CLASS_PIXEL_SHADER: - case HLSL_CLASS_RASTERIZER_STATE: - case HLSL_CLASS_RENDER_TARGET_VIEW: -@@ -1155,6 +1160,7 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 - case HLSL_CLASS_DEPTH_STENCIL_STATE: - case HLSL_CLASS_DEPTH_STENCIL_VIEW: - case HLSL_CLASS_EFFECT_GROUP: -+ case HLSL_CLASS_ERROR: - case HLSL_CLASS_PASS: - case HLSL_CLASS_PIXEL_SHADER: - case HLSL_CLASS_RASTERIZER_STATE: -@@ -1629,6 +1635,16 @@ struct hlsl_ir_node *hlsl_new_ternary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_ex - return hlsl_new_expr(ctx, op, operands, arg1->data_type, &arg1->loc); - } - -+static struct hlsl_ir_node *hlsl_new_error_expr(struct hlsl_ctx *ctx) -+{ -+ static const struct vkd3d_shader_location loc = {.source_name = ""}; -+ struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; -+ -+ /* Use a dummy location; we should never report any messages related to -+ * this expression. */ -+ return hlsl_new_expr(ctx, HLSL_OP0_ERROR, operands, ctx->builtin_types.error, &loc); -+} -+ - struct hlsl_ir_node *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *condition, - struct hlsl_block *then_block, struct hlsl_block *else_block, const struct vkd3d_shader_location *loc) - { -@@ -2710,6 +2726,10 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru - } - return string; - -+ case HLSL_CLASS_ERROR: -+ vkd3d_string_buffer_printf(string, ""); -+ return string; -+ - case HLSL_CLASS_DEPTH_STENCIL_STATE: - case HLSL_CLASS_DEPTH_STENCIL_VIEW: - case HLSL_CLASS_EFFECT_GROUP: -@@ -3049,6 +3069,7 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op) - { - static const char *const op_names[] = - { -+ [HLSL_OP0_ERROR] = "error", - [HLSL_OP0_VOID] = "void", - [HLSL_OP0_RASTERIZER_SAMPLE_COUNT] = "GetRenderTargetSampleCount", - -@@ -3990,12 +4011,12 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) - - static const char * const names[] = - { -- "float", -- "half", -- "double", -- "int", -- "uint", -- "bool", -+ [HLSL_TYPE_FLOAT] = "float", -+ [HLSL_TYPE_HALF] = "half", -+ [HLSL_TYPE_DOUBLE] = "double", -+ [HLSL_TYPE_INT] = "int", -+ [HLSL_TYPE_UINT] = "uint", -+ [HLSL_TYPE_BOOL] = "bool", - }; - - static const char *const variants_float[] = {"min10float", "min16float"}; -@@ -4146,6 +4167,7 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) - ctx->builtin_types.Void = hlsl_new_simple_type(ctx, "void", HLSL_CLASS_VOID); - ctx->builtin_types.null = hlsl_new_type(ctx, "NULL", HLSL_CLASS_NULL, HLSL_TYPE_UINT, 1, 1); - ctx->builtin_types.string = hlsl_new_simple_type(ctx, "string", HLSL_CLASS_STRING); -+ ctx->builtin_types.error = hlsl_new_simple_type(ctx, "", HLSL_CLASS_ERROR); - hlsl_scope_add_type(ctx->globals, ctx->builtin_types.string); - hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "DepthStencilView", HLSL_CLASS_DEPTH_STENCIL_VIEW)); - hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "DepthStencilState", HLSL_CLASS_DEPTH_STENCIL_STATE)); -@@ -4248,6 +4270,7 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil - - case VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY: - ctx->semantic_compat_mapping = option->value & VKD3D_SHADER_COMPILE_OPTION_BACKCOMPAT_MAP_SEMANTIC_NAMES; -+ ctx->double_as_float_alias = option->value & VKD3D_SHADER_COMPILE_OPTION_DOUBLE_AS_FLOAT_ALIAS; - break; - - case VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT: -@@ -4267,6 +4290,10 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil - } - } - -+ if (!(ctx->error_instr = hlsl_new_error_expr(ctx))) -+ return false; -+ hlsl_block_add_instr(&ctx->static_initializers, ctx->error_instr); -+ - ctx->domain = VKD3D_TESSELLATOR_DOMAIN_INVALID; - ctx->output_control_point_count = UINT_MAX; - ctx->output_primitive = 0; -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index 20a96692a48..b8678962f67 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -106,6 +106,7 @@ enum hlsl_type_class - HLSL_CLASS_BLEND_STATE, - HLSL_CLASS_VOID, - HLSL_CLASS_NULL, -+ HLSL_CLASS_ERROR, - }; - - enum hlsl_base_type -@@ -361,6 +362,9 @@ struct hlsl_block - { - /* List containing instruction nodes; linked by the hlsl_ir_node.entry fields. */ - struct list instrs; -+ /* Instruction representing the "value" of this block, if applicable. -+ * This may point to an instruction outside of this block! */ -+ struct hlsl_ir_node *value; - }; - - /* A reference to an instruction node (struct hlsl_ir_node), usable as a field in other structs. -@@ -657,6 +661,7 @@ struct hlsl_ir_switch - - enum hlsl_ir_expr_op - { -+ HLSL_OP0_ERROR, - HLSL_OP0_VOID, - HLSL_OP0_RASTERIZER_SAMPLE_COUNT, - -@@ -1043,8 +1048,12 @@ struct hlsl_ctx - struct hlsl_type *string; - struct hlsl_type *Void; - struct hlsl_type *null; -+ struct hlsl_type *error; - } builtin_types; - -+ /* Pre-allocated "error" expression. */ -+ struct hlsl_ir_node *error_instr; -+ - /* List of the instruction nodes for initializing static variables. */ - struct hlsl_block static_initializers; - -@@ -1091,6 +1100,7 @@ struct hlsl_ctx - bool child_effect; - bool include_empty_buffers; - bool warn_implicit_truncation; -+ bool double_as_float_alias; - }; - - static inline bool hlsl_version_ge(const struct hlsl_ctx *ctx, unsigned int major, unsigned int minor) -@@ -1211,16 +1221,19 @@ static inline struct hlsl_ir_stateblock_constant *hlsl_ir_stateblock_constant(co - static inline void hlsl_block_init(struct hlsl_block *block) - { - list_init(&block->instrs); -+ block->value = NULL; - } - - static inline void hlsl_block_add_instr(struct hlsl_block *block, struct hlsl_ir_node *instr) - { - list_add_tail(&block->instrs, &instr->entry); -+ block->value = (instr->data_type ? instr : NULL); - } - - static inline void hlsl_block_add_block(struct hlsl_block *block, struct hlsl_block *add) - { - list_move_tail(&block->instrs, &add->instrs); -+ block->value = add->value; - } - - static inline void hlsl_src_from_node(struct hlsl_src *src, struct hlsl_ir_node *node) -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l -index b7c242661e3..97d8b13772b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l -@@ -90,7 +90,6 @@ default {return KW_DEFAULT; } - discard {return KW_DISCARD; } - DomainShader {return KW_DOMAINSHADER; } - do {return KW_DO; } --double {return KW_DOUBLE; } - else {return KW_ELSE; } - export {return KW_EXPORT; } - extern {return KW_EXTERN; } -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 67262c2ccfd..c39f2020ef7 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -147,7 +147,7 @@ static void yyerror(YYLTYPE *loc, void *scanner, struct hlsl_ctx *ctx, const cha - - static struct hlsl_ir_node *node_from_block(struct hlsl_block *block) - { -- return LIST_ENTRY(list_tail(&block->instrs), struct hlsl_ir_node, entry); -+ return block->value; - } - - static struct hlsl_block *make_empty_block(struct hlsl_ctx *ctx) -@@ -489,9 +489,10 @@ static bool append_conditional_break(struct hlsl_ctx *ctx, struct hlsl_block *co - check_condition_type(ctx, condition); - - bool_type = hlsl_get_scalar_type(ctx, HLSL_TYPE_BOOL); -- if (!(cast = hlsl_new_cast(ctx, condition, bool_type, &condition->loc))) -+ /* We already checked for a 1-component numeric type, so -+ * add_implicit_conversion() is equivalent to add_cast() here. */ -+ if (!(cast = add_cast(ctx, cond_block, condition, bool_type, &condition->loc))) - return false; -- hlsl_block_add_instr(cond_block, cast); - - if (!(not = hlsl_new_unary_expr(ctx, HLSL_OP1_LOGIC_NOT, cast, &condition->loc))) - return false; -@@ -639,14 +640,14 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx - return ret; - hlsl_block_add_block(&expr, block); - -- if (!add_implicit_conversion(ctx, &expr, node_from_block(&expr), dst_type, loc)) -+ if (!(node = add_implicit_conversion(ctx, &expr, node_from_block(&expr), dst_type, loc))) - { - hlsl_block_cleanup(&expr); - return ret; - } - - /* Wrap the node into a src to allow the reference to survive the multiple const passes. */ -- hlsl_src_from_node(&src, node_from_block(&expr)); -+ hlsl_src_from_node(&src, node); - hlsl_run_const_passes(ctx, &expr); - node = src.node; - hlsl_src_remove(&src); -@@ -1710,12 +1711,18 @@ static struct hlsl_ir_node *add_unary_arithmetic_expr(struct hlsl_ctx *ctx, stru - { - struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {arg}; - -+ if (arg->data_type->class == HLSL_CLASS_ERROR) -+ return arg; -+ - return add_expr(ctx, block, op, args, arg->data_type, loc); - } - - static struct hlsl_ir_node *add_unary_bitwise_expr(struct hlsl_ctx *ctx, struct hlsl_block *block, - enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, const struct vkd3d_shader_location *loc) - { -+ if (arg->data_type->class == HLSL_CLASS_ERROR) -+ return arg; -+ - check_integer_type(ctx, arg); - - return add_unary_arithmetic_expr(ctx, block, op, arg, loc); -@@ -1727,6 +1734,9 @@ static struct hlsl_ir_node *add_unary_logical_expr(struct hlsl_ctx *ctx, struct - struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; - struct hlsl_type *bool_type; - -+ if (arg->data_type->class == HLSL_CLASS_ERROR) -+ return arg; -+ - bool_type = hlsl_get_numeric_type(ctx, arg->data_type->class, HLSL_TYPE_BOOL, - arg->data_type->dimx, arg->data_type->dimy); - -@@ -1756,7 +1766,11 @@ static struct hlsl_ir_node *add_binary_arithmetic_expr(struct hlsl_ctx *ctx, str - struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; - struct hlsl_type *common_type; - -- common_type = get_common_numeric_type(ctx, arg1, arg2, loc); -+ if (!(common_type = get_common_numeric_type(ctx, arg1, arg2, loc))) -+ { -+ block->value = ctx->error_instr; -+ return block->value; -+ } - - if (!(args[0] = add_implicit_conversion(ctx, block, arg1, common_type, loc))) - return NULL; -@@ -2059,18 +2073,17 @@ static bool invert_swizzle_matrix(uint32_t *swizzle, unsigned int *writemask, un - return true; - } - --static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *lhs, -+static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *lhs, - enum parse_assign_op assign_op, struct hlsl_ir_node *rhs) - { - struct hlsl_type *lhs_type = lhs->data_type; -- struct hlsl_ir_node *copy; - unsigned int writemask = 0, width = 0; - bool matrix_writemask = false; - - if (assign_op == ASSIGN_OP_SUB) - { - if (!(rhs = add_unary_arithmetic_expr(ctx, block, HLSL_OP1_NEG, rhs, &rhs->loc))) -- return NULL; -+ return false; - assign_op = ASSIGN_OP_ADD; - } - if (assign_op != ASSIGN_OP_ASSIGN) -@@ -2079,7 +2092,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - - VKD3D_ASSERT(op); - if (!(rhs = add_binary_expr(ctx, block, op, lhs, rhs, &rhs->loc))) -- return NULL; -+ return false; - } - - if (hlsl_is_numeric_type(lhs_type)) -@@ -2089,14 +2102,14 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - } - - if (!(rhs = add_implicit_conversion(ctx, block, rhs, lhs_type, &rhs->loc))) -- return NULL; -+ return false; - - while (lhs->type != HLSL_IR_LOAD && lhs->type != HLSL_IR_INDEX) - { - if (lhs->type == HLSL_IR_EXPR && hlsl_ir_expr(lhs)->op == HLSL_OP1_CAST) - { - hlsl_fixme(ctx, &lhs->loc, "Cast on the LHS."); -- return NULL; -+ return false; - } - else if (lhs->type == HLSL_IR_SWIZZLE) - { -@@ -2111,25 +2124,23 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - if (swizzle->val.node->type != HLSL_IR_LOAD && swizzle->val.node->type != HLSL_IR_INDEX) - { - hlsl_fixme(ctx, &lhs->loc, "Unhandled source of matrix swizzle."); -- return NULL; -+ return false; - } - if (!invert_swizzle_matrix(&s, &writemask, &width)) - { - hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask for matrix."); -- return NULL; -+ return false; - } - matrix_writemask = true; - } - else if (!invert_swizzle(&s, &writemask, &width)) - { - hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_WRITEMASK, "Invalid writemask."); -- return NULL; -+ return false; - } - - if (!(new_swizzle = hlsl_new_swizzle(ctx, s, width, rhs, &swizzle->node.loc))) -- { -- return NULL; -- } -+ return false; - hlsl_block_add_instr(block, new_swizzle); - - lhs = swizzle->val.node; -@@ -2138,7 +2149,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - else - { - hlsl_error(ctx, &lhs->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_LVALUE, "Invalid lvalue."); -- return NULL; -+ return false; - } - } - -@@ -2153,11 +2164,11 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - if (!hlsl_index_is_resource_access(hlsl_ir_index(lhs))) - { - hlsl_fixme(ctx, &lhs->loc, "Non-direct structured resource store."); -- return NULL; -+ return false; - } - - if (!hlsl_init_deref_from_index_chain(ctx, &resource_deref, hlsl_ir_index(lhs)->val.node)) -- return NULL; -+ return false; - - resource_type = hlsl_deref_get_type(ctx, &resource_deref); - VKD3D_ASSERT(resource_type->class == HLSL_CLASS_TEXTURE || resource_type->class == HLSL_CLASS_UAV); -@@ -2179,7 +2190,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - if (!(store = hlsl_new_resource_store(ctx, &resource_deref, coords, rhs, &lhs->loc))) - { - hlsl_cleanup_deref(&resource_deref); -- return NULL; -+ return false; - } - hlsl_block_add_instr(block, store); - hlsl_cleanup_deref(&resource_deref); -@@ -2206,13 +2217,13 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - if (!(load = hlsl_add_load_component(ctx, block, rhs, k++, &rhs->loc))) - { - hlsl_cleanup_deref(&deref); -- return NULL; -+ return false; - } - - if (!hlsl_new_store_component(ctx, &store_block, &deref, component, load)) - { - hlsl_cleanup_deref(&deref); -- return NULL; -+ return false; - } - hlsl_block_add_block(block, &store_block); - } -@@ -2237,23 +2248,23 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - continue; - - if (!(c = hlsl_new_uint_constant(ctx, i, &lhs->loc))) -- return NULL; -+ return false; - hlsl_block_add_instr(block, c); - - if (!(cell = hlsl_new_index(ctx, &row->node, c, &lhs->loc))) -- return NULL; -+ return false; - hlsl_block_add_instr(block, cell); - - if (!(load = hlsl_add_load_component(ctx, block, rhs, k++, &rhs->loc))) -- return NULL; -+ return false; - - if (!hlsl_init_deref_from_index_chain(ctx, &deref, cell)) -- return NULL; -+ return false; - - if (!(store = hlsl_new_store_index(ctx, &deref, NULL, load, 0, &rhs->loc))) - { - hlsl_cleanup_deref(&deref); -- return NULL; -+ return false; - } - hlsl_block_add_instr(block, store); - hlsl_cleanup_deref(&deref); -@@ -2265,24 +2276,19 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - struct hlsl_deref deref; - - if (!hlsl_init_deref_from_index_chain(ctx, &deref, lhs)) -- return NULL; -+ return false; - - if (!(store = hlsl_new_store_index(ctx, &deref, NULL, rhs, writemask, &rhs->loc))) - { - hlsl_cleanup_deref(&deref); -- return NULL; -+ return false; - } - hlsl_block_add_instr(block, store); - hlsl_cleanup_deref(&deref); - } - -- /* Don't use the instruction itself as a source, as this makes structure -- * splitting easier. Instead copy it here. Since we retrieve sources from -- * the last instruction in the list, we do need to copy. */ -- if (!(copy = hlsl_new_copy(ctx, rhs))) -- return NULL; -- hlsl_block_add_instr(block, copy); -- return copy; -+ block->value = rhs; -+ return true; - } - - static bool add_increment(struct hlsl_ctx *ctx, struct hlsl_block *block, bool decrement, bool post, -@@ -5340,11 +5346,6 @@ static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, - } - else - { -- cond_type = hlsl_get_numeric_type(ctx, cond_type->class, HLSL_TYPE_BOOL, -- cond_type->dimx, cond_type->dimy); -- if (!(cond = add_implicit_conversion(ctx, block, cond, cond_type, &cond->loc))) -- return false; -- - if (common_type->dimx == 1 && common_type->dimy == 1) - { - common_type = hlsl_get_numeric_type(ctx, cond_type->class, -@@ -5366,6 +5367,11 @@ static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, - hlsl_release_string_buffer(ctx, cond_string); - hlsl_release_string_buffer(ctx, value_string); - } -+ -+ cond_type = hlsl_get_numeric_type(ctx, common_type->class, HLSL_TYPE_BOOL, -+ common_type->dimx, common_type->dimy); -+ if (!(cond = add_implicit_conversion(ctx, block, cond, cond_type, &cond->loc))) -+ return false; - } - - if (!(first = add_implicit_conversion(ctx, block, first, common_type, &first->loc))) -@@ -6296,7 +6302,6 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h - %token KW_DISCARD - %token KW_DO - %token KW_DOMAINSHADER --%token KW_DOUBLE - %token KW_ELSE - %token KW_EXPORT - %token KW_EXTERN -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 6cae0e3b5c9..feab6cf06c1 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -1655,11 +1655,16 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, - case HLSL_CLASS_MATRIX: - case HLSL_CLASS_ARRAY: - case HLSL_CLASS_STRUCT: -- case HLSL_CLASS_CONSTANT_BUFFER: -- /* FIXME: Actually we shouldn't even get here, but we don't split -- * matrices yet. */ -+ /* We can't handle complex types here. -+ * They should have been already split anyway by earlier passes, -+ * but they may not have been deleted yet. We can't rely on DCE to -+ * solve that problem for us, since we may be called on a partial -+ * block, but DCE deletes dead stores, so it needs to be able to -+ * see the whole program. */ -+ case HLSL_CLASS_ERROR: - return false; - -+ case HLSL_CLASS_CONSTANT_BUFFER: - case HLSL_CLASS_EFFECT_GROUP: - case HLSL_CLASS_PASS: - case HLSL_CLASS_TECHNIQUE: -@@ -6622,7 +6627,13 @@ static bool sm1_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, - return true; - - case HLSL_TYPE_DOUBLE: -- hlsl_fixme(ctx, &instr->loc, "SM1 cast from double to float."); -+ if (ctx->double_as_float_alias) -+ { -+ sm1_generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOV, 0, 0, true); -+ return true; -+ } -+ hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -+ "The 'double' type is not supported for the %s profile.", ctx->profile->name); - break; - - default: -@@ -6660,7 +6671,22 @@ static bool sm1_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, - break; - - case HLSL_TYPE_DOUBLE: -- hlsl_fixme(ctx, &instr->loc, "SM1 cast to double."); -+ switch (src_type->e.numeric.type) -+ { -+ case HLSL_TYPE_FLOAT: -+ if (ctx->double_as_float_alias) -+ { -+ sm1_generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOV, 0, 0, true); -+ return true; -+ } -+ hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -+ "The 'double' type is not supported for the %s profile.", ctx->profile->name); -+ break; -+ -+ default: -+ hlsl_fixme(ctx, &instr->loc, "SM1 cast to double."); -+ break; -+ } - break; - - case HLSL_TYPE_BOOL: -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 7f1e0fea2c3..1876ad38653 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -394,6 +394,7 @@ struct vkd3d_spirv_builder - uint32_t type_bool_id; - uint32_t type_void_id; - uint32_t scope_subgroup_id; -+ uint32_t numeric_type_ids[VKD3D_SHADER_COMPONENT_TYPE_COUNT][VKD3D_VEC4_SIZE]; - - struct vkd3d_spirv_stream debug_stream; /* debug instructions */ - struct vkd3d_spirv_stream annotation_stream; /* decoration instructions */ -@@ -1902,29 +1903,37 @@ static uint32_t vkd3d_spirv_build_op_glsl_std450_nclamp(struct vkd3d_spirv_build - static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder, - enum vkd3d_shader_component_type component_type, unsigned int component_count) - { -- uint32_t scalar_id; -+ uint32_t scalar_id, type_id; -+ -+ VKD3D_ASSERT(component_type < VKD3D_SHADER_COMPONENT_TYPE_COUNT); -+ VKD3D_ASSERT(1 <= component_count && component_count <= VKD3D_VEC4_SIZE); -+ -+ if ((type_id = builder->numeric_type_ids[component_type][component_count - 1])) -+ return type_id; - - if (component_count == 1) - { - switch (component_type) - { - case VKD3D_SHADER_COMPONENT_VOID: -- return vkd3d_spirv_get_op_type_void(builder); -+ type_id = vkd3d_spirv_get_op_type_void(builder); - break; - case VKD3D_SHADER_COMPONENT_FLOAT: -- return vkd3d_spirv_get_op_type_float(builder, 32); -+ type_id = vkd3d_spirv_get_op_type_float(builder, 32); - break; - case VKD3D_SHADER_COMPONENT_INT: - case VKD3D_SHADER_COMPONENT_UINT: -- return vkd3d_spirv_get_op_type_int(builder, 32, component_type == VKD3D_SHADER_COMPONENT_INT); -+ type_id = vkd3d_spirv_get_op_type_int(builder, 32, component_type == VKD3D_SHADER_COMPONENT_INT); - break; - case VKD3D_SHADER_COMPONENT_BOOL: -- return vkd3d_spirv_get_op_type_bool(builder); -+ type_id = vkd3d_spirv_get_op_type_bool(builder); - break; - case VKD3D_SHADER_COMPONENT_DOUBLE: -- return vkd3d_spirv_get_op_type_float(builder, 64); -+ type_id = vkd3d_spirv_get_op_type_float(builder, 64); -+ break; - case VKD3D_SHADER_COMPONENT_UINT64: -- return vkd3d_spirv_get_op_type_int(builder, 64, 0); -+ type_id = vkd3d_spirv_get_op_type_int(builder, 64, 0); -+ break; - default: - FIXME("Unhandled component type %#x.\n", component_type); - return 0; -@@ -1934,46 +1943,21 @@ static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder, - { - VKD3D_ASSERT(component_type != VKD3D_SHADER_COMPONENT_VOID); - scalar_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -- return vkd3d_spirv_get_op_type_vector(builder, scalar_id, component_count); -+ type_id = vkd3d_spirv_get_op_type_vector(builder, scalar_id, component_count); - } -+ -+ builder->numeric_type_ids[component_type][component_count - 1] = type_id; -+ -+ return type_id; - } - - static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder *builder, - enum vkd3d_data_type data_type, unsigned int component_count) - { -- uint32_t scalar_id; -+ enum vkd3d_shader_component_type component_type; - -- if (component_count == 1) -- { -- switch (data_type) -- { -- case VKD3D_DATA_HALF: /* Minimum precision. TODO: native 16-bit */ -- case VKD3D_DATA_FLOAT: -- case VKD3D_DATA_SNORM: -- case VKD3D_DATA_UNORM: -- return vkd3d_spirv_get_op_type_float(builder, 32); -- break; -- case VKD3D_DATA_INT: -- case VKD3D_DATA_UINT: -- case VKD3D_DATA_UINT16: /* Minimum precision. TODO: native 16-bit */ -- return vkd3d_spirv_get_op_type_int(builder, 32, data_type == VKD3D_DATA_INT); -- break; -- case VKD3D_DATA_DOUBLE: -- return vkd3d_spirv_get_op_type_float(builder, 64); -- case VKD3D_DATA_UINT64: -- return vkd3d_spirv_get_op_type_int(builder, 64, 0); -- case VKD3D_DATA_BOOL: -- return vkd3d_spirv_get_op_type_bool(builder); -- default: -- FIXME("Unhandled data type %#x.\n", data_type); -- return 0; -- } -- } -- else -- { -- scalar_id = vkd3d_spirv_get_type_id_for_data_type(builder, data_type, 1); -- return vkd3d_spirv_get_op_type_vector(builder, scalar_id, component_count); -- } -+ component_type = vkd3d_component_type_from_data_type(data_type); -+ return vkd3d_spirv_get_type_id(builder, component_type, component_count); - } - - static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, const char *entry_point) -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 884a2998d5b..ab9f4cf2b57 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -3236,6 +3236,7 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type) - case HLSL_CLASS_DEPTH_STENCIL_STATE: - case HLSL_CLASS_DEPTH_STENCIL_VIEW: - case HLSL_CLASS_EFFECT_GROUP: -+ case HLSL_CLASS_ERROR: - case HLSL_CLASS_STRUCT: - case HLSL_CLASS_PASS: - case HLSL_CLASS_PIXEL_SHADER: -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 447210449da..7ac86e35227 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -59,6 +59,8 @@ - #define VKD3D_VEC4_SIZE 4 - #define VKD3D_DVEC2_SIZE 2 - -+#define VKD3D_SHADER_COMPONENT_TYPE_COUNT (VKD3D_SHADER_COMPONENT_UINT64 + 1) -+ - enum vkd3d_shader_error - { - VKD3D_SHADER_ERROR_DXBC_INVALID_SIZE = 1, -diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c -index ea7d8f040b5..fb377177403 100644 ---- a/libs/vkd3d/libs/vkd3d/state.c -+++ b/libs/vkd3d/libs/vkd3d/state.c -@@ -1107,7 +1107,9 @@ static int compare_descriptor_range(const void *a, const void *b) - if ((ret = vkd3d_u32_compare(range_a->offset, range_b->offset))) - return ret; - -- return (range_a->descriptor_count == UINT_MAX) - (range_b->descriptor_count == UINT_MAX); -+ /* Place bounded ranges after unbounded ones of equal offset, -+ * so the bounded range can be mapped to the unbounded one. */ -+ return (range_b->descriptor_count == UINT_MAX) - (range_a->descriptor_count == UINT_MAX); - } - - static HRESULT d3d12_root_signature_init_root_descriptor_tables(struct d3d12_root_signature *root_signature, --- -2.45.2 - diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-cd74461d6dabae4e702de61a90533d811aa.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-cd74461d6dabae4e702de61a90533d811aa.patch new file mode 100644 index 00000000..ff90313d --- /dev/null +++ b/patches/vkd3d-latest/0002-Updated-vkd3d-to-cd74461d6dabae4e702de61a90533d811aa.patch @@ -0,0 +1,1718 @@ +From ca6c91b4e3a8a1585c09b55ec35a7871e3a62213 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Wed, 9 Oct 2024 20:40:25 +1100 +Subject: [PATCH] Updated vkd3d to cd74461d6dabae4e702de61a90533d811aa0a3fb. + +--- + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 59 ++- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 2 +- + libs/vkd3d/libs/vkd3d-shader/dxbc.c | 2 - + libs/vkd3d/libs/vkd3d-shader/dxil.c | 10 +- + libs/vkd3d/libs/vkd3d-shader/glsl.c | 254 ++++++++++--- + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 1 - + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 103 ++--- + libs/vkd3d/libs/vkd3d-shader/ir.c | 9 +- + libs/vkd3d/libs/vkd3d-shader/msl.c | 357 +++++++++++++++++- + libs/vkd3d/libs/vkd3d-shader/preproc.h | 3 +- + libs/vkd3d/libs/vkd3d-shader/preproc.l | 53 +-- + libs/vkd3d/libs/vkd3d-shader/preproc.y | 13 - + libs/vkd3d/libs/vkd3d-shader/spirv.c | 17 +- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 7 +- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 2 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 10 +- + 16 files changed, 726 insertions(+), 176 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +index 9fe4b74486a..38d566d9fe0 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +@@ -2268,7 +2268,7 @@ static const char *get_semantic_register_name(enum vkd3d_shader_sysval_semantic + } + } + +-static enum vkd3d_result dump_signature(struct vkd3d_d3d_asm_compiler *compiler, ++static enum vkd3d_result dump_dxbc_signature(struct vkd3d_d3d_asm_compiler *compiler, + const char *name, const char *register_name, const struct shader_signature *signature) + { + struct vkd3d_string_buffer *buffer = &compiler->buffer; +@@ -2335,21 +2335,21 @@ static enum vkd3d_result dump_signature(struct vkd3d_d3d_asm_compiler *compiler, + return VKD3D_OK; + } + +-static enum vkd3d_result dump_signatures(struct vkd3d_d3d_asm_compiler *compiler, ++static enum vkd3d_result dump_dxbc_signatures(struct vkd3d_d3d_asm_compiler *compiler, + const struct vsir_program *program) + { + enum vkd3d_result ret; + +- if ((ret = dump_signature(compiler, ".input", ++ if ((ret = dump_dxbc_signature(compiler, ".input", + program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN ? "vicp" : "v", + &program->input_signature)) < 0) + return ret; + +- if ((ret = dump_signature(compiler, ".output", "o", ++ if ((ret = dump_dxbc_signature(compiler, ".output", "o", + &program->output_signature)) < 0) + return ret; + +- if ((ret = dump_signature(compiler, ".patch_constant", ++ if ((ret = dump_dxbc_signature(compiler, ".patch_constant", + program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN ? "vpc" : "o", + &program->patch_constant_signature)) < 0) + return ret; +@@ -2437,7 +2437,7 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, + * doesn't even have an explicit concept of signature. */ + if (formatting & VKD3D_SHADER_COMPILE_OPTION_FORMATTING_IO_SIGNATURES && shader_version->major >= 4) + { +- if ((result = dump_signatures(&compiler, program)) < 0) ++ if ((result = dump_dxbc_signatures(&compiler, program)) < 0) + { + vkd3d_string_buffer_cleanup(buffer); + return result; +@@ -2499,12 +2499,57 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, + return result; + } + +-void vkd3d_shader_trace(const struct vsir_program *program) ++/* This is meant exclusively for development use. Therefore, differently from ++ * dump_dxbc_signature(), it doesn't try particularly hard to make the output ++ * nice or easily parsable, and it dumps all fields, not just the DXBC ones. ++ * This format isn't meant to be stable. */ ++static void trace_signature(const struct shader_signature *signature, const char *signature_type) ++{ ++ struct vkd3d_string_buffer buffer; ++ unsigned int i; ++ ++ TRACE("%s signature:%s\n", signature_type, signature->element_count == 0 ? " empty" : ""); ++ ++ vkd3d_string_buffer_init(&buffer); ++ ++ for (i = 0; i < signature->element_count; ++i) ++ { ++ const struct signature_element *element = &signature->elements[i]; ++ ++ vkd3d_string_buffer_clear(&buffer); ++ ++ vkd3d_string_buffer_printf(&buffer, "Element %u: %s %u-%u %s", i, ++ get_component_type_name(element->component_type), ++ element->register_index, element->register_index + element->register_count, ++ element->semantic_name); ++ if (element->semantic_index != -1) ++ vkd3d_string_buffer_printf(&buffer, "%u", element->semantic_index); ++ vkd3d_string_buffer_printf(&buffer, ++ " mask %#x used_mask %#x sysval %s min_precision %s interpolation %u stream %u", ++ element->mask, element->used_mask, get_sysval_semantic_name(element->sysval_semantic), ++ get_minimum_precision_name(element->min_precision), element->interpolation_mode, ++ element->stream_index); ++ if (element->target_location != -1) ++ vkd3d_string_buffer_printf(&buffer, " target %u", element->target_location); ++ else ++ vkd3d_string_buffer_printf(&buffer, " unused"); ++ ++ TRACE("%s\n", buffer.buffer); ++ } ++ ++ vkd3d_string_buffer_cleanup(&buffer); ++} ++ ++void vsir_program_trace(const struct vsir_program *program) + { + const unsigned int flags = VSIR_ASM_FLAG_DUMP_TYPES | VSIR_ASM_FLAG_DUMP_ALL_INDICES; + struct vkd3d_shader_code code; + const char *p, *q, *end; + ++ trace_signature(&program->input_signature, "Input"); ++ trace_signature(&program->output_signature, "Output"); ++ trace_signature(&program->patch_constant_signature, "Patch-constant"); ++ + if (d3d_asm_compile(program, NULL, &code, flags) != VKD3D_OK) + return; + +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index 267cf410cbe..589b800f8c9 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -1390,7 +1390,7 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c + WARN("Failed to validate shader after parsing, ret %d.\n", ret); + + if (TRACE_ON()) +- vkd3d_shader_trace(program); ++ vsir_program_trace(program); + + vsir_program_cleanup(program); + return ret; +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +index 93fc993e0d1..f6ac8e0829e 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +@@ -419,8 +419,6 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s + const char *name; + uint32_t mask; + +- e[i].sort_index = i; +- + if (has_stream_index) + e[i].stream_index = read_u32(&ptr); + else +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index d4296ef4bc5..c66b059325a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -4174,6 +4174,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty + const struct sm6_type *type_b, struct sm6_parser *sm6) + { + bool is_int = sm6_type_is_bool_i16_i32_i64(type_a); ++ bool is_double = sm6_type_is_double(type_a); + bool is_bool = sm6_type_is_bool(type_a); + enum vkd3d_shader_opcode op; + bool is_valid; +@@ -4198,7 +4199,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty + case BINOP_ADD: + case BINOP_SUB: + /* NEG is applied later for subtraction. */ +- op = is_int ? VKD3DSIH_IADD : VKD3DSIH_ADD; ++ op = is_int ? VKD3DSIH_IADD : (is_double ? VKD3DSIH_DADD : VKD3DSIH_ADD); + is_valid = !is_bool; + break; + case BINOP_AND: +@@ -4214,7 +4215,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty + is_valid = is_int && !is_bool; + break; + case BINOP_MUL: +- op = is_int ? VKD3DSIH_UMUL : VKD3DSIH_MUL; ++ op = is_int ? VKD3DSIH_UMUL : (is_double ? VKD3DSIH_DMUL : VKD3DSIH_MUL); + is_valid = !is_bool; + break; + case BINOP_OR: +@@ -4222,7 +4223,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty + is_valid = is_int; + break; + case BINOP_SDIV: +- op = is_int ? VKD3DSIH_IDIV : VKD3DSIH_DIV; ++ op = is_int ? VKD3DSIH_IDIV : (is_double ? VKD3DSIH_DDIV : VKD3DSIH_DIV); + is_valid = !is_bool; + break; + case BINOP_SREM: +@@ -9637,6 +9638,7 @@ static enum vkd3d_result sm6_parser_emit_thread_group(struct sm6_parser *sm6, co + ins->declaration.thread_group_size.x = group_sizes[0]; + ins->declaration.thread_group_size.y = group_sizes[1]; + ins->declaration.thread_group_size.z = group_sizes[2]; ++ sm6->p.program->thread_group_size = ins->declaration.thread_group_size; + + return VKD3D_OK; + } +@@ -10592,7 +10594,7 @@ int dxil_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t co + WARN("Failed to validate shader after parsing, ret %d.\n", ret); + + if (TRACE_ON()) +- vkd3d_shader_trace(program); ++ vsir_program_trace(program); + + sm6_parser_cleanup(&sm6); + vsir_program_cleanup(program); +diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c +index c2fb58c55e6..4dc95899a11 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c +@@ -62,6 +62,9 @@ struct vkd3d_glsl_generator + const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info; + }; + ++static void shader_glsl_print_subscript(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, ++ const struct vkd3d_shader_src_param *rel_addr, unsigned int offset); ++ + static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error( + struct vkd3d_glsl_generator *generator, + enum vkd3d_shader_error error, const char *fmt, ...) +@@ -263,6 +266,11 @@ static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, + gen->prefix, reg->idx[0].offset, reg->idx[2].offset); + break; + ++ case VKD3DSPR_IDXTEMP: ++ vkd3d_string_buffer_printf(buffer, "x%u", reg->idx[0].offset); ++ shader_glsl_print_subscript(buffer, gen, reg->idx[1].rel_addr, reg->idx[1].offset); ++ break; ++ + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled register type %#x.", reg->type); +@@ -438,6 +446,26 @@ static uint32_t glsl_dst_init(struct glsl_dst *glsl_dst, struct vkd3d_glsl_gener + return write_mask; + } + ++static void shader_glsl_print_subscript(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, ++ const struct vkd3d_shader_src_param *rel_addr, unsigned int offset) ++{ ++ struct glsl_src r; ++ ++ if (!rel_addr) ++ { ++ vkd3d_string_buffer_printf(buffer, "[%u]", offset); ++ return; ++ } ++ ++ glsl_src_init(&r, gen, rel_addr, VKD3DSP_WRITEMASK_0); ++ vkd3d_string_buffer_printf(buffer, "[%s", r.str->buffer); ++ if (offset) ++ vkd3d_string_buffer_printf(buffer, " + %u", offset); ++ else ++ vkd3d_string_buffer_printf(buffer, "]"); ++ glsl_src_cleanup(&r, &gen->string_buffers); ++} ++ + static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_glsl_generator *gen, + struct glsl_dst *dst, enum vkd3d_data_type data_type, const char *format, va_list args) + { +@@ -903,19 +931,27 @@ static void shader_glsl_print_sysval_name(struct vkd3d_string_buffer *buffer, st + switch (sysval) + { + case VKD3D_SHADER_SV_POSITION: +- if (version->type == VKD3D_SHADER_TYPE_PIXEL || version->type == VKD3D_SHADER_TYPE_COMPUTE) ++ if (version->type == VKD3D_SHADER_TYPE_COMPUTE) + { + vkd3d_string_buffer_printf(buffer, "", sysval); + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, +- "Internal compiler error: Unhandled system value %#x.", sysval); ++ "Internal compiler error: Unhandled SV_POSITION in shader type #%x.", version->type); ++ break; + } ++ if (idx) ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled SV_POSITION index %u.", idx); ++ if (version->type == VKD3D_SHADER_TYPE_PIXEL) ++ vkd3d_string_buffer_printf(buffer, "gl_FragCoord"); + else +- { + vkd3d_string_buffer_printf(buffer, "gl_Position"); +- if (idx) +- vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, +- "Internal compiler error: Unhandled SV_POSITION index %u.", idx); +- } ++ break; ++ ++ case VKD3D_SHADER_SV_VERTEX_ID: ++ if (version->type != VKD3D_SHADER_TYPE_VERTEX) ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled SV_VERTEX_ID in shader type #%x.", version->type); ++ vkd3d_string_buffer_printf(buffer, "intBitsToFloat(ivec4(gl_VertexID, 0, 0, 0))"); + break; + + case VKD3D_SHADER_SV_IS_FRONT_FACE: +@@ -972,7 +1008,19 @@ static void shader_glsl_shader_prologue(struct vkd3d_glsl_generator *gen) + } + else + { +- vkd3d_string_buffer_printf(buffer, " = shader_in_%u", i); ++ switch (e->component_type) ++ { ++ case VKD3D_SHADER_COMPONENT_UINT: ++ vkd3d_string_buffer_printf(buffer, " = uintBitsToFloat(shader_in_%u)", i); ++ break; ++ default: ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled input component type %#x.", e->component_type); ++ /* fall through */ ++ case VKD3D_SHADER_COMPONENT_FLOAT: ++ vkd3d_string_buffer_printf(buffer, " = shader_in_%u", i); ++ break; ++ } + } + } + else +@@ -989,6 +1037,7 @@ static void shader_glsl_shader_epilogue(struct vkd3d_glsl_generator *gen) + { + const struct shader_signature *signature = &gen->program->output_signature; + struct vkd3d_string_buffer *buffer = gen->buffer; ++ enum vkd3d_shader_component_type type; + const struct signature_element *e; + unsigned int i; + +@@ -999,11 +1048,13 @@ static void shader_glsl_shader_epilogue(struct vkd3d_glsl_generator *gen) + if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) + continue; + ++ type = e->component_type; + shader_glsl_print_indent(buffer, gen->indent); + if (e->sysval_semantic == VKD3D_SHADER_SV_NONE) + { + if (gen->interstage_output) + { ++ type = VKD3D_SHADER_COMPONENT_FLOAT; + vkd3d_string_buffer_printf(buffer, "shader_out.reg_%u", e->target_location); + if (e->target_location >= gen->limits.output_count) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, +@@ -1023,7 +1074,19 @@ static void shader_glsl_shader_epilogue(struct vkd3d_glsl_generator *gen) + shader_glsl_print_sysval_name(buffer, gen, e->sysval_semantic, e->semantic_index); + } + shader_glsl_print_write_mask(buffer, e->mask); +- vkd3d_string_buffer_printf(buffer, " = %s_out[%u]", gen->prefix, e->register_index); ++ switch (type) ++ { ++ case VKD3D_SHADER_COMPONENT_UINT: ++ vkd3d_string_buffer_printf(buffer, " = floatBitsToUint(%s_out[%u])", gen->prefix, e->register_index); ++ break; ++ default: ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled output component type %#x.", e->component_type); ++ /* fall through */ ++ case VKD3D_SHADER_COMPONENT_FLOAT: ++ vkd3d_string_buffer_printf(buffer, " = %s_out[%u]", gen->prefix, e->register_index); ++ break; ++ } + shader_glsl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, ";\n"); + } +@@ -1041,6 +1104,15 @@ static void shader_glsl_ret(struct vkd3d_glsl_generator *gen, const struct vkd3d + } + } + ++static void shader_glsl_dcl_indexable_temp(struct vkd3d_glsl_generator *gen, ++ const struct vkd3d_shader_instruction *ins) ++{ ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "vec4 x%u[%u];\n", ++ ins->declaration.indexable_temp.register_idx, ++ ins->declaration.indexable_temp.register_size); ++} ++ + static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_instruction *ins) + { +@@ -1049,14 +1121,19 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + switch (ins->opcode) + { + case VKD3DSIH_ADD: ++ case VKD3DSIH_IADD: + shader_glsl_binop(gen, ins, "+"); + break; + case VKD3DSIH_AND: + shader_glsl_binop(gen, ins, "&"); + break; ++ case VKD3DSIH_DCL_INDEXABLE_TEMP: ++ shader_glsl_dcl_indexable_temp(gen, ins); ++ break; + case VKD3DSIH_DCL_INPUT: + case VKD3DSIH_DCL_INPUT_PS: + case VKD3DSIH_DCL_INPUT_PS_SIV: ++ case VKD3DSIH_DCL_INPUT_SGV: + case VKD3DSIH_DCL_OUTPUT: + case VKD3DSIH_DCL_OUTPUT_SIV: + case VKD3DSIH_NOP: +@@ -1079,6 +1156,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + case VKD3DSIH_ENDIF: + shader_glsl_endif(gen); + break; ++ case VKD3DSIH_EQO: + case VKD3DSIH_IEQ: + shader_glsl_relop(gen, ins, "==", "equal"); + break; +@@ -1108,26 +1186,30 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + case VKD3DSIH_LTO: + shader_glsl_relop(gen, ins, "<", "lessThan"); + break; +- case VKD3DSIH_IMUL: +- shader_glsl_mul_extended(gen, ins); +- break; +- case VKD3DSIH_ISHL: +- shader_glsl_binop(gen, ins, "<<"); +- break; +- case VKD3DSIH_ISHR: +- case VKD3DSIH_USHR: +- shader_glsl_binop(gen, ins, ">>"); +- break; ++ case VKD3DSIH_IMAX: + case VKD3DSIH_MAX: + shader_glsl_intrinsic(gen, ins, "max"); + break; + case VKD3DSIH_MIN: + shader_glsl_intrinsic(gen, ins, "min"); + break; ++ case VKD3DSIH_IMUL: ++ shader_glsl_mul_extended(gen, ins); ++ break; + case VKD3DSIH_INE: + case VKD3DSIH_NEU: + shader_glsl_relop(gen, ins, "!=", "notEqual"); + break; ++ case VKD3DSIH_INEG: ++ shader_glsl_unary_op(gen, ins, "-"); ++ break; ++ case VKD3DSIH_ISHL: ++ shader_glsl_binop(gen, ins, "<<"); ++ break; ++ case VKD3DSIH_ISHR: ++ case VKD3DSIH_USHR: ++ shader_glsl_binop(gen, ins, ">>"); ++ break; + case VKD3DSIH_ITOF: + case VKD3DSIH_UTOF: + shader_glsl_cast(gen, ins, "float", "vec"); +@@ -1485,15 +1567,62 @@ static void shader_glsl_generate_descriptor_declarations(struct vkd3d_glsl_gener + vkd3d_string_buffer_printf(gen->buffer, "\n"); + } + +-static void shader_glsl_generate_interface_block(struct vkd3d_string_buffer *buffer, +- const char *type, unsigned int count) ++static const struct signature_element *signature_get_element_by_location( ++ const struct shader_signature *signature, unsigned int location) + { ++ const struct signature_element *e; ++ unsigned int i; ++ ++ for (i = 0; i < signature->element_count; ++i) ++ { ++ e = &signature->elements[i]; ++ ++ if (e->target_location != location) ++ continue; ++ ++ return e; ++ } ++ ++ return NULL; ++} ++ ++static const char *shader_glsl_get_interpolation(struct vkd3d_glsl_generator *gen, ++ const struct shader_signature *signature, const char *type, unsigned int location) ++{ ++ enum vkd3d_shader_interpolation_mode m; ++ const struct signature_element *e; ++ ++ if ((e = signature_get_element_by_location(signature, location))) ++ m = e->interpolation_mode; ++ else ++ m = VKD3DSIM_NONE; ++ ++ switch (m) ++ { ++ case VKD3DSIM_NONE: ++ case VKD3DSIM_LINEAR: ++ return ""; ++ case VKD3DSIM_CONSTANT: ++ return "flat "; ++ default: ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled interpolation mode %#x for %s location %u.", m, type, location); ++ return ""; ++ } ++} ++ ++static void shader_glsl_generate_interface_block(struct vkd3d_glsl_generator *gen, ++ const struct shader_signature *signature, const char *type, unsigned int count) ++{ ++ struct vkd3d_string_buffer *buffer = gen->buffer; ++ const char *interpolation; + unsigned int i; + + vkd3d_string_buffer_printf(buffer, "%s shader_in_out\n{\n", type); + for (i = 0; i < count; ++i) + { +- vkd3d_string_buffer_printf(buffer, " vec4 reg_%u;\n", i); ++ interpolation = shader_glsl_get_interpolation(gen, signature, type, i); ++ vkd3d_string_buffer_printf(buffer, " %svec4 reg_%u;\n", interpolation, i); + } + vkd3d_string_buffer_printf(buffer, "} shader_%s;\n", type); + } +@@ -1503,30 +1632,16 @@ static void shader_glsl_generate_input_declarations(struct vkd3d_glsl_generator + const struct shader_signature *signature = &gen->program->input_signature; + struct vkd3d_string_buffer *buffer = gen->buffer; + const struct signature_element *e; +- unsigned int i; ++ unsigned int i, count; + + if (!gen->interstage_input) + { +- for (i = 0; i < signature->element_count; ++i) ++ for (i = 0, count = 0; i < signature->element_count; ++i) + { + e = &signature->elements[i]; + +- if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) +- continue; +- +- if (e->sysval_semantic) +- { +- vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, +- "Internal compiler error: Unhandled system value %#x.", e->sysval_semantic); +- continue; +- } +- +- if (e->component_type != VKD3D_SHADER_COMPONENT_FLOAT) +- { +- vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, +- "Internal compiler error: Unhandled component type %#x.", e->component_type); ++ if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED || e->sysval_semantic) + continue; +- } + + if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) + { +@@ -1542,15 +1657,32 @@ static void shader_glsl_generate_input_declarations(struct vkd3d_glsl_generator + continue; + } + +- vkd3d_string_buffer_printf(buffer, +- "layout(location = %u) in vec4 shader_in_%u;\n", e->target_location, i); ++ vkd3d_string_buffer_printf(buffer, "layout(location = %u) in ", e->target_location); ++ switch (e->component_type) ++ { ++ case VKD3D_SHADER_COMPONENT_UINT: ++ vkd3d_string_buffer_printf(buffer, "uvec4"); ++ break; ++ case VKD3D_SHADER_COMPONENT_FLOAT: ++ vkd3d_string_buffer_printf(buffer, "vec4"); ++ break; ++ default: ++ vkd3d_string_buffer_printf(buffer, "", e->component_type); ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled input component type %#x.", e->component_type); ++ break; ++ } ++ vkd3d_string_buffer_printf(buffer, " shader_in_%u;\n", i); ++ ++count; + } ++ if (count) ++ vkd3d_string_buffer_printf(buffer, "\n"); + } + else if (gen->limits.input_count) + { +- shader_glsl_generate_interface_block(buffer, "in", gen->limits.input_count); ++ shader_glsl_generate_interface_block(gen, signature, "in", gen->limits.input_count); ++ vkd3d_string_buffer_printf(buffer, "\n"); + } +- vkd3d_string_buffer_printf(buffer, "\n"); + } + + static void shader_glsl_generate_output_declarations(struct vkd3d_glsl_generator *gen) +@@ -1558,11 +1690,11 @@ static void shader_glsl_generate_output_declarations(struct vkd3d_glsl_generator + const struct shader_signature *signature = &gen->program->output_signature; + struct vkd3d_string_buffer *buffer = gen->buffer; + const struct signature_element *e; +- unsigned int i; ++ unsigned int i, count; + + if (!gen->interstage_output) + { +- for (i = 0; i < signature->element_count; ++i) ++ for (i = 0, count = 0; i < signature->element_count; ++i) + { + e = &signature->elements[i]; + +@@ -1576,13 +1708,6 @@ static void shader_glsl_generate_output_declarations(struct vkd3d_glsl_generator + continue; + } + +- if (e->component_type != VKD3D_SHADER_COMPONENT_FLOAT) +- { +- vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, +- "Internal compiler error: Unhandled component type %#x.", e->component_type); +- continue; +- } +- + if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) + { + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, +@@ -1597,15 +1722,32 @@ static void shader_glsl_generate_output_declarations(struct vkd3d_glsl_generator + continue; + } + +- vkd3d_string_buffer_printf(buffer, +- "layout(location = %u) out vec4 shader_out_%u;\n", e->target_location, i); ++ vkd3d_string_buffer_printf(buffer, "layout(location = %u) out ", e->target_location); ++ switch (e->component_type) ++ { ++ case VKD3D_SHADER_COMPONENT_UINT: ++ vkd3d_string_buffer_printf(buffer, "uvec4"); ++ break; ++ case VKD3D_SHADER_COMPONENT_FLOAT: ++ vkd3d_string_buffer_printf(buffer, "vec4"); ++ break; ++ default: ++ vkd3d_string_buffer_printf(buffer, "", e->component_type); ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled output component type %#x.", e->component_type); ++ break; ++ } ++ vkd3d_string_buffer_printf(buffer, " shader_out_%u;\n", i); ++ ++count; + } ++ if (count) ++ vkd3d_string_buffer_printf(buffer, "\n"); + } + else if (gen->limits.output_count) + { +- shader_glsl_generate_interface_block(buffer, "out", gen->limits.output_count); ++ shader_glsl_generate_interface_block(gen, signature, "out", gen->limits.output_count); ++ vkd3d_string_buffer_printf(buffer, "\n"); + } +- vkd3d_string_buffer_printf(buffer, "\n"); + } + + static void shader_glsl_generate_declarations(struct vkd3d_glsl_generator *gen) +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +index 9ace1930c1b..b44c0296f69 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +@@ -1621,7 +1621,6 @@ struct hlsl_ir_node *hlsl_new_binary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_exp + { + struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {arg1, arg2}; + +- VKD3D_ASSERT(hlsl_types_are_equal(arg1->data_type, arg2->data_type)); + return hlsl_new_expr(ctx, op, operands, arg1->data_type, &arg1->loc); + } + +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index ef37eb75f03..2230cd5b919 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -461,6 +461,40 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct + return add_cast(ctx, block, node, dst_type, loc); + } + ++static bool add_explicit_conversion(struct hlsl_ctx *ctx, struct hlsl_block *block, ++ struct hlsl_type *dst_type, const struct parse_array_sizes *arrays, const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_ir_node *instr = node_from_block(block); ++ struct hlsl_type *src_type = instr->data_type; ++ unsigned int i; ++ ++ for (i = 0; i < arrays->count; ++i) ++ { ++ if (arrays->sizes[i] == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT) ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Implicit size arrays not allowed in casts."); ++ dst_type = hlsl_new_array_type(ctx, dst_type, arrays->sizes[i]); ++ } ++ ++ if (instr->data_type->class == HLSL_CLASS_ERROR) ++ return true; ++ ++ if (!explicit_compatible_data_types(ctx, src_type, dst_type)) ++ { ++ struct vkd3d_string_buffer *src_string, *dst_string; ++ ++ src_string = hlsl_type_to_string(ctx, src_type); ++ dst_string = hlsl_type_to_string(ctx, dst_type); ++ if (src_string && dst_string) ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Can't cast from %s to %s.", ++ src_string->buffer, dst_string->buffer); ++ hlsl_release_string_buffer(ctx, src_string); ++ hlsl_release_string_buffer(ctx, dst_string); ++ return false; ++ } ++ ++ return add_cast(ctx, block, instr, dst_type, loc); ++} ++ + static uint32_t add_modifiers(struct hlsl_ctx *ctx, uint32_t modifiers, uint32_t mod, + const struct vkd3d_shader_location *loc) + { +@@ -978,6 +1012,12 @@ static bool add_array_access(struct hlsl_ctx *ctx, struct hlsl_block *block, str + const struct hlsl_type *expr_type = array->data_type, *index_type = index->data_type; + struct hlsl_ir_node *return_index, *cast; + ++ if (array->data_type->class == HLSL_CLASS_ERROR || index->data_type->class == HLSL_CLASS_ERROR) ++ { ++ block->value = ctx->error_instr; ++ return true; ++ } ++ + if ((expr_type->class == HLSL_CLASS_TEXTURE || expr_type->class == HLSL_CLASS_UAV) + && expr_type->sampler_dim != HLSL_SAMPLER_DIM_GENERIC) + { +@@ -2314,6 +2354,9 @@ static bool add_increment(struct hlsl_ctx *ctx, struct hlsl_block *block, bool d + struct hlsl_ir_node *lhs = node_from_block(block); + struct hlsl_ir_node *one; + ++ if (lhs->data_type->class == HLSL_CLASS_ERROR) ++ return true; ++ + if (lhs->data_type->modifiers & HLSL_MODIFIER_CONST) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_MODIFIES_CONST, + "Argument to %s%screment operator is const.", post ? "post" : "pre", decrement ? "de" : "in"); +@@ -2366,9 +2409,9 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i + { + struct hlsl_default_value default_value = {0}; + +- if (hlsl_is_numeric_type(dst_comp_type)) ++ if (src->type == HLSL_IR_COMPILE || src->type == HLSL_IR_SAMPLER_STATE) + { +- if (src->type == HLSL_IR_COMPILE || src->type == HLSL_IR_SAMPLER_STATE) ++ if (hlsl_is_numeric_type(dst_comp_type)) + { + /* Default values are discarded if they contain an object + * literal expression for a numeric component. */ +@@ -2381,17 +2424,17 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i + dst->default_values = NULL; + } + } +- else +- { +- if (!hlsl_clone_block(ctx, &block, instrs)) +- return; +- default_value = evaluate_static_expression(ctx, &block, dst_comp_type, &src->loc); ++ } ++ else ++ { ++ if (!hlsl_clone_block(ctx, &block, instrs)) ++ return; ++ default_value = evaluate_static_expression(ctx, &block, dst_comp_type, &src->loc); + +- if (dst->default_values) +- dst->default_values[*store_index] = default_value; ++ if (dst->default_values) ++ dst->default_values[*store_index] = default_value; + +- hlsl_block_cleanup(&block); +- } ++ hlsl_block_cleanup(&block); + } + } + else +@@ -8770,7 +8813,6 @@ postfix_expr: + YYABORT; + } + vkd3d_free($3); +- $$ = $1; + } + else if (hlsl_is_numeric_type(node->data_type)) + { +@@ -8784,14 +8826,14 @@ postfix_expr: + } + hlsl_block_add_instr($1, swizzle); + vkd3d_free($3); +- $$ = $1; + } +- else ++ else if (node->data_type->class != HLSL_CLASS_ERROR) + { + hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Invalid subscript \"%s\".", $3); + vkd3d_free($3); + YYABORT; + } ++ $$ = $1; + } + | postfix_expr '[' expr ']' + { +@@ -8903,10 +8945,6 @@ unary_expr: + /* var_modifiers is necessary to avoid shift/reduce conflicts. */ + | '(' var_modifiers type arrays ')' unary_expr + { +- struct hlsl_type *src_type = node_from_block($6)->data_type; +- struct hlsl_type *dst_type; +- unsigned int i; +- + if ($2) + { + hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, +@@ -8914,36 +8952,13 @@ unary_expr: + YYABORT; + } + +- dst_type = $3; +- for (i = 0; i < $4.count; ++i) +- { +- if ($4.sizes[i] == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT) +- { +- hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, +- "Implicit size arrays not allowed in casts."); +- } +- dst_type = hlsl_new_array_type(ctx, dst_type, $4.sizes[i]); +- } +- +- if (!explicit_compatible_data_types(ctx, src_type, dst_type)) +- { +- struct vkd3d_string_buffer *src_string, *dst_string; +- +- src_string = hlsl_type_to_string(ctx, src_type); +- dst_string = hlsl_type_to_string(ctx, dst_type); +- if (src_string && dst_string) +- hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Can't cast from %s to %s.", +- src_string->buffer, dst_string->buffer); +- hlsl_release_string_buffer(ctx, src_string); +- hlsl_release_string_buffer(ctx, dst_string); +- YYABORT; +- } +- +- if (!add_cast(ctx, $6, node_from_block($6), dst_type, &@3)) ++ if (!add_explicit_conversion(ctx, $6, $3, &$4, &@3)) + { + destroy_block($6); ++ vkd3d_free($4.sizes); + YYABORT; + } ++ vkd3d_free($4.sizes); + $$ = $6; + } + +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 6a74e2eb8de..14cf23e8d1a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -681,6 +681,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr + case VKD3DSIH_DCL_CONSTANT_BUFFER: + case VKD3DSIH_DCL_SAMPLER: + case VKD3DSIH_DCL_TEMPS: ++ case VKD3DSIH_DCL_THREAD_GROUP: + vkd3d_shader_instruction_make_nop(ins); + break; + +@@ -763,7 +764,7 @@ static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_i + } + + for (i = 0; i < ins->dst_count; ++i) +- shader_register_eliminate_phase_addressing((struct vkd3d_shader_register *)&ins->dst[i].reg, instance_id); ++ shader_register_eliminate_phase_addressing(&ins->dst[i].reg, instance_id); + } + + static const struct vkd3d_shader_varying_map *find_varying_map( +@@ -1470,6 +1471,9 @@ static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map + return false; + memcpy(elements, s->elements, element_count * sizeof(*elements)); + ++ for (i = 0; i < element_count; ++i) ++ elements[i].sort_index = i; ++ + qsort(elements, element_count, sizeof(elements[0]), signature_element_register_compare); + + for (i = 0, new_count = 0; i < element_count; i = j, elements[new_count++] = *e) +@@ -1667,7 +1671,6 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par + vkd3d_unreachable(); + e = &signature->elements[element_idx]; + +- dst_param->write_mask >>= vsir_write_mask_get_component_idx(e->mask); + if (is_io_dcl) + { + /* Validated in the TPF reader. */ +@@ -7149,7 +7152,7 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t + vsir_transform(&ctx, vsir_program_insert_clip_planes); + + if (TRACE_ON()) +- vkd3d_shader_trace(program); ++ vsir_program_trace(program); + + return ctx.result; + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c +index 6b41363d60e..bfc013959e7 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/msl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/msl.c +@@ -38,6 +38,7 @@ struct msl_generator + struct vkd3d_shader_location location; + struct vkd3d_shader_message_context *message_context; + unsigned int indent; ++ const char *prefix; + }; + + static void VKD3D_PRINTF_FUNC(3, 4) msl_compiler_error(struct msl_generator *gen, +@@ -50,16 +51,37 @@ static void VKD3D_PRINTF_FUNC(3, 4) msl_compiler_error(struct msl_generator *gen + va_end(args); + } + ++static const char *msl_get_prefix(enum vkd3d_shader_type type) ++{ ++ switch (type) ++ { ++ case VKD3D_SHADER_TYPE_VERTEX: ++ return "vs"; ++ case VKD3D_SHADER_TYPE_HULL: ++ return "hs"; ++ case VKD3D_SHADER_TYPE_DOMAIN: ++ return "ds"; ++ case VKD3D_SHADER_TYPE_GEOMETRY: ++ return "gs"; ++ case VKD3D_SHADER_TYPE_PIXEL: ++ return "ps"; ++ case VKD3D_SHADER_TYPE_COMPUTE: ++ return "cs"; ++ default: ++ return NULL; ++ } ++} ++ + static void msl_print_indent(struct vkd3d_string_buffer *buffer, unsigned int indent) + { + vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, ""); + } + + static void msl_print_register_datatype(struct vkd3d_string_buffer *buffer, +- struct msl_generator *gen, const struct vkd3d_shader_register *reg) ++ struct msl_generator *gen, enum vkd3d_data_type data_type) + { + vkd3d_string_buffer_printf(buffer, "."); +- switch (reg->data_type) ++ switch (data_type) + { + case VKD3D_DATA_FLOAT: + vkd3d_string_buffer_printf(buffer, "f"); +@@ -72,8 +94,8 @@ static void msl_print_register_datatype(struct vkd3d_string_buffer *buffer, + break; + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, +- "Internal compiler error: Unhandled register datatype %#x.", reg->data_type); +- vkd3d_string_buffer_printf(buffer, "", reg->data_type); ++ "Internal compiler error: Unhandled register datatype %#x.", data_type); ++ vkd3d_string_buffer_printf(buffer, "", data_type); + break; + } + } +@@ -85,7 +107,7 @@ static void msl_print_register_name(struct vkd3d_string_buffer *buffer, + { + case VKD3DSPR_TEMP: + vkd3d_string_buffer_printf(buffer, "r[%u]", reg->idx[0].offset); +- msl_print_register_datatype(buffer, gen, reg); ++ msl_print_register_datatype(buffer, gen, reg->data_type); + break; + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, +@@ -244,6 +266,309 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + } + } + ++static void msl_generate_input_struct_declarations(struct msl_generator *gen) ++{ ++ const struct shader_signature *signature = &gen->program->input_signature; ++ enum vkd3d_shader_type type = gen->program->shader_version.type; ++ struct vkd3d_string_buffer *buffer = gen->buffer; ++ const struct signature_element *e; ++ unsigned int i; ++ ++ vkd3d_string_buffer_printf(buffer, "struct vkd3d_%s_in\n{\n", gen->prefix); ++ ++ for (i = 0; i < signature->element_count; ++i) ++ { ++ e = &signature->elements[i]; ++ ++ if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) ++ continue; ++ ++ if (e->sysval_semantic) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled system value %#x.", e->sysval_semantic); ++ continue; ++ } ++ ++ if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled minimum precision %#x.", e->min_precision); ++ continue; ++ } ++ ++ if (e->interpolation_mode != VKD3DSIM_NONE) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled interpolation mode %#x.", e->interpolation_mode); ++ continue; ++ } ++ ++ if(e->register_count > 1) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled register count %u.", e->register_count); ++ continue; ++ } ++ ++ msl_print_indent(gen->buffer, 1); ++ ++ switch(e->component_type) ++ { ++ case VKD3D_SHADER_COMPONENT_FLOAT: ++ vkd3d_string_buffer_printf(buffer, "float4 "); ++ break; ++ case VKD3D_SHADER_COMPONENT_INT: ++ vkd3d_string_buffer_printf(buffer, "int4 "); ++ break; ++ case VKD3D_SHADER_COMPONENT_UINT: ++ vkd3d_string_buffer_printf(buffer, "uint4 "); ++ break; ++ default: ++ vkd3d_string_buffer_printf(buffer, " ", e->component_type); ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled component type %#x.", e->component_type); ++ break; ++ } ++ ++ vkd3d_string_buffer_printf(buffer, "shader_in_%u ", i); ++ ++ switch (type) ++ { ++ case VKD3D_SHADER_TYPE_VERTEX: ++ vkd3d_string_buffer_printf(gen->buffer, "[[attribute(%u)]]", e->target_location); ++ break; ++ case VKD3D_SHADER_TYPE_PIXEL: ++ vkd3d_string_buffer_printf(gen->buffer, "[[user(locn%u)]]", e->target_location); ++ break; ++ default: ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled shader type %#x.", type); ++ break; ++ } ++ ++ vkd3d_string_buffer_printf(buffer, ";\n"); ++ } ++ ++ vkd3d_string_buffer_printf(buffer, "};\n\n"); ++} ++ ++static void msl_generate_vertex_output_element_attribute(struct msl_generator *gen, const struct signature_element *e) ++{ ++ switch (e->sysval_semantic) ++ { ++ case VKD3D_SHADER_SV_POSITION: ++ vkd3d_string_buffer_printf(gen->buffer, "[[position]]"); ++ break; ++ case VKD3D_SHADER_SV_NONE: ++ vkd3d_string_buffer_printf(gen->buffer, "[[user(locn%u)]]", e->target_location); ++ break; ++ default: ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled vertex shader system value %#x.", e->sysval_semantic); ++ break; ++ } ++} ++ ++static void msl_generate_pixel_output_element_attribute(struct msl_generator *gen, const struct signature_element *e) ++{ ++ switch (e->sysval_semantic) ++ { ++ case VKD3D_SHADER_SV_TARGET: ++ vkd3d_string_buffer_printf(gen->buffer, "[[color(%u)]]", e->target_location); ++ break; ++ default: ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled pixel shader system value %#x.", e->sysval_semantic); ++ break; ++ } ++} ++ ++static void msl_generate_output_struct_declarations(struct msl_generator *gen) ++{ ++ const struct shader_signature *signature = &gen->program->output_signature; ++ enum vkd3d_shader_type type = gen->program->shader_version.type; ++ struct vkd3d_string_buffer *buffer = gen->buffer; ++ const struct signature_element *e; ++ unsigned int i; ++ ++ vkd3d_string_buffer_printf(buffer, "struct vkd3d_%s_out\n{\n", gen->prefix); ++ ++ for (i = 0; i < signature->element_count; ++i) ++ { ++ e = &signature->elements[i]; ++ ++ if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) ++ continue; ++ ++ if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled minimum precision %#x.", e->min_precision); ++ continue; ++ } ++ ++ if (e->interpolation_mode != VKD3DSIM_NONE) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled interpolation mode %#x.", e->interpolation_mode); ++ continue; ++ } ++ ++ if(e->register_count > 1) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled register count %u.", e->register_count); ++ continue; ++ } ++ ++ msl_print_indent(gen->buffer, 1); ++ ++ switch(e->component_type) ++ { ++ case VKD3D_SHADER_COMPONENT_FLOAT: ++ vkd3d_string_buffer_printf(buffer, "float4 "); ++ break; ++ case VKD3D_SHADER_COMPONENT_INT: ++ vkd3d_string_buffer_printf(buffer, "int4 "); ++ break; ++ case VKD3D_SHADER_COMPONENT_UINT: ++ vkd3d_string_buffer_printf(buffer, "uint4 "); ++ break; ++ default: ++ vkd3d_string_buffer_printf(buffer, " ", e->component_type); ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled component type %#x.", e->component_type); ++ break; ++ } ++ ++ vkd3d_string_buffer_printf(buffer, "shader_out_%u ", i); ++ ++ switch (type) ++ { ++ case VKD3D_SHADER_TYPE_VERTEX: ++ msl_generate_vertex_output_element_attribute(gen, e); ++ break; ++ case VKD3D_SHADER_TYPE_PIXEL: ++ msl_generate_pixel_output_element_attribute(gen, e); ++ break; ++ default: ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled shader type %#x.", type); ++ break; ++ } ++ ++ vkd3d_string_buffer_printf(buffer, ";\n"); ++ } ++ ++ vkd3d_string_buffer_printf(buffer, "};\n\n"); ++} ++ ++static void msl_generate_entrypoint_prologue(struct msl_generator *gen) ++{ ++ const struct shader_signature *signature = &gen->program->input_signature; ++ struct vkd3d_string_buffer *buffer = gen->buffer; ++ const struct signature_element *e; ++ unsigned int i; ++ ++ for (i = 0; i < signature->element_count; ++i) ++ { ++ e = &signature->elements[i]; ++ ++ if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) ++ continue; ++ ++ vkd3d_string_buffer_printf(buffer, " %s_in[%u]", gen->prefix, e->register_index); ++ if (e->sysval_semantic == VKD3D_SHADER_SV_NONE) ++ { ++ msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); ++ msl_print_write_mask(buffer, e->mask); ++ vkd3d_string_buffer_printf(buffer, " = input.shader_in_%u", i); ++ msl_print_write_mask(buffer, e->mask); ++ } ++ else ++ { ++ vkd3d_string_buffer_printf(buffer, " = ", e->sysval_semantic); ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled system value %#x input.", e->sysval_semantic); ++ } ++ vkd3d_string_buffer_printf(buffer, ";\n"); ++ } ++} ++ ++static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) ++{ ++ const struct shader_signature *signature = &gen->program->output_signature; ++ struct vkd3d_string_buffer *buffer = gen->buffer; ++ const struct signature_element *e; ++ unsigned int i; ++ ++ for (i = 0; i < signature->element_count; ++i) ++ { ++ e = &signature->elements[i]; ++ ++ if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) ++ continue; ++ ++ switch (e->sysval_semantic) ++ { ++ case VKD3D_SHADER_SV_NONE: ++ case VKD3D_SHADER_SV_TARGET: ++ case VKD3D_SHADER_SV_POSITION: ++ vkd3d_string_buffer_printf(buffer, " output.shader_out_%u", i); ++ msl_print_write_mask(buffer, e->mask); ++ vkd3d_string_buffer_printf(buffer, " = %s_out", gen->prefix); ++ msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); ++ msl_print_write_mask(buffer, e->mask); ++ break; ++ default: ++ vkd3d_string_buffer_printf(buffer, " ", e->sysval_semantic); ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled system value %#x input.", e->sysval_semantic); ++ } ++ vkd3d_string_buffer_printf(buffer, ";\n"); ++ } ++} ++ ++static void msl_generate_entrypoint(struct msl_generator *gen) ++{ ++ enum vkd3d_shader_type type = gen->program->shader_version.type; ++ ++ switch (type) ++ { ++ case VKD3D_SHADER_TYPE_VERTEX: ++ vkd3d_string_buffer_printf(gen->buffer, "vertex "); ++ break; ++ case VKD3D_SHADER_TYPE_PIXEL: ++ vkd3d_string_buffer_printf(gen->buffer, "fragment "); ++ break; ++ default: ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled shader type %#x.", type); ++ return; ++ } ++ ++ vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_out shader_entry(\n", gen->prefix); ++ ++ /* TODO: descriptor declaration */ ++ ++ msl_print_indent(gen->buffer, 1); ++ vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_in input [[stage_in]])\n{\n", gen->prefix); ++ ++ /* TODO: declare #maximum_register + 1 */ ++ vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 %s_in[%u];\n", gen->prefix, 32); ++ vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 %s_out[%u];\n", gen->prefix, 32); ++ vkd3d_string_buffer_printf(gen->buffer, " vkd3d_%s_out output;\n", gen->prefix); ++ ++ msl_generate_entrypoint_prologue(gen); ++ ++ vkd3d_string_buffer_printf(gen->buffer, " %s_main(%s_in, %s_out);\n", gen->prefix, gen->prefix, gen->prefix); ++ ++ msl_generate_entrypoint_epilogue(gen); ++ ++ vkd3d_string_buffer_printf(gen->buffer, " return output;\n}\n"); ++} ++ + static void msl_generator_generate(struct msl_generator *gen) + { + const struct vkd3d_shader_instruction_array *instructions = &gen->program->instructions; +@@ -258,7 +583,13 @@ static void msl_generator_generate(struct msl_generator *gen) + vkd3d_string_buffer_printf(gen->buffer, " int4 i;\n"); + vkd3d_string_buffer_printf(gen->buffer, " float4 f;\n};\n\n"); + +- vkd3d_string_buffer_printf(gen->buffer, "void shader_main()\n{\n"); ++ msl_generate_input_struct_declarations(gen); ++ msl_generate_output_struct_declarations(gen); ++ ++ vkd3d_string_buffer_printf(gen->buffer, ++ "void %s_main(thread vkd3d_vec4 *v, " ++ "thread vkd3d_vec4 *o)\n{\n", ++ gen->prefix); + + ++gen->indent; + +@@ -273,7 +604,11 @@ static void msl_generator_generate(struct msl_generator *gen) + msl_handle_instruction(gen, &instructions->elements[i]); + } + +- vkd3d_string_buffer_printf(gen->buffer, "}\n"); ++ --gen->indent; ++ ++ vkd3d_string_buffer_printf(gen->buffer, "}\n\n"); ++ ++ msl_generate_entrypoint(gen); + + if (TRACE_ON()) + vkd3d_string_buffer_trace(gen->buffer); +@@ -288,6 +623,8 @@ static void msl_generator_cleanup(struct msl_generator *gen) + static int msl_generator_init(struct msl_generator *gen, struct vsir_program *program, + struct vkd3d_shader_message_context *message_context) + { ++ enum vkd3d_shader_type type = program->shader_version.type; ++ + memset(gen, 0, sizeof(*gen)); + gen->program = program; + vkd3d_string_buffer_cache_init(&gen->string_buffers); +@@ -297,6 +634,12 @@ static int msl_generator_init(struct msl_generator *gen, struct vsir_program *pr + return VKD3D_ERROR_OUT_OF_MEMORY; + } + gen->message_context = message_context; ++ if (!(gen->prefix = msl_get_prefix(type))) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled shader type %#x.", type); ++ return VKD3D_ERROR_INVALID_SHADER; ++ } + + return VKD3D_OK; + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.h b/libs/vkd3d/libs/vkd3d-shader/preproc.h +index 9806614a35b..a98c8ae3df5 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/preproc.h ++++ b/libs/vkd3d/libs/vkd3d-shader/preproc.h +@@ -60,6 +60,7 @@ struct preproc_expansion + { + struct preproc_buffer buffer; + const struct preproc_text *text; ++ struct preproc_text *arg_values; + /* Back-pointer to the macro, if this expansion a macro body. This is + * necessary so that argument tokens can be correctly replaced. */ + struct preproc_macro *macro; +@@ -72,7 +73,6 @@ struct preproc_macro + + char **arg_names; + size_t arg_count; +- struct preproc_text *arg_values; + + struct preproc_text body; + }; +@@ -117,6 +117,7 @@ struct preproc_ctx + STATE_ARGS, + } state; + unsigned int paren_depth; ++ struct preproc_text *arg_values; + } text_func, directive_func; + + int current_directive; +diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l +index 41c21cca1f5..d167415c356 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/preproc.l ++++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l +@@ -30,11 +30,11 @@ + + #define YY_DECL static int preproc_lexer_lex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) + +-static struct preproc_macro *preproc_get_top_macro(struct preproc_ctx *ctx) ++static struct preproc_expansion *preproc_get_top_expansion(struct preproc_ctx *ctx) + { + if (!ctx->expansion_count) + return NULL; +- return ctx->expansion_stack[ctx->expansion_count - 1].macro; ++ return &ctx->expansion_stack[ctx->expansion_count - 1]; + } + + static void update_location(struct preproc_ctx *ctx); +@@ -133,14 +133,14 @@ INT_SUFFIX [uUlL]{0,2} + + if (!ctx->last_was_newline) + { +- struct preproc_macro *macro; ++ struct preproc_expansion *exp; + + /* Stringification is only done for function-like macro bodies. + * Anywhere else, we need to parse it as two separate tokens. + * We could use a state for this, but yyless() is easier and cheap. + */ + +- if ((macro = preproc_get_top_macro(ctx)) && macro->arg_count) ++ if ((exp = preproc_get_top_expansion(ctx)) && exp->macro && exp->macro->arg_count) + return T_HASHSTRING; + + yyless(1); +@@ -259,6 +259,12 @@ static void preproc_pop_buffer(struct preproc_ctx *ctx) + + yy_delete_buffer(exp->buffer.lexer_buffer, ctx->scanner); + ++ if (exp->macro) ++ { ++ for (unsigned int i = 0; i < exp->macro->arg_count; ++i) ++ vkd3d_string_buffer_cleanup(&exp->arg_values[i].text); ++ free(exp->arg_values); ++ } + --ctx->expansion_count; + TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count); + } +@@ -311,15 +317,15 @@ static int return_token(int token, YYSTYPE *lval, const char *text) + + static const struct preproc_text *find_arg_expansion(struct preproc_ctx *ctx, const char *s) + { +- struct preproc_macro *macro; ++ struct preproc_expansion *exp; + unsigned int i; + +- if ((macro = preproc_get_top_macro(ctx))) ++ if ((exp = preproc_get_top_expansion(ctx)) && exp->macro) + { +- for (i = 0; i < macro->arg_count; ++i) ++ for (i = 0; i < exp->macro->arg_count; ++i) + { +- if (!strcmp(s, macro->arg_names[i])) +- return ¯o->arg_values[i]; ++ if (!strcmp(s, exp->macro->arg_names[i])) ++ return &exp->arg_values[i]; + } + } + return NULL; +@@ -331,7 +337,7 @@ static void preproc_text_add(struct preproc_text *text, const char *string) + } + + static bool preproc_push_expansion(struct preproc_ctx *ctx, +- const struct preproc_text *text, struct preproc_macro *macro) ++ const struct preproc_text *text, struct preproc_macro *macro, struct preproc_text *arg_values) + { + struct preproc_expansion *exp; + +@@ -343,6 +349,7 @@ static bool preproc_push_expansion(struct preproc_ctx *ctx, + exp->buffer.lexer_buffer = yy_scan_bytes(text->text.buffer, text->text.content_size, ctx->scanner); + exp->buffer.location = text->location; + exp->macro = macro; ++ exp->arg_values = arg_values; + TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count); + return true; + } +@@ -543,7 +550,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) + + if ((expansion = find_arg_expansion(ctx, text))) + { +- preproc_push_expansion(ctx, expansion, NULL); ++ preproc_push_expansion(ctx, expansion, NULL, NULL); + continue; + } + +@@ -551,7 +558,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) + { + if (!macro->arg_count) + { +- preproc_push_expansion(ctx, ¯o->body, macro); ++ preproc_push_expansion(ctx, ¯o->body, macro, NULL); + } + else + { +@@ -617,16 +624,19 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) + case STATE_IDENTIFIER: + if (token == '(') + { +- struct preproc_text *first_arg = &func_state->macro->arg_values[0]; +- unsigned int i; ++ struct preproc_text *arg_values; ++ ++ if (!(arg_values = calloc(func_state->macro->arg_count, sizeof(*arg_values)))) ++ return 0; ++ ++ for (unsigned int i = 0; i < func_state->macro->arg_count; ++i) ++ vkd3d_string_buffer_init(&arg_values[i].text); ++ arg_values[0].location = *lloc; + + func_state->arg_count = 0; + func_state->paren_depth = 1; + func_state->state = STATE_ARGS; +- for (i = 0; i < func_state->macro->arg_count; ++i) +- func_state->macro->arg_values[i].text.content_size = 0; +- +- first_arg->location = *lloc; ++ func_state->arg_values = arg_values; + } + else + { +@@ -650,7 +660,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) + VKD3D_ASSERT(func_state->macro->arg_count); + + if (func_state->arg_count < func_state->macro->arg_count) +- current_arg = &func_state->macro->arg_values[func_state->arg_count]; ++ current_arg = &func_state->arg_values[func_state->arg_count]; + + switch (token) + { +@@ -665,7 +675,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) + + if ((expansion = find_arg_expansion(ctx, text))) + { +- preproc_push_expansion(ctx, expansion, NULL); ++ preproc_push_expansion(ctx, expansion, NULL, NULL); + continue; + } + +@@ -701,7 +711,8 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) + { + if (++func_state->arg_count == func_state->macro->arg_count) + { +- preproc_push_expansion(ctx, &func_state->macro->body, func_state->macro); ++ preproc_push_expansion(ctx, &func_state->macro->body, ++ func_state->macro, func_state->arg_values); + } + else + { +diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.y b/libs/vkd3d/libs/vkd3d-shader/preproc.y +index 366e351e3b5..c6be17bd230 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/preproc.y ++++ b/libs/vkd3d/libs/vkd3d-shader/preproc.y +@@ -91,7 +91,6 @@ bool preproc_add_macro(struct preproc_ctx *ctx, const struct vkd3d_shader_locati + size_t arg_count, const struct vkd3d_shader_location *body_loc, struct vkd3d_string_buffer *body) + { + struct preproc_macro *macro; +- unsigned int i; + int ret; + + if ((macro = preproc_find_macro(ctx, name))) +@@ -108,14 +107,6 @@ bool preproc_add_macro(struct preproc_ctx *ctx, const struct vkd3d_shader_locati + macro->name = name; + macro->arg_names = arg_names; + macro->arg_count = arg_count; +- macro->arg_values = NULL; +- if (arg_count && !(macro->arg_values = vkd3d_calloc(arg_count, sizeof(*macro->arg_values)))) +- { +- vkd3d_free(macro); +- return false; +- } +- for (i = 0; i < arg_count; ++i) +- vkd3d_string_buffer_init(¯o->arg_values[i].text); + macro->body.text = *body; + macro->body.location = *body_loc; + ret = rb_put(&ctx->macros, name, ¯o->entry); +@@ -129,12 +120,8 @@ void preproc_free_macro(struct preproc_macro *macro) + + vkd3d_free(macro->name); + for (i = 0; i < macro->arg_count; ++i) +- { +- vkd3d_string_buffer_cleanup(¯o->arg_values[i].text); + vkd3d_free(macro->arg_names[i]); +- } + vkd3d_free(macro->arg_names); +- vkd3d_free(macro->arg_values); + vkd3d_string_buffer_cleanup(¯o->body.text); + vkd3d_free(macro); + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index 11c054a28f5..cb610c929b6 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -5510,7 +5510,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + const struct shader_signature *shader_signature; + const struct vkd3d_spirv_builtin *builtin; + enum vkd3d_shader_sysval_semantic sysval; +- uint32_t write_mask, reg_write_mask; ++ uint32_t write_mask; + bool use_private_variable = false; + struct vkd3d_symbol reg_symbol; + SpvStorageClass storage_class; +@@ -5561,7 +5561,6 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + use_private_variable = true; + } + +- reg_write_mask = write_mask >> component_idx; + vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); + + if (rb_get(&compiler->symbol_table, ®_symbol)) +@@ -5639,7 +5638,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + + vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, + use_private_variable ? VKD3D_SHADER_COMPONENT_FLOAT : component_type, +- use_private_variable ? VKD3DSP_WRITEMASK_ALL : reg_write_mask); ++ use_private_variable ? VKD3DSP_WRITEMASK_ALL : write_mask); + reg_symbol.info.reg.is_aggregate = array_sizes[0] || array_sizes[1]; + VKD3D_ASSERT(!builtin || !builtin->spirv_array_size || use_private_variable || array_sizes[0] || array_sizes[1]); + +@@ -5650,7 +5649,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] |= reg_write_mask; ++ compiler->private_output_variable_write_mask[element_idx] |= write_mask >> component_idx; + if (!compiler->epilogue_function_id) + compiler->epilogue_function_id = vkd3d_spirv_alloc_id(builder); + } +@@ -6891,10 +6890,9 @@ static void spirv_compiler_emit_tessellator_partitioning(struct spirv_compiler * + spirv_compiler_emit_execution_mode(compiler, mode, NULL, 0); + } + +-static void spirv_compiler_emit_dcl_thread_group(struct spirv_compiler *compiler, +- const struct vkd3d_shader_instruction *instruction) ++static void spirv_compiler_emit_thread_group_size(struct spirv_compiler *compiler, ++ const struct vsir_thread_group_size *group_size) + { +- const struct vkd3d_shader_thread_group_size *group_size = &instruction->declaration.thread_group_size; + const uint32_t local_size[] = {group_size->x, group_size->y, group_size->z}; + + spirv_compiler_emit_execution_mode(compiler, +@@ -10228,9 +10226,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, + spirv_compiler_emit_tessellator_partitioning(compiler, + instruction->declaration.tessellator_partitioning); + break; +- case VKD3DSIH_DCL_THREAD_GROUP: +- spirv_compiler_emit_dcl_thread_group(compiler, instruction); +- break; + case VKD3DSIH_HS_CONTROL_POINT_PHASE: + case VKD3DSIH_HS_FORK_PHASE: + case VKD3DSIH_HS_JOIN_PHASE: +@@ -10650,6 +10645,8 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct + spirv_compiler_emit_temps(compiler, program->temp_count); + if (program->ssa_count) + spirv_compiler_allocate_ssa_register_ids(compiler, program->ssa_count); ++ if (compiler->shader_type == VKD3D_SHADER_TYPE_COMPUTE) ++ spirv_compiler_emit_thread_group_size(compiler, &program->thread_group_size); + + spirv_compiler_emit_descriptor_declarations(compiler); + +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index 00a525c9ac3..75bdb06fe0e 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -1289,11 +1289,14 @@ static void shader_sm5_read_dcl_hs_max_tessfactor(struct vkd3d_shader_instructio + } + + static void shader_sm5_read_dcl_thread_group(struct vkd3d_shader_instruction *ins, uint32_t opcode, +- uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) ++ uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *sm4) + { ++ struct vsir_program *program = sm4->p.program; ++ + ins->declaration.thread_group_size.x = *tokens++; + ins->declaration.thread_group_size.y = *tokens++; + ins->declaration.thread_group_size.z = *tokens++; ++ program->thread_group_size = ins->declaration.thread_group_size; + } + + static void shader_sm5_read_dcl_uav_raw(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token, +@@ -2959,7 +2962,7 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con + WARN("Failed to validate shader after parsing, ret %d.\n", ret); + + if (TRACE_ON()) +- vkd3d_shader_trace(program); ++ vsir_program_trace(program); + + vsir_program_cleanup(program); + return ret; +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index ee8a633431a..9b320106340 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -1489,7 +1489,7 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh + descriptor_info1, combined_sampler_info, message_context); + + if (TRACE_ON()) +- vkd3d_shader_trace(program); ++ vsir_program_trace(program); + + for (i = 0; i < program->instructions.count; ++i) + { +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index eab164cc848..1a42f385fc0 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -1061,6 +1061,9 @@ enum vkd3d_shader_input_sysval_semantic + + struct signature_element + { ++ /* sort_index is not a property of the signature element, it is just a ++ * convenience field used to retain the original order in a signature and ++ * recover it after having permuted the signature itself. */ + unsigned int sort_index; + const char *semantic_name; + unsigned int semantic_index; +@@ -1164,7 +1167,7 @@ struct vkd3d_shader_tgsm_structured + bool zero_init; + }; + +-struct vkd3d_shader_thread_group_size ++struct vsir_thread_group_size + { + unsigned int x, y, z; + }; +@@ -1243,7 +1246,7 @@ struct vkd3d_shader_instruction + struct vkd3d_shader_structured_resource structured_resource; + struct vkd3d_shader_tgsm_raw tgsm_raw; + struct vkd3d_shader_tgsm_structured tgsm_structured; +- struct vkd3d_shader_thread_group_size thread_group_size; ++ struct vsir_thread_group_size thread_group_size; + enum vkd3d_tessellator_domain tessellator_domain; + enum vkd3d_shader_tessellator_output_primitive tessellator_output_primitive; + enum vkd3d_shader_tessellator_partitioning tessellator_partitioning; +@@ -1390,6 +1393,7 @@ struct vsir_program + bool free_parameters; + + unsigned int input_control_point_count, output_control_point_count; ++ struct vsir_thread_group_size thread_group_size; + unsigned int flat_constant_count[3]; + unsigned int block_count; + unsigned int temp_count; +@@ -1474,7 +1478,7 @@ struct vkd3d_shader_scan_descriptor_info1 + unsigned int descriptor_count; + }; + +-void vkd3d_shader_trace(const struct vsir_program *program); ++void vsir_program_trace(const struct vsir_program *program); + + const char *shader_get_type_prefix(enum vkd3d_shader_type type); + +-- +2.45.2 + diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-9cb4207c92ec3ee05fce15580c89f2e5146.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-9cb4207c92ec3ee05fce15580c89f2e5146.patch new file mode 100644 index 00000000..edc20380 --- /dev/null +++ b/patches/vkd3d-latest/0003-Updated-vkd3d-to-9cb4207c92ec3ee05fce15580c89f2e5146.patch @@ -0,0 +1,386 @@ +From b7ab480481541737db8e9b5514bc0e52309211c9 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Thu, 10 Oct 2024 07:16:15 +1100 +Subject: [PATCH] Updated vkd3d to 9cb4207c92ec3ee05fce15580c89f2e5146354db. + +--- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 15 +++ + libs/vkd3d/libs/vkd3d-shader/glsl.c | 101 ++++++++++++++++-- + libs/vkd3d/libs/vkd3d-shader/ir.c | 40 +++++++ + libs/vkd3d/libs/vkd3d-shader/spirv.c | 24 ++--- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 15 +++ + .../libs/vkd3d-shader/vkd3d_shader_main.c | 2 + + .../libs/vkd3d-shader/vkd3d_shader_private.h | 1 + + 7 files changed, 173 insertions(+), 25 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index c66b059325a..5db9d6da063 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -10315,6 +10315,21 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro + sm6->ptr = &sm6->start[1]; + sm6->bitpos = 2; + ++ switch (program->shader_version.type) ++ { ++ case VKD3D_SHADER_TYPE_HULL: ++ case VKD3D_SHADER_TYPE_DOMAIN: ++ break; ++ ++ default: ++ if (program->patch_constant_signature.element_count != 0) ++ { ++ WARN("The patch constant signature only makes sense for Hull and Domain Shaders, ignoring it.\n"); ++ shader_signature_cleanup(&program->patch_constant_signature); ++ } ++ break; ++ } ++ + input_signature = &program->input_signature; + output_signature = &program->output_signature; + patch_constant_signature = &program->patch_constant_signature; +diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c +index 4dc95899a11..91ee355ed39 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c +@@ -651,6 +651,20 @@ static void shader_glsl_cast(struct vkd3d_glsl_generator *gen, const struct vkd3 + glsl_dst_cleanup(&dst, &gen->string_buffers); + } + ++static void shader_glsl_end_block(struct vkd3d_glsl_generator *gen) ++{ ++ --gen->indent; ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "}\n"); ++} ++ ++static void shader_glsl_begin_block(struct vkd3d_glsl_generator *gen) ++{ ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "{\n"); ++ ++gen->indent; ++} ++ + static void shader_glsl_if(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) + { + const char *condition; +@@ -664,23 +678,65 @@ static void shader_glsl_if(struct vkd3d_glsl_generator *gen, const struct vkd3d_ + + glsl_src_cleanup(&src, &gen->string_buffers); + +- shader_glsl_print_indent(gen->buffer, gen->indent); +- vkd3d_string_buffer_printf(gen->buffer, "{\n"); +- ++gen->indent; ++ shader_glsl_begin_block(gen); + } + + static void shader_glsl_else(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) + { +- unsigned int i = 4 * (gen->indent - 1); ++ shader_glsl_end_block(gen); ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "else\n"); ++ shader_glsl_begin_block(gen); ++} + +- vkd3d_string_buffer_printf(gen->buffer, "%*s}\n%*selse\n%*s{\n", i, "", i, "", i, ""); ++static void shader_glsl_loop(struct vkd3d_glsl_generator *gen) ++{ ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "for (;;)\n"); ++ shader_glsl_begin_block(gen); + } + +-static void shader_glsl_endif(struct vkd3d_glsl_generator *gen) ++static void shader_glsl_break(struct vkd3d_glsl_generator *gen) + { +- --gen->indent; + shader_glsl_print_indent(gen->buffer, gen->indent); +- vkd3d_string_buffer_printf(gen->buffer, "}\n"); ++ vkd3d_string_buffer_printf(gen->buffer, "break;\n"); ++} ++ ++static void shader_glsl_continue(struct vkd3d_glsl_generator *gen) ++{ ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "continue;\n"); ++} ++ ++static void shader_glsl_switch(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ struct glsl_src src; ++ ++ glsl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); ++ ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "switch (%s)\n", src.str->buffer); ++ shader_glsl_begin_block(gen); ++ ++ glsl_src_cleanup(&src, &gen->string_buffers); ++} ++ ++static void shader_glsl_case(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ struct glsl_src src; ++ ++ glsl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); ++ ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "case %s:\n", src.str->buffer); ++ ++ glsl_src_cleanup(&src, &gen->string_buffers); ++} ++ ++static void shader_glsl_default(struct vkd3d_glsl_generator *gen) ++{ ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "default:\n"); + } + + static void shader_glsl_ld(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) +@@ -1013,6 +1069,9 @@ static void shader_glsl_shader_prologue(struct vkd3d_glsl_generator *gen) + case VKD3D_SHADER_COMPONENT_UINT: + vkd3d_string_buffer_printf(buffer, " = uintBitsToFloat(shader_in_%u)", i); + break; ++ case VKD3D_SHADER_COMPONENT_INT: ++ vkd3d_string_buffer_printf(buffer, " = intBitsToFloat(shader_in_%u)", i); ++ break; + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled input component type %#x.", e->component_type); +@@ -1127,6 +1186,15 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + case VKD3DSIH_AND: + shader_glsl_binop(gen, ins, "&"); + break; ++ case VKD3DSIH_BREAK: ++ shader_glsl_break(gen); ++ break; ++ case VKD3DSIH_CASE: ++ shader_glsl_case(gen, ins); ++ break; ++ case VKD3DSIH_CONTINUE: ++ shader_glsl_continue(gen); ++ break; + case VKD3DSIH_DCL_INDEXABLE_TEMP: + shader_glsl_dcl_indexable_temp(gen, ins); + break; +@@ -1138,6 +1206,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + case VKD3DSIH_DCL_OUTPUT_SIV: + case VKD3DSIH_NOP: + break; ++ case VKD3DSIH_DEFAULT: ++ shader_glsl_default(gen); ++ break; + case VKD3DSIH_DIV: + shader_glsl_binop(gen, ins, "/"); + break; +@@ -1154,7 +1225,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + shader_glsl_else(gen, ins); + break; + case VKD3DSIH_ENDIF: +- shader_glsl_endif(gen); ++ case VKD3DSIH_ENDLOOP: ++ case VKD3DSIH_ENDSWITCH: ++ shader_glsl_end_block(gen); + break; + case VKD3DSIH_EQO: + case VKD3DSIH_IEQ: +@@ -1184,6 +1257,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + break; + case VKD3DSIH_ILT: + case VKD3DSIH_LTO: ++ case VKD3DSIH_ULT: + shader_glsl_relop(gen, ins, "<", "lessThan"); + break; + case VKD3DSIH_IMAX: +@@ -1220,6 +1294,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + case VKD3DSIH_LOG: + shader_glsl_intrinsic(gen, ins, "log2"); + break; ++ case VKD3DSIH_LOOP: ++ shader_glsl_loop(gen); ++ break; + case VKD3DSIH_MOV: + shader_glsl_mov(gen, ins); + break; +@@ -1259,6 +1336,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + case VKD3DSIH_SQRT: + shader_glsl_intrinsic(gen, ins, "sqrt"); + break; ++ case VKD3DSIH_SWITCH: ++ shader_glsl_switch(gen, ins); ++ break; + default: + shader_glsl_unhandled(gen, ins); + break; +@@ -1663,6 +1743,9 @@ static void shader_glsl_generate_input_declarations(struct vkd3d_glsl_generator + case VKD3D_SHADER_COMPONENT_UINT: + vkd3d_string_buffer_printf(buffer, "uvec4"); + break; ++ case VKD3D_SHADER_COMPONENT_INT: ++ vkd3d_string_buffer_printf(buffer, "ivec4"); ++ break; + case VKD3D_SHADER_COMPONENT_FLOAT: + vkd3d_string_buffer_printf(buffer, "vec4"); + break; +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 14cf23e8d1a..affbae3ea4e 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -6505,6 +6505,30 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx, + return true; + } + ++static void vsir_validate_signature_element(struct validation_context *ctx, ++ const struct shader_signature *signature, const char *signature_type, ++ unsigned int idx) ++{ ++ const struct signature_element *element = &signature->elements[idx]; ++ ++ if (element->register_count == 0) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "element %u of %s signature: Invalid zero register count.", idx, signature_type); ++ ++ if (element->mask == 0 || (element->mask & ~0xf)) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "element %u of %s signature: Invalid mask %#x.", idx, signature_type, element->mask); ++} ++ ++static void vsir_validate_signature(struct validation_context *ctx, ++ const struct shader_signature *signature, const char *signature_type) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < signature->element_count; ++i) ++ vsir_validate_signature_element(ctx, signature, signature_type, i); ++} ++ + static const char *name_from_cf_type(enum vsir_control_flow_type type) + { + switch (type) +@@ -7042,6 +7066,22 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c + if (!(config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)) + return VKD3D_OK; + ++ switch (program->shader_version.type) ++ { ++ case VKD3D_SHADER_TYPE_HULL: ++ case VKD3D_SHADER_TYPE_DOMAIN: ++ break; ++ ++ default: ++ if (program->patch_constant_signature.element_count != 0) ++ validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "Patch constant signature is only valid for hull and domain shaders."); ++ } ++ ++ vsir_validate_signature(&ctx, &program->input_signature, "input"); ++ vsir_validate_signature(&ctx, &program->output_signature, "output"); ++ vsir_validate_signature(&ctx, &program->patch_constant_signature, "patch constant"); ++ + if (!(ctx.temps = vkd3d_calloc(ctx.program->temp_count, sizeof(*ctx.temps)))) + goto fail; + +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index cb610c929b6..692432d5513 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -3267,18 +3267,6 @@ static void spirv_compiler_emit_register_debug_name(struct vkd3d_spirv_builder * + vkd3d_spirv_build_op_name(builder, id, "%s", debug_name); + } + +-static uint32_t spirv_compiler_emit_variable(struct spirv_compiler *compiler, +- struct vkd3d_spirv_stream *stream, SpvStorageClass storage_class, +- enum vkd3d_shader_component_type component_type, unsigned int component_count) +-{ +- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- uint32_t type_id, ptr_type_id; +- +- type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); +- ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); +- return vkd3d_spirv_build_op_variable(builder, stream, ptr_type_id, storage_class, 0); +-} +- + static uint32_t spirv_compiler_emit_array_variable(struct spirv_compiler *compiler, + struct vkd3d_spirv_stream *stream, SpvStorageClass storage_class, + enum vkd3d_shader_component_type component_type, unsigned int component_count, +@@ -3288,10 +3276,6 @@ static uint32_t spirv_compiler_emit_array_variable(struct spirv_compiler *compil + uint32_t type_id, length_id, ptr_type_id; + unsigned int i; + +- if (!length_count) +- return spirv_compiler_emit_variable(compiler, +- stream, storage_class, component_type, component_count); +- + type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); + for (i = 0; i < length_count; ++i) + { +@@ -3305,6 +3289,14 @@ static uint32_t spirv_compiler_emit_array_variable(struct spirv_compiler *compil + return vkd3d_spirv_build_op_variable(builder, stream, ptr_type_id, storage_class, 0); + } + ++static uint32_t spirv_compiler_emit_variable(struct spirv_compiler *compiler, ++ struct vkd3d_spirv_stream *stream, SpvStorageClass storage_class, ++ enum vkd3d_shader_component_type component_type, unsigned int component_count) ++{ ++ return spirv_compiler_emit_array_variable(compiler, stream, storage_class, ++ component_type, component_count, NULL, 0); ++} ++ + static const struct vkd3d_spec_constant_info + { + enum vkd3d_shader_parameter_name name; +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index 75bdb06fe0e..f79e97e92d4 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -2914,6 +2914,21 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con + if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL) + uninvert_used_masks(&program->patch_constant_signature); + ++ switch (program->shader_version.type) ++ { ++ case VKD3D_SHADER_TYPE_HULL: ++ case VKD3D_SHADER_TYPE_DOMAIN: ++ break; ++ ++ default: ++ if (program->patch_constant_signature.element_count != 0) ++ { ++ WARN("The patch constant signature only makes sense for Hull and Domain Shaders, ignoring it.\n"); ++ shader_signature_cleanup(&program->patch_constant_signature); ++ } ++ break; ++ } ++ + if (!shader_sm4_parser_validate_signature(&sm4, &program->input_signature, + sm4.input_register_masks, "Input") + || !shader_sm4_parser_validate_signature(&sm4, &program->output_signature, +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index 9b320106340..f84ac551272 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -1846,6 +1846,8 @@ void shader_signature_cleanup(struct shader_signature *signature) + } + vkd3d_free(signature->elements); + signature->elements = NULL; ++ signature->elements_capacity = 0; ++ signature->element_count = 0; + } + + int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 1a42f385fc0..41b879af4b4 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -245,6 +245,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_ERROR_VSIR_INVALID_GS = 9019, + VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER = 9020, + VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC = 9021, ++ VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE = 9022, + + VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300, + +-- +2.45.2 + diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-e8b14d765dbebae32d83aa5d2a7521932d9.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-e8b14d765dbebae32d83aa5d2a7521932d9.patch deleted file mode 100644 index b61ca4d5..00000000 --- a/patches/vkd3d-latest/0003-Updated-vkd3d-to-e8b14d765dbebae32d83aa5d2a7521932d9.patch +++ /dev/null @@ -1,303 +0,0 @@ -From 3bca6a7e645ca8f48f2ec73a13b63a412cb7f2be Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Wed, 25 Sep 2024 07:29:36 +1000 -Subject: [PATCH] Updated vkd3d to e8b14d765dbebae32d83aa5d2a7521932d9943f9. - ---- - libs/vkd3d/libs/vkd3d-shader/glsl.c | 38 ++++++++++++++++++++ - libs/vkd3d/libs/vkd3d-shader/ir.c | 5 +-- - libs/vkd3d/libs/vkd3d-shader/msl.c | 50 ++++++++++++++++++++++++-- - libs/vkd3d/libs/vkd3d-shader/preproc.l | 2 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 25 ++++--------- - libs/vkd3d/libs/vkd3d/vkd3d_main.c | 1 + - 6 files changed, 96 insertions(+), 25 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index b29f13f2b19..a8cc6d87c40 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/glsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -379,6 +379,9 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( - case VKD3D_DATA_FLOAT: - close = false; - break; -+ case VKD3D_DATA_INT: -+ vkd3d_string_buffer_printf(buffer, "intBitsToFloat("); -+ break; - case VKD3D_DATA_UINT: - vkd3d_string_buffer_printf(buffer, "uintBitsToFloat("); - break; -@@ -457,6 +460,28 @@ static void shader_glsl_relop(struct vkd3d_glsl_generator *gen, - glsl_dst_cleanup(&dst, &gen->string_buffers); - } - -+static void shader_glsl_cast(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins, -+ const char *scalar_constructor, const char *vector_constructor) -+{ -+ unsigned int component_count; -+ struct glsl_src src; -+ struct glsl_dst dst; -+ uint32_t mask; -+ -+ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); -+ glsl_src_init(&src, gen, &ins->src[0], mask); -+ -+ if ((component_count = vsir_write_mask_component_count(mask)) > 1) -+ shader_glsl_print_assignment(gen, &dst, "%s%u(%s)", -+ vector_constructor, component_count, src.str->buffer); -+ else -+ shader_glsl_print_assignment(gen, &dst, "%s(%s)", -+ scalar_constructor, src.str->buffer); -+ -+ glsl_src_cleanup(&src, &gen->string_buffers); -+ glsl_dst_cleanup(&dst, &gen->string_buffers); -+} -+ - static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) - { - struct glsl_src src; -@@ -658,6 +683,12 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_FRC: - shader_glsl_intrinsic(gen, ins, "fract"); - break; -+ case VKD3DSIH_FTOI: -+ shader_glsl_cast(gen, ins, "int", "ivec"); -+ break; -+ case VKD3DSIH_FTOU: -+ shader_glsl_cast(gen, ins, "uint", "uvec"); -+ break; - case VKD3DSIH_GEO: - shader_glsl_relop(gen, ins, ">=", "greaterThanEqual"); - break; -@@ -665,6 +696,10 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_NEU: - shader_glsl_relop(gen, ins, "!=", "notEqual"); - break; -+ case VKD3DSIH_ITOF: -+ case VKD3DSIH_UTOF: -+ shader_glsl_cast(gen, ins, "float", "vec"); -+ break; - case VKD3DSIH_MOV: - shader_glsl_mov(gen, ins); - break; -@@ -680,6 +715,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_RET: - shader_glsl_ret(gen, ins); - break; -+ case VKD3DSIH_ROUND_PI: -+ shader_glsl_intrinsic(gen, ins, "ceil"); -+ break; - default: - shader_glsl_unhandled(gen, ins); - break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index db9992d9715..0bbe13ad7d8 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -1211,12 +1211,13 @@ static bool io_normaliser_is_in_control_point_phase(const struct io_normaliser * - static bool shader_signature_find_element_for_reg(const struct shader_signature *signature, - unsigned int reg_idx, unsigned int write_mask, unsigned int *element_idx) - { -+ const struct signature_element *e; - unsigned int i, base_write_mask; - - for (i = 0; i < signature->element_count; ++i) - { -- struct signature_element *e = &signature->elements[i]; -- if (e->register_index <= reg_idx && e->register_index + e->register_count > reg_idx -+ e = &signature->elements[i]; -+ if (e->register_index <= reg_idx && e->register_count > reg_idx - e->register_index - && (e->mask & write_mask) == write_mask) - { - *element_idx = i; -diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index 7d2e713cddc..6b41363d60e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -55,12 +55,44 @@ static void msl_print_indent(struct vkd3d_string_buffer *buffer, unsigned int in - vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, ""); - } - -+static void msl_print_register_datatype(struct vkd3d_string_buffer *buffer, -+ struct msl_generator *gen, const struct vkd3d_shader_register *reg) -+{ -+ vkd3d_string_buffer_printf(buffer, "."); -+ switch (reg->data_type) -+ { -+ case VKD3D_DATA_FLOAT: -+ vkd3d_string_buffer_printf(buffer, "f"); -+ break; -+ case VKD3D_DATA_INT: -+ vkd3d_string_buffer_printf(buffer, "i"); -+ break; -+ case VKD3D_DATA_UINT: -+ vkd3d_string_buffer_printf(buffer, "u"); -+ break; -+ default: -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled register datatype %#x.", reg->data_type); -+ vkd3d_string_buffer_printf(buffer, "", reg->data_type); -+ break; -+ } -+} -+ - static void msl_print_register_name(struct vkd3d_string_buffer *buffer, - struct msl_generator *gen, const struct vkd3d_shader_register *reg) - { -- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -- "Internal compiler error: Unhandled register type %#x.", reg->type); -- vkd3d_string_buffer_printf(buffer, "", reg->type); -+ switch (reg->type) -+ { -+ case VKD3DSPR_TEMP: -+ vkd3d_string_buffer_printf(buffer, "r[%u]", reg->idx[0].offset); -+ msl_print_register_datatype(buffer, gen, reg); -+ break; -+ default: -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled register type %#x.", reg->type); -+ vkd3d_string_buffer_printf(buffer, "", reg->type); -+ break; -+ } - } - - static void msl_print_swizzle(struct vkd3d_string_buffer *buffer, uint32_t swizzle, uint32_t mask) -@@ -221,9 +253,21 @@ static void msl_generator_generate(struct msl_generator *gen) - - vkd3d_string_buffer_printf(gen->buffer, "/* Generated by %s. */\n\n", vkd3d_shader_get_version(NULL, NULL)); - -+ vkd3d_string_buffer_printf(gen->buffer, "union vkd3d_vec4\n{\n"); -+ vkd3d_string_buffer_printf(gen->buffer, " uint4 u;\n"); -+ vkd3d_string_buffer_printf(gen->buffer, " int4 i;\n"); -+ vkd3d_string_buffer_printf(gen->buffer, " float4 f;\n};\n\n"); -+ - vkd3d_string_buffer_printf(gen->buffer, "void shader_main()\n{\n"); - - ++gen->indent; -+ -+ if (gen->program->temp_count) -+ { -+ msl_print_indent(gen->buffer, gen->indent); -+ vkd3d_string_buffer_printf(gen->buffer, "vkd3d_vec4 r[%u];\n\n", gen->program->temp_count); -+ } -+ - for (i = 0; i < instructions->count; ++i) - { - msl_handle_instruction(gen, &instructions->elements[i]); -diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l -index 7fc963192cf..41c21cca1f5 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/preproc.l -+++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l -@@ -67,7 +67,7 @@ static void update_location(struct preproc_ctx *ctx); - - NEWLINE \r?\n - WS [ \t\r] --IDENTIFIER [A-Za-z_][A-Za-z0-9_]* -+IDENTIFIER (::)?[A-Za-z_]((::)?[A-Za-z0-9_]+)* - INT_SUFFIX [uUlL]{0,2} - - %% -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 1876ad38653..0278a6ca232 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -6354,7 +6354,7 @@ static SpvImageFormat image_format_for_image_read(enum vkd3d_shader_component_ty - static uint32_t spirv_compiler_get_image_type_id(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, const struct vkd3d_shader_register_range *range, - const struct vkd3d_spirv_resource_type *resource_type_info, enum vkd3d_shader_component_type data_type, -- bool raw_structured, uint32_t depth) -+ bool raw_structured) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_descriptor_info1 *d; -@@ -6377,7 +6377,7 @@ static uint32_t spirv_compiler_get_image_type_id(struct spirv_compiler *compiler - - sampled_type_id = vkd3d_spirv_get_type_id(builder, data_type, 1); - return vkd3d_spirv_get_op_type_image(builder, sampled_type_id, resource_type_info->dim, -- depth, resource_type_info->arrayed, resource_type_info->ms, -+ 2, resource_type_info->arrayed, resource_type_info->ms, - reg->type == VKD3DSPR_UAV ? 2 : 1, format); - } - -@@ -6392,18 +6392,14 @@ static void spirv_compiler_emit_combined_sampler_declarations(struct spirv_compi - const struct vkd3d_shader_combined_resource_sampler *current; - uint32_t image_type_id, type_id, ptr_type_id, var_id; - enum vkd3d_shader_binding_flag resource_type_flag; -- const struct vkd3d_shader_descriptor_info1 *d; - struct vkd3d_symbol symbol; - unsigned int i; -- bool depth; - - resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER - ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE; - - for (i = 0; i < shader_interface->combined_sampler_count; ++i) - { -- struct vkd3d_shader_register_range sampler_range; -- - current = &shader_interface->combined_samplers[i]; - - if (current->resource_space != resource_range->space || current->resource_index != resource_range->first) -@@ -6425,16 +6421,8 @@ static void spirv_compiler_emit_combined_sampler_declarations(struct spirv_compi - current->sampler_space, current->binding.count); - } - -- sampler_range.space = current->sampler_space; -- sampler_range.first = current->sampler_index; -- sampler_range.last = current->sampler_index; -- d = spirv_compiler_get_descriptor_info(compiler, -- VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, &sampler_range); -- depth = current->sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX -- && (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE); -- - image_type_id = spirv_compiler_get_image_type_id(compiler, resource, resource_range, -- resource_type_info, sampled_type, structure_stride || raw, depth); -+ resource_type_info, sampled_type, structure_stride || raw); - type_id = vkd3d_spirv_get_op_type_sampled_image(builder, image_type_id); - - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); -@@ -6528,7 +6516,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp - else - { - type_id = spirv_compiler_get_image_type_id(compiler, ®, range, -- resource_type_info, sampled_type, structure_stride || raw, 0); -+ resource_type_info, sampled_type, structure_stride || raw); - } - - var_id = spirv_compiler_build_descriptor_variable(compiler, storage_class, -@@ -8440,11 +8428,10 @@ static void spirv_compiler_prepare_image(struct spirv_compiler *compiler, - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t sampler_var_id, sampler_id, sampled_image_type_id; - const struct vkd3d_symbol *symbol = NULL; -- bool load, sampled, depth_comparison; -+ bool load, sampled; - - load = !(flags & VKD3D_IMAGE_FLAG_NO_LOAD); - sampled = flags & VKD3D_IMAGE_FLAG_SAMPLED; -- depth_comparison = flags & VKD3D_IMAGE_FLAG_DEPTH; - - if (resource_reg->type == VKD3DSPR_RESOURCE) - symbol = spirv_compiler_find_combined_sampler(compiler, resource_reg, sampler_reg); -@@ -8498,7 +8485,7 @@ static void spirv_compiler_prepare_image(struct spirv_compiler *compiler, - - image->image_type_id = spirv_compiler_get_image_type_id(compiler, resource_reg, - &symbol->info.resource.range, image->resource_type_info, -- image->sampled_type, image->structure_stride || image->raw, depth_comparison); -+ image->sampled_type, image->structure_stride || image->raw); - - if (sampled) - { -diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_main.c b/libs/vkd3d/libs/vkd3d/vkd3d_main.c -index 9eccec111c7..5215cf8ef86 100644 ---- a/libs/vkd3d/libs/vkd3d/vkd3d_main.c -+++ b/libs/vkd3d/libs/vkd3d/vkd3d_main.c -@@ -415,6 +415,7 @@ HRESULT vkd3d_create_versioned_root_signature_deserializer(const void *data, SIZ - if (FAILED(hr = d3d12_versioned_root_signature_deserializer_init(object, &dxbc))) - { - vkd3d_free(object); -+ *deserializer = NULL; - return hr; - } - --- -2.45.2 - diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-cd249a47b86545fe0b3a4b477f854965e85.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-cd249a47b86545fe0b3a4b477f854965e85.patch new file mode 100644 index 00000000..717e8475 --- /dev/null +++ b/patches/vkd3d-latest/0004-Updated-vkd3d-to-cd249a47b86545fe0b3a4b477f854965e85.patch @@ -0,0 +1,1533 @@ +From 67023ff9d755c33d6d2a21fdaf3647a44871c830 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Fri, 11 Oct 2024 07:30:59 +1100 +Subject: [PATCH] Updated vkd3d to cd249a47b86545fe0b3a4b477f854965e858b744. + +--- + libs/vkd3d/include/vkd3d_shader.h | 52 +++ + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 26 +- + libs/vkd3d/libs/vkd3d-shader/glsl.c | 297 +++++++++++++-- + libs/vkd3d/libs/vkd3d-shader/ir.c | 349 ++++++++++++++++-- + libs/vkd3d/libs/vkd3d-shader/msl.c | 226 +++++++++++- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 35 +- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 5 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 11 + + 8 files changed, 921 insertions(+), 80 deletions(-) + +diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h +index d08ee74a3a0..e22f236ecd1 100644 +--- a/libs/vkd3d/include/vkd3d_shader.h ++++ b/libs/vkd3d/include/vkd3d_shader.h +@@ -648,6 +648,58 @@ enum vkd3d_shader_parameter_name + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_5, + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_6, + VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_7, ++ /** ++ * Point size. ++ * ++ * When this parameter is provided to a vertex, tessellation, or geometry ++ * shader, and the source shader does not write point size, it specifies a ++ * uniform value which will be written to point size. ++ * If the source shader writes point size, this parameter is ignored. ++ * ++ * This parameter can be used to implement fixed function point size, as ++ * present in Direct3D versions 8 and 9, if the target environment does not ++ * support point size as part of its own fixed-function API (as Vulkan and ++ * core OpenGL). ++ * ++ * The data type for this parameter must be ++ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32. ++ * ++ * \since 1.14 ++ */ ++ VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE, ++ /** ++ * Minimum point size. ++ * ++ * When this parameter is provided to a vertex, tessellation, or geometry ++ * shader, and the source shader writes point size or uses the ++ * VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE parameter, the point size will ++ * be clamped to the provided minimum value. ++ * If point size is not written in one of these ways, ++ * this parameter is ignored. ++ * If this parameter is not provided, the point size will not be clamped ++ * to a minimum size by vkd3d-shader. ++ * ++ * This parameter can be used to implement fixed function point size, as ++ * present in Direct3D versions 8 and 9, if the target environment does not ++ * support point size as part of its own fixed-function API (as Vulkan and ++ * core OpenGL). ++ * ++ * The data type for this parameter must be ++ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32. ++ * ++ * \since 1.14 ++ */ ++ VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN, ++ /** ++ * Maximum point size. ++ * ++ * This parameter has identical behaviour to ++ * VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN, except that it provides ++ * the maximum size rather than the minimum. ++ * ++ * \since 1.14 ++ */ ++ VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME), + }; +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index 589b800f8c9..44b1714b56b 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -110,13 +110,6 @@ enum vkd3d_sm1_misc_register + VKD3D_SM1_MISC_FACE = 0x1, + }; + +-enum vkd3d_sm1_rastout_register +-{ +- VKD3D_SM1_RASTOUT_POSITION = 0x0, +- VKD3D_SM1_RASTOUT_FOG = 0x1, +- VKD3D_SM1_RASTOUT_POINT_SIZE = 0x2, +-}; +- + enum vkd3d_sm1_opcode + { + VKD3D_SM1_OP_NOP = 0x00, +@@ -957,6 +950,9 @@ static void shader_sm1_read_dst_param(struct vkd3d_shader_sm1_parser *sm1, const + shader_sm1_parse_src_param(addr_token, NULL, dst_rel_addr); + } + shader_sm1_parse_dst_param(token, dst_rel_addr, dst_param); ++ ++ if (dst_param->reg.type == VKD3DSPR_RASTOUT && dst_param->reg.idx[0].offset == VSIR_RASTOUT_POINT_SIZE) ++ sm1->p.program->has_point_size = true; + } + + static void shader_sm1_read_semantic(struct vkd3d_shader_sm1_parser *sm1, +@@ -1434,17 +1430,17 @@ bool hlsl_sm1_register_from_semantic(const struct vkd3d_shader_version *version, + {"vpos", false, VKD3D_SHADER_TYPE_PIXEL, 3, VKD3DSPR_MISCTYPE, VKD3D_SM1_MISC_POSITION}, + + {"color", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_ATTROUT}, +- {"fog", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_FOG}, +- {"position", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POSITION}, +- {"psize", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POINT_SIZE}, +- {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POSITION}, ++ {"fog", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VSIR_RASTOUT_FOG}, ++ {"position", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POSITION}, ++ {"psize", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POINT_SIZE}, ++ {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POSITION}, + {"texcoord", true, VKD3D_SHADER_TYPE_VERTEX, 1, VKD3DSPR_TEXCRDOUT}, + + {"color", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_ATTROUT}, +- {"fog", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_FOG}, +- {"position", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POSITION}, +- {"psize", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POINT_SIZE}, +- {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VKD3D_SM1_RASTOUT_POSITION}, ++ {"fog", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VSIR_RASTOUT_FOG}, ++ {"position", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POSITION}, ++ {"psize", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POINT_SIZE}, ++ {"sv_position", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_RASTOUT, VSIR_RASTOUT_POSITION}, + {"texcoord", true, VKD3D_SHADER_TYPE_VERTEX, 2, VKD3DSPR_TEXCRDOUT}, + }; + +diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c +index 91ee355ed39..c8efdae3386 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c +@@ -22,7 +22,7 @@ struct glsl_resource_type_info + { + size_t coord_size; + bool shadow; +- const char *sampler_type; ++ const char *type_suffix; + }; + + struct glsl_src +@@ -102,17 +102,17 @@ static const struct glsl_resource_type_info *shader_glsl_get_resource_type_info( + { + static const struct glsl_resource_type_info info[] = + { +- {0, 0, "samplerNone"}, /* VKD3D_SHADER_RESOURCE_NONE */ +- {1, 0, "samplerBuffer"}, /* VKD3D_SHADER_RESOURCE_BUFFER */ +- {1, 1, "sampler1D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1D */ +- {2, 1, "sampler2D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2D */ +- {2, 0, "sampler2DMS"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMS */ +- {3, 0, "sampler3D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_3D */ +- {3, 1, "samplerCube"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBE */ +- {2, 1, "sampler1DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY */ +- {3, 1, "sampler2DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY */ +- {3, 0, "sampler2DMSArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY */ +- {4, 1, "samplerCubeArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY */ ++ {0, 0, "None"}, /* VKD3D_SHADER_RESOURCE_NONE */ ++ {1, 0, "Buffer"}, /* VKD3D_SHADER_RESOURCE_BUFFER */ ++ {1, 1, "1D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1D */ ++ {2, 1, "2D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2D */ ++ {2, 0, "2DMS"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMS */ ++ {3, 0, "3D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_3D */ ++ {3, 1, "Cube"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBE */ ++ {2, 1, "1DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY */ ++ {3, 1, "2DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY */ ++ {3, 0, "2DMSArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY */ ++ {4, 1, "CubeArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY */ + }; + + if (!t || t >= ARRAY_SIZE(info)) +@@ -173,6 +173,14 @@ static void shader_glsl_print_combined_sampler_name(struct vkd3d_string_buffer * + } + } + ++static void shader_glsl_print_image_name(struct vkd3d_string_buffer *buffer, ++ struct vkd3d_glsl_generator *gen, unsigned int idx, unsigned int space) ++{ ++ vkd3d_string_buffer_printf(buffer, "%s_image_%u", gen->prefix, idx); ++ if (space) ++ vkd3d_string_buffer_printf(buffer, "_%u", space); ++} ++ + static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, + struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_register *reg) + { +@@ -363,15 +371,14 @@ static void shader_glsl_print_bitcast(struct vkd3d_string_buffer *dst, struct vk + vkd3d_string_buffer_printf(dst, "%s", src); + } + +-static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator *gen, +- const struct vkd3d_shader_src_param *vsir_src, uint32_t mask) ++static void shader_glsl_print_src(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, ++ const struct vkd3d_shader_src_param *vsir_src, uint32_t mask, enum vkd3d_data_type data_type) + { + const struct vkd3d_shader_register *reg = &vsir_src->reg; + struct vkd3d_string_buffer *register_name, *str; + enum vkd3d_data_type src_data_type; + unsigned int size; + +- glsl_src->str = vkd3d_string_buffer_get(&gen->string_buffers); + register_name = vkd3d_string_buffer_get(&gen->string_buffers); + + if (reg->non_uniform) +@@ -386,12 +393,12 @@ static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator + shader_glsl_print_register_name(register_name, gen, reg); + + if (!vsir_src->modifiers) +- str = glsl_src->str; ++ str = buffer; + else + str = vkd3d_string_buffer_get(&gen->string_buffers); + + size = reg->dimension == VSIR_DIMENSION_VEC4 ? 4 : 1; +- shader_glsl_print_bitcast(str, gen, register_name->buffer, reg->data_type, src_data_type, size); ++ shader_glsl_print_bitcast(str, gen, register_name->buffer, data_type, src_data_type, size); + if (reg->dimension == VSIR_DIMENSION_VEC4) + shader_glsl_print_swizzle(str, vsir_src->swizzle, mask); + +@@ -400,24 +407,31 @@ static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator + case VKD3DSPSM_NONE: + break; + case VKD3DSPSM_NEG: +- vkd3d_string_buffer_printf(glsl_src->str, "-%s", str->buffer); ++ vkd3d_string_buffer_printf(buffer, "-%s", str->buffer); + break; + case VKD3DSPSM_ABS: +- vkd3d_string_buffer_printf(glsl_src->str, "abs(%s)", str->buffer); ++ vkd3d_string_buffer_printf(buffer, "abs(%s)", str->buffer); + break; + default: +- vkd3d_string_buffer_printf(glsl_src->str, "(%s)", ++ vkd3d_string_buffer_printf(buffer, "(%s)", + vsir_src->modifiers, str->buffer); + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled source modifier(s) %#x.", vsir_src->modifiers); + break; + } + +- if (str != glsl_src->str) ++ if (str != buffer) + vkd3d_string_buffer_release(&gen->string_buffers, str); + vkd3d_string_buffer_release(&gen->string_buffers, register_name); + } + ++static void glsl_src_init(struct glsl_src *glsl_src, struct vkd3d_glsl_generator *gen, ++ const struct vkd3d_shader_src_param *vsir_src, uint32_t mask) ++{ ++ glsl_src->str = vkd3d_string_buffer_get(&gen->string_buffers); ++ shader_glsl_print_src(glsl_src->str, gen, vsir_src, mask, vsir_src->reg.data_type); ++} ++ + static void glsl_dst_cleanup(struct glsl_dst *dst, struct vkd3d_string_buffer_cache *cache) + { + vkd3d_string_buffer_release(cache, dst->mask); +@@ -892,6 +906,85 @@ static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vk + glsl_dst_cleanup(&dst, &gen->string_buffers); + } + ++static void shader_glsl_store_uav_typed(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ const struct glsl_resource_type_info *resource_type_info; ++ enum vkd3d_shader_component_type component_type; ++ const struct vkd3d_shader_descriptor_info1 *d; ++ enum vkd3d_shader_resource_type resource_type; ++ unsigned int uav_id, uav_idx, uav_space; ++ struct vkd3d_string_buffer *image_data; ++ struct glsl_src image_coord; ++ uint32_t coord_mask; ++ ++ if (ins->dst[0].reg.idx[0].rel_addr || ins->dst[0].reg.idx[1].rel_addr) ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, ++ "Descriptor indexing is not supported."); ++ ++ uav_id = ins->dst[0].reg.idx[0].offset; ++ uav_idx = ins->dst[0].reg.idx[1].offset; ++ if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, uav_id))) ++ { ++ resource_type = d->resource_type; ++ uav_space = d->register_space; ++ component_type = vkd3d_component_type_from_resource_data_type(d->resource_data_type); ++ } ++ else ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Undeclared UAV descriptor %u.", uav_id); ++ uav_space = 0; ++ resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; ++ component_type = VKD3D_SHADER_COMPONENT_FLOAT; ++ } ++ ++ if ((resource_type_info = shader_glsl_get_resource_type_info(resource_type))) ++ { ++ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); ++ } ++ else ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled UAV type %#x.", resource_type); ++ coord_mask = vkd3d_write_mask_from_component_count(2); ++ } ++ ++ glsl_src_init(&image_coord, gen, &ins->src[0], coord_mask); ++ image_data = vkd3d_string_buffer_get(&gen->string_buffers); ++ ++ if (ins->src[1].reg.dimension == VSIR_DIMENSION_SCALAR) ++ { ++ switch (component_type) ++ { ++ case VKD3D_SHADER_COMPONENT_UINT: ++ vkd3d_string_buffer_printf(image_data, "uvec4("); ++ break; ++ case VKD3D_SHADER_COMPONENT_INT: ++ vkd3d_string_buffer_printf(image_data, "ivec4("); ++ break; ++ default: ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled component type %#x.", component_type); ++ /* fall through */ ++ case VKD3D_SHADER_COMPONENT_FLOAT: ++ vkd3d_string_buffer_printf(image_data, "vec4("); ++ break; ++ } ++ } ++ shader_glsl_print_src(image_data, gen, &ins->src[1], VKD3DSP_WRITEMASK_ALL, ++ vkd3d_data_type_from_component_type(component_type)); ++ if (ins->src[1].reg.dimension == VSIR_DIMENSION_SCALAR) ++ vkd3d_string_buffer_printf(image_data, ", 0, 0, 0)"); ++ ++ shader_glsl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "imageStore("); ++ shader_glsl_print_image_name(gen->buffer, gen, uav_idx, uav_space); ++ vkd3d_string_buffer_printf(gen->buffer, ", %s, %s);\n", image_coord.str->buffer, image_data->buffer); ++ ++ vkd3d_string_buffer_release(&gen->string_buffers, image_data); ++ glsl_src_cleanup(&image_coord, &gen->string_buffers); ++} ++ + static void shader_glsl_unary_op(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_instruction *ins, const char *op) + { +@@ -1336,6 +1429,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, + case VKD3DSIH_SQRT: + shader_glsl_intrinsic(gen, ins, "sqrt"); + break; ++ case VKD3DSIH_STORE_UAV_TYPED: ++ shader_glsl_store_uav_typed(gen, ins); ++ break; + case VKD3DSIH_SWITCH: + shader_glsl_switch(gen, ins); + break; +@@ -1372,6 +1468,137 @@ static bool shader_glsl_check_shader_visibility(const struct vkd3d_glsl_generato + } + } + ++static bool shader_glsl_get_uav_binding(const struct vkd3d_glsl_generator *gen, unsigned int register_space, ++ unsigned int register_idx, enum vkd3d_shader_resource_type resource_type, unsigned int *binding_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 false; ++ ++ 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 (!shader_glsl_check_shader_visibility(gen, binding->shader_visibility)) ++ continue; ++ if (!(binding->flags & resource_type_flag)) ++ continue; ++ *binding_idx = i; ++ return true; ++ } ++ ++ return false; ++} ++ ++static void shader_glsl_generate_uav_declaration(struct vkd3d_glsl_generator *gen, ++ const struct vkd3d_shader_descriptor_info1 *uav) ++{ ++ const struct glsl_resource_type_info *resource_type_info; ++ const char *image_type_prefix, *image_type, *read_format; ++ const struct vkd3d_shader_descriptor_binding *binding; ++ const struct vkd3d_shader_descriptor_offset *offset; ++ struct vkd3d_string_buffer *buffer = gen->buffer; ++ enum vkd3d_shader_component_type component_type; ++ unsigned int binding_idx; ++ ++ if (uav->count != 1) ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, ++ "UAV %u has unsupported descriptor array size %u.", uav->register_id, uav->count); ++ return; ++ } ++ ++ if (!shader_glsl_get_uav_binding(gen, uav->register_space, ++ uav->register_index, uav->resource_type, &binding_idx)) ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, ++ "No descriptor binding specified for UAV %u.", uav->register_id); ++ return; ++ } ++ ++ binding = &gen->interface_info->bindings[binding_idx].binding; ++ ++ if (binding->set != 0) ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, ++ "Unsupported binding set %u specified for UAV %u.", binding->set, uav->register_id); ++ return; ++ } ++ ++ if (binding->count != 1) ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, ++ "Unsupported binding count %u specified for UAV %u.", binding->count, uav->register_id); ++ return; ++ } ++ ++ if (gen->offset_info && gen->offset_info->binding_offsets) ++ { ++ offset = &gen->offset_info->binding_offsets[binding_idx]; ++ if (offset->static_offset || offset->dynamic_offset_index != ~0u) ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled descriptor offset specified for UAV %u.", ++ uav->register_id); ++ return; ++ } ++ } ++ ++ if ((resource_type_info = shader_glsl_get_resource_type_info(uav->resource_type))) ++ { ++ image_type = resource_type_info->type_suffix; ++ } ++ else ++ { ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled UAV type %#x.", uav->resource_type); ++ image_type = ""; ++ } ++ ++ switch ((component_type = vkd3d_component_type_from_resource_data_type(uav->resource_data_type))) ++ { ++ case VKD3D_SHADER_COMPONENT_UINT: ++ image_type_prefix = "u"; ++ read_format = "r32ui"; ++ break; ++ case VKD3D_SHADER_COMPONENT_INT: ++ image_type_prefix = "i"; ++ read_format = "r32i"; ++ break; ++ default: ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, ++ "Internal compiler error: Unhandled component type %#x for UAV %u.", ++ component_type, uav->register_id); ++ /* fall through */ ++ case VKD3D_SHADER_COMPONENT_FLOAT: ++ image_type_prefix = ""; ++ read_format = "r32f"; ++ break; ++ } ++ ++ vkd3d_string_buffer_printf(buffer, "layout(binding = %u", binding->binding); ++ if (uav->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ) ++ vkd3d_string_buffer_printf(buffer, ", %s) ", read_format); ++ else ++ vkd3d_string_buffer_printf(buffer, ") writeonly "); ++ vkd3d_string_buffer_printf(buffer, "uniform %simage%s ", image_type_prefix, image_type); ++ shader_glsl_print_image_name(buffer, gen, uav->register_index, uav->register_space); ++ vkd3d_string_buffer_printf(buffer, ";\n"); ++} ++ + static bool shader_glsl_get_cbv_binding(const struct vkd3d_glsl_generator *gen, + unsigned int register_space, unsigned int register_idx, unsigned int *binding_idx) + { +@@ -1415,7 +1642,7 @@ static void shader_glsl_generate_cbv_declaration(struct vkd3d_glsl_generator *ge + + if (cbv->count != 1) + { +- vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, ++ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, + "Constant buffer %u has unsupported descriptor array size %u.", cbv->register_id, cbv->count); + return; + } +@@ -1540,7 +1767,7 @@ static void shader_glsl_generate_sampler_declaration(struct vkd3d_glsl_generator + + if ((resource_type_info = shader_glsl_get_resource_type_info(srv->resource_type))) + { +- sampler_type = resource_type_info->sampler_type; ++ sampler_type = resource_type_info->type_suffix; + if (shadow && !resource_type_info->shadow) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, + "Comparison samplers are not supported with resource type %#x.", srv->resource_type); +@@ -1603,7 +1830,7 @@ static void shader_glsl_generate_sampler_declaration(struct vkd3d_glsl_generator + return; + } + +- vkd3d_string_buffer_printf(buffer, "layout(binding = %u) uniform %s%s%s ", ++ vkd3d_string_buffer_printf(buffer, "layout(binding = %u) uniform %ssampler%s%s ", + binding->binding, sampler_type_prefix, sampler_type, shadow ? "Shadow" : ""); + shader_glsl_print_combined_sampler_name(buffer, gen, crs->resource_index, + crs->resource_space, crs->sampler_index, crs->sampler_space); +@@ -1628,6 +1855,10 @@ static void shader_glsl_generate_descriptor_declarations(struct vkd3d_glsl_gener + /* GLSL uses combined resource/sampler descriptors.*/ + break; + ++ case VKD3D_SHADER_DESCRIPTOR_TYPE_UAV: ++ shader_glsl_generate_uav_declaration(gen, descriptor); ++ break; ++ + case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV: + shader_glsl_generate_cbv_declaration(gen, descriptor); + break; +@@ -1820,7 +2051,7 @@ static void shader_glsl_generate_output_declarations(struct vkd3d_glsl_generator + "Internal compiler error: Unhandled output component type %#x.", e->component_type); + break; + } +- vkd3d_string_buffer_printf(buffer, " shader_out_%u;\n", i); ++ vkd3d_string_buffer_printf(buffer, " shader_out_%u;\n", e->semantic_index); + ++count; + } + if (count) +@@ -1837,6 +2068,14 @@ static void shader_glsl_generate_declarations(struct vkd3d_glsl_generator *gen) + { + const struct vsir_program *program = gen->program; + struct vkd3d_string_buffer *buffer = gen->buffer; ++ const struct vsir_thread_group_size *group_size; ++ ++ if (program->shader_version.type == VKD3D_SHADER_TYPE_COMPUTE) ++ { ++ group_size = &program->thread_group_size; ++ vkd3d_string_buffer_printf(buffer, "layout(local_size_x = %u, local_size_y = %u, local_size_z = %u) in;\n\n", ++ group_size->x, group_size->y, group_size->z); ++ } + + shader_glsl_generate_descriptor_declarations(gen); + shader_glsl_generate_input_declarations(gen); +@@ -1918,6 +2157,10 @@ static void shader_glsl_init_limits(struct vkd3d_glsl_generator *gen, const stru + limits->input_count = 32; + limits->output_count = 8; + break; ++ case VKD3D_SHADER_TYPE_COMPUTE: ++ limits->input_count = 0; ++ limits->output_count = 0; ++ break; + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled shader type %#x.", version->type); +@@ -1948,8 +2191,8 @@ static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen, + gen->prefix = "unknown"; + } + shader_glsl_init_limits(gen, &program->shader_version); +- gen->interstage_input = type != VKD3D_SHADER_TYPE_VERTEX; +- gen->interstage_output = type != VKD3D_SHADER_TYPE_PIXEL; ++ gen->interstage_input = type != VKD3D_SHADER_TYPE_VERTEX && type != VKD3D_SHADER_TYPE_COMPUTE; ++ gen->interstage_output = type != VKD3D_SHADER_TYPE_PIXEL && type != VKD3D_SHADER_TYPE_COMPUTE; + + gen->interface_info = vkd3d_find_struct(compile_info->next, INTERFACE_INFO); + gen->offset_info = vkd3d_find_struct(compile_info->next, DESCRIPTOR_OFFSET_INFO); +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index affbae3ea4e..9d24126fba8 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -203,6 +203,12 @@ static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned + src->reg.idx[0].offset = idx; + } + ++static void src_param_init_ssa_float(struct vkd3d_shader_src_param *src, unsigned int idx) ++{ ++ vsir_src_param_init(src, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1); ++ src->reg.idx[0].offset = idx; ++} ++ + static void src_param_init_temp_bool(struct vkd3d_shader_src_param *src, unsigned int idx) + { + vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_BOOL, 1); +@@ -244,6 +250,12 @@ static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned + dst->reg.idx[0].offset = idx; + } + ++static void dst_param_init_ssa_float(struct vkd3d_shader_dst_param *dst, unsigned int idx) ++{ ++ vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1); ++ dst->reg.idx[0].offset = idx; ++} ++ + static void dst_param_init_temp_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) + { + vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_BOOL, 1); +@@ -254,7 +266,6 @@ static void dst_param_init_temp_uint(struct vkd3d_shader_dst_param *dst, unsigne + { + vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); + dst->reg.idx[0].offset = idx; +- dst->write_mask = VKD3DSP_WRITEMASK_0; + } + + void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, +@@ -682,6 +693,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr + case VKD3DSIH_DCL_SAMPLER: + case VKD3DSIH_DCL_TEMPS: + case VKD3DSIH_DCL_THREAD_GROUP: ++ case VKD3DSIH_DCL_UAV_TYPED: + vkd3d_shader_instruction_make_nop(ins); + break; + +@@ -1221,7 +1233,7 @@ static bool shader_signature_find_element_for_reg(const struct shader_signature + unsigned int reg_idx, unsigned int write_mask, unsigned int *element_idx) + { + const struct signature_element *e; +- unsigned int i, base_write_mask; ++ unsigned int i; + + for (i = 0; i < signature->element_count; ++i) + { +@@ -1234,14 +1246,6 @@ static bool shader_signature_find_element_for_reg(const struct shader_signature + } + } + +- /* Validated in the TPF reader, but failure in signature_element_range_expand_mask() +- * can land us here on an unmatched vector mask. */ +- FIXME("Failed to find signature element for register index %u, mask %#x; using scalar mask.\n", +- reg_idx, write_mask); +- base_write_mask = 1u << vsir_write_mask_get_component_idx(write_mask); +- if (base_write_mask != write_mask) +- return shader_signature_find_element_for_reg(signature, reg_idx, base_write_mask, element_idx); +- + return false; + } + +@@ -1655,6 +1659,9 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par + break; + + case VKD3DSPR_RASTOUT: ++ /* Leave point size as a system value for the backends to consume. */ ++ if (reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE) ++ return true; + reg_idx = SM1_RASTOUT_REGISTER_OFFSET + reg->idx[0].offset; + signature = normaliser->output_signature; + reg->type = VKD3DSPR_OUTPUT; +@@ -5777,11 +5784,12 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog + return VKD3D_OK; + } + +-static bool find_position_signature_idx(const struct shader_signature *signature, uint32_t *idx) ++static bool find_sysval_signature_idx(const struct shader_signature *signature, ++ enum vkd3d_shader_sysval_semantic sysval, uint32_t *idx) + { + for (unsigned int i = 0; i < signature->element_count; ++i) + { +- if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_POSITION) ++ if (signature->elements[i].sysval_semantic == sysval) + { + *idx = i; + return true; +@@ -5846,7 +5854,7 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr + } + } + +- if (!find_position_signature_idx(signature, &position_signature_idx)) ++ if (!find_sysval_signature_idx(signature, VKD3D_SHADER_SV_POSITION, &position_signature_idx)) + { + vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC, + "Shader does not write position."); +@@ -5923,6 +5931,191 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr + return VKD3D_OK; + } + ++static enum vkd3d_result insert_point_size_before_ret(struct vsir_program *program, ++ const struct vkd3d_shader_instruction *ret, size_t *ret_pos) ++{ ++ struct vkd3d_shader_instruction_array *instructions = &program->instructions; ++ size_t pos = ret - instructions->elements; ++ struct vkd3d_shader_instruction *ins; ++ ++ if (!shader_instruction_array_insert_at(&program->instructions, pos, 1)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ ins = &program->instructions.elements[pos]; ++ ++ vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_MOV, 1, 1); ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); ++ ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; ++ src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE, VKD3D_DATA_FLOAT); ++ ++ *ret_pos = pos + 1; ++ return VKD3D_OK; ++} ++ ++static enum vkd3d_result vsir_program_insert_point_size(struct vsir_program *program, ++ struct vsir_transformation_context *ctx) ++{ ++ const struct vkd3d_shader_parameter1 *size_parameter = NULL; ++ static const struct vkd3d_shader_location no_loc; ++ ++ if (program->has_point_size) ++ return VKD3D_OK; ++ ++ if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX ++ && program->shader_version.type != VKD3D_SHADER_TYPE_GEOMETRY ++ && program->shader_version.type != VKD3D_SHADER_TYPE_HULL ++ && program->shader_version.type != VKD3D_SHADER_TYPE_DOMAIN) ++ return VKD3D_OK; ++ ++ for (unsigned int i = 0; i < program->parameter_count; ++i) ++ { ++ const struct vkd3d_shader_parameter1 *parameter = &program->parameters[i]; ++ ++ if (parameter->name == VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE) ++ size_parameter = parameter; ++ } ++ ++ if (!size_parameter) ++ return VKD3D_OK; ++ ++ if (size_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32) ++ { ++ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid point size parameter data type %#x.", size_parameter->data_type); ++ return VKD3D_ERROR_INVALID_ARGUMENT; ++ } ++ ++ program->has_point_size = true; ++ ++ /* Append a point size write before each ret. */ ++ for (size_t i = 0; i < program->instructions.count; ++i) ++ { ++ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; ++ ++ if (ins->opcode == VKD3DSIH_RET) ++ { ++ size_t new_pos; ++ int ret; ++ ++ if ((ret = insert_point_size_before_ret(program, ins, &new_pos)) < 0) ++ return ret; ++ i = new_pos; ++ } ++ } ++ ++ return VKD3D_OK; ++} ++ ++static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_program *program, ++ struct vsir_transformation_context *ctx) ++{ ++ const struct vkd3d_shader_parameter1 *min_parameter = NULL, *max_parameter = NULL; ++ static const struct vkd3d_shader_location no_loc; ++ ++ if (!program->has_point_size) ++ return VKD3D_OK; ++ ++ if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX ++ && program->shader_version.type != VKD3D_SHADER_TYPE_GEOMETRY ++ && program->shader_version.type != VKD3D_SHADER_TYPE_HULL ++ && program->shader_version.type != VKD3D_SHADER_TYPE_DOMAIN) ++ return VKD3D_OK; ++ ++ for (unsigned int i = 0; i < program->parameter_count; ++i) ++ { ++ const struct vkd3d_shader_parameter1 *parameter = &program->parameters[i]; ++ ++ if (parameter->name == VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN) ++ min_parameter = parameter; ++ else if (parameter->name == VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX) ++ max_parameter = parameter; ++ } ++ ++ if (!min_parameter && !max_parameter) ++ return VKD3D_OK; ++ ++ if (min_parameter && min_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32) ++ { ++ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid minimum point size parameter data type %#x.", min_parameter->data_type); ++ return VKD3D_ERROR_INVALID_ARGUMENT; ++ } ++ ++ if (max_parameter && max_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32) ++ { ++ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid maximum point size parameter data type %#x.", max_parameter->data_type); ++ return VKD3D_ERROR_INVALID_ARGUMENT; ++ } ++ ++ /* Replace writes to the point size by inserting a clamp before each write. */ ++ ++ for (size_t i = 0; i < program->instructions.count; ++i) ++ { ++ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; ++ const struct vkd3d_shader_location *loc; ++ unsigned int ssa_value; ++ bool clamp = false; ++ ++ if (vsir_instruction_is_dcl(ins)) ++ continue; ++ ++ for (size_t j = 0; j < ins->dst_count; ++j) ++ { ++ struct vkd3d_shader_dst_param *dst = &ins->dst[j]; ++ ++ /* Note we run after I/O normalization. */ ++ if (dst->reg.type == VKD3DSPR_RASTOUT) ++ { ++ dst_param_init_ssa_float(dst, program->ssa_count); ++ ssa_value = program->ssa_count++; ++ clamp = true; ++ } ++ } ++ ++ if (!clamp) ++ continue; ++ ++ if (!shader_instruction_array_insert_at(&program->instructions, i + 1, !!min_parameter + !!max_parameter)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ loc = &program->instructions.elements[i].location; ++ ins = &program->instructions.elements[i + 1]; ++ ++ if (min_parameter) ++ { ++ vsir_instruction_init_with_params(program, ins, loc, VKD3DSIH_MAX, 1, 2); ++ src_param_init_ssa_float(&ins->src[0], ssa_value); ++ src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN, VKD3D_DATA_FLOAT); ++ if (max_parameter) ++ { ++ dst_param_init_ssa_float(&ins->dst[0], program->ssa_count); ++ ssa_value = program->ssa_count++; ++ } ++ else ++ { ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); ++ ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; ++ } ++ ++ins; ++ ++i; ++ } ++ ++ if (max_parameter) ++ { ++ vsir_instruction_init_with_params(program, ins, loc, VKD3DSIH_MIN, 1, 2); ++ src_param_init_ssa_float(&ins->src[0], ssa_value); ++ src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX, VKD3D_DATA_FLOAT); ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); ++ ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; ++ ++ ++i; ++ } ++ } ++ ++ return VKD3D_OK; ++} ++ + struct validation_context + { + struct vkd3d_shader_message_context *message_context; +@@ -6395,23 +6588,18 @@ static void vsir_validate_dst_param(struct validation_context *ctx, + break; + + case VKD3DSPR_IMMCONST: +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, +- "Invalid IMMCONST register used as destination parameter."); +- break; +- + case VKD3DSPR_IMMCONST64: +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, +- "Invalid IMMCONST64 register used as destination parameter."); +- break; +- + case VKD3DSPR_SAMPLER: ++ case VKD3DSPR_RESOURCE: ++ case VKD3DSPR_INPUT: + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, +- "Invalid SAMPLER register used as destination parameter."); ++ "Invalid %#x register used as destination parameter.", dst->reg.type); + break; + +- case VKD3DSPR_RESOURCE: +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, +- "Invalid RESOURCE register used as destination parameter."); ++ case VKD3DSPR_PATCHCONST: ++ if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "PATCHCONST register used as destination parameters are only allowed in Hull Shaders."); + break; + + default: +@@ -6454,6 +6642,20 @@ static void vsir_validate_src_param(struct validation_context *ctx, + "Invalid NULL register used as source parameter."); + break; + ++ case VKD3DSPR_OUTPUT: ++ if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL ++ || (ctx->phase != VKD3DSIH_HS_FORK_PHASE && ctx->phase != VKD3DSIH_HS_JOIN_PHASE)) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "Invalid OUTPUT register used as source parameter."); ++ break; ++ ++ case VKD3DSPR_PATCHCONST: ++ if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_DOMAIN ++ && ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, ++ "PATCHCONST register used as source parameters are only allowed in Hull and Domain Shaders."); ++ break; ++ + default: + break; + } +@@ -6510,6 +6712,7 @@ static void vsir_validate_signature_element(struct validation_context *ctx, + unsigned int idx) + { + const struct signature_element *element = &signature->elements[idx]; ++ bool integer_type = false; + + if (element->register_count == 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, +@@ -6518,6 +6721,97 @@ static void vsir_validate_signature_element(struct validation_context *ctx, + if (element->mask == 0 || (element->mask & ~0xf)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Invalid mask %#x.", idx, signature_type, element->mask); ++ ++ /* Here we'd likely want to validate that the usage mask is a subset of the ++ * signature mask. Unfortunately the D3DBC parser sometimes violates this. ++ * For example I've seen a shader like this: ++ * ps_3_0 ++ * [...] ++ * dcl_texcoord0 v0 ++ * [...] ++ * texld r2.xyzw, v0.xyzw, s1.xyzw ++ * [...] ++ * ++ * The dcl_textcoord0 instruction secretly has a .xy mask, which is used to ++ * compute the signature mask, but the texld instruction apparently uses all ++ * the components. Of course the last two components are ignored, but ++ * formally they seem to be used. So we end up with a signature element with ++ * mask .xy and usage mask .xyzw. ++ * ++ * The correct fix would probably be to make the D3DBC parser aware of which ++ * components are really used for each instruction, but that would take some ++ * time. */ ++ if (element->used_mask & ~0xf) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "element %u of %s signature: Invalid usage mask %#x.", ++ idx, signature_type, element->used_mask); ++ ++ switch (element->sysval_semantic) ++ { ++ case VKD3D_SHADER_SV_NONE: ++ case VKD3D_SHADER_SV_POSITION: ++ case VKD3D_SHADER_SV_CLIP_DISTANCE: ++ case VKD3D_SHADER_SV_CULL_DISTANCE: ++ case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX: ++ case VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX: ++ case VKD3D_SHADER_SV_VERTEX_ID: ++ case VKD3D_SHADER_SV_PRIMITIVE_ID: ++ case VKD3D_SHADER_SV_INSTANCE_ID: ++ case VKD3D_SHADER_SV_IS_FRONT_FACE: ++ case VKD3D_SHADER_SV_SAMPLE_INDEX: ++ case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: ++ case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: ++ case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: ++ case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: ++ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: ++ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: ++ case VKD3D_SHADER_SV_TARGET: ++ case VKD3D_SHADER_SV_DEPTH: ++ case VKD3D_SHADER_SV_COVERAGE: ++ case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL: ++ case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL: ++ case VKD3D_SHADER_SV_STENCIL_REF: ++ break; ++ ++ default: ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "element %u of %s signature: Invalid system value semantic %#x.", ++ idx, signature_type, element->sysval_semantic); ++ break; ++ } ++ ++ switch (element->component_type) ++ { ++ case VKD3D_SHADER_COMPONENT_INT: ++ case VKD3D_SHADER_COMPONENT_UINT: ++ integer_type = true; ++ break; ++ ++ case VKD3D_SHADER_COMPONENT_FLOAT: ++ break; ++ ++ default: ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "element %u of %s signature: Invalid component type %#x.", ++ idx, signature_type, element->component_type); ++ break; ++ } ++ ++ if (element->min_precision >= VKD3D_SHADER_MINIMUM_PRECISION_COUNT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "element %u of %s signature: Invalid minimum precision %#x.", ++ idx, signature_type, element->min_precision); ++ ++ if (element->interpolation_mode >= VKD3DSIM_COUNT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "element %u of %s signature: Invalid interpolation mode %#x.", ++ idx, signature_type, element->interpolation_mode); ++ ++ if (integer_type && element->interpolation_mode != VKD3DSIM_NONE ++ && element->interpolation_mode != VKD3DSIM_CONSTANT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "element %u of %s signature: Invalid interpolation mode %#x for integer component type.", ++ idx, signature_type, element->interpolation_mode); + } + + static void vsir_validate_signature(struct validation_context *ctx, +@@ -7060,6 +7354,7 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c + .null_location = {.source_name = source_name}, + .status = VKD3D_OK, + .phase = VKD3DSIH_INVALID, ++ .invalid_instruction_idx = true, + }; + unsigned int i; + +@@ -7088,6 +7383,8 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c + if (!(ctx.ssas = vkd3d_calloc(ctx.program->ssa_count, sizeof(*ctx.ssas)))) + goto fail; + ++ ctx.invalid_instruction_idx = false; ++ + for (ctx.instruction_idx = 0; ctx.instruction_idx < program->instructions.count + && ctx.status != VKD3D_ERROR_OUT_OF_MEMORY; ++ctx.instruction_idx) + vsir_validate_instruction(&ctx); +@@ -7190,6 +7487,8 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t + + vsir_transform(&ctx, vsir_program_insert_alpha_test); + vsir_transform(&ctx, vsir_program_insert_clip_planes); ++ vsir_transform(&ctx, vsir_program_insert_point_size); ++ vsir_transform(&ctx, vsir_program_insert_point_size_clamp); + + if (TRACE_ON()) + vsir_program_trace(program); +diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c +index bfc013959e7..36750de1fd8 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/msl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/msl.c +@@ -39,6 +39,8 @@ struct msl_generator + struct vkd3d_shader_message_context *message_context; + unsigned int indent; + const char *prefix; ++ const struct vkd3d_shader_interface_info *interface_info; ++ const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info; + }; + + static void VKD3D_PRINTF_FUNC(3, 4) msl_compiler_error(struct msl_generator *gen, +@@ -109,6 +111,64 @@ static void msl_print_register_name(struct vkd3d_string_buffer *buffer, + vkd3d_string_buffer_printf(buffer, "r[%u]", reg->idx[0].offset); + msl_print_register_datatype(buffer, gen, reg->data_type); + break; ++ ++ case VKD3DSPR_INPUT: ++ if (reg->idx_count != 1) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled input register index count %u.", reg->idx_count); ++ vkd3d_string_buffer_printf(buffer, "", reg->type); ++ break; ++ } ++ if (reg->idx[0].rel_addr) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled input register indirect addressing."); ++ vkd3d_string_buffer_printf(buffer, "", reg->type); ++ break; ++ } ++ vkd3d_string_buffer_printf(buffer, "v[%u]", reg->idx[0].offset); ++ msl_print_register_datatype(buffer, gen, reg->data_type); ++ break; ++ ++ case VKD3DSPR_OUTPUT: ++ if (reg->idx_count != 1) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled output register index count %u.", reg->idx_count); ++ vkd3d_string_buffer_printf(buffer, "", reg->type); ++ break; ++ } ++ if (reg->idx[0].rel_addr) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled output register indirect addressing."); ++ vkd3d_string_buffer_printf(buffer, "", reg->type); ++ break; ++ } ++ vkd3d_string_buffer_printf(buffer, "o[%u]", reg->idx[0].offset); ++ msl_print_register_datatype(buffer, gen, reg->data_type); ++ break; ++ ++ case VKD3DSPR_CONSTBUFFER: ++ 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); ++ break; ++ } ++ if (reg->idx[0].rel_addr || reg->idx[2].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); ++ break; ++ } ++ vkd3d_string_buffer_printf(buffer, "descriptors.cb_%u[%u]", reg->idx[0].offset, reg->idx[2].offset); ++ msl_print_register_datatype(buffer, gen, reg->data_type); ++ break; ++ + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled register type %#x.", reg->type); +@@ -266,6 +326,144 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d + } + } + ++static bool msl_check_shader_visibility(const struct msl_generator *gen, ++ enum vkd3d_shader_visibility visibility) ++{ ++ enum vkd3d_shader_type t = gen->program->shader_version.type; ++ ++ switch (visibility) ++ { ++ case VKD3D_SHADER_VISIBILITY_ALL: ++ return true; ++ case VKD3D_SHADER_VISIBILITY_VERTEX: ++ return t == VKD3D_SHADER_TYPE_VERTEX; ++ case VKD3D_SHADER_VISIBILITY_HULL: ++ return t == VKD3D_SHADER_TYPE_HULL; ++ case VKD3D_SHADER_VISIBILITY_DOMAIN: ++ return t == VKD3D_SHADER_TYPE_DOMAIN; ++ case VKD3D_SHADER_VISIBILITY_GEOMETRY: ++ return t == VKD3D_SHADER_TYPE_GEOMETRY; ++ case VKD3D_SHADER_VISIBILITY_PIXEL: ++ return t == VKD3D_SHADER_TYPE_PIXEL; ++ case VKD3D_SHADER_VISIBILITY_COMPUTE: ++ return t == VKD3D_SHADER_TYPE_COMPUTE; ++ default: ++ WARN("Invalid shader visibility %#x.\n", visibility); ++ return false; ++ } ++} ++ ++static bool msl_get_cbv_binding(const struct msl_generator *gen, ++ unsigned int register_space, unsigned int register_idx, unsigned int *binding_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 false; ++ ++ for (i = 0; i < interface_info->binding_count; ++i) ++ { ++ binding = &interface_info->bindings[i]; ++ ++ if (binding->type != VKD3D_SHADER_DESCRIPTOR_TYPE_CBV) ++ 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 & VKD3D_SHADER_BINDING_FLAG_BUFFER)) ++ continue; ++ *binding_idx = i; ++ return true; ++ } ++ ++ return false; ++} ++ ++static void msl_generate_cbv_declaration(struct msl_generator *gen, ++ const struct vkd3d_shader_descriptor_info1 *cbv) ++{ ++ const struct vkd3d_shader_descriptor_binding *binding; ++ struct vkd3d_string_buffer *buffer = gen->buffer; ++ unsigned int binding_idx; ++ size_t size; ++ ++ if (cbv->count != 1) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, ++ "Constant buffer %u has unsupported descriptor array size %u.", cbv->register_id, cbv->count); ++ return; ++ } ++ ++ if (!msl_get_cbv_binding(gen, cbv->register_space, cbv->register_index, &binding_idx)) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, ++ "No descriptor binding specified for constant buffer %u.", cbv->register_id); ++ return; ++ } ++ ++ binding = &gen->interface_info->bindings[binding_idx].binding; ++ ++ if (binding->set != 0) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, ++ "Unsupported binding set %u specified for constant buffer %u.", binding->set, cbv->register_id); ++ return; ++ } ++ ++ if (binding->count != 1) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, ++ "Unsupported binding count %u specified for constant buffer %u.", binding->count, cbv->register_id); ++ return; ++ } ++ ++ size = align(cbv->buffer_size, VKD3D_VEC4_SIZE * sizeof(uint32_t)); ++ size /= VKD3D_VEC4_SIZE * sizeof(uint32_t); ++ ++ vkd3d_string_buffer_printf(buffer, ++ "constant vkd3d_vec4 (&cb_%u)[%zu] [[id(%u)]];", cbv->register_id, size, binding->binding); ++}; ++ ++static void msl_generate_descriptor_struct_declarations(struct msl_generator *gen) ++{ ++ const struct vkd3d_shader_scan_descriptor_info1 *info = gen->descriptor_info; ++ const struct vkd3d_shader_descriptor_info1 *descriptor; ++ struct vkd3d_string_buffer *buffer = gen->buffer; ++ unsigned int i; ++ ++ if (!info->descriptor_count) ++ return; ++ ++ vkd3d_string_buffer_printf(buffer, "struct vkd3d_%s_descriptors\n{\n", gen->prefix); ++ ++ for (i = 0; i < info->descriptor_count; ++i) ++ { ++ descriptor = &info->descriptors[i]; ++ ++ msl_print_indent(buffer, 1); ++ switch (descriptor->type) ++ { ++ case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV: ++ msl_generate_cbv_declaration(gen, descriptor); ++ break; ++ ++ default: ++ vkd3d_string_buffer_printf(buffer, "/* */", descriptor->type); ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled descriptor type %#x.", descriptor->type); ++ break; ++ } ++ vkd3d_string_buffer_printf(buffer, "\n"); ++ } ++ ++ vkd3d_string_buffer_printf(buffer, "};\n\n"); ++} ++ + static void msl_generate_input_struct_declarations(struct msl_generator *gen) + { + const struct shader_signature *signature = &gen->program->input_signature; +@@ -550,9 +748,15 @@ static void msl_generate_entrypoint(struct msl_generator *gen) + + vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_out shader_entry(\n", gen->prefix); + +- /* TODO: descriptor declaration */ ++ if (gen->descriptor_info->descriptor_count) ++ { ++ msl_print_indent(gen->buffer, 2); ++ /* TODO: Configurable argument buffer binding location. */ ++ vkd3d_string_buffer_printf(gen->buffer, ++ "constant vkd3d_%s_descriptors& descriptors [[buffer(0)]],\n", gen->prefix); ++ } + +- msl_print_indent(gen->buffer, 1); ++ msl_print_indent(gen->buffer, 2); + vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_in input [[stage_in]])\n{\n", gen->prefix); + + /* TODO: declare #maximum_register + 1 */ +@@ -562,7 +766,10 @@ static void msl_generate_entrypoint(struct msl_generator *gen) + + msl_generate_entrypoint_prologue(gen); + +- vkd3d_string_buffer_printf(gen->buffer, " %s_main(%s_in, %s_out);\n", gen->prefix, gen->prefix, gen->prefix); ++ vkd3d_string_buffer_printf(gen->buffer, " %s_main(%s_in, %s_out", gen->prefix, gen->prefix, gen->prefix); ++ if (gen->descriptor_info->descriptor_count) ++ vkd3d_string_buffer_printf(gen->buffer, ", descriptors"); ++ vkd3d_string_buffer_printf(gen->buffer, ");\n"); + + msl_generate_entrypoint_epilogue(gen); + +@@ -583,13 +790,17 @@ static void msl_generator_generate(struct msl_generator *gen) + vkd3d_string_buffer_printf(gen->buffer, " int4 i;\n"); + vkd3d_string_buffer_printf(gen->buffer, " float4 f;\n};\n\n"); + ++ msl_generate_descriptor_struct_declarations(gen); + msl_generate_input_struct_declarations(gen); + msl_generate_output_struct_declarations(gen); + + vkd3d_string_buffer_printf(gen->buffer, + "void %s_main(thread vkd3d_vec4 *v, " +- "thread vkd3d_vec4 *o)\n{\n", ++ "thread vkd3d_vec4 *o", + gen->prefix); ++ if (gen->descriptor_info->descriptor_count) ++ vkd3d_string_buffer_printf(gen->buffer, ", constant vkd3d_%s_descriptors& descriptors", gen->prefix); ++ vkd3d_string_buffer_printf(gen->buffer, ")\n{\n"); + + ++gen->indent; + +@@ -621,6 +832,8 @@ static void msl_generator_cleanup(struct msl_generator *gen) + } + + static int msl_generator_init(struct msl_generator *gen, struct vsir_program *program, ++ const struct vkd3d_shader_compile_info *compile_info, ++ const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, + struct vkd3d_shader_message_context *message_context) + { + enum vkd3d_shader_type type = program->shader_version.type; +@@ -640,11 +853,14 @@ static int msl_generator_init(struct msl_generator *gen, struct vsir_program *pr + "Internal compiler error: Unhandled shader type %#x.", type); + return VKD3D_ERROR_INVALID_SHADER; + } ++ gen->interface_info = vkd3d_find_struct(compile_info->next, INTERFACE_INFO); ++ gen->descriptor_info = descriptor_info; + + return VKD3D_OK; + } + + int msl_compile(struct vsir_program *program, uint64_t config_flags, ++ const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) + { + struct msl_generator generator; +@@ -653,7 +869,7 @@ int msl_compile(struct vsir_program *program, uint64_t config_flags, + if ((ret = vsir_program_transform(program, config_flags, compile_info, message_context)) < 0) + return ret; + +- if ((ret = msl_generator_init(&generator, program, message_context)) < 0) ++ if ((ret = msl_generator_init(&generator, program, compile_info, descriptor_info, message_context)) < 0) + return ret; + msl_generator_generate(&generator); + msl_generator_cleanup(&generator); +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index 692432d5513..1efd717e970 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -2662,8 +2662,6 @@ static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *p + if ((shader_interface = vkd3d_find_struct(compile_info->next, INTERFACE_INFO))) + { + compiler->xfb_info = vkd3d_find_struct(compile_info->next, TRANSFORM_FEEDBACK_INFO); +- compiler->emit_point_size = compiler->xfb_info && compiler->xfb_info->element_count +- && compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY; + + compiler->shader_interface = *shader_interface; + if (shader_interface->push_constant_buffer_count) +@@ -2690,6 +2688,11 @@ static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *p + } + } + ++ if (compiler->shader_type == VKD3D_SHADER_TYPE_VERTEX) ++ compiler->emit_point_size = true; ++ else if (compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY) ++ compiler->emit_point_size = compiler->xfb_info && compiler->xfb_info->element_count; ++ + compiler->scan_descriptor_info = scan_descriptor_info; + + compiler->phase = VKD3DSIH_INVALID; +@@ -4860,6 +4863,10 @@ static const struct vkd3d_spirv_builtin vkd3d_pixel_shader_position_builtin = + { + VKD3D_SHADER_COMPONENT_FLOAT, 4, SpvBuiltInFragCoord, frag_coord_fixup, + }; ++static const struct vkd3d_spirv_builtin vkd3d_output_point_size_builtin = ++{ ++ VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInPointSize, ++}; + static const struct + { + enum vkd3d_shader_register_type reg_type; +@@ -5449,7 +5456,11 @@ static void spirv_compiler_emit_output_register(struct spirv_compiler *compiler, + VKD3D_ASSERT(!reg->idx_count || !reg->idx[0].rel_addr); + VKD3D_ASSERT(reg->idx_count < 2); + +- if (!(builtin = get_spirv_builtin_for_register(reg->type))) ++ if (reg->type == VKD3DSPR_RASTOUT && reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE) ++ { ++ builtin = &vkd3d_output_point_size_builtin; ++ } ++ else if (!(builtin = get_spirv_builtin_for_register(reg->type))) + { + FIXME("Unhandled register %#x.\n", reg->type); + return; +@@ -6746,7 +6757,8 @@ static void spirv_compiler_emit_dcl_input_primitive(struct spirv_compiler *compi + + static void spirv_compiler_emit_point_size(struct spirv_compiler *compiler) + { +- static const struct vkd3d_spirv_builtin point_size = {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInPointSize}; ++ if (compiler->program->has_point_size) ++ return; + + /* Set the point size. Point sprites are not supported in d3d10+, but + * point primitives can still be used with e.g. stream output. Vulkan +@@ -6760,7 +6772,8 @@ static void spirv_compiler_emit_point_size(struct spirv_compiler *compiler) + || compiler->write_tess_geom_point_size) + { + vkd3d_spirv_build_op_store(&compiler->spirv_builder, +- spirv_compiler_emit_builtin_variable(compiler, &point_size, SpvStorageClassOutput, 0), ++ spirv_compiler_emit_builtin_variable(compiler, ++ &vkd3d_output_point_size_builtin, SpvStorageClassOutput, 0), + spirv_compiler_get_constant_float(compiler, 1.0f), SpvMemoryAccessMaskNone); + } + } +@@ -7427,7 +7440,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, + uint32_t components[VKD3D_VEC4_SIZE]; + + if (register_is_constant_or_undef(&src->reg) || src->reg.type == VKD3DSPR_SSA || dst->reg.type == VKD3DSPR_SSA +- || dst->modifiers || src->modifiers) ++ || src->reg.type == VKD3DSPR_PARAMETER || dst->modifiers || src->modifiers) + goto general_implementation; + + spirv_compiler_get_register_info(compiler, &dst->reg, &dst_reg_info); +@@ -10538,7 +10551,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, + case VKD3DSIH_DCL_RESOURCE_STRUCTURED: + case VKD3DSIH_DCL_UAV_RAW: + case VKD3DSIH_DCL_UAV_STRUCTURED: +- case VKD3DSIH_DCL_UAV_TYPED: + case VKD3DSIH_HS_DECLS: + case VKD3DSIH_NOP: + /* nothing to do */ +@@ -10575,6 +10587,15 @@ static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) + else + spirv_compiler_emit_input(compiler, VKD3DSPR_PATCHCONST, i); + } ++ ++ if (compiler->program->has_point_size) ++ { ++ struct vkd3d_shader_dst_param dst; ++ ++ vsir_dst_param_init(&dst, VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); ++ dst.reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; ++ spirv_compiler_emit_output_register(compiler, &dst); ++ } + } + + static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *compiler) +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index f84ac551272..cde8dc3146c 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -1655,7 +1655,10 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, + break; + + case VKD3D_SHADER_TARGET_MSL: +- ret = msl_compile(program, config_flags, compile_info, message_context); ++ if ((ret = vsir_program_scan(program, &scan_info, message_context, &scan_descriptor_info)) < 0) ++ return ret; ++ ret = msl_compile(program, config_flags, &scan_descriptor_info, compile_info, message_context); ++ vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); + break; + + default: +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 41b879af4b4..9ca3c328147 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -60,6 +60,7 @@ + #define VKD3D_DVEC2_SIZE 2 + + #define VKD3D_SHADER_COMPONENT_TYPE_COUNT (VKD3D_SHADER_COMPONENT_UINT64 + 1) ++#define VKD3D_SHADER_MINIMUM_PRECISION_COUNT (VKD3D_SHADER_MINIMUM_PRECISION_UINT_16 + 1) + + enum vkd3d_shader_error + { +@@ -250,6 +251,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300, + + VKD3D_SHADER_ERROR_MSL_INTERNAL = 10000, ++ VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND = 10001, + }; + + enum vkd3d_shader_opcode +@@ -648,6 +650,13 @@ enum vkd3d_shader_register_type + VKD3DSPR_INVALID = ~0u, + }; + ++enum vsir_rastout_register ++{ ++ VSIR_RASTOUT_POSITION = 0x0, ++ VSIR_RASTOUT_FOG = 0x1, ++ VSIR_RASTOUT_POINT_SIZE = 0x2, ++}; ++ + enum vkd3d_shader_register_precision + { + VKD3D_SHADER_REGISTER_PRECISION_DEFAULT, +@@ -1400,6 +1409,7 @@ struct vsir_program + unsigned int temp_count; + unsigned int ssa_count; + bool use_vocp; ++ bool has_point_size; + enum vsir_control_flow_type cf_type; + + const char **block_names; +@@ -1617,6 +1627,7 @@ int spirv_compile(struct vsir_program *program, uint64_t config_flags, + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); + + int msl_compile(struct vsir_program *program, uint64_t config_flags, ++ const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context); + + enum vkd3d_md5_variant +-- +2.45.2 + diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-f28d39b609036ce9bc3a4baaf6cda012fc2.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-f28d39b609036ce9bc3a4baaf6cda012fc2.patch deleted file mode 100644 index 62ab691e..00000000 --- a/patches/vkd3d-latest/0004-Updated-vkd3d-to-f28d39b609036ce9bc3a4baaf6cda012fc2.patch +++ /dev/null @@ -1,1233 +0,0 @@ -From 9ddf8bb46c1ecb41b9c5dc6abd3e4148ba2db043 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 1 Oct 2024 21:50:23 +1000 -Subject: [PATCH] Updated vkd3d to f28d39b609036ce9bc3a4baaf6cda012fc2e3002. - ---- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 29 +++- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 16 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 79 +++++---- - libs/vkd3d/libs/vkd3d-shader/fx.c | 157 ++++++++++++------ - libs/vkd3d/libs/vkd3d-shader/glsl.c | 107 ++++++++++++ - libs/vkd3d/libs/vkd3d-shader/ir.c | 71 +++++++- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 150 +++++++++-------- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 4 +- - 8 files changed, 444 insertions(+), 169 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index cfee053d49c..9fe4b74486a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -675,9 +675,6 @@ static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum - { - [VKD3D_DATA_FLOAT ] = "float", - [VKD3D_DATA_INT ] = "int", -- [VKD3D_DATA_RESOURCE ] = "resource", -- [VKD3D_DATA_SAMPLER ] = "sampler", -- [VKD3D_DATA_UAV ] = "uav", - [VKD3D_DATA_UINT ] = "uint", - [VKD3D_DATA_UNORM ] = "unorm", - [VKD3D_DATA_SNORM ] = "snorm", -@@ -1229,8 +1226,6 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const - case VKD3D_DATA_INT: - shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); - break; -- case VKD3D_DATA_RESOURCE: -- case VKD3D_DATA_SAMPLER: - case VKD3D_DATA_UINT: - shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); - break; -@@ -1266,8 +1261,6 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const - shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[2], ""); - shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[3], ""); - break; -- case VKD3D_DATA_RESOURCE: -- case VKD3D_DATA_SAMPLER: - case VKD3D_DATA_UINT: - shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); - shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[1], ""); -@@ -1319,6 +1312,23 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const - } - vkd3d_string_buffer_printf(buffer, ")"); - } -+ else if (compiler->flags & VSIR_ASM_FLAG_DUMP_ALL_INDICES) -+ { -+ unsigned int i = 0; -+ -+ if (reg->idx_count == 0 || reg->idx[0].rel_addr) -+ { -+ vkd3d_string_buffer_printf(buffer, "%s", compiler->colours.reset); -+ } -+ else -+ { -+ vkd3d_string_buffer_printf(buffer, "%u%s", offset, compiler->colours.reset); -+ i = 1; -+ } -+ -+ for (; i < reg->idx_count; ++i) -+ shader_print_subscript(compiler, reg->idx[i].offset, reg->idx[i].rel_addr); -+ } - else if (reg->type != VKD3DSPR_RASTOUT - && reg->type != VKD3DSPR_MISCTYPE - && reg->type != VKD3DSPR_NULL -@@ -2491,10 +2501,11 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, - - void vkd3d_shader_trace(const struct vsir_program *program) - { -- const char *p, *q, *end; -+ const unsigned int flags = VSIR_ASM_FLAG_DUMP_TYPES | VSIR_ASM_FLAG_DUMP_ALL_INDICES; - struct vkd3d_shader_code code; -+ const char *p, *q, *end; - -- if (d3d_asm_compile(program, NULL, &code, VSIR_ASM_FLAG_DUMP_TYPES) != VKD3D_OK) -+ if (d3d_asm_compile(program, NULL, &code, flags) != VKD3D_OK) - return; - - end = (const char *)code.code + code.size; -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 34752a1ab89..763d52e1b62 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -1352,9 +1352,6 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c - for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i) - program->flat_constant_count[i] = get_external_constant_count(&sm1, i); - -- if (!sm1.p.failed) -- ret = vkd3d_shader_parser_validate(&sm1.p, config_flags); -- - if (sm1.p.failed && ret >= 0) - ret = VKD3D_ERROR_INVALID_SHADER; - -@@ -1365,7 +1362,18 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c - return ret; - } - -- return ret; -+ if ((ret = vkd3d_shader_parser_validate(&sm1.p, config_flags)) < 0) -+ { -+ WARN("Failed to validate shader after parsing, ret %d.\n", ret); -+ -+ if (TRACE_ON()) -+ vkd3d_shader_trace(program); -+ -+ vsir_program_cleanup(program); -+ return ret; -+ } -+ -+ return VKD3D_OK; - } - - bool hlsl_sm1_register_from_semantic(const struct vkd3d_shader_version *version, const char *semantic_name, -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index ee78b6251f9..165ab222fca 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -4161,8 +4161,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ - dst_param_init(&dst_params[0]); - - dst_params[1].reg = ptr->u.reg; -- /* The groupshared register has data type UAV when accessed. */ -- dst_params[1].reg.data_type = VKD3D_DATA_UAV; -+ dst_params[1].reg.data_type = VKD3D_DATA_UNUSED; - dst_params[1].reg.idx[1].rel_addr = NULL; - dst_params[1].reg.idx[1].offset = ~0u; - dst_params[1].reg.idx_count = 1; -@@ -6861,7 +6860,6 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re - struct vkd3d_shader_dst_param *dst_params; - struct vkd3d_shader_src_param *src_params; - const struct sm6_value *ptr, *cmp, *new; -- const struct sm6_type *type; - unsigned int i = 0; - bool is_volatile; - uint64_t code; -@@ -6887,9 +6885,10 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re - return; - } - -- type = ptr->type->u.pointer.type; -- cmp = sm6_parser_get_value_by_ref(sm6, record, type, &i); -- new = sm6_parser_get_value_by_ref(sm6, record, type, &i); -+ /* Forward-referenced comparands are stored as value/type pairs, even -+ * though in principle we could use the destination type. */ -+ cmp = sm6_parser_get_value_by_ref(sm6, record, NULL, &i); -+ new = sm6_parser_get_value_by_ref(sm6, record, ptr->type->u.pointer.type, &i); - if (!cmp || !new) - return; - -@@ -7287,7 +7286,6 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco - unsigned int i = 0, alignment, operand_count; - struct vkd3d_shader_src_param *src_params; - struct vkd3d_shader_dst_param *dst_param; -- const struct sm6_type *pointee_type; - const struct sm6_value *ptr, *src; - uint64_t alignment_code; - -@@ -7299,13 +7297,14 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco - return; - } - -- pointee_type = ptr->type->u.pointer.type; -- if (!(src = sm6_parser_get_value_by_ref(sm6, record, pointee_type, &i))) -+ /* Forward-referenced sources are stored as value/type pairs, even -+ * though in principle we could use the destination type. */ -+ if (!(src = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))) - return; - if (!sm6_value_validate_is_numeric(src, sm6)) - return; - -- if (pointee_type != src->type) -+ if (ptr->type->u.pointer.type != src->type) - { - WARN("Type mismatch.\n"); - vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -@@ -8908,7 +8907,7 @@ static enum vkd3d_result sm6_parser_resources_load_srv(struct sm6_parser *sm6, - d->resource_type = ins->resource_type; - d->kind = kind; - d->reg_type = VKD3DSPR_RESOURCE; -- d->reg_data_type = (ins->resource_type == VKD3D_SHADER_RESOURCE_BUFFER) ? VKD3D_DATA_UINT : VKD3D_DATA_RESOURCE; -+ d->reg_data_type = VKD3D_DATA_UNUSED; - d->resource_data_type = (ins->opcode == VKD3DSIH_DCL) - ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; - -@@ -8982,7 +8981,7 @@ static enum vkd3d_result sm6_parser_resources_load_uav(struct sm6_parser *sm6, - d->resource_type = ins->resource_type; - d->kind = values[0]; - d->reg_type = VKD3DSPR_UAV; -- d->reg_data_type = (ins->resource_type == VKD3D_SHADER_RESOURCE_BUFFER) ? VKD3D_DATA_UINT : VKD3D_DATA_UAV; -+ d->reg_data_type = VKD3D_DATA_UNUSED; - d->resource_data_type = (ins->opcode == VKD3DSIH_DCL_UAV_TYPED) - ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; - -@@ -9346,7 +9345,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - WARN("Signature element is not a node.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, - "Signature element is not a metadata node."); -- return VKD3D_ERROR_INVALID_SHADER; -+ goto invalid; - } - - element_node = m->u.node; -@@ -9355,7 +9354,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - WARN("Invalid operand count %u.\n", element_node->operand_count); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, - "Invalid signature element operand count %u.", element_node->operand_count); -- return VKD3D_ERROR_INVALID_SHADER; -+ goto invalid; - } - if (element_node->operand_count > 11) - { -@@ -9374,7 +9373,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - WARN("Failed to load uint value at index %u.\n", j); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, - "Signature element value at index %u is not an integer.", j); -- return VKD3D_ERROR_INVALID_SHADER; -+ goto invalid; - } - } - -@@ -9385,7 +9384,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - FIXME("Unsupported element id %u not equal to its index %u.\n", values[0], i); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, - "A non-sequential and non-zero-based element id is not supported."); -- return VKD3D_ERROR_INVALID_SHADER; -+ goto invalid; - } - - if (!sm6_metadata_value_is_string(element_node->operands[1])) -@@ -9393,7 +9392,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - WARN("Element name is not a string.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, - "Signature element name is not a metadata string."); -- return VKD3D_ERROR_INVALID_SHADER; -+ goto invalid; - } - e->semantic_name = element_node->operands[1]->u.string_value; - -@@ -9407,7 +9406,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - WARN("Unhandled semantic kind %u.\n", j); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, - "DXIL semantic kind %u is unhandled.", j); -- return VKD3D_ERROR_INVALID_SHADER; -+ goto invalid; - } - - if ((e->interpolation_mode = values[5]) >= VKD3DSIM_COUNT) -@@ -9415,7 +9414,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - WARN("Unhandled interpolation mode %u.\n", e->interpolation_mode); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, - "Interpolation mode %u is unhandled.", e->interpolation_mode); -- return VKD3D_ERROR_INVALID_SHADER; -+ goto invalid; - } - - e->register_count = values[6]; -@@ -9430,7 +9429,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - WARN("Unhandled I/O register semantic kind %u.\n", j); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, - "DXIL semantic kind %u is unhandled for an I/O register.", j); -- return VKD3D_ERROR_INVALID_SHADER; -+ goto invalid; - } - } - else if (e->register_index > MAX_REG_OUTPUT || e->register_count > MAX_REG_OUTPUT - e->register_index) -@@ -9439,7 +9438,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, - "A signature element starting row of %u with count %u is invalid.", - e->register_index, e->register_count); -- return VKD3D_ERROR_INVALID_SHADER; -+ goto invalid; - } - - index = values[9]; -@@ -9448,7 +9447,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - WARN("Invalid column start %u with count %u.\n", index, column_count); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, - "A signature element starting column %u with count %u is invalid.", index, column_count); -- return VKD3D_ERROR_INVALID_SHADER; -+ goto invalid; - } - - e->mask = vkd3d_write_mask_from_component_count(column_count); -@@ -9471,7 +9470,7 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - WARN("Semantic index list is not a node.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, - "Signature element semantic index list is not a metadata node."); -- return VKD3D_ERROR_INVALID_SHADER; -+ goto invalid; - } - - element_node = m->u.node; -@@ -9516,6 +9515,10 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const - s->element_count = operand_count; - - return VKD3D_OK; -+ -+invalid: -+ vkd3d_free(elements); -+ return VKD3D_ERROR_INVALID_SHADER; - } - - static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, const struct sm6_metadata_value *m, -@@ -10526,9 +10529,16 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro - - dxil_block_destroy(&sm6->root_block); - -+ if (sm6->p.failed) -+ { -+ ret = VKD3D_ERROR_INVALID_SHADER; -+ goto fail; -+ } -+ - return VKD3D_OK; - - fail: -+ sm6_parser_cleanup(sm6); - vsir_program_cleanup(program); - return ret; - } -@@ -10570,18 +10580,25 @@ int dxil_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t co - free_dxbc_shader_desc(&dxbc_desc); - vkd3d_free(byte_code); - -- if (!sm6.p.failed && ret >= 0) -- ret = vkd3d_shader_parser_validate(&sm6.p, config_flags); -- -- if (sm6.p.failed && ret >= 0) -- ret = VKD3D_ERROR_INVALID_SHADER; -- -- sm6_parser_cleanup(&sm6); - if (ret < 0) - { - WARN("Failed to parse shader.\n"); - return ret; - } - -- return ret; -+ if ((ret = vkd3d_shader_parser_validate(&sm6.p, config_flags)) < 0) -+ { -+ WARN("Failed to validate shader after parsing, ret %d.\n", ret); -+ -+ if (TRACE_ON()) -+ vkd3d_shader_trace(program); -+ -+ sm6_parser_cleanup(&sm6); -+ vsir_program_cleanup(program); -+ return ret; -+ } -+ -+ sm6_parser_cleanup(&sm6); -+ -+ return VKD3D_OK; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index 7d4a9d2e2ff..84e827e7943 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -224,11 +224,6 @@ static void set_status(struct fx_write_context *fx, int status) - fx->status = status; - } - --static bool has_annotations(const struct hlsl_ir_var *var) --{ -- return var->annotations && !list_empty(&var->annotations->vars); --} -- - static uint32_t write_string(const char *string, struct fx_write_context *fx) - { - return fx->ops->write_string(string, fx); -@@ -435,17 +430,26 @@ static void write_fx_4_pass(struct hlsl_ir_var *var, struct fx_write_context *fx - write_fx_4_state_block(var, 0, count_offset, fx); - } - -+static void write_fx_2_annotations(struct hlsl_ir_var *var, uint32_t count_offset, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t count; -+ -+ count = write_annotations(var->annotations, fx); -+ set_u32(buffer, count_offset, count); -+} -+ - static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) - { - struct vkd3d_bytecode_buffer *buffer = &fx->structured; -- uint32_t name_offset; -+ uint32_t name_offset, annotation_count_offset; - - name_offset = write_string(var->name, fx); - put_u32(buffer, name_offset); -- put_u32(buffer, 0); /* Annotation count. */ -+ annotation_count_offset = put_u32(buffer, 0); - put_u32(buffer, 0); /* Assignment count. */ - -- /* TODO: annotations */ -+ write_fx_2_annotations(var, annotation_count_offset, fx); - /* TODO: assignments */ - - if (var->state_block_count && var->state_blocks[0]->count) -@@ -467,6 +471,7 @@ static uint32_t get_fx_4_type_size(const struct hlsl_type *type) - - static const uint32_t fx_4_numeric_base_type[] = - { -+ [HLSL_TYPE_HALF] = 1, - [HLSL_TYPE_FLOAT] = 1, - [HLSL_TYPE_INT ] = 2, - [HLSL_TYPE_UINT ] = 3, -@@ -503,6 +508,7 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, - switch (type->e.numeric.type) - { - case HLSL_TYPE_FLOAT: -+ case HLSL_TYPE_HALF: - case HLSL_TYPE_INT: - case HLSL_TYPE_UINT: - case HLSL_TYPE_BOOL: -@@ -579,6 +585,12 @@ static const char * get_fx_4_type_name(const struct hlsl_type *type) - case HLSL_CLASS_STRING: - return "String"; - -+ case HLSL_CLASS_SCALAR: -+ case HLSL_CLASS_VECTOR: -+ case HLSL_CLASS_MATRIX: -+ if (type->e.numeric.type == HLSL_TYPE_HALF) -+ return "float"; -+ /* fall-through */ - default: - return type->name; - } -@@ -977,16 +989,16 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n - - static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) - { -+ uint32_t name_offset, pass_count_offset, annotation_count_offset, count = 0; - struct vkd3d_bytecode_buffer *buffer = &fx->structured; -- uint32_t name_offset, count_offset, count = 0; - struct hlsl_ir_var *pass; - - name_offset = write_string(var->name, fx); - put_u32(buffer, name_offset); -- put_u32(buffer, 0); /* Annotation count. */ -- count_offset = put_u32(buffer, 0); /* Pass count. */ -+ annotation_count_offset = put_u32(buffer, 0); -+ pass_count_offset = put_u32(buffer, 0); - -- /* FIXME: annotations */ -+ write_fx_2_annotations(var, annotation_count_offset, fx); - - LIST_FOR_EACH_ENTRY(pass, &var->scope->vars, struct hlsl_ir_var, scope_entry) - { -@@ -994,41 +1006,78 @@ static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_contex - ++count; - } - -- set_u32(buffer, count_offset, count); -+ set_u32(buffer, pass_count_offset, count); - } - --static uint32_t get_fx_2_type_size(const struct hlsl_type *type) -+static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hlsl_default_value *value, -+ struct fx_write_context *fx) - { -- uint32_t size = 0, elements_count; -- size_t i; -+ const struct hlsl_type *type = hlsl_get_multiarray_element_type(value_type); -+ uint32_t elements_count = hlsl_get_multiarray_size(value_type), i, j; -+ struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; -+ struct hlsl_ctx *ctx = fx->ctx; -+ uint32_t offset = buffer->size; -+ unsigned int comp_count; - -- if (type->class == HLSL_CLASS_ARRAY) -- { -- elements_count = hlsl_get_multiarray_size(type); -- type = hlsl_get_multiarray_element_type(type); -- return get_fx_2_type_size(type) * elements_count; -- } -- else if (type->class == HLSL_CLASS_STRUCT) -+ if (!value) -+ return 0; -+ -+ comp_count = hlsl_type_component_count(type); -+ -+ for (i = 0; i < elements_count; ++i) - { -- for (i = 0; i < type->e.record.field_count; ++i) -+ switch (type->class) - { -- const struct hlsl_struct_field *field = &type->e.record.fields[i]; -- size += get_fx_2_type_size(field->type); -- } -+ case HLSL_CLASS_SCALAR: -+ case HLSL_CLASS_VECTOR: -+ case HLSL_CLASS_MATRIX: -+ { -+ switch (type->e.numeric.type) -+ { -+ case HLSL_TYPE_FLOAT: -+ case HLSL_TYPE_HALF: -+ case HLSL_TYPE_INT: -+ case HLSL_TYPE_UINT: -+ case HLSL_TYPE_BOOL: -+ -+ for (j = 0; j < comp_count; ++j) -+ { -+ put_u32(buffer, value->number.u); -+ value++; -+ } -+ break; -+ default: -+ hlsl_fixme(ctx, &ctx->location, "Writing default values for numeric type %u is not implemented.", -+ type->e.numeric.type); -+ } - -- return size; -+ break; -+ } -+ case HLSL_CLASS_STRUCT: -+ { -+ struct hlsl_struct_field *fields = type->e.record.fields; -+ -+ for (j = 0; j < type->e.record.field_count; ++j) -+ { -+ write_fx_2_default_value(fields[i].type, value, fx); -+ value += hlsl_type_component_count(fields[i].type); -+ } -+ break; -+ } -+ default: -+ hlsl_fixme(ctx, &ctx->location, "Writing default values for class %u is not implemented.", type->class); -+ } - } - -- return type->dimx * type->dimy * sizeof(float); -+ return offset; - } - - static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct fx_write_context *fx) - { - struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; - const struct hlsl_type *type = var->data_type; -- uint32_t offset, size, elements_count = 1; -- -- size = get_fx_2_type_size(type); -+ uint32_t offset, elements_count = 1; -+ struct hlsl_ctx *ctx = fx->ctx; - - if (type->class == HLSL_CLASS_ARRAY) - { -@@ -1044,16 +1093,17 @@ static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct f - case HLSL_CLASS_VECTOR: - case HLSL_CLASS_MATRIX: - case HLSL_CLASS_STRUCT: -- /* FIXME: write actual initial value */ -- if (var->default_values) -- hlsl_fixme(fx->ctx, &var->loc, "Write default values.\n"); -- -- offset = put_u32(buffer, 0); -- -- for (uint32_t i = 1; i < size / sizeof(uint32_t); ++i) -- put_u32(buffer, 0); -+ offset = write_fx_2_default_value(var->data_type, var->default_values, fx); - break; - -+ case HLSL_CLASS_TEXTURE: -+ case HLSL_CLASS_PIXEL_SHADER: -+ case HLSL_CLASS_SAMPLER: -+ case HLSL_CLASS_STRING: -+ case HLSL_CLASS_VERTEX_SHADER: -+ hlsl_fixme(ctx, &var->loc, "Write fx 2.0 object initializer."); -+ /* fallthrough */ -+ - default: - /* Objects are given sequential ids. */ - offset = put_u32(buffer, fx->object_variable_count++); -@@ -1132,8 +1182,8 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type - - static void write_fx_2_parameters(struct fx_write_context *fx) - { -+ uint32_t desc_offset, value_offset, flags, annotation_count_offset; - struct vkd3d_bytecode_buffer *buffer = &fx->structured; -- uint32_t desc_offset, value_offset, flags; - struct hlsl_ctx *ctx = fx->ctx; - struct hlsl_ir_var *var; - enum fx_2_parameter_flags -@@ -1153,23 +1203,35 @@ static void write_fx_2_parameters(struct fx_write_context *fx) - if (var->storage_modifiers & HLSL_STORAGE_SHARED) - flags |= IS_SHARED; - -- put_u32(buffer, desc_offset); /* Parameter description */ -- put_u32(buffer, value_offset); /* Value */ -- put_u32(buffer, flags); /* Flags */ -+ put_u32(buffer, desc_offset); -+ put_u32(buffer, value_offset); -+ put_u32(buffer, flags); - -- put_u32(buffer, 0); /* Annotations count */ -- if (has_annotations(var)) -- hlsl_fixme(ctx, &ctx->location, "Writing annotations for parameters is not implemented."); -+ annotation_count_offset = put_u32(buffer, 0); -+ write_fx_2_annotations(var, annotation_count_offset, fx); - - ++fx->parameter_count; - } - } - -+static void write_fx_2_annotation(struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t desc_offset, value_offset; -+ -+ desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, fx); -+ value_offset = write_fx_2_initial_value(var, fx); -+ -+ put_u32(buffer, desc_offset); -+ put_u32(buffer, value_offset); -+} -+ - static const struct fx_write_context_ops fx_2_ops = - { - .write_string = write_fx_2_string, - .write_technique = write_fx_2_technique, - .write_pass = write_fx_2_pass, -+ .write_annotation = write_fx_2_annotation, - }; - - static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) -@@ -1267,6 +1329,7 @@ static uint32_t write_fx_4_default_value(struct hlsl_type *value_type, struct hl - switch (type->e.numeric.type) - { - case HLSL_TYPE_FLOAT: -+ case HLSL_TYPE_HALF: - case HLSL_TYPE_INT: - case HLSL_TYPE_UINT: - case HLSL_TYPE_BOOL: -diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index a8cc6d87c40..26fd4818970 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/glsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -137,6 +137,14 @@ static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, - vkd3d_string_buffer_printf(buffer, "%s_out[%u]", gen->prefix, reg->idx[0].offset); - break; - -+ case VKD3DSPR_DEPTHOUT: -+ if (gen->program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL) -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Unhandled depth output in shader type #%x.", -+ gen->program->shader_version.type); -+ vkd3d_string_buffer_printf(buffer, "gl_FragDepth"); -+ break; -+ - case VKD3DSPR_IMMCONST: - switch (reg->dimension) - { -@@ -420,6 +428,30 @@ static void shader_glsl_binop(struct vkd3d_glsl_generator *gen, - glsl_dst_cleanup(&dst, &gen->string_buffers); - } - -+static void shader_glsl_dot(struct vkd3d_glsl_generator *gen, -+ const struct vkd3d_shader_instruction *ins, uint32_t src_mask) -+{ -+ unsigned int component_count; -+ struct glsl_src src[2]; -+ struct glsl_dst dst; -+ uint32_t dst_mask; -+ -+ dst_mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); -+ glsl_src_init(&src[0], gen, &ins->src[0], src_mask); -+ glsl_src_init(&src[1], gen, &ins->src[1], src_mask); -+ -+ if ((component_count = vsir_write_mask_component_count(dst_mask)) > 1) -+ shader_glsl_print_assignment(gen, &dst, "vec%d(dot(%s, %s))", -+ component_count, src[0].str->buffer, src[1].str->buffer); -+ else -+ shader_glsl_print_assignment(gen, &dst, "dot(%s, %s)", -+ src[0].str->buffer, src[1].str->buffer); -+ -+ glsl_src_cleanup(&src[1], &gen->string_buffers); -+ glsl_src_cleanup(&src[0], &gen->string_buffers); -+ glsl_dst_cleanup(&dst, &gen->string_buffers); -+} -+ - static void shader_glsl_intrinsic(struct vkd3d_glsl_generator *gen, - const struct vkd3d_shader_instruction *ins, const char *op) - { -@@ -482,6 +514,31 @@ static void shader_glsl_cast(struct vkd3d_glsl_generator *gen, const struct vkd3 - glsl_dst_cleanup(&dst, &gen->string_buffers); - } - -+static void shader_glsl_if(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ const char *condition; -+ struct glsl_src src; -+ -+ glsl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); -+ -+ shader_glsl_print_indent(gen->buffer, gen->indent); -+ condition = ins->flags == VKD3D_SHADER_CONDITIONAL_OP_NZ ? "bool" : "!bool"; -+ vkd3d_string_buffer_printf(gen->buffer, "if (%s(%s))\n", condition, src.str->buffer); -+ -+ glsl_src_cleanup(&src, &gen->string_buffers); -+ -+ shader_glsl_print_indent(gen->buffer, gen->indent); -+ vkd3d_string_buffer_printf(gen->buffer, "{\n"); -+ ++gen->indent; -+} -+ -+static void shader_glsl_endif(struct vkd3d_glsl_generator *gen) -+{ -+ --gen->indent; -+ shader_glsl_print_indent(gen->buffer, gen->indent); -+ vkd3d_string_buffer_printf(gen->buffer, "}\n"); -+} -+ - static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) - { - struct glsl_src src; -@@ -545,6 +602,15 @@ static void shader_glsl_print_sysval_name(struct vkd3d_string_buffer *buffer, st - } - break; - -+ case VKD3D_SHADER_SV_IS_FRONT_FACE: -+ if (version->type != VKD3D_SHADER_TYPE_PIXEL) -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Unhandled SV_IS_FRONT_FACE in shader type #%x.", version->type); -+ vkd3d_string_buffer_printf(buffer, -+ "uintBitsToFloat(uvec4(gl_FrontFacing ? 0xffffffffu : 0u, 0u, 0u, 0u))"); -+ -+ break; -+ - case VKD3D_SHADER_SV_TARGET: - if (version->type != VKD3D_SHADER_TYPE_PIXEL) - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -@@ -673,6 +739,8 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - shader_glsl_binop(gen, ins, "&"); - break; - case VKD3DSIH_DCL_INPUT: -+ case VKD3DSIH_DCL_INPUT_PS: -+ case VKD3DSIH_DCL_INPUT_PS_SIV: - case VKD3DSIH_DCL_OUTPUT: - case VKD3DSIH_DCL_OUTPUT_SIV: - case VKD3DSIH_NOP: -@@ -680,6 +748,24 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_DIV: - shader_glsl_binop(gen, ins, "/"); - break; -+ case VKD3DSIH_DP2: -+ shader_glsl_dot(gen, ins, vkd3d_write_mask_from_component_count(2)); -+ break; -+ case VKD3DSIH_DP3: -+ shader_glsl_dot(gen, ins, vkd3d_write_mask_from_component_count(3)); -+ break; -+ case VKD3DSIH_DP4: -+ shader_glsl_dot(gen, ins, VKD3DSP_WRITEMASK_ALL); -+ break; -+ case VKD3DSIH_ENDIF: -+ shader_glsl_endif(gen); -+ break; -+ case VKD3DSIH_IEQ: -+ shader_glsl_relop(gen, ins, "==", "equal"); -+ break; -+ case VKD3DSIH_EXP: -+ shader_glsl_intrinsic(gen, ins, "exp2"); -+ break; - case VKD3DSIH_FRC: - shader_glsl_intrinsic(gen, ins, "fract"); - break; -@@ -692,6 +778,12 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_GEO: - shader_glsl_relop(gen, ins, ">=", "greaterThanEqual"); - break; -+ case VKD3DSIH_IF: -+ shader_glsl_if(gen, ins); -+ break; -+ case VKD3DSIH_LTO: -+ shader_glsl_relop(gen, ins, "<", "lessThan"); -+ break; - case VKD3DSIH_INE: - case VKD3DSIH_NEU: - shader_glsl_relop(gen, ins, "!=", "notEqual"); -@@ -700,6 +792,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_UTOF: - shader_glsl_cast(gen, ins, "float", "vec"); - break; -+ case VKD3DSIH_LOG: -+ shader_glsl_intrinsic(gen, ins, "log2"); -+ break; - case VKD3DSIH_MOV: - shader_glsl_mov(gen, ins); - break; -@@ -715,9 +810,21 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_RET: - shader_glsl_ret(gen, ins); - break; -+ case VKD3DSIH_ROUND_NE: -+ shader_glsl_intrinsic(gen, ins, "roundEven"); -+ break; -+ case VKD3DSIH_ROUND_NI: -+ shader_glsl_intrinsic(gen, ins, "floor"); -+ break; - case VKD3DSIH_ROUND_PI: - shader_glsl_intrinsic(gen, ins, "ceil"); - break; -+ case VKD3DSIH_ROUND_Z: -+ shader_glsl_intrinsic(gen, ins, "trunc"); -+ break; -+ case VKD3DSIH_SQRT: -+ shader_glsl_intrinsic(gen, ins, "sqrt"); -+ break; - default: - shader_glsl_unhandled(gen, ins); - break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 0bbe13ad7d8..88650a97068 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -182,7 +182,7 @@ static void src_param_init_parameter(struct vkd3d_shader_src_param *src, uint32_ - - static void vsir_src_param_init_resource(struct vkd3d_shader_src_param *src, unsigned int id, unsigned int idx) - { -- vsir_src_param_init(src, VKD3DSPR_RESOURCE, VKD3D_DATA_RESOURCE, 2); -+ vsir_src_param_init(src, VKD3DSPR_RESOURCE, VKD3D_DATA_UNUSED, 2); - src->reg.idx[0].offset = id; - src->reg.idx[1].offset = idx; - src->reg.dimension = VSIR_DIMENSION_VEC4; -@@ -191,7 +191,7 @@ static void vsir_src_param_init_resource(struct vkd3d_shader_src_param *src, uns - - static void vsir_src_param_init_sampler(struct vkd3d_shader_src_param *src, unsigned int id, unsigned int idx) - { -- vsir_src_param_init(src, VKD3DSPR_SAMPLER, VKD3D_DATA_SAMPLER, 2); -+ vsir_src_param_init(src, VKD3DSPR_SAMPLER, VKD3D_DATA_UNUSED, 2); - src->reg.idx[0].offset = id; - src->reg.idx[1].offset = idx; - src->reg.dimension = VSIR_DIMENSION_NONE; -@@ -5960,6 +5960,58 @@ static void vsir_validate_register(struct validation_context *ctx, - reg->idx_count); - break; - -+ case VKD3DSPR_SAMPLER: -+ if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, -+ "Invalid precision %#x for a SAMPLER register.", -+ reg->precision); -+ -+ if (reg->data_type != VKD3D_DATA_UNUSED) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -+ "Invalid data type %#x for a SAMPLER register.", -+ reg->data_type); -+ -+ /* VEC4 is allowed in gather operations. */ -+ if (reg->dimension == VSIR_DIMENSION_SCALAR) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, -+ "Invalid dimension SCALAR for a SAMPLER register."); -+ break; -+ -+ case VKD3DSPR_RESOURCE: -+ if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, -+ "Invalid precision %#x for a RESOURCE register.", -+ reg->precision); -+ -+ if (reg->data_type != VKD3D_DATA_UNUSED) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -+ "Invalid data type %#x for a RESOURCE register.", -+ reg->data_type); -+ -+ if (reg->dimension != VSIR_DIMENSION_VEC4) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, -+ "Invalid dimension %#x for a RESOURCE register.", -+ reg->dimension); -+ break; -+ -+ case VKD3DSPR_UAV: -+ if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, -+ "Invalid precision %#x for a UAV register.", -+ reg->precision); -+ -+ if (reg->data_type != VKD3D_DATA_UNUSED) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -+ "Invalid data type %#x for a UAV register.", -+ reg->data_type); -+ -+ /* NONE is allowed in counter operations. */ -+ if (reg->dimension == VSIR_DIMENSION_SCALAR) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, -+ "Invalid dimension %#x for a UAV register.", -+ reg->dimension); -+ break; -+ - default: - break; - } -@@ -6045,6 +6097,16 @@ static void vsir_validate_dst_param(struct validation_context *ctx, - "Invalid IMMCONST64 register used as destination parameter."); - break; - -+ case VKD3DSPR_SAMPLER: -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid SAMPLER register used as destination parameter."); -+ break; -+ -+ case VKD3DSPR_RESOURCE: -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid RESOURCE register used as destination parameter."); -+ break; -+ - default: - break; - } -@@ -6080,6 +6142,11 @@ static void vsir_validate_src_param(struct validation_context *ctx, - } - break; - -+ case VKD3DSPR_NULL: -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, -+ "Invalid NULL register used as source parameter."); -+ break; -+ - default: - break; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index ab9f4cf2b57..389946e2c2f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -896,7 +896,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u - >> VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; - } - -- reg_data_type = opcode == VKD3D_SM4_OP_DCL_RESOURCE ? VKD3D_DATA_RESOURCE : VKD3D_DATA_UAV; -+ reg_data_type = VKD3D_DATA_UNUSED; - shader_sm4_read_dst_param(priv, &tokens, end, reg_data_type, &semantic->resource.reg); - shader_sm4_set_descriptor_register_range(priv, &semantic->resource.reg.reg, &semantic->resource.range); - -@@ -916,7 +916,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u - } - } - -- if (reg_data_type == VKD3D_DATA_UAV) -+ if (opcode != VKD3D_SM4_OP_DCL_RESOURCE) - ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT; - - shader_sm4_read_register_space(priv, &tokens, end, &semantic->resource.range.space); -@@ -958,7 +958,7 @@ static void shader_sm4_read_dcl_sampler(struct vkd3d_shader_instruction *ins, ui - ins->flags = (opcode_token & VKD3D_SM4_SAMPLER_MODE_MASK) >> VKD3D_SM4_SAMPLER_MODE_SHIFT; - if (ins->flags & ~VKD3D_SM4_SAMPLER_COMPARISON) - FIXME("Unhandled sampler mode %#x.\n", ins->flags); -- shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_SAMPLER, &ins->declaration.sampler.src); -+ shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &ins->declaration.sampler.src); - shader_sm4_set_descriptor_register_range(priv, &ins->declaration.sampler.src.reg, &ins->declaration.sampler.range); - shader_sm4_read_register_space(priv, &tokens, end, &ins->declaration.sampler.range.space); - } -@@ -1302,7 +1302,7 @@ static void shader_sm5_read_dcl_uav_raw(struct vkd3d_shader_instruction *ins, ui - struct vkd3d_shader_raw_resource *resource = &ins->declaration.raw_resource; - const uint32_t *end = &tokens[token_count]; - -- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UAV, &resource->resource.reg); -+ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); - shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); - ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT; - shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.range.space); -@@ -1314,7 +1314,7 @@ static void shader_sm5_read_dcl_uav_structured(struct vkd3d_shader_instruction * - struct vkd3d_shader_structured_resource *resource = &ins->declaration.structured_resource; - const uint32_t *end = &tokens[token_count]; - -- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UAV, &resource->resource.reg); -+ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); - shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); - ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT; - resource->byte_stride = *tokens++; -@@ -1351,7 +1351,7 @@ static void shader_sm5_read_dcl_resource_structured(struct vkd3d_shader_instruct - struct vkd3d_shader_structured_resource *resource = &ins->declaration.structured_resource; - const uint32_t *end = &tokens[token_count]; - -- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_RESOURCE, &resource->resource.reg); -+ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); - shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); - resource->byte_stride = *tokens++; - if (resource->byte_stride % 4) -@@ -1365,7 +1365,7 @@ static void shader_sm5_read_dcl_resource_raw(struct vkd3d_shader_instruction *in - struct vkd3d_shader_raw_resource *resource = &ins->declaration.raw_resource; - const uint32_t *end = &tokens[token_count]; - -- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_RESOURCE, &resource->resource.reg); -+ shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); - shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); - shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.range.space); - } -@@ -1471,8 +1471,8 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) - {VKD3D_SM4_OP_ISHR, VKD3DSIH_ISHR, "i", "ii"}, - {VKD3D_SM4_OP_ITOF, VKD3DSIH_ITOF, "f", "i"}, - {VKD3D_SM4_OP_LABEL, VKD3DSIH_LABEL, "", "O"}, -- {VKD3D_SM4_OP_LD, VKD3DSIH_LD, "u", "iR"}, -- {VKD3D_SM4_OP_LD2DMS, VKD3DSIH_LD2DMS, "u", "iRi"}, -+ {VKD3D_SM4_OP_LD, VKD3DSIH_LD, "u", "i*"}, -+ {VKD3D_SM4_OP_LD2DMS, VKD3DSIH_LD2DMS, "u", "i*i"}, - {VKD3D_SM4_OP_LOG, VKD3DSIH_LOG, "f", "f"}, - {VKD3D_SM4_OP_LOOP, VKD3DSIH_LOOP, "", ""}, - {VKD3D_SM4_OP_LT, VKD3DSIH_LTO, "u", "ff"}, -@@ -1488,7 +1488,7 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) - {VKD3D_SM4_OP_NOP, VKD3DSIH_NOP, "", ""}, - {VKD3D_SM4_OP_NOT, VKD3DSIH_NOT, "u", "u"}, - {VKD3D_SM4_OP_OR, VKD3DSIH_OR, "u", "uu"}, -- {VKD3D_SM4_OP_RESINFO, VKD3DSIH_RESINFO, "f", "iR"}, -+ {VKD3D_SM4_OP_RESINFO, VKD3DSIH_RESINFO, "f", "i*"}, - {VKD3D_SM4_OP_RET, VKD3DSIH_RET, "", ""}, - {VKD3D_SM4_OP_RETC, VKD3DSIH_RETP, "", "u", - shader_sm4_read_conditional_op}, -@@ -1497,12 +1497,12 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) - {VKD3D_SM4_OP_ROUND_PI, VKD3DSIH_ROUND_PI, "f", "f"}, - {VKD3D_SM4_OP_ROUND_Z, VKD3DSIH_ROUND_Z, "f", "f"}, - {VKD3D_SM4_OP_RSQ, VKD3DSIH_RSQ, "f", "f"}, -- {VKD3D_SM4_OP_SAMPLE, VKD3DSIH_SAMPLE, "u", "fRS"}, -- {VKD3D_SM4_OP_SAMPLE_C, VKD3DSIH_SAMPLE_C, "f", "fRSf"}, -- {VKD3D_SM4_OP_SAMPLE_C_LZ, VKD3DSIH_SAMPLE_C_LZ, "f", "fRSf"}, -- {VKD3D_SM4_OP_SAMPLE_LOD, VKD3DSIH_SAMPLE_LOD, "u", "fRSf"}, -- {VKD3D_SM4_OP_SAMPLE_GRAD, VKD3DSIH_SAMPLE_GRAD, "u", "fRSff"}, -- {VKD3D_SM4_OP_SAMPLE_B, VKD3DSIH_SAMPLE_B, "u", "fRSf"}, -+ {VKD3D_SM4_OP_SAMPLE, VKD3DSIH_SAMPLE, "u", "f**"}, -+ {VKD3D_SM4_OP_SAMPLE_C, VKD3DSIH_SAMPLE_C, "f", "f**f"}, -+ {VKD3D_SM4_OP_SAMPLE_C_LZ, VKD3DSIH_SAMPLE_C_LZ, "f", "f**f"}, -+ {VKD3D_SM4_OP_SAMPLE_LOD, VKD3DSIH_SAMPLE_LOD, "u", "f**f"}, -+ {VKD3D_SM4_OP_SAMPLE_GRAD, VKD3DSIH_SAMPLE_GRAD, "u", "f**ff"}, -+ {VKD3D_SM4_OP_SAMPLE_B, VKD3DSIH_SAMPLE_B, "u", "f**f"}, - {VKD3D_SM4_OP_SQRT, VKD3DSIH_SQRT, "f", "f"}, - {VKD3D_SM4_OP_SWITCH, VKD3DSIH_SWITCH, "", "i"}, - {VKD3D_SM4_OP_SINCOS, VKD3DSIH_SINCOS, "ff", "f"}, -@@ -1551,10 +1551,10 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) - shader_sm4_read_dcl_indexable_temp}, - {VKD3D_SM4_OP_DCL_GLOBAL_FLAGS, VKD3DSIH_DCL_GLOBAL_FLAGS, "", "", - shader_sm4_read_dcl_global_flags}, -- {VKD3D_SM4_OP_LOD, VKD3DSIH_LOD, "f", "fRS"}, -- {VKD3D_SM4_OP_GATHER4, VKD3DSIH_GATHER4, "u", "fRS"}, -- {VKD3D_SM4_OP_SAMPLE_POS, VKD3DSIH_SAMPLE_POS, "f", "Ru"}, -- {VKD3D_SM4_OP_SAMPLE_INFO, VKD3DSIH_SAMPLE_INFO, "f", "R"}, -+ {VKD3D_SM4_OP_LOD, VKD3DSIH_LOD, "f", "f**"}, -+ {VKD3D_SM4_OP_GATHER4, VKD3DSIH_GATHER4, "u", "f**"}, -+ {VKD3D_SM4_OP_SAMPLE_POS, VKD3DSIH_SAMPLE_POS, "f", "*u"}, -+ {VKD3D_SM4_OP_SAMPLE_INFO, VKD3DSIH_SAMPLE_INFO, "f", "*"}, - {VKD3D_SM5_OP_HS_DECLS, VKD3DSIH_HS_DECLS, "", ""}, - {VKD3D_SM5_OP_HS_CONTROL_POINT_PHASE, VKD3DSIH_HS_CONTROL_POINT_PHASE, "", ""}, - {VKD3D_SM5_OP_HS_FORK_PHASE, VKD3DSIH_HS_FORK_PHASE, "", ""}, -@@ -1563,14 +1563,14 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) - {VKD3D_SM5_OP_CUT_STREAM, VKD3DSIH_CUT_STREAM, "", "f"}, - {VKD3D_SM5_OP_FCALL, VKD3DSIH_FCALL, "", "O", - shader_sm5_read_fcall}, -- {VKD3D_SM5_OP_BUFINFO, VKD3DSIH_BUFINFO, "i", "U"}, -+ {VKD3D_SM5_OP_BUFINFO, VKD3DSIH_BUFINFO, "i", "*"}, - {VKD3D_SM5_OP_DERIV_RTX_COARSE, VKD3DSIH_DSX_COARSE, "f", "f"}, - {VKD3D_SM5_OP_DERIV_RTX_FINE, VKD3DSIH_DSX_FINE, "f", "f"}, - {VKD3D_SM5_OP_DERIV_RTY_COARSE, VKD3DSIH_DSY_COARSE, "f", "f"}, - {VKD3D_SM5_OP_DERIV_RTY_FINE, VKD3DSIH_DSY_FINE, "f", "f"}, -- {VKD3D_SM5_OP_GATHER4_C, VKD3DSIH_GATHER4_C, "f", "fRSf"}, -- {VKD3D_SM5_OP_GATHER4_PO, VKD3DSIH_GATHER4_PO, "f", "fiRS"}, -- {VKD3D_SM5_OP_GATHER4_PO_C, VKD3DSIH_GATHER4_PO_C, "f", "fiRSf"}, -+ {VKD3D_SM5_OP_GATHER4_C, VKD3DSIH_GATHER4_C, "f", "f**f"}, -+ {VKD3D_SM5_OP_GATHER4_PO, VKD3DSIH_GATHER4_PO, "f", "fi**"}, -+ {VKD3D_SM5_OP_GATHER4_PO_C, VKD3DSIH_GATHER4_PO_C, "f", "fi**f"}, - {VKD3D_SM5_OP_RCP, VKD3DSIH_RCP, "f", "f"}, - {VKD3D_SM5_OP_F32TOF16, VKD3DSIH_F32TOF16, "u", "f"}, - {VKD3D_SM5_OP_F16TOF32, VKD3DSIH_F16TOF32, "f", "u"}, -@@ -1622,33 +1622,33 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) - shader_sm5_read_dcl_resource_raw}, - {VKD3D_SM5_OP_DCL_RESOURCE_STRUCTURED, VKD3DSIH_DCL_RESOURCE_STRUCTURED, "", "", - shader_sm5_read_dcl_resource_structured}, -- {VKD3D_SM5_OP_LD_UAV_TYPED, VKD3DSIH_LD_UAV_TYPED, "u", "iU"}, -- {VKD3D_SM5_OP_STORE_UAV_TYPED, VKD3DSIH_STORE_UAV_TYPED, "U", "iu"}, -- {VKD3D_SM5_OP_LD_RAW, VKD3DSIH_LD_RAW, "u", "iU"}, -- {VKD3D_SM5_OP_STORE_RAW, VKD3DSIH_STORE_RAW, "U", "uu"}, -- {VKD3D_SM5_OP_LD_STRUCTURED, VKD3DSIH_LD_STRUCTURED, "u", "iiR"}, -- {VKD3D_SM5_OP_STORE_STRUCTURED, VKD3DSIH_STORE_STRUCTURED, "U", "iiu"}, -- {VKD3D_SM5_OP_ATOMIC_AND, VKD3DSIH_ATOMIC_AND, "U", "iu"}, -- {VKD3D_SM5_OP_ATOMIC_OR, VKD3DSIH_ATOMIC_OR, "U", "iu"}, -- {VKD3D_SM5_OP_ATOMIC_XOR, VKD3DSIH_ATOMIC_XOR, "U", "iu"}, -- {VKD3D_SM5_OP_ATOMIC_CMP_STORE, VKD3DSIH_ATOMIC_CMP_STORE, "U", "iuu"}, -- {VKD3D_SM5_OP_ATOMIC_IADD, VKD3DSIH_ATOMIC_IADD, "U", "ii"}, -- {VKD3D_SM5_OP_ATOMIC_IMAX, VKD3DSIH_ATOMIC_IMAX, "U", "ii"}, -- {VKD3D_SM5_OP_ATOMIC_IMIN, VKD3DSIH_ATOMIC_IMIN, "U", "ii"}, -- {VKD3D_SM5_OP_ATOMIC_UMAX, VKD3DSIH_ATOMIC_UMAX, "U", "iu"}, -- {VKD3D_SM5_OP_ATOMIC_UMIN, VKD3DSIH_ATOMIC_UMIN, "U", "iu"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_ALLOC, VKD3DSIH_IMM_ATOMIC_ALLOC, "u", "U"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_CONSUME, VKD3DSIH_IMM_ATOMIC_CONSUME, "u", "U"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_IADD, VKD3DSIH_IMM_ATOMIC_IADD, "uU", "ii"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_AND, VKD3DSIH_IMM_ATOMIC_AND, "uU", "iu"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_OR, VKD3DSIH_IMM_ATOMIC_OR, "uU", "iu"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_XOR, VKD3DSIH_IMM_ATOMIC_XOR, "uU", "iu"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_EXCH, VKD3DSIH_IMM_ATOMIC_EXCH, "uU", "iu"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_CMP_EXCH, VKD3DSIH_IMM_ATOMIC_CMP_EXCH, "uU", "iuu"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_IMAX, VKD3DSIH_IMM_ATOMIC_IMAX, "iU", "ii"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_IMIN, VKD3DSIH_IMM_ATOMIC_IMIN, "iU", "ii"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_UMAX, VKD3DSIH_IMM_ATOMIC_UMAX, "uU", "iu"}, -- {VKD3D_SM5_OP_IMM_ATOMIC_UMIN, VKD3DSIH_IMM_ATOMIC_UMIN, "uU", "iu"}, -+ {VKD3D_SM5_OP_LD_UAV_TYPED, VKD3DSIH_LD_UAV_TYPED, "u", "i*"}, -+ {VKD3D_SM5_OP_STORE_UAV_TYPED, VKD3DSIH_STORE_UAV_TYPED, "*", "iu"}, -+ {VKD3D_SM5_OP_LD_RAW, VKD3DSIH_LD_RAW, "u", "i*"}, -+ {VKD3D_SM5_OP_STORE_RAW, VKD3DSIH_STORE_RAW, "*", "uu"}, -+ {VKD3D_SM5_OP_LD_STRUCTURED, VKD3DSIH_LD_STRUCTURED, "u", "ii*"}, -+ {VKD3D_SM5_OP_STORE_STRUCTURED, VKD3DSIH_STORE_STRUCTURED, "*", "iiu"}, -+ {VKD3D_SM5_OP_ATOMIC_AND, VKD3DSIH_ATOMIC_AND, "*", "iu"}, -+ {VKD3D_SM5_OP_ATOMIC_OR, VKD3DSIH_ATOMIC_OR, "*", "iu"}, -+ {VKD3D_SM5_OP_ATOMIC_XOR, VKD3DSIH_ATOMIC_XOR, "*", "iu"}, -+ {VKD3D_SM5_OP_ATOMIC_CMP_STORE, VKD3DSIH_ATOMIC_CMP_STORE, "*", "iuu"}, -+ {VKD3D_SM5_OP_ATOMIC_IADD, VKD3DSIH_ATOMIC_IADD, "*", "ii"}, -+ {VKD3D_SM5_OP_ATOMIC_IMAX, VKD3DSIH_ATOMIC_IMAX, "*", "ii"}, -+ {VKD3D_SM5_OP_ATOMIC_IMIN, VKD3DSIH_ATOMIC_IMIN, "*", "ii"}, -+ {VKD3D_SM5_OP_ATOMIC_UMAX, VKD3DSIH_ATOMIC_UMAX, "*", "iu"}, -+ {VKD3D_SM5_OP_ATOMIC_UMIN, VKD3DSIH_ATOMIC_UMIN, "*", "iu"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_ALLOC, VKD3DSIH_IMM_ATOMIC_ALLOC, "u", "*"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_CONSUME, VKD3DSIH_IMM_ATOMIC_CONSUME, "u", "*"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_IADD, VKD3DSIH_IMM_ATOMIC_IADD, "u*", "ii"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_AND, VKD3DSIH_IMM_ATOMIC_AND, "u*", "iu"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_OR, VKD3DSIH_IMM_ATOMIC_OR, "u*", "iu"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_XOR, VKD3DSIH_IMM_ATOMIC_XOR, "u*", "iu"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_EXCH, VKD3DSIH_IMM_ATOMIC_EXCH, "u*", "iu"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_CMP_EXCH, VKD3DSIH_IMM_ATOMIC_CMP_EXCH, "u*", "iuu"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_IMAX, VKD3DSIH_IMM_ATOMIC_IMAX, "i*", "ii"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_IMIN, VKD3DSIH_IMM_ATOMIC_IMIN, "i*", "ii"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_UMAX, VKD3DSIH_IMM_ATOMIC_UMAX, "u*", "iu"}, -+ {VKD3D_SM5_OP_IMM_ATOMIC_UMIN, VKD3DSIH_IMM_ATOMIC_UMIN, "u*", "iu"}, - {VKD3D_SM5_OP_SYNC, VKD3DSIH_SYNC, "", "", - shader_sm5_read_sync}, - {VKD3D_SM5_OP_DADD, VKD3DSIH_DADD, "d", "dd"}, -@@ -1675,21 +1675,21 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) - {VKD3D_SM5_OP_DTOU, VKD3DSIH_DTOU, "u", "d"}, - {VKD3D_SM5_OP_ITOD, VKD3DSIH_ITOD, "d", "i"}, - {VKD3D_SM5_OP_UTOD, VKD3DSIH_UTOD, "d", "u"}, -- {VKD3D_SM5_OP_GATHER4_S, VKD3DSIH_GATHER4_S, "uu", "fRS"}, -- {VKD3D_SM5_OP_GATHER4_C_S, VKD3DSIH_GATHER4_C_S, "fu", "fRSf"}, -- {VKD3D_SM5_OP_GATHER4_PO_S, VKD3DSIH_GATHER4_PO_S, "fu", "fiRS"}, -- {VKD3D_SM5_OP_GATHER4_PO_C_S, VKD3DSIH_GATHER4_PO_C_S, "fu", "fiRSf"}, -- {VKD3D_SM5_OP_LD_S, VKD3DSIH_LD_S, "uu", "iR"}, -- {VKD3D_SM5_OP_LD2DMS_S, VKD3DSIH_LD2DMS_S, "uu", "iRi"}, -+ {VKD3D_SM5_OP_GATHER4_S, VKD3DSIH_GATHER4_S, "uu", "f**"}, -+ {VKD3D_SM5_OP_GATHER4_C_S, VKD3DSIH_GATHER4_C_S, "fu", "f**f"}, -+ {VKD3D_SM5_OP_GATHER4_PO_S, VKD3DSIH_GATHER4_PO_S, "fu", "fi**"}, -+ {VKD3D_SM5_OP_GATHER4_PO_C_S, VKD3DSIH_GATHER4_PO_C_S, "fu", "fi**f"}, -+ {VKD3D_SM5_OP_LD_S, VKD3DSIH_LD_S, "uu", "i*"}, -+ {VKD3D_SM5_OP_LD2DMS_S, VKD3DSIH_LD2DMS_S, "uu", "i*i"}, - {VKD3D_SM5_OP_LD_UAV_TYPED_S, VKD3DSIH_LD_UAV_TYPED_S, "uu", "iU"}, - {VKD3D_SM5_OP_LD_RAW_S, VKD3DSIH_LD_RAW_S, "uu", "iU"}, -- {VKD3D_SM5_OP_LD_STRUCTURED_S, VKD3DSIH_LD_STRUCTURED_S, "uu", "iiR"}, -- {VKD3D_SM5_OP_SAMPLE_LOD_S, VKD3DSIH_SAMPLE_LOD_S, "uu", "fRSf"}, -- {VKD3D_SM5_OP_SAMPLE_C_LZ_S, VKD3DSIH_SAMPLE_C_LZ_S, "fu", "fRSf"}, -- {VKD3D_SM5_OP_SAMPLE_CL_S, VKD3DSIH_SAMPLE_CL_S, "uu", "fRSf"}, -- {VKD3D_SM5_OP_SAMPLE_B_CL_S, VKD3DSIH_SAMPLE_B_CL_S, "uu", "fRSff"}, -- {VKD3D_SM5_OP_SAMPLE_GRAD_CL_S, VKD3DSIH_SAMPLE_GRAD_CL_S, "uu", "fRSfff"}, -- {VKD3D_SM5_OP_SAMPLE_C_CL_S, VKD3DSIH_SAMPLE_C_CL_S, "fu", "fRSff"}, -+ {VKD3D_SM5_OP_LD_STRUCTURED_S, VKD3DSIH_LD_STRUCTURED_S, "uu", "ii*"}, -+ {VKD3D_SM5_OP_SAMPLE_LOD_S, VKD3DSIH_SAMPLE_LOD_S, "uu", "f**f"}, -+ {VKD3D_SM5_OP_SAMPLE_C_LZ_S, VKD3DSIH_SAMPLE_C_LZ_S, "fu", "f**f"}, -+ {VKD3D_SM5_OP_SAMPLE_CL_S, VKD3DSIH_SAMPLE_CL_S, "uu", "f**f"}, -+ {VKD3D_SM5_OP_SAMPLE_B_CL_S, VKD3DSIH_SAMPLE_B_CL_S, "uu", "f**ff"}, -+ {VKD3D_SM5_OP_SAMPLE_GRAD_CL_S, VKD3DSIH_SAMPLE_GRAD_CL_S, "uu", "f**fff"}, -+ {VKD3D_SM5_OP_SAMPLE_C_CL_S, VKD3DSIH_SAMPLE_C_CL_S, "fu", "f**ff"}, - {VKD3D_SM5_OP_CHECK_ACCESS_FULLY_MAPPED, VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED, "u", "u"}, - }; - -@@ -1980,12 +1980,8 @@ static enum vkd3d_data_type map_data_type(char t) - return VKD3D_DATA_UINT; - case 'O': - return VKD3D_DATA_OPAQUE; -- case 'R': -- return VKD3D_DATA_RESOURCE; -- case 'S': -- return VKD3D_DATA_SAMPLER; -- case 'U': -- return VKD3D_DATA_UAV; -+ case '*': -+ return VKD3D_DATA_UNUSED; - default: - ERR("Invalid data type '%c'.\n", t); - return VKD3D_DATA_FLOAT; -@@ -2951,9 +2947,6 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con - && !sm4.has_control_point_phase && !sm4.p.failed) - shader_sm4_validate_default_phase_index_ranges(&sm4); - -- if (!sm4.p.failed) -- vkd3d_shader_parser_validate(&sm4.p, config_flags); -- - if (sm4.p.failed) - { - WARN("Failed to parse shader.\n"); -@@ -2961,6 +2954,17 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con - return VKD3D_ERROR_INVALID_SHADER; - } - -+ if ((ret = vkd3d_shader_parser_validate(&sm4.p, config_flags)) < 0) -+ { -+ WARN("Failed to validate shader after parsing, ret %d.\n", ret); -+ -+ if (TRACE_ON()) -+ vkd3d_shader_trace(program); -+ -+ vsir_program_cleanup(program); -+ return ret; -+ } -+ - return VKD3D_OK; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 7ac86e35227..112bdc4da7f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -660,9 +660,6 @@ enum vkd3d_data_type - { - VKD3D_DATA_FLOAT, - VKD3D_DATA_INT, -- VKD3D_DATA_RESOURCE, -- VKD3D_DATA_SAMPLER, -- VKD3D_DATA_UAV, - VKD3D_DATA_UINT, - VKD3D_DATA_UNORM, - VKD3D_DATA_SNORM, -@@ -1493,6 +1490,7 @@ enum vsir_asm_flags - { - VSIR_ASM_FLAG_NONE = 0, - VSIR_ASM_FLAG_DUMP_TYPES = 0x1, -+ VSIR_ASM_FLAG_DUMP_ALL_INDICES = 0x2, - }; - - enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, --- -2.45.2 - diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-9dd42d15ddca66458042b5e4b7775fa054b.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-9dd42d15ddca66458042b5e4b7775fa054b.patch new file mode 100644 index 00000000..352373a2 --- /dev/null +++ b/patches/vkd3d-latest/0005-Updated-vkd3d-to-9dd42d15ddca66458042b5e4b7775fa054b.patch @@ -0,0 +1,1465 @@ +From ddc89bca32897d5d4ad81a9a566ba987f49c91de Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Tue, 15 Oct 2024 07:31:45 +1100 +Subject: [PATCH] Updated vkd3d to 9dd42d15ddca66458042b5e4b7775fa054b4b0a2. + +--- + libs/vkd3d/include/vkd3d_shader.h | 5 + + libs/vkd3d/libs/vkd3d-shader/fx.c | 504 ++++++++++++- + libs/vkd3d/libs/vkd3d-shader/ir.c | 678 +++++++++++------- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 14 + + .../libs/vkd3d-shader/vkd3d_shader_private.h | 5 + + 5 files changed, 909 insertions(+), 297 deletions(-) + +diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h +index e22f236ecd1..5c0d13ea9e2 100644 +--- a/libs/vkd3d/include/vkd3d_shader.h ++++ b/libs/vkd3d/include/vkd3d_shader.h +@@ -1181,6 +1181,11 @@ enum vkd3d_shader_source_type + * the format used for Direct3D shader model 6 shaders. \since 1.9 + */ + VKD3D_SHADER_SOURCE_DXBC_DXIL, ++ /** ++ * Binary format used by Direct3D 9/10.x/11 effects. ++ * Input is a raw FX section without container. \since 1.14 ++ */ ++ VKD3D_SHADER_SOURCE_FX, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SOURCE_TYPE), + }; +diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c +index cc18857a010..e98dfcf4f32 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/fx.c ++++ b/libs/vkd3d/libs/vkd3d-shader/fx.c +@@ -470,26 +470,48 @@ static uint32_t get_fx_4_type_size(const struct hlsl_type *type) + return type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float) * elements_count; + } + +-static const uint32_t fx_4_numeric_base_type[] = ++enum fx_4_type_constants ++{ ++ /* Numeric types encoding */ ++ FX_4_NUMERIC_TYPE_FLOAT = 1, ++ FX_4_NUMERIC_TYPE_INT = 2, ++ FX_4_NUMERIC_TYPE_UINT = 3, ++ FX_4_NUMERIC_TYPE_BOOL = 4, ++ ++ FX_4_NUMERIC_CLASS_SCALAR = 1, ++ FX_4_NUMERIC_CLASS_VECTOR = 2, ++ FX_4_NUMERIC_CLASS_MATRIX = 3, ++ ++ FX_4_NUMERIC_BASE_TYPE_SHIFT = 3, ++ FX_4_NUMERIC_ROWS_SHIFT = 8, ++ FX_4_NUMERIC_COLUMNS_SHIFT = 11, ++ FX_4_NUMERIC_COLUMN_MAJOR_MASK = 0x4000, ++ ++ /* Object types */ ++ FX_4_OBJECT_TYPE_STRING = 1, ++ ++ /* Types */ ++ FX_4_TYPE_CLASS_NUMERIC = 1, ++ FX_4_TYPE_CLASS_OBJECT = 2, ++ FX_4_TYPE_CLASS_STRUCT = 3, ++}; ++ ++static const uint32_t fx_4_numeric_base_types[] = + { +- [HLSL_TYPE_HALF] = 1, +- [HLSL_TYPE_FLOAT] = 1, +- [HLSL_TYPE_INT ] = 2, +- [HLSL_TYPE_UINT ] = 3, +- [HLSL_TYPE_BOOL ] = 4, ++ [HLSL_TYPE_HALF ] = FX_4_NUMERIC_TYPE_FLOAT, ++ [HLSL_TYPE_FLOAT] = FX_4_NUMERIC_TYPE_FLOAT, ++ [HLSL_TYPE_INT ] = FX_4_NUMERIC_TYPE_INT, ++ [HLSL_TYPE_UINT ] = FX_4_NUMERIC_TYPE_UINT, ++ [HLSL_TYPE_BOOL ] = FX_4_NUMERIC_TYPE_BOOL, + }; + + static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, struct fx_write_context *fx) + { +- static const unsigned int NUMERIC_BASE_TYPE_SHIFT = 3; +- static const unsigned int NUMERIC_ROWS_SHIFT = 8; +- static const unsigned int NUMERIC_COLUMNS_SHIFT = 11; +- static const unsigned int NUMERIC_COLUMN_MAJOR_MASK = 0x4000; + static const uint32_t numeric_type_class[] = + { +- [HLSL_CLASS_SCALAR] = 1, +- [HLSL_CLASS_VECTOR] = 2, +- [HLSL_CLASS_MATRIX] = 3, ++ [HLSL_CLASS_SCALAR] = FX_4_NUMERIC_CLASS_SCALAR, ++ [HLSL_CLASS_VECTOR] = FX_4_NUMERIC_CLASS_VECTOR, ++ [HLSL_CLASS_MATRIX] = FX_4_NUMERIC_CLASS_MATRIX, + }; + struct hlsl_ctx *ctx = fx->ctx; + uint32_t value = 0; +@@ -513,17 +535,17 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, + case HLSL_TYPE_INT: + case HLSL_TYPE_UINT: + case HLSL_TYPE_BOOL: +- value |= (fx_4_numeric_base_type[type->e.numeric.type] << NUMERIC_BASE_TYPE_SHIFT); ++ value |= (fx_4_numeric_base_types[type->e.numeric.type] << FX_4_NUMERIC_BASE_TYPE_SHIFT); + break; + default: + hlsl_fixme(ctx, &ctx->location, "Not implemented for base type %u.", type->e.numeric.type); + return 0; + } + +- value |= (type->dimy & 0x7) << NUMERIC_ROWS_SHIFT; +- value |= (type->dimx & 0x7) << NUMERIC_COLUMNS_SHIFT; ++ value |= (type->dimy & 0x7) << FX_4_NUMERIC_ROWS_SHIFT; ++ value |= (type->dimx & 0x7) << FX_4_NUMERIC_COLUMNS_SHIFT; + if (type->modifiers & HLSL_MODIFIER_COLUMN_MAJOR) +- value |= NUMERIC_COLUMN_MAJOR_MASK; ++ value |= FX_4_NUMERIC_COLUMN_MAJOR_MASK; + + return value; + } +@@ -651,7 +673,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + case HLSL_CLASS_SCALAR: + case HLSL_CLASS_VECTOR: + case HLSL_CLASS_MATRIX: +- put_u32_unaligned(buffer, 1); ++ put_u32_unaligned(buffer, FX_4_TYPE_CLASS_NUMERIC); + break; + + case HLSL_CLASS_DEPTH_STENCIL_STATE: +@@ -669,11 +691,11 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + case HLSL_CLASS_GEOMETRY_SHADER: + case HLSL_CLASS_BLEND_STATE: + case HLSL_CLASS_STRING: +- put_u32_unaligned(buffer, 2); ++ put_u32_unaligned(buffer, FX_4_TYPE_CLASS_OBJECT); + break; + + case HLSL_CLASS_STRUCT: +- put_u32_unaligned(buffer, 3); ++ put_u32_unaligned(buffer, FX_4_TYPE_CLASS_STRUCT); + break; + + case HLSL_CLASS_ARRAY: +@@ -794,7 +816,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + } + else if (element_type->class == HLSL_CLASS_STRING) + { +- put_u32_unaligned(buffer, 1); ++ put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_STRING); + } + else if (hlsl_is_numeric_type(element_type)) + { +@@ -1543,7 +1565,7 @@ static uint32_t write_fx_4_state_numeric_value(struct hlsl_ir_constant *value, s + case HLSL_TYPE_INT: + case HLSL_TYPE_UINT: + case HLSL_TYPE_BOOL: +- type = fx_4_numeric_base_type[data_type->e.numeric.type]; ++ type = fx_4_numeric_base_types[data_type->e.numeric.type]; + break; + default: + type = 0; +@@ -2814,3 +2836,441 @@ int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) + vkd3d_unreachable(); + } + } ++ ++struct fx_parser ++{ ++ const uint8_t *ptr, *start, *end; ++ struct vkd3d_shader_message_context *message_context; ++ struct vkd3d_string_buffer buffer; ++ struct ++ { ++ const uint8_t *ptr; ++ const uint8_t *end; ++ uint32_t size; ++ } unstructured; ++ uint32_t buffer_count; ++ uint32_t object_count; ++ bool failed; ++}; ++ ++static uint32_t fx_parser_read_u32(struct fx_parser *parser) ++{ ++ uint32_t ret; ++ ++ if ((parser->end - parser->ptr) < sizeof(uint32_t)) ++ { ++ parser->failed = true; ++ return 0; ++ } ++ ++ ret = *(uint32_t *)parser->ptr; ++ parser->ptr += sizeof(uint32_t); ++ ++ return ret; ++} ++ ++static void fx_parser_read_u32s(struct fx_parser *parser, void *dst, size_t size) ++{ ++ uint32_t *ptr = dst; ++ size_t i; ++ ++ for (i = 0; i < size / sizeof(uint32_t); ++i) ++ ptr[i] = fx_parser_read_u32(parser); ++} ++ ++static void fx_parser_skip(struct fx_parser *parser, size_t size) ++{ ++ if ((parser->end - parser->ptr) < size) ++ { ++ parser->ptr = parser->end; ++ parser->failed = true; ++ return; ++ } ++ parser->ptr += size; ++} ++ ++static void VKD3D_PRINTF_FUNC(3, 4) fx_parser_error(struct fx_parser *parser, enum vkd3d_shader_error error, ++ const char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ vkd3d_shader_verror(parser->message_context, NULL, error, format, args); ++ va_end(args); ++ ++ parser->failed = true; ++} ++ ++static int fx_2_parse(struct fx_parser *parser) ++{ ++ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED, "Parsing fx_2_0 binaries is not implemented.\n"); ++ ++ return -1; ++} ++ ++static void fx_parser_read_unstructured(struct fx_parser *parser, void *dst, uint32_t offset, size_t size) ++{ ++ const uint8_t *ptr = parser->unstructured.ptr; ++ ++ memset(dst, 0, size); ++ if (offset >= parser->unstructured.size ++ || size > parser->unstructured.size - offset) ++ { ++ parser->failed = true; ++ return; ++ } ++ ++ ptr += offset; ++ memcpy(dst, ptr, size); ++} ++ ++static const char *fx_4_get_string(struct fx_parser *parser, uint32_t offset) ++{ ++ const uint8_t *ptr = parser->unstructured.ptr; ++ const uint8_t *end = parser->unstructured.end; ++ ++ if (offset >= parser->unstructured.size) ++ { ++ parser->failed = true; ++ return ""; ++ } ++ ++ ptr += offset; ++ ++ while (ptr < end && *ptr) ++ ++ptr; ++ ++ if (*ptr) ++ { ++ parser->failed = true; ++ return ""; ++ } ++ ++ return (const char *)(parser->unstructured.ptr + offset); ++} ++ ++static void fx_parse_fx_4_numeric_variables(struct fx_parser *parser, uint32_t count) ++{ ++ struct fx_4_numeric_variable ++ { ++ uint32_t name; ++ uint32_t type; ++ uint32_t semantic; ++ uint32_t offset; ++ uint32_t value; ++ uint32_t flags; ++ } var; ++ struct fx_4_type ++ { ++ uint32_t name; ++ uint32_t class; ++ uint32_t element_count; ++ uint32_t unpacked_size; ++ uint32_t stride; ++ uint32_t packed_size; ++ uint32_t typeinfo; ++ } type; ++ const char *name, *semantic, *type_name; ++ uint32_t i; ++ ++ for (i = 0; i < count; ++i) ++ { ++ fx_parser_read_u32s(parser, &var, sizeof(var)); ++ fx_parser_read_unstructured(parser, &type, var.type, sizeof(type)); ++ ++ name = fx_4_get_string(parser, var.name); ++ type_name = fx_4_get_string(parser, type.name); ++ ++ vkd3d_string_buffer_printf(&parser->buffer, " %s %s", type_name, name); ++ if (type.element_count) ++ vkd3d_string_buffer_printf(&parser->buffer, "[%u]", type.element_count); ++ if (var.semantic) ++ { ++ semantic = fx_4_get_string(parser, var.semantic); ++ vkd3d_string_buffer_printf(&parser->buffer, " : %s", semantic); ++ } ++ if (var.value) ++ { ++ unsigned int base_type, comp_count; ++ size_t j; ++ ++ if (type.class == FX_4_TYPE_CLASS_NUMERIC) ++ base_type = (type.typeinfo >> FX_4_NUMERIC_BASE_TYPE_SHIFT) & 0xf; ++ else ++ base_type = 0; ++ ++ vkd3d_string_buffer_printf(&parser->buffer, " = { "); ++ ++ comp_count = type.unpacked_size / sizeof(uint32_t); ++ for (j = 0; j < comp_count; ++j) ++ { ++ union hlsl_constant_value_component value; ++ ++ fx_parser_read_unstructured(parser, &value, var.value + j * sizeof(uint32_t), sizeof(uint32_t)); ++ ++ if (base_type == FX_4_NUMERIC_TYPE_FLOAT) ++ vkd3d_string_buffer_printf(&parser->buffer, "%f", value.f); ++ else if (base_type == FX_4_NUMERIC_TYPE_INT) ++ vkd3d_string_buffer_printf(&parser->buffer, "%d", value.i); ++ else if (base_type == FX_4_NUMERIC_TYPE_UINT) ++ vkd3d_string_buffer_printf(&parser->buffer, "%u", value.u); ++ else if (base_type == FX_4_NUMERIC_TYPE_BOOL) ++ vkd3d_string_buffer_printf(&parser->buffer, "%s", value.u ? "true" : "false" ); ++ else ++ vkd3d_string_buffer_printf(&parser->buffer, "%#x", value.u); ++ ++ if (j < comp_count - 1) ++ vkd3d_string_buffer_printf(&parser->buffer, ", "); ++ } ++ ++ vkd3d_string_buffer_printf(&parser->buffer, " }"); ++ } ++ vkd3d_string_buffer_printf(&parser->buffer, "; // Offset: %u, size %u.\n", var.offset, type.unpacked_size); ++ ++ if (fx_parser_read_u32(parser)) ++ { ++ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED, "Parsing annotations is not implemented.\n"); ++ return; ++ } ++ } ++} ++ ++static void fx_parse_buffers(struct fx_parser *parser) ++{ ++ struct fx_buffer ++ { ++ uint32_t name; ++ uint32_t size; ++ uint32_t flags; ++ uint32_t count; ++ uint32_t bind_point; ++ } buffer; ++ const char *name; ++ uint32_t i; ++ ++ if (parser->failed) ++ return; ++ ++ for (i = 0; i < parser->buffer_count; ++i) ++ { ++ fx_parser_read_u32s(parser, &buffer, sizeof(buffer)); ++ ++ name = fx_4_get_string(parser, buffer.name); ++ ++ vkd3d_string_buffer_printf(&parser->buffer, "cbuffer %s\n", name); ++ vkd3d_string_buffer_printf(&parser->buffer, "{\n"); ++ ++ if (fx_parser_read_u32(parser)) ++ { ++ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED, "Parsing annotations is not implemented.\n"); ++ return; ++ } ++ ++ fx_parse_fx_4_numeric_variables(parser, buffer.count); ++ ++ vkd3d_string_buffer_printf(&parser->buffer, "}\n\n"); ++ } ++} ++ ++static void fx_4_parse_string_initializer(struct fx_parser *parser, uint32_t offset) ++{ ++ const char *str = fx_4_get_string(parser, offset); ++ vkd3d_string_buffer_printf(&parser->buffer, "\"%s\"", str); ++} ++ ++static void fx_4_parse_objects(struct fx_parser *parser) ++{ ++ struct fx_4_object_variable ++ { ++ uint32_t name; ++ uint32_t type; ++ uint32_t semantic; ++ uint32_t bind_point; ++ } var; ++ struct fx_4_type ++ { ++ uint32_t name; ++ uint32_t class; ++ uint32_t element_count; ++ uint32_t unpacked_size; ++ uint32_t stride; ++ uint32_t packed_size; ++ uint32_t typeinfo; ++ } type; ++ uint32_t i, j, value, element_count; ++ const char *name, *type_name; ++ ++ if (parser->failed) ++ return; ++ ++ for (i = 0; i < parser->object_count; ++i) ++ { ++ fx_parser_read_u32s(parser, &var, sizeof(var)); ++ fx_parser_read_unstructured(parser, &type, var.type, sizeof(type)); ++ ++ name = fx_4_get_string(parser, var.name); ++ type_name = fx_4_get_string(parser, type.name); ++ vkd3d_string_buffer_printf(&parser->buffer, "%s %s", type_name, name); ++ if (type.element_count) ++ vkd3d_string_buffer_printf(&parser->buffer, "[%u]", type.element_count); ++ vkd3d_string_buffer_printf(&parser->buffer, " = {\n"); ++ ++ element_count = max(type.element_count, 1); ++ for (j = 0; j < element_count; ++j) ++ { ++ switch (type.typeinfo) ++ { ++ case FX_4_OBJECT_TYPE_STRING: ++ vkd3d_string_buffer_printf(&parser->buffer, " "); ++ value = fx_parser_read_u32(parser); ++ fx_4_parse_string_initializer(parser, value); ++ break; ++ default: ++ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED, ++ "Parsing object type %u is not implemented.\n", type.typeinfo); ++ return; ++ } ++ vkd3d_string_buffer_printf(&parser->buffer, ",\n"); ++ } ++ vkd3d_string_buffer_printf(&parser->buffer, "};\n"); ++ } ++} ++ ++static int fx_4_parse(struct fx_parser *parser) ++{ ++ struct fx_4_header ++ { ++ uint32_t version; ++ uint32_t buffer_count; ++ uint32_t numeric_variable_count; ++ uint32_t object_count; ++ uint32_t shared_buffer_count; ++ uint32_t shared_numeric_variable_count; ++ uint32_t shared_object_count; ++ uint32_t technique_count; ++ uint32_t unstructured_size; ++ uint32_t string_count; ++ uint32_t texture_count; ++ uint32_t depth_stencil_state_count; ++ uint32_t blend_state_count; ++ uint32_t rasterizer_state_count; ++ uint32_t sampler_state_count; ++ uint32_t rtv_count; ++ uint32_t dsv_count; ++ uint32_t shader_count; ++ uint32_t inline_shader_count; ++ } header; ++ ++ fx_parser_read_u32s(parser, &header, sizeof(header)); ++ parser->buffer_count = header.buffer_count; ++ parser->object_count = header.object_count; ++ ++ if (parser->end - parser->ptr < header.unstructured_size) ++ { ++ parser->failed = true; ++ return -1; ++ } ++ ++ parser->unstructured.ptr = parser->ptr; ++ parser->unstructured.end = parser->ptr + header.unstructured_size; ++ parser->unstructured.size = header.unstructured_size; ++ fx_parser_skip(parser, header.unstructured_size); ++ ++ fx_parse_buffers(parser); ++ fx_4_parse_objects(parser); ++ ++ return parser->failed ? - 1 : 0; ++} ++ ++static int fx_5_parse(struct fx_parser *parser) ++{ ++ struct fx_5_header ++ { ++ uint32_t version; ++ uint32_t buffer_count; ++ uint32_t numeric_variable_count; ++ uint32_t object_count; ++ uint32_t shared_buffer_count; ++ uint32_t shared_numeric_variable_count; ++ uint32_t shared_object_count; ++ uint32_t technique_count; ++ uint32_t unstructured_size; ++ uint32_t string_count; ++ uint32_t texture_count; ++ uint32_t depth_stencil_state_count; ++ uint32_t blend_state_count; ++ uint32_t rasterizer_state_count; ++ uint32_t sampler_state_count; ++ uint32_t rtv_count; ++ uint32_t dsv_count; ++ uint32_t shader_count; ++ uint32_t inline_shader_count; ++ uint32_t group_count; ++ uint32_t uav_count; ++ uint32_t interface_variable_count; ++ uint32_t interface_variable_element_count; ++ uint32_t class_instance_element_count; ++ } header; ++ ++ fx_parser_read_u32s(parser, &header, sizeof(header)); ++ parser->buffer_count = header.buffer_count; ++ parser->object_count = header.object_count; ++ ++ if (parser->end - parser->ptr < header.unstructured_size) ++ { ++ parser->failed = true; ++ return -1; ++ } ++ ++ parser->unstructured.ptr = parser->ptr; ++ parser->unstructured.end = parser->ptr + header.unstructured_size; ++ parser->unstructured.size = header.unstructured_size; ++ fx_parser_skip(parser, header.unstructured_size); ++ ++ fx_parse_buffers(parser); ++ fx_4_parse_objects(parser); ++ ++ return parser->failed ? - 1 : 0; ++} ++ ++int fx_parse(const struct vkd3d_shader_compile_info *compile_info, ++ struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) ++{ ++ struct fx_parser parser = ++ { ++ .start = compile_info->source.code, ++ .ptr = compile_info->source.code, ++ .end = (uint8_t *)compile_info->source.code + compile_info->source.size, ++ .message_context = message_context, ++ }; ++ uint32_t version; ++ int ret; ++ ++ vkd3d_string_buffer_init(&parser.buffer); ++ ++ if (parser.end - parser.start < sizeof(version)) ++ return -1; ++ version = *(uint32_t *)parser.ptr; ++ ++ switch (version) ++ { ++ case 0xfeff0901: ++ ret = fx_2_parse(&parser); ++ break; ++ case 0xfeff1001: ++ case 0xfeff1011: ++ ret = fx_4_parse(&parser); ++ break; ++ case 0xfeff2001: ++ ret = fx_5_parse(&parser); ++ break; ++ default: ++ fx_parser_error(&parser, VKD3D_SHADER_ERROR_FX_INVALID_VERSION, ++ "Invalid effect binary version value 0x%08x.", version); ++ ret = -1; ++ } ++ ++ vkd3d_shader_code_from_string_buffer(out, &parser.buffer); ++ ++ return ret; ++} +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 9d24126fba8..0bcc3d0a1f7 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -6180,6 +6180,287 @@ static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *c + ctx->status = VKD3D_ERROR_INVALID_SHADER; + } + ++static void vsir_validate_register_without_indices(struct validation_context *ctx, ++ const struct vkd3d_shader_register *reg) ++{ ++ if (reg->idx_count != 0) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a register of type %#x.", ++ reg->idx_count, reg->type); ++} ++ ++static void vsir_validate_temp_register(struct validation_context *ctx, ++ const struct vkd3d_shader_register *reg) ++{ ++ struct validation_context_temp_data *data; ++ ++ if (reg->idx_count != 1) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a TEMP register.", ++ reg->idx_count); ++ return; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for a TEMP register."); ++ ++ if (reg->idx[0].offset >= ctx->program->temp_count) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "TEMP register index %u exceeds the maximum count %u.", ++ reg->idx[0].offset, ctx->program->temp_count); ++ return; ++ } ++ ++ data = &ctx->temps[reg->idx[0].offset]; ++ ++ if (reg->dimension == VSIR_DIMENSION_NONE) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, ++ "Invalid dimension NONE for a TEMP register."); ++ return; ++ } ++ ++ /* TEMP registers can be scalar or vec4, provided that ++ * each individual register always appears with the same ++ * dimension. */ ++ if (data->dimension == VSIR_DIMENSION_NONE) ++ { ++ data->dimension = reg->dimension; ++ data->first_seen = ctx->instruction_idx; ++ } ++ else if (data->dimension != reg->dimension) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, ++ "Invalid dimension %#x for a TEMP register: " ++ "it has already been seen with dimension %#x at instruction %zu.", ++ reg->dimension, data->dimension, data->first_seen); ++ } ++} ++ ++static void vsir_validate_rastout_register(struct validation_context *ctx, ++ const struct vkd3d_shader_register *reg) ++{ ++ if (reg->idx_count != 1) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a RASTOUT register.", ++ reg->idx_count); ++ return; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for a RASTOUT register."); ++ ++ if (reg->idx[0].offset >= 3) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Invalid offset for a RASTOUT register."); ++} ++ ++static void vsir_validate_misctype_register(struct validation_context *ctx, ++ const struct vkd3d_shader_register *reg) ++{ ++ if (reg->idx_count != 1) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a MISCTYPE register.", ++ reg->idx_count); ++ return; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for a MISCTYPE register."); ++ ++ if (reg->idx[0].offset >= 2) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Invalid offset for a MISCTYPE register."); ++} ++ ++static void vsir_validate_label_register(struct validation_context *ctx, ++ const struct vkd3d_shader_register *reg) ++{ ++ if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, ++ "Invalid precision %#x for a LABEL register.", reg->precision); ++ ++ if (reg->data_type != VKD3D_DATA_UNUSED) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for a LABEL register.", reg->data_type); ++ ++ if (reg->dimension != VSIR_DIMENSION_NONE) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, ++ "Invalid dimension %#x for a LABEL register.", reg->dimension); ++ ++ if (reg->idx_count != 1) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a LABEL register.", reg->idx_count); ++ return; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for a LABEL register."); ++ ++ /* Index == 0 is invalid, but it is temporarily allowed ++ * for intermediate stages. Once we support validation ++ * dialects we can selectively check for that. */ ++ if (reg->idx[0].offset > ctx->program->block_count) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "LABEL register index %u exceeds the maximum count %u.", ++ reg->idx[0].offset, ctx->program->block_count); ++} ++ ++static void vsir_validate_sampler_register(struct validation_context *ctx, ++ const struct vkd3d_shader_register *reg) ++{ ++ if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, ++ "Invalid precision %#x for a SAMPLER register.", reg->precision); ++ ++ if (reg->data_type != VKD3D_DATA_UNUSED) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for a SAMPLER register.", reg->data_type); ++ ++ /* VEC4 is allowed in gather operations. */ ++ if (reg->dimension == VSIR_DIMENSION_SCALAR) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, ++ "Invalid dimension SCALAR for a SAMPLER register."); ++ ++ if (reg->idx_count != 2) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a SAMPLER register.", reg->idx_count); ++ return; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for the descriptor index of a SAMPLER register."); ++} ++ ++static void vsir_validate_resource_register(struct validation_context *ctx, ++ const struct vkd3d_shader_register *reg) ++{ ++ if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, ++ "Invalid precision %#x for a RESOURCE register.", reg->precision); ++ ++ if (reg->data_type != VKD3D_DATA_UNUSED) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for a RESOURCE register.", reg->data_type); ++ ++ if (reg->dimension != VSIR_DIMENSION_VEC4) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, ++ "Invalid dimension %#x for a RESOURCE register.", reg->dimension); ++ ++ if (reg->idx_count != 2) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a RESOURCE register.", reg->idx_count); ++ return; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for the descriptor index of a RESOURCE register."); ++} ++ ++static void vsir_validate_uav_register(struct validation_context *ctx, ++ const struct vkd3d_shader_register *reg) ++{ ++ if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, ++ "Invalid precision %#x for a UAV register.", ++ reg->precision); ++ ++ if (reg->data_type != VKD3D_DATA_UNUSED) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for a UAV register.", ++ reg->data_type); ++ ++ /* NONE is allowed in counter operations. */ ++ if (reg->dimension == VSIR_DIMENSION_SCALAR) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, ++ "Invalid dimension %#x for a UAV register.", ++ reg->dimension); ++ ++ if (reg->idx_count != 2) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a UAV register.", ++ reg->idx_count); ++ return; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for the descriptor index of a UAV register."); ++} ++ ++static void vsir_validate_ssa_register(struct validation_context *ctx, ++ const struct vkd3d_shader_register *reg) ++{ ++ struct validation_context_ssa_data *data; ++ ++ if (reg->idx_count != 1) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a SSA register.", ++ reg->idx_count); ++ return; ++ } ++ ++ if (reg->idx[0].rel_addr) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Non-NULL relative address for a SSA register."); ++ ++ if (reg->idx[0].offset >= ctx->program->ssa_count) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "SSA register index %u exceeds the maximum count %u.", ++ reg->idx[0].offset, ctx->program->ssa_count); ++ return; ++ } ++ ++ data = &ctx->ssas[reg->idx[0].offset]; ++ ++ if (reg->dimension == VSIR_DIMENSION_NONE) ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, ++ "Invalid dimension NONE for a SSA register."); ++ return; ++ } ++ ++ /* SSA registers can be scalar or vec4, provided that each ++ * individual register always appears with the same ++ * dimension. */ ++ if (data->dimension == VSIR_DIMENSION_NONE) ++ { ++ data->dimension = reg->dimension; ++ data->data_type = reg->data_type; ++ data->first_seen = ctx->instruction_idx; ++ } ++ else ++ { ++ if (data->dimension != reg->dimension) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, ++ "Invalid dimension %#x for a SSA register: " ++ "it has already been seen with dimension %#x at instruction %zu.", ++ reg->dimension, data->dimension, data->first_seen); ++ ++ if (data_type_is_64_bit(data->data_type) != data_type_is_64_bit(reg->data_type)) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for a SSA register: " ++ "it has already been seen with data type %#x at instruction %zu.", ++ reg->data_type, data->data_type, data->first_seen); ++ } ++} ++ + static void vsir_validate_src_param(struct validation_context *ctx, + const struct vkd3d_shader_src_param *src); + +@@ -6218,298 +6499,59 @@ static void vsir_validate_register(struct validation_context *ctx, + switch (reg->type) + { + case VKD3DSPR_TEMP: +- { +- struct validation_context_temp_data *data; +- +- if (reg->idx_count != 1) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a TEMP register.", +- reg->idx_count); +- break; +- } +- +- if (reg->idx[0].rel_addr) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Non-NULL relative address for a TEMP register."); +- +- if (reg->idx[0].offset >= ctx->program->temp_count) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "TEMP register index %u exceeds the maximum count %u.", +- reg->idx[0].offset, ctx->program->temp_count); +- break; +- } +- +- data = &ctx->temps[reg->idx[0].offset]; +- +- if (reg->dimension == VSIR_DIMENSION_NONE) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension NONE for a TEMP register."); +- break; +- } +- +- /* TEMP registers can be scalar or vec4, provided that +- * each individual register always appears with the same +- * dimension. */ +- if (data->dimension == VSIR_DIMENSION_NONE) +- { +- data->dimension = reg->dimension; +- data->first_seen = ctx->instruction_idx; +- } +- else if (data->dimension != reg->dimension) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a TEMP register: " +- "it has already been seen with dimension %#x at instruction %zu.", +- reg->dimension, data->dimension, data->first_seen); +- } ++ vsir_validate_temp_register(ctx, reg); + break; +- } +- +- case VKD3DSPR_SSA: +- { +- struct validation_context_ssa_data *data; +- +- if (reg->idx_count != 1) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a SSA register.", +- reg->idx_count); +- break; +- } +- +- if (reg->idx[0].rel_addr) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Non-NULL relative address for a SSA register."); + +- if (reg->idx[0].offset >= ctx->program->ssa_count) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, +- "SSA register index %u exceeds the maximum count %u.", +- reg->idx[0].offset, ctx->program->ssa_count); +- break; +- } +- +- data = &ctx->ssas[reg->idx[0].offset]; +- +- if (reg->dimension == VSIR_DIMENSION_NONE) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension NONE for a SSA register."); +- break; +- } +- +- /* SSA registers can be scalar or vec4, provided that each +- * individual register always appears with the same +- * dimension. */ +- if (data->dimension == VSIR_DIMENSION_NONE) +- { +- data->dimension = reg->dimension; +- data->data_type = reg->data_type; +- data->first_seen = ctx->instruction_idx; +- } +- else +- { +- if (data->dimension != reg->dimension) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a SSA register: " +- "it has already been seen with dimension %#x at instruction %zu.", +- reg->dimension, data->dimension, data->first_seen); +- +- if (data_type_is_64_bit(data->data_type) != data_type_is_64_bit(reg->data_type)) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid data type %#x for a SSA register: " +- "it has already been seen with data type %#x at instruction %zu.", +- reg->data_type, data->data_type, data->first_seen); +- } ++ case VKD3DSPR_RASTOUT: ++ vsir_validate_rastout_register(ctx, reg); + break; +- } + +- case VKD3DSPR_LABEL: +- if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, "Invalid precision %#x for a LABEL register.", +- reg->precision); +- +- if (reg->data_type != VKD3D_DATA_UNUSED) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid data type %#x for a LABEL register.", +- reg->data_type); +- +- if (reg->dimension != VSIR_DIMENSION_NONE) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a LABEL register.", +- reg->dimension); +- +- if (reg->idx_count != 1) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a LABEL register.", +- reg->idx_count); +- break; +- } ++ case VKD3DSPR_DEPTHOUT: ++ vsir_validate_register_without_indices(ctx, reg); ++ break; + +- if (reg->idx[0].rel_addr) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Non-NULL relative address for a LABEL register."); +- +- /* Index == 0 is invalid, but it is temporarily allowed +- * for intermediate stages. Once we support validation +- * dialects we can selectively check for that. */ +- if (reg->idx[0].offset > ctx->program->block_count) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, +- "LABEL register index %u exceeds the maximum count %u.", +- reg->idx[0].offset, ctx->program->block_count); ++ case VKD3DSPR_MISCTYPE: ++ vsir_validate_misctype_register(ctx, reg); + break; + +- case VKD3DSPR_NULL: +- if (reg->idx_count != 0) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a NULL register.", +- reg->idx_count); ++ case VKD3DSPR_LABEL: ++ vsir_validate_label_register(ctx, reg); + break; + + case VKD3DSPR_IMMCONST: +- if (reg->idx_count != 0) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a IMMCONST register.", +- reg->idx_count); ++ vsir_validate_register_without_indices(ctx, reg); + break; + + case VKD3DSPR_IMMCONST64: +- if (reg->idx_count != 0) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a IMMCONST64 register.", +- reg->idx_count); ++ vsir_validate_register_without_indices(ctx, reg); + break; + +- case VKD3DSPR_SAMPLER: +- if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, +- "Invalid precision %#x for a SAMPLER register.", +- reg->precision); +- +- if (reg->data_type != VKD3D_DATA_UNUSED) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, +- "Invalid data type %#x for a SAMPLER register.", +- reg->data_type); +- +- /* VEC4 is allowed in gather operations. */ +- if (reg->dimension == VSIR_DIMENSION_SCALAR) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, +- "Invalid dimension SCALAR for a SAMPLER register."); +- +- if (reg->idx_count != 2) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, +- "Invalid index count %u for a SAMPLER register.", +- reg->idx_count); +- break; +- } ++ case VKD3DSPR_NULL: ++ vsir_validate_register_without_indices(ctx, reg); ++ break; + +- if (reg->idx[0].rel_addr) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, +- "Non-NULL relative address for the descriptor index of a SAMPLER register."); ++ case VKD3DSPR_SAMPLER: ++ vsir_validate_sampler_register(ctx, reg); + break; + + case VKD3DSPR_RESOURCE: +- if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, +- "Invalid precision %#x for a RESOURCE register.", +- reg->precision); +- +- if (reg->data_type != VKD3D_DATA_UNUSED) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, +- "Invalid data type %#x for a RESOURCE register.", +- reg->data_type); +- +- if (reg->dimension != VSIR_DIMENSION_VEC4) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, +- "Invalid dimension %#x for a RESOURCE register.", +- reg->dimension); +- +- if (reg->idx_count != 2) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, +- "Invalid index count %u for a RESOURCE register.", +- reg->idx_count); +- break; +- } +- +- if (reg->idx[0].rel_addr) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, +- "Non-NULL relative address for the descriptor index of a RESOURCE register."); ++ vsir_validate_resource_register(ctx, reg); + break; + + case VKD3DSPR_UAV: +- if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, +- "Invalid precision %#x for a UAV register.", +- reg->precision); +- +- if (reg->data_type != VKD3D_DATA_UNUSED) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, +- "Invalid data type %#x for a UAV register.", +- reg->data_type); +- +- /* NONE is allowed in counter operations. */ +- if (reg->dimension == VSIR_DIMENSION_SCALAR) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, +- "Invalid dimension %#x for a UAV register.", +- reg->dimension); +- +- if (reg->idx_count != 2) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, +- "Invalid index count %u for a UAV register.", +- reg->idx_count); +- break; +- } +- +- if (reg->idx[0].rel_addr) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, +- "Non-NULL relative address for the descriptor index of a UAV register."); +- break; +- +- case VKD3DSPR_DEPTHOUT: +- if (reg->idx_count != 0) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, +- "Invalid index count %u for a DEPTHOUT register.", +- reg->idx_count); ++ vsir_validate_uav_register(ctx, reg); + break; + + case VKD3DSPR_DEPTHOUTGE: +- if (reg->idx_count != 0) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, +- "Invalid index count %u for a DEPTHOUTGE register.", +- reg->idx_count); ++ vsir_validate_register_without_indices(ctx, reg); + break; + + case VKD3DSPR_DEPTHOUTLE: +- if (reg->idx_count != 0) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, +- "Invalid index count %u for a DEPTHOUTLE register.", +- reg->idx_count); +- break; +- +- case VKD3DSPR_RASTOUT: +- if (reg->idx_count != 1) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, +- "Invalid index count %u for a RASTOUT register.", +- reg->idx_count); +- break; +- } +- +- if (reg->idx[0].rel_addr) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, +- "Non-NULL relative address for a RASTOUT register."); +- +- if (reg->idx[0].offset >= 3) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, +- "Invalid offset for a RASTOUT register."); ++ vsir_validate_register_without_indices(ctx, reg); + break; + +- case VKD3DSPR_MISCTYPE: +- if (reg->idx_count != 1) +- { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, +- "Invalid index count %u for a MISCTYPE register.", +- reg->idx_count); +- break; +- } +- +- if (reg->idx[0].rel_addr) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, +- "Non-NULL relative address for a MISCTYPE register."); +- +- if (reg->idx[0].offset >= 2) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, +- "Invalid offset for a MISCTYPE register."); ++ case VKD3DSPR_SSA: ++ vsir_validate_ssa_register(ctx, reg); + break; + + default: +@@ -6707,20 +6749,60 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx, + return true; + } + ++enum vsir_signature_type ++{ ++ SIGNATURE_TYPE_INPUT, ++ SIGNATURE_TYPE_OUTPUT, ++ SIGNATURE_TYPE_PATCH_CONSTANT, ++}; ++ ++static const char * const signature_type_names[] = ++{ ++ [SIGNATURE_TYPE_INPUT] = "input", ++ [SIGNATURE_TYPE_OUTPUT] = "output", ++ [SIGNATURE_TYPE_PATCH_CONSTANT] = "patch constant", ++}; ++ ++#define PS_BIT (1u << VKD3D_SHADER_TYPE_PIXEL) ++#define VS_BIT (1u << VKD3D_SHADER_TYPE_VERTEX) ++#define GS_BIT (1u << VKD3D_SHADER_TYPE_GEOMETRY) ++#define HS_BIT (1u << VKD3D_SHADER_TYPE_HULL) ++#define DS_BIT (1u << VKD3D_SHADER_TYPE_DOMAIN) ++#define CS_BIT (1u << VKD3D_SHADER_TYPE_COMPUTE) ++ ++static const struct sysval_validation_data_element ++{ ++ unsigned int input; ++ unsigned int output; ++ unsigned int patch_constant; ++ enum vkd3d_shader_component_type data_type; ++ unsigned int component_count; ++} ++sysval_validation_data[] = ++{ ++ [VKD3D_SHADER_SV_POSITION] = {PS_BIT | GS_BIT | HS_BIT | DS_BIT, VS_BIT | GS_BIT | HS_BIT | DS_BIT, 0, ++ VKD3D_SHADER_COMPONENT_FLOAT, 4}, ++ [VKD3D_SHADER_SV_CLIP_DISTANCE] = {PS_BIT | GS_BIT | HS_BIT | DS_BIT, PS_BIT | VS_BIT | GS_BIT | HS_BIT | DS_BIT, 0, ++ VKD3D_SHADER_COMPONENT_FLOAT, 4}, ++ [VKD3D_SHADER_SV_CULL_DISTANCE] = {PS_BIT | GS_BIT | HS_BIT | DS_BIT, PS_BIT | VS_BIT | GS_BIT | HS_BIT | DS_BIT, 0, ++ VKD3D_SHADER_COMPONENT_FLOAT, 4}, ++}; ++ + static void vsir_validate_signature_element(struct validation_context *ctx, +- const struct shader_signature *signature, const char *signature_type, ++ const struct shader_signature *signature, enum vsir_signature_type signature_type, + unsigned int idx) + { ++ const char *signature_type_name = signature_type_names[signature_type]; + const struct signature_element *element = &signature->elements[idx]; + bool integer_type = false; + + if (element->register_count == 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, +- "element %u of %s signature: Invalid zero register count.", idx, signature_type); ++ "element %u of %s signature: Invalid zero register count.", idx, signature_type_name); + + if (element->mask == 0 || (element->mask & ~0xf)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, +- "element %u of %s signature: Invalid mask %#x.", idx, signature_type, element->mask); ++ "element %u of %s signature: Invalid mask %#x.", idx, signature_type_name, element->mask); + + /* Here we'd likely want to validate that the usage mask is a subset of the + * signature mask. Unfortunately the D3DBC parser sometimes violates this. +@@ -6744,7 +6826,7 @@ static void vsir_validate_signature_element(struct validation_context *ctx, + if (element->used_mask & ~0xf) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Invalid usage mask %#x.", +- idx, signature_type, element->used_mask); ++ idx, signature_type_name, element->used_mask); + + switch (element->sysval_semantic) + { +@@ -6776,10 +6858,56 @@ static void vsir_validate_signature_element(struct validation_context *ctx, + default: + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Invalid system value semantic %#x.", +- idx, signature_type, element->sysval_semantic); ++ idx, signature_type_name, element->sysval_semantic); + break; + } + ++ if (element->sysval_semantic < ARRAY_SIZE(sysval_validation_data)) ++ { ++ const struct sysval_validation_data_element *data = &sysval_validation_data[element->sysval_semantic]; ++ ++ if (data->input || data->output || data->patch_constant) ++ { ++ unsigned int mask; ++ ++ switch (signature_type) ++ { ++ case SIGNATURE_TYPE_INPUT: ++ mask = data->input; ++ break; ++ ++ case SIGNATURE_TYPE_OUTPUT: ++ mask = data->output; ++ break; ++ ++ case SIGNATURE_TYPE_PATCH_CONSTANT: ++ mask = data->patch_constant; ++ break; ++ ++ default: ++ vkd3d_unreachable(); ++ } ++ ++ if (!(mask & (1u << ctx->program->shader_version.type))) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "element %u of %s signature: Invalid system value semantic %#x.", ++ idx, signature_type_name, element->sysval_semantic); ++ } ++ ++ if (data->component_count != 0) ++ { ++ if (element->component_type != data->data_type) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "element %u of %s signature: Invalid data type %#x for system value semantic %#x.", ++ idx, signature_type_name, element->component_type, element->sysval_semantic); ++ ++ if (vsir_write_mask_component_count(element->mask) > data->component_count) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "element %u of %s signature: Invalid mask %#x for system value semantic %#x.", ++ idx, signature_type_name, element->mask, element->sysval_semantic); ++ } ++ } ++ + switch (element->component_type) + { + case VKD3D_SHADER_COMPONENT_INT: +@@ -6793,29 +6921,29 @@ static void vsir_validate_signature_element(struct validation_context *ctx, + default: + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Invalid component type %#x.", +- idx, signature_type, element->component_type); ++ idx, signature_type_name, element->component_type); + break; + } + + if (element->min_precision >= VKD3D_SHADER_MINIMUM_PRECISION_COUNT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Invalid minimum precision %#x.", +- idx, signature_type, element->min_precision); ++ idx, signature_type_name, element->min_precision); + + if (element->interpolation_mode >= VKD3DSIM_COUNT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Invalid interpolation mode %#x.", +- idx, signature_type, element->interpolation_mode); ++ idx, signature_type_name, element->interpolation_mode); + + if (integer_type && element->interpolation_mode != VKD3DSIM_NONE + && element->interpolation_mode != VKD3DSIM_CONSTANT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Invalid interpolation mode %#x for integer component type.", +- idx, signature_type, element->interpolation_mode); ++ idx, signature_type_name, element->interpolation_mode); + } + + static void vsir_validate_signature(struct validation_context *ctx, +- const struct shader_signature *signature, const char *signature_type) ++ const struct shader_signature *signature, enum vsir_signature_type signature_type) + { + unsigned int i; + +@@ -7373,9 +7501,9 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c + "Patch constant signature is only valid for hull and domain shaders."); + } + +- vsir_validate_signature(&ctx, &program->input_signature, "input"); +- vsir_validate_signature(&ctx, &program->output_signature, "output"); +- vsir_validate_signature(&ctx, &program->patch_constant_signature, "patch constant"); ++ vsir_validate_signature(&ctx, &program->input_signature, SIGNATURE_TYPE_INPUT); ++ vsir_validate_signature(&ctx, &program->output_signature, SIGNATURE_TYPE_OUTPUT); ++ vsir_validate_signature(&ctx, &program->patch_constant_signature, SIGNATURE_TYPE_PATCH_CONSTANT); + + if (!(ctx.temps = vkd3d_calloc(ctx.program->temp_count, sizeof(*ctx.temps)))) + goto fail; +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index cde8dc3146c..ca012d4948a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -1710,6 +1710,10 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, + { + ret = compile_hlsl(compile_info, out, &message_context); + } ++ else if (compile_info->source_type == VKD3D_SHADER_SOURCE_FX) ++ { ++ ret = fx_parse(compile_info, out, &message_context); ++ } + else + { + uint64_t config_flags = vkd3d_shader_init_config_flags(); +@@ -1942,6 +1946,7 @@ const enum vkd3d_shader_source_type *vkd3d_shader_get_supported_source_types(uns + #ifdef VKD3D_SHADER_UNSUPPORTED_DXIL + VKD3D_SHADER_SOURCE_DXBC_DXIL, + #endif ++ VKD3D_SHADER_SOURCE_FX, + }; + + TRACE("count %p.\n", count); +@@ -2000,6 +2005,11 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( + }; + #endif + ++ static const enum vkd3d_shader_target_type fx_types[] = ++ { ++ VKD3D_SHADER_TARGET_D3D_ASM, ++ }; ++ + TRACE("source_type %#x, count %p.\n", source_type, count); + + switch (source_type) +@@ -2022,6 +2032,10 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( + return dxbc_dxil_types; + #endif + ++ case VKD3D_SHADER_SOURCE_FX: ++ *count = ARRAY_SIZE(fx_types); ++ return fx_types; ++ + default: + *count = 0; + return NULL; +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 9ca3c328147..54b87373ed1 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -252,6 +252,9 @@ enum vkd3d_shader_error + + VKD3D_SHADER_ERROR_MSL_INTERNAL = 10000, + VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND = 10001, ++ ++ VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED = 11000, ++ VKD3D_SHADER_ERROR_FX_INVALID_VERSION = 11001, + }; + + enum vkd3d_shader_opcode +@@ -1605,6 +1608,8 @@ int dxil_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t co + struct vkd3d_shader_message_context *message_context, struct vsir_program *program); + int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags, + struct vkd3d_shader_message_context *message_context, struct vsir_program *program); ++int fx_parse(const struct vkd3d_shader_compile_info *compile_info, ++ struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); + + void free_dxbc_shader_desc(struct dxbc_shader_desc *desc); + +-- +2.45.2 + diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-ae27fded1a039fda84b526cd9bd7b64aeb5.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-ae27fded1a039fda84b526cd9bd7b64aeb5.patch deleted file mode 100644 index 280eadbe..00000000 --- a/patches/vkd3d-latest/0005-Updated-vkd3d-to-ae27fded1a039fda84b526cd9bd7b64aeb5.patch +++ /dev/null @@ -1,1977 +0,0 @@ -From f12a3f3127f1bb47c8b2e6b7b9a5eaad1434ae3d Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Thu, 3 Oct 2024 10:05:51 +1000 -Subject: [PATCH] Updated vkd3d to ae27fded1a039fda84b526cd9bd7b64aeb5573b5. - ---- - libs/vkd3d/include/vkd3d_shader.h | 78 ++++- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 37 ++- - libs/vkd3d/libs/vkd3d-shader/fx.c | 172 ++++++++--- - libs/vkd3d/libs/vkd3d-shader/glsl.c | 75 ++++- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 106 ++++++- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 24 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 146 +++++---- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 32 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 281 +++++++++++++++++- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 131 +++++--- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 47 ++- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 3 + - 12 files changed, 945 insertions(+), 187 deletions(-) - -diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h -index 115bb21b932..d08ee74a3a0 100644 ---- a/libs/vkd3d/include/vkd3d_shader.h -+++ b/libs/vkd3d/include/vkd3d_shader.h -@@ -480,8 +480,8 @@ enum vkd3d_shader_parameter_type - /** The parameter value is embedded directly in the shader. */ - VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT, - /** -- * The parameter value is provided to the shader via a specialization -- * constant. This value is only supported for the SPIR-V target type. -+ * The parameter value is provided to the shader via specialization -+ * constants. This value is only supported for the SPIR-V target type. - */ - VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT, - /** -@@ -506,6 +506,13 @@ enum vkd3d_shader_parameter_data_type - VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32, - /** The parameter is provided as a 32-bit float. \since 1.13 */ - VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32, -+ /** -+ * The parameter is provided as a 4-dimensional vector of 32-bit floats. -+ * This parameter must be used with struct vkd3d_shader_parameter1; -+ * it cannot be used with struct vkd3d_shader_parameter. -+ * \since 1.14 -+ */ -+ VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_DATA_TYPE), - }; -@@ -589,6 +596,58 @@ enum vkd3d_shader_parameter_name - * \since 1.13 - */ - VKD3D_SHADER_PARAMETER_NAME_FLAT_INTERPOLATION, -+ /** -+ * A mask of enabled clip planes. -+ * -+ * When this parameter is provided to a vertex shader, for each nonzero bit -+ * of this mask, a user clip distance will be generated from vertex position -+ * in clip space, and the clip plane defined by the indexed vector, taken -+ * from the VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_# parameter. -+ * -+ * Regardless of the specific clip planes which are enabled, the clip -+ * distances which are output are a contiguous array starting from clip -+ * distance 0. This affects the interface of OpenGL. For example, if only -+ * clip planes 1 and 3 are enabled (and so the value of the mask is 0xa), -+ * the user should enable only GL_CLIP_DISTANCE0 and GL_CLIP_DISTANCE1. -+ * -+ * The default value is zero, i.e. do not enable any clip planes. -+ * -+ * The data type for this parameter must be -+ * VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32. -+ * -+ * Only VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT is supported in this -+ * version of vkd3d-shader. -+ * -+ * If the source shader writes clip distances and this parameter is nonzero, -+ * compilation fails. -+ * -+ * \since 1.14 -+ */ -+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK, -+ /** -+ * Clip plane values. -+ * See VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK for documentation of -+ * clip planes. -+ * -+ * These enum values are contiguous and arithmetic may safely be performed -+ * on them. That is, VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_[n] is -+ * VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 plus n. -+ * -+ * The data type for each parameter must be -+ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4. -+ * -+ * The default value for each plane is a (0, 0, 0, 0) vector. -+ * -+ * \since 1.14 -+ */ -+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0, -+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_1, -+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_2, -+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_3, -+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_4, -+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_5, -+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_6, -+ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_7, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME), - }; -@@ -636,6 +695,13 @@ struct vkd3d_shader_parameter_immediate_constant1 - * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32. - */ - float f32; -+ /** -+ * A pointer to the value if the parameter's data type is -+ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4. -+ * -+ * \since 1.14 -+ */ -+ float f32_vec4[4]; - void *_pointer_pad; - uint32_t _pad[4]; - } u; -@@ -647,7 +713,13 @@ struct vkd3d_shader_parameter_immediate_constant1 - */ - struct vkd3d_shader_parameter_specialization_constant - { -- /** The ID of the specialization constant. */ -+ /** -+ * The ID of the specialization constant. -+ * If the type comprises more than one constant, such as -+ * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4, then a contiguous -+ * array of specialization constants should be used, one for each component, -+ * and this ID should point to the first component. -+ */ - uint32_t id; - }; - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 763d52e1b62..267cf410cbe 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -457,17 +457,36 @@ static uint32_t swizzle_from_sm1(uint32_t swizzle) - shader_sm1_get_swizzle_component(swizzle, 3)); - } - -+/* D3DBC doesn't have the concept of index count. All registers implicitly have -+ * exactly one index. However for some register types the index doesn't make -+ * sense, so we remove it. */ -+static unsigned int idx_count_from_reg_type(enum vkd3d_shader_register_type reg_type) -+{ -+ switch (reg_type) -+ { -+ case VKD3DSPR_DEPTHOUT: -+ return 0; -+ -+ default: -+ return 1; -+ } -+} -+ - static void shader_sm1_parse_src_param(uint32_t param, struct vkd3d_shader_src_param *rel_addr, - struct vkd3d_shader_src_param *src) - { - enum vkd3d_shader_register_type reg_type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT) - | ((param & VKD3D_SM1_REGISTER_TYPE_MASK2) >> VKD3D_SM1_REGISTER_TYPE_SHIFT2); -+ unsigned int idx_count = idx_count_from_reg_type(reg_type); - -- vsir_register_init(&src->reg, reg_type, VKD3D_DATA_FLOAT, 1); -+ vsir_register_init(&src->reg, reg_type, VKD3D_DATA_FLOAT, idx_count); - src->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT; - src->reg.non_uniform = false; -- src->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK; -- src->reg.idx[0].rel_addr = rel_addr; -+ if (idx_count == 1) -+ { -+ src->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK; -+ src->reg.idx[0].rel_addr = rel_addr; -+ } - if (src->reg.type == VKD3DSPR_SAMPLER) - src->reg.dimension = VSIR_DIMENSION_NONE; - else if (src->reg.type == VKD3DSPR_DEPTHOUT) -@@ -483,12 +502,16 @@ static void shader_sm1_parse_dst_param(uint32_t param, struct vkd3d_shader_src_p - { - enum vkd3d_shader_register_type reg_type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT) - | ((param & VKD3D_SM1_REGISTER_TYPE_MASK2) >> VKD3D_SM1_REGISTER_TYPE_SHIFT2); -+ unsigned int idx_count = idx_count_from_reg_type(reg_type); - -- vsir_register_init(&dst->reg, reg_type, VKD3D_DATA_FLOAT, 1); -+ vsir_register_init(&dst->reg, reg_type, VKD3D_DATA_FLOAT, idx_count); - dst->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT; - dst->reg.non_uniform = false; -- dst->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK; -- dst->reg.idx[0].rel_addr = rel_addr; -+ if (idx_count == 1) -+ { -+ dst->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK; -+ dst->reg.idx[0].rel_addr = rel_addr; -+ } - if (dst->reg.type == VKD3DSPR_SAMPLER) - dst->reg.dimension = VSIR_DIMENSION_NONE; - else if (dst->reg.type == VKD3DSPR_DEPTHOUT) -@@ -614,7 +637,7 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * - const struct vkd3d_shader_register *reg, bool is_dcl, unsigned int mask) - { - const struct vkd3d_shader_version *version = &sm1->p.program->shader_version; -- unsigned int register_index = reg->idx[0].offset; -+ unsigned int register_index = reg->idx_count > 0 ? reg->idx[0].offset : 0; - - switch (reg->type) - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index 84e827e7943..cc18857a010 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -182,6 +182,7 @@ struct fx_write_context - - struct vkd3d_bytecode_buffer unstructured; - struct vkd3d_bytecode_buffer structured; -+ struct vkd3d_bytecode_buffer objects; - - struct rb_tree strings; - struct list types; -@@ -1072,19 +1073,63 @@ static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hl - return offset; - } - --static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct fx_write_context *fx) -+static uint32_t write_fx_2_object_initializer(const struct hlsl_ir_var *var, struct fx_write_context *fx) - { -- struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; -- const struct hlsl_type *type = var->data_type; -- uint32_t offset, elements_count = 1; -+ const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); -+ unsigned int i, elements_count = hlsl_get_multiarray_size(var->data_type); -+ struct vkd3d_bytecode_buffer *buffer = &fx->objects; -+ uint32_t offset = fx->unstructured.size, id, size; - struct hlsl_ctx *ctx = fx->ctx; -+ const void *data; - -- if (type->class == HLSL_CLASS_ARRAY) -+ for (i = 0; i < elements_count; ++i) - { -- elements_count = hlsl_get_multiarray_size(type); -- type = hlsl_get_multiarray_element_type(type); -+ if (type->class == HLSL_CLASS_SAMPLER) -+ { -+ hlsl_fixme(ctx, &var->loc, "Writing fx_2_0 sampler objects initializers is not implemented."); -+ } -+ else -+ { -+ switch (type->class) -+ { -+ case HLSL_CLASS_STRING: -+ { -+ const char *string = var->default_values[i].string ? var->default_values[i].string : ""; -+ size = strlen(string) + 1; -+ data = string; -+ break; -+ } -+ case HLSL_CLASS_TEXTURE: -+ size = 0; -+ break; -+ case HLSL_CLASS_PIXEL_SHADER: -+ case HLSL_CLASS_VERTEX_SHADER: -+ size = 0; -+ hlsl_fixme(ctx, &var->loc, "Writing fx_2_0 shader objects initializers is not implemented."); -+ break; -+ default: -+ vkd3d_unreachable(); -+ } -+ id = fx->object_variable_count++; -+ -+ put_u32(&fx->unstructured, id); -+ -+ put_u32(buffer, id); -+ put_u32(buffer, size); -+ if (size) -+ bytecode_put_bytes(buffer, data, size); -+ } - } - -+ return offset; -+} -+ -+static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); -+ struct hlsl_ctx *ctx = fx->ctx; -+ uint32_t offset; -+ - /* Note that struct fields must all be numeric; - * this was validated in check_invalid_object_fields(). */ - switch (type->class) -@@ -1096,19 +1141,17 @@ static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct f - offset = write_fx_2_default_value(var->data_type, var->default_values, fx); - break; - -- case HLSL_CLASS_TEXTURE: -- case HLSL_CLASS_PIXEL_SHADER: - case HLSL_CLASS_SAMPLER: -+ case HLSL_CLASS_TEXTURE: - case HLSL_CLASS_STRING: -+ case HLSL_CLASS_PIXEL_SHADER: - case HLSL_CLASS_VERTEX_SHADER: -- hlsl_fixme(ctx, &var->loc, "Write fx 2.0 object initializer."); -- /* fallthrough */ -+ offset = write_fx_2_object_initializer(var, fx); -+ break; - - default: -- /* Objects are given sequential ids. */ -- offset = put_u32(buffer, fx->object_variable_count++); -- for (uint32_t i = 1; i < elements_count; ++i) -- put_u32(buffer, fx->object_variable_count++); -+ offset = 0; -+ hlsl_fixme(ctx, &var->loc, "Writing initializer not implemented for parameter class %#x.", type->class); - break; - } - -@@ -1134,6 +1177,7 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type - return is_type_supported_fx_2(ctx, type->e.array.type, loc); - - case HLSL_CLASS_TEXTURE: -+ case HLSL_CLASS_SAMPLER: - switch (type->sampler_dim) - { - case HLSL_SAMPLER_DIM_1D: -@@ -1147,9 +1191,10 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type - } - break; - -- case HLSL_CLASS_PIXEL_SHADER: -- case HLSL_CLASS_SAMPLER: - case HLSL_CLASS_STRING: -+ return true; -+ -+ case HLSL_CLASS_PIXEL_SHADER: - case HLSL_CLASS_VERTEX_SHADER: - hlsl_fixme(ctx, loc, "Write fx 2.0 parameter class %#x.", type->class); - return false; -@@ -1257,19 +1302,18 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - object_count = put_u32(structured, 0); - - write_fx_2_parameters(&fx); -- set_u32(structured, parameter_count, fx.parameter_count); -- set_u32(structured, object_count, fx.object_variable_count); -- - write_techniques(ctx->globals, &fx); -- set_u32(structured, technique_count, fx.technique_count); -- set_u32(structured, shader_count, fx.shader_count); -- -- put_u32(structured, 0); /* String count */ -+ put_u32(structured, fx.object_variable_count - 1); - put_u32(structured, 0); /* Resource count */ - -- /* TODO: strings */ -+ bytecode_put_bytes(structured, fx.objects.data, fx.objects.size); - /* TODO: resources */ - -+ set_u32(structured, parameter_count, fx.parameter_count); -+ set_u32(structured, object_count, fx.object_variable_count); -+ set_u32(structured, technique_count, fx.technique_count); -+ set_u32(structured, shader_count, fx.shader_count); -+ - size = align(fx.unstructured.size, 4); - set_u32(&buffer, offset, size); - -@@ -1278,6 +1322,7 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - - vkd3d_free(fx.unstructured.data); - vkd3d_free(fx.structured.data); -+ vkd3d_free(fx.objects.data); - - if (!fx.technique_count) - hlsl_error(ctx, &ctx->location, VKD3D_SHADER_ERROR_HLSL_MISSING_TECHNIQUE, "No techniques found."); -@@ -1516,11 +1561,14 @@ static uint32_t write_fx_4_state_numeric_value(struct hlsl_ir_constant *value, s - static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry, - struct fx_write_context *fx) - { -- uint32_t value_offset = 0, assignment_type = 0, rhs_offset; -- uint32_t type_offset; -+ uint32_t value_offset = 0, assignment_type = 0, rhs_offset, type_offset, offset; -+ struct vkd3d_bytecode_buffer *unstructured = &fx->unstructured; - struct vkd3d_bytecode_buffer *buffer = &fx->structured; -- struct hlsl_ctx *ctx = fx->ctx; - struct hlsl_ir_node *value = entry->args->node; -+ struct hlsl_ctx *ctx = fx->ctx; -+ struct hlsl_ir_var *index_var; -+ struct hlsl_ir_constant *c; -+ struct hlsl_ir_load *load; - - put_u32(buffer, entry->name_id); - put_u32(buffer, entry->lhs_index); -@@ -1531,7 +1579,7 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl - { - case HLSL_IR_CONSTANT: - { -- struct hlsl_ir_constant *c = hlsl_ir_constant(value); -+ c = hlsl_ir_constant(value); - - value_offset = write_fx_4_state_numeric_value(c, fx); - assignment_type = 1; -@@ -1539,15 +1587,71 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl - } - case HLSL_IR_LOAD: - { -- struct hlsl_ir_load *l = hlsl_ir_load(value); -+ load = hlsl_ir_load(value); - -- if (l->src.path_len) -+ if (load->src.path_len) - hlsl_fixme(ctx, &var->loc, "Indexed access in RHS values is not implemented."); - -- value_offset = write_fx_4_string(l->src.var->name, fx); -+ value_offset = write_fx_4_string(load->src.var->name, fx); - assignment_type = 2; - break; - } -+ case HLSL_IR_INDEX: -+ { -+ struct hlsl_ir_index *index = hlsl_ir_index(value); -+ struct hlsl_ir_node *val = index->val.node; -+ struct hlsl_ir_node *idx = index->idx.node; -+ struct hlsl_type *type; -+ -+ if (val->type != HLSL_IR_LOAD) -+ { -+ hlsl_fixme(ctx, &var->loc, "Unexpected indexed RHS value type."); -+ break; -+ } -+ -+ load = hlsl_ir_load(val); -+ value_offset = write_fx_4_string(load->src.var->name, fx); -+ type = load->src.var->data_type; -+ -+ switch (idx->type) -+ { -+ case HLSL_IR_CONSTANT: -+ { -+ c = hlsl_ir_constant(idx); -+ value_offset = put_u32(unstructured, value_offset); -+ put_u32(unstructured, c->value.u[0].u); -+ assignment_type = 3; -+ -+ if (c->value.u[0].u >= type->e.array.elements_count) -+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS, -+ "Array index %u exceeds array size %u.", c->value.u[0].u, type->e.array.elements_count); -+ break; -+ } -+ -+ case HLSL_IR_LOAD: -+ { -+ load = hlsl_ir_load(idx); -+ index_var = load->src.var; -+ -+ /* Special case for uint index variables, for anything more complex use an expression. */ -+ if (hlsl_types_are_equal(index_var->data_type, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT)) -+ && !load->src.path_len) -+ { -+ offset = write_fx_4_string(index_var->name, fx); -+ -+ value_offset = put_u32(unstructured, value_offset); -+ put_u32(unstructured, offset); -+ assignment_type = 4; -+ break; -+ } -+ } -+ /* fall through */ -+ -+ default: -+ hlsl_fixme(ctx, &var->loc, "Complex array index expressions in RHS values are not implemented."); -+ } -+ break; -+ } - default: - hlsl_fixme(ctx, &var->loc, "Unsupported assignment type for state %s.", entry->name); - } -@@ -2196,7 +2300,7 @@ static unsigned int decompose_fx_4_state_function_call(struct hlsl_ir_var *var, - const struct function_component *comp = &components[i]; - unsigned int arg_index = (i + 1) % entry->args_count; - block->entries[entry_index + i] = clone_stateblock_entry(ctx, entry, comp->name, -- comp->lhs_has_index, comp->lhs_index, arg_index); -+ comp->lhs_has_index, comp->lhs_index, true, arg_index); - } - hlsl_free_state_block_entry(entry); - -@@ -2242,7 +2346,7 @@ static unsigned int decompose_fx_4_state_block_expand_array(struct hlsl_ir_var * - for (i = 1; i < array_size; ++i) - { - block->entries[entry_index + i] = clone_stateblock_entry(ctx, entry, -- entry->name, true, i, 0); -+ entry->name, true, i, true, 0); - } - - return array_size; -diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index 26fd4818970..e2bcca56f05 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/glsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -365,18 +365,21 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( - { - const struct vkd3d_shader_register *dst_reg = &dst->vsir->reg; - struct vkd3d_string_buffer *buffer = gen->buffer; -+ uint32_t modifiers = dst->vsir->modifiers; - bool close = true; - va_list args; - - if (dst->vsir->shift) - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled destination shift %#x.", dst->vsir->shift); -- if (dst->vsir->modifiers) -+ if (modifiers & ~VKD3DSPDM_SATURATE) - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -- "Internal compiler error: Unhandled destination modifier(s) %#x.", dst->vsir->modifiers); -+ "Internal compiler error: Unhandled destination modifier(s) %#x.", modifiers); - - shader_glsl_print_indent(buffer, gen->indent); - vkd3d_string_buffer_printf(buffer, "%s%s = ", dst->register_name->buffer, dst->mask->buffer); -+ if (modifiers & VKD3DSPDM_SATURATE) -+ vkd3d_string_buffer_printf(buffer, "clamp("); - - switch (dst_reg->data_type) - { -@@ -399,7 +402,11 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( - vkd3d_string_buffer_vprintf(buffer, format, args); - va_end(args); - -- vkd3d_string_buffer_printf(buffer, "%s;\n", close ? ")" : ""); -+ if (close) -+ vkd3d_string_buffer_printf(buffer, ")"); -+ if (modifiers & VKD3DSPDM_SATURATE) -+ vkd3d_string_buffer_printf(buffer, ", 0.0, 1.0)"); -+ vkd3d_string_buffer_printf(buffer, ";\n"); - } - - static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) -@@ -455,16 +462,24 @@ static void shader_glsl_dot(struct vkd3d_glsl_generator *gen, - static void shader_glsl_intrinsic(struct vkd3d_glsl_generator *gen, - const struct vkd3d_shader_instruction *ins, const char *op) - { -+ struct vkd3d_string_buffer *args; - struct glsl_src src; - struct glsl_dst dst; -+ unsigned int i; - uint32_t mask; - - mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); -- glsl_src_init(&src, gen, &ins->src[0], mask); -+ args = vkd3d_string_buffer_get(&gen->string_buffers); - -- shader_glsl_print_assignment(gen, &dst, "%s(%s)", op, src.str->buffer); -+ for (i = 0; i < ins->src_count; ++i) -+ { -+ glsl_src_init(&src, gen, &ins->src[i], mask); -+ vkd3d_string_buffer_printf(args, "%s%s", i ? ", " : "", src.str->buffer); -+ glsl_src_cleanup(&src, &gen->string_buffers); -+ } -+ shader_glsl_print_assignment(gen, &dst, "%s(%s)", op, args->buffer); - -- glsl_src_cleanup(&src, &gen->string_buffers); -+ vkd3d_string_buffer_release(&gen->string_buffers, args); - glsl_dst_cleanup(&dst, &gen->string_buffers); - } - -@@ -532,6 +547,13 @@ static void shader_glsl_if(struct vkd3d_glsl_generator *gen, const struct vkd3d_ - ++gen->indent; - } - -+static void shader_glsl_else(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ unsigned int i = 4 * (gen->indent - 1); -+ -+ vkd3d_string_buffer_printf(gen->buffer, "%*s}\n%*selse\n%*s{\n", i, "", i, "", i, ""); -+} -+ - static void shader_glsl_endif(struct vkd3d_glsl_generator *gen) - { - --gen->indent; -@@ -539,6 +561,22 @@ static void shader_glsl_endif(struct vkd3d_glsl_generator *gen) - vkd3d_string_buffer_printf(gen->buffer, "}\n"); - } - -+static void shader_glsl_unary_op(struct vkd3d_glsl_generator *gen, -+ const struct vkd3d_shader_instruction *ins, const char *op) -+{ -+ struct glsl_src src; -+ struct glsl_dst dst; -+ uint32_t mask; -+ -+ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); -+ glsl_src_init(&src, gen, &ins->src[0], mask); -+ -+ shader_glsl_print_assignment(gen, &dst, "%s%s", op, src.str->buffer); -+ -+ glsl_src_cleanup(&src, &gen->string_buffers); -+ glsl_dst_cleanup(&dst, &gen->string_buffers); -+} -+ - static void shader_glsl_mov(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) - { - struct glsl_src src; -@@ -757,6 +795,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_DP4: - shader_glsl_dot(gen, ins, VKD3DSP_WRITEMASK_ALL); - break; -+ case VKD3DSIH_ELSE: -+ shader_glsl_else(gen, ins); -+ break; - case VKD3DSIH_ENDIF: - shader_glsl_endif(gen); - break; -@@ -781,9 +822,25 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_IF: - shader_glsl_if(gen, ins); - break; -+ case VKD3DSIH_MAD: -+ shader_glsl_intrinsic(gen, ins, "fma"); -+ break; -+ case VKD3DSIH_ISHL: -+ shader_glsl_binop(gen, ins, "<<"); -+ break; -+ case VKD3DSIH_ISHR: -+ case VKD3DSIH_USHR: -+ shader_glsl_binop(gen, ins, ">>"); -+ break; - case VKD3DSIH_LTO: - shader_glsl_relop(gen, ins, "<", "lessThan"); - break; -+ case VKD3DSIH_MAX: -+ shader_glsl_intrinsic(gen, ins, "max"); -+ break; -+ case VKD3DSIH_MIN: -+ shader_glsl_intrinsic(gen, ins, "min"); -+ break; - case VKD3DSIH_INE: - case VKD3DSIH_NEU: - shader_glsl_relop(gen, ins, "!=", "notEqual"); -@@ -804,6 +861,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_MUL: - shader_glsl_binop(gen, ins, "*"); - break; -+ case VKD3DSIH_NOT: -+ shader_glsl_unary_op(gen, ins, "~"); -+ break; - case VKD3DSIH_OR: - shader_glsl_binop(gen, ins, "|"); - break; -@@ -822,6 +882,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_ROUND_Z: - shader_glsl_intrinsic(gen, ins, "trunc"); - break; -+ case VKD3DSIH_RSQ: -+ shader_glsl_intrinsic(gen, ins, "inversesqrt"); -+ break; - case VKD3DSIH_SQRT: - shader_glsl_intrinsic(gen, ins, "sqrt"); - break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index f4401bc5d89..ce3dd91f04f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -1907,6 +1907,59 @@ struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, enum hlsl_compile_ty - return &compile->node; - } - -+bool hlsl_state_block_add_entry(struct hlsl_state_block *state_block, -+ struct hlsl_state_block_entry *entry) -+{ -+ if (!vkd3d_array_reserve((void **)&state_block->entries, -+ &state_block->capacity, state_block->count + 1, -+ sizeof(*state_block->entries))) -+ return false; -+ -+ state_block->entries[state_block->count++] = entry; -+ return true; -+} -+ -+struct hlsl_ir_node *hlsl_new_sampler_state(struct hlsl_ctx *ctx, -+ const struct hlsl_state_block *state_block, struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_ir_sampler_state *sampler_state; -+ struct hlsl_type *type = ctx->builtin_types.sampler[HLSL_SAMPLER_DIM_GENERIC]; -+ -+ if (!(sampler_state = hlsl_alloc(ctx, sizeof(*sampler_state)))) -+ return NULL; -+ -+ init_node(&sampler_state->node, HLSL_IR_SAMPLER_STATE, type, loc); -+ -+ if (!(sampler_state->state_block = hlsl_alloc(ctx, sizeof(*sampler_state->state_block)))) -+ { -+ vkd3d_free(sampler_state); -+ return NULL; -+ } -+ -+ if (state_block) -+ { -+ for (unsigned int i = 0; i < state_block->count; ++i) -+ { -+ const struct hlsl_state_block_entry *src = state_block->entries[i]; -+ struct hlsl_state_block_entry *entry; -+ -+ if (!(entry = clone_stateblock_entry(ctx, src, src->name, src->lhs_has_index, src->lhs_index, false, 0))) -+ { -+ hlsl_free_instr(&sampler_state->node); -+ return NULL; -+ } -+ -+ if (!hlsl_state_block_add_entry(sampler_state->state_block, entry)) -+ { -+ hlsl_free_instr(&sampler_state->node); -+ return NULL; -+ } -+ } -+ } -+ -+ return &sampler_state->node; -+} -+ - struct hlsl_ir_node *hlsl_new_stateblock_constant(struct hlsl_ctx *ctx, const char *name, - struct vkd3d_shader_location *loc) - { -@@ -2295,6 +2348,13 @@ static struct hlsl_ir_node *clone_compile(struct hlsl_ctx *ctx, - return node; - } - -+static struct hlsl_ir_node *clone_sampler_state(struct hlsl_ctx *ctx, -+ struct clone_instr_map *map, struct hlsl_ir_sampler_state *sampler_state) -+{ -+ return hlsl_new_sampler_state(ctx, sampler_state->state_block, -+ &sampler_state->node.loc); -+} -+ - static struct hlsl_ir_node *clone_stateblock_constant(struct hlsl_ctx *ctx, - struct clone_instr_map *map, struct hlsl_ir_stateblock_constant *constant) - { -@@ -2302,8 +2362,8 @@ static struct hlsl_ir_node *clone_stateblock_constant(struct hlsl_ctx *ctx, - } - - struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx, -- struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index, -- unsigned int lhs_index, unsigned int arg_index) -+ const struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index, -+ unsigned int lhs_index, bool single_arg, unsigned int arg_index) - { - struct hlsl_state_block_entry *entry; - struct clone_instr_map map = { 0 }; -@@ -2319,7 +2379,11 @@ struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx, - return NULL; - } - -- entry->args_count = 1; -+ if (single_arg) -+ entry->args_count = 1; -+ else -+ entry->args_count = src->args_count; -+ - if (!(entry->args = hlsl_alloc(ctx, sizeof(*entry->args) * entry->args_count))) - { - hlsl_free_state_block_entry(entry); -@@ -2332,7 +2396,16 @@ struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx, - hlsl_free_state_block_entry(entry); - return NULL; - } -- clone_src(&map, entry->args, &src->args[arg_index]); -+ -+ if (single_arg) -+ { -+ clone_src(&map, entry->args, &src->args[arg_index]); -+ } -+ else -+ { -+ for (unsigned int i = 0; i < src->args_count; ++i) -+ clone_src(&map, &entry->args[i], &src->args[i]); -+ } - vkd3d_free(map.instrs); - - return entry; -@@ -2440,6 +2513,9 @@ static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx, - case HLSL_IR_COMPILE: - return clone_compile(ctx, map, hlsl_ir_compile(instr)); - -+ case HLSL_IR_SAMPLER_STATE: -+ return clone_sampler_state(ctx, map, hlsl_ir_sampler_state(instr)); -+ - case HLSL_IR_STATEBLOCK_CONSTANT: - return clone_stateblock_constant(ctx, map, hlsl_ir_stateblock_constant(instr)); - } -@@ -2860,6 +2936,7 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type) - [HLSL_IR_SWIZZLE ] = "HLSL_IR_SWIZZLE", - - [HLSL_IR_COMPILE] = "HLSL_IR_COMPILE", -+ [HLSL_IR_SAMPLER_STATE] = "HLSL_IR_SAMPLER_STATE", - [HLSL_IR_STATEBLOCK_CONSTANT] = "HLSL_IR_STATEBLOCK_CONSTANT", - }; - -@@ -3337,6 +3414,12 @@ static void dump_ir_compile(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *bu - vkd3d_string_buffer_printf(buffer, ")"); - } - -+static void dump_ir_sampler_state(struct vkd3d_string_buffer *buffer, -+ const struct hlsl_ir_sampler_state *sampler_state) -+{ -+ vkd3d_string_buffer_printf(buffer, "sampler_state {...}"); -+} -+ - static void dump_ir_stateblock_constant(struct vkd3d_string_buffer *buffer, - const struct hlsl_ir_stateblock_constant *constant) - { -@@ -3440,6 +3523,10 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, - dump_ir_compile(ctx, buffer, hlsl_ir_compile(instr)); - break; - -+ case HLSL_IR_SAMPLER_STATE: -+ dump_ir_sampler_state(buffer, hlsl_ir_sampler_state(instr)); -+ break; -+ - case HLSL_IR_STATEBLOCK_CONSTANT: - dump_ir_stateblock_constant(buffer, hlsl_ir_stateblock_constant(instr)); - break; -@@ -3665,6 +3752,13 @@ static void free_ir_compile(struct hlsl_ir_compile *compile) - vkd3d_free(compile); - } - -+static void free_ir_sampler_state(struct hlsl_ir_sampler_state *sampler_state) -+{ -+ if (sampler_state->state_block) -+ hlsl_free_state_block(sampler_state->state_block); -+ vkd3d_free(sampler_state); -+} -+ - static void free_ir_stateblock_constant(struct hlsl_ir_stateblock_constant *constant) - { - vkd3d_free(constant->name); -@@ -3737,6 +3831,10 @@ void hlsl_free_instr(struct hlsl_ir_node *node) - free_ir_compile(hlsl_ir_compile(node)); - break; - -+ case HLSL_IR_SAMPLER_STATE: -+ free_ir_sampler_state(hlsl_ir_sampler_state(node)); -+ break; -+ - case HLSL_IR_STATEBLOCK_CONSTANT: - free_ir_stateblock_constant(hlsl_ir_stateblock_constant(node)); - break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index b8678962f67..4082b14fe04 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -326,6 +326,7 @@ enum hlsl_ir_node_type - HLSL_IR_SWITCH, - - HLSL_IR_COMPILE, -+ HLSL_IR_SAMPLER_STATE, - HLSL_IR_STATEBLOCK_CONSTANT, - }; - -@@ -899,6 +900,14 @@ struct hlsl_ir_compile - unsigned int args_count; - }; - -+/* Represents a state block initialized with the "sampler_state" keyword. */ -+struct hlsl_ir_sampler_state -+{ -+ struct hlsl_ir_node node; -+ -+ struct hlsl_state_block *state_block; -+}; -+ - /* Stateblock constants are undeclared values found on state blocks or technique passes descriptions, - * that do not concern regular pixel, vertex, or compute shaders, except for parsing. */ - struct hlsl_ir_stateblock_constant -@@ -1212,6 +1221,12 @@ static inline struct hlsl_ir_compile *hlsl_ir_compile(const struct hlsl_ir_node - return CONTAINING_RECORD(node, struct hlsl_ir_compile, node); - } - -+static inline struct hlsl_ir_sampler_state *hlsl_ir_sampler_state(const struct hlsl_ir_node *node) -+{ -+ VKD3D_ASSERT(node->type == HLSL_IR_SAMPLER_STATE); -+ return CONTAINING_RECORD(node, struct hlsl_ir_sampler_state, node); -+}; -+ - static inline struct hlsl_ir_stateblock_constant *hlsl_ir_stateblock_constant(const struct hlsl_ir_node *node) - { - VKD3D_ASSERT(node->type == HLSL_IR_STATEBLOCK_CONSTANT); -@@ -1396,12 +1411,15 @@ bool hlsl_clone_block(struct hlsl_ctx *ctx, struct hlsl_block *dst_block, const - void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func); - void hlsl_dump_var_default_values(const struct hlsl_ir_var *var); - -+bool hlsl_state_block_add_entry(struct hlsl_state_block *state_block, -+ struct hlsl_state_block_entry *entry); - bool hlsl_validate_state_block_entry(struct hlsl_ctx *ctx, struct hlsl_state_block_entry *entry, - const struct vkd3d_shader_location *loc); - struct hlsl_state_block_entry *clone_stateblock_entry(struct hlsl_ctx *ctx, -- struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index, -- unsigned int lhs_index, unsigned int arg_index); -+ const struct hlsl_state_block_entry *src, const char *name, bool lhs_has_index, -+ unsigned int lhs_index, bool single_arg, unsigned int arg_index); - -+void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body); - void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body); - int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, - enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out); -@@ -1509,6 +1527,8 @@ struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name, - struct hlsl_struct_field *fields, size_t field_count); - struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int components, - struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc); -+struct hlsl_ir_node *hlsl_new_sampler_state(struct hlsl_ctx *ctx, -+ const struct hlsl_state_block *state_block, struct vkd3d_shader_location *loc); - struct hlsl_ir_node *hlsl_new_stateblock_constant(struct hlsl_ctx *ctx, const char *name, - struct vkd3d_shader_location *loc); - struct hlsl_ir_node *hlsl_new_string_constant(struct hlsl_ctx *ctx, const char *str, -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index c39f2020ef7..b4d9f0988b0 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -437,6 +437,9 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct - if (hlsl_types_are_equal(src_type, dst_type)) - return node; - -+ if (node->type == HLSL_IR_SAMPLER_STATE && dst_type->class == HLSL_CLASS_SAMPLER) -+ return node; -+ - if (!implicit_compatible_data_types(ctx, src_type, dst_type)) - { - struct vkd3d_string_buffer *src_string, *dst_string; -@@ -613,6 +616,7 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx - case HLSL_IR_COMPILE: - case HLSL_IR_CONSTANT: - case HLSL_IR_EXPR: -+ case HLSL_IR_SAMPLER_STATE: - case HLSL_IR_STRING_CONSTANT: - case HLSL_IR_SWIZZLE: - case HLSL_IR_LOAD: -@@ -648,6 +652,7 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx - - /* Wrap the node into a src to allow the reference to survive the multiple const passes. */ - hlsl_src_from_node(&src, node); -+ hlsl_lower_index_loads(ctx, &expr); - hlsl_run_const_passes(ctx, &expr); - node = src.node; - hlsl_src_remove(&src); -@@ -2324,55 +2329,6 @@ static bool add_increment(struct hlsl_ctx *ctx, struct hlsl_block *block, bool d - return true; - } - --/* For some reason, for matrices, values from default value initializers end up in different -- * components than from regular initializers. Default value initializers fill the matrix in -- * vertical reading order (left-to-right top-to-bottom) instead of regular reading order -- * (top-to-bottom left-to-right), so they have to be adjusted. -- * An exception is that the order of matrix initializers for function parameters are row-major -- * (top-to-bottom left-to-right). */ --static unsigned int get_component_index_from_default_initializer_index(struct hlsl_ctx *ctx, -- struct hlsl_type *type, unsigned int index) --{ -- unsigned int element_comp_count, element, x, y, i; -- unsigned int base = 0; -- -- if (ctx->profile->major_version < 4) -- return index; -- -- if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT) -- return index; -- -- switch (type->class) -- { -- case HLSL_CLASS_MATRIX: -- x = index / type->dimy; -- y = index % type->dimy; -- return y * type->dimx + x; -- -- case HLSL_CLASS_ARRAY: -- element_comp_count = hlsl_type_component_count(type->e.array.type); -- element = index / element_comp_count; -- base = element * element_comp_count; -- return base + get_component_index_from_default_initializer_index(ctx, type->e.array.type, index - base); -- -- case HLSL_CLASS_STRUCT: -- for (i = 0; i < type->e.record.field_count; ++i) -- { -- struct hlsl_type *field_type = type->e.record.fields[i].type; -- -- element_comp_count = hlsl_type_component_count(field_type); -- if (index - base < element_comp_count) -- return base + get_component_index_from_default_initializer_index(ctx, field_type, index - base); -- base += element_comp_count; -- } -- break; -- -- default: -- return index; -- } -- vkd3d_unreachable(); --} -- - static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *instrs, - struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src, - bool is_default_values_initializer) -@@ -2397,11 +2353,10 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i - if (is_default_values_initializer) - { - struct hlsl_default_value default_value = {0}; -- unsigned int dst_index; - - if (hlsl_is_numeric_type(dst_comp_type)) - { -- if (src->type == HLSL_IR_COMPILE) -+ if (src->type == HLSL_IR_COMPILE || src->type == HLSL_IR_SAMPLER_STATE) - { - /* Default values are discarded if they contain an object - * literal expression for a numeric component. */ -@@ -2420,13 +2375,8 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i - return; - default_value = evaluate_static_expression(ctx, &block, dst_comp_type, &src->loc); - -- if (dst->is_param) -- dst_index = *store_index; -- else -- dst_index = get_component_index_from_default_initializer_index(ctx, dst->data_type, *store_index); -- - if (dst->default_values) -- dst->default_values[dst_index] = default_value; -+ dst->default_values[*store_index] = default_value; - - hlsl_block_cleanup(&block); - } -@@ -2434,12 +2384,41 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i - } - else - { -- if (!(conv = add_implicit_conversion(ctx, instrs, load, dst_comp_type, &src->loc))) -- return; -+ if (src->type == HLSL_IR_SAMPLER_STATE) -+ { -+ /* Sampler states end up in the variable's state_blocks instead of -+ * being used to initialize its value. */ -+ struct hlsl_ir_sampler_state *sampler_state = hlsl_ir_sampler_state(src); -+ -+ if (dst_comp_type->class != HLSL_CLASS_SAMPLER) -+ { -+ struct vkd3d_string_buffer *dst_string; -+ -+ dst_string = hlsl_type_to_string(ctx, dst_comp_type); -+ if (dst_string) -+ hlsl_error(ctx, &src->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -+ "Cannot assign sampler_state to %s.", dst_string->buffer); -+ hlsl_release_string_buffer(ctx, dst_string); -+ return; -+ } - -- if (!hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv)) -- return; -- hlsl_block_add_block(instrs, &block); -+ if (!hlsl_array_reserve(ctx, (void **)&dst->state_blocks, &dst->state_block_capacity, -+ dst->state_block_count + 1, sizeof(*dst->state_blocks))) -+ return; -+ -+ dst->state_blocks[dst->state_block_count] = sampler_state->state_block; -+ sampler_state->state_block = NULL; -+ ++dst->state_block_count; -+ } -+ else -+ { -+ if (!(conv = add_implicit_conversion(ctx, instrs, load, dst_comp_type, &src->loc))) -+ return; -+ -+ if (!hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv)) -+ return; -+ hlsl_block_add_block(instrs, &block); -+ } - } - - ++*store_index; -@@ -2778,6 +2757,8 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var - is_default_values_initializer = (ctx->cur_buffer != ctx->globals_buffer) - || (var->storage_modifiers & HLSL_STORAGE_UNIFORM) - || ctx->cur_scope->annotations; -+ if (hlsl_get_multiarray_element_type(type)->class == HLSL_CLASS_SAMPLER) -+ is_default_values_initializer = false; - if (hlsl_type_is_shader(type)) - is_default_values_initializer = false; - -@@ -2836,6 +2817,9 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var - { - hlsl_block_add_block(initializers, v->initializer.instrs); - } -+ -+ if (var->state_blocks) -+ TRACE("Variable %s has %u state blocks.\n", var->name, var->state_block_count); - } - else if (var->storage_modifiers & HLSL_STORAGE_STATIC) - { -@@ -6228,16 +6212,6 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, - hlsl_release_string_buffer(ctx, string); - } - --static bool state_block_add_entry(struct hlsl_state_block *state_block, struct hlsl_state_block_entry *entry) --{ -- if (!vkd3d_array_reserve((void **)&state_block->entries, &state_block->capacity, state_block->count + 1, -- sizeof(*state_block->entries))) -- return false; -- -- state_block->entries[state_block->count++] = entry; -- return true; --} -- - } - - %locations -@@ -7850,6 +7824,11 @@ stateblock_lhs_identifier: - if (!($$ = hlsl_strdup(ctx, "pixelshader"))) - YYABORT; - } -+ | KW_TEXTURE -+ { -+ if (!($$ = hlsl_strdup(ctx, "texture"))) -+ YYABORT; -+ } - | KW_VERTEXSHADER - { - if (!($$ = hlsl_strdup(ctx, "vertexshader"))) -@@ -7907,7 +7886,7 @@ state_block: - vkd3d_free($5.args); - - $$ = $1; -- state_block_add_entry($$, entry); -+ hlsl_state_block_add_entry($$, entry); - } - | state_block any_identifier '(' func_arguments ')' ';' - { -@@ -7935,7 +7914,7 @@ state_block: - hlsl_validate_state_block_entry(ctx, entry, &@4); - - $$ = $1; -- state_block_add_entry($$, entry); -+ hlsl_state_block_add_entry($$, entry); - } - - state_block_list: -@@ -8668,6 +8647,25 @@ primary_expr: - } - vkd3d_free($1); - } -+ | KW_SAMPLER_STATE '{' state_block_start state_block '}' -+ { -+ struct hlsl_ir_node *sampler_state; -+ ctx->in_state_block = 0; -+ -+ if (!ctx->in_state_block && ctx->cur_scope != ctx->globals) -+ hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_MISPLACED_SAMPLER_STATE, -+ "sampler_state must be in global scope or a state block."); -+ -+ if (!(sampler_state = hlsl_new_sampler_state(ctx, $4, &@1))) -+ { -+ hlsl_free_state_block($4); -+ YYABORT; -+ } -+ hlsl_free_state_block($4); -+ -+ if (!($$ = make_block(ctx, sampler_state))) -+ YYABORT; -+ } - | NEW_IDENTIFIER - { - if (ctx->in_state_block) -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index feab6cf06c1..c5dd5e71e02 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -4062,6 +4062,7 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) - case HLSL_IR_RESOURCE_LOAD: - case HLSL_IR_STRING_CONSTANT: - case HLSL_IR_SWIZZLE: -+ case HLSL_IR_SAMPLER_STATE: - if (list_empty(&instr->uses)) - { - list_remove(&instr->entry); -@@ -4344,7 +4345,8 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop - case HLSL_IR_STRING_CONSTANT: - break; - case HLSL_IR_COMPILE: -- /* Compile calls are skipped as they are only relevent to effects. */ -+ case HLSL_IR_SAMPLER_STATE: -+ /* These types are skipped as they are only relevant to effects. */ - break; - } - } -@@ -5206,7 +5208,8 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx) - } - } - --static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint32_t space, uint32_t index) -+static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, -+ uint32_t space, uint32_t index, bool allocated_only) - { - const struct hlsl_buffer *buffer; - -@@ -5214,7 +5217,12 @@ static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint3 - { - if (buffer->reservation.reg_type == 'b' - && buffer->reservation.reg_space == space && buffer->reservation.reg_index == index) -+ { -+ if (allocated_only && !buffer->reg.allocated) -+ continue; -+ - return buffer; -+ } - } - return NULL; - } -@@ -5397,8 +5405,8 @@ static void allocate_buffers(struct hlsl_ctx *ctx) - - if (reservation->reg_type == 'b') - { -- const struct hlsl_buffer *reserved_buffer = get_reserved_buffer(ctx, -- reservation->reg_space, reservation->reg_index); -+ const struct hlsl_buffer *allocated_buffer = get_reserved_buffer(ctx, -+ reservation->reg_space, reservation->reg_index, true); - unsigned int max_index = get_max_cbuffer_reg_index(ctx); - - if (buffer->reservation.reg_index > max_index) -@@ -5406,14 +5414,14 @@ static void allocate_buffers(struct hlsl_ctx *ctx) - "Buffer reservation cb%u exceeds target's maximum (cb%u).", - buffer->reservation.reg_index, max_index); - -- if (reserved_buffer && reserved_buffer != buffer) -+ if (allocated_buffer && allocated_buffer != buffer) - { - hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_OVERLAPPING_RESERVATIONS, - "Multiple buffers bound to space %u, index %u.", - reservation->reg_space, reservation->reg_index); -- hlsl_note(ctx, &reserved_buffer->loc, VKD3D_SHADER_LOG_ERROR, -+ hlsl_note(ctx, &allocated_buffer->loc, VKD3D_SHADER_LOG_ERROR, - "Buffer %s is already bound to space %u, index %u.", -- reserved_buffer->name, reservation->reg_space, reservation->reg_index); -+ allocated_buffer->name, reservation->reg_space, reservation->reg_index); - } - - buffer->reg.space = reservation->reg_space; -@@ -5430,12 +5438,12 @@ static void allocate_buffers(struct hlsl_ctx *ctx) - else if (!reservation->reg_type) - { - unsigned int max_index = get_max_cbuffer_reg_index(ctx); -- while (get_reserved_buffer(ctx, 0, index)) -+ while (get_reserved_buffer(ctx, 0, index, false)) - ++index; - - if (index > max_index) - hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, -- "Too many buffers allocated, target's maximum is %u.", max_index); -+ "Too many buffers reserved, target's maximum is %u.", max_index); - - buffer->reg.space = 0; - buffer->reg.index = index; -@@ -6178,12 +6186,16 @@ static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *bod - } - } - -+void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body) -+{ -+ lower_ir(ctx, lower_index_loads, body); -+} -+ - void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body) - { - bool progress; - - lower_ir(ctx, lower_matrix_swizzles, body); -- lower_ir(ctx, lower_index_loads, body); - - lower_ir(ctx, lower_broadcasts, body); - while (hlsl_transform_ir(ctx, fold_redundant_casts, body, NULL)); -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 88650a97068..2fe5472167f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -215,6 +215,14 @@ static void src_param_init_temp_float(struct vkd3d_shader_src_param *src, unsign - src->reg.idx[0].offset = idx; - } - -+static void src_param_init_temp_float4(struct vkd3d_shader_src_param *src, unsigned int idx) -+{ -+ vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); -+ src->reg.dimension = VSIR_DIMENSION_VEC4; -+ src->swizzle = VKD3D_SHADER_NO_SWIZZLE; -+ src->reg.idx[0].offset = idx; -+} -+ - static void src_param_init_temp_uint(struct vkd3d_shader_src_param *src, unsigned int idx) - { - vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); -@@ -1864,13 +1872,13 @@ static bool use_flat_interpolation(const struct vsir_program *program, - if (parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) - { - vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, -- "Unsupported flat interpolation parameter type %#x.\n", parameter->type); -+ "Unsupported flat interpolation parameter type %#x.", parameter->type); - return false; - } - if (parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) - { - vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -- "Invalid flat interpolation parameter data type %#x.\n", parameter->data_type); -+ "Invalid flat interpolation parameter data type %#x.", parameter->data_type); - return false; - } - -@@ -5539,9 +5547,11 @@ static bool find_colour_signature_idx(const struct shader_signature *signature, - - static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *program, - const struct vkd3d_shader_instruction *ret, enum vkd3d_shader_comparison_func compare_func, -- const struct vkd3d_shader_parameter1 *ref, uint32_t colour_signature_idx, uint32_t colour_temp, size_t *ret_pos) -+ const struct vkd3d_shader_parameter1 *ref, uint32_t colour_signature_idx, -+ uint32_t colour_temp, size_t *ret_pos, struct vkd3d_shader_message_context *message_context) - { - struct vkd3d_shader_instruction_array *instructions = &program->instructions; -+ static const struct vkd3d_shader_location no_loc; - size_t pos = ret - instructions->elements; - struct vkd3d_shader_instruction *ins; - -@@ -5596,6 +5606,11 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr - VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF, VKD3D_DATA_UINT); - break; - -+ case VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4: -+ vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER, -+ "Alpha test reference data type must be a single component."); -+ return VKD3D_ERROR_INVALID_ARGUMENT; -+ - default: - FIXME("Unhandled parameter data type %#x.\n", ref->data_type); - return VKD3D_ERROR_NOT_IMPLEMENTED; -@@ -5652,13 +5667,13 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro - if (func->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) - { - vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, -- "Unsupported alpha test function parameter type %#x.\n", func->type); -+ "Unsupported alpha test function parameter type %#x.", func->type); - return VKD3D_ERROR_NOT_IMPLEMENTED; - } - if (func->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) - { - vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -- "Invalid alpha test function parameter data type %#x.\n", func->data_type); -+ "Invalid alpha test function parameter data type %#x.", func->data_type); - return VKD3D_ERROR_INVALID_ARGUMENT; - } - compare_func = func->u.immediate_constant.u.u32; -@@ -5682,7 +5697,7 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro - if (ins->opcode == VKD3DSIH_RET) - { - if ((ret = insert_alpha_test_before_ret(program, ins, compare_func, -- ref, colour_signature_idx, colour_temp, &new_pos)) < 0) -+ ref, colour_signature_idx, colour_temp, &new_pos, message_context)) < 0) - return ret; - i = new_pos; - continue; -@@ -5709,6 +5724,202 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro - return VKD3D_OK; - } - -+static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *program, -+ const struct vkd3d_shader_instruction *ret, uint32_t mask, uint32_t position_signature_idx, -+ uint32_t position_temp, uint32_t low_signature_idx, uint32_t high_signature_idx, size_t *ret_pos) -+{ -+ struct vkd3d_shader_instruction_array *instructions = &program->instructions; -+ size_t pos = ret - instructions->elements; -+ struct vkd3d_shader_instruction *ins; -+ unsigned int output_idx = 0; -+ -+ if (!shader_instruction_array_insert_at(&program->instructions, pos, vkd3d_popcount(mask) + 1)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ ins = &program->instructions.elements[pos]; -+ -+ for (unsigned int i = 0; i < 8; ++i) -+ { -+ if (!(mask & (1u << i))) -+ continue; -+ -+ vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_DP4, 1, 2); -+ src_param_init_temp_float4(&ins->src[0], position_temp); -+ src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 + i, VKD3D_DATA_FLOAT); -+ ins->src[1].swizzle = VKD3D_SHADER_NO_SWIZZLE; -+ ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; -+ -+ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); -+ if (output_idx < 4) -+ ins->dst[0].reg.idx[0].offset = low_signature_idx; -+ else -+ ins->dst[0].reg.idx[0].offset = high_signature_idx; -+ ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->dst[0].write_mask = (1u << (output_idx % 4)); -+ ++output_idx; -+ -+ ++ins; -+ } -+ -+ vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_MOV, 1, 1); -+ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); -+ ins->dst[0].reg.idx[0].offset = position_signature_idx; -+ ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->dst[0].write_mask = program->output_signature.elements[position_signature_idx].mask; -+ src_param_init_temp_float(&ins->src[0], position_temp); -+ ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; -+ -+ *ret_pos = pos + vkd3d_popcount(mask) + 1; -+ return VKD3D_OK; -+} -+ -+static bool find_position_signature_idx(const struct shader_signature *signature, uint32_t *idx) -+{ -+ for (unsigned int i = 0; i < signature->element_count; ++i) -+ { -+ if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_POSITION) -+ { -+ *idx = i; -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *program, -+ struct vsir_transformation_context *ctx) -+{ -+ struct shader_signature *signature = &program->output_signature; -+ unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u; -+ const struct vkd3d_shader_parameter1 *mask_parameter = NULL; -+ struct signature_element *new_elements, *clip_element; -+ uint32_t position_signature_idx, position_temp, mask; -+ static const struct vkd3d_shader_location no_loc; -+ struct vkd3d_shader_instruction *ins; -+ unsigned int plane_count; -+ size_t new_pos; -+ int ret; -+ -+ if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX) -+ return VKD3D_OK; -+ -+ for (unsigned int i = 0; i < program->parameter_count; ++i) -+ { -+ const struct vkd3d_shader_parameter1 *parameter = &program->parameters[i]; -+ -+ if (parameter->name == VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK) -+ mask_parameter = parameter; -+ } -+ -+ if (!mask_parameter) -+ return VKD3D_OK; -+ -+ if (mask_parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) -+ { -+ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, -+ "Unsupported clip plane mask parameter type %#x.", mask_parameter->type); -+ return VKD3D_ERROR_NOT_IMPLEMENTED; -+ } -+ if (mask_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) -+ { -+ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -+ "Invalid clip plane mask parameter data type %#x.", mask_parameter->data_type); -+ return VKD3D_ERROR_INVALID_ARGUMENT; -+ } -+ mask = mask_parameter->u.immediate_constant.u.u32; -+ -+ if (!mask) -+ return VKD3D_OK; -+ -+ for (unsigned int i = 0; i < signature->element_count; ++i) -+ { -+ if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_CLIP_DISTANCE) -+ { -+ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER, -+ "Clip planes cannot be used if the shader writes clip distance."); -+ return VKD3D_ERROR_INVALID_ARGUMENT; -+ } -+ } -+ -+ if (!find_position_signature_idx(signature, &position_signature_idx)) -+ { -+ vkd3d_shader_error(ctx->message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC, -+ "Shader does not write position."); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ -+ /* Append the clip plane signature indices. */ -+ -+ plane_count = vkd3d_popcount(mask); -+ -+ if (!(new_elements = vkd3d_realloc(signature->elements, -+ (signature->element_count + 2) * sizeof(*signature->elements)))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ signature->elements = new_elements; -+ -+ low_signature_idx = signature->element_count; -+ clip_element = &signature->elements[signature->element_count++]; -+ memset(clip_element, 0, sizeof(*clip_element)); -+ clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; -+ clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; -+ clip_element->register_count = 1; -+ clip_element->mask = vkd3d_write_mask_from_component_count(min(plane_count, 4)); -+ clip_element->used_mask = clip_element->mask; -+ clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; -+ -+ if (plane_count > 4) -+ { -+ high_signature_idx = signature->element_count; -+ clip_element = &signature->elements[signature->element_count++]; -+ memset(clip_element, 0, sizeof(*clip_element)); -+ clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; -+ clip_element->semantic_index = 1; -+ clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; -+ clip_element->register_count = 1; -+ clip_element->mask = vkd3d_write_mask_from_component_count(plane_count - 4); -+ clip_element->used_mask = clip_element->mask; -+ clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; -+ } -+ -+ /* We're going to be reading from the output position, so we need to go -+ * through the whole shader and convert it to a temp. */ -+ -+ position_temp = program->temp_count++; -+ -+ for (size_t i = 0; i < program->instructions.count; ++i) -+ { -+ ins = &program->instructions.elements[i]; -+ -+ if (vsir_instruction_is_dcl(ins)) -+ continue; -+ -+ if (ins->opcode == VKD3DSIH_RET) -+ { -+ if ((ret = insert_clip_planes_before_ret(program, ins, mask, position_signature_idx, -+ position_temp, low_signature_idx, high_signature_idx, &new_pos)) < 0) -+ return ret; -+ i = new_pos; -+ continue; -+ } -+ -+ for (size_t j = 0; j < ins->dst_count; ++j) -+ { -+ struct vkd3d_shader_dst_param *dst = &ins->dst[j]; -+ -+ /* Note we run after I/O normalization. */ -+ if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == position_signature_idx) -+ { -+ dst->reg.type = VKD3DSPR_TEMP; -+ dst->reg.idx[0].offset = position_temp; -+ } -+ } -+ } -+ -+ return VKD3D_OK; -+} -+ - struct validation_context - { - struct vkd3d_shader_message_context *message_context; -@@ -6012,6 +6223,63 @@ static void vsir_validate_register(struct validation_context *ctx, - reg->dimension); - break; - -+ case VKD3DSPR_DEPTHOUT: -+ if (reg->idx_count != 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, -+ "Invalid index count %u for a DEPTHOUT register.", -+ reg->idx_count); -+ break; -+ -+ case VKD3DSPR_DEPTHOUTGE: -+ if (reg->idx_count != 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, -+ "Invalid index count %u for a DEPTHOUTGE register.", -+ reg->idx_count); -+ break; -+ -+ case VKD3DSPR_DEPTHOUTLE: -+ if (reg->idx_count != 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, -+ "Invalid index count %u for a DEPTHOUTLE register.", -+ reg->idx_count); -+ break; -+ -+ case VKD3DSPR_RASTOUT: -+ if (reg->idx_count != 1) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, -+ "Invalid index count %u for a RASTOUT register.", -+ reg->idx_count); -+ break; -+ } -+ -+ if (reg->idx[0].rel_addr) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "Non-NULL relative address for a RASTOUT register."); -+ -+ if (reg->idx[0].offset >= 3) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "Invalid offset for a RASTOUT register."); -+ break; -+ -+ case VKD3DSPR_MISCTYPE: -+ if (reg->idx_count != 1) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, -+ "Invalid index count %u for a MISCTYPE register.", -+ reg->idx_count); -+ break; -+ } -+ -+ if (reg->idx[0].rel_addr) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "Non-NULL relative address for a MISCTYPE register."); -+ -+ if (reg->idx[0].offset >= 2) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "Invalid offset for a MISCTYPE register."); -+ break; -+ - default: - break; - } -@@ -6842,6 +7110,7 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t - } - - vsir_transform(&ctx, vsir_program_insert_alpha_test); -+ vsir_transform(&ctx, vsir_program_insert_clip_planes); - - if (TRACE_ON()) - vkd3d_shader_trace(program); -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 0278a6ca232..11c054a28f5 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -1228,6 +1228,13 @@ static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_build - SpvOpConstantComposite, result_type, constituents, constituent_count); - } - -+static uint32_t vkd3d_spirv_build_op_spec_constant_composite(struct vkd3d_spirv_builder *builder, -+ uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) -+{ -+ return vkd3d_spirv_build_op_trv(builder, &builder->global_stream, -+ SpvOpSpecConstantComposite, result_type, constituents, constituent_count); -+} -+ - static uint32_t vkd3d_spirv_get_op_constant_composite(struct vkd3d_spirv_builder *builder, - uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) - { -@@ -3324,8 +3331,10 @@ static const struct vkd3d_spec_constant_info *get_spec_constant_info(enum vkd3d_ - return NULL; - } - --static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *compiler) -+static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *compiler, unsigned int count) - { -+ uint32_t ret; -+ - if (!compiler->current_spec_constant_id) - { - unsigned int i, id = 0; -@@ -3335,28 +3344,52 @@ static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *com - const struct vkd3d_shader_parameter1 *current = &compiler->program->parameters[i]; - - if (current->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT) -- id = max(current->u.specialization_constant.id + 1, id); -+ { -+ switch (current->data_type) -+ { -+ case VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4: -+ id = max(current->u.specialization_constant.id + 4, id); -+ break; -+ -+ default: -+ id = max(current->u.specialization_constant.id + 1, id); -+ break; -+ } -+ } - } - - compiler->current_spec_constant_id = id; - } - -- return compiler->current_spec_constant_id++; -+ ret = compiler->current_spec_constant_id; -+ compiler->current_spec_constant_id += count; -+ return ret; - } - - static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compiler, -- enum vkd3d_shader_parameter_name name, uint32_t spec_id, enum vkd3d_data_type type) -+ enum vkd3d_shader_parameter_name name, uint32_t spec_id, -+ enum vkd3d_data_type type, unsigned int component_count) - { -+ uint32_t scalar_type_id, vector_type_id, id, default_value, components[4]; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_spec_constant_info *info; -- uint32_t type_id, id, default_value; - - info = get_spec_constant_info(name); - default_value = info ? info->default_value : 0; - -- type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1); -- id = vkd3d_spirv_build_op_spec_constant(builder, type_id, default_value); -- vkd3d_spirv_build_op_decorate1(builder, id, SpvDecorationSpecId, spec_id); -+ scalar_type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1); -+ vector_type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), component_count); -+ -+ for (unsigned int i = 0; i < component_count; ++i) -+ { -+ components[i] = vkd3d_spirv_build_op_spec_constant(builder, scalar_type_id, default_value); -+ vkd3d_spirv_build_op_decorate1(builder, components[i], SpvDecorationSpecId, spec_id + i); -+ } -+ -+ if (component_count == 1) -+ id = components[0]; -+ else -+ id = vkd3d_spirv_build_op_spec_constant_composite(builder, vector_type_id, components, component_count); - - if (info) - vkd3d_spirv_build_op_name(builder, id, "%s", info->debug_name); -@@ -3373,7 +3406,8 @@ static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compile - } - - static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler, -- enum vkd3d_shader_parameter_name name, uint32_t spec_id, enum vkd3d_data_type type) -+ enum vkd3d_shader_parameter_name name, uint32_t spec_id, -+ enum vkd3d_data_type type, unsigned int component_count) - { - unsigned int i; - -@@ -3383,17 +3417,17 @@ static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler - return compiler->spec_constants[i].id; - } - -- return spirv_compiler_emit_spec_constant(compiler, name, spec_id, type); -+ return spirv_compiler_emit_spec_constant(compiler, name, spec_id, type, component_count); - } - - static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compiler, -- const struct vkd3d_shader_parameter1 *parameter, enum vkd3d_data_type type) -+ const struct vkd3d_shader_parameter1 *parameter, enum vkd3d_data_type type, unsigned int component_count) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - unsigned int index = parameter - compiler->program->parameters; - uint32_t type_id, ptr_id, ptr_type_id; - -- type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), 1); -+ type_id = vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(type), component_count); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id); - ptr_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, - compiler->spirv_parameter_info[index].buffer_id, -@@ -3401,48 +3435,49 @@ static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compi - return vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone); - } - -+static const struct -+{ -+ enum vkd3d_data_type type; -+ unsigned int component_count; -+} -+parameter_data_type_map[] = -+{ -+ [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32] = {VKD3D_DATA_FLOAT, 1}, -+ [VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32] = {VKD3D_DATA_UINT, 1}, -+ [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4] = {VKD3D_DATA_FLOAT, 4}, -+}; -+ - static uint32_t spirv_compiler_emit_shader_parameter(struct spirv_compiler *compiler, -- enum vkd3d_shader_parameter_name name, enum vkd3d_data_type type) -+ enum vkd3d_shader_parameter_name name, enum vkd3d_data_type type, unsigned int component_count) - { - const struct vkd3d_shader_parameter1 *parameter; - -- static const struct -- { -- enum vkd3d_data_type type; -- } -- type_map[] = -- { -- [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32] = {VKD3D_DATA_FLOAT}, -- [VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32] = {VKD3D_DATA_UINT}, -- }; -- - if (!(parameter = vsir_program_get_parameter(compiler->program, name))) - { - WARN("Unresolved shader parameter %#x.\n", name); - goto default_parameter; - } - -- if (type_map[parameter->data_type].type != type) -- ERR("Expected data type %#x for parameter %#x, got %#x.\n", type, name, parameter->data_type); -+ if (parameter_data_type_map[parameter->data_type].type != type -+ || parameter_data_type_map[parameter->data_type].component_count != component_count) -+ ERR("Expected type %#x, count %u for parameter %#x, got %#x.\n", -+ type, component_count, name, parameter->data_type); - - if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) -- { -- if (parameter->data_type == VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32) -- return spirv_compiler_get_constant_float(compiler, parameter->u.immediate_constant.u.f32); -- else -- return spirv_compiler_get_constant_uint(compiler, parameter->u.immediate_constant.u.u32); -- } -+ return spirv_compiler_get_constant(compiler, vkd3d_component_type_from_data_type(type), -+ component_count, (const uint32_t *)¶meter->u.immediate_constant); - - if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT) -- return spirv_compiler_get_spec_constant(compiler, name, parameter->u.specialization_constant.id, type); -+ return spirv_compiler_get_spec_constant(compiler, name, -+ parameter->u.specialization_constant.id, type, component_count); - if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_BUFFER) -- return spirv_compiler_get_buffer_parameter(compiler, parameter, type); -+ return spirv_compiler_get_buffer_parameter(compiler, parameter, type, component_count); - - FIXME("Unhandled parameter type %#x.\n", parameter->type); - - default_parameter: - return spirv_compiler_get_spec_constant(compiler, -- name, spirv_compiler_alloc_spec_constant_id(compiler), type); -+ name, spirv_compiler_alloc_spec_constant_id(compiler, component_count), type, component_count); - } - - static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *compiler, -@@ -4218,7 +4253,8 @@ 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, reg->data_type); -+ return spirv_compiler_emit_shader_parameter(compiler, reg->idx[0].offset, -+ reg->data_type, reg->dimension == VSIR_DIMENSION_VEC4 ? 4 : 1); - - component_count = vsir_write_mask_component_count(write_mask); - component_type = vkd3d_component_type_from_data_type(reg->data_type); -@@ -4508,9 +4544,24 @@ static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler, - static void spirv_compiler_emit_store_dst(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst, uint32_t val_id) - { -- VKD3D_ASSERT(!(dst->modifiers & ~VKD3DSPDM_SATURATE)); -- if (dst->modifiers & VKD3DSPDM_SATURATE) -+ uint32_t modifiers = dst->modifiers; -+ -+ /* It is always legitimate to ignore _pp. */ -+ modifiers &= ~VKD3DSPDM_PARTIALPRECISION; -+ -+ if (modifiers & VKD3DSPDM_SATURATE) -+ { - val_id = spirv_compiler_emit_sat(compiler, &dst->reg, dst->write_mask, val_id); -+ modifiers &= ~VKD3DSPDM_SATURATE; -+ } -+ -+ if (dst->modifiers & VKD3DSPDM_MSAMPCENTROID) -+ { -+ FIXME("Ignoring _centroid modifier.\n"); -+ modifiers &= ~VKD3DSPDM_MSAMPCENTROID; -+ } -+ -+ VKD3D_ASSERT(!modifiers); - - spirv_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, val_id); - } -@@ -9563,7 +9614,7 @@ static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *co - if (src->reg.type == VKD3DSPR_RASTERIZER) - { - val_id = spirv_compiler_emit_shader_parameter(compiler, -- VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, VKD3D_DATA_UINT); -+ VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, VKD3D_DATA_UINT, 1); - } - else - { -@@ -10611,7 +10662,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct - { - uint32_t type_id, struct_id, ptr_type_id, var_id; - -- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); -+ type_id = vkd3d_spirv_get_type_id(builder, -+ vkd3d_component_type_from_data_type(parameter_data_type_map[parameter->data_type].type), -+ parameter_data_type_map[parameter->data_type].component_count); - - struct_id = vkd3d_spirv_build_op_type_struct(builder, &type_id, 1); - vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBlock, NULL, 0); -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 389946e2c2f..00a525c9ac3 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -3649,6 +3649,48 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un - return extern_resources; - } - -+/* For some reason, for matrices, values from default value initializers end up in different -+ * components than from regular initializers. Default value initializers fill the matrix in -+ * vertical reading order (left-to-right top-to-bottom) instead of regular reading order -+ * (top-to-bottom left-to-right), so they have to be adjusted. -+ * An exception is that the order of matrix initializers for function parameters are row-major -+ * (top-to-bottom left-to-right). */ -+static unsigned int get_component_index_from_default_initializer_index(struct hlsl_type *type, unsigned int index) -+{ -+ unsigned int element_comp_count, element, x, y, i; -+ unsigned int base = 0; -+ -+ switch (type->class) -+ { -+ case HLSL_CLASS_MATRIX: -+ x = index / type->dimy; -+ y = index % type->dimy; -+ return y * type->dimx + x; -+ -+ case HLSL_CLASS_ARRAY: -+ element_comp_count = hlsl_type_component_count(type->e.array.type); -+ element = index / element_comp_count; -+ base = element * element_comp_count; -+ return base + get_component_index_from_default_initializer_index(type->e.array.type, index - base); -+ -+ case HLSL_CLASS_STRUCT: -+ for (i = 0; i < type->e.record.field_count; ++i) -+ { -+ struct hlsl_type *field_type = type->e.record.fields[i].type; -+ -+ element_comp_count = hlsl_type_component_count(field_type); -+ if (index - base < element_comp_count) -+ return base + get_component_index_from_default_initializer_index(field_type, index - base); -+ base += element_comp_count; -+ } -+ break; -+ -+ default: -+ return index; -+ } -+ vkd3d_unreachable(); -+} -+ - static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) - { - uint32_t binding_desc_size = (hlsl_version_ge(ctx, 5, 1) ? 10 : 8) * sizeof(uint32_t); -@@ -3849,7 +3891,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) - for (k = 0; k < comp_count; ++k) - { - struct hlsl_type *comp_type = hlsl_type_get_component_type(ctx, var->data_type, k); -- unsigned int comp_offset; -+ unsigned int comp_offset, comp_index; - enum hlsl_regset regset; - - if (comp_type->class == HLSL_CLASS_STRING) -@@ -3859,7 +3901,8 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) - continue; - } - -- comp_offset = hlsl_type_get_component_offset(ctx, var->data_type, k, ®set); -+ comp_index = get_component_index_from_default_initializer_index(var->data_type, k); -+ comp_offset = hlsl_type_get_component_offset(ctx, var->data_type, comp_index, ®set); - if (regset == HLSL_REGSET_NUMERIC) - { - if (comp_type->e.numeric.type == HLSL_TYPE_DOUBLE) -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 112bdc4da7f..d9d5b4a405e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -161,6 +161,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT = 5036, - VKD3D_SHADER_ERROR_HLSL_INVALID_OUTPUT_PRIMITIVE = 5037, - VKD3D_SHADER_ERROR_HLSL_INVALID_PARTITIONING = 5038, -+ VKD3D_SHADER_ERROR_HLSL_MISPLACED_SAMPLER_STATE = 5039, - - VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, - VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, -@@ -241,6 +242,8 @@ enum vkd3d_shader_error - VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE = 9017, - VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION = 9018, - VKD3D_SHADER_ERROR_VSIR_INVALID_GS = 9019, -+ VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER = 9020, -+ VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC = 9021, - - VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300, - --- -2.45.2 - diff --git a/patches/vkd3d-latest/0006-Updated-vkd3d-to-25232f2b2b35bcf1c265bc380c31cd1d32e.patch b/patches/vkd3d-latest/0006-Updated-vkd3d-to-25232f2b2b35bcf1c265bc380c31cd1d32e.patch deleted file mode 100644 index 716d1c5a..00000000 --- a/patches/vkd3d-latest/0006-Updated-vkd3d-to-25232f2b2b35bcf1c265bc380c31cd1d32e.patch +++ /dev/null @@ -1,893 +0,0 @@ -From baf455d7ecc67cac7c6c450535226f67d3af6c21 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Sat, 5 Oct 2024 11:26:42 +1000 -Subject: [PATCH] Updated vkd3d to 25232f2b2b35bcf1c265bc380c31cd1d32e4f4a6. - ---- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 7 +- - libs/vkd3d/libs/vkd3d-shader/glsl.c | 474 +++++++++++++++++- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 4 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 42 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 36 ++ - .../libs/vkd3d-shader/vkd3d_shader_main.c | 7 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 2 + - 7 files changed, 553 insertions(+), 19 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 165ab222fca..d4296ef4bc5 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -4864,8 +4864,10 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; - src_param_init_vector_from_reg(src_param, &buffer->u.handle.reg); -+ /* Differently from other descriptors, constant buffers require an -+ * additional index, used to index within the constant buffer itself. */ -+ src_param->reg.idx_count = 3; - register_index_address_init(&src_param->reg.idx[2], operands[1], sm6); -- VKD3D_ASSERT(src_param->reg.idx_count == 3); - - type = sm6_type_get_scalar_type(dst->type, 0); - VKD3D_ASSERT(type); -@@ -4964,8 +4966,7 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int - dst->u.handle.d = d; - - reg = &dst->u.handle.reg; -- /* Set idx_count to 3 for use with load/store instructions. */ -- vsir_register_init(reg, d->reg_type, d->reg_data_type, 3); -+ vsir_register_init(reg, d->reg_type, d->reg_data_type, 2); - reg->dimension = VSIR_DIMENSION_VEC4; - reg->idx[0].offset = id; - register_index_address_init(®->idx[1], operands[2], sm6); -diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index e2bcca56f05..c2fb58c55e6 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/glsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -18,6 +18,13 @@ - - #include "vkd3d_shader_private.h" - -+struct glsl_resource_type_info -+{ -+ size_t coord_size; -+ bool shadow; -+ const char *sampler_type; -+}; -+ - struct glsl_src - { - struct vkd3d_string_buffer *str; -@@ -52,6 +59,7 @@ struct vkd3d_glsl_generator - const struct vkd3d_shader_interface_info *interface_info; - const struct vkd3d_shader_descriptor_offset_info *offset_info; - const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info; -+ const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info; - }; - - static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error( -@@ -87,11 +95,81 @@ static const char *shader_glsl_get_prefix(enum vkd3d_shader_type type) - } - } - -+static const struct glsl_resource_type_info *shader_glsl_get_resource_type_info(enum vkd3d_shader_resource_type t) -+{ -+ static const struct glsl_resource_type_info info[] = -+ { -+ {0, 0, "samplerNone"}, /* VKD3D_SHADER_RESOURCE_NONE */ -+ {1, 0, "samplerBuffer"}, /* VKD3D_SHADER_RESOURCE_BUFFER */ -+ {1, 1, "sampler1D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1D */ -+ {2, 1, "sampler2D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2D */ -+ {2, 0, "sampler2DMS"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMS */ -+ {3, 0, "sampler3D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_3D */ -+ {3, 1, "samplerCube"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBE */ -+ {2, 1, "sampler1DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY */ -+ {3, 1, "sampler2DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY */ -+ {3, 0, "sampler2DMSArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY */ -+ {4, 1, "samplerCubeArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY */ -+ }; -+ -+ if (!t || t >= ARRAY_SIZE(info)) -+ return NULL; -+ -+ return &info[t]; -+} -+ -+static const struct vkd3d_shader_descriptor_info1 *shader_glsl_get_descriptor(struct vkd3d_glsl_generator *gen, -+ enum vkd3d_shader_descriptor_type type, unsigned int idx, unsigned int space) -+{ -+ const struct vkd3d_shader_scan_descriptor_info1 *info = gen->descriptor_info; -+ -+ for (unsigned int i = 0; i < info->descriptor_count; ++i) -+ { -+ const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i]; -+ -+ if (d->type == type && d->register_space == space && d->register_index == idx) -+ return d; -+ } -+ -+ return NULL; -+} -+ -+static const struct vkd3d_shader_descriptor_info1 *shader_glsl_get_descriptor_by_id( -+ struct vkd3d_glsl_generator *gen, enum vkd3d_shader_descriptor_type type, unsigned int id) -+{ -+ const struct vkd3d_shader_scan_descriptor_info1 *info = gen->descriptor_info; -+ -+ for (unsigned int i = 0; i < info->descriptor_count; ++i) -+ { -+ const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i]; -+ -+ if (d->type == type && d->register_id == id) -+ return d; -+ } -+ -+ return NULL; -+} -+ - static void shader_glsl_print_indent(struct vkd3d_string_buffer *buffer, unsigned int indent) - { - vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, ""); - } - -+static void shader_glsl_print_combined_sampler_name(struct vkd3d_string_buffer *buffer, -+ struct vkd3d_glsl_generator *gen, unsigned int resource_index, -+ unsigned int resource_space, unsigned int sampler_index, unsigned int sampler_space) -+{ -+ vkd3d_string_buffer_printf(buffer, "%s_t_%u", gen->prefix, resource_index); -+ if (resource_space) -+ vkd3d_string_buffer_printf(buffer, "_%u", resource_space); -+ if (sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX) -+ { -+ vkd3d_string_buffer_printf(buffer, "_s_%u", sampler_index); -+ if (sampler_space) -+ vkd3d_string_buffer_printf(buffer, "_%u", sampler_space); -+ } -+} -+ - static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, - struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_register *reg) - { -@@ -360,14 +438,12 @@ static uint32_t glsl_dst_init(struct glsl_dst *glsl_dst, struct vkd3d_glsl_gener - return write_mask; - } - --static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( -- struct vkd3d_glsl_generator *gen, struct glsl_dst *dst, const char *format, ...) -+static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_glsl_generator *gen, -+ struct glsl_dst *dst, enum vkd3d_data_type data_type, const char *format, va_list args) - { -- const struct vkd3d_shader_register *dst_reg = &dst->vsir->reg; - struct vkd3d_string_buffer *buffer = gen->buffer; - uint32_t modifiers = dst->vsir->modifiers; - bool close = true; -- va_list args; - - if (dst->vsir->shift) - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -@@ -381,11 +457,11 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( - if (modifiers & VKD3DSPDM_SATURATE) - vkd3d_string_buffer_printf(buffer, "clamp("); - -- switch (dst_reg->data_type) -+ switch (data_type) - { - default: - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -- "Internal compiler error: Unhandled destination register data type %#x.", dst_reg->data_type); -+ "Internal compiler error: Unhandled destination register data type %#x.", data_type); - /* fall through */ - case VKD3D_DATA_FLOAT: - close = false; -@@ -398,9 +474,7 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( - break; - } - -- va_start(args, format); - vkd3d_string_buffer_vprintf(buffer, format, args); -- va_end(args); - - if (close) - vkd3d_string_buffer_printf(buffer, ")"); -@@ -409,6 +483,26 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( - vkd3d_string_buffer_printf(buffer, ";\n"); - } - -+static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( -+ struct vkd3d_glsl_generator *gen, struct glsl_dst *dst, const char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ shader_glsl_vprint_assignment(gen, dst, dst->vsir->reg.data_type, format, args); -+ va_end(args); -+} -+ -+static void VKD3D_PRINTF_FUNC(4, 5) shader_glsl_print_assignment_ext(struct vkd3d_glsl_generator *gen, -+ struct glsl_dst *dst, enum vkd3d_data_type data_type, const char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ shader_glsl_vprint_assignment(gen, dst, data_type, format, args); -+ va_end(args); -+} -+ - static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) - { - shader_glsl_print_indent(gen->buffer, gen->indent); -@@ -561,6 +655,159 @@ static void shader_glsl_endif(struct vkd3d_glsl_generator *gen) - vkd3d_string_buffer_printf(gen->buffer, "}\n"); - } - -+static void shader_glsl_ld(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ const struct glsl_resource_type_info *resource_type_info; -+ unsigned int resource_id, resource_idx, resource_space; -+ const struct vkd3d_shader_descriptor_info1 *d; -+ enum vkd3d_shader_component_type sampled_type; -+ enum vkd3d_shader_resource_type resource_type; -+ struct vkd3d_string_buffer *fetch; -+ enum vkd3d_data_type data_type; -+ struct glsl_src coord, lod; -+ struct glsl_dst dst; -+ uint32_t coord_mask; -+ -+ if (vkd3d_shader_instruction_has_texel_offset(ins)) -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Unhandled texel fetch offset."); -+ -+ if (ins->src[1].reg.idx[0].rel_addr || ins->src[1].reg.idx[1].rel_addr) -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, -+ "Descriptor indexing is not supported."); -+ -+ resource_id = ins->src[1].reg.idx[0].offset; -+ resource_idx = ins->src[1].reg.idx[1].offset; -+ if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_id))) -+ { -+ resource_type = d->resource_type; -+ resource_space = d->register_space; -+ sampled_type = vkd3d_component_type_from_resource_data_type(d->resource_data_type); -+ data_type = vkd3d_data_type_from_component_type(sampled_type); -+ } -+ else -+ { -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Undeclared resource descriptor %u.", resource_id); -+ resource_space = 0; -+ resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; -+ data_type = VKD3D_DATA_FLOAT; -+ } -+ -+ if ((resource_type_info = shader_glsl_get_resource_type_info(resource_type))) -+ { -+ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); -+ } -+ else -+ { -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Unhandled resource type %#x.", resource_type); -+ coord_mask = vkd3d_write_mask_from_component_count(2); -+ } -+ -+ glsl_dst_init(&dst, gen, ins, &ins->dst[0]); -+ glsl_src_init(&coord, gen, &ins->src[0], coord_mask); -+ glsl_src_init(&lod, gen, &ins->src[0], VKD3DSP_WRITEMASK_3); -+ fetch = vkd3d_string_buffer_get(&gen->string_buffers); -+ -+ vkd3d_string_buffer_printf(fetch, "texelFetch("); -+ shader_glsl_print_combined_sampler_name(fetch, gen, resource_idx, -+ resource_space, VKD3D_SHADER_DUMMY_SAMPLER_INDEX, 0); -+ vkd3d_string_buffer_printf(fetch, ", %s", coord.str->buffer); -+ if (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) -+ vkd3d_string_buffer_printf(fetch, ", %s", lod.str->buffer); -+ vkd3d_string_buffer_printf(fetch, ")"); -+ shader_glsl_print_swizzle(fetch, ins->src[1].swizzle, ins->dst[0].write_mask); -+ -+ shader_glsl_print_assignment_ext(gen, &dst, data_type, "%s", fetch->buffer); -+ -+ vkd3d_string_buffer_release(&gen->string_buffers, fetch); -+ glsl_src_cleanup(&lod, &gen->string_buffers); -+ glsl_src_cleanup(&coord, &gen->string_buffers); -+ glsl_dst_cleanup(&dst, &gen->string_buffers); -+} -+ -+static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ const struct glsl_resource_type_info *resource_type_info; -+ unsigned int resource_id, resource_idx, resource_space; -+ unsigned int sampler_id, sampler_idx, sampler_space; -+ const struct vkd3d_shader_descriptor_info1 *d; -+ enum vkd3d_shader_component_type sampled_type; -+ enum vkd3d_shader_resource_type resource_type; -+ struct vkd3d_string_buffer *sample; -+ enum vkd3d_data_type data_type; -+ struct glsl_src coord; -+ struct glsl_dst dst; -+ uint32_t coord_mask; -+ -+ if (vkd3d_shader_instruction_has_texel_offset(ins)) -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Unhandled texel sample offset."); -+ -+ if (ins->src[1].reg.idx[0].rel_addr || ins->src[1].reg.idx[1].rel_addr -+ || ins->src[2].reg.idx[0].rel_addr || ins->src[2].reg.idx[1].rel_addr) -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, -+ "Descriptor indexing is not supported."); -+ -+ resource_id = ins->src[1].reg.idx[0].offset; -+ resource_idx = ins->src[1].reg.idx[1].offset; -+ if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_id))) -+ { -+ resource_type = d->resource_type; -+ resource_space = d->register_space; -+ sampled_type = vkd3d_component_type_from_resource_data_type(d->resource_data_type); -+ data_type = vkd3d_data_type_from_component_type(sampled_type); -+ } -+ else -+ { -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Undeclared resource descriptor %u.", resource_id); -+ resource_space = 0; -+ resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; -+ data_type = VKD3D_DATA_FLOAT; -+ } -+ -+ if ((resource_type_info = shader_glsl_get_resource_type_info(resource_type))) -+ { -+ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); -+ } -+ else -+ { -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Unhandled resource type %#x.", resource_type); -+ coord_mask = vkd3d_write_mask_from_component_count(2); -+ } -+ -+ sampler_id = ins->src[2].reg.idx[0].offset; -+ sampler_idx = ins->src[2].reg.idx[1].offset; -+ if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler_id))) -+ { -+ sampler_space = d->register_space; -+ } -+ else -+ { -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Undeclared sampler descriptor %u.", sampler_id); -+ sampler_space = 0; -+ } -+ -+ glsl_dst_init(&dst, gen, ins, &ins->dst[0]); -+ glsl_src_init(&coord, gen, &ins->src[0], coord_mask); -+ sample = vkd3d_string_buffer_get(&gen->string_buffers); -+ -+ vkd3d_string_buffer_printf(sample, "texture("); -+ shader_glsl_print_combined_sampler_name(sample, gen, resource_idx, resource_space, sampler_idx, sampler_space); -+ vkd3d_string_buffer_printf(sample, ", %s)", coord.str->buffer); -+ shader_glsl_print_swizzle(sample, ins->src[1].swizzle, ins->dst[0].write_mask); -+ -+ shader_glsl_print_assignment_ext(gen, &dst, data_type, "%s", sample->buffer); -+ -+ vkd3d_string_buffer_release(&gen->string_buffers, sample); -+ glsl_src_cleanup(&coord, &gen->string_buffers); -+ glsl_dst_cleanup(&dst, &gen->string_buffers); -+} -+ - static void shader_glsl_unary_op(struct vkd3d_glsl_generator *gen, - const struct vkd3d_shader_instruction *ins, const char *op) - { -@@ -617,6 +864,37 @@ static void shader_glsl_movc(struct vkd3d_glsl_generator *gen, const struct vkd3 - glsl_dst_cleanup(&dst, &gen->string_buffers); - } - -+static void shader_glsl_mul_extended(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ struct glsl_src src[2]; -+ struct glsl_dst dst; -+ uint32_t mask; -+ -+ if (ins->dst[0].reg.type != VKD3DSPR_NULL) -+ { -+ /* FIXME: imulExtended()/umulExtended() from ARB_gpu_shader5/GLSL 4.00+. */ -+ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); -+ shader_glsl_print_assignment(gen, &dst, ""); -+ glsl_dst_cleanup(&dst, &gen->string_buffers); -+ -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Unhandled 64-bit integer multiplication."); -+ } -+ -+ if (ins->dst[1].reg.type != VKD3DSPR_NULL) -+ { -+ mask = glsl_dst_init(&dst, gen, ins, &ins->dst[1]); -+ glsl_src_init(&src[0], gen, &ins->src[0], mask); -+ glsl_src_init(&src[1], gen, &ins->src[1], mask); -+ -+ shader_glsl_print_assignment(gen, &dst, "%s * %s", src[0].str->buffer, src[1].str->buffer); -+ -+ glsl_src_cleanup(&src[1], &gen->string_buffers); -+ glsl_src_cleanup(&src[0], &gen->string_buffers); -+ glsl_dst_cleanup(&dst, &gen->string_buffers); -+ } -+} -+ - static void shader_glsl_print_sysval_name(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, - enum vkd3d_shader_sysval_semantic sysval, unsigned int idx) - { -@@ -817,6 +1095,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - shader_glsl_cast(gen, ins, "uint", "uvec"); - break; - case VKD3DSIH_GEO: -+ case VKD3DSIH_IGE: - shader_glsl_relop(gen, ins, ">=", "greaterThanEqual"); - break; - case VKD3DSIH_IF: -@@ -825,6 +1104,13 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_MAD: - shader_glsl_intrinsic(gen, ins, "fma"); - break; -+ case VKD3DSIH_ILT: -+ case VKD3DSIH_LTO: -+ shader_glsl_relop(gen, ins, "<", "lessThan"); -+ break; -+ case VKD3DSIH_IMUL: -+ shader_glsl_mul_extended(gen, ins); -+ break; - case VKD3DSIH_ISHL: - shader_glsl_binop(gen, ins, "<<"); - break; -@@ -832,9 +1118,6 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_USHR: - shader_glsl_binop(gen, ins, ">>"); - break; -- case VKD3DSIH_LTO: -- shader_glsl_relop(gen, ins, "<", "lessThan"); -- break; - case VKD3DSIH_MAX: - shader_glsl_intrinsic(gen, ins, "max"); - break; -@@ -849,6 +1132,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_UTOF: - shader_glsl_cast(gen, ins, "float", "vec"); - break; -+ case VKD3DSIH_LD: -+ shader_glsl_ld(gen, ins); -+ break; - case VKD3DSIH_LOG: - shader_glsl_intrinsic(gen, ins, "log2"); - break; -@@ -885,6 +1171,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_RSQ: - shader_glsl_intrinsic(gen, ins, "inversesqrt"); - break; -+ case VKD3DSIH_SAMPLE: -+ shader_glsl_sample(gen, ins); -+ break; - case VKD3DSIH_SQRT: - shader_glsl_intrinsic(gen, ins, "sqrt"); - break; -@@ -1012,8 +1301,156 @@ static void shader_glsl_generate_cbv_declaration(struct vkd3d_glsl_generator *ge - binding->binding, prefix, cbv->register_id, prefix, cbv->register_id, size); - } - -+static bool shader_glsl_get_combined_sampler_binding(const struct vkd3d_glsl_generator *gen, -+ const struct vkd3d_shader_combined_resource_sampler_info *crs, -+ enum vkd3d_shader_resource_type resource_type, unsigned int *binding_idx) -+{ -+ const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; -+ const struct vkd3d_shader_combined_resource_sampler *s; -+ enum vkd3d_shader_binding_flag resource_type_flag; -+ unsigned int i; -+ -+ if (!interface_info) -+ return false; -+ -+ 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->combined_sampler_count; ++i) -+ { -+ s = &interface_info->combined_samplers[i]; -+ -+ if (s->resource_space != crs->resource_space) -+ continue; -+ if (s->resource_index != crs->resource_index) -+ continue; -+ if (crs->sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX) -+ { -+ if (s->sampler_space != crs->sampler_space) -+ continue; -+ if (s->sampler_index != crs->sampler_index) -+ continue; -+ } -+ if (!shader_glsl_check_shader_visibility(gen, s->shader_visibility)) -+ continue; -+ if (!(s->flags & resource_type_flag)) -+ continue; -+ *binding_idx = i; -+ return true; -+ } -+ -+ return false; -+} -+ -+static void shader_glsl_generate_sampler_declaration(struct vkd3d_glsl_generator *gen, -+ const struct vkd3d_shader_combined_resource_sampler_info *crs) -+{ -+ const struct vkd3d_shader_descriptor_info1 *sampler, *srv; -+ const struct glsl_resource_type_info *resource_type_info; -+ const struct vkd3d_shader_descriptor_binding *binding; -+ struct vkd3d_string_buffer *buffer = gen->buffer; -+ enum vkd3d_shader_component_type component_type; -+ const char *sampler_type, *sampler_type_prefix; -+ unsigned int binding_idx; -+ bool shadow = false; -+ -+ if (crs->sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX) -+ { -+ if (!(sampler = shader_glsl_get_descriptor(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, -+ crs->sampler_index, crs->sampler_space))) -+ { -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: No descriptor found for sampler %u, space %u.", -+ crs->sampler_index, crs->sampler_space); -+ return; -+ } -+ shadow = sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE; -+ } -+ -+ if (!(srv = shader_glsl_get_descriptor(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, -+ crs->resource_index, crs->resource_space))) -+ { -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: No descriptor found for resource %u, space %u.", -+ crs->resource_index, crs->resource_space); -+ return; -+ } -+ -+ if ((resource_type_info = shader_glsl_get_resource_type_info(srv->resource_type))) -+ { -+ sampler_type = resource_type_info->sampler_type; -+ if (shadow && !resource_type_info->shadow) -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, -+ "Comparison samplers are not supported with resource type %#x.", srv->resource_type); -+ } -+ else -+ { -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Unhandled resource type %#x for combined resource/sampler " -+ "for resource %u, space %u and sampler %u, space %u.", srv->resource_type, -+ crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); -+ sampler_type = ""; -+ } -+ -+ switch ((component_type = vkd3d_component_type_from_resource_data_type(srv->resource_data_type))) -+ { -+ case VKD3D_SHADER_COMPONENT_UINT: -+ sampler_type_prefix = "u"; -+ break; -+ case VKD3D_SHADER_COMPONENT_INT: -+ sampler_type_prefix = "i"; -+ break; -+ case VKD3D_SHADER_COMPONENT_FLOAT: -+ sampler_type_prefix = ""; -+ break; -+ default: -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -+ "Internal compiler error: Unhandled component type %#x for combined resource/sampler " -+ "for resource %u, space %u and sampler %u, space %u.", component_type, -+ crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); -+ sampler_type_prefix = ""; -+ break; -+ } -+ -+ if (!shader_glsl_get_combined_sampler_binding(gen, crs, srv->resource_type, &binding_idx)) -+ { -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, -+ "No descriptor binding specified for combined resource/sampler " -+ "for resource %u, space %u and sampler %u, space %u.", -+ crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); -+ return; -+ } -+ -+ binding = &gen->interface_info->combined_samplers[binding_idx].binding; -+ -+ if (binding->set != 0) -+ { -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, -+ "Unsupported binding set %u specified for combined resource/sampler " -+ "for resource %u, space %u and sampler %u, space %u.", binding->set, -+ crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); -+ return; -+ } -+ -+ if (binding->count != 1) -+ { -+ vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, -+ "Unsupported binding count %u specified for combined resource/sampler " -+ "for resource %u, space %u and sampler %u, space %u.", binding->count, -+ crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); -+ return; -+ } -+ -+ vkd3d_string_buffer_printf(buffer, "layout(binding = %u) uniform %s%s%s ", -+ binding->binding, sampler_type_prefix, sampler_type, shadow ? "Shadow" : ""); -+ shader_glsl_print_combined_sampler_name(buffer, gen, crs->resource_index, -+ crs->resource_space, crs->sampler_index, crs->sampler_space); -+ vkd3d_string_buffer_printf(buffer, ";\n"); -+} -+ - static void shader_glsl_generate_descriptor_declarations(struct vkd3d_glsl_generator *gen) - { -+ const struct vkd3d_shader_scan_combined_resource_sampler_info *sampler_info = gen->combined_sampler_info; - const struct vkd3d_shader_scan_descriptor_info1 *info = gen->descriptor_info; - const struct vkd3d_shader_descriptor_info1 *descriptor; - unsigned int i; -@@ -1024,6 +1461,11 @@ static void shader_glsl_generate_descriptor_declarations(struct vkd3d_glsl_gener - - switch (descriptor->type) - { -+ case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV: -+ case VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER: -+ /* GLSL uses combined resource/sampler descriptors.*/ -+ break; -+ - case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV: - shader_glsl_generate_cbv_declaration(gen, descriptor); - break; -@@ -1035,6 +1477,10 @@ static void shader_glsl_generate_descriptor_declarations(struct vkd3d_glsl_gener - break; - } - } -+ for (i = 0; i < sampler_info->combined_sampler_count; ++i) -+ { -+ shader_glsl_generate_sampler_declaration(gen, &sampler_info->combined_samplers[i]); -+ } - if (info->descriptor_count) - vkd3d_string_buffer_printf(gen->buffer, "\n"); - } -@@ -1259,6 +1705,7 @@ static void shader_glsl_init_limits(struct vkd3d_glsl_generator *gen, const stru - static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen, - struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, - const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, -+ const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info, - struct vkd3d_shader_message_context *message_context) - { - enum vkd3d_shader_type type = program->shader_version.type; -@@ -1282,10 +1729,12 @@ static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen, - gen->interface_info = vkd3d_find_struct(compile_info->next, INTERFACE_INFO); - gen->offset_info = vkd3d_find_struct(compile_info->next, DESCRIPTOR_OFFSET_INFO); - gen->descriptor_info = descriptor_info; -+ gen->combined_sampler_info = combined_sampler_info; - } - - int glsl_compile(struct vsir_program *program, uint64_t config_flags, - const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, -+ const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info, - const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) - { -@@ -1295,7 +1744,8 @@ int glsl_compile(struct vsir_program *program, uint64_t config_flags, - if ((ret = vsir_program_transform(program, config_flags, compile_info, message_context)) < 0) - return ret; - -- vkd3d_glsl_generator_init(&generator, program, compile_info, descriptor_info, message_context); -+ vkd3d_glsl_generator_init(&generator, program, compile_info, -+ descriptor_info, combined_sampler_info, message_context); - ret = vkd3d_glsl_generator_generate(&generator, out); - vkd3d_glsl_generator_cleanup(&generator); - -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index ce3dd91f04f..9ace1930c1b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -4408,8 +4408,6 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) - struct hlsl_type *type, *next_type; - unsigned int i; - -- hlsl_block_cleanup(&ctx->static_initializers); -- - for (i = 0; i < ctx->source_files_count; ++i) - vkd3d_free((void *)ctx->source_files[i]); - vkd3d_free(ctx->source_files); -@@ -4417,6 +4415,8 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) - - rb_destroy(&ctx->functions, free_function_rb, NULL); - -+ hlsl_block_cleanup(&ctx->static_initializers); -+ - /* State blocks must be free before the variables, because they contain instructions that may - * refer to them. */ - LIST_FOR_EACH_ENTRY_SAFE(scope, next_scope, &ctx->scopes, struct hlsl_scope, entry) -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index b4d9f0988b0..ef37eb75f03 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -1972,6 +1972,12 @@ static struct hlsl_block *add_binary_expr_merge(struct hlsl_ctx *ctx, struct hls - hlsl_block_add_block(block1, block2); - destroy_block(block2); - -+ if (arg1->data_type->class == HLSL_CLASS_ERROR || arg2->data_type->class == HLSL_CLASS_ERROR) -+ { -+ block1->value = ctx->error_instr; -+ return block1; -+ } -+ - if (add_binary_expr(ctx, block1, op, arg1, arg2, loc) == NULL) - return NULL; - -@@ -2085,6 +2091,12 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc - unsigned int writemask = 0, width = 0; - bool matrix_writemask = false; - -+ if (lhs->data_type->class == HLSL_CLASS_ERROR || rhs->data_type->class == HLSL_CLASS_ERROR) -+ { -+ block->value = ctx->error_instr; -+ return true; -+ } -+ - if (assign_op == ASSIGN_OP_SUB) - { - if (!(rhs = add_unary_arithmetic_expr(ctx, block, HLSL_OP1_NEG, rhs, &rhs->loc))) -@@ -5141,6 +5153,15 @@ static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name, - struct intrinsic_function *intrinsic; - struct hlsl_ir_function_decl *decl; - -+ for (unsigned int i = 0; i < args->args_count; ++i) -+ { -+ if (args->args[i]->data_type->class == HLSL_CLASS_ERROR) -+ { -+ args->instrs->value = ctx->error_instr; -+ return args->instrs; -+ } -+ } -+ - if ((decl = find_function_call(ctx, name, args, false, loc))) - { - if (!add_user_call(ctx, decl, args, false, loc)) -@@ -6071,6 +6092,21 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, stru - const struct hlsl_type *object_type = object->data_type; - const struct method_function *method; - -+ if (object_type->class == HLSL_CLASS_ERROR) -+ { -+ block->value = ctx->error_instr; -+ return true; -+ } -+ -+ for (unsigned int i = 0; i < params->args_count; ++i) -+ { -+ if (params->args[i]->data_type->class == HLSL_CLASS_ERROR) -+ { -+ block->value = ctx->error_instr; -+ return true; -+ } -+ } -+ - if (object_type->class != HLSL_CLASS_TEXTURE || object_type->sampler_dim == HLSL_SAMPLER_DIM_GENERIC) - { - struct vkd3d_string_buffer *string; -@@ -8682,7 +8718,11 @@ primary_expr: - else - { - hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Identifier \"%s\" is not declared.", $1); -- YYABORT; -+ vkd3d_free($1); -+ -+ if (!($$ = make_empty_block(ctx))) -+ YYABORT; -+ $$->value = ctx->error_instr; - } - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 2fe5472167f..6a74e2eb8de 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -6186,6 +6186,18 @@ static void vsir_validate_register(struct validation_context *ctx, - if (reg->dimension == VSIR_DIMENSION_SCALAR) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, - "Invalid dimension SCALAR for a SAMPLER register."); -+ -+ if (reg->idx_count != 2) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, -+ "Invalid index count %u for a SAMPLER register.", -+ reg->idx_count); -+ break; -+ } -+ -+ if (reg->idx[0].rel_addr) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "Non-NULL relative address for the descriptor index of a SAMPLER register."); - break; - - case VKD3DSPR_RESOURCE: -@@ -6203,6 +6215,18 @@ static void vsir_validate_register(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, - "Invalid dimension %#x for a RESOURCE register.", - reg->dimension); -+ -+ if (reg->idx_count != 2) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, -+ "Invalid index count %u for a RESOURCE register.", -+ reg->idx_count); -+ break; -+ } -+ -+ if (reg->idx[0].rel_addr) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "Non-NULL relative address for the descriptor index of a RESOURCE register."); - break; - - case VKD3DSPR_UAV: -@@ -6221,6 +6245,18 @@ static void vsir_validate_register(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, - "Invalid dimension %#x for a UAV register.", - reg->dimension); -+ -+ if (reg->idx_count != 2) -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, -+ "Invalid index count %u for a UAV register.", -+ reg->idx_count); -+ break; -+ } -+ -+ if (reg->idx[0].rel_addr) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "Non-NULL relative address for the descriptor index of a UAV register."); - break; - - case VKD3DSPR_DEPTHOUT: -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index fc217860403..ee8a633431a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -1620,6 +1620,7 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, - const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, - struct vkd3d_shader_message_context *message_context) - { -+ struct vkd3d_shader_scan_combined_resource_sampler_info combined_sampler_info; - struct vkd3d_shader_scan_descriptor_info1 scan_descriptor_info; - struct vkd3d_shader_compile_info scan_info; - int ret; -@@ -1633,10 +1634,14 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, - break; - - case VKD3D_SHADER_TARGET_GLSL: -+ combined_sampler_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_COMBINED_RESOURCE_SAMPLER_INFO; -+ combined_sampler_info.next = scan_info.next; -+ scan_info.next = &combined_sampler_info; - if ((ret = vsir_program_scan(program, &scan_info, message_context, &scan_descriptor_info)) < 0) - return ret; - ret = glsl_compile(program, config_flags, &scan_descriptor_info, -- compile_info, out, message_context); -+ &combined_sampler_info, compile_info, out, message_context); -+ vkd3d_shader_free_scan_combined_resource_sampler_info(&combined_sampler_info); - vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); - break; - -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index d9d5b4a405e..eab164cc848 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -173,6 +173,7 @@ enum vkd3d_shader_error - - VKD3D_SHADER_ERROR_GLSL_INTERNAL = 6000, - VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND = 6001, -+ VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED = 6002, - - VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF = 7000, - VKD3D_SHADER_ERROR_D3DBC_INVALID_VERSION_TOKEN = 7001, -@@ -1599,6 +1600,7 @@ int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, - - int glsl_compile(struct vsir_program *program, uint64_t config_flags, - const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, -+ const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info, - const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); - --- -2.45.2 -