From e045af48e83b871090dff62a639648b91f1802d7 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 18 Jan 2024 12:10:03 +1100 Subject: [PATCH] Updated vkd3d-latest patchset Squashed afer release + rebased to latest (Added patch 0003). --- ...-3bafee344d8d50172d8da18512ba070c682.patch | 4526 +++++++++++++++++ ...-45679a966c73669bdb7fa371569dcc34a44.patch | 1165 ----- ...-1015cc952e42828d79a68cfa0e659cac537.patch | 1213 ----- ...-68b898fcb6b4ab2a9660f35edf3554465ab.patch | 3188 ++++++++++++ ...-21491d1bbb168da8aeaa7bdde6e5f182b22.patch | 850 ---- ...-cd77b2a9be23b9a34d2d6a5cb566ac3873f.patch | 2252 ++++++++ ...-f96a791807701a4583e6c613c2f5bd47c00.patch | 819 --- ...-78343dcf87d3a911264c6c9a87a9146c43c.patch | 332 -- ...-3bafee344d8d50172d8da18512ba070c682.patch | 595 --- ...-50cebc72780dada0822a1d081f3247f7d1d.patch | 433 -- ...-bb64bfff6334c847d06d219840882ec7576.patch | 636 --- ...-3e2ace8d33a203bf0c8d6a7bf140ef9a9a0.patch | 1460 ------ ...-68b898fcb6b4ab2a9660f35edf3554465ab.patch | 956 ---- 13 files changed, 9966 insertions(+), 8459 deletions(-) create mode 100644 patches/vkd3d-latest/0001-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch delete mode 100644 patches/vkd3d-latest/0001-Updated-vkd3d-to-45679a966c73669bdb7fa371569dcc34a44.patch delete mode 100644 patches/vkd3d-latest/0002-Updated-vkd3d-to-1015cc952e42828d79a68cfa0e659cac537.patch create mode 100644 patches/vkd3d-latest/0002-Updated-vkd3d-to-68b898fcb6b4ab2a9660f35edf3554465ab.patch delete mode 100644 patches/vkd3d-latest/0003-Updated-vkd3d-to-21491d1bbb168da8aeaa7bdde6e5f182b22.patch create mode 100644 patches/vkd3d-latest/0003-Updated-vkd3d-to-cd77b2a9be23b9a34d2d6a5cb566ac3873f.patch delete mode 100644 patches/vkd3d-latest/0004-Updated-vkd3d-to-f96a791807701a4583e6c613c2f5bd47c00.patch delete mode 100644 patches/vkd3d-latest/0005-Updated-vkd3d-to-78343dcf87d3a911264c6c9a87a9146c43c.patch delete mode 100644 patches/vkd3d-latest/0006-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch delete mode 100644 patches/vkd3d-latest/0008-Updated-vkd3d-to-50cebc72780dada0822a1d081f3247f7d1d.patch delete mode 100644 patches/vkd3d-latest/0009-Updated-vkd3d-to-bb64bfff6334c847d06d219840882ec7576.patch delete mode 100644 patches/vkd3d-latest/0010-Updated-vkd3d-to-3e2ace8d33a203bf0c8d6a7bf140ef9a9a0.patch delete mode 100644 patches/vkd3d-latest/0011-Updated-vkd3d-to-68b898fcb6b4ab2a9660f35edf3554465ab.patch diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch new file mode 100644 index 00000000..f962c6a5 --- /dev/null +++ b/patches/vkd3d-latest/0001-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch @@ -0,0 +1,4526 @@ +From bff92c3733134be7c7318f1d5b0d492f36951d26 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Fri, 8 Dec 2023 13:21:19 +1100 +Subject: [PATCH] Updated vkd3d to 3bafee344d8d50172d8da18512ba070c6826b18d. + +--- + libs/vkd3d/include/private/vkd3d_common.h | 4 +- + libs/vkd3d/include/vkd3d_shader.h | 20 + + libs/vkd3d/libs/vkd3d-common/blob.c | 1 + + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 135 ++-- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 16 +- + libs/vkd3d/libs/vkd3d-shader/dxbc.c | 4 - + libs/vkd3d/libs/vkd3d-shader/dxil.c | 699 +++++++++++++++--- + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 20 +- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 12 +- + libs/vkd3d/libs/vkd3d-shader/ir.c | 29 +- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 669 ++++++++++------- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 82 +- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 86 ++- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 54 +- + libs/vkd3d/libs/vkd3d/command.c | 4 + + libs/vkd3d/libs/vkd3d/device.c | 114 ++- + libs/vkd3d/libs/vkd3d/resource.c | 19 +- + libs/vkd3d/libs/vkd3d/state.c | 27 +- + libs/vkd3d/libs/vkd3d/utils.c | 2 + + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 23 +- + 20 files changed, 1475 insertions(+), 545 deletions(-) + +diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h +index 34fde1a2aa0..e9bff2fbba3 100644 +--- a/libs/vkd3d/include/private/vkd3d_common.h ++++ b/libs/vkd3d/include/private/vkd3d_common.h +@@ -80,7 +80,7 @@ static inline size_t align(size_t addr, size_t alignment) + # ifdef __MINGW_PRINTF_FORMAT + # define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, args))) + # else +-# define VKD3D_PRINTF_FUNC(fmt, args) /* __attribute__((format(printf, fmt, args))) */ ++# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args))) + # endif + # define VKD3D_UNUSED __attribute__((unused)) + # define VKD3D_UNREACHABLE __builtin_unreachable() +@@ -107,7 +107,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v) + { + #ifdef _MSC_VER + return __popcnt(v); +-#elif defined(__MINGW32__) ++#elif defined(HAVE_BUILTIN_POPCOUNT) + return __builtin_popcount(v); + #else + v -= (v >> 1) & 0x55555555; +diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h +index 290f9085d2d..b1a1fff6451 100644 +--- a/libs/vkd3d/include/vkd3d_shader.h ++++ b/libs/vkd3d/include/vkd3d_shader.h +@@ -196,6 +196,14 @@ enum vkd3d_shader_compile_option_fragment_coordinate_origin + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN), + }; + ++/** Advertises feature availability. \since 1.11 */ ++enum vkd3d_shader_compile_option_feature_flags ++{ ++ VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64 = 0x00000001, ++ ++ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLAGS), ++}; ++ + enum vkd3d_shader_compile_option_name + { + /** +@@ -253,6 +261,16 @@ enum vkd3d_shader_compile_option_name + * \since 1.10 + */ + VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN = 0x00000009, ++ /** ++ * This option specifies the shader features available in the target ++ * environment. These are not extensions, i.e. they are always supported ++ * by the driver, but may not be supported by the available hardware. ++ * ++ * \a value is a member of enum vkd3d_shader_compile_option_feature_flags. ++ * ++ * \since 1.11 ++ */ ++ VKD3D_SHADER_COMPILE_OPTION_FEATURE = 0x0000000a, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME), + }; +@@ -1551,6 +1569,8 @@ enum vkd3d_shader_component_type + VKD3D_SHADER_COMPONENT_BOOL = 0x4, + /** 64-bit IEEE floating-point. */ + VKD3D_SHADER_COMPONENT_DOUBLE = 0x5, ++ /** 64-bit unsigned integer. \since 1.11 */ ++ VKD3D_SHADER_COMPONENT_UINT64 = 0x6, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPONENT_TYPE), + }; +diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c +index 71ab9a2c51e..fa2812619ac 100644 +--- a/libs/vkd3d/libs/vkd3d-common/blob.c ++++ b/libs/vkd3d/libs/vkd3d-common/blob.c +@@ -17,6 +17,7 @@ + */ + + #define COBJMACROS ++ + #define CONST_VTABLE + #include "vkd3d.h" + #include "vkd3d_blob.h" +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +index 82d1d71d9d3..0589bc42174 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +@@ -364,6 +364,7 @@ struct vkd3d_d3d_asm_compiler + struct vkd3d_string_buffer buffer; + struct vkd3d_shader_version shader_version; + struct vkd3d_d3d_asm_colours colours; ++ enum vsir_asm_dialect dialect; + }; + + static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...) +@@ -606,7 +607,7 @@ static void shader_dump_resource_type(struct vkd3d_d3d_asm_compiler *compiler, e + vkd3d_string_buffer_printf(&compiler->buffer, "unknown"); + } + +-static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type) ++static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_data_type type) + { + static const char *const data_type_names[] = + { +@@ -623,19 +624,31 @@ static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, const + [VKD3D_DATA_DOUBLE ] = "double", + [VKD3D_DATA_CONTINUED] = "", + [VKD3D_DATA_UNUSED ] = "", ++ [VKD3D_DATA_UINT8 ] = "uint8", ++ [VKD3D_DATA_UINT64 ] = "uint64", ++ [VKD3D_DATA_BOOL ] = "bool", + }; ++ + const char *name; ++ ++ if (type < ARRAY_SIZE(data_type_names)) ++ name = data_type_names[type]; ++ else ++ name = ""; ++ ++ vkd3d_string_buffer_printf(&compiler->buffer, "%s", name); ++} ++ ++static void shader_dump_resource_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type) ++{ + int i; + + vkd3d_string_buffer_printf(&compiler->buffer, "("); + + for (i = 0; i < 4; i++) + { +- if (type[i] < ARRAY_SIZE(data_type_names)) +- name = data_type_names[type[i]]; +- else +- name = "unknown"; +- vkd3d_string_buffer_printf(&compiler->buffer, "%s%s", i == 0 ? "" : ",", name); ++ vkd3d_string_buffer_printf(&compiler->buffer, "%s", i == 0 ? "" : ","); ++ shader_dump_data_type(compiler, type[i]); + } + + vkd3d_string_buffer_printf(&compiler->buffer, ")"); +@@ -682,7 +695,7 @@ static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler, + if (semantic->resource.reg.reg.type == VKD3DSPR_UAV) + shader_dump_uav_flags(compiler, flags); + shader_addline(buffer, " "); +- shader_dump_data_type(compiler, semantic->resource_data_type); ++ shader_dump_resource_data_type(compiler, semantic->resource_data_type); + } + else + { +@@ -1096,15 +1109,15 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const + switch (reg->data_type) + { + case VKD3D_DATA_FLOAT: +- shader_print_float_literal(compiler, "", reg->u.immconst_float[0], ""); ++ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); + break; + case VKD3D_DATA_INT: +- shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], ""); ++ 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_uint[0], ""); ++ shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); + break; + default: + shader_addline(buffer, "", reg->data_type); +@@ -1116,24 +1129,24 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const + switch (reg->data_type) + { + case VKD3D_DATA_FLOAT: +- shader_print_float_literal(compiler, "", reg->u.immconst_float[0], ""); +- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[1], ""); +- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[2], ""); +- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[3], ""); ++ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); ++ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[1], ""); ++ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[2], ""); ++ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[3], ""); + break; + case VKD3D_DATA_INT: +- shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], ""); +- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[1], ""); +- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[2], ""); +- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[3], ""); ++ shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); ++ shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[1], ""); ++ 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_uint[0], ""); +- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[1], ""); +- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[2], ""); +- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[3], ""); ++ shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); ++ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[1], ""); ++ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[2], ""); ++ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[3], ""); + break; + default: + shader_addline(buffer, "", reg->data_type); +@@ -1155,9 +1168,9 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const + { + if (reg->data_type == VKD3D_DATA_DOUBLE) + { +- shader_print_double_literal(compiler, "", reg->u.immconst_double[0], ""); ++ shader_print_double_literal(compiler, "", reg->u.immconst_f64[0], ""); + if (reg->dimension == VSIR_DIMENSION_VEC4) +- shader_print_double_literal(compiler, ", ", reg->u.immconst_double[1], ""); ++ shader_print_double_literal(compiler, ", ", reg->u.immconst_f64[1], ""); + } + else + { +@@ -1265,6 +1278,32 @@ static void shader_print_non_uniform(struct vkd3d_d3d_asm_compiler *compiler, co + compiler->colours.modifier, compiler->colours.reset); + } + ++static void shader_dump_reg_type(struct vkd3d_d3d_asm_compiler *compiler, ++ const struct vkd3d_shader_register *reg) ++{ ++ static const char *dimensions[] = ++ { ++ [VSIR_DIMENSION_NONE] = "", ++ [VSIR_DIMENSION_SCALAR] = "s:", ++ [VSIR_DIMENSION_VEC4] = "v4:", ++ }; ++ ++ struct vkd3d_string_buffer *buffer = &compiler->buffer; ++ const char *dimension; ++ ++ if (compiler->dialect != VSIR_ASM_VSIR) ++ return; ++ ++ if (reg->dimension < ARRAY_SIZE(dimensions)) ++ dimension = dimensions[reg->dimension]; ++ else ++ dimension = "??"; ++ ++ shader_addline(buffer, " <%s", dimension); ++ shader_dump_data_type(compiler, reg->data_type); ++ shader_addline(buffer, ">"); ++} ++ + static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, + const struct vkd3d_shader_dst_param *param, bool is_declaration) + { +@@ -1278,7 +1317,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, + static const char write_mask_chars[] = "xyzw"; + + if (param->reg.data_type == VKD3D_DATA_DOUBLE) +- write_mask = vkd3d_write_mask_32_from_64(write_mask); ++ write_mask = vsir_write_mask_32_from_64(write_mask); + + shader_addline(buffer, ".%s", compiler->colours.write_mask); + if (write_mask & VKD3DSP_WRITEMASK_0) +@@ -1294,6 +1333,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, + + shader_print_precision(compiler, ¶m->reg); + shader_print_non_uniform(compiler, ¶m->reg); ++ shader_dump_reg_type(compiler, ¶m->reg); + } + + static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, +@@ -1341,10 +1381,10 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, + if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_IMMCONST64 + && param->reg.dimension == VSIR_DIMENSION_VEC4) + { +- unsigned int swizzle_x = vkd3d_swizzle_get_component(swizzle, 0); +- unsigned int swizzle_y = vkd3d_swizzle_get_component(swizzle, 1); +- unsigned int swizzle_z = vkd3d_swizzle_get_component(swizzle, 2); +- unsigned int swizzle_w = vkd3d_swizzle_get_component(swizzle, 3); ++ unsigned int swizzle_x = vsir_swizzle_get_component(swizzle, 0); ++ unsigned int swizzle_y = vsir_swizzle_get_component(swizzle, 1); ++ unsigned int swizzle_z = vsir_swizzle_get_component(swizzle, 2); ++ unsigned int swizzle_w = vsir_swizzle_get_component(swizzle, 3); + + static const char swizzle_chars[] = "xyzw"; + +@@ -1367,6 +1407,7 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, + + shader_print_precision(compiler, ¶m->reg); + shader_print_non_uniform(compiler, ¶m->reg); ++ shader_dump_reg_type(compiler, ¶m->reg); + } + + static void shader_dump_ins_modifiers(struct vkd3d_d3d_asm_compiler *compiler, +@@ -1577,6 +1618,12 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile + shader_addline(buffer, "p"); + break; + ++ case VKD3DSIH_ISHL: ++ case VKD3DSIH_ISHR: ++ case VKD3DSIH_USHR: ++ if (ins->flags & VKD3DSI_SHIFT_UNMASKED) ++ shader_addline(buffer, "_unmasked"); ++ /* fall through */ + default: + shader_dump_precise_flags(compiler, ins->flags); + break; +@@ -1835,25 +1882,25 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, + vkd3d_string_buffer_printf(buffer, " %sc%u%s", compiler->colours.reg, + shader_get_float_offset(ins->dst[0].reg.type, ins->dst[0].reg.idx[0].offset), + compiler->colours.reset); +- shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_float[0], ""); +- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[1], ""); +- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[2], ""); +- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[3], ""); ++ shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_f32[0], ""); ++ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[1], ""); ++ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[2], ""); ++ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[3], ""); + break; + + case VKD3DSIH_DEFI: + vkd3d_string_buffer_printf(buffer, " %si%u%s", compiler->colours.reg, + ins->dst[0].reg.idx[0].offset, compiler->colours.reset); +- shader_print_int_literal(compiler, " = ", ins->src[0].reg.u.immconst_uint[0], ""); +- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[1], ""); +- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[2], ""); +- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[3], ""); ++ shader_print_int_literal(compiler, " = ", ins->src[0].reg.u.immconst_u32[0], ""); ++ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[1], ""); ++ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[2], ""); ++ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[3], ""); + break; + + case VKD3DSIH_DEFB: + vkd3d_string_buffer_printf(buffer, " %sb%u%s", compiler->colours.reg, + ins->dst[0].reg.idx[0].offset, compiler->colours.reset); +- shader_print_bool_literal(compiler, " = ", ins->src[0].reg.u.immconst_uint[0], ""); ++ shader_print_bool_literal(compiler, " = ", ins->src[0].reg.u.immconst_u32[0], ""); + break; + + default: +@@ -1883,7 +1930,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, + || ins->resource_data_type[1] != VKD3D_DATA_FLOAT + || ins->resource_data_type[2] != VKD3D_DATA_FLOAT + || ins->resource_data_type[3] != VKD3D_DATA_FLOAT) +- shader_dump_data_type(compiler, ins->resource_data_type); ++ shader_dump_resource_data_type(compiler, ins->resource_data_type); + + for (i = 0; i < ins->dst_count; ++i) + { +@@ -1906,10 +1953,13 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, + + enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions, + const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info, +- struct vkd3d_shader_code *out) ++ struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect) + { + enum vkd3d_shader_compile_option_formatting_flags formatting; +- struct vkd3d_d3d_asm_compiler compiler; ++ struct vkd3d_d3d_asm_compiler compiler = ++ { ++ .dialect = dialect, ++ }; + enum vkd3d_result result = VKD3D_OK; + struct vkd3d_string_buffer *buffer; + unsigned int indent, i, j; +@@ -2002,6 +2052,7 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instructio + { + case VKD3DSIH_ELSE: + case VKD3DSIH_IF: ++ case VKD3DSIH_IFC: + case VKD3DSIH_LOOP: + case VKD3DSIH_SWITCH: + ++indent; +@@ -2034,7 +2085,7 @@ void vkd3d_shader_trace(const struct vkd3d_shader_instruction_array *instruction + const char *p, *q, *end; + struct vkd3d_shader_code code; + +- if (vkd3d_dxbc_binary_to_text(instructions, shader_version, NULL, &code) != VKD3D_OK) ++ if (vkd3d_dxbc_binary_to_text(instructions, shader_version, NULL, &code, VSIR_ASM_VSIR) != 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 3d139416b61..ca6e3b72de9 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -987,7 +987,7 @@ static void shader_sm1_read_immconst(struct vkd3d_shader_sm1_parser *sm1, const + src_param->reg.idx[2].rel_addr = NULL; + src_param->reg.idx_count = 0; + src_param->reg.dimension = dimension; +- memcpy(src_param->reg.u.immconst_uint, *ptr, count * sizeof(uint32_t)); ++ memcpy(src_param->reg.u.immconst_u32, *ptr, count * sizeof(uint32_t)); + src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE; + src_param->modifiers = 0; + +@@ -1063,12 +1063,12 @@ static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1, + } + } + +-static unsigned int mask_from_swizzle(unsigned int swizzle) ++static unsigned int mask_from_swizzle(uint32_t swizzle) + { +- return (1u << vkd3d_swizzle_get_component(swizzle, 0)) +- | (1u << vkd3d_swizzle_get_component(swizzle, 1)) +- | (1u << vkd3d_swizzle_get_component(swizzle, 2)) +- | (1u << vkd3d_swizzle_get_component(swizzle, 3)); ++ return (1u << vsir_swizzle_get_component(swizzle, 0)) ++ | (1u << vsir_swizzle_get_component(swizzle, 1)) ++ | (1u << vsir_swizzle_get_component(swizzle, 2)) ++ | (1u << vsir_swizzle_get_component(swizzle, 3)); + } + + static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, struct vkd3d_shader_instruction *ins) +@@ -2253,7 +2253,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b + { + struct hlsl_reg *reg = &jump->condition.node->reg; + +- struct sm1_instruction instr = ++ struct sm1_instruction sm1_instr = + { + .opcode = D3DSIO_TEXKILL, + +@@ -2263,7 +2263,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b + .has_dst = 1, + }; + +- write_sm1_instruction(ctx, buffer, &instr); ++ write_sm1_instruction(ctx, buffer, &sm1_instr); + break; + } + +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +index 7834c1e1615..63deaaad29a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +@@ -431,10 +431,6 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s + case TAG_OSG5: + if (e[i].sysval_semantic == VKD3D_SHADER_SV_NONE) + e[i].sysval_semantic = map_fragment_output_sysval(e[i].semantic_name); +- /* Fall through. */ +- case TAG_PCSG: +- case TAG_PSG1: +- e[i].used_mask = e[i].mask & ~e[i].used_mask; + break; + } + +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index beb9ae574dc..2424b176068 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -29,6 +29,9 @@ static const uint64_t MAX_ALIGNMENT_EXPONENT = 29; + static const uint64_t GLOBALVAR_FLAG_IS_CONSTANT = 1; + static const uint64_t GLOBALVAR_FLAG_EXPLICIT_TYPE = 2; + static const unsigned int GLOBALVAR_ADDRESS_SPACE_SHIFT = 2; ++static const uint64_t ALLOCA_FLAG_IN_ALLOCA = 0x20; ++static const uint64_t ALLOCA_FLAG_EXPLICIT_TYPE = 0x40; ++static const uint64_t ALLOCA_ALIGNMENT_MASK = ALLOCA_FLAG_IN_ALLOCA - 1; + static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4; + + static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64}; +@@ -296,8 +299,28 @@ enum dx_intrinsic_opcode + { + DX_LOAD_INPUT = 4, + DX_STORE_OUTPUT = 5, ++ DX_EXP = 21, ++ DX_FRC = 22, ++ DX_LOG = 23, ++ DX_SQRT = 24, ++ DX_RSQRT = 25, ++ DX_ROUND_NE = 26, ++ DX_ROUND_NI = 27, ++ DX_ROUND_PI = 28, ++ DX_ROUND_Z = 29, ++ DX_BFREV = 30, ++ DX_COUNT_BITS = 31, ++ DX_FIRST_BIT_LO = 32, ++ DX_FIRST_BIT_HI = 33, ++ DX_FIRST_BIT_SHI = 34, + DX_CREATE_HANDLE = 57, + DX_CBUFFER_LOAD_LEGACY = 59, ++ DX_DERIV_COARSEX = 83, ++ DX_DERIV_COARSEY = 84, ++ DX_DERIV_FINEX = 85, ++ DX_DERIV_FINEY = 86, ++ DX_LEGACY_F32TOF16 = 130, ++ DX_LEGACY_F16TOF32 = 131, + }; + + enum dxil_cast_code +@@ -439,6 +462,7 @@ struct dxil_record + { + unsigned int code; + unsigned int operand_count; ++ const struct dxil_record *attachment; + uint64_t operands[]; + }; + +@@ -581,6 +605,7 @@ struct sm6_parser + size_t descriptor_count; + + unsigned int indexable_temp_count; ++ unsigned int icb_count; + + struct sm6_value *values; + size_t value_count; +@@ -796,6 +821,7 @@ static enum vkd3d_result sm6_parser_read_unabbrev_record(struct sm6_parser *sm6) + + record->code = code; + record->operand_count = count; ++ record->attachment = NULL; + + for (i = 0; i < count; ++i) + record->operands[i] = sm6_parser_read_vbr(sm6, 6); +@@ -1012,6 +1038,7 @@ static enum vkd3d_result sm6_parser_read_abbrev_record(struct sm6_parser *sm6, u + if (!abbrev->operands[i + 1].read_operand(sm6, abbrev->operands[i + 1].context, &record->operands[i])) + goto fail; + record->operand_count = count; ++ record->attachment = NULL; + + /* An array can occur only as the last operand. */ + if (abbrev->is_array) +@@ -1210,7 +1237,7 @@ static size_t dxil_block_compute_module_decl_count(const struct dxil_block *bloc + size_t i, count; + + for (i = 0, count = 0; i < block->record_count; ++i) +- count += block->records[i]->code == MODULE_CODE_FUNCTION; ++ count += block->records[i]->code == MODULE_CODE_FUNCTION || block->records[i]->code == MODULE_CODE_GLOBALVAR; + return count; + } + +@@ -1572,6 +1599,11 @@ static bool sm6_type_is_bool_i16_i32_i64(const struct sm6_type *type) + return type->class == TYPE_CLASS_INTEGER && (type->u.width == 1 || type->u.width >= 16); + } + ++static bool sm6_type_is_i16_i32_i64(const struct sm6_type *type) ++{ ++ return type->class == TYPE_CLASS_INTEGER && type->u.width >= 16; ++} ++ + static bool sm6_type_is_bool(const struct sm6_type *type) + { + return type->class == TYPE_CLASS_INTEGER && type->u.width == 1; +@@ -1587,6 +1619,16 @@ static inline bool sm6_type_is_i32(const struct sm6_type *type) + return type->class == TYPE_CLASS_INTEGER && type->u.width == 32; + } + ++static bool sm6_type_is_float(const struct sm6_type *type) ++{ ++ return type->class == TYPE_CLASS_FLOAT && type->u.width == 32; ++} ++ ++static bool sm6_type_is_f16_f32(const struct sm6_type *type) ++{ ++ return type->class == TYPE_CLASS_FLOAT && (type->u.width == 16 || type->u.width == 32); ++} ++ + static inline bool sm6_type_is_floating_point(const struct sm6_type *type) + { + return type->class == TYPE_CLASS_FLOAT; +@@ -1844,12 +1886,12 @@ static unsigned int register_get_uint_value(const struct vkd3d_shader_register * + + if (reg->type == VKD3DSPR_IMMCONST64) + { +- if (reg->u.immconst_uint64[0] > UINT_MAX) ++ if (reg->u.immconst_u64[0] > UINT_MAX) + FIXME("Truncating 64-bit value.\n"); +- return reg->u.immconst_uint64[0]; ++ return reg->u.immconst_u64[0]; + } + +- return reg->u.immconst_uint[0]; ++ return reg->u.immconst_u32[0]; + } + + static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *reg) +@@ -1860,7 +1902,7 @@ static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *re + if (reg->dimension == VSIR_DIMENSION_VEC4) + WARN("Returning vec4.x.\n"); + +- return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_uint64[0] : reg->u.immconst_uint[0]; ++ return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_u64[0] : reg->u.immconst_u32[0]; + } + + static inline bool sm6_value_is_function_dcl(const struct sm6_value *value) +@@ -2412,7 +2454,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + return VKD3D_ERROR_INVALID_SHADER; + } + size = max(size, sizeof(icb->data[0])); +- count = type->u.array.count * size / sizeof(icb->data[0]); ++ count = operands ? type->u.array.count * size / sizeof(icb->data[0]) : 0; + + if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[count])))) + { +@@ -2433,9 +2475,14 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + dst->value_type = VALUE_TYPE_ICB; + dst->u.icb = icb; + ++ icb->register_idx = sm6->icb_count++; + icb->data_type = vkd3d_data_type_from_sm6_type(elem_type); + icb->element_count = type->u.array.count; + icb->component_count = 1; ++ icb->is_null = !operands; ++ ++ if (!operands) ++ return VKD3D_OK; + + count = type->u.array.count; + if (size > sizeof(icb->data[0])) +@@ -2510,12 +2557,10 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + switch (record->code) + { + case CST_CODE_NULL: +- if (sm6_type_is_array(type)) ++ if (sm6_type_is_array(type) ++ && (ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) + { +- FIXME("Constant null arrays are not supported.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +- "Constant null arrays are not supported."); +- return VKD3D_ERROR_INVALID_SHADER; ++ return ret; + } + /* For non-aggregates, register constant data is already zero-filled. */ + break; +@@ -2532,9 +2577,9 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + + value = decode_rotated_signed_value(record->operands[0]); + if (type->u.width <= 32) +- dst->u.reg.u.immconst_uint[0] = value & ((1ull << type->u.width) - 1); ++ dst->u.reg.u.immconst_u32[0] = value & ((1ull << type->u.width) - 1); + else +- dst->u.reg.u.immconst_uint64[0] = value; ++ dst->u.reg.u.immconst_u64[0] = value; + + break; + +@@ -2551,9 +2596,9 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + if (type->u.width == 16) + FIXME("Half float type is not supported yet.\n"); + else if (type->u.width == 32) +- dst->u.reg.u.immconst_float[0] = bitcast_uint64_to_float(record->operands[0]); ++ dst->u.reg.u.immconst_f32[0] = bitcast_uint64_to_float(record->operands[0]); + else if (type->u.width == 64) +- dst->u.reg.u.immconst_double[0] = bitcast_uint64_to_double(record->operands[0]); ++ dst->u.reg.u.immconst_f64[0] = bitcast_uint64_to_double(record->operands[0]); + else + vkd3d_unreachable(); + +@@ -2588,6 +2633,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + break; + } + ++ if (record->attachment) ++ { ++ WARN("Ignoring metadata attachment.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring a metadata attachment for a constant."); ++ } ++ + ++sm6->value_count; + } + +@@ -2626,13 +2678,28 @@ static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_pa + return ins; + } + +-static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, +- unsigned int count, unsigned int alignment, unsigned int init, struct sm6_value *dst) ++static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type *elem_type, unsigned int count, ++ unsigned int alignment, unsigned int init, struct sm6_value *dst) + { + enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); + struct vkd3d_shader_instruction *ins; + +- ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_INDEXABLE_TEMP); ++ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER); ++ /* The icb value index will be resolved later so forward references can be handled. */ ++ ins->declaration.icb = (void *)(intptr_t)init; ++ register_init_with_id(&dst->u.reg, VKD3DSPR_IMMCONSTBUFFER, data_type, init); ++} ++ ++static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, ++ unsigned int count, unsigned int alignment, unsigned int init, struct vkd3d_shader_instruction *ins, ++ struct sm6_value *dst) ++{ ++ enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); ++ ++ if (ins) ++ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_DCL_INDEXABLE_TEMP); ++ else ++ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_INDEXABLE_TEMP); + ins->declaration.indexable_temp.register_idx = sm6->indexable_temp_count++; + ins->declaration.indexable_temp.register_size = count; + ins->declaration.indexable_temp.alignment = alignment; +@@ -2762,7 +2829,10 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ + + if (address_space == ADDRESS_SPACE_DEFAULT) + { +- sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst); ++ if (is_constant) ++ sm6_parser_declare_icb(sm6, scalar_type, count, alignment, init, dst); ++ else ++ sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, NULL, dst); + } + else if (address_space == ADDRESS_SPACE_GROUPSHARED) + { +@@ -2790,31 +2860,37 @@ static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_init + + assert(index); + --index; +- if (!(value = sm6_parser_get_value_safe(sm6, index)) || !sm6_value_is_icb(value)) ++ if (!(value = sm6_parser_get_value_safe(sm6, index)) || (!sm6_value_is_icb(value) && !sm6_value_is_undef(value))) + { + WARN("Invalid initialiser index %zu.\n", index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Global variable initialiser value index %zu is invalid.", index); + return NULL; + } +- else ++ else if (sm6_value_is_icb(value)) + { + return value->u.icb; + } ++ /* In VSIR, initialisation with undefined values of objects is implied, not explicit. */ ++ return NULL; + } + + static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) + { ++ size_t i, count, base_value_idx = sm6->value_count; + const struct dxil_block *block = &sm6->root_block; + struct vkd3d_shader_instruction *ins; + const struct dxil_record *record; + enum vkd3d_result ret; + uint64_t version; +- size_t i; + + sm6->p.location.line = block->id; + sm6->p.location.column = 0; + ++ for (i = 0, count = 0; i < block->record_count; ++i) ++ count += block->records[i]->code == MODULE_CODE_GLOBALVAR; ++ sm6_parser_require_space(sm6, count); ++ + for (i = 0; i < block->record_count; ++i) + { + sm6->p.location.column = i; +@@ -2868,6 +2944,21 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) + ins->declaration.indexable_temp.initialiser = resolve_forward_initialiser( + (uintptr_t)ins->declaration.indexable_temp.initialiser, sm6); + } ++ else if (ins->handler_idx == VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER) ++ { ++ ins->declaration.icb = resolve_forward_initialiser((uintptr_t)ins->declaration.icb, sm6); ++ } ++ } ++ for (i = base_value_idx; i < sm6->value_count; ++i) ++ { ++ const struct vkd3d_shader_immediate_constant_buffer *icb; ++ struct sm6_value *value = &sm6->values[i]; ++ ++ if (!sm6_value_is_register(value) || value->u.reg.type != VKD3DSPR_IMMCONSTBUFFER) ++ continue; ++ ++ if ((icb = resolve_forward_initialiser(value->u.reg.idx[0].offset, sm6))) ++ value->u.reg.idx[0].offset = icb->register_idx; + } + + return VKD3D_OK; +@@ -2908,45 +2999,6 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade + } + } + +-static void sm6_parser_emit_signature(struct sm6_parser *sm6, const struct shader_signature *s, +- enum vkd3d_shader_opcode handler_idx, enum vkd3d_shader_opcode siv_handler_idx, +- struct vkd3d_shader_dst_param *params) +-{ +- struct vkd3d_shader_instruction *ins; +- struct vkd3d_shader_dst_param *param; +- const struct signature_element *e; +- unsigned int i; +- +- for (i = 0; i < s->element_count; ++i) +- { +- e = &s->elements[i]; +- +- /* Do not check e->used_mask because in some cases it is zero for used elements. +- * TODO: scan ahead for used I/O elements. */ +- +- if (e->sysval_semantic != VKD3D_SHADER_SV_NONE && e->sysval_semantic != VKD3D_SHADER_SV_TARGET) +- { +- ins = sm6_parser_add_instruction(sm6, siv_handler_idx); +- param = &ins->declaration.register_semantic.reg; +- ins->declaration.register_semantic.sysval_semantic = vkd3d_siv_from_sysval(e->sysval_semantic); +- } +- else +- { +- ins = sm6_parser_add_instruction(sm6, handler_idx); +- param = &ins->declaration.dst; +- } +- +- ins->flags = e->interpolation_mode; +- *param = params[i]; +- +- if (e->register_count > 1) +- { +- param->reg.idx[0].rel_addr = NULL; +- param->reg.idx[0].offset = e->register_count; +- } +- } +-} +- + static void sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) + { + sm6_parser_init_signature(sm6, output_signature, VKD3DSPR_OUTPUT, sm6->output_params); +@@ -2957,19 +3009,6 @@ static void sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct + sm6_parser_init_signature(sm6, input_signature, VKD3DSPR_INPUT, sm6->input_params); + } + +-static void sm6_parser_emit_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) +-{ +- sm6_parser_emit_signature(sm6, output_signature, VKD3DSIH_DCL_OUTPUT, VKD3DSIH_DCL_OUTPUT_SIV, sm6->output_params); +-} +- +-static void sm6_parser_emit_input_signature(struct sm6_parser *sm6, const struct shader_signature *input_signature) +-{ +- sm6_parser_emit_signature(sm6, input_signature, +- (sm6->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3DSIH_DCL_INPUT_PS : VKD3DSIH_DCL_INPUT, +- (sm6->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3DSIH_DCL_INPUT_PS_SIV : VKD3DSIH_DCL_INPUT_SIV, +- sm6->input_params); +-} +- + static const struct sm6_value *sm6_parser_next_function_definition(struct sm6_parser *sm6) + { + size_t i, count = sm6->function_count; +@@ -2992,6 +3031,81 @@ static struct sm6_block *sm6_block_create() + return block; + } + ++static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_record *record, ++ struct vkd3d_shader_instruction *ins, struct sm6_value *dst) ++{ ++ const struct sm6_type *type[2], *elem_type; ++ const struct sm6_value *size; ++ unsigned int i, alignment; ++ uint64_t packed_operands; ++ ++ if (!dxil_record_validate_operand_count(record, 4, 4, sm6)) ++ return; ++ ++ for (i = 0; i < 2; ++i) ++ { ++ if (!(type[i] = sm6_parser_get_type(sm6, record->operands[i]))) ++ return; ++ } ++ ++ packed_operands = record->operands[3]; ++ if (packed_operands & ALLOCA_FLAG_IN_ALLOCA) ++ WARN("Ignoring in_alloca flag.\n"); ++ if (!(packed_operands & ALLOCA_FLAG_EXPLICIT_TYPE)) ++ { ++ FIXME("Unhandled implicit type.\n"); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Implicit result type for ALLOCA instructions is not supported."); ++ return; ++ } ++ packed_operands &= ~(ALLOCA_FLAG_IN_ALLOCA | ALLOCA_FLAG_EXPLICIT_TYPE); ++ ++ if (!sm6_type_is_array(type[0]) || !sm6_type_is_numeric(elem_type = type[0]->u.array.elem_type)) ++ { ++ WARN("Type is not a numeric array.\n"); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Result type of an ALLOCA instruction is not a numeric array."); ++ return; ++ } ++ /* The second type operand is the type of the allocation size operand, in case it is a ++ * forward reference. We only support a constant size, so no forward ref support is needed. */ ++ if (!sm6_type_is_integer(type[1])) ++ { ++ WARN("Size operand type is not scalar integer.\n"); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "The type of the allocation size operand of an ALLOCA instruction is not scalar integer."); ++ return; ++ } ++ ++ if (!(dst->type = sm6_type_get_pointer_to_type(type[0], ADDRESS_SPACE_DEFAULT, sm6))) ++ { ++ WARN("Failed to get pointer type for type class %u.\n", type[0]->class); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, ++ "Module does not define a pointer type for an ALLOCA instruction."); ++ return; ++ } ++ ++ if (!(size = sm6_parser_get_value_safe(sm6, record->operands[2]))) ++ return; ++ /* A size of 1 means one instance of type[0], i.e. one array. */ ++ if (sm6_value_get_constant_uint(size) != 1) ++ { ++ FIXME("Allocation size is not 1.\n"); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "ALLOCA instruction allocation sizes other than 1 are not supported."); ++ return; ++ } ++ ++ if (!bitcode_parse_alignment(packed_operands & ALLOCA_ALIGNMENT_MASK, &alignment)) ++ WARN("Invalid alignment %"PRIu64".\n", packed_operands); ++ packed_operands &= ~ALLOCA_ALIGNMENT_MASK; ++ ++ if (packed_operands) ++ WARN("Ignoring flags %#"PRIx64".\n", packed_operands); ++ ++ sm6_parser_declare_indexable_temp(sm6, elem_type, type[0]->u.array.count, alignment, 0, ins, dst); ++} ++ + static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_type *type_a, + const struct sm6_type *type_b, struct sm6_parser *sm6) + { +@@ -3092,8 +3206,10 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco + unsigned int i = 0; + + a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i); ++ if (!a) ++ return; + b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i); +- if (!a || !b) ++ if (!b) + return; + + if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6)) +@@ -3167,10 +3283,77 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco + } + else + { ++ if (handler_idx == VKD3DSIH_ISHL || handler_idx == VKD3DSIH_ISHR || handler_idx == VKD3DSIH_USHR) ++ { ++ /* DXC emits AND instructions where necessary to mask shift counts. Shift binops ++ * do not imply masking the shift as the TPF equivalents do. */ ++ ins->flags |= VKD3DSI_SHIFT_UNMASKED; ++ } + instruction_dst_param_init_ssa_scalar(ins, sm6); + } + } + ++static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) ++{ ++ switch (op) ++ { ++ case DX_EXP: ++ return VKD3DSIH_EXP; ++ case DX_FRC: ++ return VKD3DSIH_FRC; ++ case DX_LOG: ++ return VKD3DSIH_LOG; ++ case DX_SQRT: ++ return VKD3DSIH_SQRT; ++ case DX_RSQRT: ++ return VKD3DSIH_RSQ; ++ case DX_ROUND_NE: ++ return VKD3DSIH_ROUND_NE; ++ case DX_ROUND_NI: ++ return VKD3DSIH_ROUND_NI; ++ case DX_ROUND_PI: ++ return VKD3DSIH_ROUND_PI; ++ case DX_ROUND_Z: ++ return VKD3DSIH_ROUND_Z; ++ case DX_BFREV: ++ return VKD3DSIH_BFREV; ++ case DX_COUNT_BITS: ++ return VKD3DSIH_COUNTBITS; ++ case DX_FIRST_BIT_LO: ++ return VKD3DSIH_FIRSTBIT_LO; ++ case DX_FIRST_BIT_HI: ++ return VKD3DSIH_FIRSTBIT_HI; ++ case DX_FIRST_BIT_SHI: ++ return VKD3DSIH_FIRSTBIT_SHI; ++ case DX_DERIV_COARSEX: ++ return VKD3DSIH_DSX_COARSE; ++ case DX_DERIV_COARSEY: ++ return VKD3DSIH_DSY_COARSE; ++ case DX_DERIV_FINEX: ++ return VKD3DSIH_DSX_FINE; ++ case DX_DERIV_FINEY: ++ return VKD3DSIH_DSY_FINE; ++ case DX_LEGACY_F32TOF16: ++ return VKD3DSIH_F32TOF16; ++ case DX_LEGACY_F16TOF32: ++ return VKD3DSIH_F16TOF32; ++ default: ++ vkd3d_unreachable(); ++ } ++} ++ ++static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, struct sm6_block *code_block, ++ enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) ++{ ++ struct vkd3d_shader_src_param *src_param; ++ ++ vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); ++ src_param = instruction_src_params_alloc(ins, 1, sm6); ++ src_param_init_from_value(src_param, operands[0]); ++ ++ instruction_dst_param_init_ssa_scalar(ins, sm6); ++} ++ + static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, struct sm6_block *code_block, + enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) + { +@@ -3344,7 +3527,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, struct sm6_b + + struct sm6_dx_opcode_info + { +- const char ret_type; ++ const char *ret_type; + const char *operand_info; + void (*handler)(struct sm6_parser *, struct sm6_block *, enum dx_intrinsic_opcode, + const struct sm6_value **, struct vkd3d_shader_instruction *); +@@ -3355,16 +3538,40 @@ struct sm6_dx_opcode_info + b -> constant int1 + c -> constant int8/16/32 + i -> int32 ++ m -> int16/32/64 ++ f -> float ++ e -> half/float ++ g -> half/float/double + H -> handle + v -> void + o -> overloaded + */ + static const struct sm6_dx_opcode_info sm6_dx_op_table[] = + { +- [DX_CBUFFER_LOAD_LEGACY ] = {'o', "Hi", sm6_parser_emit_dx_cbuffer_load}, +- [DX_CREATE_HANDLE ] = {'H', "ccib", sm6_parser_emit_dx_create_handle}, +- [DX_LOAD_INPUT ] = {'o', "ii8i", sm6_parser_emit_dx_load_input}, +- [DX_STORE_OUTPUT ] = {'v', "ii8o", sm6_parser_emit_dx_store_output}, ++ [DX_BFREV ] = {"m0", "m", sm6_parser_emit_dx_unary}, ++ [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, ++ [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, ++ [DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle}, ++ [DX_DERIV_COARSEX ] = {"e0", "e", sm6_parser_emit_dx_unary}, ++ [DX_DERIV_COARSEY ] = {"e0", "e", sm6_parser_emit_dx_unary}, ++ [DX_DERIV_FINEX ] = {"e0", "e", sm6_parser_emit_dx_unary}, ++ [DX_DERIV_FINEY ] = {"e0", "e", sm6_parser_emit_dx_unary}, ++ [DX_EXP ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_FIRST_BIT_HI ] = {"i", "m", sm6_parser_emit_dx_unary}, ++ [DX_FIRST_BIT_LO ] = {"i", "m", sm6_parser_emit_dx_unary}, ++ [DX_FIRST_BIT_SHI ] = {"i", "m", sm6_parser_emit_dx_unary}, ++ [DX_FRC ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_LEGACY_F16TOF32 ] = {"f", "i", sm6_parser_emit_dx_unary}, ++ [DX_LEGACY_F32TOF16 ] = {"i", "f", sm6_parser_emit_dx_unary}, ++ [DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input}, ++ [DX_LOG ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_ROUND_NE ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_ROUND_NI ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_ROUND_PI ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_ROUND_Z ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_RSQRT ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_SQRT ] = {"g0", "g", sm6_parser_emit_dx_unary}, ++ [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, + }; + + static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type, +@@ -3389,6 +3596,14 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc + && type->u.width <= 32; + case 'i': + return sm6_type_is_i32(type); ++ case 'm': ++ return sm6_type_is_i16_i32_i64(type); ++ case 'f': ++ return sm6_type_is_float(type); ++ case 'e': ++ return sm6_type_is_f16_f32(type); ++ case 'g': ++ return sm6_type_is_floating_point(type); + case 'H': + return (is_return || sm6_value_is_handle(value)) && type == sm6->handle_type; + case 'v': +@@ -3402,6 +3617,17 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc + } + } + ++static bool operand_types_match(struct sm6_value *dst, const struct sm6_value **operands, unsigned int operand_count, ++ char index_char) ++{ ++ unsigned int i = index_char - '0'; ++ ++ assert(i < 10); ++ if (i >= operand_count) ++ return false; ++ return dst->type == operands[i]->type; ++} ++ + static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const char *name, + const struct sm6_value **operands, unsigned int operand_count, struct sm6_value *dst) + { +@@ -3410,7 +3636,9 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ + + info = &sm6_dx_op_table[op]; + +- if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type, true)) ++ assert(info->ret_type[0]); ++ if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type[0], true) ++ || (info->ret_type[1] && !operand_types_match(dst, operands, operand_count, info->ret_type[1]))) + { + WARN("Failed to validate return type for dx intrinsic id %u, '%s'.\n", op, name); + /* Return type validation failure is not so critical. We only need to set +@@ -3700,6 +3928,9 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor + if (handler_idx == VKD3DSIH_NOP) + { + dst->u.reg = value->u.reg; ++ /* Set the result type for casts from 16-bit min precision. */ ++ if (type->u.width != 16) ++ dst->u.reg.data_type = vkd3d_data_type_from_sm6_type(type); + return; + } + +@@ -3775,8 +4006,10 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor + } + + a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i); ++ if (!a) ++ return; + b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i); +- if (!a || !b) ++ if (!b) + return; + + if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6)) +@@ -4065,6 +4298,57 @@ static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record + ins->handler_idx = VKD3DSIH_NOP; + } + ++static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_record *record, ++ struct vkd3d_shader_instruction *ins, struct sm6_value *dst) ++{ ++ struct vkd3d_shader_src_param *src_param; ++ struct vkd3d_shader_dst_param *dst_param; ++ const struct sm6_type *pointee_type; ++ const struct sm6_value *ptr, *src; ++ unsigned int i = 0, alignment; ++ uint64_t alignment_code; ++ ++ if (!(ptr = sm6_parser_get_value_by_ref(sm6, record, NULL, &i)) ++ || !sm6_value_validate_is_register(ptr, sm6) ++ || !sm6_value_validate_is_pointer(ptr, sm6)) ++ { ++ return; ++ } ++ ++ pointee_type = ptr->type->u.pointer.type; ++ if (!(src = sm6_parser_get_value_by_ref(sm6, record, pointee_type, &i))) ++ return; ++ if (!sm6_value_validate_is_numeric(src, sm6)) ++ return; ++ ++ if (pointee_type != src->type) ++ { ++ WARN("Type mismatch.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, ++ "Type mismatch in pointer store arguments."); ++ } ++ ++ if (!dxil_record_validate_operand_count(record, i + 2, i + 2, sm6)) ++ return; ++ ++ alignment_code = record->operands[i++]; ++ if (!bitcode_parse_alignment(alignment_code, &alignment)) ++ WARN("Invalid alignment %"PRIu64".\n", alignment_code); ++ ++ if (record->operands[i]) ++ WARN("Ignoring volatile modifier.\n"); ++ ++ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); ++ ++ src_param = instruction_src_params_alloc(ins, 1, sm6); ++ src_param_init_from_value(&src_param[0], src); ++ ++ dst_param = instruction_dst_params_alloc(ins, 1, sm6); ++ dst_param_init(dst_param); ++ dst_param->reg = ptr->u.reg; ++ dst_param->reg.alignment = alignment; ++} ++ + static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_record *record, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst) + { +@@ -4153,6 +4437,208 @@ static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, + return true; + } + ++static void sm6_parser_metadata_attachment_block_init(struct sm6_parser *sm6, const struct dxil_block *target_block, ++ const struct dxil_block *block) ++{ ++ struct dxil_record *target_record; ++ const struct dxil_record *record; ++ unsigned int i; ++ uint64_t index; ++ ++ for (i = 0; i < block->record_count; ++i) ++ { ++ record = block->records[i]; ++ if (record->code != METADATA_ATTACHMENT) ++ { ++ WARN("Ignoring record with code %u.\n", record->code); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring a metadata attachment record with code %u.", record->code); ++ continue; ++ } ++ if (!(record->operand_count & 1)) ++ { ++ WARN("Ignoring function attachment.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring a metadata function attachment."); ++ continue; ++ } ++ ++ index = record->operands[0]; ++ if (!target_block->record_count || index >= target_block->record_count - 1) ++ { ++ WARN("Invalid record index %"PRIu64".\n", index); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Invalid record index %"PRIu64" for a metadata attachment.", index); ++ continue; ++ } ++ /* 'index' is an instruction index, but records[0] is DECLAREBLOCKS, not an instruction. */ ++ target_record = target_block->records[index + 1]; ++ if (target_record->attachment) ++ { ++ WARN("Overwriting record attachment.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "The target record for a metadata attachment already has an attachment."); ++ } ++ target_record->attachment = record; ++ } ++} ++ ++static void sm6_parser_metadata_attachments_init(struct sm6_parser *sm6, const struct dxil_block *block) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < block->child_block_count; ++i) ++ { ++ if (block->child_blocks[i]->id == METADATA_ATTACHMENT_BLOCK) ++ sm6_parser_metadata_attachment_block_init(sm6, block, block->child_blocks[i]); ++ } ++} ++ ++static const struct sm6_metadata_value *sm6_parser_find_metadata_kind(const struct sm6_parser *sm6, uint64_t id) ++{ ++ unsigned int i, j; ++ ++ for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) ++ { ++ for (j = 0; j < sm6->metadata_tables[i].count; ++j) ++ { ++ if (sm6->metadata_tables[i].values[j].type == VKD3D_METADATA_KIND ++ && sm6->metadata_tables[i].values[j].u.kind.id == id) ++ return &sm6->metadata_tables[i].values[j]; ++ } ++ } ++ ++ return NULL; ++} ++ ++static const struct sm6_metadata_value *sm6_parser_metadata_get_value(const struct sm6_parser *sm6, uint64_t index) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) ++ { ++ if (sm6->metadata_tables[i].count > index) ++ break; ++ index -= sm6->metadata_tables[i].count; ++ } ++ ++ return (index < sm6->metadata_tables[i].count) ? &sm6->metadata_tables[i].values[index] : NULL; ++} ++ ++static bool metadata_node_get_unary_uint(const struct sm6_metadata_node *node, unsigned int *operand, ++ struct sm6_parser *sm6) ++{ ++ if (node->operand_count != 1) ++ { ++ FIXME("Ignoring node with %u operands.\n", node->operand_count); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring metadata attachment node with %u operands; expected unary.", node->operand_count); ++ return false; ++ } ++ if (!sm6_metadata_value_is_value(node->operands[0]) ++ || !sm6_metadata_get_uint_value(sm6, node->operands[0], operand)) ++ { ++ WARN("Failed to get operand value.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Failed to get a metadata attachment operand value; ignoring the attachment."); ++ return false; ++ } ++ ++ return true; ++} ++ ++static void metadata_attachment_record_apply(const struct dxil_record *record, enum bitcode_function_code func_code, ++ struct vkd3d_shader_instruction *ins, struct sm6_value *dst, struct sm6_parser *sm6) ++{ ++ static const char *ignored_names[] = ++ { ++ "alias.scope", ++ "dx.controlflow.hints", ++ "llvm.loop", ++ "noalias", ++ "tbaa", ++ "range", ++ }; ++ const struct sm6_metadata_node *node; ++ const struct sm6_metadata_value *m; ++ unsigned int i, j, operand; ++ bool ignored = false; ++ const char *name; ++ ++ if (record->attachment) ++ { ++ WARN("Ignoring nested metadata attachment.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring a nested metadata attachment."); ++ } ++ ++ assert(record->operand_count & 1); ++ for (i = 1; i < record->operand_count; i += 2) ++ { ++ if (!(m = sm6_parser_find_metadata_kind(sm6, record->operands[i]))) ++ { ++ WARN("Failed to find metadata kind %"PRIx64".\n", record->operands[i]); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Failed to find metadata kind %"PRIx64" for an attachment.", record->operands[i]); ++ continue; ++ } ++ name = m->u.kind.name; ++ ++ m = sm6_parser_metadata_get_value(sm6, record->operands[i + 1]); ++ if (!m || !sm6_metadata_value_is_node(m)) ++ { ++ WARN("Failed to retrieve metadata attachment node.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Failed to retrieve a metadata attachment node."); ++ continue; ++ } ++ node = m->u.node; ++ ++ if (!strcmp(name, "dx.precise")) ++ { ++ if (!sm6_value_is_register(dst)) ++ { ++ WARN("Precise value is not a register.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "A value marked as precise is not a register."); ++ } ++ else if (metadata_node_get_unary_uint(node, &operand, sm6) && operand) ++ { ++ ins->flags |= sm6_type_is_scalar(dst->type) ? VKD3DSI_PRECISE_X : VKD3DSI_PRECISE_XYZW; ++ } ++ } ++ else if (!strcmp(name, "dx.nonuniform")) ++ { ++ if (!sm6_value_is_register(dst)) ++ { ++ WARN("Non-uniform value is not a register.\n"); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "A value marked as non-uniform is not a register."); ++ } ++ else if (metadata_node_get_unary_uint(node, &operand, sm6)) ++ { ++ dst->u.reg.non_uniform = !!operand; ++ } ++ } ++ else ++ { ++ for (j = 0; j < ARRAY_SIZE(ignored_names); ++j) ++ if (!strcmp(name, ignored_names[j])) ++ break; ++ if (j == ARRAY_SIZE(ignored_names)) ++ { ++ WARN("Ignoring metadata attachment '%s'.\n", name); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring a metadata attachment named '%s'.", name); ++ } ++ ignored = true; ++ } ++ ++ if (func_code != FUNC_CODE_INST_CALL && !ignored) ++ WARN("Metadata attachment target is not a function call.\n"); ++ } ++} ++ + static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, + struct sm6_function *function) + { +@@ -4240,6 +4726,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + record = block->records[i]; + switch (record->code) + { ++ case FUNC_CODE_INST_ALLOCA: ++ sm6_parser_emit_alloca(sm6, record, ins, dst); ++ break; + case FUNC_CODE_INST_BINOP: + sm6_parser_emit_binop(sm6, record, ins, dst); + break; +@@ -4266,6 +4755,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + is_terminator = true; + ret_found = true; + break; ++ case FUNC_CODE_INST_STORE: ++ sm6_parser_emit_store(sm6, record, ins, dst); ++ break; + case FUNC_CODE_INST_VSELECT: + sm6_parser_emit_vselect(sm6, record, ins, dst); + break; +@@ -4278,6 +4770,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + return VKD3D_ERROR; + assert(ins->handler_idx != VKD3DSIH_INVALID); + ++ if (record->attachment) ++ metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); ++ + if (is_terminator) + { + ++block_idx; +@@ -4331,6 +4826,8 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st + sm6->p.location.line = block->id; + sm6->p.location.column = 0; + ++ sm6_parser_metadata_attachments_init(sm6, block); ++ + switch (block->id) + { + case CONSTANTS_BLOCK: +@@ -4645,7 +5142,7 @@ static const enum vkd3d_shader_sysval_semantic sysval_semantic_table[] = + { + [SEMANTIC_KIND_ARBITRARY] = VKD3D_SHADER_SV_NONE, + [SEMANTIC_KIND_POSITION] = VKD3D_SHADER_SV_POSITION, +- [SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_NONE, ++ [SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_TARGET, + }; + + static enum vkd3d_shader_sysval_semantic sysval_semantic_from_dxil_semantic_kind(enum dxil_semantic_kind kind) +@@ -5538,7 +6035,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + if ((magic = sm6->start[0]) != BITCODE_MAGIC) + { + WARN("Unknown magic number 0x%08x.\n", magic); +- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER, ++ vkd3d_shader_warning(message_context, &location, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER, + "DXIL bitcode chunk magic number 0x%08x is not the expected 0x%08x.", magic, BITCODE_MAGIC); + } + +@@ -5547,7 +6044,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + if ((version.type = version_token >> 16) >= VKD3D_SHADER_TYPE_COUNT) + { + FIXME("Unknown shader type %#x.\n", version.type); +- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE, ++ vkd3d_shader_warning(message_context, &location, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE, + "Unknown shader type %#x.", version.type); + } + +@@ -5573,10 +6070,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + if ((ret = dxil_block_init(block, NULL, sm6)) < 0) + { + if (ret == VKD3D_ERROR_OUT_OF_MEMORY) +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory parsing DXIL bitcode chunk."); + else if (ret == VKD3D_ERROR_INVALID_SHADER) +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_BITCODE, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_BITCODE, + "DXIL bitcode chunk has invalid bitcode."); + else + vkd3d_unreachable(); +@@ -5606,10 +6103,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + if ((ret = sm6_parser_type_table_init(sm6)) < 0) + { + if (ret == VKD3D_ERROR_OUT_OF_MEMORY) +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory parsing DXIL type table."); + else if (ret == VKD3D_ERROR_INVALID_SHADER) +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_TYPE_TABLE, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_TYPE_TABLE, + "DXIL type table is invalid."); + else + vkd3d_unreachable(); +@@ -5619,10 +6116,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + if ((ret = sm6_parser_symtab_init(sm6)) < 0) + { + if (ret == VKD3D_ERROR_OUT_OF_MEMORY) +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory parsing DXIL value symbol table."); + else if (ret == VKD3D_ERROR_INVALID_SHADER) +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_VALUE_SYMTAB, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_VALUE_SYMTAB, + "DXIL value symbol table is invalid."); + else + vkd3d_unreachable(); +@@ -5633,7 +6130,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + || !(sm6->input_params = shader_parser_get_dst_params(&sm6->p, input_signature->element_count))) + { + ERR("Failed to allocate input/output parameters.\n"); +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory allocating input/output parameters."); + return VKD3D_ERROR_OUT_OF_MEMORY; + } +@@ -5642,7 +6139,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + if (!(sm6->functions = vkd3d_calloc(function_count, sizeof(*sm6->functions)))) + { + ERR("Failed to allocate function array.\n"); +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory allocating DXIL function array."); + return VKD3D_ERROR_OUT_OF_MEMORY; + } +@@ -5650,14 +6147,14 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + if (sm6_parser_compute_max_value_count(sm6, &sm6->root_block, 0) == SIZE_MAX) + { + WARN("Value array count overflowed.\n"); +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + "Overflow occurred in the DXIL module value count."); + return VKD3D_ERROR_INVALID_SHADER; + } + if (!(sm6->values = vkd3d_calloc(sm6->value_capacity, sizeof(*sm6->values)))) + { + ERR("Failed to allocate value array.\n"); +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory allocating DXIL value array."); + return VKD3D_ERROR_OUT_OF_MEMORY; + } +@@ -5684,7 +6181,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + if (j == ARRAY_SIZE(sm6->metadata_tables)) + { + FIXME("Too many metadata tables.\n"); +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA, + "A metadata table count greater than %zu is unsupported.", ARRAY_SIZE(sm6->metadata_tables)); + return VKD3D_ERROR_INVALID_SHADER; + } +@@ -5702,22 +6199,20 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + if ((ret = sm6_parser_module_init(sm6, &sm6->root_block, 0)) < 0) + { + if (ret == VKD3D_ERROR_OUT_OF_MEMORY) +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory parsing DXIL module."); + else if (ret == VKD3D_ERROR_INVALID_SHADER) +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + "DXIL module is invalid."); + return ret; + } + + if (!sm6_parser_require_space(sm6, output_signature->element_count + input_signature->element_count)) + { +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory emitting shader signature declarations."); + return VKD3D_ERROR_OUT_OF_MEMORY; + } +- sm6_parser_emit_output_signature(sm6, output_signature); +- sm6_parser_emit_input_signature(sm6, input_signature); + + sm6->p.shader_desc.ssa_count = sm6->ssa_next_id; + +@@ -5732,7 +6227,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + assert(sm6->function_count == 1); + if (!sm6_block_emit_instructions(fn->blocks[0], sm6)) + { +- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory emitting shader instructions."); + return VKD3D_ERROR_OUT_OF_MEMORY; + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index 0dde4c18587..ed053f16312 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -487,27 +487,27 @@ static void resolve_loop_continue(struct hlsl_ctx *ctx, struct hlsl_block *block + else if (instr->type == HLSL_IR_JUMP) + { + struct hlsl_ir_jump *jump = hlsl_ir_jump(instr); +- struct hlsl_block block; ++ struct hlsl_block cond_block; + + if (jump->type != HLSL_IR_JUMP_UNRESOLVED_CONTINUE) + continue; + + if (type == LOOP_DO_WHILE) + { +- if (!hlsl_clone_block(ctx, &block, cond)) ++ if (!hlsl_clone_block(ctx, &cond_block, cond)) + return; +- if (!append_conditional_break(ctx, &block)) ++ if (!append_conditional_break(ctx, &cond_block)) + { +- hlsl_block_cleanup(&block); ++ hlsl_block_cleanup(&cond_block); + return; + } +- list_move_before(&instr->entry, &block.instrs); ++ list_move_before(&instr->entry, &cond_block.instrs); + } + else if (type == LOOP_FOR) + { +- if (!hlsl_clone_block(ctx, &block, iter)) ++ if (!hlsl_clone_block(ctx, &cond_block, iter)) + return; +- list_move_before(&instr->entry, &block.instrs); ++ list_move_before(&instr->entry, &cond_block.instrs); + } + jump->type = HLSL_IR_JUMP_CONTINUE; + } +@@ -3553,7 +3553,7 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * + { + struct hlsl_resource_load_params load_params = { 0 }; + const struct hlsl_type *sampler_type; +- struct hlsl_ir_node *coords, *load; ++ struct hlsl_ir_node *coords, *sample; + + if (params->args_count != 2 && params->args_count != 4) + { +@@ -3688,9 +3688,9 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * + load_params.format = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4); + load_params.sampling_dim = dim; + +- if (!(load = hlsl_new_resource_load(ctx, &load_params, loc))) ++ if (!(sample = hlsl_new_resource_load(ctx, &load_params, loc))) + return false; +- hlsl_block_add_instr(params->instrs, load); ++ hlsl_block_add_instr(params->instrs, sample); + return true; + } + +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index 4a622185741..88cbef61d5f 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -1090,7 +1090,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + unsigned int dim_count = hlsl_sampler_dim_count(val->data_type->sampler_dim); + struct hlsl_ir_node *coords = index->idx.node; + struct hlsl_resource_load_params params = {0}; +- struct hlsl_ir_node *load; ++ struct hlsl_ir_node *resource_load; + + assert(coords->data_type->class == HLSL_CLASS_VECTOR); + assert(coords->data_type->base_type == HLSL_TYPE_UINT); +@@ -1104,9 +1104,9 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + params.coords = coords; + params.format = val->data_type->e.resource_format; + +- if (!(load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) ++ if (!(resource_load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) + return false; +- hlsl_block_add_instr(block, load); ++ hlsl_block_add_instr(block, resource_load); + return true; + } + +@@ -2301,7 +2301,6 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + struct hlsl_ir_switch_case *c, *def = NULL; + bool missing_terminal_break = false; + struct hlsl_ir_node *node; +- struct hlsl_ir_jump *jump; + struct hlsl_ir_switch *s; + + if (instr->type != HLSL_IR_SWITCH) +@@ -2320,10 +2319,7 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + { + node = LIST_ENTRY(list_tail(&c->body.instrs), struct hlsl_ir_node, entry); + if (node->type == HLSL_IR_JUMP) +- { +- jump = hlsl_ir_jump(node); +- terminal_break = jump->type == HLSL_IR_JUMP_BREAK; +- } ++ terminal_break = (hlsl_ir_jump(node)->type == HLSL_IR_JUMP_BREAK); + } + + missing_terminal_break |= !terminal_break; +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 710811c6761..d38b3c39712 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -63,7 +63,7 @@ static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_i + if (shader_register_is_phase_instance_id(reg)) + { + vsir_register_init(reg, VKD3DSPR_IMMCONST, reg->data_type, 0); +- reg->u.immconst_uint[0] = instance_id; ++ reg->u.immconst_u32[0] = instance_id; + continue; + } + shader_register_eliminate_phase_addressing(reg, instance_id); +@@ -463,6 +463,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i + struct vkd3d_shader_instruction_array *instructions; + struct control_point_normaliser normaliser; + unsigned int input_control_point_count; ++ struct vkd3d_shader_location location; + struct vkd3d_shader_instruction *ins; + enum vkd3d_result ret; + unsigned int i, j; +@@ -513,8 +514,10 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i + return VKD3D_OK; + case VKD3DSIH_HS_FORK_PHASE: + case VKD3DSIH_HS_JOIN_PHASE: ++ /* ins may be relocated if the instruction array expands. */ ++ location = ins->location; + ret = control_point_normaliser_emit_hs_input(&normaliser, input_signature, +- input_control_point_count, i, &ins->location); ++ input_control_point_count, i, &location); + *src_instructions = normaliser.instructions; + return ret; + default: +@@ -590,19 +593,19 @@ struct signature_element *vsir_signature_find_element_for_reg(const struct shade + } + + static unsigned int range_map_get_register_count(uint8_t range_map[][VKD3D_VEC4_SIZE], +- unsigned int register_idx, unsigned int write_mask) ++ unsigned int register_idx, uint32_t write_mask) + { +- return range_map[register_idx][vkd3d_write_mask_get_component_idx(write_mask)]; ++ return range_map[register_idx][vsir_write_mask_get_component_idx(write_mask)]; + } + + static void range_map_set_register_range(uint8_t range_map[][VKD3D_VEC4_SIZE], unsigned int register_idx, +- unsigned int register_count, unsigned int write_mask, bool is_dcl_indexrange) ++ unsigned int register_count, uint32_t write_mask, bool is_dcl_indexrange) + { + unsigned int i, j, r, c, component_idx, component_count; + + assert(write_mask <= VKD3DSP_WRITEMASK_ALL); +- component_idx = vkd3d_write_mask_get_component_idx(write_mask); +- component_count = vkd3d_write_mask_component_count(write_mask); ++ component_idx = vsir_write_mask_get_component_idx(write_mask); ++ component_count = vsir_write_mask_component_count(write_mask); + + assert(register_idx < MAX_REG_OUTPUT && MAX_REG_OUTPUT - register_idx >= register_count); + +@@ -896,7 +899,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par + element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); + e = &signature->elements[element_idx]; + +- dst_param->write_mask >>= vkd3d_write_mask_get_component_idx(e->mask); ++ dst_param->write_mask >>= vsir_write_mask_get_component_idx(e->mask); + if (is_io_dcl) + { + /* Validated in the TPF reader. */ +@@ -999,7 +1002,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par + + id_idx = reg->idx_count - 1; + reg_idx = reg->idx[id_idx].offset; +- write_mask = VKD3DSP_WRITEMASK_0 << vkd3d_swizzle_get_component(src_param->swizzle, 0); ++ write_mask = VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(src_param->swizzle, 0); + element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); + + e = &signature->elements[element_idx]; +@@ -1008,10 +1011,10 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par + reg->idx[id_idx].offset = element_idx; + reg->idx_count = id_idx + 1; + +- if ((component_idx = vkd3d_write_mask_get_component_idx(e->mask))) ++ if ((component_idx = vsir_write_mask_get_component_idx(e->mask))) + { + for (i = 0; i < VKD3D_VEC4_SIZE; ++i) +- if (vkd3d_swizzle_get_component(src_param->swizzle, i)) ++ if (vsir_swizzle_get_component(src_param->swizzle, i)) + src_param->swizzle -= component_idx << VKD3D_SHADER_SWIZZLE_SHIFT(i); + } + } +@@ -1215,7 +1218,7 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par + param->reg.idx_count = 0; + param->reg.dimension = VSIR_DIMENSION_VEC4; + for (j = 0; j < 4; ++j) +- param->reg.u.immconst_uint[j] = normaliser->defs[i].value[j]; ++ param->reg.u.immconst_u32[j] = normaliser->defs[i].value[j]; + return; + } + } +@@ -1251,7 +1254,7 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d + + get_flat_constant_register_type((struct vkd3d_shader_register *)&ins->dst[0].reg, &def->set, &def->index); + for (j = 0; j < 4; ++j) +- def->value[j] = ins->src[0].reg.u.immconst_uint[j]; ++ def->value[j] = ins->src[0].reg.u.immconst_u32[j]; + + vkd3d_shader_instruction_make_nop(ins); + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index c8a43adbe03..387784f2358 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -133,7 +133,7 @@ static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, + } + } + +-static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, ++static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv, + enum vkd3d_shader_spirv_environment environment) + { + spv_diagnostic diagnostic = NULL; +@@ -145,12 +145,13 @@ static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, + if ((ret = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t), + &diagnostic))) + { +- FIXME("Failed to validate SPIR-V binary, ret %d.\n", ret); +- FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error)); ++ vkd3d_string_buffer_printf(buffer, "%s", diagnostic->error); + } + + spvDiagnosticDestroy(diagnostic); + spvContextDestroy(context); ++ ++ return !ret; + } + + #else +@@ -163,8 +164,11 @@ static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_co + } + static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, + enum vkd3d_shader_spirv_environment environment) {} +-static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, +- enum vkd3d_shader_spirv_environment environment) {} ++static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv, ++ enum vkd3d_shader_spirv_environment environment) ++{ ++ return true; ++} + + #endif /* HAVE_SPIRV_TOOLS */ + +@@ -1194,6 +1198,16 @@ static uint32_t vkd3d_spirv_get_op_constant64(struct vkd3d_spirv_builder *builde + (const uint32_t *)&value, 2, vkd3d_spirv_build_op_constant64); + } + ++static uint32_t vkd3d_spirv_build_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) ++{ ++ return vkd3d_spirv_build_op_tr(builder, &builder->global_stream, SpvOpConstantNull, result_type); ++} ++ ++static uint32_t vkd3d_spirv_get_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) ++{ ++ return vkd3d_spirv_build_once1(builder, SpvOpConstantNull, result_type, vkd3d_spirv_build_op_constant_null); ++} ++ + static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_builder *builder, + uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) + { +@@ -1783,6 +1797,8 @@ static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder, + break; + case VKD3D_SHADER_COMPONENT_DOUBLE: + return vkd3d_spirv_get_op_type_float(builder, 64); ++ case VKD3D_SHADER_COMPONENT_UINT64: ++ return vkd3d_spirv_get_op_type_int(builder, 64, 0); + default: + FIXME("Unhandled component type %#x.\n", component_type); + return 0; +@@ -1816,6 +1832,8 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder + 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: +@@ -2152,6 +2170,7 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol, + break; + + case VKD3DSPR_IMMCONSTBUFFER: ++ symbol->key.reg.idx = reg->idx_count > 1 ? reg->idx[0].offset : 0; + break; + + default: +@@ -2159,6 +2178,15 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol, + } + } + ++static void vkd3d_symbol_make_io(struct vkd3d_symbol *symbol, ++ enum vkd3d_shader_register_type type, unsigned int index) ++{ ++ symbol->type = VKD3D_SYMBOL_REGISTER; ++ memset(&symbol->key, 0, sizeof(symbol->key)); ++ symbol->key.reg.type = type; ++ symbol->key.reg.idx = index; ++} ++ + static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol, + uint32_t val_id, SpvStorageClass storage_class, + enum vkd3d_shader_component_type component_type, DWORD write_mask) +@@ -2376,12 +2404,15 @@ struct spirv_compiler + struct vkd3d_shader_spec_constant *spec_constants; + size_t spec_constants_size; + enum vkd3d_shader_compile_option_formatting_flags formatting; ++ enum vkd3d_shader_compile_option_feature_flags features; + bool write_tess_geom_point_size; + + struct vkd3d_string_buffer_cache string_buffers; + + struct ssa_register_info *ssa_register_info; + unsigned int ssa_register_count; ++ ++ uint64_t config_flags; + }; + + static bool is_in_default_phase(const struct spirv_compiler *compiler) +@@ -2437,7 +2468,8 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler) + static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *shader_version, + struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, + const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info, +- struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location) ++ struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location, ++ uint64_t config_flags) + { + const struct shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature; + const struct shader_signature *output_signature = &shader_desc->output_signature; +@@ -2454,6 +2486,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve + memset(compiler, 0, sizeof(*compiler)); + compiler->message_context = message_context; + compiler->location = *location; ++ compiler->config_flags = config_flags; + + if ((target_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO))) + { +@@ -2533,6 +2566,10 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve + WARN("Ignoring unrecognised value %#x for option %#x.\n", option->value, option->name); + break; + ++ case VKD3D_SHADER_COMPILE_OPTION_FEATURE: ++ compiler->features = option->value; ++ break; ++ + default: + WARN("Ignoring unrecognised option %#x with value %#x.\n", option->name, option->value); + break; +@@ -2955,7 +2992,7 @@ static uint32_t spirv_compiler_get_constant64(struct spirv_compiler *compiler, + assert(0 < component_count && component_count <= VKD3D_DVEC2_SIZE); + type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); + +- if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE) ++ if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE && component_type != VKD3D_SHADER_COMPONENT_UINT64) + { + FIXME("Unhandled component_type %#x.\n", component_type); + return vkd3d_spirv_get_op_undef(builder, type_id); +@@ -3015,14 +3052,21 @@ static uint32_t spirv_compiler_get_constant_double_vector(struct spirv_compiler + component_count, (const uint64_t *)values); + } + ++static uint32_t spirv_compiler_get_constant_uint64_vector(struct spirv_compiler *compiler, ++ uint64_t value, unsigned int component_count) ++{ ++ const uint64_t values[] = {value, value}; ++ return spirv_compiler_get_constant64(compiler, VKD3D_SHADER_COMPONENT_UINT64, component_count, values); ++} ++ + static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, DWORD write_mask) ++ const struct vkd3d_shader_register *reg, uint32_t write_mask) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + + return vkd3d_spirv_get_type_id(builder, + vkd3d_component_type_from_data_type(reg->data_type), +- vkd3d_write_mask_component_count(write_mask)); ++ vsir_write_mask_component_count(write_mask)); + } + + static uint32_t spirv_compiler_get_type_id_for_dst(struct spirv_compiler *compiler, +@@ -3498,7 +3542,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp + } + else if (reg->type == VKD3DSPR_IMMCONSTBUFFER) + { +- indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[0]); ++ indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[reg->idx_count - 1]); + } + else if (reg->type == VKD3DSPR_IDXTEMP) + { +@@ -3530,7 +3574,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp + + if (index_count) + { +- component_count = vkd3d_write_mask_component_count(register_info->write_mask); ++ component_count = vsir_write_mask_component_count(register_info->write_mask); + type_id = vkd3d_spirv_get_type_id(builder, register_info->component_type, component_count); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, register_info->storage_class, type_id); + register_info->id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, +@@ -3562,24 +3606,24 @@ static bool vkd3d_swizzle_is_equal(unsigned int dst_write_mask, + return vkd3d_compact_swizzle(VKD3D_SHADER_NO_SWIZZLE, dst_write_mask) == vkd3d_compact_swizzle(swizzle, write_mask); + } + +-static bool vkd3d_swizzle_is_scalar(unsigned int swizzle) ++static bool vkd3d_swizzle_is_scalar(uint32_t swizzle) + { +- unsigned int component_idx = vkd3d_swizzle_get_component(swizzle, 0); +- return vkd3d_swizzle_get_component(swizzle, 1) == component_idx +- && vkd3d_swizzle_get_component(swizzle, 2) == component_idx +- && vkd3d_swizzle_get_component(swizzle, 3) == component_idx; ++ unsigned int component_idx = vsir_swizzle_get_component(swizzle, 0); ++ return vsir_swizzle_get_component(swizzle, 1) == component_idx ++ && vsir_swizzle_get_component(swizzle, 2) == component_idx ++ && vsir_swizzle_get_component(swizzle, 3) == component_idx; + } + + static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, +- uint32_t val_id, unsigned int val_write_mask, enum vkd3d_shader_component_type component_type, +- unsigned int swizzle, unsigned int write_mask) ++ uint32_t val_id, uint32_t val_write_mask, enum vkd3d_shader_component_type component_type, ++ uint32_t swizzle, uint32_t write_mask) + { + unsigned int i, component_idx, component_count, val_component_count; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, components[VKD3D_VEC4_SIZE]; + +- component_count = vkd3d_write_mask_component_count(write_mask); +- val_component_count = vkd3d_write_mask_component_count(val_write_mask); ++ component_count = vsir_write_mask_component_count(write_mask); ++ val_component_count = vsir_write_mask_component_count(val_write_mask); + + if (component_count == val_component_count + && (component_count == 1 || vkd3d_swizzle_is_equal(val_write_mask, swizzle, write_mask))) +@@ -3589,9 +3633,9 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, + + if (component_count == 1) + { +- component_idx = vkd3d_write_mask_get_component_idx(write_mask); +- component_idx = vkd3d_swizzle_get_component(swizzle, component_idx); +- component_idx -= vkd3d_write_mask_get_component_idx(val_write_mask); ++ component_idx = vsir_write_mask_get_component_idx(write_mask); ++ component_idx = vsir_swizzle_get_component(swizzle, component_idx); ++ component_idx -= vsir_write_mask_get_component_idx(val_write_mask); + return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx); + } + +@@ -3601,7 +3645,7 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, + { + if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) + { +- assert(VKD3DSP_WRITEMASK_0 << vkd3d_swizzle_get_component(swizzle, i) == val_write_mask); ++ assert(VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(swizzle, i) == val_write_mask); + components[component_idx++] = val_id; + } + } +@@ -3611,14 +3655,14 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, + for (i = 0, component_idx = 0; i < VKD3D_VEC4_SIZE; ++i) + { + if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) +- components[component_idx++] = vkd3d_swizzle_get_component(swizzle, i); ++ components[component_idx++] = vsir_swizzle_get_component(swizzle, i); + } + return vkd3d_spirv_build_op_vector_shuffle(builder, + type_id, val_id, val_id, components, component_count); + } + + static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compiler, +- uint32_t vector1_id, uint32_t vector2_id, unsigned int swizzle, unsigned int write_mask, ++ uint32_t vector1_id, uint32_t vector2_id, uint32_t swizzle, uint32_t write_mask, + enum vkd3d_shader_component_type component_type, unsigned int component_count) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +@@ -3631,9 +3675,9 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil + for (i = 0; i < component_count; ++i) + { + if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) +- components[i] = vkd3d_swizzle_get_component(swizzle, i); ++ components[i] = vsir_swizzle_get_component(swizzle, i); + else +- components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(swizzle, i); ++ components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(swizzle, i); + } + + type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); +@@ -3642,9 +3686,9 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil + } + + static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) ++ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) + { +- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); ++ unsigned int component_count = vsir_write_mask_component_count(write_mask); + uint32_t values[VKD3D_VEC4_SIZE] = {0}; + unsigned int i, j; + +@@ -3653,14 +3697,14 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile + if (reg->dimension == VSIR_DIMENSION_SCALAR) + { + for (i = 0; i < component_count; ++i) +- values[i] = *reg->u.immconst_uint; ++ values[i] = *reg->u.immconst_u32; + } + else + { + for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) + { + if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) +- values[j++] = reg->u.immconst_uint[vkd3d_swizzle_get_component(swizzle, i)]; ++ values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]; + } + } + +@@ -3669,9 +3713,9 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile + } + + static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) ++ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) + { +- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); ++ unsigned int component_count = vsir_write_mask_component_count(write_mask); + uint64_t values[VKD3D_DVEC2_SIZE] = {0}; + unsigned int i, j; + +@@ -3680,14 +3724,14 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi + if (reg->dimension == VSIR_DIMENSION_SCALAR) + { + for (i = 0; i < component_count; ++i) +- values[i] = *reg->u.immconst_uint64; ++ values[i] = *reg->u.immconst_u64; + } + else + { + for (i = 0, j = 0; i < VKD3D_DVEC2_SIZE; ++i) + { + if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) +- values[j++] = reg->u.immconst_uint64[vkd3d_swizzle_get_component64(swizzle, i)]; ++ values[j++] = reg->u.immconst_u64[vsir_swizzle_get_component64(swizzle, i)]; + } + } + +@@ -3696,9 +3740,9 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi + } + + static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, DWORD write_mask) ++ const struct vkd3d_shader_register *reg, uint32_t write_mask) + { +- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); ++ unsigned int component_count = vsir_write_mask_component_count(write_mask); + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id; + +@@ -3709,28 +3753,28 @@ static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, + } + + static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask, ++ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask, + const struct vkd3d_shader_register_info *reg_info) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, ptr_type_id, index, reg_id, val_id; + unsigned int component_idx, reg_component_count; + enum vkd3d_shader_component_type component_type; +- unsigned int skipped_component_mask; ++ uint32_t skipped_component_mask; + + assert(!register_is_constant_or_undef(reg)); +- assert(vkd3d_write_mask_component_count(write_mask) == 1); ++ assert(vsir_write_mask_component_count(write_mask) == 1); + +- component_idx = vkd3d_write_mask_get_component_idx(write_mask); +- component_idx = vkd3d_swizzle_get_component(swizzle, component_idx); ++ component_idx = vsir_write_mask_get_component_idx(write_mask); ++ component_idx = vsir_swizzle_get_component(swizzle, component_idx); + skipped_component_mask = ~reg_info->write_mask & ((VKD3DSP_WRITEMASK_0 << component_idx) - 1); + if (skipped_component_mask) +- component_idx -= vkd3d_write_mask_component_count(skipped_component_mask); ++ component_idx -= vsir_write_mask_component_count(skipped_component_mask); + component_type = vkd3d_component_type_from_data_type(reg->data_type); + +- reg_component_count = vkd3d_write_mask_component_count(reg_info->write_mask); ++ reg_component_count = vsir_write_mask_component_count(reg_info->write_mask); + +- if (component_idx >= vkd3d_write_mask_component_count(reg_info->write_mask)) ++ if (component_idx >= vsir_write_mask_component_count(reg_info->write_mask)) + { + ERR("Invalid component_idx %u for register %#x, %u (write_mask %#x).\n", + component_idx, reg->type, reg->idx[0].offset, reg_info->write_mask); +@@ -3756,6 +3800,69 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, + return val_id; + } + ++static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compiler, ++ const struct vkd3d_shader_immediate_constant_buffer *icb, uint32_t *type_id_out) ++{ ++ uint32_t *elements, elem_type_id, length_id, type_id, const_id; ++ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ enum vkd3d_shader_component_type component_type; ++ unsigned int i, element_count, component_count; ++ ++ element_count = icb->element_count; ++ ++ component_type = vkd3d_component_type_from_data_type(icb->data_type); ++ component_count = icb->component_count; ++ elem_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, icb->data_type, component_count); ++ length_id = spirv_compiler_get_constant_uint(compiler, element_count); ++ type_id = vkd3d_spirv_get_op_type_array(builder, elem_type_id, length_id); ++ ++ if (type_id_out) ++ *type_id_out = type_id; ++ ++ if (icb->is_null) ++ { ++ /* All values are null. Workgroup memory initialisers require OpConstantNull. */ ++ return vkd3d_spirv_get_op_constant_null(builder, type_id); ++ } ++ ++ if (!(elements = vkd3d_calloc(element_count, sizeof(*elements)))) ++ { ++ ERR("Failed to allocate %u elements.", element_count); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY, ++ "Failed to allocate %u constant array elements.", element_count); ++ return 0; ++ } ++ ++ switch (icb->data_type) ++ { ++ case VKD3D_DATA_FLOAT: ++ case VKD3D_DATA_INT: ++ case VKD3D_DATA_UINT: ++ for (i = 0; i < element_count; ++i) ++ elements[i] = spirv_compiler_get_constant(compiler, component_type, component_count, ++ &icb->data[component_count * i]); ++ break; ++ case VKD3D_DATA_DOUBLE: ++ case VKD3D_DATA_UINT64: ++ { ++ uint64_t *data = (uint64_t *)icb->data; ++ for (i = 0; i < element_count; ++i) ++ elements[i] = spirv_compiler_get_constant64(compiler, component_type, component_count, ++ &data[component_count * i]); ++ break; ++ } ++ default: ++ FIXME("Unhandled data type %u.\n", icb->data_type); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, ++ "Immediate constant buffer data type %u is unhandled.", icb->data_type); ++ break; ++ } ++ ++ const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, element_count); ++ vkd3d_free(elements); ++ return const_id; ++} ++ + static const struct ssa_register_info *spirv_compiler_get_ssa_register_info(const struct spirv_compiler *compiler, + const struct vkd3d_shader_register *reg) + { +@@ -3775,7 +3882,7 @@ static void spirv_compiler_set_ssa_register_info(const struct spirv_compiler *co + + static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler, + const struct vkd3d_shader_register *reg, enum vkd3d_shader_component_type component_type, +- unsigned int swizzle) ++ uint32_t swizzle) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + enum vkd3d_shader_component_type reg_component_type; +@@ -3801,19 +3908,19 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler + } + + type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); +- component_idx = vkd3d_swizzle_get_component(swizzle, 0); ++ component_idx = vsir_swizzle_get_component(swizzle, 0); + return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx); + } + + static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) ++ const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + enum vkd3d_shader_component_type component_type; + struct vkd3d_shader_register_info reg_info; + unsigned int component_count; +- unsigned int write_mask32; + uint32_t type_id, val_id; ++ uint32_t write_mask32; + + if (reg->type == VKD3DSPR_IMMCONST) + return spirv_compiler_emit_load_constant(compiler, reg, swizzle, write_mask); +@@ -3822,7 +3929,7 @@ 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); + +- component_count = vkd3d_write_mask_component_count(write_mask); ++ component_count = vsir_write_mask_component_count(write_mask); + component_type = vkd3d_component_type_from_data_type(reg->data_type); + + if (reg->type == VKD3DSPR_SSA) +@@ -3836,21 +3943,21 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, + assert(reg_info.component_type != VKD3D_SHADER_COMPONENT_DOUBLE); + spirv_compiler_emit_dereference_register(compiler, reg, ®_info); + +- write_mask32 = (reg->data_type == VKD3D_DATA_DOUBLE) ? vkd3d_write_mask_32_from_64(write_mask) : write_mask; ++ write_mask32 = data_type_is_64_bit(reg->data_type) ? vsir_write_mask_32_from_64(write_mask) : write_mask; + + /* Intermediate value (no storage class). */ + if (reg_info.storage_class == SpvStorageClassMax) + { + val_id = reg_info.id; + } +- else if (vkd3d_write_mask_component_count(write_mask32) == 1) ++ else if (vsir_write_mask_component_count(write_mask32) == 1) + { + return spirv_compiler_emit_load_scalar(compiler, reg, swizzle, write_mask, ®_info); + } + else + { + type_id = vkd3d_spirv_get_type_id(builder, +- reg_info.component_type, vkd3d_write_mask_component_count(reg_info.write_mask)); ++ reg_info.component_type, vsir_write_mask_component_count(reg_info.write_mask)); + val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_info.id, SpvMemoryAccessMaskNone); + } + +@@ -3904,7 +4011,7 @@ static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, + type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask); + if (reg->data_type == VKD3D_DATA_FLOAT || reg->data_type == VKD3D_DATA_DOUBLE) + return vkd3d_spirv_build_op_fnegate(builder, type_id, val_id); +- else if (reg->data_type == VKD3D_DATA_INT || reg->data_type == VKD3D_DATA_UINT) ++ else if (data_type_is_integer(reg->data_type)) + return vkd3d_spirv_build_op_snegate(builder, type_id, val_id); + + FIXME("Unhandled data type %#x.\n", reg->data_type); +@@ -3953,19 +4060,19 @@ static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *co + } + + static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, +- uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type, +- SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id) ++ uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type, ++ SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, ptr_type_id, index; + unsigned int component_idx; + +- if (vkd3d_write_mask_component_count(dst_write_mask) > 1) ++ if (vsir_write_mask_component_count(dst_write_mask) > 1) + { + type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); +- component_idx = vkd3d_write_mask_get_component_idx(write_mask); +- component_idx -= vkd3d_write_mask_get_component_idx(dst_write_mask); ++ component_idx = vsir_write_mask_get_component_idx(write_mask); ++ component_idx -= vsir_write_mask_get_component_idx(dst_write_mask); + index = spirv_compiler_get_constant_uint(compiler, component_idx); + dst_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, dst_id, index); + } +@@ -3974,8 +4081,8 @@ static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, + } + + static void spirv_compiler_emit_store(struct spirv_compiler *compiler, +- uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type, +- SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id) ++ uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type, ++ SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + unsigned int component_count, dst_component_count; +@@ -3985,14 +4092,14 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, + + assert(write_mask); + +- component_count = vkd3d_write_mask_component_count(write_mask); +- dst_component_count = vkd3d_write_mask_component_count(dst_write_mask); ++ component_count = vsir_write_mask_component_count(write_mask); ++ dst_component_count = vsir_write_mask_component_count(dst_write_mask); + + if (dst_component_count == 1 && component_count != 1) + { + type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); + val_id = vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, +- vkd3d_write_mask_get_component_idx(dst_write_mask)); ++ vsir_write_mask_get_component_idx(dst_write_mask)); + write_mask &= dst_write_mask; + component_count = 1; + } +@@ -4029,12 +4136,12 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, + } + + static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, unsigned int write_mask, uint32_t val_id) ++ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + enum vkd3d_shader_component_type component_type; + struct vkd3d_shader_register_info reg_info; +- unsigned int src_write_mask = write_mask; ++ uint32_t src_write_mask = write_mask; + uint32_t type_id; + + assert(!register_is_constant_or_undef(reg)); +@@ -4052,10 +4159,10 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, + component_type = vkd3d_component_type_from_data_type(reg->data_type); + if (component_type != reg_info.component_type) + { +- if (reg->data_type == VKD3D_DATA_DOUBLE) +- src_write_mask = vkd3d_write_mask_32_from_64(write_mask); ++ if (data_type_is_64_bit(reg->data_type)) ++ src_write_mask = vsir_write_mask_32_from_64(write_mask); + type_id = vkd3d_spirv_get_type_id(builder, reg_info.component_type, +- vkd3d_write_mask_component_count(src_write_mask)); ++ vsir_write_mask_component_count(src_write_mask)); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + component_type = reg_info.component_type; + } +@@ -4065,9 +4172,9 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, + } + + static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id) ++ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) + { +- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); ++ unsigned int component_count = vsir_write_mask_component_count(write_mask); + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, zero_id, one_id; + +@@ -4118,7 +4225,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp + const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_component_type component_type, + uint32_t *component_ids) + { +- unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, val_id; + +@@ -4137,16 +4244,16 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp + + static void spirv_compiler_emit_store_dst_scalar(struct spirv_compiler *compiler, + const struct vkd3d_shader_dst_param *dst, uint32_t val_id, +- enum vkd3d_shader_component_type component_type, DWORD swizzle) ++ enum vkd3d_shader_component_type component_type, uint32_t swizzle) + { +- unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); + uint32_t component_ids[VKD3D_VEC4_SIZE]; + unsigned int component_idx, i; + +- component_idx = vkd3d_write_mask_get_component_idx(dst->write_mask); ++ component_idx = vsir_write_mask_get_component_idx(dst->write_mask); + for (i = 0; i < component_count; ++i) + { +- if (vkd3d_swizzle_get_component(swizzle, component_idx + i)) ++ if (vsir_swizzle_get_component(swizzle, component_idx + i)) + ERR("Invalid swizzle %#x for scalar value, write mask %#x.\n", swizzle, dst->write_mask); + + component_ids[i] = val_id; +@@ -4191,14 +4298,18 @@ static void spirv_compiler_decorate_builtin(struct spirv_compiler *compiler, + } + + static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler *compiler, +- uint32_t id, enum vkd3d_shader_interpolation_mode mode) ++ enum vkd3d_shader_component_type component_type, uint32_t id, enum vkd3d_shader_interpolation_mode mode) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + + switch (mode) + { + case VKD3DSIM_NONE: +- break; ++ /* VUID-StandaloneSpirv-Flat-04744: integer or double types must be ++ * decorated 'Flat' for fragment shaders. */ ++ if (compiler->shader_type != VKD3D_SHADER_TYPE_PIXEL || component_type == VKD3D_SHADER_COMPONENT_FLOAT) ++ break; ++ /* fall through */ + case VKD3DSIM_CONSTANT: + vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationFlat, NULL, 0); + break; +@@ -4226,7 +4337,8 @@ static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler + } + + static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, +- enum vkd3d_shader_conditional_op condition, unsigned int component_count, uint32_t val_id) ++ enum vkd3d_shader_conditional_op condition, enum vkd3d_data_type data_type, ++ unsigned int component_count, uint32_t val_id) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id; +@@ -4237,7 +4349,9 @@ static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); + op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual; + return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, val_id, +- spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); ++ data_type == VKD3D_DATA_UINT64 ++ ? spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count) ++ : spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); + } + + static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, +@@ -4252,6 +4366,19 @@ static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); + } + ++static uint32_t spirv_compiler_emit_bool_to_int64(struct spirv_compiler *compiler, ++ unsigned int component_count, uint32_t val_id, bool signedness) ++{ ++ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ uint32_t type_id, true_id, false_id; ++ ++ true_id = spirv_compiler_get_constant_uint64_vector(compiler, signedness ? UINT64_MAX : 1, ++ component_count); ++ false_id = spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count); ++ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT64, component_count); ++ return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); ++} ++ + static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compiler, + unsigned int component_count, uint32_t val_id, bool signedness) + { +@@ -4422,9 +4549,9 @@ vkd3d_register_builtins[] = + }; + + static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg) ++ enum vkd3d_shader_register_type type) + { +- switch (reg->type) ++ switch (type) + { + case VKD3DSPR_DEPTHOUTGE: + spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeDepthGreater, NULL, 0); +@@ -4437,9 +4564,9 @@ static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *c + VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT)) + { + FIXME("The target environment does not support stencil export.\n"); +- spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED, +- "Cannot export stencil reference value for register id %u. " +- "The target environment does not support stencil export.", reg->idx[0].offset); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, ++ "Cannot export stencil reference value. " ++ "The target environment does not support stencil export."); + } + vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityStencilExportEXT); + spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeStencilRefReplacingEXT, NULL, 0); +@@ -4674,17 +4801,16 @@ static unsigned int shader_signature_next_location(const struct shader_signature + } + + static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, +- const struct vkd3d_shader_dst_param *dst) ++ enum vkd3d_shader_register_type reg_type, unsigned int element_idx) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- const struct vkd3d_shader_register *reg = &dst->reg; + unsigned int component_idx, input_component_count; + const struct signature_element *signature_element; + const struct shader_signature *shader_signature; + enum vkd3d_shader_component_type component_type; + const struct vkd3d_spirv_builtin *builtin; + enum vkd3d_shader_sysval_semantic sysval; +- unsigned int write_mask, reg_write_mask; ++ uint32_t write_mask, reg_write_mask; + struct vkd3d_symbol *symbol = NULL; + uint32_t val_id, input_id, var_id; + uint32_t type_id, float_type_id; +@@ -4693,26 +4819,21 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, + struct rb_entry *entry = NULL; + bool use_private_var = false; + unsigned int array_sizes[2]; +- unsigned int element_idx; +- +- assert(!reg->idx_count || !reg->idx[0].rel_addr); +- assert(reg->idx_count < 2 || !reg->idx[1].rel_addr); + +- shader_signature = reg->type == VKD3DSPR_PATCHCONST ++ shader_signature = reg_type == VKD3DSPR_PATCHCONST + ? &compiler->patch_constant_signature : &compiler->input_signature; + +- element_idx = reg->idx[reg->idx_count - 1].offset; + signature_element = &shader_signature->elements[element_idx]; + sysval = signature_element->sysval_semantic; + /* The Vulkan spec does not explicitly forbid passing varyings from the + * TCS to the TES via builtins. However, Mesa doesn't seem to handle it + * well, and we don't actually need them to be in builtins. */ +- if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN && reg->type != VKD3DSPR_PATCHCONST) ++ if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN && reg_type != VKD3DSPR_PATCHCONST) + sysval = VKD3D_SHADER_SV_NONE; + + builtin = get_spirv_builtin_for_sysval(compiler, sysval); + +- array_sizes[0] = (reg->type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); ++ array_sizes[0] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); + array_sizes[1] = signature_element->register_count; + if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic) + && (!vsir_sysval_semantic_is_clip_cull(signature_element->sysval_semantic) || array_sizes[0])) +@@ -4731,8 +4852,8 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, + else + { + component_type = signature_element->component_type; +- input_component_count = vkd3d_write_mask_component_count(signature_element->mask); +- component_idx = vkd3d_write_mask_get_component_idx(signature_element->mask); ++ input_component_count = vsir_write_mask_component_count(signature_element->mask); ++ component_idx = vsir_write_mask_get_component_idx(signature_element->mask); + } + + if (needs_private_io_variable(builtin)) +@@ -4742,13 +4863,13 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, + } + else + { +- component_idx = vkd3d_write_mask_get_component_idx(write_mask); ++ component_idx = vsir_write_mask_get_component_idx(write_mask); + reg_write_mask = write_mask >> component_idx; + } + + storage_class = SpvStorageClassInput; + +- vkd3d_symbol_make_register(®_symbol, reg); ++ vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); + + if ((entry = rb_get(&compiler->symbol_table, ®_symbol))) + { +@@ -4756,7 +4877,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, + * duplicate declarations are: a single register split into multiple declarations having + * different components, which should have been merged, and declarations in one phase + * being repeated in another (i.e. vcp/vocp), which should have been deleted. */ +- if (reg->type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler)) ++ if (reg_type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler)) + FIXME("Duplicate input definition found.\n"); + symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); + return symbol->id; +@@ -4765,7 +4886,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, + if (builtin) + { + input_id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, storage_class, array_sizes, 2); +- if (reg->type == VKD3DSPR_PATCHCONST) ++ if (reg_type == VKD3DSPR_PATCHCONST) + vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0); + } + else +@@ -4775,7 +4896,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, + input_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, + storage_class, component_type, input_component_count, array_sizes, 2); + vkd3d_spirv_add_iface_variable(builder, input_id); +- if (reg->type == VKD3DSPR_PATCHCONST) ++ if (reg_type == VKD3DSPR_PATCHCONST) + { + vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0); + location += shader_signature_next_location(&compiler->input_signature); +@@ -4784,7 +4905,8 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, + if (component_idx) + vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationComponent, component_idx); + +- spirv_compiler_emit_interpolation_decorations(compiler, input_id, signature_element->interpolation_mode); ++ spirv_compiler_emit_interpolation_decorations(compiler, component_type, input_id, ++ signature_element->interpolation_mode); + } + + var_id = input_id; +@@ -4802,12 +4924,14 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, + assert(!builtin || !builtin->spirv_array_size || use_private_var || array_sizes[0] || array_sizes[1]); + spirv_compiler_put_symbol(compiler, ®_symbol); + +- spirv_compiler_emit_register_debug_name(builder, var_id, reg); ++ vkd3d_spirv_build_op_name(builder, var_id, reg_type == VKD3DSPR_PATCHCONST ? "vpc%u" : "v%u", element_idx); + + if (use_private_var) + { +- struct vkd3d_shader_register dst_reg = *reg; +- dst_reg.data_type = VKD3D_DATA_FLOAT; ++ struct vkd3d_shader_register dst_reg; ++ ++ vsir_register_init(&dst_reg, reg_type, VKD3D_DATA_FLOAT, 1); ++ dst_reg.idx[0].offset = element_idx; + + type_id = vkd3d_spirv_get_type_id(builder, component_type, input_component_count); + +@@ -4824,9 +4948,9 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, + + val_id = spirv_compiler_emit_swizzle(compiler, val_id, + vkd3d_write_mask_from_component_count(input_component_count), +- VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, dst->write_mask >> component_idx); ++ VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, signature_element->mask >> component_idx); + +- spirv_compiler_emit_store_reg(compiler, &dst_reg, dst->write_mask, val_id); ++ spirv_compiler_emit_store_reg(compiler, &dst_reg, signature_element->mask, val_id); + } + + return input_id; +@@ -4896,7 +5020,7 @@ static void calculate_clip_or_cull_distance_mask(const struct signature_element + return; + } + +- write_mask = e->mask >> vkd3d_write_mask_get_component_idx(e->mask); ++ write_mask = e->mask >> vsir_write_mask_get_component_idx(e->mask); + *mask |= (write_mask & VKD3DSP_WRITEMASK_ALL) << (VKD3D_VEC4_SIZE * e->semantic_index); + } + +@@ -4995,7 +5119,7 @@ static void spirv_compiler_emit_output_register(struct spirv_compiler *compiler, + SpvStorageClassOutput, builtin->component_type, write_mask); + reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size; + spirv_compiler_put_symbol(compiler, ®_symbol); +- spirv_compiler_emit_register_execution_mode(compiler, reg); ++ spirv_compiler_emit_register_execution_mode(compiler, reg->type); + spirv_compiler_emit_register_debug_name(builder, output_id, reg); + } + +@@ -5024,46 +5148,44 @@ static uint32_t spirv_compiler_emit_shader_phase_builtin_variable(struct spirv_c + return id; + } + +-static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const struct vkd3d_shader_dst_param *dst) ++static void spirv_compiler_emit_output(struct spirv_compiler *compiler, ++ enum vkd3d_shader_register_type reg_type, unsigned int element_idx) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- const struct vkd3d_shader_register *reg = &dst->reg; + unsigned int component_idx, output_component_count; + const struct signature_element *signature_element; + enum vkd3d_shader_component_type component_type; + const struct shader_signature *shader_signature; + const struct vkd3d_spirv_builtin *builtin; + enum vkd3d_shader_sysval_semantic sysval; +- unsigned int write_mask, reg_write_mask; ++ uint32_t write_mask, reg_write_mask; + bool use_private_variable = false; + struct vkd3d_symbol reg_symbol; + SpvStorageClass storage_class; + unsigned int array_sizes[2]; +- unsigned int element_idx; + bool is_patch_constant; + uint32_t id, var_id; + +- is_patch_constant = is_in_fork_or_join_phase(compiler); ++ is_patch_constant = (reg_type == VKD3DSPR_PATCHCONST); + + shader_signature = is_patch_constant ? &compiler->patch_constant_signature : &compiler->output_signature; + +- element_idx = reg->idx[reg->idx_count - 1].offset; + signature_element = &shader_signature->elements[element_idx]; + sysval = signature_element->sysval_semantic; + /* Don't use builtins for TCS -> TES varyings. See spirv_compiler_emit_input(). */ + if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && !is_patch_constant) + sysval = VKD3D_SHADER_SV_NONE; +- array_sizes[0] = (reg->type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); ++ array_sizes[0] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); + array_sizes[1] = signature_element->register_count; + if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic)) + array_sizes[1] = 0; + +- builtin = vkd3d_get_spirv_builtin(compiler, dst->reg.type, sysval); ++ builtin = vkd3d_get_spirv_builtin(compiler, reg_type, sysval); + + write_mask = signature_element->mask; + +- component_idx = vkd3d_write_mask_get_component_idx(write_mask); +- output_component_count = vkd3d_write_mask_component_count(write_mask); ++ component_idx = vsir_write_mask_get_component_idx(write_mask); ++ output_component_count = vsir_write_mask_component_count(write_mask); + if (builtin) + { + component_type = builtin->component_type; +@@ -5077,15 +5199,18 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st + + storage_class = SpvStorageClassOutput; + +- if (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE +- || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask) +- || needs_private_io_variable(builtin)) ++ if (needs_private_io_variable(builtin)) ++ use_private_variable = true; ++ ++ if (!is_patch_constant ++ && (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE ++ || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask))) + { + use_private_variable = true; + } + + reg_write_mask = write_mask >> component_idx; +- vkd3d_symbol_make_register(®_symbol, reg); ++ vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); + + if (rb_get(&compiler->symbol_table, ®_symbol)) + { +@@ -5094,7 +5219,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st + return; + } + +- if (compiler->output_info[element_idx].id) ++ if (!is_patch_constant && compiler->output_info[element_idx].id) + { + id = compiler->output_info[element_idx].id; + } +@@ -5105,7 +5230,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st + else + id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, storage_class, array_sizes, 2); + +- spirv_compiler_emit_register_execution_mode(compiler, &dst->reg); ++ spirv_compiler_emit_register_execution_mode(compiler, reg_type); + } + else if (signature_element->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) + { +@@ -5146,8 +5271,11 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st + + spirv_compiler_decorate_xfb_output(compiler, id, output_component_count, signature_element); + +- compiler->output_info[element_idx].id = id; +- compiler->output_info[element_idx].component_type = component_type; ++ if (!is_patch_constant) ++ { ++ compiler->output_info[element_idx].id = id; ++ compiler->output_info[element_idx].component_type = component_type; ++ } + + var_id = id; + if (use_private_variable) +@@ -5165,8 +5293,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st + + spirv_compiler_put_symbol(compiler, ®_symbol); + +- if (!is_patch_constant) +- spirv_compiler_emit_register_debug_name(builder, var_id, reg); ++ vkd3d_spirv_build_op_name(builder, var_id, reg_type == VKD3DSPR_PATCHCONST ? "vpc%u" : "o%u", element_idx); + + if (use_private_variable) + { +@@ -5198,9 +5325,9 @@ static uint32_t spirv_compiler_get_output_array_index(struct spirv_compiler *com + static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compiler, + const struct shader_signature *signature, const struct signature_element *output, + const struct vkd3d_shader_output_info *output_info, +- uint32_t output_index_id, uint32_t val_id, unsigned int write_mask) ++ uint32_t output_index_id, uint32_t val_id, uint32_t write_mask) + { +- unsigned int dst_write_mask, use_mask, uninit_mask, swizzle, mask; ++ uint32_t dst_write_mask, use_mask, uninit_mask, swizzle, mask; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, zero_id, ptr_type_id, chain_id, object_id; + const struct signature_element *element; +@@ -5222,7 +5349,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + use_mask |= element->used_mask; + } + } +- index = vkd3d_write_mask_get_component_idx(output->mask); ++ index = vsir_write_mask_get_component_idx(output->mask); + dst_write_mask >>= index; + use_mask >>= index; + write_mask &= dst_write_mask; +@@ -5246,7 +5373,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + output_info->component_type, VKD3D_VEC4_SIZE, 0); + val_id = spirv_compiler_emit_vector_shuffle(compiler, + zero_id, val_id, swizzle, uninit_mask, output_info->component_type, +- vkd3d_write_mask_component_count(write_mask)); ++ vsir_write_mask_component_count(write_mask)); + } + else + { +@@ -5258,7 +5385,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + if (output_index_id) + { + type_id = vkd3d_spirv_get_type_id(builder, +- output_info->component_type, vkd3d_write_mask_component_count(dst_write_mask)); ++ output_info->component_type, vsir_write_mask_component_count(dst_write_mask)); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); + output_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, output_id, output_index_id); + } +@@ -5444,6 +5571,21 @@ static void spirv_compiler_emit_dcl_global_flags(struct spirv_compiler *compiler + flags &= ~(VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS | VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS); + } + ++ if (flags & VKD3DSGF_ENABLE_INT64) ++ { ++ if (compiler->features & VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64) ++ { ++ vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityInt64); ++ } ++ else ++ { ++ WARN("Unsupported 64-bit integer ops.\n"); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, ++ "The target environment does not support 64-bit integers."); ++ } ++ flags &= ~VKD3DSGF_ENABLE_INT64; ++ } ++ + if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS)) + FIXME("Unhandled global flags %#"PRIx64".\n", (uint64_t)flags); + else +@@ -5493,39 +5635,40 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil + { + const struct vkd3d_shader_indexable_temp *temp = &instruction->declaration.indexable_temp; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ uint32_t id, type_id, length_id, ptr_type_id, init_id = 0; ++ enum vkd3d_shader_component_type component_type; + struct vkd3d_shader_register reg; + struct vkd3d_symbol reg_symbol; ++ SpvStorageClass storage_class; + size_t function_location; +- uint32_t id; + +- if (temp->component_count != 4) +- FIXME("Unhandled component count %u.\n", temp->component_count); ++ storage_class = SpvStorageClassFunction; + + vsir_register_init(®, VKD3DSPR_IDXTEMP, VKD3D_DATA_FLOAT, 1); + reg.idx[0].offset = temp->register_idx; + + if (temp->alignment) + WARN("Ignoring alignment %u.\n", temp->alignment); +- if (temp->initialiser) +- { +- FIXME("Initialisers are not supported.\n"); +- spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, +- "Initialisers for indexable temps are not supported."); +- } + + function_location = spirv_compiler_get_current_function_location(compiler); + vkd3d_spirv_begin_function_stream_insertion(builder, function_location); + +- id = spirv_compiler_emit_array_variable(compiler, &builder->function_stream, +- SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &temp->register_size, 1); ++ component_type = vkd3d_component_type_from_data_type(temp->data_type); ++ type_id = vkd3d_spirv_get_type_id(builder, component_type, temp->component_count); ++ length_id = spirv_compiler_get_constant_uint(compiler, temp->register_size); ++ type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); ++ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); ++ if (temp->initialiser) ++ init_id = spirv_compiler_emit_constant_array(compiler, temp->initialiser, NULL); ++ id = vkd3d_spirv_build_op_variable(builder, &builder->function_stream, ptr_type_id, storage_class, init_id); + + spirv_compiler_emit_register_debug_name(builder, id, ®); + + vkd3d_spirv_end_function_stream_insertion(builder); + + vkd3d_symbol_make_register(®_symbol, ®); +- vkd3d_symbol_set_register_info(®_symbol, id, +- SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); ++ vkd3d_symbol_set_register_info(®_symbol, id, storage_class, ++ component_type, vkd3d_write_mask_from_component_count(temp->component_count)); + spirv_compiler_put_symbol(compiler, ®_symbol); + } + +@@ -5743,34 +5886,24 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi + const struct vkd3d_shader_instruction *instruction) + { + const struct vkd3d_shader_immediate_constant_buffer *icb = instruction->declaration.icb; +- uint32_t *elements, length_id, type_id, const_id, ptr_type_id, icb_id; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ uint32_t type_id, const_id, ptr_type_id, icb_id; + struct vkd3d_shader_register reg; + struct vkd3d_symbol reg_symbol; +- unsigned int i; + +- assert(icb->data_type == VKD3D_DATA_FLOAT); +- assert(icb->component_count == VKD3D_VEC4_SIZE); +- +- if (!(elements = vkd3d_calloc(icb->element_count, sizeof(*elements)))) +- return; +- for (i = 0; i < icb->element_count; ++i) +- elements[i] = spirv_compiler_get_constant(compiler, +- VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &icb->data[4 * i]); +- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); +- length_id = spirv_compiler_get_constant_uint(compiler, icb->element_count); +- type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); +- const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, icb->element_count); ++ const_id = spirv_compiler_emit_constant_array(compiler, icb, &type_id); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id); + icb_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, + ptr_type_id, SpvStorageClassPrivate, const_id); + vkd3d_spirv_build_op_name(builder, icb_id, "icb"); +- vkd3d_free(elements); + +- vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 0); ++ /* Set an index count of 2 so vkd3d_symbol_make_register() uses idx[0] as a buffer id. */ ++ vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 2); ++ reg.idx[0].offset = icb->register_idx; + vkd3d_symbol_make_register(®_symbol, ®); + vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate, +- VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); ++ vkd3d_component_type_from_data_type(icb->data_type), ++ vkd3d_write_mask_from_component_count(icb->component_count)); + spirv_compiler_put_symbol(compiler, ®_symbol); + } + +@@ -6147,37 +6280,22 @@ static void spirv_compiler_emit_dcl_input(struct spirv_compiler *compiler, + { + const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst; + +- /* OUTPOINTID is handled in spirv_compiler_emit_hull_shader_builtins(). */ +- if (dst->reg.type == VKD3DSPR_INPUT || dst->reg.type == VKD3DSPR_PATCHCONST) +- spirv_compiler_emit_input(compiler, dst); +- else if (dst->reg.type != VKD3DSPR_OUTPOINTID) ++ /* INPUT and PATCHCONST are handled in spirv_compiler_emit_io_declarations(). ++ * OUTPOINTID is handled in spirv_compiler_emit_hull_shader_builtins(). */ ++ if (dst->reg.type != VKD3DSPR_INPUT && dst->reg.type != VKD3DSPR_PATCHCONST ++ && dst->reg.type != VKD3DSPR_OUTPOINTID) + spirv_compiler_emit_input_register(compiler, dst); + } + +-static void spirv_compiler_emit_dcl_input_sysval(struct spirv_compiler *compiler, +- const struct vkd3d_shader_instruction *instruction) +-{ +- spirv_compiler_emit_input(compiler, &instruction->declaration.register_semantic.reg); +-} +- + static void spirv_compiler_emit_dcl_output(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { + const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst; + +- if (dst->reg.type == VKD3DSPR_OUTPUT +- || (is_in_fork_or_join_phase(compiler) && dst->reg.type == VKD3DSPR_PATCHCONST)) +- spirv_compiler_emit_output(compiler, dst); +- else ++ if (dst->reg.type != VKD3DSPR_OUTPUT && dst->reg.type != VKD3DSPR_PATCHCONST) + spirv_compiler_emit_output_register(compiler, dst); + } + +-static void spirv_compiler_emit_dcl_output_siv(struct spirv_compiler *compiler, +- const struct vkd3d_shader_instruction *instruction) +-{ +- spirv_compiler_emit_output(compiler, &instruction->declaration.register_semantic.reg); +-} +- + static void spirv_compiler_emit_dcl_stream(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { +@@ -6377,7 +6495,6 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile + + static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler) + { +- const struct shader_signature *signature = &compiler->output_signature; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + + if (is_in_control_point_phase(compiler) && compiler->emit_default_control_point_phase) +@@ -6395,7 +6512,6 @@ static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler) + + /* Fork and join phases share output registers (patch constants). + * Control point phase has separate output registers. */ +- memset(compiler->output_info, 0, signature->element_count * sizeof(*compiler->output_info)); + memset(compiler->private_output_variable, 0, sizeof(compiler->private_output_variable)); + memset(compiler->private_output_variable_write_mask, 0, sizeof(compiler->private_output_variable_write_mask)); + } +@@ -6438,15 +6554,12 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile + { + const struct shader_signature *output_signature = &compiler->output_signature; + const struct shader_signature *input_signature = &compiler->input_signature; ++ uint32_t type_id, output_ptr_type_id, input_id, dst_id, invocation_id; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + enum vkd3d_shader_component_type component_type; + struct vkd3d_shader_src_param invocation; + struct vkd3d_shader_register input_reg; +- uint32_t type_id, output_ptr_type_id; +- uint32_t input_id, output_id, dst_id; + unsigned int component_count; +- unsigned int array_sizes[2]; +- uint32_t invocation_id; + unsigned int i; + + invocation_id = spirv_compiler_emit_load_invocation_id(compiler); +@@ -6466,6 +6579,8 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile + { + const struct signature_element *output = &output_signature->elements[i]; + const struct signature_element *input = &input_signature->elements[i]; ++ struct vkd3d_shader_register_info output_reg_info; ++ struct vkd3d_shader_register output_reg; + + assert(input->mask == output->mask); + assert(input->component_type == output->component_type); +@@ -6473,22 +6588,16 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile + input_reg.idx[1].offset = i; + input_id = spirv_compiler_get_register_id(compiler, &input_reg); + ++ vsir_register_init(&output_reg, VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); ++ output_reg.idx[0].offset = i; ++ spirv_compiler_get_register_info(compiler, &output_reg, &output_reg_info); ++ + component_type = output->component_type; +- component_count = vkd3d_write_mask_component_count(output->mask); ++ component_count = vsir_write_mask_component_count(output->mask); + type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); +- if ((array_sizes[0] = (input->register_count > 1) ? input->register_count : 0)) +- type_id = vkd3d_spirv_get_op_type_array(builder, type_id, spirv_compiler_get_constant_uint(compiler, +- array_sizes[0])); +- +- array_sizes[1] = compiler->output_control_point_count; +- output_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, SpvStorageClassOutput, +- component_type, component_count, array_sizes, 2); +- vkd3d_spirv_add_iface_variable(builder, output_id); +- vkd3d_spirv_build_op_decorate1(builder, output_id, SpvDecorationLocation, output->register_index); +- vkd3d_spirv_build_op_name(builder, output_id, "vocp%u", output->register_index); +- + output_ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); +- dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_id, invocation_id); ++ ++ dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_reg_info.id, invocation_id); + + vkd3d_spirv_build_op_copy_memory(builder, dst_id, input_id, SpvMemoryAccessMaskNone); + } +@@ -6593,12 +6702,14 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru + {VKD3DSIH_ISHR, SpvOpShiftRightArithmetic}, + {VKD3DSIH_ITOD, SpvOpConvertSToF}, + {VKD3DSIH_ITOF, SpvOpConvertSToF}, ++ {VKD3DSIH_ITOI, SpvOpSConvert}, + {VKD3DSIH_MUL, SpvOpFMul}, + {VKD3DSIH_NOT, SpvOpNot}, + {VKD3DSIH_OR, SpvOpBitwiseOr}, + {VKD3DSIH_USHR, SpvOpShiftRightLogical}, + {VKD3DSIH_UTOD, SpvOpConvertUToF}, + {VKD3DSIH_UTOF, SpvOpConvertUToF}, ++ {VKD3DSIH_UTOU, SpvOpUConvert}, + {VKD3DSIH_XOR, SpvOpBitwiseXor}, + }; + unsigned int i; +@@ -6650,6 +6761,10 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, + { + val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); + } ++ else if (dst->reg.data_type == VKD3D_DATA_UINT64) ++ { ++ val_id = spirv_compiler_emit_bool_to_int64(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); ++ } + else + { + WARN("Unhandled data type %u.\n", dst->reg.data_type); +@@ -6715,11 +6830,11 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil + * Microsoft fxc will compile immediate constants larger than 5 bits. + * Fixing up the constants would be more elegant, but the simplest way is + * to let this handle constants too. */ +- if (instruction->handler_idx == VKD3DSIH_ISHL || instruction->handler_idx == VKD3DSIH_ISHR +- || instruction->handler_idx == VKD3DSIH_USHR) ++ if (!(instruction->flags & VKD3DSI_SHIFT_UNMASKED) && (instruction->handler_idx == VKD3DSIH_ISHL ++ || instruction->handler_idx == VKD3DSIH_ISHR || instruction->handler_idx == VKD3DSIH_USHR)) + { + uint32_t mask_id = spirv_compiler_get_constant_vector(compiler, +- VKD3D_SHADER_COMPONENT_UINT, vkd3d_write_mask_component_count(dst->write_mask), 0x1f); ++ VKD3D_SHADER_COMPONENT_UINT, vsir_write_mask_component_count(dst->write_mask), 0x1f); + src_ids[1] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[1], mask_id); + } + +@@ -6849,7 +6964,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, + return; + } + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + if (component_count != 1 && component_count != VKD3D_VEC4_SIZE + && dst_reg_info.write_mask == VKD3DSP_WRITEMASK_ALL) + { +@@ -6863,7 +6978,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, + for (i = 0; i < ARRAY_SIZE(components); ++i) + { + if (dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)) +- components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(src->swizzle, i); ++ components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(src->swizzle, i); + else + components[i] = i; + } +@@ -6877,6 +6992,11 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, + + general_implementation: + val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); ++ if (dst->reg.data_type != src->reg.data_type) ++ { ++ val_id = vkd3d_spirv_build_op_bitcast(builder, vkd3d_spirv_get_type_id_for_data_type(builder, ++ dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)), val_id); ++ } + spirv_compiler_emit_store_dst(compiler, dst, val_id); + } + +@@ -6893,12 +7013,12 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, + src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); + src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask); + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); + + if (src[0].reg.data_type != VKD3D_DATA_BOOL) + condition_id = spirv_compiler_emit_int_to_bool(compiler, +- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id); ++ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); + val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id); + + spirv_compiler_emit_store_dst(compiler, dst, val_id); +@@ -6919,11 +7039,11 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler, + src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); + src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask); + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); + + condition_id = spirv_compiler_emit_int_to_bool(compiler, +- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id); ++ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); + + val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src2_id, src1_id); + spirv_compiler_emit_store_dst(compiler, &dst[0], val_id); +@@ -6942,7 +7062,7 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, + unsigned int component_count, i; + DWORD write_mask; + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); + + if (instruction->handler_idx == VKD3DSIH_DP4) +@@ -6980,7 +7100,7 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler, + uint32_t type_id, src_id, val_id, div_id; + unsigned int component_count; + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); + + src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); +@@ -7060,7 +7180,7 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, + uint32_t type_id, val_id, src_ids[3]; + unsigned int i, component_count; + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, component_count); + + for (i = 0; i < ARRAY_SIZE(src_ids); ++i) +@@ -7087,16 +7207,18 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, + + if (dst[0].reg.type != VKD3DSPR_NULL) + { +- component_count = vkd3d_write_mask_component_count(dst[0].write_mask); ++ component_count = vsir_write_mask_component_count(dst[0].write_mask); + type_id = spirv_compiler_get_type_id_for_dst(compiler, &dst[0]); + + src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst[0].write_mask); + src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst[0].write_mask); + + condition_id = spirv_compiler_emit_int_to_bool(compiler, +- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id); +- uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, +- 0xffffffff, component_count); ++ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src1_id); ++ if (dst[0].reg.data_type == VKD3D_DATA_UINT64) ++ uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count); ++ else ++ uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count); + + val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, div_op, type_id, src0_id, src1_id); + /* The SPIR-V spec says: "The resulting value is undefined if Operand 2 is 0." */ +@@ -7109,16 +7231,18 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, + { + if (!component_count || dst[0].write_mask != dst[1].write_mask) + { +- component_count = vkd3d_write_mask_component_count(dst[1].write_mask); ++ component_count = vsir_write_mask_component_count(dst[1].write_mask); + type_id = spirv_compiler_get_type_id_for_dst(compiler, &dst[1]); + + src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst[1].write_mask); + src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst[1].write_mask); + + condition_id = spirv_compiler_emit_int_to_bool(compiler, +- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id); +- uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, +- 0xffffffff, component_count); ++ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src1_id); ++ if (dst[1].reg.data_type == VKD3D_DATA_UINT64) ++ uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count); ++ else ++ uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count); + } + + val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, mod_op, type_id, src0_id, src1_id); +@@ -7147,7 +7271,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, + * as a signed integer, but Direct3D expects the result to saturate, + * and for NaN to yield zero. */ + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask); + dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); + src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); +@@ -7200,7 +7324,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, + * as an unsigned integer, but Direct3D expects the result to saturate, + * and for NaN to yield zero. */ + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask); + dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); + src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); +@@ -7387,7 +7511,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co + return; + } + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + + src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); + src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); +@@ -7409,7 +7533,7 @@ static uint32_t spirv_compiler_emit_conditional_branch(struct spirv_compiler *co + uint32_t condition_id, merge_block_id; + + condition_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); +- condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, 1, condition_id); ++ condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, src->reg.data_type, 1, condition_id); + + merge_block_id = vkd3d_spirv_alloc_id(builder); + +@@ -7542,7 +7666,7 @@ static int spirv_compiler_emit_control_flow_instruction(struct spirv_compiler *c + return VKD3D_ERROR_OUT_OF_MEMORY; + + val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); +- condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, 1, val_id); ++ condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, src->reg.data_type, 1, val_id); + + true_label = vkd3d_spirv_alloc_id(builder); + merge_block_id = vkd3d_spirv_alloc_id(builder); +@@ -7705,7 +7829,7 @@ static int spirv_compiler_emit_control_flow_instruction(struct spirv_compiler *c + "The swizzle for a switch case value is not scalar."); + } + assert(src->reg.type == VKD3DSPR_IMMCONST); +- value = *src->reg.u.immconst_uint; ++ value = *src->reg.u.immconst_u32; + + if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size, + 2 * (cf_info->u.switch_.case_block_count + 1), sizeof(*cf_info->u.switch_.case_blocks))) +@@ -8325,7 +8449,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, + } + else + { +- component_idx = vkd3d_swizzle_get_component(sampler->swizzle, 0); ++ component_idx = vsir_swizzle_get_component(sampler->swizzle, 0); + /* Nvidia driver requires signed integer type. */ + component_id = spirv_compiler_get_constant(compiler, + VKD3D_SHADER_COMPONENT_INT, 1, &component_idx); +@@ -8403,7 +8527,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler + if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) + continue; + +- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); ++ component_idx = vsir_swizzle_get_component(resource->swizzle, i); + coordinate_id = base_coordinate_id; + if (component_idx) + coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, +@@ -8435,7 +8559,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler + if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) + continue; + +- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); ++ component_idx = vsir_swizzle_get_component(resource->swizzle, i); + coordinate_id = base_coordinate_id; + if (component_idx) + coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, +@@ -8479,7 +8603,7 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, + if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) + continue; + +- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); ++ component_idx = vsir_swizzle_get_component(resource->swizzle, i); + coordinate_id = base_coordinate_id; + if (component_idx) + coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, +@@ -8540,7 +8664,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * + assert(data->reg.data_type == VKD3D_DATA_UINT); + val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + for (component_idx = 0; component_idx < component_count; ++component_idx) + { + data_id = component_count > 1 ? +@@ -8569,7 +8693,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * + assert(data->reg.data_type == VKD3D_DATA_UINT); + val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + for (component_idx = 0; component_idx < component_count; ++component_idx) + { + /* Mesa Vulkan drivers require the texel parameter to be a vector. */ +@@ -8613,7 +8737,7 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, + assert(data->reg.data_type == VKD3D_DATA_UINT); + val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); + +- component_count = vkd3d_write_mask_component_count(dst->write_mask); ++ component_count = vsir_write_mask_component_count(dst->write_mask); + for (component_idx = 0; component_idx < component_count; ++component_idx) + { + data_id = component_count > 1 ? +@@ -9275,7 +9399,7 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, + } + + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, +- vkd3d_write_mask_component_count(register_info.write_mask)); ++ vsir_write_mask_component_count(register_info.write_mask)); + + instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); + val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id, instr_set_id, op, src_ids, src_count); +@@ -9425,18 +9549,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, + case VKD3DSIH_DCL_INPUT: + spirv_compiler_emit_dcl_input(compiler, instruction); + break; +- case VKD3DSIH_DCL_INPUT_PS_SGV: +- case VKD3DSIH_DCL_INPUT_PS_SIV: +- case VKD3DSIH_DCL_INPUT_SGV: +- case VKD3DSIH_DCL_INPUT_SIV: +- spirv_compiler_emit_dcl_input_sysval(compiler, instruction); +- break; + case VKD3DSIH_DCL_OUTPUT: + spirv_compiler_emit_dcl_output(compiler, instruction); + break; +- case VKD3DSIH_DCL_OUTPUT_SIV: +- spirv_compiler_emit_dcl_output_siv(compiler, instruction); +- break; + case VKD3DSIH_DCL_STREAM: + spirv_compiler_emit_dcl_stream(compiler, instruction); + break; +@@ -9719,6 +9834,11 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, + case VKD3DSIH_DCL_CONSTANT_BUFFER: + case VKD3DSIH_DCL_HS_MAX_TESSFACTOR: + case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT: ++ case VKD3DSIH_DCL_INPUT_SGV: ++ case VKD3DSIH_DCL_INPUT_SIV: ++ case VKD3DSIH_DCL_INPUT_PS_SGV: ++ case VKD3DSIH_DCL_INPUT_PS_SIV: ++ case VKD3DSIH_DCL_OUTPUT_SIV: + case VKD3DSIH_DCL_RESOURCE_RAW: + case VKD3DSIH_DCL_RESOURCE_STRUCTURED: + case VKD3DSIH_DCL_SAMPLER: +@@ -9740,6 +9860,30 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, + return ret; + } + ++static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) ++{ ++ for (unsigned int i = 0; i < compiler->input_signature.element_count; ++i) ++ spirv_compiler_emit_input(compiler, VKD3DSPR_INPUT, i); ++ ++ for (unsigned int i = 0; i < compiler->output_signature.element_count; ++i) ++ { ++ /* PS outputs other than TARGET have dedicated registers and therefore ++ * go through spirv_compiler_emit_dcl_output() for now. */ ++ if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL ++ && compiler->output_signature.elements[i].sysval_semantic != VKD3D_SHADER_SV_TARGET) ++ continue; ++ spirv_compiler_emit_output(compiler, VKD3DSPR_OUTPUT, i); ++ } ++ ++ for (unsigned int i = 0; i < compiler->patch_constant_signature.element_count; ++i) ++ { ++ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL) ++ spirv_compiler_emit_output(compiler, VKD3DSPR_PATCHCONST, i); ++ else ++ spirv_compiler_emit_input(compiler, VKD3DSPR_PATCHCONST, i); ++ } ++} ++ + static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *compiler) + { + unsigned int i; +@@ -9826,6 +9970,8 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) + spirv_compiler_emit_shader_signature_outputs(compiler); + ++ spirv_compiler_emit_io_declarations(compiler); ++ + for (i = 0; i < instructions.count && result >= 0; ++i) + { + compiler->location.line = i + 1; +@@ -9874,11 +10020,28 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + if (!vkd3d_spirv_compile_module(builder, spirv, spirv_compiler_get_entry_point_name(compiler))) + return VKD3D_ERROR; + +- if (TRACE_ON()) ++ if (TRACE_ON() || parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION) + { + enum vkd3d_shader_spirv_environment environment = spirv_compiler_get_target_environment(compiler); +- vkd3d_spirv_dump(spirv, environment); +- vkd3d_spirv_validate(spirv, environment); ++ struct vkd3d_string_buffer buffer; ++ ++ if (TRACE_ON()) ++ vkd3d_spirv_dump(spirv, environment); ++ ++ vkd3d_string_buffer_init(&buffer); ++ if (!vkd3d_spirv_validate(&buffer, spirv, environment)) ++ { ++ FIXME("Failed to validate SPIR-V binary.\n"); ++ vkd3d_shader_trace_text(buffer.buffer, buffer.content_size); ++ ++ if (compiler->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION) ++ { ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER, ++ "Execution generated an invalid shader, failing compilation:\n%s", ++ buffer.buffer); ++ } ++ } ++ vkd3d_string_buffer_cleanup(&buffer); + } + + if (compiler->failed) +@@ -9905,7 +10068,7 @@ int spirv_compile(struct vkd3d_shader_parser *parser, + int ret; + + if (!(spirv_compiler = spirv_compiler_create(&parser->shader_version, &parser->shader_desc, +- compile_info, scan_descriptor_info, message_context, &parser->location))) ++ compile_info, scan_descriptor_info, message_context, &parser->location, parser->config_flags))) + { + ERR("Failed to create SPIR-V compiler.\n"); + return VKD3D_ERROR; +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index 80f8ab98c08..f859e758d8e 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -792,9 +792,11 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui + ins->handler_idx = VKD3DSIH_INVALID; + return; + } ++ icb->register_idx = 0; + icb->data_type = VKD3D_DATA_FLOAT; + icb->component_count = VKD3D_VEC4_SIZE; + icb->element_count = icb_size / VKD3D_VEC4_SIZE; ++ icb->is_null = false; + memcpy(icb->data, tokens, sizeof(*tokens) * icb_size); + shader_instruction_array_add_icb(&priv->p.instructions, icb); + ins->declaration.icb = icb; +@@ -918,10 +920,11 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins + uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) + { + struct vkd3d_shader_index_range *index_range = &ins->declaration.index_range; +- unsigned int i, register_idx, register_count, write_mask; ++ unsigned int i, register_idx, register_count; + enum vkd3d_shader_register_type type; + struct sm4_index_range_array *ranges; + unsigned int *io_masks; ++ uint32_t write_mask; + + shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, + &index_range->dst); +@@ -931,7 +934,7 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins + register_count = index_range->register_count; + write_mask = index_range->dst.write_mask; + +- if (vkd3d_write_mask_component_count(write_mask) != 1) ++ if (vsir_write_mask_component_count(write_mask) != 1) + { + WARN("Unhandled write mask %#x.\n", write_mask); + vkd3d_shader_parser_warning(&priv->p, VKD3D_SHADER_WARNING_TPF_UNHANDLED_INDEX_RANGE_MASK, +@@ -1900,19 +1903,19 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui + + if (register_type == VKD3D_SM4_RT_IMMCONST || register_type == VKD3D_SM4_RT_IMMCONST64) + { +- unsigned int dword_count; ++ unsigned int u32_count; + + switch (param->dimension) + { + case VSIR_DIMENSION_SCALAR: +- dword_count = 1 + (register_type == VKD3D_SM4_RT_IMMCONST64); +- if (end - *ptr < dword_count) ++ u32_count = 1 + (register_type == VKD3D_SM4_RT_IMMCONST64); ++ if (end - *ptr < u32_count) + { + WARN("Invalid ptr %p, end %p.\n", *ptr, end); + return false; + } +- memcpy(param->u.immconst_uint, *ptr, dword_count * sizeof(DWORD)); +- *ptr += dword_count; ++ memcpy(param->u.immconst_u32, *ptr, u32_count * sizeof(uint32_t)); ++ *ptr += u32_count; + break; + + case VSIR_DIMENSION_VEC4: +@@ -1921,7 +1924,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui + WARN("Invalid ptr %p, end %p.\n", *ptr, end); + return false; + } +- memcpy(param->u.immconst_uint, *ptr, VKD3D_VEC4_SIZE * sizeof(DWORD)); ++ memcpy(param->u.immconst_u32, *ptr, VKD3D_VEC4_SIZE * sizeof(uint32_t)); + *ptr += 4; + break; + +@@ -1930,6 +1933,15 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui + break; + } + } ++ else if (register_type == VKD3D_SM4_RT_IMMCONSTBUFFER) ++ { ++ if (param->idx_count != 1) ++ { ++ WARN("Unexpected idx count %u.\n", param->idx_count); ++ vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_INDEX_COUNT, ++ "Invalid index count %u for immediate const buffer register; expected count 1.", param->idx_count); ++ } ++ } + else if (!shader_is_sm_5_1(priv) && vsir_register_is_descriptor(param)) + { + /* SM5.1 places a symbol identifier in idx[0] and moves +@@ -1970,10 +1982,10 @@ static uint32_t swizzle_from_sm4(uint32_t s) + static uint32_t swizzle_to_sm4(uint32_t s) + { + uint32_t ret = 0; +- ret |= ((vkd3d_swizzle_get_component(s, 0)) & 0x3); +- ret |= ((vkd3d_swizzle_get_component(s, 1)) & 0x3) << 2; +- ret |= ((vkd3d_swizzle_get_component(s, 2)) & 0x3) << 4; +- ret |= ((vkd3d_swizzle_get_component(s, 3)) & 0x3) << 6; ++ ret |= ((vsir_swizzle_get_component(s, 0)) & 0x3); ++ ret |= ((vsir_swizzle_get_component(s, 1)) & 0x3) << 2; ++ ret |= ((vsir_swizzle_get_component(s, 2)) & 0x3) << 4; ++ ret |= ((vsir_swizzle_get_component(s, 3)) & 0x3) << 6; + return ret; + } + +@@ -2002,12 +2014,12 @@ static bool register_is_control_point_input(const struct vkd3d_shader_register * + || priv->p.shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY)); + } + +-static unsigned int mask_from_swizzle(unsigned int swizzle) ++static uint32_t mask_from_swizzle(uint32_t swizzle) + { +- return (1u << vkd3d_swizzle_get_component(swizzle, 0)) +- | (1u << vkd3d_swizzle_get_component(swizzle, 1)) +- | (1u << vkd3d_swizzle_get_component(swizzle, 2)) +- | (1u << vkd3d_swizzle_get_component(swizzle, 3)); ++ return (1u << vsir_swizzle_get_component(swizzle, 0)) ++ | (1u << vsir_swizzle_get_component(swizzle, 1)) ++ | (1u << vsir_swizzle_get_component(swizzle, 2)) ++ | (1u << vsir_swizzle_get_component(swizzle, 3)); + } + + static bool shader_sm4_validate_input_output_register(struct vkd3d_shader_sm4_parser *priv, +@@ -2219,7 +2231,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons + } + + if (data_type == VKD3D_DATA_DOUBLE) +- dst_param->write_mask = vkd3d_write_mask_64_from_32(dst_param->write_mask); ++ dst_param->write_mask = vsir_write_mask_64_from_32(dst_param->write_mask); + /* Some scalar registers are declared with no write mask in shader bytecode. */ + if (!dst_param->write_mask && shader_sm4_is_scalar_register(&dst_param->reg)) + dst_param->write_mask = VKD3DSP_WRITEMASK_0; +@@ -2533,6 +2545,16 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t + return true; + } + ++static void uninvert_used_masks(struct shader_signature *signature) ++{ ++ for (unsigned int i = 0; i < signature->element_count; ++i) ++ { ++ struct signature_element *e = &signature->elements[i]; ++ ++ e->used_mask = e->mask & ~e->used_mask; ++ } ++} ++ + static bool shader_sm4_parser_validate_signature(struct vkd3d_shader_sm4_parser *sm4, + const struct shader_signature *signature, unsigned int *masks, const char *name) + { +@@ -2628,6 +2650,12 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi + return VKD3D_ERROR_INVALID_ARGUMENT; + } + ++ /* DXBC stores used masks inverted for output signatures, for some reason. ++ * We return them un-inverted. */ ++ uninvert_used_masks(&shader_desc->output_signature); ++ if (sm4->p.shader_version.type == VKD3D_SHADER_TYPE_HULL) ++ uninvert_used_masks(&shader_desc->patch_constant_signature); ++ + if (!shader_sm4_parser_validate_signature(sm4, &shader_desc->input_signature, + sm4->input_register_masks, "Input") + || !shader_sm4_parser_validate_signature(sm4, &shader_desc->output_signature, +@@ -3842,7 +3870,7 @@ static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src, + if (width == 1) + { + src->reg.dimension = VSIR_DIMENSION_SCALAR; +- src->reg.u.immconst_uint[0] = value->u[0].u; ++ src->reg.u.immconst_u32[0] = value->u[0].u; + } + else + { +@@ -3852,9 +3880,9 @@ static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src, + for (i = 0; i < 4; ++i) + { + if ((map_writemask & (1u << i)) && (j < width)) +- src->reg.u.immconst_uint[i] = value->u[j++].u; ++ src->reg.u.immconst_u32[i] = value->u[j++].u; + else +- src->reg.u.immconst_uint[i] = 0; ++ src->reg.u.immconst_u32[i] = 0; + } + } + } +@@ -4049,12 +4077,12 @@ static void sm4_write_src_register(const struct tpf_writer *tpf, const struct vk + + if (src->reg.type == VKD3DSPR_IMMCONST) + { +- put_u32(buffer, src->reg.u.immconst_uint[0]); ++ put_u32(buffer, src->reg.u.immconst_u32[0]); + if (src->reg.dimension == VSIR_DIMENSION_VEC4) + { +- put_u32(buffer, src->reg.u.immconst_uint[1]); +- put_u32(buffer, src->reg.u.immconst_uint[2]); +- put_u32(buffer, src->reg.u.immconst_uint[3]); ++ put_u32(buffer, src->reg.u.immconst_u32[1]); ++ put_u32(buffer, src->reg.u.immconst_u32[2]); ++ put_u32(buffer, src->reg.u.immconst_u32[3]); + } + } + } +@@ -4589,7 +4617,7 @@ static void write_sm4_ld(const struct tpf_writer *tpf, const struct hlsl_ir_node + memset(&instr.srcs[2], 0, sizeof(instr.srcs[2])); + reg->type = VKD3DSPR_IMMCONST; + reg->dimension = VSIR_DIMENSION_SCALAR; +- reg->u.immconst_uint[0] = index->value.u[0].u; ++ reg->u.immconst_u32[0] = index->value.u[0].u; + } + else if (tpf->ctx->profile->major_version == 4 && tpf->ctx->profile->minor_version == 0) + { +@@ -4750,7 +4778,7 @@ static void write_sm4_cast_from_bool(const struct tpf_writer *tpf, const struct + sm4_src_from_node(tpf, &instr.srcs[0], arg, instr.dsts[0].write_mask); + instr.srcs[1].reg.type = VKD3DSPR_IMMCONST; + instr.srcs[1].reg.dimension = VSIR_DIMENSION_SCALAR; +- instr.srcs[1].reg.u.immconst_uint[0] = mask; ++ instr.srcs[1].reg.u.immconst_u32[0] = mask; + instr.src_count = 2; + + write_sm4_instruction(tpf, &instr); +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index 8fd8945151f..8fd98d2a551 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -23,6 +23,8 @@ + #include + #include + ++/* VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG"); */ ++ + static inline int char_to_int(char c) + { + if ('0' <= c && c <= '9') +@@ -305,6 +307,16 @@ void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const s + vkd3d_string_buffer_printf(&context->messages, "\n"); + } + ++void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, ++ enum vkd3d_shader_error error, const char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ vkd3d_shader_vwarning(context, location, error, format, args); ++ va_end(args); ++} ++ + void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, + enum vkd3d_shader_error error, const char *format, va_list args) + { +@@ -888,6 +900,21 @@ static void vkd3d_shader_scan_combined_sampler_declaration( + &semantic->resource.range, semantic->resource_type, VKD3D_SHADER_RESOURCE_DATA_FLOAT); + } + ++static const struct vkd3d_shader_descriptor_info1 *find_descriptor( ++ const struct vkd3d_shader_scan_descriptor_info1 *info, ++ enum vkd3d_shader_descriptor_type type, unsigned int register_id) ++{ ++ for (unsigned int i = 0; i < info->descriptor_count; ++i) ++ { ++ const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i]; ++ ++ if (d->type == type && d->register_id == register_id) ++ return d; ++ } ++ ++ return NULL; ++} ++ + static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_context *context, + const struct vkd3d_shader_register *resource, const struct vkd3d_shader_register *sampler) + { +@@ -913,7 +940,6 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co + + if (vkd3d_shader_ver_ge(context->version, 5, 1)) + { +- const struct vkd3d_shader_scan_descriptor_info1 *info = context->scan_descriptor_info; + const struct vkd3d_shader_descriptor_info1 *d; + bool dynamic_resource, dynamic_sampler; + +@@ -928,30 +954,13 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co + if (dynamic_resource || dynamic_sampler) + return; + +- for (i = 0; i < info->descriptor_count; ++i) +- { +- d = &info->descriptors[i]; +- if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SRV) +- continue; +- if (d->register_id != resource->idx[0].offset) +- continue; ++ if ((d = find_descriptor(context->scan_descriptor_info, ++ VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource->idx[0].offset))) + resource_space = d->register_space; +- break; +- } + +- if (sampler) +- { +- for (i = 0; i < info->descriptor_count; ++i) +- { +- d = &info->descriptors[i]; +- if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) +- continue; +- if (d->register_id != sampler->idx[0].offset) +- continue; +- sampler_space = d->register_space; +- break; +- } +- } ++ if (sampler && (d = find_descriptor(context->scan_descriptor_info, ++ VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler->idx[0].offset))) ++ sampler_space = d->register_space; + } + + for (i = 0; i < info->combined_sampler_count; ++i) +@@ -1074,6 +1083,9 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte + vkd3d_shader_scan_sampler_declaration(context, instruction); + break; + case VKD3DSIH_DCL: ++ if (instruction->declaration.semantic.resource_type == VKD3D_SHADER_RESOURCE_NONE) ++ break; ++ + if (instruction->declaration.semantic.resource.reg.reg.type == VKD3DSPR_COMBINED_SAMPLER) + { + vkd3d_shader_scan_combined_sampler_declaration(context, &instruction->declaration.semantic); +@@ -1541,16 +1553,15 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, + + scan_info = *compile_info; + +- if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) +- return ret; +- + switch (compile_info->target_type) + { + case VKD3D_SHADER_TARGET_D3D_ASM: +- ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out); ++ ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out, VSIR_ASM_D3D); + break; + + case VKD3D_SHADER_TARGET_GLSL: ++ if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) ++ return ret; + if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->shader_version, + message_context, &parser->location))) + { +@@ -1561,19 +1572,22 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, + + ret = vkd3d_glsl_generator_generate(glsl_generator, parser, out); + vkd3d_glsl_generator_destroy(glsl_generator); ++ vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); + break; + + case VKD3D_SHADER_TARGET_SPIRV_BINARY: + case VKD3D_SHADER_TARGET_SPIRV_TEXT: ++ if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) ++ return ret; + ret = spirv_compile(parser, &scan_descriptor_info, compile_info, out, message_context); ++ vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); + break; + + default: + /* Validation should prevent us from reaching this. */ +- assert(0); ++ vkd3d_unreachable(); + } + +- vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); + return ret; + } + +@@ -1622,14 +1636,10 @@ static int compile_d3d_bytecode(const struct vkd3d_shader_compile_info *compile_ + return ret; + } + +- if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM) +- { +- ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out); +- vkd3d_shader_parser_destroy(parser); +- return ret; +- } ++ ret = vkd3d_shader_parser_compile(parser, compile_info, out, message_context); + +- return VKD3D_ERROR; ++ vkd3d_shader_parser_destroy(parser); ++ return ret; + } + + static int compile_dxbc_dxil(const struct vkd3d_shader_compile_info *compile_info, +@@ -1907,6 +1917,10 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( + + static const enum vkd3d_shader_target_type d3dbc_types[] = + { ++ VKD3D_SHADER_TARGET_SPIRV_BINARY, ++#ifdef HAVE_SPIRV_TOOLS ++ VKD3D_SHADER_TARGET_SPIRV_TEXT, ++#endif + VKD3D_SHADER_TARGET_D3D_ASM, + }; + +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index a93fa7160f7..47b245bd7ee 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -91,11 +91,12 @@ enum vkd3d_shader_error + VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001, + VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING = 2002, + VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED = 2003, +- VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED = 2004, ++ VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE = 2004, + VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY = 2005, + VKD3D_SHADER_ERROR_SPV_INVALID_TYPE = 2006, + VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER = 2007, + VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED = 2008, ++ VKD3D_SHADER_ERROR_SPV_INVALID_SHADER = 2009, + + VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300, + +@@ -196,6 +197,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH = 8306, + VKD3D_SHADER_WARNING_DXIL_INVALID_MASK = 8307, + VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308, ++ VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT = 8309, + + VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, + VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001, +@@ -618,6 +620,11 @@ static inline bool data_type_is_bool(enum vkd3d_data_type data_type) + return data_type == VKD3D_DATA_BOOL; + } + ++static inline bool data_type_is_64_bit(enum vkd3d_data_type data_type) ++{ ++ return data_type == VKD3D_DATA_DOUBLE || data_type == VKD3D_DATA_UINT64; ++} ++ + enum vsir_dimension + { + VSIR_DIMENSION_NONE, +@@ -740,6 +747,7 @@ enum vkd3d_tessellator_domain + #define VKD3DSI_RESINFO_UINT 0x2 + #define VKD3DSI_SAMPLE_INFO_UINT 0x1 + #define VKD3DSI_SAMPLER_COMPARISON_MODE 0x1 ++#define VKD3DSI_SHIFT_UNMASKED 0x1 + + #define VKD3DSI_PRECISE_X 0x100 + #define VKD3DSI_PRECISE_Y 0x200 +@@ -793,10 +801,12 @@ struct vkd3d_shader_version + + struct vkd3d_shader_immediate_constant_buffer + { ++ unsigned int register_idx; + enum vkd3d_data_type data_type; + /* total count is element_count * component_count */ + unsigned int element_count; + unsigned int component_count; ++ bool is_null; + uint32_t data[]; + }; + +@@ -831,10 +841,10 @@ struct vkd3d_shader_register + unsigned int alignment; + union + { +- DWORD immconst_uint[VKD3D_VEC4_SIZE]; +- float immconst_float[VKD3D_VEC4_SIZE]; +- uint64_t immconst_uint64[VKD3D_DVEC2_SIZE]; +- double immconst_double[VKD3D_DVEC2_SIZE]; ++ uint32_t immconst_u32[VKD3D_VEC4_SIZE]; ++ float immconst_f32[VKD3D_VEC4_SIZE]; ++ uint64_t immconst_u64[VKD3D_DVEC2_SIZE]; ++ double immconst_f64[VKD3D_DVEC2_SIZE]; + unsigned fp_body_idx; + } u; + }; +@@ -1311,9 +1321,15 @@ struct vkd3d_string_buffer_cache + size_t count, max_count, capacity; + }; + ++enum vsir_asm_dialect ++{ ++ VSIR_ASM_VSIR, ++ VSIR_ASM_D3D, ++}; ++ + enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions, + const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info, +- struct vkd3d_shader_code *out); ++ struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect); + void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer); + struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list); + void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer); +@@ -1382,6 +1398,8 @@ void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const str + enum vkd3d_shader_error error, const char *format, va_list args); + void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, + enum vkd3d_shader_log_level level, const char *format, va_list args); ++void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, ++ enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(4, 5); + 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); + +@@ -1444,6 +1462,8 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty + return VKD3D_SHADER_COMPONENT_INT; + case VKD3D_DATA_DOUBLE: + return VKD3D_SHADER_COMPONENT_DOUBLE; ++ case VKD3D_DATA_UINT64: ++ return VKD3D_SHADER_COMPONENT_UINT64; + case VKD3D_DATA_BOOL: + return VKD3D_SHADER_COMPONENT_BOOL; + default: +@@ -1505,7 +1525,7 @@ static inline enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum + return vkd3d_siv_from_sysval_indexed(sysval, 0); + } + +-static inline unsigned int vkd3d_write_mask_get_component_idx(DWORD write_mask) ++static inline unsigned int vsir_write_mask_get_component_idx(uint32_t write_mask) + { + unsigned int i; + +@@ -1520,7 +1540,7 @@ static inline unsigned int vkd3d_write_mask_get_component_idx(DWORD write_mask) + return 0; + } + +-static inline unsigned int vkd3d_write_mask_component_count(DWORD write_mask) ++static inline unsigned int vsir_write_mask_component_count(uint32_t write_mask) + { + unsigned int count = vkd3d_popcount(write_mask & VKD3DSP_WRITEMASK_ALL); + assert(1 <= count && count <= VKD3D_VEC4_SIZE); +@@ -1533,32 +1553,30 @@ static inline unsigned int vkd3d_write_mask_from_component_count(unsigned int co + return (VKD3DSP_WRITEMASK_0 << component_count) - 1; + } + +-static inline unsigned int vkd3d_write_mask_64_from_32(DWORD write_mask32) ++static inline uint32_t vsir_write_mask_64_from_32(uint32_t write_mask32) + { +- unsigned int write_mask64 = write_mask32 | (write_mask32 >> 1); ++ uint32_t write_mask64 = write_mask32 | (write_mask32 >> 1); + return (write_mask64 & VKD3DSP_WRITEMASK_0) | ((write_mask64 & VKD3DSP_WRITEMASK_2) >> 1); + } + +-static inline unsigned int vkd3d_write_mask_32_from_64(unsigned int write_mask64) ++static inline uint32_t vsir_write_mask_32_from_64(uint32_t write_mask64) + { +- unsigned int write_mask32 = (write_mask64 | (write_mask64 << 1)) ++ uint32_t write_mask32 = (write_mask64 | (write_mask64 << 1)) + & (VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_2); + return write_mask32 | (write_mask32 << 1); + } + +-static inline unsigned int vkd3d_swizzle_get_component(DWORD swizzle, +- unsigned int idx) ++static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx) + { + return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK; + } + +-static inline unsigned int vkd3d_swizzle_get_component64(DWORD swizzle, +- unsigned int idx) ++static inline unsigned int vsir_swizzle_get_component64(uint32_t swizzle, unsigned int idx) + { + return ((swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx * 2)) & VKD3D_SHADER_SWIZZLE_MASK) / 2u; + } + +-static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned int write_mask) ++static inline unsigned int vkd3d_compact_swizzle(uint32_t swizzle, uint32_t write_mask) + { + unsigned int i, compacted_swizzle = 0; + +@@ -1567,7 +1585,7 @@ static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned + if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) + { + compacted_swizzle <<= VKD3D_SHADER_SWIZZLE_SHIFT(1); +- compacted_swizzle |= vkd3d_swizzle_get_component(swizzle, i); ++ compacted_swizzle |= vsir_swizzle_get_component(swizzle, i); + } + } + +diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c +index 15c8317b191..549f6a45ffb 100644 +--- a/libs/vkd3d/libs/vkd3d/command.c ++++ b/libs/vkd3d/libs/vkd3d/command.c +@@ -2644,6 +2644,8 @@ static bool d3d12_command_list_update_compute_pipeline(struct d3d12_command_list + { + const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; + ++ vkd3d_cond_signal(&list->device->worker_cond); ++ + if (list->current_pipeline != VK_NULL_HANDLE) + return true; + +@@ -2665,6 +2667,8 @@ static bool d3d12_command_list_update_graphics_pipeline(struct d3d12_command_lis + VkRenderPass vk_render_pass; + VkPipeline vk_pipeline; + ++ vkd3d_cond_signal(&list->device->worker_cond); ++ + if (list->current_pipeline != VK_NULL_HANDLE) + return true; + +diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c +index 5c801ca4676..69a46e9188a 100644 +--- a/libs/vkd3d/libs/vkd3d/device.c ++++ b/libs/vkd3d/libs/vkd3d/device.c +@@ -2056,7 +2056,7 @@ static HRESULT d3d12_device_init_pipeline_cache(struct d3d12_device *device) + VkPipelineCacheCreateInfo cache_info; + VkResult vr; + +- vkd3d_mutex_init(&device->mutex); ++ vkd3d_mutex_init(&device->pipeline_cache_mutex); + + cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + cache_info.pNext = NULL; +@@ -2080,7 +2080,7 @@ static void d3d12_device_destroy_pipeline_cache(struct d3d12_device *device) + if (device->vk_pipeline_cache) + VK_CALL(vkDestroyPipelineCache(device->vk_device, device->vk_pipeline_cache, NULL)); + +- vkd3d_mutex_destroy(&device->mutex); ++ vkd3d_mutex_destroy(&device->pipeline_cache_mutex); + } + + #define VKD3D_VA_FALLBACK_BASE 0x8000000000000000ull +@@ -2495,6 +2495,28 @@ static ULONG STDMETHODCALLTYPE d3d12_device_AddRef(ID3D12Device5 *iface) + return refcount; + } + ++static HRESULT device_worker_stop(struct d3d12_device *device) ++{ ++ HRESULT hr; ++ ++ TRACE("device %p.\n", device); ++ ++ vkd3d_mutex_lock(&device->worker_mutex); ++ ++ device->worker_should_exit = true; ++ vkd3d_cond_signal(&device->worker_cond); ++ ++ vkd3d_mutex_unlock(&device->worker_mutex); ++ ++ if (FAILED(hr = vkd3d_join_thread(device->vkd3d_instance, &device->worker_thread))) ++ return hr; ++ ++ vkd3d_mutex_destroy(&device->worker_mutex); ++ vkd3d_cond_destroy(&device->worker_cond); ++ ++ return S_OK; ++} ++ + static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface) + { + struct d3d12_device *device = impl_from_ID3D12Device5(iface); +@@ -2520,6 +2542,9 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface) + d3d12_device_destroy_vkd3d_queues(device); + vkd3d_desc_object_cache_cleanup(&device->view_desc_cache); + vkd3d_desc_object_cache_cleanup(&device->cbuffer_desc_cache); ++ if (device->use_vk_heaps) ++ device_worker_stop(device); ++ vkd3d_free(device->heaps); + VK_CALL(vkDestroyDevice(device->vk_device, NULL)); + if (device->parent) + IUnknown_Release(device->parent); +@@ -4251,6 +4276,40 @@ struct d3d12_device *unsafe_impl_from_ID3D12Device5(ID3D12Device5 *iface) + return impl_from_ID3D12Device5(iface); + } + ++static void *device_worker_main(void *arg) ++{ ++ struct d3d12_descriptor_heap *heap; ++ struct d3d12_device *device = arg; ++ size_t i; ++ ++ vkd3d_set_thread_name("device_worker"); ++ ++ vkd3d_mutex_lock(&device->worker_mutex); ++ ++ while (!device->worker_should_exit) ++ { ++ for (i = 0; i < device->heap_count; ++i) ++ { ++ /* Descriptor updates are not written to Vulkan descriptor sets until a command list ++ * is submitted to a queue, while the client is free to write d3d12 descriptors earlier, ++ * from any thread. This causes a delay right before command list execution, so ++ * handling these updates in a worker thread can speed up execution significantly. */ ++ heap = device->heaps[i]; ++ if (heap->dirty_list_head == UINT_MAX) ++ continue; ++ vkd3d_mutex_lock(&heap->vk_sets_mutex); ++ d3d12_desc_flush_vk_heap_updates_locked(heap, device); ++ vkd3d_mutex_unlock(&heap->vk_sets_mutex); ++ } ++ ++ vkd3d_cond_wait(&device->worker_cond, &device->worker_mutex); ++ } ++ ++ vkd3d_mutex_unlock(&device->worker_mutex); ++ ++ return NULL; ++} ++ + static HRESULT d3d12_device_init(struct d3d12_device *device, + struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info) + { +@@ -4270,6 +4329,14 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, + + device->vk_device = VK_NULL_HANDLE; + ++ device->heaps = NULL; ++ device->heap_capacity = 0; ++ device->heap_count = 0; ++ memset(&device->worker_thread, 0, sizeof(device->worker_thread)); ++ device->worker_should_exit = false; ++ vkd3d_mutex_init(&device->worker_mutex); ++ vkd3d_cond_init(&device->worker_cond); ++ + if (FAILED(hr = vkd3d_create_vk_device(device, create_info))) + goto out_free_instance; + +@@ -4291,6 +4358,13 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, + if (FAILED(hr = vkd3d_vk_descriptor_heap_layouts_init(device))) + goto out_cleanup_uav_clear_state; + ++ if (device->use_vk_heaps && FAILED(hr = vkd3d_create_thread(device->vkd3d_instance, ++ device_worker_main, device, &device->worker_thread))) ++ { ++ WARN("Failed to create worker thread, hr %#x.\n", hr); ++ goto out_cleanup_descriptor_heap_layouts; ++ } ++ + vkd3d_render_pass_cache_init(&device->render_pass_cache); + vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator); + vkd3d_time_domains_init(device); +@@ -4308,6 +4382,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, + + return S_OK; + ++out_cleanup_descriptor_heap_layouts: ++ vkd3d_vk_descriptor_heap_layouts_cleanup(device); + out_cleanup_uav_clear_state: + vkd3d_uav_clear_state_cleanup(&device->uav_clear_state, device); + out_destroy_null_resources: +@@ -4361,6 +4437,40 @@ void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, + device->removed_reason = reason; + } + ++HRESULT d3d12_device_add_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap) ++{ ++ vkd3d_mutex_lock(&device->worker_mutex); ++ ++ if (!vkd3d_array_reserve((void **)&device->heaps, &device->heap_capacity, device->heap_count + 1, ++ sizeof(*device->heaps))) ++ { ++ vkd3d_mutex_unlock(&device->worker_mutex); ++ return E_OUTOFMEMORY; ++ } ++ device->heaps[device->heap_count++] = heap; ++ ++ vkd3d_mutex_unlock(&device->worker_mutex); ++ ++ return S_OK; ++} ++ ++void d3d12_device_remove_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap) ++{ ++ size_t i; ++ ++ vkd3d_mutex_lock(&device->worker_mutex); ++ ++ for (i = 0; i < device->heap_count; ++i) ++ { ++ if (device->heaps[i] == heap) ++ { ++ device->heaps[i] = device->heaps[--device->heap_count]; ++ break; ++ } ++ } ++ ++ vkd3d_mutex_unlock(&device->worker_mutex); ++} + + #ifdef _WIN32 + struct thread_data +diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c +index abbdfbe2015..609c67102a6 100644 +--- a/libs/vkd3d/libs/vkd3d/resource.c ++++ b/libs/vkd3d/libs/vkd3d/resource.c +@@ -2632,20 +2632,18 @@ void d3d12_desc_flush_vk_heap_updates_locked(struct d3d12_descriptor_heap *descr + for (; i != UINT_MAX; i = next) + { + src = &descriptors[i]; +- next = (int)src->next >> 1; ++ next = vkd3d_atomic_exchange(&src->next, 0); ++ next = (int)next >> 1; + ++ /* A race exists here between updating src->next and getting the current object. The best ++ * we can do is get the object last, which may result in a harmless rewrite later. */ + u.object = d3d12_desc_get_object_ref(src, device); + + if (!u.object) +- { +- vkd3d_atomic_exchange(&src->next, 0); + continue; +- } + + writes.held_refs[writes.held_ref_count++] = u.object; + d3d12_desc_write_vk_heap(descriptor_heap, i, &writes, u.object, device); +- +- vkd3d_atomic_exchange(&src->next, 0); + } + + /* Avoid thunk calls wherever possible. */ +@@ -3997,6 +3995,9 @@ static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHea + { + struct d3d12_desc *descriptors = (struct d3d12_desc *)heap->descriptors; + ++ if (heap->use_vk_heaps) ++ d3d12_device_remove_descriptor_heap(device, heap); ++ + for (i = 0; i < heap->desc.NumDescriptors; ++i) + { + d3d12_desc_destroy(&descriptors[i], device); +@@ -4320,6 +4321,12 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device, + dst[i].next = 0; + } + object->dirty_list_head = UINT_MAX; ++ ++ if (object->use_vk_heaps && FAILED(hr = d3d12_device_add_descriptor_heap(device, object))) ++ { ++ vkd3d_free(object); ++ return hr; ++ } + } + else + { +diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c +index fc3187f4bea..1457ddf9c7f 100644 +--- a/libs/vkd3d/libs/vkd3d/state.c ++++ b/libs/vkd3d/libs/vkd3d/state.c +@@ -515,7 +515,7 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat + assert(p->ShaderVisibility <= D3D12_SHADER_VISIBILITY_PIXEL); + push_constants[p->ShaderVisibility].stageFlags = use_vk_heaps ? VK_SHADER_STAGE_ALL + : stage_flags_from_visibility(p->ShaderVisibility); +- push_constants[p->ShaderVisibility].size += p->u.Constants.Num32BitValues * sizeof(uint32_t); ++ push_constants[p->ShaderVisibility].size += align(p->u.Constants.Num32BitValues, 4) * sizeof(uint32_t); + } + if (push_constants[D3D12_SHADER_VISIBILITY_ALL].size) + { +@@ -564,7 +564,7 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat + + idx = push_constant_count == 1 ? 0 : p->ShaderVisibility; + offset = push_constants_offset[idx]; +- push_constants_offset[idx] += p->u.Constants.Num32BitValues * sizeof(uint32_t); ++ push_constants_offset[idx] += align(p->u.Constants.Num32BitValues, 4) * sizeof(uint32_t); + + root_signature->parameters[i].parameter_type = p->ParameterType; + root_constant->stage_flags = push_constant_count == 1 +@@ -1691,7 +1691,7 @@ HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache, + HRESULT hr = S_OK; + unsigned int i; + +- vkd3d_mutex_lock(&device->mutex); ++ vkd3d_mutex_lock(&device->pipeline_cache_mutex); + + for (i = 0; i < cache->render_pass_count; ++i) + { +@@ -1708,7 +1708,7 @@ HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache, + if (!found) + hr = vkd3d_render_pass_cache_create_pass_locked(cache, device, key, vk_render_pass); + +- vkd3d_mutex_unlock(&device->mutex); ++ vkd3d_mutex_unlock(&device->pipeline_cache_mutex); + + return hr; + } +@@ -2129,6 +2129,16 @@ static inline unsigned int typed_uav_compile_option(const struct d3d12_device *d + : VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV_READ_FORMAT_R32; + } + ++static unsigned int feature_flags_compile_option(const struct d3d12_device *device) ++{ ++ unsigned int flags = 0; ++ ++ if (device->feature_options1.Int64ShaderOps) ++ flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64; ++ ++ return flags; ++} ++ + static HRESULT create_shader_stage(struct d3d12_device *device, + struct VkPipelineShaderStageCreateInfo *stage_desc, enum VkShaderStageFlagBits stage, + const D3D12_SHADER_BYTECODE *code, const struct vkd3d_shader_interface_info *shader_interface) +@@ -2145,6 +2155,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device, + {VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_10}, + {VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV, typed_uav_compile_option(device)}, + {VKD3D_SHADER_COMPILE_OPTION_WRITE_TESS_GEOM_POINT_SIZE, 0}, ++ {VKD3D_SHADER_COMPILE_OPTION_FEATURE, feature_flags_compile_option(device)}, + }; + + stage_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; +@@ -3615,7 +3626,7 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12 + + *vk_render_pass = VK_NULL_HANDLE; + +- vkd3d_mutex_lock(&device->mutex); ++ vkd3d_mutex_lock(&device->pipeline_cache_mutex); + + LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry) + { +@@ -3627,7 +3638,7 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12 + } + } + +- vkd3d_mutex_unlock(&device->mutex); ++ vkd3d_mutex_unlock(&device->pipeline_cache_mutex); + + return vk_pipeline; + } +@@ -3646,7 +3657,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta + compiled_pipeline->vk_pipeline = vk_pipeline; + compiled_pipeline->vk_render_pass = vk_render_pass; + +- vkd3d_mutex_lock(&device->mutex); ++ vkd3d_mutex_lock(&device->pipeline_cache_mutex); + + LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry) + { +@@ -3661,7 +3672,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta + if (compiled_pipeline) + list_add_tail(&graphics->compiled_pipelines, &compiled_pipeline->entry); + +- vkd3d_mutex_unlock(&device->mutex); ++ vkd3d_mutex_unlock(&device->pipeline_cache_mutex); + return compiled_pipeline; + } + +diff --git a/libs/vkd3d/libs/vkd3d/utils.c b/libs/vkd3d/libs/vkd3d/utils.c +index 9b28068be51..5ebe1b63e99 100644 +--- a/libs/vkd3d/libs/vkd3d/utils.c ++++ b/libs/vkd3d/libs/vkd3d/utils.c +@@ -539,6 +539,7 @@ bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) + { + static const D3D_FEATURE_LEVEL valid_feature_levels[] = + { ++ D3D_FEATURE_LEVEL_12_2, + D3D_FEATURE_LEVEL_12_1, + D3D_FEATURE_LEVEL_12_0, + D3D_FEATURE_LEVEL_11_1, +@@ -548,6 +549,7 @@ bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1, ++ D3D_FEATURE_LEVEL_1_0_CORE, + }; + unsigned int i; + +diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +index f06f564d6ea..bd7e7290d9e 100644 +--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h ++++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +@@ -1757,9 +1757,23 @@ struct d3d12_device + + struct vkd3d_gpu_va_allocator gpu_va_allocator; + +- struct vkd3d_mutex mutex; + struct vkd3d_desc_object_cache view_desc_cache; + struct vkd3d_desc_object_cache cbuffer_desc_cache; ++ ++ VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT]; ++ unsigned int vk_pool_count; ++ struct vkd3d_vk_descriptor_heap_layout vk_descriptor_heap_layouts[VKD3D_SET_INDEX_COUNT]; ++ bool use_vk_heaps; ++ ++ struct d3d12_descriptor_heap **heaps; ++ size_t heap_capacity; ++ size_t heap_count; ++ union vkd3d_thread_handle worker_thread; ++ struct vkd3d_mutex worker_mutex; ++ struct vkd3d_cond worker_cond; ++ bool worker_should_exit; ++ ++ struct vkd3d_mutex pipeline_cache_mutex; + struct vkd3d_render_pass_cache render_pass_cache; + VkPipelineCache vk_pipeline_cache; + +@@ -1799,11 +1813,6 @@ struct d3d12_device + const struct vkd3d_format_compatibility_list *format_compatibility_lists; + struct vkd3d_null_resources null_resources; + struct vkd3d_uav_clear_state uav_clear_state; +- +- VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT]; +- unsigned int vk_pool_count; +- struct vkd3d_vk_descriptor_heap_layout vk_descriptor_heap_layouts[VKD3D_SET_INDEX_COUNT]; +- bool use_vk_heaps; + }; + + HRESULT d3d12_device_create(struct vkd3d_instance *instance, +@@ -1813,6 +1822,8 @@ bool d3d12_device_is_uma(struct d3d12_device *device, bool *coherent); + void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, + const char *message, ...) VKD3D_PRINTF_FUNC(3, 4); + struct d3d12_device *unsafe_impl_from_ID3D12Device5(ID3D12Device5 *iface); ++HRESULT d3d12_device_add_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap); ++void d3d12_device_remove_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap); + + static inline HRESULT d3d12_device_query_interface(struct d3d12_device *device, REFIID iid, void **object) + { +-- +2.43.0 + diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-45679a966c73669bdb7fa371569dcc34a44.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-45679a966c73669bdb7fa371569dcc34a44.patch deleted file mode 100644 index 56483ae8..00000000 --- a/patches/vkd3d-latest/0001-Updated-vkd3d-to-45679a966c73669bdb7fa371569dcc34a44.patch +++ /dev/null @@ -1,1165 +0,0 @@ -From 4ac1439386bfba7bf93556d32be02ae56643efb5 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Fri, 8 Dec 2023 13:21:19 +1100 -Subject: [PATCH] Updated vkd3d to 45679a966c73669bdb7fa371569dcc34a448d8d4. - ---- - libs/vkd3d/include/private/vkd3d_common.h | 4 +- - libs/vkd3d/libs/vkd3d-common/blob.c | 1 + - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 4 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 423 +++++++++++++++++- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 20 +- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 12 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 5 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 127 ++++-- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 11 + - .../libs/vkd3d-shader/vkd3d_shader_main.c | 45 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 3 + - 11 files changed, 564 insertions(+), 91 deletions(-) - -diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h -index 34fde1a2aa0..e9bff2fbba3 100644 ---- a/libs/vkd3d/include/private/vkd3d_common.h -+++ b/libs/vkd3d/include/private/vkd3d_common.h -@@ -80,7 +80,7 @@ static inline size_t align(size_t addr, size_t alignment) - # ifdef __MINGW_PRINTF_FORMAT - # define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, args))) - # else --# define VKD3D_PRINTF_FUNC(fmt, args) /* __attribute__((format(printf, fmt, args))) */ -+# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args))) - # endif - # define VKD3D_UNUSED __attribute__((unused)) - # define VKD3D_UNREACHABLE __builtin_unreachable() -@@ -107,7 +107,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v) - { - #ifdef _MSC_VER - return __popcnt(v); --#elif defined(__MINGW32__) -+#elif defined(HAVE_BUILTIN_POPCOUNT) - return __builtin_popcount(v); - #else - v -= (v >> 1) & 0x55555555; -diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c -index 71ab9a2c51e..fa2812619ac 100644 ---- a/libs/vkd3d/libs/vkd3d-common/blob.c -+++ b/libs/vkd3d/libs/vkd3d-common/blob.c -@@ -17,6 +17,7 @@ - */ - - #define COBJMACROS -+ - #define CONST_VTABLE - #include "vkd3d.h" - #include "vkd3d_blob.h" -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 3d139416b61..c78ffebac69 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -2253,7 +2253,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b - { - struct hlsl_reg *reg = &jump->condition.node->reg; - -- struct sm1_instruction instr = -+ struct sm1_instruction sm1_instr = - { - .opcode = D3DSIO_TEXKILL, - -@@ -2263,7 +2263,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b - .has_dst = 1, - }; - -- write_sm1_instruction(ctx, buffer, &instr); -+ write_sm1_instruction(ctx, buffer, &sm1_instr); - break; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index beb9ae574dc..a1065c8bc45 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -296,8 +296,28 @@ enum dx_intrinsic_opcode - { - DX_LOAD_INPUT = 4, - DX_STORE_OUTPUT = 5, -+ DX_EXP = 21, -+ DX_FRC = 22, -+ DX_LOG = 23, -+ DX_SQRT = 24, -+ DX_RSQRT = 25, -+ DX_ROUND_NE = 26, -+ DX_ROUND_NI = 27, -+ DX_ROUND_PI = 28, -+ DX_ROUND_Z = 29, -+ DX_BFREV = 30, -+ DX_COUNT_BITS = 31, -+ DX_FIRST_BIT_LO = 32, -+ DX_FIRST_BIT_HI = 33, -+ DX_FIRST_BIT_SHI = 34, - DX_CREATE_HANDLE = 57, - DX_CBUFFER_LOAD_LEGACY = 59, -+ DX_DERIV_COARSEX = 83, -+ DX_DERIV_COARSEY = 84, -+ DX_DERIV_FINEX = 85, -+ DX_DERIV_FINEY = 86, -+ DX_LEGACY_F32TOF16 = 130, -+ DX_LEGACY_F16TOF32 = 131, - }; - - enum dxil_cast_code -@@ -439,6 +459,7 @@ struct dxil_record - { - unsigned int code; - unsigned int operand_count; -+ const struct dxil_record *attachment; - uint64_t operands[]; - }; - -@@ -581,6 +602,7 @@ struct sm6_parser - size_t descriptor_count; - - unsigned int indexable_temp_count; -+ unsigned int icb_count; - - struct sm6_value *values; - size_t value_count; -@@ -796,6 +818,7 @@ static enum vkd3d_result sm6_parser_read_unabbrev_record(struct sm6_parser *sm6) - - record->code = code; - record->operand_count = count; -+ record->attachment = NULL; - - for (i = 0; i < count; ++i) - record->operands[i] = sm6_parser_read_vbr(sm6, 6); -@@ -1012,6 +1035,7 @@ static enum vkd3d_result sm6_parser_read_abbrev_record(struct sm6_parser *sm6, u - if (!abbrev->operands[i + 1].read_operand(sm6, abbrev->operands[i + 1].context, &record->operands[i])) - goto fail; - record->operand_count = count; -+ record->attachment = NULL; - - /* An array can occur only as the last operand. */ - if (abbrev->is_array) -@@ -1572,6 +1596,11 @@ static bool sm6_type_is_bool_i16_i32_i64(const struct sm6_type *type) - return type->class == TYPE_CLASS_INTEGER && (type->u.width == 1 || type->u.width >= 16); - } - -+static bool sm6_type_is_i16_i32_i64(const struct sm6_type *type) -+{ -+ return type->class == TYPE_CLASS_INTEGER && type->u.width >= 16; -+} -+ - static bool sm6_type_is_bool(const struct sm6_type *type) - { - return type->class == TYPE_CLASS_INTEGER && type->u.width == 1; -@@ -1587,6 +1616,16 @@ static inline bool sm6_type_is_i32(const struct sm6_type *type) - return type->class == TYPE_CLASS_INTEGER && type->u.width == 32; - } - -+static bool sm6_type_is_float(const struct sm6_type *type) -+{ -+ return type->class == TYPE_CLASS_FLOAT && type->u.width == 32; -+} -+ -+static bool sm6_type_is_f16_f32(const struct sm6_type *type) -+{ -+ return type->class == TYPE_CLASS_FLOAT && (type->u.width == 16 || type->u.width == 32); -+} -+ - static inline bool sm6_type_is_floating_point(const struct sm6_type *type) - { - return type->class == TYPE_CLASS_FLOAT; -@@ -2412,7 +2451,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - return VKD3D_ERROR_INVALID_SHADER; - } - size = max(size, sizeof(icb->data[0])); -- count = type->u.array.count * size / sizeof(icb->data[0]); -+ count = operands ? type->u.array.count * size / sizeof(icb->data[0]) : 0; - - if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[count])))) - { -@@ -2433,9 +2472,14 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - dst->value_type = VALUE_TYPE_ICB; - dst->u.icb = icb; - -+ icb->register_idx = sm6->icb_count++; - icb->data_type = vkd3d_data_type_from_sm6_type(elem_type); - icb->element_count = type->u.array.count; - icb->component_count = 1; -+ icb->is_null = !operands; -+ -+ if (!operands) -+ return VKD3D_OK; - - count = type->u.array.count; - if (size > sizeof(icb->data[0])) -@@ -2510,12 +2554,10 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - switch (record->code) - { - case CST_CODE_NULL: -- if (sm6_type_is_array(type)) -+ if (sm6_type_is_array(type) -+ && (ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) - { -- FIXME("Constant null arrays are not supported.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -- "Constant null arrays are not supported."); -- return VKD3D_ERROR_INVALID_SHADER; -+ return ret; - } - /* For non-aggregates, register constant data is already zero-filled. */ - break; -@@ -2588,6 +2630,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - break; - } - -+ if (record->attachment) -+ { -+ WARN("Ignoring metadata attachment.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring a metadata attachment for a constant."); -+ } -+ - ++sm6->value_count; - } - -@@ -2626,6 +2675,18 @@ static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_pa - return ins; - } - -+static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type *elem_type, unsigned int count, -+ unsigned int alignment, unsigned int init, struct sm6_value *dst) -+{ -+ enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); -+ struct vkd3d_shader_instruction *ins; -+ -+ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER); -+ /* The icb value index will be resolved later so forward references can be handled. */ -+ ins->declaration.icb = (void *)(intptr_t)init; -+ register_init_with_id(&dst->u.reg, VKD3DSPR_IMMCONSTBUFFER, data_type, init); -+} -+ - static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, - unsigned int count, unsigned int alignment, unsigned int init, struct sm6_value *dst) - { -@@ -2762,7 +2823,10 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ - - if (address_space == ADDRESS_SPACE_DEFAULT) - { -- sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst); -+ if (is_constant) -+ sm6_parser_declare_icb(sm6, scalar_type, count, alignment, init, dst); -+ else -+ sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst); - } - else if (address_space == ADDRESS_SPACE_GROUPSHARED) - { -@@ -2806,11 +2870,11 @@ static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_init - static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) - { - const struct dxil_block *block = &sm6->root_block; -+ size_t i, base_value_idx = sm6->value_count; - struct vkd3d_shader_instruction *ins; - const struct dxil_record *record; - enum vkd3d_result ret; - uint64_t version; -- size_t i; - - sm6->p.location.line = block->id; - sm6->p.location.column = 0; -@@ -2868,6 +2932,21 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) - ins->declaration.indexable_temp.initialiser = resolve_forward_initialiser( - (uintptr_t)ins->declaration.indexable_temp.initialiser, sm6); - } -+ else if (ins->handler_idx == VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER) -+ { -+ ins->declaration.icb = resolve_forward_initialiser((uintptr_t)ins->declaration.icb, sm6); -+ } -+ } -+ for (i = base_value_idx; i < sm6->value_count; ++i) -+ { -+ const struct vkd3d_shader_immediate_constant_buffer *icb; -+ struct sm6_value *value = &sm6->values[i]; -+ -+ if (!sm6_value_is_register(value) || value->u.reg.type != VKD3DSPR_IMMCONSTBUFFER) -+ continue; -+ -+ if ((icb = resolve_forward_initialiser(value->u.reg.idx[0].offset, sm6))) -+ value->u.reg.idx[0].offset = icb->register_idx; - } - - return VKD3D_OK; -@@ -3171,6 +3250,67 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - } - } - -+static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) -+{ -+ switch (op) -+ { -+ case DX_EXP: -+ return VKD3DSIH_EXP; -+ case DX_FRC: -+ return VKD3DSIH_FRC; -+ case DX_LOG: -+ return VKD3DSIH_LOG; -+ case DX_SQRT: -+ return VKD3DSIH_SQRT; -+ case DX_RSQRT: -+ return VKD3DSIH_RSQ; -+ case DX_ROUND_NE: -+ return VKD3DSIH_ROUND_NE; -+ case DX_ROUND_NI: -+ return VKD3DSIH_ROUND_NI; -+ case DX_ROUND_PI: -+ return VKD3DSIH_ROUND_PI; -+ case DX_ROUND_Z: -+ return VKD3DSIH_ROUND_Z; -+ case DX_BFREV: -+ return VKD3DSIH_BFREV; -+ case DX_COUNT_BITS: -+ return VKD3DSIH_COUNTBITS; -+ case DX_FIRST_BIT_LO: -+ return VKD3DSIH_FIRSTBIT_LO; -+ case DX_FIRST_BIT_HI: -+ return VKD3DSIH_FIRSTBIT_HI; -+ case DX_FIRST_BIT_SHI: -+ return VKD3DSIH_FIRSTBIT_SHI; -+ case DX_DERIV_COARSEX: -+ return VKD3DSIH_DSX_COARSE; -+ case DX_DERIV_COARSEY: -+ return VKD3DSIH_DSY_COARSE; -+ case DX_DERIV_FINEX: -+ return VKD3DSIH_DSX_FINE; -+ case DX_DERIV_FINEY: -+ return VKD3DSIH_DSY_FINE; -+ case DX_LEGACY_F32TOF16: -+ return VKD3DSIH_F32TOF16; -+ case DX_LEGACY_F16TOF32: -+ return VKD3DSIH_F16TOF32; -+ default: -+ vkd3d_unreachable(); -+ } -+} -+ -+static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, struct sm6_block *code_block, -+ enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) -+{ -+ struct vkd3d_shader_src_param *src_param; -+ -+ vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); -+ src_param = instruction_src_params_alloc(ins, 1, sm6); -+ src_param_init_from_value(src_param, operands[0]); -+ -+ instruction_dst_param_init_ssa_scalar(ins, sm6); -+} -+ - static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, struct sm6_block *code_block, - enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) - { -@@ -3344,7 +3484,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, struct sm6_b - - struct sm6_dx_opcode_info - { -- const char ret_type; -+ const char *ret_type; - const char *operand_info; - void (*handler)(struct sm6_parser *, struct sm6_block *, enum dx_intrinsic_opcode, - const struct sm6_value **, struct vkd3d_shader_instruction *); -@@ -3355,16 +3495,40 @@ struct sm6_dx_opcode_info - b -> constant int1 - c -> constant int8/16/32 - i -> int32 -+ m -> int16/32/64 -+ f -> float -+ e -> half/float -+ g -> half/float/double - H -> handle - v -> void - o -> overloaded - */ - static const struct sm6_dx_opcode_info sm6_dx_op_table[] = - { -- [DX_CBUFFER_LOAD_LEGACY ] = {'o', "Hi", sm6_parser_emit_dx_cbuffer_load}, -- [DX_CREATE_HANDLE ] = {'H', "ccib", sm6_parser_emit_dx_create_handle}, -- [DX_LOAD_INPUT ] = {'o', "ii8i", sm6_parser_emit_dx_load_input}, -- [DX_STORE_OUTPUT ] = {'v', "ii8o", sm6_parser_emit_dx_store_output}, -+ [DX_BFREV ] = {"m0", "m", sm6_parser_emit_dx_unary}, -+ [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, -+ [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, -+ [DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle}, -+ [DX_DERIV_COARSEX ] = {"e0", "e", sm6_parser_emit_dx_unary}, -+ [DX_DERIV_COARSEY ] = {"e0", "e", sm6_parser_emit_dx_unary}, -+ [DX_DERIV_FINEX ] = {"e0", "e", sm6_parser_emit_dx_unary}, -+ [DX_DERIV_FINEY ] = {"e0", "e", sm6_parser_emit_dx_unary}, -+ [DX_EXP ] = {"g0", "g", sm6_parser_emit_dx_unary}, -+ [DX_FIRST_BIT_HI ] = {"i", "m", sm6_parser_emit_dx_unary}, -+ [DX_FIRST_BIT_LO ] = {"i", "m", sm6_parser_emit_dx_unary}, -+ [DX_FIRST_BIT_SHI ] = {"i", "m", sm6_parser_emit_dx_unary}, -+ [DX_FRC ] = {"g0", "g", sm6_parser_emit_dx_unary}, -+ [DX_LEGACY_F16TOF32 ] = {"f", "i", sm6_parser_emit_dx_unary}, -+ [DX_LEGACY_F32TOF16 ] = {"i", "f", sm6_parser_emit_dx_unary}, -+ [DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input}, -+ [DX_LOG ] = {"g0", "g", sm6_parser_emit_dx_unary}, -+ [DX_ROUND_NE ] = {"g0", "g", sm6_parser_emit_dx_unary}, -+ [DX_ROUND_NI ] = {"g0", "g", sm6_parser_emit_dx_unary}, -+ [DX_ROUND_PI ] = {"g0", "g", sm6_parser_emit_dx_unary}, -+ [DX_ROUND_Z ] = {"g0", "g", sm6_parser_emit_dx_unary}, -+ [DX_RSQRT ] = {"g0", "g", sm6_parser_emit_dx_unary}, -+ [DX_SQRT ] = {"g0", "g", sm6_parser_emit_dx_unary}, -+ [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, - }; - - static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type, -@@ -3389,6 +3553,14 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc - && type->u.width <= 32; - case 'i': - return sm6_type_is_i32(type); -+ case 'm': -+ return sm6_type_is_i16_i32_i64(type); -+ case 'f': -+ return sm6_type_is_float(type); -+ case 'e': -+ return sm6_type_is_f16_f32(type); -+ case 'g': -+ return sm6_type_is_floating_point(type); - case 'H': - return (is_return || sm6_value_is_handle(value)) && type == sm6->handle_type; - case 'v': -@@ -3402,6 +3574,17 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc - } - } - -+static bool operand_types_match(struct sm6_value *dst, const struct sm6_value **operands, unsigned int operand_count, -+ char index_char) -+{ -+ unsigned int i = index_char - '0'; -+ -+ assert(i < 10); -+ if (i >= operand_count) -+ return false; -+ return dst->type == operands[i]->type; -+} -+ - static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const char *name, - const struct sm6_value **operands, unsigned int operand_count, struct sm6_value *dst) - { -@@ -3410,7 +3593,9 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ - - info = &sm6_dx_op_table[op]; - -- if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type, true)) -+ assert(info->ret_type[0]); -+ if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type[0], true) -+ || (info->ret_type[1] && !operand_types_match(dst, operands, operand_count, info->ret_type[1]))) - { - WARN("Failed to validate return type for dx intrinsic id %u, '%s'.\n", op, name); - /* Return type validation failure is not so critical. We only need to set -@@ -3700,6 +3885,9 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor - if (handler_idx == VKD3DSIH_NOP) - { - dst->u.reg = value->u.reg; -+ /* Set the result type for casts from 16-bit min precision. */ -+ if (type->u.width != 16) -+ dst->u.reg.data_type = vkd3d_data_type_from_sm6_type(type); - return; - } - -@@ -4153,6 +4341,208 @@ static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, - return true; - } - -+static void sm6_parser_metadata_attachment_block_init(struct sm6_parser *sm6, const struct dxil_block *target_block, -+ const struct dxil_block *block) -+{ -+ struct dxil_record *target_record; -+ const struct dxil_record *record; -+ unsigned int i; -+ uint64_t index; -+ -+ for (i = 0; i < block->record_count; ++i) -+ { -+ record = block->records[i]; -+ if (record->code != METADATA_ATTACHMENT) -+ { -+ WARN("Ignoring record with code %u.\n", record->code); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring a metadata attachment record with code %u.", record->code); -+ continue; -+ } -+ if (!(record->operand_count & 1)) -+ { -+ WARN("Ignoring function attachment.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring a metadata function attachment."); -+ continue; -+ } -+ -+ index = record->operands[0]; -+ if (!target_block->record_count || index >= target_block->record_count - 1) -+ { -+ WARN("Invalid record index %"PRIu64".\n", index); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Invalid record index %"PRIu64" for a metadata attachment.", index); -+ continue; -+ } -+ /* 'index' is an instruction index, but records[0] is DECLAREBLOCKS, not an instruction. */ -+ target_record = target_block->records[index + 1]; -+ if (target_record->attachment) -+ { -+ WARN("Overwriting record attachment.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "The target record for a metadata attachment already has an attachment."); -+ } -+ target_record->attachment = record; -+ } -+} -+ -+static void sm6_parser_metadata_attachments_init(struct sm6_parser *sm6, const struct dxil_block *block) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < block->child_block_count; ++i) -+ { -+ if (block->child_blocks[i]->id == METADATA_ATTACHMENT_BLOCK) -+ sm6_parser_metadata_attachment_block_init(sm6, block, block->child_blocks[i]); -+ } -+} -+ -+static const struct sm6_metadata_value *sm6_parser_find_metadata_kind(const struct sm6_parser *sm6, uint64_t id) -+{ -+ unsigned int i, j; -+ -+ for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) -+ { -+ for (j = 0; j < sm6->metadata_tables[i].count; ++j) -+ { -+ if (sm6->metadata_tables[i].values[j].type == VKD3D_METADATA_KIND -+ && sm6->metadata_tables[i].values[j].u.kind.id == id) -+ return &sm6->metadata_tables[i].values[j]; -+ } -+ } -+ -+ return NULL; -+} -+ -+static const struct sm6_metadata_value *sm6_parser_metadata_get_value(const struct sm6_parser *sm6, uint64_t index) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) -+ { -+ if (sm6->metadata_tables[i].count > index) -+ break; -+ index -= sm6->metadata_tables[i].count; -+ } -+ -+ return (index < sm6->metadata_tables[i].count) ? &sm6->metadata_tables[i].values[index] : NULL; -+} -+ -+static bool metadata_node_get_unary_uint(const struct sm6_metadata_node *node, unsigned int *operand, -+ struct sm6_parser *sm6) -+{ -+ if (node->operand_count != 1) -+ { -+ FIXME("Ignoring node with %u operands.\n", node->operand_count); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring metadata attachment node with %u operands; expected unary.", node->operand_count); -+ return false; -+ } -+ if (!sm6_metadata_value_is_value(node->operands[0]) -+ || !sm6_metadata_get_uint_value(sm6, node->operands[0], operand)) -+ { -+ WARN("Failed to get operand value.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Failed to get a metadata attachment operand value; ignoring the attachment."); -+ return false; -+ } -+ -+ return true; -+} -+ -+static void metadata_attachment_record_apply(const struct dxil_record *record, enum bitcode_function_code func_code, -+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst, struct sm6_parser *sm6) -+{ -+ static const char *ignored_names[] = -+ { -+ "alias.scope", -+ "dx.controlflow.hints", -+ "llvm.loop", -+ "noalias", -+ "tbaa", -+ "range", -+ }; -+ const struct sm6_metadata_node *node; -+ const struct sm6_metadata_value *m; -+ unsigned int i, j, operand; -+ bool ignored = false; -+ const char *name; -+ -+ if (record->attachment) -+ { -+ WARN("Ignoring nested metadata attachment.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring a nested metadata attachment."); -+ } -+ -+ assert(record->operand_count & 1); -+ for (i = 1; i < record->operand_count; i += 2) -+ { -+ if (!(m = sm6_parser_find_metadata_kind(sm6, record->operands[i]))) -+ { -+ WARN("Failed to find metadata kind %"PRIx64".\n", record->operands[i]); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Failed to find metadata kind %"PRIx64" for an attachment.", record->operands[i]); -+ continue; -+ } -+ name = m->u.kind.name; -+ -+ m = sm6_parser_metadata_get_value(sm6, record->operands[i + 1]); -+ if (!m || !sm6_metadata_value_is_node(m)) -+ { -+ WARN("Failed to retrieve metadata attachment node.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Failed to retrieve a metadata attachment node."); -+ continue; -+ } -+ node = m->u.node; -+ -+ if (!strcmp(name, "dx.precise")) -+ { -+ if (!sm6_value_is_register(dst)) -+ { -+ WARN("Precise value is not a register.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "A value marked as precise is not a register."); -+ } -+ else if (metadata_node_get_unary_uint(node, &operand, sm6) && operand) -+ { -+ ins->flags |= sm6_type_is_scalar(dst->type) ? VKD3DSI_PRECISE_X : VKD3DSI_PRECISE_XYZW; -+ } -+ } -+ else if (!strcmp(name, "dx.nonuniform")) -+ { -+ if (!sm6_value_is_register(dst)) -+ { -+ WARN("Non-uniform value is not a register.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "A value marked as non-uniform is not a register."); -+ } -+ else if (metadata_node_get_unary_uint(node, &operand, sm6)) -+ { -+ dst->u.reg.non_uniform = !!operand; -+ } -+ } -+ else -+ { -+ for (j = 0; j < ARRAY_SIZE(ignored_names); ++j) -+ if (!strcmp(name, ignored_names[j])) -+ break; -+ if (j == ARRAY_SIZE(ignored_names)) -+ { -+ WARN("Ignoring metadata attachment '%s'.\n", name); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring a metadata attachment named '%s'.", name); -+ } -+ ignored = true; -+ } -+ -+ if (func_code != FUNC_CODE_INST_CALL && !ignored) -+ WARN("Metadata attachment target is not a function call.\n"); -+ } -+} -+ - static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, - struct sm6_function *function) - { -@@ -4278,6 +4668,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - return VKD3D_ERROR; - assert(ins->handler_idx != VKD3DSIH_INVALID); - -+ if (record->attachment) -+ metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); -+ - if (is_terminator) - { - ++block_idx; -@@ -4331,6 +4724,8 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st - sm6->p.location.line = block->id; - sm6->p.location.column = 0; - -+ sm6_parser_metadata_attachments_init(sm6, block); -+ - switch (block->id) - { - case CONSTANTS_BLOCK: -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 0dde4c18587..ed053f16312 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -487,27 +487,27 @@ static void resolve_loop_continue(struct hlsl_ctx *ctx, struct hlsl_block *block - else if (instr->type == HLSL_IR_JUMP) - { - struct hlsl_ir_jump *jump = hlsl_ir_jump(instr); -- struct hlsl_block block; -+ struct hlsl_block cond_block; - - if (jump->type != HLSL_IR_JUMP_UNRESOLVED_CONTINUE) - continue; - - if (type == LOOP_DO_WHILE) - { -- if (!hlsl_clone_block(ctx, &block, cond)) -+ if (!hlsl_clone_block(ctx, &cond_block, cond)) - return; -- if (!append_conditional_break(ctx, &block)) -+ if (!append_conditional_break(ctx, &cond_block)) - { -- hlsl_block_cleanup(&block); -+ hlsl_block_cleanup(&cond_block); - return; - } -- list_move_before(&instr->entry, &block.instrs); -+ list_move_before(&instr->entry, &cond_block.instrs); - } - else if (type == LOOP_FOR) - { -- if (!hlsl_clone_block(ctx, &block, iter)) -+ if (!hlsl_clone_block(ctx, &cond_block, iter)) - return; -- list_move_before(&instr->entry, &block.instrs); -+ list_move_before(&instr->entry, &cond_block.instrs); - } - jump->type = HLSL_IR_JUMP_CONTINUE; - } -@@ -3553,7 +3553,7 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * - { - struct hlsl_resource_load_params load_params = { 0 }; - const struct hlsl_type *sampler_type; -- struct hlsl_ir_node *coords, *load; -+ struct hlsl_ir_node *coords, *sample; - - if (params->args_count != 2 && params->args_count != 4) - { -@@ -3688,9 +3688,9 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * - load_params.format = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4); - load_params.sampling_dim = dim; - -- if (!(load = hlsl_new_resource_load(ctx, &load_params, loc))) -+ if (!(sample = hlsl_new_resource_load(ctx, &load_params, loc))) - return false; -- hlsl_block_add_instr(params->instrs, load); -+ hlsl_block_add_instr(params->instrs, sample); - return true; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 4a622185741..88cbef61d5f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -1090,7 +1090,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, - unsigned int dim_count = hlsl_sampler_dim_count(val->data_type->sampler_dim); - struct hlsl_ir_node *coords = index->idx.node; - struct hlsl_resource_load_params params = {0}; -- struct hlsl_ir_node *load; -+ struct hlsl_ir_node *resource_load; - - assert(coords->data_type->class == HLSL_CLASS_VECTOR); - assert(coords->data_type->base_type == HLSL_TYPE_UINT); -@@ -1104,9 +1104,9 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, - params.coords = coords; - params.format = val->data_type->e.resource_format; - -- if (!(load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) -+ if (!(resource_load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) - return false; -- hlsl_block_add_instr(block, load); -+ hlsl_block_add_instr(block, resource_load); - return true; - } - -@@ -2301,7 +2301,6 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in - struct hlsl_ir_switch_case *c, *def = NULL; - bool missing_terminal_break = false; - struct hlsl_ir_node *node; -- struct hlsl_ir_jump *jump; - struct hlsl_ir_switch *s; - - if (instr->type != HLSL_IR_SWITCH) -@@ -2320,10 +2319,7 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in - { - node = LIST_ENTRY(list_tail(&c->body.instrs), struct hlsl_ir_node, entry); - if (node->type == HLSL_IR_JUMP) -- { -- jump = hlsl_ir_jump(node); -- terminal_break = jump->type == HLSL_IR_JUMP_BREAK; -- } -+ terminal_break = (hlsl_ir_jump(node)->type == HLSL_IR_JUMP_BREAK); - } - - missing_terminal_break |= !terminal_break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 710811c6761..a35ef862096 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -463,6 +463,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i - struct vkd3d_shader_instruction_array *instructions; - struct control_point_normaliser normaliser; - unsigned int input_control_point_count; -+ struct vkd3d_shader_location location; - struct vkd3d_shader_instruction *ins; - enum vkd3d_result ret; - unsigned int i, j; -@@ -513,8 +514,10 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i - return VKD3D_OK; - case VKD3DSIH_HS_FORK_PHASE: - case VKD3DSIH_HS_JOIN_PHASE: -+ /* ins may be relocated if the instruction array expands. */ -+ location = ins->location; - ret = control_point_normaliser_emit_hs_input(&normaliser, input_signature, -- input_control_point_count, i, &ins->location); -+ input_control_point_count, i, &location); - *src_instructions = normaliser.instructions; - return ret; - default: -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index c8a43adbe03..a22c59577ac 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -1194,6 +1194,16 @@ static uint32_t vkd3d_spirv_get_op_constant64(struct vkd3d_spirv_builder *builde - (const uint32_t *)&value, 2, vkd3d_spirv_build_op_constant64); - } - -+static uint32_t vkd3d_spirv_build_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) -+{ -+ return vkd3d_spirv_build_op_tr(builder, &builder->global_stream, SpvOpConstantNull, result_type); -+} -+ -+static uint32_t vkd3d_spirv_get_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) -+{ -+ return vkd3d_spirv_build_once1(builder, SpvOpConstantNull, result_type, vkd3d_spirv_build_op_constant_null); -+} -+ - static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_builder *builder, - uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) - { -@@ -2152,6 +2162,7 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol, - break; - - case VKD3DSPR_IMMCONSTBUFFER: -+ symbol->key.reg.idx = reg->idx_count > 1 ? reg->idx[0].offset : 0; - break; - - default: -@@ -3498,7 +3509,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp - } - else if (reg->type == VKD3DSPR_IMMCONSTBUFFER) - { -- indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[0]); -+ indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[reg->idx_count - 1]); - } - else if (reg->type == VKD3DSPR_IDXTEMP) - { -@@ -3756,6 +3767,69 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, - return val_id; - } - -+static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compiler, -+ const struct vkd3d_shader_immediate_constant_buffer *icb, uint32_t *type_id_out) -+{ -+ uint32_t *elements, elem_type_id, length_id, type_id, const_id; -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ enum vkd3d_shader_component_type component_type; -+ unsigned int i, element_count, component_count; -+ -+ element_count = icb->element_count; -+ -+ component_type = vkd3d_component_type_from_data_type(icb->data_type); -+ component_count = icb->component_count; -+ elem_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, icb->data_type, component_count); -+ length_id = spirv_compiler_get_constant_uint(compiler, element_count); -+ type_id = vkd3d_spirv_get_op_type_array(builder, elem_type_id, length_id); -+ -+ if (type_id_out) -+ *type_id_out = type_id; -+ -+ if (icb->is_null) -+ { -+ /* All values are null. Workgroup memory initialisers require OpConstantNull. */ -+ return vkd3d_spirv_get_op_constant_null(builder, type_id); -+ } -+ -+ if (!(elements = vkd3d_calloc(element_count, sizeof(*elements)))) -+ { -+ ERR("Failed to allocate %u elements.", element_count); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY, -+ "Failed to allocate %u constant array elements.", element_count); -+ return 0; -+ } -+ -+ switch (icb->data_type) -+ { -+ case VKD3D_DATA_FLOAT: -+ case VKD3D_DATA_INT: -+ case VKD3D_DATA_UINT: -+ for (i = 0; i < element_count; ++i) -+ elements[i] = spirv_compiler_get_constant(compiler, component_type, component_count, -+ &icb->data[component_count * i]); -+ break; -+ case VKD3D_DATA_DOUBLE: -+ case VKD3D_DATA_UINT64: -+ { -+ uint64_t *data = (uint64_t *)icb->data; -+ for (i = 0; i < element_count; ++i) -+ elements[i] = spirv_compiler_get_constant64(compiler, component_type, component_count, -+ &data[component_count * i]); -+ break; -+ } -+ default: -+ FIXME("Unhandled data type %u.\n", icb->data_type); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, -+ "Immediate constant buffer data type %u is unhandled.", icb->data_type); -+ break; -+ } -+ -+ const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, element_count); -+ vkd3d_free(elements); -+ return const_id; -+} -+ - static const struct ssa_register_info *spirv_compiler_get_ssa_register_info(const struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg) - { -@@ -5493,39 +5567,40 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil - { - const struct vkd3d_shader_indexable_temp *temp = &instruction->declaration.indexable_temp; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ uint32_t id, type_id, length_id, ptr_type_id, init_id = 0; -+ enum vkd3d_shader_component_type component_type; - struct vkd3d_shader_register reg; - struct vkd3d_symbol reg_symbol; -+ SpvStorageClass storage_class; - size_t function_location; -- uint32_t id; - -- if (temp->component_count != 4) -- FIXME("Unhandled component count %u.\n", temp->component_count); -+ storage_class = SpvStorageClassFunction; - - vsir_register_init(®, VKD3DSPR_IDXTEMP, VKD3D_DATA_FLOAT, 1); - reg.idx[0].offset = temp->register_idx; - - if (temp->alignment) - WARN("Ignoring alignment %u.\n", temp->alignment); -- if (temp->initialiser) -- { -- FIXME("Initialisers are not supported.\n"); -- spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, -- "Initialisers for indexable temps are not supported."); -- } - - function_location = spirv_compiler_get_current_function_location(compiler); - vkd3d_spirv_begin_function_stream_insertion(builder, function_location); - -- id = spirv_compiler_emit_array_variable(compiler, &builder->function_stream, -- SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &temp->register_size, 1); -+ component_type = vkd3d_component_type_from_data_type(temp->data_type); -+ type_id = vkd3d_spirv_get_type_id(builder, component_type, temp->component_count); -+ length_id = spirv_compiler_get_constant_uint(compiler, temp->register_size); -+ type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); -+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); -+ if (temp->initialiser) -+ init_id = spirv_compiler_emit_constant_array(compiler, temp->initialiser, NULL); -+ id = vkd3d_spirv_build_op_variable(builder, &builder->function_stream, ptr_type_id, storage_class, init_id); - - spirv_compiler_emit_register_debug_name(builder, id, ®); - - vkd3d_spirv_end_function_stream_insertion(builder); - - vkd3d_symbol_make_register(®_symbol, ®); -- vkd3d_symbol_set_register_info(®_symbol, id, -- SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); -+ vkd3d_symbol_set_register_info(®_symbol, id, storage_class, -+ component_type, vkd3d_write_mask_from_component_count(temp->component_count)); - spirv_compiler_put_symbol(compiler, ®_symbol); - } - -@@ -5743,34 +5818,24 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi - const struct vkd3d_shader_instruction *instruction) - { - const struct vkd3d_shader_immediate_constant_buffer *icb = instruction->declaration.icb; -- uint32_t *elements, length_id, type_id, const_id, ptr_type_id, icb_id; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ uint32_t type_id, const_id, ptr_type_id, icb_id; - struct vkd3d_shader_register reg; - struct vkd3d_symbol reg_symbol; -- unsigned int i; - -- assert(icb->data_type == VKD3D_DATA_FLOAT); -- assert(icb->component_count == VKD3D_VEC4_SIZE); -- -- if (!(elements = vkd3d_calloc(icb->element_count, sizeof(*elements)))) -- return; -- for (i = 0; i < icb->element_count; ++i) -- elements[i] = spirv_compiler_get_constant(compiler, -- VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &icb->data[4 * i]); -- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); -- length_id = spirv_compiler_get_constant_uint(compiler, icb->element_count); -- type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); -- const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, icb->element_count); -+ const_id = spirv_compiler_emit_constant_array(compiler, icb, &type_id); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id); - icb_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, - ptr_type_id, SpvStorageClassPrivate, const_id); - vkd3d_spirv_build_op_name(builder, icb_id, "icb"); -- vkd3d_free(elements); - -- vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 0); -+ /* Set an index count of 2 so vkd3d_symbol_make_register() uses idx[0] as a buffer id. */ -+ vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 2); -+ reg.idx[0].offset = icb->register_idx; - vkd3d_symbol_make_register(®_symbol, ®); - vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate, -- VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); -+ vkd3d_component_type_from_data_type(icb->data_type), -+ vkd3d_write_mask_from_component_count(icb->component_count)); - spirv_compiler_put_symbol(compiler, ®_symbol); - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 80f8ab98c08..163cd90ee13 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -792,9 +792,11 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui - ins->handler_idx = VKD3DSIH_INVALID; - return; - } -+ icb->register_idx = 0; - icb->data_type = VKD3D_DATA_FLOAT; - icb->component_count = VKD3D_VEC4_SIZE; - icb->element_count = icb_size / VKD3D_VEC4_SIZE; -+ icb->is_null = false; - memcpy(icb->data, tokens, sizeof(*tokens) * icb_size); - shader_instruction_array_add_icb(&priv->p.instructions, icb); - ins->declaration.icb = icb; -@@ -1930,6 +1932,15 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - break; - } - } -+ else if (register_type == VKD3D_SM4_RT_IMMCONSTBUFFER) -+ { -+ if (param->idx_count != 1) -+ { -+ WARN("Unexpected idx count %u.\n", param->idx_count); -+ vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_INDEX_COUNT, -+ "Invalid index count %u for immediate const buffer register; expected count 1.", param->idx_count); -+ } -+ } - else if (!shader_is_sm_5_1(priv) && vsir_register_is_descriptor(param)) - { - /* SM5.1 places a symbol identifier in idx[0] and moves -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index 8fd8945151f..d4a9d391477 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -23,6 +23,8 @@ - #include - #include - -+/* VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG"); */ -+ - static inline int char_to_int(char c) - { - if ('0' <= c && c <= '9') -@@ -888,6 +890,21 @@ static void vkd3d_shader_scan_combined_sampler_declaration( - &semantic->resource.range, semantic->resource_type, VKD3D_SHADER_RESOURCE_DATA_FLOAT); - } - -+static const struct vkd3d_shader_descriptor_info1 *find_descriptor( -+ const struct vkd3d_shader_scan_descriptor_info1 *info, -+ enum vkd3d_shader_descriptor_type type, unsigned int register_id) -+{ -+ for (unsigned int i = 0; i < info->descriptor_count; ++i) -+ { -+ const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i]; -+ -+ if (d->type == type && d->register_id == register_id) -+ return d; -+ } -+ -+ return NULL; -+} -+ - static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_context *context, - const struct vkd3d_shader_register *resource, const struct vkd3d_shader_register *sampler) - { -@@ -913,7 +930,6 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co - - if (vkd3d_shader_ver_ge(context->version, 5, 1)) - { -- const struct vkd3d_shader_scan_descriptor_info1 *info = context->scan_descriptor_info; - const struct vkd3d_shader_descriptor_info1 *d; - bool dynamic_resource, dynamic_sampler; - -@@ -928,30 +944,13 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co - if (dynamic_resource || dynamic_sampler) - return; - -- for (i = 0; i < info->descriptor_count; ++i) -- { -- d = &info->descriptors[i]; -- if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SRV) -- continue; -- if (d->register_id != resource->idx[0].offset) -- continue; -+ if ((d = find_descriptor(context->scan_descriptor_info, -+ VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource->idx[0].offset))) - resource_space = d->register_space; -- break; -- } - -- if (sampler) -- { -- for (i = 0; i < info->descriptor_count; ++i) -- { -- d = &info->descriptors[i]; -- if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) -- continue; -- if (d->register_id != sampler->idx[0].offset) -- continue; -- sampler_space = d->register_space; -- break; -- } -- } -+ if (sampler && (d = find_descriptor(context->scan_descriptor_info, -+ VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler->idx[0].offset))) -+ sampler_space = d->register_space; - } - - for (i = 0; i < info->combined_sampler_count; ++i) -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index a93fa7160f7..4944b8a1c53 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -196,6 +196,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH = 8306, - VKD3D_SHADER_WARNING_DXIL_INVALID_MASK = 8307, - VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308, -+ VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT = 8309, - - VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, - VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001, -@@ -793,10 +794,12 @@ struct vkd3d_shader_version - - struct vkd3d_shader_immediate_constant_buffer - { -+ unsigned int register_idx; - enum vkd3d_data_type data_type; - /* total count is element_count * component_count */ - unsigned int element_count; - unsigned int component_count; -+ bool is_null; - uint32_t data[]; - }; - --- -2.43.0 - diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-1015cc952e42828d79a68cfa0e659cac537.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-1015cc952e42828d79a68cfa0e659cac537.patch deleted file mode 100644 index 0976b534..00000000 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-1015cc952e42828d79a68cfa0e659cac537.patch +++ /dev/null @@ -1,1213 +0,0 @@ -From e860d3e97d558b909a3162629d45926260497bab Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Wed, 13 Dec 2023 09:32:05 +1100 -Subject: [PATCH] Updated vkd3d to 1015cc952e42828d79a68cfa0e659cac53772676. - ---- - libs/vkd3d/include/vkd3d_shader.h | 18 ++ - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 73 +++++- - libs/vkd3d/libs/vkd3d-shader/dxbc.c | 4 - - libs/vkd3d/libs/vkd3d-shader/dxil.c | 222 +++++++++++++----- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 220 ++++++++++------- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 16 ++ - .../libs/vkd3d-shader/vkd3d_shader_main.c | 4 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 11 +- - 8 files changed, 395 insertions(+), 173 deletions(-) - -diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h -index 290f9085d2d..a6bf8964183 100644 ---- a/libs/vkd3d/include/vkd3d_shader.h -+++ b/libs/vkd3d/include/vkd3d_shader.h -@@ -196,6 +196,14 @@ enum vkd3d_shader_compile_option_fragment_coordinate_origin - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN), - }; - -+/** Advertises feature availability. \since 1.11 */ -+enum vkd3d_shader_compile_option_feature_flags -+{ -+ VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64 = 0x00000001, -+ -+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLAGS), -+}; -+ - enum vkd3d_shader_compile_option_name - { - /** -@@ -253,6 +261,16 @@ enum vkd3d_shader_compile_option_name - * \since 1.10 - */ - VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN = 0x00000009, -+ /** -+ * This option specifies the shader features available in the target -+ * environment. These are not extensions, i.e. they are always supported -+ * by the driver, but may not be supported by the available hardware. -+ * -+ * \a value is a member of enum vkd3d_shader_compile_option_feature_flags. -+ * -+ * \since 1.11 -+ */ -+ VKD3D_SHADER_COMPILE_OPTION_FEATURE = 0x0000000a, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME), - }; -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index 82d1d71d9d3..2d52ee07724 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -364,6 +364,7 @@ struct vkd3d_d3d_asm_compiler - struct vkd3d_string_buffer buffer; - struct vkd3d_shader_version shader_version; - struct vkd3d_d3d_asm_colours colours; -+ enum vsir_asm_dialect dialect; - }; - - static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...) -@@ -606,7 +607,7 @@ static void shader_dump_resource_type(struct vkd3d_d3d_asm_compiler *compiler, e - vkd3d_string_buffer_printf(&compiler->buffer, "unknown"); - } - --static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type) -+static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_data_type type) - { - static const char *const data_type_names[] = - { -@@ -623,19 +624,31 @@ static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, const - [VKD3D_DATA_DOUBLE ] = "double", - [VKD3D_DATA_CONTINUED] = "", - [VKD3D_DATA_UNUSED ] = "", -+ [VKD3D_DATA_UINT8 ] = "uint8", -+ [VKD3D_DATA_UINT64 ] = "uint64", -+ [VKD3D_DATA_BOOL ] = "bool", - }; -+ - const char *name; -+ -+ if (type < ARRAY_SIZE(data_type_names)) -+ name = data_type_names[type]; -+ else -+ name = ""; -+ -+ vkd3d_string_buffer_printf(&compiler->buffer, "%s", name); -+} -+ -+static void shader_dump_resource_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type) -+{ - int i; - - vkd3d_string_buffer_printf(&compiler->buffer, "("); - - for (i = 0; i < 4; i++) - { -- if (type[i] < ARRAY_SIZE(data_type_names)) -- name = data_type_names[type[i]]; -- else -- name = "unknown"; -- vkd3d_string_buffer_printf(&compiler->buffer, "%s%s", i == 0 ? "" : ",", name); -+ vkd3d_string_buffer_printf(&compiler->buffer, "%s", i == 0 ? "" : ","); -+ shader_dump_data_type(compiler, type[i]); - } - - vkd3d_string_buffer_printf(&compiler->buffer, ")"); -@@ -682,7 +695,7 @@ static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler, - if (semantic->resource.reg.reg.type == VKD3DSPR_UAV) - shader_dump_uav_flags(compiler, flags); - shader_addline(buffer, " "); -- shader_dump_data_type(compiler, semantic->resource_data_type); -+ shader_dump_resource_data_type(compiler, semantic->resource_data_type); - } - else - { -@@ -1265,6 +1278,32 @@ static void shader_print_non_uniform(struct vkd3d_d3d_asm_compiler *compiler, co - compiler->colours.modifier, compiler->colours.reset); - } - -+static void shader_dump_reg_type(struct vkd3d_d3d_asm_compiler *compiler, -+ const struct vkd3d_shader_register *reg) -+{ -+ static const char *dimensions[] = -+ { -+ [VSIR_DIMENSION_NONE] = "", -+ [VSIR_DIMENSION_SCALAR] = "s:", -+ [VSIR_DIMENSION_VEC4] = "v4:", -+ }; -+ -+ struct vkd3d_string_buffer *buffer = &compiler->buffer; -+ const char *dimension; -+ -+ if (compiler->dialect != VSIR_ASM_VSIR) -+ return; -+ -+ if (reg->dimension < ARRAY_SIZE(dimensions)) -+ dimension = dimensions[reg->dimension]; -+ else -+ dimension = "??"; -+ -+ shader_addline(buffer, " <%s", dimension); -+ shader_dump_data_type(compiler, reg->data_type); -+ shader_addline(buffer, ">"); -+} -+ - static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, - const struct vkd3d_shader_dst_param *param, bool is_declaration) - { -@@ -1294,6 +1333,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, - - shader_print_precision(compiler, ¶m->reg); - shader_print_non_uniform(compiler, ¶m->reg); -+ shader_dump_reg_type(compiler, ¶m->reg); - } - - static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, -@@ -1367,6 +1407,7 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, - - shader_print_precision(compiler, ¶m->reg); - shader_print_non_uniform(compiler, ¶m->reg); -+ shader_dump_reg_type(compiler, ¶m->reg); - } - - static void shader_dump_ins_modifiers(struct vkd3d_d3d_asm_compiler *compiler, -@@ -1577,6 +1618,12 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile - shader_addline(buffer, "p"); - break; - -+ case VKD3DSIH_ISHL: -+ case VKD3DSIH_ISHR: -+ case VKD3DSIH_USHR: -+ if (ins->flags & VKD3DSI_SHIFT_UNMASKED) -+ shader_addline(buffer, "_unmasked"); -+ /* fall through */ - default: - shader_dump_precise_flags(compiler, ins->flags); - break; -@@ -1883,7 +1930,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, - || ins->resource_data_type[1] != VKD3D_DATA_FLOAT - || ins->resource_data_type[2] != VKD3D_DATA_FLOAT - || ins->resource_data_type[3] != VKD3D_DATA_FLOAT) -- shader_dump_data_type(compiler, ins->resource_data_type); -+ shader_dump_resource_data_type(compiler, ins->resource_data_type); - - for (i = 0; i < ins->dst_count; ++i) - { -@@ -1906,10 +1953,13 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, - - enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions, - const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info, -- struct vkd3d_shader_code *out) -+ struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect) - { - enum vkd3d_shader_compile_option_formatting_flags formatting; -- struct vkd3d_d3d_asm_compiler compiler; -+ struct vkd3d_d3d_asm_compiler compiler = -+ { -+ .dialect = dialect, -+ }; - enum vkd3d_result result = VKD3D_OK; - struct vkd3d_string_buffer *buffer; - unsigned int indent, i, j; -@@ -2002,6 +2052,7 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instructio - { - case VKD3DSIH_ELSE: - case VKD3DSIH_IF: -+ case VKD3DSIH_IFC: - case VKD3DSIH_LOOP: - case VKD3DSIH_SWITCH: - ++indent; -@@ -2034,7 +2085,7 @@ void vkd3d_shader_trace(const struct vkd3d_shader_instruction_array *instruction - const char *p, *q, *end; - struct vkd3d_shader_code code; - -- if (vkd3d_dxbc_binary_to_text(instructions, shader_version, NULL, &code) != VKD3D_OK) -+ if (vkd3d_dxbc_binary_to_text(instructions, shader_version, NULL, &code, VSIR_ASM_VSIR) != VKD3D_OK) - return; - - end = (const char *)code.code + code.size; -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c -index 7834c1e1615..63deaaad29a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c -@@ -431,10 +431,6 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s - case TAG_OSG5: - if (e[i].sysval_semantic == VKD3D_SHADER_SV_NONE) - e[i].sysval_semantic = map_fragment_output_sysval(e[i].semantic_name); -- /* Fall through. */ -- case TAG_PCSG: -- case TAG_PSG1: -- e[i].used_mask = e[i].mask & ~e[i].used_mask; - break; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index a1065c8bc45..602056e25d4 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -29,6 +29,9 @@ static const uint64_t MAX_ALIGNMENT_EXPONENT = 29; - static const uint64_t GLOBALVAR_FLAG_IS_CONSTANT = 1; - static const uint64_t GLOBALVAR_FLAG_EXPLICIT_TYPE = 2; - static const unsigned int GLOBALVAR_ADDRESS_SPACE_SHIFT = 2; -+static const uint64_t ALLOCA_FLAG_IN_ALLOCA = 0x20; -+static const uint64_t ALLOCA_FLAG_EXPLICIT_TYPE = 0x40; -+static const uint64_t ALLOCA_ALIGNMENT_MASK = ALLOCA_FLAG_IN_ALLOCA - 1; - static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4; - - static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64}; -@@ -2688,12 +2691,15 @@ static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type - } - - static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, -- unsigned int count, unsigned int alignment, unsigned int init, struct sm6_value *dst) -+ unsigned int count, unsigned int alignment, unsigned int init, struct vkd3d_shader_instruction *ins, -+ struct sm6_value *dst) - { - enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); -- struct vkd3d_shader_instruction *ins; - -- ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_INDEXABLE_TEMP); -+ if (ins) -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_DCL_INDEXABLE_TEMP); -+ else -+ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_INDEXABLE_TEMP); - ins->declaration.indexable_temp.register_idx = sm6->indexable_temp_count++; - ins->declaration.indexable_temp.register_size = count; - ins->declaration.indexable_temp.alignment = alignment; -@@ -2826,7 +2832,7 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ - if (is_constant) - sm6_parser_declare_icb(sm6, scalar_type, count, alignment, init, dst); - else -- sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst); -+ sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, NULL, dst); - } - else if (address_space == ADDRESS_SPACE_GROUPSHARED) - { -@@ -2854,17 +2860,19 @@ static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_init - - assert(index); - --index; -- if (!(value = sm6_parser_get_value_safe(sm6, index)) || !sm6_value_is_icb(value)) -+ if (!(value = sm6_parser_get_value_safe(sm6, index)) || (!sm6_value_is_icb(value) && !sm6_value_is_undef(value))) - { - WARN("Invalid initialiser index %zu.\n", index); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Global variable initialiser value index %zu is invalid.", index); - return NULL; - } -- else -+ else if (sm6_value_is_icb(value)) - { - return value->u.icb; - } -+ /* In VSIR, initialisation with undefined values of objects is implied, not explicit. */ -+ return NULL; - } - - static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) -@@ -2987,45 +2995,6 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade - } - } - --static void sm6_parser_emit_signature(struct sm6_parser *sm6, const struct shader_signature *s, -- enum vkd3d_shader_opcode handler_idx, enum vkd3d_shader_opcode siv_handler_idx, -- struct vkd3d_shader_dst_param *params) --{ -- struct vkd3d_shader_instruction *ins; -- struct vkd3d_shader_dst_param *param; -- const struct signature_element *e; -- unsigned int i; -- -- for (i = 0; i < s->element_count; ++i) -- { -- e = &s->elements[i]; -- -- /* Do not check e->used_mask because in some cases it is zero for used elements. -- * TODO: scan ahead for used I/O elements. */ -- -- if (e->sysval_semantic != VKD3D_SHADER_SV_NONE && e->sysval_semantic != VKD3D_SHADER_SV_TARGET) -- { -- ins = sm6_parser_add_instruction(sm6, siv_handler_idx); -- param = &ins->declaration.register_semantic.reg; -- ins->declaration.register_semantic.sysval_semantic = vkd3d_siv_from_sysval(e->sysval_semantic); -- } -- else -- { -- ins = sm6_parser_add_instruction(sm6, handler_idx); -- param = &ins->declaration.dst; -- } -- -- ins->flags = e->interpolation_mode; -- *param = params[i]; -- -- if (e->register_count > 1) -- { -- param->reg.idx[0].rel_addr = NULL; -- param->reg.idx[0].offset = e->register_count; -- } -- } --} -- - static void sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) - { - sm6_parser_init_signature(sm6, output_signature, VKD3DSPR_OUTPUT, sm6->output_params); -@@ -3036,19 +3005,6 @@ static void sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct - sm6_parser_init_signature(sm6, input_signature, VKD3DSPR_INPUT, sm6->input_params); - } - --static void sm6_parser_emit_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) --{ -- sm6_parser_emit_signature(sm6, output_signature, VKD3DSIH_DCL_OUTPUT, VKD3DSIH_DCL_OUTPUT_SIV, sm6->output_params); --} -- --static void sm6_parser_emit_input_signature(struct sm6_parser *sm6, const struct shader_signature *input_signature) --{ -- sm6_parser_emit_signature(sm6, input_signature, -- (sm6->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3DSIH_DCL_INPUT_PS : VKD3DSIH_DCL_INPUT, -- (sm6->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3DSIH_DCL_INPUT_PS_SIV : VKD3DSIH_DCL_INPUT_SIV, -- sm6->input_params); --} -- - static const struct sm6_value *sm6_parser_next_function_definition(struct sm6_parser *sm6) - { - size_t i, count = sm6->function_count; -@@ -3071,6 +3027,81 @@ static struct sm6_block *sm6_block_create() - return block; - } - -+static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_record *record, -+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst) -+{ -+ const struct sm6_type *type[2], *elem_type; -+ const struct sm6_value *size; -+ unsigned int i, alignment; -+ uint64_t packed_operands; -+ -+ if (!dxil_record_validate_operand_count(record, 4, 4, sm6)) -+ return; -+ -+ for (i = 0; i < 2; ++i) -+ { -+ if (!(type[i] = sm6_parser_get_type(sm6, record->operands[i]))) -+ return; -+ } -+ -+ packed_operands = record->operands[3]; -+ if (packed_operands & ALLOCA_FLAG_IN_ALLOCA) -+ WARN("Ignoring in_alloca flag.\n"); -+ if (!(packed_operands & ALLOCA_FLAG_EXPLICIT_TYPE)) -+ { -+ FIXME("Unhandled implicit type.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Implicit result type for ALLOCA instructions is not supported."); -+ return; -+ } -+ packed_operands &= ~(ALLOCA_FLAG_IN_ALLOCA | ALLOCA_FLAG_EXPLICIT_TYPE); -+ -+ if (!sm6_type_is_array(type[0]) || !sm6_type_is_numeric(elem_type = type[0]->u.array.elem_type)) -+ { -+ WARN("Type is not a numeric array.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Result type of an ALLOCA instruction is not a numeric array."); -+ return; -+ } -+ /* The second type operand is the type of the allocation size operand, in case it is a -+ * forward reference. We only support a constant size, so no forward ref support is needed. */ -+ if (!sm6_type_is_integer(type[1])) -+ { -+ WARN("Size operand type is not scalar integer.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "The type of the allocation size operand of an ALLOCA instruction is not scalar integer."); -+ return; -+ } -+ -+ if (!(dst->type = sm6_type_get_pointer_to_type(type[0], ADDRESS_SPACE_DEFAULT, sm6))) -+ { -+ WARN("Failed to get pointer type for type class %u.\n", type[0]->class); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, -+ "Module does not define a pointer type for an ALLOCA instruction."); -+ return; -+ } -+ -+ if (!(size = sm6_parser_get_value_safe(sm6, record->operands[2]))) -+ return; -+ /* A size of 1 means one instance of type[0], i.e. one array. */ -+ if (sm6_value_get_constant_uint(size) != 1) -+ { -+ FIXME("Allocation size is not 1.\n"); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "ALLOCA instruction allocation sizes other than 1 are not supported."); -+ return; -+ } -+ -+ if (!bitcode_parse_alignment(packed_operands & ALLOCA_ALIGNMENT_MASK, &alignment)) -+ WARN("Invalid alignment %"PRIu64".\n", packed_operands); -+ packed_operands &= ~ALLOCA_ALIGNMENT_MASK; -+ -+ if (packed_operands) -+ WARN("Ignoring flags %#"PRIx64".\n", packed_operands); -+ -+ sm6_parser_declare_indexable_temp(sm6, elem_type, type[0]->u.array.count, alignment, 0, ins, dst); -+} -+ - static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_type *type_a, - const struct sm6_type *type_b, struct sm6_parser *sm6) - { -@@ -3171,8 +3202,10 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - unsigned int i = 0; - - a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i); -+ if (!a) -+ return; - b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i); -- if (!a || !b) -+ if (!b) - return; - - if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6)) -@@ -3246,6 +3279,12 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - } - else - { -+ if (handler_idx == VKD3DSIH_ISHL || handler_idx == VKD3DSIH_ISHR || handler_idx == VKD3DSIH_USHR) -+ { -+ /* DXC emits AND instructions where necessary to mask shift counts. Shift binops -+ * do not imply masking the shift as the TPF equivalents do. */ -+ ins->flags |= VKD3DSI_SHIFT_UNMASKED; -+ } - instruction_dst_param_init_ssa_scalar(ins, sm6); - } - } -@@ -3963,8 +4002,10 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor - } - - a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i); -+ if (!a) -+ return; - b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i); -- if (!a || !b) -+ if (!b) - return; - - if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6)) -@@ -4253,6 +4294,57 @@ static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record - ins->handler_idx = VKD3DSIH_NOP; - } - -+static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_record *record, -+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst) -+{ -+ struct vkd3d_shader_src_param *src_param; -+ struct vkd3d_shader_dst_param *dst_param; -+ const struct sm6_type *pointee_type; -+ const struct sm6_value *ptr, *src; -+ unsigned int i = 0, alignment; -+ uint64_t alignment_code; -+ -+ if (!(ptr = sm6_parser_get_value_by_ref(sm6, record, NULL, &i)) -+ || !sm6_value_validate_is_register(ptr, sm6) -+ || !sm6_value_validate_is_pointer(ptr, sm6)) -+ { -+ return; -+ } -+ -+ pointee_type = ptr->type->u.pointer.type; -+ if (!(src = sm6_parser_get_value_by_ref(sm6, record, pointee_type, &i))) -+ return; -+ if (!sm6_value_validate_is_numeric(src, sm6)) -+ return; -+ -+ if (pointee_type != src->type) -+ { -+ WARN("Type mismatch.\n"); -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "Type mismatch in pointer store arguments."); -+ } -+ -+ if (!dxil_record_validate_operand_count(record, i + 2, i + 2, sm6)) -+ return; -+ -+ alignment_code = record->operands[i++]; -+ if (!bitcode_parse_alignment(alignment_code, &alignment)) -+ WARN("Invalid alignment %"PRIu64".\n", alignment_code); -+ -+ if (record->operands[i]) -+ WARN("Ignoring volatile modifier.\n"); -+ -+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); -+ -+ src_param = instruction_src_params_alloc(ins, 1, sm6); -+ src_param_init_from_value(&src_param[0], src); -+ -+ dst_param = instruction_dst_params_alloc(ins, 1, sm6); -+ dst_param_init(dst_param); -+ dst_param->reg = ptr->u.reg; -+ dst_param->reg.alignment = alignment; -+} -+ - static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_record *record, - struct vkd3d_shader_instruction *ins, struct sm6_value *dst) - { -@@ -4630,6 +4722,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - record = block->records[i]; - switch (record->code) - { -+ case FUNC_CODE_INST_ALLOCA: -+ sm6_parser_emit_alloca(sm6, record, ins, dst); -+ break; - case FUNC_CODE_INST_BINOP: - sm6_parser_emit_binop(sm6, record, ins, dst); - break; -@@ -4656,6 +4751,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - is_terminator = true; - ret_found = true; - break; -+ case FUNC_CODE_INST_STORE: -+ sm6_parser_emit_store(sm6, record, ins, dst); -+ break; - case FUNC_CODE_INST_VSELECT: - sm6_parser_emit_vselect(sm6, record, ins, dst); - break; -@@ -5040,7 +5138,7 @@ static const enum vkd3d_shader_sysval_semantic sysval_semantic_table[] = - { - [SEMANTIC_KIND_ARBITRARY] = VKD3D_SHADER_SV_NONE, - [SEMANTIC_KIND_POSITION] = VKD3D_SHADER_SV_POSITION, -- [SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_NONE, -+ [SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_TARGET, - }; - - static enum vkd3d_shader_sysval_semantic sysval_semantic_from_dxil_semantic_kind(enum dxil_semantic_kind kind) -@@ -6111,8 +6209,6 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - "Out of memory emitting shader signature declarations."); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -- sm6_parser_emit_output_signature(sm6, output_signature); -- sm6_parser_emit_input_signature(sm6, input_signature); - - sm6->p.shader_desc.ssa_count = sm6->ssa_next_id; - -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index a22c59577ac..db45920200d 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -2170,6 +2170,15 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol, - } - } - -+static void vkd3d_symbol_make_io(struct vkd3d_symbol *symbol, -+ enum vkd3d_shader_register_type type, unsigned int index) -+{ -+ symbol->type = VKD3D_SYMBOL_REGISTER; -+ memset(&symbol->key, 0, sizeof(symbol->key)); -+ symbol->key.reg.type = type; -+ symbol->key.reg.idx = index; -+} -+ - static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol, - uint32_t val_id, SpvStorageClass storage_class, - enum vkd3d_shader_component_type component_type, DWORD write_mask) -@@ -2387,6 +2396,7 @@ struct spirv_compiler - struct vkd3d_shader_spec_constant *spec_constants; - size_t spec_constants_size; - enum vkd3d_shader_compile_option_formatting_flags formatting; -+ enum vkd3d_shader_compile_option_feature_flags features; - bool write_tess_geom_point_size; - - struct vkd3d_string_buffer_cache string_buffers; -@@ -2544,6 +2554,10 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve - WARN("Ignoring unrecognised value %#x for option %#x.\n", option->value, option->name); - break; - -+ case VKD3D_SHADER_COMPILE_OPTION_FEATURE: -+ compiler->features = option->value; -+ break; -+ - default: - WARN("Ignoring unrecognised option %#x with value %#x.\n", option->name, option->value); - break; -@@ -4496,9 +4510,9 @@ vkd3d_register_builtins[] = - }; - - static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg) -+ enum vkd3d_shader_register_type type) - { -- switch (reg->type) -+ switch (type) - { - case VKD3DSPR_DEPTHOUTGE: - spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeDepthGreater, NULL, 0); -@@ -4511,9 +4525,9 @@ static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *c - VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT)) - { - FIXME("The target environment does not support stencil export.\n"); -- spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED, -- "Cannot export stencil reference value for register id %u. " -- "The target environment does not support stencil export.", reg->idx[0].offset); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, -+ "Cannot export stencil reference value. " -+ "The target environment does not support stencil export."); - } - vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityStencilExportEXT); - spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeStencilRefReplacingEXT, NULL, 0); -@@ -4748,10 +4762,9 @@ static unsigned int shader_signature_next_location(const struct shader_signature - } - - static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, -- const struct vkd3d_shader_dst_param *dst) -+ enum vkd3d_shader_register_type reg_type, unsigned int element_idx) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- const struct vkd3d_shader_register *reg = &dst->reg; - unsigned int component_idx, input_component_count; - const struct signature_element *signature_element; - const struct shader_signature *shader_signature; -@@ -4767,26 +4780,21 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - struct rb_entry *entry = NULL; - bool use_private_var = false; - unsigned int array_sizes[2]; -- unsigned int element_idx; -- -- assert(!reg->idx_count || !reg->idx[0].rel_addr); -- assert(reg->idx_count < 2 || !reg->idx[1].rel_addr); - -- shader_signature = reg->type == VKD3DSPR_PATCHCONST -+ shader_signature = reg_type == VKD3DSPR_PATCHCONST - ? &compiler->patch_constant_signature : &compiler->input_signature; - -- element_idx = reg->idx[reg->idx_count - 1].offset; - signature_element = &shader_signature->elements[element_idx]; - sysval = signature_element->sysval_semantic; - /* The Vulkan spec does not explicitly forbid passing varyings from the - * TCS to the TES via builtins. However, Mesa doesn't seem to handle it - * well, and we don't actually need them to be in builtins. */ -- if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN && reg->type != VKD3DSPR_PATCHCONST) -+ if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN && reg_type != VKD3DSPR_PATCHCONST) - sysval = VKD3D_SHADER_SV_NONE; - - builtin = get_spirv_builtin_for_sysval(compiler, sysval); - -- array_sizes[0] = (reg->type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); -+ array_sizes[0] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); - array_sizes[1] = signature_element->register_count; - if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic) - && (!vsir_sysval_semantic_is_clip_cull(signature_element->sysval_semantic) || array_sizes[0])) -@@ -4822,7 +4830,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - - storage_class = SpvStorageClassInput; - -- vkd3d_symbol_make_register(®_symbol, reg); -+ vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); - - if ((entry = rb_get(&compiler->symbol_table, ®_symbol))) - { -@@ -4830,7 +4838,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - * duplicate declarations are: a single register split into multiple declarations having - * different components, which should have been merged, and declarations in one phase - * being repeated in another (i.e. vcp/vocp), which should have been deleted. */ -- if (reg->type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler)) -+ if (reg_type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler)) - FIXME("Duplicate input definition found.\n"); - symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); - return symbol->id; -@@ -4839,7 +4847,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - if (builtin) - { - input_id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, storage_class, array_sizes, 2); -- if (reg->type == VKD3DSPR_PATCHCONST) -+ if (reg_type == VKD3DSPR_PATCHCONST) - vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0); - } - else -@@ -4849,7 +4857,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - input_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, - storage_class, component_type, input_component_count, array_sizes, 2); - vkd3d_spirv_add_iface_variable(builder, input_id); -- if (reg->type == VKD3DSPR_PATCHCONST) -+ if (reg_type == VKD3DSPR_PATCHCONST) - { - vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0); - location += shader_signature_next_location(&compiler->input_signature); -@@ -4876,12 +4884,14 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - assert(!builtin || !builtin->spirv_array_size || use_private_var || array_sizes[0] || array_sizes[1]); - spirv_compiler_put_symbol(compiler, ®_symbol); - -- spirv_compiler_emit_register_debug_name(builder, var_id, reg); -+ vkd3d_spirv_build_op_name(builder, var_id, reg_type == VKD3DSPR_PATCHCONST ? "vpc%u" : "v%u", element_idx); - - if (use_private_var) - { -- struct vkd3d_shader_register dst_reg = *reg; -- dst_reg.data_type = VKD3D_DATA_FLOAT; -+ struct vkd3d_shader_register dst_reg; -+ -+ vsir_register_init(&dst_reg, reg_type, VKD3D_DATA_FLOAT, 1); -+ dst_reg.idx[0].offset = element_idx; - - type_id = vkd3d_spirv_get_type_id(builder, component_type, input_component_count); - -@@ -4898,9 +4908,9 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - - val_id = spirv_compiler_emit_swizzle(compiler, val_id, - vkd3d_write_mask_from_component_count(input_component_count), -- VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, dst->write_mask >> component_idx); -+ VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, signature_element->mask >> component_idx); - -- spirv_compiler_emit_store_reg(compiler, &dst_reg, dst->write_mask, val_id); -+ spirv_compiler_emit_store_reg(compiler, &dst_reg, signature_element->mask, val_id); - } - - return input_id; -@@ -5069,7 +5079,7 @@ static void spirv_compiler_emit_output_register(struct spirv_compiler *compiler, - SpvStorageClassOutput, builtin->component_type, write_mask); - reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size; - spirv_compiler_put_symbol(compiler, ®_symbol); -- spirv_compiler_emit_register_execution_mode(compiler, reg); -+ spirv_compiler_emit_register_execution_mode(compiler, reg->type); - spirv_compiler_emit_register_debug_name(builder, output_id, reg); - } - -@@ -5098,10 +5108,10 @@ static uint32_t spirv_compiler_emit_shader_phase_builtin_variable(struct spirv_c - return id; - } - --static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const struct vkd3d_shader_dst_param *dst) -+static void spirv_compiler_emit_output(struct spirv_compiler *compiler, -+ enum vkd3d_shader_register_type reg_type, unsigned int element_idx) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- const struct vkd3d_shader_register *reg = &dst->reg; - unsigned int component_idx, output_component_count; - const struct signature_element *signature_element; - enum vkd3d_shader_component_type component_type; -@@ -5113,26 +5123,24 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st - struct vkd3d_symbol reg_symbol; - SpvStorageClass storage_class; - unsigned int array_sizes[2]; -- unsigned int element_idx; - bool is_patch_constant; - uint32_t id, var_id; - -- is_patch_constant = is_in_fork_or_join_phase(compiler); -+ is_patch_constant = (reg_type == VKD3DSPR_PATCHCONST); - - shader_signature = is_patch_constant ? &compiler->patch_constant_signature : &compiler->output_signature; - -- element_idx = reg->idx[reg->idx_count - 1].offset; - signature_element = &shader_signature->elements[element_idx]; - sysval = signature_element->sysval_semantic; - /* Don't use builtins for TCS -> TES varyings. See spirv_compiler_emit_input(). */ - if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && !is_patch_constant) - sysval = VKD3D_SHADER_SV_NONE; -- array_sizes[0] = (reg->type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); -+ array_sizes[0] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); - array_sizes[1] = signature_element->register_count; - if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic)) - array_sizes[1] = 0; - -- builtin = vkd3d_get_spirv_builtin(compiler, dst->reg.type, sysval); -+ builtin = vkd3d_get_spirv_builtin(compiler, reg_type, sysval); - - write_mask = signature_element->mask; - -@@ -5151,15 +5159,18 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st - - storage_class = SpvStorageClassOutput; - -- if (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE -- || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask) -- || needs_private_io_variable(builtin)) -+ if (needs_private_io_variable(builtin)) -+ use_private_variable = true; -+ -+ if (!is_patch_constant -+ && (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE -+ || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask))) - { - use_private_variable = true; - } - - reg_write_mask = write_mask >> component_idx; -- vkd3d_symbol_make_register(®_symbol, reg); -+ vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); - - if (rb_get(&compiler->symbol_table, ®_symbol)) - { -@@ -5168,7 +5179,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st - return; - } - -- if (compiler->output_info[element_idx].id) -+ if (!is_patch_constant && compiler->output_info[element_idx].id) - { - id = compiler->output_info[element_idx].id; - } -@@ -5179,7 +5190,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st - else - id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, storage_class, array_sizes, 2); - -- spirv_compiler_emit_register_execution_mode(compiler, &dst->reg); -+ spirv_compiler_emit_register_execution_mode(compiler, reg_type); - } - else if (signature_element->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) - { -@@ -5220,8 +5231,11 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st - - spirv_compiler_decorate_xfb_output(compiler, id, output_component_count, signature_element); - -- compiler->output_info[element_idx].id = id; -- compiler->output_info[element_idx].component_type = component_type; -+ if (!is_patch_constant) -+ { -+ compiler->output_info[element_idx].id = id; -+ compiler->output_info[element_idx].component_type = component_type; -+ } - - var_id = id; - if (use_private_variable) -@@ -5239,8 +5253,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st - - spirv_compiler_put_symbol(compiler, ®_symbol); - -- if (!is_patch_constant) -- spirv_compiler_emit_register_debug_name(builder, var_id, reg); -+ vkd3d_spirv_build_op_name(builder, var_id, reg_type == VKD3DSPR_PATCHCONST ? "vpc%u" : "o%u", element_idx); - - if (use_private_variable) - { -@@ -5518,6 +5531,21 @@ static void spirv_compiler_emit_dcl_global_flags(struct spirv_compiler *compiler - flags &= ~(VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS | VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS); - } - -+ if (flags & VKD3DSGF_ENABLE_INT64) -+ { -+ if (compiler->features & VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64) -+ { -+ vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityInt64); -+ } -+ else -+ { -+ WARN("Unsupported 64-bit integer ops.\n"); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, -+ "The target environment does not support 64-bit integers."); -+ } -+ flags &= ~VKD3DSGF_ENABLE_INT64; -+ } -+ - if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS)) - FIXME("Unhandled global flags %#"PRIx64".\n", (uint64_t)flags); - else -@@ -6212,37 +6240,22 @@ static void spirv_compiler_emit_dcl_input(struct spirv_compiler *compiler, - { - const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst; - -- /* OUTPOINTID is handled in spirv_compiler_emit_hull_shader_builtins(). */ -- if (dst->reg.type == VKD3DSPR_INPUT || dst->reg.type == VKD3DSPR_PATCHCONST) -- spirv_compiler_emit_input(compiler, dst); -- else if (dst->reg.type != VKD3DSPR_OUTPOINTID) -+ /* INPUT and PATCHCONST are handled in spirv_compiler_emit_io_declarations(). -+ * OUTPOINTID is handled in spirv_compiler_emit_hull_shader_builtins(). */ -+ if (dst->reg.type != VKD3DSPR_INPUT && dst->reg.type != VKD3DSPR_PATCHCONST -+ && dst->reg.type != VKD3DSPR_OUTPOINTID) - spirv_compiler_emit_input_register(compiler, dst); - } - --static void spirv_compiler_emit_dcl_input_sysval(struct spirv_compiler *compiler, -- const struct vkd3d_shader_instruction *instruction) --{ -- spirv_compiler_emit_input(compiler, &instruction->declaration.register_semantic.reg); --} -- - static void spirv_compiler_emit_dcl_output(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { - const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst; - -- if (dst->reg.type == VKD3DSPR_OUTPUT -- || (is_in_fork_or_join_phase(compiler) && dst->reg.type == VKD3DSPR_PATCHCONST)) -- spirv_compiler_emit_output(compiler, dst); -- else -+ if (dst->reg.type != VKD3DSPR_OUTPUT && dst->reg.type != VKD3DSPR_PATCHCONST) - spirv_compiler_emit_output_register(compiler, dst); - } - --static void spirv_compiler_emit_dcl_output_siv(struct spirv_compiler *compiler, -- const struct vkd3d_shader_instruction *instruction) --{ -- spirv_compiler_emit_output(compiler, &instruction->declaration.register_semantic.reg); --} -- - static void spirv_compiler_emit_dcl_stream(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { -@@ -6442,7 +6455,6 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile - - static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler) - { -- const struct shader_signature *signature = &compiler->output_signature; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - - if (is_in_control_point_phase(compiler) && compiler->emit_default_control_point_phase) -@@ -6460,7 +6472,6 @@ static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler) - - /* Fork and join phases share output registers (patch constants). - * Control point phase has separate output registers. */ -- memset(compiler->output_info, 0, signature->element_count * sizeof(*compiler->output_info)); - memset(compiler->private_output_variable, 0, sizeof(compiler->private_output_variable)); - memset(compiler->private_output_variable_write_mask, 0, sizeof(compiler->private_output_variable_write_mask)); - } -@@ -6503,15 +6514,12 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile - { - const struct shader_signature *output_signature = &compiler->output_signature; - const struct shader_signature *input_signature = &compiler->input_signature; -+ uint32_t type_id, output_ptr_type_id, input_id, dst_id, invocation_id; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - enum vkd3d_shader_component_type component_type; - struct vkd3d_shader_src_param invocation; - struct vkd3d_shader_register input_reg; -- uint32_t type_id, output_ptr_type_id; -- uint32_t input_id, output_id, dst_id; - unsigned int component_count; -- unsigned int array_sizes[2]; -- uint32_t invocation_id; - unsigned int i; - - invocation_id = spirv_compiler_emit_load_invocation_id(compiler); -@@ -6531,6 +6539,8 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile - { - const struct signature_element *output = &output_signature->elements[i]; - const struct signature_element *input = &input_signature->elements[i]; -+ struct vkd3d_shader_register_info output_reg_info; -+ struct vkd3d_shader_register output_reg; - - assert(input->mask == output->mask); - assert(input->component_type == output->component_type); -@@ -6538,22 +6548,16 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile - input_reg.idx[1].offset = i; - input_id = spirv_compiler_get_register_id(compiler, &input_reg); - -+ vsir_register_init(&output_reg, VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); -+ output_reg.idx[0].offset = i; -+ spirv_compiler_get_register_info(compiler, &output_reg, &output_reg_info); -+ - component_type = output->component_type; - component_count = vkd3d_write_mask_component_count(output->mask); - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); -- if ((array_sizes[0] = (input->register_count > 1) ? input->register_count : 0)) -- type_id = vkd3d_spirv_get_op_type_array(builder, type_id, spirv_compiler_get_constant_uint(compiler, -- array_sizes[0])); -- -- array_sizes[1] = compiler->output_control_point_count; -- output_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, SpvStorageClassOutput, -- component_type, component_count, array_sizes, 2); -- vkd3d_spirv_add_iface_variable(builder, output_id); -- vkd3d_spirv_build_op_decorate1(builder, output_id, SpvDecorationLocation, output->register_index); -- vkd3d_spirv_build_op_name(builder, output_id, "vocp%u", output->register_index); -- - output_ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); -- dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_id, invocation_id); -+ -+ dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_reg_info.id, invocation_id); - - vkd3d_spirv_build_op_copy_memory(builder, dst_id, input_id, SpvMemoryAccessMaskNone); - } -@@ -6780,8 +6784,8 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil - * Microsoft fxc will compile immediate constants larger than 5 bits. - * Fixing up the constants would be more elegant, but the simplest way is - * to let this handle constants too. */ -- if (instruction->handler_idx == VKD3DSIH_ISHL || instruction->handler_idx == VKD3DSIH_ISHR -- || instruction->handler_idx == VKD3DSIH_USHR) -+ if (!(instruction->flags & VKD3DSI_SHIFT_UNMASKED) && (instruction->handler_idx == VKD3DSIH_ISHL -+ || instruction->handler_idx == VKD3DSIH_ISHR || instruction->handler_idx == VKD3DSIH_USHR)) - { - uint32_t mask_id = spirv_compiler_get_constant_vector(compiler, - VKD3D_SHADER_COMPONENT_UINT, vkd3d_write_mask_component_count(dst->write_mask), 0x1f); -@@ -6942,6 +6946,11 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, - - general_implementation: - val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); -+ if (dst->reg.data_type != src->reg.data_type) -+ { -+ val_id = vkd3d_spirv_build_op_bitcast(builder, vkd3d_spirv_get_type_id_for_data_type(builder, -+ dst->reg.data_type, vkd3d_write_mask_component_count(dst->write_mask)), val_id); -+ } - spirv_compiler_emit_store_dst(compiler, dst, val_id); - } - -@@ -7150,6 +7159,13 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, - div_op = instruction->handler_idx == VKD3DSIH_IDIV ? SpvOpSDiv : SpvOpUDiv; - mod_op = instruction->handler_idx == VKD3DSIH_IDIV ? SpvOpSRem : SpvOpUMod; - -+ if (dst[0].reg.data_type == VKD3D_DATA_UINT64 || dst[1].reg.data_type == VKD3D_DATA_UINT64) -+ { -+ FIXME("Unsupported 64-bit result.\n"); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, -+ "Bool cast to 64-bit integer is not supported."); -+ } -+ - if (dst[0].reg.type != VKD3DSPR_NULL) - { - component_count = vkd3d_write_mask_component_count(dst[0].write_mask); -@@ -9490,18 +9506,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_DCL_INPUT: - spirv_compiler_emit_dcl_input(compiler, instruction); - break; -- case VKD3DSIH_DCL_INPUT_PS_SGV: -- case VKD3DSIH_DCL_INPUT_PS_SIV: -- case VKD3DSIH_DCL_INPUT_SGV: -- case VKD3DSIH_DCL_INPUT_SIV: -- spirv_compiler_emit_dcl_input_sysval(compiler, instruction); -- break; - case VKD3DSIH_DCL_OUTPUT: - spirv_compiler_emit_dcl_output(compiler, instruction); - break; -- case VKD3DSIH_DCL_OUTPUT_SIV: -- spirv_compiler_emit_dcl_output_siv(compiler, instruction); -- break; - case VKD3DSIH_DCL_STREAM: - spirv_compiler_emit_dcl_stream(compiler, instruction); - break; -@@ -9784,6 +9791,11 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_DCL_CONSTANT_BUFFER: - case VKD3DSIH_DCL_HS_MAX_TESSFACTOR: - case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT: -+ case VKD3DSIH_DCL_INPUT_SGV: -+ case VKD3DSIH_DCL_INPUT_SIV: -+ case VKD3DSIH_DCL_INPUT_PS_SGV: -+ case VKD3DSIH_DCL_INPUT_PS_SIV: -+ case VKD3DSIH_DCL_OUTPUT_SIV: - case VKD3DSIH_DCL_RESOURCE_RAW: - case VKD3DSIH_DCL_RESOURCE_STRUCTURED: - case VKD3DSIH_DCL_SAMPLER: -@@ -9805,6 +9817,30 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - return ret; - } - -+static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) -+{ -+ for (unsigned int i = 0; i < compiler->input_signature.element_count; ++i) -+ spirv_compiler_emit_input(compiler, VKD3DSPR_INPUT, i); -+ -+ for (unsigned int i = 0; i < compiler->output_signature.element_count; ++i) -+ { -+ /* PS outputs other than TARGET have dedicated registers and therefore -+ * go through spirv_compiler_emit_dcl_output() for now. */ -+ if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL -+ && compiler->output_signature.elements[i].sysval_semantic != VKD3D_SHADER_SV_TARGET) -+ continue; -+ spirv_compiler_emit_output(compiler, VKD3DSPR_OUTPUT, i); -+ } -+ -+ for (unsigned int i = 0; i < compiler->patch_constant_signature.element_count; ++i) -+ { -+ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL) -+ spirv_compiler_emit_output(compiler, VKD3DSPR_PATCHCONST, i); -+ else -+ spirv_compiler_emit_input(compiler, VKD3DSPR_PATCHCONST, i); -+ } -+} -+ - static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *compiler) - { - unsigned int i; -@@ -9891,6 +9927,8 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) - spirv_compiler_emit_shader_signature_outputs(compiler); - -+ spirv_compiler_emit_io_declarations(compiler); -+ - for (i = 0; i < instructions.count && result >= 0; ++i) - { - compiler->location.line = i + 1; -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 163cd90ee13..1b009c13016 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -2544,6 +2544,16 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t - return true; - } - -+static void uninvert_used_masks(struct shader_signature *signature) -+{ -+ for (unsigned int i = 0; i < signature->element_count; ++i) -+ { -+ struct signature_element *e = &signature->elements[i]; -+ -+ e->used_mask = e->mask & ~e->used_mask; -+ } -+} -+ - static bool shader_sm4_parser_validate_signature(struct vkd3d_shader_sm4_parser *sm4, - const struct shader_signature *signature, unsigned int *masks, const char *name) - { -@@ -2639,6 +2649,12 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi - return VKD3D_ERROR_INVALID_ARGUMENT; - } - -+ /* DXBC stores used masks inverted for output signatures, for some reason. -+ * We return them un-inverted. */ -+ uninvert_used_masks(&shader_desc->output_signature); -+ if (sm4->p.shader_version.type == VKD3D_SHADER_TYPE_HULL) -+ uninvert_used_masks(&shader_desc->patch_constant_signature); -+ - if (!shader_sm4_parser_validate_signature(sm4, &shader_desc->input_signature, - sm4->input_register_masks, "Input") - || !shader_sm4_parser_validate_signature(sm4, &shader_desc->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 d4a9d391477..4fd5c9bd034 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -1546,7 +1546,7 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, - switch (compile_info->target_type) - { - case VKD3D_SHADER_TARGET_D3D_ASM: -- ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out); -+ ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out, VSIR_ASM_D3D); - break; - - case VKD3D_SHADER_TARGET_GLSL: -@@ -1623,7 +1623,7 @@ static int compile_d3d_bytecode(const struct vkd3d_shader_compile_info *compile_ - - if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM) - { -- ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out); -+ ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out, VSIR_ASM_D3D); - vkd3d_shader_parser_destroy(parser); - return ret; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 4944b8a1c53..0e8d75d9897 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -91,7 +91,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001, - VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING = 2002, - VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED = 2003, -- VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED = 2004, -+ VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE = 2004, - VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY = 2005, - VKD3D_SHADER_ERROR_SPV_INVALID_TYPE = 2006, - VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER = 2007, -@@ -741,6 +741,7 @@ enum vkd3d_tessellator_domain - #define VKD3DSI_RESINFO_UINT 0x2 - #define VKD3DSI_SAMPLE_INFO_UINT 0x1 - #define VKD3DSI_SAMPLER_COMPARISON_MODE 0x1 -+#define VKD3DSI_SHIFT_UNMASKED 0x1 - - #define VKD3DSI_PRECISE_X 0x100 - #define VKD3DSI_PRECISE_Y 0x200 -@@ -1314,9 +1315,15 @@ struct vkd3d_string_buffer_cache - size_t count, max_count, capacity; - }; - -+enum vsir_asm_dialect -+{ -+ VSIR_ASM_VSIR, -+ VSIR_ASM_D3D, -+}; -+ - enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions, - const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info, -- struct vkd3d_shader_code *out); -+ struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect); - void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer); - struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list); - void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer); --- -2.43.0 - diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-68b898fcb6b4ab2a9660f35edf3554465ab.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-68b898fcb6b4ab2a9660f35edf3554465ab.patch new file mode 100644 index 00000000..2631e4b4 --- /dev/null +++ b/patches/vkd3d-latest/0002-Updated-vkd3d-to-68b898fcb6b4ab2a9660f35edf3554465ab.patch @@ -0,0 +1,3188 @@ +From 14870dfefe8b625927240a107b7b841d8e0060f5 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Fri, 5 Jan 2024 11:03:00 +1100 +Subject: [PATCH] Updated vkd3d to 68b898fcb6b4ab2a9660f35edf3554465ab0efbe. + +--- + libs/vkd3d/Makefile.in | 1 + + libs/vkd3d/include/private/vkd3d_common.h | 5 +- + libs/vkd3d/include/vkd3d_shader.h | 7 + + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 60 ++- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 35 +- + libs/vkd3d/libs/vkd3d-shader/dxbc.c | 34 +- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 15 +- + libs/vkd3d/libs/vkd3d-shader/fx.c | 377 ++++++++++++++++++ + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 99 ++++- + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 35 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.l | 1 + + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 142 +++++-- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 61 ++- + libs/vkd3d/libs/vkd3d-shader/ir.c | 311 +++++++++++++-- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 69 ++-- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 39 +- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 36 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 20 +- + libs/vkd3d/libs/vkd3d/command.c | 6 +- + libs/vkd3d/libs/vkd3d/device.c | 42 +- + libs/vkd3d/libs/vkd3d/resource.c | 96 ++++- + libs/vkd3d/libs/vkd3d/state.c | 23 +- + libs/vkd3d/libs/vkd3d/utils.c | 12 +- + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 3 +- + 24 files changed, 1289 insertions(+), 240 deletions(-) + create mode 100644 libs/vkd3d/libs/vkd3d-shader/fx.c + +diff --git a/libs/vkd3d/Makefile.in b/libs/vkd3d/Makefile.in +index dbc10594f62..448e9a0e61d 100644 +--- a/libs/vkd3d/Makefile.in ++++ b/libs/vkd3d/Makefile.in +@@ -17,6 +17,7 @@ SOURCES = \ + libs/vkd3d-shader/d3dbc.c \ + libs/vkd3d-shader/dxbc.c \ + libs/vkd3d-shader/dxil.c \ ++ libs/vkd3d-shader/fx.c \ + libs/vkd3d-shader/glsl.c \ + libs/vkd3d-shader/hlsl.c \ + libs/vkd3d-shader/hlsl.l \ +diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h +index e9bff2fbba3..4c97fa06e32 100644 +--- a/libs/vkd3d/include/private/vkd3d_common.h ++++ b/libs/vkd3d/include/private/vkd3d_common.h +@@ -52,6 +52,7 @@ + #define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9') + #define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C') + #define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L') ++#define TAG_FX10 VKD3D_MAKE_TAG('F', 'X', '1', '0') + #define TAG_ISG1 VKD3D_MAKE_TAG('I', 'S', 'G', '1') + #define TAG_ISGN VKD3D_MAKE_TAG('I', 'S', 'G', 'N') + #define TAG_OSG1 VKD3D_MAKE_TAG('O', 'S', 'G', '1') +@@ -276,10 +277,6 @@ static inline LONG64 InterlockedIncrement64(LONG64 volatile *x) + { + return __sync_add_and_fetch(x, 1); + } +-static inline LONG InterlockedAdd(LONG volatile *x, LONG val) +-{ +- return __sync_add_and_fetch(x, val); +-} + # else + # error "InterlockedIncrement() not implemented for this platform" + # endif /* HAVE_SYNC_ADD_AND_FETCH */ +diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h +index b1a1fff6451..a9c9ccc4a52 100644 +--- a/libs/vkd3d/include/vkd3d_shader.h ++++ b/libs/vkd3d/include/vkd3d_shader.h +@@ -785,6 +785,11 @@ enum vkd3d_shader_target_type + * An 'OpenGL Shading Language' shader. \since 1.3 + */ + VKD3D_SHADER_TARGET_GLSL, ++ /** ++ * Binary format used by Direct3D 9/10.x/11 effects profiles. ++ * Output is a raw FX section without container. \since 1.11 ++ */ ++ VKD3D_SHADER_TARGET_FX, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TARGET_TYPE), + }; +@@ -1270,6 +1275,8 @@ enum vkd3d_shader_descriptor_range_flags + VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE = 0x2, + VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4, + VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8, ++ /** \since 1.11 */ ++ VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS = 0x10000, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_DESCRIPTOR_RANGE_FLAGS), + }; +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +index 0589bc42174..4829956cecf 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +@@ -365,6 +365,7 @@ struct vkd3d_d3d_asm_compiler + struct vkd3d_shader_version shader_version; + struct vkd3d_d3d_asm_colours colours; + enum vsir_asm_dialect dialect; ++ const struct vkd3d_shader_instruction *current; + }; + + static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...) +@@ -841,6 +842,27 @@ static void shader_print_bool_literal(struct vkd3d_d3d_asm_compiler *compiler, + compiler->colours.literal, b ? "true" : "false", compiler->colours.reset, suffix); + } + ++static void shader_print_untyped_literal(struct vkd3d_d3d_asm_compiler *compiler, ++ const char *prefix, uint32_t u, const char *suffix) ++{ ++ union ++ { ++ uint32_t u; ++ float f; ++ } value; ++ unsigned int exponent = (u >> 23) & 0xff; ++ ++ value.u = u; ++ ++ if (exponent != 0 && exponent != 0xff) ++ return shader_print_float_literal(compiler, prefix, value.f, suffix); ++ ++ if (u <= 10000) ++ return shader_print_uint_literal(compiler, prefix, value.u, suffix); ++ ++ return shader_print_hex_literal(compiler, prefix, value.u, suffix); ++} ++ + static void shader_print_subscript(struct vkd3d_d3d_asm_compiler *compiler, + unsigned int offset, const struct vkd3d_shader_src_param *rel_addr) + { +@@ -1102,6 +1124,19 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const + + if (reg->type == VKD3DSPR_IMMCONST) + { ++ bool untyped = false; ++ ++ switch (compiler->current->handler_idx) ++ { ++ case VKD3DSIH_MOV: ++ case VKD3DSIH_MOVC: ++ untyped = true; ++ break; ++ ++ default: ++ break; ++ } ++ + shader_addline(buffer, "%s(", compiler->colours.reset); + switch (reg->dimension) + { +@@ -1109,7 +1144,10 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const + switch (reg->data_type) + { + case VKD3D_DATA_FLOAT: +- shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); ++ if (untyped) ++ shader_print_untyped_literal(compiler, "", reg->u.immconst_u32[0], ""); ++ else ++ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); + break; + case VKD3D_DATA_INT: + shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); +@@ -1129,10 +1167,20 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const + switch (reg->data_type) + { + case VKD3D_DATA_FLOAT: +- shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); +- shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[1], ""); +- shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[2], ""); +- shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[3], ""); ++ if (untyped) ++ { ++ shader_print_untyped_literal(compiler, "", reg->u.immconst_u32[0], ""); ++ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[1], ""); ++ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[2], ""); ++ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[3], ""); ++ } ++ else ++ { ++ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); ++ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[1], ""); ++ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[2], ""); ++ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[3], ""); ++ } + break; + case VKD3D_DATA_INT: + shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); +@@ -1678,6 +1726,8 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, + struct vkd3d_string_buffer *buffer = &compiler->buffer; + unsigned int i; + ++ compiler->current = ins; ++ + if (ins->predicate) + { + vkd3d_string_buffer_printf(buffer, "("); +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index ca6e3b72de9..aa0dd8f4b0d 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -482,9 +482,23 @@ static void shader_sm1_parse_dst_param(uint32_t param, const struct vkd3d_shader + dst->reg.dimension = VSIR_DIMENSION_SCALAR; + else + dst->reg.dimension = VSIR_DIMENSION_VEC4; +- dst->write_mask = (param & VKD3D_SM1_WRITEMASK_MASK) >> VKD3D_SM1_WRITEMASK_SHIFT; + dst->modifiers = (param & VKD3D_SM1_DST_MODIFIER_MASK) >> VKD3D_SM1_DST_MODIFIER_SHIFT; + dst->shift = (param & VKD3D_SM1_DSTSHIFT_MASK) >> VKD3D_SM1_DSTSHIFT_SHIFT; ++ ++ switch (dst->reg.dimension) ++ { ++ case VSIR_DIMENSION_SCALAR: ++ dst->write_mask = VKD3DSP_WRITEMASK_0; ++ break; ++ ++ case VSIR_DIMENSION_VEC4: ++ dst->write_mask = (param & VKD3D_SM1_WRITEMASK_MASK) >> VKD3D_SM1_WRITEMASK_SHIFT; ++ break; ++ ++ default: ++ dst->write_mask = 0; ++ break; ++ } + } + + static struct signature_element *find_signature_element(const struct shader_signature *signature, +@@ -518,8 +532,6 @@ static struct signature_element *find_signature_element_by_register_index( + return NULL; + } + +-#define SM1_COLOR_REGISTER_OFFSET 8 +- + static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool output, + const char *name, unsigned int index, enum vkd3d_shader_sysval_semantic sysval, + unsigned int register_index, bool is_dcl, unsigned int mask) +@@ -647,15 +659,15 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * + { + case 0: + return add_signature_element(sm1, true, "POSITION", 0, +- VKD3D_SHADER_SV_POSITION, register_index, is_dcl, mask); ++ VKD3D_SHADER_SV_POSITION, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, mask); + + case 1: + return add_signature_element(sm1, true, "FOG", 0, +- VKD3D_SHADER_SV_NONE, register_index, is_dcl, 0x1); ++ VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1); + + case 2: + return add_signature_element(sm1, true, "PSIZE", 0, +- VKD3D_SHADER_SV_NONE, register_index, is_dcl, 0x1); ++ VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1); + + default: + vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX, +@@ -1348,18 +1360,21 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi + sm1->p.shader_desc.flat_constant_count[i].external = get_external_constant_count(sm1, i); + + if (!sm1->p.failed) +- vsir_validate(&sm1->p); ++ ret = vsir_validate(&sm1->p); ++ ++ if (sm1->p.failed && ret >= 0) ++ ret = VKD3D_ERROR_INVALID_SHADER; + +- if (sm1->p.failed) ++ if (ret < 0) + { + WARN("Failed to parse shader.\n"); + shader_sm1_destroy(&sm1->p); +- return VKD3D_ERROR_INVALID_SHADER; ++ return ret; + } + + *parser = &sm1->p; + +- return VKD3D_OK; ++ return ret; + } + + bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +index 63deaaad29a..37ebc73c099 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +@@ -130,13 +130,13 @@ static void skip_dword_unknown(const char **ptr, unsigned int count) + } + } + +-static const char *shader_get_string(const char *data, size_t data_size, DWORD offset) ++static const char *shader_get_string(const char *data, size_t data_size, size_t offset) + { + size_t len, max_len; + + if (offset >= data_size) + { +- WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size); ++ WARN("Invalid offset %#zx (data size %#zx).\n", offset, data_size); + return NULL; + } + +@@ -230,7 +230,7 @@ static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_ + chunk_offset = read_u32(&ptr); + TRACE("chunk %u at offset %#x\n", i, chunk_offset); + +- if (chunk_offset >= data_size || !require_space(chunk_offset, 2, sizeof(DWORD), data_size)) ++ if (chunk_offset >= data_size || !require_space(chunk_offset, 2, sizeof(uint32_t), data_size)) + { + WARN("Invalid chunk offset %#x (data size %zu).\n", chunk_offset, data_size); + vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET, +@@ -399,7 +399,8 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s + + for (i = 0; i < count; ++i) + { +- uint32_t name_offset, mask; ++ size_t name_offset; ++ uint32_t mask; + + e[i].sort_index = i; + +@@ -411,7 +412,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s + name_offset = read_u32(&ptr); + if (!(e[i].semantic_name = shader_get_string(data, section->data.size, name_offset))) + { +- WARN("Invalid name offset %#x (data size %#zx).\n", name_offset, section->data.size); ++ WARN("Invalid name offset %#zx (data size %#zx).\n", name_offset, section->data.size); + vkd3d_free(e); + return VKD3D_ERROR_INVALID_ARGUMENT; + } +@@ -592,7 +593,7 @@ static int shader_parse_descriptor_ranges(struct root_signature_parser_context * + const char *ptr; + unsigned int i; + +- if (!require_space(offset, 5 * count, sizeof(DWORD), context->data_size)) ++ if (!require_space(offset, 5 * count, sizeof(uint32_t), context->data_size)) + { + WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); + return VKD3D_ERROR_INVALID_ARGUMENT; +@@ -623,7 +624,8 @@ static void shader_validate_descriptor_range1(const struct vkd3d_shader_descript + | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE + | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE + | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE +- | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC); ++ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC ++ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS); + + if (unknown_flags) + FIXME("Unknown descriptor range flags %#x.\n", unknown_flags); +@@ -670,7 +672,7 @@ static int shader_parse_descriptor_table(struct root_signature_parser_context *c + unsigned int count; + const char *ptr; + +- if (!require_space(offset, 2, sizeof(DWORD), context->data_size)) ++ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size)) + { + WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); + return VKD3D_ERROR_INVALID_ARGUMENT; +@@ -697,7 +699,7 @@ static int shader_parse_descriptor_table1(struct root_signature_parser_context * + unsigned int count; + const char *ptr; + +- if (!require_space(offset, 2, sizeof(DWORD), context->data_size)) ++ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size)) + { + WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); + return VKD3D_ERROR_INVALID_ARGUMENT; +@@ -722,7 +724,7 @@ static int shader_parse_root_constants(struct root_signature_parser_context *con + { + const char *ptr; + +- if (!require_space(offset, 3, sizeof(DWORD), context->data_size)) ++ if (!require_space(offset, 3, sizeof(uint32_t), context->data_size)) + { + WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); + return VKD3D_ERROR_INVALID_ARGUMENT; +@@ -744,7 +746,7 @@ static int shader_parse_root_descriptor(struct root_signature_parser_context *co + { + const char *ptr; + +- if (!require_space(offset, 2, sizeof(DWORD), context->data_size)) ++ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size)) + { + WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); + return VKD3D_ERROR_INVALID_ARGUMENT; +@@ -776,7 +778,7 @@ static int shader_parse_root_descriptor1(struct root_signature_parser_context *c + { + const char *ptr; + +- if (!require_space(offset, 3, sizeof(DWORD), context->data_size)) ++ if (!require_space(offset, 3, sizeof(uint32_t), context->data_size)) + { + WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); + return VKD3D_ERROR_INVALID_ARGUMENT; +@@ -802,7 +804,7 @@ static int shader_parse_root_parameters(struct root_signature_parser_context *co + unsigned int i; + int ret; + +- if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size)) ++ if (!require_space(offset, 3 * count, sizeof(uint32_t), context->data_size)) + { + WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); + return VKD3D_ERROR_INVALID_ARGUMENT; +@@ -844,13 +846,13 @@ static int shader_parse_root_parameters(struct root_signature_parser_context *co + } + + static int shader_parse_root_parameters1(struct root_signature_parser_context *context, +- uint32_t offset, DWORD count, struct vkd3d_shader_root_parameter1 *parameters) ++ uint32_t offset, unsigned int count, struct vkd3d_shader_root_parameter1 *parameters) + { + const char *ptr; + unsigned int i; + int ret; + +- if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size)) ++ if (!require_space(offset, 3 * count, sizeof(uint32_t), context->data_size)) + { + WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); + return VKD3D_ERROR_INVALID_ARGUMENT; +@@ -897,7 +899,7 @@ static int shader_parse_static_samplers(struct root_signature_parser_context *co + const char *ptr; + unsigned int i; + +- if (!require_space(offset, 13 * count, sizeof(DWORD), context->data_size)) ++ if (!require_space(offset, 13 * count, sizeof(uint32_t), context->data_size)) + { + WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); + return VKD3D_ERROR_INVALID_ARGUMENT; +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index 2424b176068..b39ec204bff 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -2331,8 +2331,8 @@ static const struct sm6_value *sm6_parser_get_value_by_ref(struct sm6_parser *sm + + static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxil_record *record) + { ++ const struct sm6_type *type, *ret_type; + const unsigned int max_count = 15; +- const struct sm6_type *ret_type; + struct sm6_value *fn; + unsigned int i, j; + +@@ -2347,18 +2347,18 @@ static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxi + fn->u.function.name = ""; + } + +- if (!(fn->type = sm6_parser_get_type(sm6, record->operands[0]))) ++ if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) + return false; +- if (!sm6_type_is_function(fn->type)) ++ if (!sm6_type_is_function(type)) + { + WARN("Type is not a function.\n"); + return false; + } +- ret_type = fn->type->u.function->ret_type; ++ ret_type = type->u.function->ret_type; + +- if (!(fn->type = sm6_type_get_pointer_to_type(fn->type, ADDRESS_SPACE_DEFAULT, sm6))) ++ if (!(fn->type = sm6_type_get_pointer_to_type(type, ADDRESS_SPACE_DEFAULT, sm6))) + { +- WARN("Failed to get pointer type for type %u.\n", fn->type->class); ++ WARN("Failed to get pointer type for type %u.\n", type->class); + return false; + } + +@@ -3432,6 +3432,7 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, struct sm6_ + /* Set idx_count to 3 for use with load instructions. + * TODO: set register type from resource type when other types are supported. */ + vsir_register_init(reg, VKD3DSPR_CONSTBUFFER, VKD3D_DATA_FLOAT, 3); ++ reg->dimension = VSIR_DIMENSION_VEC4; + reg->idx[0].offset = id; + register_index_address_init(®->idx[1], operands[2], sm6); + reg->non_uniform = !!sm6_value_get_constant_uint(operands[3]); +@@ -6281,7 +6282,7 @@ int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compi + vkd3d_free(byte_code); + + if (!sm6->p.failed && ret >= 0) +- vsir_validate(&sm6->p); ++ ret = vsir_validate(&sm6->p); + + if (sm6->p.failed && ret >= 0) + ret = VKD3D_ERROR_INVALID_SHADER; +diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c +new file mode 100644 +index 00000000000..17b9627b6bd +--- /dev/null ++++ b/libs/vkd3d/libs/vkd3d-shader/fx.c +@@ -0,0 +1,377 @@ ++/* ++ * FX (Direct3D 9/10/11 effect) support ++ * ++ * Copyright 2023 Nikolay Sivov for CodeWeavers ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#include "hlsl.h" ++ ++struct string_entry ++{ ++ struct rb_entry entry; ++ /* String points to original data, should not be freed. */ ++ const char *string; ++ uint32_t offset; ++}; ++ ++static int string_storage_compare(const void *key, const struct rb_entry *entry) ++{ ++ struct string_entry *string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry); ++ const char *string = key; ++ ++ return strcmp(string, string_entry->string); ++} ++ ++static void string_storage_destroy(struct rb_entry *entry, void *context) ++{ ++ struct string_entry *string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry); ++ ++ vkd3d_free(string_entry); ++} ++ ++struct fx_write_context ++{ ++ struct hlsl_ctx *ctx; ++ ++ struct vkd3d_bytecode_buffer unstructured; ++ struct vkd3d_bytecode_buffer structured; ++ ++ struct rb_tree strings; ++ ++ unsigned int min_technique_version; ++ unsigned int max_technique_version; ++ ++ uint32_t technique_count; ++ uint32_t group_count; ++ int status; ++}; ++ ++static void fx_write_context_init(struct hlsl_ctx *ctx, struct fx_write_context *fx) ++{ ++ unsigned int version = ctx->profile->major_version; ++ ++ memset(fx, 0, sizeof(*fx)); ++ ++ fx->ctx = ctx; ++ if (version == 2) ++ { ++ fx->min_technique_version = 9; ++ fx->max_technique_version = 9; ++ } ++ else if (version == 4) ++ { ++ fx->min_technique_version = 10; ++ fx->max_technique_version = 10; ++ } ++ else if (version == 5) ++ { ++ fx->min_technique_version = 10; ++ fx->max_technique_version = 11; ++ } ++ ++ rb_init(&fx->strings, string_storage_compare); ++} ++ ++static int fx_write_context_cleanup(struct fx_write_context *fx) ++{ ++ int status = fx->status; ++ rb_destroy(&fx->strings, string_storage_destroy, NULL); ++ ++ return status; ++} ++ ++static bool technique_matches_version(const struct hlsl_ir_var *var, const struct fx_write_context *fx) ++{ ++ const struct hlsl_type *type = var->data_type; ++ ++ if (type->base_type != HLSL_TYPE_TECHNIQUE) ++ return false; ++ ++ return type->e.version >= fx->min_technique_version && type->e.version <= fx->max_technique_version; ++} ++ ++static uint32_t fx_put_raw_string(struct fx_write_context *fx, const char *string) ++{ ++ struct string_entry *string_entry; ++ struct rb_entry *entry; ++ ++ /* NULLs are emitted as empty strings using the same 4 bytes at the start of the section. */ ++ if (!string) ++ return 0; ++ ++ if ((entry = rb_get(&fx->strings, string))) ++ { ++ string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry); ++ return string_entry->offset; ++ } ++ ++ if (!(string_entry = hlsl_alloc(fx->ctx, sizeof(*string_entry)))) ++ return 0; ++ ++ string_entry->offset = put_string(&fx->unstructured, string); ++ string_entry->string = string; ++ ++ rb_put(&fx->strings, string, &string_entry->entry); ++ ++ return string_entry->offset; ++} ++ ++static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) ++{ ++ struct vkd3d_bytecode_buffer *buffer = &fx->structured; ++ uint32_t name_offset; ++ ++ name_offset = fx_put_raw_string(fx, var->name); ++ put_u32(buffer, name_offset); ++ put_u32(buffer, 0); /* Annotation count. */ ++ put_u32(buffer, 0); /* Assignment count. */ ++} ++ ++static void write_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) ++{ ++ struct vkd3d_bytecode_buffer *buffer = &fx->structured; ++ uint32_t name_offset, count = 0; ++ struct hlsl_ir_var *pass; ++ uint32_t count_offset; ++ ++ name_offset = fx_put_raw_string(fx, var->name); ++ put_u32(buffer, name_offset); ++ count_offset = put_u32(buffer, 0); ++ put_u32(buffer, 0); /* Annotation count. */ ++ ++ LIST_FOR_EACH_ENTRY(pass, &var->scope->vars, struct hlsl_ir_var, scope_entry) ++ { ++ write_pass(pass, fx); ++ ++count; ++ } ++ ++ set_u32(buffer, count_offset, count); ++} ++ ++static void set_status(struct fx_write_context *fx, int status) ++{ ++ if (fx->status < 0) ++ return; ++ if (status < 0) ++ fx->status = status; ++} ++ ++static void write_techniques(struct hlsl_scope *scope, struct fx_write_context *fx) ++{ ++ struct hlsl_ir_var *var; ++ ++ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) ++ { ++ const struct hlsl_type *type = var->data_type; ++ ++ if (type->base_type == HLSL_TYPE_TECHNIQUE && type->e.version == 10) ++ { ++ write_technique(var, fx); ++ ++fx->technique_count; ++ } ++ } ++ ++ set_status(fx, fx->unstructured.status); ++ set_status(fx, fx->structured.status); ++} ++ ++static void write_group(struct hlsl_scope *scope, const char *name, struct fx_write_context *fx) ++{ ++ struct vkd3d_bytecode_buffer *buffer = &fx->structured; ++ uint32_t name_offset = fx_put_raw_string(fx, name); ++ uint32_t count_offset, count; ++ ++ put_u32(buffer, name_offset); ++ count_offset = put_u32(buffer, 0); /* Technique count */ ++ put_u32(buffer, 0); /* Annotation count */ ++ ++ count = fx->technique_count; ++ write_techniques(scope, fx); ++ set_u32(buffer, count_offset, fx->technique_count - count); ++ ++ ++fx->group_count; ++} ++ ++static void write_groups(struct hlsl_scope *scope, struct fx_write_context *fx) ++{ ++ bool needs_default_group = false; ++ struct hlsl_ir_var *var; ++ ++ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) ++ { ++ if (technique_matches_version(var, fx)) ++ { ++ needs_default_group = true; ++ break; ++ } ++ } ++ ++ if (needs_default_group) ++ write_group(scope, NULL, fx); ++ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) ++ { ++ const struct hlsl_type *type = var->data_type; ++ ++ if (type->base_type == HLSL_TYPE_EFFECT_GROUP) ++ write_group(var->scope, var->name, fx); ++ } ++} ++ ++static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) ++{ ++ struct vkd3d_bytecode_buffer buffer = { 0 }; ++ struct fx_write_context fx; ++ uint32_t size_offset, size; ++ ++ fx_write_context_init(ctx, &fx); ++ ++ put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ ++ ++ /* TODO: buffers */ ++ /* TODO: objects */ ++ /* TODO: shared buffers */ ++ /* TODO: shared objects */ ++ ++ write_techniques(ctx->globals, &fx); ++ ++ put_u32(&buffer, ctx->profile->minor_version == 0 ? 0xfeff1001 : 0xfeff1011); /* Version. */ ++ put_u32(&buffer, 0); /* Buffer count. */ ++ put_u32(&buffer, 0); /* Variable count. */ ++ put_u32(&buffer, 0); /* Object count. */ ++ put_u32(&buffer, 0); /* Pool buffer count. */ ++ put_u32(&buffer, 0); /* Pool variable count. */ ++ put_u32(&buffer, 0); /* Pool object count. */ ++ put_u32(&buffer, fx.technique_count); ++ size_offset = put_u32(&buffer, 0); /* Unstructured size. */ ++ put_u32(&buffer, 0); /* String count. */ ++ put_u32(&buffer, 0); /* Texture object count. */ ++ put_u32(&buffer, 0); /* Depth stencil state count. */ ++ put_u32(&buffer, 0); /* Blend state count. */ ++ put_u32(&buffer, 0); /* Rasterizer state count. */ ++ put_u32(&buffer, 0); /* Sampler state count. */ ++ put_u32(&buffer, 0); /* Rendertarget view count. */ ++ put_u32(&buffer, 0); /* Depth stencil view count. */ ++ put_u32(&buffer, 0); /* Shader count. */ ++ put_u32(&buffer, 0); /* Inline shader count. */ ++ ++ size = align(fx.unstructured.size, 4); ++ set_u32(&buffer, size_offset, size); ++ ++ bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size); ++ bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size); ++ ++ vkd3d_free(fx.unstructured.data); ++ vkd3d_free(fx.structured.data); ++ ++ set_status(&fx, buffer.status); ++ ++ if (!fx.status) ++ { ++ out->code = buffer.data; ++ out->size = buffer.size; ++ } ++ ++ if (fx.status < 0) ++ ctx->result = fx.status; ++ ++ return fx_write_context_cleanup(&fx); ++} ++ ++static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) ++{ ++ struct vkd3d_bytecode_buffer buffer = { 0 }; ++ struct fx_write_context fx; ++ uint32_t size_offset, size; ++ ++ fx_write_context_init(ctx, &fx); ++ ++ put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ ++ ++ /* TODO: buffers */ ++ /* TODO: objects */ ++ /* TODO: interface variables */ ++ ++ write_groups(ctx->globals, &fx); ++ ++ put_u32(&buffer, 0xfeff2001); /* Version. */ ++ put_u32(&buffer, 0); /* Buffer count. */ ++ put_u32(&buffer, 0); /* Variable count. */ ++ put_u32(&buffer, 0); /* Object count. */ ++ put_u32(&buffer, 0); /* Pool buffer count. */ ++ put_u32(&buffer, 0); /* Pool variable count. */ ++ put_u32(&buffer, 0); /* Pool object count. */ ++ put_u32(&buffer, fx.technique_count); ++ size_offset = put_u32(&buffer, 0); /* Unstructured size. */ ++ put_u32(&buffer, 0); /* String count. */ ++ put_u32(&buffer, 0); /* Texture object count. */ ++ put_u32(&buffer, 0); /* Depth stencil state count. */ ++ put_u32(&buffer, 0); /* Blend state count. */ ++ put_u32(&buffer, 0); /* Rasterizer state count. */ ++ put_u32(&buffer, 0); /* Sampler state count. */ ++ put_u32(&buffer, 0); /* Rendertarget view count. */ ++ put_u32(&buffer, 0); /* Depth stencil view count. */ ++ put_u32(&buffer, 0); /* Shader count. */ ++ put_u32(&buffer, 0); /* Inline shader count. */ ++ put_u32(&buffer, fx.group_count); /* Group count. */ ++ put_u32(&buffer, 0); /* UAV count. */ ++ put_u32(&buffer, 0); /* Interface variables count. */ ++ put_u32(&buffer, 0); /* Interface variable element count. */ ++ put_u32(&buffer, 0); /* Class instance elements count. */ ++ ++ size = align(fx.unstructured.size, 4); ++ set_u32(&buffer, size_offset, size); ++ ++ bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size); ++ bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size); ++ ++ vkd3d_free(fx.unstructured.data); ++ vkd3d_free(fx.structured.data); ++ ++ set_status(&fx, buffer.status); ++ ++ if (!fx.status) ++ { ++ out->code = buffer.data; ++ out->size = buffer.size; ++ } ++ ++ if (fx.status < 0) ++ ctx->result = fx.status; ++ ++ return fx_write_context_cleanup(&fx); ++} ++ ++int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) ++{ ++ if (ctx->profile->major_version == 2) ++ { ++ hlsl_fixme(ctx, &ctx->location, "Writing fx_2_0 binaries is not implemented."); ++ return VKD3D_ERROR_NOT_IMPLEMENTED; ++ } ++ else if (ctx->profile->major_version == 4) ++ { ++ return hlsl_fx_4_write(ctx, out); ++ } ++ else if (ctx->profile->major_version == 5) ++ { ++ return hlsl_fx_5_write(ctx, out); ++ } ++ else ++ { ++ vkd3d_unreachable(); ++ } ++} +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +index da3bbda1bc3..1e247445119 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +@@ -98,19 +98,22 @@ bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var + struct hlsl_scope *scope = ctx->cur_scope; + struct hlsl_ir_var *var; + +- LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) +- { +- if (!strcmp(decl->name, var->name)) +- return false; +- } +- if (local_var && scope->upper->upper == ctx->globals) ++ if (decl->name) + { +- /* Check whether the variable redefines a function parameter. */ +- LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry) ++ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) + { +- if (!strcmp(decl->name, var->name)) ++ if (var->name && !strcmp(decl->name, var->name)) + return false; + } ++ if (local_var && scope->upper->upper == ctx->globals) ++ { ++ /* Check whether the variable redefines a function parameter. */ ++ LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry) ++ { ++ if (var->name && !strcmp(decl->name, var->name)) ++ return false; ++ } ++ } + } + + list_add_tail(&scope->vars, &decl->scope_entry); +@@ -123,7 +126,7 @@ struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name) + + LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) + { +- if (!strcmp(name, var->name)) ++ if (var->name && !strcmp(name, var->name)) + return var; + } + if (!scope->upper) +@@ -915,12 +918,17 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 + if (t1->class == HLSL_CLASS_ARRAY) + return t1->e.array.elements_count == t2->e.array.elements_count + && hlsl_types_are_equal(t1->e.array.type, t2->e.array.type); ++ if (t1->class == HLSL_CLASS_OBJECT) ++ { ++ if (t1->base_type == HLSL_TYPE_TECHNIQUE && t1->e.version != t2->e.version) ++ return false; ++ } + + return true; + } + + struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, +- unsigned int default_majority, unsigned int modifiers) ++ unsigned int default_majority, uint32_t modifiers) + { + struct hlsl_type *type; + +@@ -993,6 +1001,13 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, + break; + } + ++ case HLSL_CLASS_OBJECT: ++ { ++ if (type->base_type == HLSL_TYPE_TECHNIQUE) ++ type->e.version = old->e.version; ++ break; ++ } ++ + default: + break; + } +@@ -1030,7 +1045,7 @@ struct hlsl_ir_node *hlsl_new_copy(struct hlsl_ctx *ctx, struct hlsl_ir_node *no + } + + struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type, +- const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, unsigned int modifiers, ++ const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, uint32_t modifiers, + const struct hlsl_reg_reservation *reg_reservation) + { + struct hlsl_ir_var *var; +@@ -1505,7 +1520,7 @@ struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct + return &store->node; + } + +-struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components, ++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_swizzle *swizzle; +@@ -2246,7 +2261,7 @@ const char *debug_hlsl_type(struct hlsl_ctx *ctx, const struct hlsl_type *type) + return ret; + } + +-struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, unsigned int modifiers) ++struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, uint32_t modifiers) + { + struct vkd3d_string_buffer *string; + +@@ -2432,7 +2447,7 @@ const char *debug_hlsl_writemask(unsigned int writemask) + return vkd3d_dbg_sprintf(".%s", string); + } + +-const char *debug_hlsl_swizzle(unsigned int swizzle, unsigned int size) ++const char *debug_hlsl_swizzle(uint32_t swizzle, unsigned int size) + { + static const char components[] = {'x', 'y', 'z', 'w'}; + char string[5]; +@@ -3147,9 +3162,10 @@ void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function + rb_put(&ctx->functions, func->name, &func->entry); + } + +-unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask) ++uint32_t hlsl_map_swizzle(uint32_t swizzle, unsigned int writemask) + { +- unsigned int i, ret = 0; ++ uint32_t ret = 0; ++ unsigned int i; + + /* Leave replicate swizzles alone; some instructions need them. */ + if (swizzle == HLSL_SWIZZLE(X, X, X, X) +@@ -3169,7 +3185,7 @@ unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask) + return ret; + } + +-unsigned int hlsl_swizzle_from_writemask(unsigned int writemask) ++uint32_t hlsl_swizzle_from_writemask(unsigned int writemask) + { + static const unsigned int swizzles[16] = + { +@@ -3210,9 +3226,10 @@ unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second) + return ret; + } + +-unsigned int hlsl_combine_swizzles(unsigned int first, unsigned int second, unsigned int dim) ++uint32_t hlsl_combine_swizzles(uint32_t first, uint32_t second, unsigned int dim) + { +- unsigned int ret = 0, i; ++ uint32_t ret = 0; ++ unsigned int i; + for (i = 0; i < dim; ++i) + { + unsigned int s = hlsl_swizzle_get_component(second, i); +@@ -3349,12 +3366,25 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) + {"float", HLSL_CLASS_SCALAR, HLSL_TYPE_FLOAT, 1, 1}, + {"vector", HLSL_CLASS_VECTOR, HLSL_TYPE_FLOAT, 4, 1}, + {"matrix", HLSL_CLASS_MATRIX, HLSL_TYPE_FLOAT, 4, 4}, ++ {"fxgroup", HLSL_CLASS_OBJECT, HLSL_TYPE_EFFECT_GROUP, 1, 1}, + {"STRING", HLSL_CLASS_OBJECT, HLSL_TYPE_STRING, 1, 1}, + {"TEXTURE", HLSL_CLASS_OBJECT, HLSL_TYPE_TEXTURE, 1, 1}, + {"PIXELSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_PIXELSHADER, 1, 1}, + {"VERTEXSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_VERTEXSHADER, 1, 1}, + }; + ++ static const struct ++ { ++ char *name; ++ unsigned int version; ++ } ++ technique_types[] = ++ { ++ {"technique", 9}, ++ {"technique10", 10}, ++ {"technique11", 11}, ++ }; ++ + for (bt = 0; bt <= HLSL_TYPE_LAST_SCALAR; ++bt) + { + for (y = 1; y <= 4; ++y) +@@ -3459,6 +3489,13 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) + effect_types[i].base_type, effect_types[i].dimx, effect_types[i].dimy); + hlsl_scope_add_type(ctx->globals, type); + } ++ ++ for (i = 0; i < ARRAY_SIZE(technique_types); ++i) ++ { ++ type = hlsl_new_type(ctx, technique_types[i].name, HLSL_CLASS_OBJECT, HLSL_TYPE_TECHNIQUE, 1, 1); ++ type->e.version = technique_types[i].version; ++ hlsl_scope_add_type(ctx->globals, type); ++ } + } + + static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info, +@@ -3594,7 +3631,13 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + +- if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3) ++ if (compile_info->target_type != VKD3D_SHADER_TARGET_FX && profile->type == VKD3D_SHADER_TYPE_EFFECT) ++ { ++ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, ++ "The '%s' target profile is only compatible with the 'fx' target type.", profile->name); ++ return VKD3D_ERROR_INVALID_ARGUMENT; ++ } ++ else if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3) + { + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, + "The '%s' target profile is incompatible with the 'd3dbc' target type.", profile->name); +@@ -3606,6 +3649,12 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d + "The '%s' target profile is incompatible with the 'dxbc-tpf' target type.", profile->name); + return VKD3D_ERROR_INVALID_ARGUMENT; + } ++ else if (compile_info->target_type == VKD3D_SHADER_TARGET_FX && profile->type != VKD3D_SHADER_TYPE_EFFECT) ++ { ++ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, ++ "The '%s' target profile is incompatible with the 'fx' target type.", profile->name); ++ return VKD3D_ERROR_INVALID_ARGUMENT; ++ } + + if (!hlsl_ctx_init(&ctx, compile_info, profile, message_context)) + return VKD3D_ERROR_OUT_OF_MEMORY; +@@ -3630,6 +3679,14 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + ++ if (ctx.profile->type == VKD3D_SHADER_TYPE_EFFECT) ++ { ++ ret = hlsl_emit_effect_binary(&ctx, out); ++ ++ hlsl_ctx_cleanup(&ctx); ++ return ret; ++ } ++ + if ((func = hlsl_get_function(&ctx, entry_point))) + { + LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry) +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +index ca75a1936f1..8bc98b99e8a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +@@ -65,7 +65,7 @@ + #define HLSL_SWIZZLE_MASK (0x3u) + #define HLSL_SWIZZLE_SHIFT(idx) (2u * (idx)) + +-static inline unsigned int hlsl_swizzle_get_component(unsigned int swizzle, unsigned int idx) ++static inline unsigned int hlsl_swizzle_get_component(uint32_t swizzle, unsigned int idx) + { + return (swizzle >> HLSL_SWIZZLE_SHIFT(idx)) & HLSL_SWIZZLE_MASK; + } +@@ -95,6 +95,8 @@ enum hlsl_base_type + HLSL_TYPE_UAV, + HLSL_TYPE_PIXELSHADER, + HLSL_TYPE_VERTEXSHADER, ++ HLSL_TYPE_TECHNIQUE, ++ HLSL_TYPE_EFFECT_GROUP, + HLSL_TYPE_STRING, + HLSL_TYPE_VOID, + }; +@@ -138,8 +140,10 @@ struct hlsl_type + struct rb_entry scope_entry; + + enum hlsl_type_class class; +- /* If type is <= HLSL_CLASS_LAST_NUMERIC, then base_type is <= HLSL_TYPE_LAST_SCALAR. +- * If type is HLSL_CLASS_OBJECT, then base_type is > HLSL_TYPE_LAST_SCALAR. ++ /* If class is <= HLSL_CLASS_LAST_NUMERIC, then base_type is <= HLSL_TYPE_LAST_SCALAR. ++ * If class is HLSL_CLASS_OBJECT, then base_type is > HLSL_TYPE_LAST_SCALAR. ++ * If class is HLSL_CLASS_OBJECT and base_type is HLSL_TYPE_TECHNIQUE, additional version ++ * field is used to distinguish between technique types. + * Otherwise, base_type is not used. */ + enum hlsl_base_type base_type; + +@@ -155,7 +159,7 @@ struct hlsl_type + /* Bitfield for storing type modifiers, subset of HLSL_TYPE_MODIFIERS_MASK. + * Modifiers that don't fall inside this mask are to be stored in the variable in + * hlsl_ir_var.modifiers, or in the struct field in hlsl_ir_field.modifiers. */ +- unsigned int modifiers; ++ uint32_t modifiers; + /* Size of the type values on each dimension. For non-numeric types, they are set for the + * convenience of the sm1/sm4 backends. + * If type is HLSL_CLASS_SCALAR, then both dimx = 1 and dimy = 1. +@@ -191,6 +195,8 @@ struct hlsl_type + /* Format of the data contained within the type if the base_type is HLSL_TYPE_TEXTURE or + * HLSL_TYPE_UAV. */ + struct hlsl_type *resource_format; ++ /* Additional field to distinguish object types. Currently used only for technique types. */ ++ unsigned int version; + } e; + + /* Number of numeric register components used by one value of this type, for each regset. +@@ -234,7 +240,7 @@ struct hlsl_struct_field + /* Bitfield for storing modifiers that are not in HLSL_TYPE_MODIFIERS_MASK (these are stored in + * type->modifiers instead) and that also are specific to the field and not the whole variable. + * In particular, interpolation modifiers. */ +- unsigned int storage_modifiers; ++ uint32_t storage_modifiers; + /* Offset of the field within the type it belongs to, in register components, for each regset. */ + unsigned int reg_offset[HLSL_REGSET_LAST + 1]; + +@@ -392,7 +398,7 @@ struct hlsl_ir_var + /* Buffer where the variable's value is stored, in case it is uniform. */ + struct hlsl_buffer *buffer; + /* Bitfield for storage modifiers (type modifiers are stored in data_type->modifiers). */ +- unsigned int storage_modifiers; ++ uint32_t storage_modifiers; + /* Optional reservations of registers and/or offsets for variables within constant buffers. */ + struct hlsl_reg_reservation reg_reservation; + +@@ -400,6 +406,8 @@ struct hlsl_ir_var + struct list scope_entry; + /* Item entry in hlsl_ctx.extern_vars, if the variable is extern. */ + struct list extern_entry; ++ /* Scope that variable itself defines, used to provide a container for techniques and passes. */ ++ struct hlsl_scope *scope; + + /* Indexes of the IR instructions where the variable is first written and last read (liveness + * range). The IR instructions are numerated starting from 2, because 0 means unused, and 1 +@@ -622,7 +630,7 @@ struct hlsl_ir_swizzle + { + struct hlsl_ir_node node; + struct hlsl_src val; +- DWORD swizzle; ++ uint32_t swizzle; + }; + + struct hlsl_ir_index +@@ -1160,6 +1168,7 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl + + 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); ++int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out); + + bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *chain); + bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struct hlsl_deref *other); +@@ -1250,7 +1259,7 @@ struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct + struct hlsl_ir_node *coords, struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc); + 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, DWORD s, unsigned int components, ++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_var *hlsl_new_synthetic_var(struct hlsl_ctx *ctx, const char *template, + struct hlsl_type *type, const struct vkd3d_shader_location *loc); +@@ -1264,7 +1273,7 @@ struct hlsl_ir_node *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n + struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, + const struct vkd3d_shader_location *loc); + struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type, +- const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, unsigned int modifiers, ++ const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, uint32_t modifiers, + const struct hlsl_reg_reservation *reg_reservation); + struct hlsl_ir_switch_case *hlsl_new_switch_case(struct hlsl_ctx *ctx, unsigned int value, bool is_default, + struct hlsl_block *body, const struct vkd3d_shader_location *loc); +@@ -1286,7 +1295,7 @@ void hlsl_pop_scope(struct hlsl_ctx *ctx); + bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type); + + struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, +- unsigned int default_majority, unsigned int modifiers); ++ unsigned int default_majority, uint32_t modifiers); + unsigned int hlsl_type_component_count(const struct hlsl_type *type); + unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type, enum hlsl_regset regset); + struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type, +@@ -1304,10 +1313,10 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 + const struct hlsl_type *hlsl_get_multiarray_element_type(const struct hlsl_type *type); + unsigned int hlsl_get_multiarray_size(const struct hlsl_type *type); + +-unsigned int hlsl_combine_swizzles(unsigned int first, unsigned int second, unsigned int dim); ++uint32_t hlsl_combine_swizzles(uint32_t first, uint32_t second, unsigned int dim); + unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second); +-unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask); +-unsigned int hlsl_swizzle_from_writemask(unsigned int writemask); ++uint32_t hlsl_map_swizzle(uint32_t swizzle, unsigned int writemask); ++uint32_t hlsl_swizzle_from_writemask(unsigned int writemask); + + struct hlsl_type *hlsl_deref_get_type(struct hlsl_ctx *ctx, const struct hlsl_deref *deref); + enum hlsl_regset hlsl_deref_get_regset(struct hlsl_ctx *ctx, const struct hlsl_deref *deref); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l +index fe838750747..6cef0e02eff 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l +@@ -89,6 +89,7 @@ else {return KW_ELSE; } + extern {return KW_EXTERN; } + false {return KW_FALSE; } + for {return KW_FOR; } ++fxgroup {return KW_FXGROUP; } + GeometryShader {return KW_GEOMETRYSHADER; } + groupshared {return KW_GROUPSHARED; } + if {return KW_IF; } +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index ed053f16312..b11cbde26f1 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -40,7 +40,7 @@ struct parse_parameter + const char *name; + struct hlsl_semantic semantic; + struct hlsl_reg_reservation reg_reservation; +- unsigned int modifiers; ++ uint32_t modifiers; + }; + + struct parse_colon_attribute +@@ -75,7 +75,7 @@ struct parse_variable_def + struct parse_initializer initializer; + + struct hlsl_type *basic_type; +- unsigned int modifiers; ++ uint32_t modifiers; + struct vkd3d_shader_location modifiers_loc; + }; + +@@ -405,7 +405,7 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct + return add_cast(ctx, block, node, dst_type, loc); + } + +-static DWORD add_modifiers(struct hlsl_ctx *ctx, DWORD modifiers, DWORD mod, ++static uint32_t add_modifiers(struct hlsl_ctx *ctx, uint32_t modifiers, uint32_t mod, + const struct vkd3d_shader_location *loc) + { + if (modifiers & mod) +@@ -868,7 +868,7 @@ static const struct hlsl_struct_field *get_struct_field(const struct hlsl_struct + } + + static struct hlsl_type *apply_type_modifiers(struct hlsl_ctx *ctx, struct hlsl_type *type, +- unsigned int *modifiers, bool force_majority, const struct vkd3d_shader_location *loc) ++ uint32_t *modifiers, bool force_majority, const struct vkd3d_shader_location *loc) + { + unsigned int default_majority = 0; + struct hlsl_type *new_type; +@@ -926,7 +926,7 @@ static bool shader_profile_version_lt(const struct hlsl_ctx *ctx, unsigned int m + } + + static bool gen_struct_fields(struct hlsl_ctx *ctx, struct parse_fields *fields, +- struct hlsl_type *type, unsigned int modifiers, struct list *defs) ++ struct hlsl_type *type, uint32_t modifiers, struct list *defs) + { + struct parse_variable_def *v, *v_next; + size_t i = 0; +@@ -1019,7 +1019,7 @@ static bool add_typedef(struct hlsl_ctx *ctx, struct hlsl_type *const orig_type, + } + else + { +- unsigned int var_modifiers = 0; ++ uint32_t var_modifiers = 0; + + if (!(type = apply_type_modifiers(ctx, orig_type, &var_modifiers, true, &v->loc))) + { +@@ -1096,6 +1096,56 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters + return true; + } + ++static bool add_technique(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope, ++ const char *typename, const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_ir_var *var; ++ struct hlsl_type *type; ++ ++ type = hlsl_get_type(ctx->globals, typename, false, false); ++ if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) ++ return false; ++ var->scope = scope; ++ ++ if (!hlsl_add_var(ctx, var, false)) ++ { ++ struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); ++ ++ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, ++ "Identifier \"%s\" was already declared in this scope.", var->name); ++ hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); ++ hlsl_free_var(var); ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope, ++ const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_ir_var *var; ++ struct hlsl_type *type; ++ ++ type = hlsl_get_type(ctx->globals, "fxgroup", false, false); ++ if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) ++ return false; ++ var->scope = scope; ++ ++ if (!hlsl_add_var(ctx, var, false)) ++ { ++ struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); ++ ++ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, ++ "Identifier \"%s\" was already declared in this scope.", var->name); ++ hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); ++ hlsl_free_var(var); ++ return false; ++ } ++ ++ return true; ++} ++ + static struct hlsl_reg_reservation parse_reg_reservation(const char *reg_string) + { + struct hlsl_reg_reservation reservation = {0}; +@@ -1717,7 +1767,7 @@ static enum hlsl_ir_expr_op op_from_assignment(enum parse_assign_op op) + return ops[op]; + } + +-static bool invert_swizzle(unsigned int *swizzle, unsigned int *writemask, unsigned int *ret_width) ++static bool invert_swizzle(uint32_t *swizzle, unsigned int *writemask, unsigned int *ret_width) + { + unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0, new_swizzle = 0; + +@@ -1791,8 +1841,9 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo + else if (lhs->type == HLSL_IR_SWIZZLE) + { + struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(lhs); +- unsigned int width, s = swizzle->swizzle; + struct hlsl_ir_node *new_swizzle; ++ uint32_t s = swizzle->swizzle; ++ unsigned int width; + + if (lhs->data_type->class == HLSL_CLASS_MATRIX) + hlsl_fixme(ctx, &lhs->loc, "Matrix assignment with a writemask."); +@@ -4844,7 +4895,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls + FLOAT floatval; + bool boolval; + char *name; +- DWORD modifiers; ++ uint32_t modifiers; + struct hlsl_ir_node *instr; + struct hlsl_block *block; + struct list *list; +@@ -4887,6 +4938,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls + %token KW_EXTERN + %token KW_FALSE + %token KW_FOR ++%token KW_FXGROUP + %token KW_GEOMETRYSHADER + %token KW_GROUPSHARED + %token KW_IF +@@ -5051,7 +5103,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls + + %type any_identifier + %type var_identifier +-%type technique_name ++%type name_opt + + %type parameter + +@@ -5093,50 +5145,88 @@ hlsl_prog: + destroy_block($2); + } + | hlsl_prog preproc_directive +- | hlsl_prog technique ++ | hlsl_prog global_technique ++ | hlsl_prog effect_group + | hlsl_prog ';' + +-technique_name: ++name_opt: + %empty + { + $$ = NULL; + } + | any_identifier + ++pass: ++ KW_PASS name_opt '{' '}' ++ + pass_list: +- %empty ++ pass ++ | pass_list pass ++ ++passes: ++ scope_start ++ | scope_start pass_list + + technique9: +- KW_TECHNIQUE technique_name '{' pass_list '}' ++ KW_TECHNIQUE name_opt '{' passes '}' + { +- hlsl_fixme(ctx, &@$, "Unsupported \'technique\' declaration."); ++ struct hlsl_scope *scope = ctx->cur_scope; ++ hlsl_pop_scope(ctx); ++ ++ if (!add_technique(ctx, $2, scope, "technique", &@1)) ++ YYABORT; + } + + technique10: +- KW_TECHNIQUE10 technique_name '{' pass_list '}' ++ KW_TECHNIQUE10 name_opt '{' passes '}' + { ++ struct hlsl_scope *scope = ctx->cur_scope; ++ hlsl_pop_scope(ctx); ++ + if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) + hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, + "The 'technique10' keyword is invalid for this profile."); + +- hlsl_fixme(ctx, &@$, "Unsupported \'technique10\' declaration."); ++ if (!add_technique(ctx, $2, scope, "technique10", &@1)) ++ YYABORT; + } + + technique11: +- KW_TECHNIQUE11 technique_name '{' pass_list '}' ++ KW_TECHNIQUE11 name_opt '{' passes '}' + { ++ struct hlsl_scope *scope = ctx->cur_scope; ++ hlsl_pop_scope(ctx); ++ + if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) + hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, + "The 'technique11' keyword is invalid for this profile."); + +- hlsl_fixme(ctx, &@$, "Unsupported \'technique11\' declaration."); ++ if (!add_technique(ctx, $2, scope, "technique11", &@1)) ++ YYABORT; + } + +-technique: ++global_technique: + technique9 + | technique10 + | technique11 + ++group_technique: ++ technique10 ++ | technique11 ++ ++group_techniques: ++ group_technique ++ | group_techniques group_technique ++ ++effect_group: ++ KW_FXGROUP any_identifier '{' scope_start group_techniques '}' ++ { ++ struct hlsl_scope *scope = ctx->cur_scope; ++ hlsl_pop_scope(ctx); ++ if (!(add_effect_group(ctx, $2, scope, &@2))) ++ YYABORT; ++ } ++ + buffer_declaration: + buffer_type any_identifier colon_attribute + { +@@ -5282,7 +5372,7 @@ field: + var_modifiers field_type variables_def ';' + { + struct hlsl_type *type; +- unsigned int modifiers = $1; ++ uint32_t modifiers = $1; + + if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) + YYABORT; +@@ -5435,7 +5525,7 @@ func_prototype_no_attrs: + /* var_modifiers is necessary to avoid shift/reduce conflicts. */ + var_modifiers type var_identifier '(' parameters ')' colon_attribute + { +- unsigned int modifiers = $1; ++ uint32_t modifiers = $1; + struct hlsl_ir_var *var; + struct hlsl_type *type; + +@@ -5709,7 +5799,7 @@ param_list: + parameter: + var_modifiers type_no_void any_identifier arrays colon_attribute + { +- unsigned int modifiers = $1; ++ uint32_t modifiers = $1; + struct hlsl_type *type; + unsigned int i; + +@@ -6023,7 +6113,7 @@ typedef: + KW_TYPEDEF var_modifiers typedef_type type_specs ';' + { + struct parse_variable_def *v, *v_next; +- unsigned int modifiers = $2; ++ uint32_t modifiers = $2; + struct hlsl_type *type; + + if (!(type = apply_type_modifiers(ctx, $3, &modifiers, false, &@2))) +@@ -6160,7 +6250,7 @@ variable_def: + variable_def_typed: + var_modifiers struct_spec variable_def + { +- unsigned int modifiers = $1; ++ uint32_t modifiers = $1; + struct hlsl_type *type; + + if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) +@@ -6175,7 +6265,7 @@ variable_def_typed: + } + | var_modifiers type variable_def + { +- unsigned int modifiers = $1; ++ uint32_t modifiers = $1; + struct hlsl_type *type; + + if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index 88cbef61d5f..d37bef15cce 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -32,6 +32,11 @@ static struct hlsl_ir_node *new_offset_from_path_index(struct hlsl_ctx *ctx, str + switch (type->class) + { + case HLSL_CLASS_VECTOR: ++ if (idx->type != HLSL_IR_CONSTANT) ++ { ++ hlsl_fixme(ctx, &idx->loc, "Non-constant vector addressing."); ++ break; ++ } + *offset_component += hlsl_ir_constant(idx)->value.u[0].u; + break; + +@@ -263,7 +268,7 @@ static bool types_are_semantic_equivalent(struct hlsl_ctx *ctx, const struct hls + } + + static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, +- struct hlsl_type *type, unsigned int modifiers, struct hlsl_semantic *semantic, ++ struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic, + uint32_t index, bool output, const struct vkd3d_shader_location *loc) + { + struct hlsl_semantic new_semantic; +@@ -331,7 +336,7 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir + } + + static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *lhs, +- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) ++ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) + { + struct hlsl_type *type = lhs->node.data_type, *vector_type_src, *vector_type_dst; + struct vkd3d_shader_location *loc = &lhs->node.loc; +@@ -395,7 +400,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, s + } + + static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *lhs, +- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) ++ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) + { + struct vkd3d_shader_location *loc = &lhs->node.loc; + struct hlsl_type *type = lhs->node.data_type; +@@ -411,7 +416,7 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * + + for (i = 0; i < hlsl_type_element_count(type); ++i) + { +- unsigned int element_modifiers = modifiers; ++ uint32_t element_modifiers = modifiers; + + if (type->class == HLSL_CLASS_ARRAY) + { +@@ -473,7 +478,7 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_block *bloc + } + + static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *rhs, +- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) ++ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) + { + struct hlsl_type *type = rhs->node.data_type, *vector_type; + struct vkd3d_shader_location *loc = &rhs->node.loc; +@@ -529,7 +534,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, s + } + + static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *rhs, +- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) ++ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) + { + struct vkd3d_shader_location *loc = &rhs->node.loc; + struct hlsl_type *type = rhs->node.data_type; +@@ -1519,7 +1524,7 @@ static void copy_propagation_set_value(struct hlsl_ctx *ctx, struct copy_propaga + + static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx, + const struct copy_propagation_state *state, const struct hlsl_ir_load *load, +- unsigned int swizzle, struct hlsl_ir_node *instr) ++ uint32_t swizzle, struct hlsl_ir_node *instr) + { + const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type); + const struct hlsl_deref *deref = &load->src; +@@ -1527,7 +1532,7 @@ static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx, + struct hlsl_ir_node *new_instr = NULL; + unsigned int time = load->node.index; + unsigned int start, count, i; +- unsigned int ret_swizzle = 0; ++ uint32_t ret_swizzle = 0; + + if (!hlsl_component_index_range_from_deref(ctx, deref, &start, &count)) + return false; +@@ -1573,7 +1578,7 @@ static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx, + + static bool copy_propagation_replace_with_constant_vector(struct hlsl_ctx *ctx, + const struct copy_propagation_state *state, const struct hlsl_ir_load *load, +- unsigned int swizzle, struct hlsl_ir_node *instr) ++ uint32_t swizzle, struct hlsl_ir_node *instr) + { + const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type); + const struct hlsl_deref *deref = &load->src; +@@ -2239,7 +2244,7 @@ static bool fold_swizzle_chains(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + if (next_instr->type == HLSL_IR_SWIZZLE) + { + struct hlsl_ir_node *new_swizzle; +- unsigned int combined_swizzle; ++ uint32_t combined_swizzle; + + combined_swizzle = hlsl_combine_swizzles(hlsl_ir_swizzle(next_instr)->swizzle, + swizzle->swizzle, instr->data_type->dimx); +@@ -2478,6 +2483,38 @@ static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir + return false; + } + ++static bool validate_nonconstant_vector_store_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) ++{ ++ struct hlsl_ir_node *idx; ++ struct hlsl_deref *deref; ++ struct hlsl_type *type; ++ unsigned int i; ++ ++ if (instr->type != HLSL_IR_STORE) ++ return false; ++ ++ deref = &hlsl_ir_store(instr)->lhs; ++ assert(deref->var); ++ ++ if (deref->path_len == 0) ++ return false; ++ ++ type = deref->var->data_type; ++ for (i = 0; i < deref->path_len - 1; ++i) ++ type = hlsl_get_element_type_from_path_index(ctx, type, deref->path[i].node); ++ ++ idx = deref->path[deref->path_len - 1].node; ++ ++ if (type->class == HLSL_CLASS_VECTOR && idx->type != HLSL_IR_CONSTANT) ++ { ++ /* We should turn this into an hlsl_error after we implement unrolling, because if we get ++ * here after that, it means that the HLSL is invalid. */ ++ hlsl_fixme(ctx, &instr->loc, "Non-constant vector addressing on store. Unrolling may be missing."); ++ } ++ ++ return false; ++} ++ + /* Lower combined samples and sampler variables to synthesized separated textures and samplers. + * That is, translate SM1-style samples in the source to SM4-style samples in the bytecode. */ + static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +@@ -3145,7 +3182,7 @@ static bool lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru + + for (i = 0; i < dimx; ++i) + { +- unsigned int s = hlsl_swizzle_from_writemask(1 << i); ++ uint32_t s = hlsl_swizzle_from_writemask(1 << i); + + if (!(comps[i] = hlsl_new_swizzle(ctx, s, 1, mult, &instr->loc))) + return false; +@@ -4969,6 +5006,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry + lower_ir(ctx, lower_abs, body); + } + ++ lower_ir(ctx, validate_nonconstant_vector_store_derefs, body); ++ + /* TODO: move forward, remove when no longer needed */ + transform_derefs(ctx, replace_deref_path_with_offset, body); + while (hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL)); +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index d38b3c39712..28c7d158452 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -492,7 +492,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i + if (shader_instruction_is_dcl(ins)) + break; + for (j = 0; j < ins->dst_count; ++j) +- shader_dst_param_normalise_outpointid((struct vkd3d_shader_dst_param *)&ins->dst[j], &normaliser); ++ shader_dst_param_normalise_outpointid(&ins->dst[j], &normaliser); + break; + } + } +@@ -533,6 +533,7 @@ struct io_normaliser + { + struct vkd3d_shader_instruction_array instructions; + enum vkd3d_shader_type shader_type; ++ uint8_t major; + struct shader_signature *input_signature; + struct shader_signature *output_signature; + struct shader_signature *patch_constant_signature; +@@ -867,34 +868,65 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par + const struct shader_signature *signature; + const struct signature_element *e; + +- if ((reg->type == VKD3DSPR_OUTPUT && io_normaliser_is_in_fork_or_join_phase(normaliser)) +- || reg->type == VKD3DSPR_PATCHCONST) +- { +- signature = normaliser->patch_constant_signature; +- /* Convert patch constant outputs to the patch constant register type to avoid the need +- * to convert compiler symbols when accessed as inputs in a later stage. */ +- reg->type = VKD3DSPR_PATCHCONST; +- dcl_params = normaliser->pc_dcl_params; +- } +- else if (reg->type == VKD3DSPR_OUTPUT || dst_param->reg.type == VKD3DSPR_COLOROUT) +- { +- signature = normaliser->output_signature; +- reg->type = VKD3DSPR_OUTPUT; +- dcl_params = normaliser->output_dcl_params; +- } +- else if (dst_param->reg.type == VKD3DSPR_INCONTROLPOINT || dst_param->reg.type == VKD3DSPR_INPUT) +- { +- signature = normaliser->input_signature; +- reg->type = VKD3DSPR_INPUT; +- dcl_params = normaliser->input_dcl_params; +- } +- else ++ switch (reg->type) + { +- return true; ++ case VKD3DSPR_OUTPUT: ++ reg_idx = reg->idx[reg->idx_count - 1].offset; ++ if (io_normaliser_is_in_fork_or_join_phase(normaliser)) ++ { ++ signature = normaliser->patch_constant_signature; ++ /* Convert patch constant outputs to the patch constant register type to avoid the need ++ * to convert compiler symbols when accessed as inputs in a later stage. */ ++ reg->type = VKD3DSPR_PATCHCONST; ++ dcl_params = normaliser->pc_dcl_params; ++ } ++ else ++ { ++ signature = normaliser->output_signature; ++ dcl_params = normaliser->output_dcl_params; ++ } ++ break; ++ ++ case VKD3DSPR_PATCHCONST: ++ reg_idx = reg->idx[reg->idx_count - 1].offset; ++ signature = normaliser->patch_constant_signature; ++ dcl_params = normaliser->pc_dcl_params; ++ break; ++ ++ case VKD3DSPR_COLOROUT: ++ reg_idx = reg->idx[0].offset; ++ signature = normaliser->output_signature; ++ reg->type = VKD3DSPR_OUTPUT; ++ dcl_params = normaliser->output_dcl_params; ++ break; ++ ++ case VKD3DSPR_INCONTROLPOINT: ++ case VKD3DSPR_INPUT: ++ reg_idx = reg->idx[reg->idx_count - 1].offset; ++ signature = normaliser->input_signature; ++ reg->type = VKD3DSPR_INPUT; ++ dcl_params = normaliser->input_dcl_params; ++ break; ++ ++ case VKD3DSPR_ATTROUT: ++ reg_idx = SM1_COLOR_REGISTER_OFFSET + reg->idx[0].offset; ++ signature = normaliser->output_signature; ++ reg->type = VKD3DSPR_OUTPUT; ++ dcl_params = normaliser->output_dcl_params; ++ break; ++ ++ case VKD3DSPR_RASTOUT: ++ reg_idx = SM1_RASTOUT_REGISTER_OFFSET + reg->idx[0].offset; ++ signature = normaliser->output_signature; ++ reg->type = VKD3DSPR_OUTPUT; ++ dcl_params = normaliser->output_dcl_params; ++ break; ++ ++ default: ++ return true; + } + + id_idx = reg->idx_count - 1; +- reg_idx = reg->idx[id_idx].offset; + write_mask = dst_param->write_mask; + element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); + e = &signature->elements[element_idx]; +@@ -982,26 +1014,42 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par + switch (reg->type) + { + case VKD3DSPR_PATCHCONST: ++ reg_idx = reg->idx[reg->idx_count - 1].offset; + signature = normaliser->patch_constant_signature; + break; ++ + case VKD3DSPR_INCONTROLPOINT: + reg->type = VKD3DSPR_INPUT; + /* fall through */ + case VKD3DSPR_INPUT: ++ if (normaliser->major < 3 && normaliser->shader_type == VKD3D_SHADER_TYPE_PIXEL) ++ reg_idx = SM1_COLOR_REGISTER_OFFSET + reg->idx[0].offset; ++ else ++ reg_idx = reg->idx[reg->idx_count - 1].offset; + signature = normaliser->input_signature; + break; ++ + case VKD3DSPR_OUTCONTROLPOINT: + reg->type = VKD3DSPR_OUTPUT; + /* fall through */ + case VKD3DSPR_OUTPUT: ++ reg_idx = reg->idx[reg->idx_count - 1].offset; + signature = normaliser->output_signature; + break; ++ ++ case VKD3DSPR_TEXTURE: ++ if (normaliser->shader_type != VKD3D_SHADER_TYPE_PIXEL) ++ return; ++ reg->type = VKD3DSPR_INPUT; ++ reg_idx = reg->idx[0].offset; ++ signature = normaliser->input_signature; ++ break; ++ + default: + return; + } + + id_idx = reg->idx_count - 1; +- reg_idx = reg->idx[id_idx].offset; + write_mask = VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(src_param->swizzle, 0); + element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); + +@@ -1068,9 +1116,9 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi + if (shader_instruction_is_dcl(ins)) + break; + for (i = 0; i < ins->dst_count; ++i) +- shader_dst_param_io_normalise((struct vkd3d_shader_dst_param *)&ins->dst[i], false, normaliser); ++ shader_dst_param_io_normalise(&ins->dst[i], false, normaliser); + for (i = 0; i < ins->src_count; ++i) +- shader_src_param_io_normalise((struct vkd3d_shader_src_param *)&ins->src[i], normaliser); ++ shader_src_param_io_normalise(&ins->src[i], normaliser); + break; + } + } +@@ -1084,6 +1132,7 @@ static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parse + + normaliser.phase = VKD3DSIH_INVALID; + normaliser.shader_type = parser->shader_version.type; ++ normaliser.major = parser->shader_version.major; + normaliser.input_signature = &parser->shader_desc.input_signature; + normaliser.output_signature = &parser->shader_desc.output_signature; + normaliser.patch_constant_signature = &parser->shader_desc.patch_constant_signature; +@@ -1261,7 +1310,7 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d + else + { + for (j = 0; j < ins->src_count; ++j) +- shader_register_normalise_flat_constants((struct vkd3d_shader_src_param *)&ins->src[j], &normaliser); ++ shader_register_normalise_flat_constants(&ins->src[j], &normaliser); + } + } + +@@ -1462,7 +1511,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, + vkd3d_shader_trace(instructions, &parser->shader_version); + + if (result >= 0 && !parser->failed) +- vsir_validate(parser); ++ result = vsir_validate(parser); + + if (result >= 0 && parser->failed) + result = VKD3D_ERROR_INVALID_SHADER; +@@ -1474,10 +1523,26 @@ struct validation_context + { + struct vkd3d_shader_parser *parser; + size_t instruction_idx; ++ bool invalid_instruction_idx; + bool dcl_temps_found; + unsigned int temp_count; + enum vkd3d_shader_opcode phase; + ++ struct validation_context_temp_data ++ { ++ enum vsir_dimension dimension; ++ size_t first_seen; ++ } *temps; ++ ++ struct validation_context_ssa_data ++ { ++ enum vsir_dimension dimension; ++ 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; +@@ -1495,8 +1560,16 @@ static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *c + vkd3d_string_buffer_vprintf(&buf, format, args); + va_end(args); + +- vkd3d_shader_parser_error(ctx->parser, error, "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer); +- ERR("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer); ++ if (ctx->invalid_instruction_idx) ++ { ++ vkd3d_shader_parser_error(ctx->parser, error, "%s", buf.buffer); ++ ERR("VSIR validation error: %s\n", buf.buffer); ++ } ++ else ++ { ++ vkd3d_shader_parser_error(ctx->parser, error, "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer); ++ ERR("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer); ++ } + + vkd3d_string_buffer_cleanup(&buf); + } +@@ -1543,17 +1616,101 @@ 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_count >= 1 && reg->idx[0].rel_addr) ++ 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_count >= 1 && reg->idx[0].offset >= temp_count) ++ if (reg->idx[0].offset >= temp_count) ++ { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "TEMP register index %u exceeds the maximum count %u.", + reg->idx[0].offset, temp_count); ++ break; ++ } ++ ++ /* parser->shader_desc.temp_count might be smaller then ++ * temp_count if the parser made a mistake; we still don't ++ * want to overflow the array. */ ++ if (reg->idx[0].offset >= ctx->parser->shader_desc.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); ++ } ++ 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->parser->shader_desc.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->parser->shader_desc.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->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); ++ } + break; ++ } + + case VKD3DSPR_NULL: + if (reg->idx_count != 0) +@@ -1587,6 +1744,26 @@ static void vsir_validate_dst_param(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Destination has invalid write mask %#x.", + dst->write_mask); + ++ switch (dst->reg.dimension) ++ { ++ case VSIR_DIMENSION_SCALAR: ++ if (dst->write_mask != VKD3DSP_WRITEMASK_0) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Scalar destination has invalid write mask %#x.", ++ dst->write_mask); ++ break; ++ ++ case VSIR_DIMENSION_VEC4: ++ if (dst->write_mask == 0) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Vec4 destination has empty write mask."); ++ break; ++ ++ default: ++ if (dst->write_mask != 0) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Destination of dimension %u has invalid write mask %#x.", ++ dst->reg.dimension, dst->write_mask); ++ break; ++ } ++ + if (dst->modifiers & ~VKD3DSPDM_MASK) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Destination has invalid modifiers %#x.", + dst->modifiers); +@@ -1606,6 +1783,23 @@ static void vsir_validate_dst_param(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT, "Destination has invalid shift %#x.", + dst->shift); + } ++ ++ if (dst->reg.type == VKD3DSPR_SSA && dst->reg.idx[0].offset < ctx->parser->shader_desc.ssa_count) ++ { ++ struct validation_context_ssa_data *data = &ctx->ssas[dst->reg.idx[0].offset]; ++ ++ if (data->write_mask == 0) ++ { ++ data->write_mask = dst->write_mask; ++ data->first_assigned = ctx->instruction_idx; ++ } ++ else ++ { ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE, ++ "SSA register is already assigned at instruction %zu.", ++ data->first_assigned); ++ } ++ } + } + + static void vsir_validate_src_param(struct validation_context *ctx, +@@ -1617,9 +1811,22 @@ static void vsir_validate_src_param(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source has invalid swizzle %#x.", + src->swizzle); + ++ if (src->reg.dimension != VSIR_DIMENSION_VEC4 && src->swizzle != 0) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source of dimension %u has invalid swizzle %#x.", ++ src->reg.dimension, src->swizzle); ++ + if (src->modifiers >= VKD3DSPSM_COUNT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", + src->modifiers); ++ ++ if (src->reg.type == VKD3DSPR_SSA && src->reg.idx[0].offset < ctx->parser->shader_desc.ssa_count) ++ { ++ struct validation_context_ssa_data *data = &ctx->ssas[src->reg.idx[0].offset]; ++ unsigned int i; ++ ++ for (i = 0; i < VKD3D_VEC4_SIZE; ++i) ++ data->read_mask |= (1u << vsir_swizzle_get_component(src->swizzle, i)); ++ } + } + + static void vsir_validate_dst_count(struct validation_context *ctx, +@@ -1791,22 +1998,52 @@ static void vsir_validate_instruction(struct validation_context *ctx) + } + } + +-void vsir_validate(struct vkd3d_shader_parser *parser) ++enum vkd3d_result vsir_validate(struct vkd3d_shader_parser *parser) + { + struct validation_context ctx = + { + .parser = parser, + .phase = VKD3DSIH_INVALID, + }; ++ unsigned int i; + + if (!(parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)) +- return; ++ return VKD3D_OK; ++ ++ if (!(ctx.temps = vkd3d_calloc(parser->shader_desc.temp_count, sizeof(*ctx.temps)))) ++ goto fail; ++ ++ if (!(ctx.ssas = vkd3d_calloc(parser->shader_desc.ssa_count, sizeof(*ctx.ssas)))) ++ goto fail; + + for (ctx.instruction_idx = 0; ctx.instruction_idx < parser->instructions.count; ++ctx.instruction_idx) + vsir_validate_instruction(&ctx); + ++ ctx.invalid_instruction_idx = true; ++ + if (ctx.depth != 0) + validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "%zu nested blocks were not closed.", ctx.depth); + +- free(ctx.blocks); ++ for (i = 0; i < parser->shader_desc.ssa_count; ++i) ++ { ++ struct validation_context_ssa_data *data = &ctx.ssas[i]; ++ ++ if ((data->write_mask | data->read_mask) != data->write_mask) ++ validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE, ++ "SSA register %u has invalid read mask %#x, which is not a subset of the write mask %#x " ++ "at the point of definition.", i, data->read_mask, data->write_mask); ++ } ++ ++ vkd3d_free(ctx.blocks); ++ vkd3d_free(ctx.temps); ++ vkd3d_free(ctx.ssas); ++ ++ return VKD3D_OK; ++ ++fail: ++ vkd3d_free(ctx.blocks); ++ vkd3d_free(ctx.temps); ++ vkd3d_free(ctx.ssas); ++ ++ return VKD3D_ERROR_OUT_OF_MEMORY; + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index 387784f2358..7743319bed5 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -1764,6 +1764,15 @@ static uint32_t vkd3d_spirv_build_op_glsl_std450_max(struct vkd3d_spirv_builder + GLSLstd450NMax, operands, ARRAY_SIZE(operands)); + } + ++static uint32_t vkd3d_spirv_build_op_glsl_std450_umin(struct vkd3d_spirv_builder *builder, ++ uint32_t result_type, uint32_t x, uint32_t y) ++{ ++ uint32_t glsl_std450_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); ++ uint32_t operands[] = {x, y}; ++ return vkd3d_spirv_build_op_ext_inst(builder, result_type, glsl_std450_id, ++ GLSLstd450UMin, operands, ARRAY_SIZE(operands)); ++} ++ + static uint32_t vkd3d_spirv_build_op_glsl_std450_nclamp(struct vkd3d_spirv_builder *builder, + uint32_t result_type, uint32_t x, uint32_t min, uint32_t max) + { +@@ -2189,7 +2198,7 @@ static void vkd3d_symbol_make_io(struct vkd3d_symbol *symbol, + + static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol, + uint32_t val_id, SpvStorageClass storage_class, +- enum vkd3d_shader_component_type component_type, DWORD write_mask) ++ enum vkd3d_shader_component_type component_type, uint32_t write_mask) + { + symbol->id = val_id; + symbol->descriptor_array = NULL; +@@ -3361,7 +3370,7 @@ static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *comp + } + + static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, +- const struct vkd3d_shader_src_param *src, DWORD write_mask); ++ const struct vkd3d_shader_src_param *src, uint32_t write_mask); + + static uint32_t spirv_compiler_emit_register_addressing(struct spirv_compiler *compiler, + const struct vkd3d_shader_register_index *reg_index) +@@ -3600,8 +3609,7 @@ static uint32_t spirv_compiler_get_register_id(struct spirv_compiler *compiler, + SpvStorageClassPrivate, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); + } + +-static bool vkd3d_swizzle_is_equal(unsigned int dst_write_mask, +- unsigned int swizzle, unsigned int write_mask) ++static bool vkd3d_swizzle_is_equal(uint32_t dst_write_mask, uint32_t swizzle, uint32_t write_mask) + { + return vkd3d_compact_swizzle(VKD3D_SHADER_NO_SWIZZLE, dst_write_mask) == vkd3d_compact_swizzle(swizzle, write_mask); + } +@@ -3913,7 +3921,7 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler + } + + static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask) ++ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + enum vkd3d_shader_component_type component_type; +@@ -3989,7 +3997,7 @@ static void spirv_compiler_emit_execution_mode1(struct spirv_compiler *compiler, + } + + static uint32_t spirv_compiler_emit_abs(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id) ++ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id; +@@ -4003,7 +4011,7 @@ static uint32_t spirv_compiler_emit_abs(struct spirv_compiler *compiler, + } + + static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id) ++ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id; +@@ -4019,7 +4027,7 @@ static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, + } + + static uint32_t spirv_compiler_emit_src_modifier(struct spirv_compiler *compiler, +- const struct vkd3d_shader_register *reg, DWORD write_mask, ++ const struct vkd3d_shader_register *reg, uint32_t write_mask, + enum vkd3d_shader_src_modifier modifier, uint32_t val_id) + { + switch (modifier) +@@ -4042,7 +4050,7 @@ static uint32_t spirv_compiler_emit_src_modifier(struct spirv_compiler *compiler + } + + static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, +- const struct vkd3d_shader_src_param *src, DWORD write_mask) ++ const struct vkd3d_shader_src_param *src, uint32_t write_mask) + { + uint32_t val_id; + +@@ -4051,7 +4059,7 @@ static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, + } + + static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *compiler, +- const struct vkd3d_shader_src_param *src, DWORD write_mask, enum vkd3d_shader_component_type component_type) ++ const struct vkd3d_shader_src_param *src, uint32_t write_mask, enum vkd3d_shader_component_type component_type) + { + struct vkd3d_shader_src_param src_param = *src; + +@@ -4209,7 +4217,7 @@ static void spirv_compiler_emit_store_dst(struct spirv_compiler *compiler, + + static void spirv_compiler_emit_store_dst_swizzled(struct spirv_compiler *compiler, + const struct vkd3d_shader_dst_param *dst, uint32_t val_id, +- enum vkd3d_shader_component_type component_type, DWORD swizzle) ++ enum vkd3d_shader_component_type component_type, uint32_t swizzle) + { + struct vkd3d_shader_dst_param typed_dst = *dst; + val_id = spirv_compiler_emit_swizzle(compiler, +@@ -6899,8 +6907,8 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t src_id[SPIRV_MAX_SRC_COUNT]; + uint32_t instr_set_id, type_id, val_id; ++ unsigned int i, component_count; + enum GLSLstd450 glsl_inst; +- unsigned int i; + + glsl_inst = spirv_compiler_map_ext_glsl_instruction(instruction); + if (glsl_inst == GLSLstd450Bad) +@@ -6926,8 +6934,9 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp + || instruction->handler_idx == VKD3DSIH_FIRSTBIT_SHI) + { + /* In D3D bits are numbered from the most significant bit. */ ++ component_count = vsir_write_mask_component_count(dst->write_mask); + val_id = vkd3d_spirv_build_op_isub(builder, type_id, +- spirv_compiler_get_constant_uint(compiler, 31), val_id); ++ spirv_compiler_get_constant_uint_vector(compiler, 31, component_count), val_id); + } + + spirv_compiler_emit_store_dst(compiler, dst, val_id); +@@ -7060,7 +7069,7 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, + enum vkd3d_shader_component_type component_type; + uint32_t type_id, val_id, src_ids[2]; + unsigned int component_count, i; +- DWORD write_mask; ++ uint32_t write_mask; + + component_count = vsir_write_mask_component_count(dst->write_mask); + component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); +@@ -7356,13 +7365,13 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, + static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { +- uint32_t src_ids[4], constituents[VKD3D_VEC4_SIZE], type_id, mask_id; ++ uint32_t src_ids[4], constituents[VKD3D_VEC4_SIZE], type_id, mask_id, size_id, max_count_id; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + enum vkd3d_shader_component_type component_type; + unsigned int i, j, k, src_count; +- DWORD write_mask; ++ uint32_t write_mask; + SpvOp op; + + src_count = instruction->src_count; +@@ -7371,6 +7380,7 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp + component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); + type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); + mask_id = spirv_compiler_get_constant_uint(compiler, 0x1f); ++ size_id = spirv_compiler_get_constant_uint(compiler, 0x20); + + switch (instruction->handler_idx) + { +@@ -7399,6 +7409,9 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp + { + src_ids[j] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[j], mask_id); + } ++ max_count_id = vkd3d_spirv_build_op_isub(builder, type_id, size_id, src_ids[src_count - 2]); ++ src_ids[src_count - 1] = vkd3d_spirv_build_op_glsl_std450_umin(builder, type_id, ++ src_ids[src_count - 1], max_count_id); + + constituents[k++] = vkd3d_spirv_build_op_trv(builder, &builder->function_stream, + op, type_id, src_ids, src_count); +@@ -7415,8 +7428,8 @@ static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler, + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t components[VKD3D_VEC4_SIZE]; ++ uint32_t write_mask; + unsigned int i, j; +- DWORD write_mask; + + instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); +@@ -7448,8 +7461,8 @@ static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler, + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t components[VKD3D_VEC4_SIZE]; ++ uint32_t write_mask; + unsigned int i, j; +- DWORD write_mask; + + instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); +@@ -8214,7 +8227,7 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, + unsigned int image_operand_count = 0; + struct vkd3d_shader_image image; + uint32_t image_operands[2]; +- DWORD coordinate_mask; ++ uint32_t coordinate_mask; + bool multisample; + + multisample = instruction->handler_idx == VKD3DSIH_LD2DMS; +@@ -8288,7 +8301,7 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, + unsigned int image_operand_count = 0; + struct vkd3d_shader_image image; + uint32_t image_operands[3]; +- DWORD coordinate_mask; ++ uint32_t coordinate_mask; + SpvOp op; + + resource = &src[1]; +@@ -8404,7 +8417,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, + struct vkd3d_shader_image image; + unsigned int component_idx; + uint32_t image_operands[1]; +- DWORD coordinate_mask; ++ uint32_t coordinate_mask; + bool extended_offset; + + if (instruction->handler_idx == VKD3DSIH_GATHER4_C +@@ -8464,13 +8477,13 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, + + static uint32_t spirv_compiler_emit_raw_structured_addressing( + struct spirv_compiler *compiler, uint32_t type_id, unsigned int stride, +- const struct vkd3d_shader_src_param *src0, DWORD src0_mask, +- const struct vkd3d_shader_src_param *src1, DWORD src1_mask) ++ const struct vkd3d_shader_src_param *src0, uint32_t src0_mask, ++ const struct vkd3d_shader_src_param *src1, uint32_t src1_mask) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_src_param *offset; + uint32_t structure_id = 0, offset_id; +- DWORD offset_write_mask; ++ uint32_t offset_write_mask; + + if (stride) + { +@@ -8779,7 +8792,7 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, + const struct vkd3d_shader_src_param *src = instruction->src; + const struct vkd3d_symbol *resource_symbol; + struct vkd3d_shader_image image; +- DWORD coordinate_mask; ++ uint32_t coordinate_mask; + uint32_t indices[2]; + + resource_symbol = spirv_compiler_find_resource(compiler, &src[1].reg); +@@ -8822,7 +8835,7 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler, + const struct vkd3d_shader_src_param *src = instruction->src; + const struct vkd3d_symbol *resource_symbol; + struct vkd3d_shader_image image; +- DWORD coordinate_mask; ++ uint32_t coordinate_mask; + uint32_t indices[2]; + + resource_symbol = spirv_compiler_find_resource(compiler, &dst->reg); +@@ -8988,7 +9001,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + struct vkd3d_shader_register_info reg_info; + struct vkd3d_shader_image image; + unsigned int structure_stride; +- DWORD coordinate_mask; ++ uint32_t coordinate_mask; + uint32_t operands[6]; + unsigned int i = 0; + SpvScope scope; +@@ -9420,9 +9433,9 @@ static void spirv_compiler_emit_sync(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { + unsigned int memory_semantics = SpvMemorySemanticsAcquireReleaseMask; +- unsigned int flags = instruction->flags; + SpvScope execution_scope = SpvScopeMax; + SpvScope memory_scope = SpvScopeDevice; ++ uint32_t flags = instruction->flags; + + if (flags & VKD3DSSF_GROUP_SHARED_MEMORY) + { +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index f859e758d8e..1f1944bc0da 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -742,8 +742,7 @@ static bool shader_sm4_read_register_space(struct vkd3d_shader_sm4_parser *priv, + static void shader_sm4_read_conditional_op(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) + { +- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, +- (struct vkd3d_shader_src_param *)&ins->src[0]); ++ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &ins->src[0]); + ins->flags = (opcode_token & VKD3D_SM4_CONDITIONAL_NZ) ? + VKD3D_SHADER_CONDITIONAL_OP_NZ : VKD3D_SHADER_CONDITIONAL_OP_Z; + } +@@ -751,8 +750,7 @@ static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins, + static void shader_sm4_read_case_condition(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) + { +- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, +- (struct vkd3d_shader_src_param *)&ins->src[0]); ++ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &ins->src[0]); + if (ins->src[0].reg.type != VKD3DSPR_IMMCONST) + { + FIXME("Switch case value is not a 32-bit constant.\n"); +@@ -823,7 +821,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u + const uint32_t *end = &tokens[token_count]; + enum vkd3d_sm4_data_type data_type; + enum vkd3d_data_type reg_data_type; +- DWORD components; ++ uint32_t components; + unsigned int i; + + resource_type = (opcode_token & VKD3D_SM4_RESOURCE_TYPE_MASK) >> VKD3D_SM4_RESOURCE_TYPE_SHIFT; +@@ -1130,9 +1128,8 @@ static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *in + static void shader_sm5_read_fcall(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) + { +- struct vkd3d_shader_src_param *src_params = (struct vkd3d_shader_src_param *)ins->src; +- src_params[0].reg.u.fp_body_idx = *tokens++; +- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &src_params[0]); ++ ins->src[0].reg.u.fp_body_idx = *tokens++; ++ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &ins->src[0]); + } + + static void shader_sm5_read_dcl_function_body(struct vkd3d_shader_instruction *ins, uint32_t opcode, +@@ -1762,11 +1759,11 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui + const struct vkd3d_sm4_register_type_info *register_type_info; + enum vkd3d_shader_register_type vsir_register_type; + enum vkd3d_sm4_register_precision precision; ++ uint32_t token, order, extended, addressing; + enum vkd3d_sm4_register_type register_type; + enum vkd3d_sm4_extended_operand_type type; +- enum vkd3d_sm4_register_modifier m; + enum vkd3d_sm4_dimension sm4_dimension; +- uint32_t token, order, extended; ++ enum vkd3d_sm4_register_modifier m; + + if (*ptr >= end) + { +@@ -1864,7 +1861,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui + + if (order >= 1) + { +- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK0) >> VKD3D_SM4_ADDRESSING_SHIFT0; ++ addressing = (token & VKD3D_SM4_ADDRESSING_MASK0) >> VKD3D_SM4_ADDRESSING_SHIFT0; + if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[0]))) + { + ERR("Failed to read register index.\n"); +@@ -1874,7 +1871,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui + + if (order >= 2) + { +- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK1) >> VKD3D_SM4_ADDRESSING_SHIFT1; ++ addressing = (token & VKD3D_SM4_ADDRESSING_MASK1) >> VKD3D_SM4_ADDRESSING_SHIFT1; + if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[1]))) + { + ERR("Failed to read register index.\n"); +@@ -1884,7 +1881,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui + + if (order >= 3) + { +- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK2) >> VKD3D_SM4_ADDRESSING_SHIFT2; ++ addressing = (token & VKD3D_SM4_ADDRESSING_MASK2) >> VKD3D_SM4_ADDRESSING_SHIFT2; + if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[2]))) + { + ERR("Failed to read register index.\n"); +@@ -2078,7 +2075,7 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons + const uint32_t *end, enum vkd3d_data_type data_type, struct vkd3d_shader_src_param *src_param) + { + unsigned int dimension, mask; +- DWORD token; ++ uint32_t token; + + if (*ptr >= end) + { +@@ -2165,7 +2162,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons + enum vkd3d_sm4_swizzle_type swizzle_type; + enum vkd3d_shader_src_modifier modifier; + unsigned int dimension, swizzle; +- DWORD token; ++ uint32_t token; + + if (*ptr >= end) + { +@@ -2245,7 +2242,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons + return true; + } + +-static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_shader_instruction *ins) ++static void shader_sm4_read_instruction_modifier(uint32_t modifier, struct vkd3d_shader_instruction *ins) + { + enum vkd3d_sm4_instruction_modifier modifier_type = modifier & VKD3D_SM4_MODIFIER_MASK; + +@@ -2253,7 +2250,7 @@ static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_sh + { + case VKD3D_SM4_MODIFIER_AOFFIMMI: + { +- static const DWORD recognized_bits = VKD3D_SM4_INSTRUCTION_MODIFIER ++ static const uint32_t recognized_bits = VKD3D_SM4_INSTRUCTION_MODIFIER + | VKD3D_SM4_MODIFIER_MASK + | VKD3D_SM4_AOFFIMMI_U_MASK + | VKD3D_SM4_AOFFIMMI_V_MASK +@@ -2281,7 +2278,7 @@ static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_sh + + case VKD3D_SM5_MODIFIER_DATA_TYPE: + { +- DWORD components = (modifier & VKD3D_SM5_MODIFIER_DATA_TYPE_MASK) >> VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT; ++ uint32_t components = (modifier & VKD3D_SM5_MODIFIER_DATA_TYPE_MASK) >> VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT; + unsigned int i; + + for (i = 0; i < VKD3D_VEC4_SIZE; i++) +@@ -2337,9 +2334,9 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str + struct vkd3d_shader_src_param *src_params; + const uint32_t **ptr = &sm4->ptr; + unsigned int i, len; +- size_t remaining; + const uint32_t *p; +- DWORD precise; ++ uint32_t precise; ++ size_t remaining; + + if (*ptr >= sm4->end) + { +@@ -5488,7 +5485,7 @@ static void write_sm4_loop(const struct tpf_writer *tpf, const struct hlsl_ir_lo + + static void write_sm4_gather(const struct tpf_writer *tpf, const struct hlsl_ir_node *dst, + const struct hlsl_deref *resource, const struct hlsl_deref *sampler, +- const struct hlsl_ir_node *coords, DWORD swizzle, const struct hlsl_ir_node *texel_offset) ++ const struct hlsl_ir_node *coords, uint32_t swizzle, const struct hlsl_ir_node *texel_offset) + { + struct vkd3d_shader_src_param *src; + struct sm4_instruction instr; +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index 8fd98d2a551..61e46f5538e 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -383,13 +383,42 @@ size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *byte + return offset; + } + +-void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value) ++size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size) ++{ ++ size_t offset = bytecode_align(buffer); ++ ++ if (buffer->status) ++ return offset; ++ ++ if (!vkd3d_array_reserve((void **)&buffer->data, &buffer->capacity, offset + size, 1)) ++ { ++ buffer->status = VKD3D_ERROR_OUT_OF_MEMORY; ++ return offset; ++ } ++ ++ memset(buffer->data + offset, 0, size); ++ buffer->size = offset + size; ++ return offset; ++} ++ ++static void bytecode_set_bytes(struct vkd3d_bytecode_buffer *buffer, size_t offset, ++ const void *value, size_t size) + { + if (buffer->status) + return; + +- assert(vkd3d_bound_range(offset, sizeof(value), buffer->size)); +- memcpy(buffer->data + offset, &value, sizeof(value)); ++ assert(vkd3d_bound_range(offset, size, buffer->size)); ++ memcpy(buffer->data + offset, value, size); ++} ++ ++void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value) ++{ ++ bytecode_set_bytes(buffer, offset, &value, sizeof(value)); ++} ++ ++void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char *string, size_t length) ++{ ++ bytecode_set_bytes(buffer, offset, string, length); + } + + static void vkd3d_shader_dump_blob(const char *path, const char *profile, +@@ -1913,6 +1942,7 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( + { + VKD3D_SHADER_TARGET_D3D_BYTECODE, + VKD3D_SHADER_TARGET_DXBC_TPF, ++ VKD3D_SHADER_TARGET_FX, + }; + + static const enum vkd3d_shader_target_type d3dbc_types[] = +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 47b245bd7ee..0af7ea0d266 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -216,6 +216,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS = 9014, + VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX = 9015, + VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING = 9016, ++ VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE = 9017, + + VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300, + }; +@@ -871,14 +872,14 @@ struct vkd3d_shader_dst_param + { + struct vkd3d_shader_register reg; + uint32_t write_mask; +- DWORD modifiers; +- DWORD shift; ++ uint32_t modifiers; ++ unsigned int shift; + }; + + struct vkd3d_shader_src_param + { + struct vkd3d_shader_register reg; +- DWORD swizzle; ++ uint32_t swizzle; + enum vkd3d_shader_src_modifier modifiers; + }; + +@@ -955,6 +956,9 @@ enum vkd3d_shader_input_sysval_semantic + VKD3D_SIV_LINE_DENSITY_TESS_FACTOR = 22, + }; + ++#define SM1_COLOR_REGISTER_OFFSET 8 ++#define SM1_RASTOUT_REGISTER_OFFSET 10 ++ + #define SIGNATURE_TARGET_LOCATION_UNUSED (~0u) + + struct signature_element +@@ -1120,11 +1124,11 @@ struct vkd3d_shader_instruction + { + struct vkd3d_shader_location location; + enum vkd3d_shader_opcode handler_idx; +- DWORD flags; ++ uint32_t flags; + unsigned int dst_count; + unsigned int src_count; +- const struct vkd3d_shader_dst_param *dst; +- const struct vkd3d_shader_src_param *src; ++ struct vkd3d_shader_dst_param *dst; ++ struct vkd3d_shader_src_param *src; + struct vkd3d_shader_texel_offset texel_offset; + enum vkd3d_shader_resource_type resource_type; + unsigned int resource_stride; +@@ -1354,7 +1358,9 @@ struct vkd3d_bytecode_buffer + /* Align to the next 4-byte offset, and return that offset. */ + size_t bytecode_align(struct vkd3d_bytecode_buffer *buffer); + size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size); ++size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size); + void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value); ++void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char *string, size_t length); + + static inline size_t put_u32(struct vkd3d_bytecode_buffer *buffer, uint32_t value) + { +@@ -1445,7 +1451,7 @@ int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info, + int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); + +-void vsir_validate(struct vkd3d_shader_parser *parser); ++enum vkd3d_result vsir_validate(struct vkd3d_shader_parser *parser); + + static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type( + enum vkd3d_data_type data_type) +diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c +index 549f6a45ffb..4c39d00de24 100644 +--- a/libs/vkd3d/libs/vkd3d/command.c ++++ b/libs/vkd3d/libs/vkd3d/command.c +@@ -3270,7 +3270,8 @@ static void d3d12_command_list_bind_descriptor_heap(struct d3d12_command_list *l + { + VkDescriptorSet vk_descriptor_set = heap->vk_descriptor_sets[set].vk_set; + +- if (!vk_descriptor_set) ++ /* Null vk_set_layout means set 0 uses mutable descriptors, and this set is unused. */ ++ if (!vk_descriptor_set || !list->device->vk_descriptor_heap_layouts[set].vk_set_layout) + continue; + + VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, bindings->vk_bind_point, rs->vk_pipeline_layout, +@@ -6512,7 +6513,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12Command + if (!(op = d3d12_command_queue_op_array_require_space(&command_queue->op_queue))) + { + ERR("Failed to add op.\n"); +- return; ++ goto unlock_mutex; + } + op->opcode = VKD3D_CS_OP_COPY_MAPPINGS; + op->u.copy_mappings.dst_resource = dst_resource_impl; +@@ -6524,6 +6525,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12Command + + d3d12_command_queue_submit_locked(command_queue); + ++unlock_mutex: + vkd3d_mutex_unlock(&command_queue->op_mutex); + } + +diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c +index 69a46e9188a..ea243977c22 100644 +--- a/libs/vkd3d/libs/vkd3d/device.c ++++ b/libs/vkd3d/libs/vkd3d/device.c +@@ -94,6 +94,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = + VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker), + VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable), + VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing), ++ VK_EXTENSION(EXT_MUTABLE_DESCRIPTOR_TYPE, EXT_mutable_descriptor_type), + VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2), + VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation), + VK_EXTENSION(EXT_SHADER_STENCIL_EXPORT, EXT_shader_stencil_export), +@@ -106,13 +107,32 @@ static HRESULT vkd3d_create_vk_descriptor_heap_layout(struct d3d12_device *devic + { + const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + VkDescriptorSetLayoutBindingFlagsCreateInfoEXT flags_info; ++ VkMutableDescriptorTypeCreateInfoEXT mutable_info; ++ VkMutableDescriptorTypeListEXT type_list; + VkDescriptorSetLayoutCreateInfo set_desc; + VkDescriptorBindingFlagsEXT set_flags; + VkDescriptorSetLayoutBinding binding; + VkResult vr; + ++ static const VkDescriptorType descriptor_types[] = ++ { ++ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, ++ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, ++ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, ++ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, ++ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ++ }; ++ ++ if (device->vk_info.EXT_mutable_descriptor_type && index && index != VKD3D_SET_INDEX_UAV_COUNTER ++ && device->vk_descriptor_heap_layouts[index].applicable_heap_type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) ++ { ++ device->vk_descriptor_heap_layouts[index].vk_set_layout = VK_NULL_HANDLE; ++ return S_OK; ++ } ++ + binding.binding = 0; +- binding.descriptorType = device->vk_descriptor_heap_layouts[index].type; ++ binding.descriptorType = (device->vk_info.EXT_mutable_descriptor_type && !index) ++ ? VK_DESCRIPTOR_TYPE_MUTABLE_EXT : device->vk_descriptor_heap_layouts[index].type; + binding.descriptorCount = device->vk_descriptor_heap_layouts[index].count; + binding.stageFlags = VK_SHADER_STAGE_ALL; + binding.pImmutableSamplers = NULL; +@@ -132,6 +152,17 @@ static HRESULT vkd3d_create_vk_descriptor_heap_layout(struct d3d12_device *devic + flags_info.bindingCount = 1; + flags_info.pBindingFlags = &set_flags; + ++ if (binding.descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_EXT) ++ { ++ type_list.descriptorTypeCount = ARRAY_SIZE(descriptor_types); ++ type_list.pDescriptorTypes = descriptor_types; ++ mutable_info.sType = VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT; ++ mutable_info.pNext = NULL; ++ mutable_info.mutableDescriptorTypeListCount = 1; ++ mutable_info.pMutableDescriptorTypeLists = &type_list; ++ flags_info.pNext = &mutable_info; ++ } ++ + if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device->vk_device, &set_desc, NULL, + &device->vk_descriptor_heap_layouts[index].vk_set_layout))) < 0) + { +@@ -763,6 +794,7 @@ struct vkd3d_physical_device_info + VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features; + VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features; + VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timeline_semaphore_features; ++ VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT mutable_features; + + VkPhysicalDeviceFeatures2 features2; + }; +@@ -780,6 +812,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i + VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features; + VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features; + VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *timeline_semaphore_features; ++ VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT *mutable_features; + VkPhysicalDeviceDepthClipEnableFeaturesEXT *depth_clip_features; + VkPhysicalDeviceMaintenance3Properties *maintenance3_properties; + VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb_properties; +@@ -800,6 +833,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i + vertex_divisor_features = &info->vertex_divisor_features; + vertex_divisor_properties = &info->vertex_divisor_properties; + timeline_semaphore_features = &info->timeline_semaphore_features; ++ mutable_features = &info->mutable_features; + xfb_features = &info->xfb_features; + xfb_properties = &info->xfb_properties; + +@@ -823,6 +857,8 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i + vk_prepend_struct(&info->features2, vertex_divisor_features); + timeline_semaphore_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR; + vk_prepend_struct(&info->features2, timeline_semaphore_features); ++ mutable_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT; ++ vk_prepend_struct(&info->features2, mutable_features); + + if (vulkan_info->KHR_get_physical_device_properties2) + VK_CALL(vkGetPhysicalDeviceFeatures2KHR(physical_device, &info->features2)); +@@ -1594,6 +1630,8 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, + vulkan_info->EXT_shader_demote_to_helper_invocation = false; + if (!physical_device_info->texel_buffer_alignment_features.texelBufferAlignment) + vulkan_info->EXT_texel_buffer_alignment = false; ++ if (!physical_device_info->mutable_features.mutableDescriptorType) ++ vulkan_info->EXT_mutable_descriptor_type = false; + if (!physical_device_info->timeline_semaphore_features.timelineSemaphore) + vulkan_info->KHR_timeline_semaphore = false; + +@@ -4513,7 +4551,7 @@ HRESULT vkd3d_create_thread(struct vkd3d_instance *instance, + thread_data->data = data; + if (!(thread->handle = CreateThread(NULL, 0, call_thread_main, thread_data, 0, NULL))) + { +- ERR("Failed to create thread, error %d.\n", GetLastError()); ++ ERR("Failed to create thread, error %lu.\n", GetLastError()); + vkd3d_free(thread_data); + hr = E_FAIL; + } +diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c +index 609c67102a6..163dd6ce210 100644 +--- a/libs/vkd3d/libs/vkd3d/resource.c ++++ b/libs/vkd3d/libs/vkd3d/resource.c +@@ -2470,12 +2470,14 @@ static void d3d12_desc_write_vk_heap_null_descriptor(struct d3d12_descriptor_hea + { + const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + struct d3d12_descriptor_heap_vk_set *descriptor_set; +- enum vkd3d_vk_descriptor_set_index set; ++ enum vkd3d_vk_descriptor_set_index set, end; + unsigned int i = writes->count; + ++ end = device->vk_info.EXT_mutable_descriptor_type ? VKD3D_SET_INDEX_UNIFORM_BUFFER ++ : VKD3D_SET_INDEX_STORAGE_IMAGE; + /* Binding a shader with the wrong null descriptor type works in Windows. + * To support that here we must write one to all applicable Vulkan sets. */ +- for (set = VKD3D_SET_INDEX_UNIFORM_BUFFER; set <= VKD3D_SET_INDEX_STORAGE_IMAGE; ++set) ++ for (set = VKD3D_SET_INDEX_UNIFORM_BUFFER; set <= end; ++set) + { + descriptor_set = &descriptor_heap->vk_descriptor_sets[set]; + writes->vk_descriptor_writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; +@@ -3444,6 +3446,7 @@ static void vkd3d_create_null_uav(struct d3d12_desc *descriptor, + vkd3d_desc.miplevel_count = 1; + vkd3d_desc.layer_idx = 0; + vkd3d_desc.layer_count = 1; ++ vkd3d_desc.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT; + vkd3d_desc.components.r = VK_COMPONENT_SWIZZLE_R; + vkd3d_desc.components.g = VK_COMPONENT_SWIZZLE_G; + vkd3d_desc.components.b = VK_COMPONENT_SWIZZLE_B; +@@ -3661,11 +3664,27 @@ static VkSamplerAddressMode vk_address_mode_from_d3d12(const struct d3d12_device + } + } + ++static VkBorderColor vk_border_colour_from_d3d12(D3D12_STATIC_BORDER_COLOR colour) ++{ ++ switch (colour) ++ { ++ case D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK: ++ return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; ++ case D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK: ++ return VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; ++ case D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE: ++ return VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; ++ default: ++ FIXME("Unhandled border colour %#x.\n", colour); ++ return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; ++ } ++} ++ + static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER filter, + D3D12_TEXTURE_ADDRESS_MODE address_u, D3D12_TEXTURE_ADDRESS_MODE address_v, + D3D12_TEXTURE_ADDRESS_MODE address_w, float mip_lod_bias, unsigned int max_anisotropy, +- D3D12_COMPARISON_FUNC comparison_func, float min_lod, float max_lod, +- VkSampler *vk_sampler) ++ D3D12_COMPARISON_FUNC comparison_func, D3D12_STATIC_BORDER_COLOR border_colour, ++ float min_lod, float max_lod, VkSampler *vk_sampler) + { + const struct vkd3d_vk_device_procs *vk_procs; + struct VkSamplerCreateInfo sampler_desc; +@@ -3695,15 +3714,48 @@ static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER f + sampler_desc.maxLod = max_lod; + sampler_desc.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + sampler_desc.unnormalizedCoordinates = VK_FALSE; ++ ++ if (address_u == D3D12_TEXTURE_ADDRESS_MODE_BORDER || address_v == D3D12_TEXTURE_ADDRESS_MODE_BORDER ++ || address_w == D3D12_TEXTURE_ADDRESS_MODE_BORDER) ++ sampler_desc.borderColor = vk_border_colour_from_d3d12(border_colour); ++ + if ((vr = VK_CALL(vkCreateSampler(device->vk_device, &sampler_desc, NULL, vk_sampler))) < 0) + WARN("Failed to create Vulkan sampler, vr %d.\n", vr); + + return vr; + } + ++static D3D12_STATIC_BORDER_COLOR d3d12_static_border_colour(const float *colour) ++{ ++ unsigned int i; ++ ++ static const struct ++ { ++ float colour[4]; ++ D3D12_STATIC_BORDER_COLOR static_colour; ++ } ++ colours[] = ++ { ++ {{0.0f, 0.0f, 0.0f, 0.0f}, D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK}, ++ {{0.0f, 0.0f, 0.0f, 1.0f}, D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK}, ++ {{1.0f, 1.0f, 1.0f, 1.0f}, D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE}, ++ }; ++ ++ for (i = 0; i < ARRAY_SIZE(colours); ++i) ++ { ++ if (!memcmp(colour, colours[i].colour, sizeof(colours[i].colour))) ++ return colours[i].static_colour; ++ } ++ ++ FIXME("Unhandled border colour {%.8e, %.8e, %.8e, %.8e}.\n", colour[0], colour[1], colour[2], colour[3]); ++ ++ return D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; ++} ++ + void d3d12_desc_create_sampler(struct d3d12_desc *sampler, + struct d3d12_device *device, const D3D12_SAMPLER_DESC *desc) + { ++ D3D12_STATIC_BORDER_COLOR static_colour = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + struct vkd3d_view *view; + + if (!desc) +@@ -3715,8 +3767,7 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler, + if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER + || desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER + || desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER) +- FIXME("Ignoring border color {%.8e, %.8e, %.8e, %.8e}.\n", +- desc->BorderColor[0], desc->BorderColor[1], desc->BorderColor[2], desc->BorderColor[3]); ++ static_colour = d3d12_static_border_colour(desc->BorderColor); + + if (!(view = vkd3d_view_create(VKD3D_DESCRIPTOR_MAGIC_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLER, + VKD3D_VIEW_TYPE_SAMPLER, device))) +@@ -3724,9 +3775,9 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler, + view->v.u.vk_sampler = VK_NULL_HANDLE; + view->v.format = NULL; + +- if (d3d12_create_sampler(device, desc->Filter, desc->AddressU, +- desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, +- desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, &view->v.u.vk_sampler) < 0) ++ if (d3d12_create_sampler(device, desc->Filter, desc->AddressU, desc->AddressV, ++ desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, desc->ComparisonFunc, ++ static_colour, desc->MinLOD, desc->MaxLOD, &view->v.u.vk_sampler) < 0) + { + vkd3d_view_decref(view, device); + return; +@@ -3740,14 +3791,9 @@ HRESULT vkd3d_create_static_sampler(struct d3d12_device *device, + { + VkResult vr; + +- if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER +- || desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER +- || desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER) +- FIXME("Ignoring border %#x.\n", desc->BorderColor); +- +- vr = d3d12_create_sampler(device, desc->Filter, desc->AddressU, +- desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, +- desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, vk_sampler); ++ vr = d3d12_create_sampler(device, desc->Filter, desc->AddressU, desc->AddressV, ++ desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, desc->ComparisonFunc, ++ desc->BorderColor, desc->MinLOD, desc->MaxLOD, vk_sampler); + return hresult_from_vk_result(vr); + } + +@@ -4176,9 +4222,11 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_pool(struct d3d12_descrip + + for (set = 0, pool_desc.poolSizeCount = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set) + { +- if (device->vk_descriptor_heap_layouts[set].applicable_heap_type == desc->Type) ++ if (device->vk_descriptor_heap_layouts[set].applicable_heap_type == desc->Type ++ && device->vk_descriptor_heap_layouts[set].vk_set_layout) + { +- pool_sizes[pool_desc.poolSizeCount].type = device->vk_descriptor_heap_layouts[set].type; ++ pool_sizes[pool_desc.poolSizeCount].type = (device->vk_info.EXT_mutable_descriptor_type && !set) ++ ? VK_DESCRIPTOR_TYPE_MUTABLE_EXT : device->vk_descriptor_heap_layouts[set].type; + pool_sizes[pool_desc.poolSizeCount++].descriptorCount = desc->NumDescriptors; + } + } +@@ -4204,6 +4252,16 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_set(struct d3d12_descript + VkDescriptorSetAllocateInfo set_desc; + VkResult vr; + ++ if (!device->vk_descriptor_heap_layouts[set].vk_set_layout) ++ { ++ /* Set 0 uses mutable descriptors, and this set is unused. */ ++ if (!descriptor_heap->vk_descriptor_sets[0].vk_set) ++ d3d12_descriptor_heap_create_descriptor_set(descriptor_heap, device, 0); ++ descriptor_set->vk_set = descriptor_heap->vk_descriptor_sets[0].vk_set; ++ descriptor_set->vk_type = device->vk_descriptor_heap_layouts[set].type; ++ return S_OK; ++ } ++ + set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + set_desc.pNext = &set_size; + set_desc.descriptorPool = descriptor_heap->vk_descriptor_pool; +diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c +index 1457ddf9c7f..82782e7d5fc 100644 +--- a/libs/vkd3d/libs/vkd3d/state.c ++++ b/libs/vkd3d/libs/vkd3d/state.c +@@ -848,7 +848,20 @@ static void vkd3d_descriptor_heap_binding_from_descriptor_range(const struct d3d + const struct vkd3d_device_descriptor_limits *descriptor_limits = &root_signature->device->vk_info.descriptor_limits; + unsigned int descriptor_set_size; + +- switch (range->type) ++ if (root_signature->device->vk_info.EXT_mutable_descriptor_type) ++ { ++ if (range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) ++ { ++ binding->set = VKD3D_SET_INDEX_SAMPLER; ++ descriptor_set_size = descriptor_limits->sampler_max_descriptors; ++ } ++ else ++ { ++ binding->set = 0; ++ descriptor_set_size = descriptor_limits->sampled_image_max_descriptors; ++ } ++ } ++ else switch (range->type) + { + case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV: + binding->set = is_buffer ? VKD3D_SET_INDEX_UNIFORM_TEXEL_BUFFER : VKD3D_SET_INDEX_SAMPLED_IMAGE; +@@ -1368,8 +1381,14 @@ static unsigned int d3d12_root_signature_copy_descriptor_set_layouts(const struc + + if (device->use_vk_heaps) + { ++ VkDescriptorSetLayout mutable_layout = device->vk_descriptor_heap_layouts[0].vk_set_layout; ++ + for (set = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set) +- vk_set_layouts[i++] = device->vk_descriptor_heap_layouts[set].vk_set_layout; ++ { ++ VkDescriptorSetLayout vk_set_layout = device->vk_descriptor_heap_layouts[set].vk_set_layout; ++ /* All layouts must be valid, so if null, just set it to the mutable one. */ ++ vk_set_layouts[i++] = vk_set_layout ? vk_set_layout : mutable_layout; ++ } + } + + return i; +diff --git a/libs/vkd3d/libs/vkd3d/utils.c b/libs/vkd3d/libs/vkd3d/utils.c +index 5ebe1b63e99..751971220e7 100644 +--- a/libs/vkd3d/libs/vkd3d/utils.c ++++ b/libs/vkd3d/libs/vkd3d/utils.c +@@ -683,7 +683,7 @@ const char *debug_vk_extent_3d(VkExtent3D extent) + + const char *debug_vk_queue_flags(VkQueueFlags flags) + { +- char buffer[120]; ++ char buffer[159]; + + buffer[0] = '\0'; + #define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; } +@@ -691,6 +691,10 @@ const char *debug_vk_queue_flags(VkQueueFlags flags) + FLAG_TO_STR(VK_QUEUE_COMPUTE_BIT) + FLAG_TO_STR(VK_QUEUE_TRANSFER_BIT) + FLAG_TO_STR(VK_QUEUE_SPARSE_BINDING_BIT) ++ FLAG_TO_STR(VK_QUEUE_PROTECTED_BIT) ++#undef FLAG_TO_STR ++#define FLAG_TO_STR(f, n) if (flags & f) { strcat(buffer, " | "#n); flags &= ~f; } ++ FLAG_TO_STR(0x20, VK_QUEUE_VIDEO_DECODE_BIT_KHR) + #undef FLAG_TO_STR + if (flags) + FIXME("Unrecognized flag(s) %#x.\n", flags); +@@ -729,10 +733,8 @@ const char *debug_vk_memory_property_flags(VkMemoryPropertyFlags flags) + FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_CACHED_BIT) + FLAG_TO_STR(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) + FLAG_TO_STR(VK_MEMORY_PROPERTY_PROTECTED_BIT) +-#undef FLAG_TO_STR +-#define FLAG_TO_STR(f, n) if (flags & f) { strcat(buffer, " | "#n); flags &= ~f; } +- FLAG_TO_STR(0x40, VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD) +- FLAG_TO_STR(0x80, VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD) ++ FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD) ++ FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD) + #undef FLAG_TO_STR + if (flags) + FIXME("Unrecognized flag(s) %#x.\n", flags); +diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +index bd7e7290d9e..9bf4575d46a 100644 +--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h ++++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +@@ -133,6 +133,7 @@ struct vkd3d_vulkan_info + bool EXT_debug_marker; + bool EXT_depth_clip_enable; + bool EXT_descriptor_indexing; ++ bool EXT_mutable_descriptor_type; + bool EXT_robustness2; + bool EXT_shader_demote_to_helper_invocation; + bool EXT_shader_stencil_export; +@@ -248,7 +249,7 @@ static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond) + static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock) + { + if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE)) +- ERR("Could not sleep on the condition variable, error %u.\n", GetLastError()); ++ ERR("Could not sleep on the condition variable, error %lu.\n", GetLastError()); + } + + static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond) +-- +2.43.0 + diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-21491d1bbb168da8aeaa7bdde6e5f182b22.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-21491d1bbb168da8aeaa7bdde6e5f182b22.patch deleted file mode 100644 index ae34b15b..00000000 --- a/patches/vkd3d-latest/0003-Updated-vkd3d-to-21491d1bbb168da8aeaa7bdde6e5f182b22.patch +++ /dev/null @@ -1,850 +0,0 @@ -From 9f12a2158273f6dda33aa5e74fa2853acaeb5a63 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Thu, 14 Dec 2023 10:07:09 +1100 -Subject: [PATCH] Updated vkd3d to 21491d1bbb168da8aeaa7bdde6e5f182b2205558. - ---- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 2 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 14 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 201 ++++++++++-------- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 7 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 13 +- - libs/vkd3d/libs/vkd3d/state.c | 4 +- - 6 files changed, 134 insertions(+), 107 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index 2d52ee07724..86ddd1ffded 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -1317,7 +1317,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, - static const char write_mask_chars[] = "xyzw"; - - if (param->reg.data_type == VKD3D_DATA_DOUBLE) -- write_mask = vkd3d_write_mask_32_from_64(write_mask); -+ write_mask = vsir_write_mask_32_from_64(write_mask); - - shader_addline(buffer, ".%s", compiler->colours.write_mask); - if (write_mask & VKD3DSP_WRITEMASK_0) -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index a35ef862096..1a569619707 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -593,19 +593,19 @@ struct signature_element *vsir_signature_find_element_for_reg(const struct shade - } - - static unsigned int range_map_get_register_count(uint8_t range_map[][VKD3D_VEC4_SIZE], -- unsigned int register_idx, unsigned int write_mask) -+ unsigned int register_idx, uint32_t write_mask) - { -- return range_map[register_idx][vkd3d_write_mask_get_component_idx(write_mask)]; -+ return range_map[register_idx][vsir_write_mask_get_component_idx(write_mask)]; - } - - static void range_map_set_register_range(uint8_t range_map[][VKD3D_VEC4_SIZE], unsigned int register_idx, -- unsigned int register_count, unsigned int write_mask, bool is_dcl_indexrange) -+ unsigned int register_count, uint32_t write_mask, bool is_dcl_indexrange) - { - unsigned int i, j, r, c, component_idx, component_count; - - assert(write_mask <= VKD3DSP_WRITEMASK_ALL); -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -- component_count = vkd3d_write_mask_component_count(write_mask); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); -+ component_count = vsir_write_mask_component_count(write_mask); - - assert(register_idx < MAX_REG_OUTPUT && MAX_REG_OUTPUT - register_idx >= register_count); - -@@ -899,7 +899,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par - element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); - e = &signature->elements[element_idx]; - -- dst_param->write_mask >>= vkd3d_write_mask_get_component_idx(e->mask); -+ dst_param->write_mask >>= vsir_write_mask_get_component_idx(e->mask); - if (is_io_dcl) - { - /* Validated in the TPF reader. */ -@@ -1011,7 +1011,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par - reg->idx[id_idx].offset = element_idx; - reg->idx_count = id_idx + 1; - -- if ((component_idx = vkd3d_write_mask_get_component_idx(e->mask))) -+ if ((component_idx = vsir_write_mask_get_component_idx(e->mask))) - { - for (i = 0; i < VKD3D_VEC4_SIZE; ++i) - if (vkd3d_swizzle_get_component(src_param->swizzle, i)) -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index db45920200d..5c537598e1e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -133,7 +133,7 @@ static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, - } - } - --static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, -+static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv, - enum vkd3d_shader_spirv_environment environment) - { - spv_diagnostic diagnostic = NULL; -@@ -145,12 +145,13 @@ static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, - if ((ret = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t), - &diagnostic))) - { -- FIXME("Failed to validate SPIR-V binary, ret %d.\n", ret); -- FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error)); -+ vkd3d_string_buffer_printf(buffer, "%s", diagnostic->error); - } - - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(context); -+ -+ return !ret; - } - - #else -@@ -163,8 +164,11 @@ static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_co - } - static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, - enum vkd3d_shader_spirv_environment environment) {} --static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, -- enum vkd3d_shader_spirv_environment environment) {} -+static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv, -+ enum vkd3d_shader_spirv_environment environment) -+{ -+ return true; -+} - - #endif /* HAVE_SPIRV_TOOLS */ - -@@ -2403,6 +2407,8 @@ struct spirv_compiler - - struct ssa_register_info *ssa_register_info; - unsigned int ssa_register_count; -+ -+ uint64_t config_flags; - }; - - static bool is_in_default_phase(const struct spirv_compiler *compiler) -@@ -2458,7 +2464,8 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler) - static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *shader_version, - struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, - const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info, -- struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location) -+ struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location, -+ uint64_t config_flags) - { - const struct shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature; - const struct shader_signature *output_signature = &shader_desc->output_signature; -@@ -2475,6 +2482,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve - memset(compiler, 0, sizeof(*compiler)); - compiler->message_context = message_context; - compiler->location = *location; -+ compiler->config_flags = config_flags; - - if ((target_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO))) - { -@@ -3041,13 +3049,13 @@ static uint32_t spirv_compiler_get_constant_double_vector(struct spirv_compiler - } - - static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - - return vkd3d_spirv_get_type_id(builder, - vkd3d_component_type_from_data_type(reg->data_type), -- vkd3d_write_mask_component_count(write_mask)); -+ vsir_write_mask_component_count(write_mask)); - } - - static uint32_t spirv_compiler_get_type_id_for_dst(struct spirv_compiler *compiler, -@@ -3555,7 +3563,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp - - if (index_count) - { -- component_count = vkd3d_write_mask_component_count(register_info->write_mask); -+ component_count = vsir_write_mask_component_count(register_info->write_mask); - type_id = vkd3d_spirv_get_type_id(builder, register_info->component_type, component_count); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, register_info->storage_class, type_id); - register_info->id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, -@@ -3596,15 +3604,15 @@ static bool vkd3d_swizzle_is_scalar(unsigned int swizzle) - } - - static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, -- uint32_t val_id, unsigned int val_write_mask, enum vkd3d_shader_component_type component_type, -- unsigned int swizzle, unsigned int write_mask) -+ uint32_t val_id, uint32_t val_write_mask, enum vkd3d_shader_component_type component_type, -+ unsigned int swizzle, uint32_t write_mask) - { - unsigned int i, component_idx, component_count, val_component_count; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, components[VKD3D_VEC4_SIZE]; - -- component_count = vkd3d_write_mask_component_count(write_mask); -- val_component_count = vkd3d_write_mask_component_count(val_write_mask); -+ component_count = vsir_write_mask_component_count(write_mask); -+ val_component_count = vsir_write_mask_component_count(val_write_mask); - - if (component_count == val_component_count - && (component_count == 1 || vkd3d_swizzle_is_equal(val_write_mask, swizzle, write_mask))) -@@ -3614,9 +3622,9 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, - - if (component_count == 1) - { -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); - component_idx = vkd3d_swizzle_get_component(swizzle, component_idx); -- component_idx -= vkd3d_write_mask_get_component_idx(val_write_mask); -+ component_idx -= vsir_write_mask_get_component_idx(val_write_mask); - return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx); - } - -@@ -3667,9 +3675,9 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil - } - - static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) -+ const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask) - { -- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(write_mask); - uint32_t values[VKD3D_VEC4_SIZE] = {0}; - unsigned int i, j; - -@@ -3694,9 +3702,9 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile - } - - static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) -+ const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask) - { -- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(write_mask); - uint64_t values[VKD3D_DVEC2_SIZE] = {0}; - unsigned int i, j; - -@@ -3721,9 +3729,9 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi - } - - static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask) - { -- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(write_mask); - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id; - -@@ -3734,28 +3742,28 @@ static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask, -+ const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask, - const struct vkd3d_shader_register_info *reg_info) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, ptr_type_id, index, reg_id, val_id; - unsigned int component_idx, reg_component_count; - enum vkd3d_shader_component_type component_type; -- unsigned int skipped_component_mask; -+ uint32_t skipped_component_mask; - - assert(!register_is_constant_or_undef(reg)); -- assert(vkd3d_write_mask_component_count(write_mask) == 1); -+ assert(vsir_write_mask_component_count(write_mask) == 1); - -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); - component_idx = vkd3d_swizzle_get_component(swizzle, component_idx); - skipped_component_mask = ~reg_info->write_mask & ((VKD3DSP_WRITEMASK_0 << component_idx) - 1); - if (skipped_component_mask) -- component_idx -= vkd3d_write_mask_component_count(skipped_component_mask); -+ component_idx -= vsir_write_mask_component_count(skipped_component_mask); - component_type = vkd3d_component_type_from_data_type(reg->data_type); - -- reg_component_count = vkd3d_write_mask_component_count(reg_info->write_mask); -+ reg_component_count = vsir_write_mask_component_count(reg_info->write_mask); - -- if (component_idx >= vkd3d_write_mask_component_count(reg_info->write_mask)) -+ if (component_idx >= vsir_write_mask_component_count(reg_info->write_mask)) - { - ERR("Invalid component_idx %u for register %#x, %u (write_mask %#x).\n", - component_idx, reg->type, reg->idx[0].offset, reg_info->write_mask); -@@ -3894,14 +3902,14 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler - } - - static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) -+ const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - enum vkd3d_shader_component_type component_type; - struct vkd3d_shader_register_info reg_info; - unsigned int component_count; -- unsigned int write_mask32; - uint32_t type_id, val_id; -+ uint32_t write_mask32; - - if (reg->type == VKD3DSPR_IMMCONST) - return spirv_compiler_emit_load_constant(compiler, reg, swizzle, write_mask); -@@ -3910,7 +3918,7 @@ 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); - -- component_count = vkd3d_write_mask_component_count(write_mask); -+ component_count = vsir_write_mask_component_count(write_mask); - component_type = vkd3d_component_type_from_data_type(reg->data_type); - - if (reg->type == VKD3DSPR_SSA) -@@ -3924,21 +3932,21 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, - assert(reg_info.component_type != VKD3D_SHADER_COMPONENT_DOUBLE); - spirv_compiler_emit_dereference_register(compiler, reg, ®_info); - -- write_mask32 = (reg->data_type == VKD3D_DATA_DOUBLE) ? vkd3d_write_mask_32_from_64(write_mask) : write_mask; -+ write_mask32 = (reg->data_type == VKD3D_DATA_DOUBLE) ? vsir_write_mask_32_from_64(write_mask) : write_mask; - - /* Intermediate value (no storage class). */ - if (reg_info.storage_class == SpvStorageClassMax) - { - val_id = reg_info.id; - } -- else if (vkd3d_write_mask_component_count(write_mask32) == 1) -+ else if (vsir_write_mask_component_count(write_mask32) == 1) - { - return spirv_compiler_emit_load_scalar(compiler, reg, swizzle, write_mask, ®_info); - } - else - { - type_id = vkd3d_spirv_get_type_id(builder, -- reg_info.component_type, vkd3d_write_mask_component_count(reg_info.write_mask)); -+ reg_info.component_type, vsir_write_mask_component_count(reg_info.write_mask)); - val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_info.id, SpvMemoryAccessMaskNone); - } - -@@ -4041,19 +4049,19 @@ static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *co - } - - static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, -- uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type, -- SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id) -+ uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type, -+ SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, ptr_type_id, index; - unsigned int component_idx; - -- if (vkd3d_write_mask_component_count(dst_write_mask) > 1) -+ if (vsir_write_mask_component_count(dst_write_mask) > 1) - { - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -- component_idx -= vkd3d_write_mask_get_component_idx(dst_write_mask); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); -+ component_idx -= vsir_write_mask_get_component_idx(dst_write_mask); - index = spirv_compiler_get_constant_uint(compiler, component_idx); - dst_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, dst_id, index); - } -@@ -4062,8 +4070,8 @@ static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, - } - - static void spirv_compiler_emit_store(struct spirv_compiler *compiler, -- uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type, -- SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id) -+ uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type, -+ SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - unsigned int component_count, dst_component_count; -@@ -4073,14 +4081,14 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, - - assert(write_mask); - -- component_count = vkd3d_write_mask_component_count(write_mask); -- dst_component_count = vkd3d_write_mask_component_count(dst_write_mask); -+ component_count = vsir_write_mask_component_count(write_mask); -+ dst_component_count = vsir_write_mask_component_count(dst_write_mask); - - if (dst_component_count == 1 && component_count != 1) - { - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); - val_id = vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, -- vkd3d_write_mask_get_component_idx(dst_write_mask)); -+ vsir_write_mask_get_component_idx(dst_write_mask)); - write_mask &= dst_write_mask; - component_count = 1; - } -@@ -4117,12 +4125,12 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, - } - - static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, unsigned int write_mask, uint32_t val_id) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - enum vkd3d_shader_component_type component_type; - struct vkd3d_shader_register_info reg_info; -- unsigned int src_write_mask = write_mask; -+ uint32_t src_write_mask = write_mask; - uint32_t type_id; - - assert(!register_is_constant_or_undef(reg)); -@@ -4141,9 +4149,9 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, - if (component_type != reg_info.component_type) - { - if (reg->data_type == VKD3D_DATA_DOUBLE) -- src_write_mask = vkd3d_write_mask_32_from_64(write_mask); -+ src_write_mask = vsir_write_mask_32_from_64(write_mask); - type_id = vkd3d_spirv_get_type_id(builder, reg_info.component_type, -- vkd3d_write_mask_component_count(src_write_mask)); -+ vsir_write_mask_component_count(src_write_mask)); - val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); - component_type = reg_info.component_type; - } -@@ -4153,9 +4161,9 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) - { -- unsigned int component_count = vkd3d_write_mask_component_count(write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(write_mask); - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, zero_id, one_id; - -@@ -4206,7 +4214,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp - const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_component_type component_type, - uint32_t *component_ids) - { -- unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, val_id; - -@@ -4227,11 +4235,11 @@ static void spirv_compiler_emit_store_dst_scalar(struct spirv_compiler *compiler - const struct vkd3d_shader_dst_param *dst, uint32_t val_id, - enum vkd3d_shader_component_type component_type, DWORD swizzle) - { -- unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); - uint32_t component_ids[VKD3D_VEC4_SIZE]; - unsigned int component_idx, i; - -- component_idx = vkd3d_write_mask_get_component_idx(dst->write_mask); -+ component_idx = vsir_write_mask_get_component_idx(dst->write_mask); - for (i = 0; i < component_count; ++i) - { - if (vkd3d_swizzle_get_component(swizzle, component_idx + i)) -@@ -4771,7 +4779,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - enum vkd3d_shader_component_type component_type; - const struct vkd3d_spirv_builtin *builtin; - enum vkd3d_shader_sysval_semantic sysval; -- unsigned int write_mask, reg_write_mask; -+ uint32_t write_mask, reg_write_mask; - struct vkd3d_symbol *symbol = NULL; - uint32_t val_id, input_id, var_id; - uint32_t type_id, float_type_id; -@@ -4813,8 +4821,8 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - else - { - component_type = signature_element->component_type; -- input_component_count = vkd3d_write_mask_component_count(signature_element->mask); -- component_idx = vkd3d_write_mask_get_component_idx(signature_element->mask); -+ input_component_count = vsir_write_mask_component_count(signature_element->mask); -+ component_idx = vsir_write_mask_get_component_idx(signature_element->mask); - } - - if (needs_private_io_variable(builtin)) -@@ -4824,7 +4832,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - } - else - { -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); - reg_write_mask = write_mask >> component_idx; - } - -@@ -4980,7 +4988,7 @@ static void calculate_clip_or_cull_distance_mask(const struct signature_element - return; - } - -- write_mask = e->mask >> vkd3d_write_mask_get_component_idx(e->mask); -+ write_mask = e->mask >> vsir_write_mask_get_component_idx(e->mask); - *mask |= (write_mask & VKD3DSP_WRITEMASK_ALL) << (VKD3D_VEC4_SIZE * e->semantic_index); - } - -@@ -5118,7 +5126,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; -- unsigned int write_mask, reg_write_mask; -+ uint32_t write_mask, reg_write_mask; - bool use_private_variable = false; - struct vkd3d_symbol reg_symbol; - SpvStorageClass storage_class; -@@ -5144,8 +5152,8 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, - - write_mask = signature_element->mask; - -- component_idx = vkd3d_write_mask_get_component_idx(write_mask); -- output_component_count = vkd3d_write_mask_component_count(write_mask); -+ component_idx = vsir_write_mask_get_component_idx(write_mask); -+ output_component_count = vsir_write_mask_component_count(write_mask); - if (builtin) - { - component_type = builtin->component_type; -@@ -5285,9 +5293,9 @@ static uint32_t spirv_compiler_get_output_array_index(struct spirv_compiler *com - static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compiler, - const struct shader_signature *signature, const struct signature_element *output, - const struct vkd3d_shader_output_info *output_info, -- uint32_t output_index_id, uint32_t val_id, unsigned int write_mask) -+ uint32_t output_index_id, uint32_t val_id, uint32_t write_mask) - { -- unsigned int dst_write_mask, use_mask, uninit_mask, swizzle, mask; -+ uint32_t dst_write_mask, use_mask, uninit_mask, swizzle, mask; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, zero_id, ptr_type_id, chain_id, object_id; - const struct signature_element *element; -@@ -5309,7 +5317,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi - use_mask |= element->used_mask; - } - } -- index = vkd3d_write_mask_get_component_idx(output->mask); -+ index = vsir_write_mask_get_component_idx(output->mask); - dst_write_mask >>= index; - use_mask >>= index; - write_mask &= dst_write_mask; -@@ -5333,7 +5341,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi - output_info->component_type, VKD3D_VEC4_SIZE, 0); - val_id = spirv_compiler_emit_vector_shuffle(compiler, - zero_id, val_id, swizzle, uninit_mask, output_info->component_type, -- vkd3d_write_mask_component_count(write_mask)); -+ vsir_write_mask_component_count(write_mask)); - } - else - { -@@ -5345,7 +5353,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi - if (output_index_id) - { - type_id = vkd3d_spirv_get_type_id(builder, -- output_info->component_type, vkd3d_write_mask_component_count(dst_write_mask)); -+ output_info->component_type, vsir_write_mask_component_count(dst_write_mask)); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); - output_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, output_id, output_index_id); - } -@@ -6553,7 +6561,7 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile - spirv_compiler_get_register_info(compiler, &output_reg, &output_reg_info); - - component_type = output->component_type; -- component_count = vkd3d_write_mask_component_count(output->mask); -+ component_count = vsir_write_mask_component_count(output->mask); - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); - output_ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); - -@@ -6788,7 +6796,7 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil - || instruction->handler_idx == VKD3DSIH_ISHR || instruction->handler_idx == VKD3DSIH_USHR)) - { - uint32_t mask_id = spirv_compiler_get_constant_vector(compiler, -- VKD3D_SHADER_COMPONENT_UINT, vkd3d_write_mask_component_count(dst->write_mask), 0x1f); -+ VKD3D_SHADER_COMPONENT_UINT, vsir_write_mask_component_count(dst->write_mask), 0x1f); - src_ids[1] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[1], mask_id); - } - -@@ -6918,7 +6926,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, - return; - } - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - if (component_count != 1 && component_count != VKD3D_VEC4_SIZE - && dst_reg_info.write_mask == VKD3DSP_WRITEMASK_ALL) - { -@@ -6949,7 +6957,7 @@ general_implementation: - if (dst->reg.data_type != src->reg.data_type) - { - val_id = vkd3d_spirv_build_op_bitcast(builder, vkd3d_spirv_get_type_id_for_data_type(builder, -- dst->reg.data_type, vkd3d_write_mask_component_count(dst->write_mask)), val_id); -+ dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)), val_id); - } - spirv_compiler_emit_store_dst(compiler, dst, val_id); - } -@@ -6967,7 +6975,7 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); - src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask); - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); - - if (src[0].reg.data_type != VKD3D_DATA_BOOL) -@@ -6993,7 +7001,7 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler, - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); - src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask); - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); - - condition_id = spirv_compiler_emit_int_to_bool(compiler, -@@ -7016,7 +7024,7 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, - unsigned int component_count, i; - DWORD write_mask; - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); - - if (instruction->handler_idx == VKD3DSIH_DP4) -@@ -7054,7 +7062,7 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler, - uint32_t type_id, src_id, val_id, div_id; - unsigned int component_count; - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); - - src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); -@@ -7134,7 +7142,7 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, - uint32_t type_id, val_id, src_ids[3]; - unsigned int i, component_count; - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, component_count); - - for (i = 0; i < ARRAY_SIZE(src_ids); ++i) -@@ -7168,7 +7176,7 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, - - if (dst[0].reg.type != VKD3DSPR_NULL) - { -- component_count = vkd3d_write_mask_component_count(dst[0].write_mask); -+ component_count = vsir_write_mask_component_count(dst[0].write_mask); - type_id = spirv_compiler_get_type_id_for_dst(compiler, &dst[0]); - - src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst[0].write_mask); -@@ -7190,7 +7198,7 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, - { - if (!component_count || dst[0].write_mask != dst[1].write_mask) - { -- component_count = vkd3d_write_mask_component_count(dst[1].write_mask); -+ component_count = vsir_write_mask_component_count(dst[1].write_mask); - type_id = spirv_compiler_get_type_id_for_dst(compiler, &dst[1]); - - src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst[1].write_mask); -@@ -7228,7 +7236,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, - * as a signed integer, but Direct3D expects the result to saturate, - * and for NaN to yield zero. */ - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask); - dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); - src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); -@@ -7281,7 +7289,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, - * as an unsigned integer, but Direct3D expects the result to saturate, - * and for NaN to yield zero. */ - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask); - dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); - src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); -@@ -7468,7 +7476,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co - return; - } - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - - src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); -@@ -8621,7 +8629,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * - assert(data->reg.data_type == VKD3D_DATA_UINT); - val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - for (component_idx = 0; component_idx < component_count; ++component_idx) - { - data_id = component_count > 1 ? -@@ -8650,7 +8658,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * - assert(data->reg.data_type == VKD3D_DATA_UINT); - val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - for (component_idx = 0; component_idx < component_count; ++component_idx) - { - /* Mesa Vulkan drivers require the texel parameter to be a vector. */ -@@ -8694,7 +8702,7 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, - assert(data->reg.data_type == VKD3D_DATA_UINT); - val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); - -- component_count = vkd3d_write_mask_component_count(dst->write_mask); -+ component_count = vsir_write_mask_component_count(dst->write_mask); - for (component_idx = 0; component_idx < component_count; ++component_idx) - { - data_id = component_count > 1 ? -@@ -9356,7 +9364,7 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, - } - - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, -- vkd3d_write_mask_component_count(register_info.write_mask)); -+ vsir_write_mask_component_count(register_info.write_mask)); - - instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); - val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id, instr_set_id, op, src_ids, src_count); -@@ -9977,11 +9985,28 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - if (!vkd3d_spirv_compile_module(builder, spirv, spirv_compiler_get_entry_point_name(compiler))) - return VKD3D_ERROR; - -- if (TRACE_ON()) -+ if (TRACE_ON() || parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION) - { - enum vkd3d_shader_spirv_environment environment = spirv_compiler_get_target_environment(compiler); -- vkd3d_spirv_dump(spirv, environment); -- vkd3d_spirv_validate(spirv, environment); -+ struct vkd3d_string_buffer buffer; -+ -+ if (TRACE_ON()) -+ vkd3d_spirv_dump(spirv, environment); -+ -+ vkd3d_string_buffer_init(&buffer); -+ if (!vkd3d_spirv_validate(&buffer, spirv, environment)) -+ { -+ FIXME("Failed to validate SPIR-V binary.\n"); -+ vkd3d_shader_trace_text(buffer.buffer, buffer.content_size); -+ -+ if (compiler->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION) -+ { -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER, -+ "Execution generated an invalid shader, failing compilation:\n%s", -+ buffer.buffer); -+ } -+ } -+ vkd3d_string_buffer_cleanup(&buffer); - } - - if (compiler->failed) -@@ -10008,7 +10033,7 @@ int spirv_compile(struct vkd3d_shader_parser *parser, - int ret; - - if (!(spirv_compiler = spirv_compiler_create(&parser->shader_version, &parser->shader_desc, -- compile_info, scan_descriptor_info, message_context, &parser->location))) -+ compile_info, scan_descriptor_info, message_context, &parser->location, parser->config_flags))) - { - ERR("Failed to create SPIR-V compiler.\n"); - return VKD3D_ERROR; -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 1b009c13016..235e855223f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -920,10 +920,11 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins - uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) - { - struct vkd3d_shader_index_range *index_range = &ins->declaration.index_range; -- unsigned int i, register_idx, register_count, write_mask; -+ unsigned int i, register_idx, register_count; - enum vkd3d_shader_register_type type; - struct sm4_index_range_array *ranges; - unsigned int *io_masks; -+ uint32_t write_mask; - - shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, - &index_range->dst); -@@ -933,7 +934,7 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins - register_count = index_range->register_count; - write_mask = index_range->dst.write_mask; - -- if (vkd3d_write_mask_component_count(write_mask) != 1) -+ if (vsir_write_mask_component_count(write_mask) != 1) - { - WARN("Unhandled write mask %#x.\n", write_mask); - vkd3d_shader_parser_warning(&priv->p, VKD3D_SHADER_WARNING_TPF_UNHANDLED_INDEX_RANGE_MASK, -@@ -2230,7 +2231,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons - } - - if (data_type == VKD3D_DATA_DOUBLE) -- dst_param->write_mask = vkd3d_write_mask_64_from_32(dst_param->write_mask); -+ dst_param->write_mask = vsir_write_mask_64_from_32(dst_param->write_mask); - /* Some scalar registers are declared with no write mask in shader bytecode. */ - if (!dst_param->write_mask && shader_sm4_is_scalar_register(&dst_param->reg)) - dst_param->write_mask = VKD3DSP_WRITEMASK_0; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 0e8d75d9897..6fa57a111bb 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -96,6 +96,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_ERROR_SPV_INVALID_TYPE = 2006, - VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER = 2007, - VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED = 2008, -+ VKD3D_SHADER_ERROR_SPV_INVALID_SHADER = 2009, - - VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300, - -@@ -1515,7 +1516,7 @@ static inline enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum - return vkd3d_siv_from_sysval_indexed(sysval, 0); - } - --static inline unsigned int vkd3d_write_mask_get_component_idx(DWORD write_mask) -+static inline unsigned int vsir_write_mask_get_component_idx(uint32_t write_mask) - { - unsigned int i; - -@@ -1530,7 +1531,7 @@ static inline unsigned int vkd3d_write_mask_get_component_idx(DWORD write_mask) - return 0; - } - --static inline unsigned int vkd3d_write_mask_component_count(DWORD write_mask) -+static inline unsigned int vsir_write_mask_component_count(uint32_t write_mask) - { - unsigned int count = vkd3d_popcount(write_mask & VKD3DSP_WRITEMASK_ALL); - assert(1 <= count && count <= VKD3D_VEC4_SIZE); -@@ -1543,15 +1544,15 @@ static inline unsigned int vkd3d_write_mask_from_component_count(unsigned int co - return (VKD3DSP_WRITEMASK_0 << component_count) - 1; - } - --static inline unsigned int vkd3d_write_mask_64_from_32(DWORD write_mask32) -+static inline uint32_t vsir_write_mask_64_from_32(uint32_t write_mask32) - { -- unsigned int write_mask64 = write_mask32 | (write_mask32 >> 1); -+ uint32_t write_mask64 = write_mask32 | (write_mask32 >> 1); - return (write_mask64 & VKD3DSP_WRITEMASK_0) | ((write_mask64 & VKD3DSP_WRITEMASK_2) >> 1); - } - --static inline unsigned int vkd3d_write_mask_32_from_64(unsigned int write_mask64) -+static inline uint32_t vsir_write_mask_32_from_64(uint32_t write_mask64) - { -- unsigned int write_mask32 = (write_mask64 | (write_mask64 << 1)) -+ uint32_t write_mask32 = (write_mask64 | (write_mask64 << 1)) - & (VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_2); - return write_mask32 | (write_mask32 << 1); - } -diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c -index fc3187f4bea..9a039452c99 100644 ---- a/libs/vkd3d/libs/vkd3d/state.c -+++ b/libs/vkd3d/libs/vkd3d/state.c -@@ -515,7 +515,7 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat - assert(p->ShaderVisibility <= D3D12_SHADER_VISIBILITY_PIXEL); - push_constants[p->ShaderVisibility].stageFlags = use_vk_heaps ? VK_SHADER_STAGE_ALL - : stage_flags_from_visibility(p->ShaderVisibility); -- push_constants[p->ShaderVisibility].size += p->u.Constants.Num32BitValues * sizeof(uint32_t); -+ push_constants[p->ShaderVisibility].size += align(p->u.Constants.Num32BitValues, 4) * sizeof(uint32_t); - } - if (push_constants[D3D12_SHADER_VISIBILITY_ALL].size) - { -@@ -564,7 +564,7 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat - - idx = push_constant_count == 1 ? 0 : p->ShaderVisibility; - offset = push_constants_offset[idx]; -- push_constants_offset[idx] += p->u.Constants.Num32BitValues * sizeof(uint32_t); -+ push_constants_offset[idx] += align(p->u.Constants.Num32BitValues, 4) * sizeof(uint32_t); - - root_signature->parameters[i].parameter_type = p->ParameterType; - root_constant->stage_flags = push_constant_count == 1 --- -2.43.0 - diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-cd77b2a9be23b9a34d2d6a5cb566ac3873f.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-cd77b2a9be23b9a34d2d6a5cb566ac3873f.patch new file mode 100644 index 00000000..83a15a51 --- /dev/null +++ b/patches/vkd3d-latest/0003-Updated-vkd3d-to-cd77b2a9be23b9a34d2d6a5cb566ac3873f.patch @@ -0,0 +1,2252 @@ +From 8b637cc107807cf7a7179fc5c015c7d08c8d4f8f Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Thu, 18 Jan 2024 11:50:14 +1100 +Subject: [PATCH] Updated vkd3d to cd77b2a9be23b9a34d2d6a5cb566ac3873ff29b5. + +--- + libs/vkd3d/include/private/vkd3d_common.h | 20 +- + libs/vkd3d/include/private/vkd3d_debug.h | 23 + + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 2 + + libs/vkd3d/libs/vkd3d-shader/dxbc.c | 5 + + libs/vkd3d/libs/vkd3d-shader/dxil.c | 23 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 1 - + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 59 +- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 6 + + libs/vkd3d/libs/vkd3d-shader/ir.c | 758 +++++++++++++++++- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 648 +++++---------- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 26 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 14 + + libs/vkd3d/libs/vkd3d/resource.c | 4 +- + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 2 +- + 14 files changed, 1092 insertions(+), 499 deletions(-) + +diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h +index 4c97fa06e32..63e21c22067 100644 +--- a/libs/vkd3d/include/private/vkd3d_common.h ++++ b/libs/vkd3d/include/private/vkd3d_common.h +@@ -267,16 +267,28 @@ static inline int ascii_strcasecmp(const char *a, const char *b) + return c_a - c_b; + } + ++static inline uint64_t vkd3d_atomic_add_fetch_u64(uint64_t volatile *x, uint64_t val) ++{ ++#if HAVE_SYNC_ADD_AND_FETCH ++ return __sync_add_and_fetch(x, val); ++#elif defined(_WIN32) ++ return InterlockedAdd64((LONG64 *)x, val); ++#else ++# error "vkd3d_atomic_add_fetch_u64() not implemented for this platform" ++#endif ++} ++ ++static inline uint64_t vkd3d_atomic_increment_u64(uint64_t volatile *x) ++{ ++ return vkd3d_atomic_add_fetch_u64(x, 1); ++} ++ + #ifndef _WIN32 + # if HAVE_SYNC_ADD_AND_FETCH + static inline LONG InterlockedIncrement(LONG volatile *x) + { + return __sync_add_and_fetch(x, 1); + } +-static inline LONG64 InterlockedIncrement64(LONG64 volatile *x) +-{ +- return __sync_add_and_fetch(x, 1); +-} + # else + # error "InterlockedIncrement() not implemented for this platform" + # endif /* HAVE_SYNC_ADD_AND_FETCH */ +diff --git a/libs/vkd3d/include/private/vkd3d_debug.h b/libs/vkd3d/include/private/vkd3d_debug.h +index 6708cad344f..663fc311adf 100644 +--- a/libs/vkd3d/include/private/vkd3d_debug.h ++++ b/libs/vkd3d/include/private/vkd3d_debug.h +@@ -104,6 +104,29 @@ static inline const char *debugstr_guid(const GUID *guid) + guid->Data4[5], guid->Data4[6], guid->Data4[7]); + } + ++static inline const char *debugstr_hresult(HRESULT hr) ++{ ++ switch (hr) ++ { ++#define TO_STR(u) case u: return #u; ++ TO_STR(S_OK) ++ TO_STR(S_FALSE) ++ TO_STR(E_NOTIMPL) ++ TO_STR(E_NOINTERFACE) ++ TO_STR(E_POINTER) ++ TO_STR(E_ABORT) ++ TO_STR(E_FAIL) ++ TO_STR(E_OUTOFMEMORY) ++ TO_STR(E_INVALIDARG) ++ TO_STR(DXGI_ERROR_NOT_FOUND) ++ TO_STR(DXGI_ERROR_MORE_DATA) ++ TO_STR(DXGI_ERROR_UNSUPPORTED) ++#undef TO_STR ++ default: ++ return vkd3d_dbg_sprintf("%#x", (int)hr); ++ } ++} ++ + unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value); + + struct vkd3d_debug_option +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +index 4829956cecf..5685fe4d4a4 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +@@ -44,6 +44,7 @@ static const char * const shader_opcode_names[] = + [VKD3DSIH_BEM ] = "bem", + [VKD3DSIH_BFI ] = "bfi", + [VKD3DSIH_BFREV ] = "bfrev", ++ [VKD3DSIH_BRANCH ] = "branch", + [VKD3DSIH_BREAK ] = "break", + [VKD3DSIH_BREAKC ] = "breakc", + [VKD3DSIH_BREAKP ] = "breakp", +@@ -278,6 +279,7 @@ static const char * const shader_opcode_names[] = + [VKD3DSIH_SUB ] = "sub", + [VKD3DSIH_SWAPC ] = "swapc", + [VKD3DSIH_SWITCH ] = "switch", ++ [VKD3DSIH_SWITCH_MONOLITHIC ] = "switch", + [VKD3DSIH_SYNC ] = "sync", + [VKD3DSIH_TEX ] = "texld", + [VKD3DSIH_TEXBEM ] = "texbem", +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +index 37ebc73c099..edb65d2e92f 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +@@ -552,9 +552,14 @@ static int shdr_handler(const struct vkd3d_shader_dxbc_section_desc *section, + + void free_shader_desc(struct vkd3d_shader_desc *desc) + { ++ size_t i; ++ + shader_signature_cleanup(&desc->input_signature); + shader_signature_cleanup(&desc->output_signature); + shader_signature_cleanup(&desc->patch_constant_signature); ++ for (i = 0; i < desc->block_name_count; ++i) ++ vkd3d_free((void *)desc->block_names[i]); ++ vkd3d_free(desc->block_names); + } + + int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc, +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index b39ec204bff..78c1a052539 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -2691,8 +2691,8 @@ static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type + } + + static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, +- unsigned int count, unsigned int alignment, unsigned int init, struct vkd3d_shader_instruction *ins, +- struct sm6_value *dst) ++ unsigned int count, unsigned int alignment, bool has_function_scope, unsigned int init, ++ struct vkd3d_shader_instruction *ins, struct sm6_value *dst) + { + enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); + +@@ -2705,6 +2705,7 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const stru + ins->declaration.indexable_temp.alignment = alignment; + ins->declaration.indexable_temp.data_type = data_type; + ins->declaration.indexable_temp.component_count = 1; ++ ins->declaration.indexable_temp.has_function_scope = has_function_scope; + /* The initialiser value index will be resolved later so forward references can be handled. */ + ins->declaration.indexable_temp.initialiser = (void *)(uintptr_t)init; + +@@ -2832,7 +2833,7 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ + if (is_constant) + sm6_parser_declare_icb(sm6, scalar_type, count, alignment, init, dst); + else +- sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, NULL, dst); ++ sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, false, init, NULL, dst); + } + else if (address_space == ADDRESS_SPACE_GROUPSHARED) + { +@@ -3103,7 +3104,7 @@ static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_rec + if (packed_operands) + WARN("Ignoring flags %#"PRIx64".\n", packed_operands); + +- sm6_parser_declare_indexable_temp(sm6, elem_type, type[0]->u.array.count, alignment, 0, ins, dst); ++ sm6_parser_declare_indexable_temp(sm6, elem_type, type[0]->u.array.count, alignment, true, 0, ins, dst); + } + + static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_type *type_a, +@@ -4868,6 +4869,18 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st + return VKD3D_OK; + } + ++static void sm6_parser_emit_label(struct sm6_parser *sm6, unsigned int label_id) ++{ ++ struct vkd3d_shader_src_param *src_param; ++ struct vkd3d_shader_instruction *ins; ++ ++ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_LABEL); ++ ++ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ return; ++ vsir_src_param_init_label(src_param, label_id); ++} ++ + static bool sm6_parser_allocate_named_metadata(struct sm6_parser *sm6) + { + struct dxil_block *block; +@@ -6216,6 +6229,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + } + + sm6->p.shader_desc.ssa_count = sm6->ssa_next_id; ++ sm6->p.shader_desc.block_count = 1; + + if (!(fn = sm6_parser_get_function(sm6, sm6->entry_point))) + { +@@ -6226,6 +6240,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t + } + + assert(sm6->function_count == 1); ++ sm6_parser_emit_label(sm6, 1); + if (!sm6_block_emit_instructions(fn->blocks[0], sm6)) + { + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +index 1e247445119..6a5a6d0e3c1 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +@@ -3363,7 +3363,6 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) + effect_types[] = + { + {"dword", HLSL_CLASS_SCALAR, HLSL_TYPE_UINT, 1, 1}, +- {"float", HLSL_CLASS_SCALAR, HLSL_TYPE_FLOAT, 1, 1}, + {"vector", HLSL_CLASS_VECTOR, HLSL_TYPE_FLOAT, 4, 1}, + {"matrix", HLSL_CLASS_MATRIX, HLSL_TYPE_FLOAT, 4, 4}, + {"fxgroup", HLSL_CLASS_OBJECT, HLSL_TYPE_EFFECT_GROUP, 1, 1}, +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index b11cbde26f1..e30b3dc5f55 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -4085,6 +4085,49 @@ static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type + return params->instrs; + } + ++static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, ++ struct hlsl_ir_node *cond, struct hlsl_ir_node *first, struct hlsl_ir_node *second) ++{ ++ struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; ++ struct hlsl_type *common_type; ++ ++ if (first->data_type->class <= HLSL_CLASS_LAST_NUMERIC ++ && second->data_type->class <= HLSL_CLASS_LAST_NUMERIC) ++ { ++ if (!(common_type = get_common_numeric_type(ctx, first, second, &first->loc))) ++ return false; ++ ++ if (!(first = add_implicit_conversion(ctx, block, first, common_type, &first->loc))) ++ return false; ++ ++ if (!(second = add_implicit_conversion(ctx, block, second, common_type, &second->loc))) ++ return false; ++ } ++ else ++ { ++ struct vkd3d_string_buffer *first_string, *second_string; ++ ++ if (!hlsl_types_are_equal(first->data_type, second->data_type)) ++ { ++ first_string = hlsl_type_to_string(ctx, first->data_type); ++ second_string = hlsl_type_to_string(ctx, second->data_type); ++ if (first_string && second_string) ++ hlsl_error(ctx, &first->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, ++ "Ternary argument types '%s' and '%s' do not match.", ++ first_string->buffer, second_string->buffer); ++ hlsl_release_string_buffer(ctx, first_string); ++ hlsl_release_string_buffer(ctx, second_string); ++ } ++ ++ common_type = first->data_type; ++ } ++ ++ args[0] = cond; ++ args[1] = first; ++ args[2] = second; ++ return add_expr(ctx, block, HLSL_OP3_TERNARY, args, common_type, &first->loc); ++} ++ + static unsigned int hlsl_offset_dim_count(enum hlsl_sampler_dim dim) + { + switch (dim) +@@ -7202,27 +7245,13 @@ conditional_expr: + struct hlsl_ir_node *cond = node_from_block($1); + struct hlsl_ir_node *first = node_from_block($3); + struct hlsl_ir_node *second = node_from_block($5); +- struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = { 0 }; +- struct hlsl_type *common_type; + + hlsl_block_add_block($1, $3); + hlsl_block_add_block($1, $5); + destroy_block($3); + destroy_block($5); + +- if (!(common_type = get_common_numeric_type(ctx, first, second, &@3))) +- YYABORT; +- +- if (!(first = add_implicit_conversion(ctx, $1, first, common_type, &@3))) +- YYABORT; +- +- if (!(second = add_implicit_conversion(ctx, $1, second, common_type, &@5))) +- YYABORT; +- +- args[0] = cond; +- args[1] = first; +- args[2] = second; +- if (!add_expr(ctx, $1, HLSL_OP3_TERNARY, args, common_type, &@1)) ++ if (!add_ternary(ctx, $1, cond, first, second)) + YYABORT; + $$ = $1; + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index d37bef15cce..1fe141a346a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -2890,6 +2890,12 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru + first = expr->operands[1].node; + second = expr->operands[2].node; + ++ if (cond->data_type->class > HLSL_CLASS_VECTOR || instr->data_type->class > HLSL_CLASS_VECTOR) ++ { ++ hlsl_fixme(ctx, &instr->loc, "Lower ternary of type other than scalar or vector.\n"); ++ return false; ++ } ++ + if (ctx->profile->major_version < 4 && ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL) + { + struct hlsl_ir_node *abs, *neg; +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 28c7d158452..d6978171beb 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -312,6 +312,21 @@ void vsir_register_init(struct vkd3d_shader_register *reg, enum vkd3d_shader_reg + reg->alignment = 0; + } + ++static 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) ++{ ++ vsir_register_init(¶m->reg, reg_type, data_type, idx_count); ++ param->swizzle = 0; ++ param->modifiers = VKD3DSPSM_NONE; ++} ++ ++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_UINT, 1); ++ param->reg.dimension = VSIR_DIMENSION_NONE; ++ param->reg.idx[0].offset = label_id; ++} ++ + void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, + enum vkd3d_shader_opcode handler_idx) + { +@@ -320,6 +335,23 @@ void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vk + ins->handler_idx = handler_idx; + } + ++static bool vsir_instruction_init_label(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, ++ unsigned int label_id, void *parser) ++{ ++ struct vkd3d_shader_src_param *src_param; ++ ++ if (!(src_param = shader_parser_get_src_params(parser, 1))) ++ return false; ++ ++ vsir_src_param_init_label(src_param, label_id); ++ ++ vsir_instruction_init(ins, location, VKD3DSIH_LABEL); ++ ins->src = src_param; ++ ins->src_count = 1; ++ ++ return true; ++} ++ + static enum vkd3d_result instruction_array_flatten_hull_shader_phases(struct vkd3d_shader_instruction_array *src_instructions) + { + struct hull_flattener flattener = {*src_instructions}; +@@ -571,7 +603,7 @@ static bool io_normaliser_is_in_control_point_phase(const struct io_normaliser * + static unsigned int shader_signature_find_element_for_reg(const struct shader_signature *signature, + unsigned int reg_idx, unsigned int write_mask) + { +- unsigned int i; ++ unsigned int i, base_write_mask; + + for (i = 0; i < signature->element_count; ++i) + { +@@ -583,7 +615,14 @@ static unsigned int shader_signature_find_element_for_reg(const struct shader_si + } + } + +- /* Validated in the TPF reader. */ ++ /* 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); ++ + vkd3d_unreachable(); + } + +@@ -750,6 +789,51 @@ static int signature_element_index_compare(const void *a, const void *b) + return vkd3d_u32_compare(e->sort_index, f->sort_index); + } + ++static unsigned int signature_element_range_expand_mask(struct signature_element *e, unsigned int register_count, ++ uint8_t range_map[][VKD3D_VEC4_SIZE]) ++{ ++ unsigned int i, j, component_idx, component_count, merged_write_mask = e->mask; ++ ++ /* dcl_indexrange instructions can declare a subset of the full mask, and the masks of ++ * the elements within the range may differ. TPF's handling of arrayed inputs with ++ * dcl_indexrange is really just a hack. Here we create a mask which covers all element ++ * masks, and check for collisions with other ranges. */ ++ ++ for (i = 1; i < register_count; ++i) ++ merged_write_mask |= e[i].mask; ++ ++ if (merged_write_mask == e->mask) ++ return merged_write_mask; ++ ++ /* Reaching this point is very rare to begin with, and collisions are even rarer or ++ * impossible. If the latter shows up, the fallback in shader_signature_find_element_for_reg() ++ * may be sufficient. */ ++ ++ component_idx = vsir_write_mask_get_component_idx(e->mask); ++ component_count = vsir_write_mask_component_count(e->mask); ++ ++ for (i = e->register_index; i < e->register_index + register_count; ++i) ++ { ++ for (j = 0; j < component_idx; ++j) ++ if (range_map[i][j]) ++ break; ++ for (j = component_idx + component_count; j < VKD3D_VEC4_SIZE; ++j) ++ if (range_map[i][j]) ++ break; ++ } ++ ++ if (i == register_count) ++ { ++ WARN("Expanding mask %#x to %#x for %s, base reg %u, count %u.\n", e->mask, merged_write_mask, ++ e->semantic_name, e->register_index, register_count); ++ return merged_write_mask; ++ } ++ ++ WARN("Cannot expand mask %#x to %#x for %s, base reg %u, count %u.\n", e->mask, merged_write_mask, ++ e->semantic_name, e->register_index, register_count); ++ return e->mask; ++} ++ + static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map[][VKD3D_VEC4_SIZE], + bool is_patch_constant) + { +@@ -820,6 +904,7 @@ 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); + } + } + element_count = new_count; +@@ -844,6 +929,13 @@ static unsigned int shader_register_normalise_arrayed_addressing(struct vkd3d_sh + reg->idx[id_idx + 1].rel_addr = NULL; + reg->idx[id_idx + 1].offset = reg->idx[id_idx].offset; + reg->idx[id_idx].offset -= register_index; ++ if (id_idx) ++ { ++ /* idx[id_idx] now contains the array index, which must be moved below the control point id. */ ++ struct vkd3d_shader_register_index tmp = reg->idx[id_idx]; ++ reg->idx[id_idx] = reg->idx[id_idx - 1]; ++ reg->idx[id_idx - 1] = tmp; ++ } + ++id_idx; + } + /* Otherwise we have no address for the arrayed register, so insert one. This happens e.g. where +@@ -1476,6 +1568,665 @@ static enum vkd3d_result normalise_combined_samplers(struct vkd3d_shader_parser + return VKD3D_OK; + } + ++struct cf_flattener_if_info ++{ ++ struct vkd3d_shader_src_param *false_param; ++ unsigned int id; ++ uint32_t merge_block_id; ++ unsigned int else_block_id; ++}; ++ ++struct cf_flattener_loop_info ++{ ++ unsigned int header_block_id; ++ unsigned int continue_block_id; ++ uint32_t merge_block_id; ++}; ++ ++struct cf_flattener_switch_case ++{ ++ unsigned int value; ++ unsigned int block_id; ++}; ++ ++struct cf_flattener_switch_info ++{ ++ size_t ins_location; ++ const struct vkd3d_shader_src_param *condition; ++ unsigned int id; ++ unsigned int merge_block_id; ++ unsigned int default_block_id; ++ struct cf_flattener_switch_case *cases; ++ size_t cases_size; ++ unsigned int cases_count; ++}; ++ ++struct cf_flattener_info ++{ ++ union ++ { ++ struct cf_flattener_if_info if_; ++ struct cf_flattener_loop_info loop; ++ struct cf_flattener_switch_info switch_; ++ } u; ++ ++ enum ++ { ++ VKD3D_BLOCK_IF, ++ VKD3D_BLOCK_LOOP, ++ VKD3D_BLOCK_SWITCH, ++ } current_block; ++ bool inside_block; ++}; ++ ++struct cf_flattener ++{ ++ struct vkd3d_shader_parser *parser; ++ ++ struct vkd3d_shader_location location; ++ bool allocation_failed; ++ ++ struct vkd3d_shader_instruction *instructions; ++ size_t instruction_capacity; ++ size_t instruction_count; ++ ++ unsigned int block_id; ++ const char **block_names; ++ size_t block_name_capacity; ++ size_t block_name_count; ++ ++ unsigned int branch_id; ++ unsigned int loop_id; ++ unsigned int switch_id; ++ ++ unsigned int control_flow_depth; ++ struct cf_flattener_info *control_flow_info; ++ size_t control_flow_info_size; ++}; ++ ++static struct vkd3d_shader_instruction *cf_flattener_require_space(struct cf_flattener *flattener, size_t count) ++{ ++ if (!vkd3d_array_reserve((void **)&flattener->instructions, &flattener->instruction_capacity, ++ flattener->instruction_count + count, sizeof(*flattener->instructions))) ++ { ++ ERR("Failed to allocate instructions.\n"); ++ flattener->allocation_failed = true; ++ return NULL; ++ } ++ return &flattener->instructions[flattener->instruction_count]; ++} ++ ++static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ struct vkd3d_shader_instruction *dst_ins; ++ ++ if (instruction->handler_idx == VKD3DSIH_NOP) ++ return true; ++ ++ if (!(dst_ins = cf_flattener_require_space(flattener, 1))) ++ return false; ++ ++ *dst_ins = *instruction; ++ ++flattener->instruction_count; ++ return true; ++} ++ ++static unsigned int cf_flattener_alloc_block_id(struct cf_flattener *flattener) ++{ ++ return ++flattener->block_id; ++} ++ ++static struct vkd3d_shader_src_param *instruction_src_params_alloc(struct vkd3d_shader_instruction *ins, ++ unsigned int count, struct cf_flattener *flattener) ++{ ++ struct vkd3d_shader_src_param *params = shader_parser_get_src_params(flattener->parser, count); ++ if (!params) ++ { ++ flattener->allocation_failed = true; ++ return NULL; ++ } ++ ins->src = params; ++ ins->src_count = count; ++ return params; ++} ++ ++static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int label_id) ++{ ++ struct vkd3d_shader_instruction *ins; ++ ++ if (!(ins = cf_flattener_require_space(flattener, 1))) ++ return; ++ if (vsir_instruction_init_label(ins, &flattener->location, label_id, flattener->parser)) ++ ++flattener->instruction_count; ++ else ++ flattener->allocation_failed = true; ++} ++ ++/* For conditional branches, this returns the false target branch parameter. */ ++static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flattener *flattener, ++ unsigned int merge_block_id, unsigned int continue_block_id, ++ const struct vkd3d_shader_src_param *condition, unsigned int true_id, unsigned int false_id, ++ unsigned int flags) ++{ ++ struct vkd3d_shader_src_param *src_params, *false_branch_param; ++ struct vkd3d_shader_instruction *ins; ++ ++ if (!(ins = cf_flattener_require_space(flattener, 1))) ++ return NULL; ++ vsir_instruction_init(ins, &flattener->location, VKD3DSIH_BRANCH); ++ ++ if (condition) ++ { ++ if (!(src_params = instruction_src_params_alloc(ins, 4 + !!continue_block_id, flattener))) ++ return NULL; ++ src_params[0] = *condition; ++ if (flags == VKD3D_SHADER_CONDITIONAL_OP_Z) ++ { ++ vsir_src_param_init_label(&src_params[1], false_id); ++ vsir_src_param_init_label(&src_params[2], true_id); ++ false_branch_param = &src_params[1]; ++ } ++ else ++ { ++ vsir_src_param_init_label(&src_params[1], true_id); ++ vsir_src_param_init_label(&src_params[2], false_id); ++ false_branch_param = &src_params[2]; ++ } ++ vsir_src_param_init_label(&src_params[3], merge_block_id); ++ if (continue_block_id) ++ vsir_src_param_init_label(&src_params[4], continue_block_id); ++ } ++ else ++ { ++ if (!(src_params = instruction_src_params_alloc(ins, merge_block_id ? 3 : 1, flattener))) ++ return NULL; ++ vsir_src_param_init_label(&src_params[0], true_id); ++ if (merge_block_id) ++ { ++ /* An unconditional branch may only have merge information for a loop, which ++ * must have both a merge block and continue block. */ ++ vsir_src_param_init_label(&src_params[1], merge_block_id); ++ vsir_src_param_init_label(&src_params[2], continue_block_id); ++ } ++ false_branch_param = NULL; ++ } ++ ++ ++flattener->instruction_count; ++ ++ return false_branch_param; ++} ++ ++static void cf_flattener_emit_conditional_branch_and_merge(struct cf_flattener *flattener, ++ const struct vkd3d_shader_src_param *condition, unsigned int true_id, unsigned int flags) ++{ ++ unsigned int merge_block_id; ++ ++ merge_block_id = cf_flattener_alloc_block_id(flattener); ++ cf_flattener_emit_branch(flattener, merge_block_id, 0, condition, true_id, merge_block_id, flags); ++ cf_flattener_emit_label(flattener, merge_block_id); ++} ++ ++static void cf_flattener_emit_unconditional_branch(struct cf_flattener *flattener, unsigned int target_block_id) ++{ ++ cf_flattener_emit_branch(flattener, 0, 0, NULL, target_block_id, 0, 0); ++} ++ ++static struct cf_flattener_info *cf_flattener_push_control_flow_level(struct cf_flattener *flattener) ++{ ++ if (!vkd3d_array_reserve((void **)&flattener->control_flow_info, &flattener->control_flow_info_size, ++ flattener->control_flow_depth + 1, sizeof(*flattener->control_flow_info))) ++ { ++ ERR("Failed to allocate control flow info structure.\n"); ++ flattener->allocation_failed = true; ++ return NULL; ++ } ++ ++ return &flattener->control_flow_info[flattener->control_flow_depth++]; ++} ++ ++static void cf_flattener_pop_control_flow_level(struct cf_flattener *flattener) ++{ ++ struct cf_flattener_info *cf_info; ++ ++ cf_info = &flattener->control_flow_info[--flattener->control_flow_depth]; ++ memset(cf_info, 0, sizeof(*cf_info)); ++} ++ ++static struct cf_flattener_info *cf_flattener_find_innermost_loop(struct cf_flattener *flattener) ++{ ++ int depth; ++ ++ for (depth = flattener->control_flow_depth - 1; depth >= 0; --depth) ++ { ++ if (flattener->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP) ++ return &flattener->control_flow_info[depth]; ++ } ++ ++ return NULL; ++} ++ ++static struct cf_flattener_info *cf_flattener_find_innermost_breakable_cf_construct(struct cf_flattener *flattener) ++{ ++ int depth; ++ ++ for (depth = flattener->control_flow_depth - 1; depth >= 0; --depth) ++ { ++ if (flattener->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP ++ || flattener->control_flow_info[depth].current_block == VKD3D_BLOCK_SWITCH) ++ return &flattener->control_flow_info[depth]; ++ } ++ ++ return NULL; ++} ++ ++static void VKD3D_PRINTF_FUNC(3, 4) cf_flattener_create_block_name(struct cf_flattener *flattener, ++ unsigned int block_id, const char *fmt, ...) ++{ ++ struct vkd3d_string_buffer buffer; ++ size_t block_name_count; ++ va_list args; ++ ++ --block_id; ++ ++ block_name_count = max(flattener->block_name_count, block_id + 1); ++ if (!vkd3d_array_reserve((void **)&flattener->block_names, &flattener->block_name_capacity, ++ block_name_count, sizeof(*flattener->block_names))) ++ return; ++ memset(&flattener->block_names[flattener->block_name_count], 0, ++ (block_name_count - flattener->block_name_count) * sizeof(*flattener->block_names)); ++ flattener->block_name_count = block_name_count; ++ ++ vkd3d_string_buffer_init(&buffer); ++ va_start(args, fmt); ++ vkd3d_string_buffer_vprintf(&buffer, fmt, args); ++ va_end(args); ++ ++ flattener->block_names[block_id] = buffer.buffer; ++} ++ ++static bool vsir_instruction_is_dcl(const struct vkd3d_shader_instruction *instruction) ++{ ++ enum vkd3d_shader_opcode handler_idx = instruction->handler_idx; ++ return (VKD3DSIH_DCL <= handler_idx && handler_idx <= VKD3DSIH_DCL_VERTICES_OUT) ++ || handler_idx == VKD3DSIH_HS_DECLS; ++} ++ ++static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flattener *flattener) ++{ ++ bool main_block_open, is_hull_shader, after_declarations_section; ++ struct vkd3d_shader_parser *parser = flattener->parser; ++ struct vkd3d_shader_instruction_array *instructions; ++ struct vkd3d_shader_instruction *dst_ins; ++ size_t i; ++ ++ instructions = &parser->instructions; ++ is_hull_shader = parser->shader_version.type == VKD3D_SHADER_TYPE_HULL; ++ main_block_open = !is_hull_shader; ++ after_declarations_section = is_hull_shader; ++ ++ if (!cf_flattener_require_space(flattener, instructions->count + 1)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ for (i = 0; i < instructions->count; ++i) ++ { ++ unsigned int loop_header_block_id, loop_body_block_id, continue_block_id, merge_block_id, true_block_id; ++ const struct vkd3d_shader_instruction *instruction = &instructions->elements[i]; ++ const struct vkd3d_shader_src_param *src = instruction->src; ++ struct cf_flattener_info *cf_info; ++ ++ flattener->location = instruction->location; ++ ++ /* Declarations should occur before the first code block, which in hull shaders is marked by the first ++ * phase instruction, and in all other shader types begins with the first label instruction. */ ++ if (!after_declarations_section && !vsir_instruction_is_dcl(instruction) ++ && instruction->handler_idx != VKD3DSIH_NOP) ++ { ++ after_declarations_section = true; ++ cf_flattener_emit_label(flattener, cf_flattener_alloc_block_id(flattener)); ++ } ++ ++ cf_info = flattener->control_flow_depth ++ ? &flattener->control_flow_info[flattener->control_flow_depth - 1] : NULL; ++ ++ switch (instruction->handler_idx) ++ { ++ case VKD3DSIH_HS_CONTROL_POINT_PHASE: ++ case VKD3DSIH_HS_FORK_PHASE: ++ case VKD3DSIH_HS_JOIN_PHASE: ++ if (!cf_flattener_copy_instruction(flattener, instruction)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ if (instruction->handler_idx != VKD3DSIH_HS_CONTROL_POINT_PHASE || !instruction->flags) ++ after_declarations_section = false; ++ break; ++ ++ case VKD3DSIH_LABEL: ++ vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, ++ "Aborting due to not yet implemented feature: Label instruction."); ++ return VKD3D_ERROR_NOT_IMPLEMENTED; ++ ++ case VKD3DSIH_IF: ++ if (!(cf_info = cf_flattener_push_control_flow_level(flattener))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ true_block_id = cf_flattener_alloc_block_id(flattener); ++ merge_block_id = cf_flattener_alloc_block_id(flattener); ++ cf_info->u.if_.false_param = cf_flattener_emit_branch(flattener, merge_block_id, 0, ++ src, true_block_id, merge_block_id, instruction->flags); ++ if (!cf_info->u.if_.false_param) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ cf_flattener_emit_label(flattener, true_block_id); ++ ++ cf_info->u.if_.id = flattener->branch_id; ++ cf_info->u.if_.merge_block_id = merge_block_id; ++ cf_info->u.if_.else_block_id = 0; ++ cf_info->inside_block = true; ++ cf_info->current_block = VKD3D_BLOCK_IF; ++ ++ cf_flattener_create_block_name(flattener, merge_block_id, "branch%u_merge", flattener->branch_id); ++ cf_flattener_create_block_name(flattener, true_block_id, "branch%u_true", flattener->branch_id); ++ ++flattener->branch_id; ++ break; ++ ++ case VKD3DSIH_ELSE: ++ if (cf_info->inside_block) ++ cf_flattener_emit_unconditional_branch(flattener, cf_info->u.if_.merge_block_id); ++ ++ cf_info->u.if_.else_block_id = cf_flattener_alloc_block_id(flattener); ++ cf_info->u.if_.false_param->reg.idx[0].offset = cf_info->u.if_.else_block_id; ++ ++ cf_flattener_create_block_name(flattener, ++ cf_info->u.if_.else_block_id, "branch%u_false", cf_info->u.if_.id); ++ cf_flattener_emit_label(flattener, cf_info->u.if_.else_block_id); ++ ++ cf_info->inside_block = true; ++ break; ++ ++ case VKD3DSIH_ENDIF: ++ if (cf_info->inside_block) ++ cf_flattener_emit_unconditional_branch(flattener, cf_info->u.if_.merge_block_id); ++ ++ cf_flattener_emit_label(flattener, cf_info->u.if_.merge_block_id); ++ ++ cf_flattener_pop_control_flow_level(flattener); ++ break; ++ ++ case VKD3DSIH_LOOP: ++ if (!(cf_info = cf_flattener_push_control_flow_level(flattener))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ loop_header_block_id = cf_flattener_alloc_block_id(flattener); ++ loop_body_block_id = cf_flattener_alloc_block_id(flattener); ++ continue_block_id = cf_flattener_alloc_block_id(flattener); ++ merge_block_id = cf_flattener_alloc_block_id(flattener); ++ ++ cf_flattener_emit_unconditional_branch(flattener, loop_header_block_id); ++ cf_flattener_emit_label(flattener, loop_header_block_id); ++ cf_flattener_emit_branch(flattener, merge_block_id, continue_block_id, ++ NULL, loop_body_block_id, 0, 0); ++ ++ cf_flattener_emit_label(flattener, loop_body_block_id); ++ ++ cf_info->u.loop.header_block_id = loop_header_block_id; ++ cf_info->u.loop.continue_block_id = continue_block_id; ++ cf_info->u.loop.merge_block_id = merge_block_id; ++ cf_info->current_block = VKD3D_BLOCK_LOOP; ++ cf_info->inside_block = true; ++ ++ cf_flattener_create_block_name(flattener, loop_header_block_id, "loop%u_header", flattener->loop_id); ++ cf_flattener_create_block_name(flattener, loop_body_block_id, "loop%u_body", flattener->loop_id); ++ cf_flattener_create_block_name(flattener, continue_block_id, "loop%u_continue", flattener->loop_id); ++ cf_flattener_create_block_name(flattener, merge_block_id, "loop%u_merge", flattener->loop_id); ++ ++flattener->loop_id; ++ break; ++ ++ case VKD3DSIH_ENDLOOP: ++ if (cf_info->inside_block) ++ cf_flattener_emit_unconditional_branch(flattener, cf_info->u.loop.continue_block_id); ++ ++ cf_flattener_emit_label(flattener, cf_info->u.loop.continue_block_id); ++ cf_flattener_emit_unconditional_branch(flattener, cf_info->u.loop.header_block_id); ++ cf_flattener_emit_label(flattener, cf_info->u.loop.merge_block_id); ++ ++ cf_flattener_pop_control_flow_level(flattener); ++ break; ++ ++ case VKD3DSIH_SWITCH: ++ if (!(cf_info = cf_flattener_push_control_flow_level(flattener))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ merge_block_id = cf_flattener_alloc_block_id(flattener); ++ ++ cf_info->u.switch_.ins_location = flattener->instruction_count; ++ cf_info->u.switch_.condition = src; ++ ++ if (!(dst_ins = cf_flattener_require_space(flattener, 1))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ vsir_instruction_init(dst_ins, &instruction->location, VKD3DSIH_SWITCH_MONOLITHIC); ++ ++flattener->instruction_count; ++ ++ cf_info->u.switch_.id = flattener->switch_id; ++ cf_info->u.switch_.merge_block_id = merge_block_id; ++ cf_info->u.switch_.cases = NULL; ++ cf_info->u.switch_.cases_size = 0; ++ cf_info->u.switch_.cases_count = 0; ++ cf_info->u.switch_.default_block_id = 0; ++ cf_info->inside_block = false; ++ cf_info->current_block = VKD3D_BLOCK_SWITCH; ++ ++ cf_flattener_create_block_name(flattener, merge_block_id, "switch%u_merge", flattener->switch_id); ++ ++flattener->switch_id; ++ ++ if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.cases, &cf_info->u.switch_.cases_size, ++ 10, sizeof(*cf_info->u.switch_.cases))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ break; ++ ++ case VKD3DSIH_ENDSWITCH: ++ { ++ struct vkd3d_shader_src_param *src_params; ++ unsigned int j; ++ ++ if (!cf_info->u.switch_.default_block_id) ++ cf_info->u.switch_.default_block_id = cf_info->u.switch_.merge_block_id; ++ ++ cf_flattener_emit_label(flattener, cf_info->u.switch_.merge_block_id); ++ ++ /* The SWITCH instruction is completed when the endswitch ++ * instruction is processed because we do not know the number ++ * of case statements or the default block id in advance.*/ ++ dst_ins = &flattener->instructions[cf_info->u.switch_.ins_location]; ++ if (!(src_params = instruction_src_params_alloc(dst_ins, cf_info->u.switch_.cases_count * 2 + 3, flattener))) ++ { ++ vkd3d_free(cf_info->u.switch_.cases); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ } ++ src_params[0] = *cf_info->u.switch_.condition; ++ vsir_src_param_init_label(&src_params[1], cf_info->u.switch_.default_block_id); ++ vsir_src_param_init_label(&src_params[2], cf_info->u.switch_.merge_block_id); ++ for (j = 0; j < cf_info->u.switch_.cases_count; ++j) ++ { ++ unsigned int index = j * 2 + 3; ++ vsir_src_param_init(&src_params[index], VKD3DSPR_IMMCONST, VKD3D_DATA_UINT, 0); ++ src_params[index].reg.u.immconst_u32[0] = cf_info->u.switch_.cases[j].value; ++ vsir_src_param_init_label(&src_params[index + 1], cf_info->u.switch_.cases[j].block_id); ++ } ++ vkd3d_free(cf_info->u.switch_.cases); ++ ++ cf_flattener_pop_control_flow_level(flattener); ++ break; ++ } ++ ++ case VKD3DSIH_CASE: ++ { ++ unsigned int label_id, value; ++ ++ if (src->swizzle != VKD3D_SHADER_SWIZZLE(X, X, X, X)) ++ { ++ WARN("Unexpected src swizzle %#x.\n", src->swizzle); ++ vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, ++ "The swizzle for a switch case value is not scalar X."); ++ } ++ value = *src->reg.u.immconst_u32; ++ ++ if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.cases, &cf_info->u.switch_.cases_size, ++ cf_info->u.switch_.cases_count + 1, sizeof(*cf_info->u.switch_.cases))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ label_id = cf_flattener_alloc_block_id(flattener); ++ if (cf_info->inside_block) /* fall-through */ ++ cf_flattener_emit_unconditional_branch(flattener, label_id); ++ ++ cf_info->u.switch_.cases[cf_info->u.switch_.cases_count].value = value; ++ cf_info->u.switch_.cases[cf_info->u.switch_.cases_count].block_id = label_id; ++ ++cf_info->u.switch_.cases_count; ++ ++ cf_flattener_emit_label(flattener, label_id); ++ cf_flattener_create_block_name(flattener, label_id, "switch%u_case%u", cf_info->u.switch_.id, value); ++ cf_info->inside_block = true; ++ break; ++ } ++ ++ case VKD3DSIH_DEFAULT: ++ cf_info->u.switch_.default_block_id = cf_flattener_alloc_block_id(flattener); ++ if (cf_info->inside_block) /* fall-through */ ++ cf_flattener_emit_unconditional_branch(flattener, cf_info->u.switch_.default_block_id); ++ ++ cf_flattener_emit_label(flattener, cf_info->u.switch_.default_block_id); ++ ++ cf_flattener_create_block_name(flattener, cf_info->u.switch_.default_block_id, ++ "switch%u_default", cf_info->u.switch_.id); ++ cf_info->inside_block = true; ++ break; ++ ++ case VKD3DSIH_BREAK: ++ { ++ struct cf_flattener_info *breakable_cf_info; ++ ++ if (!(breakable_cf_info = cf_flattener_find_innermost_breakable_cf_construct(flattener))) ++ { ++ FIXME("Unhandled break instruction.\n"); ++ return VKD3D_ERROR_INVALID_SHADER; ++ } ++ ++ if (breakable_cf_info->current_block == VKD3D_BLOCK_LOOP) ++ { ++ cf_flattener_emit_unconditional_branch(flattener, breakable_cf_info->u.loop.merge_block_id); ++ } ++ else if (breakable_cf_info->current_block == VKD3D_BLOCK_SWITCH) ++ { ++ cf_flattener_emit_unconditional_branch(flattener, breakable_cf_info->u.switch_.merge_block_id); ++ } ++ ++ cf_info->inside_block = false; ++ break; ++ } ++ ++ case VKD3DSIH_BREAKP: ++ { ++ struct cf_flattener_info *loop_cf_info; ++ ++ if (!(loop_cf_info = cf_flattener_find_innermost_loop(flattener))) ++ { ++ ERR("Invalid 'breakc' instruction outside loop.\n"); ++ return VKD3D_ERROR_INVALID_SHADER; ++ } ++ ++ cf_flattener_emit_conditional_branch_and_merge(flattener, ++ src, loop_cf_info->u.loop.merge_block_id, instruction->flags); ++ break; ++ } ++ ++ case VKD3DSIH_CONTINUE: ++ { ++ struct cf_flattener_info *loop_cf_info; ++ ++ if (!(loop_cf_info = cf_flattener_find_innermost_loop(flattener))) ++ { ++ ERR("Invalid 'continue' instruction outside loop.\n"); ++ return VKD3D_ERROR_INVALID_SHADER; ++ } ++ ++ cf_flattener_emit_unconditional_branch(flattener, loop_cf_info->u.loop.continue_block_id); ++ ++ cf_info->inside_block = false; ++ break; ++ } ++ ++ case VKD3DSIH_CONTINUEP: ++ { ++ struct cf_flattener_info *loop_cf_info; ++ ++ if (!(loop_cf_info = cf_flattener_find_innermost_loop(flattener))) ++ { ++ ERR("Invalid 'continuec' instruction outside loop.\n"); ++ return VKD3D_ERROR_INVALID_SHADER; ++ } ++ ++ cf_flattener_emit_conditional_branch_and_merge(flattener, ++ src, loop_cf_info->u.loop.continue_block_id, instruction->flags); ++ break; ++ } ++ ++ case VKD3DSIH_RET: ++ if (!cf_flattener_copy_instruction(flattener, instruction)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ if (cf_info) ++ cf_info->inside_block = false; ++ else ++ main_block_open = false; ++ break; ++ ++ default: ++ if (!cf_flattener_copy_instruction(flattener, instruction)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ break; ++ } ++ } ++ ++ if (main_block_open) ++ { ++ if (!(dst_ins = cf_flattener_require_space(flattener, 1))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ vsir_instruction_init(dst_ins, &flattener->location, VKD3DSIH_RET); ++ ++flattener->instruction_count; ++ } ++ ++ return flattener->allocation_failed ? VKD3D_ERROR_OUT_OF_MEMORY : VKD3D_OK; ++} ++ ++static enum vkd3d_result flatten_control_flow_constructs(struct vkd3d_shader_parser *parser) ++{ ++ struct cf_flattener flattener = {0}; ++ enum vkd3d_result result; ++ ++ flattener.parser = parser; ++ result = cf_flattener_iterate_instruction_array(&flattener); ++ ++ if (result >= 0) ++ { ++ vkd3d_free(parser->instructions.elements); ++ parser->instructions.elements = flattener.instructions; ++ parser->instructions.capacity = flattener.instruction_capacity; ++ parser->instructions.count = flattener.instruction_count; ++ parser->shader_desc.block_count = flattener.block_id; ++ } ++ else ++ { ++ vkd3d_free(flattener.instructions); ++ } ++ ++ vkd3d_free(flattener.control_flow_info); ++ /* Simpler to always free these in free_shader_desc(). */ ++ parser->shader_desc.block_names = flattener.block_names; ++ parser->shader_desc.block_name_count = flattener.block_name_count; ++ ++ return result; ++} ++ + enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, + const struct vkd3d_shader_compile_info *compile_info) + { +@@ -1504,6 +2255,9 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, + if (result >= 0) + remove_dead_code(parser); + ++ if (result >= 0) ++ result = flatten_control_flow_constructs(parser); ++ + if (result >= 0) + result = normalise_combined_samplers(parser); + +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index 7743319bed5..0eeb04bfe59 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -855,20 +855,6 @@ static void vkd3d_spirv_end_function_stream_insertion(struct vkd3d_spirv_builder + builder->insertion_location = ~(size_t)0; + } + +-struct vkd3d_spirv_op_branch_conditional +-{ +- uint32_t opcode; +- uint32_t condition_id; +- uint32_t true_label; +- uint32_t false_label; +-}; +- +-static struct vkd3d_spirv_op_branch_conditional *vkd3d_spirv_as_op_branch_conditional( +- struct vkd3d_spirv_stream *stream, size_t location) +-{ +- return (struct vkd3d_spirv_op_branch_conditional *)&stream->words[location]; +-} +- + static void vkd3d_spirv_build_op_capability(struct vkd3d_spirv_stream *stream, + SpvCapability cap) + { +@@ -1885,8 +1871,6 @@ static void vkd3d_spirv_builder_begin_main_function(struct vkd3d_spirv_builder * + + vkd3d_spirv_build_op_function(builder, void_id, + builder->main_function_id, SpvFunctionControlMaskNone, function_type_id); +- vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder)); +- builder->main_function_location = vkd3d_spirv_stream_current_location(&builder->function_stream); + } + + static void vkd3d_spirv_builder_free(struct vkd3d_spirv_builder *builder) +@@ -2267,51 +2251,6 @@ static const char *debug_vkd3d_symbol(const struct vkd3d_symbol *symbol) + } + } + +-struct vkd3d_if_cf_info +-{ +- size_t stream_location; +- unsigned int id; +- uint32_t merge_block_id; +- uint32_t else_block_id; +-}; +- +-struct vkd3d_loop_cf_info +-{ +- uint32_t header_block_id; +- uint32_t continue_block_id; +- uint32_t merge_block_id; +-}; +- +-struct vkd3d_switch_cf_info +-{ +- size_t stream_location; +- unsigned int id; +- uint32_t selector_id; +- uint32_t merge_block_id; +- uint32_t default_block_id; +- uint32_t *case_blocks; +- size_t case_blocks_size; +- unsigned int case_block_count; +-}; +- +-struct vkd3d_control_flow_info +-{ +- union +- { +- struct vkd3d_if_cf_info if_; +- struct vkd3d_loop_cf_info loop; +- struct vkd3d_switch_cf_info switch_; +- } u; +- +- enum +- { +- VKD3D_BLOCK_IF, +- VKD3D_BLOCK_LOOP, +- VKD3D_BLOCK_SWITCH, +- } current_block; +- bool inside_block; +-}; +- + struct vkd3d_push_constant_buffer_binding + { + struct vkd3d_shader_register reg; +@@ -2365,13 +2304,6 @@ struct spirv_compiler + + enum vkd3d_shader_type shader_type; + +- unsigned int branch_id; +- unsigned int loop_id; +- unsigned int switch_id; +- unsigned int control_flow_depth; +- struct vkd3d_control_flow_info *control_flow_info; +- size_t control_flow_info_size; +- + struct vkd3d_shader_interface_info shader_interface; + struct vkd3d_shader_descriptor_offset_info offset_info; + uint32_t descriptor_offsets_member_id; +@@ -2380,8 +2312,7 @@ struct spirv_compiler + struct vkd3d_push_constant_buffer_binding *push_constants; + const struct vkd3d_shader_spirv_target_info *spirv_target_info; + +- bool main_block_open; +- bool after_declarations_section; ++ bool prolog_emitted; + struct shader_signature input_signature; + struct shader_signature output_signature; + struct shader_signature patch_constant_signature; +@@ -2401,7 +2332,9 @@ struct spirv_compiler + const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info; + unsigned int input_control_point_count; + unsigned int output_control_point_count; ++ + bool use_vocp; ++ bool emit_point_size; + + enum vkd3d_shader_opcode phase; + bool emit_default_control_point_phase; +@@ -2422,6 +2355,11 @@ struct spirv_compiler + unsigned int ssa_register_count; + + uint64_t config_flags; ++ ++ uint32_t *block_label_ids; ++ unsigned int block_count; ++ const char **block_names; ++ size_t block_name_count; + }; + + static bool is_in_default_phase(const struct spirv_compiler *compiler) +@@ -2440,6 +2378,9 @@ static bool is_in_fork_or_join_phase(const struct spirv_compiler *compiler) + } + + static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *compiler); ++static size_t spirv_compiler_get_current_function_location(struct spirv_compiler *compiler); ++static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler); ++static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler); + + static const char *spirv_compiler_get_entry_point_name(const struct spirv_compiler *compiler) + { +@@ -2450,8 +2391,6 @@ static const char *spirv_compiler_get_entry_point_name(const struct spirv_compil + + static void spirv_compiler_destroy(struct spirv_compiler *compiler) + { +- vkd3d_free(compiler->control_flow_info); +- + vkd3d_free(compiler->output_info); + + vkd3d_free(compiler->push_constants); +@@ -2470,6 +2409,7 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler) + shader_signature_cleanup(&compiler->patch_constant_signature); + + vkd3d_free(compiler->ssa_register_info); ++ vkd3d_free(compiler->block_label_ids); + + vkd3d_free(compiler); + } +@@ -2592,6 +2532,8 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve + 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) +@@ -2805,6 +2747,14 @@ static struct vkd3d_string_buffer *vkd3d_shader_register_range_string(struct spi + return buffer; + } + ++static uint32_t spirv_compiler_get_label_id(struct spirv_compiler *compiler, unsigned int block_id) ++{ ++ --block_id; ++ if (!compiler->block_label_ids[block_id]) ++ compiler->block_label_ids[block_id] = vkd3d_spirv_alloc_id(&compiler->spirv_builder); ++ return compiler->block_label_ids[block_id]; ++} ++ + static struct vkd3d_shader_descriptor_binding spirv_compiler_get_descriptor_binding( + struct spirv_compiler *compiler, const struct vkd3d_shader_register *reg, + const struct vkd3d_shader_register_range *range, enum vkd3d_shader_resource_type resource_type, +@@ -3520,11 +3470,13 @@ static uint32_t spirv_compiler_get_descriptor_index(struct spirv_compiler *compi + index_ids[0] = compiler->descriptor_offsets_member_id; + index_ids[1] = spirv_compiler_get_constant_uint(compiler, push_constant_index); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPushConstant, type_id); ++ vkd3d_spirv_begin_function_stream_insertion(builder, ++ spirv_compiler_get_current_function_location(compiler)); + ptr_id = vkd3d_spirv_build_op_in_bounds_access_chain(builder, ptr_type_id, + compiler->push_constants_var_id, index_ids, 2); + offset_id = vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone); +- if (!compiler->control_flow_depth) +- compiler->descriptor_offset_ids[push_constant_index] = offset_id; ++ vkd3d_spirv_end_function_stream_insertion(builder); ++ compiler->descriptor_offset_ids[push_constant_index] = offset_id; + } + index_id = vkd3d_spirv_build_op_iadd(builder, type_id, index_id, offset_id); + } +@@ -4770,7 +4722,7 @@ static uint32_t spirv_compiler_emit_builtin_variable_v(struct spirv_compiler *co + assert(size_count <= ARRAY_SIZE(sizes)); + memcpy(sizes, array_sizes, size_count * sizeof(sizes[0])); + array_sizes = sizes; +- sizes[size_count - 1] = max(sizes[size_count - 1], builtin->spirv_array_size); ++ sizes[0] = max(sizes[0], builtin->spirv_array_size); + + id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, storage_class, + builtin->component_type, builtin->component_count, array_sizes, size_count); +@@ -4841,12 +4793,12 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, + + builtin = get_spirv_builtin_for_sysval(compiler, sysval); + +- array_sizes[0] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); +- array_sizes[1] = signature_element->register_count; +- if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic) +- && (!vsir_sysval_semantic_is_clip_cull(signature_element->sysval_semantic) || array_sizes[0])) ++ array_sizes[0] = signature_element->register_count; ++ array_sizes[1] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); ++ if (array_sizes[0] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic) ++ && (!vsir_sysval_semantic_is_clip_cull(signature_element->sysval_semantic) || array_sizes[1])) + { +- array_sizes[1] = 0; ++ array_sizes[0] = 0; + } + + write_mask = signature_element->mask; +@@ -5183,10 +5135,10 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + /* Don't use builtins for TCS -> TES varyings. See spirv_compiler_emit_input(). */ + if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && !is_patch_constant) + sysval = VKD3D_SHADER_SV_NONE; +- array_sizes[0] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); +- array_sizes[1] = signature_element->register_count; +- if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic)) +- array_sizes[1] = 0; ++ array_sizes[0] = signature_element->register_count; ++ array_sizes[1] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); ++ if (array_sizes[0] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic)) ++ array_sizes[0] = 0; + + builtin = vkd3d_get_spirv_builtin(compiler, reg_type, sysval); + +@@ -5547,7 +5499,6 @@ static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *comp + if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) + { + vkd3d_spirv_builder_begin_main_function(builder); +- compiler->main_block_open = true; + } + } + +@@ -5650,7 +5601,10 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil + SpvStorageClass storage_class; + size_t function_location; + +- storage_class = SpvStorageClassFunction; ++ /* Indexable temps may be used by more than one function in hull shaders, and ++ * declarations generally should not occur within VSIR code blocks unless function ++ * scope is specified, e.g. DXIL alloca. */ ++ storage_class = temp->has_function_scope ? SpvStorageClassFunction : SpvStorageClassPrivate; + + vsir_register_init(®, VKD3DSPR_IDXTEMP, VKD3D_DATA_FLOAT, 1); + reg.idx[0].offset = temp->register_idx; +@@ -6382,7 +6336,7 @@ static void spirv_compiler_emit_dcl_output_topology(struct spirv_compiler *compi + { + case VKD3D_PT_POINTLIST: + mode = SpvExecutionModeOutputPoints; +- spirv_compiler_emit_point_size(compiler); ++ compiler->emit_point_size = true; + break; + case VKD3D_PT_LINESTRIP: + mode = SpvExecutionModeOutputLineStrip; +@@ -6544,20 +6498,45 @@ static void spirv_compiler_enter_shader_phase(struct spirv_compiler *compiler, + vkd3d_spirv_build_op_function(builder, void_id, function_id, + SpvFunctionControlMaskNone, function_type_id); + +- vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder)); +- + compiler->phase = instruction->handler_idx; + spirv_compiler_emit_shader_phase_name(compiler, function_id, NULL); + + phase = (instruction->handler_idx == VKD3DSIH_HS_CONTROL_POINT_PHASE) + ? &compiler->control_point_phase : &compiler->patch_constant_phase; + phase->function_id = function_id; +- phase->function_location = vkd3d_spirv_stream_current_location(&builder->function_stream); ++ /* The insertion location must be set after the label is emitted. */ ++ phase->function_location = 0; + + if (instruction->handler_idx == VKD3DSIH_HS_CONTROL_POINT_PHASE) + compiler->emit_default_control_point_phase = instruction->flags; + } + ++static void spirv_compiler_initialise_block(struct spirv_compiler *compiler) ++{ ++ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ ++ /* Insertion locations must point immediately after the function's initial label. */ ++ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL) ++ { ++ struct vkd3d_shader_phase *phase = (compiler->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE) ++ ? &compiler->control_point_phase : &compiler->patch_constant_phase; ++ if (!phase->function_location) ++ phase->function_location = vkd3d_spirv_stream_current_location(&builder->function_stream); ++ } ++ else if (!builder->main_function_location) ++ { ++ builder->main_function_location = vkd3d_spirv_stream_current_location(&builder->function_stream); ++ } ++ ++ /* I/O declarations can result in emission of fixups, which must occur after the initial label. */ ++ if (!compiler->prolog_emitted) ++ { ++ spirv_compiler_emit_main_prolog(compiler); ++ spirv_compiler_emit_io_declarations(compiler); ++ compiler->prolog_emitted = true; ++ } ++} ++ + static void spirv_compiler_emit_default_control_point_phase(struct spirv_compiler *compiler) + { + const struct shader_signature *output_signature = &compiler->output_signature; +@@ -6570,6 +6549,8 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile + unsigned int component_count; + unsigned int i; + ++ vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder)); ++ spirv_compiler_initialise_block(compiler); + invocation_id = spirv_compiler_emit_load_invocation_id(compiler); + + memset(&invocation, 0, sizeof(invocation)); +@@ -6664,7 +6645,11 @@ static void spirv_compiler_emit_hull_shader_main(struct spirv_compiler *compiler + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t void_id; + ++ /* If a patch constant function used descriptor indexing the offsets must be reloaded. */ ++ memset(compiler->descriptor_offset_ids, 0, compiler->offset_info.descriptor_table_count ++ * sizeof(*compiler->descriptor_offset_ids)); + vkd3d_spirv_builder_begin_main_function(builder); ++ vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder)); + + void_id = vkd3d_spirv_get_op_type_void(builder); + +@@ -7608,379 +7593,129 @@ static void spirv_compiler_emit_kill(struct spirv_compiler *compiler, + vkd3d_spirv_build_op_label(builder, merge_block_id); + } + +-static struct vkd3d_control_flow_info *spirv_compiler_push_control_flow_level( +- struct spirv_compiler *compiler) ++static bool spirv_compiler_init_blocks(struct spirv_compiler *compiler, unsigned int block_count) + { +- if (!vkd3d_array_reserve((void **)&compiler->control_flow_info, &compiler->control_flow_info_size, +- compiler->control_flow_depth + 1, sizeof(*compiler->control_flow_info))) +- { +- ERR("Failed to allocate control flow info structure.\n"); +- return NULL; +- } ++ compiler->block_count = block_count; ++ ++ if (!(compiler->block_label_ids = vkd3d_calloc(block_count, sizeof(*compiler->block_label_ids)))) ++ return false; + +- return &compiler->control_flow_info[compiler->control_flow_depth++]; ++ return true; + } + +-static void spirv_compiler_pop_control_flow_level(struct spirv_compiler *compiler) ++static void spirv_compiler_emit_label(struct spirv_compiler *compiler, ++ const struct vkd3d_shader_instruction *instruction) + { +- struct vkd3d_control_flow_info *cf_info; ++ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ const struct vkd3d_shader_src_param *src = instruction->src; ++ unsigned int block_id = src->reg.idx[0].offset; ++ uint32_t label_id; ++ ++ label_id = spirv_compiler_get_label_id(compiler, block_id); ++ vkd3d_spirv_build_op_label(builder, label_id); + +- assert(compiler->control_flow_depth); ++ --block_id; ++ if (block_id < compiler->block_name_count && compiler->block_names[block_id]) ++ vkd3d_spirv_build_op_name(builder, label_id, compiler->block_names[block_id]); + +- cf_info = &compiler->control_flow_info[--compiler->control_flow_depth]; +- memset(cf_info, 0, sizeof(*cf_info)); ++ spirv_compiler_initialise_block(compiler); + } + +-static struct vkd3d_control_flow_info *spirv_compiler_find_innermost_loop( +- struct spirv_compiler *compiler) ++static void spirv_compiler_emit_merge(struct spirv_compiler *compiler, ++ uint32_t merge_block_id, uint32_t continue_block_id) + { +- int depth; ++ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + +- for (depth = compiler->control_flow_depth - 1; depth >= 0; --depth) ++ if (!merge_block_id) ++ return; ++ ++ merge_block_id = spirv_compiler_get_label_id(compiler, merge_block_id); ++ if (!continue_block_id) + { +- if (compiler->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP) +- return &compiler->control_flow_info[depth]; ++ vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone); + } +- +- return NULL; +-} +- +-static struct vkd3d_control_flow_info *spirv_compiler_find_innermost_breakable_cf_construct( +- struct spirv_compiler *compiler) +-{ +- int depth; +- +- for (depth = compiler->control_flow_depth - 1; depth >= 0; --depth) ++ else + { +- if (compiler->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP +- || compiler->control_flow_info[depth].current_block == VKD3D_BLOCK_SWITCH) +- return &compiler->control_flow_info[depth]; ++ continue_block_id = spirv_compiler_get_label_id(compiler, continue_block_id); ++ vkd3d_spirv_build_op_loop_merge(builder, merge_block_id, continue_block_id, SpvLoopControlMaskNone); + } +- +- return NULL; + } + +-static int spirv_compiler_emit_control_flow_instruction(struct spirv_compiler *compiler, ++static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { +- uint32_t loop_header_block_id, loop_body_block_id, continue_block_id; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_src_param *src = instruction->src; +- uint32_t merge_block_id, val_id, condition_id, true_label; +- struct vkd3d_control_flow_info *cf_info; +- +- cf_info = compiler->control_flow_depth +- ? &compiler->control_flow_info[compiler->control_flow_depth - 1] : NULL; ++ uint32_t condition_id; + +- switch (instruction->handler_idx) ++ if (vsir_register_is_label(&src[0].reg)) + { +- case VKD3DSIH_IF: +- if (!(cf_info = spirv_compiler_push_control_flow_level(compiler))) +- return VKD3D_ERROR_OUT_OF_MEMORY; +- +- val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); +- condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, src->reg.data_type, 1, val_id); +- +- true_label = vkd3d_spirv_alloc_id(builder); +- merge_block_id = vkd3d_spirv_alloc_id(builder); +- vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone); +- cf_info->u.if_.stream_location = vkd3d_spirv_stream_current_location(&builder->function_stream); +- vkd3d_spirv_build_op_branch_conditional(builder, condition_id, true_label, merge_block_id); +- +- vkd3d_spirv_build_op_label(builder, true_label); +- +- cf_info->u.if_.id = compiler->branch_id; +- cf_info->u.if_.merge_block_id = merge_block_id; +- cf_info->u.if_.else_block_id = 0; +- cf_info->inside_block = true; +- cf_info->current_block = VKD3D_BLOCK_IF; +- +- vkd3d_spirv_build_op_name(builder, merge_block_id, "branch%u_merge", compiler->branch_id); +- vkd3d_spirv_build_op_name(builder, true_label, "branch%u_true", compiler->branch_id); +- ++compiler->branch_id; +- break; +- +- case VKD3DSIH_ELSE: +- assert(compiler->control_flow_depth); +- assert(cf_info->current_block == VKD3D_BLOCK_IF); +- +- if (cf_info->inside_block) +- vkd3d_spirv_build_op_branch(builder, cf_info->u.if_.merge_block_id); +- +- cf_info->u.if_.else_block_id = vkd3d_spirv_alloc_id(builder); +- vkd3d_spirv_as_op_branch_conditional(&builder->function_stream, +- cf_info->u.if_.stream_location)->false_label = cf_info->u.if_.else_block_id; +- vkd3d_spirv_build_op_name(builder, +- cf_info->u.if_.else_block_id, "branch%u_false", cf_info->u.if_.id); +- vkd3d_spirv_build_op_label(builder, cf_info->u.if_.else_block_id); +- cf_info->inside_block = true; +- break; +- +- case VKD3DSIH_ENDIF: +- assert(compiler->control_flow_depth); +- assert(cf_info->current_block == VKD3D_BLOCK_IF); +- +- if (cf_info->inside_block) +- vkd3d_spirv_build_op_branch(builder, cf_info->u.if_.merge_block_id); +- +- vkd3d_spirv_build_op_label(builder, cf_info->u.if_.merge_block_id); +- +- spirv_compiler_pop_control_flow_level(compiler); +- break; +- +- case VKD3DSIH_LOOP: +- if (!(cf_info = spirv_compiler_push_control_flow_level(compiler))) +- return VKD3D_ERROR_OUT_OF_MEMORY; +- +- loop_header_block_id = vkd3d_spirv_alloc_id(builder); +- loop_body_block_id = vkd3d_spirv_alloc_id(builder); +- continue_block_id = vkd3d_spirv_alloc_id(builder); +- merge_block_id = vkd3d_spirv_alloc_id(builder); +- +- vkd3d_spirv_build_op_branch(builder, loop_header_block_id); +- vkd3d_spirv_build_op_label(builder, loop_header_block_id); +- vkd3d_spirv_build_op_loop_merge(builder, merge_block_id, continue_block_id, SpvLoopControlMaskNone); +- vkd3d_spirv_build_op_branch(builder, loop_body_block_id); +- +- vkd3d_spirv_build_op_label(builder, loop_body_block_id); +- +- cf_info->u.loop.header_block_id = loop_header_block_id; +- cf_info->u.loop.continue_block_id = continue_block_id; +- cf_info->u.loop.merge_block_id = merge_block_id; +- cf_info->current_block = VKD3D_BLOCK_LOOP; +- cf_info->inside_block = true; +- +- vkd3d_spirv_build_op_name(builder, loop_header_block_id, "loop%u_header", compiler->loop_id); +- vkd3d_spirv_build_op_name(builder, loop_body_block_id, "loop%u_body", compiler->loop_id); +- vkd3d_spirv_build_op_name(builder, continue_block_id, "loop%u_continue", compiler->loop_id); +- vkd3d_spirv_build_op_name(builder, merge_block_id, "loop%u_merge", compiler->loop_id); +- ++compiler->loop_id; +- break; +- +- case VKD3DSIH_ENDLOOP: +- assert(compiler->control_flow_depth); +- assert(cf_info->current_block == VKD3D_BLOCK_LOOP); +- +- /* The loop block may have already been ended by an unconditional +- * break instruction right before the end of the loop. */ +- if (cf_info->inside_block) +- vkd3d_spirv_build_op_branch(builder, cf_info->u.loop.continue_block_id); +- +- vkd3d_spirv_build_op_label(builder, cf_info->u.loop.continue_block_id); +- vkd3d_spirv_build_op_branch(builder, cf_info->u.loop.header_block_id); +- vkd3d_spirv_build_op_label(builder, cf_info->u.loop.merge_block_id); +- +- spirv_compiler_pop_control_flow_level(compiler); +- break; +- +- case VKD3DSIH_SWITCH: +- if (!(cf_info = spirv_compiler_push_control_flow_level(compiler))) +- return VKD3D_ERROR_OUT_OF_MEMORY; +- +- merge_block_id = vkd3d_spirv_alloc_id(builder); +- +- assert(src->reg.data_type == VKD3D_DATA_INT); +- val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); +- +- vkd3d_spirv_build_op_selection_merge(builder, merge_block_id, SpvSelectionControlMaskNone); +- +- cf_info->u.switch_.id = compiler->switch_id; +- cf_info->u.switch_.merge_block_id = merge_block_id; +- cf_info->u.switch_.stream_location = vkd3d_spirv_stream_current_location(&builder->function_stream); +- cf_info->u.switch_.selector_id = val_id; +- cf_info->u.switch_.case_blocks = NULL; +- cf_info->u.switch_.case_blocks_size = 0; +- cf_info->u.switch_.case_block_count = 0; +- cf_info->u.switch_.default_block_id = 0; +- cf_info->inside_block = false; +- cf_info->current_block = VKD3D_BLOCK_SWITCH; +- +- vkd3d_spirv_build_op_name(builder, merge_block_id, "switch%u_merge", compiler->switch_id); +- +- ++compiler->switch_id; +- +- if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size, +- 10, sizeof(*cf_info->u.switch_.case_blocks))) +- return VKD3D_ERROR_OUT_OF_MEMORY; +- +- break; +- +- case VKD3DSIH_ENDSWITCH: +- assert(compiler->control_flow_depth); +- assert(cf_info->current_block == VKD3D_BLOCK_SWITCH); +- assert(!cf_info->inside_block); +- +- if (!cf_info->u.switch_.default_block_id) +- cf_info->u.switch_.default_block_id = cf_info->u.switch_.merge_block_id; +- +- vkd3d_spirv_build_op_label(builder, cf_info->u.switch_.merge_block_id); +- +- /* The OpSwitch instruction is inserted when the endswitch +- * instruction is processed because we do not know the number +- * of case statements in advance.*/ +- vkd3d_spirv_begin_function_stream_insertion(builder, cf_info->u.switch_.stream_location); +- vkd3d_spirv_build_op_switch(builder, cf_info->u.switch_.selector_id, +- cf_info->u.switch_.default_block_id, cf_info->u.switch_.case_blocks, +- cf_info->u.switch_.case_block_count); +- vkd3d_spirv_end_function_stream_insertion(builder); +- +- vkd3d_free(cf_info->u.switch_.case_blocks); +- spirv_compiler_pop_control_flow_level(compiler); +- break; +- +- case VKD3DSIH_CASE: +- { +- uint32_t label_id, value; +- +- assert(compiler->control_flow_depth); +- assert(cf_info->current_block == VKD3D_BLOCK_SWITCH); +- +- if (src->swizzle != VKD3D_SHADER_SWIZZLE(X, X, X, X)) +- { +- WARN("Unexpected src swizzle %#x.\n", src->swizzle); +- spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE, +- "The swizzle for a switch case value is not scalar."); +- } +- assert(src->reg.type == VKD3DSPR_IMMCONST); +- value = *src->reg.u.immconst_u32; +- +- if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size, +- 2 * (cf_info->u.switch_.case_block_count + 1), sizeof(*cf_info->u.switch_.case_blocks))) +- return VKD3D_ERROR_OUT_OF_MEMORY; +- +- label_id = vkd3d_spirv_alloc_id(builder); +- if (cf_info->inside_block) /* fall-through */ +- vkd3d_spirv_build_op_branch(builder, label_id); +- +- cf_info->u.switch_.case_blocks[2 * cf_info->u.switch_.case_block_count + 0] = value; +- cf_info->u.switch_.case_blocks[2 * cf_info->u.switch_.case_block_count + 1] = label_id; +- ++cf_info->u.switch_.case_block_count; +- +- vkd3d_spirv_build_op_label(builder, label_id); +- cf_info->inside_block = true; +- vkd3d_spirv_build_op_name(builder, label_id, "switch%u_case%u", cf_info->u.switch_.id, value); +- break; +- } +- +- case VKD3DSIH_DEFAULT: +- assert(compiler->control_flow_depth); +- assert(cf_info->current_block == VKD3D_BLOCK_SWITCH); +- assert(!cf_info->u.switch_.default_block_id); +- +- cf_info->u.switch_.default_block_id = vkd3d_spirv_alloc_id(builder); +- if (cf_info->inside_block) /* fall-through */ +- vkd3d_spirv_build_op_branch(builder, cf_info->u.switch_.default_block_id); +- +- vkd3d_spirv_build_op_label(builder, cf_info->u.switch_.default_block_id); +- vkd3d_spirv_build_op_name(builder, cf_info->u.switch_.default_block_id, +- "switch%u_default", cf_info->u.switch_.id); +- cf_info->inside_block = true; +- break; +- +- case VKD3DSIH_BREAK: +- { +- struct vkd3d_control_flow_info *breakable_cf_info; +- +- assert(compiler->control_flow_depth); +- +- if (!(breakable_cf_info = spirv_compiler_find_innermost_breakable_cf_construct(compiler))) +- { +- FIXME("Unhandled break instruction.\n"); +- return VKD3D_ERROR_INVALID_SHADER; +- } +- +- if (breakable_cf_info->current_block == VKD3D_BLOCK_LOOP) +- { +- vkd3d_spirv_build_op_branch(builder, breakable_cf_info->u.loop.merge_block_id); +- } +- else if (breakable_cf_info->current_block == VKD3D_BLOCK_SWITCH) +- { +- /* The current case block may have already been ended by an +- * unconditional continue instruction. */ +- if (breakable_cf_info->inside_block) +- vkd3d_spirv_build_op_branch(builder, breakable_cf_info->u.switch_.merge_block_id); +- } +- +- cf_info->inside_block = false; +- break; +- } +- +- case VKD3DSIH_BREAKP: ++ if (instruction->src_count > 1) + { +- struct vkd3d_control_flow_info *loop_cf_info; +- +- assert(compiler->control_flow_depth); +- +- if (!(loop_cf_info = spirv_compiler_find_innermost_loop(compiler))) +- { +- ERR("Invalid 'breakc' instruction outside loop.\n"); +- return VKD3D_ERROR_INVALID_SHADER; +- } +- +- merge_block_id = spirv_compiler_emit_conditional_branch(compiler, +- instruction, loop_cf_info->u.loop.merge_block_id); +- vkd3d_spirv_build_op_label(builder, merge_block_id); +- break; +- } +- +- case VKD3DSIH_CONTINUE: +- { +- struct vkd3d_control_flow_info *loop_cf_info; +- +- assert(compiler->control_flow_depth); +- +- if (!(loop_cf_info = spirv_compiler_find_innermost_loop(compiler))) +- { +- ERR("Invalid 'continue' instruction outside loop.\n"); +- return VKD3D_ERROR_INVALID_SHADER; +- } +- +- vkd3d_spirv_build_op_branch(builder, loop_cf_info->u.loop.continue_block_id); +- +- cf_info->inside_block = false; +- break; ++ /* Loop merge only. Must have a merge block and a continue block. */ ++ spirv_compiler_emit_merge(compiler, src[1].reg.idx[0].offset, src[2].reg.idx[0].offset); + } ++ vkd3d_spirv_build_op_branch(builder, spirv_compiler_get_label_id(compiler, src[0].reg.idx[0].offset)); ++ return; ++ } + +- case VKD3DSIH_CONTINUEP: +- { +- struct vkd3d_control_flow_info *loop_cf_info; +- +- if (!(loop_cf_info = spirv_compiler_find_innermost_loop(compiler))) +- { +- ERR("Invalid 'continuec' instruction outside loop.\n"); +- return VKD3D_ERROR_INVALID_SHADER; +- } ++ if (!vkd3d_swizzle_is_scalar(src->swizzle)) ++ { ++ WARN("Unexpected src swizzle %#x.\n", src->swizzle); ++ spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE, ++ "The swizzle for a branch condition value is not scalar."); ++ } + +- merge_block_id = spirv_compiler_emit_conditional_branch(compiler, +- instruction, loop_cf_info->u.loop.continue_block_id); +- vkd3d_spirv_build_op_label(builder, merge_block_id); +- break; +- } ++ condition_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); ++ condition_id = spirv_compiler_emit_int_to_bool(compiler, ++ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, 1, condition_id); ++ /* Emit the merge immediately before the branch instruction. */ ++ spirv_compiler_emit_merge(compiler, src[3].reg.idx[0].offset, ++ (instruction->src_count > 4) ? src[4].reg.idx[0].offset : 0); ++ vkd3d_spirv_build_op_branch_conditional(builder, condition_id, ++ spirv_compiler_get_label_id(compiler, src[1].reg.idx[0].offset), ++ spirv_compiler_get_label_id(compiler, src[2].reg.idx[0].offset)); ++} + +- case VKD3DSIH_RET: +- spirv_compiler_emit_return(compiler, instruction); ++static void spirv_compiler_emit_switch(struct spirv_compiler *compiler, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ const struct vkd3d_shader_src_param *src = instruction->src; ++ uint32_t val_id, default_id; ++ unsigned int i, word_count; ++ uint32_t *cases; + +- if (cf_info) +- cf_info->inside_block = false; +- else +- compiler->main_block_open = false; +- break; ++ if (!vkd3d_swizzle_is_scalar(src[0].swizzle)) ++ { ++ WARN("Unexpected src swizzle %#x.\n", src[0].swizzle); ++ spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE, ++ "The swizzle for a switch value is not scalar."); ++ } + +- case VKD3DSIH_RETP: +- spirv_compiler_emit_retc(compiler, instruction); +- break; ++ word_count = instruction->src_count - 3; ++ if (!(cases = vkd3d_calloc(word_count, sizeof(*cases)))) ++ { ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY, ++ "Failed to allocate %u words for switch cases.", word_count); ++ return; ++ } + +- case VKD3DSIH_DISCARD: +- case VKD3DSIH_TEXKILL: +- spirv_compiler_emit_kill(compiler, instruction); +- break; ++ val_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); ++ default_id = spirv_compiler_get_label_id(compiler, src[1].reg.idx[0].offset); ++ /* No instructions may occur between the merge and the switch. */ ++ spirv_compiler_emit_merge(compiler, src[2].reg.idx[0].offset, 0); + +- default: +- ERR("Unexpected instruction %#x.\n", instruction->handler_idx); +- break; ++ src = &src[3]; ++ for (i = 0; i < word_count; i += 2) ++ { ++ cases[i] = src[i].reg.u.immconst_u32[0]; ++ cases[i + 1] = spirv_compiler_get_label_id(compiler, src[i + 1].reg.idx[0].offset); + } + +- return VKD3D_OK; ++ vkd3d_spirv_build_op_switch(builder, val_id, default_id, cases, word_count / 2u); ++ ++ vkd3d_free(cases); + } + + static void spirv_compiler_emit_deriv_instruction(struct spirv_compiler *compiler, +@@ -9519,28 +9254,15 @@ static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler) + { + spirv_compiler_emit_push_constant_buffers(compiler); + +- if (compiler->xfb_info && compiler->xfb_info->element_count +- && compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY) ++ if (compiler->emit_point_size) + spirv_compiler_emit_point_size(compiler); + } + +-static bool is_dcl_instruction(enum vkd3d_shader_opcode handler_idx) +-{ +- return (VKD3DSIH_DCL <= handler_idx && handler_idx <= VKD3DSIH_DCL_VERTICES_OUT) +- || handler_idx == VKD3DSIH_HS_DECLS; +-} +- + static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { + int ret = VKD3D_OK; + +- if (!is_dcl_instruction(instruction->handler_idx) && !compiler->after_declarations_section) +- { +- compiler->after_declarations_section = true; +- spirv_compiler_emit_main_prolog(compiler); +- } +- + switch (instruction->handler_idx) + { + case VKD3DSIH_DCL_GLOBAL_FLAGS: +@@ -9727,24 +9449,24 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, + case VKD3DSIH_F32TOF16: + spirv_compiler_emit_f32tof16(compiler, instruction); + break; +- case VKD3DSIH_BREAK: +- case VKD3DSIH_BREAKP: +- case VKD3DSIH_CASE: +- case VKD3DSIH_CONTINUE: +- case VKD3DSIH_CONTINUEP: +- case VKD3DSIH_DEFAULT: +- case VKD3DSIH_DISCARD: +- case VKD3DSIH_ELSE: +- case VKD3DSIH_ENDIF: +- case VKD3DSIH_ENDLOOP: +- case VKD3DSIH_ENDSWITCH: +- case VKD3DSIH_IF: +- case VKD3DSIH_LOOP: + case VKD3DSIH_RET: ++ spirv_compiler_emit_return(compiler, instruction); ++ break; + case VKD3DSIH_RETP: +- case VKD3DSIH_SWITCH: ++ spirv_compiler_emit_retc(compiler, instruction); ++ break; ++ case VKD3DSIH_DISCARD: + case VKD3DSIH_TEXKILL: +- ret = spirv_compiler_emit_control_flow_instruction(compiler, instruction); ++ spirv_compiler_emit_kill(compiler, instruction); ++ break; ++ case VKD3DSIH_LABEL: ++ spirv_compiler_emit_label(compiler, instruction); ++ break; ++ case VKD3DSIH_BRANCH: ++ spirv_compiler_emit_branch(compiler, instruction); ++ break; ++ case VKD3DSIH_SWITCH_MONOLITHIC: ++ spirv_compiler_emit_switch(compiler, instruction); + break; + case VKD3DSIH_DSX: + case VKD3DSIH_DSX_COARSE: +@@ -9966,6 +9688,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + if ((result = vkd3d_shader_normalise(parser, compile_info)) < 0) + return result; + ++ if (parser->shader_desc.block_count && !spirv_compiler_init_blocks(compiler, parser->shader_desc.block_count)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ + instructions = parser->instructions; + memset(&parser->instructions, 0, sizeof(parser->instructions)); + +@@ -9976,6 +9701,8 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + memset(&shader_desc->output_signature, 0, sizeof(shader_desc->output_signature)); + memset(&shader_desc->patch_constant_signature, 0, sizeof(shader_desc->patch_constant_signature)); + compiler->use_vocp = parser->shader_desc.use_vocp; ++ compiler->block_names = parser->shader_desc.block_names; ++ compiler->block_name_count = parser->shader_desc.block_name_count; + + compiler->input_control_point_count = shader_desc->input_control_point_count; + compiler->output_control_point_count = shader_desc->output_control_point_count; +@@ -9983,8 +9710,6 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) + spirv_compiler_emit_shader_signature_outputs(compiler); + +- spirv_compiler_emit_io_declarations(compiler); +- + for (i = 0; i < instructions.count && result >= 0; ++i) + { + compiler->location.line = i + 1; +@@ -9996,9 +9721,6 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + if (result < 0) + return result; + +- if (compiler->main_block_open) +- vkd3d_spirv_build_op_return(builder); +- + if (!is_in_default_phase(compiler)) + spirv_compiler_leave_shader_phase(compiler); + else +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index 1f1944bc0da..e4dfb5235ec 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -919,6 +919,7 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins + { + struct vkd3d_shader_index_range *index_range = &ins->declaration.index_range; + unsigned int i, register_idx, register_count; ++ const struct shader_signature *signature; + enum vkd3d_shader_register_type type; + struct sm4_index_range_array *ranges; + unsigned int *io_masks; +@@ -932,40 +933,38 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins + register_count = index_range->register_count; + write_mask = index_range->dst.write_mask; + +- if (vsir_write_mask_component_count(write_mask) != 1) +- { +- WARN("Unhandled write mask %#x.\n", write_mask); +- vkd3d_shader_parser_warning(&priv->p, VKD3D_SHADER_WARNING_TPF_UNHANDLED_INDEX_RANGE_MASK, +- "Index range mask %#x is not scalar.", write_mask); +- } +- + switch ((type = index_range->dst.reg.type)) + { + case VKD3DSPR_INPUT: + case VKD3DSPR_INCONTROLPOINT: + io_masks = priv->input_register_masks; + ranges = &priv->input_index_ranges; ++ signature = &priv->p.shader_desc.input_signature; + break; + case VKD3DSPR_OUTPUT: + if (sm4_parser_is_in_fork_or_join_phase(priv)) + { + io_masks = priv->patch_constant_register_masks; + ranges = &priv->patch_constant_index_ranges; ++ signature = &priv->p.shader_desc.patch_constant_signature; + } + else + { + io_masks = priv->output_register_masks; + ranges = &priv->output_index_ranges; ++ signature = &priv->p.shader_desc.output_signature; + } + break; + case VKD3DSPR_COLOROUT: + case VKD3DSPR_OUTCONTROLPOINT: + io_masks = priv->output_register_masks; + ranges = &priv->output_index_ranges; ++ signature = &priv->p.shader_desc.output_signature; + break; + case VKD3DSPR_PATCHCONST: + io_masks = priv->patch_constant_register_masks; + ranges = &priv->patch_constant_index_ranges; ++ signature = &priv->p.shader_desc.patch_constant_signature; + break; + + default: +@@ -1003,6 +1002,18 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins + + for (i = 0; i < register_count; ++i) + { ++ const struct signature_element *e = vsir_signature_find_element_for_reg(signature, register_idx + i, write_mask); ++ /* Index ranges should not contain non-arrayed sysvals. FXC tries to forbid this but it is buggy, ++ * and can emit a range containing a sysval if the sysval is not actually accessed. */ ++ if (e && e->sysval_semantic && register_count > 1 && !vsir_sysval_semantic_is_tess_factor(e->sysval_semantic) ++ && !vsir_sysval_semantic_is_clip_cull(e->sysval_semantic)) ++ { ++ WARN("Sysval %u included in an index range declaration.\n", e->sysval_semantic); ++ vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_INDEX_RANGE_DCL, ++ "Index range base %u, count %u, mask %#x contains sysval %u.", ++ register_idx, register_count, write_mask, e->sysval_semantic); ++ return; ++ } + if ((io_masks[register_idx + i] & write_mask) != write_mask) + { + WARN("No matching declaration for index range base %u, count %u, mask %#x.\n", +@@ -1117,6 +1128,7 @@ static void shader_sm4_read_dcl_indexable_temp(struct vkd3d_shader_instruction * + ins->declaration.indexable_temp.alignment = 0; + ins->declaration.indexable_temp.data_type = VKD3D_DATA_FLOAT; + ins->declaration.indexable_temp.component_count = *tokens; ++ ins->declaration.indexable_temp.has_function_scope = false; + } + + static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *ins, uint32_t opcode, +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 0af7ea0d266..ace58161e6b 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -238,6 +238,7 @@ enum vkd3d_shader_opcode + VKD3DSIH_BEM, + VKD3DSIH_BFI, + VKD3DSIH_BFREV, ++ VKD3DSIH_BRANCH, + VKD3DSIH_BREAK, + VKD3DSIH_BREAKC, + VKD3DSIH_BREAKP, +@@ -472,6 +473,7 @@ enum vkd3d_shader_opcode + VKD3DSIH_SUB, + VKD3DSIH_SWAPC, + VKD3DSIH_SWITCH, ++ VKD3DSIH_SWITCH_MONOLITHIC, + VKD3DSIH_SYNC, + VKD3DSIH_TEX, + VKD3DSIH_TEXBEM, +@@ -818,6 +820,7 @@ struct vkd3d_shader_indexable_temp + unsigned int alignment; + enum vkd3d_data_type data_type; + unsigned int component_count; ++ bool has_function_scope; + const struct vkd3d_shader_immediate_constant_buffer *initialiser; + }; + +@@ -883,6 +886,8 @@ struct vkd3d_shader_src_param + enum vkd3d_shader_src_modifier modifiers; + }; + ++void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id); ++ + struct vkd3d_shader_index_range + { + struct vkd3d_shader_dst_param dst; +@@ -1016,6 +1021,7 @@ struct vkd3d_shader_desc + + uint32_t temp_count; + unsigned int ssa_count; ++ unsigned int block_count; + + struct + { +@@ -1023,6 +1029,9 @@ struct vkd3d_shader_desc + } flat_constant_count[3]; + + bool use_vocp; ++ ++ const char **block_names; ++ size_t block_name_count; + }; + + struct vkd3d_shader_register_semantic +@@ -1185,6 +1194,11 @@ static inline bool register_is_constant(const struct vkd3d_shader_register *reg) + return (reg->type == VKD3DSPR_IMMCONST || reg->type == VKD3DSPR_IMMCONST64); + } + ++static inline bool vsir_register_is_label(const struct vkd3d_shader_register *reg) ++{ ++ return reg->type == VKD3DSPR_LABEL; ++} ++ + struct vkd3d_shader_param_node + { + struct vkd3d_shader_param_node *next; +diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c +index 163dd6ce210..f9e50335fa8 100644 +--- a/libs/vkd3d/libs/vkd3d/resource.c ++++ b/libs/vkd3d/libs/vkd3d/resource.c +@@ -22,7 +22,7 @@ + #define VKD3D_NULL_BUFFER_SIZE 16 + #define VKD3D_NULL_VIEW_FORMAT DXGI_FORMAT_R8G8B8A8_UNORM + +-LONG64 object_global_serial_id; ++uint64_t object_global_serial_id; + + static inline bool is_cpu_accessible_heap(const D3D12_HEAP_PROPERTIES *properties) + { +@@ -4314,7 +4314,7 @@ static HRESULT d3d12_descriptor_heap_init(struct d3d12_descriptor_heap *descript + + descriptor_heap->ID3D12DescriptorHeap_iface.lpVtbl = &d3d12_descriptor_heap_vtbl; + descriptor_heap->refcount = 1; +- descriptor_heap->serial_id = InterlockedIncrement64(&object_global_serial_id); ++ descriptor_heap->serial_id = vkd3d_atomic_increment_u64(&object_global_serial_id); + + descriptor_heap->desc = *desc; + +diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +index 9bf4575d46a..4abe7df3a95 100644 +--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h ++++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h +@@ -67,7 +67,7 @@ + * this number to prevent excessive pool memory use. */ + #define VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE (16 * 1024u) + +-extern LONG64 object_global_serial_id; ++extern uint64_t object_global_serial_id; + + struct d3d12_command_list; + struct d3d12_device; +-- +2.43.0 + diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-f96a791807701a4583e6c613c2f5bd47c00.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-f96a791807701a4583e6c613c2f5bd47c00.patch deleted file mode 100644 index 00fe098b..00000000 --- a/patches/vkd3d-latest/0004-Updated-vkd3d-to-f96a791807701a4583e6c613c2f5bd47c00.patch +++ /dev/null @@ -1,819 +0,0 @@ -From 69aefad3adb6facfe89d9347d333da1c7603d8ac Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Sat, 16 Dec 2023 09:37:22 +1100 -Subject: [PATCH] Updated vkd3d to f96a791807701a4583e6c613c2f5bd47c00ea767. - ---- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 8 +- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 10 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 4 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 54 ++++----- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 18 +-- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 29 +++-- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 10 +- - libs/vkd3d/libs/vkd3d/command.c | 4 + - libs/vkd3d/libs/vkd3d/device.c | 114 +++++++++++++++++- - libs/vkd3d/libs/vkd3d/resource.c | 19 ++- - libs/vkd3d/libs/vkd3d/state.c | 12 +- - libs/vkd3d/libs/vkd3d/vkd3d_private.h | 23 +++- - 12 files changed, 220 insertions(+), 85 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index 86ddd1ffded..ac1c41f96e2 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -1381,10 +1381,10 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, - if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_IMMCONST64 - && param->reg.dimension == VSIR_DIMENSION_VEC4) - { -- unsigned int swizzle_x = vkd3d_swizzle_get_component(swizzle, 0); -- unsigned int swizzle_y = vkd3d_swizzle_get_component(swizzle, 1); -- unsigned int swizzle_z = vkd3d_swizzle_get_component(swizzle, 2); -- unsigned int swizzle_w = vkd3d_swizzle_get_component(swizzle, 3); -+ unsigned int swizzle_x = vsir_swizzle_get_component(swizzle, 0); -+ unsigned int swizzle_y = vsir_swizzle_get_component(swizzle, 1); -+ unsigned int swizzle_z = vsir_swizzle_get_component(swizzle, 2); -+ unsigned int swizzle_w = vsir_swizzle_get_component(swizzle, 3); - - static const char swizzle_chars[] = "xyzw"; - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index c78ffebac69..d40ea4b5942 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -1063,12 +1063,12 @@ static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1, - } - } - --static unsigned int mask_from_swizzle(unsigned int swizzle) -+static unsigned int mask_from_swizzle(uint32_t swizzle) - { -- return (1u << vkd3d_swizzle_get_component(swizzle, 0)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 1)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 2)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 3)); -+ return (1u << vsir_swizzle_get_component(swizzle, 0)) -+ | (1u << vsir_swizzle_get_component(swizzle, 1)) -+ | (1u << vsir_swizzle_get_component(swizzle, 2)) -+ | (1u << vsir_swizzle_get_component(swizzle, 3)); - } - - static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, struct vkd3d_shader_instruction *ins) -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 1a569619707..a0b5ea27698 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -1002,7 +1002,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par - - id_idx = reg->idx_count - 1; - reg_idx = reg->idx[id_idx].offset; -- write_mask = VKD3DSP_WRITEMASK_0 << vkd3d_swizzle_get_component(src_param->swizzle, 0); -+ write_mask = VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(src_param->swizzle, 0); - element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); - - e = &signature->elements[element_idx]; -@@ -1014,7 +1014,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par - if ((component_idx = vsir_write_mask_get_component_idx(e->mask))) - { - for (i = 0; i < VKD3D_VEC4_SIZE; ++i) -- if (vkd3d_swizzle_get_component(src_param->swizzle, i)) -+ if (vsir_swizzle_get_component(src_param->swizzle, i)) - src_param->swizzle -= component_idx << VKD3D_SHADER_SWIZZLE_SHIFT(i); - } - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 5c537598e1e..f77bc25329d 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -3595,17 +3595,17 @@ static bool vkd3d_swizzle_is_equal(unsigned int dst_write_mask, - return vkd3d_compact_swizzle(VKD3D_SHADER_NO_SWIZZLE, dst_write_mask) == vkd3d_compact_swizzle(swizzle, write_mask); - } - --static bool vkd3d_swizzle_is_scalar(unsigned int swizzle) -+static bool vkd3d_swizzle_is_scalar(uint32_t swizzle) - { -- unsigned int component_idx = vkd3d_swizzle_get_component(swizzle, 0); -- return vkd3d_swizzle_get_component(swizzle, 1) == component_idx -- && vkd3d_swizzle_get_component(swizzle, 2) == component_idx -- && vkd3d_swizzle_get_component(swizzle, 3) == component_idx; -+ unsigned int component_idx = vsir_swizzle_get_component(swizzle, 0); -+ return vsir_swizzle_get_component(swizzle, 1) == component_idx -+ && vsir_swizzle_get_component(swizzle, 2) == component_idx -+ && vsir_swizzle_get_component(swizzle, 3) == component_idx; - } - - static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, - uint32_t val_id, uint32_t val_write_mask, enum vkd3d_shader_component_type component_type, -- unsigned int swizzle, uint32_t write_mask) -+ uint32_t swizzle, uint32_t write_mask) - { - unsigned int i, component_idx, component_count, val_component_count; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -@@ -3623,7 +3623,7 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, - if (component_count == 1) - { - component_idx = vsir_write_mask_get_component_idx(write_mask); -- component_idx = vkd3d_swizzle_get_component(swizzle, component_idx); -+ component_idx = vsir_swizzle_get_component(swizzle, component_idx); - component_idx -= vsir_write_mask_get_component_idx(val_write_mask); - return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx); - } -@@ -3634,7 +3634,7 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - { -- assert(VKD3DSP_WRITEMASK_0 << vkd3d_swizzle_get_component(swizzle, i) == val_write_mask); -+ assert(VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(swizzle, i) == val_write_mask); - components[component_idx++] = val_id; - } - } -@@ -3644,14 +3644,14 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, - for (i = 0, component_idx = 0; i < VKD3D_VEC4_SIZE; ++i) - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- components[component_idx++] = vkd3d_swizzle_get_component(swizzle, i); -+ components[component_idx++] = vsir_swizzle_get_component(swizzle, i); - } - return vkd3d_spirv_build_op_vector_shuffle(builder, - type_id, val_id, val_id, components, component_count); - } - - static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compiler, -- uint32_t vector1_id, uint32_t vector2_id, unsigned int swizzle, unsigned int write_mask, -+ uint32_t vector1_id, uint32_t vector2_id, uint32_t swizzle, uint32_t write_mask, - enum vkd3d_shader_component_type component_type, unsigned int component_count) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -@@ -3664,9 +3664,9 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil - for (i = 0; i < component_count; ++i) - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- components[i] = vkd3d_swizzle_get_component(swizzle, i); -+ components[i] = vsir_swizzle_get_component(swizzle, i); - else -- components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(swizzle, i); -+ components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(swizzle, i); - } - - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); -@@ -3675,7 +3675,7 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil - } - - static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask) -+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) - { - unsigned int component_count = vsir_write_mask_component_count(write_mask); - uint32_t values[VKD3D_VEC4_SIZE] = {0}; -@@ -3693,7 +3693,7 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile - for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- values[j++] = reg->u.immconst_uint[vkd3d_swizzle_get_component(swizzle, i)]; -+ values[j++] = reg->u.immconst_uint[vsir_swizzle_get_component(swizzle, i)]; - } - } - -@@ -3702,7 +3702,7 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile - } - - static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask) -+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) - { - unsigned int component_count = vsir_write_mask_component_count(write_mask); - uint64_t values[VKD3D_DVEC2_SIZE] = {0}; -@@ -3720,7 +3720,7 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi - for (i = 0, j = 0; i < VKD3D_DVEC2_SIZE; ++i) - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- values[j++] = reg->u.immconst_uint64[vkd3d_swizzle_get_component64(swizzle, i)]; -+ values[j++] = reg->u.immconst_uint64[vsir_swizzle_get_component64(swizzle, i)]; - } - } - -@@ -3742,7 +3742,7 @@ static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask, -+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask, - const struct vkd3d_shader_register_info *reg_info) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -@@ -3755,7 +3755,7 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, - assert(vsir_write_mask_component_count(write_mask) == 1); - - component_idx = vsir_write_mask_get_component_idx(write_mask); -- component_idx = vkd3d_swizzle_get_component(swizzle, component_idx); -+ component_idx = vsir_swizzle_get_component(swizzle, component_idx); - skipped_component_mask = ~reg_info->write_mask & ((VKD3DSP_WRITEMASK_0 << component_idx) - 1); - if (skipped_component_mask) - component_idx -= vsir_write_mask_component_count(skipped_component_mask); -@@ -3871,7 +3871,7 @@ static void spirv_compiler_set_ssa_register_info(const struct spirv_compiler *co - - static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, enum vkd3d_shader_component_type component_type, -- unsigned int swizzle) -+ uint32_t swizzle) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - enum vkd3d_shader_component_type reg_component_type; -@@ -3897,7 +3897,7 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler - } - - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); -- component_idx = vkd3d_swizzle_get_component(swizzle, 0); -+ component_idx = vsir_swizzle_get_component(swizzle, 0); - return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx); - } - -@@ -4233,7 +4233,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp - - static void spirv_compiler_emit_store_dst_scalar(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst, uint32_t val_id, -- enum vkd3d_shader_component_type component_type, DWORD swizzle) -+ enum vkd3d_shader_component_type component_type, uint32_t swizzle) - { - unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); - uint32_t component_ids[VKD3D_VEC4_SIZE]; -@@ -4242,7 +4242,7 @@ static void spirv_compiler_emit_store_dst_scalar(struct spirv_compiler *compiler - component_idx = vsir_write_mask_get_component_idx(dst->write_mask); - for (i = 0; i < component_count; ++i) - { -- if (vkd3d_swizzle_get_component(swizzle, component_idx + i)) -+ if (vsir_swizzle_get_component(swizzle, component_idx + i)) - ERR("Invalid swizzle %#x for scalar value, write mask %#x.\n", swizzle, dst->write_mask); - - component_ids[i] = val_id; -@@ -6940,7 +6940,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, - for (i = 0; i < ARRAY_SIZE(components); ++i) - { - if (dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(src->swizzle, i); -+ components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(src->swizzle, i); - else - components[i] = i; - } -@@ -8414,7 +8414,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, - } - else - { -- component_idx = vkd3d_swizzle_get_component(sampler->swizzle, 0); -+ component_idx = vsir_swizzle_get_component(sampler->swizzle, 0); - /* Nvidia driver requires signed integer type. */ - component_id = spirv_compiler_get_constant(compiler, - VKD3D_SHADER_COMPONENT_INT, 1, &component_idx); -@@ -8492,7 +8492,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler - if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) - continue; - -- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); -+ component_idx = vsir_swizzle_get_component(resource->swizzle, i); - coordinate_id = base_coordinate_id; - if (component_idx) - coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, -@@ -8524,7 +8524,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler - if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) - continue; - -- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); -+ component_idx = vsir_swizzle_get_component(resource->swizzle, i); - coordinate_id = base_coordinate_id; - if (component_idx) - coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, -@@ -8568,7 +8568,7 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, - if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) - continue; - -- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); -+ component_idx = vsir_swizzle_get_component(resource->swizzle, i); - coordinate_id = base_coordinate_id; - if (component_idx) - coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 235e855223f..9508abfb868 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -1982,10 +1982,10 @@ static uint32_t swizzle_from_sm4(uint32_t s) - static uint32_t swizzle_to_sm4(uint32_t s) - { - uint32_t ret = 0; -- ret |= ((vkd3d_swizzle_get_component(s, 0)) & 0x3); -- ret |= ((vkd3d_swizzle_get_component(s, 1)) & 0x3) << 2; -- ret |= ((vkd3d_swizzle_get_component(s, 2)) & 0x3) << 4; -- ret |= ((vkd3d_swizzle_get_component(s, 3)) & 0x3) << 6; -+ ret |= ((vsir_swizzle_get_component(s, 0)) & 0x3); -+ ret |= ((vsir_swizzle_get_component(s, 1)) & 0x3) << 2; -+ ret |= ((vsir_swizzle_get_component(s, 2)) & 0x3) << 4; -+ ret |= ((vsir_swizzle_get_component(s, 3)) & 0x3) << 6; - return ret; - } - -@@ -2014,12 +2014,12 @@ static bool register_is_control_point_input(const struct vkd3d_shader_register * - || priv->p.shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY)); - } - --static unsigned int mask_from_swizzle(unsigned int swizzle) -+static uint32_t mask_from_swizzle(uint32_t swizzle) - { -- return (1u << vkd3d_swizzle_get_component(swizzle, 0)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 1)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 2)) -- | (1u << vkd3d_swizzle_get_component(swizzle, 3)); -+ return (1u << vsir_swizzle_get_component(swizzle, 0)) -+ | (1u << vsir_swizzle_get_component(swizzle, 1)) -+ | (1u << vsir_swizzle_get_component(swizzle, 2)) -+ | (1u << vsir_swizzle_get_component(swizzle, 3)); - } - - static bool shader_sm4_validate_input_output_register(struct vkd3d_shader_sm4_parser *priv, -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index 4fd5c9bd034..caf8a6a4a3e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -1073,6 +1073,9 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte - vkd3d_shader_scan_sampler_declaration(context, instruction); - break; - case VKD3DSIH_DCL: -+ if (instruction->declaration.semantic.resource_type == VKD3D_SHADER_RESOURCE_NONE) -+ break; -+ - if (instruction->declaration.semantic.resource.reg.reg.type == VKD3DSPR_COMBINED_SAMPLER) - { - vkd3d_shader_scan_combined_sampler_declaration(context, &instruction->declaration.semantic); -@@ -1540,9 +1543,6 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, - - scan_info = *compile_info; - -- if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) -- return ret; -- - switch (compile_info->target_type) - { - case VKD3D_SHADER_TARGET_D3D_ASM: -@@ -1550,6 +1550,8 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, - break; - - case VKD3D_SHADER_TARGET_GLSL: -+ if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) -+ return ret; - if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->shader_version, - message_context, &parser->location))) - { -@@ -1560,19 +1562,22 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, - - ret = vkd3d_glsl_generator_generate(glsl_generator, parser, out); - vkd3d_glsl_generator_destroy(glsl_generator); -+ vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); - break; - - case VKD3D_SHADER_TARGET_SPIRV_BINARY: - case VKD3D_SHADER_TARGET_SPIRV_TEXT: -+ if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) -+ return ret; - ret = spirv_compile(parser, &scan_descriptor_info, compile_info, out, message_context); -+ vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); - break; - - default: - /* Validation should prevent us from reaching this. */ -- assert(0); -+ vkd3d_unreachable(); - } - -- vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); - return ret; - } - -@@ -1621,14 +1626,10 @@ static int compile_d3d_bytecode(const struct vkd3d_shader_compile_info *compile_ - return ret; - } - -- if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM) -- { -- ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out, VSIR_ASM_D3D); -- vkd3d_shader_parser_destroy(parser); -- return ret; -- } -+ ret = vkd3d_shader_parser_compile(parser, compile_info, out, message_context); - -- return VKD3D_ERROR; -+ vkd3d_shader_parser_destroy(parser); -+ return ret; - } - - static int compile_dxbc_dxil(const struct vkd3d_shader_compile_info *compile_info, -@@ -1906,6 +1907,10 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( - - static const enum vkd3d_shader_target_type d3dbc_types[] = - { -+ VKD3D_SHADER_TARGET_SPIRV_BINARY, -+#ifdef HAVE_SPIRV_TOOLS -+ VKD3D_SHADER_TARGET_SPIRV_TEXT, -+#endif - VKD3D_SHADER_TARGET_D3D_ASM, - }; - -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 6fa57a111bb..274faf296e8 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -1557,19 +1557,17 @@ static inline uint32_t vsir_write_mask_32_from_64(uint32_t write_mask64) - return write_mask32 | (write_mask32 << 1); - } - --static inline unsigned int vkd3d_swizzle_get_component(DWORD swizzle, -- unsigned int idx) -+static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx) - { - return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK; - } - --static inline unsigned int vkd3d_swizzle_get_component64(DWORD swizzle, -- unsigned int idx) -+static inline unsigned int vsir_swizzle_get_component64(uint32_t swizzle, unsigned int idx) - { - return ((swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx * 2)) & VKD3D_SHADER_SWIZZLE_MASK) / 2u; - } - --static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned int write_mask) -+static inline unsigned int vkd3d_compact_swizzle(uint32_t swizzle, uint32_t write_mask) - { - unsigned int i, compacted_swizzle = 0; - -@@ -1578,7 +1576,7 @@ static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - { - compacted_swizzle <<= VKD3D_SHADER_SWIZZLE_SHIFT(1); -- compacted_swizzle |= vkd3d_swizzle_get_component(swizzle, i); -+ compacted_swizzle |= vsir_swizzle_get_component(swizzle, i); - } - } - -diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c -index 15c8317b191..549f6a45ffb 100644 ---- a/libs/vkd3d/libs/vkd3d/command.c -+++ b/libs/vkd3d/libs/vkd3d/command.c -@@ -2644,6 +2644,8 @@ static bool d3d12_command_list_update_compute_pipeline(struct d3d12_command_list - { - const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; - -+ vkd3d_cond_signal(&list->device->worker_cond); -+ - if (list->current_pipeline != VK_NULL_HANDLE) - return true; - -@@ -2665,6 +2667,8 @@ static bool d3d12_command_list_update_graphics_pipeline(struct d3d12_command_lis - VkRenderPass vk_render_pass; - VkPipeline vk_pipeline; - -+ vkd3d_cond_signal(&list->device->worker_cond); -+ - if (list->current_pipeline != VK_NULL_HANDLE) - return true; - -diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c -index 5c801ca4676..69a46e9188a 100644 ---- a/libs/vkd3d/libs/vkd3d/device.c -+++ b/libs/vkd3d/libs/vkd3d/device.c -@@ -2056,7 +2056,7 @@ static HRESULT d3d12_device_init_pipeline_cache(struct d3d12_device *device) - VkPipelineCacheCreateInfo cache_info; - VkResult vr; - -- vkd3d_mutex_init(&device->mutex); -+ vkd3d_mutex_init(&device->pipeline_cache_mutex); - - cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - cache_info.pNext = NULL; -@@ -2080,7 +2080,7 @@ static void d3d12_device_destroy_pipeline_cache(struct d3d12_device *device) - if (device->vk_pipeline_cache) - VK_CALL(vkDestroyPipelineCache(device->vk_device, device->vk_pipeline_cache, NULL)); - -- vkd3d_mutex_destroy(&device->mutex); -+ vkd3d_mutex_destroy(&device->pipeline_cache_mutex); - } - - #define VKD3D_VA_FALLBACK_BASE 0x8000000000000000ull -@@ -2495,6 +2495,28 @@ static ULONG STDMETHODCALLTYPE d3d12_device_AddRef(ID3D12Device5 *iface) - return refcount; - } - -+static HRESULT device_worker_stop(struct d3d12_device *device) -+{ -+ HRESULT hr; -+ -+ TRACE("device %p.\n", device); -+ -+ vkd3d_mutex_lock(&device->worker_mutex); -+ -+ device->worker_should_exit = true; -+ vkd3d_cond_signal(&device->worker_cond); -+ -+ vkd3d_mutex_unlock(&device->worker_mutex); -+ -+ if (FAILED(hr = vkd3d_join_thread(device->vkd3d_instance, &device->worker_thread))) -+ return hr; -+ -+ vkd3d_mutex_destroy(&device->worker_mutex); -+ vkd3d_cond_destroy(&device->worker_cond); -+ -+ return S_OK; -+} -+ - static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface) - { - struct d3d12_device *device = impl_from_ID3D12Device5(iface); -@@ -2520,6 +2542,9 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface) - d3d12_device_destroy_vkd3d_queues(device); - vkd3d_desc_object_cache_cleanup(&device->view_desc_cache); - vkd3d_desc_object_cache_cleanup(&device->cbuffer_desc_cache); -+ if (device->use_vk_heaps) -+ device_worker_stop(device); -+ vkd3d_free(device->heaps); - VK_CALL(vkDestroyDevice(device->vk_device, NULL)); - if (device->parent) - IUnknown_Release(device->parent); -@@ -4251,6 +4276,40 @@ struct d3d12_device *unsafe_impl_from_ID3D12Device5(ID3D12Device5 *iface) - return impl_from_ID3D12Device5(iface); - } - -+static void *device_worker_main(void *arg) -+{ -+ struct d3d12_descriptor_heap *heap; -+ struct d3d12_device *device = arg; -+ size_t i; -+ -+ vkd3d_set_thread_name("device_worker"); -+ -+ vkd3d_mutex_lock(&device->worker_mutex); -+ -+ while (!device->worker_should_exit) -+ { -+ for (i = 0; i < device->heap_count; ++i) -+ { -+ /* Descriptor updates are not written to Vulkan descriptor sets until a command list -+ * is submitted to a queue, while the client is free to write d3d12 descriptors earlier, -+ * from any thread. This causes a delay right before command list execution, so -+ * handling these updates in a worker thread can speed up execution significantly. */ -+ heap = device->heaps[i]; -+ if (heap->dirty_list_head == UINT_MAX) -+ continue; -+ vkd3d_mutex_lock(&heap->vk_sets_mutex); -+ d3d12_desc_flush_vk_heap_updates_locked(heap, device); -+ vkd3d_mutex_unlock(&heap->vk_sets_mutex); -+ } -+ -+ vkd3d_cond_wait(&device->worker_cond, &device->worker_mutex); -+ } -+ -+ vkd3d_mutex_unlock(&device->worker_mutex); -+ -+ return NULL; -+} -+ - static HRESULT d3d12_device_init(struct d3d12_device *device, - struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info) - { -@@ -4270,6 +4329,14 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, - - device->vk_device = VK_NULL_HANDLE; - -+ device->heaps = NULL; -+ device->heap_capacity = 0; -+ device->heap_count = 0; -+ memset(&device->worker_thread, 0, sizeof(device->worker_thread)); -+ device->worker_should_exit = false; -+ vkd3d_mutex_init(&device->worker_mutex); -+ vkd3d_cond_init(&device->worker_cond); -+ - if (FAILED(hr = vkd3d_create_vk_device(device, create_info))) - goto out_free_instance; - -@@ -4291,6 +4358,13 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, - if (FAILED(hr = vkd3d_vk_descriptor_heap_layouts_init(device))) - goto out_cleanup_uav_clear_state; - -+ if (device->use_vk_heaps && FAILED(hr = vkd3d_create_thread(device->vkd3d_instance, -+ device_worker_main, device, &device->worker_thread))) -+ { -+ WARN("Failed to create worker thread, hr %#x.\n", hr); -+ goto out_cleanup_descriptor_heap_layouts; -+ } -+ - vkd3d_render_pass_cache_init(&device->render_pass_cache); - vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator); - vkd3d_time_domains_init(device); -@@ -4308,6 +4382,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, - - return S_OK; - -+out_cleanup_descriptor_heap_layouts: -+ vkd3d_vk_descriptor_heap_layouts_cleanup(device); - out_cleanup_uav_clear_state: - vkd3d_uav_clear_state_cleanup(&device->uav_clear_state, device); - out_destroy_null_resources: -@@ -4361,6 +4437,40 @@ void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, - device->removed_reason = reason; - } - -+HRESULT d3d12_device_add_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap) -+{ -+ vkd3d_mutex_lock(&device->worker_mutex); -+ -+ if (!vkd3d_array_reserve((void **)&device->heaps, &device->heap_capacity, device->heap_count + 1, -+ sizeof(*device->heaps))) -+ { -+ vkd3d_mutex_unlock(&device->worker_mutex); -+ return E_OUTOFMEMORY; -+ } -+ device->heaps[device->heap_count++] = heap; -+ -+ vkd3d_mutex_unlock(&device->worker_mutex); -+ -+ return S_OK; -+} -+ -+void d3d12_device_remove_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap) -+{ -+ size_t i; -+ -+ vkd3d_mutex_lock(&device->worker_mutex); -+ -+ for (i = 0; i < device->heap_count; ++i) -+ { -+ if (device->heaps[i] == heap) -+ { -+ device->heaps[i] = device->heaps[--device->heap_count]; -+ break; -+ } -+ } -+ -+ vkd3d_mutex_unlock(&device->worker_mutex); -+} - - #ifdef _WIN32 - struct thread_data -diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c -index abbdfbe2015..609c67102a6 100644 ---- a/libs/vkd3d/libs/vkd3d/resource.c -+++ b/libs/vkd3d/libs/vkd3d/resource.c -@@ -2632,20 +2632,18 @@ void d3d12_desc_flush_vk_heap_updates_locked(struct d3d12_descriptor_heap *descr - for (; i != UINT_MAX; i = next) - { - src = &descriptors[i]; -- next = (int)src->next >> 1; -+ next = vkd3d_atomic_exchange(&src->next, 0); -+ next = (int)next >> 1; - -+ /* A race exists here between updating src->next and getting the current object. The best -+ * we can do is get the object last, which may result in a harmless rewrite later. */ - u.object = d3d12_desc_get_object_ref(src, device); - - if (!u.object) -- { -- vkd3d_atomic_exchange(&src->next, 0); - continue; -- } - - writes.held_refs[writes.held_ref_count++] = u.object; - d3d12_desc_write_vk_heap(descriptor_heap, i, &writes, u.object, device); -- -- vkd3d_atomic_exchange(&src->next, 0); - } - - /* Avoid thunk calls wherever possible. */ -@@ -3997,6 +3995,9 @@ static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHea - { - struct d3d12_desc *descriptors = (struct d3d12_desc *)heap->descriptors; - -+ if (heap->use_vk_heaps) -+ d3d12_device_remove_descriptor_heap(device, heap); -+ - for (i = 0; i < heap->desc.NumDescriptors; ++i) - { - d3d12_desc_destroy(&descriptors[i], device); -@@ -4320,6 +4321,12 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device, - dst[i].next = 0; - } - object->dirty_list_head = UINT_MAX; -+ -+ if (object->use_vk_heaps && FAILED(hr = d3d12_device_add_descriptor_heap(device, object))) -+ { -+ vkd3d_free(object); -+ return hr; -+ } - } - else - { -diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c -index 9a039452c99..626d6d62b3c 100644 ---- a/libs/vkd3d/libs/vkd3d/state.c -+++ b/libs/vkd3d/libs/vkd3d/state.c -@@ -1691,7 +1691,7 @@ HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache, - HRESULT hr = S_OK; - unsigned int i; - -- vkd3d_mutex_lock(&device->mutex); -+ vkd3d_mutex_lock(&device->pipeline_cache_mutex); - - for (i = 0; i < cache->render_pass_count; ++i) - { -@@ -1708,7 +1708,7 @@ HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache, - if (!found) - hr = vkd3d_render_pass_cache_create_pass_locked(cache, device, key, vk_render_pass); - -- vkd3d_mutex_unlock(&device->mutex); -+ vkd3d_mutex_unlock(&device->pipeline_cache_mutex); - - return hr; - } -@@ -3615,7 +3615,7 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12 - - *vk_render_pass = VK_NULL_HANDLE; - -- vkd3d_mutex_lock(&device->mutex); -+ vkd3d_mutex_lock(&device->pipeline_cache_mutex); - - LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry) - { -@@ -3627,7 +3627,7 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12 - } - } - -- vkd3d_mutex_unlock(&device->mutex); -+ vkd3d_mutex_unlock(&device->pipeline_cache_mutex); - - return vk_pipeline; - } -@@ -3646,7 +3646,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta - compiled_pipeline->vk_pipeline = vk_pipeline; - compiled_pipeline->vk_render_pass = vk_render_pass; - -- vkd3d_mutex_lock(&device->mutex); -+ vkd3d_mutex_lock(&device->pipeline_cache_mutex); - - LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry) - { -@@ -3661,7 +3661,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta - if (compiled_pipeline) - list_add_tail(&graphics->compiled_pipelines, &compiled_pipeline->entry); - -- vkd3d_mutex_unlock(&device->mutex); -+ vkd3d_mutex_unlock(&device->pipeline_cache_mutex); - return compiled_pipeline; - } - -diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -index f06f564d6ea..bd7e7290d9e 100644 ---- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h -+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -@@ -1757,9 +1757,23 @@ struct d3d12_device - - struct vkd3d_gpu_va_allocator gpu_va_allocator; - -- struct vkd3d_mutex mutex; - struct vkd3d_desc_object_cache view_desc_cache; - struct vkd3d_desc_object_cache cbuffer_desc_cache; -+ -+ VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT]; -+ unsigned int vk_pool_count; -+ struct vkd3d_vk_descriptor_heap_layout vk_descriptor_heap_layouts[VKD3D_SET_INDEX_COUNT]; -+ bool use_vk_heaps; -+ -+ struct d3d12_descriptor_heap **heaps; -+ size_t heap_capacity; -+ size_t heap_count; -+ union vkd3d_thread_handle worker_thread; -+ struct vkd3d_mutex worker_mutex; -+ struct vkd3d_cond worker_cond; -+ bool worker_should_exit; -+ -+ struct vkd3d_mutex pipeline_cache_mutex; - struct vkd3d_render_pass_cache render_pass_cache; - VkPipelineCache vk_pipeline_cache; - -@@ -1799,11 +1813,6 @@ struct d3d12_device - const struct vkd3d_format_compatibility_list *format_compatibility_lists; - struct vkd3d_null_resources null_resources; - struct vkd3d_uav_clear_state uav_clear_state; -- -- VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT]; -- unsigned int vk_pool_count; -- struct vkd3d_vk_descriptor_heap_layout vk_descriptor_heap_layouts[VKD3D_SET_INDEX_COUNT]; -- bool use_vk_heaps; - }; - - HRESULT d3d12_device_create(struct vkd3d_instance *instance, -@@ -1813,6 +1822,8 @@ bool d3d12_device_is_uma(struct d3d12_device *device, bool *coherent); - void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, - const char *message, ...) VKD3D_PRINTF_FUNC(3, 4); - struct d3d12_device *unsafe_impl_from_ID3D12Device5(ID3D12Device5 *iface); -+HRESULT d3d12_device_add_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap); -+void d3d12_device_remove_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap); - - static inline HRESULT d3d12_device_query_interface(struct d3d12_device *device, REFIID iid, void **object) - { --- -2.43.0 - diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-78343dcf87d3a911264c6c9a87a9146c43c.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-78343dcf87d3a911264c6c9a87a9146c43c.patch deleted file mode 100644 index 03a3dcef..00000000 --- a/patches/vkd3d-latest/0005-Updated-vkd3d-to-78343dcf87d3a911264c6c9a87a9146c43c.patch +++ /dev/null @@ -1,332 +0,0 @@ -From 4c76fe254fce377da5668d686843895d0d2d6d8c Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Wed, 3 Jan 2024 19:06:40 +1100 -Subject: [PATCH] Updated vkd3d to 78343dcf87d3a911264c6c9a87a9146c43c859c3. - ---- - libs/vkd3d/include/vkd3d_shader.h | 2 + - libs/vkd3d/libs/vkd3d-shader/spirv.c | 87 +++++++++++++------ - .../libs/vkd3d-shader/vkd3d_shader_private.h | 7 ++ - libs/vkd3d/libs/vkd3d/state.c | 11 +++ - 4 files changed, 81 insertions(+), 26 deletions(-) - -diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h -index a6bf8964183..b1a1fff6451 100644 ---- a/libs/vkd3d/include/vkd3d_shader.h -+++ b/libs/vkd3d/include/vkd3d_shader.h -@@ -1569,6 +1569,8 @@ enum vkd3d_shader_component_type - VKD3D_SHADER_COMPONENT_BOOL = 0x4, - /** 64-bit IEEE floating-point. */ - VKD3D_SHADER_COMPONENT_DOUBLE = 0x5, -+ /** 64-bit unsigned integer. \since 1.11 */ -+ VKD3D_SHADER_COMPONENT_UINT64 = 0x6, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPONENT_TYPE), - }; -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index f77bc25329d..9e3cd7549ba 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -1797,6 +1797,8 @@ static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder, - break; - case VKD3D_SHADER_COMPONENT_DOUBLE: - return vkd3d_spirv_get_op_type_float(builder, 64); -+ case VKD3D_SHADER_COMPONENT_UINT64: -+ return vkd3d_spirv_get_op_type_int(builder, 64, 0); - default: - FIXME("Unhandled component type %#x.\n", component_type); - return 0; -@@ -1830,6 +1832,8 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder - 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: -@@ -2988,7 +2992,7 @@ static uint32_t spirv_compiler_get_constant64(struct spirv_compiler *compiler, - assert(0 < component_count && component_count <= VKD3D_DVEC2_SIZE); - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); - -- if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE) -+ if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE && component_type != VKD3D_SHADER_COMPONENT_UINT64) - { - FIXME("Unhandled component_type %#x.\n", component_type); - return vkd3d_spirv_get_op_undef(builder, type_id); -@@ -3048,6 +3052,13 @@ static uint32_t spirv_compiler_get_constant_double_vector(struct spirv_compiler - component_count, (const uint64_t *)values); - } - -+static uint32_t spirv_compiler_get_constant_uint64_vector(struct spirv_compiler *compiler, -+ uint64_t value, unsigned int component_count) -+{ -+ const uint64_t values[] = {value, value}; -+ return spirv_compiler_get_constant64(compiler, VKD3D_SHADER_COMPONENT_UINT64, component_count, values); -+} -+ - static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, uint32_t write_mask) - { -@@ -3932,7 +3943,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, - assert(reg_info.component_type != VKD3D_SHADER_COMPONENT_DOUBLE); - spirv_compiler_emit_dereference_register(compiler, reg, ®_info); - -- write_mask32 = (reg->data_type == VKD3D_DATA_DOUBLE) ? vsir_write_mask_32_from_64(write_mask) : write_mask; -+ write_mask32 = data_type_is_64_bit(reg->data_type) ? vsir_write_mask_32_from_64(write_mask) : write_mask; - - /* Intermediate value (no storage class). */ - if (reg_info.storage_class == SpvStorageClassMax) -@@ -4000,7 +4011,7 @@ static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, - type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask); - if (reg->data_type == VKD3D_DATA_FLOAT || reg->data_type == VKD3D_DATA_DOUBLE) - return vkd3d_spirv_build_op_fnegate(builder, type_id, val_id); -- else if (reg->data_type == VKD3D_DATA_INT || reg->data_type == VKD3D_DATA_UINT) -+ else if (data_type_is_integer(reg->data_type)) - return vkd3d_spirv_build_op_snegate(builder, type_id, val_id); - - FIXME("Unhandled data type %#x.\n", reg->data_type); -@@ -4148,7 +4159,7 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, - component_type = vkd3d_component_type_from_data_type(reg->data_type); - if (component_type != reg_info.component_type) - { -- if (reg->data_type == VKD3D_DATA_DOUBLE) -+ if (data_type_is_64_bit(reg->data_type)) - src_write_mask = vsir_write_mask_32_from_64(write_mask); - type_id = vkd3d_spirv_get_type_id(builder, reg_info.component_type, - vsir_write_mask_component_count(src_write_mask)); -@@ -4287,14 +4298,18 @@ static void spirv_compiler_decorate_builtin(struct spirv_compiler *compiler, - } - - static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler *compiler, -- uint32_t id, enum vkd3d_shader_interpolation_mode mode) -+ enum vkd3d_shader_component_type component_type, uint32_t id, enum vkd3d_shader_interpolation_mode mode) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - - switch (mode) - { - case VKD3DSIM_NONE: -- break; -+ /* VUID-StandaloneSpirv-Flat-04744: integer or double types must be -+ * decorated 'Flat' for fragment shaders. */ -+ if (compiler->shader_type != VKD3D_SHADER_TYPE_PIXEL || component_type == VKD3D_SHADER_COMPONENT_FLOAT) -+ break; -+ /* fall through */ - case VKD3DSIM_CONSTANT: - vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationFlat, NULL, 0); - break; -@@ -4322,7 +4337,8 @@ static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler - } - - static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, -- enum vkd3d_shader_conditional_op condition, unsigned int component_count, uint32_t val_id) -+ enum vkd3d_shader_conditional_op condition, enum vkd3d_data_type data_type, -+ unsigned int component_count, uint32_t val_id) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id; -@@ -4333,7 +4349,9 @@ static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); - op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual; - return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, val_id, -- spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); -+ data_type == VKD3D_DATA_UINT64 -+ ? spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count) -+ : spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); - } - - static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, -@@ -4348,6 +4366,19 @@ static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, - return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); - } - -+static uint32_t spirv_compiler_emit_bool_to_int64(struct spirv_compiler *compiler, -+ unsigned int component_count, uint32_t val_id, bool signedness) -+{ -+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -+ uint32_t type_id, true_id, false_id; -+ -+ true_id = spirv_compiler_get_constant_uint64_vector(compiler, signedness ? UINT64_MAX : 1, -+ component_count); -+ false_id = spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count); -+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT64, component_count); -+ return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); -+} -+ - static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compiler, - unsigned int component_count, uint32_t val_id, bool signedness) - { -@@ -4874,7 +4905,8 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - if (component_idx) - vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationComponent, component_idx); - -- spirv_compiler_emit_interpolation_decorations(compiler, input_id, signature_element->interpolation_mode); -+ spirv_compiler_emit_interpolation_decorations(compiler, component_type, input_id, -+ signature_element->interpolation_mode); - } - - var_id = input_id; -@@ -6670,12 +6702,14 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru - {VKD3DSIH_ISHR, SpvOpShiftRightArithmetic}, - {VKD3DSIH_ITOD, SpvOpConvertSToF}, - {VKD3DSIH_ITOF, SpvOpConvertSToF}, -+ {VKD3DSIH_ITOI, SpvOpSConvert}, - {VKD3DSIH_MUL, SpvOpFMul}, - {VKD3DSIH_NOT, SpvOpNot}, - {VKD3DSIH_OR, SpvOpBitwiseOr}, - {VKD3DSIH_USHR, SpvOpShiftRightLogical}, - {VKD3DSIH_UTOD, SpvOpConvertUToF}, - {VKD3DSIH_UTOF, SpvOpConvertUToF}, -+ {VKD3DSIH_UTOU, SpvOpUConvert}, - {VKD3DSIH_XOR, SpvOpBitwiseXor}, - }; - unsigned int i; -@@ -6727,6 +6761,10 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, - { - val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); - } -+ else if (dst->reg.data_type == VKD3D_DATA_UINT64) -+ { -+ val_id = spirv_compiler_emit_bool_to_int64(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); -+ } - else - { - WARN("Unhandled data type %u.\n", dst->reg.data_type); -@@ -6980,7 +7018,7 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, - - if (src[0].reg.data_type != VKD3D_DATA_BOOL) - condition_id = spirv_compiler_emit_int_to_bool(compiler, -- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id); -+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); - val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id); - - spirv_compiler_emit_store_dst(compiler, dst, val_id); -@@ -7005,7 +7043,7 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler, - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); - - condition_id = spirv_compiler_emit_int_to_bool(compiler, -- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id); -+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); - - val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src2_id, src1_id); - spirv_compiler_emit_store_dst(compiler, &dst[0], val_id); -@@ -7167,13 +7205,6 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, - div_op = instruction->handler_idx == VKD3DSIH_IDIV ? SpvOpSDiv : SpvOpUDiv; - mod_op = instruction->handler_idx == VKD3DSIH_IDIV ? SpvOpSRem : SpvOpUMod; - -- if (dst[0].reg.data_type == VKD3D_DATA_UINT64 || dst[1].reg.data_type == VKD3D_DATA_UINT64) -- { -- FIXME("Unsupported 64-bit result.\n"); -- spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, -- "Bool cast to 64-bit integer is not supported."); -- } -- - if (dst[0].reg.type != VKD3DSPR_NULL) - { - component_count = vsir_write_mask_component_count(dst[0].write_mask); -@@ -7183,9 +7214,11 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst[0].write_mask); - - condition_id = spirv_compiler_emit_int_to_bool(compiler, -- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id); -- uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, -- 0xffffffff, component_count); -+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src1_id); -+ if (dst[0].reg.data_type == VKD3D_DATA_UINT64) -+ uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count); -+ else -+ uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count); - - val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, div_op, type_id, src0_id, src1_id); - /* The SPIR-V spec says: "The resulting value is undefined if Operand 2 is 0." */ -@@ -7205,9 +7238,11 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, - src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst[1].write_mask); - - condition_id = spirv_compiler_emit_int_to_bool(compiler, -- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id); -- uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, -- 0xffffffff, component_count); -+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src1_id); -+ if (dst[1].reg.data_type == VKD3D_DATA_UINT64) -+ uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count); -+ else -+ uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count); - } - - val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, mod_op, type_id, src0_id, src1_id); -@@ -7498,7 +7533,7 @@ static uint32_t spirv_compiler_emit_conditional_branch(struct spirv_compiler *co - uint32_t condition_id, merge_block_id; - - condition_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); -- condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, 1, condition_id); -+ condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, src->reg.data_type, 1, condition_id); - - merge_block_id = vkd3d_spirv_alloc_id(builder); - -@@ -7631,7 +7666,7 @@ static int spirv_compiler_emit_control_flow_instruction(struct spirv_compiler *c - return VKD3D_ERROR_OUT_OF_MEMORY; - - val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); -- condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, 1, val_id); -+ condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, src->reg.data_type, 1, val_id); - - true_label = vkd3d_spirv_alloc_id(builder); - merge_block_id = vkd3d_spirv_alloc_id(builder); -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 274faf296e8..ce7d74a72dc 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -620,6 +620,11 @@ static inline bool data_type_is_bool(enum vkd3d_data_type data_type) - return data_type == VKD3D_DATA_BOOL; - } - -+static inline bool data_type_is_64_bit(enum vkd3d_data_type data_type) -+{ -+ return data_type == VKD3D_DATA_DOUBLE || data_type == VKD3D_DATA_UINT64; -+} -+ - enum vsir_dimension - { - VSIR_DIMENSION_NONE, -@@ -1455,6 +1460,8 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty - return VKD3D_SHADER_COMPONENT_INT; - case VKD3D_DATA_DOUBLE: - return VKD3D_SHADER_COMPONENT_DOUBLE; -+ case VKD3D_DATA_UINT64: -+ return VKD3D_SHADER_COMPONENT_UINT64; - case VKD3D_DATA_BOOL: - return VKD3D_SHADER_COMPONENT_BOOL; - default: -diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c -index 626d6d62b3c..1457ddf9c7f 100644 ---- a/libs/vkd3d/libs/vkd3d/state.c -+++ b/libs/vkd3d/libs/vkd3d/state.c -@@ -2129,6 +2129,16 @@ static inline unsigned int typed_uav_compile_option(const struct d3d12_device *d - : VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV_READ_FORMAT_R32; - } - -+static unsigned int feature_flags_compile_option(const struct d3d12_device *device) -+{ -+ unsigned int flags = 0; -+ -+ if (device->feature_options1.Int64ShaderOps) -+ flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64; -+ -+ return flags; -+} -+ - static HRESULT create_shader_stage(struct d3d12_device *device, - struct VkPipelineShaderStageCreateInfo *stage_desc, enum VkShaderStageFlagBits stage, - const D3D12_SHADER_BYTECODE *code, const struct vkd3d_shader_interface_info *shader_interface) -@@ -2145,6 +2155,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device, - {VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_10}, - {VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV, typed_uav_compile_option(device)}, - {VKD3D_SHADER_COMPILE_OPTION_WRITE_TESS_GEOM_POINT_SIZE, 0}, -+ {VKD3D_SHADER_COMPILE_OPTION_FEATURE, feature_flags_compile_option(device)}, - }; - - stage_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; --- -2.43.0 - diff --git a/patches/vkd3d-latest/0006-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch b/patches/vkd3d-latest/0006-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch deleted file mode 100644 index 0c26db59..00000000 --- a/patches/vkd3d-latest/0006-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch +++ /dev/null @@ -1,595 +0,0 @@ -From 46f901c7b05653250a0b038d4a6195fc3ab19790 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Thu, 4 Jan 2024 12:22:17 +1100 -Subject: [PATCH] Updated vkd3d to 3bafee344d8d50172d8da18512ba070c6826b18d. - ---- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 52 ++++++++--------- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 2 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 58 ++++++++++--------- - libs/vkd3d/libs/vkd3d-shader/ir.c | 6 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 10 ++-- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 30 +++++----- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 10 ++++ - .../libs/vkd3d-shader/vkd3d_shader_private.h | 10 ++-- - libs/vkd3d/libs/vkd3d/utils.c | 2 + - 9 files changed, 99 insertions(+), 81 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index ac1c41f96e2..0589bc42174 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -1109,15 +1109,15 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const - switch (reg->data_type) - { - case VKD3D_DATA_FLOAT: -- shader_print_float_literal(compiler, "", reg->u.immconst_float[0], ""); -+ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); - break; - case VKD3D_DATA_INT: -- shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], ""); -+ 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_uint[0], ""); -+ shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); - break; - default: - shader_addline(buffer, "", reg->data_type); -@@ -1129,24 +1129,24 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const - switch (reg->data_type) - { - case VKD3D_DATA_FLOAT: -- shader_print_float_literal(compiler, "", reg->u.immconst_float[0], ""); -- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[1], ""); -- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[2], ""); -- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[3], ""); -+ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); -+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[1], ""); -+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[2], ""); -+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[3], ""); - break; - case VKD3D_DATA_INT: -- shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], ""); -- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[1], ""); -- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[2], ""); -- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[3], ""); -+ shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); -+ shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[1], ""); -+ 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_uint[0], ""); -- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[1], ""); -- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[2], ""); -- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[3], ""); -+ shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); -+ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[1], ""); -+ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[2], ""); -+ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[3], ""); - break; - default: - shader_addline(buffer, "", reg->data_type); -@@ -1168,9 +1168,9 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const - { - if (reg->data_type == VKD3D_DATA_DOUBLE) - { -- shader_print_double_literal(compiler, "", reg->u.immconst_double[0], ""); -+ shader_print_double_literal(compiler, "", reg->u.immconst_f64[0], ""); - if (reg->dimension == VSIR_DIMENSION_VEC4) -- shader_print_double_literal(compiler, ", ", reg->u.immconst_double[1], ""); -+ shader_print_double_literal(compiler, ", ", reg->u.immconst_f64[1], ""); - } - else - { -@@ -1882,25 +1882,25 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, - vkd3d_string_buffer_printf(buffer, " %sc%u%s", compiler->colours.reg, - shader_get_float_offset(ins->dst[0].reg.type, ins->dst[0].reg.idx[0].offset), - compiler->colours.reset); -- shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_float[0], ""); -- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[1], ""); -- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[2], ""); -- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[3], ""); -+ shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_f32[0], ""); -+ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[1], ""); -+ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[2], ""); -+ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[3], ""); - break; - - case VKD3DSIH_DEFI: - vkd3d_string_buffer_printf(buffer, " %si%u%s", compiler->colours.reg, - ins->dst[0].reg.idx[0].offset, compiler->colours.reset); -- shader_print_int_literal(compiler, " = ", ins->src[0].reg.u.immconst_uint[0], ""); -- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[1], ""); -- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[2], ""); -- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[3], ""); -+ shader_print_int_literal(compiler, " = ", ins->src[0].reg.u.immconst_u32[0], ""); -+ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[1], ""); -+ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[2], ""); -+ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[3], ""); - break; - - case VKD3DSIH_DEFB: - vkd3d_string_buffer_printf(buffer, " %sb%u%s", compiler->colours.reg, - ins->dst[0].reg.idx[0].offset, compiler->colours.reset); -- shader_print_bool_literal(compiler, " = ", ins->src[0].reg.u.immconst_uint[0], ""); -+ shader_print_bool_literal(compiler, " = ", ins->src[0].reg.u.immconst_u32[0], ""); - break; - - default: -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index d40ea4b5942..ca6e3b72de9 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -987,7 +987,7 @@ static void shader_sm1_read_immconst(struct vkd3d_shader_sm1_parser *sm1, const - src_param->reg.idx[2].rel_addr = NULL; - src_param->reg.idx_count = 0; - src_param->reg.dimension = dimension; -- memcpy(src_param->reg.u.immconst_uint, *ptr, count * sizeof(uint32_t)); -+ memcpy(src_param->reg.u.immconst_u32, *ptr, count * sizeof(uint32_t)); - src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE; - src_param->modifiers = 0; - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 602056e25d4..2424b176068 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -1237,7 +1237,7 @@ static size_t dxil_block_compute_module_decl_count(const struct dxil_block *bloc - size_t i, count; - - for (i = 0, count = 0; i < block->record_count; ++i) -- count += block->records[i]->code == MODULE_CODE_FUNCTION; -+ count += block->records[i]->code == MODULE_CODE_FUNCTION || block->records[i]->code == MODULE_CODE_GLOBALVAR; - return count; - } - -@@ -1886,12 +1886,12 @@ static unsigned int register_get_uint_value(const struct vkd3d_shader_register * - - if (reg->type == VKD3DSPR_IMMCONST64) - { -- if (reg->u.immconst_uint64[0] > UINT_MAX) -+ if (reg->u.immconst_u64[0] > UINT_MAX) - FIXME("Truncating 64-bit value.\n"); -- return reg->u.immconst_uint64[0]; -+ return reg->u.immconst_u64[0]; - } - -- return reg->u.immconst_uint[0]; -+ return reg->u.immconst_u32[0]; - } - - static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *reg) -@@ -1902,7 +1902,7 @@ static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *re - if (reg->dimension == VSIR_DIMENSION_VEC4) - WARN("Returning vec4.x.\n"); - -- return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_uint64[0] : reg->u.immconst_uint[0]; -+ return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_u64[0] : reg->u.immconst_u32[0]; - } - - static inline bool sm6_value_is_function_dcl(const struct sm6_value *value) -@@ -2577,9 +2577,9 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - - value = decode_rotated_signed_value(record->operands[0]); - if (type->u.width <= 32) -- dst->u.reg.u.immconst_uint[0] = value & ((1ull << type->u.width) - 1); -+ dst->u.reg.u.immconst_u32[0] = value & ((1ull << type->u.width) - 1); - else -- dst->u.reg.u.immconst_uint64[0] = value; -+ dst->u.reg.u.immconst_u64[0] = value; - - break; - -@@ -2596,9 +2596,9 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - if (type->u.width == 16) - FIXME("Half float type is not supported yet.\n"); - else if (type->u.width == 32) -- dst->u.reg.u.immconst_float[0] = bitcast_uint64_to_float(record->operands[0]); -+ dst->u.reg.u.immconst_f32[0] = bitcast_uint64_to_float(record->operands[0]); - else if (type->u.width == 64) -- dst->u.reg.u.immconst_double[0] = bitcast_uint64_to_double(record->operands[0]); -+ dst->u.reg.u.immconst_f64[0] = bitcast_uint64_to_double(record->operands[0]); - else - vkd3d_unreachable(); - -@@ -2877,8 +2877,8 @@ static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_init - - static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) - { -+ size_t i, count, base_value_idx = sm6->value_count; - const struct dxil_block *block = &sm6->root_block; -- size_t i, base_value_idx = sm6->value_count; - struct vkd3d_shader_instruction *ins; - const struct dxil_record *record; - enum vkd3d_result ret; -@@ -2887,6 +2887,10 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) - sm6->p.location.line = block->id; - sm6->p.location.column = 0; - -+ for (i = 0, count = 0; i < block->record_count; ++i) -+ count += block->records[i]->code == MODULE_CODE_GLOBALVAR; -+ sm6_parser_require_space(sm6, count); -+ - for (i = 0; i < block->record_count; ++i) - { - sm6->p.location.column = i; -@@ -6031,7 +6035,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((magic = sm6->start[0]) != BITCODE_MAGIC) - { - WARN("Unknown magic number 0x%08x.\n", magic); -- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER, -+ vkd3d_shader_warning(message_context, &location, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER, - "DXIL bitcode chunk magic number 0x%08x is not the expected 0x%08x.", magic, BITCODE_MAGIC); - } - -@@ -6040,7 +6044,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((version.type = version_token >> 16) >= VKD3D_SHADER_TYPE_COUNT) - { - FIXME("Unknown shader type %#x.\n", version.type); -- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE, -+ vkd3d_shader_warning(message_context, &location, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE, - "Unknown shader type %#x.", version.type); - } - -@@ -6066,10 +6070,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((ret = dxil_block_init(block, NULL, sm6)) < 0) - { - if (ret == VKD3D_ERROR_OUT_OF_MEMORY) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory parsing DXIL bitcode chunk."); - else if (ret == VKD3D_ERROR_INVALID_SHADER) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_BITCODE, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_BITCODE, - "DXIL bitcode chunk has invalid bitcode."); - else - vkd3d_unreachable(); -@@ -6099,10 +6103,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((ret = sm6_parser_type_table_init(sm6)) < 0) - { - if (ret == VKD3D_ERROR_OUT_OF_MEMORY) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory parsing DXIL type table."); - else if (ret == VKD3D_ERROR_INVALID_SHADER) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_TYPE_TABLE, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_TYPE_TABLE, - "DXIL type table is invalid."); - else - vkd3d_unreachable(); -@@ -6112,10 +6116,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((ret = sm6_parser_symtab_init(sm6)) < 0) - { - if (ret == VKD3D_ERROR_OUT_OF_MEMORY) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory parsing DXIL value symbol table."); - else if (ret == VKD3D_ERROR_INVALID_SHADER) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_VALUE_SYMTAB, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_VALUE_SYMTAB, - "DXIL value symbol table is invalid."); - else - vkd3d_unreachable(); -@@ -6126,7 +6130,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - || !(sm6->input_params = shader_parser_get_dst_params(&sm6->p, input_signature->element_count))) - { - ERR("Failed to allocate input/output parameters.\n"); -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory allocating input/output parameters."); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -@@ -6135,7 +6139,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if (!(sm6->functions = vkd3d_calloc(function_count, sizeof(*sm6->functions)))) - { - ERR("Failed to allocate function array.\n"); -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory allocating DXIL function array."); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -@@ -6143,14 +6147,14 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if (sm6_parser_compute_max_value_count(sm6, &sm6->root_block, 0) == SIZE_MAX) - { - WARN("Value array count overflowed.\n"); -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, - "Overflow occurred in the DXIL module value count."); - return VKD3D_ERROR_INVALID_SHADER; - } - if (!(sm6->values = vkd3d_calloc(sm6->value_capacity, sizeof(*sm6->values)))) - { - ERR("Failed to allocate value array.\n"); -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory allocating DXIL value array."); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -@@ -6177,7 +6181,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if (j == ARRAY_SIZE(sm6->metadata_tables)) - { - FIXME("Too many metadata tables.\n"); -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA, - "A metadata table count greater than %zu is unsupported.", ARRAY_SIZE(sm6->metadata_tables)); - return VKD3D_ERROR_INVALID_SHADER; - } -@@ -6195,17 +6199,17 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - if ((ret = sm6_parser_module_init(sm6, &sm6->root_block, 0)) < 0) - { - if (ret == VKD3D_ERROR_OUT_OF_MEMORY) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory parsing DXIL module."); - else if (ret == VKD3D_ERROR_INVALID_SHADER) -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, - "DXIL module is invalid."); - return ret; - } - - if (!sm6_parser_require_space(sm6, output_signature->element_count + input_signature->element_count)) - { -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory emitting shader signature declarations."); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -@@ -6223,7 +6227,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t - assert(sm6->function_count == 1); - if (!sm6_block_emit_instructions(fn->blocks[0], sm6)) - { -- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory emitting shader instructions."); - return VKD3D_ERROR_OUT_OF_MEMORY; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index a0b5ea27698..d38b3c39712 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -63,7 +63,7 @@ static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_i - if (shader_register_is_phase_instance_id(reg)) - { - vsir_register_init(reg, VKD3DSPR_IMMCONST, reg->data_type, 0); -- reg->u.immconst_uint[0] = instance_id; -+ reg->u.immconst_u32[0] = instance_id; - continue; - } - shader_register_eliminate_phase_addressing(reg, instance_id); -@@ -1218,7 +1218,7 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par - param->reg.idx_count = 0; - param->reg.dimension = VSIR_DIMENSION_VEC4; - for (j = 0; j < 4; ++j) -- param->reg.u.immconst_uint[j] = normaliser->defs[i].value[j]; -+ param->reg.u.immconst_u32[j] = normaliser->defs[i].value[j]; - return; - } - } -@@ -1254,7 +1254,7 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d - - get_flat_constant_register_type((struct vkd3d_shader_register *)&ins->dst[0].reg, &def->set, &def->index); - for (j = 0; j < 4; ++j) -- def->value[j] = ins->src[0].reg.u.immconst_uint[j]; -+ def->value[j] = ins->src[0].reg.u.immconst_u32[j]; - - vkd3d_shader_instruction_make_nop(ins); - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 9e3cd7549ba..387784f2358 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -3697,14 +3697,14 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile - if (reg->dimension == VSIR_DIMENSION_SCALAR) - { - for (i = 0; i < component_count; ++i) -- values[i] = *reg->u.immconst_uint; -+ values[i] = *reg->u.immconst_u32; - } - else - { - for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- values[j++] = reg->u.immconst_uint[vsir_swizzle_get_component(swizzle, i)]; -+ values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]; - } - } - -@@ -3724,14 +3724,14 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi - if (reg->dimension == VSIR_DIMENSION_SCALAR) - { - for (i = 0; i < component_count; ++i) -- values[i] = *reg->u.immconst_uint64; -+ values[i] = *reg->u.immconst_u64; - } - else - { - for (i = 0, j = 0; i < VKD3D_DVEC2_SIZE; ++i) - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- values[j++] = reg->u.immconst_uint64[vsir_swizzle_get_component64(swizzle, i)]; -+ values[j++] = reg->u.immconst_u64[vsir_swizzle_get_component64(swizzle, i)]; - } - } - -@@ -7829,7 +7829,7 @@ static int spirv_compiler_emit_control_flow_instruction(struct spirv_compiler *c - "The swizzle for a switch case value is not scalar."); - } - assert(src->reg.type == VKD3DSPR_IMMCONST); -- value = *src->reg.u.immconst_uint; -+ value = *src->reg.u.immconst_u32; - - if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size, - 2 * (cf_info->u.switch_.case_block_count + 1), sizeof(*cf_info->u.switch_.case_blocks))) -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 9508abfb868..f859e758d8e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -1903,19 +1903,19 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - - if (register_type == VKD3D_SM4_RT_IMMCONST || register_type == VKD3D_SM4_RT_IMMCONST64) - { -- unsigned int dword_count; -+ unsigned int u32_count; - - switch (param->dimension) - { - case VSIR_DIMENSION_SCALAR: -- dword_count = 1 + (register_type == VKD3D_SM4_RT_IMMCONST64); -- if (end - *ptr < dword_count) -+ u32_count = 1 + (register_type == VKD3D_SM4_RT_IMMCONST64); -+ if (end - *ptr < u32_count) - { - WARN("Invalid ptr %p, end %p.\n", *ptr, end); - return false; - } -- memcpy(param->u.immconst_uint, *ptr, dword_count * sizeof(DWORD)); -- *ptr += dword_count; -+ memcpy(param->u.immconst_u32, *ptr, u32_count * sizeof(uint32_t)); -+ *ptr += u32_count; - break; - - case VSIR_DIMENSION_VEC4: -@@ -1924,7 +1924,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - WARN("Invalid ptr %p, end %p.\n", *ptr, end); - return false; - } -- memcpy(param->u.immconst_uint, *ptr, VKD3D_VEC4_SIZE * sizeof(DWORD)); -+ memcpy(param->u.immconst_u32, *ptr, VKD3D_VEC4_SIZE * sizeof(uint32_t)); - *ptr += 4; - break; - -@@ -3870,7 +3870,7 @@ static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src, - if (width == 1) - { - src->reg.dimension = VSIR_DIMENSION_SCALAR; -- src->reg.u.immconst_uint[0] = value->u[0].u; -+ src->reg.u.immconst_u32[0] = value->u[0].u; - } - else - { -@@ -3880,9 +3880,9 @@ static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src, - for (i = 0; i < 4; ++i) - { - if ((map_writemask & (1u << i)) && (j < width)) -- src->reg.u.immconst_uint[i] = value->u[j++].u; -+ src->reg.u.immconst_u32[i] = value->u[j++].u; - else -- src->reg.u.immconst_uint[i] = 0; -+ src->reg.u.immconst_u32[i] = 0; - } - } - } -@@ -4077,12 +4077,12 @@ static void sm4_write_src_register(const struct tpf_writer *tpf, const struct vk - - if (src->reg.type == VKD3DSPR_IMMCONST) - { -- put_u32(buffer, src->reg.u.immconst_uint[0]); -+ put_u32(buffer, src->reg.u.immconst_u32[0]); - if (src->reg.dimension == VSIR_DIMENSION_VEC4) - { -- put_u32(buffer, src->reg.u.immconst_uint[1]); -- put_u32(buffer, src->reg.u.immconst_uint[2]); -- put_u32(buffer, src->reg.u.immconst_uint[3]); -+ put_u32(buffer, src->reg.u.immconst_u32[1]); -+ put_u32(buffer, src->reg.u.immconst_u32[2]); -+ put_u32(buffer, src->reg.u.immconst_u32[3]); - } - } - } -@@ -4617,7 +4617,7 @@ static void write_sm4_ld(const struct tpf_writer *tpf, const struct hlsl_ir_node - memset(&instr.srcs[2], 0, sizeof(instr.srcs[2])); - reg->type = VKD3DSPR_IMMCONST; - reg->dimension = VSIR_DIMENSION_SCALAR; -- reg->u.immconst_uint[0] = index->value.u[0].u; -+ reg->u.immconst_u32[0] = index->value.u[0].u; - } - else if (tpf->ctx->profile->major_version == 4 && tpf->ctx->profile->minor_version == 0) - { -@@ -4778,7 +4778,7 @@ static void write_sm4_cast_from_bool(const struct tpf_writer *tpf, const struct - sm4_src_from_node(tpf, &instr.srcs[0], arg, instr.dsts[0].write_mask); - instr.srcs[1].reg.type = VKD3DSPR_IMMCONST; - instr.srcs[1].reg.dimension = VSIR_DIMENSION_SCALAR; -- instr.srcs[1].reg.u.immconst_uint[0] = mask; -+ instr.srcs[1].reg.u.immconst_u32[0] = mask; - instr.src_count = 2; - - write_sm4_instruction(tpf, &instr); -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index caf8a6a4a3e..8fd98d2a551 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -307,6 +307,16 @@ void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const s - vkd3d_string_buffer_printf(&context->messages, "\n"); - } - -+void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, -+ enum vkd3d_shader_error error, const char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ vkd3d_shader_vwarning(context, location, error, format, args); -+ va_end(args); -+} -+ - void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, - enum vkd3d_shader_error error, const char *format, va_list args) - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index ce7d74a72dc..47b245bd7ee 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -841,10 +841,10 @@ struct vkd3d_shader_register - unsigned int alignment; - union - { -- DWORD immconst_uint[VKD3D_VEC4_SIZE]; -- float immconst_float[VKD3D_VEC4_SIZE]; -- uint64_t immconst_uint64[VKD3D_DVEC2_SIZE]; -- double immconst_double[VKD3D_DVEC2_SIZE]; -+ uint32_t immconst_u32[VKD3D_VEC4_SIZE]; -+ float immconst_f32[VKD3D_VEC4_SIZE]; -+ uint64_t immconst_u64[VKD3D_DVEC2_SIZE]; -+ double immconst_f64[VKD3D_DVEC2_SIZE]; - unsigned fp_body_idx; - } u; - }; -@@ -1398,6 +1398,8 @@ void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const str - enum vkd3d_shader_error error, const char *format, va_list args); - void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, - enum vkd3d_shader_log_level level, const char *format, va_list args); -+void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, -+ enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(4, 5); - 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); - -diff --git a/libs/vkd3d/libs/vkd3d/utils.c b/libs/vkd3d/libs/vkd3d/utils.c -index 9b28068be51..5ebe1b63e99 100644 ---- a/libs/vkd3d/libs/vkd3d/utils.c -+++ b/libs/vkd3d/libs/vkd3d/utils.c -@@ -539,6 +539,7 @@ bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) - { - static const D3D_FEATURE_LEVEL valid_feature_levels[] = - { -+ D3D_FEATURE_LEVEL_12_2, - D3D_FEATURE_LEVEL_12_1, - D3D_FEATURE_LEVEL_12_0, - D3D_FEATURE_LEVEL_11_1, -@@ -548,6 +549,7 @@ bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) - D3D_FEATURE_LEVEL_9_3, - D3D_FEATURE_LEVEL_9_2, - D3D_FEATURE_LEVEL_9_1, -+ D3D_FEATURE_LEVEL_1_0_CORE, - }; - unsigned int i; - --- -2.43.0 - diff --git a/patches/vkd3d-latest/0008-Updated-vkd3d-to-50cebc72780dada0822a1d081f3247f7d1d.patch b/patches/vkd3d-latest/0008-Updated-vkd3d-to-50cebc72780dada0822a1d081f3247f7d1d.patch deleted file mode 100644 index 30ef6bb0..00000000 --- a/patches/vkd3d-latest/0008-Updated-vkd3d-to-50cebc72780dada0822a1d081f3247f7d1d.patch +++ /dev/null @@ -1,433 +0,0 @@ -From 4d4c7dc00548735da1f6d446971b74e15a74d106 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Fri, 5 Jan 2024 11:03:00 +1100 -Subject: [PATCH] Updated vkd3d to 50cebc72780dada0822a1d081f3247f7d1dbc728. - ---- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 24 +++- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 1 + - libs/vkd3d/libs/vkd3d-shader/ir.c | 136 ++++++++++++++---- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 9 +- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 2 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 11 +- - libs/vkd3d/libs/vkd3d/utils.c | 12 +- - 7 files changed, 149 insertions(+), 46 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index ca6e3b72de9..8fec1e6371a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -482,9 +482,23 @@ static void shader_sm1_parse_dst_param(uint32_t param, const struct vkd3d_shader - dst->reg.dimension = VSIR_DIMENSION_SCALAR; - else - dst->reg.dimension = VSIR_DIMENSION_VEC4; -- dst->write_mask = (param & VKD3D_SM1_WRITEMASK_MASK) >> VKD3D_SM1_WRITEMASK_SHIFT; - dst->modifiers = (param & VKD3D_SM1_DST_MODIFIER_MASK) >> VKD3D_SM1_DST_MODIFIER_SHIFT; - dst->shift = (param & VKD3D_SM1_DSTSHIFT_MASK) >> VKD3D_SM1_DSTSHIFT_SHIFT; -+ -+ switch (dst->reg.dimension) -+ { -+ case VSIR_DIMENSION_SCALAR: -+ dst->write_mask = VKD3DSP_WRITEMASK_0; -+ break; -+ -+ case VSIR_DIMENSION_VEC4: -+ dst->write_mask = (param & VKD3D_SM1_WRITEMASK_MASK) >> VKD3D_SM1_WRITEMASK_SHIFT; -+ break; -+ -+ default: -+ dst->write_mask = 0; -+ break; -+ } - } - - static struct signature_element *find_signature_element(const struct shader_signature *signature, -@@ -518,8 +532,6 @@ static struct signature_element *find_signature_element_by_register_index( - return NULL; - } - --#define SM1_COLOR_REGISTER_OFFSET 8 -- - static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool output, - const char *name, unsigned int index, enum vkd3d_shader_sysval_semantic sysval, - unsigned int register_index, bool is_dcl, unsigned int mask) -@@ -647,15 +659,15 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * - { - case 0: - return add_signature_element(sm1, true, "POSITION", 0, -- VKD3D_SHADER_SV_POSITION, register_index, is_dcl, mask); -+ VKD3D_SHADER_SV_POSITION, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, mask); - - case 1: - return add_signature_element(sm1, true, "FOG", 0, -- VKD3D_SHADER_SV_NONE, register_index, is_dcl, 0x1); -+ VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1); - - case 2: - return add_signature_element(sm1, true, "PSIZE", 0, -- VKD3D_SHADER_SV_NONE, register_index, is_dcl, 0x1); -+ VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1); - - default: - vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX, -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 2424b176068..c744dfcedf0 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -3432,6 +3432,7 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, struct sm6_ - /* Set idx_count to 3 for use with load instructions. - * TODO: set register type from resource type when other types are supported. */ - vsir_register_init(reg, VKD3DSPR_CONSTBUFFER, VKD3D_DATA_FLOAT, 3); -+ reg->dimension = VSIR_DIMENSION_VEC4; - reg->idx[0].offset = id; - register_index_address_init(®->idx[1], operands[2], sm6); - reg->non_uniform = !!sm6_value_get_constant_uint(operands[3]); -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index d38b3c39712..bac4269198b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -533,6 +533,7 @@ struct io_normaliser - { - struct vkd3d_shader_instruction_array instructions; - enum vkd3d_shader_type shader_type; -+ uint8_t major; - struct shader_signature *input_signature; - struct shader_signature *output_signature; - struct shader_signature *patch_constant_signature; -@@ -867,34 +868,65 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par - const struct shader_signature *signature; - const struct signature_element *e; - -- if ((reg->type == VKD3DSPR_OUTPUT && io_normaliser_is_in_fork_or_join_phase(normaliser)) -- || reg->type == VKD3DSPR_PATCHCONST) -- { -- signature = normaliser->patch_constant_signature; -- /* Convert patch constant outputs to the patch constant register type to avoid the need -- * to convert compiler symbols when accessed as inputs in a later stage. */ -- reg->type = VKD3DSPR_PATCHCONST; -- dcl_params = normaliser->pc_dcl_params; -- } -- else if (reg->type == VKD3DSPR_OUTPUT || dst_param->reg.type == VKD3DSPR_COLOROUT) -- { -- signature = normaliser->output_signature; -- reg->type = VKD3DSPR_OUTPUT; -- dcl_params = normaliser->output_dcl_params; -- } -- else if (dst_param->reg.type == VKD3DSPR_INCONTROLPOINT || dst_param->reg.type == VKD3DSPR_INPUT) -- { -- signature = normaliser->input_signature; -- reg->type = VKD3DSPR_INPUT; -- dcl_params = normaliser->input_dcl_params; -- } -- else -+ switch (reg->type) - { -- return true; -+ case VKD3DSPR_OUTPUT: -+ reg_idx = reg->idx[reg->idx_count - 1].offset; -+ if (io_normaliser_is_in_fork_or_join_phase(normaliser)) -+ { -+ signature = normaliser->patch_constant_signature; -+ /* Convert patch constant outputs to the patch constant register type to avoid the need -+ * to convert compiler symbols when accessed as inputs in a later stage. */ -+ reg->type = VKD3DSPR_PATCHCONST; -+ dcl_params = normaliser->pc_dcl_params; -+ } -+ else -+ { -+ signature = normaliser->output_signature; -+ dcl_params = normaliser->output_dcl_params; -+ } -+ break; -+ -+ case VKD3DSPR_PATCHCONST: -+ reg_idx = reg->idx[reg->idx_count - 1].offset; -+ signature = normaliser->patch_constant_signature; -+ dcl_params = normaliser->pc_dcl_params; -+ break; -+ -+ case VKD3DSPR_COLOROUT: -+ reg_idx = reg->idx[0].offset; -+ signature = normaliser->output_signature; -+ reg->type = VKD3DSPR_OUTPUT; -+ dcl_params = normaliser->output_dcl_params; -+ break; -+ -+ case VKD3DSPR_INCONTROLPOINT: -+ case VKD3DSPR_INPUT: -+ reg_idx = reg->idx[reg->idx_count - 1].offset; -+ signature = normaliser->input_signature; -+ reg->type = VKD3DSPR_INPUT; -+ dcl_params = normaliser->input_dcl_params; -+ break; -+ -+ case VKD3DSPR_ATTROUT: -+ reg_idx = SM1_COLOR_REGISTER_OFFSET + reg->idx[0].offset; -+ signature = normaliser->output_signature; -+ reg->type = VKD3DSPR_OUTPUT; -+ dcl_params = normaliser->output_dcl_params; -+ break; -+ -+ case VKD3DSPR_RASTOUT: -+ reg_idx = SM1_RASTOUT_REGISTER_OFFSET + reg->idx[0].offset; -+ signature = normaliser->output_signature; -+ reg->type = VKD3DSPR_OUTPUT; -+ dcl_params = normaliser->output_dcl_params; -+ break; -+ -+ default: -+ return true; - } - - id_idx = reg->idx_count - 1; -- reg_idx = reg->idx[id_idx].offset; - write_mask = dst_param->write_mask; - element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); - e = &signature->elements[element_idx]; -@@ -982,26 +1014,42 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par - switch (reg->type) - { - case VKD3DSPR_PATCHCONST: -+ reg_idx = reg->idx[reg->idx_count - 1].offset; - signature = normaliser->patch_constant_signature; - break; -+ - case VKD3DSPR_INCONTROLPOINT: - reg->type = VKD3DSPR_INPUT; - /* fall through */ - case VKD3DSPR_INPUT: -+ if (normaliser->major < 3 && normaliser->shader_type == VKD3D_SHADER_TYPE_PIXEL) -+ reg_idx = SM1_COLOR_REGISTER_OFFSET + reg->idx[0].offset; -+ else -+ reg_idx = reg->idx[reg->idx_count - 1].offset; - signature = normaliser->input_signature; - break; -+ - case VKD3DSPR_OUTCONTROLPOINT: - reg->type = VKD3DSPR_OUTPUT; - /* fall through */ - case VKD3DSPR_OUTPUT: -+ reg_idx = reg->idx[reg->idx_count - 1].offset; - signature = normaliser->output_signature; - break; -+ -+ case VKD3DSPR_TEXTURE: -+ if (normaliser->shader_type != VKD3D_SHADER_TYPE_PIXEL) -+ return; -+ reg->type = VKD3DSPR_INPUT; -+ reg_idx = reg->idx[0].offset; -+ signature = normaliser->input_signature; -+ break; -+ - default: - return; - } - - id_idx = reg->idx_count - 1; -- reg_idx = reg->idx[id_idx].offset; - write_mask = VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(src_param->swizzle, 0); - element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); - -@@ -1084,6 +1132,7 @@ static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parse - - normaliser.phase = VKD3DSIH_INVALID; - normaliser.shader_type = parser->shader_version.type; -+ normaliser.major = parser->shader_version.major; - normaliser.input_signature = &parser->shader_desc.input_signature; - normaliser.output_signature = &parser->shader_desc.output_signature; - normaliser.patch_constant_signature = &parser->shader_desc.patch_constant_signature; -@@ -1555,6 +1604,19 @@ static void vsir_validate_register(struct validation_context *ctx, - reg->idx[0].offset, temp_count); - break; - -+ case VKD3DSPR_SSA: -+ 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); -+ -+ if (reg->idx_count >= 1 && 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_count >= 1 && reg->idx[0].offset >= ctx->parser->shader_desc.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->parser->shader_desc.ssa_count); -+ 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.", -@@ -1587,6 +1649,26 @@ static void vsir_validate_dst_param(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Destination has invalid write mask %#x.", - dst->write_mask); - -+ switch (dst->reg.dimension) -+ { -+ case VSIR_DIMENSION_SCALAR: -+ if (dst->write_mask != VKD3DSP_WRITEMASK_0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Scalar destination has invalid write mask %#x.", -+ dst->write_mask); -+ break; -+ -+ case VSIR_DIMENSION_VEC4: -+ if (dst->write_mask == 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Vec4 destination has empty write mask."); -+ break; -+ -+ default: -+ if (dst->write_mask != 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Destination of dimension %u has invalid write mask %#x.", -+ dst->reg.dimension, dst->write_mask); -+ break; -+ } -+ - if (dst->modifiers & ~VKD3DSPDM_MASK) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Destination has invalid modifiers %#x.", - dst->modifiers); -@@ -1617,6 +1699,10 @@ static void vsir_validate_src_param(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source has invalid swizzle %#x.", - src->swizzle); - -+ if (src->reg.dimension != VSIR_DIMENSION_VEC4 && src->swizzle != 0) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source of dimension %u has invalid swizzle %#x.", -+ src->reg.dimension, src->swizzle); -+ - if (src->modifiers >= VKD3DSPSM_COUNT) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", - src->modifiers); -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 387784f2358..a5565d552c0 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -3600,8 +3600,7 @@ static uint32_t spirv_compiler_get_register_id(struct spirv_compiler *compiler, - SpvStorageClassPrivate, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); - } - --static bool vkd3d_swizzle_is_equal(unsigned int dst_write_mask, -- unsigned int swizzle, unsigned int write_mask) -+static bool vkd3d_swizzle_is_equal(uint32_t dst_write_mask, uint32_t swizzle, uint32_t write_mask) - { - return vkd3d_compact_swizzle(VKD3D_SHADER_NO_SWIZZLE, dst_write_mask) == vkd3d_compact_swizzle(swizzle, write_mask); - } -@@ -3913,7 +3912,7 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler - } - - static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask) -+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - enum vkd3d_shader_component_type component_type; -@@ -4209,7 +4208,7 @@ static void spirv_compiler_emit_store_dst(struct spirv_compiler *compiler, - - static void spirv_compiler_emit_store_dst_swizzled(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst, uint32_t val_id, -- enum vkd3d_shader_component_type component_type, DWORD swizzle) -+ enum vkd3d_shader_component_type component_type, uint32_t swizzle) - { - struct vkd3d_shader_dst_param typed_dst = *dst; - val_id = spirv_compiler_emit_swizzle(compiler, -@@ -9420,9 +9419,9 @@ static void spirv_compiler_emit_sync(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { - unsigned int memory_semantics = SpvMemorySemanticsAcquireReleaseMask; -- unsigned int flags = instruction->flags; - SpvScope execution_scope = SpvScopeMax; - SpvScope memory_scope = SpvScopeDevice; -+ uint32_t flags = instruction->flags; - - if (flags & VKD3DSSF_GROUP_SHARED_MEMORY) - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index f859e758d8e..2cc56663efe 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -5488,7 +5488,7 @@ static void write_sm4_loop(const struct tpf_writer *tpf, const struct hlsl_ir_lo - - static void write_sm4_gather(const struct tpf_writer *tpf, const struct hlsl_ir_node *dst, - const struct hlsl_deref *resource, const struct hlsl_deref *sampler, -- const struct hlsl_ir_node *coords, DWORD swizzle, const struct hlsl_ir_node *texel_offset) -+ const struct hlsl_ir_node *coords, uint32_t swizzle, const struct hlsl_ir_node *texel_offset) - { - struct vkd3d_shader_src_param *src; - struct sm4_instruction instr; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 47b245bd7ee..224d27f4e1b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -871,14 +871,14 @@ struct vkd3d_shader_dst_param - { - struct vkd3d_shader_register reg; - uint32_t write_mask; -- DWORD modifiers; -- DWORD shift; -+ uint32_t modifiers; -+ unsigned int shift; - }; - - struct vkd3d_shader_src_param - { - struct vkd3d_shader_register reg; -- DWORD swizzle; -+ uint32_t swizzle; - enum vkd3d_shader_src_modifier modifiers; - }; - -@@ -955,6 +955,9 @@ enum vkd3d_shader_input_sysval_semantic - VKD3D_SIV_LINE_DENSITY_TESS_FACTOR = 22, - }; - -+#define SM1_COLOR_REGISTER_OFFSET 8 -+#define SM1_RASTOUT_REGISTER_OFFSET 10 -+ - #define SIGNATURE_TARGET_LOCATION_UNUSED (~0u) - - struct signature_element -@@ -1120,7 +1123,7 @@ struct vkd3d_shader_instruction - { - struct vkd3d_shader_location location; - enum vkd3d_shader_opcode handler_idx; -- DWORD flags; -+ uint32_t flags; - unsigned int dst_count; - unsigned int src_count; - const struct vkd3d_shader_dst_param *dst; -diff --git a/libs/vkd3d/libs/vkd3d/utils.c b/libs/vkd3d/libs/vkd3d/utils.c -index 5ebe1b63e99..751971220e7 100644 ---- a/libs/vkd3d/libs/vkd3d/utils.c -+++ b/libs/vkd3d/libs/vkd3d/utils.c -@@ -683,7 +683,7 @@ const char *debug_vk_extent_3d(VkExtent3D extent) - - const char *debug_vk_queue_flags(VkQueueFlags flags) - { -- char buffer[120]; -+ char buffer[159]; - - buffer[0] = '\0'; - #define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; } -@@ -691,6 +691,10 @@ const char *debug_vk_queue_flags(VkQueueFlags flags) - FLAG_TO_STR(VK_QUEUE_COMPUTE_BIT) - FLAG_TO_STR(VK_QUEUE_TRANSFER_BIT) - FLAG_TO_STR(VK_QUEUE_SPARSE_BINDING_BIT) -+ FLAG_TO_STR(VK_QUEUE_PROTECTED_BIT) -+#undef FLAG_TO_STR -+#define FLAG_TO_STR(f, n) if (flags & f) { strcat(buffer, " | "#n); flags &= ~f; } -+ FLAG_TO_STR(0x20, VK_QUEUE_VIDEO_DECODE_BIT_KHR) - #undef FLAG_TO_STR - if (flags) - FIXME("Unrecognized flag(s) %#x.\n", flags); -@@ -729,10 +733,8 @@ const char *debug_vk_memory_property_flags(VkMemoryPropertyFlags flags) - FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_CACHED_BIT) - FLAG_TO_STR(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) - FLAG_TO_STR(VK_MEMORY_PROPERTY_PROTECTED_BIT) --#undef FLAG_TO_STR --#define FLAG_TO_STR(f, n) if (flags & f) { strcat(buffer, " | "#n); flags &= ~f; } -- FLAG_TO_STR(0x40, VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD) -- FLAG_TO_STR(0x80, VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD) -+ FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD) -+ FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD) - #undef FLAG_TO_STR - if (flags) - FIXME("Unrecognized flag(s) %#x.\n", flags); --- -2.43.0 - diff --git a/patches/vkd3d-latest/0009-Updated-vkd3d-to-bb64bfff6334c847d06d219840882ec7576.patch b/patches/vkd3d-latest/0009-Updated-vkd3d-to-bb64bfff6334c847d06d219840882ec7576.patch deleted file mode 100644 index a04dde27..00000000 --- a/patches/vkd3d-latest/0009-Updated-vkd3d-to-bb64bfff6334c847d06d219840882ec7576.patch +++ /dev/null @@ -1,636 +0,0 @@ -From ce0a7dcf546461d3aa2bad522274f09def0e8daa Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Wed, 10 Jan 2024 07:40:09 +1100 -Subject: [PATCH] Updated vkd3d to bb64bfff6334c847d06d219840882ec75766b330. - ---- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 22 +++--- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 22 +++--- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 31 ++++----- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 22 +++--- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 15 ++++- - libs/vkd3d/libs/vkd3d/command.c | 3 +- - libs/vkd3d/libs/vkd3d/resource.c | 74 ++++++++++++++++----- - 7 files changed, 125 insertions(+), 64 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index da3bbda1bc3..a41967876a2 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -920,7 +920,7 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 - } - - struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, -- unsigned int default_majority, unsigned int modifiers) -+ unsigned int default_majority, uint32_t modifiers) - { - struct hlsl_type *type; - -@@ -1030,7 +1030,7 @@ struct hlsl_ir_node *hlsl_new_copy(struct hlsl_ctx *ctx, struct hlsl_ir_node *no - } - - struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type, -- const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, unsigned int modifiers, -+ const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, uint32_t modifiers, - const struct hlsl_reg_reservation *reg_reservation) - { - struct hlsl_ir_var *var; -@@ -1505,7 +1505,7 @@ struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct - return &store->node; - } - --struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components, -+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_swizzle *swizzle; -@@ -2246,7 +2246,7 @@ const char *debug_hlsl_type(struct hlsl_ctx *ctx, const struct hlsl_type *type) - return ret; - } - --struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, unsigned int modifiers) -+struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, uint32_t modifiers) - { - struct vkd3d_string_buffer *string; - -@@ -2432,7 +2432,7 @@ const char *debug_hlsl_writemask(unsigned int writemask) - return vkd3d_dbg_sprintf(".%s", string); - } - --const char *debug_hlsl_swizzle(unsigned int swizzle, unsigned int size) -+const char *debug_hlsl_swizzle(uint32_t swizzle, unsigned int size) - { - static const char components[] = {'x', 'y', 'z', 'w'}; - char string[5]; -@@ -3147,9 +3147,10 @@ void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function - rb_put(&ctx->functions, func->name, &func->entry); - } - --unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask) -+uint32_t hlsl_map_swizzle(uint32_t swizzle, unsigned int writemask) - { -- unsigned int i, ret = 0; -+ uint32_t ret = 0; -+ unsigned int i; - - /* Leave replicate swizzles alone; some instructions need them. */ - if (swizzle == HLSL_SWIZZLE(X, X, X, X) -@@ -3169,7 +3170,7 @@ unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask) - return ret; - } - --unsigned int hlsl_swizzle_from_writemask(unsigned int writemask) -+uint32_t hlsl_swizzle_from_writemask(unsigned int writemask) - { - static const unsigned int swizzles[16] = - { -@@ -3210,9 +3211,10 @@ unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second) - return ret; - } - --unsigned int hlsl_combine_swizzles(unsigned int first, unsigned int second, unsigned int dim) -+uint32_t hlsl_combine_swizzles(uint32_t first, uint32_t second, unsigned int dim) - { -- unsigned int ret = 0, i; -+ uint32_t ret = 0; -+ unsigned int i; - for (i = 0; i < dim; ++i) - { - unsigned int s = hlsl_swizzle_get_component(second, i); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index ca75a1936f1..b56dea10f4c 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -65,7 +65,7 @@ - #define HLSL_SWIZZLE_MASK (0x3u) - #define HLSL_SWIZZLE_SHIFT(idx) (2u * (idx)) - --static inline unsigned int hlsl_swizzle_get_component(unsigned int swizzle, unsigned int idx) -+static inline unsigned int hlsl_swizzle_get_component(uint32_t swizzle, unsigned int idx) - { - return (swizzle >> HLSL_SWIZZLE_SHIFT(idx)) & HLSL_SWIZZLE_MASK; - } -@@ -155,7 +155,7 @@ struct hlsl_type - /* Bitfield for storing type modifiers, subset of HLSL_TYPE_MODIFIERS_MASK. - * Modifiers that don't fall inside this mask are to be stored in the variable in - * hlsl_ir_var.modifiers, or in the struct field in hlsl_ir_field.modifiers. */ -- unsigned int modifiers; -+ uint32_t modifiers; - /* Size of the type values on each dimension. For non-numeric types, they are set for the - * convenience of the sm1/sm4 backends. - * If type is HLSL_CLASS_SCALAR, then both dimx = 1 and dimy = 1. -@@ -234,7 +234,7 @@ struct hlsl_struct_field - /* Bitfield for storing modifiers that are not in HLSL_TYPE_MODIFIERS_MASK (these are stored in - * type->modifiers instead) and that also are specific to the field and not the whole variable. - * In particular, interpolation modifiers. */ -- unsigned int storage_modifiers; -+ uint32_t storage_modifiers; - /* Offset of the field within the type it belongs to, in register components, for each regset. */ - unsigned int reg_offset[HLSL_REGSET_LAST + 1]; - -@@ -392,7 +392,7 @@ struct hlsl_ir_var - /* Buffer where the variable's value is stored, in case it is uniform. */ - struct hlsl_buffer *buffer; - /* Bitfield for storage modifiers (type modifiers are stored in data_type->modifiers). */ -- unsigned int storage_modifiers; -+ uint32_t storage_modifiers; - /* Optional reservations of registers and/or offsets for variables within constant buffers. */ - struct hlsl_reg_reservation reg_reservation; - -@@ -622,7 +622,7 @@ struct hlsl_ir_swizzle - { - struct hlsl_ir_node node; - struct hlsl_src val; -- DWORD swizzle; -+ uint32_t swizzle; - }; - - struct hlsl_ir_index -@@ -1250,7 +1250,7 @@ struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct - struct hlsl_ir_node *coords, struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc); - 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, DWORD s, unsigned int components, -+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_var *hlsl_new_synthetic_var(struct hlsl_ctx *ctx, const char *template, - struct hlsl_type *type, const struct vkd3d_shader_location *loc); -@@ -1264,7 +1264,7 @@ struct hlsl_ir_node *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n - struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, - const struct vkd3d_shader_location *loc); - struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type, -- const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, unsigned int modifiers, -+ const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, uint32_t modifiers, - const struct hlsl_reg_reservation *reg_reservation); - struct hlsl_ir_switch_case *hlsl_new_switch_case(struct hlsl_ctx *ctx, unsigned int value, bool is_default, - struct hlsl_block *body, const struct vkd3d_shader_location *loc); -@@ -1286,7 +1286,7 @@ void hlsl_pop_scope(struct hlsl_ctx *ctx); - bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type); - - struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, -- unsigned int default_majority, unsigned int modifiers); -+ unsigned int default_majority, uint32_t modifiers); - unsigned int hlsl_type_component_count(const struct hlsl_type *type); - unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type, enum hlsl_regset regset); - struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type, -@@ -1304,10 +1304,10 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 - const struct hlsl_type *hlsl_get_multiarray_element_type(const struct hlsl_type *type); - unsigned int hlsl_get_multiarray_size(const struct hlsl_type *type); - --unsigned int hlsl_combine_swizzles(unsigned int first, unsigned int second, unsigned int dim); -+uint32_t hlsl_combine_swizzles(uint32_t first, uint32_t second, unsigned int dim); - unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second); --unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask); --unsigned int hlsl_swizzle_from_writemask(unsigned int writemask); -+uint32_t hlsl_map_swizzle(uint32_t swizzle, unsigned int writemask); -+uint32_t hlsl_swizzle_from_writemask(unsigned int writemask); - - struct hlsl_type *hlsl_deref_get_type(struct hlsl_ctx *ctx, const struct hlsl_deref *deref); - enum hlsl_regset hlsl_deref_get_regset(struct hlsl_ctx *ctx, const struct hlsl_deref *deref); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index ed053f16312..26f9357419b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -40,7 +40,7 @@ struct parse_parameter - const char *name; - struct hlsl_semantic semantic; - struct hlsl_reg_reservation reg_reservation; -- unsigned int modifiers; -+ uint32_t modifiers; - }; - - struct parse_colon_attribute -@@ -75,7 +75,7 @@ struct parse_variable_def - struct parse_initializer initializer; - - struct hlsl_type *basic_type; -- unsigned int modifiers; -+ uint32_t modifiers; - struct vkd3d_shader_location modifiers_loc; - }; - -@@ -405,7 +405,7 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct - return add_cast(ctx, block, node, dst_type, loc); - } - --static DWORD add_modifiers(struct hlsl_ctx *ctx, DWORD modifiers, DWORD mod, -+static uint32_t add_modifiers(struct hlsl_ctx *ctx, uint32_t modifiers, uint32_t mod, - const struct vkd3d_shader_location *loc) - { - if (modifiers & mod) -@@ -868,7 +868,7 @@ static const struct hlsl_struct_field *get_struct_field(const struct hlsl_struct - } - - static struct hlsl_type *apply_type_modifiers(struct hlsl_ctx *ctx, struct hlsl_type *type, -- unsigned int *modifiers, bool force_majority, const struct vkd3d_shader_location *loc) -+ uint32_t *modifiers, bool force_majority, const struct vkd3d_shader_location *loc) - { - unsigned int default_majority = 0; - struct hlsl_type *new_type; -@@ -926,7 +926,7 @@ static bool shader_profile_version_lt(const struct hlsl_ctx *ctx, unsigned int m - } - - static bool gen_struct_fields(struct hlsl_ctx *ctx, struct parse_fields *fields, -- struct hlsl_type *type, unsigned int modifiers, struct list *defs) -+ struct hlsl_type *type, uint32_t modifiers, struct list *defs) - { - struct parse_variable_def *v, *v_next; - size_t i = 0; -@@ -1019,7 +1019,7 @@ static bool add_typedef(struct hlsl_ctx *ctx, struct hlsl_type *const orig_type, - } - else - { -- unsigned int var_modifiers = 0; -+ uint32_t var_modifiers = 0; - - if (!(type = apply_type_modifiers(ctx, orig_type, &var_modifiers, true, &v->loc))) - { -@@ -1717,7 +1717,7 @@ static enum hlsl_ir_expr_op op_from_assignment(enum parse_assign_op op) - return ops[op]; - } - --static bool invert_swizzle(unsigned int *swizzle, unsigned int *writemask, unsigned int *ret_width) -+static bool invert_swizzle(uint32_t *swizzle, unsigned int *writemask, unsigned int *ret_width) - { - unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0, new_swizzle = 0; - -@@ -1791,8 +1791,9 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo - else if (lhs->type == HLSL_IR_SWIZZLE) - { - struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(lhs); -- unsigned int width, s = swizzle->swizzle; - struct hlsl_ir_node *new_swizzle; -+ uint32_t s = swizzle->swizzle; -+ unsigned int width; - - if (lhs->data_type->class == HLSL_CLASS_MATRIX) - hlsl_fixme(ctx, &lhs->loc, "Matrix assignment with a writemask."); -@@ -4844,7 +4845,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls - FLOAT floatval; - bool boolval; - char *name; -- DWORD modifiers; -+ uint32_t modifiers; - struct hlsl_ir_node *instr; - struct hlsl_block *block; - struct list *list; -@@ -5282,7 +5283,7 @@ field: - var_modifiers field_type variables_def ';' - { - struct hlsl_type *type; -- unsigned int modifiers = $1; -+ uint32_t modifiers = $1; - - if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) - YYABORT; -@@ -5435,7 +5436,7 @@ func_prototype_no_attrs: - /* var_modifiers is necessary to avoid shift/reduce conflicts. */ - var_modifiers type var_identifier '(' parameters ')' colon_attribute - { -- unsigned int modifiers = $1; -+ uint32_t modifiers = $1; - struct hlsl_ir_var *var; - struct hlsl_type *type; - -@@ -5709,7 +5710,7 @@ param_list: - parameter: - var_modifiers type_no_void any_identifier arrays colon_attribute - { -- unsigned int modifiers = $1; -+ uint32_t modifiers = $1; - struct hlsl_type *type; - unsigned int i; - -@@ -6023,7 +6024,7 @@ typedef: - KW_TYPEDEF var_modifiers typedef_type type_specs ';' - { - struct parse_variable_def *v, *v_next; -- unsigned int modifiers = $2; -+ uint32_t modifiers = $2; - struct hlsl_type *type; - - if (!(type = apply_type_modifiers(ctx, $3, &modifiers, false, &@2))) -@@ -6160,7 +6161,7 @@ variable_def: - variable_def_typed: - var_modifiers struct_spec variable_def - { -- unsigned int modifiers = $1; -+ uint32_t modifiers = $1; - struct hlsl_type *type; - - if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) -@@ -6175,7 +6176,7 @@ variable_def_typed: - } - | var_modifiers type variable_def - { -- unsigned int modifiers = $1; -+ uint32_t modifiers = $1; - struct hlsl_type *type; - - if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 88cbef61d5f..acc19dd8ba5 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -263,7 +263,7 @@ static bool types_are_semantic_equivalent(struct hlsl_ctx *ctx, const struct hls - } - - static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, -- struct hlsl_type *type, unsigned int modifiers, struct hlsl_semantic *semantic, -+ struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic, - uint32_t index, bool output, const struct vkd3d_shader_location *loc) - { - struct hlsl_semantic new_semantic; -@@ -331,7 +331,7 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir - } - - static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *lhs, -- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) -+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) - { - struct hlsl_type *type = lhs->node.data_type, *vector_type_src, *vector_type_dst; - struct vkd3d_shader_location *loc = &lhs->node.loc; -@@ -395,7 +395,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, s - } - - static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *lhs, -- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) -+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) - { - struct vkd3d_shader_location *loc = &lhs->node.loc; - struct hlsl_type *type = lhs->node.data_type; -@@ -411,7 +411,7 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * - - for (i = 0; i < hlsl_type_element_count(type); ++i) - { -- unsigned int element_modifiers = modifiers; -+ uint32_t element_modifiers = modifiers; - - if (type->class == HLSL_CLASS_ARRAY) - { -@@ -473,7 +473,7 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_block *bloc - } - - static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *rhs, -- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) -+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) - { - struct hlsl_type *type = rhs->node.data_type, *vector_type; - struct vkd3d_shader_location *loc = &rhs->node.loc; -@@ -529,7 +529,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, s - } - - static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *rhs, -- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) -+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index) - { - struct vkd3d_shader_location *loc = &rhs->node.loc; - struct hlsl_type *type = rhs->node.data_type; -@@ -1519,7 +1519,7 @@ static void copy_propagation_set_value(struct hlsl_ctx *ctx, struct copy_propaga - - static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx, - const struct copy_propagation_state *state, const struct hlsl_ir_load *load, -- unsigned int swizzle, struct hlsl_ir_node *instr) -+ uint32_t swizzle, struct hlsl_ir_node *instr) - { - const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type); - const struct hlsl_deref *deref = &load->src; -@@ -1527,7 +1527,7 @@ static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx, - struct hlsl_ir_node *new_instr = NULL; - unsigned int time = load->node.index; - unsigned int start, count, i; -- unsigned int ret_swizzle = 0; -+ uint32_t ret_swizzle = 0; - - if (!hlsl_component_index_range_from_deref(ctx, deref, &start, &count)) - return false; -@@ -1573,7 +1573,7 @@ static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx, - - static bool copy_propagation_replace_with_constant_vector(struct hlsl_ctx *ctx, - const struct copy_propagation_state *state, const struct hlsl_ir_load *load, -- unsigned int swizzle, struct hlsl_ir_node *instr) -+ uint32_t swizzle, struct hlsl_ir_node *instr) - { - const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type); - const struct hlsl_deref *deref = &load->src; -@@ -2239,7 +2239,7 @@ static bool fold_swizzle_chains(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr - if (next_instr->type == HLSL_IR_SWIZZLE) - { - struct hlsl_ir_node *new_swizzle; -- unsigned int combined_swizzle; -+ uint32_t combined_swizzle; - - combined_swizzle = hlsl_combine_swizzles(hlsl_ir_swizzle(next_instr)->swizzle, - swizzle->swizzle, instr->data_type->dimx); -@@ -3145,7 +3145,7 @@ static bool lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru - - for (i = 0; i < dimx; ++i) - { -- unsigned int s = hlsl_swizzle_from_writemask(1 << i); -+ uint32_t s = hlsl_swizzle_from_writemask(1 << i); - - if (!(comps[i] = hlsl_new_swizzle(ctx, s, 1, mult, &instr->loc))) - return false; -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index a5565d552c0..987197887de 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -1764,6 +1764,15 @@ static uint32_t vkd3d_spirv_build_op_glsl_std450_max(struct vkd3d_spirv_builder - GLSLstd450NMax, operands, ARRAY_SIZE(operands)); - } - -+static uint32_t vkd3d_spirv_build_op_glsl_std450_umin(struct vkd3d_spirv_builder *builder, -+ uint32_t result_type, uint32_t x, uint32_t y) -+{ -+ uint32_t glsl_std450_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); -+ uint32_t operands[] = {x, y}; -+ return vkd3d_spirv_build_op_ext_inst(builder, result_type, glsl_std450_id, -+ GLSLstd450UMin, operands, ARRAY_SIZE(operands)); -+} -+ - static uint32_t vkd3d_spirv_build_op_glsl_std450_nclamp(struct vkd3d_spirv_builder *builder, - uint32_t result_type, uint32_t x, uint32_t min, uint32_t max) - { -@@ -7355,7 +7364,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, - static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { -- uint32_t src_ids[4], constituents[VKD3D_VEC4_SIZE], type_id, mask_id; -+ uint32_t src_ids[4], constituents[VKD3D_VEC4_SIZE], type_id, mask_id, size_id, max_count_id; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_dst_param *dst = instruction->dst; - const struct vkd3d_shader_src_param *src = instruction->src; -@@ -7370,6 +7379,7 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp - component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); - mask_id = spirv_compiler_get_constant_uint(compiler, 0x1f); -+ size_id = spirv_compiler_get_constant_uint(compiler, 0x20); - - switch (instruction->handler_idx) - { -@@ -7398,6 +7408,9 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp - { - src_ids[j] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[j], mask_id); - } -+ max_count_id = vkd3d_spirv_build_op_isub(builder, type_id, size_id, src_ids[src_count - 2]); -+ src_ids[src_count - 1] = vkd3d_spirv_build_op_glsl_std450_umin(builder, type_id, -+ src_ids[src_count - 1], max_count_id); - - constituents[k++] = vkd3d_spirv_build_op_trv(builder, &builder->function_stream, - op, type_id, src_ids, src_count); -diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c -index 549f6a45ffb..013b5d0751f 100644 ---- a/libs/vkd3d/libs/vkd3d/command.c -+++ b/libs/vkd3d/libs/vkd3d/command.c -@@ -6512,7 +6512,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12Command - if (!(op = d3d12_command_queue_op_array_require_space(&command_queue->op_queue))) - { - ERR("Failed to add op.\n"); -- return; -+ goto unlock_mutex; - } - op->opcode = VKD3D_CS_OP_COPY_MAPPINGS; - op->u.copy_mappings.dst_resource = dst_resource_impl; -@@ -6524,6 +6524,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12Command - - d3d12_command_queue_submit_locked(command_queue); - -+unlock_mutex: - vkd3d_mutex_unlock(&command_queue->op_mutex); - } - -diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c -index 609c67102a6..f4ce1ccaffa 100644 ---- a/libs/vkd3d/libs/vkd3d/resource.c -+++ b/libs/vkd3d/libs/vkd3d/resource.c -@@ -3444,6 +3444,7 @@ static void vkd3d_create_null_uav(struct d3d12_desc *descriptor, - vkd3d_desc.miplevel_count = 1; - vkd3d_desc.layer_idx = 0; - vkd3d_desc.layer_count = 1; -+ vkd3d_desc.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT; - vkd3d_desc.components.r = VK_COMPONENT_SWIZZLE_R; - vkd3d_desc.components.g = VK_COMPONENT_SWIZZLE_G; - vkd3d_desc.components.b = VK_COMPONENT_SWIZZLE_B; -@@ -3661,11 +3662,27 @@ static VkSamplerAddressMode vk_address_mode_from_d3d12(const struct d3d12_device - } - } - -+static VkBorderColor vk_border_colour_from_d3d12(D3D12_STATIC_BORDER_COLOR colour) -+{ -+ switch (colour) -+ { -+ case D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK: -+ return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; -+ case D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK: -+ return VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK; -+ case D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE: -+ return VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; -+ default: -+ FIXME("Unhandled border colour %#x.\n", colour); -+ return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; -+ } -+} -+ - static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER filter, - D3D12_TEXTURE_ADDRESS_MODE address_u, D3D12_TEXTURE_ADDRESS_MODE address_v, - D3D12_TEXTURE_ADDRESS_MODE address_w, float mip_lod_bias, unsigned int max_anisotropy, -- D3D12_COMPARISON_FUNC comparison_func, float min_lod, float max_lod, -- VkSampler *vk_sampler) -+ D3D12_COMPARISON_FUNC comparison_func, D3D12_STATIC_BORDER_COLOR border_colour, -+ float min_lod, float max_lod, VkSampler *vk_sampler) - { - const struct vkd3d_vk_device_procs *vk_procs; - struct VkSamplerCreateInfo sampler_desc; -@@ -3695,15 +3712,48 @@ static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER f - sampler_desc.maxLod = max_lod; - sampler_desc.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; - sampler_desc.unnormalizedCoordinates = VK_FALSE; -+ -+ if (address_u == D3D12_TEXTURE_ADDRESS_MODE_BORDER || address_v == D3D12_TEXTURE_ADDRESS_MODE_BORDER -+ || address_w == D3D12_TEXTURE_ADDRESS_MODE_BORDER) -+ sampler_desc.borderColor = vk_border_colour_from_d3d12(border_colour); -+ - if ((vr = VK_CALL(vkCreateSampler(device->vk_device, &sampler_desc, NULL, vk_sampler))) < 0) - WARN("Failed to create Vulkan sampler, vr %d.\n", vr); - - return vr; - } - -+static D3D12_STATIC_BORDER_COLOR d3d12_static_border_colour(const float *colour) -+{ -+ unsigned int i; -+ -+ static const struct -+ { -+ float colour[4]; -+ D3D12_STATIC_BORDER_COLOR static_colour; -+ } -+ colours[] = -+ { -+ {{0.0f, 0.0f, 0.0f, 0.0f}, D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK}, -+ {{0.0f, 0.0f, 0.0f, 1.0f}, D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK}, -+ {{1.0f, 1.0f, 1.0f, 1.0f}, D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE}, -+ }; -+ -+ for (i = 0; i < ARRAY_SIZE(colours); ++i) -+ { -+ if (!memcmp(colour, colours[i].colour, sizeof(colours[i].colour))) -+ return colours[i].static_colour; -+ } -+ -+ FIXME("Unhandled border colour {%.8e, %.8e, %.8e, %.8e}.\n", colour[0], colour[1], colour[2], colour[3]); -+ -+ return D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; -+} -+ - void d3d12_desc_create_sampler(struct d3d12_desc *sampler, - struct d3d12_device *device, const D3D12_SAMPLER_DESC *desc) - { -+ D3D12_STATIC_BORDER_COLOR static_colour = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; - struct vkd3d_view *view; - - if (!desc) -@@ -3715,8 +3765,7 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler, - if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER - || desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER - || desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER) -- FIXME("Ignoring border color {%.8e, %.8e, %.8e, %.8e}.\n", -- desc->BorderColor[0], desc->BorderColor[1], desc->BorderColor[2], desc->BorderColor[3]); -+ static_colour = d3d12_static_border_colour(desc->BorderColor); - - if (!(view = vkd3d_view_create(VKD3D_DESCRIPTOR_MAGIC_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLER, - VKD3D_VIEW_TYPE_SAMPLER, device))) -@@ -3724,9 +3773,9 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler, - view->v.u.vk_sampler = VK_NULL_HANDLE; - view->v.format = NULL; - -- if (d3d12_create_sampler(device, desc->Filter, desc->AddressU, -- desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, -- desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, &view->v.u.vk_sampler) < 0) -+ if (d3d12_create_sampler(device, desc->Filter, desc->AddressU, desc->AddressV, -+ desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, desc->ComparisonFunc, -+ static_colour, desc->MinLOD, desc->MaxLOD, &view->v.u.vk_sampler) < 0) - { - vkd3d_view_decref(view, device); - return; -@@ -3740,14 +3789,9 @@ HRESULT vkd3d_create_static_sampler(struct d3d12_device *device, - { - VkResult vr; - -- if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER -- || desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER -- || desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER) -- FIXME("Ignoring border %#x.\n", desc->BorderColor); -- -- vr = d3d12_create_sampler(device, desc->Filter, desc->AddressU, -- desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, -- desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, vk_sampler); -+ vr = d3d12_create_sampler(device, desc->Filter, desc->AddressU, desc->AddressV, -+ desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, desc->ComparisonFunc, -+ desc->BorderColor, desc->MinLOD, desc->MaxLOD, vk_sampler); - return hresult_from_vk_result(vr); - } - --- -2.43.0 - diff --git a/patches/vkd3d-latest/0010-Updated-vkd3d-to-3e2ace8d33a203bf0c8d6a7bf140ef9a9a0.patch b/patches/vkd3d-latest/0010-Updated-vkd3d-to-3e2ace8d33a203bf0c8d6a7bf140ef9a9a0.patch deleted file mode 100644 index 866003ae..00000000 --- a/patches/vkd3d-latest/0010-Updated-vkd3d-to-3e2ace8d33a203bf0c8d6a7bf140ef9a9a0.patch +++ /dev/null @@ -1,1460 +0,0 @@ -From 96a2e42f5ccb7e3029e00834598ad625083ee770 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Sat, 13 Jan 2024 11:46:16 +1100 -Subject: [PATCH] Updated vkd3d to 3e2ace8d33a203bf0c8d6a7bf140ef9a9a08352d. - ---- - libs/vkd3d/Makefile.in | 1 + - libs/vkd3d/include/private/vkd3d_common.h | 1 + - libs/vkd3d/include/vkd3d_shader.h | 7 + - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 60 ++++++- - libs/vkd3d/libs/vkd3d-shader/dxbc.c | 34 ++-- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 12 +- - libs/vkd3d/libs/vkd3d-shader/fx.c | 158 ++++++++++++++++++ - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 77 +++++++-- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 13 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.l | 1 + - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 81 ++++++++- - libs/vkd3d/libs/vkd3d-shader/ir.c | 8 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 40 ++--- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 11 +- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 36 +++- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 6 +- - libs/vkd3d/libs/vkd3d/command.c | 3 +- - libs/vkd3d/libs/vkd3d/device.c | 42 ++++- - libs/vkd3d/libs/vkd3d/resource.c | 22 ++- - libs/vkd3d/libs/vkd3d/state.c | 23 ++- - libs/vkd3d/libs/vkd3d/vkd3d_private.h | 3 +- - 21 files changed, 548 insertions(+), 91 deletions(-) - create mode 100644 libs/vkd3d/libs/vkd3d-shader/fx.c - -diff --git a/libs/vkd3d/Makefile.in b/libs/vkd3d/Makefile.in -index dbc10594f62..448e9a0e61d 100644 ---- a/libs/vkd3d/Makefile.in -+++ b/libs/vkd3d/Makefile.in -@@ -17,6 +17,7 @@ SOURCES = \ - libs/vkd3d-shader/d3dbc.c \ - libs/vkd3d-shader/dxbc.c \ - libs/vkd3d-shader/dxil.c \ -+ libs/vkd3d-shader/fx.c \ - libs/vkd3d-shader/glsl.c \ - libs/vkd3d-shader/hlsl.c \ - libs/vkd3d-shader/hlsl.l \ -diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h -index e9bff2fbba3..54fe1ca5017 100644 ---- a/libs/vkd3d/include/private/vkd3d_common.h -+++ b/libs/vkd3d/include/private/vkd3d_common.h -@@ -52,6 +52,7 @@ - #define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9') - #define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C') - #define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L') -+#define TAG_FX10 VKD3D_MAKE_TAG('F', 'X', '1', '0') - #define TAG_ISG1 VKD3D_MAKE_TAG('I', 'S', 'G', '1') - #define TAG_ISGN VKD3D_MAKE_TAG('I', 'S', 'G', 'N') - #define TAG_OSG1 VKD3D_MAKE_TAG('O', 'S', 'G', '1') -diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h -index b1a1fff6451..a9c9ccc4a52 100644 ---- a/libs/vkd3d/include/vkd3d_shader.h -+++ b/libs/vkd3d/include/vkd3d_shader.h -@@ -785,6 +785,11 @@ enum vkd3d_shader_target_type - * An 'OpenGL Shading Language' shader. \since 1.3 - */ - VKD3D_SHADER_TARGET_GLSL, -+ /** -+ * Binary format used by Direct3D 9/10.x/11 effects profiles. -+ * Output is a raw FX section without container. \since 1.11 -+ */ -+ VKD3D_SHADER_TARGET_FX, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TARGET_TYPE), - }; -@@ -1270,6 +1275,8 @@ enum vkd3d_shader_descriptor_range_flags - VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE = 0x2, - VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4, - VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8, -+ /** \since 1.11 */ -+ VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS = 0x10000, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_DESCRIPTOR_RANGE_FLAGS), - }; -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index 0589bc42174..4829956cecf 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -365,6 +365,7 @@ struct vkd3d_d3d_asm_compiler - struct vkd3d_shader_version shader_version; - struct vkd3d_d3d_asm_colours colours; - enum vsir_asm_dialect dialect; -+ const struct vkd3d_shader_instruction *current; - }; - - static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...) -@@ -841,6 +842,27 @@ static void shader_print_bool_literal(struct vkd3d_d3d_asm_compiler *compiler, - compiler->colours.literal, b ? "true" : "false", compiler->colours.reset, suffix); - } - -+static void shader_print_untyped_literal(struct vkd3d_d3d_asm_compiler *compiler, -+ const char *prefix, uint32_t u, const char *suffix) -+{ -+ union -+ { -+ uint32_t u; -+ float f; -+ } value; -+ unsigned int exponent = (u >> 23) & 0xff; -+ -+ value.u = u; -+ -+ if (exponent != 0 && exponent != 0xff) -+ return shader_print_float_literal(compiler, prefix, value.f, suffix); -+ -+ if (u <= 10000) -+ return shader_print_uint_literal(compiler, prefix, value.u, suffix); -+ -+ return shader_print_hex_literal(compiler, prefix, value.u, suffix); -+} -+ - static void shader_print_subscript(struct vkd3d_d3d_asm_compiler *compiler, - unsigned int offset, const struct vkd3d_shader_src_param *rel_addr) - { -@@ -1102,6 +1124,19 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const - - if (reg->type == VKD3DSPR_IMMCONST) - { -+ bool untyped = false; -+ -+ switch (compiler->current->handler_idx) -+ { -+ case VKD3DSIH_MOV: -+ case VKD3DSIH_MOVC: -+ untyped = true; -+ break; -+ -+ default: -+ break; -+ } -+ - shader_addline(buffer, "%s(", compiler->colours.reset); - switch (reg->dimension) - { -@@ -1109,7 +1144,10 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const - switch (reg->data_type) - { - case VKD3D_DATA_FLOAT: -- shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); -+ if (untyped) -+ shader_print_untyped_literal(compiler, "", reg->u.immconst_u32[0], ""); -+ else -+ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); - break; - case VKD3D_DATA_INT: - shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); -@@ -1129,10 +1167,20 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const - switch (reg->data_type) - { - case VKD3D_DATA_FLOAT: -- shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); -- shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[1], ""); -- shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[2], ""); -- shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[3], ""); -+ if (untyped) -+ { -+ shader_print_untyped_literal(compiler, "", reg->u.immconst_u32[0], ""); -+ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[1], ""); -+ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[2], ""); -+ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[3], ""); -+ } -+ else -+ { -+ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); -+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[1], ""); -+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[2], ""); -+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[3], ""); -+ } - break; - case VKD3D_DATA_INT: - shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); -@@ -1678,6 +1726,8 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, - struct vkd3d_string_buffer *buffer = &compiler->buffer; - unsigned int i; - -+ compiler->current = ins; -+ - if (ins->predicate) - { - vkd3d_string_buffer_printf(buffer, "("); -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c -index 63deaaad29a..37ebc73c099 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c -@@ -130,13 +130,13 @@ static void skip_dword_unknown(const char **ptr, unsigned int count) - } - } - --static const char *shader_get_string(const char *data, size_t data_size, DWORD offset) -+static const char *shader_get_string(const char *data, size_t data_size, size_t offset) - { - size_t len, max_len; - - if (offset >= data_size) - { -- WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size); -+ WARN("Invalid offset %#zx (data size %#zx).\n", offset, data_size); - return NULL; - } - -@@ -230,7 +230,7 @@ static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_ - chunk_offset = read_u32(&ptr); - TRACE("chunk %u at offset %#x\n", i, chunk_offset); - -- if (chunk_offset >= data_size || !require_space(chunk_offset, 2, sizeof(DWORD), data_size)) -+ if (chunk_offset >= data_size || !require_space(chunk_offset, 2, sizeof(uint32_t), data_size)) - { - WARN("Invalid chunk offset %#x (data size %zu).\n", chunk_offset, data_size); - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET, -@@ -399,7 +399,8 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s - - for (i = 0; i < count; ++i) - { -- uint32_t name_offset, mask; -+ size_t name_offset; -+ uint32_t mask; - - e[i].sort_index = i; - -@@ -411,7 +412,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s - name_offset = read_u32(&ptr); - if (!(e[i].semantic_name = shader_get_string(data, section->data.size, name_offset))) - { -- WARN("Invalid name offset %#x (data size %#zx).\n", name_offset, section->data.size); -+ WARN("Invalid name offset %#zx (data size %#zx).\n", name_offset, section->data.size); - vkd3d_free(e); - return VKD3D_ERROR_INVALID_ARGUMENT; - } -@@ -592,7 +593,7 @@ static int shader_parse_descriptor_ranges(struct root_signature_parser_context * - const char *ptr; - unsigned int i; - -- if (!require_space(offset, 5 * count, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 5 * count, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -623,7 +624,8 @@ static void shader_validate_descriptor_range1(const struct vkd3d_shader_descript - | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE - | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE - | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE -- | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC); -+ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC -+ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS); - - if (unknown_flags) - FIXME("Unknown descriptor range flags %#x.\n", unknown_flags); -@@ -670,7 +672,7 @@ static int shader_parse_descriptor_table(struct root_signature_parser_context *c - unsigned int count; - const char *ptr; - -- if (!require_space(offset, 2, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -697,7 +699,7 @@ static int shader_parse_descriptor_table1(struct root_signature_parser_context * - unsigned int count; - const char *ptr; - -- if (!require_space(offset, 2, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -722,7 +724,7 @@ static int shader_parse_root_constants(struct root_signature_parser_context *con - { - const char *ptr; - -- if (!require_space(offset, 3, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 3, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -744,7 +746,7 @@ static int shader_parse_root_descriptor(struct root_signature_parser_context *co - { - const char *ptr; - -- if (!require_space(offset, 2, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -776,7 +778,7 @@ static int shader_parse_root_descriptor1(struct root_signature_parser_context *c - { - const char *ptr; - -- if (!require_space(offset, 3, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 3, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -802,7 +804,7 @@ static int shader_parse_root_parameters(struct root_signature_parser_context *co - unsigned int i; - int ret; - -- if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 3 * count, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -844,13 +846,13 @@ static int shader_parse_root_parameters(struct root_signature_parser_context *co - } - - static int shader_parse_root_parameters1(struct root_signature_parser_context *context, -- uint32_t offset, DWORD count, struct vkd3d_shader_root_parameter1 *parameters) -+ uint32_t offset, unsigned int count, struct vkd3d_shader_root_parameter1 *parameters) - { - const char *ptr; - unsigned int i; - int ret; - -- if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 3 * count, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); - return VKD3D_ERROR_INVALID_ARGUMENT; -@@ -897,7 +899,7 @@ static int shader_parse_static_samplers(struct root_signature_parser_context *co - const char *ptr; - unsigned int i; - -- if (!require_space(offset, 13 * count, sizeof(DWORD), context->data_size)) -+ if (!require_space(offset, 13 * count, sizeof(uint32_t), context->data_size)) - { - WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); - return VKD3D_ERROR_INVALID_ARGUMENT; -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index c744dfcedf0..869a709d63f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -2331,8 +2331,8 @@ static const struct sm6_value *sm6_parser_get_value_by_ref(struct sm6_parser *sm - - static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxil_record *record) - { -+ const struct sm6_type *type, *ret_type; - const unsigned int max_count = 15; -- const struct sm6_type *ret_type; - struct sm6_value *fn; - unsigned int i, j; - -@@ -2347,18 +2347,18 @@ static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxi - fn->u.function.name = ""; - } - -- if (!(fn->type = sm6_parser_get_type(sm6, record->operands[0]))) -+ if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) - return false; -- if (!sm6_type_is_function(fn->type)) -+ if (!sm6_type_is_function(type)) - { - WARN("Type is not a function.\n"); - return false; - } -- ret_type = fn->type->u.function->ret_type; -+ ret_type = type->u.function->ret_type; - -- if (!(fn->type = sm6_type_get_pointer_to_type(fn->type, ADDRESS_SPACE_DEFAULT, sm6))) -+ if (!(fn->type = sm6_type_get_pointer_to_type(type, ADDRESS_SPACE_DEFAULT, sm6))) - { -- WARN("Failed to get pointer type for type %u.\n", fn->type->class); -+ WARN("Failed to get pointer type for type %u.\n", type->class); - return false; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -new file mode 100644 -index 00000000000..6c4c1203d48 ---- /dev/null -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -0,0 +1,158 @@ -+/* -+ * FX (Direct3D 9/10/11 effect) support -+ * -+ * Copyright 2023 Nikolay Sivov for CodeWeavers -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -+ */ -+ -+#include "hlsl.h" -+ -+struct fx_write_context -+{ -+ struct vkd3d_bytecode_buffer unstructured; -+ struct vkd3d_bytecode_buffer structured; -+ -+ uint32_t technique_count; -+ int status; -+}; -+ -+static uint32_t fx_put_raw_string(struct fx_write_context *fx, const char *string) -+{ -+ /* NULLs are emitted as empty strings using the same 4 bytes at the start of the section. */ -+ return string ? put_string(&fx->unstructured, string) : 0; -+} -+ -+static void write_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t name_offset; -+ -+ name_offset = fx_put_raw_string(fx, var->name); -+ put_u32(buffer, name_offset); -+ put_u32(buffer, 0); /* Pass count. */ -+ put_u32(buffer, 0); /* Annotation count. */ -+ -+ /* TODO: passes */ -+} -+ -+static void set_status(struct fx_write_context *fx, int status) -+{ -+ if (fx->status < 0) -+ return; -+ if (status < 0) -+ fx->status = status; -+} -+ -+static void write_techniques(struct hlsl_scope *scope, struct fx_write_context *fx) -+{ -+ struct hlsl_ir_var *var; -+ -+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) -+ { -+ const struct hlsl_type *type = var->data_type; -+ -+ if (type->base_type == HLSL_TYPE_TECHNIQUE && type->e.version == 10) -+ { -+ write_technique(var, fx); -+ ++fx->technique_count; -+ } -+ } -+ -+ set_status(fx, fx->unstructured.status); -+ set_status(fx, fx->structured.status); -+} -+ -+static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) -+{ -+ struct vkd3d_bytecode_buffer buffer = { 0 }; -+ struct fx_write_context fx; -+ uint32_t size_offset, size; -+ -+ memset(&fx, 0, sizeof(fx)); -+ -+ put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ -+ -+ /* TODO: buffers */ -+ /* TODO: objects */ -+ /* TODO: shared buffers */ -+ /* TODO: shared objects */ -+ -+ write_techniques(ctx->globals, &fx); -+ -+ put_u32(&buffer, ctx->profile->minor_version == 0 ? 0xfeff1001 : 0xfeff1011); /* Version. */ -+ put_u32(&buffer, 0); /* Buffer count. */ -+ put_u32(&buffer, 0); /* Variable count. */ -+ put_u32(&buffer, 0); /* Object count. */ -+ put_u32(&buffer, 0); /* Pool buffer count. */ -+ put_u32(&buffer, 0); /* Pool variable count. */ -+ put_u32(&buffer, 0); /* Pool object count. */ -+ put_u32(&buffer, fx.technique_count); -+ size_offset = put_u32(&buffer, 0); /* Unstructured size. */ -+ put_u32(&buffer, 0); /* String count. */ -+ put_u32(&buffer, 0); /* Texture object count. */ -+ put_u32(&buffer, 0); /* Depth stencil state count. */ -+ put_u32(&buffer, 0); /* Blend state count. */ -+ put_u32(&buffer, 0); /* Rasterizer state count. */ -+ put_u32(&buffer, 0); /* Sampler state count. */ -+ put_u32(&buffer, 0); /* Rendertarget view count. */ -+ put_u32(&buffer, 0); /* Depth stencil view count. */ -+ put_u32(&buffer, 0); /* Shader count. */ -+ put_u32(&buffer, 0); /* Inline shader count. */ -+ -+ size = align(fx.unstructured.size, 4); -+ set_u32(&buffer, size_offset, size); -+ -+ bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size); -+ bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size); -+ -+ vkd3d_free(fx.unstructured.data); -+ vkd3d_free(fx.structured.data); -+ -+ set_status(&fx, buffer.status); -+ -+ if (!fx.status) -+ { -+ out->code = buffer.data; -+ out->size = buffer.size; -+ } -+ -+ if (fx.status < 0) -+ ctx->result = fx.status; -+ -+ return fx.status; -+} -+ -+int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) -+{ -+ if (ctx->profile->major_version == 2) -+ { -+ hlsl_fixme(ctx, &ctx->location, "Writing fx_2_0 binaries is not implemented."); -+ return VKD3D_ERROR_NOT_IMPLEMENTED; -+ } -+ else if (ctx->profile->major_version == 4) -+ { -+ return hlsl_fx_4_write(ctx, out); -+ } -+ else if (ctx->profile->major_version == 5) -+ { -+ hlsl_fixme(ctx, &ctx->location, "Writing fx_5_0 binaries is not implemented."); -+ return VKD3D_ERROR_NOT_IMPLEMENTED; -+ } -+ else -+ { -+ vkd3d_unreachable(); -+ } -+} -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index a41967876a2..1e247445119 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -98,19 +98,22 @@ bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var - struct hlsl_scope *scope = ctx->cur_scope; - struct hlsl_ir_var *var; - -- LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) -+ if (decl->name) - { -- if (!strcmp(decl->name, var->name)) -- return false; -- } -- if (local_var && scope->upper->upper == ctx->globals) -- { -- /* Check whether the variable redefines a function parameter. */ -- LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry) -+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) - { -- if (!strcmp(decl->name, var->name)) -+ if (var->name && !strcmp(decl->name, var->name)) - return false; - } -+ if (local_var && scope->upper->upper == ctx->globals) -+ { -+ /* Check whether the variable redefines a function parameter. */ -+ LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry) -+ { -+ if (var->name && !strcmp(decl->name, var->name)) -+ return false; -+ } -+ } - } - - list_add_tail(&scope->vars, &decl->scope_entry); -@@ -123,7 +126,7 @@ struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name) - - LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) - { -- if (!strcmp(name, var->name)) -+ if (var->name && !strcmp(name, var->name)) - return var; - } - if (!scope->upper) -@@ -915,6 +918,11 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 - if (t1->class == HLSL_CLASS_ARRAY) - return t1->e.array.elements_count == t2->e.array.elements_count - && hlsl_types_are_equal(t1->e.array.type, t2->e.array.type); -+ if (t1->class == HLSL_CLASS_OBJECT) -+ { -+ if (t1->base_type == HLSL_TYPE_TECHNIQUE && t1->e.version != t2->e.version) -+ return false; -+ } - - return true; - } -@@ -993,6 +1001,13 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, - break; - } - -+ case HLSL_CLASS_OBJECT: -+ { -+ if (type->base_type == HLSL_TYPE_TECHNIQUE) -+ type->e.version = old->e.version; -+ break; -+ } -+ - default: - break; - } -@@ -3351,12 +3366,25 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) - {"float", HLSL_CLASS_SCALAR, HLSL_TYPE_FLOAT, 1, 1}, - {"vector", HLSL_CLASS_VECTOR, HLSL_TYPE_FLOAT, 4, 1}, - {"matrix", HLSL_CLASS_MATRIX, HLSL_TYPE_FLOAT, 4, 4}, -+ {"fxgroup", HLSL_CLASS_OBJECT, HLSL_TYPE_EFFECT_GROUP, 1, 1}, - {"STRING", HLSL_CLASS_OBJECT, HLSL_TYPE_STRING, 1, 1}, - {"TEXTURE", HLSL_CLASS_OBJECT, HLSL_TYPE_TEXTURE, 1, 1}, - {"PIXELSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_PIXELSHADER, 1, 1}, - {"VERTEXSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_VERTEXSHADER, 1, 1}, - }; - -+ static const struct -+ { -+ char *name; -+ unsigned int version; -+ } -+ technique_types[] = -+ { -+ {"technique", 9}, -+ {"technique10", 10}, -+ {"technique11", 11}, -+ }; -+ - for (bt = 0; bt <= HLSL_TYPE_LAST_SCALAR; ++bt) - { - for (y = 1; y <= 4; ++y) -@@ -3461,6 +3489,13 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) - effect_types[i].base_type, effect_types[i].dimx, effect_types[i].dimy); - hlsl_scope_add_type(ctx->globals, type); - } -+ -+ for (i = 0; i < ARRAY_SIZE(technique_types); ++i) -+ { -+ type = hlsl_new_type(ctx, technique_types[i].name, HLSL_CLASS_OBJECT, HLSL_TYPE_TECHNIQUE, 1, 1); -+ type->e.version = technique_types[i].version; -+ hlsl_scope_add_type(ctx->globals, type); -+ } - } - - static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info, -@@ -3596,7 +3631,13 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d - return VKD3D_ERROR_NOT_IMPLEMENTED; - } - -- if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3) -+ if (compile_info->target_type != VKD3D_SHADER_TARGET_FX && profile->type == VKD3D_SHADER_TYPE_EFFECT) -+ { -+ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, -+ "The '%s' target profile is only compatible with the 'fx' target type.", profile->name); -+ return VKD3D_ERROR_INVALID_ARGUMENT; -+ } -+ else if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3) - { - vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, - "The '%s' target profile is incompatible with the 'd3dbc' target type.", profile->name); -@@ -3608,6 +3649,12 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d - "The '%s' target profile is incompatible with the 'dxbc-tpf' target type.", profile->name); - return VKD3D_ERROR_INVALID_ARGUMENT; - } -+ else if (compile_info->target_type == VKD3D_SHADER_TARGET_FX && profile->type != VKD3D_SHADER_TYPE_EFFECT) -+ { -+ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, -+ "The '%s' target profile is incompatible with the 'fx' target type.", profile->name); -+ return VKD3D_ERROR_INVALID_ARGUMENT; -+ } - - if (!hlsl_ctx_init(&ctx, compile_info, profile, message_context)) - return VKD3D_ERROR_OUT_OF_MEMORY; -@@ -3632,6 +3679,14 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d - return VKD3D_ERROR_NOT_IMPLEMENTED; - } - -+ if (ctx.profile->type == VKD3D_SHADER_TYPE_EFFECT) -+ { -+ ret = hlsl_emit_effect_binary(&ctx, out); -+ -+ hlsl_ctx_cleanup(&ctx); -+ return ret; -+ } -+ - if ((func = hlsl_get_function(&ctx, entry_point))) - { - LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry) -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index b56dea10f4c..8bc98b99e8a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -95,6 +95,8 @@ enum hlsl_base_type - HLSL_TYPE_UAV, - HLSL_TYPE_PIXELSHADER, - HLSL_TYPE_VERTEXSHADER, -+ HLSL_TYPE_TECHNIQUE, -+ HLSL_TYPE_EFFECT_GROUP, - HLSL_TYPE_STRING, - HLSL_TYPE_VOID, - }; -@@ -138,8 +140,10 @@ struct hlsl_type - struct rb_entry scope_entry; - - enum hlsl_type_class class; -- /* If type is <= HLSL_CLASS_LAST_NUMERIC, then base_type is <= HLSL_TYPE_LAST_SCALAR. -- * If type is HLSL_CLASS_OBJECT, then base_type is > HLSL_TYPE_LAST_SCALAR. -+ /* If class is <= HLSL_CLASS_LAST_NUMERIC, then base_type is <= HLSL_TYPE_LAST_SCALAR. -+ * If class is HLSL_CLASS_OBJECT, then base_type is > HLSL_TYPE_LAST_SCALAR. -+ * If class is HLSL_CLASS_OBJECT and base_type is HLSL_TYPE_TECHNIQUE, additional version -+ * field is used to distinguish between technique types. - * Otherwise, base_type is not used. */ - enum hlsl_base_type base_type; - -@@ -191,6 +195,8 @@ struct hlsl_type - /* Format of the data contained within the type if the base_type is HLSL_TYPE_TEXTURE or - * HLSL_TYPE_UAV. */ - struct hlsl_type *resource_format; -+ /* Additional field to distinguish object types. Currently used only for technique types. */ -+ unsigned int version; - } e; - - /* Number of numeric register components used by one value of this type, for each regset. -@@ -400,6 +406,8 @@ struct hlsl_ir_var - struct list scope_entry; - /* Item entry in hlsl_ctx.extern_vars, if the variable is extern. */ - struct list extern_entry; -+ /* Scope that variable itself defines, used to provide a container for techniques and passes. */ -+ struct hlsl_scope *scope; - - /* Indexes of the IR instructions where the variable is first written and last read (liveness - * range). The IR instructions are numerated starting from 2, because 0 means unused, and 1 -@@ -1160,6 +1168,7 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl - - 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); -+int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out); - - bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *chain); - bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struct hlsl_deref *other); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l -index fe838750747..6cef0e02eff 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l -@@ -89,6 +89,7 @@ else {return KW_ELSE; } - extern {return KW_EXTERN; } - false {return KW_FALSE; } - for {return KW_FOR; } -+fxgroup {return KW_FXGROUP; } - GeometryShader {return KW_GEOMETRYSHADER; } - groupshared {return KW_GROUPSHARED; } - if {return KW_IF; } -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 26f9357419b..7424e63a478 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -1096,6 +1096,55 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters - return true; - } - -+static bool add_technique(struct hlsl_ctx *ctx, const char *name, const char *typename, -+ const struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_ir_var *var; -+ struct hlsl_type *type; -+ -+ type = hlsl_get_type(ctx->globals, typename, false, false); -+ if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) -+ return false; -+ -+ if (!hlsl_add_var(ctx, var, false)) -+ { -+ struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); -+ -+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, -+ "Identifier \"%s\" was already declared in this scope.", var->name); -+ hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); -+ hlsl_free_var(var); -+ return false; -+ } -+ -+ return true; -+} -+ -+static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope, -+ const struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_ir_var *var; -+ struct hlsl_type *type; -+ -+ type = hlsl_get_type(ctx->globals, "fxgroup", false, false); -+ if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) -+ return false; -+ var->scope = scope; -+ -+ if (!hlsl_add_var(ctx, var, false)) -+ { -+ struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); -+ -+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, -+ "Identifier \"%s\" was already declared in this scope.", var->name); -+ hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name); -+ hlsl_free_var(var); -+ return false; -+ } -+ -+ return true; -+} -+ - static struct hlsl_reg_reservation parse_reg_reservation(const char *reg_string) - { - struct hlsl_reg_reservation reservation = {0}; -@@ -4888,6 +4937,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls - %token KW_EXTERN - %token KW_FALSE - %token KW_FOR -+%token KW_FXGROUP - %token KW_GEOMETRYSHADER - %token KW_GROUPSHARED - %token KW_IF -@@ -5094,7 +5144,8 @@ hlsl_prog: - destroy_block($2); - } - | hlsl_prog preproc_directive -- | hlsl_prog technique -+ | hlsl_prog global_technique -+ | hlsl_prog effect_group - | hlsl_prog ';' - - technique_name: -@@ -5110,7 +5161,8 @@ pass_list: - technique9: - KW_TECHNIQUE technique_name '{' pass_list '}' - { -- hlsl_fixme(ctx, &@$, "Unsupported \'technique\' declaration."); -+ if (!add_technique(ctx, $2, "technique", &@1)) -+ YYABORT; - } - - technique10: -@@ -5120,7 +5172,8 @@ technique10: - hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, - "The 'technique10' keyword is invalid for this profile."); - -- hlsl_fixme(ctx, &@$, "Unsupported \'technique10\' declaration."); -+ if (!add_technique(ctx, $2, "technique10", &@1)) -+ YYABORT; - } - - technique11: -@@ -5130,14 +5183,32 @@ technique11: - hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, - "The 'technique11' keyword is invalid for this profile."); - -- hlsl_fixme(ctx, &@$, "Unsupported \'technique11\' declaration."); -+ if (!add_technique(ctx, $2, "technique11", &@1)) -+ YYABORT; - } - --technique: -+global_technique: - technique9 - | technique10 - | technique11 - -+group_technique: -+ technique10 -+ | technique11 -+ -+group_techniques: -+ group_technique -+ | group_techniques group_technique -+ -+effect_group: -+ KW_FXGROUP any_identifier '{' scope_start group_techniques '}' -+ { -+ struct hlsl_scope *scope = ctx->cur_scope; -+ hlsl_pop_scope(ctx); -+ if (!(add_effect_group(ctx, $2, scope, &@2))) -+ YYABORT; -+ } -+ - buffer_declaration: - buffer_type any_identifier colon_attribute - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index bac4269198b..9fd60fa76a4 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -492,7 +492,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i - if (shader_instruction_is_dcl(ins)) - break; - for (j = 0; j < ins->dst_count; ++j) -- shader_dst_param_normalise_outpointid((struct vkd3d_shader_dst_param *)&ins->dst[j], &normaliser); -+ shader_dst_param_normalise_outpointid(&ins->dst[j], &normaliser); - break; - } - } -@@ -1116,9 +1116,9 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi - if (shader_instruction_is_dcl(ins)) - break; - for (i = 0; i < ins->dst_count; ++i) -- shader_dst_param_io_normalise((struct vkd3d_shader_dst_param *)&ins->dst[i], false, normaliser); -+ shader_dst_param_io_normalise(&ins->dst[i], false, normaliser); - for (i = 0; i < ins->src_count; ++i) -- shader_src_param_io_normalise((struct vkd3d_shader_src_param *)&ins->src[i], normaliser); -+ shader_src_param_io_normalise(&ins->src[i], normaliser); - break; - } - } -@@ -1310,7 +1310,7 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d - else - { - for (j = 0; j < ins->src_count; ++j) -- shader_register_normalise_flat_constants((struct vkd3d_shader_src_param *)&ins->src[j], &normaliser); -+ shader_register_normalise_flat_constants(&ins->src[j], &normaliser); - } - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 987197887de..a9e02d0a98e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -2198,7 +2198,7 @@ static void vkd3d_symbol_make_io(struct vkd3d_symbol *symbol, - - static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol, - uint32_t val_id, SpvStorageClass storage_class, -- enum vkd3d_shader_component_type component_type, DWORD write_mask) -+ enum vkd3d_shader_component_type component_type, uint32_t write_mask) - { - symbol->id = val_id; - symbol->descriptor_array = NULL; -@@ -3370,7 +3370,7 @@ static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *comp - } - - static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, -- const struct vkd3d_shader_src_param *src, DWORD write_mask); -+ const struct vkd3d_shader_src_param *src, uint32_t write_mask); - - static uint32_t spirv_compiler_emit_register_addressing(struct spirv_compiler *compiler, - const struct vkd3d_shader_register_index *reg_index) -@@ -3997,7 +3997,7 @@ static void spirv_compiler_emit_execution_mode1(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_abs(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id; -@@ -4011,7 +4011,7 @@ static uint32_t spirv_compiler_emit_abs(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id) -+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id; -@@ -4027,7 +4027,7 @@ static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_src_modifier(struct spirv_compiler *compiler, -- const struct vkd3d_shader_register *reg, DWORD write_mask, -+ const struct vkd3d_shader_register *reg, uint32_t write_mask, - enum vkd3d_shader_src_modifier modifier, uint32_t val_id) - { - switch (modifier) -@@ -4050,7 +4050,7 @@ static uint32_t spirv_compiler_emit_src_modifier(struct spirv_compiler *compiler - } - - static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, -- const struct vkd3d_shader_src_param *src, DWORD write_mask) -+ const struct vkd3d_shader_src_param *src, uint32_t write_mask) - { - uint32_t val_id; - -@@ -4059,7 +4059,7 @@ static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, - } - - static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *compiler, -- const struct vkd3d_shader_src_param *src, DWORD write_mask, enum vkd3d_shader_component_type component_type) -+ const struct vkd3d_shader_src_param *src, uint32_t write_mask, enum vkd3d_shader_component_type component_type) - { - struct vkd3d_shader_src_param src_param = *src; - -@@ -7068,7 +7068,7 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, - enum vkd3d_shader_component_type component_type; - uint32_t type_id, val_id, src_ids[2]; - unsigned int component_count, i; -- DWORD write_mask; -+ uint32_t write_mask; - - component_count = vsir_write_mask_component_count(dst->write_mask); - component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); -@@ -7370,7 +7370,7 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp - const struct vkd3d_shader_src_param *src = instruction->src; - enum vkd3d_shader_component_type component_type; - unsigned int i, j, k, src_count; -- DWORD write_mask; -+ uint32_t write_mask; - SpvOp op; - - src_count = instruction->src_count; -@@ -7427,8 +7427,8 @@ static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst = instruction->dst; - const struct vkd3d_shader_src_param *src = instruction->src; - uint32_t components[VKD3D_VEC4_SIZE]; -+ uint32_t write_mask; - unsigned int i, j; -- DWORD write_mask; - - instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -@@ -7460,8 +7460,8 @@ static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst = instruction->dst; - const struct vkd3d_shader_src_param *src = instruction->src; - uint32_t components[VKD3D_VEC4_SIZE]; -+ uint32_t write_mask; - unsigned int i, j; -- DWORD write_mask; - - instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2); -@@ -8226,7 +8226,7 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, - unsigned int image_operand_count = 0; - struct vkd3d_shader_image image; - uint32_t image_operands[2]; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - bool multisample; - - multisample = instruction->handler_idx == VKD3DSIH_LD2DMS; -@@ -8300,7 +8300,7 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, - unsigned int image_operand_count = 0; - struct vkd3d_shader_image image; - uint32_t image_operands[3]; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - SpvOp op; - - resource = &src[1]; -@@ -8416,7 +8416,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, - struct vkd3d_shader_image image; - unsigned int component_idx; - uint32_t image_operands[1]; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - bool extended_offset; - - if (instruction->handler_idx == VKD3DSIH_GATHER4_C -@@ -8476,13 +8476,13 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, - - static uint32_t spirv_compiler_emit_raw_structured_addressing( - struct spirv_compiler *compiler, uint32_t type_id, unsigned int stride, -- const struct vkd3d_shader_src_param *src0, DWORD src0_mask, -- const struct vkd3d_shader_src_param *src1, DWORD src1_mask) -+ const struct vkd3d_shader_src_param *src0, uint32_t src0_mask, -+ const struct vkd3d_shader_src_param *src1, uint32_t src1_mask) - { - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_src_param *offset; - uint32_t structure_id = 0, offset_id; -- DWORD offset_write_mask; -+ uint32_t offset_write_mask; - - if (stride) - { -@@ -8791,7 +8791,7 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, - const struct vkd3d_shader_src_param *src = instruction->src; - const struct vkd3d_symbol *resource_symbol; - struct vkd3d_shader_image image; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - uint32_t indices[2]; - - resource_symbol = spirv_compiler_find_resource(compiler, &src[1].reg); -@@ -8834,7 +8834,7 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler, - const struct vkd3d_shader_src_param *src = instruction->src; - const struct vkd3d_symbol *resource_symbol; - struct vkd3d_shader_image image; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - uint32_t indices[2]; - - resource_symbol = spirv_compiler_find_resource(compiler, &dst->reg); -@@ -9000,7 +9000,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil - struct vkd3d_shader_register_info reg_info; - struct vkd3d_shader_image image; - unsigned int structure_stride; -- DWORD coordinate_mask; -+ uint32_t coordinate_mask; - uint32_t operands[6]; - unsigned int i = 0; - SpvScope scope; -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 2cc56663efe..43b3525bb7b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -742,8 +742,7 @@ static bool shader_sm4_read_register_space(struct vkd3d_shader_sm4_parser *priv, - static void shader_sm4_read_conditional_op(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) - { -- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, -- (struct vkd3d_shader_src_param *)&ins->src[0]); -+ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &ins->src[0]); - ins->flags = (opcode_token & VKD3D_SM4_CONDITIONAL_NZ) ? - VKD3D_SHADER_CONDITIONAL_OP_NZ : VKD3D_SHADER_CONDITIONAL_OP_Z; - } -@@ -751,8 +750,7 @@ static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins, - static void shader_sm4_read_case_condition(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) - { -- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, -- (struct vkd3d_shader_src_param *)&ins->src[0]); -+ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &ins->src[0]); - if (ins->src[0].reg.type != VKD3DSPR_IMMCONST) - { - FIXME("Switch case value is not a 32-bit constant.\n"); -@@ -1130,9 +1128,8 @@ static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *in - static void shader_sm5_read_fcall(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) - { -- struct vkd3d_shader_src_param *src_params = (struct vkd3d_shader_src_param *)ins->src; -- src_params[0].reg.u.fp_body_idx = *tokens++; -- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &src_params[0]); -+ ins->src[0].reg.u.fp_body_idx = *tokens++; -+ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &ins->src[0]); - } - - static void shader_sm5_read_dcl_function_body(struct vkd3d_shader_instruction *ins, uint32_t opcode, -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index 8fd98d2a551..61e46f5538e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -383,13 +383,42 @@ size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *byte - return offset; - } - --void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value) -+size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size) -+{ -+ size_t offset = bytecode_align(buffer); -+ -+ if (buffer->status) -+ return offset; -+ -+ if (!vkd3d_array_reserve((void **)&buffer->data, &buffer->capacity, offset + size, 1)) -+ { -+ buffer->status = VKD3D_ERROR_OUT_OF_MEMORY; -+ return offset; -+ } -+ -+ memset(buffer->data + offset, 0, size); -+ buffer->size = offset + size; -+ return offset; -+} -+ -+static void bytecode_set_bytes(struct vkd3d_bytecode_buffer *buffer, size_t offset, -+ const void *value, size_t size) - { - if (buffer->status) - return; - -- assert(vkd3d_bound_range(offset, sizeof(value), buffer->size)); -- memcpy(buffer->data + offset, &value, sizeof(value)); -+ assert(vkd3d_bound_range(offset, size, buffer->size)); -+ memcpy(buffer->data + offset, value, size); -+} -+ -+void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value) -+{ -+ bytecode_set_bytes(buffer, offset, &value, sizeof(value)); -+} -+ -+void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char *string, size_t length) -+{ -+ bytecode_set_bytes(buffer, offset, string, length); - } - - static void vkd3d_shader_dump_blob(const char *path, const char *profile, -@@ -1913,6 +1942,7 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( - { - VKD3D_SHADER_TARGET_D3D_BYTECODE, - VKD3D_SHADER_TARGET_DXBC_TPF, -+ VKD3D_SHADER_TARGET_FX, - }; - - static const enum vkd3d_shader_target_type d3dbc_types[] = -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 224d27f4e1b..cc156f88074 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -1126,8 +1126,8 @@ struct vkd3d_shader_instruction - uint32_t flags; - unsigned int dst_count; - unsigned int src_count; -- const struct vkd3d_shader_dst_param *dst; -- const struct vkd3d_shader_src_param *src; -+ struct vkd3d_shader_dst_param *dst; -+ struct vkd3d_shader_src_param *src; - struct vkd3d_shader_texel_offset texel_offset; - enum vkd3d_shader_resource_type resource_type; - unsigned int resource_stride; -@@ -1357,7 +1357,9 @@ struct vkd3d_bytecode_buffer - /* Align to the next 4-byte offset, and return that offset. */ - size_t bytecode_align(struct vkd3d_bytecode_buffer *buffer); - size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size); -+size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size); - void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value); -+void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char *string, size_t length); - - static inline size_t put_u32(struct vkd3d_bytecode_buffer *buffer, uint32_t value) - { -diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c -index 013b5d0751f..4c39d00de24 100644 ---- a/libs/vkd3d/libs/vkd3d/command.c -+++ b/libs/vkd3d/libs/vkd3d/command.c -@@ -3270,7 +3270,8 @@ static void d3d12_command_list_bind_descriptor_heap(struct d3d12_command_list *l - { - VkDescriptorSet vk_descriptor_set = heap->vk_descriptor_sets[set].vk_set; - -- if (!vk_descriptor_set) -+ /* Null vk_set_layout means set 0 uses mutable descriptors, and this set is unused. */ -+ if (!vk_descriptor_set || !list->device->vk_descriptor_heap_layouts[set].vk_set_layout) - continue; - - VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, bindings->vk_bind_point, rs->vk_pipeline_layout, -diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c -index 69a46e9188a..ea243977c22 100644 ---- a/libs/vkd3d/libs/vkd3d/device.c -+++ b/libs/vkd3d/libs/vkd3d/device.c -@@ -94,6 +94,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = - VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker), - VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable), - VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing), -+ VK_EXTENSION(EXT_MUTABLE_DESCRIPTOR_TYPE, EXT_mutable_descriptor_type), - VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2), - VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation), - VK_EXTENSION(EXT_SHADER_STENCIL_EXPORT, EXT_shader_stencil_export), -@@ -106,13 +107,32 @@ static HRESULT vkd3d_create_vk_descriptor_heap_layout(struct d3d12_device *devic - { - const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; - VkDescriptorSetLayoutBindingFlagsCreateInfoEXT flags_info; -+ VkMutableDescriptorTypeCreateInfoEXT mutable_info; -+ VkMutableDescriptorTypeListEXT type_list; - VkDescriptorSetLayoutCreateInfo set_desc; - VkDescriptorBindingFlagsEXT set_flags; - VkDescriptorSetLayoutBinding binding; - VkResult vr; - -+ static const VkDescriptorType descriptor_types[] = -+ { -+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, -+ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, -+ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, -+ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, -+ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, -+ }; -+ -+ if (device->vk_info.EXT_mutable_descriptor_type && index && index != VKD3D_SET_INDEX_UAV_COUNTER -+ && device->vk_descriptor_heap_layouts[index].applicable_heap_type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) -+ { -+ device->vk_descriptor_heap_layouts[index].vk_set_layout = VK_NULL_HANDLE; -+ return S_OK; -+ } -+ - binding.binding = 0; -- binding.descriptorType = device->vk_descriptor_heap_layouts[index].type; -+ binding.descriptorType = (device->vk_info.EXT_mutable_descriptor_type && !index) -+ ? VK_DESCRIPTOR_TYPE_MUTABLE_EXT : device->vk_descriptor_heap_layouts[index].type; - binding.descriptorCount = device->vk_descriptor_heap_layouts[index].count; - binding.stageFlags = VK_SHADER_STAGE_ALL; - binding.pImmutableSamplers = NULL; -@@ -132,6 +152,17 @@ static HRESULT vkd3d_create_vk_descriptor_heap_layout(struct d3d12_device *devic - flags_info.bindingCount = 1; - flags_info.pBindingFlags = &set_flags; - -+ if (binding.descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_EXT) -+ { -+ type_list.descriptorTypeCount = ARRAY_SIZE(descriptor_types); -+ type_list.pDescriptorTypes = descriptor_types; -+ mutable_info.sType = VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT; -+ mutable_info.pNext = NULL; -+ mutable_info.mutableDescriptorTypeListCount = 1; -+ mutable_info.pMutableDescriptorTypeLists = &type_list; -+ flags_info.pNext = &mutable_info; -+ } -+ - if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device->vk_device, &set_desc, NULL, - &device->vk_descriptor_heap_layouts[index].vk_set_layout))) < 0) - { -@@ -763,6 +794,7 @@ struct vkd3d_physical_device_info - VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features; - VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features; - VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timeline_semaphore_features; -+ VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT mutable_features; - - VkPhysicalDeviceFeatures2 features2; - }; -@@ -780,6 +812,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i - VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features; - VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features; - VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *timeline_semaphore_features; -+ VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT *mutable_features; - VkPhysicalDeviceDepthClipEnableFeaturesEXT *depth_clip_features; - VkPhysicalDeviceMaintenance3Properties *maintenance3_properties; - VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb_properties; -@@ -800,6 +833,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i - vertex_divisor_features = &info->vertex_divisor_features; - vertex_divisor_properties = &info->vertex_divisor_properties; - timeline_semaphore_features = &info->timeline_semaphore_features; -+ mutable_features = &info->mutable_features; - xfb_features = &info->xfb_features; - xfb_properties = &info->xfb_properties; - -@@ -823,6 +857,8 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i - vk_prepend_struct(&info->features2, vertex_divisor_features); - timeline_semaphore_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR; - vk_prepend_struct(&info->features2, timeline_semaphore_features); -+ mutable_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT; -+ vk_prepend_struct(&info->features2, mutable_features); - - if (vulkan_info->KHR_get_physical_device_properties2) - VK_CALL(vkGetPhysicalDeviceFeatures2KHR(physical_device, &info->features2)); -@@ -1594,6 +1630,8 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, - vulkan_info->EXT_shader_demote_to_helper_invocation = false; - if (!physical_device_info->texel_buffer_alignment_features.texelBufferAlignment) - vulkan_info->EXT_texel_buffer_alignment = false; -+ if (!physical_device_info->mutable_features.mutableDescriptorType) -+ vulkan_info->EXT_mutable_descriptor_type = false; - if (!physical_device_info->timeline_semaphore_features.timelineSemaphore) - vulkan_info->KHR_timeline_semaphore = false; - -@@ -4513,7 +4551,7 @@ HRESULT vkd3d_create_thread(struct vkd3d_instance *instance, - thread_data->data = data; - if (!(thread->handle = CreateThread(NULL, 0, call_thread_main, thread_data, 0, NULL))) - { -- ERR("Failed to create thread, error %d.\n", GetLastError()); -+ ERR("Failed to create thread, error %lu.\n", GetLastError()); - vkd3d_free(thread_data); - hr = E_FAIL; - } -diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c -index f4ce1ccaffa..163dd6ce210 100644 ---- a/libs/vkd3d/libs/vkd3d/resource.c -+++ b/libs/vkd3d/libs/vkd3d/resource.c -@@ -2470,12 +2470,14 @@ static void d3d12_desc_write_vk_heap_null_descriptor(struct d3d12_descriptor_hea - { - const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; - struct d3d12_descriptor_heap_vk_set *descriptor_set; -- enum vkd3d_vk_descriptor_set_index set; -+ enum vkd3d_vk_descriptor_set_index set, end; - unsigned int i = writes->count; - -+ end = device->vk_info.EXT_mutable_descriptor_type ? VKD3D_SET_INDEX_UNIFORM_BUFFER -+ : VKD3D_SET_INDEX_STORAGE_IMAGE; - /* Binding a shader with the wrong null descriptor type works in Windows. - * To support that here we must write one to all applicable Vulkan sets. */ -- for (set = VKD3D_SET_INDEX_UNIFORM_BUFFER; set <= VKD3D_SET_INDEX_STORAGE_IMAGE; ++set) -+ for (set = VKD3D_SET_INDEX_UNIFORM_BUFFER; set <= end; ++set) - { - descriptor_set = &descriptor_heap->vk_descriptor_sets[set]; - writes->vk_descriptor_writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; -@@ -4220,9 +4222,11 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_pool(struct d3d12_descrip - - for (set = 0, pool_desc.poolSizeCount = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set) - { -- if (device->vk_descriptor_heap_layouts[set].applicable_heap_type == desc->Type) -+ if (device->vk_descriptor_heap_layouts[set].applicable_heap_type == desc->Type -+ && device->vk_descriptor_heap_layouts[set].vk_set_layout) - { -- pool_sizes[pool_desc.poolSizeCount].type = device->vk_descriptor_heap_layouts[set].type; -+ pool_sizes[pool_desc.poolSizeCount].type = (device->vk_info.EXT_mutable_descriptor_type && !set) -+ ? VK_DESCRIPTOR_TYPE_MUTABLE_EXT : device->vk_descriptor_heap_layouts[set].type; - pool_sizes[pool_desc.poolSizeCount++].descriptorCount = desc->NumDescriptors; - } - } -@@ -4248,6 +4252,16 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_set(struct d3d12_descript - VkDescriptorSetAllocateInfo set_desc; - VkResult vr; - -+ if (!device->vk_descriptor_heap_layouts[set].vk_set_layout) -+ { -+ /* Set 0 uses mutable descriptors, and this set is unused. */ -+ if (!descriptor_heap->vk_descriptor_sets[0].vk_set) -+ d3d12_descriptor_heap_create_descriptor_set(descriptor_heap, device, 0); -+ descriptor_set->vk_set = descriptor_heap->vk_descriptor_sets[0].vk_set; -+ descriptor_set->vk_type = device->vk_descriptor_heap_layouts[set].type; -+ return S_OK; -+ } -+ - set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - set_desc.pNext = &set_size; - set_desc.descriptorPool = descriptor_heap->vk_descriptor_pool; -diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c -index 1457ddf9c7f..82782e7d5fc 100644 ---- a/libs/vkd3d/libs/vkd3d/state.c -+++ b/libs/vkd3d/libs/vkd3d/state.c -@@ -848,7 +848,20 @@ static void vkd3d_descriptor_heap_binding_from_descriptor_range(const struct d3d - const struct vkd3d_device_descriptor_limits *descriptor_limits = &root_signature->device->vk_info.descriptor_limits; - unsigned int descriptor_set_size; - -- switch (range->type) -+ if (root_signature->device->vk_info.EXT_mutable_descriptor_type) -+ { -+ if (range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) -+ { -+ binding->set = VKD3D_SET_INDEX_SAMPLER; -+ descriptor_set_size = descriptor_limits->sampler_max_descriptors; -+ } -+ else -+ { -+ binding->set = 0; -+ descriptor_set_size = descriptor_limits->sampled_image_max_descriptors; -+ } -+ } -+ else switch (range->type) - { - case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV: - binding->set = is_buffer ? VKD3D_SET_INDEX_UNIFORM_TEXEL_BUFFER : VKD3D_SET_INDEX_SAMPLED_IMAGE; -@@ -1368,8 +1381,14 @@ static unsigned int d3d12_root_signature_copy_descriptor_set_layouts(const struc - - if (device->use_vk_heaps) - { -+ VkDescriptorSetLayout mutable_layout = device->vk_descriptor_heap_layouts[0].vk_set_layout; -+ - for (set = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set) -- vk_set_layouts[i++] = device->vk_descriptor_heap_layouts[set].vk_set_layout; -+ { -+ VkDescriptorSetLayout vk_set_layout = device->vk_descriptor_heap_layouts[set].vk_set_layout; -+ /* All layouts must be valid, so if null, just set it to the mutable one. */ -+ vk_set_layouts[i++] = vk_set_layout ? vk_set_layout : mutable_layout; -+ } - } - - return i; -diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -index bd7e7290d9e..9bf4575d46a 100644 ---- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h -+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -@@ -133,6 +133,7 @@ struct vkd3d_vulkan_info - bool EXT_debug_marker; - bool EXT_depth_clip_enable; - bool EXT_descriptor_indexing; -+ bool EXT_mutable_descriptor_type; - bool EXT_robustness2; - bool EXT_shader_demote_to_helper_invocation; - bool EXT_shader_stencil_export; -@@ -248,7 +249,7 @@ static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond) - static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock) - { - if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE)) -- ERR("Could not sleep on the condition variable, error %u.\n", GetLastError()); -+ ERR("Could not sleep on the condition variable, error %lu.\n", GetLastError()); - } - - static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond) --- -2.43.0 - diff --git a/patches/vkd3d-latest/0011-Updated-vkd3d-to-68b898fcb6b4ab2a9660f35edf3554465ab.patch b/patches/vkd3d-latest/0011-Updated-vkd3d-to-68b898fcb6b4ab2a9660f35edf3554465ab.patch deleted file mode 100644 index 7f565424..00000000 --- a/patches/vkd3d-latest/0011-Updated-vkd3d-to-68b898fcb6b4ab2a9660f35edf3554465ab.patch +++ /dev/null @@ -1,956 +0,0 @@ -From 6763e88d1a79484e304096631e47726784ebcb6a Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 16 Jan 2024 10:48:52 +1100 -Subject: [PATCH] Updated vkd3d to 68b898fcb6b4ab2a9660f35edf3554465ab0efbe. - ---- - libs/vkd3d/include/private/vkd3d_common.h | 4 - - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 11 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 2 +- - libs/vkd3d/libs/vkd3d-shader/fx.c | 235 +++++++++++++++++- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 40 ++- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 39 +++ - libs/vkd3d/libs/vkd3d-shader/ir.c | 171 ++++++++++++- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 5 +- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 26 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 3 +- - 10 files changed, 482 insertions(+), 54 deletions(-) - -diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h -index 54fe1ca5017..4c97fa06e32 100644 ---- a/libs/vkd3d/include/private/vkd3d_common.h -+++ b/libs/vkd3d/include/private/vkd3d_common.h -@@ -277,10 +277,6 @@ static inline LONG64 InterlockedIncrement64(LONG64 volatile *x) - { - return __sync_add_and_fetch(x, 1); - } --static inline LONG InterlockedAdd(LONG volatile *x, LONG val) --{ -- return __sync_add_and_fetch(x, val); --} - # else - # error "InterlockedIncrement() not implemented for this platform" - # endif /* HAVE_SYNC_ADD_AND_FETCH */ -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 8fec1e6371a..aa0dd8f4b0d 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -1360,18 +1360,21 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi - sm1->p.shader_desc.flat_constant_count[i].external = get_external_constant_count(sm1, i); - - if (!sm1->p.failed) -- vsir_validate(&sm1->p); -+ ret = vsir_validate(&sm1->p); - -- if (sm1->p.failed) -+ if (sm1->p.failed && ret >= 0) -+ ret = VKD3D_ERROR_INVALID_SHADER; -+ -+ if (ret < 0) - { - WARN("Failed to parse shader.\n"); - shader_sm1_destroy(&sm1->p); -- return VKD3D_ERROR_INVALID_SHADER; -+ return ret; - } - - *parser = &sm1->p; - -- return VKD3D_OK; -+ return ret; - } - - bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 869a709d63f..b39ec204bff 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -6282,7 +6282,7 @@ int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compi - vkd3d_free(byte_code); - - if (!sm6->p.failed && ret >= 0) -- vsir_validate(&sm6->p); -+ ret = vsir_validate(&sm6->p); - - if (sm6->p.failed && ret >= 0) - ret = VKD3D_ERROR_INVALID_SHADER; -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index 6c4c1203d48..17b9627b6bd 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -20,32 +20,146 @@ - - #include "hlsl.h" - -+struct string_entry -+{ -+ struct rb_entry entry; -+ /* String points to original data, should not be freed. */ -+ const char *string; -+ uint32_t offset; -+}; -+ -+static int string_storage_compare(const void *key, const struct rb_entry *entry) -+{ -+ struct string_entry *string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry); -+ const char *string = key; -+ -+ return strcmp(string, string_entry->string); -+} -+ -+static void string_storage_destroy(struct rb_entry *entry, void *context) -+{ -+ struct string_entry *string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry); -+ -+ vkd3d_free(string_entry); -+} -+ - struct fx_write_context - { -+ struct hlsl_ctx *ctx; -+ - struct vkd3d_bytecode_buffer unstructured; - struct vkd3d_bytecode_buffer structured; - -+ struct rb_tree strings; -+ -+ unsigned int min_technique_version; -+ unsigned int max_technique_version; -+ - uint32_t technique_count; -+ uint32_t group_count; - int status; - }; - -+static void fx_write_context_init(struct hlsl_ctx *ctx, struct fx_write_context *fx) -+{ -+ unsigned int version = ctx->profile->major_version; -+ -+ memset(fx, 0, sizeof(*fx)); -+ -+ fx->ctx = ctx; -+ if (version == 2) -+ { -+ fx->min_technique_version = 9; -+ fx->max_technique_version = 9; -+ } -+ else if (version == 4) -+ { -+ fx->min_technique_version = 10; -+ fx->max_technique_version = 10; -+ } -+ else if (version == 5) -+ { -+ fx->min_technique_version = 10; -+ fx->max_technique_version = 11; -+ } -+ -+ rb_init(&fx->strings, string_storage_compare); -+} -+ -+static int fx_write_context_cleanup(struct fx_write_context *fx) -+{ -+ int status = fx->status; -+ rb_destroy(&fx->strings, string_storage_destroy, NULL); -+ -+ return status; -+} -+ -+static bool technique_matches_version(const struct hlsl_ir_var *var, const struct fx_write_context *fx) -+{ -+ const struct hlsl_type *type = var->data_type; -+ -+ if (type->base_type != HLSL_TYPE_TECHNIQUE) -+ return false; -+ -+ return type->e.version >= fx->min_technique_version && type->e.version <= fx->max_technique_version; -+} -+ - static uint32_t fx_put_raw_string(struct fx_write_context *fx, const char *string) - { -+ struct string_entry *string_entry; -+ struct rb_entry *entry; -+ - /* NULLs are emitted as empty strings using the same 4 bytes at the start of the section. */ -- return string ? put_string(&fx->unstructured, string) : 0; -+ if (!string) -+ return 0; -+ -+ if ((entry = rb_get(&fx->strings, string))) -+ { -+ string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry); -+ return string_entry->offset; -+ } -+ -+ if (!(string_entry = hlsl_alloc(fx->ctx, sizeof(*string_entry)))) -+ return 0; -+ -+ string_entry->offset = put_string(&fx->unstructured, string); -+ string_entry->string = string; -+ -+ rb_put(&fx->strings, string, &string_entry->entry); -+ -+ return string_entry->offset; - } - --static void write_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) -+static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) - { - struct vkd3d_bytecode_buffer *buffer = &fx->structured; - uint32_t name_offset; - - name_offset = fx_put_raw_string(fx, var->name); - put_u32(buffer, name_offset); -- put_u32(buffer, 0); /* Pass count. */ - put_u32(buffer, 0); /* Annotation count. */ -+ put_u32(buffer, 0); /* Assignment count. */ -+} -+ -+static void write_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t name_offset, count = 0; -+ struct hlsl_ir_var *pass; -+ uint32_t count_offset; - -- /* TODO: passes */ -+ name_offset = fx_put_raw_string(fx, var->name); -+ put_u32(buffer, name_offset); -+ count_offset = put_u32(buffer, 0); -+ put_u32(buffer, 0); /* Annotation count. */ -+ -+ LIST_FOR_EACH_ENTRY(pass, &var->scope->vars, struct hlsl_ir_var, scope_entry) -+ { -+ write_pass(pass, fx); -+ ++count; -+ } -+ -+ set_u32(buffer, count_offset, count); - } - - static void set_status(struct fx_write_context *fx, int status) -@@ -75,13 +189,55 @@ static void write_techniques(struct hlsl_scope *scope, struct fx_write_context * - set_status(fx, fx->structured.status); - } - -+static void write_group(struct hlsl_scope *scope, const char *name, struct fx_write_context *fx) -+{ -+ struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ uint32_t name_offset = fx_put_raw_string(fx, name); -+ uint32_t count_offset, count; -+ -+ put_u32(buffer, name_offset); -+ count_offset = put_u32(buffer, 0); /* Technique count */ -+ put_u32(buffer, 0); /* Annotation count */ -+ -+ count = fx->technique_count; -+ write_techniques(scope, fx); -+ set_u32(buffer, count_offset, fx->technique_count - count); -+ -+ ++fx->group_count; -+} -+ -+static void write_groups(struct hlsl_scope *scope, struct fx_write_context *fx) -+{ -+ bool needs_default_group = false; -+ struct hlsl_ir_var *var; -+ -+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) -+ { -+ if (technique_matches_version(var, fx)) -+ { -+ needs_default_group = true; -+ break; -+ } -+ } -+ -+ if (needs_default_group) -+ write_group(scope, NULL, fx); -+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) -+ { -+ const struct hlsl_type *type = var->data_type; -+ -+ if (type->base_type == HLSL_TYPE_EFFECT_GROUP) -+ write_group(var->scope, var->name, fx); -+ } -+} -+ - static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - { - struct vkd3d_bytecode_buffer buffer = { 0 }; - struct fx_write_context fx; - uint32_t size_offset, size; - -- memset(&fx, 0, sizeof(fx)); -+ fx_write_context_init(ctx, &fx); - - put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ - -@@ -132,7 +288,71 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - if (fx.status < 0) - ctx->result = fx.status; - -- return fx.status; -+ return fx_write_context_cleanup(&fx); -+} -+ -+static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) -+{ -+ struct vkd3d_bytecode_buffer buffer = { 0 }; -+ struct fx_write_context fx; -+ uint32_t size_offset, size; -+ -+ fx_write_context_init(ctx, &fx); -+ -+ put_u32(&fx.unstructured, 0); /* Empty string placeholder. */ -+ -+ /* TODO: buffers */ -+ /* TODO: objects */ -+ /* TODO: interface variables */ -+ -+ write_groups(ctx->globals, &fx); -+ -+ put_u32(&buffer, 0xfeff2001); /* Version. */ -+ put_u32(&buffer, 0); /* Buffer count. */ -+ put_u32(&buffer, 0); /* Variable count. */ -+ put_u32(&buffer, 0); /* Object count. */ -+ put_u32(&buffer, 0); /* Pool buffer count. */ -+ put_u32(&buffer, 0); /* Pool variable count. */ -+ put_u32(&buffer, 0); /* Pool object count. */ -+ put_u32(&buffer, fx.technique_count); -+ size_offset = put_u32(&buffer, 0); /* Unstructured size. */ -+ put_u32(&buffer, 0); /* String count. */ -+ put_u32(&buffer, 0); /* Texture object count. */ -+ put_u32(&buffer, 0); /* Depth stencil state count. */ -+ put_u32(&buffer, 0); /* Blend state count. */ -+ put_u32(&buffer, 0); /* Rasterizer state count. */ -+ put_u32(&buffer, 0); /* Sampler state count. */ -+ put_u32(&buffer, 0); /* Rendertarget view count. */ -+ put_u32(&buffer, 0); /* Depth stencil view count. */ -+ put_u32(&buffer, 0); /* Shader count. */ -+ put_u32(&buffer, 0); /* Inline shader count. */ -+ put_u32(&buffer, fx.group_count); /* Group count. */ -+ put_u32(&buffer, 0); /* UAV count. */ -+ put_u32(&buffer, 0); /* Interface variables count. */ -+ put_u32(&buffer, 0); /* Interface variable element count. */ -+ put_u32(&buffer, 0); /* Class instance elements count. */ -+ -+ size = align(fx.unstructured.size, 4); -+ set_u32(&buffer, size_offset, size); -+ -+ bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size); -+ bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size); -+ -+ vkd3d_free(fx.unstructured.data); -+ vkd3d_free(fx.structured.data); -+ -+ set_status(&fx, buffer.status); -+ -+ if (!fx.status) -+ { -+ out->code = buffer.data; -+ out->size = buffer.size; -+ } -+ -+ if (fx.status < 0) -+ ctx->result = fx.status; -+ -+ return fx_write_context_cleanup(&fx); - } - - int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) -@@ -148,8 +368,7 @@ int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - } - else if (ctx->profile->major_version == 5) - { -- hlsl_fixme(ctx, &ctx->location, "Writing fx_5_0 binaries is not implemented."); -- return VKD3D_ERROR_NOT_IMPLEMENTED; -+ return hlsl_fx_5_write(ctx, out); - } - else - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 7424e63a478..b11cbde26f1 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -1096,8 +1096,8 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters - return true; - } - --static bool add_technique(struct hlsl_ctx *ctx, const char *name, const char *typename, -- const struct vkd3d_shader_location *loc) -+static bool add_technique(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope, -+ const char *typename, const struct vkd3d_shader_location *loc) - { - struct hlsl_ir_var *var; - struct hlsl_type *type; -@@ -1105,6 +1105,7 @@ static bool add_technique(struct hlsl_ctx *ctx, const char *name, const char *ty - type = hlsl_get_type(ctx->globals, typename, false, false); - if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) - return false; -+ var->scope = scope; - - if (!hlsl_add_var(ctx, var, false)) - { -@@ -5102,7 +5103,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls - - %type any_identifier - %type var_identifier --%type technique_name -+%type name_opt - - %type parameter - -@@ -5148,42 +5149,59 @@ hlsl_prog: - | hlsl_prog effect_group - | hlsl_prog ';' - --technique_name: -+name_opt: - %empty - { - $$ = NULL; - } - | any_identifier - -+pass: -+ KW_PASS name_opt '{' '}' -+ - pass_list: -- %empty -+ pass -+ | pass_list pass -+ -+passes: -+ scope_start -+ | scope_start pass_list - - technique9: -- KW_TECHNIQUE technique_name '{' pass_list '}' -+ KW_TECHNIQUE name_opt '{' passes '}' - { -- if (!add_technique(ctx, $2, "technique", &@1)) -+ struct hlsl_scope *scope = ctx->cur_scope; -+ hlsl_pop_scope(ctx); -+ -+ if (!add_technique(ctx, $2, scope, "technique", &@1)) - YYABORT; - } - - technique10: -- KW_TECHNIQUE10 technique_name '{' pass_list '}' -+ KW_TECHNIQUE10 name_opt '{' passes '}' - { -+ struct hlsl_scope *scope = ctx->cur_scope; -+ hlsl_pop_scope(ctx); -+ - if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) - hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, - "The 'technique10' keyword is invalid for this profile."); - -- if (!add_technique(ctx, $2, "technique10", &@1)) -+ if (!add_technique(ctx, $2, scope, "technique10", &@1)) - YYABORT; - } - - technique11: -- KW_TECHNIQUE11 technique_name '{' pass_list '}' -+ KW_TECHNIQUE11 name_opt '{' passes '}' - { -+ struct hlsl_scope *scope = ctx->cur_scope; -+ hlsl_pop_scope(ctx); -+ - if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) - hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, - "The 'technique11' keyword is invalid for this profile."); - -- if (!add_technique(ctx, $2, "technique11", &@1)) -+ if (!add_technique(ctx, $2, scope, "technique11", &@1)) - YYABORT; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index acc19dd8ba5..d37bef15cce 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -32,6 +32,11 @@ static struct hlsl_ir_node *new_offset_from_path_index(struct hlsl_ctx *ctx, str - switch (type->class) - { - case HLSL_CLASS_VECTOR: -+ if (idx->type != HLSL_IR_CONSTANT) -+ { -+ hlsl_fixme(ctx, &idx->loc, "Non-constant vector addressing."); -+ break; -+ } - *offset_component += hlsl_ir_constant(idx)->value.u[0].u; - break; - -@@ -2478,6 +2483,38 @@ static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir - return false; - } - -+static bool validate_nonconstant_vector_store_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) -+{ -+ struct hlsl_ir_node *idx; -+ struct hlsl_deref *deref; -+ struct hlsl_type *type; -+ unsigned int i; -+ -+ if (instr->type != HLSL_IR_STORE) -+ return false; -+ -+ deref = &hlsl_ir_store(instr)->lhs; -+ assert(deref->var); -+ -+ if (deref->path_len == 0) -+ return false; -+ -+ type = deref->var->data_type; -+ for (i = 0; i < deref->path_len - 1; ++i) -+ type = hlsl_get_element_type_from_path_index(ctx, type, deref->path[i].node); -+ -+ idx = deref->path[deref->path_len - 1].node; -+ -+ if (type->class == HLSL_CLASS_VECTOR && idx->type != HLSL_IR_CONSTANT) -+ { -+ /* We should turn this into an hlsl_error after we implement unrolling, because if we get -+ * here after that, it means that the HLSL is invalid. */ -+ hlsl_fixme(ctx, &instr->loc, "Non-constant vector addressing on store. Unrolling may be missing."); -+ } -+ -+ return false; -+} -+ - /* Lower combined samples and sampler variables to synthesized separated textures and samplers. - * That is, translate SM1-style samples in the source to SM4-style samples in the bytecode. */ - static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) -@@ -4969,6 +5006,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry - lower_ir(ctx, lower_abs, body); - } - -+ lower_ir(ctx, validate_nonconstant_vector_store_derefs, body); -+ - /* TODO: move forward, remove when no longer needed */ - transform_derefs(ctx, replace_deref_path_with_offset, body); - while (hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL)); -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 9fd60fa76a4..28c7d158452 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -1511,7 +1511,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, - vkd3d_shader_trace(instructions, &parser->shader_version); - - if (result >= 0 && !parser->failed) -- vsir_validate(parser); -+ result = vsir_validate(parser); - - if (result >= 0 && parser->failed) - result = VKD3D_ERROR_INVALID_SHADER; -@@ -1523,10 +1523,26 @@ struct validation_context - { - struct vkd3d_shader_parser *parser; - size_t instruction_idx; -+ bool invalid_instruction_idx; - bool dcl_temps_found; - unsigned int temp_count; - enum vkd3d_shader_opcode phase; - -+ struct validation_context_temp_data -+ { -+ enum vsir_dimension dimension; -+ size_t first_seen; -+ } *temps; -+ -+ struct validation_context_ssa_data -+ { -+ enum vsir_dimension dimension; -+ 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; -@@ -1544,8 +1560,16 @@ static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *c - vkd3d_string_buffer_vprintf(&buf, format, args); - va_end(args); - -- vkd3d_shader_parser_error(ctx->parser, error, "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer); -- ERR("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer); -+ if (ctx->invalid_instruction_idx) -+ { -+ vkd3d_shader_parser_error(ctx->parser, error, "%s", buf.buffer); -+ ERR("VSIR validation error: %s\n", buf.buffer); -+ } -+ else -+ { -+ vkd3d_shader_parser_error(ctx->parser, error, "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer); -+ ERR("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer); -+ } - - vkd3d_string_buffer_cleanup(&buf); - } -@@ -1592,30 +1616,101 @@ 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_count >= 1 && reg->idx[0].rel_addr) -+ 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_count >= 1 && reg->idx[0].offset >= temp_count) -+ if (reg->idx[0].offset >= temp_count) -+ { - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "TEMP register index %u exceeds the maximum count %u.", - reg->idx[0].offset, temp_count); -+ break; -+ } -+ -+ /* parser->shader_desc.temp_count might be smaller then -+ * temp_count if the parser made a mistake; we still don't -+ * want to overflow the array. */ -+ if (reg->idx[0].offset >= ctx->parser->shader_desc.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); -+ } - 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_count >= 1 && reg->idx[0].rel_addr) -+ 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_count >= 1 && reg->idx[0].offset >= ctx->parser->shader_desc.ssa_count) -+ if (reg->idx[0].offset >= ctx->parser->shader_desc.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->parser->shader_desc.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->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); -+ } - break; -+ } - - case VKD3DSPR_NULL: - if (reg->idx_count != 0) -@@ -1688,6 +1783,23 @@ static void vsir_validate_dst_param(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT, "Destination has invalid shift %#x.", - dst->shift); - } -+ -+ if (dst->reg.type == VKD3DSPR_SSA && dst->reg.idx[0].offset < ctx->parser->shader_desc.ssa_count) -+ { -+ struct validation_context_ssa_data *data = &ctx->ssas[dst->reg.idx[0].offset]; -+ -+ if (data->write_mask == 0) -+ { -+ data->write_mask = dst->write_mask; -+ data->first_assigned = ctx->instruction_idx; -+ } -+ else -+ { -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE, -+ "SSA register is already assigned at instruction %zu.", -+ data->first_assigned); -+ } -+ } - } - - static void vsir_validate_src_param(struct validation_context *ctx, -@@ -1706,6 +1818,15 @@ static void vsir_validate_src_param(struct validation_context *ctx, - if (src->modifiers >= VKD3DSPSM_COUNT) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", - src->modifiers); -+ -+ if (src->reg.type == VKD3DSPR_SSA && src->reg.idx[0].offset < ctx->parser->shader_desc.ssa_count) -+ { -+ struct validation_context_ssa_data *data = &ctx->ssas[src->reg.idx[0].offset]; -+ unsigned int i; -+ -+ for (i = 0; i < VKD3D_VEC4_SIZE; ++i) -+ data->read_mask |= (1u << vsir_swizzle_get_component(src->swizzle, i)); -+ } - } - - static void vsir_validate_dst_count(struct validation_context *ctx, -@@ -1877,22 +1998,52 @@ static void vsir_validate_instruction(struct validation_context *ctx) - } - } - --void vsir_validate(struct vkd3d_shader_parser *parser) -+enum vkd3d_result vsir_validate(struct vkd3d_shader_parser *parser) - { - struct validation_context ctx = - { - .parser = parser, - .phase = VKD3DSIH_INVALID, - }; -+ unsigned int i; - - if (!(parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)) -- return; -+ return VKD3D_OK; -+ -+ if (!(ctx.temps = vkd3d_calloc(parser->shader_desc.temp_count, sizeof(*ctx.temps)))) -+ goto fail; -+ -+ if (!(ctx.ssas = vkd3d_calloc(parser->shader_desc.ssa_count, sizeof(*ctx.ssas)))) -+ goto fail; - - for (ctx.instruction_idx = 0; ctx.instruction_idx < parser->instructions.count; ++ctx.instruction_idx) - vsir_validate_instruction(&ctx); - -+ ctx.invalid_instruction_idx = true; -+ - if (ctx.depth != 0) - validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "%zu nested blocks were not closed.", ctx.depth); - -- free(ctx.blocks); -+ for (i = 0; i < parser->shader_desc.ssa_count; ++i) -+ { -+ struct validation_context_ssa_data *data = &ctx.ssas[i]; -+ -+ if ((data->write_mask | data->read_mask) != data->write_mask) -+ validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE, -+ "SSA register %u has invalid read mask %#x, which is not a subset of the write mask %#x " -+ "at the point of definition.", i, data->read_mask, data->write_mask); -+ } -+ -+ vkd3d_free(ctx.blocks); -+ vkd3d_free(ctx.temps); -+ vkd3d_free(ctx.ssas); -+ -+ return VKD3D_OK; -+ -+fail: -+ vkd3d_free(ctx.blocks); -+ vkd3d_free(ctx.temps); -+ vkd3d_free(ctx.ssas); -+ -+ return VKD3D_ERROR_OUT_OF_MEMORY; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index a9e02d0a98e..7743319bed5 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -6907,8 +6907,8 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp - const struct vkd3d_shader_src_param *src = instruction->src; - uint32_t src_id[SPIRV_MAX_SRC_COUNT]; - uint32_t instr_set_id, type_id, val_id; -+ unsigned int i, component_count; - enum GLSLstd450 glsl_inst; -- unsigned int i; - - glsl_inst = spirv_compiler_map_ext_glsl_instruction(instruction); - if (glsl_inst == GLSLstd450Bad) -@@ -6934,8 +6934,9 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp - || instruction->handler_idx == VKD3DSIH_FIRSTBIT_SHI) - { - /* In D3D bits are numbered from the most significant bit. */ -+ component_count = vsir_write_mask_component_count(dst->write_mask); - val_id = vkd3d_spirv_build_op_isub(builder, type_id, -- spirv_compiler_get_constant_uint(compiler, 31), val_id); -+ spirv_compiler_get_constant_uint_vector(compiler, 31, component_count), val_id); - } - - spirv_compiler_emit_store_dst(compiler, dst, val_id); -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 43b3525bb7b..1f1944bc0da 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -821,7 +821,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u - const uint32_t *end = &tokens[token_count]; - enum vkd3d_sm4_data_type data_type; - enum vkd3d_data_type reg_data_type; -- DWORD components; -+ uint32_t components; - unsigned int i; - - resource_type = (opcode_token & VKD3D_SM4_RESOURCE_TYPE_MASK) >> VKD3D_SM4_RESOURCE_TYPE_SHIFT; -@@ -1759,11 +1759,11 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - const struct vkd3d_sm4_register_type_info *register_type_info; - enum vkd3d_shader_register_type vsir_register_type; - enum vkd3d_sm4_register_precision precision; -+ uint32_t token, order, extended, addressing; - enum vkd3d_sm4_register_type register_type; - enum vkd3d_sm4_extended_operand_type type; -- enum vkd3d_sm4_register_modifier m; - enum vkd3d_sm4_dimension sm4_dimension; -- uint32_t token, order, extended; -+ enum vkd3d_sm4_register_modifier m; - - if (*ptr >= end) - { -@@ -1861,7 +1861,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - - if (order >= 1) - { -- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK0) >> VKD3D_SM4_ADDRESSING_SHIFT0; -+ addressing = (token & VKD3D_SM4_ADDRESSING_MASK0) >> VKD3D_SM4_ADDRESSING_SHIFT0; - if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[0]))) - { - ERR("Failed to read register index.\n"); -@@ -1871,7 +1871,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - - if (order >= 2) - { -- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK1) >> VKD3D_SM4_ADDRESSING_SHIFT1; -+ addressing = (token & VKD3D_SM4_ADDRESSING_MASK1) >> VKD3D_SM4_ADDRESSING_SHIFT1; - if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[1]))) - { - ERR("Failed to read register index.\n"); -@@ -1881,7 +1881,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui - - if (order >= 3) - { -- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK2) >> VKD3D_SM4_ADDRESSING_SHIFT2; -+ addressing = (token & VKD3D_SM4_ADDRESSING_MASK2) >> VKD3D_SM4_ADDRESSING_SHIFT2; - if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[2]))) - { - ERR("Failed to read register index.\n"); -@@ -2075,7 +2075,7 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons - const uint32_t *end, enum vkd3d_data_type data_type, struct vkd3d_shader_src_param *src_param) - { - unsigned int dimension, mask; -- DWORD token; -+ uint32_t token; - - if (*ptr >= end) - { -@@ -2162,7 +2162,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons - enum vkd3d_sm4_swizzle_type swizzle_type; - enum vkd3d_shader_src_modifier modifier; - unsigned int dimension, swizzle; -- DWORD token; -+ uint32_t token; - - if (*ptr >= end) - { -@@ -2242,7 +2242,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons - return true; - } - --static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_shader_instruction *ins) -+static void shader_sm4_read_instruction_modifier(uint32_t modifier, struct vkd3d_shader_instruction *ins) - { - enum vkd3d_sm4_instruction_modifier modifier_type = modifier & VKD3D_SM4_MODIFIER_MASK; - -@@ -2250,7 +2250,7 @@ static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_sh - { - case VKD3D_SM4_MODIFIER_AOFFIMMI: - { -- static const DWORD recognized_bits = VKD3D_SM4_INSTRUCTION_MODIFIER -+ static const uint32_t recognized_bits = VKD3D_SM4_INSTRUCTION_MODIFIER - | VKD3D_SM4_MODIFIER_MASK - | VKD3D_SM4_AOFFIMMI_U_MASK - | VKD3D_SM4_AOFFIMMI_V_MASK -@@ -2278,7 +2278,7 @@ static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_sh - - case VKD3D_SM5_MODIFIER_DATA_TYPE: - { -- DWORD components = (modifier & VKD3D_SM5_MODIFIER_DATA_TYPE_MASK) >> VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT; -+ uint32_t components = (modifier & VKD3D_SM5_MODIFIER_DATA_TYPE_MASK) >> VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT; - unsigned int i; - - for (i = 0; i < VKD3D_VEC4_SIZE; i++) -@@ -2334,9 +2334,9 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str - struct vkd3d_shader_src_param *src_params; - const uint32_t **ptr = &sm4->ptr; - unsigned int i, len; -- size_t remaining; - const uint32_t *p; -- DWORD precise; -+ uint32_t precise; -+ size_t remaining; - - if (*ptr >= sm4->end) - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index cc156f88074..0af7ea0d266 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -216,6 +216,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS = 9014, - VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX = 9015, - VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING = 9016, -+ VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE = 9017, - - VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300, - }; -@@ -1450,7 +1451,7 @@ int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info, - int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); - --void vsir_validate(struct vkd3d_shader_parser *parser); -+enum vkd3d_result vsir_validate(struct vkd3d_shader_parser *parser); - - static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type( - enum vkd3d_data_type data_type) --- -2.43.0 -