From 6336965159696d5dae2cd853c4e4a706fbfdc6fa Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 24 Jul 2025 07:31:47 +1000 Subject: [PATCH] Updated vkd3d-latest patchset --- ...3163e589bc41b674c46750bef9a3cbbaa90.patch} | 11782 +++++++++++++--- ...-a8ca1f95c50561a16de5769646dcda0c045.patch | 6661 --------- ...-7c0da1747a89a8cea27a42ace51b318e9d8.patch | 501 - ...-ba545669cd09682960f5da17b9131780642.patch | 135 + ...-9d490b83d4d6c9b8cbb5bcfa5a2e6aadf25.patch | 931 -- ...-decc155cca45d7c4a60699990452b921a6e.patch | 3953 ++++++ ...-68cd72c7fc7a364ecce87a19617acb382c7.patch | 1701 +++ ...-d8edf20c2b4224384d8e206c620bfbd61c5.patch | 2731 ---- ...-5452e79a19c0b895d0c2ac22d3da5595a57.patch | 699 - ...-a4c25b81c59ae783a94c1b25714eb080231.patch | 2302 +++ patches/vkd3d-latest/definition | 1 - 11 files changed, 18201 insertions(+), 13196 deletions(-) rename patches/vkd3d-latest/{0006-Updated-vkd3d-to-0c3250122cb7dcefef171d1288a1b704a30.patch => 0001-Updated-vkd3d-to-3163e589bc41b674c46750bef9a3cbbaa90.patch} (51%) delete mode 100644 patches/vkd3d-latest/0001-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch delete mode 100644 patches/vkd3d-latest/0002-Updated-vkd3d-to-7c0da1747a89a8cea27a42ace51b318e9d8.patch create mode 100644 patches/vkd3d-latest/0002-Updated-vkd3d-to-ba545669cd09682960f5da17b9131780642.patch delete mode 100644 patches/vkd3d-latest/0003-Updated-vkd3d-to-9d490b83d4d6c9b8cbb5bcfa5a2e6aadf25.patch create mode 100644 patches/vkd3d-latest/0003-Updated-vkd3d-to-decc155cca45d7c4a60699990452b921a6e.patch create mode 100644 patches/vkd3d-latest/0004-Updated-vkd3d-to-68cd72c7fc7a364ecce87a19617acb382c7.patch delete mode 100644 patches/vkd3d-latest/0004-Updated-vkd3d-to-d8edf20c2b4224384d8e206c620bfbd61c5.patch delete mode 100644 patches/vkd3d-latest/0005-Updated-vkd3d-to-5452e79a19c0b895d0c2ac22d3da5595a57.patch create mode 100644 patches/vkd3d-latest/0005-Updated-vkd3d-to-a4c25b81c59ae783a94c1b25714eb080231.patch delete mode 100644 patches/vkd3d-latest/definition diff --git a/patches/vkd3d-latest/0006-Updated-vkd3d-to-0c3250122cb7dcefef171d1288a1b704a30.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-3163e589bc41b674c46750bef9a3cbbaa90.patch similarity index 51% rename from patches/vkd3d-latest/0006-Updated-vkd3d-to-0c3250122cb7dcefef171d1288a1b704a30.patch rename to patches/vkd3d-latest/0001-Updated-vkd3d-to-3163e589bc41b674c46750bef9a3cbbaa90.patch index 7f9e0844..e32a8d1e 100644 --- a/patches/vkd3d-latest/0006-Updated-vkd3d-to-0c3250122cb7dcefef171d1288a1b704a30.patch +++ b/patches/vkd3d-latest/0001-Updated-vkd3d-to-3163e589bc41b674c46750bef9a3cbbaa90.patch @@ -1,30 +1,453 @@ -From 8d41d4b89e716cec200618599e2eb070a781c13f Mon Sep 17 00:00:00 2001 +From 2ad0e772bf3539c14f8a42491c8334e005180cbe Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes -Date: Fri, 27 Jun 2025 08:08:51 +1000 -Subject: [PATCH] Updated vkd3d to 0c3250122cb7dcefef171d1288a1b704a303d4a1. +Date: Mon, 26 May 2025 07:03:34 +1000 +Subject: [PATCH] Updated vkd3d to 3163e589bc41b674c46750bef9a3cbbaa90fc560. --- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 184 +- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 371 +-- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 560 ++-- - libs/vkd3d/libs/vkd3d-shader/glsl.c | 160 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 2 +- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 489 ++-- - libs/vkd3d/libs/vkd3d-shader/ir.c | 2294 +++++++++-------- - libs/vkd3d/libs/vkd3d-shader/msl.c | 182 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 898 ++++--- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 795 +++--- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 124 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 669 ++--- - libs/vkd3d/libs/vkd3d/resource.c | 27 +- - libs/vkd3d/libs/vkd3d/vkd3d_private.h | 2 +- - 14 files changed, 3453 insertions(+), 3304 deletions(-) + libs/vkd3d/include/private/vkd3d_common.h | 3 +- + libs/vkd3d/include/private/vkd3d_version.h | 2 +- + libs/vkd3d/include/vkd3d_shader.h | 6 + + libs/vkd3d/libs/vkd3d-common/blob.c | 1 + + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 517 +-- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 407 +-- + libs/vkd3d/libs/vkd3d-shader/dxbc.c | 10 +- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 1547 +++++---- + libs/vkd3d/libs/vkd3d-shader/fx.c | 1347 +++++--- + libs/vkd3d/libs/vkd3d-shader/glsl.c | 207 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 25 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 11 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 41 +- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 867 +++-- + libs/vkd3d/libs/vkd3d-shader/ir.c | 2854 ++++++++++++++--- + libs/vkd3d/libs/vkd3d-shader/msl.c | 956 +++++- + libs/vkd3d/libs/vkd3d-shader/preproc.h | 2 +- + libs/vkd3d/libs/vkd3d-shader/preproc.l | 39 +- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 1179 +++---- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 865 ++--- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 194 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 700 ++-- + .../vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c | 2 + + libs/vkd3d/libs/vkd3d/resource.c | 73 +- + libs/vkd3d/libs/vkd3d/state.c | 12 + + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 13 +- + 26 files changed, 7383 insertions(+), 4497 deletions(-) +diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h +index beb23257fb7..0501e6a06c2 100644 +--- a/libs/vkd3d/include/private/vkd3d_common.h ++++ b/libs/vkd3d/include/private/vkd3d_common.h +@@ -66,6 +66,7 @@ + + #define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9') + #define TAG_CLI4 VKD3D_MAKE_TAG('C', 'L', 'I', '4') ++#define TAG_CLIT VKD3D_MAKE_TAG('C', 'L', 'I', 'T') + #define TAG_CTAB VKD3D_MAKE_TAG('C', 'T', 'A', 'B') + #define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C') + #define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L') +@@ -278,7 +279,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/private/vkd3d_version.h b/libs/vkd3d/include/private/vkd3d_version.h +index 0edc4428022..687751d6a5f 100644 +--- a/libs/vkd3d/include/private/vkd3d_version.h ++++ b/libs/vkd3d/include/private/vkd3d_version.h +@@ -1 +1 @@ +-#define VKD3D_VCS_ID " (Wine bundled)" ++#define VKD3D_VCS_ID " (git a8ca1f95)" +diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h +index 30b6a070018..b50271ce9bb 100644 +--- a/libs/vkd3d/include/vkd3d_shader.h ++++ b/libs/vkd3d/include/vkd3d_shader.h +@@ -1431,6 +1431,11 @@ enum vkd3d_shader_source_type + * Input is a raw FX section without container. \since 1.14 + */ + VKD3D_SHADER_SOURCE_FX, ++ /** ++ * A D3DX texture shader. This is the format used for the 'tx_1_0' HLSL ++ * target profile. \since 1.17 ++ */ ++ VKD3D_SHADER_SOURCE_TX, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SOURCE_TYPE), + }; +@@ -2761,6 +2766,7 @@ VKD3D_SHADER_API const enum vkd3d_shader_target_type *vkd3d_shader_get_supported + * - VKD3D_SHADER_SOURCE_HLSL to VKD3D_SHADER_TARGET_DXBC_TPF + * - VKD3D_SHADER_SOURCE_HLSL to VKD3D_SHADER_TARGET_FX + * - VKD3D_SHADER_SOURCE_FX to VKD3D_SHADER_TARGET_D3D_ASM ++ * - VKD3D_SHADER_SOURCE_TX to VKD3D_SHADER_TARGET_D3D_ASM + * + * Supported transformations can also be detected at runtime with the functions + * vkd3d_shader_get_supported_source_types() and +diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c +index f60ef7db769..c2c6ad67804 100644 +--- a/libs/vkd3d/libs/vkd3d-common/blob.c ++++ b/libs/vkd3d/libs/vkd3d-common/blob.c +@@ -20,6 +20,7 @@ + #define WIDL_C_INLINE_WRAPPERS + #endif + #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 21feb75d639..ae9278f68b1 100644 +index 4521bfabd8e..ae9278f68b1 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -715,8 +715,8 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const +@@ -27,333 +27,6 @@ + #include + #include + +-static const char * const shader_opcode_names[] = +-{ +- [VKD3DSIH_ABS ] = "abs", +- [VKD3DSIH_ACOS ] = "acos", +- [VKD3DSIH_ADD ] = "add", +- [VKD3DSIH_AND ] = "and", +- [VKD3DSIH_ASIN ] = "asin", +- [VKD3DSIH_ATAN ] = "atan", +- [VKD3DSIH_ATOMIC_AND ] = "atomic_and", +- [VKD3DSIH_ATOMIC_CMP_STORE ] = "atomic_cmp_store", +- [VKD3DSIH_ATOMIC_IADD ] = "atomic_iadd", +- [VKD3DSIH_ATOMIC_IMAX ] = "atomic_imax", +- [VKD3DSIH_ATOMIC_IMIN ] = "atomic_imin", +- [VKD3DSIH_ATOMIC_OR ] = "atomic_or", +- [VKD3DSIH_ATOMIC_UMAX ] = "atomic_umax", +- [VKD3DSIH_ATOMIC_UMIN ] = "atomic_umin", +- [VKD3DSIH_ATOMIC_XOR ] = "atomic_xor", +- [VKD3DSIH_BEM ] = "bem", +- [VKD3DSIH_BFI ] = "bfi", +- [VKD3DSIH_BFREV ] = "bfrev", +- [VKD3DSIH_BRANCH ] = "branch", +- [VKD3DSIH_BREAK ] = "break", +- [VKD3DSIH_BREAKC ] = "break", +- [VKD3DSIH_BREAKP ] = "breakp", +- [VKD3DSIH_BUFINFO ] = "bufinfo", +- [VKD3DSIH_CALL ] = "call", +- [VKD3DSIH_CALLNZ ] = "callnz", +- [VKD3DSIH_CASE ] = "case", +- [VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED ] = "check_access_fully_mapped", +- [VKD3DSIH_CMP ] = "cmp", +- [VKD3DSIH_CND ] = "cnd", +- [VKD3DSIH_CONTINUE ] = "continue", +- [VKD3DSIH_CONTINUEP ] = "continuec", +- [VKD3DSIH_COUNTBITS ] = "countbits", +- [VKD3DSIH_CRS ] = "crs", +- [VKD3DSIH_CUT ] = "cut", +- [VKD3DSIH_CUT_STREAM ] = "cut_stream", +- [VKD3DSIH_DADD ] = "dadd", +- [VKD3DSIH_DCL ] = "dcl", +- [VKD3DSIH_DCL_CONSTANT_BUFFER ] = "dcl_constantBuffer", +- [VKD3DSIH_DCL_FUNCTION_BODY ] = "dcl_function_body", +- [VKD3DSIH_DCL_FUNCTION_TABLE ] = "dcl_function_table", +- [VKD3DSIH_DCL_GLOBAL_FLAGS ] = "dcl_globalFlags", +- [VKD3DSIH_DCL_GS_INSTANCES ] = "dcl_gs_instances", +- [VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT] = "dcl_hs_fork_phase_instance_count", +- [VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT] = "dcl_hs_join_phase_instance_count", +- [VKD3DSIH_DCL_HS_MAX_TESSFACTOR ] = "dcl_hs_max_tessfactor", +- [VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER ] = "dcl_immediateConstantBuffer", +- [VKD3DSIH_DCL_INDEX_RANGE ] = "dcl_index_range", +- [VKD3DSIH_DCL_INDEXABLE_TEMP ] = "dcl_indexableTemp", +- [VKD3DSIH_DCL_INPUT ] = "dcl_input", +- [VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT ] = "dcl_input_control_point_count", +- [VKD3DSIH_DCL_INPUT_PRIMITIVE ] = "dcl_inputprimitive", +- [VKD3DSIH_DCL_INPUT_PS ] = "dcl_input_ps", +- [VKD3DSIH_DCL_INPUT_PS_SGV ] = "dcl_input_ps_sgv", +- [VKD3DSIH_DCL_INPUT_PS_SIV ] = "dcl_input_ps_siv", +- [VKD3DSIH_DCL_INPUT_SGV ] = "dcl_input_sgv", +- [VKD3DSIH_DCL_INPUT_SIV ] = "dcl_input_siv", +- [VKD3DSIH_DCL_INTERFACE ] = "dcl_interface", +- [VKD3DSIH_DCL_OUTPUT ] = "dcl_output", +- [VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT ] = "dcl_output_control_point_count", +- [VKD3DSIH_DCL_OUTPUT_SIV ] = "dcl_output_siv", +- [VKD3DSIH_DCL_OUTPUT_TOPOLOGY ] = "dcl_outputtopology", +- [VKD3DSIH_DCL_RESOURCE_RAW ] = "dcl_resource_raw", +- [VKD3DSIH_DCL_RESOURCE_STRUCTURED ] = "dcl_resource_structured", +- [VKD3DSIH_DCL_SAMPLER ] = "dcl_sampler", +- [VKD3DSIH_DCL_STREAM ] = "dcl_stream", +- [VKD3DSIH_DCL_TEMPS ] = "dcl_temps", +- [VKD3DSIH_DCL_TESSELLATOR_DOMAIN ] = "dcl_tessellator_domain", +- [VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE] = "dcl_tessellator_output_primitive", +- [VKD3DSIH_DCL_TESSELLATOR_PARTITIONING ] = "dcl_tessellator_partitioning", +- [VKD3DSIH_DCL_TGSM_RAW ] = "dcl_tgsm_raw", +- [VKD3DSIH_DCL_TGSM_STRUCTURED ] = "dcl_tgsm_structured", +- [VKD3DSIH_DCL_THREAD_GROUP ] = "dcl_thread_group", +- [VKD3DSIH_DCL_UAV_RAW ] = "dcl_uav_raw", +- [VKD3DSIH_DCL_UAV_STRUCTURED ] = "dcl_uav_structured", +- [VKD3DSIH_DCL_UAV_TYPED ] = "dcl_uav_typed", +- [VKD3DSIH_DCL_VERTICES_OUT ] = "dcl_maxout", +- [VKD3DSIH_DDIV ] = "ddiv", +- [VKD3DSIH_DEF ] = "def", +- [VKD3DSIH_DEFAULT ] = "default", +- [VKD3DSIH_DEFB ] = "defb", +- [VKD3DSIH_DEFI ] = "defi", +- [VKD3DSIH_DEQO ] = "deq", +- [VKD3DSIH_DFMA ] = "dfma", +- [VKD3DSIH_DGEO ] = "dge", +- [VKD3DSIH_DISCARD ] = "discard", +- [VKD3DSIH_DIV ] = "div", +- [VKD3DSIH_DLT ] = "dlt", +- [VKD3DSIH_DMAX ] = "dmax", +- [VKD3DSIH_DMIN ] = "dmin", +- [VKD3DSIH_DMOV ] = "dmov", +- [VKD3DSIH_DMOVC ] = "dmovc", +- [VKD3DSIH_DMUL ] = "dmul", +- [VKD3DSIH_DNE ] = "dne", +- [VKD3DSIH_DP2 ] = "dp2", +- [VKD3DSIH_DP2ADD ] = "dp2add", +- [VKD3DSIH_DP3 ] = "dp3", +- [VKD3DSIH_DP4 ] = "dp4", +- [VKD3DSIH_DRCP ] = "drcp", +- [VKD3DSIH_DST ] = "dst", +- [VKD3DSIH_DSX ] = "dsx", +- [VKD3DSIH_DSX_COARSE ] = "deriv_rtx_coarse", +- [VKD3DSIH_DSX_FINE ] = "deriv_rtx_fine", +- [VKD3DSIH_DSY ] = "dsy", +- [VKD3DSIH_DSY_COARSE ] = "deriv_rty_coarse", +- [VKD3DSIH_DSY_FINE ] = "deriv_rty_fine", +- [VKD3DSIH_DTOF ] = "dtof", +- [VKD3DSIH_DTOI ] = "dtoi", +- [VKD3DSIH_DTOU ] = "dtou", +- [VKD3DSIH_ELSE ] = "else", +- [VKD3DSIH_EMIT ] = "emit", +- [VKD3DSIH_EMIT_STREAM ] = "emit_stream", +- [VKD3DSIH_ENDIF ] = "endif", +- [VKD3DSIH_ENDLOOP ] = "endloop", +- [VKD3DSIH_ENDREP ] = "endrep", +- [VKD3DSIH_ENDSWITCH ] = "endswitch", +- [VKD3DSIH_EQO ] = "eq", +- [VKD3DSIH_EQU ] = "eq_unord", +- [VKD3DSIH_EVAL_CENTROID ] = "eval_centroid", +- [VKD3DSIH_EVAL_SAMPLE_INDEX ] = "eval_sample_index", +- [VKD3DSIH_EXP ] = "exp", +- [VKD3DSIH_EXPP ] = "expp", +- [VKD3DSIH_F16TOF32 ] = "f16tof32", +- [VKD3DSIH_F32TOF16 ] = "f32tof16", +- [VKD3DSIH_FCALL ] = "fcall", +- [VKD3DSIH_FIRSTBIT_HI ] = "firstbit_hi", +- [VKD3DSIH_FIRSTBIT_LO ] = "firstbit_lo", +- [VKD3DSIH_FIRSTBIT_SHI ] = "firstbit_shi", +- [VKD3DSIH_FRC ] = "frc", +- [VKD3DSIH_FREM ] = "frem", +- [VKD3DSIH_FTOD ] = "ftod", +- [VKD3DSIH_FTOI ] = "ftoi", +- [VKD3DSIH_FTOU ] = "ftou", +- [VKD3DSIH_GATHER4 ] = "gather4", +- [VKD3DSIH_GATHER4_C ] = "gather4_c", +- [VKD3DSIH_GATHER4_C_S ] = "gather4_c_s", +- [VKD3DSIH_GATHER4_PO ] = "gather4_po", +- [VKD3DSIH_GATHER4_PO_C ] = "gather4_po_c", +- [VKD3DSIH_GATHER4_PO_C_S ] = "gather4_po_c_s", +- [VKD3DSIH_GATHER4_PO_S ] = "gather4_po_s", +- [VKD3DSIH_GATHER4_S ] = "gather4_s", +- [VKD3DSIH_GEO ] = "ge", +- [VKD3DSIH_GEU ] = "ge_unord", +- [VKD3DSIH_HCOS ] = "hcos", +- [VKD3DSIH_HS_CONTROL_POINT_PHASE ] = "hs_control_point_phase", +- [VKD3DSIH_HS_DECLS ] = "hs_decls", +- [VKD3DSIH_HS_FORK_PHASE ] = "hs_fork_phase", +- [VKD3DSIH_HS_JOIN_PHASE ] = "hs_join_phase", +- [VKD3DSIH_HSIN ] = "hsin", +- [VKD3DSIH_HTAN ] = "htan", +- [VKD3DSIH_IADD ] = "iadd", +- [VKD3DSIH_IBFE ] = "ibfe", +- [VKD3DSIH_IDIV ] = "idiv", +- [VKD3DSIH_IEQ ] = "ieq", +- [VKD3DSIH_IF ] = "if", +- [VKD3DSIH_IFC ] = "if", +- [VKD3DSIH_IGE ] = "ige", +- [VKD3DSIH_ILT ] = "ilt", +- [VKD3DSIH_IMAD ] = "imad", +- [VKD3DSIH_IMAX ] = "imax", +- [VKD3DSIH_IMIN ] = "imin", +- [VKD3DSIH_IMM_ATOMIC_ALLOC ] = "imm_atomic_alloc", +- [VKD3DSIH_IMM_ATOMIC_AND ] = "imm_atomic_and", +- [VKD3DSIH_IMM_ATOMIC_CMP_EXCH ] = "imm_atomic_cmp_exch", +- [VKD3DSIH_IMM_ATOMIC_CONSUME ] = "imm_atomic_consume", +- [VKD3DSIH_IMM_ATOMIC_EXCH ] = "imm_atomic_exch", +- [VKD3DSIH_IMM_ATOMIC_IADD ] = "imm_atomic_iadd", +- [VKD3DSIH_IMM_ATOMIC_IMAX ] = "imm_atomic_imax", +- [VKD3DSIH_IMM_ATOMIC_IMIN ] = "imm_atomic_imin", +- [VKD3DSIH_IMM_ATOMIC_OR ] = "imm_atomic_or", +- [VKD3DSIH_IMM_ATOMIC_UMAX ] = "imm_atomic_umax", +- [VKD3DSIH_IMM_ATOMIC_UMIN ] = "imm_atomic_umin", +- [VKD3DSIH_IMM_ATOMIC_XOR ] = "imm_atomic_xor", +- [VKD3DSIH_IMUL ] = "imul", +- [VKD3DSIH_INE ] = "ine", +- [VKD3DSIH_INEG ] = "ineg", +- [VKD3DSIH_ISFINITE ] = "isfinite", +- [VKD3DSIH_ISHL ] = "ishl", +- [VKD3DSIH_ISHR ] = "ishr", +- [VKD3DSIH_ISINF ] = "isinf", +- [VKD3DSIH_ISNAN ] = "isnan", +- [VKD3DSIH_ITOD ] = "itod", +- [VKD3DSIH_ITOF ] = "itof", +- [VKD3DSIH_ITOI ] = "itoi", +- [VKD3DSIH_LABEL ] = "label", +- [VKD3DSIH_LD ] = "ld", +- [VKD3DSIH_LD2DMS ] = "ld2dms", +- [VKD3DSIH_LD2DMS_S ] = "ld2dms_s", +- [VKD3DSIH_LD_RAW ] = "ld_raw", +- [VKD3DSIH_LD_RAW_S ] = "ld_raw_s", +- [VKD3DSIH_LD_S ] = "ld_s", +- [VKD3DSIH_LD_STRUCTURED ] = "ld_structured", +- [VKD3DSIH_LD_STRUCTURED_S ] = "ld_structured_s", +- [VKD3DSIH_LD_UAV_TYPED ] = "ld_uav_typed", +- [VKD3DSIH_LD_UAV_TYPED_S ] = "ld_uav_typed_s", +- [VKD3DSIH_LIT ] = "lit", +- [VKD3DSIH_LOD ] = "lod", +- [VKD3DSIH_LOG ] = "log", +- [VKD3DSIH_LOGP ] = "logp", +- [VKD3DSIH_LOOP ] = "loop", +- [VKD3DSIH_LRP ] = "lrp", +- [VKD3DSIH_LTO ] = "lt", +- [VKD3DSIH_LTU ] = "lt_unord", +- [VKD3DSIH_M3x2 ] = "m3x2", +- [VKD3DSIH_M3x3 ] = "m3x3", +- [VKD3DSIH_M3x4 ] = "m3x4", +- [VKD3DSIH_M4x3 ] = "m4x3", +- [VKD3DSIH_M4x4 ] = "m4x4", +- [VKD3DSIH_MAD ] = "mad", +- [VKD3DSIH_MAX ] = "max", +- [VKD3DSIH_MIN ] = "min", +- [VKD3DSIH_MOV ] = "mov", +- [VKD3DSIH_MOVA ] = "mova", +- [VKD3DSIH_MOVC ] = "movc", +- [VKD3DSIH_MSAD ] = "msad", +- [VKD3DSIH_MUL ] = "mul", +- [VKD3DSIH_NEO ] = "ne_ord", +- [VKD3DSIH_NEU ] = "ne", +- [VKD3DSIH_NOP ] = "nop", +- [VKD3DSIH_NOT ] = "not", +- [VKD3DSIH_NRM ] = "nrm", +- [VKD3DSIH_OR ] = "or", +- [VKD3DSIH_ORD ] = "ord", +- [VKD3DSIH_PHASE ] = "phase", +- [VKD3DSIH_PHI ] = "phi", +- [VKD3DSIH_POW ] = "pow", +- [VKD3DSIH_QUAD_READ_ACROSS_D ] = "quad_read_across_d", +- [VKD3DSIH_QUAD_READ_ACROSS_X ] = "quad_read_across_x", +- [VKD3DSIH_QUAD_READ_ACROSS_Y ] = "quad_read_across_y", +- [VKD3DSIH_QUAD_READ_LANE_AT ] = "quad_read_lane_at", +- [VKD3DSIH_RCP ] = "rcp", +- [VKD3DSIH_REP ] = "rep", +- [VKD3DSIH_RESINFO ] = "resinfo", +- [VKD3DSIH_RET ] = "ret", +- [VKD3DSIH_RETP ] = "retp", +- [VKD3DSIH_ROUND_NE ] = "round_ne", +- [VKD3DSIH_ROUND_NI ] = "round_ni", +- [VKD3DSIH_ROUND_PI ] = "round_pi", +- [VKD3DSIH_ROUND_Z ] = "round_z", +- [VKD3DSIH_RSQ ] = "rsq", +- [VKD3DSIH_SAMPLE ] = "sample", +- [VKD3DSIH_SAMPLE_B ] = "sample_b", +- [VKD3DSIH_SAMPLE_B_CL_S ] = "sample_b_cl_s", +- [VKD3DSIH_SAMPLE_C ] = "sample_c", +- [VKD3DSIH_SAMPLE_C_CL_S ] = "sample_c_cl_s", +- [VKD3DSIH_SAMPLE_C_LZ ] = "sample_c_lz", +- [VKD3DSIH_SAMPLE_C_LZ_S ] = "sample_c_lz_s", +- [VKD3DSIH_SAMPLE_CL_S ] = "sample_cl_s", +- [VKD3DSIH_SAMPLE_GRAD ] = "sample_d", +- [VKD3DSIH_SAMPLE_GRAD_CL_S ] = "sample_d_cl_s", +- [VKD3DSIH_SAMPLE_INFO ] = "sample_info", +- [VKD3DSIH_SAMPLE_LOD ] = "sample_l", +- [VKD3DSIH_SAMPLE_LOD_S ] = "sample_l_s", +- [VKD3DSIH_SAMPLE_POS ] = "sample_pos", +- [VKD3DSIH_SETP ] = "setp", +- [VKD3DSIH_SGE ] = "sge", +- [VKD3DSIH_SGN ] = "sgn", +- [VKD3DSIH_SINCOS ] = "sincos", +- [VKD3DSIH_SLT ] = "slt", +- [VKD3DSIH_SQRT ] = "sqrt", +- [VKD3DSIH_STORE_RAW ] = "store_raw", +- [VKD3DSIH_STORE_STRUCTURED ] = "store_structured", +- [VKD3DSIH_STORE_UAV_TYPED ] = "store_uav_typed", +- [VKD3DSIH_SUB ] = "sub", +- [VKD3DSIH_SWAPC ] = "swapc", +- [VKD3DSIH_SWITCH ] = "switch", +- [VKD3DSIH_SWITCH_MONOLITHIC ] = "switch", +- [VKD3DSIH_SYNC ] = "sync", +- [VKD3DSIH_TAN ] = "tan", +- [VKD3DSIH_TEX ] = "texld", +- [VKD3DSIH_TEXBEM ] = "texbem", +- [VKD3DSIH_TEXBEML ] = "texbeml", +- [VKD3DSIH_TEXCOORD ] = "texcrd", +- [VKD3DSIH_TEXDEPTH ] = "texdepth", +- [VKD3DSIH_TEXDP3 ] = "texdp3", +- [VKD3DSIH_TEXDP3TEX ] = "texdp3tex", +- [VKD3DSIH_TEXKILL ] = "texkill", +- [VKD3DSIH_TEXLDD ] = "texldd", +- [VKD3DSIH_TEXLDL ] = "texldl", +- [VKD3DSIH_TEXM3x2DEPTH ] = "texm3x2depth", +- [VKD3DSIH_TEXM3x2PAD ] = "texm3x2pad", +- [VKD3DSIH_TEXM3x2TEX ] = "texm3x2tex", +- [VKD3DSIH_TEXM3x3 ] = "texm3x3", +- [VKD3DSIH_TEXM3x3DIFF ] = "texm3x3diff", +- [VKD3DSIH_TEXM3x3PAD ] = "texm3x3pad", +- [VKD3DSIH_TEXM3x3SPEC ] = "texm3x3spec", +- [VKD3DSIH_TEXM3x3TEX ] = "texm3x3tex", +- [VKD3DSIH_TEXM3x3VSPEC ] = "texm3x3vspec", +- [VKD3DSIH_TEXREG2AR ] = "texreg2ar", +- [VKD3DSIH_TEXREG2GB ] = "texreg2gb", +- [VKD3DSIH_TEXREG2RGB ] = "texreg2rgb", +- [VKD3DSIH_UBFE ] = "ubfe", +- [VKD3DSIH_UDIV ] = "udiv", +- [VKD3DSIH_UGE ] = "uge", +- [VKD3DSIH_ULT ] = "ult", +- [VKD3DSIH_UMAX ] = "umax", +- [VKD3DSIH_UMIN ] = "umin", +- [VKD3DSIH_UMUL ] = "umul", +- [VKD3DSIH_UNO ] = "uno", +- [VKD3DSIH_USHR ] = "ushr", +- [VKD3DSIH_UTOD ] = "utod", +- [VKD3DSIH_UTOF ] = "utof", +- [VKD3DSIH_UTOU ] = "utou", +- [VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL ] = "wave_active_all_equal", +- [VKD3DSIH_WAVE_ACTIVE_BALLOT ] = "wave_active_ballot", +- [VKD3DSIH_WAVE_ACTIVE_BIT_AND ] = "wave_active_bit_and", +- [VKD3DSIH_WAVE_ACTIVE_BIT_OR ] = "wave_active_bit_or", +- [VKD3DSIH_WAVE_ACTIVE_BIT_XOR ] = "wave_active_bit_xor", +- [VKD3DSIH_WAVE_ALL_BIT_COUNT ] = "wave_all_bit_count", +- [VKD3DSIH_WAVE_ALL_TRUE ] = "wave_all_true", +- [VKD3DSIH_WAVE_ANY_TRUE ] = "wave_any_true", +- [VKD3DSIH_WAVE_IS_FIRST_LANE ] = "wave_is_first_lane", +- [VKD3DSIH_WAVE_OP_ADD ] = "wave_op_add", +- [VKD3DSIH_WAVE_OP_IMAX ] = "wave_op_imax", +- [VKD3DSIH_WAVE_OP_IMIN ] = "wave_op_imin", +- [VKD3DSIH_WAVE_OP_MAX ] = "wave_op_max", +- [VKD3DSIH_WAVE_OP_MIN ] = "wave_op_min", +- [VKD3DSIH_WAVE_OP_MUL ] = "wave_op_mul", +- [VKD3DSIH_WAVE_OP_UMAX ] = "wave_op_umax", +- [VKD3DSIH_WAVE_OP_UMIN ] = "wave_op_umin", +- [VKD3DSIH_WAVE_PREFIX_BIT_COUNT ] = "wave_prefix_bit_count", +- [VKD3DSIH_WAVE_READ_LANE_AT ] = "wave_read_lane_at", +- [VKD3DSIH_WAVE_READ_LANE_FIRST ] = "wave_read_lane_first", +- [VKD3DSIH_XOR ] = "xor", +-}; +- + static const char * const shader_register_names[] = + { + [VKD3DSPR_ADDR ] = "a", +@@ -917,9 +590,10 @@ static void shader_print_double_literal(struct vkd3d_d3d_asm_compiler *compiler, + static void shader_print_int_literal(struct vkd3d_d3d_asm_compiler *compiler, + const char *prefix, int i, const char *suffix) + { ++ /* Note that we need to handle INT_MIN here as well. */ + if (i < 0) +- vkd3d_string_buffer_printf(&compiler->buffer, "%s-%s%d%s%s", +- prefix, compiler->colours.literal, -i, compiler->colours.reset, suffix); ++ vkd3d_string_buffer_printf(&compiler->buffer, "%s-%s%u%s%s", ++ prefix, compiler->colours.literal, -(unsigned int)i, compiler->colours.reset, suffix); + else + vkd3d_string_buffer_printf(&compiler->buffer, "%s%s%d%s%s", + prefix, compiler->colours.literal, i, compiler->colours.reset, suffix); +@@ -1041,8 +715,8 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const switch (compiler->current->opcode) { @@ -35,7 +458,7 @@ index 21feb75d639..ae9278f68b1 100644 untyped = true; break; -@@ -1284,11 +1284,11 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile +@@ -1610,11 +1284,11 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile switch (ins->opcode) { @@ -52,7 +475,7 @@ index 21feb75d639..ae9278f68b1 100644 switch (ins->flags) { case VKD3D_SHADER_CONDITIONAL_OP_NZ: -@@ -1303,8 +1303,8 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile +@@ -1629,8 +1303,8 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile } break; @@ -63,7 +486,7 @@ index 21feb75d639..ae9278f68b1 100644 switch (ins->flags) { case VKD3D_SHADER_REL_OP_GT: -@@ -1331,7 +1331,7 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile +@@ -1657,7 +1331,7 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile } break; @@ -72,7 +495,7 @@ index 21feb75d639..ae9278f68b1 100644 switch (ins->flags) { case VKD3DSI_NONE: -@@ -1348,7 +1348,7 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile +@@ -1674,7 +1348,7 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile } break; @@ -81,7 +504,7 @@ index 21feb75d639..ae9278f68b1 100644 switch (ins->flags) { case VKD3DSI_NONE: -@@ -1362,24 +1362,24 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile +@@ -1688,24 +1362,24 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile } break; @@ -113,12 +536,12 @@ index 21feb75d639..ae9278f68b1 100644 shader_dump_sync_flags(compiler, ins->flags); break; -- case VKD3DSIH_TEXLD: +- case VKD3DSIH_TEX: + case VSIR_OP_TEXLD: if (vkd3d_shader_ver_ge(&compiler->shader_version, 2, 0)) { if (ins->flags & VKD3DSI_TEXLD_PROJECT) -@@ -1389,20 +1389,20 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile +@@ -1715,20 +1389,20 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile } break; @@ -150,7 +573,16 @@ index 21feb75d639..ae9278f68b1 100644 if (ins->flags & VKD3DSI_SHIFT_UNMASKED) vkd3d_string_buffer_printf(buffer, "_unmasked"); /* fall through */ -@@ -1473,8 +1473,8 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, +@@ -1747,7 +1421,7 @@ static void shader_dump_register_space(struct vkd3d_d3d_asm_compiler *compiler, + static void shader_print_opcode(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_shader_opcode opcode) + { + vkd3d_string_buffer_printf(&compiler->buffer, "%s%s%s", compiler->colours.opcode, +- shader_opcode_names[opcode], compiler->colours.reset); ++ vsir_opcode_get_name(opcode, ""), compiler->colours.reset); + } + + static void shader_dump_icb(struct vkd3d_d3d_asm_compiler *compiler, +@@ -1799,8 +1473,8 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, switch (ins->opcode) { @@ -161,7 +593,7 @@ index 21feb75d639..ae9278f68b1 100644 vkd3d_string_buffer_printf(buffer, "%s", compiler->colours.opcode); shader_print_dcl_usage(compiler, "_", &ins->declaration.semantic, ins->flags, ""); shader_dump_ins_modifiers(compiler, &ins->declaration.semantic.resource.reg); -@@ -1483,7 +1483,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, +@@ -1809,7 +1483,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, shader_dump_register_space(compiler, ins->declaration.semantic.resource.range.space); break; @@ -170,7 +602,7 @@ index 21feb75d639..ae9278f68b1 100644 shader_print_register(compiler, " ", &ins->declaration.cb.src.reg, true, ""); if (vkd3d_shader_ver_ge(&compiler->shader_version, 6, 0)) shader_print_subscript(compiler, ins->declaration.cb.size, NULL); -@@ -1494,33 +1494,33 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, +@@ -1820,33 +1494,33 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, shader_dump_register_space(compiler, ins->declaration.cb.range.space); break; @@ -211,7 +643,7 @@ index 21feb75d639..ae9278f68b1 100644 vkd3d_string_buffer_printf(buffer, " %sx%u%s", compiler->colours.reg, ins->declaration.indexable_temp.register_idx, compiler->colours.reset); shader_print_subscript(compiler, ins->declaration.indexable_temp.register_size, NULL); -@@ -1531,113 +1531,113 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, +@@ -1857,112 +1531,113 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, shader_dump_icb(compiler, ins->declaration.indexable_temp.initialiser); break; @@ -224,7 +656,6 @@ index 21feb75d639..ae9278f68b1 100644 - case VKD3DSIH_DCL_INPUT_PS_SGV: - case VKD3DSIH_DCL_INPUT_SGV: - case VKD3DSIH_DCL_INPUT_SIV: -- case VKD3DSIH_DCL_OUTPUT_SGV: - case VKD3DSIH_DCL_OUTPUT_SIV: + case VSIR_OP_DCL_INPUT_PS_SGV: + case VSIR_OP_DCL_INPUT_SGV: @@ -356,7 +787,7 @@ index 21feb75d639..ae9278f68b1 100644 vkd3d_string_buffer_printf(buffer, " %sc%u%s", compiler->colours.reg, ins->dst[0].reg.idx[0].offset, compiler->colours.reset); shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_f32[0], ""); -@@ -1646,7 +1646,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, +@@ -1971,7 +1646,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[3], ""); break; @@ -365,7 +796,7 @@ index 21feb75d639..ae9278f68b1 100644 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_u32[0], ""); -@@ -1655,7 +1655,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, +@@ -1980,7 +1655,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[3], ""); break; @@ -374,7 +805,7 @@ index 21feb75d639..ae9278f68b1 100644 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_u32[0], ""); -@@ -2048,19 +2048,19 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, +@@ -2373,19 +2048,19 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, switch (ins->opcode) { @@ -403,7 +834,7 @@ index 21feb75d639..ae9278f68b1 100644 indent = 0; break; -@@ -2077,12 +2077,12 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, +@@ -2402,12 +2077,12 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, switch (ins->opcode) { @@ -423,7 +854,7 @@ index 21feb75d639..ae9278f68b1 100644 break; diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index f19a6283197..eeb4deff61f 100644 +index 57d874efe37..eeb4deff61f 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -259,159 +259,159 @@ struct vkd3d_shader_sm1_parser @@ -661,11 +1092,11 @@ index f19a6283197..eeb4deff61f 100644 + {VKD3D_SM1_OP_LABEL, 0, 1, VSIR_OP_LABEL, {2, 1}}, /* Texture */ - {VKD3D_SM1_OP_TEXCOORD, 1, 0, VKD3DSIH_TEXCOORD, {0, 0}, {1, 3}}, -- {VKD3D_SM1_OP_TEXCOORD, 1, 1, VKD3DSIH_TEXCRD, {1, 4}, {1, 4}}, +- {VKD3D_SM1_OP_TEXCOORD, 1, 1, VKD3DSIH_TEXCOORD, {1, 4}, {1, 4}}, - {VKD3D_SM1_OP_TEXKILL, 1, 0, VKD3DSIH_TEXKILL, {1, 0}}, - {VKD3D_SM1_OP_TEX, 1, 0, VKD3DSIH_TEX, {0, 0}, {1, 3}}, -- {VKD3D_SM1_OP_TEX, 1, 1, VKD3DSIH_TEXLD, {1, 4}, {1, 4}}, -- {VKD3D_SM1_OP_TEX, 1, 2, VKD3DSIH_TEXLD, {2, 0}}, +- {VKD3D_SM1_OP_TEX, 1, 1, VKD3DSIH_TEX, {1, 4}, {1, 4}}, +- {VKD3D_SM1_OP_TEX, 1, 2, VKD3DSIH_TEX, {2, 0}}, - {VKD3D_SM1_OP_TEXBEM, 1, 1, VKD3DSIH_TEXBEM, {0, 0}, {1, 3}}, - {VKD3D_SM1_OP_TEXBEML, 1, 1, VKD3DSIH_TEXBEML, {1, 0}, {1, 3}}, - {VKD3D_SM1_OP_TEXREG2AR, 1, 1, VKD3DSIH_TEXREG2AR, {1, 0}, {1, 3}}, @@ -832,7 +1263,38 @@ index f19a6283197..eeb4deff61f 100644 return NULL; if (vkd3d_opcode == info->vkd3d_opcode -@@ -1773,7 +1773,7 @@ static bool is_inconsequential_instr(const struct vkd3d_shader_instruction *ins) +@@ -1681,7 +1681,8 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir_ + if (!(info = shader_sm1_get_opcode_info_from_vsir(d3dbc, ins->opcode))) + { + vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, +- "Opcode %#x not supported for shader profile.", ins->opcode); ++ "Instruction \"%s\" (%#x) is not supported for the current target.", ++ vsir_opcode_get_name(ins->opcode, ""), ins->opcode); + d3dbc->failed = true; + return NULL; + } +@@ -1689,16 +1690,16 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir_ + if (ins->dst_count != info->dst_count) + { + vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, +- "Invalid destination count %u for vsir instruction %#x (expected %u).", +- ins->dst_count, ins->opcode, info->dst_count); ++ "Invalid destination parameter count %u for instruction \"%s\" (%#x); expected %u.", ++ ins->dst_count, vsir_opcode_get_name(ins->opcode, ""), ins->opcode, info->dst_count); + d3dbc->failed = true; + return NULL; + } + if (ins->src_count != info->src_count) + { + vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, +- "Invalid source count %u for vsir instruction %#x (expected %u).", +- ins->src_count, ins->opcode, info->src_count); ++ "Invalid source parameter count %u for instruction \"%s\" (%#x); expected %u.", ++ ins->src_count, vsir_opcode_get_name(ins->opcode, ""), ins->opcode, info->src_count); + d3dbc->failed = true; + return NULL; + } +@@ -1772,7 +1773,7 @@ static bool is_inconsequential_instr(const struct vkd3d_shader_instruction *ins) const struct vkd3d_shader_src_param *src = &ins->src[0]; unsigned int i; @@ -841,7 +1303,41 @@ index f19a6283197..eeb4deff61f 100644 return false; if (dst->modifiers != VKD3DSPDM_NONE) return false; -@@ -1990,47 +1990,47 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str +@@ -1829,6 +1830,7 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct v + struct vkd3d_bytecode_buffer *buffer = &d3dbc->buffer; + const struct vkd3d_shader_src_param *src; + const struct vkd3d_sm1_opcode_info *info; ++ size_t size, token_position; + unsigned int i; + uint32_t token; + +@@ -1841,9 +1843,7 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct v + token = info->sm1_opcode; + token |= VKD3D_SM1_INSTRUCTION_FLAGS_MASK & (ins->flags << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT); + +- if (version->major > 1) +- token |= (ins->dst_count + ins->src_count) << VKD3D_SM1_INSTRUCTION_LENGTH_SHIFT; +- put_u32(buffer, token); ++ token_position = put_u32(buffer, 0); + + for (i = 0; i < ins->dst_count; ++i) + { +@@ -1863,6 +1863,14 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct v + if (src->reg.idx_count && src->reg.idx[0].rel_addr) + write_sm1_src_register(buffer, src->reg.idx[0].rel_addr); + } ++ ++ if (version->major > 1) ++ { ++ size = (bytecode_get_size(buffer) - token_position) / sizeof(uint32_t); ++ token |= ((size - 1) << VKD3D_SM1_INSTRUCTION_LENGTH_SHIFT); ++ } ++ ++ set_u32(buffer, token_position, token); + }; + + static void d3dbc_write_texkill(struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_instruction *ins) +@@ -1982,55 +1990,55 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str switch (ins->opcode) { @@ -880,7 +1376,7 @@ index f19a6283197..eeb4deff61f 100644 - case VKD3DSIH_MUL: - case VKD3DSIH_SINCOS: - case VKD3DSIH_SLT: -- case VKD3DSIH_TEXLD: +- case VKD3DSIH_TEX: - case VKD3DSIH_TEXLDD: + case VSIR_OP_ABS: + case VSIR_OP_ADD: @@ -918,7 +1414,27 @@ index f19a6283197..eeb4deff61f 100644 writemask = ins->dst->write_mask; if (writemask != VKD3DSP_WRITEMASK_0 && writemask != VKD3DSP_WRITEMASK_1 && writemask != VKD3DSP_WRITEMASK_2 && writemask != VKD3DSP_WRITEMASK_3) -@@ -2076,6 +2076,13 @@ static void d3dbc_write_semantic_dcl(struct d3dbc_compiler *d3dbc, + { + vkd3d_shader_error(d3dbc->message_context, &ins->location, + VKD3D_SHADER_ERROR_D3DBC_INVALID_WRITEMASK, +- "writemask %#x for vsir instruction with opcode %#x is not single component.", +- writemask, ins->opcode); ++ "Writemask %#x for instruction \"%s\" (%#x) is not single component.", ++ writemask, vsir_opcode_get_name(ins->opcode, ""), ins->opcode); + d3dbc->failed = true; + } + d3dbc_write_instruction(d3dbc, ins); +@@ -2038,7 +2046,8 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str + + default: + vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, +- "vsir instruction with opcode %#x.", ins->opcode); ++ "Internal compiler error: Unhandled instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(ins->opcode, ""), ins->opcode); + d3dbc->failed = true; + break; + } +@@ -2067,6 +2076,13 @@ static void d3dbc_write_semantic_dcl(struct d3dbc_compiler *d3dbc, VKD3D_ASSERT(ret); reg.reg.type = output ? VKD3DSPR_OUTPUT : VKD3DSPR_INPUT; reg.reg.idx[0].offset = element->register_index; @@ -932,11 +1448,1018 @@ index f19a6283197..eeb4deff61f 100644 } token = VKD3D_SM1_OP_DCL; +@@ -2128,6 +2144,9 @@ int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, + struct vkd3d_bytecode_buffer *buffer = &d3dbc.buffer; + int result; + ++ if ((result = vsir_allocate_temp_registers(program, message_context))) ++ return result; ++ + d3dbc.program = program; + d3dbc.message_context = message_context; + switch (version->type) +@@ -2147,7 +2166,7 @@ int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, + } + + put_u32(buffer, sm1_version(version->type, version->major, version->minor)); +- d3dbc_write_comment(&d3dbc, VKD3D_MAKE_TAG('C','T','A','B'), ctab); ++ d3dbc_write_comment(&d3dbc, TAG_CTAB, ctab); + d3dbc_write_semantic_dcls(&d3dbc); + d3dbc_write_program_instructions(&d3dbc); + +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +index 9e3a57132a1..45a45c3ad4a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +@@ -388,7 +388,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s + { + WARN("Invalid data size %#zx.\n", section->data.size); + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_SIGNATURE, +- "Section size %zu is smaller than the minimum signature header size.\n", section->data.size); ++ "Section size %zu is smaller than the minimum signature header size.", section->data.size); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + +@@ -402,7 +402,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s + { + WARN("Invalid header size %#x.\n", header_size); + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_SIGNATURE, +- "Signature header size %#x is invalid.\n", header_size); ++ "Signature header size %#x is invalid.", header_size); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + skip_dword_unknown(&ptr, i - 2); +@@ -438,7 +438,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s + || !(e[i].semantic_name = vkd3d_strdup(name))) + { + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_STRING_REFERENCE, +- "Element %u has invalid semantic name reference %#zx (data size %#zx).\n", ++ "Element %u has invalid semantic name reference %#zx (data size %#zx).", + i, name_offset, section->data.size); + fail = true; + } +@@ -447,7 +447,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s + if ((e[i].component_type = read_u32(&ptr)) > VKD3D_SHADER_COMPONENT_FLOAT) + { + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_COMPONENT_TYPE, +- "Element %u has invalid component type %#x.\n", i, e[i].component_type); ++ "Element %u has invalid component type %#x.", i, e[i].component_type); + fail = true; + } + e[i].register_index = read_u32(&ptr); +@@ -531,7 +531,7 @@ static int shdr_parse_features(const struct vkd3d_shader_dxbc_section_desc *sect + { + WARN("Invalid data size %#zx.\n", section->data.size); + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE, +- "SFI0 section size %zu is too small to contain flags.\n", section->data.size); ++ "SFI0 section size %zu is too small to contain flags.", section->data.size); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + flags = read_u64(&ptr); diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 194c51a6ffd..db74a7bfbcc 100644 +index ca79939a39b..db74a7bfbcc 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -3679,7 +3679,7 @@ static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type +@@ -643,16 +643,22 @@ struct sm6_type + + enum sm6_value_type + { ++ VALUE_TYPE_INVALID, + VALUE_TYPE_FUNCTION, +- VALUE_TYPE_REG, + VALUE_TYPE_DATA, + VALUE_TYPE_HANDLE, + VALUE_TYPE_SSA, + VALUE_TYPE_ICB, + VALUE_TYPE_IDXTEMP, + VALUE_TYPE_GROUPSHAREDMEM, ++ VALUE_TYPE_CONSTANT, + VALUE_TYPE_UNDEFINED, +- VALUE_TYPE_INVALID, ++}; ++ ++struct sm6_index ++{ ++ const struct sm6_value *index; ++ bool is_in_bounds; + }; + + struct sm6_function_data +@@ -678,16 +684,24 @@ struct sm6_icb_data + { + unsigned int data_id; + unsigned int id; ++ struct sm6_index index; + }; + + struct sm6_idxtemp_data + { + unsigned int id; ++ struct sm6_index index; + }; + + struct sm6_groupsharedmem_data + { + unsigned int id; ++ struct sm6_index index; ++}; ++ ++struct sm6_constant_data ++{ ++ union vsir_immediate_constant immconst; + }; + + struct sm6_value +@@ -696,6 +710,7 @@ struct sm6_value + enum sm6_value_type value_type; + unsigned int structure_stride; + bool is_back_ref; ++ bool non_uniform; + union + { + struct sm6_function_data function; +@@ -705,8 +720,8 @@ struct sm6_value + struct sm6_icb_data icb; + struct sm6_idxtemp_data idxtemp; + struct sm6_groupsharedmem_data groupsharedmem; ++ struct sm6_constant_data constant; + } u; +- struct vkd3d_shader_register reg; + }; + + struct dxil_record +@@ -731,7 +746,7 @@ struct incoming_value + + struct sm6_phi + { +- struct vkd3d_shader_register reg; ++ struct sm6_value value; + struct incoming_value *incoming; + size_t incoming_capacity; + size_t incoming_count; +@@ -2010,11 +2025,6 @@ static inline bool sm6_type_is_handle(const struct sm6_type *type) + return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.Handle"); + } + +-static inline const struct sm6_type *sm6_type_get_element_type(const struct sm6_type *type) +-{ +- return (type->class == TYPE_CLASS_ARRAY || type->class == TYPE_CLASS_VECTOR) ? type->u.array.elem_type : type; +-} +- + static const struct sm6_type *sm6_type_get_pointer_to_type(const struct sm6_type *type, + enum bitcode_address_space addr_space, struct sm6_parser *sm6) + { +@@ -2214,38 +2224,14 @@ static const char *sm6_parser_get_global_symbol_name(const struct sm6_parser *sm + return NULL; + } + +-static unsigned int register_get_uint_value(const struct vkd3d_shader_register *reg) +-{ +- if (!register_is_constant(reg) || (!data_type_is_integer(reg->data_type) && !data_type_is_bool(reg->data_type))) +- return UINT_MAX; +- +- if (reg->dimension == VSIR_DIMENSION_VEC4) +- WARN("Returning vec4.x.\n"); +- +- if (reg->type == VKD3DSPR_IMMCONST64) +- { +- if (reg->u.immconst_u64[0] > UINT_MAX) +- FIXME("Truncating 64-bit value.\n"); +- return reg->u.immconst_u64[0]; +- } +- +- return reg->u.immconst_u32[0]; +-} +- +-static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *reg) ++static inline bool sm6_value_is_function_dcl(const struct sm6_value *value) + { +- if (!register_is_constant(reg) || !data_type_is_integer(reg->data_type)) +- return UINT64_MAX; +- +- if (reg->dimension == VSIR_DIMENSION_VEC4) +- WARN("Returning vec4.x.\n"); +- +- return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_u64[0] : reg->u.immconst_u32[0]; ++ return value->value_type == VALUE_TYPE_FUNCTION; + } + +-static inline bool sm6_value_is_function_dcl(const struct sm6_value *value) ++static bool sm6_value_is_invalid(const struct sm6_value *value) + { +- return value->value_type == VALUE_TYPE_FUNCTION; ++ return value->value_type == VALUE_TYPE_INVALID; + } + + static inline bool sm6_value_is_dx_intrinsic_dcl(const struct sm6_value *fn) +@@ -2264,11 +2250,11 @@ static inline bool sm6_value_is_register(const struct sm6_value *value) + { + switch (value->value_type) + { +- case VALUE_TYPE_REG: + case VALUE_TYPE_SSA: + case VALUE_TYPE_ICB: + case VALUE_TYPE_IDXTEMP: + case VALUE_TYPE_GROUPSHAREDMEM: ++ case VALUE_TYPE_CONSTANT: + case VALUE_TYPE_UNDEFINED: + case VALUE_TYPE_INVALID: + return true; +@@ -2285,18 +2271,41 @@ static bool sm6_value_is_handle(const struct sm6_value *value) + + static inline bool sm6_value_is_constant(const struct sm6_value *value) + { +- return sm6_value_is_register(value) && register_is_constant(&value->reg); ++ return value->value_type == VALUE_TYPE_CONSTANT; + } + + static bool sm6_value_is_constant_zero(const struct sm6_value *value) + { +- /* Constant vectors do not occur. */ +- return sm6_value_is_register(value) && register_is_scalar_constant_zero(&value->reg); ++ if (value->value_type != VALUE_TYPE_CONSTANT) ++ return false; ++ ++ switch (value->type->class) ++ { ++ case TYPE_CLASS_INTEGER: ++ case TYPE_CLASS_FLOAT: ++ break; ++ ++ default: ++ return false; ++ } ++ ++ if (value->type->u.width == 64) ++ return value->u.constant.immconst.immconst_u64[0] == 0; ++ else ++ return value->u.constant.immconst.immconst_u32[0] == 0; + } + + static inline bool sm6_value_is_undef(const struct sm6_value *value) + { +- return sm6_value_is_register(value) && value->reg.type == VKD3DSPR_UNDEF; ++ switch (value->value_type) ++ { ++ case VALUE_TYPE_UNDEFINED: ++ case VALUE_TYPE_INVALID: ++ return true; ++ ++ default: ++ return false; ++ } + } + + static bool sm6_value_vector_is_constant_or_undef(const struct sm6_value **values, unsigned int count) +@@ -2315,26 +2324,98 @@ static bool sm6_value_is_data(const struct sm6_value *value) + + static bool sm6_value_is_ssa(const struct sm6_value *value) + { +- return sm6_value_is_register(value) && register_is_ssa(&value->reg); ++ return value->value_type == VALUE_TYPE_SSA; + } + + static bool sm6_value_is_numeric_array(const struct sm6_value *value) + { +- return sm6_value_is_register(value) && register_is_numeric_array(&value->reg); ++ switch (value->value_type) ++ { ++ case VALUE_TYPE_ICB: ++ case VALUE_TYPE_IDXTEMP: ++ case VALUE_TYPE_GROUPSHAREDMEM: ++ return true; ++ ++ default: ++ return false; ++ } + } + +-static inline unsigned int sm6_value_get_constant_uint(const struct sm6_value *value) ++static unsigned int sm6_value_get_constant_uint(const struct sm6_value *value, struct sm6_parser *sm6) + { + if (!sm6_value_is_constant(value)) ++ { ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, ++ "Invalid non-constant value."); + return UINT_MAX; +- return register_get_uint_value(&value->reg); ++ } ++ ++ if (value->type->class != TYPE_CLASS_INTEGER) ++ { ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, ++ "Invalid non-integer constant value."); ++ return UINT_MAX; ++ } ++ ++ if (value->type->u.width == 64) ++ { ++ uint64_t val = value->u.constant.immconst.immconst_u64[0]; ++ if (val > UINT_MAX) ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, ++ "Invalid 64-bit constant %"PRIu64" will be truncated do %u.", val, (unsigned int)val); ++ return val; ++ } ++ ++ return value->u.constant.immconst.immconst_u32[0]; + } + +-static uint64_t sm6_value_get_constant_uint64(const struct sm6_value *value) ++static uint64_t sm6_value_get_constant_uint64(const struct sm6_value *value, struct sm6_parser *sm6) + { + if (!sm6_value_is_constant(value)) ++ { ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, ++ "Invalid non-constant value."); + return UINT64_MAX; +- return register_get_uint64_value(&value->reg); ++ } ++ ++ if (value->type->class != TYPE_CLASS_INTEGER) ++ { ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, ++ "Invalid non-integer constant value."); ++ return UINT64_MAX; ++ } ++ ++ if (value->type->u.width == 64) ++ return value->u.constant.immconst.immconst_u64[0]; ++ else ++ return value->u.constant.immconst.immconst_u32[0]; ++} ++ ++static float sm6_value_get_constant_float(const struct sm6_value *value, struct sm6_parser *sm6) ++{ ++ if (!sm6_value_is_constant(value)) ++ { ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, ++ "Invalid non-constant value."); ++ return 0.0f; ++ } ++ ++ if (value->type->class != TYPE_CLASS_FLOAT) ++ { ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, ++ "Invalid non-floating-point constant value."); ++ return 0.0f; ++ } ++ ++ if (value->type->u.width == 64) ++ { ++ double val = value->u.constant.immconst.immconst_f64[0]; ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, ++ "Invalid double constant %lf will be truncated do float %f.", val, (float)val); ++ return val; ++ } ++ ++ return value->u.constant.immconst.immconst_f32[0]; + } + + static unsigned int sm6_parser_alloc_ssa_id(struct sm6_parser *sm6) +@@ -2433,33 +2514,123 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type + return VKD3D_DATA_UINT; + } + +-static void sm6_register_from_value(struct vkd3d_shader_register *reg, const struct sm6_value *value) ++/* Based on the implementation in the OpenGL Mathematics library. */ ++static uint32_t half_to_float(uint16_t value) + { +- enum vkd3d_data_type data_type; ++ uint32_t s = (value & 0x8000u) << 16; ++ uint32_t e = (value >> 10) & 0x1fu; ++ uint32_t m = value & 0x3ffu; + +- data_type = vkd3d_data_type_from_sm6_type(sm6_type_get_scalar_type(value->type, 0)); ++ if (!e) ++ { ++ if (!m) ++ { ++ /* Plus or minus zero */ ++ return s; ++ } ++ else ++ { ++ /* Denormalized number -- renormalize it */ ++ while (!(m & 0x400u)) ++ { ++ m <<= 1; ++ --e; ++ } + +- switch (value->value_type) ++ ++e; ++ m &= ~0x400u; ++ } ++ } ++ else if (e == 31u) ++ { ++ /* Positive or negative infinity for zero 'm'. ++ * Nan for non-zero 'm' -- preserve sign and significand bits */ ++ return s | 0x7f800000u | (m << 13); ++ } ++ ++ /* Normalized number */ ++ e += 127u - 15u; ++ m <<= 13; ++ ++ /* Assemble s, e and m. */ ++ return s | (e << 23) | m; ++} ++ ++static void register_convert_to_minimum_precision(struct vkd3d_shader_register *reg) ++{ ++ unsigned int i; ++ ++ switch (reg->data_type) + { +- case VALUE_TYPE_REG: +- *reg = value->reg; ++ case VKD3D_DATA_HALF: ++ reg->data_type = VKD3D_DATA_FLOAT; ++ reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_FLOAT_16; ++ if (reg->type == VKD3DSPR_IMMCONST) ++ { ++ for (i = 0; i < VSIR_DIMENSION_VEC4; ++i) ++ reg->u.immconst_u32[i] = half_to_float(reg->u.immconst_u32[i]); ++ } ++ break; ++ ++ case VKD3D_DATA_UINT16: ++ reg->data_type = VKD3D_DATA_UINT; ++ reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_UINT_16; ++ if (reg->type == VKD3DSPR_IMMCONST) ++ { ++ for (i = 0; i < VSIR_DIMENSION_VEC4; ++i) ++ reg->u.immconst_u32[i] = (int16_t)reg->u.immconst_u32[i]; ++ } + break; + ++ default: ++ break; ++ } ++} ++ ++static void register_index_address_init(struct vkd3d_shader_register_index *idx, const struct sm6_value *address, ++ struct sm6_parser *sm6); ++ ++static void sm6_register_from_value(struct vkd3d_shader_register *reg, const struct sm6_value *value, ++ struct sm6_parser *sm6) ++{ ++ const struct sm6_type *scalar_type; ++ enum vkd3d_data_type data_type; ++ ++ scalar_type = sm6_type_get_scalar_type(value->type, 0); ++ data_type = vkd3d_data_type_from_sm6_type(scalar_type); ++ ++ switch (value->value_type) ++ { + case VALUE_TYPE_SSA: + register_init_with_id(reg, VKD3DSPR_SSA, data_type, value->u.ssa.id); + reg->dimension = sm6_type_is_scalar(value->type) ? VSIR_DIMENSION_SCALAR : VSIR_DIMENSION_VEC4; + break; + + case VALUE_TYPE_ICB: +- register_init_with_id(reg, VKD3DSPR_IMMCONSTBUFFER, data_type, value->u.icb.id); ++ vsir_register_init(reg, VKD3DSPR_IMMCONSTBUFFER, data_type, 2); ++ reg->idx[0].offset = value->u.icb.id; ++ register_index_address_init(®->idx[1], value->u.icb.index.index, sm6); ++ reg->idx[1].is_in_bounds = value->u.icb.index.is_in_bounds; + break; + + case VALUE_TYPE_IDXTEMP: +- register_init_with_id(reg, VKD3DSPR_IDXTEMP, data_type, value->u.idxtemp.id); ++ vsir_register_init(reg, VKD3DSPR_IDXTEMP, data_type, 2); ++ reg->idx[0].offset = value->u.idxtemp.id; ++ register_index_address_init(®->idx[1], value->u.idxtemp.index.index, sm6); ++ reg->idx[1].is_in_bounds = value->u.idxtemp.index.is_in_bounds; + break; + + case VALUE_TYPE_GROUPSHAREDMEM: +- register_init_with_id(reg, VKD3DSPR_GROUPSHAREDMEM, data_type, value->u.groupsharedmem.id); ++ vsir_register_init(reg, VKD3DSPR_GROUPSHAREDMEM, data_type, 2); ++ reg->idx[0].offset = value->u.groupsharedmem.id; ++ register_index_address_init(®->idx[1], value->u.groupsharedmem.index.index, sm6); ++ reg->idx[1].is_in_bounds = value->u.groupsharedmem.index.is_in_bounds; ++ break; ++ ++ case VALUE_TYPE_CONSTANT: ++ vsir_register_init(reg, scalar_type->u.width == 64 ? VKD3DSPR_IMMCONST64 : VKD3DSPR_IMMCONST, ++ data_type, 0); ++ reg->u = value->u.constant.immconst; + break; + + case VALUE_TYPE_UNDEFINED: +@@ -2472,15 +2643,18 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str + case VALUE_TYPE_DATA: + vkd3d_unreachable(); + } ++ ++ register_convert_to_minimum_precision(reg); ++ reg->non_uniform = value->non_uniform; + } + + static void sm6_parser_init_ssa_value(struct sm6_parser *sm6, struct sm6_value *value) + { + unsigned int id; + +- if (register_is_ssa(&value->reg) && value->reg.idx[0].offset) ++ if (value->value_type == VALUE_TYPE_SSA && value->u.ssa.id) + { +- id = value->reg.idx[0].offset; ++ id = value->u.ssa.id; + TRACE("Using forward-allocated id %u.\n", id); + } + else +@@ -2490,7 +2664,6 @@ static void sm6_parser_init_ssa_value(struct sm6_parser *sm6, struct sm6_value * + + value->value_type = VALUE_TYPE_SSA; + value->u.ssa.id = id; +- sm6_register_from_value(&value->reg, value); + } + + static void register_make_constant_uint(struct vkd3d_shader_register *reg, unsigned int value) +@@ -2547,10 +2720,11 @@ static void src_param_init_vector(struct vkd3d_shader_src_param *param, unsigned + param->modifiers = VKD3DSPSM_NONE; + } + +-static void src_param_init_from_value(struct vkd3d_shader_src_param *param, const struct sm6_value *src) ++static void src_param_init_from_value(struct vkd3d_shader_src_param *param, const struct sm6_value *src, ++ struct sm6_parser *sm6) + { + src_param_init(param); +- sm6_register_from_value(¶m->reg, src); ++ sm6_register_from_value(¶m->reg, src, sm6); + } + + static void src_param_init_vector_from_reg(struct vkd3d_shader_src_param *param, +@@ -2570,12 +2744,12 @@ static void src_param_make_constant_uint(struct vkd3d_shader_src_param *param, u + static void register_index_address_init(struct vkd3d_shader_register_index *idx, const struct sm6_value *address, + struct sm6_parser *sm6) + { +- if (sm6_value_is_constant(address)) ++ if (address && sm6_value_is_constant(address)) + { +- idx->offset = sm6_value_get_constant_uint(address); ++ idx->offset = sm6_value_get_constant_uint(address, sm6); + idx->rel_addr = NULL; + } +- else if (sm6_value_is_undef(address)) ++ else if (!address || sm6_value_is_undef(address)) + { + idx->offset = 0; + idx->rel_addr = NULL; +@@ -2584,7 +2758,7 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, + { + struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(sm6->p.program, 1); + if (rel_addr) +- src_param_init_from_value(rel_addr, address); ++ src_param_init_from_value(rel_addr, address, sm6); + idx->offset = 0; + idx->rel_addr = rel_addr; + } +@@ -2619,7 +2793,7 @@ static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instructio + + dst_param_init(param); + sm6_parser_init_ssa_value(sm6, dst); +- sm6_register_from_value(¶m->reg, dst); ++ sm6_register_from_value(¶m->reg, dst, sm6); + return true; + } + +@@ -2631,22 +2805,20 @@ static void instruction_dst_param_init_ssa_vector(struct vkd3d_shader_instructio + + dst_param_init_vector(param, component_count); + sm6_parser_init_ssa_value(sm6, dst); +- sm6_register_from_value(¶m->reg, dst); ++ sm6_register_from_value(¶m->reg, dst, sm6); + } + +-static bool instruction_dst_param_init_temp_vector(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) ++static bool instruction_dst_param_init_uint_temp_vector(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) + { +- struct sm6_value *dst = sm6_parser_get_current_value(sm6); + struct vkd3d_shader_dst_param *param; + + if (!(param = instruction_dst_params_alloc(ins, 1, sm6))) + return false; + +- vsir_dst_param_init(param, VKD3DSPR_TEMP, vkd3d_data_type_from_sm6_type(sm6_type_get_scalar_type(dst->type, 0)), 1); ++ vsir_dst_param_init(param, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); + param->write_mask = VKD3DSP_WRITEMASK_ALL; + param->reg.idx[0].offset = 0; + param->reg.dimension = VSIR_DIMENSION_VEC4; +- dst->reg = param->reg; + + return true; + } +@@ -2928,7 +3100,6 @@ static size_t sm6_parser_get_value_idx_by_ref(struct sm6_parser *sm6, const stru + value->type = fwd_type; + value->value_type = VALUE_TYPE_SSA; + value->u.ssa.id = sm6_parser_alloc_ssa_id(sm6); +- sm6_register_from_value(&value->reg, value); + } + } + +@@ -3017,53 +3188,13 @@ static inline uint64_t decode_rotated_signed_value(uint64_t value) + return value << 63; + } + +-static float bitcast_uint_to_float(unsigned int value) +-{ +- union +- { +- uint32_t uint32_value; +- float float_value; +- } u; +- +- u.uint32_value = value; +- return u.float_value; +-} +- +-static inline double bitcast_uint64_to_double(uint64_t value) +-{ +- union +- { +- uint64_t uint64_value; +- double double_value; +- } u; +- +- u.uint64_value = value; +- return u.double_value; +-} +- +-static float register_get_float_value(const struct vkd3d_shader_register *reg) +-{ +- if (!register_is_constant(reg) || !data_type_is_floating_point(reg->data_type)) +- return 0.0; +- +- if (reg->dimension == VSIR_DIMENSION_VEC4) +- WARN("Returning vec4.x.\n"); +- +- if (reg->type == VKD3DSPR_IMMCONST64) +- { +- WARN("Truncating double to float.\n"); +- return bitcast_uint64_to_double(reg->u.immconst_u64[0]); +- } +- +- return bitcast_uint_to_float(reg->u.immconst_u32[0]); +-} +- + static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, const struct sm6_type *type, + const uint64_t *operands, struct sm6_parser *sm6) + { + struct vkd3d_shader_immediate_constant_buffer *icb; + const struct sm6_type *elem_type; + unsigned int i, size, count; ++ uint64_t *data64; + + elem_type = type->u.array.elem_type; + /* Multidimensional arrays are emitted in flattened form. */ +@@ -3115,28 +3246,70 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + return VKD3D_OK; + + count = type->u.array.count; +- if (size > sizeof(icb->data[0])) ++ switch (icb->data_type) + { +- uint64_t *data = (uint64_t *)icb->data; +- for (i = 0; i < count; ++i) +- data[i] = operands[i]; +- } +- else +- { +- for (i = 0; i < count; ++i) +- icb->data[i] = operands[i]; ++ case VKD3D_DATA_HALF: ++ for (i = 0; i < count; ++i) ++ icb->data[i] = half_to_float(operands[i]); ++ icb->data_type = VKD3D_DATA_FLOAT; ++ break; ++ ++ case VKD3D_DATA_UINT16: ++ for (i = 0; i < count; ++i) ++ icb->data[i] = (int16_t)operands[i]; ++ icb->data_type = VKD3D_DATA_UINT; ++ break; ++ ++ case VKD3D_DATA_FLOAT: ++ case VKD3D_DATA_UINT: ++ for (i = 0; i < count; ++i) ++ icb->data[i] = operands[i]; ++ break; ++ ++ case VKD3D_DATA_DOUBLE: ++ case VKD3D_DATA_UINT64: ++ data64 = (uint64_t *)icb->data; ++ for (i = 0; i < count; ++i) ++ data64[i] = operands[i]; ++ break; ++ ++ default: ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Invalid array of type %u.", icb->data_type); ++ return VKD3D_ERROR_INVALID_SHADER; + } + + return VKD3D_OK; + } + ++static struct sm6_index *sm6_get_value_index(struct sm6_parser *sm6, struct sm6_value *value) ++{ ++ switch (value->value_type) ++ { ++ case VALUE_TYPE_ICB: ++ return &value->u.icb.index; ++ ++ case VALUE_TYPE_IDXTEMP: ++ return &value->u.idxtemp.index; ++ ++ case VALUE_TYPE_GROUPSHAREDMEM: ++ return &value->u.groupsharedmem.index; ++ ++ default: ++ WARN("Cannot index into value of type %#x.\n", value->value_type); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Cannot index into value of type %#x.", value->value_type); ++ return NULL; ++ } ++} ++ + static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, const struct dxil_record *record, + struct sm6_value *dst) + { + const struct sm6_type *elem_type, *pointee_type, *gep_type, *ptr_type; +- struct vkd3d_shader_register reg; + struct sm6_value *operands[3]; + unsigned int i, j, offset; ++ struct sm6_index *index; + uint64_t value; + + i = 0; +@@ -3178,9 +3351,13 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c + } + } + +- sm6_register_from_value(®, operands[0]); ++ *dst = *operands[0]; ++ index = sm6_get_value_index(sm6, dst); + +- if (reg.idx_count > 1) ++ if (!index) ++ return VKD3D_ERROR_INVALID_SHADER; ++ ++ if (index->index) + { + WARN("Unsupported stacked GEP.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +@@ -3203,8 +3380,6 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c + return VKD3D_ERROR_INVALID_SHADER; + } + +- dst->structure_stride = operands[0]->structure_stride; +- + ptr_type = operands[0]->type; + if (!sm6_type_is_pointer(ptr_type)) + { +@@ -3225,7 +3400,7 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c + "Explicit pointee type for constexpr GEP does not match the element type."); + } + +- offset = sm6_value_get_constant_uint(operands[2]); ++ offset = sm6_value_get_constant_uint(operands[2], sm6); + if (!(gep_type = sm6_type_get_element_type_at_index(pointee_type, offset))) + { + WARN("Failed to get element type.\n"); +@@ -3241,20 +3416,17 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c + "Module does not define a pointer type for a constexpr GEP result."); + return VKD3D_ERROR_INVALID_SHADER; + } +- dst->reg = reg; +- dst->reg.idx[1].offset = offset; +- dst->reg.idx[1].is_in_bounds = record->code == CST_CODE_CE_INBOUNDS_GEP; +- dst->reg.idx_count = 2; ++ ++ index->index = operands[2]; ++ index->is_in_bounds = record->code == CST_CODE_CE_INBOUNDS_GEP; + + return VKD3D_OK; + } + + static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const struct dxil_block *block) + { +- enum vkd3d_shader_register_type reg_type = VKD3DSPR_INVALID; +- const struct sm6_type *type, *elem_type, *ptr_type; ++ const struct sm6_type *type, *ptr_type; + size_t i, base_value_idx, value_idx; +- enum vkd3d_data_type reg_data_type; + const struct dxil_record *record; + const struct sm6_value *src; + enum vkd3d_result ret; +@@ -3275,18 +3447,6 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) + return VKD3D_ERROR_INVALID_SHADER; + +- elem_type = sm6_type_get_element_type(type); +- if (sm6_type_is_numeric(elem_type)) +- { +- reg_data_type = vkd3d_data_type_from_sm6_type(elem_type); +- reg_type = elem_type->u.width > 32 ? VKD3DSPR_IMMCONST64 : VKD3DSPR_IMMCONST; +- } +- else +- { +- reg_data_type = VKD3D_DATA_UNUSED; +- reg_type = VKD3DSPR_INVALID; +- } +- + if (i == block->record_count - 1) + WARN("Unused SETTYPE record.\n"); + +@@ -3301,19 +3461,21 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + + dst = sm6_parser_get_current_value(sm6); + dst->type = type; +- dst->value_type = VALUE_TYPE_REG; + dst->is_back_ref = true; +- vsir_register_init(&dst->reg, reg_type, reg_data_type, 0); + + switch (record->code) + { + case CST_CODE_NULL: +- if (sm6_type_is_array(type) +- && (ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) ++ if (sm6_type_is_array(type)) + { +- return ret; ++ if ((ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) ++ return ret; ++ } ++ else ++ { ++ dst->value_type = VALUE_TYPE_CONSTANT; ++ memset(&dst->u.constant, 0, sizeof(dst->u.constant)); + } +- /* For non-aggregates, register constant data is already zero-filled. */ + break; + + case CST_CODE_INTEGER: +@@ -3326,11 +3488,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + return VKD3D_ERROR_INVALID_SHADER; + } + ++ dst->value_type = VALUE_TYPE_CONSTANT; ++ + value = decode_rotated_signed_value(record->operands[0]); + if (type->u.width <= 32) +- dst->reg.u.immconst_u32[0] = value & ((1ull << type->u.width) - 1); ++ dst->u.constant.immconst.immconst_u32[0] = value & ((1ull << type->u.width) - 1); + else +- dst->reg.u.immconst_u64[0] = value; ++ dst->u.constant.immconst.immconst_u64[0] = value; + + break; + +@@ -3344,14 +3508,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + return VKD3D_ERROR_INVALID_SHADER; + } + +- if (type->u.width == 16) +- dst->reg.u.immconst_u32[0] = record->operands[0]; +- else if (type->u.width == 32) +- dst->reg.u.immconst_f32[0] = bitcast_uint_to_float(record->operands[0]); +- else if (type->u.width == 64) +- dst->reg.u.immconst_f64[0] = bitcast_uint64_to_double(record->operands[0]); ++ dst->value_type = VALUE_TYPE_CONSTANT; ++ ++ value = record->operands[0]; ++ if (type->u.width <= 32) ++ dst->u.constant.immconst.immconst_u32[0] = value & ((1ull << type->u.width) - 1); + else +- vkd3d_unreachable(); ++ dst->u.constant.immconst.immconst_u64[0] = value; + + break; + +@@ -3377,6 +3540,46 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + return ret; + break; + ++ case CST_CODE_CE_CAST: ++ /* Resolve later in case forward refs exist. */ ++ dst->type = type; ++ dst->value_type = VALUE_TYPE_INVALID; ++ break; ++ ++ case CST_CODE_UNDEF: ++ dxil_record_validate_operand_max_count(record, 0, sm6); ++ dst->value_type = VALUE_TYPE_UNDEFINED; ++ break; ++ ++ default: ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Constant code %u is unhandled.", record->code); ++ dst->value_type = VALUE_TYPE_INVALID; ++ break; ++ } ++ ++ if (record->attachment) ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, ++ "Ignoring a metadata attachment for a constant."); ++ ++ ++sm6->value_count; ++ } ++ ++ value_idx = base_value_idx; ++ ++ for (i = 0; i < block->record_count; ++i) ++ { ++ sm6->p.location.column = i; ++ record = block->records[i]; ++ ++ switch (record->code) ++ { ++ case CST_CODE_SETTYPE: ++ continue; ++ ++ default: ++ break; ++ + case CST_CODE_CE_CAST: + if (!dxil_record_validate_operand_count(record, 3, 3, sm6)) + return VKD3D_ERROR_INVALID_SHADER; +@@ -3413,59 +3616,26 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const + return VKD3D_ERROR_INVALID_SHADER; + } + +- /* Resolve later in case forward refs exist. */ +- dst->type = type; +- dst->reg.type = VKD3DSPR_COUNT; +- dst->reg.idx[0].offset = value; +- break; ++ dst = &sm6->values[value_idx]; ++ src = &sm6->values[value]; + +- case CST_CODE_UNDEF: +- dxil_record_validate_operand_max_count(record, 0, sm6); +- dst->value_type = VALUE_TYPE_UNDEFINED; +- sm6_register_from_value(&dst->reg, dst); +- break; ++ if (!sm6_value_is_numeric_array(src)) ++ { ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Constexpr cast source value is not a global array element."); ++ return VKD3D_ERROR_INVALID_SHADER; ++ } + +- default: +- FIXME("Unhandled constant code %u.\n", record->code); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +- "Constant code %u is unhandled.", record->code); +- dst->value_type = VALUE_TYPE_INVALID; +- sm6_register_from_value(&dst->reg, dst); ++ type = dst->type; ++ *dst = *src; ++ dst->type = type; + 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; ++ ++value_idx; + } + +- /* Resolve cast forward refs. */ +- for (i = base_value_idx; i < sm6->value_count; ++i) +- { +- dst = &sm6->values[i]; +- if (dst->reg.type != VKD3DSPR_COUNT) +- continue; +- +- type = dst->type; +- +- src = &sm6->values[dst->reg.idx[0].offset]; +- if (!sm6_value_is_numeric_array(src)) +- { +- WARN("Value is not an array.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +- "Constexpr cast source value is not a global array element."); +- return VKD3D_ERROR_INVALID_SHADER; +- } +- +- *dst = *src; +- dst->type = type; +- dst->reg.data_type = vkd3d_data_type_from_sm6_type(type->u.pointer.type); +- } ++ VKD3D_ASSERT(value_idx == sm6->value_count); + + return VKD3D_OK; + } +@@ -3509,7 +3679,7 @@ static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type { struct vkd3d_shader_instruction *ins; @@ -945,7 +2468,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 /* The icb value index will be resolved later so forward references can be handled. */ ins->declaration.icb = (void *)(intptr_t)init; dst->value_type = VALUE_TYPE_ICB; -@@ -3693,9 +3693,9 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const stru +@@ -3523,9 +3693,9 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const stru enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); if (ins) @@ -957,7 +2480,15 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->declaration.indexable_temp.register_idx = sm6->indexable_temp_count++; ins->declaration.indexable_temp.register_size = count; ins->declaration.indexable_temp.alignment = alignment; -@@ -3715,7 +3715,7 @@ static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6 +@@ -3537,7 +3707,6 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const stru + + dst->value_type = VALUE_TYPE_IDXTEMP; + dst->u.idxtemp.id = ins->declaration.indexable_temp.register_idx; +- sm6_register_from_value(&dst->reg, dst); + } + + static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6_type *elem_type, +@@ -3546,15 +3715,17 @@ static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6 struct vkd3d_shader_instruction *ins; unsigned int byte_count; @@ -966,7 +2497,20 @@ index 194c51a6ffd..db74a7bfbcc 100644 dst_param_init(&ins->declaration.tgsm_raw.reg); dst->value_type = VALUE_TYPE_GROUPSHAREDMEM; dst->u.groupsharedmem.id = sm6->tgsm_count++; -@@ -3742,7 +3742,7 @@ static void sm6_parser_declare_tgsm_structured(struct sm6_parser *sm6, const str + dst->structure_stride = 0; +- sm6_register_from_value(&dst->reg, dst); +- sm6_register_from_value(&ins->declaration.tgsm_raw.reg.reg, dst); ++ sm6_register_from_value(&ins->declaration.tgsm_raw.reg.reg, dst, sm6); + ins->declaration.tgsm_raw.alignment = alignment; +- byte_count = elem_type->u.width / 8u; ++ byte_count = elem_type->u.width / CHAR_BIT; ++ /* Convert minimum precision types to their 32-bit equivalent. */ ++ if (byte_count == 2) ++ byte_count = 4; + if (byte_count != 4) + { + FIXME("Unsupported byte count %u.\n", byte_count); +@@ -3571,13 +3742,15 @@ static void sm6_parser_declare_tgsm_structured(struct sm6_parser *sm6, const str { struct vkd3d_shader_instruction *ins; @@ -975,7 +2519,26 @@ index 194c51a6ffd..db74a7bfbcc 100644 dst_param_init(&ins->declaration.tgsm_structured.reg); dst->value_type = VALUE_TYPE_GROUPSHAREDMEM; dst->u.groupsharedmem.id = sm6->tgsm_count++; -@@ -4031,21 +4031,21 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) +- dst->structure_stride = elem_type->u.width / 8u; +- sm6_register_from_value(&dst->reg, dst); +- sm6_register_from_value(&ins->declaration.tgsm_structured.reg.reg, dst); ++ dst->structure_stride = elem_type->u.width / CHAR_BIT; ++ /* Convert minimum precision types to their 32-bit equivalent. */ ++ if (dst->structure_stride == 2) ++ dst->structure_stride = 4; ++ sm6_register_from_value(&ins->declaration.tgsm_structured.reg.reg, dst, sm6); + if (dst->structure_stride != 4) + { + FIXME("Unsupported structure stride %u.\n", dst->structure_stride); +@@ -3697,7 +3870,6 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ + + dst = sm6_parser_get_current_value(sm6); + dst->type = type; +- dst->value_type = VALUE_TYPE_REG; + dst->is_back_ref = true; + + if (is_constant && !init) +@@ -3859,21 +4031,21 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) for (i = 0; i < sm6->p.program->instructions.count; ++i) { ins = &sm6->p.program->instructions.elements[i]; @@ -1001,7 +2564,39 @@ index 194c51a6ffd..db74a7bfbcc 100644 { ins->declaration.tgsm_structured.zero_init = resolve_forward_zero_initialiser(ins->flags, sm6); ins->flags = 0; -@@ -4357,26 +4357,26 @@ static enum vkd3d_shader_opcode map_dx_atomicrmw_op(uint64_t code) +@@ -3891,7 +4063,6 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) + value->u.icb.id = icb->register_idx; + else + value->u.icb.id = 0; +- sm6_register_from_value(&value->reg, value); + } + + return VKD3D_OK; +@@ -3912,12 +4083,12 @@ static void dst_param_io_init(struct vkd3d_shader_dst_param *param, + } + + static void src_params_init_from_operands(struct vkd3d_shader_src_param *src_params, +- const struct sm6_value **operands, unsigned int count) ++ const struct sm6_value **operands, unsigned int count, struct sm6_parser *sm6) + { + unsigned int i; + + for (i = 0; i < count; ++i) +- src_param_init_from_value(&src_params[i], operands[i]); ++ src_param_init_from_value(&src_params[i], operands[i], sm6); + } + + static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( +@@ -4163,7 +4334,7 @@ static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_rec + 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) ++ if (sm6_value_get_constant_uint(size, sm6) != 1) + { + FIXME("Allocation size is not 1.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +@@ -4186,26 +4357,26 @@ static enum vkd3d_shader_opcode map_dx_atomicrmw_op(uint64_t code) switch (code) { case RMW_ADD: @@ -1038,7 +2633,16 @@ index 194c51a6ffd..db74a7bfbcc 100644 } } -@@ -4417,7 +4417,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ +@@ -4228,7 +4399,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ + || !sm6_value_validate_is_backward_ref(ptr, sm6)) + return; + +- sm6_register_from_value(®, ptr); ++ sm6_register_from_value(®, ptr, sm6); + + if (reg.type != VKD3DSPR_GROUPSHAREDMEM) + { +@@ -4246,7 +4417,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ if (!dxil_record_validate_operand_count(record, i + 4, i + 4, sm6)) return; @@ -1047,7 +2651,22 @@ index 194c51a6ffd..db74a7bfbcc 100644 { FIXME("Unhandled atomicrmw op %"PRIu64".\n", code); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -@@ -4485,7 +4485,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty +@@ -4284,12 +4455,12 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ + src_param_init_vector_from_reg(&src_params[0], &coord); + else + src_param_make_constant_uint(&src_params[0], 0); +- src_param_init_from_value(&src_params[1], src); ++ src_param_init_from_value(&src_params[1], src, sm6); + + sm6_parser_init_ssa_value(sm6, dst); + + dst_params = instruction_dst_params_alloc(ins, 2, sm6); +- sm6_register_from_value(&dst_params[0].reg, dst); ++ sm6_register_from_value(&dst_params[0].reg, dst, sm6); + dst_param_init(&dst_params[0]); + + dst_params[1].reg = reg; +@@ -4314,7 +4485,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty WARN("Argument type %u is not bool, int16/32/64 or floating point.\n", type_a->class); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, "An argument to a binary operation is not bool, int16/32/64 or floating point."); @@ -1056,7 +2675,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 } if (type_a != type_b) { -@@ -4500,55 +4500,58 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty +@@ -4329,55 +4500,58 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty case BINOP_ADD: case BINOP_SUB: /* NEG is applied later for subtraction. */ @@ -1080,7 +2699,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 is_valid = is_int && !is_bool; break; case BINOP_MUL: -- op = is_int ? VKD3DSIH_IMUL_LOW : (is_double ? VKD3DSIH_DMUL : VKD3DSIH_MUL); +- op = is_int ? VKD3DSIH_UMUL : (is_double ? VKD3DSIH_DMUL : VKD3DSIH_MUL); + op = is_int ? VSIR_OP_IMUL_LOW : (is_double ? VSIR_OP_DMUL : VSIR_OP_MUL); is_valid = !is_bool; break; @@ -1127,7 +2746,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 } if (!is_valid) -@@ -4582,7 +4585,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco +@@ -4411,7 +4585,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco return; code = record->operands[i++]; @@ -1136,7 +2755,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 return; vsir_instruction_init(ins, &sm6->p.location, handler_idx); -@@ -4592,25 +4595,27 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco +@@ -4421,25 +4595,27 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco switch (handler_idx) { @@ -1155,7 +2774,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 silence_warning = !(flags & ~(FP_NO_NAN | FP_NO_INF | FP_NO_SIGNED_ZEROS | FP_ALLOW_RECIPROCAL)); break; - case VKD3DSIH_IADD: -- case VKD3DSIH_IMUL_LOW: +- case VKD3DSIH_UMUL: - case VKD3DSIH_ISHL: + case VSIR_OP_IADD: + case VSIR_OP_IMUL_LOW: @@ -1175,24 +2794,33 @@ index 194c51a6ffd..db74a7bfbcc 100644 silence_warning = !(flags & ~PEB_EXACT); break; default: -@@ -4637,27 +4642,14 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco +@@ -4459,34 +4635,21 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; +- src_param_init_from_value(&src_params[0], a); +- src_param_init_from_value(&src_params[1], b); ++ src_param_init_from_value(&src_params[0], a, sm6); ++ src_param_init_from_value(&src_params[1], b, sm6); + if (code == BINOP_SUB) + src_params[1].modifiers = VKD3DSPSM_NEG; dst->type = a->type; -- if (handler_idx == VKD3DSIH_UDIV || handler_idx == VKD3DSIH_IDIV) -+ if (handler_idx == VSIR_OP_ISHL || handler_idx == VSIR_OP_ISHR || handler_idx == VSIR_OP_USHR) - { +- if (handler_idx == VKD3DSIH_UMUL || handler_idx == VKD3DSIH_UDIV || handler_idx == VKD3DSIH_IDIV) +- { - struct vkd3d_shader_dst_param *dst_params = instruction_dst_params_alloc(ins, 2, sm6); - unsigned int index = code != BINOP_UDIV && code != BINOP_SDIV; - - dst_param_init(&dst_params[0]); - dst_param_init(&dst_params[1]); - sm6_parser_init_ssa_value(sm6, dst); -- sm6_register_from_value(&dst_params[index].reg, dst, sm6); +- sm6_register_from_value(&dst_params[index].reg, dst); - vsir_dst_param_init_null(&dst_params[index ^ 1]); - } - else -- { ++ if (handler_idx == VSIR_OP_ISHL || handler_idx == VSIR_OP_ISHR || handler_idx == VSIR_OP_USHR) + { - 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 @@ -1209,7 +2837,13 @@ index 194c51a6ffd..db74a7bfbcc 100644 } static const struct sm6_block *sm6_function_get_block(const struct sm6_function *function, uint64_t index, -@@ -4712,7 +4704,7 @@ static void sm6_parser_emit_br(struct sm6_parser *sm6, const struct dxil_record +@@ -4536,12 +4699,12 @@ static void sm6_parser_emit_br(struct sm6_parser *sm6, const struct dxil_record + dxil_record_validate_operand_max_count(record, i, sm6); + + code_block->terminator.type = TERMINATOR_COND_BR; +- sm6_register_from_value(&code_block->terminator.conditional_reg, value); ++ sm6_register_from_value(&code_block->terminator.conditional_reg, value, sm6); + code_block->terminator.true_block = sm6_function_get_block(function, record->operands[0], sm6); code_block->terminator.false_block = sm6_function_get_block(function, record->operands[1], sm6); } @@ -1218,7 +2852,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 } static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, -@@ -4750,7 +4742,7 @@ static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, +@@ -4579,7 +4742,7 @@ static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, for (i = 0; i < component_count; ++i, ++ins) { @@ -1227,7 +2861,30 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) return false; -@@ -4808,7 +4800,7 @@ static enum vkd3d_shader_opcode sm6_dx_map_void_op(enum dx_intrinsic_opcode op) +@@ -4607,7 +4770,7 @@ static bool sm6_parser_emit_composite_construct(struct sm6_parser *sm6, const st + unsigned int i; + + for (i = 0; i < component_count; ++i) +- sm6_register_from_value(&operand_regs[i], operands[i]); ++ sm6_register_from_value(&operand_regs[i], operands[i], sm6); + + return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); + } +@@ -4623,11 +4786,11 @@ static bool sm6_parser_emit_coordinate_construct(struct sm6_parser *sm6, const s + { + if (!z_operand && operands[component_count]->value_type == VALUE_TYPE_UNDEFINED) + break; +- sm6_register_from_value(&operand_regs[component_count], operands[component_count]); ++ sm6_register_from_value(&operand_regs[component_count], operands[component_count], sm6); + } + + if (z_operand) +- sm6_register_from_value(&operand_regs[component_count++], z_operand); ++ sm6_register_from_value(&operand_regs[component_count++], z_operand, sm6); + + return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); + } +@@ -4637,7 +4800,7 @@ static enum vkd3d_shader_opcode sm6_dx_map_void_op(enum dx_intrinsic_opcode op) switch (op) { case DX_WAVE_IS_FIRST_LANE: @@ -1236,7 +2893,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 default: vkd3d_unreachable(); } -@@ -4827,81 +4819,81 @@ static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) +@@ -4656,77 +4819,81 @@ static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) switch (op) { case DX_ISNAN: @@ -1248,11 +2905,9 @@ index 194c51a6ffd..db74a7bfbcc 100644 case DX_ISFINITE: - return VKD3DSIH_ISFINITE; + return VSIR_OP_ISFINITE; - case DX_COS: -- return VKD3DSIH_COS; ++ case DX_COS: + return VSIR_OP_COS; - case DX_SIN: -- return VKD3DSIH_SIN; ++ case DX_SIN: + return VSIR_OP_SIN; case DX_TAN: - return VKD3DSIH_TAN; @@ -1356,7 +3011,16 @@ index 194c51a6ffd..db74a7bfbcc 100644 default: vkd3d_unreachable(); } -@@ -4926,21 +4918,21 @@ static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, co +@@ -4741,7 +4908,7 @@ static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, enum dx_intrinsic_o + vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0]); ++ src_param_init_from_value(src_param, operands[0], sm6); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + } +@@ -4751,21 +4918,21 @@ static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, co switch (op) { case DX_FMAX: @@ -1386,7 +3050,23 @@ index 194c51a6ffd..db74a7bfbcc 100644 default: vkd3d_unreachable(); } -@@ -4968,29 +4960,29 @@ static enum vkd3d_shader_opcode map_dx_atomic_binop(const struct sm6_value *oper +@@ -4780,42 +4947,42 @@ static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_ + vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type)); + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; +- src_param_init_from_value(&src_params[0], operands[0]); +- src_param_init_from_value(&src_params[1], operands[1]); ++ src_param_init_from_value(&src_params[0], operands[0], sm6); ++ src_param_init_from_value(&src_params[1], operands[1], sm6); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + } + + static enum vkd3d_shader_opcode map_dx_atomic_binop(const struct sm6_value *operand, struct sm6_parser *sm6) + { +- uint64_t code = sm6_value_get_constant_uint(operand); ++ uint64_t code = sm6_value_get_constant_uint(operand, sm6); + switch (code) { case ATOMIC_BINOP_ADD: @@ -1426,7 +3106,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 } } -@@ -5013,8 +5005,8 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr +@@ -4838,8 +5005,8 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr return; if (is_cmp_xchg) @@ -1437,16 +3117,54 @@ index 194c51a6ffd..db74a7bfbcc 100644 return; coord_idx = 2 - is_cmp_xchg; -@@ -5066,7 +5058,7 @@ static void sm6_parser_emit_dx_barrier(struct sm6_parser *sm6, enum dx_intrinsic +@@ -4852,7 +5019,7 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr + } + else + { +- sm6_register_from_value(®, operands[coord_idx]); ++ sm6_register_from_value(®, operands[coord_idx], sm6); + } + + for (i = coord_idx + coord_count; i < coord_idx + 3; ++i) +@@ -4873,14 +5040,14 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr + return; + src_param_init_vector_from_reg(&src_params[0], ®); + if (is_cmp_xchg) +- src_param_init_from_value(&src_params[1], operands[4]); +- src_param_init_from_value(&src_params[1 + is_cmp_xchg], operands[5]); ++ src_param_init_from_value(&src_params[1], operands[4], sm6); ++ src_param_init_from_value(&src_params[1 + is_cmp_xchg], operands[5], sm6); + + sm6_parser_init_ssa_value(sm6, dst); + + dst_params = instruction_dst_params_alloc(ins, 2, sm6); + dst_param_init(&dst_params[0]); +- sm6_register_from_value(&dst_params[0].reg, dst); ++ sm6_register_from_value(&dst_params[0].reg, dst, sm6); + dst_param_init(&dst_params[1]); + sm6_register_from_handle(sm6, &resource->u.handle, &dst_params[1].reg); + } +@@ -4891,8 +5058,8 @@ static void sm6_parser_emit_dx_barrier(struct sm6_parser *sm6, enum dx_intrinsic struct vkd3d_shader_instruction *ins = state->ins; enum dxil_sync_flags flags; - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SYNC); +- flags = sm6_value_get_constant_uint(operands[0]); + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_SYNC); - flags = sm6_value_get_constant_uint(operands[0], sm6); ++ flags = sm6_value_get_constant_uint(operands[0], sm6); ins->flags = flags & (SYNC_THREAD_GROUP | SYNC_THREAD_GROUP_UAV); if (flags & SYNC_GLOBAL_UAV) -@@ -5110,7 +5102,7 @@ static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enu + ins->flags |= VKD3DSSF_GLOBAL_UAV; +@@ -4926,7 +5093,7 @@ static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enu + "A dynamic update value for a UAV counter operation is not supported."); + return; + } +- i = sm6_value_get_constant_uint(operands[1]); ++ i = sm6_value_get_constant_uint(operands[1], sm6); + if (i != 1 && i != 255) + { + WARN("Unexpected update value %#x.\n", i); +@@ -4935,7 +5102,7 @@ static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enu } inc = i; @@ -1455,8 +3173,12 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) return; src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); -@@ -5141,7 +5133,7 @@ static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_int - clamp = sm6_value_get_constant_uint(operands[5], sm6); +@@ -4963,10 +5130,10 @@ static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_int + if (!sm6_parser_emit_coordinate_construct(sm6, &operands[2], 3, NULL, state, &coord)) + return; + +- clamp = sm6_value_get_constant_uint(operands[5]); ++ clamp = sm6_value_get_constant_uint(operands[5], sm6); ins = state->ins; - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_LOD); @@ -1464,7 +3186,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) return; src_param_init_vector_from_reg(&src_params[0], &coord); -@@ -5165,7 +5157,7 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr +@@ -4990,7 +5157,7 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr if (!sm6_value_validate_is_handle(buffer, sm6)) return; @@ -1473,7 +3195,16 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; -@@ -5207,11 +5199,11 @@ static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, +@@ -5005,6 +5172,8 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr + src_param->reg.data_type = vkd3d_data_type_from_sm6_type(type); + if (data_type_is_64_bit(src_param->reg.data_type)) + src_param->swizzle = vsir_swizzle_64_from_32(src_param->swizzle); ++ else ++ register_convert_to_minimum_precision(&src_param->reg); + + instruction_dst_param_init_ssa_vector(ins, sm6_type_max_vector_size(type), sm6); + } +@@ -5030,11 +5199,11 @@ static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, { struct vkd3d_shader_src_param *src_param; @@ -1487,8 +3218,32 @@ index 194c51a6ffd..db74a7bfbcc 100644 vsir_register_init(&src_param->reg, reg_type, data_type, 0); src_param_init(src_param); -@@ -5275,7 +5267,7 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int - dst->u.handle.non_uniform = !!sm6_value_get_constant_uint(operands[3], sm6); +@@ -5064,7 +5233,7 @@ static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_pa + if (!sm6_value_is_constant(address)) + return d; + +- register_index = sm6_value_get_constant_uint(address); ++ register_index = sm6_value_get_constant_uint(address, sm6); + if (register_index >= d->range.first && register_index <= d->range.last) + return d; + } +@@ -5081,8 +5250,8 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int + struct sm6_value *dst; + unsigned int id; + +- type = sm6_value_get_constant_uint(operands[0]); +- id = sm6_value_get_constant_uint(operands[1]); ++ type = sm6_value_get_constant_uint(operands[0], sm6); ++ id = sm6_value_get_constant_uint(operands[1], sm6); + if (!(d = sm6_parser_get_descriptor(sm6, type, id, operands[2]))) + { + WARN("Failed to find resource type %#x, id %#x.\n", type, id); +@@ -5095,10 +5264,10 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int + dst->value_type = VALUE_TYPE_HANDLE; + dst->u.handle.d = d; + dst->u.handle.index = operands[2]; +- dst->u.handle.non_uniform = !!sm6_value_get_constant_uint(operands[3]); ++ dst->u.handle.non_uniform = !!sm6_value_get_constant_uint(operands[3], sm6); /* NOP is used to flag no instruction emitted. */ - ins->opcode = VKD3DSIH_NOP; @@ -1496,7 +3251,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 } static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5285,7 +5277,7 @@ static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_ +@@ -5108,12 +5277,12 @@ static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_ struct vkd3d_shader_src_param *src_param; unsigned int i; @@ -1505,7 +3260,13 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; -@@ -5316,7 +5308,7 @@ static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic + +- i = sm6_value_get_constant_uint(operands[0]); ++ i = sm6_value_get_constant_uint(operands[0], sm6); + if (i >= MAX_GS_OUTPUT_STREAMS) + { + WARN("Invalid stream index %u.\n", i); +@@ -5139,10 +5308,10 @@ static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic struct vkd3d_shader_instruction *ins = state->ins; struct vkd3d_shader_src_param *src_param; @@ -1513,17 +3274,24 @@ index 194c51a6ffd..db74a7bfbcc 100644 + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_DISCARD); if ((src_param = instruction_src_params_alloc(ins, 1, sm6))) - src_param_init_from_value(src_param, operands[0], sm6); -@@ -5329,7 +5321,7 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i +- src_param_init_from_value(src_param, operands[0]); ++ src_param_init_from_value(src_param, operands[0], sm6); + } + + static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5152,9 +5321,9 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i struct vkd3d_shader_src_param *src_param; unsigned int component_idx; - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); - if ((component_idx = sm6_value_get_constant_uint(operands[0], sm6)) >= 3) +- if ((component_idx = sm6_value_get_constant_uint(operands[0])) >= 3) ++ if ((component_idx = sm6_value_get_constant_uint(operands[0], sm6)) >= 3) { -@@ -5341,7 +5333,7 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i + WARN("Invalid component index %u.\n", component_idx); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +@@ -5164,7 +5333,7 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; @@ -1532,7 +3300,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 vsir_register_init(&src_param->reg, VKD3DSPR_TESSCOORD, VKD3D_DATA_FLOAT, 0); src_param->reg.dimension = VSIR_DIMENSION_VEC4; src_param_init_scalar(src_param, component_idx); -@@ -5361,15 +5353,15 @@ static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opc +@@ -5184,15 +5353,15 @@ static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opc switch (op) { case DX_DOT2: @@ -1551,7 +3319,18 @@ index 194c51a6ffd..db74a7bfbcc 100644 component_count = 4; break; default: -@@ -5422,7 +5414,7 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri +@@ -5223,8 +5392,8 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri + unsigned int row_index, column_index; + const struct signature_element *e; + +- row_index = sm6_value_get_constant_uint(operands[0]); +- column_index = sm6_value_get_constant_uint(operands[2]); ++ row_index = sm6_value_get_constant_uint(operands[0], sm6); ++ column_index = sm6_value_get_constant_uint(operands[2], sm6); + + signature = &sm6->p.program->input_signature; + if (row_index >= signature->element_count) +@@ -5245,7 +5414,7 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri } vsir_instruction_init(ins, &sm6->p.location, (op == DX_EVAL_CENTROID) @@ -1560,7 +3339,16 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 1 + (op == DX_EVAL_SAMPLE_INDEX), sm6))) return; -@@ -5444,7 +5436,7 @@ static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_op +@@ -5256,7 +5425,7 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri + register_index_address_init(&src_params[0].reg.idx[0], operands[1], sm6); + + if (op == DX_EVAL_SAMPLE_INDEX) +- src_param_init_from_value(&src_params[1], operands[3]); ++ src_param_init_from_value(&src_params[1], operands[3], sm6); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + } +@@ -5267,10 +5436,10 @@ static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_op struct vkd3d_shader_instruction *ins = state->ins; struct vkd3d_shader_src_param *src_param; @@ -1568,8 +3356,12 @@ index 194c51a6ffd..db74a7bfbcc 100644 + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0], sm6); -@@ -5480,8 +5472,8 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i +- src_param_init_from_value(src_param, operands[0]); ++ src_param_init_from_value(src_param, operands[0], sm6); + src_param->modifiers = VKD3DSPSM_ABS; + + instruction_dst_param_init_ssa_scalar(ins, sm6); +@@ -5303,15 +5472,15 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i vkd3d_unreachable(); } @@ -1580,7 +3372,15 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; vsir_register_init(&src_param->reg, reg_type, VKD3D_DATA_UINT, 0); -@@ -5500,12 +5492,12 @@ static enum vkd3d_shader_opcode sm6_dx_map_ma_op(enum dx_intrinsic_opcode op, co + if (component_count > 1) + { + src_param->reg.dimension = VSIR_DIMENSION_VEC4; +- component_idx = sm6_value_get_constant_uint(operands[0]); ++ component_idx = sm6_value_get_constant_uint(operands[0], sm6); + } + src_param_init_scalar(src_param, component_idx); + +@@ -5323,12 +5492,12 @@ static enum vkd3d_shader_opcode sm6_dx_map_ma_op(enum dx_intrinsic_opcode op, co switch (op) { case DX_FMA: @@ -1596,7 +3396,16 @@ index 194c51a6ffd..db74a7bfbcc 100644 default: vkd3d_unreachable(); } -@@ -5543,7 +5535,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in +@@ -5345,7 +5514,7 @@ static void sm6_parser_emit_dx_ma(struct sm6_parser *sm6, enum dx_intrinsic_opco + if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) + return; + for (i = 0; i < 3; ++i) +- src_param_init_from_value(&src_params[i], operands[i]); ++ src_param_init_from_value(&src_params[i], operands[i], sm6); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + } +@@ -5366,7 +5535,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in is_texture = resource->u.handle.d->resource_type != VKD3D_SHADER_RESOURCE_BUFFER; resource_kind = resource->u.handle.d->kind; @@ -1605,7 +3414,19 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 1 + is_texture, sm6))) return; -@@ -5562,7 +5554,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in +@@ -5375,17 +5544,17 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in + if (is_texture) + { + ins->flags = VKD3DSI_RESINFO_UINT; +- src_param_init_from_value(&src_params[0], operands[1]); ++ src_param_init_from_value(&src_params[0], operands[1], sm6); + component_count = VKD3D_VEC4_SIZE; + + if (resource_kind_is_multisampled(resource_kind)) + { +- instruction_dst_param_init_temp_vector(ins++, sm6); ++ instruction_dst_param_init_uint_temp_vector(ins++, sm6); + state->temp_idx = 1; /* DXIL does not have an intrinsic for sample info, and resinfo is expected to return * the sample count in .w for MS textures. The result is always a struct of 4 x uint32. */ @@ -1614,7 +3435,16 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->flags = VKD3DSI_SAMPLE_INFO_UINT; if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) -@@ -5578,7 +5570,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in +@@ -5393,7 +5562,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in + src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); + src_params[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); + +- if (!instruction_dst_param_init_temp_vector(ins, sm6)) ++ if (!instruction_dst_param_init_uint_temp_vector(ins, sm6)) + return; + dst = ins->dst; + dst->write_mask = VKD3DSP_WRITEMASK_3; +@@ -5401,7 +5570,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in /* Move the result to an SSA in case another instruction overwrites r0 before * the components are extracted for use. */ ++ins; @@ -1623,7 +3453,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) return; src_param_init_vector_from_reg(&src_params[0], &dst->reg); -@@ -5606,9 +5598,9 @@ static enum vkd3d_shader_opcode sm6_dx_map_tertiary_op(enum dx_intrinsic_opcode +@@ -5429,9 +5598,9 @@ static enum vkd3d_shader_opcode sm6_dx_map_tertiary_op(enum dx_intrinsic_opcode switch (op) { case DX_IBFE: @@ -1635,7 +3465,27 @@ index 194c51a6ffd..db74a7bfbcc 100644 default: vkd3d_unreachable(); } -@@ -5654,7 +5646,7 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin +@@ -5448,7 +5617,7 @@ static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsi + if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) + return; + for (i = 0; i < 3; ++i) +- src_param_init_from_value(&src_params[i], operands[i]); ++ src_param_init_from_value(&src_params[i], operands[i], sm6); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + } +@@ -5466,8 +5635,8 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin + const struct shader_signature *signature; + const struct signature_element *e; + +- row_index = sm6_value_get_constant_uint(operands[0]); +- column_index = sm6_value_get_constant_uint(operands[2]); ++ row_index = sm6_value_get_constant_uint(operands[0], sm6); ++ column_index = sm6_value_get_constant_uint(operands[2], sm6); + + if (is_control_point && operands[3]->value_type == VALUE_TYPE_UNDEFINED) + { +@@ -5477,7 +5646,7 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin "The index for a control point load is undefined."); } @@ -1644,7 +3494,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (is_patch_constant) { -@@ -5709,7 +5701,7 @@ static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intri +@@ -5532,7 +5701,7 @@ static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intri return; ins = state->ins; @@ -1653,7 +3503,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) return; src_params[0].reg = reg; -@@ -5735,13 +5727,13 @@ static enum vkd3d_shader_opcode dx_map_quad_op(enum dxil_quad_op_kind op) +@@ -5558,13 +5727,13 @@ static enum vkd3d_shader_opcode dx_map_quad_op(enum dxil_quad_op_kind op) switch (op) { case QUAD_READ_ACROSS_X: @@ -1671,16 +3521,36 @@ index 194c51a6ffd..db74a7bfbcc 100644 } } -@@ -5754,7 +5746,7 @@ static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic +@@ -5576,8 +5745,8 @@ static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic + enum vkd3d_shader_opcode opcode; enum dxil_quad_op_kind quad_op; - quad_op = sm6_value_get_constant_uint(operands[1], sm6); +- quad_op = sm6_value_get_constant_uint(operands[1]); - if ((opcode = dx_map_quad_op(quad_op)) == VKD3DSIH_INVALID) ++ quad_op = sm6_value_get_constant_uint(operands[1], sm6); + if ((opcode = dx_map_quad_op(quad_op)) == VSIR_OP_INVALID) { FIXME("Unhandled quad op kind %u.\n", quad_op); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_UNHANDLED_INTRINSIC, -@@ -5804,7 +5796,7 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i +@@ -5589,7 +5758,7 @@ static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0]); ++ src_param_init_from_value(src_param, operands[0], sm6); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + } +@@ -5610,7 +5779,7 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i + + if (op == DX_RAW_BUFFER_LOAD) + { +- write_mask = sm6_value_get_constant_uint(operands[3]); ++ write_mask = sm6_value_get_constant_uint(operands[3], sm6); + if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) + { + WARN("Invalid write mask %#x.\n", write_mask); +@@ -5627,11 +5796,11 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i component_count = vsir_write_mask_component_count(write_mask); } @@ -1689,7 +3559,30 @@ index 194c51a6ffd..db74a7bfbcc 100644 operand_count = 2 + !raw; if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) return; -@@ -5869,7 +5861,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ +- src_params_init_from_operands(src_params, &operands[1], operand_count - 1); ++ src_params_init_from_operands(src_params, &operands[1], operand_count - 1, sm6); + src_param_init_vector_from_handle(sm6, &src_params[operand_count - 1], &resource->u.handle); + + instruction_dst_param_init_ssa_vector(ins, component_count, sm6); +@@ -5653,7 +5822,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ + return; + raw = resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER; + +- write_mask = sm6_value_get_constant_uint(operands[7]); ++ write_mask = sm6_value_get_constant_uint(operands[7], sm6); + if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) + { + WARN("Invalid write mask %#x.\n", write_mask); +@@ -5679,7 +5848,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ + "Resource for a raw buffer store is not a raw or structured buffer."); + } + +- alignment = sm6_value_get_constant_uint(operands[8]); ++ alignment = sm6_value_get_constant_uint(operands[8], sm6); + if (alignment & (alignment - 1)) + { + FIXME("Invalid alignment %#x.\n", alignment); +@@ -5692,12 +5861,12 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ return; ins = state->ins; @@ -1698,7 +3591,13 @@ index 194c51a6ffd..db74a7bfbcc 100644 operand_count = 2 + !raw; if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) -@@ -5909,7 +5901,7 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri + return; +- src_params_init_from_operands(src_params, &operands[1], operand_count - 1); ++ src_params_init_from_operands(src_params, &operands[1], operand_count - 1, sm6); + data.data_type = VKD3D_DATA_UINT; + src_param_init_vector_from_reg(&src_params[operand_count - 1], &data); + +@@ -5732,11 +5901,11 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri } instruction_init_with_resource(ins, (resource->u.handle.d->type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) @@ -1707,7 +3606,21 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) return; -@@ -5974,7 +5966,7 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr +- src_param_init_from_value(&src_params[0], operands[1]); ++ src_param_init_from_value(&src_params[0], operands[1], sm6); + if (!sm6_value_is_undef(operands[2])) + { + /* Constant zero would be ok, but is not worth checking for unless it shows up. */ +@@ -5776,7 +5945,7 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr + "Resource for a typed buffer store is not a typed buffer."); + } + +- write_mask = sm6_value_get_constant_uint(operands[7]); ++ write_mask = sm6_value_get_constant_uint(operands[7], sm6); + if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) + { + WARN("Invalid write mask %#x.\n", write_mask); +@@ -5797,11 +5966,11 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr return; ins = state->ins; @@ -1716,7 +3629,12 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) return; -@@ -5999,7 +5991,7 @@ static void sm6_parser_emit_dx_get_sample_count(struct sm6_parser *sm6, enum dx_ +- src_param_init_from_value(&src_params[0], operands[1]); ++ src_param_init_from_value(&src_params[0], operands[1], sm6); + if (!sm6_value_is_undef(operands[2])) + { + /* Constant zero would have no effect, but is not worth checking for unless it shows up. */ +@@ -5822,7 +5991,7 @@ static void sm6_parser_emit_dx_get_sample_count(struct sm6_parser *sm6, enum dx_ struct vkd3d_shader_instruction *ins = state->ins; struct vkd3d_shader_src_param *src_param; @@ -1725,7 +3643,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->flags = VKD3DSI_SAMPLE_INFO_UINT; if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -@@ -6026,7 +6018,7 @@ static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_in +@@ -5849,37 +6018,37 @@ static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_in return; } @@ -1734,7 +3652,44 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) return; -@@ -6091,7 +6083,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ + if (op == DX_TEX2DMS_GET_SAMPLE_POS) + { + src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); +- src_param_init_from_value(&src_params[1], operands[1]); ++ src_param_init_from_value(&src_params[1], operands[1], sm6); + } + else + { + src_param_init_vector(&src_params[0], 2); + vsir_register_init(&src_params[0].reg, VKD3DSPR_RASTERIZER, VKD3D_DATA_FLOAT, 0); + src_params[0].reg.dimension = VSIR_DIMENSION_VEC4; +- src_param_init_from_value(&src_params[1], operands[0]); ++ src_param_init_from_value(&src_params[1], operands[0], sm6); + } + + instruction_dst_param_init_ssa_vector(ins, 2, sm6); + } + +-static unsigned int sm6_value_get_texel_offset(const struct sm6_value *value) ++static unsigned int sm6_value_get_texel_offset(const struct sm6_value *value, struct sm6_parser *sm6) + { +- return sm6_value_is_undef(value) ? 0 : sm6_value_get_constant_uint(value); ++ return sm6_value_is_undef(value) ? 0 : sm6_value_get_constant_uint(value, sm6); + } + + static void instruction_set_texel_offset(struct vkd3d_shader_instruction *ins, + const struct sm6_value **operands, struct sm6_parser *sm6) + { +- ins->texel_offset.u = sm6_value_get_texel_offset(operands[0]); +- ins->texel_offset.v = sm6_value_get_texel_offset(operands[1]); +- ins->texel_offset.w = sm6_value_get_texel_offset(operands[2]); ++ ins->texel_offset.u = sm6_value_get_texel_offset(operands[0], sm6); ++ ins->texel_offset.v = sm6_value_get_texel_offset(operands[1], sm6); ++ ins->texel_offset.w = sm6_value_get_texel_offset(operands[2], sm6); + } + + static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5914,7 +6083,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ switch (op) { case DX_SAMPLE: @@ -1743,7 +3698,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 src_params = instruction_src_params_alloc(ins, 3, sm6); clamp_idx = 9; break; -@@ -6099,7 +6091,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ +@@ -5922,23 +6091,23 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ clamp_idx = 10; /* fall through */ case DX_SAMPLE_LOD: @@ -1751,8 +3706,10 @@ index 194c51a6ffd..db74a7bfbcc 100644 + instruction_init_with_resource(ins, (op == DX_SAMPLE_B) ? VSIR_OP_SAMPLE_B : VSIR_OP_SAMPLE_LOD, resource, sm6); src_params = instruction_src_params_alloc(ins, 4, sm6); - src_param_init_from_value(&src_params[3], operands[9], sm6); -@@ -6108,14 +6100,14 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ +- src_param_init_from_value(&src_params[3], operands[9]); ++ src_param_init_from_value(&src_params[3], operands[9], sm6); + break; + case DX_SAMPLE_C: clamp_idx = 10; /* fall through */ case DX_SAMPLE_C_LZ: @@ -1760,7 +3717,8 @@ index 194c51a6ffd..db74a7bfbcc 100644 + instruction_init_with_resource(ins, (op == DX_SAMPLE_C_LZ) ? VSIR_OP_SAMPLE_C_LZ : VSIR_OP_SAMPLE_C, resource, sm6); src_params = instruction_src_params_alloc(ins, 4, sm6); - src_param_init_from_value(&src_params[3], operands[9], sm6); +- src_param_init_from_value(&src_params[3], operands[9]); ++ src_param_init_from_value(&src_params[3], operands[9], sm6); component_count = 1; break; case DX_SAMPLE_GRAD: @@ -1769,7 +3727,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 src_params = instruction_src_params_alloc(ins, 5, sm6); src_param_init_vector_from_reg(&src_params[3], &ddx); src_param_init_vector_from_reg(&src_params[4], &ddy); -@@ -6151,7 +6143,7 @@ static void sm6_parser_emit_dx_sample_index(struct sm6_parser *sm6, enum dx_intr +@@ -5974,7 +6143,7 @@ static void sm6_parser_emit_dx_sample_index(struct sm6_parser *sm6, enum dx_intr struct vkd3d_shader_src_param *src_param; unsigned int element_idx; @@ -1778,7 +3736,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 /* SV_SampleIndex is identified in VSIR by its signature element index, * but the index is not supplied as a parameter to the DXIL intrinsic. */ -@@ -6177,7 +6169,7 @@ static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsi +@@ -6000,49 +6169,25 @@ static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsi struct vkd3d_shader_instruction *ins = state->ins; struct vkd3d_shader_src_param *src_param; @@ -1786,8 +3744,40 @@ index 194c51a6ffd..db74a7bfbcc 100644 + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0], sm6); -@@ -6192,7 +6184,7 @@ static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intr +- src_param_init_from_value(src_param, operands[0]); ++ src_param_init_from_value(src_param, operands[0], sm6); + + if (instruction_dst_param_init_ssa_scalar(ins, sm6)) + ins->dst->modifiers = VKD3DSPDM_SATURATE; + } + +-static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +- const struct sm6_value **operands, struct function_emission_state *state) +-{ +- struct sm6_value *dst = sm6_parser_get_current_value(sm6); +- struct vkd3d_shader_instruction *ins = state->ins; +- struct vkd3d_shader_dst_param *dst_params; +- struct vkd3d_shader_src_param *src_param; +- unsigned int index; +- +- vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SINCOS); +- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) +- return; +- src_param_init_from_value(src_param, operands[0]); +- +- sm6_parser_init_ssa_value(sm6, dst); +- +- index = op == DX_COS; +- dst_params = instruction_dst_params_alloc(ins, 2, sm6); +- dst_param_init(&dst_params[0]); +- dst_param_init(&dst_params[1]); +- sm6_register_from_value(&dst_params[index].reg, dst); +- vsir_dst_param_init_null(&dst_params[index ^ 1]); +-} +- + static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { struct vkd3d_shader_instruction *ins = state->ins; struct vkd3d_shader_src_param *src_param; @@ -1795,8 +3785,23 @@ index 194c51a6ffd..db74a7bfbcc 100644 + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0], sm6); -@@ -6245,7 +6237,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr +- src_param_init_from_value(src_param, operands[0]); ++ src_param_init_from_value(src_param, operands[0], sm6); + + instruction_dst_param_init_ssa_vector(ins, 2, sm6); + } +@@ -6060,8 +6205,8 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr + const struct signature_element *e; + const struct sm6_value *value; + +- row_index = sm6_value_get_constant_uint(operands[0]); +- column_index = sm6_value_get_constant_uint(operands[2]); ++ row_index = sm6_value_get_constant_uint(operands[0], sm6); ++ column_index = sm6_value_get_constant_uint(operands[2], sm6); + + signature = is_patch_constant ? &program->patch_constant_signature : &program->output_signature; + if (row_index >= signature->element_count) +@@ -6092,7 +6237,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr return; } @@ -1805,7 +3810,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) return; -@@ -6256,7 +6248,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr +@@ -6103,12 +6248,12 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr if (e->register_index == UINT_MAX) { @@ -1814,7 +3819,13 @@ index 194c51a6ffd..db74a7bfbcc 100644 dst_param->reg.data_type, vsir_write_mask_component_count(e->mask)); } -@@ -6294,13 +6286,13 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in + if ((src_param = instruction_src_params_alloc(ins, 1, sm6))) +- src_param_init_from_value(src_param, value); ++ src_param_init_from_value(src_param, value, sm6); + } + + static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -6141,16 +6286,16 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in ins = state->ins; if (op == DX_TEXTURE_GATHER) { @@ -1829,8 +3840,21 @@ index 194c51a6ffd..db74a7bfbcc 100644 + instruction_init_with_resource(ins, extended_offset ? VSIR_OP_GATHER4_PO_C : VSIR_OP_GATHER4_C, resource, sm6); if (!(src_params = instruction_src_params_alloc(ins, 4 + extended_offset, sm6))) return; - src_param_init_from_value(&src_params[3 + extended_offset], operands[9], sm6); -@@ -6354,8 +6346,8 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr +- src_param_init_from_value(&src_params[3 + extended_offset], operands[9]); ++ src_param_init_from_value(&src_params[3 + extended_offset], operands[9], sm6); + } + + src_param_init_vector_from_reg(&src_params[0], &coord); +@@ -6161,7 +6306,7 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in + src_param_init_vector_from_handle(sm6, &src_params[1 + extended_offset], &resource->u.handle); + src_param_init_vector_from_handle(sm6, &src_params[2 + extended_offset], &sampler->u.handle); + /* Swizzle stored in the sampler parameter is the scalar component index to be gathered. */ +- swizzle = sm6_value_get_constant_uint(operands[8]); ++ swizzle = sm6_value_get_constant_uint(operands[8], sm6); + if (swizzle >= VKD3D_VEC4_SIZE) + { + WARN("Invalid swizzle %#x.\n", swizzle); +@@ -6201,8 +6346,8 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr } ins = state->ins; @@ -1841,7 +3865,25 @@ index 194c51a6ffd..db74a7bfbcc 100644 instruction_set_texel_offset(ins, &operands[5], sm6); for (i = 0; i < VKD3D_VEC4_SIZE; ++i) -@@ -6409,7 +6401,7 @@ static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_int +@@ -6213,7 +6358,7 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr + src_param_init_vector_from_reg(&src_params[0], &coord); + src_param_init_vector_from_handle(sm6, &src_params[1], &resource->u.handle); + if (is_multisample) +- src_param_init_from_value(&src_params[2], mip_level_or_sample_count); ++ src_param_init_from_value(&src_params[2], mip_level_or_sample_count, sm6); + + instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); + } +@@ -6235,7 +6380,7 @@ static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_int + if (!sm6_parser_emit_coordinate_construct(sm6, &operands[1], 3, NULL, state, &coord)) + return; + +- write_mask = sm6_value_get_constant_uint(operands[8]); ++ write_mask = sm6_value_get_constant_uint(operands[8], sm6); + if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) + { + WARN("Invalid write mask %#x.\n", write_mask); +@@ -6256,7 +6401,7 @@ static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_int return; ins = state->ins; @@ -1850,7 +3892,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) return; -@@ -6427,7 +6419,7 @@ static void sm6_parser_emit_dx_wave_active_ballot(struct sm6_parser *sm6, enum d +@@ -6274,10 +6419,10 @@ static void sm6_parser_emit_dx_wave_active_ballot(struct sm6_parser *sm6, enum d struct vkd3d_shader_instruction *ins = state->ins; struct vkd3d_shader_src_param *src_param; @@ -1858,8 +3900,12 @@ index 194c51a6ffd..db74a7bfbcc 100644 + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_WAVE_ACTIVE_BALLOT); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0], sm6); -@@ -6441,16 +6433,16 @@ static enum vkd3d_shader_opcode sm6_dx_map_wave_bit_op(enum dxil_wave_bit_op_kin +- src_param_init_from_value(src_param, operands[0]); ++ src_param_init_from_value(src_param, operands[0], sm6); + + instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); + } +@@ -6288,16 +6433,16 @@ static enum vkd3d_shader_opcode sm6_dx_map_wave_bit_op(enum dxil_wave_bit_op_kin switch (op) { case WAVE_BIT_OP_AND: @@ -1874,22 +3920,33 @@ index 194c51a6ffd..db74a7bfbcc 100644 default: FIXME("Unhandled wave bit op %u.\n", op); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_UNHANDLED_INTRINSIC, - "Wave bit operation %u is unhandled.", op); +- "Wave bit operation %u is unhandled.\n", op); - return VKD3DSIH_INVALID; ++ "Wave bit operation %u is unhandled.", op); + return VSIR_OP_INVALID; } } -@@ -6464,7 +6456,7 @@ static void sm6_parser_emit_dx_wave_active_bit(struct sm6_parser *sm6, enum dx_i +@@ -6309,15 +6454,15 @@ static void sm6_parser_emit_dx_wave_active_bit(struct sm6_parser *sm6, enum dx_i + enum dxil_wave_bit_op_kind wave_op; + enum vkd3d_shader_opcode opcode; - wave_op = sm6_value_get_constant_uint(operands[1], sm6); +- wave_op = sm6_value_get_constant_uint(operands[1]); ++ wave_op = sm6_value_get_constant_uint(operands[1], sm6); - if ((opcode = sm6_dx_map_wave_bit_op(wave_op, sm6)) == VKD3DSIH_INVALID) + if ((opcode = sm6_dx_map_wave_bit_op(wave_op, sm6)) == VSIR_OP_INVALID) return; vsir_instruction_init(ins, &sm6->p.location, opcode); -@@ -6481,22 +6473,22 @@ static enum vkd3d_shader_opcode sm6_dx_map_wave_op(enum dxil_wave_op_kind op, bo + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0]); ++ src_param_init_from_value(src_param, operands[0], sm6); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + } +@@ -6328,22 +6473,22 @@ static enum vkd3d_shader_opcode sm6_dx_map_wave_op(enum dxil_wave_op_kind op, bo switch (op) { case WAVE_OP_ADD: @@ -1913,14 +3970,21 @@ index 194c51a6ffd..db74a7bfbcc 100644 default: FIXME("Unhandled wave op %u.\n", op); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_UNHANDLED_INTRINSIC, - "Wave operation %u is unhandled.", op); +- "Wave operation %u is unhandled.\n", op); - return VKD3DSIH_INVALID; ++ "Wave operation %u is unhandled.", op); + return VSIR_OP_INVALID; } } -@@ -6513,7 +6505,7 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic - is_signed = !sm6_value_get_constant_uint(operands[2], sm6); +@@ -6356,11 +6501,11 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic + enum dxil_wave_op_kind wave_op; + bool is_signed; + +- wave_op = sm6_value_get_constant_uint(operands[1]); +- is_signed = !sm6_value_get_constant_uint(operands[2]); ++ wave_op = sm6_value_get_constant_uint(operands[1], sm6); ++ is_signed = !sm6_value_get_constant_uint(operands[2], sm6); opcode = sm6_dx_map_wave_op(wave_op, is_signed, sm6_type_is_floating_point(operands[0]->type), sm6); - if (opcode == VKD3DSIH_INVALID) @@ -1928,7 +3992,88 @@ index 194c51a6ffd..db74a7bfbcc 100644 return; vsir_instruction_init(ins, &sm6->p.location, opcode); -@@ -6786,7 +6778,7 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ +@@ -6368,7 +6513,7 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, operands[0]); ++ src_param_init_from_value(src_param, operands[0], sm6); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + } +@@ -6436,7 +6581,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = + [DX_BUFFER_UPDATE_COUNTER ] = {"i", "H8", sm6_parser_emit_dx_buffer_update_counter}, + [DX_CALCULATE_LOD ] = {"f", "HHfffb", sm6_parser_emit_dx_calculate_lod}, + [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, +- [DX_COS ] = {"g", "R", sm6_parser_emit_dx_sincos}, ++ [DX_COS ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, + [DX_COVERAGE ] = {"i", "", sm6_parser_emit_dx_coverage}, + [DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle}, +@@ -6505,7 +6650,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = + [DX_SAMPLE_INDEX ] = {"i", "", sm6_parser_emit_dx_sample_index}, + [DX_SAMPLE_LOD ] = {"o", "HHffffiiif", sm6_parser_emit_dx_sample}, + [DX_SATURATE ] = {"g", "R", sm6_parser_emit_dx_saturate}, +- [DX_SIN ] = {"g", "R", sm6_parser_emit_dx_sincos}, ++ [DX_SIN ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_SPLIT_DOUBLE ] = {"S", "d", sm6_parser_emit_dx_split_double}, + [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, +@@ -6539,11 +6684,13 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = + }; + + static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type, +- const struct sm6_type *ret_type, bool is_return) ++ const struct sm6_type *ret_type) + { + const struct sm6_type *type = value->type; + +- if (info_type != 'H' && !sm6_value_is_register(value)) ++ if (info_type != 'H' && info_type != 'v' && !sm6_value_is_register(value)) ++ return false; ++ if (!type && info_type != 'v') + return false; + + switch (info_type) +@@ -6578,7 +6725,7 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc + case 'g': + return sm6_type_is_floating_point(type); + case 'H': +- return (is_return || sm6_value_is_handle(value)) && type == sm6->handle_type; ++ return sm6_value_is_handle(value) && type == sm6->handle_type; + case 'D': + return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.Dimensions"); + case 'S': +@@ -6586,7 +6733,7 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc + case 'V': + return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.fouri32"); + case 'v': +- return !type; ++ return sm6_value_is_invalid(value) && !type; + case 'o': + /* TODO: some type checking may be possible */ + return true; +@@ -6606,18 +6753,10 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ + + info = &sm6_dx_op_table[op]; + +- VKD3D_ASSERT(info->ret_type[0]); +- if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type[0], NULL, true)) +- { +- 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 +- * a data type for the SSA result. */ +- } +- + for (i = 0; i < operand_count; ++i) + { + const struct sm6_value *value = operands[i]; +- if (!sm6_parser_validate_operand_type(sm6, value, info->operand_info[i], dst->type, false)) ++ if (!sm6_parser_validate_operand_type(sm6, value, info->operand_info[i], dst->type)) + { + WARN("Failed to validate operand %u for dx intrinsic id %u, '%s'.\n", i + 1, op, name); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +@@ -6639,13 +6778,12 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ static void sm6_parser_emit_unhandled(struct sm6_parser *sm6, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { @@ -1937,16 +4082,58 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!dst->type) return; -@@ -6915,7 +6907,7 @@ static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_recor + + dst->value_type = VALUE_TYPE_INVALID; +- sm6_register_from_value(&dst->reg, dst); + } + + static void sm6_parser_decode_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -6661,10 +6799,22 @@ static void sm6_parser_decode_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_op + return; + } + +- if (sm6_parser_validate_dx_op(sm6, op, name, operands, operand_count, dst)) +- sm6_dx_op_table[op].handler(sm6, op, operands, state); +- else ++ if (!sm6_parser_validate_dx_op(sm6, op, name, operands, operand_count, dst)) ++ { + sm6_parser_emit_unhandled(sm6, state->ins, dst); ++ return; ++ } ++ ++ sm6_dx_op_table[op].handler(sm6, op, operands, state); ++ ++ VKD3D_ASSERT(sm6_dx_op_table[op].ret_type[0]); ++ if (!sm6_parser_validate_operand_type(sm6, dst, sm6_dx_op_table[op].ret_type[0], NULL)) ++ { ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Failed to validate return type for dx intrinsic id %u, '%s'.", op, name); ++ /* Return type validation failure is not so critical. We only need to set ++ * a data type for the SSA result. */ ++ } + } + + static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_record *record, +@@ -6750,15 +6900,16 @@ static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_recor + "Expected a constant integer dx intrinsic function id."); + return; + } +- sm6_parser_decode_dx_op(sm6, sm6_value_get_constant_uint(op_value), ++ sm6_parser_decode_dx_op(sm6, sm6_value_get_constant_uint(op_value, sm6), + fn_value->u.function.name, &operands[1], operand_count - 1, state, dst); + } + static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_type *from, const struct sm6_type *to, struct sm6_parser *sm6) { - enum vkd3d_shader_opcode op = VKD3DSIH_INVALID; + enum vkd3d_shader_opcode op = VSIR_OP_INVALID; bool from_int, to_int, from_fp, to_fp; - unsigned int from_width, to_width; ++ unsigned int from_width, to_width; bool is_valid = false; -@@ -6931,65 +6923,65 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ + + from_int = sm6_type_is_integer(from); +@@ -6772,92 +6923,98 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ FIXME("Unhandled cast of type class %u to type class %u.\n", from->class, to->class); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, "Cast of type class %u to type class %u is not implemented.", from->class, to->class); @@ -1962,96 +4149,129 @@ index 194c51a6ffd..db74a7bfbcc 100644 + return VSIR_OP_INVALID; } +- /* DXC emits minimum precision types as 16-bit. These must be emitted +- * as 32-bit in VSIR, so all width extensions to 32 bits are no-ops. */ switch (code) { case CAST_TRUNC: -- op = VKD3DSIH_UTOU; +- /* nop or min precision. TODO: native 16-bit */ +- if (to->u.width == from->u.width || (to->u.width == 16 && from->u.width == 32)) +- op = VKD3DSIH_NOP; +- else +- op = VKD3DSIH_UTOU; + op = VSIR_OP_UTOU; is_valid = from_int && to_int && to->u.width <= from->u.width; break; - ++ case CAST_ZEXT: -- op = VKD3DSIH_UTOU; + op = VSIR_OP_UTOU; - is_valid = from_int && to_int && to->u.width >= from->u.width; - break; - ++ is_valid = from_int && to_int && to->u.width >= from->u.width; ++ break; ++ case CAST_SEXT: -- op = VKD3DSIH_ITOI; +- /* nop or min precision. TODO: native 16-bit. +- * Extension instructions could be emitted for min precision, but in Windows +- * the AMD RX 580 simply drops such instructions, which makes sense as no +- * assumptions should be made about any behaviour which depends on bit width. */ +- if (to->u.width == from->u.width || (to->u.width == 32 && from->u.width == 16)) +- { +- op = VKD3DSIH_NOP; +- is_valid = from_int && to_int; +- } +- else if (to->u.width > from->u.width) +- { +- op = (code == CAST_ZEXT) ? VKD3DSIH_UTOU : VKD3DSIH_ITOI; +- VKD3D_ASSERT(from->u.width == 1 || to->u.width == 64); +- is_valid = from_int && to_int; +- } + op = VSIR_OP_ITOI; - is_valid = from_int && to_int && to->u.width >= from->u.width; ++ is_valid = from_int && to_int && to->u.width >= from->u.width; break; - ++ case CAST_FPTOUI: - op = VKD3DSIH_FTOU; + op = VSIR_OP_FTOU; is_valid = from_fp && to_int && to->u.width > 1; break; - ++ case CAST_FPTOSI: - op = VKD3DSIH_FTOI; + op = VSIR_OP_FTOI; is_valid = from_fp && to_int && to->u.width > 1; break; - ++ case CAST_UITOFP: - op = VKD3DSIH_UTOF; + op = VSIR_OP_UTOF; is_valid = from_int && to_fp; break; - ++ case CAST_SITOFP: - op = VKD3DSIH_ITOF; + op = VSIR_OP_ITOF; is_valid = from_int && to_fp; break; - ++ case CAST_FPTRUNC: -- op = VKD3DSIH_DTOF; +- /* TODO: native 16-bit */ +- op = (from->u.width == 64) ? VKD3DSIH_DTOF : VKD3DSIH_NOP; +- is_valid = from_fp && to_fp; + op = VSIR_OP_DTOF; - is_valid = from_fp && to_fp && to->u.width <= from->u.width; ++ is_valid = from_fp && to_fp && to->u.width <= from->u.width; break; - ++ case CAST_FPEXT: -- op = VKD3DSIH_FTOD; +- /* TODO: native 16-bit */ +- op = (to->u.width == 64) ? VKD3DSIH_FTOD : VKD3DSIH_NOP; +- is_valid = from_fp && to_fp; + op = VSIR_OP_FTOD; - is_valid = from_fp && to_fp && to->u.width >= from->u.width; ++ is_valid = from_fp && to_fp && to->u.width >= from->u.width; break; - ++ case CAST_BITCAST: - op = VKD3DSIH_MOV; + op = VSIR_OP_MOV; is_valid = to->u.width == from->u.width; break; - -@@ -6997,7 +6989,7 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ ++ + default: FIXME("Unhandled cast op %"PRIu64".\n", code); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Cast operation %"PRIu64" is unhandled.", code); +- "Cast operation %"PRIu64" is unhandled.\n", code); - return VKD3DSIH_INVALID; ++ "Cast operation %"PRIu64" is unhandled.", code); + return VSIR_OP_INVALID; } if (!is_valid) -@@ -7006,7 +6998,7 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ + { + FIXME("Invalid types %u and/or %u for op %"PRIu64".\n", from->class, to->class, code); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.", +- "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.\n", ++ "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.", code, from->class, from->u.width, to->class, to->u.width); - return VKD3DSIH_INVALID; + return VSIR_OP_INVALID; } - /* 16-bit values are currently treated as 32-bit, because 16-bit is -@@ -7021,7 +7013,7 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ - to_width = 32; - - if (from->class == to->class && from_width == to_width) -- op = VKD3DSIH_NOP; ++ /* 16-bit values are currently treated as 32-bit, because 16-bit is ++ * interpreted as a minimum precision hint in SM 6.0, and we don't handle ++ * SM > 6.0 yet. */ ++ from_width = from->u.width; ++ if (from_width == 16) ++ from_width = 32; ++ ++ to_width = to->u.width; ++ if (to_width == 16) ++ to_width = 32; ++ ++ if (from->class == to->class && from_width == to_width) + op = VSIR_OP_NOP; - ++ return op; } -@@ -7050,16 +7042,16 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor + +@@ -6885,33 +7042,33 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor { *dst = *value; dst->type = type; @@ -2069,18 +4289,34 @@ index 194c51a6ffd..db74a7bfbcc 100644 - if (handler_idx == VKD3DSIH_NOP) + if (handler_idx == VSIR_OP_NOP) { - *dst = *value; - dst->type = type; -@@ -7075,7 +7067,7 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor - /* VSIR bitcasts are represented by source registers with types different - * from the types they were written with, rather than with different types - * for the MOV source and destination. */ +- sm6_register_from_value(&dst->reg, value); +- /* Set the result type for casts from 16-bit min precision. */ +- if (type->u.width != 16) +- dst->reg.data_type = vkd3d_data_type_from_sm6_type(type); ++ *dst = *value; ++ dst->type = type; + return; + } + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- src_param_init_from_value(src_param, value); ++ src_param_init_from_value(src_param, value, sm6); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + +- /* bitcast */ - if (handler_idx == VKD3DSIH_MOV) +- src_param->reg.data_type = dst->reg.data_type; ++ /* VSIR bitcasts are represented by source registers with types different ++ * from the types they were written with, rather than with different types ++ * for the MOV source and destination. */ + if (handler_idx == VSIR_OP_MOV) - src_param->reg.data_type = ins->dst[0].reg.data_type; ++ src_param->reg.data_type = ins->dst[0].reg.data_type; } -@@ -7089,33 +7081,33 @@ static const struct sm6_cmp_info *sm6_map_cmp2_op(uint64_t code) + struct sm6_cmp_info +@@ -6924,33 +7081,33 @@ static const struct sm6_cmp_info *sm6_map_cmp2_op(uint64_t code) { static const struct sm6_cmp_info cmp_op_table[] = { @@ -2141,7 +4377,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 }; return (code < ARRAY_SIZE(cmp_op_table)) ? &cmp_op_table[code] : NULL; -@@ -7161,7 +7153,7 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor +@@ -6996,7 +7153,7 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor * do not otherwise occur, so deleting these avoids the need for backend support. */ if (sm6_type_is_bool(type_a) && code == ICMP_NE && sm6_value_is_constant_zero(b)) { @@ -2150,7 +4386,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 *dst = *a; return; } -@@ -7182,7 +7174,7 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor +@@ -7017,7 +7174,7 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor "Type mismatch in comparison operation arguments."); } @@ -2159,7 +4395,27 @@ index 194c51a6ffd..db74a7bfbcc 100644 { FIXME("Unhandled operation %"PRIu64".\n", code); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -@@ -7288,7 +7280,7 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re +@@ -7051,8 +7208,8 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) + return; +- src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a); +- src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b); ++ src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a, sm6); ++ src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b, sm6); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + } +@@ -7074,7 +7231,7 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re + || !sm6_value_validate_is_backward_ref(ptr, sm6)) + return; + +- sm6_register_from_value(®, ptr); ++ sm6_register_from_value(®, ptr, sm6); + + if (reg.type != VKD3DSPR_GROUPSHAREDMEM) + { +@@ -7123,20 +7280,20 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re if (record->operand_count > i && record->operands[i]) FIXME("Ignoring weak cmpxchg.\n"); @@ -2168,7 +4424,23 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->flags = is_volatile ? VKD3DARF_SEQ_CST | VKD3DARF_VOLATILE : VKD3DARF_SEQ_CST; if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) -@@ -7356,7 +7348,7 @@ static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil + return; + src_param_make_constant_uint(&src_params[0], 0); +- src_param_init_from_value(&src_params[1], cmp); +- src_param_init_from_value(&src_params[2], new); ++ src_param_init_from_value(&src_params[1], cmp, sm6); ++ src_param_init_from_value(&src_params[2], new, sm6); + + sm6_parser_init_ssa_value(sm6, dst); + + if (!(dst_params = instruction_dst_params_alloc(ins, 2, sm6))) + return; +- sm6_register_from_value(&dst_params[0].reg, dst); ++ sm6_register_from_value(&dst_params[0].reg, dst, sm6); + dst_param_init(&dst_params[0]); + dst_params[1].reg = reg; + dst_param_init(&dst_params[1]); +@@ -7191,11 +7348,11 @@ static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil } dst->type = type; @@ -2177,16 +4449,91 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; -@@ -7462,7 +7454,7 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record - index->index = elem_value; - index->is_in_bounds = record->operands[0]; +- sm6_register_from_value(&src_param->reg, src); ++ sm6_register_from_value(&src_param->reg, src, sm6); + src_param_init_scalar(src_param, elem_idx); + instruction_dst_param_init_ssa_scalar(ins, sm6); +@@ -7208,9 +7365,8 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record + unsigned int elem_idx, operand_idx = 2; + enum bitcode_address_space addr_space; + const struct sm6_value *elem_value; +- struct vkd3d_shader_register reg; + const struct sm6_value *src; +- bool is_in_bounds; ++ struct sm6_index *index; + + if (!dxil_record_validate_operand_min_count(record, 5, sm6) + || !(type = sm6_parser_get_type(sm6, record->operands[1])) +@@ -7222,9 +7378,13 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record + return; + } + +- sm6_register_from_value(®, src); ++ *dst = *src; ++ index = sm6_get_value_index(sm6, dst); + +- if (reg.idx_count > 1) ++ if (!index) ++ return; ++ ++ if (index->index) + { + WARN("Unsupported stacked GEP.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +@@ -7232,8 +7392,6 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record + return; + } + +- is_in_bounds = record->operands[0]; +- + if ((pointee_type = src->type->u.pointer.type) != type) + { + WARN("Type mismatch, type %u width %u vs type %u width %u.\n", type->class, +@@ -7247,7 +7405,7 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record + return; + + /* The first index is always zero, to form a simple pointer dereference. */ +- if (sm6_value_get_constant_uint(elem_value)) ++ if (sm6_value_get_constant_uint(elem_value, sm6)) + { + WARN("Expected constant zero.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +@@ -7267,7 +7425,7 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record + return; + + /* If indexing is dynamic, just get the type at offset zero. */ +- elem_idx = sm6_value_is_constant(elem_value) ? sm6_value_get_constant_uint(elem_value) : 0; ++ elem_idx = sm6_value_is_constant(elem_value) ? sm6_value_get_constant_uint(elem_value, sm6) : 0; + type = sm6_type_get_element_type_at_index(pointee_type, elem_idx); + if (!type) + { +@@ -7293,15 +7451,10 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record + return; + } + +- reg.idx[1].offset = 0; +- register_index_address_init(®.idx[1], elem_value, sm6); +- reg.idx[1].is_in_bounds = is_in_bounds; +- reg.idx_count = 2; ++ index->index = elem_value; ++ index->is_in_bounds = record->operands[0]; + +- dst->reg = reg; +- dst->structure_stride = src->structure_stride; +- - ins->opcode = VKD3DSIH_NOP; + ins->opcode = VSIR_OP_NOP; } static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_record *record, -@@ -7514,7 +7506,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor +@@ -7348,12 +7501,12 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor + if (record->operands[i]) + WARN("Ignoring volatile modifier.\n"); + +- sm6_register_from_value(®, ptr); ++ sm6_register_from_value(®, ptr, sm6); + if (ptr->structure_stride) { VKD3D_ASSERT(reg.type == VKD3DSPR_GROUPSHAREDMEM); @@ -2195,7 +4542,16 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) return; -@@ -7532,7 +7524,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor +@@ -7363,7 +7516,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor + src_param_make_constant_uint(&src_params[0], reg.idx[1].offset); + /* Struct offset is always zero as there is no struct, just an array. */ + src_param_make_constant_uint(&src_params[1], 0); +- src_param_init_from_value(&src_params[2], ptr); ++ src_param_init_from_value(&src_params[2], ptr, sm6); + src_params[2].reg.alignment = alignment; + /* The offset is already in src_params[0]. */ + src_params[2].reg.idx_count = 1; +@@ -7371,13 +7524,13 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor else { operand_count = 1 + (reg.type == VKD3DSPR_GROUPSHAREDMEM); @@ -2204,7 +4560,22 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) return; -@@ -7616,7 +7608,7 @@ static void sm6_parser_emit_phi(struct sm6_parser *sm6, const struct dxil_record + if (operand_count > 1) + src_param_make_constant_uint(&src_params[0], 0); +- src_param_init_from_value(&src_params[operand_count - 1], ptr); ++ src_param_init_from_value(&src_params[operand_count - 1], ptr, sm6); + src_params[operand_count - 1].reg.alignment = alignment; + } + +@@ -7425,7 +7578,6 @@ static void sm6_parser_emit_phi(struct sm6_parser *sm6, const struct dxil_record + + if (!(phi = sm6_block_phi_require_space(code_block, sm6))) + return; +- sm6_register_from_value(&phi->reg, dst); + phi->incoming_count = record->operand_count / 2u; + + if (!vkd3d_array_reserve((void **)&phi->incoming, &phi->incoming_capacity, phi->incoming_count, +@@ -7456,7 +7608,7 @@ static void sm6_parser_emit_phi(struct sm6_parser *sm6, const struct dxil_record incoming[j].block = sm6_function_get_block(function, record->operands[i + 1], sm6); } @@ -2213,7 +4584,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 qsort(incoming, phi->incoming_count, sizeof(*incoming), phi_incoming_compare); -@@ -7651,7 +7643,7 @@ static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record +@@ -7491,7 +7643,7 @@ static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record code_block->terminator.type = TERMINATOR_RET; @@ -2222,7 +4593,13 @@ index 194c51a6ffd..db74a7bfbcc 100644 } static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_record *record, -@@ -7701,7 +7693,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco +@@ -7536,12 +7688,12 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco + if (record->operands[i]) + WARN("Ignoring volatile modifier.\n"); + +- sm6_register_from_value(®, ptr); ++ sm6_register_from_value(®, ptr, sm6); + if (ptr->structure_stride) { VKD3D_ASSERT(reg.type == VKD3DSPR_GROUPSHAREDMEM); @@ -2231,7 +4608,13 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) return; -@@ -7716,7 +7708,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco +@@ -7551,18 +7703,18 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco + src_param_make_constant_uint(&src_params[0], reg.idx[1].offset); + /* Struct offset is always zero as there is no struct, just an array. */ + src_param_make_constant_uint(&src_params[1], 0); +- src_param_init_from_value(&src_params[2], src); ++ src_param_init_from_value(&src_params[2], src, sm6); + } else { operand_count = 1 + (reg.type == VKD3DSPR_GROUPSHAREDMEM); @@ -2240,8 +4623,28 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) return; -@@ -7814,7 +7806,7 @@ static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_rec - terminator->cases[i / 2u].value = sm6_value_get_constant_uint64(src, sm6); + if (operand_count > 1) + src_param_make_constant_uint(&src_params[0], 0); +- src_param_init_from_value(&src_params[operand_count - 1], src); ++ src_param_init_from_value(&src_params[operand_count - 1], src, sm6); + } + + dst_param = instruction_dst_params_alloc(ins, 1, sm6); +@@ -7612,7 +7764,7 @@ static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_rec + return; + } + +- sm6_register_from_value(&terminator->conditional_reg, src); ++ sm6_register_from_value(&terminator->conditional_reg, src, sm6); + terminator->type = TERMINATOR_SWITCH; + + terminator->case_count = record->operand_count / 2u; +@@ -7651,10 +7803,10 @@ static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_rec + "A switch case value is not a constant."); + } + +- terminator->cases[i / 2u].value = sm6_value_get_constant_uint64(src); ++ terminator->cases[i / 2u].value = sm6_value_get_constant_uint64(src, sm6); } - ins->opcode = VKD3DSIH_NOP; @@ -2249,7 +4652,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 } static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_record *record, -@@ -7843,7 +7835,7 @@ static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_re +@@ -7683,12 +7835,12 @@ static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_re if (!sm6_value_validate_is_bool(src[0], sm6)) return; @@ -2258,7 +4661,86 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) return; -@@ -8273,7 +8265,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + for (i = 0; i < 3; ++i) +- src_param_init_from_value(&src_params[i], src[i]); ++ src_param_init_from_value(&src_params[i], src[i], sm6); + + instruction_dst_param_init_ssa_scalar(ins, sm6); + } +@@ -7714,7 +7866,7 @@ static bool sm6_metadata_value_is_zero_or_undef(const struct sm6_metadata_value + && (sm6_value_is_undef(m->u.value) || sm6_value_is_constant_zero(m->u.value)); + } + +-static bool sm6_metadata_get_uint_value(const struct sm6_parser *sm6, ++static bool sm6_metadata_get_uint_value(struct sm6_parser *sm6, + const struct sm6_metadata_value *m, unsigned int *u) + { + const struct sm6_value *value; +@@ -7728,12 +7880,12 @@ static bool sm6_metadata_get_uint_value(const struct sm6_parser *sm6, + if (!sm6_type_is_integer(value->type)) + return false; + +- *u = sm6_value_get_constant_uint(value); ++ *u = sm6_value_get_constant_uint(value, sm6); + + return true; + } + +-static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, ++static bool sm6_metadata_get_uint64_value(struct sm6_parser *sm6, + const struct sm6_metadata_value *m, uint64_t *u) + { + const struct sm6_value *value; +@@ -7747,12 +7899,12 @@ static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, + if (!sm6_type_is_integer(value->type)) + return false; + +- *u = sm6_value_get_constant_uint(value); ++ *u = sm6_value_get_constant_uint(value, sm6); + + return true; + } + +-static bool sm6_metadata_get_float_value(const struct sm6_parser *sm6, ++static bool sm6_metadata_get_float_value(struct sm6_parser *sm6, + const struct sm6_metadata_value *m, float *f) + { + const struct sm6_value *value; +@@ -7766,7 +7918,7 @@ static bool sm6_metadata_get_float_value(const struct sm6_parser *sm6, + if (!sm6_type_is_floating_point(value->type)) + return false; + +- *f = register_get_float_value(&value->reg); ++ *f = sm6_value_get_constant_float(value, sm6); + + return true; + } +@@ -7951,7 +8103,7 @@ static void metadata_attachment_record_apply(const struct dxil_record *record, e + } + else if (metadata_node_get_unary_uint(node, &operand, sm6)) + { +- dst->reg.non_uniform = !!operand; ++ dst->non_uniform = !!operand; + } + } + else +@@ -8023,13 +8175,13 @@ static enum vkd3d_result sm6_function_resolve_phi_incomings(const struct sm6_fun + "A PHI incoming value is not a constant or SSA register."); + return VKD3D_ERROR_INVALID_SHADER; + } +- if (src->reg.data_type != phi->reg.data_type) ++ if (src->type != phi->value.type) + { + WARN("Type mismatch.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "The type of a phi incoming value does not match the result type."); + } +- sm6_register_from_value(&phi->incoming[j].reg, src); ++ sm6_register_from_value(&phi->incoming[j].reg, src, sm6); + } + } + } +@@ -8113,12 +8265,11 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const } ins = &code_block->instructions[code_block->instruction_count]; @@ -2267,7 +4749,22 @@ index 194c51a6ffd..db74a7bfbcc 100644 dst = sm6_parser_get_current_value(sm6); fwd_type = dst->type; -@@ -8365,7 +8357,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + dst->type = NULL; +- dst->value_type = VALUE_TYPE_REG; + dst->is_back_ref = true; + is_terminator = false; + +@@ -8196,13 +8347,17 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + if (record->attachment) + metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); + ++ /* This is specific for PHI nodes, but must happen after attachments have been applied. */ ++ if (record->code == FUNC_CODE_INST_PHI) ++ code_block->phi[code_block->phi_count - 1].value = *dst; ++ + if (is_terminator) + { + ++block_idx; code_block = (block_idx < function->block_count) ? function->blocks[block_idx] : NULL; } if (code_block) @@ -2276,7 +4773,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (dst->type && fwd_type && dst->type != fwd_type) { -@@ -8397,7 +8389,7 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ +@@ -8234,7 +8389,7 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ case TERMINATOR_UNCOND_BR: if (!block->terminator.true_block) return; @@ -2285,7 +4782,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) return; vsir_src_param_init_label(&src_params[0], block->terminator.true_block->id); -@@ -8406,7 +8398,7 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ +@@ -8243,7 +8398,7 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ case TERMINATOR_COND_BR: if (!block->terminator.true_block || !block->terminator.false_block) return; @@ -2294,7 +4791,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) return; src_param_init(&src_params[0]); -@@ -8416,7 +8408,7 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ +@@ -8253,7 +8408,7 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ break; case TERMINATOR_SWITCH: @@ -2303,7 +4800,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, block->terminator.case_count * 2u + 1, sm6))) return; src_param_init(&src_params[0]); -@@ -8463,7 +8455,7 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ +@@ -8300,7 +8455,7 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ break; case TERMINATOR_RET: @@ -2312,7 +4809,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 break; default: -@@ -8485,7 +8477,7 @@ static void sm6_block_emit_phi(const struct sm6_block *block, struct sm6_parser +@@ -8322,7 +8477,7 @@ static void sm6_block_emit_phi(const struct sm6_block *block, struct sm6_parser src_phi = &block->phi[i]; incoming_count = src_phi->incoming_count; @@ -2321,7 +4818,16 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_params = instruction_src_params_alloc(ins, incoming_count * 2u, sm6))) return; if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) -@@ -8571,7 +8563,7 @@ static void sm6_parser_emit_label(struct sm6_parser *sm6, unsigned int label_id) +@@ -8342,7 +8497,7 @@ static void sm6_block_emit_phi(const struct sm6_block *block, struct sm6_parser + } + + dst_param_init(dst_param); +- dst_param->reg = src_phi->reg; ++ sm6_register_from_value(&dst_param->reg, &src_phi->value, sm6); + } + } + +@@ -8408,7 +8563,7 @@ 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; @@ -2330,7 +4836,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; -@@ -9181,7 +9173,7 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc +@@ -9018,7 +9173,7 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc if (!m) { @@ -2339,7 +4845,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->declaration.raw_resource.resource.reg.write_mask = 0; return &ins->declaration.raw_resource.resource; } -@@ -9206,7 +9198,7 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc +@@ -9043,7 +9198,7 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc "A typed resource has no data type."); } @@ -2348,7 +4854,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 for (i = 0; i < VKD3D_VEC4_SIZE; ++i) ins->declaration.semantic.resource_data_type[i] = resource_values.data_type; ins->declaration.semantic.resource_type = resource_type; -@@ -9216,14 +9208,14 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc +@@ -9053,14 +9208,14 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc } else if (kind == RESOURCE_KIND_RAWBUFFER) { @@ -2365,7 +4871,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->declaration.structured_resource.byte_stride = resource_values.byte_stride; ins->declaration.structured_resource.resource.reg.write_mask = 0; -@@ -9292,7 +9284,7 @@ static enum vkd3d_result sm6_parser_resources_load_srv(struct sm6_parser *sm6, +@@ -9129,7 +9284,7 @@ static enum vkd3d_result sm6_parser_resources_load_srv(struct sm6_parser *sm6, return VKD3D_ERROR_INVALID_SHADER; } @@ -2374,7 +4880,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (!(resource = sm6_parser_resources_load_common_info(sm6, node->operands[1], false, kind, node->operands[8], ins))) -@@ -9304,7 +9296,7 @@ static enum vkd3d_result sm6_parser_resources_load_srv(struct sm6_parser *sm6, +@@ -9141,7 +9296,7 @@ static enum vkd3d_result sm6_parser_resources_load_srv(struct sm6_parser *sm6, d->kind = kind; d->reg_type = VKD3DSPR_RESOURCE; d->reg_data_type = VKD3D_DATA_UNUSED; @@ -2383,7 +4889,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; init_resource_declaration(resource, VKD3DSPR_RESOURCE, d->reg_data_type, d->id, &d->range); -@@ -9360,7 +9352,7 @@ static enum vkd3d_result sm6_parser_resources_load_uav(struct sm6_parser *sm6, +@@ -9197,7 +9352,7 @@ static enum vkd3d_result sm6_parser_resources_load_uav(struct sm6_parser *sm6, } } @@ -2392,7 +4898,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if (values[1]) ins->flags = VKD3DSUF_GLOBALLY_COHERENT; if (values[2]) -@@ -9378,7 +9370,7 @@ static enum vkd3d_result sm6_parser_resources_load_uav(struct sm6_parser *sm6, +@@ -9215,7 +9370,7 @@ static enum vkd3d_result sm6_parser_resources_load_uav(struct sm6_parser *sm6, d->kind = values[0]; d->reg_type = VKD3DSPR_UAV; d->reg_data_type = VKD3D_DATA_UNUSED; @@ -2401,7 +4907,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; init_resource_declaration(resource, VKD3DSPR_UAV, d->reg_data_type, d->id, &d->range); -@@ -9414,7 +9406,7 @@ static enum vkd3d_result sm6_parser_resources_load_cbv(struct sm6_parser *sm6, +@@ -9251,7 +9406,7 @@ static enum vkd3d_result sm6_parser_resources_load_cbv(struct sm6_parser *sm6, return VKD3D_ERROR_INVALID_SHADER; } @@ -2410,7 +4916,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->resource_type = VKD3D_SHADER_RESOURCE_BUFFER; ins->declaration.cb.size = buffer_size; ins->declaration.cb.src.swizzle = VKD3D_SHADER_NO_SWIZZLE; -@@ -9455,7 +9447,7 @@ static enum vkd3d_result sm6_parser_resources_load_sampler(struct sm6_parser *sm +@@ -9292,7 +9447,7 @@ static enum vkd3d_result sm6_parser_resources_load_sampler(struct sm6_parser *sm "Ignoring %u extra operands for a sampler descriptor.", node->operand_count - 7); } @@ -2419,7 +4925,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->resource_type = VKD3D_SHADER_RESOURCE_NONE; if (!sm6_metadata_get_uint_value(sm6, node->operands[6], &kind)) -@@ -9976,7 +9968,7 @@ static void sm6_parser_emit_global_flags(struct sm6_parser *sm6, const struct sm +@@ -9813,7 +9968,7 @@ static void sm6_parser_emit_global_flags(struct sm6_parser *sm6, const struct sm rotated_flags = (rotated_flags >> 1) | ((rotated_flags & 1) << 4); global_flags = (global_flags & ~mask) | rotated_flags; @@ -2428,7 +4934,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->declaration.global_flags = global_flags; sm6->p.program->global_flags = global_flags; } -@@ -10033,7 +10025,7 @@ static enum vkd3d_result sm6_parser_emit_thread_group(struct sm6_parser *sm6, co +@@ -9870,7 +10025,7 @@ static enum vkd3d_result sm6_parser_emit_thread_group(struct sm6_parser *sm6, co } } @@ -2437,7 +4943,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->declaration.thread_group_size.x = group_sizes[0]; ins->declaration.thread_group_size.y = group_sizes[1]; ins->declaration.thread_group_size.z = group_sizes[2]; -@@ -10073,7 +10065,7 @@ static void sm6_parser_emit_dcl_tessellator_domain(struct sm6_parser *sm6, +@@ -9910,7 +10065,7 @@ static void sm6_parser_emit_dcl_tessellator_domain(struct sm6_parser *sm6, "Domain shader tessellator domain %u is unhandled.", tessellator_domain); } @@ -2446,7 +4952,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->declaration.tessellator_domain = tessellator_domain; sm6->p.program->tess_domain = tessellator_domain; } -@@ -10101,7 +10093,7 @@ static void sm6_parser_emit_dcl_tessellator_partitioning(struct sm6_parser *sm6, +@@ -9938,7 +10093,7 @@ static void sm6_parser_emit_dcl_tessellator_partitioning(struct sm6_parser *sm6, "Hull shader tessellator partitioning %u is unhandled.", tessellator_partitioning); } @@ -2455,7 +4961,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->declaration.tessellator_partitioning = tessellator_partitioning; sm6->p.program->tess_partitioning = tessellator_partitioning; -@@ -10119,7 +10111,7 @@ static void sm6_parser_emit_dcl_tessellator_output_primitive(struct sm6_parser * +@@ -9956,7 +10111,7 @@ static void sm6_parser_emit_dcl_tessellator_output_primitive(struct sm6_parser * "Hull shader tessellator output primitive %u is unhandled.", primitive); } @@ -2464,7 +4970,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->declaration.tessellator_output_primitive = primitive; sm6->p.program->tess_output_primitive = primitive; -@@ -10146,7 +10138,7 @@ static void sm6_parser_emit_dcl_max_tessellation_factor(struct sm6_parser *sm6, +@@ -9983,7 +10138,7 @@ static void sm6_parser_emit_dcl_max_tessellation_factor(struct sm6_parser *sm6, "Hull shader max tessellation factor %f is invalid.", max_tessellation_factor); } @@ -2473,7 +4979,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 ins->declaration.max_tessellation_factor = max_tessellation_factor; } -@@ -10233,7 +10225,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s +@@ -10070,7 +10225,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s break; } @@ -2482,7 +4988,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 sm6->p.program->input_primitive = input_primitive; sm6->p.program->input_control_point_count = input_control_point_count; -@@ -10245,7 +10237,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s +@@ -10082,7 +10237,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, "Geometry shader output vertex count %u is invalid.", i); } @@ -2491,7 +4997,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 sm6->p.program->vertices_out_count = i; if (operands[2] > 1) -@@ -10263,7 +10255,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s +@@ -10100,7 +10255,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s "Geometry shader output primitive %u is unhandled.", output_primitive); output_primitive = VKD3D_PT_TRIANGLELIST; } @@ -2500,7 +5006,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 sm6->p.program->output_topology = output_primitive; i = operands[4]; -@@ -10273,7 +10265,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s +@@ -10110,7 +10265,7 @@ static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct s vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, "Geometry shader instance count %u is invalid.", i); } @@ -2509,7 +5015,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 } static enum vkd3d_tessellator_domain sm6_parser_ds_properties_init(struct sm6_parser *sm6, -@@ -10380,7 +10372,7 @@ static enum vkd3d_tessellator_domain sm6_parser_hs_properties_init(struct sm6_pa +@@ -10217,7 +10372,7 @@ static enum vkd3d_tessellator_domain sm6_parser_hs_properties_init(struct sm6_pa sm6_parser_validate_control_point_count(sm6, operands[1], false, "Hull shader input"); program->input_control_point_count = operands[1]; sm6_parser_validate_control_point_count(sm6, operands[2], false, "Hull shader output"); @@ -2518,7 +5024,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 program->output_control_point_count = operands[2]; sm6_parser_emit_dcl_tessellator_domain(sm6, operands[3]); sm6_parser_emit_dcl_tessellator_partitioning(sm6, operands[4]); -@@ -10905,7 +10897,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro +@@ -10742,7 +10897,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro if (version.type == VKD3D_SHADER_TYPE_HULL) { @@ -2527,7 +5033,7 @@ index 194c51a6ffd..db74a7bfbcc 100644 if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) goto fail; -@@ -10920,7 +10912,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro +@@ -10757,7 +10912,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro goto fail; } @@ -2536,11 +5042,2052 @@ index 194c51a6ffd..db74a7bfbcc 100644 if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) goto fail; +diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c +index a4f1a371299..e5a792583b3 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/fx.c ++++ b/libs/vkd3d/libs/vkd3d-shader/fx.c +@@ -54,6 +54,22 @@ enum state_property_component_type + FX_COMPONENT_TYPE_COUNT, + }; + ++enum fxlvm_constants ++{ ++ FX_FXLC_COMP_COUNT_MASK = 0xffff, ++ FX_FXLC_OPCODE_MASK = 0x7ff, ++ FX_FXLC_OPCODE_SHIFT = 20, ++ FX_FXLC_IS_SCALAR_MASK = 0x80000000, ++ ++ FX_FXLC_REG_UNUSED = 0, ++ FX_FXLC_REG_LITERAL = 1, ++ FX_FXLC_REG_CB = 2, ++ FX_FXLC_REG_INPUT = 3, ++ FX_FXLC_REG_OUTPUT = 4, ++ FX_FXLC_REG_TEMP = 7, ++ FX_FXLC_REG_MAX = FX_FXLC_REG_TEMP, ++}; ++ + struct rhs_named_value + { + const char *name; +@@ -237,6 +253,8 @@ struct fx_write_context_ops + void (*write_technique)(struct hlsl_ir_var *var, struct fx_write_context *fx); + void (*write_pass)(struct hlsl_ir_var *var, struct fx_write_context *fx); + void (*write_annotation)(struct hlsl_ir_var *var, struct fx_write_context *fx); ++ void (*write_state_assignment)(const struct hlsl_ir_var *var, ++ struct hlsl_state_block_entry *entry, struct fx_write_context *fx); + bool are_child_effects_supported; + }; + +@@ -289,15 +307,6 @@ static void set_status(struct fx_write_context *fx, int status) + fx->status = status; + } + +-static void fx_print_string(struct vkd3d_string_buffer *buffer, const char *prefix, +- const char *s, size_t len) +-{ +- if (len) +- --len; /* Trim terminating null. */ +- vkd3d_string_buffer_printf(buffer, "%s", prefix); +- vkd3d_string_buffer_print_string_escaped(buffer, s, len); +-} +- + static uint32_t write_string(const char *string, struct fx_write_context *fx) + { + return fx->ops->write_string(string, fx); +@@ -308,6 +317,15 @@ static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) + fx->ops->write_pass(var, fx); + } + ++static void write_state_assignment(const struct hlsl_ir_var *var, ++ struct hlsl_state_block_entry *entry, struct fx_write_context *fx) ++{ ++ fx->ops->write_state_assignment(var, entry, fx); ++} ++ ++static uint32_t write_state_block(struct hlsl_ir_var *var, ++ unsigned int block_index, struct fx_write_context *fx); ++ + static uint32_t write_annotations(struct hlsl_scope *scope, struct fx_write_context *fx) + { + struct hlsl_ctx *ctx = fx->ctx; +@@ -343,8 +361,6 @@ static void write_fx_4_annotations(struct hlsl_scope *scope, struct fx_write_con + static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx); + static const char * get_fx_4_type_name(const struct hlsl_type *type); + static void write_fx_4_annotation(struct hlsl_ir_var *var, struct fx_write_context *fx); +-static void write_fx_4_state_block(struct hlsl_ir_var *var, unsigned int block_index, +- uint32_t count_offset, struct fx_write_context *fx); + + static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context *fx) + { +@@ -369,18 +385,23 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context + name = get_fx_4_type_name(element_type); + modifiers = element_type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK; + +- LIST_FOR_EACH_ENTRY(type_entry, &fx->types, struct type_entry, entry) ++ /* We don't try to reuse nameless types; they will get the same ++ * "" name, but are not available for the type cache. */ ++ if (name) + { +- if (strcmp(type_entry->name, name)) +- continue; ++ LIST_FOR_EACH_ENTRY(type_entry, &fx->types, struct type_entry, entry) ++ { ++ if (strcmp(type_entry->name, name)) ++ continue; + +- if (type_entry->elements_count != elements_count) +- continue; ++ if (type_entry->elements_count != elements_count) ++ continue; + +- if (type_entry->modifiers != modifiers) +- continue; ++ if (type_entry->modifiers != modifiers) ++ continue; + +- return type_entry->offset; ++ return type_entry->offset; ++ } + } + + if (!(type_entry = hlsl_alloc(fx->ctx, sizeof(*type_entry)))) +@@ -391,7 +412,8 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context + type_entry->elements_count = elements_count; + type_entry->modifiers = modifiers; + +- list_add_tail(&fx->types, &type_entry->entry); ++ if (name) ++ list_add_tail(&fx->types, &type_entry->entry); + + return type_entry->offset; + } +@@ -491,17 +513,22 @@ static uint32_t write_fx_4_string(const char *string, struct fx_write_context *f + return string_entry->offset; + } + ++static void fx_4_decompose_state_blocks(struct hlsl_ir_var *var, struct fx_write_context *fx); ++ + static void write_fx_4_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) + { + struct vkd3d_bytecode_buffer *buffer = &fx->structured; +- uint32_t name_offset, count_offset; ++ uint32_t name_offset, count_offset, count; + + name_offset = write_string(var->name, fx); + put_u32(buffer, name_offset); + count_offset = put_u32(buffer, 0); + ++ fx_4_decompose_state_blocks(var, fx); ++ + write_fx_4_annotations(var->annotations, fx); +- write_fx_4_state_block(var, 0, count_offset, fx); ++ count = write_state_block(var, 0, fx); ++ set_u32(buffer, count_offset, count); + } + + static void write_fx_2_annotations(struct hlsl_ir_var *var, uint32_t count_offset, struct fx_write_context *fx) +@@ -764,208 +791,227 @@ static const struct rhs_named_value fx_2_filter_values[] = + { NULL } + }; + +-static const struct fx_2_state ++struct fx_state + { + const char *name; ++ enum hlsl_type_class container; + enum hlsl_type_class class; + enum state_property_component_type type; + unsigned int dimx; + uint32_t array_size; + uint32_t id; + const struct rhs_named_value *values; +-} +-fx_2_states[] = +-{ +- { "ZEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 0, fx_2_zenable_values }, +- { "FillMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 1, fx_2_fillmode_values }, +- { "ShadeMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 2, fx_2_shademode_values }, +- { "ZWriteEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 3 }, +- { "AlphaTestEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 4 }, +- { "LastPixel", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 5 }, +- { "SrcBlend", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 6, fx_2_blendmode_values }, +- { "DestBlend", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 7, fx_2_blendmode_values }, +- { "CullMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 8, fx_2_cullmode_values }, +- { "ZFunc", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 9, fx_2_cmpfunc_values }, +- { "AlphaRef", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 10 }, +- { "AlphaFunc", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 11, fx_2_cmpfunc_values }, +- { "DitherEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 12 }, +- { "AlphaBlendEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 13 }, +- { "FogEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 14 }, +- { "SpecularEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 15 }, +- { "FogColor", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 16 }, +- { "FogTableMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 17, fx_2_fogmode_values }, +- { "FogStart", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 18 }, +- { "FogEnd", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 19 }, +- { "FogDensity", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 20 }, +- { "RangeFogEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 21 }, +- { "StencilEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 22 }, +- { "StencilFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 23, fx_2_stencilcaps_values }, +- { "StencilZFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 24, fx_2_stencilcaps_values }, +- { "StencilPass", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 25, fx_2_stencilcaps_values }, +- { "StencilFunc", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 26, fx_2_cmpfunc_values }, +- { "StencilRef", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 27 }, +- { "StencilMask", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 28 }, +- { "StencilWriteMask", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 29 }, +- { "TextureFactor", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 30 }, +- { "Wrap0", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 31, fx_2_wrap_values }, +- { "Wrap1", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 32, fx_2_wrap_values }, +- { "Wrap2", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 33, fx_2_wrap_values }, +- { "Wrap3", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 34, fx_2_wrap_values }, +- { "Wrap4", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 35, fx_2_wrap_values }, +- { "Wrap5", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 36, fx_2_wrap_values }, +- { "Wrap6", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 37, fx_2_wrap_values }, +- { "Wrap7", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 38, fx_2_wrap_values }, +- { "Wrap8", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 39, fx_2_wrap_values }, +- { "Wrap9", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 40, fx_2_wrap_values }, +- { "Wrap10", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 41, fx_2_wrap_values }, +- { "Wrap11", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 42, fx_2_wrap_values }, +- { "Wrap12", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 43, fx_2_wrap_values }, +- { "Wrap13", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 44, fx_2_wrap_values }, +- { "Wrap14", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 45, fx_2_wrap_values }, +- { "Wrap15", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 46, fx_2_wrap_values }, +- { "Clipping", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 47 }, +- { "Lighting", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 48 }, +- { "Ambient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 49 }, +- { "FogVertexMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 50, fx_2_fogmode_values }, +- { "ColorVertex", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 51 }, +- { "LocalViewer", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 52 }, +- { "NormalizeNormals", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 53 }, +- +- { "DiffuseMaterialSource", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 54, fx_2_materialcolorsource_values }, +- { "SpecularMaterialSource", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 55, fx_2_materialcolorsource_values }, +- { "AmbientMaterialSource", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 56, fx_2_materialcolorsource_values }, +- { "EmissiveMaterialSource", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 57, fx_2_materialcolorsource_values }, +- +- { "VertexBlend", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 58, fx_2_vertexblend_values }, +- { "ClipPlaneEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 59, fx_2_clipplane_values }, +- { "PointSize", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 60 }, +- { "PointSize_Min", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 61 }, +- { "PointSize_Max", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 62 }, +- { "PointSpriteEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 63 }, +- { "PointScaleEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 64 }, +- { "PointScale_A", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 65 }, +- { "PointScale_B", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 66 }, +- { "PointScale_C", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 67 }, +- +- { "MultiSampleAntialias", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 68 }, +- { "MultiSampleMask", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 69 }, +- { "PatchEdgeStyle", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 70, fx_2_patchedgestyle_values }, +- { "DebugMonitorToken", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 71 }, +- { "IndexedVertexBlendEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 72 }, +- { "ColorWriteEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 73, fx_2_colorwriteenable_values }, +- { "TweenFactor", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 74 }, +- { "BlendOp", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 75, fx_2_blendop_values }, +- { "PositionDegree", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 76, fx_2_degree_values }, +- { "NormalDegree", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 77, fx_2_degree_values }, +- { "ScissorTestEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 78 }, +- { "SlopeScaleDepthBias", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 79 }, +- +- { "AntialiasedLineEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 80 }, +- { "MinTessellationLevel", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 81 }, +- { "MaxTessellationLevel", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 82 }, +- { "AdaptiveTess_X", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 83 }, +- { "AdaptiveTess_Y", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 84 }, +- { "AdaptiveTess_Z", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 85 }, +- { "AdaptiveTess_W", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 86 }, +- { "EnableAdaptiveTesselation", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 87 }, +- { "TwoSidedStencilMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 88 }, +- { "StencilFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 89, fx_2_stencilcaps_values }, +- { "StencilZFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 90, fx_2_stencilcaps_values }, +- { "StencilPass", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 91, fx_2_stencilcaps_values }, +- { "StencilFunc", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 92, fx_2_cmpfunc_values }, +- +- { "ColorWriteEnable1", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 93, fx_2_colorwriteenable_values }, +- { "ColorWriteEnable2", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 94, fx_2_colorwriteenable_values }, +- { "ColorWriteEnable3", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 95, fx_2_colorwriteenable_values }, +- { "BlendFactor", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 96 }, +- { "SRGBWriteEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 97 }, +- { "DepthBias", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 98 }, +- { "SeparateAlphaBlendEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 99 }, +- { "SrcBlendAlpha", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 100, fx_2_blendmode_values }, +- { "DestBlendAlpha", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 101, fx_2_blendmode_values }, +- { "BlendOpAlpha", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 102, fx_2_blendmode_values }, +- +- { "ColorOp", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 103, fx_2_textureop_values }, +- { "ColorArg0", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 104, fx_2_colorarg_values }, +- { "ColorArg1", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 105, fx_2_colorarg_values }, +- { "ColorArg2", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 106, fx_2_colorarg_values }, +- { "AlphaOp", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 107, fx_2_textureop_values }, +- { "AlphaArg0", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 108, fx_2_colorarg_values }, +- { "AlphaArg1", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 109, fx_2_colorarg_values }, +- { "AlphaArg2", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 110, fx_2_colorarg_values }, +- { "ResultArg", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 111, fx_2_colorarg_values }, +- { "BumpEnvMat00", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 112 }, +- { "BumpEnvMat01", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 113 }, +- { "BumpEnvMat10", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 114 }, +- { "BumpEnvMat11", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 115 }, +- { "TextCoordIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 116 }, +- { "BumpEnvLScale", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 117 }, +- { "BumpEnvLOffset", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 118 }, +- { "TextureTransformFlags", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 119, fx_2_texturetransform_values }, +- { "Constant", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 120 }, +- { "NPatchMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 121 }, +- { "FVF", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 122 }, +- +- { "ProjectionTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 123 }, +- { "ViewTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 124 }, +- { "WorldTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 125 }, +- { "TextureTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 8, 126 }, +- +- { "MaterialAmbient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 127 }, +- { "MaterialDiffuse", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 128 }, +- { "MaterialSpecular", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 129 }, +- { "MaterialEmissive", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 130 }, +- { "MaterialPower", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 131 }, +- +- { "LightType", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 132, fx_2_lighttype_values }, +- { "LightDiffuse", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 133 }, +- { "LightSpecular", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 134 }, +- { "LightAmbient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 135 }, +- { "LightPosition", HLSL_CLASS_VECTOR, FX_FLOAT, 3, 1, 136 }, +- { "LightDirection", HLSL_CLASS_VECTOR, FX_FLOAT, 3, 1, 137 }, +- { "LightRange", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 138 }, +- { "LightFalloff", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 139 }, +- { "LightAttenuation0", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 140 }, +- { "LightAttenuation1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 141 }, +- { "LightAttenuation2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 142 }, +- { "LightTheta", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 143 }, +- { "LightPhi", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 144 }, +- { "LightEnable", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 145 }, +- +- { "VertexShader", HLSL_CLASS_SCALAR, FX_VERTEXSHADER, 1, 1, 146 }, +- { "PixelShader", HLSL_CLASS_SCALAR, FX_PIXELSHADER, 1, 1, 147 }, +- +- { "VertexShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 148 }, +- { "VertexShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u-1, 149 }, +- { "VertexShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u-1, 150 }, +- { "VertexShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 151 }, +- { "VertexShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 152 }, +- { "VertexShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 153 }, +- { "VertexShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 154 }, +- { "VertexShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 155 }, +- +- { "PixelShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 156 }, +- { "PixelShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u-1, 157 }, +- { "PixelShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u-1, 158 }, +- { "PixelShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 159 }, +- { "PixelShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 160 }, +- { "PixelShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 161 }, +- { "PixelShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 162 }, +- { "PixelShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 163 }, +- +- { "Texture", HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 1, 164 }, +- { "AddressU", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 165, fx_2_address_values }, +- { "AddressV", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 166, fx_2_address_values }, +- { "AddressW", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 167, fx_2_address_values }, +- { "BorderColor", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 168 }, +- { "MagFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 169, fx_2_filter_values }, +- { "MinFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 170, fx_2_filter_values }, +- { "MipFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 171, fx_2_filter_values }, +- { "MipMapLodBias", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 172 }, +- { "MaxMipLevel", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 173 }, +- { "MaxAnisotropy", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 174 }, +- { "SRBTexture", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 175 }, +- { "ElementIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 176 }, ++}; ++ ++static const struct fx_state fx_2_pass_states[] = ++{ ++ { "ZEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 0, fx_2_zenable_values }, ++ { "FillMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 1, fx_2_fillmode_values }, ++ { "ShadeMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 2, fx_2_shademode_values }, ++ { "ZWriteEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 3 }, ++ { "AlphaTestEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 4 }, ++ { "LastPixel", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 5 }, ++ { "SrcBlend", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 6, fx_2_blendmode_values }, ++ { "DestBlend", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 7, fx_2_blendmode_values }, ++ { "CullMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 8, fx_2_cullmode_values }, ++ { "ZFunc", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 9, fx_2_cmpfunc_values }, ++ { "AlphaRef", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 10 }, ++ { "AlphaFunc", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 11, fx_2_cmpfunc_values }, ++ { "DitherEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 12 }, ++ { "AlphaBlendEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 13 }, ++ { "FogEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 14 }, ++ { "SpecularEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 15 }, ++ { "FogColor", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 16 }, ++ { "FogTableMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 17, fx_2_fogmode_values }, ++ { "FogStart", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 18 }, ++ { "FogEnd", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 19 }, ++ { "FogDensity", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 20 }, ++ { "RangeFogEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 21 }, ++ { "StencilEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 22 }, ++ { "StencilFail", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 23, fx_2_stencilcaps_values }, ++ { "StencilZFail", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 24, fx_2_stencilcaps_values }, ++ { "StencilPass", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 25, fx_2_stencilcaps_values }, ++ { "StencilFunc", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 26, fx_2_cmpfunc_values }, ++ { "StencilRef", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 27 }, ++ { "StencilMask", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 28 }, ++ { "StencilWriteMask", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 29 }, ++ { "TextureFactor", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 30 }, ++ { "Wrap0", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 31, fx_2_wrap_values }, ++ { "Wrap1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 32, fx_2_wrap_values }, ++ { "Wrap2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 33, fx_2_wrap_values }, ++ { "Wrap3", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 34, fx_2_wrap_values }, ++ { "Wrap4", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 35, fx_2_wrap_values }, ++ { "Wrap5", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 36, fx_2_wrap_values }, ++ { "Wrap6", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 37, fx_2_wrap_values }, ++ { "Wrap7", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 38, fx_2_wrap_values }, ++ { "Wrap8", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 39, fx_2_wrap_values }, ++ { "Wrap9", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 40, fx_2_wrap_values }, ++ { "Wrap10", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 41, fx_2_wrap_values }, ++ { "Wrap11", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 42, fx_2_wrap_values }, ++ { "Wrap12", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 43, fx_2_wrap_values }, ++ { "Wrap13", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 44, fx_2_wrap_values }, ++ { "Wrap14", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 45, fx_2_wrap_values }, ++ { "Wrap15", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 46, fx_2_wrap_values }, ++ { "Clipping", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 47 }, ++ { "Lighting", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 48 }, ++ { "Ambient", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 49 }, ++ { "FogVertexMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 50, fx_2_fogmode_values }, ++ { "ColorVertex", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 51 }, ++ { "LocalViewer", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 52 }, ++ { "NormalizeNormals", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 53 }, ++ ++ { "DiffuseMaterialSource", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 54, fx_2_materialcolorsource_values }, ++ { "SpecularMaterialSource", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 55, fx_2_materialcolorsource_values }, ++ { "AmbientMaterialSource", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 56, fx_2_materialcolorsource_values }, ++ { "EmissiveMaterialSource", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 57, fx_2_materialcolorsource_values }, ++ ++ { "VertexBlend", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 58, fx_2_vertexblend_values }, ++ { "ClipPlaneEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 59, fx_2_clipplane_values }, ++ { "PointSize", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 60 }, ++ { "PointSize_Min", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 61 }, ++ { "PointSize_Max", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 62 }, ++ { "PointSpriteEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 63 }, ++ { "PointScaleEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 64 }, ++ { "PointScale_A", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 65 }, ++ { "PointScale_B", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 66 }, ++ { "PointScale_C", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 67 }, ++ ++ { "MultiSampleAntialias", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 68 }, ++ { "MultiSampleMask", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 69 }, ++ { "PatchEdgeStyle", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 70, fx_2_patchedgestyle_values }, ++ { "DebugMonitorToken", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 71 }, ++ { "IndexedVertexBlendEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 72 }, ++ { "ColorWriteEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 73, fx_2_colorwriteenable_values }, ++ { "TweenFactor", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 74 }, ++ { "BlendOp", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 75, fx_2_blendop_values }, ++ { "PositionDegree", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 76, fx_2_degree_values }, ++ { "NormalDegree", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 77, fx_2_degree_values }, ++ { "ScissorTestEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 78 }, ++ { "SlopeScaleDepthBias", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 79 }, ++ ++ { "AntialiasedLineEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 80 }, ++ { "MinTessellationLevel", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 81 }, ++ { "MaxTessellationLevel", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 82 }, ++ { "AdaptiveTess_X", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 83 }, ++ { "AdaptiveTess_Y", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 84 }, ++ { "AdaptiveTess_Z", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 85 }, ++ { "AdaptiveTess_W", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 86 }, ++ { "EnableAdaptiveTessellation",HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 87 }, ++ { "TwoSidedStencilMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 88 }, ++ { "StencilFail", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 89, fx_2_stencilcaps_values }, ++ { "StencilZFail", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 90, fx_2_stencilcaps_values }, ++ { "StencilPass", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 91, fx_2_stencilcaps_values }, ++ { "StencilFunc", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 92, fx_2_cmpfunc_values }, ++ ++ { "ColorWriteEnable1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 93, fx_2_colorwriteenable_values }, ++ { "ColorWriteEnable2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 94, fx_2_colorwriteenable_values }, ++ { "ColorWriteEnable3", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 95, fx_2_colorwriteenable_values }, ++ { "BlendFactor", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 96 }, ++ { "SRGBWriteEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 97 }, ++ { "DepthBias", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 98 }, ++ { "SeparateAlphaBlendEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 99 }, ++ { "SrcBlendAlpha", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 100, fx_2_blendmode_values }, ++ { "DestBlendAlpha", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 101, fx_2_blendmode_values }, ++ { "BlendOpAlpha", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 102, fx_2_blendmode_values }, ++ ++ { "ColorOp", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 103, fx_2_textureop_values }, ++ { "ColorArg0", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 104, fx_2_colorarg_values }, ++ { "ColorArg1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 105, fx_2_colorarg_values }, ++ { "ColorArg2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 106, fx_2_colorarg_values }, ++ { "AlphaOp", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 107, fx_2_textureop_values }, ++ { "AlphaArg0", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 108, fx_2_colorarg_values }, ++ { "AlphaArg1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 109, fx_2_colorarg_values }, ++ { "AlphaArg2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 110, fx_2_colorarg_values }, ++ { "ResultArg", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 111, fx_2_colorarg_values }, ++ { "BumpEnvMat00", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 112 }, ++ { "BumpEnvMat01", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 113 }, ++ { "BumpEnvMat10", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 114 }, ++ { "BumpEnvMat11", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 115 }, ++ { "TexCoordIndex", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 116 }, ++ { "BumpEnvLScale", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 117 }, ++ { "BumpEnvLOffset", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 118 }, ++ { "TextureTransformFlags", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 119, fx_2_texturetransform_values }, ++ { "Constant", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 120 }, ++ { "PatchSegments", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 121 }, ++ { "FVF", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 122 }, ++ ++ { "ProjectionTransform", HLSL_CLASS_PASS, HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 123 }, ++ { "ViewTransform", HLSL_CLASS_PASS, HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 124 }, ++ { "WorldTransform", HLSL_CLASS_PASS, HLSL_CLASS_MATRIX, FX_FLOAT, 4, 256, 125 }, ++ { "TextureTransform", HLSL_CLASS_PASS, HLSL_CLASS_MATRIX, FX_FLOAT, 4, 8, 126 }, ++ ++ { "MaterialDiffuse", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 127 }, ++ { "MaterialAmbient", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 128 }, ++ { "MaterialSpecular", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 129 }, ++ { "MaterialEmissive", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 130 }, ++ { "MaterialPower", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 131 }, ++ ++ { "LightType", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 132, fx_2_lighttype_values }, ++ { "LightDiffuse", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 133 }, ++ { "LightSpecular", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 134 }, ++ { "LightAmbient", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 135 }, ++ { "LightPosition", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 3, ~0u, 136 }, ++ { "LightDirection", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 3, ~0u, 137 }, ++ { "LightRange", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 138 }, ++ { "LightFalloff", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 139 }, ++ { "LightAttenuation0", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 140 }, ++ { "LightAttenuation1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 141 }, ++ { "LightAttenuation2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 142 }, ++ { "LightTheta", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 143 }, ++ { "LightPhi", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 144 }, ++ { "LightEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 145 }, ++ ++ { "VertexShader", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_VERTEXSHADER, 1, 1, 146 }, ++ { "PixelShader", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_PIXELSHADER, 1, 1, 147 }, ++ ++ { "VertexShaderConstantF", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 148 }, ++ { "VertexShaderConstantB", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u, 149 }, ++ { "VertexShaderConstantI", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 150 }, ++ { "VertexShaderConstant", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 151 }, ++ { "VertexShaderConstant1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 152 }, ++ { "VertexShaderConstant2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 153 }, ++ { "VertexShaderConstant3", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 154 }, ++ { "VertexShaderConstant4", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 155 }, ++ ++ { "PixelShaderConstantF", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 156 }, ++ { "PixelShaderConstantB", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u, 157 }, ++ { "PixelShaderConstantI", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 158 }, ++ { "PixelShaderConstant", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 159 }, ++ { "PixelShaderConstant1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 160 }, ++ { "PixelShaderConstant2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 161 }, ++ { "PixelShaderConstant3", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 162 }, ++ { "PixelShaderConstant4", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 163 }, ++ ++ { "Texture", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 261, 164 }, ++ { "AddressU", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 165, fx_2_address_values }, ++ { "AddressV", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 166, fx_2_address_values }, ++ { "AddressW", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 167, fx_2_address_values }, ++ { "BorderColor", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 168 }, ++ { "MagFilter", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 169, fx_2_filter_values }, ++ { "MinFilter", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 170, fx_2_filter_values }, ++ { "MipFilter", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 171, fx_2_filter_values }, ++ { "MipMapLodBias", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 172 }, ++ { "MaxMipLevel", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 173 }, ++ { "MaxAnisotropy", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 174 }, ++ { "SRGBTexture", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 175 }, ++ { "ElementIndex", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 176 }, ++}; ++ ++static const struct fx_state fx_2_sampler_states[] = ++{ ++ { "Texture", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 1, 164 }, ++ { "AddressU", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 165, fx_2_address_values }, ++ { "AddressV", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 166, fx_2_address_values }, ++ { "AddressW", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 167, fx_2_address_values }, ++ { "BorderColor", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 168 }, ++ { "MagFilter", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 169, fx_2_filter_values }, ++ { "MinFilter", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 170, fx_2_filter_values }, ++ { "MipFilter", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 171, fx_2_filter_values }, ++ { "MipMapLodBias", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 172 }, ++ { "MaxMipLevel", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 173 }, ++ { "MaxAnisotropy", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 174 }, ++ { "SRGBTexture", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 175 }, ++ { "ElementIndex", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 176 }, + }; + + static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) +@@ -988,16 +1034,6 @@ static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx + fx->shader_count++; + } + +-static uint32_t get_fx_4_type_size(const struct hlsl_type *type) +-{ +- uint32_t elements_count; +- +- elements_count = hlsl_get_multiarray_size(type); +- type = hlsl_get_multiarray_element_type(type); +- +- return type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float) * elements_count; +-} +- + enum fx_4_type_constants + { + /* Numeric types encoding */ +@@ -1015,6 +1051,9 @@ enum fx_4_type_constants + FX_4_NUMERIC_COLUMNS_SHIFT = 11, + FX_4_NUMERIC_COLUMN_MAJOR_MASK = 0x4000, + ++ /* Variable flags */ ++ FX_4_HAS_EXPLICIT_BIND_POINT = 0x4, ++ + /* Object types */ + FX_4_OBJECT_TYPE_STRING = 0x1, + FX_4_OBJECT_TYPE_BLEND_STATE = 0x2, +@@ -1071,17 +1110,6 @@ enum fx_4_type_constants + FX_4_ASSIGNMENT_VALUE_EXPRESSION = 0x6, + FX_4_ASSIGNMENT_INLINE_SHADER = 0x7, + FX_5_ASSIGNMENT_INLINE_SHADER = 0x8, +- +- /* FXLVM constants */ +- FX_4_FXLC_COMP_COUNT_MASK = 0xffff, +- FX_4_FXLC_OPCODE_MASK = 0x7ff, +- FX_4_FXLC_OPCODE_SHIFT = 20, +- FX_4_FXLC_IS_SCALAR_MASK = 0x80000000, +- +- FX_4_FXLC_REG_LITERAL = 1, +- FX_4_FXLC_REG_CB = 2, +- FX_4_FXLC_REG_OUTPUT = 4, +- FX_4_FXLC_REG_TEMP = 7, + }; + + static const uint32_t fx_4_numeric_base_types[] = +@@ -1238,7 +1266,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + + name = get_fx_4_type_name(element_type); + +- name_offset = write_string(name, fx); ++ name_offset = write_string(name ? name : "", fx); + if (element_type->class == HLSL_CLASS_STRUCT) + { + if (!(field_offsets = hlsl_calloc(ctx, element_type->e.record.field_count, sizeof(*field_offsets)))) +@@ -1541,12 +1569,33 @@ static uint32_t get_fx_2_type_class(const struct hlsl_type *type) + return hlsl_sm1_class(type); + } + +-static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *name, +- const struct hlsl_semantic *semantic, bool is_combined_sampler, struct fx_write_context *fx) ++struct fx_2_write_type_context + { +- struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; +- uint32_t semantic_offset, offset, elements_count = 0, name_offset; +- size_t i; ++ uint32_t *names; ++ uint32_t *semantics; ++ uint32_t count; ++ ++ uint32_t offset; ++ ++ bool is_combined_sampler; ++ struct fx_write_context *fx; ++}; ++ ++static void count_type_iter(const struct hlsl_type *type, const char *name, ++ const struct hlsl_semantic *semantic, void *context) ++{ ++ struct fx_2_write_type_context *ctx = context; ++ ++ ++ctx->count; ++} ++ ++static void write_fx_2_type_iter(const struct hlsl_type *type, const char *name, ++ const struct hlsl_semantic *semantic, void *context) ++{ ++ struct fx_2_write_type_context *ctx = context; ++ struct fx_write_context *fx = ctx->fx; ++ struct vkd3d_bytecode_buffer *buffer; ++ uint32_t offset, elements_count = 0; + + /* Resolve arrays to element type and number of elements. */ + if (type->class == HLSL_CLASS_ARRAY) +@@ -1555,13 +1604,11 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n + type = hlsl_get_multiarray_element_type(type); + } + +- name_offset = write_string(name, fx); +- semantic_offset = semantic->raw_name ? write_string(semantic->raw_name, fx) : 0; +- +- offset = put_u32(buffer, hlsl_sm1_base_type(type, is_combined_sampler)); ++ buffer = &fx->unstructured; ++ offset = put_u32(buffer, hlsl_sm1_base_type(type, ctx->is_combined_sampler)); + put_u32(buffer, get_fx_2_type_class(type)); +- put_u32(buffer, name_offset); +- put_u32(buffer, semantic_offset); ++ *ctx->names++ = put_u32(buffer, 0); ++ *ctx->semantics++ = put_u32(buffer, 0); + put_u32(buffer, elements_count); + + switch (type->class) +@@ -1586,19 +1633,68 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n + ; + } + ++ /* Save the offset of the top level type. */ ++ if (!ctx->offset) ++ ctx->offset = offset; ++} ++ ++static void write_fx_2_type_strings_iter(const struct hlsl_type *type, const char *name, ++ const struct hlsl_semantic *semantic, void *context) ++{ ++ struct fx_2_write_type_context *ctx = context; ++ struct fx_write_context *fx = ctx->fx; ++ struct vkd3d_bytecode_buffer *buffer; ++ ++ buffer = &fx->unstructured; ++ set_u32(buffer, *ctx->names++, write_string(name, fx)); ++ set_u32(buffer, *ctx->semantics++, semantic->raw_name ? write_string(semantic->raw_name, fx) : 0); ++} ++ ++static void foreach_type(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic, ++ void (*iter_func)(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic, void *context), ++ void *context) ++{ ++ iter_func(type, name, semantic, context); ++ ++ type = hlsl_get_multiarray_element_type(type); + if (type->class == HLSL_CLASS_STRUCT) + { +- for (i = 0; i < type->e.record.field_count; ++i) ++ for (size_t i = 0; i < type->e.record.field_count; ++i) + { + const struct hlsl_struct_field *field = &type->e.record.fields[i]; +- +- /* Validated in check_invalid_object_fields(). */ +- VKD3D_ASSERT(hlsl_is_numeric_type(field->type)); +- write_fx_2_parameter(field->type, field->name, &field->semantic, false, fx); ++ foreach_type(field->type, field->name, &field->semantic, iter_func, context); + } + } ++} + +- return offset; ++static uint32_t write_fx_2_parameter(const struct hlsl_ir_var *var, struct fx_write_context *fx) ++{ ++ struct fx_2_write_type_context ctx = { .fx = fx, .is_combined_sampler = var->is_combined_sampler }; ++ uint32_t *offsets; ++ ++ /* Parameter type information has to be stored in a contiguous segment, so ++ * that any structure fields come right after each other. To achieve that ++ * the variable length string data is written after the type data. */ ++ ++ /* Calculate the number of string entries needed for this type. */ ++ foreach_type(var->data_type, var->name, &var->semantic, count_type_iter, &ctx); ++ ++ if (!(offsets = calloc(ctx.count, 2 * sizeof(*offsets)))) ++ return 0; ++ ++ /* Writing type information also sets string offsets. */ ++ ctx.names = offsets; ++ ctx.semantics = &offsets[ctx.count]; ++ foreach_type(var->data_type, var->name, &var->semantic, write_fx_2_type_iter, &ctx); ++ ++ /* Now the final pass to write the string data. */ ++ ctx.names = offsets; ++ ctx.semantics = &offsets[ctx.count]; ++ foreach_type(var->data_type, var->name, &var->semantic, write_fx_2_type_strings_iter, &ctx); ++ ++ free(offsets); ++ ++ return ctx.offset; + } + + static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) +@@ -1623,6 +1719,15 @@ static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_contex + set_u32(buffer, pass_count_offset, count); + } + ++/* Effects represent bool values as 1/0, as opposed to ~0u/0 as used by ++ * Direct3D shader model 4+. */ ++static uint32_t get_fx_default_numeric_value(const struct hlsl_type *type, uint32_t value) ++{ ++ if (type->e.numeric.type == HLSL_TYPE_BOOL) ++ return !!value; ++ return value; ++} ++ + static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hlsl_default_value *value, + struct fx_write_context *fx) + { +@@ -1656,7 +1761,7 @@ static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hl + + for (j = 0; j < comp_count; ++j) + { +- put_u32(buffer, value->number.u); ++ put_u32(buffer, get_fx_default_numeric_value(type, value->number.u)); + value++; + } + break; +@@ -1673,8 +1778,8 @@ static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hl + + for (j = 0; j < type->e.record.field_count; ++j) + { +- write_fx_2_default_value(fields[i].type, value, fx); +- value += hlsl_type_component_count(fields[i].type); ++ write_fx_2_default_value(fields[j].type, value, fx); ++ value += hlsl_type_component_count(fields[j].type); + } + break; + } +@@ -1861,7 +1966,7 @@ static void write_fx_2_parameters(struct fx_write_context *fx) + if (!is_type_supported_fx_2(ctx, var->data_type, &var->loc)) + continue; + +- desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, var->is_combined_sampler, fx); ++ desc_offset = write_fx_2_parameter(var, fx); + value_offset = write_fx_2_initial_value(var, fx); + + flags = 0; +@@ -1884,19 +1989,28 @@ static void write_fx_2_annotation(struct hlsl_ir_var *var, struct fx_write_conte + struct vkd3d_bytecode_buffer *buffer = &fx->structured; + uint32_t desc_offset, value_offset; + +- desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, var->is_combined_sampler, fx); ++ desc_offset = write_fx_2_parameter(var, fx); + value_offset = write_fx_2_initial_value(var, fx); + + put_u32(buffer, desc_offset); + put_u32(buffer, value_offset); + } + ++static void write_fx_2_state_assignment(const struct hlsl_ir_var *var, ++ struct hlsl_state_block_entry *entry, struct fx_write_context *fx) ++{ ++ struct hlsl_ctx *ctx = fx->ctx; ++ ++ hlsl_fixme(ctx, &var->loc, "Writing fx_2_0 state assignments is not implemented."); ++} ++ + static const struct fx_write_context_ops fx_2_ops = + { + .write_string = write_fx_2_string, + .write_technique = write_fx_2_technique, + .write_pass = write_fx_2_pass, + .write_annotation = write_fx_2_annotation, ++ .write_state_assignment = write_fx_2_state_assignment, + }; + + static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) +@@ -1959,12 +2073,16 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) + return fx_write_context_cleanup(&fx); + } + ++static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, ++ struct hlsl_state_block_entry *entry, struct fx_write_context *fx); ++ + static const struct fx_write_context_ops fx_4_ops = + { + .write_string = write_fx_4_string, + .write_technique = write_fx_4_technique, + .write_pass = write_fx_4_pass, + .write_annotation = write_fx_4_annotation, ++ .write_state_assignment = write_fx_4_state_assignment, + .are_child_effects_supported = true, + }; + +@@ -2001,7 +2119,7 @@ static uint32_t write_fx_4_default_value(struct hlsl_type *value_type, struct hl + + for (j = 0; j < comp_count; ++j) + { +- put_u32_unaligned(buffer, value->number.u); ++ put_u32_unaligned(buffer, get_fx_default_numeric_value(type, value->number.u)); + value++; + } + break; +@@ -2018,8 +2136,8 @@ static uint32_t write_fx_4_default_value(struct hlsl_type *value_type, struct hl + + for (j = 0; j < type->e.record.field_count; ++j) + { +- write_fx_4_default_value(fields[i].type, value, fx); +- value += hlsl_type_component_count(fields[i].type); ++ write_fx_4_default_value(fields[j].type, value, fx); ++ value += hlsl_type_component_count(fields[j].type); + } + break; + } +@@ -2057,13 +2175,9 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, st + struct vkd3d_bytecode_buffer *buffer = &fx->structured; + uint32_t name_offset, type_offset, value_offset; + uint32_t semantic_offset, flags = 0; +- enum fx_4_numeric_variable_flags +- { +- HAS_EXPLICIT_BIND_POINT = 0x4, +- }; + + if (var->has_explicit_bind_point) +- flags |= HAS_EXPLICIT_BIND_POINT; ++ flags |= FX_4_HAS_EXPLICIT_BIND_POINT; + + type_offset = write_type(var->data_type, fx); + name_offset = write_string(var->name, fx); +@@ -2163,7 +2277,7 @@ static uint32_t write_fx_4_state_numeric_value(struct hlsl_ir_constant *value, s + } + + put_u32_unaligned(buffer, type); +- put_u32_unaligned(buffer, value->value.u[i].u); ++ put_u32_unaligned(buffer, get_fx_default_numeric_value(data_type, value->value.u[i].u)); + } + + return offset; +@@ -2576,18 +2690,7 @@ static const struct rhs_named_value null_values[] = + { NULL } + }; + +-static const struct fx_4_state +-{ +- const char *name; +- enum hlsl_type_class container; +- enum hlsl_type_class class; +- enum state_property_component_type type; +- unsigned int dimx; +- unsigned int array_size; +- int id; +- const struct rhs_named_value *values; +-} +-fx_4_states[] = ++static const struct fx_state fx_4_states[] = + { + { "RasterizerState", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_RASTERIZER, 1, 1, 0 }, + { "DepthStencilState", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_DEPTHSTENCIL, 1, 1, 1 }, +@@ -2655,7 +2758,7 @@ fx_4_states[] = + { "ComputeShader", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_COMPUTESHADER, 1, 1, 58 }, + }; + +-static const struct fx_4_state fx_5_blend_states[] = ++static const struct fx_state fx_5_blend_states[] = + { + { "AlphaToCoverageEnable", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 1, 36, bool_values }, + { "BlendEnable", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 8, 37, bool_values }, +@@ -2668,45 +2771,61 @@ static const struct fx_4_state fx_5_blend_states[] = + { "RenderTargetWriteMask", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT8, 1, 8, 44 }, + }; + +-struct fx_4_state_table ++struct fx_state_table + { +- const struct fx_4_state *ptr; ++ const struct fx_state *ptr; + unsigned int count; + }; + +-static struct fx_4_state_table fx_4_get_state_table(enum hlsl_type_class type_class, ++static struct fx_state_table fx_get_state_table(enum hlsl_type_class type_class, + unsigned int major, unsigned int minor) + { +- struct fx_4_state_table table; ++ struct fx_state_table table; + +- if (type_class == HLSL_CLASS_BLEND_STATE && (major == 5 || (major == 4 && minor == 1))) ++ if (major == 2) + { +- table.ptr = fx_5_blend_states; +- table.count = ARRAY_SIZE(fx_5_blend_states); ++ if (type_class == HLSL_CLASS_PASS) ++ { ++ table.ptr = fx_2_pass_states; ++ table.count = ARRAY_SIZE(fx_2_pass_states); ++ } ++ else ++ { ++ table.ptr = fx_2_sampler_states; ++ table.count = ARRAY_SIZE(fx_2_sampler_states); ++ } + } + else + { +- table.ptr = fx_4_states; +- table.count = ARRAY_SIZE(fx_4_states); ++ if (type_class == HLSL_CLASS_BLEND_STATE && (major == 5 || (major == 4 && minor == 1))) ++ { ++ table.ptr = fx_5_blend_states; ++ table.count = ARRAY_SIZE(fx_5_blend_states); ++ } ++ else ++ { ++ table.ptr = fx_4_states; ++ table.count = ARRAY_SIZE(fx_4_states); ++ } + } + + return table; + } + +-static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, ++static void resolve_fx_state_block_values(struct hlsl_ir_var *var, + struct hlsl_state_block_entry *entry, struct fx_write_context *fx) + { + const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); + struct replace_state_context replace_context; +- const struct fx_4_state *state = NULL; ++ const struct fx_state *state = NULL; + struct hlsl_type *state_type = NULL; + struct hlsl_ctx *ctx = fx->ctx; + enum hlsl_base_type base_type; +- struct fx_4_state_table table; ++ struct fx_state_table table; + struct hlsl_ir_node *node; + unsigned int i; + +- table = fx_4_get_state_table(type->class, ctx->profile->major_version, ctx->profile->minor_version); ++ table = fx_get_state_table(type->class, ctx->profile->major_version, ctx->profile->minor_version); + + for (i = 0; i < table.count; ++i) + { +@@ -2992,21 +3111,34 @@ static unsigned int decompose_fx_4_state_block(struct hlsl_ir_var *var, struct h + return decompose_fx_4_state_block_expand_array(var, block, entry_index, fx); + } + +-static void write_fx_4_state_block(struct hlsl_ir_var *var, unsigned int block_index, +- uint32_t count_offset, struct fx_write_context *fx) ++static void fx_4_decompose_state_blocks(struct hlsl_ir_var *var, struct fx_write_context *fx) + { +- struct vkd3d_bytecode_buffer *buffer = &fx->structured; ++ unsigned int block_count = hlsl_get_multiarray_size(var->data_type); + struct hlsl_state_block *block; +- uint32_t i, count = 0; + +- if (var->state_blocks) ++ if (!var->state_blocks) ++ return; ++ ++ for (unsigned int i = 0; i < block_count; ++i) + { +- block = var->state_blocks[block_index]; ++ block = var->state_blocks[i]; + +- for (i = 0; i < block->count;) ++ for (unsigned int j = 0; j < block->count;) + { +- i += decompose_fx_4_state_block(var, block, i, fx); ++ j += decompose_fx_4_state_block(var, block, j, fx); + } ++ } ++} ++ ++static uint32_t write_state_block(struct hlsl_ir_var *var, unsigned int block_index, ++ struct fx_write_context *fx) ++{ ++ struct hlsl_state_block *block; ++ uint32_t i, count = 0; ++ ++ if (var->state_blocks) ++ { ++ block = var->state_blocks[block_index]; + + for (i = 0; i < block->count; ++i) + { +@@ -3017,27 +3149,29 @@ static void write_fx_4_state_block(struct hlsl_ir_var *var, unsigned int block_i + continue; + + /* Resolve special constant names and property names. */ +- resolve_fx_4_state_block_values(var, entry, fx); ++ resolve_fx_state_block_values(var, entry, fx); + +- write_fx_4_state_assignment(var, entry, fx); ++ write_state_assignment(var, entry, fx); + ++count; + } + } + +- set_u32(buffer, count_offset, count); ++ return count; + } + + static void write_fx_4_state_object_initializer(struct hlsl_ir_var *var, struct fx_write_context *fx) + { + uint32_t elements_count = hlsl_get_multiarray_size(var->data_type), i; + struct vkd3d_bytecode_buffer *buffer = &fx->structured; +- uint32_t count_offset; ++ uint32_t count_offset, count; ++ ++ fx_4_decompose_state_blocks(var, fx); + + for (i = 0; i < elements_count; ++i) + { + count_offset = put_u32(buffer, 0); +- +- write_fx_4_state_block(var, i, count_offset, fx); ++ count = write_state_block(var, i, fx); ++ set_u32(buffer, count_offset, count); + } + } + +@@ -3212,6 +3346,8 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx + size = 0; + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { ++ uint32_t unpacked_size; ++ + if (!is_numeric_fx_4_type(var->data_type)) + continue; + +@@ -3219,7 +3355,9 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx + continue; + + write_fx_4_numeric_variable(var, shared, fx); +- size += get_fx_4_type_size(var->data_type); ++ ++ unpacked_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float); ++ size = max(size, unpacked_size + var->buffer_offset * 4); + ++count; + } + +@@ -3446,6 +3584,7 @@ int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) + + struct fx_parser + { ++ enum vkd3d_shader_source_type source_type; + const uint8_t *ptr, *start, *end; + struct vkd3d_shader_message_context *message_context; + struct vkd3d_string_buffer buffer; +@@ -3572,20 +3711,43 @@ static void parse_fx_print_indent(struct fx_parser *parser) + vkd3d_string_buffer_printf(&parser->buffer, "%*s", 4 * parser->indent, ""); + } + +-static const char *fx_2_get_string(struct fx_parser *parser, uint32_t offset, uint32_t *size) ++static void fx_2_print_string_literal(struct fx_parser *parser, const char *prefix, ++ const char *s, uint32_t max_len, const char *suffix) + { +- const char *ptr; ++ uint32_t len; ++ ++ if (s) ++ len = strnlen(s, max_len); ++ if (!s || len == max_len) ++ { ++ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, "Failed to parse a string entry."); ++ return; ++ } + +- fx_parser_read_unstructured(parser, size, offset, sizeof(*size)); +- ptr = fx_parser_get_unstructured_ptr(parser, offset + 4, *size); ++ vkd3d_string_buffer_printf(&parser->buffer, "%s", prefix); ++ vkd3d_string_buffer_print_string_escaped(&parser->buffer, s, len); ++ vkd3d_string_buffer_printf(&parser->buffer, "%s", suffix); ++} + +- if (!ptr) ++static void fx_2_parse_string_literal(struct fx_parser *parser, uint32_t offset, ++ bool unstructured, const char *prefix, const char *suffix) ++{ ++ uint32_t max_len; ++ const char *s; ++ ++ if (unstructured) + { +- parser->failed = true; +- return ""; ++ fx_parser_read_unstructured(parser, &max_len, offset, sizeof(max_len)); ++ s = fx_parser_get_unstructured_ptr(parser, offset + 4, max_len); ++ } ++ else ++ { ++ max_len = fx_parser_read_u32(parser); ++ s = fx_parser_get_ptr(parser, max_len); ++ fx_parser_skip(parser, align(max_len, 4)); + } + +- return ptr; ++ fx_2_print_string_literal(parser, prefix, s, max_len, suffix); + } + + static unsigned int fx_get_fx_2_type_size(struct fx_parser *parser, uint32_t *offset) +@@ -3742,15 +3904,12 @@ static void fx_parse_fx_2_parameter(struct fx_parser *parser, uint32_t offset) + uint32_t semantic; + uint32_t element_count; + } var; +- const char *name; +- uint32_t size; + + fx_parser_read_unstructured(parser, &var, offset, sizeof(var)); + + fx_parse_fx_2_type(parser, offset); + +- name = fx_2_get_string(parser, var.name, &size); +- fx_print_string(&parser->buffer, " ", name, size); ++ fx_2_parse_string_literal(parser, var.name, true, " ", ""); + if (var.element_count) + vkd3d_string_buffer_printf(&parser->buffer, "[%u]", var.element_count); + } +@@ -3764,7 +3923,8 @@ static bool is_fx_2_sampler(uint32_t type) + || type == D3DXPT_SAMPLERCUBE; + } + +-static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_assignment *entry); ++static void fx_parse_fx_2_assignment(struct fx_parser *parser, enum hlsl_type_class container, ++ const struct fx_assignment *entry); + + static void parse_fx_2_sampler(struct fx_parser *parser, uint32_t element_count, + uint32_t offset) +@@ -3789,7 +3949,7 @@ static void parse_fx_2_sampler(struct fx_parser *parser, uint32_t element_count, + fx_parser_read_unstructured(parser, &entry, offset, sizeof(entry)); + + parse_fx_print_indent(parser); +- fx_parse_fx_2_assignment(parser, &entry); ++ fx_parse_fx_2_assignment(parser, HLSL_CLASS_SAMPLER, &entry); + } + parse_fx_end_indent(parser); + parse_fx_print_indent(parser); +@@ -3867,15 +4027,25 @@ static void fx_parse_fx_2_annotations(struct fx_parser *parser, uint32_t count) + vkd3d_string_buffer_printf(&parser->buffer, ">"); + } + +-static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_assignment *entry) ++static const struct fx_state *fx_2_get_state_by_id(enum hlsl_type_class container, uint32_t id) ++{ ++ struct fx_state_table table = fx_get_state_table(container, 2, 0); ++ ++ /* State identifiers are sequential, no gaps */ ++ if (id >= table.ptr[0].id && id <= table.ptr[table.count - 1].id) ++ return &table.ptr[id - table.ptr[0].id]; ++ ++ return NULL; ++} ++ ++static void fx_parse_fx_2_assignment(struct fx_parser *parser, enum hlsl_type_class container, ++ const struct fx_assignment *entry) + { + const struct rhs_named_value *named_value = NULL; +- const struct fx_2_state *state = NULL; ++ const struct fx_state *state; + +- if (entry->id <= ARRAY_SIZE(fx_2_states)) ++ if ((state = fx_2_get_state_by_id(container, entry->id))) + { +- state = &fx_2_states[entry->id]; +- + vkd3d_string_buffer_printf(&parser->buffer, "%s", state->name); + if (state->array_size > 1) + vkd3d_string_buffer_printf(&parser->buffer, "[%u]", entry->lhs_index); +@@ -3886,7 +4056,7 @@ static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_a + } + vkd3d_string_buffer_printf(&parser->buffer, " = "); + +- if (state && state->type == FX_UINT) ++ if (state && state->type == FX_UINT && state->values) + { + const struct rhs_named_value *ptr = state->values; + uint32_t value; +@@ -3910,13 +4080,14 @@ static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_a + } + else if (state) + { +- if (state->type == FX_UINT || state->type == FX_FLOAT) ++ if (state->type == FX_UINT || state->type == FX_FLOAT || state->type == FX_BOOL) + { +- uint32_t offset = entry->type; ++ uint32_t offset = entry->type, base_type; + unsigned int size; + + size = fx_get_fx_2_type_size(parser, &offset); +- parse_fx_2_numeric_value(parser, entry->value, size, entry->type); ++ fx_parser_read_unstructured(parser, &base_type, entry->type, sizeof(base_type)); ++ parse_fx_2_numeric_value(parser, entry->value, size, base_type); + } + else if (state->type == FX_VERTEXSHADER || state->type == FX_PIXELSHADER) + { +@@ -3951,18 +4122,14 @@ static void fx_parse_fx_2_technique(struct fx_parser *parser) + uint32_t annotation_count; + uint32_t assignment_count; + } pass; +- const char *name; +- uint32_t size; + + if (parser->failed) + return; + + fx_parser_read_u32s(parser, &technique, sizeof(technique)); + +- name = fx_2_get_string(parser, technique.name, &size); +- + parse_fx_print_indent(parser); +- fx_print_string(&parser->buffer, "technique ", name, size); ++ fx_2_parse_string_literal(parser, technique.name, true, "technique ", ""); + fx_parse_fx_2_annotations(parser, technique.annotation_count); + + vkd3d_string_buffer_printf(&parser->buffer, "\n"); +@@ -3973,10 +4140,9 @@ static void fx_parse_fx_2_technique(struct fx_parser *parser) + for (uint32_t i = 0; i < technique.pass_count; ++i) + { + fx_parser_read_u32s(parser, &pass, sizeof(pass)); +- name = fx_2_get_string(parser, pass.name, &size); + + parse_fx_print_indent(parser); +- fx_print_string(&parser->buffer, "pass ", name, size); ++ fx_2_parse_string_literal(parser, pass.name, true, "pass ", ""); + fx_parse_fx_2_annotations(parser, pass.annotation_count); + + vkd3d_string_buffer_printf(&parser->buffer, "\n"); +@@ -3990,7 +4156,7 @@ static void fx_parse_fx_2_technique(struct fx_parser *parser) + + parse_fx_print_indent(parser); + fx_parser_read_u32s(parser, &entry, sizeof(entry)); +- fx_parse_fx_2_assignment(parser, &entry); ++ fx_parse_fx_2_assignment(parser, HLSL_CLASS_PASS, &entry); + } + parse_fx_end_indent(parser); + +@@ -4112,8 +4278,7 @@ static void fx_parse_fx_2_data_blob(struct fx_parser *parser) + { + parse_fx_start_indent(parser); + parse_fx_print_indent(parser); +- fx_print_string(&parser->buffer, "\"", (const char *)data, size); +- vkd3d_string_buffer_printf(&parser->buffer, "\""); ++ fx_2_print_string_literal(parser, "\"", (const char *)data, size, "\""); + parse_fx_end_indent(parser); + } + else if (type == D3DXPT_PIXELSHADER || type == D3DXPT_VERTEXSHADER) +@@ -4135,38 +4300,18 @@ static void fx_parse_fx_2_data_blob(struct fx_parser *parser) + fx_parser_skip(parser, align(size, 4)); + } + +-static void fx_dump_blob(struct fx_parser *parser, const void *blob, uint32_t size) +-{ +- const uint32_t *data = blob; +- unsigned int i, j, n; +- +- size /= sizeof(*data); +- i = 0; +- while (i < size) +- { +- parse_fx_print_indent(parser); +- n = min(size - i, 8); +- for (j = 0; j < n; ++j) +- vkd3d_string_buffer_printf(&parser->buffer, "0x%08x,", data[i + j]); +- i += n; +- vkd3d_string_buffer_printf(&parser->buffer, "\n"); +- } +-} ++static void fx_2_parse_fxlvm_expression(struct fx_parser *parser, const uint32_t *blob, uint32_t size); + +-static void fx_parse_fx_2_array_selector(struct fx_parser *parser, uint32_t size) ++static void fx_parse_fx_2_array_selector(struct fx_parser *parser) + { +- const uint8_t *end = parser->ptr + size; +- uint32_t name_size, blob_size = 0; ++ uint32_t size, blob_size = 0; + const void *blob = NULL; +- const char *name; ++ const uint8_t *end; + +- name_size = fx_parser_read_u32(parser); +- name = fx_parser_get_ptr(parser, name_size); +- fx_parser_skip(parser, name_size); ++ size = fx_parser_read_u32(parser); ++ end = parser->ptr + size; + +- if (!name || (uint8_t *)name >= end) +- fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, +- "Malformed name entry in the array selector."); ++ fx_2_parse_string_literal(parser, 0, false, "array \"", "\"\n"); + + if (parser->ptr <= end) + { +@@ -4180,16 +4325,11 @@ static void fx_parse_fx_2_array_selector(struct fx_parser *parser, uint32_t size + "Malformed blob entry in the array selector."); + } + +- if (name) +- { +- fx_print_string(&parser->buffer, "array \"", name, name_size); +- vkd3d_string_buffer_printf(&parser->buffer, "\"\n"); +- } + if (blob) + { + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "selector blob size %u\n", blob_size); +- fx_dump_blob(parser, blob, blob_size); ++ fx_2_parse_fxlvm_expression(parser, blob, blob_size); + } + } + +@@ -4203,7 +4343,7 @@ static void fx_parse_fx_2_complex_state(struct fx_parser *parser) + uint32_t state; + uint32_t assignment_type; + } state; +- const char *data; ++ const uint32_t *data; + uint32_t size; + + fx_parser_read_u32s(parser, &state, sizeof(state)); +@@ -4219,28 +4359,29 @@ static void fx_parse_fx_2_complex_state(struct fx_parser *parser) + state.technique, state.index, state.state); + } + +- size = fx_parser_read_u32(parser); +- + parse_fx_print_indent(parser); + + if (state.assignment_type == FX_2_ASSIGNMENT_PARAMETER) + { +- data = fx_parser_get_ptr(parser, size); +- fx_print_string(&parser->buffer, "parameter \"", data, size); +- vkd3d_string_buffer_printf(&parser->buffer, "\"\n"); +- fx_parser_skip(parser, align(size, 4)); ++ fx_2_parse_string_literal(parser, 0, false, "parameter \"", "\"\n"); + } + else if (state.assignment_type == FX_2_ASSIGNMENT_ARRAY_SELECTOR) + { +- fx_parse_fx_2_array_selector(parser, size); ++ fx_parse_fx_2_array_selector(parser); + } +- else ++ else if (state.assignment_type == FX_2_ASSIGNMENT_CODE_BLOB) + { +- vkd3d_string_buffer_printf(&parser->buffer, "blob size %u\n", size); ++ size = fx_parser_read_u32(parser); + data = fx_parser_get_ptr(parser, size); +- fx_dump_blob(parser, data, size); ++ vkd3d_string_buffer_printf(&parser->buffer, "blob size %u\n", size); ++ fx_2_parse_fxlvm_expression(parser, data, size); + fx_parser_skip(parser, align(size, 4)); + } ++ else ++ { ++ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, ++ "Unknown state assignment type %u.", state.assignment_type); ++ } + } + + static void fx_2_parse(struct fx_parser *parser) +@@ -4457,6 +4598,11 @@ static void fx_parse_fx_4_numeric_variables(struct fx_parser *parser, uint32_t c + semantic = fx_4_get_string(parser, var.semantic); + vkd3d_string_buffer_printf(&parser->buffer, " : %s", semantic); + } ++ if (var.flags & FX_4_HAS_EXPLICIT_BIND_POINT) ++ { ++ vkd3d_string_buffer_printf(&parser->buffer, " : packoffset(c%u.%c)", ++ var.offset / 16, "xyzw"[(var.offset % 16) / 4]); ++ } + fx_parse_fx_4_annotations(parser); + + if (var.value) +@@ -4492,6 +4638,8 @@ static void fx_parse_buffers(struct fx_parser *parser) + name = fx_4_get_string(parser, buffer.name); + + vkd3d_string_buffer_printf(&parser->buffer, "cbuffer %s", name); ++ if (buffer.bind_point != ~0u) ++ vkd3d_string_buffer_printf(&parser->buffer, " : register(b%u)", buffer.bind_point); + fx_parse_fx_4_annotations(parser); + + vkd3d_string_buffer_printf(&parser->buffer, "\n{\n"); +@@ -4598,7 +4746,7 @@ static bool fx_4_object_has_initializer(const struct fx_4_binary_type *type) + + static int fx_4_state_id_compare(const void *a, const void *b) + { +- const struct fx_4_state *state = b; ++ const struct fx_state *state = b; + int id = *(int *)a; + + return id - state->id; +@@ -4609,7 +4757,7 @@ static const struct + uint32_t opcode; + const char *name; + } +-fx_4_fxlc_opcodes[] = ++fxlc_opcodes[] = + { + { 0x100, "mov" }, + { 0x101, "neg" }, +@@ -4634,6 +4782,8 @@ fx_4_fxlc_opcodes[] = + { 0x13a, "ceil" }, + { 0x200, "min" }, + { 0x201, "max" }, ++ { 0x202, "lt" }, ++ { 0x203, "ge" }, + { 0x204, "add" }, + { 0x205, "mul" }, + { 0x206, "atan2" }, +@@ -4659,29 +4809,24 @@ fx_4_fxlc_opcodes[] = + { 0x236, "ushr" }, + { 0x301, "movc" }, + { 0x500, "dot" }, ++ { 0x502, "noise" }, + { 0x70e, "d3ds_dotswiz" }, ++ { 0x711, "d3ds_noiseswiz" }, + }; + +-static const char *fx_4_get_fxlc_opcode_name(uint32_t opcode) ++static const char *get_fxlc_opcode_name(uint32_t opcode) + { + size_t i; + +- for (i = 0; i < ARRAY_SIZE(fx_4_fxlc_opcodes); ++i) ++ for (i = 0; i < ARRAY_SIZE(fxlc_opcodes); ++i) + { +- if (fx_4_fxlc_opcodes[i].opcode == opcode) +- return fx_4_fxlc_opcodes[i].name; ++ if (fxlc_opcodes[i].opcode == opcode) ++ return fxlc_opcodes[i].name; + } + + return ""; + } + +-struct fx_4_fxlc_argument +-{ +- uint32_t flags; +- uint32_t reg_type; +- uint32_t address; +-}; +- + struct fx_4_ctab_entry + { + uint32_t name; +@@ -4693,10 +4838,29 @@ struct fx_4_ctab_entry + uint32_t default_value; + }; + ++struct fxlc_arg ++{ ++ uint32_t reg_type; ++ uint32_t address; ++ bool indexed; ++ struct ++ { ++ uint32_t reg_type; ++ uint32_t address; ++ } index; ++}; ++ + struct fxlvm_code + { +- const float *cli4; +- uint32_t cli4_count; ++ const uint32_t *ptr, *end; ++ bool failed; ++ ++ union ++ { ++ const float *_4; ++ const double *_8; ++ } cli; ++ uint32_t cli_count; + + const struct fx_4_ctab_entry *constants; + uint32_t ctab_offset; +@@ -4707,7 +4871,45 @@ struct fxlvm_code + bool scalar; + }; + +-static void fx_4_parse_print_swizzle(struct fx_parser *parser, const struct fxlvm_code *code, unsigned int addr) ++static uint32_t fxlvm_read_u32(struct fxlvm_code *code) ++{ ++ if (code->end == code->ptr) ++ { ++ code->failed = true; ++ return 0; ++ } ++ ++ return *code->ptr++; ++} ++ ++static const uint32_t *find_d3dbc_section(const uint32_t *ptr, uint32_t count, uint32_t tag, uint32_t *size) ++{ ++ if (!count) ++ return NULL; ++ ++ /* Skip version tag */ ++ ptr++; ++ count--; ++ ++ while (count > 2 && (*ptr & 0xffff) == 0xfffe) ++ { ++ unsigned int section_size; ++ ++ section_size = (*ptr >> 16); ++ if (!section_size || section_size + 1 > count) ++ break; ++ if (*(ptr + 1) == tag) ++ { ++ *size = section_size; ++ return ptr + 2; ++ } ++ count -= section_size + 1; ++ ptr += section_size + 1; ++ } ++ return NULL; ++} ++ ++static void fx_parse_print_swizzle(struct fx_parser *parser, const struct fxlvm_code *code, unsigned int addr) + { + unsigned int comp_count = code->scalar ? 1 : code->comp_count; + static const char comp[] = "xyzw"; +@@ -4716,44 +4918,137 @@ static void fx_4_parse_print_swizzle(struct fx_parser *parser, const struct fxlv + vkd3d_string_buffer_printf(&parser->buffer, ".%.*s", comp_count, &comp[addr % 4]); + } + +-static void fx_4_parse_fxlc_constant_argument(struct fx_parser *parser, +- const struct fx_4_fxlc_argument *arg, const struct fxlvm_code *code) ++static void fx_print_fxlc_register(struct fx_parser *parser, uint32_t reg_type, ++ uint32_t address, uint32_t index_type, uint32_t index_address, struct fxlvm_code *code) + { +- uint32_t i, offset, register_index = arg->address / 4; /* Address counts in components. */ ++ static const char *table_names[FX_FXLC_REG_MAX + 1] = ++ { ++ [FX_FXLC_REG_LITERAL] = "imm", ++ [FX_FXLC_REG_CB] = "c", ++ [FX_FXLC_REG_INPUT] = "i", ++ [FX_FXLC_REG_OUTPUT] = "expr", ++ [FX_FXLC_REG_TEMP] = "r", ++ }; ++ uint32_t reg_index = address / 4; + +- for (i = 0; i < code->ctab_count; ++i) ++ if (parser->source_type == VKD3D_SHADER_SOURCE_TX ++ && (reg_type == FX_FXLC_REG_INPUT || reg_type == FX_FXLC_REG_OUTPUT)) + { +- const struct fx_4_ctab_entry *c = &code->constants[i]; ++ if (reg_type == FX_FXLC_REG_INPUT) ++ { ++ if (reg_index == 0) ++ vkd3d_string_buffer_printf(&parser->buffer, "vPos"); ++ else if (reg_index == 1) ++ vkd3d_string_buffer_printf(&parser->buffer, "vPSize"); ++ } ++ else ++ { ++ vkd3d_string_buffer_printf(&parser->buffer, "oC%u", reg_index); ++ } ++ } ++ else ++ { ++ vkd3d_string_buffer_printf(&parser->buffer, "%s%u", table_names[reg_type], reg_index); ++ } ++ if (index_type != FX_FXLC_REG_UNUSED) ++ { ++ vkd3d_string_buffer_printf(&parser->buffer, "[%s%u.%c]", table_names[index_type], ++ index_address / 4, "xyzw"[index_address % 4]); ++ } ++ fx_parse_print_swizzle(parser, code, address); ++} + +- if (register_index < c->register_index || register_index - c->register_index >= c->register_count) +- continue; ++static void fx_parse_fxlc_constant_argument(struct fx_parser *parser, ++ const struct fxlc_arg *arg, const struct fxlvm_code *code) ++{ ++ uint32_t register_index = arg->address / 4; /* Address counts in components. */ + +- vkd3d_string_buffer_printf(&parser->buffer, "%s", &code->ctab[c->name]); ++ if (code->ctab_count) ++ { ++ uint32_t i, offset; + +- /* Register offset within variable */ +- offset = arg->address - c->register_index * 4; ++ for (i = 0; i < code->ctab_count; ++i) ++ { ++ const struct fx_4_ctab_entry *c = &code->constants[i]; + +- if (offset / 4) +- vkd3d_string_buffer_printf(&parser->buffer, "[%u]", offset / 4); +- fx_4_parse_print_swizzle(parser, code, offset); +- return; ++ if (register_index < c->register_index || register_index - c->register_index >= c->register_count) ++ continue; ++ ++ vkd3d_string_buffer_printf(&parser->buffer, "%s", &code->ctab[c->name]); ++ ++ /* Register offset within variable */ ++ offset = arg->address - c->register_index * 4; ++ ++ if (offset / 4) ++ vkd3d_string_buffer_printf(&parser->buffer, "[%u]", offset / 4); ++ fx_parse_print_swizzle(parser, code, offset); ++ return; ++ } ++ ++ vkd3d_string_buffer_printf(&parser->buffer, "(var-not-found)"); ++ } ++ else ++ { ++ vkd3d_string_buffer_printf(&parser->buffer, "c%u", register_index); ++ fx_parse_print_swizzle(parser, code, arg->address); ++ } ++} ++ ++static void fx_parse_fxlc_argument(struct fx_parser *parser, struct fxlc_arg *arg, struct fxlvm_code *code) ++{ ++ uint32_t flags; ++ ++ memset(arg, 0, sizeof(*arg)); ++ ++ flags = fxlvm_read_u32(code); ++ if (flags) ++ { ++ arg->indexed = true; ++ arg->index.reg_type = fxlvm_read_u32(code); ++ arg->index.address = fxlvm_read_u32(code); + } ++ arg->reg_type = fxlvm_read_u32(code); ++ arg->address = fxlvm_read_u32(code); ++} + +- vkd3d_string_buffer_printf(&parser->buffer, "(var-not-found)"); ++static void fx_print_fxlc_literal(struct fx_parser *parser, uint32_t address, struct fxlvm_code *code) ++{ ++ if (parser->version.major >= 4) ++ vkd3d_string_buffer_print_f32(&parser->buffer, code->cli._4[address]); ++ else ++ vkd3d_string_buffer_print_f64(&parser->buffer, code->cli._8[address]); + } + +-static void fx_4_parse_fxlc_argument(struct fx_parser *parser, uint32_t offset, const struct fxlvm_code *code) ++static void fx_print_fxlc_argument(struct fx_parser *parser, const struct fxlc_arg *arg, struct fxlvm_code *code) + { +- struct fx_4_fxlc_argument arg; + uint32_t count; + +- fx_parser_read_unstructured(parser, &arg, offset, sizeof(arg)); ++ if (arg->reg_type > FX_FXLC_REG_MAX) ++ { ++ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, ++ "Unexpected register type %u.", arg->reg_type); ++ return; ++ } ++ ++ if (arg->index.reg_type > FX_FXLC_REG_MAX) ++ { ++ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, ++ "Unexpected index register type %u.", arg->index.reg_type); ++ return; ++ } + +- switch (arg.reg_type) ++ if (arg->indexed) + { +- case FX_4_FXLC_REG_LITERAL: ++ fx_print_fxlc_register(parser, arg->reg_type, arg->address, arg->index.reg_type, ++ arg->index.address, code); ++ return; ++ } ++ ++ switch (arg->reg_type) ++ { ++ case FX_FXLC_REG_LITERAL: + count = code->scalar ? 1 : code->comp_count; +- if (arg.address >= code->cli4_count || count > code->cli4_count - arg.address) ++ if (arg->address >= code->cli_count || count > code->cli_count - arg->address) + { + vkd3d_string_buffer_printf(&parser->buffer, "()"); + parser->failed = true; +@@ -4761,42 +5056,125 @@ static void fx_4_parse_fxlc_argument(struct fx_parser *parser, uint32_t offset, + } + + vkd3d_string_buffer_printf(&parser->buffer, "("); +- vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg.address]); ++ fx_print_fxlc_literal(parser, arg->address, code); + for (unsigned int i = 1; i < code->comp_count; ++i) + { + vkd3d_string_buffer_printf(&parser->buffer, ", "); +- vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg.address + (code->scalar ? 0 : i)]); ++ fx_print_fxlc_literal(parser, arg->address + (code->scalar ? 0 : i), code); + } + vkd3d_string_buffer_printf(&parser->buffer, ")"); + break; + +- case FX_4_FXLC_REG_CB: +- fx_4_parse_fxlc_constant_argument(parser, &arg, code); ++ case FX_FXLC_REG_CB: ++ fx_parse_fxlc_constant_argument(parser, arg, code); + break; + +- case FX_4_FXLC_REG_OUTPUT: +- case FX_4_FXLC_REG_TEMP: +- if (arg.reg_type == FX_4_FXLC_REG_OUTPUT) +- vkd3d_string_buffer_printf(&parser->buffer, "expr"); +- else +- vkd3d_string_buffer_printf(&parser->buffer, "r%u", arg.address / 4); +- fx_4_parse_print_swizzle(parser, code, arg.address); ++ case FX_FXLC_REG_INPUT: ++ case FX_FXLC_REG_OUTPUT: ++ case FX_FXLC_REG_TEMP: ++ fx_print_fxlc_register(parser, arg->reg_type, arg->address, FX_FXLC_REG_UNUSED, 0, code); + break; + + default: +- vkd3d_string_buffer_printf(&parser->buffer, "", arg.reg_type); ++ vkd3d_string_buffer_printf(&parser->buffer, "", arg->reg_type); ++ break; ++ } ++} ++ ++static void fx_parse_fxlvm_expression(struct fx_parser *parser, struct fxlvm_code *code) ++{ ++ struct fxlc_arg args[9]; ++ uint32_t ins_count; ++ size_t i, j; ++ ++ parse_fx_start_indent(parser); ++ if (parser->source_type == VKD3D_SHADER_SOURCE_TX) ++ { ++ parse_fx_print_indent(parser); ++ vkd3d_string_buffer_printf(&parser->buffer, "tx_1_0\n"); ++ } ++ ++ ins_count = fxlvm_read_u32(code); ++ ++ for (i = 0; i < ins_count; ++i) ++ { ++ uint32_t instr, opcode, src_count; ++ ++ instr = fxlvm_read_u32(code); ++ src_count = fxlvm_read_u32(code); ++ ++ if (src_count >= ARRAY_SIZE(args)) ++ { ++ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, ++ "Unexpected instruction source count %u.", src_count); + break; ++ } ++ ++ /* Sources entries are followed by the destination, first read them all. ++ Output format is "opcode dst, src[0]...src[n]". */ ++ for (j = 0; j < src_count; ++j) ++ fx_parse_fxlc_argument(parser, &args[j], code); ++ fx_parse_fxlc_argument(parser, &args[src_count], code); ++ ++ opcode = (instr >> FX_FXLC_OPCODE_SHIFT) & FX_FXLC_OPCODE_MASK; ++ code->comp_count = instr & FX_FXLC_COMP_COUNT_MASK; ++ ++ parse_fx_print_indent(parser); ++ vkd3d_string_buffer_printf(&parser->buffer, "%s ", get_fxlc_opcode_name(opcode)); ++ ++ code->scalar = false; ++ fx_print_fxlc_argument(parser, &args[src_count], code); ++ vkd3d_string_buffer_printf(&parser->buffer, ", "); ++ ++ for (j = 0; j < src_count; ++j) ++ { ++ /* Scalar modifier applies only to the first source. */ ++ code->scalar = j == 0 && !!(instr & FX_FXLC_IS_SCALAR_MASK); ++ fx_print_fxlc_argument(parser, &args[j], code); ++ if (j < src_count - 1) ++ vkd3d_string_buffer_printf(&parser->buffer, ", "); ++ } ++ ++ vkd3d_string_buffer_printf(&parser->buffer, "\n"); + } ++ ++ parse_fx_end_indent(parser); ++} ++ ++static void fx_2_parse_fxlvm_expression(struct fx_parser *parser, const uint32_t *blob, uint32_t size) ++{ ++ uint32_t count = size / sizeof(uint32_t); ++ struct fxlvm_code code = { 0 }; ++ uint32_t section_size; ++ const uint32_t *data; ++ ++ if (!blob) ++ return; ++ ++ /* Literal constants, using 64-bit floats. */ ++ if ((data = find_d3dbc_section(blob, count, TAG_CLIT, §ion_size))) ++ { ++ code.cli_count = *data++; ++ code.cli._8 = (const double *)data; ++ } ++ ++ /* CTAB does not contain variable names */ ++ ++ /* Code blob */ ++ code.ptr = find_d3dbc_section(blob, count, TAG_FXLC, &count); ++ code.end = code.ptr + count; ++ ++ fx_parse_fxlvm_expression(parser, &code); + } + + static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offset) + { + struct vkd3d_shader_dxbc_section_desc *section, fxlc, cli4, ctab; + struct vkd3d_shader_dxbc_desc dxbc_desc; ++ struct fxlvm_code code = { 0 }; + struct vkd3d_shader_code dxbc; +- uint32_t size, ins_count; +- struct fxlvm_code code; +- size_t i, j; ++ uint32_t size; ++ size_t i; + + offset = fx_parser_read_unstructured(parser, &size, offset, sizeof(size)); + +@@ -4832,8 +5210,8 @@ static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offse + { + uint32_t cli4_offset = offset + (size_t)cli4.data.code - (size_t)dxbc.code; + +- fx_parser_read_unstructured(parser, &code.cli4_count, cli4_offset, sizeof(code.cli4_count)); +- code.cli4 = fx_parser_get_unstructured_ptr(parser, cli4_offset + 4, code.cli4_count * sizeof(float)); ++ fx_parser_read_unstructured(parser, &code.cli_count, cli4_offset, sizeof(code.cli_count)); ++ code.cli._4 = fx_parser_get_unstructured_ptr(parser, cli4_offset + 4, code.cli_count * sizeof(float)); + } + + if (ctab.data.code) +@@ -4849,47 +5227,10 @@ static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offse + ctab_offset + consts_offset, code.ctab_count * sizeof(*code.constants)); + } + +- offset += (size_t)fxlc.data.code - (size_t)dxbc.code; +- offset = fx_parser_read_unstructured(parser, &ins_count, offset, sizeof(ins_count)); +- +- parse_fx_start_indent(parser); +- +- for (i = 0; i < ins_count; ++i) +- { +- uint32_t instr, opcode, src_count; +- struct fx_4_fxlc_argument arg; +- +- offset = fx_parser_read_unstructured(parser, &instr, offset, sizeof(instr)); +- offset = fx_parser_read_unstructured(parser, &src_count, offset, sizeof(src_count)); +- +- opcode = (instr >> FX_4_FXLC_OPCODE_SHIFT) & FX_4_FXLC_OPCODE_MASK; +- code.comp_count = instr & FX_4_FXLC_COMP_COUNT_MASK; +- code.scalar = false; +- +- parse_fx_print_indent(parser); +- vkd3d_string_buffer_printf(&parser->buffer, "%s ", fx_4_get_fxlc_opcode_name(opcode)); +- +- /* Destination first. */ +- fx_4_parse_fxlc_argument(parser, offset + sizeof(arg) * src_count, &code); +- +- for (j = 0; j < src_count; ++j) +- { +- vkd3d_string_buffer_printf(&parser->buffer, ", "); +- +- /* Scalar modifier applies only to first source. */ +- code.scalar = j == 0 && !!(instr & FX_4_FXLC_IS_SCALAR_MASK); +- fx_4_parse_fxlc_argument(parser, offset, &code); +- +- offset += sizeof(arg); +- } +- +- /* Destination */ +- offset += sizeof(arg); +- +- vkd3d_string_buffer_printf(&parser->buffer, "\n"); +- } ++ code.ptr = fxlc.data.code; ++ code.end = (uint32_t *)((uint8_t *)fxlc.data.code + fxlc.data.size); + +- parse_fx_end_indent(parser); ++ fx_parse_fxlvm_expression(parser, &code); + } + + static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32_t count, +@@ -4919,12 +5260,12 @@ static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32 + }; + const struct rhs_named_value *named_value; + struct fx_5_shader shader = { 0 }; +- struct fx_4_state_table table; ++ struct fx_state_table table; + unsigned int shader_type = 0; + uint32_t i, j, comp_count; +- struct fx_4_state *state; ++ struct fx_state *state; + +- table = fx_4_get_state_table(type_class, parser->version.major, parser->version.minor); ++ table = fx_get_state_table(type_class, parser->version.major, parser->version.minor); + + for (i = 0; i < count; ++i) + { +@@ -4995,6 +5336,8 @@ static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32 + vkd3d_string_buffer_printf(&parser->buffer, "0x%.2x", value.u); + else if (state->type == FX_UINT) + vkd3d_string_buffer_printf(&parser->buffer, "%u", value.u); ++ else if (state->type == FX_BOOL) ++ vkd3d_string_buffer_printf(&parser->buffer, "%s", value.u ? "true" : "false"); + else if (state->type == FX_FLOAT) + vkd3d_string_buffer_printf(&parser->buffer, "%g", value.f); + +@@ -5374,6 +5717,7 @@ static void fx_parser_init(struct fx_parser *parser, const struct vkd3d_shader_c + struct vkd3d_shader_message_context *message_context) + { + memset(parser, 0, sizeof(*parser)); ++ parser->source_type = compile_info->source_type; + parser->start = compile_info->source.code; + parser->ptr = compile_info->source.code; + parser->end = (uint8_t *)compile_info->source.code + compile_info->source.size; +@@ -5434,3 +5778,38 @@ int fx_parse(const struct vkd3d_shader_compile_info *compile_info, + return VKD3D_ERROR_INVALID_SHADER; + return VKD3D_OK; + } ++ ++int tx_parse(const struct vkd3d_shader_compile_info *compile_info, ++ struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) ++{ ++ struct fx_parser parser; ++ uint32_t version; ++ ++ fx_parser_init(&parser, compile_info, message_context); ++ ++ if (parser.end - parser.start < sizeof(version)) ++ { ++ fx_parser_error(&parser, VKD3D_SHADER_ERROR_FX_INVALID_SIZE, ++ "Source size %zu is smaller than the TX header size.", compile_info->source.size); ++ return VKD3D_ERROR_INVALID_SHADER; ++ } ++ version = *(uint32_t *)parser.ptr; ++ ++ switch (version) ++ { ++ case 0x54580100: ++ fx_2_parse_fxlvm_expression(&parser, (const uint32_t *)parser.ptr, parser.end - parser.ptr); ++ break; ++ default: ++ fx_parser_error(&parser, VKD3D_SHADER_ERROR_FX_INVALID_VERSION, ++ "Invalid texture shader binary version value 0x%08x.", version); ++ break; ++ } ++ ++ vkd3d_shader_code_from_string_buffer(out, &parser.buffer); ++ fx_parser_cleanup(&parser); ++ ++ if (parser.failed) ++ return VKD3D_ERROR_INVALID_SHADER; ++ return VKD3D_OK; ++} diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index 40865d842f1..b3e3d10791d 100644 +index e4497b9ac5b..b3e3d10791d 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -851,7 +851,7 @@ static void shader_glsl_ld(struct vkd3d_glsl_generator *gen, const struct vkd3d_ +@@ -421,6 +421,9 @@ static void shader_glsl_print_src(struct vkd3d_string_buffer *buffer, struct vkd + case VKD3DSPSM_ABS: + vkd3d_string_buffer_printf(buffer, "abs(%s)", str->buffer); + break; ++ case VKD3DSPSM_ABSNEG: ++ vkd3d_string_buffer_printf(buffer, "-abs(%s)", str->buffer); ++ break; + default: + vkd3d_string_buffer_printf(buffer, "(%s)", + vsir_src->modifiers, str->buffer); +@@ -495,6 +498,9 @@ static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_g + uint32_t modifiers = dst->vsir->modifiers; + bool close = true; + ++ /* It is always legitimate to ignore _pp. */ ++ modifiers &= ~VKD3DSPDM_PARTIALPRECISION; ++ + if (dst->vsir->shift) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled destination shift %#x.", dst->vsir->shift); +@@ -555,10 +561,12 @@ static void VKD3D_PRINTF_FUNC(4, 5) shader_glsl_print_assignment_ext(struct vkd3 + + static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) + { ++ const char *name = vsir_opcode_get_name(ins->opcode, ""); ++ + shader_glsl_print_indent(gen->buffer, gen->indent); +- vkd3d_string_buffer_printf(gen->buffer, "/* */\n", ins->opcode); ++ vkd3d_string_buffer_printf(gen->buffer, "/* */\n", name, ins->opcode); + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, +- "Internal compiler error: Unhandled instruction %#x.", ins->opcode); ++ "Internal compiler error: Unhandled instruction \"%s\" (%#x).", name, ins->opcode); + } + + static void shader_glsl_binop(struct vkd3d_glsl_generator *gen, +@@ -843,7 +851,7 @@ static void shader_glsl_ld(struct vkd3d_glsl_generator *gen, const struct vkd3d_ if (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) { vkd3d_string_buffer_printf(fetch, ", "); @@ -2549,7 +7096,7 @@ index 40865d842f1..b3e3d10791d 100644 shader_glsl_print_src(fetch, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, ins->src[0].reg.data_type); else if (sample_count == 1) /* If the resource isn't a true multisample resource, this is the -@@ -915,14 +915,14 @@ static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vk +@@ -907,14 +915,14 @@ static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vk enum vkd3d_data_type data_type; struct glsl_dst dst; @@ -2571,7 +7118,45 @@ index 40865d842f1..b3e3d10791d 100644 resource = &ins->src[1 + dynamic_offset]; sampler = &ins->src[2 + dynamic_offset]; -@@ -1459,177 +1459,177 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, +@@ -1242,37 +1250,6 @@ static void shader_glsl_movc(struct vkd3d_glsl_generator *gen, const struct vkd3 + glsl_dst_cleanup(&dst, &gen->string_buffers); + } + +-static void shader_glsl_mul_extended(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) +-{ +- struct glsl_src src[2]; +- struct glsl_dst dst; +- uint32_t mask; +- +- if (ins->dst[0].reg.type != VKD3DSPR_NULL) +- { +- /* FIXME: imulExtended()/umulExtended() from ARB_gpu_shader5/GLSL 4.00+. */ +- mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); +- shader_glsl_print_assignment(gen, &dst, ""); +- glsl_dst_cleanup(&dst, &gen->string_buffers); +- +- vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, +- "Internal compiler error: Unhandled 64-bit integer multiplication."); +- } +- +- if (ins->dst[1].reg.type != VKD3DSPR_NULL) +- { +- mask = glsl_dst_init(&dst, gen, ins, &ins->dst[1]); +- glsl_src_init(&src[0], gen, &ins->src[0], mask); +- glsl_src_init(&src[1], gen, &ins->src[1], mask); +- +- shader_glsl_print_assignment(gen, &dst, "%s * %s", src[0].str->buffer, src[1].str->buffer); +- +- glsl_src_cleanup(&src[1], &gen->string_buffers); +- glsl_src_cleanup(&src[0], &gen->string_buffers); +- glsl_dst_cleanup(&dst, &gen->string_buffers); +- } +-} +- + static void shader_glsl_print_sysval_name(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, + enum vkd3d_shader_sysval_semantic sysval, unsigned int idx) + { +@@ -1482,177 +1459,177 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, switch (ins->opcode) { @@ -2712,9 +7297,10 @@ index 40865d842f1..b3e3d10791d 100644 + case VSIR_OP_UMIN: shader_glsl_intrinsic(gen, ins, "min"); break; -- case VKD3DSIH_IMUL_LOW: +- case VKD3DSIH_IMUL: +- shader_glsl_mul_extended(gen, ins); + case VSIR_OP_IMUL_LOW: - shader_glsl_binop(gen, ins, "*"); ++ shader_glsl_binop(gen, ins, "*"); break; - case VKD3DSIH_INE: - case VKD3DSIH_NEU: @@ -2821,11 +7407,97 @@ index 40865d842f1..b3e3d10791d 100644 shader_glsl_binop(gen, ins, "^"); break; default: +@@ -2313,7 +2290,7 @@ static void shader_glsl_handle_global_flags(struct vkd3d_string_buffer *buffer, + flags &= ~VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL; + } + +- if (flags) ++ if (flags & ~VKD3DSGF_REFACTORING_ALLOWED) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled global flags %#"PRIx64".", (uint64_t)flags); + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +index 653ddd2e8be..678ed324919 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +@@ -3531,21 +3531,7 @@ static void dump_deref(struct vkd3d_string_buffer *buffer, const struct hlsl_der + + const char *debug_hlsl_writemask(unsigned int writemask) + { +- static const char components[] = {'x', 'y', 'z', 'w'}; +- char string[5]; +- unsigned int i = 0, pos = 0; +- +- VKD3D_ASSERT(!(writemask & ~VKD3DSP_WRITEMASK_ALL)); +- +- while (writemask) +- { +- if (writemask & 1) +- string[pos++] = components[i]; +- writemask >>= 1; +- i++; +- } +- string[pos] = '\0'; +- return vkd3d_dbg_sprintf(".%s", string); ++ return debug_vsir_writemask(writemask); + } + + const char *debug_hlsl_swizzle(uint32_t swizzle, unsigned int size) +@@ -3652,6 +3638,7 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op) + [HLSL_OP1_LOG2] = "log2", + [HLSL_OP1_LOGIC_NOT] = "!", + [HLSL_OP1_NEG] = "-", ++ [HLSL_OP1_NOISE] = "noise", + [HLSL_OP1_RCP] = "rcp", + [HLSL_OP1_REINTERPRET] = "reinterpret", + [HLSL_OP1_ROUND] = "round", +@@ -3844,11 +3831,11 @@ static void dump_ir_string(struct vkd3d_string_buffer *buffer, const struct hlsl + vkd3d_string_buffer_printf(buffer, "\"%s\"", debugstr_a(string->string)); + } + +-static void dump_ir_store(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_store *store) ++static void dump_ir_store(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, const struct hlsl_ir_store *store) + { + vkd3d_string_buffer_printf(buffer, "= ("); + dump_deref(buffer, &store->lhs); +- if (store->writemask != VKD3DSP_WRITEMASK_ALL) ++ if (store->writemask != VKD3DSP_WRITEMASK_ALL && type_is_single_reg(hlsl_deref_get_type(ctx, &store->lhs))) + vkd3d_string_buffer_printf(buffer, "%s", debug_hlsl_writemask(store->writemask)); + vkd3d_string_buffer_printf(buffer, " "); + dump_src(buffer, &store->rhs); +@@ -4046,7 +4033,7 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, + break; + + case HLSL_IR_STORE: +- dump_ir_store(buffer, hlsl_ir_store(instr)); ++ dump_ir_store(ctx, buffer, hlsl_ir_store(instr)); + break; + + case HLSL_IR_SWITCH: +@@ -4137,7 +4124,7 @@ void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new) + const struct hlsl_type *old_type = old->data_type, *new_type = new->data_type; + struct hlsl_src *src, *next; + +- if (hlsl_is_numeric_type(old_type)) ++ if (old_type && hlsl_is_numeric_type(old_type)) + { + VKD3D_ASSERT(hlsl_is_numeric_type(new_type)); + VKD3D_ASSERT(old_type->e.numeric.dimx == new_type->e.numeric.dimx); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index 369181cada8..0dce2831c3e 100644 +index 58f579cd9f9..0dce2831c3e 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -125,7 +125,7 @@ enum hlsl_sampler_dim +@@ -59,8 +59,7 @@ static inline unsigned int hlsl_swizzle_get_component(uint32_t swizzle, unsigned + + static inline void hlsl_swizzle_set_component(uint32_t *swizzle, unsigned int idx, unsigned int component) + { +- *swizzle &= ~(VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(idx)); +- *swizzle |= component << VKD3D_SHADER_SWIZZLE_SHIFT(idx); ++ vsir_swizzle_set_component(swizzle, idx, component); + } + + enum hlsl_type_class +@@ -126,7 +125,7 @@ enum hlsl_sampler_dim HLSL_SAMPLER_DIM_STRUCTURED_BUFFER, HLSL_SAMPLER_DIM_RAW_BUFFER, HLSL_SAMPLER_DIM_MAX = HLSL_SAMPLER_DIM_RAW_BUFFER, @@ -2834,11 +7506,568 @@ index 369181cada8..0dce2831c3e 100644 }; enum hlsl_so_object_type +@@ -245,6 +244,7 @@ struct hlsl_semantic + { + const char *name; + uint32_t index; ++ uint32_t stream_index; + + /* Name exactly as it appears in the sources. */ + const char *raw_name; +@@ -308,6 +308,8 @@ struct hlsl_reg + unsigned int writemask; + /* Whether the register has been allocated. */ + bool allocated; ++ /* Currently only used for numeric registers. */ ++ enum vkd3d_shader_register_type type; + }; + + /* Types of instruction nodes for the IR. +@@ -733,6 +735,7 @@ enum hlsl_ir_expr_op + HLSL_OP1_ISINF, + HLSL_OP1_LOG2, + HLSL_OP1_LOGIC_NOT, ++ HLSL_OP1_NOISE, + HLSL_OP1_NEG, + HLSL_OP1_RCP, + HLSL_OP1_REINTERPRET, +@@ -1185,6 +1188,8 @@ struct hlsl_ctx + } constant_defs; + /* 'c' registers where the constants expected by SM2 sincos are stored. */ + struct hlsl_reg d3dsincosconst1, d3dsincosconst2; ++ /* Number of allocated SSA IDs, used in translation to vsir. */ ++ unsigned int ssa_count; + + /* Number of threads to be executed (on the X, Y, and Z dimensions) in a single thread group in + * compute shader profiles. It is set using the numthreads() attribute in the entry point. */ +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index 5aee1e701cd..40353abd81b 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -2559,6 +2559,16 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Variable '%s' is declared as both \"uniform\" and \"static\".", var->name); + ++ if ((modifiers & HLSL_STORAGE_GROUPSHARED) && ctx->profile->type != VKD3D_SHADER_TYPE_COMPUTE) ++ { ++ modifiers &= ~HLSL_STORAGE_GROUPSHARED; ++ hlsl_warning(ctx, &var->loc, VKD3D_SHADER_WARNING_HLSL_IGNORED_MODIFIER, ++ "Ignoring the 'groupshared' modifier in a non-compute shader."); ++ } ++ ++ if (modifiers & HLSL_STORAGE_GROUPSHARED) ++ hlsl_fixme(ctx, &var->loc, "Group shared variables."); ++ + /* Mark it as uniform. We need to do this here since synthetic + * variables also get put in the global scope, but shouldn't be + * considered uniforms, and we have no way of telling otherwise. */ +@@ -4291,6 +4301,28 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, + return true; + } + ++static bool intrinsic_noise(struct hlsl_ctx *ctx, ++ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_type *type = params->args[0]->data_type, *ret_type; ++ struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; ++ ++ type = params->args[0]->data_type; ++ if (type->class == HLSL_CLASS_MATRIX) ++ { ++ struct vkd3d_string_buffer *string; ++ if ((string = hlsl_type_to_string(ctx, type))) ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, ++ "Wrong argument type for noise(): expected vector or scalar, but got '%s'.", string->buffer); ++ hlsl_release_string_buffer(ctx, string); ++ } ++ ++ args[0] = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); ++ ret_type = hlsl_get_scalar_type(ctx, args[0]->data_type->e.numeric.type); ++ ++ return !!add_expr(ctx, params->instrs, HLSL_OP1_NOISE, args, ret_type, loc); ++} ++ + static bool intrinsic_normalize(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +@@ -5119,10 +5151,10 @@ static bool intrinsic_InterlockedXor(struct hlsl_ctx *ctx, + + static void validate_group_barrier_profile(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc) + { +- if (ctx->profile->type != VKD3D_SHADER_TYPE_COMPUTE || hlsl_version_lt(ctx, 5, 0)) ++ if (ctx->profile->type != VKD3D_SHADER_TYPE_COMPUTE) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, +- "Group barriers can only be used in compute shaders 5.0 or higher."); ++ "Group barriers can only be used in compute shaders."); + } + } + +@@ -5146,10 +5178,10 @@ static bool intrinsic_DeviceMemoryBarrier(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { + if ((ctx->profile->type != VKD3D_SHADER_TYPE_COMPUTE && ctx->profile->type != VKD3D_SHADER_TYPE_PIXEL) +- || hlsl_version_lt(ctx, 5, 0)) ++ || hlsl_version_lt(ctx, 4, 0)) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, +- "DeviceMemoryBarrier() can only be used in pixel and compute shaders 5.0 or higher."); ++ "DeviceMemoryBarrier() can only be used in compute and pixel shaders 4.0 or higher."); + } + return !!hlsl_block_add_sync(ctx, params->instrs, VKD3DSSF_GLOBAL_UAV, loc); + } +@@ -5255,6 +5287,7 @@ intrinsic_functions[] = + {"min", 2, true, intrinsic_min}, + {"modf", 2, true, intrinsic_modf}, + {"mul", 2, true, intrinsic_mul}, ++ {"noise", 1, true, intrinsic_noise}, + {"normalize", 1, true, intrinsic_normalize}, + {"pow", 2, true, intrinsic_pow}, + {"radians", 1, true, intrinsic_radians}, diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 04bb2d98b26..afd6169514f 100644 +index 38d5c55c26b..afd6169514f 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -8020,8 +8020,19 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog +@@ -288,7 +288,8 @@ 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_function_decl *func, + struct hlsl_ir_var *var, struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic, +- uint32_t index, bool output, bool force_align, bool create, const struct vkd3d_shader_location *loc) ++ uint32_t index, uint32_t stream_index, bool output, bool force_align, bool create, ++ const struct vkd3d_shader_location *loc) + { + struct hlsl_semantic new_semantic; + struct hlsl_ir_var *ext_var; +@@ -300,7 +301,12 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir + else + prefix = output ? "output" : "input"; + +- if (!(new_name = hlsl_sprintf_alloc(ctx, "<%s-%s%u>", prefix, semantic->name, index))) ++ if (stream_index) ++ new_name = hlsl_sprintf_alloc(ctx, "<%s-m%u:%s%u>", prefix, stream_index, semantic->name, index); ++ else ++ new_name = hlsl_sprintf_alloc(ctx, "<%s-%s%u>", prefix, semantic->name, index); ++ ++ if (!new_name) + return NULL; + + LIST_FOR_EACH_ENTRY(ext_var, &func->extern_vars, struct hlsl_ir_var, extern_entry) +@@ -353,6 +359,7 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir + return NULL; + } + new_semantic.index = index; ++ new_semantic.stream_index = stream_index; + if (!(ext_var = hlsl_new_var(ctx, new_name, type, loc, &new_semantic, modifiers, NULL))) + { + vkd3d_free(new_name); +@@ -435,7 +442,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec + prim_type_src->modifiers = var->data_type->modifiers & HLSL_PRIMITIVE_MODIFIERS_MASK; + + if (!(input = add_semantic_var(ctx, func, var, prim_type_src, +- modifiers, semantic, semantic_index + i, false, force_align, true, loc))) ++ modifiers, semantic, semantic_index + i, 0, false, force_align, true, loc))) + return; + hlsl_init_simple_deref_from_var(&prim_deref, input); + +@@ -448,7 +455,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec + else + { + if (!(input = add_semantic_var(ctx, func, var, vector_type_src, +- modifiers, semantic, semantic_index + i, false, force_align, true, loc))) ++ modifiers, semantic, semantic_index + i, 0, false, force_align, true, loc))) + return; + + if (!(load = hlsl_new_var_load(ctx, input, &var->loc))) +@@ -558,7 +565,7 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function + + static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_ir_function_decl *func, struct hlsl_ir_load *rhs, uint32_t modifiers, +- struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align, bool create) ++ struct hlsl_semantic *semantic, uint32_t semantic_index, uint32_t stream_index, bool force_align, bool create) + { + struct hlsl_type *type = rhs->node.data_type, *vector_type; + struct vkd3d_shader_location *loc = &rhs->node.loc; +@@ -588,7 +595,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_ir_node *load; + + if (!(output = add_semantic_var(ctx, func, var, vector_type, +- modifiers, semantic, semantic_index + i, true, force_align, create, loc))) ++ modifiers, semantic, semantic_index + i, stream_index, true, force_align, create, loc))) + return; + + if (type->class == HLSL_CLASS_MATRIX) +@@ -609,7 +616,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, + + static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_ir_function_decl *func, const struct hlsl_type *type, struct hlsl_ir_load *rhs, uint32_t modifiers, +- struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align, bool create) ++ struct hlsl_semantic *semantic, uint32_t semantic_index, uint32_t stream_index, bool force_align, bool create) + { + struct vkd3d_shader_location *loc = &rhs->node.loc; + struct hlsl_ir_var *var = rhs->src.var; +@@ -654,12 +661,13 @@ static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * + hlsl_block_add_instr(block, &element_load->node); + + append_output_copy_recurse(ctx, block, func, element_type, element_load, element_modifiers, semantic, +- elem_semantic_index, force_align, create); ++ elem_semantic_index, stream_index, force_align, create); + } + } + else + { +- append_output_copy(ctx, block, func, rhs, modifiers, semantic, semantic_index, force_align, create); ++ append_output_copy(ctx, block, func, rhs, modifiers, semantic, ++ semantic_index, stream_index, force_align, create); + } + } + +@@ -676,7 +684,7 @@ static void append_output_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function + hlsl_block_add_instr(&func->body, &load->node); + + append_output_copy_recurse(ctx, &func->body, func, var->data_type, load, var->storage_modifiers, +- &var->semantic, var->semantic.index, false, true); ++ &var->semantic, var->semantic.index, 0, false, true); + } + + bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), +@@ -3360,7 +3368,7 @@ static bool split_struct_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + struct stream_append_ctx + { + struct hlsl_ir_function_decl *func; +- bool created; ++ bool created[VKD3D_MAX_STREAM_COUNT]; + }; + + static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +@@ -3371,6 +3379,7 @@ static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst + const struct hlsl_type *type; + struct hlsl_ir_var *var; + struct hlsl_block block; ++ uint32_t stream_index; + + if (instr->type != HLSL_IR_RESOURCE_STORE) + return false; +@@ -3390,18 +3399,17 @@ static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst + } + + VKD3D_ASSERT(var->regs[HLSL_REGSET_STREAM_OUTPUTS].allocated); ++ stream_index = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; + +- if (var->regs[HLSL_REGSET_STREAM_OUTPUTS].index) +- { +- hlsl_fixme(ctx, &instr->loc, "Append to an output stream with a nonzero stream index."); +- return false; +- } ++ VKD3D_ASSERT(stream_index < ARRAY_SIZE(append_ctx->created)); + + hlsl_block_init(&block); + +- append_output_copy_recurse(ctx, &block, append_ctx->func, type->e.so.type, hlsl_ir_load(rhs), var->storage_modifiers, +- &var->semantic, var->semantic.index, false, !append_ctx->created); +- append_ctx->created = true; ++ append_output_copy_recurse(ctx, &block, append_ctx->func, type->e.so.type, hlsl_ir_load(rhs), ++ var->storage_modifiers, &var->semantic, var->semantic.index, ++ var->regs[HLSL_REGSET_STREAM_OUTPUTS].index, false, !append_ctx->created[stream_index]); ++ ++ append_ctx->created[stream_index] = true; + + list_move_before(&instr->entry, &block.instrs); + hlsl_src_remove(&store->value); +@@ -3919,7 +3927,7 @@ static bool lower_separate_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *in + if (load->texel_offset.node) + { + hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, +- "Texel offsets are not supported on profiles lower than 4.0.\n"); ++ "Texel offsets are not supported on profiles lower than 4.0."); + return false; + } + +@@ -5648,6 +5656,7 @@ static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_a + unsigned int writemask = hlsl_combine_writemasks(available_writemask, + vkd3d_write_mask_from_component_count(reg_size)); + ++ ret.type = VKD3DSPR_TEMP; + ret.id = reg_idx; + ret.writemask = hlsl_combine_writemasks(writemask, + vkd3d_write_mask_from_component_count(component_count)); +@@ -5658,6 +5667,7 @@ static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_a + } + } + ++ ret.type = VKD3DSPR_TEMP; + ret.id = allocator->reg_count; + ret.writemask = vkd3d_write_mask_from_component_count(component_count); + record_allocation(ctx, allocator, allocator->reg_count, +@@ -5684,6 +5694,7 @@ static struct hlsl_reg allocate_register_with_masks(struct hlsl_ctx *ctx, + + record_allocation(ctx, allocator, reg_idx, reg_writemask, first_write, last_read, mode, vip); + ++ ret.type = VKD3DSPR_TEMP; + ret.id = reg_idx; + ret.allocation_size = 1; + ret.writemask = writemask; +@@ -5729,6 +5740,7 @@ static struct hlsl_reg allocate_range(struct hlsl_ctx *ctx, struct register_allo + record_allocation(ctx, allocator, reg_idx + (reg_size / 4), + (1u << (reg_size % 4)) - 1, first_write, last_read, mode, vip); + ++ ret.type = VKD3DSPR_TEMP; + ret.id = reg_idx; + ret.allocation_size = align(reg_size, 4) / 4; + ret.allocated = true; +@@ -5749,20 +5761,30 @@ static struct hlsl_reg allocate_numeric_registers_for_type(struct hlsl_ctx *ctx, + return allocate_range(ctx, allocator, first_write, last_read, reg_size, 0, false); + } + +-static const char *debug_register(char class, struct hlsl_reg reg, const struct hlsl_type *type) ++static const char *debug_register(struct hlsl_reg reg, const struct hlsl_type *type) + { + static const char writemask_offset[] = {'w','x','y','z'}; + unsigned int reg_size = type->reg_size[HLSL_REGSET_NUMERIC]; ++ const char *class = "r"; + +- if (reg_size > 4) ++ if (reg.type == VKD3DSPR_CONST) ++ class = "c"; ++ else if (reg.type == VKD3DSPR_INPUT) ++ class = "v"; ++ else if (reg.type == VKD3DSPR_OUTPUT) ++ class = "o"; ++ else if (reg.type == VKD3DSPR_SSA) ++ class = "sr"; ++ ++ if (reg_size > 4 && !hlsl_type_is_patch_array(type)) + { + if (reg_size & 3) +- return vkd3d_dbg_sprintf("%c%u-%c%u.%c", class, reg.id, class, reg.id + (reg_size / 4), ++ return vkd3d_dbg_sprintf("%s%u-%s%u.%c", class, reg.id, class, reg.id + (reg_size / 4), + writemask_offset[reg_size & 3]); + +- return vkd3d_dbg_sprintf("%c%u-%c%u", class, reg.id, class, reg.id + (reg_size / 4) - 1); ++ return vkd3d_dbg_sprintf("%s%u-%s%u", class, reg.id, class, reg.id + (reg_size / 4) - 1); + } +- return vkd3d_dbg_sprintf("%c%u%s", class, reg.id, debug_hlsl_writemask(reg.writemask)); ++ return vkd3d_dbg_sprintf("%s%u%s", class, reg.id, debug_hlsl_writemask(reg.writemask)); + } + + static bool track_object_components_sampler_dim(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +@@ -5902,11 +5924,12 @@ static void allocate_instr_temp_register(struct hlsl_ctx *ctx, + struct hlsl_ir_node *instr, struct register_allocator *allocator) + { + unsigned int reg_writemask = 0, dst_writemask = 0; ++ bool is_per_component = false; + + if (instr->reg.allocated || !instr->last_read) + return; + +- if (instr->type == HLSL_IR_EXPR) ++ if (instr->type == HLSL_IR_EXPR && ctx->profile->major_version < 4) + { + switch (hlsl_ir_expr(instr)->op) + { +@@ -5920,20 +5943,42 @@ static void allocate_instr_temp_register(struct hlsl_ctx *ctx, + reg_writemask = ctx->profile->major_version < 3 ? (1 << 3) - 1 : VKD3DSP_WRITEMASK_1; + break; + ++ case HLSL_OP1_EXP2: ++ case HLSL_OP1_LOG2: ++ case HLSL_OP1_RCP: ++ case HLSL_OP1_RSQ: ++ /* These ops can only be written one component at a time in sm1, ++ * so it'll take more than one instruction to fill the variable ++ * and thus we can't use an SSA. ++ * FIXME: We should probably handle this by splitting at the vsir ++ * level instead. */ ++ is_per_component = true; ++ break; ++ + default: + break; + } + } + ++ VKD3D_ASSERT(instr->data_type->class <= HLSL_CLASS_VECTOR); ++ + if (reg_writemask) +- instr->reg = allocate_register_with_masks(ctx, allocator, instr->index, +- instr->last_read, reg_writemask, dst_writemask, 0, false); +- else ++ instr->reg = allocate_register_with_masks(ctx, allocator, ++ instr->index, instr->last_read, reg_writemask, dst_writemask, 0, false); ++ else if (is_per_component) + instr->reg = allocate_numeric_registers_for_type(ctx, allocator, + instr->index, instr->last_read, instr->data_type); ++ else ++ { ++ instr->reg.writemask = vkd3d_write_mask_from_component_count(instr->data_type->e.numeric.dimx); ++ instr->reg.allocation_size = 1; ++ instr->reg.allocated = true; ++ instr->reg.type = VKD3DSPR_SSA; ++ instr->reg.id = ctx->ssa_count++; ++ } + + TRACE("Allocated anonymous expression @%u to %s (liveness %u-%u).\n", instr->index, +- debug_register('r', instr->reg, instr->data_type), instr->index, instr->last_read); ++ debug_register(instr->reg, instr->data_type), instr->index, instr->last_read); + } + + static void allocate_variable_temp_register(struct hlsl_ctx *ctx, +@@ -5958,8 +6003,8 @@ static void allocate_variable_temp_register(struct hlsl_ctx *ctx, + var->regs[HLSL_REGSET_NUMERIC] = allocate_numeric_registers_for_type(ctx, allocator, + var->first_write, var->last_read, var->data_type); + +- TRACE("Allocated %s to %s (liveness %u-%u).\n", var->name, debug_register('r', +- var->regs[HLSL_REGSET_NUMERIC], var->data_type), var->first_write, var->last_read); ++ TRACE("Allocated %s to %s (liveness %u-%u).\n", var->name, ++ debug_register(var->regs[HLSL_REGSET_NUMERIC], var->data_type), var->first_write, var->last_read); + } + } + } +@@ -6043,6 +6088,7 @@ static bool find_constant(struct hlsl_ctx *ctx, const float *f, unsigned int cou + if ((reg->allocated_mask & writemask) == writemask + && !memcmp(f, ®->value.f[j], count * sizeof(float))) + { ++ ret->type = VKD3DSPR_CONST; + ret->id = reg->index; + ret->allocation_size = 1; + ret->writemask = writemask; +@@ -6136,12 +6182,13 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, + if (find_constant(ctx, f, type->e.numeric.dimx, &constant->reg)) + { + TRACE("Reusing already allocated constant %s for @%u.\n", +- debug_register('c', constant->reg, type), instr->index); ++ debug_register(constant->reg, type), instr->index); + break; + } + + constant->reg = allocate_numeric_registers_for_type(ctx, allocator, 1, UINT_MAX, type); +- TRACE("Allocated constant @%u to %s.\n", instr->index, debug_register('c', constant->reg, type)); ++ constant->reg.type = VKD3DSPR_CONST; ++ TRACE("Allocated constant @%u to %s.\n", instr->index, debug_register(constant->reg, type)); + + for (unsigned int x = 0, i = 0; x < 4; ++x) + { +@@ -6238,14 +6285,16 @@ static void allocate_sincos_const_registers(struct hlsl_ctx *ctx, struct hlsl_bl + type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4); + + ctx->d3dsincosconst1 = allocate_numeric_registers_for_type(ctx, allocator, 1, UINT_MAX, type); +- TRACE("Allocated D3DSINCOSCONST1 to %s.\n", debug_register('c', ctx->d3dsincosconst1, type)); ++ ctx->d3dsincosconst1.type = VKD3DSPR_CONST; ++ TRACE("Allocated D3DSINCOSCONST1 to %s.\n", debug_register(ctx->d3dsincosconst1, type)); + record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 0, -1.55009923e-06f, &instr->loc); + record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 1, -2.17013894e-05f, &instr->loc); + record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 2, 2.60416674e-03f, &instr->loc); + record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 3, 2.60416680e-04f, &instr->loc); + + ctx->d3dsincosconst2 = allocate_numeric_registers_for_type(ctx, allocator, 1, UINT_MAX, type); +- TRACE("Allocated D3DSINCOSCONST2 to %s.\n", debug_register('c', ctx->d3dsincosconst2, type)); ++ ctx->d3dsincosconst2.type = VKD3DSPR_CONST; ++ TRACE("Allocated D3DSINCOSCONST2 to %s.\n", debug_register(ctx->d3dsincosconst2, type)); + record_constant(ctx, ctx->d3dsincosconst2.id * 4 + 0, -2.08333340e-02f, &instr->loc); + record_constant(ctx, ctx->d3dsincosconst2.id * 4 + 1, -1.25000000e-01f, &instr->loc); + record_constant(ctx, ctx->d3dsincosconst2.id * 4 + 2, 1.00000000e+00f, &instr->loc); +@@ -6293,12 +6342,13 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi + record_allocation(ctx, &allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX, 0, false); + } + ++ var->regs[HLSL_REGSET_NUMERIC].type = VKD3DSPR_CONST; + var->regs[HLSL_REGSET_NUMERIC].id = reg_idx; + var->regs[HLSL_REGSET_NUMERIC].allocation_size = reg_size / 4; + var->regs[HLSL_REGSET_NUMERIC].writemask = VKD3DSP_WRITEMASK_ALL; + var->regs[HLSL_REGSET_NUMERIC].allocated = true; + TRACE("Allocated reserved %s to %s.\n", var->name, +- debug_register('c', var->regs[HLSL_REGSET_NUMERIC], var->data_type)); ++ debug_register(var->regs[HLSL_REGSET_NUMERIC], var->data_type)); + } + } + +@@ -6314,8 +6364,9 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi + if (!var->regs[HLSL_REGSET_NUMERIC].allocated) + { + var->regs[HLSL_REGSET_NUMERIC] = allocate_range(ctx, &allocator, 1, UINT_MAX, alloc_size, 0, false); ++ var->regs[HLSL_REGSET_NUMERIC].type = VKD3DSPR_CONST; + TRACE("Allocated %s to %s.\n", var->name, +- debug_register('c', var->regs[HLSL_REGSET_NUMERIC], var->data_type)); ++ debug_register(var->regs[HLSL_REGSET_NUMERIC], var->data_type)); + } + } + +@@ -6456,6 +6507,8 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var + + if ((!output && !var->last_read) || (output && !var->first_write)) + return; ++ ++ optimize = false; + } + else + { +@@ -6509,17 +6562,18 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var + + var->regs[HLSL_REGSET_NUMERIC] = allocate_register(ctx, allocator, 1, UINT_MAX, + reg_size, component_count, mode, var->force_align, vip_allocation); ++ var->regs[HLSL_REGSET_NUMERIC].type = output ? VKD3DSPR_OUTPUT : VKD3DSPR_INPUT; + +- TRACE("Allocated %s to %s (mode %d).\n", var->name, debug_register(output ? 'o' : 'v', +- var->regs[HLSL_REGSET_NUMERIC], var->data_type), mode); ++ TRACE("Allocated %s to %s (mode %d).\n", var->name, ++ debug_register(var->regs[HLSL_REGSET_NUMERIC], var->data_type), mode); + } + } + + static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, + uint32_t *output_reg_count) + { ++ struct register_allocator input_allocator = {0}, output_allocators[VKD3D_MAX_STREAM_COUNT] = {{0}}; + struct register_allocator in_prim_allocator = {0}, patch_constant_out_patch_allocator = {0}; +- struct register_allocator input_allocator = {0}, output_allocator = {0}; + bool is_vertex_shader = ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX; + bool is_pixel_shader = ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL; + struct hlsl_ir_var *var; +@@ -6527,7 +6581,8 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun + in_prim_allocator.prioritize_smaller_writemasks = true; + patch_constant_out_patch_allocator.prioritize_smaller_writemasks = true; + input_allocator.prioritize_smaller_writemasks = true; +- output_allocator.prioritize_smaller_writemasks = true; ++ for (unsigned int i = 0; i < ARRAY_SIZE(output_allocators); ++i) ++ output_allocators[i].prioritize_smaller_writemasks = true; + + LIST_FOR_EACH_ENTRY(var, &entry_func->extern_vars, struct hlsl_ir_var, extern_entry) + { +@@ -6550,15 +6605,22 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun + } + + if (var->is_output_semantic) +- allocate_semantic_register(ctx, var, &output_allocator, true, !is_pixel_shader); ++ { ++ VKD3D_ASSERT(var->semantic.stream_index < ARRAY_SIZE(output_allocators)); ++ allocate_semantic_register(ctx, var, &output_allocators[var->semantic.stream_index], ++ true, !is_pixel_shader); ++ } + } + +- *output_reg_count = output_allocator.reg_count; ++ *output_reg_count = output_allocators[0].reg_count; ++ for (unsigned int i = 1; i < ARRAY_SIZE(output_allocators); ++i) ++ *output_reg_count = max(*output_reg_count, output_allocators[i].reg_count); + + vkd3d_free(in_prim_allocator.allocations); + vkd3d_free(patch_constant_out_patch_allocator.allocations); + vkd3d_free(input_allocator.allocations); +- vkd3d_free(output_allocator.allocations); ++ for (unsigned int i = 0; i < ARRAY_SIZE(output_allocators); ++i) ++ vkd3d_free(output_allocators[i].allocations); + } + + static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, +@@ -7715,8 +7777,6 @@ static void validate_and_record_stream_outputs(struct hlsl_ctx *ctx) + reported_invalid_index = true; + } + } +- +- /* TODO: check that maxvertexcount * outputdatasize <= 1024. */ + } + + static void validate_max_output_size(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, +@@ -7960,8 +8020,19 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog if ((!output && !var->last_read) || (output && !var->first_write)) return; @@ -2859,7 +8088,15 @@ index 04bb2d98b26..afd6169514f 100644 { enum vkd3d_decl_usage usage; unsigned int usage_idx; -@@ -8181,7 +8192,7 @@ static enum vkd3d_data_type vsir_data_type_from_hlsl_type(struct hlsl_ctx *ctx, +@@ -8018,6 +8089,7 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog + return; + } + element->semantic_index = var->semantic.index; ++ element->stream_index = var->semantic.stream_index; + element->sysval_semantic = sysval; + element->component_type = component_type; + element->register_index = register_index; +@@ -8120,7 +8192,7 @@ static enum vkd3d_data_type vsir_data_type_from_hlsl_type(struct hlsl_ctx *ctx, } } @@ -2868,7 +8105,7 @@ index 04bb2d98b26..afd6169514f 100644 } static enum vkd3d_data_type vsir_data_type_from_hlsl_instruction(struct hlsl_ctx *ctx, -@@ -8219,7 +8230,7 @@ static void sm1_generate_vsir_constant_defs(struct hlsl_ctx *ctx, struct vsir_pr +@@ -8158,7 +8230,7 @@ static void sm1_generate_vsir_constant_defs(struct hlsl_ctx *ctx, struct vsir_pr } ins = &instructions->elements[instructions->count]; @@ -2877,7 +8114,7 @@ index 04bb2d98b26..afd6169514f 100644 { ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; return; -@@ -8302,7 +8313,7 @@ static void sm1_generate_vsir_sampler_dcls(struct hlsl_ctx *ctx, +@@ -8241,7 +8313,7 @@ static void sm1_generate_vsir_sampler_dcls(struct hlsl_ctx *ctx, } ins = &instructions->elements[instructions->count]; @@ -2886,7 +8123,16 @@ index 04bb2d98b26..afd6169514f 100644 { ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; return; -@@ -8485,6 +8496,8 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p +@@ -8357,7 +8429,7 @@ static void vsir_src_from_hlsl_node(struct vkd3d_shader_src_param *src, + } + else + { +- vsir_register_init(&src->reg, VKD3DSPR_TEMP, vsir_data_type_from_hlsl_instruction(ctx, instr), 1); ++ vsir_register_init(&src->reg, instr->reg.type, vsir_data_type_from_hlsl_instruction(ctx, instr), 1); + src->reg.idx[0].offset = instr->reg.id; + src->reg.dimension = VSIR_DIMENSION_VEC4; + src->swizzle = generate_vsir_get_src_swizzle(instr->reg.writemask, map_writemask); +@@ -8424,6 +8496,8 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p const struct hlsl_type *data_type = hlsl_deref_get_type(ctx, deref); const struct hlsl_ir_var *var = deref->var; @@ -2895,7 +8141,7 @@ index 04bb2d98b26..afd6169514f 100644 if (var->is_uniform) { enum hlsl_regset regset = hlsl_deref_get_regset(ctx, deref); -@@ -8493,18 +8506,10 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p +@@ -8432,18 +8506,10 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p { reg->type = VKD3DSPR_RESOURCE; reg->dimension = VSIR_DIMENSION_VEC4; @@ -2918,7 +8164,7 @@ index 04bb2d98b26..afd6169514f 100644 VKD3D_ASSERT(regset == HLSL_REGSET_TEXTURES); *writemask = VKD3DSP_WRITEMASK_ALL; } -@@ -8512,18 +8517,10 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p +@@ -8451,18 +8517,10 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p { reg->type = VKD3DSPR_UAV; reg->dimension = VSIR_DIMENSION_VEC4; @@ -2941,7 +8187,7 @@ index 04bb2d98b26..afd6169514f 100644 VKD3D_ASSERT(regset == HLSL_REGSET_UAVS); *writemask = VKD3DSP_WRITEMASK_ALL; } -@@ -8531,18 +8528,10 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p +@@ -8470,21 +8528,21 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p { reg->type = VKD3DSPR_SAMPLER; reg->dimension = VSIR_DIMENSION_NONE; @@ -2964,7 +8210,18 @@ index 04bb2d98b26..afd6169514f 100644 VKD3D_ASSERT(regset == HLSL_REGSET_SAMPLERS); *writemask = VKD3DSP_WRITEMASK_ALL; } -@@ -8561,19 +8550,10 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p ++ else if (regset == HLSL_REGSET_STREAM_OUTPUTS) ++ { ++ reg->type = VKD3DSPR_STREAM; ++ reg->dimension = VSIR_DIMENSION_NONE; ++ reg->idx[0].offset = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; ++ reg->idx_count = 1; ++ *writemask = VKD3DSP_WRITEMASK_ALL; ++ } + else + { + unsigned int offset = deref->const_offset + var->buffer_offset; +@@ -8492,19 +8550,10 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p VKD3D_ASSERT(data_type->class <= HLSL_CLASS_VECTOR); reg->type = VKD3DSPR_CONSTBUFFER; reg->dimension = VSIR_DIMENSION_VEC4; @@ -2988,7 +8245,16 @@ index 04bb2d98b26..afd6169514f 100644 if (deref->rel_offset.node) { -@@ -8715,7 +8695,7 @@ static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, +@@ -8630,7 +8679,7 @@ static void vsir_dst_from_hlsl_node(struct vkd3d_shader_dst_param *dst, + struct hlsl_ctx *ctx, const struct hlsl_ir_node *instr) + { + VKD3D_ASSERT(instr->reg.allocated); +- vsir_dst_param_init(dst, VKD3DSPR_TEMP, vsir_data_type_from_hlsl_instruction(ctx, instr), 1); ++ vsir_dst_param_init(dst, instr->reg.type, vsir_data_type_from_hlsl_instruction(ctx, instr), 1); + dst->reg.idx[0].offset = instr->reg.id; + dst->reg.dimension = VSIR_DIMENSION_VEC4; + dst->write_mask = instr->reg.writemask; +@@ -8646,7 +8695,7 @@ static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, VKD3D_ASSERT(instr->reg.allocated); VKD3D_ASSERT(constant->reg.allocated); @@ -2997,7 +8263,7 @@ index 04bb2d98b26..afd6169514f 100644 return; src_param = &ins->src[0]; -@@ -8734,7 +8714,7 @@ static void sm4_generate_vsir_rasterizer_sample_count(struct hlsl_ctx *ctx, +@@ -8665,7 +8714,7 @@ static void sm4_generate_vsir_rasterizer_sample_count(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr = &expr->node; struct vkd3d_shader_instruction *ins; @@ -3006,7 +8272,23 @@ index 04bb2d98b26..afd6169514f 100644 return; ins->flags = VKD3DSI_SAMPLE_INFO_UINT; -@@ -8836,7 +8816,7 @@ static void sm1_generate_vsir_instr_expr_sincos(struct hlsl_ctx *ctx, struct vsi +@@ -8740,13 +8789,13 @@ static void sm1_generate_vsir_instr_expr_per_component_instr_op(struct hlsl_ctx + return; + + dst_param = &ins->dst[0]; +- vsir_register_init(&dst_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&dst_param->reg, instr->reg.type, VKD3D_DATA_FLOAT, 1); + dst_param->reg.idx[0].offset = instr->reg.id; + dst_param->reg.dimension = VSIR_DIMENSION_VEC4; + dst_param->write_mask = 1u << i; + + src_param = &ins->src[0]; +- vsir_register_init(&src_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&src_param->reg, operand->reg.type, VKD3D_DATA_FLOAT, 1); + src_param->reg.idx[0].offset = operand->reg.id; + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + c = vsir_swizzle_get_component(src_swizzle, i); +@@ -8767,7 +8816,7 @@ static void sm1_generate_vsir_instr_expr_sincos(struct hlsl_ctx *ctx, struct vsi VKD3D_ASSERT(instr->reg.allocated); src_count = (ctx->profile->major_version < 3) ? 3 : 1; @@ -3015,7 +8297,7 @@ index 04bb2d98b26..afd6169514f 100644 return; vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); -@@ -8885,13 +8865,13 @@ static bool sm1_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, +@@ -8816,13 +8865,13 @@ static bool sm1_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, /* Integrals are internally represented as floats, so no change is necessary.*/ case HLSL_TYPE_HALF: case HLSL_TYPE_FLOAT: @@ -3031,7 +8313,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; } hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -@@ -8916,7 +8896,7 @@ static bool sm1_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, +@@ -8847,7 +8896,7 @@ static bool sm1_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, case HLSL_TYPE_MIN16UINT: case HLSL_TYPE_UINT: case HLSL_TYPE_BOOL: @@ -3040,7 +8322,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; case HLSL_TYPE_DOUBLE: -@@ -8929,7 +8909,7 @@ static bool sm1_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, +@@ -8860,7 +8909,7 @@ static bool sm1_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, switch (src_type->e.numeric.type) { case HLSL_TYPE_FLOAT: @@ -3049,7 +8331,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; break; -@@ -8968,7 +8948,7 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr +@@ -8899,7 +8948,7 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr switch (expr->op) { case HLSL_OP1_ABS: @@ -3058,7 +8340,7 @@ index 04bb2d98b26..afd6169514f 100644 break; case HLSL_OP1_CAST: -@@ -8984,53 +8964,53 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr +@@ -8915,53 +8964,53 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr case HLSL_OP1_DSX: if (!hlsl_type_is_floating_point(type)) goto err; @@ -3121,7 +8403,7 @@ index 04bb2d98b26..afd6169514f 100644 break; case HLSL_OP1_SIN_REDUCED: -@@ -9043,7 +9023,7 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr +@@ -8974,7 +9023,7 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr case HLSL_OP2_ADD: if (type->e.numeric.type == HLSL_TYPE_BOOL) goto err; @@ -3130,7 +8412,7 @@ index 04bb2d98b26..afd6169514f 100644 break; case HLSL_OP2_DOT: -@@ -9052,11 +9032,11 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr +@@ -8983,11 +9032,11 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr switch (expr->operands[0].node->data_type->e.numeric.dimx) { case 3: @@ -3144,7 +8426,7 @@ index 04bb2d98b26..afd6169514f 100644 break; default: -@@ -9066,55 +9046,55 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr +@@ -8997,55 +9046,55 @@ static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_progr break; case HLSL_OP2_MAX: @@ -3210,7 +8492,7 @@ index 04bb2d98b26..afd6169514f 100644 break; default: -@@ -9194,7 +9174,7 @@ static void sm1_generate_vsir_init_dst_param_from_deref(struct hlsl_ctx *ctx, +@@ -9125,7 +9174,7 @@ static void sm1_generate_vsir_init_dst_param_from_deref(struct hlsl_ctx *ctx, static void sm1_generate_vsir_instr_mova(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_node *instr) { @@ -3219,7 +8501,7 @@ index 04bb2d98b26..afd6169514f 100644 struct vkd3d_shader_dst_param *dst_param; struct vkd3d_shader_instruction *ins; -@@ -9321,7 +9301,7 @@ static void sm1_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr +@@ -9252,7 +9301,7 @@ static void sm1_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr if (load->src.rel_offset.node) sm1_generate_vsir_instr_mova(ctx, program, load->src.rel_offset.node); @@ -3228,22 +8510,22 @@ index 04bb2d98b26..afd6169514f 100644 return; vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); -@@ -9348,21 +9328,21 @@ static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, +@@ -9279,21 +9328,21 @@ static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, switch (load->load_type) { case HLSL_RESOURCE_SAMPLE: -- opcode = VKD3DSIH_TEXLD; +- opcode = VKD3DSIH_TEX; + opcode = VSIR_OP_TEXLD; break; case HLSL_RESOURCE_SAMPLE_PROJ: -- opcode = VKD3DSIH_TEXLD; +- opcode = VKD3DSIH_TEX; + opcode = VSIR_OP_TEXLD; flags |= VKD3DSI_TEXLD_PROJECT; break; case HLSL_RESOURCE_SAMPLE_LOD_BIAS: -- opcode = VKD3DSIH_TEXLD; +- opcode = VKD3DSIH_TEX; + opcode = VSIR_OP_TEXLD; flags |= VKD3DSI_TEXLD_BIAS; break; @@ -3254,7 +8536,7 @@ index 04bb2d98b26..afd6169514f 100644 src_count += 2; break; -@@ -9403,7 +9383,7 @@ static void generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, +@@ -9334,7 +9383,7 @@ static void generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, VKD3D_ASSERT(instr->reg.allocated); @@ -3263,7 +8545,16 @@ index 04bb2d98b26..afd6169514f 100644 return; vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); -@@ -9428,7 +9408,7 @@ static void sm1_generate_vsir_instr_store(struct hlsl_ctx *ctx, struct vsir_prog +@@ -9345,7 +9394,7 @@ static void generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, + + src_param = &ins->src[0]; + VKD3D_ASSERT(val->type != HLSL_IR_CONSTANT); +- vsir_register_init(&src_param->reg, VKD3DSPR_TEMP, vsir_data_type_from_hlsl_instruction(ctx, val), 1); ++ vsir_register_init(&src_param->reg, val->reg.type, vsir_data_type_from_hlsl_instruction(ctx, val), 1); + src_param->reg.idx[0].offset = val->reg.id; + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param->swizzle = swizzle; +@@ -9359,7 +9408,7 @@ static void sm1_generate_vsir_instr_store(struct hlsl_ctx *ctx, struct vsir_prog struct vkd3d_shader_instruction *ins; struct vkd3d_shader_src_param *src_param; @@ -3272,7 +8563,7 @@ index 04bb2d98b26..afd6169514f 100644 return; sm1_generate_vsir_init_dst_param_from_deref(ctx, &ins->dst[0], &store->lhs, &ins->location, store->writemask); -@@ -9446,7 +9426,7 @@ static void sm1_generate_vsir_instr_jump(struct hlsl_ctx *ctx, +@@ -9377,7 +9426,7 @@ static void sm1_generate_vsir_instr_jump(struct hlsl_ctx *ctx, if (jump->type == HLSL_IR_JUMP_DISCARD_NEG) { @@ -3281,7 +8572,7 @@ index 04bb2d98b26..afd6169514f 100644 return; vsir_src_from_hlsl_node(&ins->src[0], ctx, condition, VKD3DSP_WRITEMASK_ALL); -@@ -9473,7 +9453,7 @@ static void sm1_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program +@@ -9404,7 +9453,7 @@ static void sm1_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program } VKD3D_ASSERT(condition->data_type->e.numeric.dimx == 1 && condition->data_type->e.numeric.dimy == 1); @@ -3290,7 +8581,7 @@ index 04bb2d98b26..afd6169514f 100644 return; ins->flags = VKD3D_SHADER_REL_OP_NE; -@@ -9487,12 +9467,12 @@ static void sm1_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program +@@ -9418,12 +9467,12 @@ static void sm1_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program sm1_generate_vsir_block(ctx, &iff->then_block, program); @@ -3305,7 +8596,82 @@ index 04bb2d98b26..afd6169514f 100644 return; } -@@ -10071,16 +10051,16 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs +@@ -9501,6 +9550,7 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl + return; + } + ++ program->ssa_count = 0; + program->temp_count = allocate_temp_registers(ctx, entry_func); + if (ctx->result) + return; +@@ -9513,6 +9563,8 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl + list_move_head(&entry_func->body.instrs, &block.instrs); + + sm1_generate_vsir_block(ctx, &entry_func->body, program); ++ ++ program->ssa_count = ctx->ssa_count; + } + + D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) +@@ -9922,6 +9974,57 @@ static void sm1_generate_ctab(struct hlsl_ctx *ctx, struct vkd3d_shader_code *ct + ctab->size = buffer.size; + } + ++static enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval, ++ unsigned int index) ++{ ++ switch (sysval) ++ { ++ case VKD3D_SHADER_SV_COVERAGE: ++ case VKD3D_SHADER_SV_DEPTH: ++ case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL: ++ case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL: ++ case VKD3D_SHADER_SV_NONE: ++ case VKD3D_SHADER_SV_STENCIL_REF: ++ case VKD3D_SHADER_SV_TARGET: ++ return VKD3D_SIV_NONE; ++ case VKD3D_SHADER_SV_POSITION: ++ return VKD3D_SIV_POSITION; ++ case VKD3D_SHADER_SV_CLIP_DISTANCE: ++ return VKD3D_SIV_CLIP_DISTANCE; ++ case VKD3D_SHADER_SV_CULL_DISTANCE: ++ return VKD3D_SIV_CULL_DISTANCE; ++ case VKD3D_SHADER_SV_INSTANCE_ID: ++ return VKD3D_SIV_INSTANCE_ID; ++ case VKD3D_SHADER_SV_IS_FRONT_FACE: ++ return VKD3D_SIV_IS_FRONT_FACE; ++ case VKD3D_SHADER_SV_PRIMITIVE_ID: ++ return VKD3D_SIV_PRIMITIVE_ID; ++ case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX: ++ return VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX; ++ case VKD3D_SHADER_SV_SAMPLE_INDEX: ++ return VKD3D_SIV_SAMPLE_INDEX; ++ case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: ++ return VKD3D_SIV_QUAD_U0_TESS_FACTOR + index; ++ case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: ++ return VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR + index; ++ case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: ++ return VKD3D_SIV_TRIANGLE_U_TESS_FACTOR + index; ++ case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: ++ return VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR; ++ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: ++ return VKD3D_SIV_LINE_DETAIL_TESS_FACTOR; ++ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: ++ return VKD3D_SIV_LINE_DENSITY_TESS_FACTOR; ++ case VKD3D_SHADER_SV_VERTEX_ID: ++ return VKD3D_SIV_VERTEX_ID; ++ case VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX: ++ return VKD3D_SIV_VIEWPORT_ARRAY_INDEX; ++ default: ++ FIXME("Unhandled sysval %#x, index %u.\n", sysval, index); ++ return VKD3D_SIV_NONE; ++ } ++} ++ + static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vsir_program *program, + const struct hlsl_ir_var *var, struct hlsl_block *block, const struct vkd3d_shader_location *loc) + { +@@ -9948,16 +10051,16 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs { case VKD3D_SHADER_SV_NONE: opcode = (version->type == VKD3D_SHADER_TYPE_PIXEL) @@ -3326,7 +8692,7 @@ index 04bb2d98b26..afd6169514f 100644 break; case VKD3D_SHADER_SV_INSTANCE_ID: -@@ -10088,16 +10068,16 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs +@@ -9965,16 +10068,16 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs case VKD3D_SHADER_SV_SAMPLE_INDEX: case VKD3D_SHADER_SV_VERTEX_ID: opcode = (version->type == VKD3D_SHADER_TYPE_PIXEL) @@ -3347,15 +8713,14 @@ index 04bb2d98b26..afd6169514f 100644 break; } } -@@ -10105,12 +10085,12 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs +@@ -9982,9 +10085,12 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs { if (semantic == VKD3D_SHADER_SV_NONE || version->type == VKD3D_SHADER_TYPE_PIXEL || (version->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func)) - opcode = VKD3DSIH_DCL_OUTPUT; + opcode = VSIR_OP_DCL_OUTPUT; - else if ((semantic == VKD3D_SHADER_SV_PRIMITIVE_ID || semantic == VKD3D_SHADER_SV_IS_FRONT_FACE) - && version->type == VKD3D_SHADER_TYPE_GEOMETRY) -- opcode = VKD3DSIH_DCL_OUTPUT_SGV; ++ else if ((semantic == VKD3D_SHADER_SV_PRIMITIVE_ID || semantic == VKD3D_SHADER_SV_IS_FRONT_FACE) ++ && version->type == VKD3D_SHADER_TYPE_GEOMETRY) + opcode = VSIR_OP_DCL_OUTPUT_SGV; else - opcode = VKD3DSIH_DCL_OUTPUT_SIV; @@ -3363,7 +8728,7 @@ index 04bb2d98b26..afd6169514f 100644 } if (sm4_register_from_semantic_name(version, var->semantic.name, output, &type, &has_idx)) -@@ -10130,13 +10110,13 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs +@@ -10004,13 +10110,13 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs if (!(ins = generate_vsir_add_program_instruction(ctx, program, loc, opcode, 0, 0))) return; @@ -3379,7 +8744,7 @@ index 04bb2d98b26..afd6169514f 100644 { VKD3D_ASSERT(semantic == VKD3D_SHADER_SV_NONE || is_primitive || version->type == VKD3D_SHADER_TYPE_GEOMETRY); dst_param = &ins->declaration.dst; -@@ -10182,7 +10162,7 @@ static void sm4_generate_vsir_instr_dcl_temps(struct hlsl_ctx *ctx, struct vsir_ +@@ -10056,7 +10162,7 @@ static void sm4_generate_vsir_instr_dcl_temps(struct hlsl_ctx *ctx, struct vsir_ { struct vkd3d_shader_instruction *ins; @@ -3388,7 +8753,7 @@ index 04bb2d98b26..afd6169514f 100644 return; ins->declaration.count = temp_count; -@@ -10194,7 +10174,7 @@ static void sm4_generate_vsir_instr_dcl_indexable_temp(struct hlsl_ctx *ctx, +@@ -10068,7 +10174,7 @@ static void sm4_generate_vsir_instr_dcl_indexable_temp(struct hlsl_ctx *ctx, { struct vkd3d_shader_instruction *ins; @@ -3397,7 +8762,7 @@ index 04bb2d98b26..afd6169514f 100644 return; ins->declaration.indexable_temp.register_idx = idx; -@@ -10221,11 +10201,12 @@ static void sm4_generate_vsir_cast_from_bool(struct hlsl_ctx *ctx, struct vsir_p +@@ -10095,11 +10201,12 @@ static void sm4_generate_vsir_cast_from_bool(struct hlsl_ctx *ctx, struct vsir_p VKD3D_ASSERT(instr->reg.allocated); @@ -3411,7 +8776,7 @@ index 04bb2d98b26..afd6169514f 100644 vsir_src_from_hlsl_node(&ins->src[0], ctx, operand, dst_param->write_mask); -@@ -10257,16 +10238,16 @@ static bool sm4_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, +@@ -10131,16 +10238,16 @@ static bool sm4_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, { case HLSL_TYPE_HALF: case HLSL_TYPE_FLOAT: @@ -3431,7 +8796,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; case HLSL_TYPE_BOOL: -@@ -10284,13 +10265,13 @@ static bool sm4_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, +@@ -10158,13 +10265,13 @@ static bool sm4_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, { case HLSL_TYPE_HALF: case HLSL_TYPE_FLOAT: @@ -3447,7 +8812,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; case HLSL_TYPE_BOOL: -@@ -10309,13 +10290,13 @@ static bool sm4_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, +@@ -10183,13 +10290,13 @@ static bool sm4_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, { case HLSL_TYPE_HALF: case HLSL_TYPE_FLOAT: @@ -3463,7 +8828,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; case HLSL_TYPE_BOOL: -@@ -10379,7 +10360,7 @@ static void sm4_generate_vsir_rcp_using_div(struct hlsl_ctx *ctx, +@@ -10253,7 +10360,7 @@ static void sm4_generate_vsir_rcp_using_div(struct hlsl_ctx *ctx, VKD3D_ASSERT(type_is_float(expr->node.data_type)); @@ -3472,7 +8837,7 @@ index 04bb2d98b26..afd6169514f 100644 return; dst_param = &ins->dst[0]; -@@ -10413,12 +10394,12 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10287,12 +10394,12 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, case HLSL_OP1_ABS: VKD3D_ASSERT(type_is_float(dst_type)); @@ -3487,7 +8852,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; case HLSL_OP1_CAST: -@@ -10426,92 +10407,92 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10300,92 +10407,92 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, case HLSL_OP1_CEIL: VKD3D_ASSERT(type_is_float(dst_type)); @@ -3597,7 +8962,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10525,7 +10506,7 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10399,7 +10506,7 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, case HLSL_TYPE_FLOAT: /* SM5 comes with a RCP opcode */ if (hlsl_version_ge(ctx, 5, 0)) @@ -3606,7 +8971,7 @@ index 04bb2d98b26..afd6169514f 100644 else sm4_generate_vsir_rcp_using_div(ctx, program, expr); return true; -@@ -10536,50 +10517,50 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10410,50 +10517,50 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, } case HLSL_OP1_REINTERPRET: @@ -3666,7 +9031,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10589,29 +10570,29 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10463,29 +10570,29 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, case HLSL_OP2_BIT_AND: VKD3D_ASSERT(hlsl_type_is_integer(dst_type)); @@ -3701,7 +9066,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10626,15 +10607,15 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10500,15 +10607,15 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, switch (expr->operands[0].node->data_type->e.numeric.dimx) { case 4: @@ -3720,7 +9085,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; case 1: -@@ -10653,14 +10634,14 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10527,14 +10634,14 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, switch (src_type->e.numeric.type) { case HLSL_TYPE_FLOAT: @@ -3737,7 +9102,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10675,17 +10656,17 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10549,17 +10656,17 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, switch (src_type->e.numeric.type) { case HLSL_TYPE_FLOAT: @@ -3758,7 +9123,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10700,17 +10681,17 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10574,17 +10681,17 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, switch (src_type->e.numeric.type) { case HLSL_TYPE_FLOAT: @@ -3779,7 +9144,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10721,31 +10702,31 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10595,31 +10702,31 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, case HLSL_OP2_LOGIC_AND: VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL); @@ -3816,7 +9181,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10757,16 +10738,16 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10631,16 +10738,16 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, switch (dst_type->e.numeric.type) { case HLSL_TYPE_FLOAT: @@ -3836,7 +9201,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10778,16 +10759,16 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10652,16 +10759,16 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, switch (dst_type->e.numeric.type) { case HLSL_TYPE_FLOAT: @@ -3856,7 +9221,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10800,7 +10781,7 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10674,7 +10781,7 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, { case HLSL_TYPE_MIN16UINT: /* FIXME: Needs minimum-precision annotations. */ case HLSL_TYPE_UINT: @@ -3865,7 +9230,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10812,7 +10793,7 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10686,7 +10793,7 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, switch (dst_type->e.numeric.type) { case HLSL_TYPE_FLOAT: @@ -3874,7 +9239,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; case HLSL_TYPE_INT: -@@ -10820,7 +10801,7 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10694,7 +10801,7 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, case HLSL_TYPE_UINT: /* Using IMUL instead of UMUL because we're taking the low * bits, and the native compiler generates IMUL. */ @@ -3883,7 +9248,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10834,14 +10815,14 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10708,14 +10815,14 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, switch (src_type->e.numeric.type) { case HLSL_TYPE_FLOAT: @@ -3900,7 +9265,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10854,11 +10835,11 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, +@@ -10728,11 +10835,11 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, VKD3D_ASSERT(hlsl_type_is_integer(dst_type)); VKD3D_ASSERT(dst_type->e.numeric.type != HLSL_TYPE_BOOL); generate_vsir_instr_expr_single_instr_op(ctx, program, expr, @@ -3914,7 +9279,7 @@ index 04bb2d98b26..afd6169514f 100644 return true; default: -@@ -10875,7 +10856,7 @@ static bool sm4_generate_vsir_instr_store(struct hlsl_ctx *ctx, +@@ -10749,7 +10856,7 @@ static bool sm4_generate_vsir_instr_store(struct hlsl_ctx *ctx, struct vkd3d_shader_src_param *src_param; struct vkd3d_shader_instruction *ins; @@ -3923,7 +9288,7 @@ index 04bb2d98b26..afd6169514f 100644 return false; dst_param = &ins->dst[0]; -@@ -10915,7 +10896,7 @@ static bool sm4_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr +@@ -10789,7 +10896,7 @@ static bool sm4_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr /* Uniform bools can be specified as anything, but internal bools * always have 0 for false and ~0 for true. Normalise that here. */ @@ -3932,7 +9297,7 @@ index 04bb2d98b26..afd6169514f 100644 return false; dst_param = &ins->dst[0]; -@@ -10934,7 +10915,7 @@ static bool sm4_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr +@@ -10808,7 +10915,7 @@ static bool sm4_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr } else { @@ -3941,22 +9306,42 @@ index 04bb2d98b26..afd6169514f 100644 return false; dst_param = &ins->dst[0]; -@@ -10965,12 +10946,12 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, +@@ -10832,20 +10939,27 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, - if (hlsl_version_lt(ctx, 5, 0)) + if (store->store_type != HLSL_RESOURCE_STORE) + { +- enum vkd3d_shader_opcode opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND +- ? VKD3DSIH_EMIT : VKD3DSIH_CUT; ++ enum vkd3d_shader_opcode opcode; + + VKD3D_ASSERT(!store->value.node && !store->coords.node); + VKD3D_ASSERT(store->resource.var->regs[HLSL_REGSET_STREAM_OUTPUTS].allocated); + +- if (store->resource.var->regs[HLSL_REGSET_STREAM_OUTPUTS].index) ++ if (hlsl_version_lt(ctx, 5, 0)) { -- opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND ? VKD3DSIH_EMIT : VKD3DSIH_CUT; +- hlsl_fixme(ctx, &instr->loc, "Stream output operation with a nonzero stream index."); +- return false; + opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND ? VSIR_OP_EMIT : VSIR_OP_CUT; - ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 0); - return !!ins; ++ ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 0); ++ return !!ins; } -- opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND ? VKD3DSIH_EMIT_STREAM : VKD3DSIH_CUT_STREAM; +- ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 0); +- return !!ins; + opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND ? VSIR_OP_EMIT_STREAM : VSIR_OP_CUT_STREAM; - if (!(ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 1))) - return false; ++ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 1))) ++ return false; ++ ++ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, &ins->src[0], ++ &store->resource, VKD3DSP_WRITEMASK_ALL, &instr->loc)) ++ return false; ++ ++ return true; + } -@@ -10995,7 +10976,7 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, + if (!store->resource.var->is_uniform) +@@ -10862,7 +10976,7 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, if (resource_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) { @@ -3965,7 +9350,7 @@ index 04bb2d98b26..afd6169514f 100644 return false; writemask = vkd3d_write_mask_from_component_count(value->data_type->e.numeric.dimx); -@@ -11005,7 +10986,7 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, +@@ -10872,7 +10986,7 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, } else { @@ -3974,7 +9359,7 @@ index 04bb2d98b26..afd6169514f 100644 return false; if (!sm4_generate_vsir_init_dst_param_from_deref(ctx, program, -@@ -11080,11 +11061,11 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, +@@ -10947,11 +11061,11 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, || resource_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY); if (uav) @@ -3989,7 +9374,7 @@ index 04bb2d98b26..afd6169514f 100644 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, 2 + multisampled))) return false; -@@ -11145,32 +11126,32 @@ static bool sm4_generate_vsir_instr_sample(struct hlsl_ctx *ctx, +@@ -11012,32 +11126,32 @@ static bool sm4_generate_vsir_instr_sample(struct hlsl_ctx *ctx, switch (load->load_type) { case HLSL_RESOURCE_SAMPLE: @@ -4028,7 +9413,7 @@ index 04bb2d98b26..afd6169514f 100644 src_count = 5; break; -@@ -11201,15 +11182,15 @@ static bool sm4_generate_vsir_instr_sample(struct hlsl_ctx *ctx, +@@ -11068,15 +11182,15 @@ static bool sm4_generate_vsir_instr_sample(struct hlsl_ctx *ctx, sampler, VKD3DSP_WRITEMASK_ALL, &instr->loc)) return false; @@ -4047,7 +9432,7 @@ index 04bb2d98b26..afd6169514f 100644 { vsir_src_from_hlsl_node(&ins->src[3], ctx, load->ddx.node, VKD3DSP_WRITEMASK_ALL); vsir_src_from_hlsl_node(&ins->src[4], ctx, load->ddy.node, VKD3DSP_WRITEMASK_ALL); -@@ -11224,7 +11205,7 @@ static bool sm4_generate_vsir_instr_gather(struct hlsl_ctx *ctx, struct vsir_pro +@@ -11091,7 +11205,7 @@ static bool sm4_generate_vsir_instr_gather(struct hlsl_ctx *ctx, struct vsir_pro const struct hlsl_ir_node *texel_offset = load->texel_offset.node; const struct hlsl_ir_node *coords = load->coords.node; const struct hlsl_deref *resource = &load->resource; @@ -4056,7 +9441,7 @@ index 04bb2d98b26..afd6169514f 100644 const struct hlsl_deref *sampler = &load->sampler; const struct hlsl_ir_node *instr = &load->node; unsigned int src_count = 3, current_arg = 0; -@@ -11238,13 +11219,13 @@ static bool sm4_generate_vsir_instr_gather(struct hlsl_ctx *ctx, struct vsir_pro +@@ -11105,13 +11219,13 @@ static bool sm4_generate_vsir_instr_gather(struct hlsl_ctx *ctx, struct vsir_pro "Offset must resolve to integer literal in the range -8 to 7 for profiles < 5."); return false; } @@ -4072,7 +9457,7 @@ index 04bb2d98b26..afd6169514f 100644 ++src_count; } -@@ -11254,7 +11235,7 @@ static bool sm4_generate_vsir_instr_gather(struct hlsl_ctx *ctx, struct vsir_pro +@@ -11121,7 +11235,7 @@ static bool sm4_generate_vsir_instr_gather(struct hlsl_ctx *ctx, struct vsir_pro vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); vsir_src_from_hlsl_node(&ins->src[current_arg++], ctx, coords, VKD3DSP_WRITEMASK_ALL); @@ -4081,7 +9466,7 @@ index 04bb2d98b26..afd6169514f 100644 vsir_src_from_hlsl_node(&ins->src[current_arg++], ctx, texel_offset, VKD3DSP_WRITEMASK_ALL); else sm4_generate_vsir_encode_texel_offset_as_aoffimmi(ins, texel_offset); -@@ -11286,7 +11267,7 @@ static bool sm4_generate_vsir_instr_sample_info(struct hlsl_ctx *ctx, +@@ -11153,7 +11267,7 @@ static bool sm4_generate_vsir_instr_sample_info(struct hlsl_ctx *ctx, VKD3D_ASSERT(type->e.numeric.type == HLSL_TYPE_UINT || type->e.numeric.type == HLSL_TYPE_FLOAT); @@ -4090,7 +9475,7 @@ index 04bb2d98b26..afd6169514f 100644 return false; if (type->e.numeric.type == HLSL_TYPE_UINT) -@@ -11318,7 +11299,7 @@ static bool sm4_generate_vsir_instr_resinfo(struct hlsl_ctx *ctx, +@@ -11185,7 +11299,7 @@ static bool sm4_generate_vsir_instr_resinfo(struct hlsl_ctx *ctx, VKD3D_ASSERT(type->e.numeric.type == HLSL_TYPE_UINT || type->e.numeric.type == HLSL_TYPE_FLOAT); @@ -4099,7 +9484,7 @@ index 04bb2d98b26..afd6169514f 100644 return false; if (type->e.numeric.type == HLSL_TYPE_UINT) -@@ -11423,25 +11404,25 @@ static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx, +@@ -11290,25 +11404,25 @@ static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx, static const enum vkd3d_shader_opcode opcodes[] = { @@ -4140,7 +9525,7 @@ index 04bb2d98b26..afd6169514f 100644 }; struct hlsl_ir_node *cmp_value = interlocked->cmp_value.node, *value = interlocked->value.node; -@@ -11456,14 +11437,14 @@ static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx, +@@ -11323,14 +11437,14 @@ static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx, if (value->data_type->e.numeric.type == HLSL_TYPE_INT) { @@ -4163,7 +9548,7 @@ index 04bb2d98b26..afd6169514f 100644 } if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, -@@ -11501,13 +11482,13 @@ static bool sm4_generate_vsir_instr_jump(struct hlsl_ctx *ctx, +@@ -11368,13 +11482,13 @@ static bool sm4_generate_vsir_instr_jump(struct hlsl_ctx *ctx, switch (jump->type) { case HLSL_IR_JUMP_BREAK: @@ -4180,7 +9565,7 @@ index 04bb2d98b26..afd6169514f 100644 return false; ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ; -@@ -11529,7 +11510,7 @@ static bool sm4_generate_vsir_instr_sync(struct hlsl_ctx *ctx, +@@ -11396,7 +11510,7 @@ static bool sm4_generate_vsir_instr_sync(struct hlsl_ctx *ctx, const struct hlsl_ir_node *instr = &sync->node; struct vkd3d_shader_instruction *ins; @@ -4189,7 +9574,7 @@ index 04bb2d98b26..afd6169514f 100644 return false; ins->flags = sync->sync_flags; -@@ -11545,7 +11526,7 @@ static void sm4_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program +@@ -11412,7 +11526,7 @@ static void sm4_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program VKD3D_ASSERT(iff->condition.node->data_type->e.numeric.dimx == 1); @@ -4198,7 +9583,7 @@ index 04bb2d98b26..afd6169514f 100644 return; ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ; -@@ -11555,12 +11536,12 @@ static void sm4_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program +@@ -11422,12 +11536,12 @@ static void sm4_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program if (!list_empty(&iff->else_block.instrs)) { @@ -4213,7 +9598,7 @@ index 04bb2d98b26..afd6169514f 100644 return; } -@@ -11570,12 +11551,12 @@ static void sm4_generate_vsir_instr_loop(struct hlsl_ctx *ctx, +@@ -11437,12 +11551,12 @@ static void sm4_generate_vsir_instr_loop(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr = &loop->node; struct vkd3d_shader_instruction *ins; @@ -4228,7 +9613,7 @@ index 04bb2d98b26..afd6169514f 100644 return; } -@@ -11587,7 +11568,7 @@ static void sm4_generate_vsir_instr_switch(struct hlsl_ctx *ctx, +@@ -11454,7 +11568,7 @@ static void sm4_generate_vsir_instr_switch(struct hlsl_ctx *ctx, struct vkd3d_shader_instruction *ins; struct hlsl_ir_switch_case *cas; @@ -4237,7 +9622,7 @@ index 04bb2d98b26..afd6169514f 100644 return; vsir_src_from_hlsl_node(&ins->src[0], ctx, selector, VKD3DSP_WRITEMASK_ALL); -@@ -11595,14 +11576,14 @@ static void sm4_generate_vsir_instr_switch(struct hlsl_ctx *ctx, +@@ -11462,14 +11576,14 @@ static void sm4_generate_vsir_instr_switch(struct hlsl_ctx *ctx, { if (cas->is_default) { @@ -4254,7 +9639,7 @@ index 04bb2d98b26..afd6169514f 100644 return; vsir_src_from_hlsl_constant_value(&ins->src[0], ctx, &value, VKD3D_DATA_UINT, 1, VKD3DSP_WRITEMASK_ALL); } -@@ -11610,7 +11591,7 @@ static void sm4_generate_vsir_instr_switch(struct hlsl_ctx *ctx, +@@ -11477,7 +11591,7 @@ static void sm4_generate_vsir_instr_switch(struct hlsl_ctx *ctx, sm4_generate_vsir_block(ctx, &cas->body, program); } @@ -4263,7 +9648,7 @@ index 04bb2d98b26..afd6169514f 100644 return; } -@@ -11750,7 +11731,7 @@ static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, +@@ -11617,7 +11731,7 @@ static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, sm4_generate_vsir_block(ctx, &func->body, program); @@ -4272,7 +9657,7 @@ index 04bb2d98b26..afd6169514f 100644 } static int sm4_compare_extern_resources(const void *a, const void *b) -@@ -12030,7 +12011,7 @@ static void sm4_generate_vsir_add_dcl_constant_buffer(struct hlsl_ctx *ctx, +@@ -11897,7 +12011,7 @@ static void sm4_generate_vsir_add_dcl_constant_buffer(struct hlsl_ctx *ctx, struct vkd3d_shader_src_param *src_param; struct vkd3d_shader_instruction *ins; @@ -4281,7 +9666,7 @@ index 04bb2d98b26..afd6169514f 100644 { ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; return; -@@ -12071,7 +12052,7 @@ static void sm4_generate_vsir_add_dcl_sampler(struct hlsl_ctx *ctx, +@@ -11938,7 +12052,7 @@ static void sm4_generate_vsir_add_dcl_sampler(struct hlsl_ctx *ctx, if (resource->var && !resource->var->objects_usage[HLSL_REGSET_SAMPLERS][i].used) continue; @@ -4290,7 +9675,31 @@ index 04bb2d98b26..afd6169514f 100644 { ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; return; -@@ -12184,13 +12165,13 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, +@@ -12026,14 +12140,11 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, + bool uav) + { + enum hlsl_regset regset = uav ? HLSL_REGSET_UAVS : HLSL_REGSET_TEXTURES; +- struct vkd3d_shader_structured_resource *structured_resource; +- struct vkd3d_shader_dst_param *dst_param; +- struct vkd3d_shader_semantic *semantic; + struct vkd3d_shader_instruction *ins; + struct hlsl_type *component_type; + enum vkd3d_shader_opcode opcode; + bool multisampled; +- unsigned int i, j; ++ unsigned int i; + + VKD3D_ASSERT(resource->regset == regset); + VKD3D_ASSERT(hlsl_version_lt(ctx, 5, 1) || resource->bind_count == 1); +@@ -12044,6 +12155,7 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, + { + unsigned int array_first = resource->index + i; + unsigned int array_last = resource->index + i; /* FIXME: array end. */ ++ struct vkd3d_shader_resource *vsir_resource; + + if (resource->var && !resource->var->objects_usage[regset][i].used) + continue; +@@ -12053,13 +12165,13 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, switch (component_type->sampler_dim) { case HLSL_SAMPLER_DIM_STRUCTURED_BUFFER: @@ -4307,7 +9716,7 @@ index 04bb2d98b26..afd6169514f 100644 break; } } -@@ -12199,10 +12180,10 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, +@@ -12068,10 +12180,10 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, switch (component_type->sampler_dim) { case HLSL_SAMPLER_DIM_RAW_BUFFER: @@ -4320,17 +9729,113 @@ index 04bb2d98b26..afd6169514f 100644 break; } } -@@ -12272,7 +12253,7 @@ static void sm4_generate_vsir_add_dcl_stream(struct hlsl_ctx *ctx, - { - struct vkd3d_shader_instruction *ins; +@@ -12081,13 +12193,16 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + return; + } +- semantic = &ins->declaration.semantic; +- structured_resource = &ins->declaration.structured_resource; +- dst_param = &semantic->resource.reg; +- vsir_dst_param_init(dst_param, uav ? VKD3DSPR_UAV : VKD3DSPR_RESOURCE, VKD3D_DATA_UNUSED, 0); -- if (!(ins = generate_vsir_add_program_instruction(ctx, program, &var->loc, VKD3DSIH_DCL_STREAM, 0, 1))) +- if (uav && component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) +- structured_resource->byte_stride = 4 * component_type->e.resource.format->reg_size[HLSL_REGSET_NUMERIC]; ++ if (component_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) ++ vsir_resource = &ins->declaration.raw_resource.resource; ++ else if (component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) ++ vsir_resource = &ins->declaration.structured_resource.resource; ++ else ++ vsir_resource = &ins->declaration.semantic.resource; ++ ++ vsir_dst_param_init(&vsir_resource->reg, uav ? VKD3DSPR_UAV : VKD3DSPR_RESOURCE, VKD3D_DATA_UNUSED, 0); ++ + if (uav && component_type->e.resource.rasteriser_ordered) + ins->flags = VKD3DSUF_RASTERISER_ORDERED_VIEW; + +@@ -12101,30 +12216,52 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, + ctx->profile->major_version, ctx->profile->minor_version); + } + +- for (j = 0; j < 4; ++j) +- semantic->resource_data_type[j] = sm4_generate_vsir_get_format_type(component_type); +- +- semantic->resource.range.first = array_first; +- semantic->resource.range.last = array_last; +- semantic->resource.range.space = resource->space; ++ vsir_resource->range.first = array_first; ++ vsir_resource->range.last = array_last; ++ vsir_resource->range.space = resource->space; + +- dst_param->reg.idx[0].offset = resource->id; +- dst_param->reg.idx[1].offset = array_first; +- dst_param->reg.idx[2].offset = array_last; +- dst_param->reg.idx_count = 3; ++ vsir_resource->reg.reg.idx[0].offset = resource->id; ++ vsir_resource->reg.reg.idx[1].offset = array_first; ++ vsir_resource->reg.reg.idx[2].offset = array_last; ++ vsir_resource->reg.reg.idx_count = 3; + + ins->resource_type = sm4_generate_vsir_get_resource_type(resource->component_type); +- if (resource->component_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) ++ ++ if (component_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) ++ { + ins->raw = true; +- if (resource->component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) ++ } ++ else if (component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) + { + ins->structured = true; + ins->resource_stride = 4 * component_type->e.resource.format->reg_size[HLSL_REGSET_NUMERIC]; ++ ins->declaration.structured_resource.byte_stride = ins->resource_stride; ++ } ++ else ++ { ++ for (unsigned int j = 0; j < 4; ++j) ++ ins->declaration.semantic.resource_data_type[j] = sm4_generate_vsir_get_format_type(component_type); ++ ++ if (multisampled) ++ ins->declaration.semantic.sample_count = component_type->sample_count; + } ++ } ++} ++ ++static void sm4_generate_vsir_add_dcl_stream(struct hlsl_ctx *ctx, ++ struct vsir_program *program, const struct hlsl_ir_var *var) ++{ ++ struct vkd3d_shader_instruction *ins; + +- if (multisampled) +- semantic->sample_count = component_type->sample_count; + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &var->loc, VSIR_OP_DCL_STREAM, 0, 1))) - { - ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; - return; -@@ -12372,12 +12353,12 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl ++ { ++ ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; ++ return; + } ++ ++ vsir_src_param_init(&ins->src[0], VKD3DSPR_STREAM, VKD3D_DATA_OPAQUE, 1); ++ ins->src[0].reg.dimension = VSIR_DIMENSION_NONE; ++ ins->src[0].reg.idx[0].offset = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; + } + /* OBJECTIVE: Translate all the information from ctx and entry_func to the +@@ -12201,19 +12338,34 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl + } + sm4_free_extern_resources(extern_resources, extern_resources_count); + ++ if (version.type == VKD3D_SHADER_TYPE_GEOMETRY && version.major >= 5) ++ { ++ const struct hlsl_ir_var *var; ++ ++ LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) ++ { ++ if (var->bind_count[HLSL_REGSET_STREAM_OUTPUTS]) ++ sm4_generate_vsir_add_dcl_stream(ctx, program, var); ++ } ++ } ++ ++ program->ssa_count = 0; ++ if (version.type == VKD3D_SHADER_TYPE_HULL) generate_vsir_add_program_instruction(ctx, program, - &ctx->patch_constant_func->loc, VKD3DSIH_HS_CONTROL_POINT_PHASE, 0, 0); @@ -4344,343 +9849,110 @@ index 04bb2d98b26..afd6169514f 100644 sm4_generate_vsir_add_function(ctx, ctx->patch_constant_func, config_flags, program); } + generate_vsir_scan_required_features(ctx, program); + generate_vsir_scan_global_flags(ctx, program, func); ++ ++ program->ssa_count = ctx->ssa_count; + } + + /* For some reason, for matrices, values from default value initializers end +@@ -13401,6 +13553,19 @@ static void process_entry_function(struct hlsl_ctx *ctx, + lower_ir(ctx, lower_matrix_swizzles, body); + lower_ir(ctx, lower_index_loads, body); + ++ if (entry_func->return_var) ++ { ++ if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY) ++ hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, ++ "Geometry shaders cannot return values."); ++ else if (entry_func->return_var->data_type->class != HLSL_CLASS_STRUCT ++ && !entry_func->return_var->semantic.name) ++ hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, ++ "Entry point \"%s\" is missing a return value semantic.", entry_func->func->name); ++ ++ append_output_var_copy(ctx, entry_func, entry_func->return_var); ++ } ++ + for (i = 0; i < entry_func->parameters.count; ++i) + { + var = entry_func->parameters.vars[i]; +@@ -13505,25 +13670,35 @@ static void process_entry_function(struct hlsl_ctx *ctx, + } + } + } ++ + if (entry_func->return_var) + { +- if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY) +- hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, +- "Geometry shaders cannot return values."); +- else if (entry_func->return_var->data_type->class != HLSL_CLASS_STRUCT +- && !entry_func->return_var->semantic.name) +- hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, +- "Entry point \"%s\" is missing a return value semantic.", entry_func->func->name); +- +- append_output_var_copy(ctx, entry_func, entry_func->return_var); +- + if (profile->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func) + ctx->output_control_point_type = entry_func->return_var->data_type; + } + else + { + if (profile->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func) +- hlsl_fixme(ctx, &entry_func->loc, "Passthrough hull shader control point function."); ++ { ++ if (!ctx->input_control_point_type) ++ { ++ hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_INPUT_PATCH, ++ "Pass-through control point function \"%s\" is missing an InputPatch parameter.", ++ entry_func->func->name); ++ } ++ else if (ctx->output_control_point_count ++ && ctx->output_control_point_count != ctx->input_control_point_count) ++ { ++ hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, ++ "Output control point count %u does not match the input control point count %u.", ++ ctx->output_control_point_count, ctx->input_control_point_count); ++ } ++ else ++ { ++ ctx->output_control_point_type = ctx->input_control_point_type; ++ ctx->output_control_point_count = ctx->input_control_point_count; ++ } ++ } + } + + if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY && ctx->input_primitive_type == VKD3D_PT_UNDEFINED) +@@ -13741,6 +13916,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry + return ctx->result; + } + ++ vsir_program_trace(&program); ++ + result = d3dbc_compile(&program, config_flags, NULL, &ctab, out, ctx->message_context); + vsir_program_cleanup(&program); + vkd3d_shader_free_shader_code(&ctab); +@@ -13766,6 +13943,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry + return ctx->result; + } + ++ vsir_program_trace(&program); ++ + result = tpf_compile(&program, config_flags, &rdef, out, ctx->message_context); + vsir_program_cleanup(&program); + vkd3d_shader_free_shader_code(&rdef); diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index c26077e43d9..9b44925888b 100644 +index 7466f7a2da1..fe7e8c54dfb 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -33,335 +33,338 @@ const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) - { - static const char * const names[] = - { -- [VKD3DSIH_ABS ] = "abs", -- [VKD3DSIH_ACOS ] = "acos", -- [VKD3DSIH_ADD ] = "add", -- [VKD3DSIH_AND ] = "and", -- [VKD3DSIH_ASIN ] = "asin", -- [VKD3DSIH_ATAN ] = "atan", -- [VKD3DSIH_ATOMIC_AND ] = "atomic_and", -- [VKD3DSIH_ATOMIC_CMP_STORE ] = "atomic_cmp_store", -- [VKD3DSIH_ATOMIC_IADD ] = "atomic_iadd", -- [VKD3DSIH_ATOMIC_IMAX ] = "atomic_imax", -- [VKD3DSIH_ATOMIC_IMIN ] = "atomic_imin", -- [VKD3DSIH_ATOMIC_OR ] = "atomic_or", -- [VKD3DSIH_ATOMIC_UMAX ] = "atomic_umax", -- [VKD3DSIH_ATOMIC_UMIN ] = "atomic_umin", -- [VKD3DSIH_ATOMIC_XOR ] = "atomic_xor", -- [VKD3DSIH_BEM ] = "bem", -- [VKD3DSIH_BFI ] = "bfi", -- [VKD3DSIH_BFREV ] = "bfrev", -- [VKD3DSIH_BRANCH ] = "branch", -- [VKD3DSIH_BREAK ] = "break", -- [VKD3DSIH_BREAKC ] = "break", -- [VKD3DSIH_BREAKP ] = "breakp", -- [VKD3DSIH_BUFINFO ] = "bufinfo", -- [VKD3DSIH_CALL ] = "call", -- [VKD3DSIH_CALLNZ ] = "callnz", -- [VKD3DSIH_CASE ] = "case", -- [VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED ] = "check_access_fully_mapped", -- [VKD3DSIH_CMP ] = "cmp", -- [VKD3DSIH_CND ] = "cnd", -- [VKD3DSIH_COS ] = "cos", -- [VKD3DSIH_CONTINUE ] = "continue", -- [VKD3DSIH_CONTINUEP ] = "continuec", -- [VKD3DSIH_COUNTBITS ] = "countbits", -- [VKD3DSIH_CRS ] = "crs", -- [VKD3DSIH_CUT ] = "cut", -- [VKD3DSIH_CUT_STREAM ] = "cut_stream", -- [VKD3DSIH_DADD ] = "dadd", -- [VKD3DSIH_DCL ] = "dcl", -- [VKD3DSIH_DCL_CONSTANT_BUFFER ] = "dcl_constantBuffer", -- [VKD3DSIH_DCL_FUNCTION_BODY ] = "dcl_function_body", -- [VKD3DSIH_DCL_FUNCTION_TABLE ] = "dcl_function_table", -- [VKD3DSIH_DCL_GLOBAL_FLAGS ] = "dcl_globalFlags", -- [VKD3DSIH_DCL_GS_INSTANCES ] = "dcl_gs_instances", -- [VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT] = "dcl_hs_fork_phase_instance_count", -- [VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT] = "dcl_hs_join_phase_instance_count", -- [VKD3DSIH_DCL_HS_MAX_TESSFACTOR ] = "dcl_hs_max_tessfactor", -- [VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER ] = "dcl_immediateConstantBuffer", -- [VKD3DSIH_DCL_INDEX_RANGE ] = "dcl_index_range", -- [VKD3DSIH_DCL_INDEXABLE_TEMP ] = "dcl_indexableTemp", -- [VKD3DSIH_DCL_INPUT ] = "dcl_input", -- [VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT ] = "dcl_input_control_point_count", -- [VKD3DSIH_DCL_INPUT_PRIMITIVE ] = "dcl_inputprimitive", -- [VKD3DSIH_DCL_INPUT_PS ] = "dcl_input_ps", -- [VKD3DSIH_DCL_INPUT_PS_SGV ] = "dcl_input_ps_sgv", -- [VKD3DSIH_DCL_INPUT_PS_SIV ] = "dcl_input_ps_siv", -- [VKD3DSIH_DCL_INPUT_SGV ] = "dcl_input_sgv", -- [VKD3DSIH_DCL_INPUT_SIV ] = "dcl_input_siv", -- [VKD3DSIH_DCL_INTERFACE ] = "dcl_interface", -- [VKD3DSIH_DCL_OUTPUT ] = "dcl_output", -- [VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT ] = "dcl_output_control_point_count", -- [VKD3DSIH_DCL_OUTPUT_SGV ] = "dcl_output_sgv", -- [VKD3DSIH_DCL_OUTPUT_SIV ] = "dcl_output_siv", -- [VKD3DSIH_DCL_OUTPUT_TOPOLOGY ] = "dcl_outputtopology", -- [VKD3DSIH_DCL_RESOURCE_RAW ] = "dcl_resource_raw", -- [VKD3DSIH_DCL_RESOURCE_STRUCTURED ] = "dcl_resource_structured", -- [VKD3DSIH_DCL_SAMPLER ] = "dcl_sampler", -- [VKD3DSIH_DCL_STREAM ] = "dcl_stream", -- [VKD3DSIH_DCL_TEMPS ] = "dcl_temps", -- [VKD3DSIH_DCL_TESSELLATOR_DOMAIN ] = "dcl_tessellator_domain", -- [VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE] = "dcl_tessellator_output_primitive", -- [VKD3DSIH_DCL_TESSELLATOR_PARTITIONING ] = "dcl_tessellator_partitioning", -- [VKD3DSIH_DCL_TGSM_RAW ] = "dcl_tgsm_raw", -- [VKD3DSIH_DCL_TGSM_STRUCTURED ] = "dcl_tgsm_structured", -- [VKD3DSIH_DCL_THREAD_GROUP ] = "dcl_thread_group", -- [VKD3DSIH_DCL_UAV_RAW ] = "dcl_uav_raw", -- [VKD3DSIH_DCL_UAV_STRUCTURED ] = "dcl_uav_structured", -- [VKD3DSIH_DCL_UAV_TYPED ] = "dcl_uav_typed", -- [VKD3DSIH_DCL_VERTICES_OUT ] = "dcl_maxout", -- [VKD3DSIH_DDIV ] = "ddiv", -- [VKD3DSIH_DEF ] = "def", -- [VKD3DSIH_DEFAULT ] = "default", -- [VKD3DSIH_DEFB ] = "defb", -- [VKD3DSIH_DEFI ] = "defi", -- [VKD3DSIH_DEQO ] = "deq", -- [VKD3DSIH_DFMA ] = "dfma", -- [VKD3DSIH_DGEO ] = "dge", -- [VKD3DSIH_DISCARD ] = "discard", -- [VKD3DSIH_DIV ] = "div", -- [VKD3DSIH_DLT ] = "dlt", -- [VKD3DSIH_DMAX ] = "dmax", -- [VKD3DSIH_DMIN ] = "dmin", -- [VKD3DSIH_DMOV ] = "dmov", -- [VKD3DSIH_DMOVC ] = "dmovc", -- [VKD3DSIH_DMUL ] = "dmul", -- [VKD3DSIH_DNE ] = "dne", -- [VKD3DSIH_DP2 ] = "dp2", -- [VKD3DSIH_DP2ADD ] = "dp2add", -- [VKD3DSIH_DP3 ] = "dp3", -- [VKD3DSIH_DP4 ] = "dp4", -- [VKD3DSIH_DRCP ] = "drcp", -- [VKD3DSIH_DST ] = "dst", -- [VKD3DSIH_DSX ] = "dsx", -- [VKD3DSIH_DSX_COARSE ] = "deriv_rtx_coarse", -- [VKD3DSIH_DSX_FINE ] = "deriv_rtx_fine", -- [VKD3DSIH_DSY ] = "dsy", -- [VKD3DSIH_DSY_COARSE ] = "deriv_rty_coarse", -- [VKD3DSIH_DSY_FINE ] = "deriv_rty_fine", -- [VKD3DSIH_DTOF ] = "dtof", -- [VKD3DSIH_DTOI ] = "dtoi", -- [VKD3DSIH_DTOU ] = "dtou", -- [VKD3DSIH_ELSE ] = "else", -- [VKD3DSIH_EMIT ] = "emit", -- [VKD3DSIH_EMIT_STREAM ] = "emit_stream", -- [VKD3DSIH_ENDIF ] = "endif", -- [VKD3DSIH_ENDLOOP ] = "endloop", -- [VKD3DSIH_ENDREP ] = "endrep", -- [VKD3DSIH_ENDSWITCH ] = "endswitch", -- [VKD3DSIH_EQO ] = "eq", -- [VKD3DSIH_EQU ] = "eq_unord", -- [VKD3DSIH_EVAL_CENTROID ] = "eval_centroid", -- [VKD3DSIH_EVAL_SAMPLE_INDEX ] = "eval_sample_index", -- [VKD3DSIH_EXP ] = "exp", -- [VKD3DSIH_EXPP ] = "expp", -- [VKD3DSIH_F16TOF32 ] = "f16tof32", -- [VKD3DSIH_F32TOF16 ] = "f32tof16", -- [VKD3DSIH_FCALL ] = "fcall", -- [VKD3DSIH_FIRSTBIT_HI ] = "firstbit_hi", -- [VKD3DSIH_FIRSTBIT_LO ] = "firstbit_lo", -- [VKD3DSIH_FIRSTBIT_SHI ] = "firstbit_shi", -- [VKD3DSIH_FRC ] = "frc", -- [VKD3DSIH_FREM ] = "frem", -- [VKD3DSIH_FTOD ] = "ftod", -- [VKD3DSIH_FTOI ] = "ftoi", -- [VKD3DSIH_FTOU ] = "ftou", -- [VKD3DSIH_GATHER4 ] = "gather4", -- [VKD3DSIH_GATHER4_C ] = "gather4_c", -- [VKD3DSIH_GATHER4_C_S ] = "gather4_c_s", -- [VKD3DSIH_GATHER4_PO ] = "gather4_po", -- [VKD3DSIH_GATHER4_PO_C ] = "gather4_po_c", -- [VKD3DSIH_GATHER4_PO_C_S ] = "gather4_po_c_s", -- [VKD3DSIH_GATHER4_PO_S ] = "gather4_po_s", -- [VKD3DSIH_GATHER4_S ] = "gather4_s", -- [VKD3DSIH_GEO ] = "ge", -- [VKD3DSIH_GEU ] = "ge_unord", -- [VKD3DSIH_HCOS ] = "hcos", -- [VKD3DSIH_HS_CONTROL_POINT_PHASE ] = "hs_control_point_phase", -- [VKD3DSIH_HS_DECLS ] = "hs_decls", -- [VKD3DSIH_HS_FORK_PHASE ] = "hs_fork_phase", -- [VKD3DSIH_HS_JOIN_PHASE ] = "hs_join_phase", -- [VKD3DSIH_HSIN ] = "hsin", -- [VKD3DSIH_HTAN ] = "htan", -- [VKD3DSIH_IADD ] = "iadd", -- [VKD3DSIH_IBFE ] = "ibfe", -- [VKD3DSIH_IDIV ] = "idiv", -- [VKD3DSIH_IEQ ] = "ieq", -- [VKD3DSIH_IF ] = "if", -- [VKD3DSIH_IFC ] = "if", -- [VKD3DSIH_IGE ] = "ige", -- [VKD3DSIH_ILT ] = "ilt", -- [VKD3DSIH_IMAD ] = "imad", -- [VKD3DSIH_IMAX ] = "imax", -- [VKD3DSIH_IMIN ] = "imin", -- [VKD3DSIH_IMM_ATOMIC_ALLOC ] = "imm_atomic_alloc", -- [VKD3DSIH_IMM_ATOMIC_AND ] = "imm_atomic_and", -- [VKD3DSIH_IMM_ATOMIC_CMP_EXCH ] = "imm_atomic_cmp_exch", -- [VKD3DSIH_IMM_ATOMIC_CONSUME ] = "imm_atomic_consume", -- [VKD3DSIH_IMM_ATOMIC_EXCH ] = "imm_atomic_exch", -- [VKD3DSIH_IMM_ATOMIC_IADD ] = "imm_atomic_iadd", -- [VKD3DSIH_IMM_ATOMIC_IMAX ] = "imm_atomic_imax", -- [VKD3DSIH_IMM_ATOMIC_IMIN ] = "imm_atomic_imin", -- [VKD3DSIH_IMM_ATOMIC_OR ] = "imm_atomic_or", -- [VKD3DSIH_IMM_ATOMIC_UMAX ] = "imm_atomic_umax", -- [VKD3DSIH_IMM_ATOMIC_UMIN ] = "imm_atomic_umin", -- [VKD3DSIH_IMM_ATOMIC_XOR ] = "imm_atomic_xor", -- [VKD3DSIH_IMUL ] = "imul", -- [VKD3DSIH_IMUL_LOW ] = "imul_low", -- [VKD3DSIH_INE ] = "ine", -- [VKD3DSIH_INEG ] = "ineg", -- [VKD3DSIH_ISFINITE ] = "isfinite", -- [VKD3DSIH_ISHL ] = "ishl", -- [VKD3DSIH_ISHR ] = "ishr", -- [VKD3DSIH_ISINF ] = "isinf", -- [VKD3DSIH_ISNAN ] = "isnan", -- [VKD3DSIH_ITOD ] = "itod", -- [VKD3DSIH_ITOF ] = "itof", -- [VKD3DSIH_ITOI ] = "itoi", -- [VKD3DSIH_LABEL ] = "label", -- [VKD3DSIH_LD ] = "ld", -- [VKD3DSIH_LD2DMS ] = "ld2dms", -- [VKD3DSIH_LD2DMS_S ] = "ld2dms_s", -- [VKD3DSIH_LD_RAW ] = "ld_raw", -- [VKD3DSIH_LD_RAW_S ] = "ld_raw_s", -- [VKD3DSIH_LD_S ] = "ld_s", -- [VKD3DSIH_LD_STRUCTURED ] = "ld_structured", -- [VKD3DSIH_LD_STRUCTURED_S ] = "ld_structured_s", -- [VKD3DSIH_LD_UAV_TYPED ] = "ld_uav_typed", -- [VKD3DSIH_LD_UAV_TYPED_S ] = "ld_uav_typed_s", -- [VKD3DSIH_LIT ] = "lit", -- [VKD3DSIH_LOD ] = "lod", -- [VKD3DSIH_LOG ] = "log", -- [VKD3DSIH_LOGP ] = "logp", -- [VKD3DSIH_LOOP ] = "loop", -- [VKD3DSIH_LRP ] = "lrp", -- [VKD3DSIH_LTO ] = "lt", -- [VKD3DSIH_LTU ] = "lt_unord", -- [VKD3DSIH_M3x2 ] = "m3x2", -- [VKD3DSIH_M3x3 ] = "m3x3", -- [VKD3DSIH_M3x4 ] = "m3x4", -- [VKD3DSIH_M4x3 ] = "m4x3", -- [VKD3DSIH_M4x4 ] = "m4x4", -- [VKD3DSIH_MAD ] = "mad", -- [VKD3DSIH_MAX ] = "max", -- [VKD3DSIH_MIN ] = "min", -- [VKD3DSIH_MOV ] = "mov", -- [VKD3DSIH_MOVA ] = "mova", -- [VKD3DSIH_MOVC ] = "movc", -- [VKD3DSIH_MSAD ] = "msad", -- [VKD3DSIH_MUL ] = "mul", -- [VKD3DSIH_NEO ] = "ne_ord", -- [VKD3DSIH_NEU ] = "ne", -- [VKD3DSIH_NOP ] = "nop", -- [VKD3DSIH_NOT ] = "not", -- [VKD3DSIH_NRM ] = "nrm", -- [VKD3DSIH_OR ] = "or", -- [VKD3DSIH_ORD ] = "ord", -- [VKD3DSIH_PHASE ] = "phase", -- [VKD3DSIH_PHI ] = "phi", -- [VKD3DSIH_POW ] = "pow", -- [VKD3DSIH_QUAD_READ_ACROSS_D ] = "quad_read_across_d", -- [VKD3DSIH_QUAD_READ_ACROSS_X ] = "quad_read_across_x", -- [VKD3DSIH_QUAD_READ_ACROSS_Y ] = "quad_read_across_y", -- [VKD3DSIH_QUAD_READ_LANE_AT ] = "quad_read_lane_at", -- [VKD3DSIH_RCP ] = "rcp", -- [VKD3DSIH_REP ] = "rep", -- [VKD3DSIH_RESINFO ] = "resinfo", -- [VKD3DSIH_RET ] = "ret", -- [VKD3DSIH_RETP ] = "retp", -- [VKD3DSIH_ROUND_NE ] = "round_ne", -- [VKD3DSIH_ROUND_NI ] = "round_ni", -- [VKD3DSIH_ROUND_PI ] = "round_pi", -- [VKD3DSIH_ROUND_Z ] = "round_z", -- [VKD3DSIH_RSQ ] = "rsq", -- [VKD3DSIH_SAMPLE ] = "sample", -- [VKD3DSIH_SAMPLE_B ] = "sample_b", -- [VKD3DSIH_SAMPLE_B_CL_S ] = "sample_b_cl_s", -- [VKD3DSIH_SAMPLE_C ] = "sample_c", -- [VKD3DSIH_SAMPLE_C_CL_S ] = "sample_c_cl_s", -- [VKD3DSIH_SAMPLE_C_LZ ] = "sample_c_lz", -- [VKD3DSIH_SAMPLE_C_LZ_S ] = "sample_c_lz_s", -- [VKD3DSIH_SAMPLE_CL_S ] = "sample_cl_s", -- [VKD3DSIH_SAMPLE_GRAD ] = "sample_d", -- [VKD3DSIH_SAMPLE_GRAD_CL_S ] = "sample_d_cl_s", -- [VKD3DSIH_SAMPLE_INFO ] = "sample_info", -- [VKD3DSIH_SAMPLE_LOD ] = "sample_l", -- [VKD3DSIH_SAMPLE_LOD_S ] = "sample_l_s", -- [VKD3DSIH_SAMPLE_POS ] = "sample_pos", -- [VKD3DSIH_SETP ] = "setp", -- [VKD3DSIH_SGE ] = "sge", -- [VKD3DSIH_SGN ] = "sgn", -- [VKD3DSIH_SIN ] = "sin", -- [VKD3DSIH_SINCOS ] = "sincos", -- [VKD3DSIH_SLT ] = "slt", -- [VKD3DSIH_SQRT ] = "sqrt", -- [VKD3DSIH_STORE_RAW ] = "store_raw", -- [VKD3DSIH_STORE_STRUCTURED ] = "store_structured", -- [VKD3DSIH_STORE_UAV_TYPED ] = "store_uav_typed", -- [VKD3DSIH_SUB ] = "sub", -- [VKD3DSIH_SWAPC ] = "swapc", -- [VKD3DSIH_SWITCH ] = "switch", -- [VKD3DSIH_SWITCH_MONOLITHIC ] = "switch", -- [VKD3DSIH_SYNC ] = "sync", -- [VKD3DSIH_TAN ] = "tan", -- [VKD3DSIH_TEX ] = "tex", -- [VKD3DSIH_TEXBEM ] = "texbem", -- [VKD3DSIH_TEXBEML ] = "texbeml", -- [VKD3DSIH_TEXCOORD ] = "texcoord", -- [VKD3DSIH_TEXCRD ] = "texcrd", -- [VKD3DSIH_TEXDEPTH ] = "texdepth", -- [VKD3DSIH_TEXDP3 ] = "texdp3", -- [VKD3DSIH_TEXDP3TEX ] = "texdp3tex", -- [VKD3DSIH_TEXKILL ] = "texkill", -- [VKD3DSIH_TEXLD ] = "texld", -- [VKD3DSIH_TEXLDD ] = "texldd", -- [VKD3DSIH_TEXLDL ] = "texldl", -- [VKD3DSIH_TEXM3x2DEPTH ] = "texm3x2depth", -- [VKD3DSIH_TEXM3x2PAD ] = "texm3x2pad", -- [VKD3DSIH_TEXM3x2TEX ] = "texm3x2tex", -- [VKD3DSIH_TEXM3x3 ] = "texm3x3", -- [VKD3DSIH_TEXM3x3DIFF ] = "texm3x3diff", -- [VKD3DSIH_TEXM3x3PAD ] = "texm3x3pad", -- [VKD3DSIH_TEXM3x3SPEC ] = "texm3x3spec", -- [VKD3DSIH_TEXM3x3TEX ] = "texm3x3tex", -- [VKD3DSIH_TEXM3x3VSPEC ] = "texm3x3vspec", -- [VKD3DSIH_TEXREG2AR ] = "texreg2ar", -- [VKD3DSIH_TEXREG2GB ] = "texreg2gb", -- [VKD3DSIH_TEXREG2RGB ] = "texreg2rgb", -- [VKD3DSIH_UBFE ] = "ubfe", -- [VKD3DSIH_UDIV ] = "udiv", -- [VKD3DSIH_UGE ] = "uge", -- [VKD3DSIH_ULT ] = "ult", -- [VKD3DSIH_UMAX ] = "umax", -- [VKD3DSIH_UMIN ] = "umin", -- [VKD3DSIH_UMUL ] = "umul", -- [VKD3DSIH_UNO ] = "uno", -- [VKD3DSIH_USHR ] = "ushr", -- [VKD3DSIH_UTOD ] = "utod", -- [VKD3DSIH_UTOF ] = "utof", -- [VKD3DSIH_UTOU ] = "utou", -- [VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL ] = "wave_active_all_equal", -- [VKD3DSIH_WAVE_ACTIVE_BALLOT ] = "wave_active_ballot", -- [VKD3DSIH_WAVE_ACTIVE_BIT_AND ] = "wave_active_bit_and", -- [VKD3DSIH_WAVE_ACTIVE_BIT_OR ] = "wave_active_bit_or", -- [VKD3DSIH_WAVE_ACTIVE_BIT_XOR ] = "wave_active_bit_xor", -- [VKD3DSIH_WAVE_ALL_BIT_COUNT ] = "wave_all_bit_count", -- [VKD3DSIH_WAVE_ALL_TRUE ] = "wave_all_true", -- [VKD3DSIH_WAVE_ANY_TRUE ] = "wave_any_true", -- [VKD3DSIH_WAVE_IS_FIRST_LANE ] = "wave_is_first_lane", -- [VKD3DSIH_WAVE_OP_ADD ] = "wave_op_add", -- [VKD3DSIH_WAVE_OP_IMAX ] = "wave_op_imax", -- [VKD3DSIH_WAVE_OP_IMIN ] = "wave_op_imin", -- [VKD3DSIH_WAVE_OP_MAX ] = "wave_op_max", -- [VKD3DSIH_WAVE_OP_MIN ] = "wave_op_min", -- [VKD3DSIH_WAVE_OP_MUL ] = "wave_op_mul", -- [VKD3DSIH_WAVE_OP_UMAX ] = "wave_op_umax", -- [VKD3DSIH_WAVE_OP_UMIN ] = "wave_op_umin", -- [VKD3DSIH_WAVE_PREFIX_BIT_COUNT ] = "wave_prefix_bit_count", -- [VKD3DSIH_WAVE_READ_LANE_AT ] = "wave_read_lane_at", -- [VKD3DSIH_WAVE_READ_LANE_FIRST ] = "wave_read_lane_first", -- [VKD3DSIH_XOR ] = "xor", +@@ -29,6 +29,350 @@ struct vsir_transformation_context + struct vkd3d_shader_message_context *message_context; + }; + ++const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) ++{ ++ static const char * const names[] = ++ { + [VSIR_OP_ABS ] = "abs", + [VSIR_OP_ACOS ] = "acos", + [VSIR_OP_ADD ] = "add", @@ -5013,19 +10285,81 @@ index c26077e43d9..9b44925888b 100644 + [VSIR_OP_WAVE_READ_LANE_AT ] = "wave_read_lane_at", + [VSIR_OP_WAVE_READ_LANE_FIRST ] = "wave_read_lane_first", + [VSIR_OP_XOR ] = "xor", - }; ++ }; ++ ++ if ((uint32_t)op < ARRAY_SIZE(names)) ++ return names[op] ? names[op] : error; ++ ++ return error; ++} ++ + static int convert_parameter_info(const struct vkd3d_shader_compile_info *compile_info, + unsigned int *ret_count, const struct vkd3d_shader_parameter1 **ret_parameters) + { +@@ -163,6 +507,53 @@ bool vsir_signature_find_sysval(const struct shader_signature *signature, + return false; + } - if ((uint32_t)op < ARRAY_SIZE(names)) -@@ -637,11 +640,23 @@ static void vsir_src_param_init_sampler(struct vkd3d_shader_src_param *src, unsi ++const char *debug_vsir_writemask(unsigned int writemask) ++{ ++ static const char components[] = {'x', 'y', 'z', 'w'}; ++ char string[5]; ++ unsigned int i = 0, pos = 0; ++ ++ VKD3D_ASSERT(!(writemask & ~VKD3DSP_WRITEMASK_ALL)); ++ ++ while (writemask) ++ { ++ if (writemask & 1) ++ string[pos++] = components[i]; ++ writemask >>= 1; ++ i++; ++ } ++ string[pos] = '\0'; ++ return vkd3d_dbg_sprintf(".%s", string); ++} ++ ++static unsigned int vsir_combine_write_masks(unsigned int first, unsigned int second) ++{ ++ unsigned int ret = 0, j = 0; ++ ++ for (unsigned int i = 0; i < VKD3D_VEC4_SIZE; ++i) ++ { ++ if (first & (1u << i)) ++ { ++ if (second & (1u << j++)) ++ ret |= (1u << i); ++ } ++ } ++ ++ return ret; ++} ++ ++static uint32_t vsir_combine_swizzles(uint32_t first, uint32_t second) ++{ ++ uint32_t ret = 0; ++ ++ for (unsigned int i = 0; i < VKD3D_VEC4_SIZE; ++i) ++ { ++ unsigned int s = vsir_swizzle_get_component(second, i); ++ vsir_swizzle_set_component(&ret, i, vsir_swizzle_get_component(first, s)); ++ } ++ return ret; ++} ++ + void vsir_register_init(struct vkd3d_shader_register *reg, enum vkd3d_shader_register_type reg_type, + enum vkd3d_data_type data_type, unsigned int idx_count) + { +@@ -249,24 +640,38 @@ static void vsir_src_param_init_sampler(struct vkd3d_shader_src_param *src, unsi src->reg.dimension = VSIR_DIMENSION_NONE; } --static void src_param_init_ssa_scalar(struct vkd3d_shader_src_param *src, unsigned int idx, -- enum vkd3d_data_type data_type) +-static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned int idx) +static void src_param_init_ssa(struct vkd3d_shader_src_param *src, unsigned int idx, + enum vkd3d_data_type data_type, enum vsir_dimension dimension) { - vsir_src_param_init(src, VKD3DSPR_SSA, data_type, 1); +- vsir_src_param_init(src, VKD3DSPR_SSA, VKD3D_DATA_BOOL, 1); ++ vsir_src_param_init(src, VKD3DSPR_SSA, data_type, 1); src->reg.idx[0].offset = idx; + + if (dimension == VSIR_DIMENSION_VEC4) @@ -5039,39 +10373,40 @@ index c26077e43d9..9b44925888b 100644 + enum vkd3d_data_type data_type) +{ + src_param_init_ssa(src, idx, data_type, VSIR_DIMENSION_SCALAR); ++} ++ ++static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned int idx) ++{ ++ src_param_init_ssa_scalar(src, idx, VKD3D_DATA_BOOL); } - static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned int idx) -@@ -654,18 +669,9 @@ static void src_param_init_ssa_float(struct vkd3d_shader_src_param *src, unsigne - src_param_init_ssa_scalar(src, idx, VKD3D_DATA_FLOAT); + static void src_param_init_ssa_float(struct vkd3d_shader_src_param *src, unsigned int idx) + { +- vsir_src_param_init(src, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1); +- src->reg.idx[0].offset = idx; ++ src_param_init_ssa_scalar(src, idx, VKD3D_DATA_FLOAT); } --static void src_param_init_ssa_vec4(struct vkd3d_shader_src_param *src, unsigned int idx, -- enum vkd3d_data_type data_type) --{ -- vsir_src_param_init(src, VKD3DSPR_SSA, data_type, 1); + static void src_param_init_ssa_float4(struct vkd3d_shader_src_param *src, unsigned int idx) + { +- vsir_src_param_init(src, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1); - src->reg.idx[0].offset = idx; - src->reg.dimension = VSIR_DIMENSION_VEC4; - src->swizzle = VKD3D_SHADER_NO_SWIZZLE; --} -- - static void src_param_init_ssa_float4(struct vkd3d_shader_src_param *src, unsigned int idx) - { -- src_param_init_ssa_vec4(src, idx, VKD3D_DATA_FLOAT); + src_param_init_ssa(src, idx, VKD3D_DATA_FLOAT, VSIR_DIMENSION_VEC4); } static void src_param_init_temp_bool(struct vkd3d_shader_src_param *src, unsigned int idx) -@@ -718,11 +724,23 @@ void vsir_dst_param_init_null(struct vkd3d_shader_dst_param *dst) +@@ -319,24 +724,38 @@ void vsir_dst_param_init_null(struct vkd3d_shader_dst_param *dst) dst->write_mask = 0; } --static void dst_param_init_ssa_scalar(struct vkd3d_shader_dst_param *dst, unsigned int idx, -- enum vkd3d_data_type data_type) +-static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) +static void dst_param_init_ssa(struct vkd3d_shader_dst_param *dst, unsigned int idx, + enum vkd3d_data_type data_type, enum vsir_dimension dimension) { - vsir_dst_param_init(dst, VKD3DSPR_SSA, data_type, 1); +- vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_BOOL, 1); ++ vsir_dst_param_init(dst, VKD3DSPR_SSA, data_type, 1); dst->reg.idx[0].offset = idx; + + if (dimension == VSIR_DIMENSION_VEC4) @@ -5085,30 +10420,31 @@ index c26077e43d9..9b44925888b 100644 + enum vkd3d_data_type data_type) +{ + dst_param_init_ssa(dst, idx, data_type, VSIR_DIMENSION_SCALAR); ++} ++ ++static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) ++{ ++ dst_param_init_ssa_scalar(dst, idx, VKD3D_DATA_BOOL); } - static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) -@@ -735,18 +753,9 @@ static void dst_param_init_ssa_float(struct vkd3d_shader_dst_param *dst, unsigne - dst_param_init_ssa_scalar(dst, idx, VKD3D_DATA_FLOAT); + static void dst_param_init_ssa_float(struct vkd3d_shader_dst_param *dst, unsigned int idx) + { +- vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1); +- dst->reg.idx[0].offset = idx; ++ dst_param_init_ssa_scalar(dst, idx, VKD3D_DATA_FLOAT); } --static void dst_param_init_ssa_vec4(struct vkd3d_shader_dst_param *dst, unsigned int idx, -- enum vkd3d_data_type data_type) --{ -- vsir_dst_param_init(dst, VKD3DSPR_SSA, data_type, 1); + static void dst_param_init_ssa_float4(struct vkd3d_shader_dst_param *dst, unsigned int idx) + { +- vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1); - dst->reg.idx[0].offset = idx; - dst->reg.dimension = VSIR_DIMENSION_VEC4; - dst->write_mask = VKD3DSP_WRITEMASK_ALL; --} -- - static void dst_param_init_ssa_float4(struct vkd3d_shader_dst_param *dst, unsigned int idx) - { -- dst_param_init_ssa_vec4(dst, idx, VKD3D_DATA_FLOAT); + dst_param_init_ssa(dst, idx, VKD3D_DATA_FLOAT, VSIR_DIMENSION_VEC4); } static void dst_param_init_temp_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) -@@ -820,7 +829,7 @@ static bool vsir_instruction_init_label(struct vkd3d_shader_instruction *ins, +@@ -410,7 +829,7 @@ static bool vsir_instruction_init_label(struct vkd3d_shader_instruction *ins, vsir_src_param_init_label(src_param, label_id); @@ -5117,7 +10453,7 @@ index c26077e43d9..9b44925888b 100644 ins->src = src_param; ins->src_count = 1; -@@ -830,15 +839,15 @@ static bool vsir_instruction_init_label(struct vkd3d_shader_instruction *ins, +@@ -420,15 +839,15 @@ static bool vsir_instruction_init_label(struct vkd3d_shader_instruction *ins, static bool vsir_instruction_is_dcl(const struct vkd3d_shader_instruction *instruction) { enum vkd3d_shader_opcode opcode = instruction->opcode; @@ -5136,7 +10472,7 @@ index c26077e43d9..9b44925888b 100644 } static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_data_type data_type, -@@ -851,7 +860,7 @@ static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_d +@@ -441,7 +860,7 @@ static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_d *requires_swap = (rel_op == VKD3D_SHADER_REL_OP_GT); if (data_type == VKD3D_DATA_FLOAT) { @@ -5145,7 +10481,7 @@ index c26077e43d9..9b44925888b 100644 return true; } break; -@@ -861,7 +870,7 @@ static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_d +@@ -451,7 +870,7 @@ static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_d *requires_swap = (rel_op == VKD3D_SHADER_REL_OP_LE); if (data_type == VKD3D_DATA_FLOAT) { @@ -5154,7 +10490,7 @@ index c26077e43d9..9b44925888b 100644 return true; } break; -@@ -870,7 +879,7 @@ static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_d +@@ -460,7 +879,7 @@ static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_d *requires_swap = false; if (data_type == VKD3D_DATA_FLOAT) { @@ -5163,7 +10499,7 @@ index c26077e43d9..9b44925888b 100644 return true; } break; -@@ -879,7 +888,7 @@ static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_d +@@ -469,7 +888,7 @@ static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_d *requires_swap = false; if (data_type == VKD3D_DATA_FLOAT) { @@ -5172,7 +10508,7 @@ index c26077e43d9..9b44925888b 100644 return true; } break; -@@ -898,17 +907,17 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra +@@ -488,17 +907,17 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra { ins = &program->instructions.elements[i]; @@ -5193,7 +10529,7 @@ index c26077e43d9..9b44925888b 100644 { if (tmp_idx == ~0u) tmp_idx = program->temp_count++; -@@ -918,12 +927,12 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra +@@ -508,12 +927,12 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra ins = &program->instructions.elements[i]; ins2 = &program->instructions.elements[i + 1]; @@ -5208,7 +10544,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; vsir_register_init(&ins2->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); -@@ -1001,7 +1010,7 @@ static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, +@@ -591,7 +1010,7 @@ static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, /* Create new if instruction using the previous result. */ ins = &instructions->elements[pos + 2]; @@ -5217,7 +10553,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ; -@@ -1035,7 +1044,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program +@@ -625,7 +1044,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program /* tmp = ins->src[0] < 0 */ ins = &instructions->elements[pos + 1]; @@ -5226,7 +10562,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); -@@ -1059,7 +1068,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program +@@ -649,7 +1068,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program for (j = 1; j < components_read; ++j) { ins = &instructions->elements[pos + 1 + j]; @@ -5235,7 +10571,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); -@@ -1080,7 +1089,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program +@@ -670,7 +1089,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program /* discard_nz tmp.x */ ins = &instructions->elements[pos + 1 + components_read]; @@ -5244,7 +10580,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ; -@@ -1122,10 +1131,10 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro +@@ -712,10 +1131,10 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro mul_ins = &instructions->elements[pos]; add_ins = &instructions->elements[pos + 1]; @@ -5257,11 +10593,23 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; add_ins->flags = mul_ins->flags & VKD3DSI_PRECISE_XYZW; -@@ -1159,7 +1168,88 @@ static enum vkd3d_result vsir_program_lower_imul(struct vsir_program *program, +@@ -736,55 +1155,236 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro + return VKD3D_OK; + } - imul->dst[0] = imul->dst[1]; - imul->dst_count = 1; -- imul->opcode = VKD3DSIH_IMUL_LOW; ++static enum vkd3d_result vsir_program_lower_imul(struct vsir_program *program, ++ struct vkd3d_shader_instruction *imul, struct vsir_transformation_context *ctx) ++{ ++ if (imul->dst[0].reg.type != VKD3DSPR_NULL) ++ { ++ vkd3d_shader_error(ctx->message_context, &imul->location, ++ VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, ++ "Extended multiplication is not implemented."); ++ return VKD3D_ERROR_NOT_IMPLEMENTED; ++ } ++ ++ imul->dst[0] = imul->dst[1]; ++ imul->dst_count = 1; + imul->opcode = VSIR_OP_IMUL_LOW; + + return VKD3D_OK; @@ -5344,79 +10692,162 @@ index c26077e43d9..9b44925888b 100644 + + vkd3d_shader_instruction_make_nop(udiv); + program->ssa_count += 2; ++ ++ return VKD3D_OK; ++} ++ + static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *program, + struct vkd3d_shader_instruction *sincos) + { + struct vkd3d_shader_instruction_array *instructions = &program->instructions; + size_t pos = sincos - instructions->elements; +- struct vkd3d_shader_instruction *ins; +- unsigned int s; ++ struct vkd3d_shader_instruction *ins, *mov; ++ unsigned int s, count; - return VKD3D_OK; - } -@@ -1182,7 +1272,7 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog +- if (sincos->dst_count != 1) +- return VKD3D_OK; ++ count = 1 + vkd3d_popcount(sincos->dst[0].write_mask & (VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1)); - /* Save the source in a SSA in case a destination collides with the source. */ - mov = ins++; -- if (!(vsir_instruction_init_with_params(program, mov, &sincos->location, VKD3DSIH_MOV, 1, 1))) +- if (!shader_instruction_array_insert_at(instructions, pos + 1, 1)) ++ if (!shader_instruction_array_insert_at(instructions, pos + 1, count)) + return VKD3D_ERROR_OUT_OF_MEMORY; + sincos = &instructions->elements[pos]; + + ins = &instructions->elements[pos + 1]; + +- if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VKD3DSIH_SINCOS, 2, 1))) ++ /* Save the source in a SSA in case a destination collides with the source. */ ++ mov = ins++; + if (!(vsir_instruction_init_with_params(program, mov, &sincos->location, VSIR_OP_MOV, 1, 1))) return VKD3D_ERROR_OUT_OF_MEMORY; - mov->src[0] = sincos->src[0]; -@@ -1195,7 +1285,7 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog +- ins->flags = sincos->flags; ++ mov->src[0] = sincos->src[0]; + +- *ins->src = *sincos->src; + /* Set the source swizzle to replicate the first component. */ + s = vsir_swizzle_get_component(sincos->src->swizzle, 0); +- ins->src->swizzle = vkd3d_shader_create_swizzle(s, s, s, s); ++ mov->src[0].swizzle = vkd3d_shader_create_swizzle(s, s, s, s); ++ ++ dst_param_init_ssa_scalar(&mov->dst[0], program->ssa_count, sincos->src[0].reg.data_type); if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_1) { -- if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VKD3DSIH_SIN, 1, 1))) + if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VSIR_OP_SIN, 1, 1))) - return VKD3D_ERROR_OUT_OF_MEMORY; - - ins->flags = sincos->flags; -@@ -1210,7 +1300,7 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog - - if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_0) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ ins->flags = sincos->flags; ++ ++ src_param_init_ssa_scalar(&ins->src[0], program->ssa_count, sincos->src[0].reg.data_type); ++ + ins->dst[0] = *sincos->dst; + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_1; ++ ++ ++ins; + } +- else ++ ++ if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_0) { -- if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VKD3DSIH_COS, 1, 1))) +- vsir_dst_param_init_null(&ins->dst[0]); + if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VSIR_OP_COS, 1, 1))) - return VKD3D_ERROR_OUT_OF_MEMORY; ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ ins->flags = sincos->flags; ++ ++ src_param_init_ssa_scalar(&ins->src[0], program->ssa_count, sincos->src[0].reg.data_type); ++ ++ ins->dst[0] = *sincos->dst; ++ ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; ++ ++ ++ins; + } - ins->flags = sincos->flags; -@@ -1259,20 +1349,21 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog - - /* Save the source in a SSA in case a destination collides with the source. */ - mov = ins++; -- if (!(vsir_instruction_init_with_params(program, mov, &sincos->location, VKD3DSIH_MOV, 1, 1))) +- if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_0) ++ vkd3d_shader_instruction_make_nop(sincos); ++ ++program->ssa_count; ++ ++ return VKD3D_OK; ++} ++ ++static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *program, ++ struct vkd3d_shader_instruction *sincos, struct vsir_transformation_context *ctx) ++{ ++ struct vkd3d_shader_instruction_array *instructions = &program->instructions; ++ size_t pos = sincos - instructions->elements; ++ struct vkd3d_shader_instruction *ins, *mov; ++ unsigned int count = 1; ++ ++ if (sincos->dst_count != 2) + { +- ins->dst[1] = *sincos->dst; +- ins->dst[1].write_mask = VKD3DSP_WRITEMASK_0; ++ vkd3d_shader_error(ctx->message_context, &sincos->location, ++ VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, ++ "Internal compiler error: invalid destination count %u for SINCOS.", ++ sincos->dst_count); ++ return VKD3D_ERROR; + } +- else ++ ++ if (sincos->dst[0].reg.type != VKD3DSPR_NULL) ++ ++count; ++ if (sincos->dst[1].reg.type != VKD3DSPR_NULL) ++ ++count; ++ ++ if (!shader_instruction_array_insert_at(instructions, pos + 1, count)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ sincos = &instructions->elements[pos]; ++ ++ ins = &instructions->elements[pos + 1]; ++ ++ /* Save the source in a SSA in case a destination collides with the source. */ ++ mov = ins++; + if (!(vsir_instruction_init_with_params(program, mov, &sincos->location, VSIR_OP_MOV, 1, 1))) - return VKD3D_ERROR_OUT_OF_MEMORY; - - mov->src[0] = sincos->src[0]; -- dst_param_init_ssa_vec4(&mov->dst[0], program->ssa_count, sincos->src[0].reg.data_type); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ mov->src[0] = sincos->src[0]; + dst_param_init_ssa(&mov->dst[0], program->ssa_count, sincos->src[0].reg.data_type, sincos->src[0].reg.dimension); - - if (sincos->dst[0].reg.type != VKD3DSPR_NULL) ++ ++ if (sincos->dst[0].reg.type != VKD3DSPR_NULL) { -- if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VKD3DSIH_SIN, 1, 1))) +- vsir_dst_param_init_null(&ins->dst[1]); + if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VSIR_OP_SIN, 1, 1))) - return VKD3D_ERROR_OUT_OF_MEMORY; - - ins->flags = sincos->flags; - -- src_param_init_ssa_vec4(&ins->src[0], program->ssa_count, sincos->src[0].reg.data_type); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ ins->flags = sincos->flags; ++ + src_param_init_ssa(&ins->src[0], program->ssa_count, + sincos->src[0].reg.data_type, sincos->src[0].reg.dimension); - ins->dst[0] = sincos->dst[0]; - - ++ins; -@@ -1280,12 +1371,13 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog - - if (sincos->dst[1].reg.type != VKD3DSPR_NULL) - { -- if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VKD3DSIH_COS, 1, 1))) ++ ins->dst[0] = sincos->dst[0]; ++ ++ ++ins; ++ } ++ ++ if (sincos->dst[1].reg.type != VKD3DSPR_NULL) ++ { + if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VSIR_OP_COS, 1, 1))) - return VKD3D_ERROR_OUT_OF_MEMORY; - - ins->flags = sincos->flags; - -- src_param_init_ssa_vec4(&ins->src[0], program->ssa_count, sincos->src[0].reg.data_type); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ ins->flags = sincos->flags; ++ + src_param_init_ssa(&ins->src[0], program->ssa_count, + sincos->src[0].reg.data_type, sincos->src[0].reg.dimension); - ins->dst[0] = sincos->dst[1]; ++ ins->dst[0] = sincos->dst[1]; ++ ++ ++ins; + } - ++ins; -@@ -1318,7 +1410,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, +- /* Make the original instruction no-op */ + vkd3d_shader_instruction_make_nop(sincos); ++ ++program->ssa_count; + + return VKD3D_OK; + } +@@ -810,7 +1410,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, div_ins = &instructions->elements[pos + 1]; tex_ins = &instructions->elements[pos + 2]; @@ -5425,16 +10856,25 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; vsir_dst_param_init(&div_ins->dst[0], VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); -@@ -1331,7 +1423,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, +@@ -823,7 +1423,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, div_ins->src[1] = tex->src[0]; div_ins->src[1].swizzle = vkd3d_shader_create_swizzle(w_comp, w_comp, w_comp, w_comp); -- if (!vsir_instruction_init_with_params(program, tex_ins, location, VKD3DSIH_TEXLD, 1, 2)) +- if (!vsir_instruction_init_with_params(program, tex_ins, location, VKD3DSIH_TEX, 1, 2)) + if (!vsir_instruction_init_with_params(program, tex_ins, location, VSIR_OP_TEXLD, 1, 2)) return VKD3D_ERROR_OUT_OF_MEMORY; tex_ins->dst[0] = tex->dst[0]; -@@ -1364,7 +1456,7 @@ static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program, +@@ -838,7 +1438,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, + return VKD3D_OK; + } + +-static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, ++static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program, + struct vkd3d_shader_instruction *tex, struct vkd3d_shader_message_context *message_context) + { + unsigned int idx = tex->src[1].reg.idx[0].offset; +@@ -856,7 +1456,7 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, if (!tex->flags) { @@ -5443,7 +10883,7 @@ index c26077e43d9..9b44925888b 100644 tex->src = srcs; tex->src_count = 3; } -@@ -1372,7 +1464,7 @@ static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program, +@@ -864,7 +1464,7 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, { enum vkd3d_shader_swizzle_component w = vsir_swizzle_get_component(srcs[0].swizzle, 3); @@ -5452,7 +10892,7 @@ index c26077e43d9..9b44925888b 100644 tex->src = srcs; tex->src_count = 4; -@@ -1407,7 +1499,7 @@ static enum vkd3d_result vsir_program_lower_texldd(struct vsir_program *program, +@@ -899,7 +1499,7 @@ static enum vkd3d_result vsir_program_lower_texldd(struct vsir_program *program, srcs[3] = texldd->src[2]; srcs[4] = texldd->src[3]; @@ -5461,7 +10901,7 @@ index c26077e43d9..9b44925888b 100644 texldd->src = srcs; texldd->src_count = 5; -@@ -1498,59 +1590,64 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr +@@ -990,57 +1590,77 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr switch (ins->opcode) { @@ -5519,7 +10959,6 @@ index c26077e43d9..9b44925888b 100644 - case VKD3DSIH_DCL_INPUT_PS: - case VKD3DSIH_DCL_INPUT_PS_SGV: - case VKD3DSIH_DCL_INPUT_PS_SIV: -- case VKD3DSIH_DCL_OUTPUT_SGV: - case VKD3DSIH_DCL_OUTPUT_SIV: + case VSIR_OP_DCL_INPUT_SGV: + case VSIR_OP_DCL_INPUT_SIV: @@ -5531,34 +10970,44 @@ index c26077e43d9..9b44925888b 100644 vkd3d_shader_instruction_make_nop(ins); break; -- case VKD3DSIH_IMUL: -- case VKD3DSIH_UMUL: +- case VKD3DSIH_SINCOS: +- if ((ret = vsir_program_lower_sm1_sincos(program, ins)) < 0) + case VSIR_OP_IMUL: + case VSIR_OP_UMUL: - if ((ret = vsir_program_lower_imul(program, ins, ctx)) < 0) - return ret; - break; - -- case VKD3DSIH_SINCOS: -+ case VSIR_OP_UDIV: -+ if ((ret = vsir_program_lower_udiv(program, ins, ctx)) < 0) ++ if ((ret = vsir_program_lower_imul(program, ins, ctx)) < 0) + return ret; + break; + -+ case VSIR_OP_SINCOS: - if (ins->dst_count == 1) - { - if ((ret = vsir_program_lower_sm1_sincos(program, ins)) < 0) -@@ -1563,7 +1660,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr - } ++ case VSIR_OP_UDIV: ++ if ((ret = vsir_program_lower_udiv(program, ins, ctx)) < 0) + return ret; break; -- case VKD3DSIH_TEXLD: +- case VKD3DSIH_TEX: ++ case VSIR_OP_SINCOS: ++ if (ins->dst_count == 1) ++ { ++ if ((ret = vsir_program_lower_sm1_sincos(program, ins)) < 0) ++ return ret; ++ } ++ else ++ { ++ if ((ret = vsir_program_lower_sm4_sincos(program, ins, ctx)) < 0) ++ return ret; ++ } ++ break; ++ + case VSIR_OP_TEXLD: if (ins->flags == VKD3DSI_TEXLD_PROJECT) { if ((ret = vsir_program_lower_texldp(program, ins, &tmp_idx)) < 0) -@@ -1576,29 +1673,29 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr +@@ -1048,36 +1668,37 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr + } + else + { +- if ((ret = vsir_program_lower_tex(program, ins, message_context)) < 0) ++ if ((ret = vsir_program_lower_texld(program, ins, message_context)) < 0) + return ret; } break; @@ -5571,7 +11020,6 @@ index c26077e43d9..9b44925888b 100644 - case VKD3DSIH_TEXBEM: - case VKD3DSIH_TEXBEML: - case VKD3DSIH_TEXCOORD: -- case VKD3DSIH_TEXCRD: - case VKD3DSIH_TEXDEPTH: - case VKD3DSIH_TEXDP3: - case VKD3DSIH_TEXDP3TEX: @@ -5605,9 +11053,58 @@ index c26077e43d9..9b44925888b 100644 + case VSIR_OP_TEXREG2GB: + case VSIR_OP_TEXREG2RGB: vkd3d_shader_error(ctx->message_context, &ins->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, - "Aborting due to unimplemented feature: Combined sampler instruction \"%s\" (%#x).", - vsir_opcode_get_name(ins->opcode, ""), ins->opcode); -@@ -1657,12 +1754,12 @@ static enum vkd3d_result vsir_program_ensure_ret(struct vsir_program *program, +- "Aborting due to unimplemented feature: Combined sampler instruction %#x.", +- ins->opcode); ++ "Aborting due to unimplemented feature: Combined sampler instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(ins->opcode, ""), ins->opcode); + return VKD3D_ERROR_NOT_IMPLEMENTED; + + default: +@@ -1088,43 +1709,6 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr + return VKD3D_OK; + } + +-static void shader_register_eliminate_phase_addressing(struct vkd3d_shader_register *reg, +- unsigned int instance_id) +-{ +- unsigned int i; +- +- for (i = 0; i < reg->idx_count; ++i) +- { +- if (reg->idx[i].rel_addr && shader_register_is_phase_instance_id(®->idx[i].rel_addr->reg)) +- { +- reg->idx[i].rel_addr = NULL; +- reg->idx[i].offset += instance_id; +- } +- } +-} +- +-static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_instruction *ins, +- unsigned int instance_id) +-{ +- struct vkd3d_shader_register *reg; +- unsigned int i; +- +- for (i = 0; i < ins->src_count; ++i) +- { +- reg = (struct vkd3d_shader_register *)&ins->src[i].reg; +- if (shader_register_is_phase_instance_id(reg)) +- { +- vsir_register_init(reg, VKD3DSPR_IMMCONST, reg->data_type, 0); +- reg->u.immconst_u32[0] = instance_id; +- continue; +- } +- shader_register_eliminate_phase_addressing(reg, instance_id); +- } +- +- for (i = 0; i < ins->dst_count; ++i) +- shader_register_eliminate_phase_addressing(&ins->dst[i].reg, instance_id); +-} +- + /* Ensure that the program closes with a ret. sm1 programs do not, by default. + * Many of our IR passes rely on this in order to insert instructions at the + * end of execution. */ +@@ -1133,24 +1717,24 @@ static enum vkd3d_result vsir_program_ensure_ret(struct vsir_program *program, { static const struct vkd3d_shader_location no_loc; if (program->instructions.count @@ -5622,7 +11119,31 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_OK; } -@@ -1733,7 +1830,7 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra +-static bool add_signature_element(struct shader_signature *signature, const char *semantic_name, +- uint32_t semantic_index, uint32_t mask, uint32_t register_index, ++static struct signature_element *add_signature_element(struct shader_signature *signature, ++ const char *semantic_name, uint32_t semantic_index, uint32_t mask, uint32_t register_index, + enum vkd3d_shader_interpolation_mode interpolation_mode) + { + struct signature_element *new_elements, *e; + + if (!(new_elements = vkd3d_realloc(signature->elements, + (signature->element_count + 1) * sizeof(*signature->elements)))) +- return false; ++ return NULL; + signature->elements = new_elements; + e = &signature->elements[signature->element_count++]; + memset(e, 0, sizeof(*e)); +@@ -1164,7 +1748,7 @@ static bool add_signature_element(struct shader_signature *signature, const char + e->register_index = register_index; + e->target_location = register_index; + e->interpolation_mode = interpolation_mode; +- return true; ++ return e; + } + + static enum vkd3d_result vsir_program_add_diffuse_output(struct vsir_program *program, +@@ -1209,7 +1793,7 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra { ins = &program->instructions.elements[i]; @@ -5631,7 +11152,7 @@ index c26077e43d9..9b44925888b 100644 break; } -@@ -1741,7 +1838,7 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra +@@ -1217,7 +1801,7 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra return VKD3D_ERROR_OUT_OF_MEMORY; ins = &program->instructions.elements[i]; @@ -5640,7 +11161,7 @@ index c26077e43d9..9b44925888b 100644 vsir_dst_param_init(&ins->dst[0], VKD3DSPR_ATTROUT, VKD3D_DATA_FLOAT, 1); ins->dst[0].reg.idx[0].offset = 0; ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; -@@ -1953,7 +2050,7 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program +@@ -1429,7 +2013,7 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; struct vkd3d_shader_location loc; @@ -5649,7 +11170,7 @@ index c26077e43d9..9b44925888b 100644 continue; loc = ins->location; -@@ -1965,7 +2062,7 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program +@@ -1441,7 +2025,7 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program { e = &signature->elements[j]; @@ -5658,7 +11179,20 @@ index c26077e43d9..9b44925888b 100644 dst_param_init_output(&ins->dst[0], VKD3D_DATA_FLOAT, e->register_index, e->mask); vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VKD3D_DATA_FLOAT, 0); ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; -@@ -2006,7 +2103,7 @@ struct hull_flattener +@@ -1472,17 +2056,19 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program + + struct hull_flattener + { +- struct vkd3d_shader_instruction_array instructions; ++ struct vsir_program *program; + + unsigned int instance_count; + unsigned int phase_body_idx; + enum vkd3d_shader_opcode phase; + struct vkd3d_shader_location last_ret_location; ++ unsigned int *ssa_map; ++ unsigned int orig_ssa_count; + }; static bool flattener_is_in_fork_or_join_phase(const struct hull_flattener *flattener) { @@ -5667,7 +11201,12 @@ index c26077e43d9..9b44925888b 100644 } struct shader_phase_location -@@ -2030,7 +2127,7 @@ static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normal +@@ -1502,11 +2088,11 @@ struct shader_phase_location_array + static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normaliser, + unsigned int index, struct shader_phase_location_array *locations) + { +- struct vkd3d_shader_instruction *ins = &normaliser->instructions.elements[index]; ++ struct vkd3d_shader_instruction *ins = &normaliser->program->instructions.elements[index]; struct shader_phase_location *loc; bool b; @@ -5676,7 +11215,7 @@ index c26077e43d9..9b44925888b 100644 { b = flattener_is_in_fork_or_join_phase(normaliser); /* Reset the phase info. */ -@@ -2042,21 +2139,21 @@ static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normal +@@ -1518,21 +2104,21 @@ static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normal vkd3d_shader_instruction_make_nop(ins); return; } @@ -5702,31 +11241,175 @@ index c26077e43d9..9b44925888b 100644 { normaliser->last_ret_location = ins->location; vkd3d_shader_instruction_make_nop(ins); -@@ -2133,7 +2230,7 @@ static enum vkd3d_result vsir_program_flatten_hull_shader_phases(struct vsir_pro +@@ -1548,26 +2134,89 @@ static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normal + } + } - instructions = &flattener.instructions; ++static void flattener_fixup_ssa_register(struct hull_flattener *normaliser, ++ struct vkd3d_shader_register *reg, unsigned int instance_id) ++{ ++ unsigned int id; ++ ++ if (!register_is_ssa(reg)) ++ return; ++ ++ /* No need to alter the first copy, they are already not conflicting. */ ++ if (instance_id == 0) ++ return; ++ ++ id = reg->idx[0].offset; ++ VKD3D_ASSERT(id < normaliser->orig_ssa_count); ++ if (normaliser->ssa_map[id] == UINT_MAX) ++ normaliser->ssa_map[id] = normaliser->program->ssa_count++; ++ reg->idx[0].offset = normaliser->ssa_map[id]; ++} ++ ++static void flattener_fixup_register_indices(struct hull_flattener *normaliser, ++ struct vkd3d_shader_register *reg, unsigned int instance_id) ++{ ++ unsigned int i; ++ ++ flattener_fixup_ssa_register(normaliser, reg, instance_id); ++ ++ for (i = 0; i < reg->idx_count; ++i) ++ { ++ if (reg->idx[i].rel_addr) ++ { ++ flattener_fixup_ssa_register(normaliser, ®->idx[i].rel_addr->reg, instance_id); ++ if (shader_register_is_phase_instance_id(®->idx[i].rel_addr->reg)) ++ { ++ reg->idx[i].rel_addr = NULL; ++ reg->idx[i].offset += instance_id; ++ } ++ } ++ } ++} ++ ++static void flattener_fixup_registers(struct hull_flattener *normaliser, ++ struct vkd3d_shader_instruction *ins, unsigned int instance_id) ++{ ++ struct vkd3d_shader_register *reg; ++ unsigned int i; ++ ++ for (i = 0; i < ins->src_count; ++i) ++ { ++ reg = &ins->src[i].reg; ++ if (shader_register_is_phase_instance_id(reg)) ++ { ++ vsir_register_init(reg, VKD3DSPR_IMMCONST, reg->data_type, 0); ++ reg->u.immconst_u32[0] = instance_id; ++ continue; ++ } ++ flattener_fixup_register_indices(normaliser, reg, instance_id); ++ } ++ ++ for (i = 0; i < ins->dst_count; ++i) ++ flattener_fixup_register_indices(normaliser, &ins->dst[i].reg, instance_id); ++} ++ + static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normaliser, + struct shader_phase_location_array *locations) + { ++ struct vkd3d_shader_instruction_array *instructions = &normaliser->program->instructions; + struct shader_phase_location *loc; + unsigned int i, j, k, end, count; + for (i = 0, count = 0; i < locations->count; ++i) + count += (locations->locations[i].instance_count - 1) * locations->locations[i].instruction_count; + +- if (!shader_instruction_array_reserve(&normaliser->instructions, normaliser->instructions.count + count)) ++ if (!shader_instruction_array_reserve(instructions, instructions->count + count)) + return VKD3D_ERROR_OUT_OF_MEMORY; +- end = normaliser->instructions.count; +- normaliser->instructions.count += count; ++ end = instructions->count; ++ instructions->count += count; + + for (i = locations->count; i > 0; --i) + { + loc = &locations->locations[i - 1]; + j = loc->index + loc->instruction_count; +- memmove(&normaliser->instructions.elements[j + count], &normaliser->instructions.elements[j], +- (end - j) * sizeof(*normaliser->instructions.elements)); ++ memmove(&instructions->elements[j + count], &instructions->elements[j], ++ (end - j) * sizeof(*instructions->elements)); + end = j; + count -= (loc->instance_count - 1) * loc->instruction_count; + loc->index += count; +@@ -1581,7 +2230,7 @@ static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normali + { + for (k = 0; k < loc->instruction_count; ++k) + { +- if (!shader_instruction_array_clone_instruction(&normaliser->instructions, ++ if (!shader_instruction_array_clone_instruction(instructions, + loc->index + loc->instruction_count * j + k, loc->index + k)) + return VKD3D_ERROR_OUT_OF_MEMORY; + } +@@ -1589,9 +2238,12 @@ static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normali + /* Replace each reference to the instance id with a constant instance id. */ + for (j = 0; j < loc->instance_count; ++j) + { ++ if (j != 0) ++ memset(normaliser->ssa_map, 0xff, normaliser->orig_ssa_count * sizeof(*normaliser->ssa_map)); ++ + for (k = 0; k < loc->instruction_count; ++k) +- shader_instruction_eliminate_phase_instance_id( +- &normaliser->instructions.elements[loc->index + loc->instruction_count * j + k], j); ++ flattener_fixup_registers(normaliser, ++ &instructions->elements[loc->index + loc->instruction_count * j + k], j); + } + } + +@@ -1601,31 +2253,38 @@ static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normali + static enum vkd3d_result vsir_program_flatten_hull_shader_phases(struct vsir_program *program, + struct vsir_transformation_context *ctx) + { +- struct hull_flattener flattener = {program->instructions}; +- struct vkd3d_shader_instruction_array *instructions; ++ struct vkd3d_shader_instruction_array *instructions = &program->instructions; + struct shader_phase_location_array locations; ++ struct hull_flattener flattener = {program}; + enum vkd3d_result result = VKD3D_OK; + unsigned int i; + +- instructions = &flattener.instructions; +- - flattener.phase = VKD3DSIH_INVALID; + flattener.phase = VSIR_OP_INVALID; for (i = 0, locations.count = 0; i < instructions->count; ++i) flattener_eliminate_phase_related_dcls(&flattener, i, &locations); bitmap_clear(program->io_dcls, VKD3DSPR_FORKINSTID); -@@ -2142,11 +2239,12 @@ static enum vkd3d_result vsir_program_flatten_hull_shader_phases(struct vsir_pro - if ((result = flattener_flatten_phases(&flattener, &locations)) < 0) + bitmap_clear(program->io_dcls, VKD3DSPR_JOININSTID); + +- if ((result = flattener_flatten_phases(&flattener, &locations)) < 0) ++ flattener.orig_ssa_count = program->ssa_count; ++ if (!(flattener.ssa_map = vkd3d_calloc(flattener.orig_ssa_count, sizeof(*flattener.ssa_map)))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ result = flattener_flatten_phases(&flattener, &locations); ++ ++ vkd3d_free(flattener.ssa_map); ++ flattener.ssa_map = NULL; ++ ++ if (result < 0) return result; - if (flattener.phase != VKD3DSIH_INVALID) + if (flattener.phase != VSIR_OP_INVALID) { - if (!shader_instruction_array_reserve(&flattener.instructions, flattener.instructions.count + 1)) +- if (!shader_instruction_array_reserve(&flattener.instructions, flattener.instructions.count + 1)) ++ if (!shader_instruction_array_reserve(instructions, instructions->count + 1)) return VKD3D_ERROR_OUT_OF_MEMORY; - vsir_instruction_init(&instructions->elements[instructions->count++], &flattener.last_ret_location, VKD3DSIH_RET); + vsir_instruction_init(&instructions->elements[instructions->count++], + &flattener.last_ret_location, VSIR_OP_RET); } - program->instructions = flattener.instructions; -@@ -2162,7 +2260,7 @@ struct control_point_normaliser +- program->instructions = flattener.instructions; + return result; + } + +@@ -1638,7 +2297,7 @@ struct control_point_normaliser static bool control_point_normaliser_is_in_control_point_phase(const struct control_point_normaliser *normaliser) { @@ -5735,7 +11418,7 @@ index c26077e43d9..9b44925888b 100644 } struct vkd3d_shader_src_param *vsir_program_create_outpointid_param(struct vsir_program *program) -@@ -2220,7 +2318,7 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p +@@ -1696,7 +2355,7 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p normaliser->instructions.count += count; ins = &normaliser->instructions.elements[dst]; @@ -5744,7 +11427,7 @@ index c26077e43d9..9b44925888b 100644 ++ins; -@@ -2230,7 +2328,7 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p +@@ -1706,7 +2365,7 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p if (!e->used_mask) continue; @@ -5753,7 +11436,7 @@ index c26077e43d9..9b44925888b 100644 ins->dst = shader_dst_param_allocator_get(&normaliser->instructions.dst_params, 1); ins->dst_count = 1; ins->src = shader_src_param_allocator_get(&normaliser->instructions.src_params, 1); -@@ -2257,7 +2355,7 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p +@@ -1733,7 +2392,7 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p ++ins; } @@ -5762,7 +11445,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_OK; } -@@ -2288,7 +2386,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i +@@ -1764,7 +2423,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i } normaliser.instructions = program->instructions; instructions = &normaliser.instructions; @@ -5771,7 +11454,7 @@ index c26077e43d9..9b44925888b 100644 for (i = 0; i < normaliser.instructions.count; ++i) { -@@ -2296,9 +2394,9 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i +@@ -1772,9 +2431,9 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i switch (ins->opcode) { @@ -5784,7 +11467,7 @@ index c26077e43d9..9b44925888b 100644 normaliser.phase = ins->opcode; break; default: -@@ -2310,7 +2408,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i +@@ -1786,7 +2445,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i } } @@ -5793,7 +11476,7 @@ index c26077e43d9..9b44925888b 100644 input_control_point_count = 1; for (i = 0; i < instructions->count; ++i) -@@ -2319,15 +2417,15 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i +@@ -1795,15 +2454,15 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i switch (ins->opcode) { @@ -5813,7 +11496,7 @@ index c26077e43d9..9b44925888b 100644 /* ins may be relocated if the instruction array expands. */ location = ins->location; ret = control_point_normaliser_emit_hs_input(&normaliser, &program->input_signature, -@@ -2359,6 +2457,7 @@ struct io_normaliser_register_data +@@ -1835,6 +2494,7 @@ struct io_normaliser_register_data struct io_normaliser { struct vkd3d_shader_message_context *message_context; @@ -5821,7 +11504,7 @@ index c26077e43d9..9b44925888b 100644 struct vkd3d_shader_instruction_array instructions; enum vkd3d_shader_type shader_type; uint8_t major; -@@ -2385,7 +2484,7 @@ struct io_normaliser +@@ -1861,7 +2521,7 @@ struct io_normaliser static bool io_normaliser_is_in_fork_or_join_phase(const struct io_normaliser *normaliser) { @@ -5830,7 +11513,7 @@ index c26077e43d9..9b44925888b 100644 } static bool shader_signature_find_element_for_reg(const struct shader_signature *signature, -@@ -2862,7 +2961,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par +@@ -2338,7 +2998,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par } static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_param, @@ -5839,7 +11522,7 @@ index c26077e43d9..9b44925888b 100644 { unsigned int i, id_idx, reg_idx, write_mask, element_idx, component_idx; struct vkd3d_shader_register *reg = &src_param->reg; -@@ -2925,7 +3024,12 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par +@@ -2401,7 +3061,12 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par id_idx = reg->idx_count - 1; write_mask = VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(src_param->swizzle, 0); if (!shader_signature_find_element_for_reg(signature, reg_idx, write_mask, &element_idx)) @@ -5853,7 +11536,7 @@ index c26077e43d9..9b44925888b 100644 e = &signature->elements[element_idx]; if ((e->register_count > 1 || vsir_sysval_semantic_is_tess_factor(e->sysval_semantic))) -@@ -2948,9 +3052,9 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi +@@ -2424,9 +3089,9 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi switch (ins->opcode) { @@ -5866,7 +11549,7 @@ index c26077e43d9..9b44925888b 100644 normaliser->phase = ins->opcode; memset(normaliser->input_dcl_params, 0, sizeof(normaliser->input_dcl_params)); memset(normaliser->output_dcl_params, 0, sizeof(normaliser->output_dcl_params)); -@@ -2962,7 +3066,7 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi +@@ -2438,7 +3103,7 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi for (i = 0; i < ins->dst_count; ++i) shader_dst_param_io_normalise(&ins->dst[i], normaliser); for (i = 0; i < ins->src_count; ++i) @@ -5875,7 +11558,7 @@ index c26077e43d9..9b44925888b 100644 break; } } -@@ -2970,14 +3074,14 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi +@@ -2446,14 +3111,14 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program *program, struct vsir_transformation_context *ctx) { @@ -5892,7 +11575,7 @@ index c26077e43d9..9b44925888b 100644 normaliser.shader_type = program->shader_version.type; normaliser.major = program->shader_version.major; normaliser.input_signature = &program->input_signature; -@@ -2990,17 +3094,17 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program +@@ -2466,17 +3131,17 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program switch (ins->opcode) { @@ -5915,7 +11598,7 @@ index c26077e43d9..9b44925888b 100644 normaliser.phase = ins->opcode; break; default: -@@ -3018,14 +3122,14 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program +@@ -2494,14 +3159,14 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program return ret; } @@ -5932,7 +11615,7 @@ index c26077e43d9..9b44925888b 100644 } struct flat_constant_def -@@ -3118,7 +3222,7 @@ static enum vkd3d_result vsir_program_normalise_flat_constants(struct vsir_progr +@@ -2594,7 +3259,7 @@ static enum vkd3d_result vsir_program_normalise_flat_constants(struct vsir_progr { struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; @@ -5941,7 +11624,7 @@ index c26077e43d9..9b44925888b 100644 { struct flat_constant_def *def; -@@ -3160,9 +3264,9 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog +@@ -2636,9 +3301,9 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog switch (ins->opcode) { @@ -5954,7 +11637,7 @@ index c26077e43d9..9b44925888b 100644 if (dead) { vkd3d_shader_instruction_make_nop(ins); -@@ -3170,15 +3274,15 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog +@@ -2646,15 +3311,15 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog } break; @@ -5975,7 +11658,7 @@ index c26077e43d9..9b44925888b 100644 --depth; vkd3d_shader_instruction_make_nop(ins); } -@@ -3193,9 +3297,9 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog +@@ -2669,9 +3334,9 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog * segment began. So it starts at zero and it signals the * termination of the dead code segment when it would * become negative. */ @@ -5988,7 +11671,7 @@ index c26077e43d9..9b44925888b 100644 if (dead) { vkd3d_shader_instruction_make_nop(ins); -@@ -3210,8 +3314,8 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog +@@ -2686,8 +3351,8 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog /* If `case' or `default' appears at zero depth, it means * that they are a possible target for the corresponding * switch, so the code is live again. */ @@ -5999,7 +11682,7 @@ index c26077e43d9..9b44925888b 100644 if (dead) { if (depth == 0) -@@ -3225,9 +3329,9 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog +@@ -2701,9 +3366,9 @@ static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *prog * outside of any block. When a phase returns, control is * moved to the following phase, so they make code live * again. */ @@ -6012,7 +11695,7 @@ index c26077e43d9..9b44925888b 100644 dead = false; break; -@@ -3341,7 +3445,7 @@ static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, +@@ -2817,7 +3482,7 @@ static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, { struct vkd3d_shader_instruction *dst_ins; @@ -6021,7 +11704,7 @@ index c26077e43d9..9b44925888b 100644 return true; if (!(dst_ins = cf_flattener_require_space(flattener, 1))) -@@ -3395,7 +3499,7 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten +@@ -2871,7 +3536,7 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten if (!(ins = cf_flattener_require_space(flattener, 1))) return NULL; @@ -6030,7 +11713,7 @@ index c26077e43d9..9b44925888b 100644 if (condition) { -@@ -3555,9 +3659,9 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3031,9 +3696,9 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte * phase instruction, and in all other shader types begins with the first label instruction. * Declaring an indexable temp with function scope is not considered a declaration, * because it needs to live inside a function. */ @@ -6042,7 +11725,7 @@ index c26077e43d9..9b44925888b 100644 && instruction->declaration.indexable_temp.has_function_scope; if (!vsir_instruction_is_dcl(instruction) || is_function_indexable) -@@ -3572,22 +3676,22 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3048,22 +3713,22 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte switch (instruction->opcode) { @@ -6071,7 +11754,7 @@ index c26077e43d9..9b44925888b 100644 if (!(cf_info = cf_flattener_push_control_flow_level(flattener))) return VKD3D_ERROR_OUT_OF_MEMORY; -@@ -3611,7 +3715,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3087,7 +3752,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte ++flattener->branch_id; break; @@ -6080,7 +11763,7 @@ index c26077e43d9..9b44925888b 100644 if (cf_info->inside_block) cf_flattener_emit_unconditional_branch(flattener, cf_info->u.if_.merge_block_id); -@@ -3625,7 +3729,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3101,7 +3766,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte cf_info->inside_block = true; break; @@ -6089,7 +11772,7 @@ index c26077e43d9..9b44925888b 100644 if (cf_info->inside_block) cf_flattener_emit_unconditional_branch(flattener, cf_info->u.if_.merge_block_id); -@@ -3634,7 +3738,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3110,7 +3775,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte cf_flattener_pop_control_flow_level(flattener); break; @@ -6098,7 +11781,7 @@ index c26077e43d9..9b44925888b 100644 if (!(cf_info = cf_flattener_push_control_flow_level(flattener))) return VKD3D_ERROR_OUT_OF_MEMORY; -@@ -3663,7 +3767,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3139,7 +3804,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte ++flattener->loop_id; break; @@ -6107,7 +11790,7 @@ index c26077e43d9..9b44925888b 100644 if (cf_info->inside_block) cf_flattener_emit_unconditional_branch(flattener, cf_info->u.loop.continue_block_id); -@@ -3674,7 +3778,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3150,7 +3815,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte cf_flattener_pop_control_flow_level(flattener); break; @@ -6116,7 +11799,7 @@ index c26077e43d9..9b44925888b 100644 if (!(cf_info = cf_flattener_push_control_flow_level(flattener))) return VKD3D_ERROR_OUT_OF_MEMORY; -@@ -3685,7 +3789,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3161,7 +3826,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte if (!(dst_ins = cf_flattener_require_space(flattener, 1))) return VKD3D_ERROR_OUT_OF_MEMORY; @@ -6125,7 +11808,7 @@ index c26077e43d9..9b44925888b 100644 ++flattener->instruction_count; cf_info->u.switch_.id = flattener->switch_id; -@@ -3706,7 +3810,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3182,7 +3847,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte break; @@ -6134,7 +11817,7 @@ index c26077e43d9..9b44925888b 100644 { struct vkd3d_shader_src_param *src_params; unsigned int j; -@@ -3741,7 +3845,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3217,7 +3882,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte break; } @@ -6143,7 +11826,7 @@ index c26077e43d9..9b44925888b 100644 { unsigned int label_id, value; -@@ -3773,7 +3877,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3249,7 +3914,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte break; } @@ -6152,7 +11835,7 @@ index c26077e43d9..9b44925888b 100644 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); -@@ -3785,7 +3889,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3261,7 +3926,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte cf_info->inside_block = true; break; @@ -6161,7 +11844,7 @@ index c26077e43d9..9b44925888b 100644 { struct cf_flattener_info *breakable_cf_info; -@@ -3808,7 +3912,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3284,7 +3949,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte break; } @@ -6170,7 +11853,7 @@ index c26077e43d9..9b44925888b 100644 { struct cf_flattener_info *loop_cf_info; -@@ -3823,7 +3927,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3299,7 +3964,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte break; } @@ -6179,7 +11862,7 @@ index c26077e43d9..9b44925888b 100644 { struct cf_flattener_info *loop_cf_info; -@@ -3839,7 +3943,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3315,7 +3980,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte break; } @@ -6188,7 +11871,7 @@ index c26077e43d9..9b44925888b 100644 { struct cf_flattener_info *loop_cf_info; -@@ -3854,7 +3958,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -3330,7 +3995,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte break; } @@ -6197,7 +11880,7 @@ index c26077e43d9..9b44925888b 100644 if (!cf_flattener_copy_instruction(flattener, instruction)) return VKD3D_ERROR_OUT_OF_MEMORY; -@@ -3971,14 +4075,14 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +@@ -3447,14 +4112,14 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs switch (ins->opcode) { @@ -6214,7 +11897,7 @@ index c26077e43d9..9b44925888b 100644 break; default: -@@ -3999,7 +4103,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +@@ -3475,7 +4140,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs goto fail; if (!vsir_instruction_init_with_params(program, &instructions[ins_count], @@ -6223,7 +11906,7 @@ index c26077e43d9..9b44925888b 100644 goto fail; vsir_src_param_init_label(&instructions[ins_count].src[0], default_label); ++ins_count; -@@ -4015,7 +4119,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +@@ -3491,7 +4156,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs unsigned int fallthrough_label, case_label = label_from_src_param(&ins->src[3 + 2 * j + 1]); if (!vsir_instruction_init_with_params(program, @@ -6232,7 +11915,7 @@ index c26077e43d9..9b44925888b 100644 goto fail; dst_param_init_ssa_bool(&instructions[ins_count].dst[0], ssa_count); instructions[ins_count].src[0] = ins->src[0]; -@@ -4031,7 +4135,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +@@ -3507,7 +4172,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs fallthrough_label = block_count + 1; if (!vsir_instruction_init_with_params(program, &instructions[ins_count], @@ -6241,7 +11924,7 @@ index c26077e43d9..9b44925888b 100644 goto fail; src_param_init_ssa_bool(&instructions[ins_count].src[0], ssa_count); vsir_src_param_init_label(&instructions[ins_count].src[1], case_label); -@@ -4053,7 +4157,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +@@ -3529,7 +4194,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs else { if (!vsir_instruction_init_with_params(program, @@ -6250,7 +11933,7 @@ index c26077e43d9..9b44925888b 100644 goto fail; vsir_src_param_init_label(&instructions[ins_count].src[0], ++block_count); ++ins_count; -@@ -4168,7 +4272,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ +@@ -3644,7 +4309,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ /* Only phi src/dst SSA values need be converted here. Structurisation may * introduce new cases of undominated SSA use, which will be handled later. */ @@ -6259,7 +11942,7 @@ index c26077e43d9..9b44925888b 100644 continue; ++phi_count; -@@ -4219,12 +4323,12 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ +@@ -3695,12 +4360,12 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ switch (ins->opcode) { @@ -6275,7 +11958,7 @@ index c26077e43d9..9b44925888b 100644 info = &block_info[current_label - 1]; for (j = 0; j < info->incoming_count; ++j) -@@ -4232,7 +4336,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ +@@ -3708,7 +4373,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ struct phi_incoming_to_temp *incoming = &info->incomings[j]; mov_ins = &instructions[ins_count++]; @@ -6284,7 +11967,7 @@ index c26077e43d9..9b44925888b 100644 goto fail; *mov_ins->dst = *incoming->dst; mov_ins->src = incoming->src; -@@ -4240,7 +4344,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ +@@ -3716,7 +4381,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ } break; @@ -6293,7 +11976,7 @@ index c26077e43d9..9b44925888b 100644 continue; default: -@@ -4277,7 +4381,7 @@ struct vsir_block_list +@@ -3753,7 +4418,7 @@ struct vsir_block_list static void vsir_block_list_init(struct vsir_block_list *list) { @@ -6302,7 +11985,7 @@ index c26077e43d9..9b44925888b 100644 } static void vsir_block_list_cleanup(struct vsir_block_list *list) -@@ -4649,11 +4753,11 @@ static void vsir_cfg_dump_dot(struct vsir_cfg *cfg) +@@ -4125,11 +4790,11 @@ static void vsir_cfg_dump_dot(struct vsir_cfg *cfg) switch (block->end->opcode) { @@ -6316,7 +11999,7 @@ index c26077e43d9..9b44925888b 100644 shape = vsir_register_is_label(&block->end->src[0].reg) ? "ellipse" : "box"; break; -@@ -4791,11 +4895,11 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program +@@ -4267,11 +4932,11 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program switch (instruction->opcode) { @@ -6331,7 +12014,7 @@ index c26077e43d9..9b44925888b 100644 { unsigned int label = label_from_src_param(&instruction->src[0]); -@@ -4812,16 +4916,16 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program +@@ -4288,16 +4953,16 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program break; } @@ -6353,7 +12036,7 @@ index c26077e43d9..9b44925888b 100644 VKD3D_ASSERT(!current_block); finish = true; break; -@@ -4846,10 +4950,10 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program +@@ -4322,10 +4987,10 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program switch (block->end->opcode) { @@ -6366,7 +12049,7 @@ index c26077e43d9..9b44925888b 100644 if (vsir_register_is_label(&block->end->src[0].reg)) { if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[0])) < 0) -@@ -5528,7 +5632,7 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) +@@ -5004,7 +5669,7 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) /* Generate between zero and two jump instructions. */ switch (block->end->opcode) { @@ -6375,7 +12058,7 @@ index c26077e43d9..9b44925888b 100644 { struct vsir_cfg_edge_action action_true, action_false; bool invert_condition = false; -@@ -5614,7 +5718,7 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) +@@ -5090,7 +5755,7 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) break; } @@ -6384,7 +12067,7 @@ index c26077e43d9..9b44925888b 100644 if (!(structure = vsir_cfg_structure_list_append(stack[stack_depth - 1], STRUCTURE_TYPE_JUMP))) goto fail; structure->u.jump.type = JUMP_RET; -@@ -6108,7 +6212,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, +@@ -5584,7 +6249,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) return VKD3D_ERROR_OUT_OF_MEMORY; @@ -6393,7 +12076,7 @@ index c26077e43d9..9b44925888b 100644 if ((ret = vsir_cfg_structure_list_emit(cfg, &loop->body, loop->idx)) < 0) return ret; -@@ -6116,7 +6220,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, +@@ -5592,7 +6257,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 5)) return VKD3D_ERROR_OUT_OF_MEMORY; @@ -6402,7 +12085,7 @@ index c26077e43d9..9b44925888b 100644 /* Add a trampoline to implement multilevel jumping depending on the stored * jump_target value. */ -@@ -6131,7 +6235,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, +@@ -5607,7 +6272,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, const unsigned int inner_break_target = loop->idx << 1; if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], @@ -6411,7 +12094,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); -@@ -6141,7 +6245,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, +@@ -5617,7 +6282,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, ++target->ins_count; if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], @@ -6420,7 +12103,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count); -@@ -6150,7 +6254,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, +@@ -5626,7 +6291,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, ++target->temp_count; if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], @@ -6429,7 +12112,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count); -@@ -6160,7 +6264,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, +@@ -5636,7 +6301,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, ++target->ins_count; if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], @@ -6438,7 +12121,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; -@@ -6184,7 +6288,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg +@@ -5660,7 +6325,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg return VKD3D_ERROR_OUT_OF_MEMORY; if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], @@ -6447,7 +12130,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; target->instructions[target->ins_count].src[0] = *selection->condition; -@@ -6202,7 +6306,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg +@@ -5678,7 +6343,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) return VKD3D_ERROR_OUT_OF_MEMORY; @@ -6456,7 +12139,7 @@ index c26077e43d9..9b44925888b 100644 if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->else_body, loop_idx)) < 0) return ret; -@@ -6211,7 +6315,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg +@@ -5687,7 +6352,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1)) return VKD3D_ERROR_OUT_OF_MEMORY; @@ -6465,7 +12148,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_OK; } -@@ -6235,19 +6339,19 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, +@@ -5711,19 +6376,19 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, * in the lowest bit of jump_target. */ if (jump->target == loop_idx) { @@ -6488,7 +12171,7 @@ index c26077e43d9..9b44925888b 100644 break; default: -@@ -6260,7 +6364,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, +@@ -5736,7 +6401,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, if (jump->needs_launcher) { if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count], @@ -6497,7 +12180,7 @@ index c26077e43d9..9b44925888b 100644 return VKD3D_ERROR_OUT_OF_MEMORY; dst_param_init_temp_uint(&target->instructions[target->ins_count].dst[0], target->jump_target_temp_idx); -@@ -6388,7 +6492,7 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, +@@ -5864,7 +6529,7 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, switch (ins->opcode) { @@ -6506,7 +12189,7 @@ index c26077e43d9..9b44925888b 100644 VKD3D_ASSERT(program->shader_version.type != VKD3D_SHADER_TYPE_HULL); TRACE("Structurizing a non-hull shader.\n"); if ((ret = vsir_program_structurize_function(program, message_context, -@@ -6397,9 +6501,9 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, +@@ -5873,9 +6538,9 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, VKD3D_ASSERT(i == program->instructions.count); break; @@ -6519,7 +12202,7 @@ index c26077e43d9..9b44925888b 100644 VKD3D_ASSERT(program->shader_version.type == VKD3D_SHADER_TYPE_HULL); TRACE("Structurizing phase %u of a hull shader.\n", ins->opcode); target.instructions[target.ins_count++] = *ins; -@@ -6565,7 +6669,7 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru +@@ -6041,7 +6706,7 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru switch (ins->opcode) { @@ -6528,7 +12211,7 @@ index c26077e43d9..9b44925888b 100644 VKD3D_ASSERT(program->shader_version.type != VKD3D_SHADER_TYPE_HULL); TRACE("Materializing undominated SSAs in a non-hull shader.\n"); if ((ret = vsir_program_materialize_undominated_ssas_to_temps_in_function( -@@ -6574,9 +6678,9 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru +@@ -6050,9 +6715,9 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru VKD3D_ASSERT(i == program->instructions.count); break; @@ -6541,7 +12224,7 @@ index c26077e43d9..9b44925888b 100644 VKD3D_ASSERT(program->shader_version.type == VKD3D_SHADER_TYPE_HULL); TRACE("Materializing undominated SSAs in phase %u of a hull shader.\n", ins->opcode); ++i; -@@ -6667,12 +6771,12 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr +@@ -6143,12 +6808,12 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr } opcodes[] = { @@ -6560,7 +12243,7 @@ index c26077e43d9..9b44925888b 100644 }; if (compare_func == VKD3D_SHADER_COMPARISON_FUNC_NEVER) -@@ -6682,7 +6786,7 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr +@@ -6158,7 +6823,7 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr ret = NULL; ins = &program->instructions.elements[pos]; @@ -6569,7 +12252,7 @@ index c26077e43d9..9b44925888b 100644 ins->flags = VKD3D_SHADER_CONDITIONAL_OP_Z; src_param_init_const_uint(&ins->src[0], 0); -@@ -6726,14 +6830,14 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr +@@ -6202,14 +6867,14 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr ins->src[opcodes[compare_func].swap ? 1 : 0].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W); ++ins; @@ -6586,7 +12269,7 @@ index c26077e43d9..9b44925888b 100644 vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); ins->dst[0].reg.idx[0].offset = colour_signature_idx; ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; -@@ -6799,7 +6903,7 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro +@@ -6275,7 +6940,7 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro if (vsir_instruction_is_dcl(ins)) continue; @@ -6595,7 +12278,7 @@ index c26077e43d9..9b44925888b 100644 { if ((ret = insert_alpha_test_before_ret(program, ins, compare_func, ref, colour_signature_idx, colour_temp, &new_pos, message_context)) < 0) -@@ -6849,7 +6953,7 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog +@@ -6325,7 +6990,7 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog if (!(mask & (1u << i))) continue; @@ -6604,7 +12287,7 @@ index c26077e43d9..9b44925888b 100644 src_param_init_temp_float4(&ins->src[0], position_temp); src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 + i, VKD3D_DATA_FLOAT); ins->src[1].swizzle = VKD3D_SHADER_NO_SWIZZLE; -@@ -6867,7 +6971,7 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog +@@ -6343,7 +7008,7 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog ++ins; } @@ -6613,7 +12296,60 @@ index c26077e43d9..9b44925888b 100644 vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); ins->dst[0].reg.idx[0].offset = position_signature_idx; ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; -@@ -6974,7 +7078,7 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr +@@ -6362,9 +7027,9 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr + struct shader_signature *signature = &program->output_signature; + unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u; + const struct vkd3d_shader_parameter1 *mask_parameter = NULL; +- struct signature_element *new_elements, *clip_element; + uint32_t position_signature_idx, position_temp, mask; + static const struct vkd3d_shader_location no_loc; ++ struct signature_element *clip_element; + struct vkd3d_shader_instruction *ins; + unsigned int plane_count; + size_t new_pos; +@@ -6422,33 +7087,20 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr + + plane_count = vkd3d_popcount(mask); + +- if (!(new_elements = vkd3d_realloc(signature->elements, +- (signature->element_count + 2) * sizeof(*signature->elements)))) ++ /* Register mask is ignored since we operate after I/O normalisation. */ ++ if (!(clip_element = add_signature_element(signature, "SV_ClipDistance", 0, ++ vkd3d_write_mask_from_component_count(min(plane_count, 4)), 0, VKD3DSIM_NONE))) + return VKD3D_ERROR_OUT_OF_MEMORY; +- signature->elements = new_elements; +- +- low_signature_idx = signature->element_count; +- clip_element = &signature->elements[signature->element_count++]; +- memset(clip_element, 0, sizeof(*clip_element)); ++ low_signature_idx = clip_element - signature->elements; + clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; +- clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; +- clip_element->register_count = 1; +- clip_element->mask = vkd3d_write_mask_from_component_count(min(plane_count, 4)); +- clip_element->used_mask = clip_element->mask; +- clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; + + if (plane_count > 4) + { +- high_signature_idx = signature->element_count; +- clip_element = &signature->elements[signature->element_count++]; +- memset(clip_element, 0, sizeof(*clip_element)); ++ if (!(clip_element = add_signature_element(signature, "SV_ClipDistance", 1, ++ vkd3d_write_mask_from_component_count(plane_count - 4), 0, VKD3DSIM_NONE))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ high_signature_idx = clip_element - signature->elements; + clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; +- clip_element->semantic_index = 1; +- clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; +- clip_element->register_count = 1; +- clip_element->mask = vkd3d_write_mask_from_component_count(plane_count - 4); +- clip_element->used_mask = clip_element->mask; +- clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; + } + + /* We're going to be reading from the output position, so we need to go +@@ -6463,7 +7115,7 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr if (vsir_instruction_is_dcl(ins)) continue; @@ -6622,7 +12358,7 @@ index c26077e43d9..9b44925888b 100644 { if ((ret = insert_clip_planes_before_ret(program, ins, mask, position_signature_idx, position_temp, low_signature_idx, high_signature_idx, &new_pos)) < 0) -@@ -7020,7 +7124,7 @@ static enum vkd3d_result insert_point_size_before_ret(struct vsir_program *progr +@@ -6509,7 +7161,7 @@ static enum vkd3d_result insert_point_size_before_ret(struct vsir_program *progr ret = NULL; ins = &program->instructions.elements[pos]; @@ -6631,7 +12367,7 @@ index c26077e43d9..9b44925888b 100644 vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE, VKD3D_DATA_FLOAT); -@@ -7066,7 +7170,7 @@ static enum vkd3d_result vsir_program_insert_point_size(struct vsir_program *pro +@@ -6555,7 +7207,7 @@ static enum vkd3d_result vsir_program_insert_point_size(struct vsir_program *pro { struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; @@ -6640,7 +12376,7 @@ index c26077e43d9..9b44925888b 100644 { size_t new_pos; int ret; -@@ -7155,7 +7259,7 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra +@@ -6644,7 +7296,7 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra if (min_parameter) { @@ -6649,7 +12385,7 @@ index c26077e43d9..9b44925888b 100644 src_param_init_ssa_float(&ins->src[0], ssa_value); src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN, VKD3D_DATA_FLOAT); if (max_parameter) -@@ -7174,7 +7278,7 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra +@@ -6663,7 +7315,7 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra if (max_parameter) { @@ -6658,7 +12394,7 @@ index c26077e43d9..9b44925888b 100644 src_param_init_ssa_float(&ins->src[0], ssa_value); src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX, VKD3D_DATA_FLOAT); vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); -@@ -7308,7 +7412,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr +@@ -6797,7 +7449,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr { ins = &program->instructions.elements[i]; @@ -6667,7 +12403,7 @@ index c26077e43d9..9b44925888b 100644 break; } -@@ -7351,7 +7455,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr +@@ -6840,7 +7492,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr return VKD3D_ERROR_OUT_OF_MEMORY; ins = &program->instructions.elements[insert_pos]; @@ -6676,7 +12412,7 @@ index c26077e43d9..9b44925888b 100644 dst_param_init_temp_float4(&ins->dst[0], coord_temp); ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; vsir_src_param_init(&ins->src[0], VKD3DSPR_POINT_COORD, VKD3D_DATA_FLOAT, 0); -@@ -7359,7 +7463,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr +@@ -6848,7 +7500,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; ++ins; @@ -6685,7 +12421,7 @@ index c26077e43d9..9b44925888b 100644 dst_param_init_temp_float4(&ins->dst[0], coord_temp); ins->dst[0].write_mask = VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VKD3D_DATA_FLOAT, 0); -@@ -7430,7 +7534,7 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -6919,7 +7571,7 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ins = &program->instructions.elements[pos]; @@ -6694,7 +12430,7 @@ index c26077e43d9..9b44925888b 100644 dst_param_init_ssa_float(&ins->dst[0], ssa_temp); src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_END, VKD3D_DATA_FLOAT); vsir_src_param_init(&ins->src[1], VKD3DSPR_INPUT, VKD3D_DATA_FLOAT, 1); -@@ -7439,7 +7543,7 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -6928,7 +7580,7 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); ins->src[1].modifiers = VKD3DSPSM_NEG; @@ -6703,7 +12439,7 @@ index c26077e43d9..9b44925888b 100644 dst_param_init_ssa_float(&ins->dst[0], ssa_factor); ins->dst[0].modifiers = VKD3DSPDM_SATURATE; src_param_init_ssa_float(&ins->src[0], ssa_temp); -@@ -7462,7 +7566,7 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -6951,7 +7603,7 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ins = &program->instructions.elements[pos]; @@ -6712,7 +12448,7 @@ index c26077e43d9..9b44925888b 100644 dst_param_init_ssa_float(&ins->dst[0], ssa_temp); src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VKD3D_DATA_FLOAT); vsir_src_param_init(&ins->src[1], VKD3DSPR_INPUT, VKD3D_DATA_FLOAT, 1); -@@ -7470,7 +7574,7 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -6959,7 +7611,7 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); @@ -6721,7 +12457,7 @@ index c26077e43d9..9b44925888b 100644 dst_param_init_ssa_float(&ins->dst[0], ssa_factor); ins->dst[0].modifiers = VKD3DSPDM_SATURATE; src_param_init_ssa_float(&ins->src[0], ssa_temp); -@@ -7495,7 +7599,7 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -6984,7 +7636,7 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ins = &program->instructions.elements[pos]; @@ -6730,7 +12466,7 @@ index c26077e43d9..9b44925888b 100644 dst_param_init_ssa_float(&ins->dst[0], ssa_temp); src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VKD3D_DATA_FLOAT); vsir_src_param_init(&ins->src[1], VKD3DSPR_INPUT, VKD3D_DATA_FLOAT, 1); -@@ -7503,12 +7607,12 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -6992,12 +7644,12 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); @@ -6745,7 +12481,7 @@ index c26077e43d9..9b44925888b 100644 dst_param_init_ssa_float(&ins->dst[0], ssa_factor); ins->dst[0].modifiers = VKD3DSPDM_SATURATE; src_param_init_ssa_float(&ins->src[0], ssa_temp2); -@@ -7525,13 +7629,13 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -7014,13 +7666,13 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro * mad oC0, sr0, srFACTOR, FOG_COLOUR */ @@ -6761,7 +12497,7 @@ index c26077e43d9..9b44925888b 100644 dst_param_init_output(&ins->dst[0], VKD3D_DATA_FLOAT, colour_signature_idx, program->output_signature.elements[colour_signature_idx].mask); src_param_init_ssa_float4(&ins->src[0], program->ssa_count - 1); -@@ -7599,7 +7703,7 @@ static enum vkd3d_result vsir_program_insert_fragment_fog(struct vsir_program *p +@@ -7088,7 +7740,7 @@ static enum vkd3d_result vsir_program_insert_fragment_fog(struct vsir_program *p if (vsir_instruction_is_dcl(ins)) continue; @@ -6770,172 +12506,160 @@ index c26077e43d9..9b44925888b 100644 { if ((ret = insert_fragment_fog_before_ret(program, ins, mode, fog_signature_idx, colour_signature_idx, colour_temp, &new_pos, message_context)) < 0) -@@ -7677,7 +7781,7 @@ static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *progr - ins = &program->instructions.elements[pos]; - - /* Write the fog output. */ -- vsir_instruction_init_with_params(program, ins, &loc, VKD3DSIH_MOV, 1, 1); -+ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); - dst_param_init_output(&ins->dst[0], VKD3D_DATA_FLOAT, fog_signature_idx, 0x1); - src_param_init_temp_float4(&ins->src[0], temp); - if (source == VKD3D_SHADER_FOG_SOURCE_Z) -@@ -7687,7 +7791,7 @@ static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *progr - ++ins; - - /* Write the position or specular output. */ -- vsir_instruction_init_with_params(program, ins, &loc, VKD3DSIH_MOV, 1, 1); -+ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); - dst_param_init_output(&ins->dst[0], vkd3d_data_type_from_component_type(e->component_type), - source_signature_idx, e->mask); - src_param_init_temp_float4(&ins->src[0], temp); -@@ -7767,7 +7871,7 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro - if (vsir_instruction_is_dcl(ins)) - continue; - -- if (ins->opcode == VKD3DSIH_RET) -+ if (ins->opcode == VSIR_OP_RET) - { - size_t new_pos; - int ret; -@@ -7809,308 +7913,311 @@ static bool vsir_src_is_masked(enum vkd3d_shader_opcode opcode, unsigned int src +@@ -7153,137 +7805,1026 @@ static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *progr + const struct vkd3d_shader_instruction *ret, enum vkd3d_shader_fog_source source, uint32_t temp, + uint32_t fog_signature_idx, uint32_t source_signature_idx, size_t *ret_pos) { - switch (opcode) - { -- case VKD3DSIH_ABS: -- case VKD3DSIH_ACOS: -- case VKD3DSIH_ADD: -- case VKD3DSIH_AND: -- case VKD3DSIH_ASIN: -- case VKD3DSIH_ATAN: -- case VKD3DSIH_BFI: -- case VKD3DSIH_BFREV: -- case VKD3DSIH_CMP: -- case VKD3DSIH_CND: -- case VKD3DSIH_COS: -- case VKD3DSIH_COUNTBITS: -- case VKD3DSIH_DADD: /* NB: These are masked, but the mask is double-sized. */ -- case VKD3DSIH_DDIV: -- case VKD3DSIH_DFMA: -- case VKD3DSIH_DIV: -- case VKD3DSIH_DMAX: -- case VKD3DSIH_DMIN: -- case VKD3DSIH_DMOV: -- case VKD3DSIH_DMOVC: -- case VKD3DSIH_DMUL: -- case VKD3DSIH_DRCP: -- case VKD3DSIH_DSX: -- case VKD3DSIH_DSX_COARSE: -- case VKD3DSIH_DSX_FINE: -- case VKD3DSIH_DSY: -- case VKD3DSIH_DSY_COARSE: -- case VKD3DSIH_DSY_FINE: -- case VKD3DSIH_EQO: -- case VKD3DSIH_EQU: -- case VKD3DSIH_EXP: -- case VKD3DSIH_EXPP: -- case VKD3DSIH_F16TOF32: -- case VKD3DSIH_F32TOF16: -- case VKD3DSIH_FIRSTBIT_HI: -- case VKD3DSIH_FIRSTBIT_LO: -- case VKD3DSIH_FIRSTBIT_SHI: -- case VKD3DSIH_FRC: -- case VKD3DSIH_FREM: -- case VKD3DSIH_FTOD: -- case VKD3DSIH_FTOI: -- case VKD3DSIH_FTOU: -- case VKD3DSIH_GEO: -- case VKD3DSIH_GEU: -- case VKD3DSIH_HCOS: -- case VKD3DSIH_HSIN: -- case VKD3DSIH_HTAN: -- case VKD3DSIH_IADD: -- case VKD3DSIH_IBFE: -- case VKD3DSIH_IDIV: -- case VKD3DSIH_IEQ: -- case VKD3DSIH_IGE: -- case VKD3DSIH_ILT: -- case VKD3DSIH_IMAD: -- case VKD3DSIH_IMAX: -- case VKD3DSIH_IMIN: -- case VKD3DSIH_IMUL: -- case VKD3DSIH_IMUL_LOW: -- case VKD3DSIH_INE: -- case VKD3DSIH_INEG: -- case VKD3DSIH_ISFINITE: -- case VKD3DSIH_ISHL: -- case VKD3DSIH_ISHR: -- case VKD3DSIH_ISINF: -- case VKD3DSIH_ISNAN: -- case VKD3DSIH_ITOD: -- case VKD3DSIH_ITOF: -- case VKD3DSIH_ITOI: -- case VKD3DSIH_LOG: -- case VKD3DSIH_LOGP: -- case VKD3DSIH_LRP: -- case VKD3DSIH_LTO: -- case VKD3DSIH_LTU: -- case VKD3DSIH_MAD: -- case VKD3DSIH_MAX: -- case VKD3DSIH_MIN: -- case VKD3DSIH_MOV: -- case VKD3DSIH_MOVA: -- case VKD3DSIH_MOVC: -- case VKD3DSIH_MSAD: /* FIXME: Is this correct? */ -- case VKD3DSIH_MUL: -- case VKD3DSIH_NEO: -- case VKD3DSIH_NEU: -- case VKD3DSIH_NOT: -- case VKD3DSIH_OR: -- case VKD3DSIH_ORD: -- case VKD3DSIH_PHI: -- case VKD3DSIH_POW: -- case VKD3DSIH_QUAD_READ_ACROSS_D: -- case VKD3DSIH_QUAD_READ_ACROSS_X: -- case VKD3DSIH_QUAD_READ_ACROSS_Y: -- case VKD3DSIH_RCP: -- case VKD3DSIH_ROUND_NE: -- case VKD3DSIH_ROUND_NI: -- case VKD3DSIH_ROUND_PI: -- case VKD3DSIH_ROUND_Z: -- case VKD3DSIH_RSQ: -- case VKD3DSIH_SETP: -- case VKD3DSIH_SGE: -- case VKD3DSIH_SGN: -- case VKD3DSIH_SIN: -- case VKD3DSIH_SINCOS: /* FIXME: Only for sm4. */ -- case VKD3DSIH_SLT: -- case VKD3DSIH_SQRT: -- case VKD3DSIH_SUB: -- case VKD3DSIH_SWAPC: -- case VKD3DSIH_TAN: -- case VKD3DSIH_UBFE: -- case VKD3DSIH_UDIV: -- case VKD3DSIH_UGE: -- case VKD3DSIH_ULT: -- case VKD3DSIH_UMAX: -- case VKD3DSIH_UMIN: -- case VKD3DSIH_UMUL: -- case VKD3DSIH_UNO: -- case VKD3DSIH_USHR: -- case VKD3DSIH_UTOD: -- case VKD3DSIH_UTOF: -- case VKD3DSIH_UTOU: -- case VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL: -- case VKD3DSIH_WAVE_ACTIVE_BIT_AND: -- case VKD3DSIH_WAVE_ACTIVE_BIT_OR: -- case VKD3DSIH_WAVE_ACTIVE_BIT_XOR: -- case VKD3DSIH_WAVE_ALL_TRUE: -- case VKD3DSIH_WAVE_ANY_TRUE: -- case VKD3DSIH_WAVE_OP_ADD: -- case VKD3DSIH_WAVE_OP_IMAX: -- case VKD3DSIH_WAVE_OP_IMIN: -- case VKD3DSIH_WAVE_OP_MAX: -- case VKD3DSIH_WAVE_OP_MIN: -- case VKD3DSIH_WAVE_OP_MUL: -- case VKD3DSIH_WAVE_OP_UMAX: -- case VKD3DSIH_WAVE_OP_UMIN: -- case VKD3DSIH_WAVE_READ_LANE_FIRST: -- case VKD3DSIH_XOR: +- const struct signature_element *e = &program->output_signature.elements[source_signature_idx]; +- struct vkd3d_shader_instruction_array *instructions = &program->instructions; +- const struct vkd3d_shader_location loc = ret->location; +- size_t pos = ret - instructions->elements; +- struct vkd3d_shader_instruction *ins; ++ const struct signature_element *e = &program->output_signature.elements[source_signature_idx]; ++ struct vkd3d_shader_instruction_array *instructions = &program->instructions; ++ const struct vkd3d_shader_location loc = ret->location; ++ size_t pos = ret - instructions->elements; ++ struct vkd3d_shader_instruction *ins; ++ ++ if (!shader_instruction_array_insert_at(&program->instructions, pos, 2)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ret = NULL; ++ ++ ins = &program->instructions.elements[pos]; ++ ++ /* Write the fog output. */ ++ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); ++ dst_param_init_output(&ins->dst[0], VKD3D_DATA_FLOAT, fog_signature_idx, 0x1); ++ src_param_init_temp_float4(&ins->src[0], temp); ++ if (source == VKD3D_SHADER_FOG_SOURCE_Z) ++ ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z); ++ else /* Position or specular W. */ ++ ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W); ++ ++ins; ++ ++ /* Write the position or specular output. */ ++ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); ++ dst_param_init_output(&ins->dst[0], vkd3d_data_type_from_component_type(e->component_type), ++ source_signature_idx, e->mask); ++ src_param_init_temp_float4(&ins->src[0], temp); ++ ++ins; ++ ++ *ret_pos = pos + 2; ++ return VKD3D_OK; ++} ++ ++static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *program, ++ struct vsir_transformation_context *ctx) ++{ ++ struct vkd3d_shader_message_context *message_context = ctx->message_context; ++ const struct vkd3d_shader_parameter1 *source_parameter = NULL; ++ uint32_t fog_signature_idx, source_signature_idx, temp; ++ static const struct vkd3d_shader_location no_loc; ++ enum vkd3d_shader_fog_source source; ++ const struct signature_element *e; ++ ++ if (!is_pre_rasterization_shader(program->shader_version.type)) ++ return VKD3D_OK; ++ ++ if (!(source_parameter = vsir_program_get_parameter(program, VKD3D_SHADER_PARAMETER_NAME_FOG_SOURCE))) ++ return VKD3D_OK; ++ ++ if (source_parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) ++ { ++ vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, ++ "Unsupported fog source parameter type %#x.", source_parameter->type); ++ return VKD3D_ERROR_NOT_IMPLEMENTED; ++ } ++ if (source_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) ++ { ++ vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid fog source parameter data type %#x.", source_parameter->data_type); ++ return VKD3D_ERROR_INVALID_ARGUMENT; ++ } ++ source = source_parameter->u.immediate_constant.u.u32; ++ ++ TRACE("Fog source %#x.\n", source); ++ ++ if (source == VKD3D_SHADER_FOG_SOURCE_FOG) ++ return VKD3D_OK; ++ ++ if (source == VKD3D_SHADER_FOG_SOURCE_FOG_OR_SPECULAR_W) ++ { ++ if (program->has_fog || !(e = vsir_signature_find_element_by_name(&program->output_signature, "COLOR", 1))) ++ return VKD3D_OK; ++ source_signature_idx = e - program->output_signature.elements; ++ } ++ else ++ { ++ if (!vsir_signature_find_sysval(&program->output_signature, ++ VKD3D_SHADER_SV_POSITION, 0, &source_signature_idx)) ++ { ++ vkd3d_shader_error(ctx->message_context, &no_loc, ++ VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC, "Shader does not write position."); ++ return VKD3D_ERROR_INVALID_SHADER; ++ } ++ } ++ ++ if (!(e = vsir_signature_find_element_by_name(&program->output_signature, "FOG", 0))) ++ { ++ ERR("Fog output not found.\n"); ++ return VKD3D_ERROR_INVALID_SHADER; ++ } ++ fog_signature_idx = e - program->output_signature.elements; ++ ++ temp = program->temp_count++; ++ ++ /* Insert a fog write before each ret, and convert either specular or ++ * position output to a temp. */ ++ for (size_t i = 0; i < program->instructions.count; ++i) ++ { ++ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; ++ ++ if (vsir_instruction_is_dcl(ins)) ++ continue; ++ ++ if (ins->opcode == VSIR_OP_RET) ++ { ++ size_t new_pos; ++ int ret; ++ ++ if ((ret = insert_vertex_fog_before_ret(program, ins, source, temp, ++ fog_signature_idx, source_signature_idx, &new_pos)) < 0) ++ return ret; ++ i = new_pos; ++ continue; ++ } ++ ++ for (size_t j = 0; j < ins->dst_count; ++j) ++ { ++ struct vkd3d_shader_dst_param *dst = &ins->dst[j]; ++ ++ /* Note we run after I/O normalization. */ ++ if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == source_signature_idx) ++ { ++ dst->reg.type = VKD3DSPR_TEMP; ++ dst->reg.idx[0].offset = temp; ++ } ++ } ++ } ++ ++ program->has_fog = true; ++ ++ return VKD3D_OK; ++} ++ ++ ++/* Distinguishes between instruction sources which are masked, where the used ++ * components of the source are determined by the write mask, and sources which ++ * are not masked, where the used components are pre-defined. ++ * ++ * E.g. "add r0.yz, r1.xyzw, r2.xyzw" uses the .yz components of r1 and r2, and ++ * therefore those sources are considered "masked", but ++ * "dp3 r0.y, r1.xyzw, r2.xyzw" uses the .xyz components. */ ++static bool vsir_src_is_masked(enum vkd3d_shader_opcode opcode, unsigned int src_idx) ++{ ++ switch (opcode) ++ { + case VSIR_OP_ABS: + case VSIR_OP_ACOS: + case VSIR_OP_ADD: @@ -7074,105 +12798,9 @@ index c26077e43d9..9b44925888b 100644 + case VSIR_OP_WAVE_OP_UMIN: + case VSIR_OP_WAVE_READ_LANE_FIRST: + case VSIR_OP_XOR: - return true; - - /* Atomics can't have a writemask. */ -- case VKD3DSIH_ATOMIC_AND: -- case VKD3DSIH_ATOMIC_CMP_STORE: -- case VKD3DSIH_ATOMIC_IADD: -- case VKD3DSIH_ATOMIC_IMAX: -- case VKD3DSIH_ATOMIC_IMIN: -- case VKD3DSIH_ATOMIC_OR: -- case VKD3DSIH_ATOMIC_UMAX: -- case VKD3DSIH_ATOMIC_UMIN: -- case VKD3DSIH_ATOMIC_XOR: -- case VKD3DSIH_BEM: -- case VKD3DSIH_BRANCH: -- case VKD3DSIH_BREAK: -- case VKD3DSIH_BREAKC: -- case VKD3DSIH_BREAKP: -- case VKD3DSIH_BUFINFO: -- case VKD3DSIH_CALL: -- case VKD3DSIH_CALLNZ: -- case VKD3DSIH_CASE: -- case VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED: /* FIXME: Is this correct? */ -- case VKD3DSIH_CONTINUE: -- case VKD3DSIH_CONTINUEP: -- case VKD3DSIH_CRS: -- case VKD3DSIH_CUT: -- case VKD3DSIH_CUT_STREAM: -- case VKD3DSIH_DCL: -- case VKD3DSIH_DCL_CONSTANT_BUFFER: -- case VKD3DSIH_DCL_FUNCTION_BODY: -- case VKD3DSIH_DCL_FUNCTION_TABLE: -- case VKD3DSIH_DCL_GLOBAL_FLAGS: -- case VKD3DSIH_DCL_GS_INSTANCES: -- case VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT: -- case VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT: -- case VKD3DSIH_DCL_HS_MAX_TESSFACTOR: -- case VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER: -- case VKD3DSIH_DCL_INDEXABLE_TEMP: -- case VKD3DSIH_DCL_INDEX_RANGE: -- case VKD3DSIH_DCL_INPUT: -- case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT: -- case VKD3DSIH_DCL_INPUT_PRIMITIVE: -- case VKD3DSIH_DCL_INPUT_PS: -- case VKD3DSIH_DCL_INPUT_PS_SGV: -- case VKD3DSIH_DCL_INPUT_PS_SIV: -- case VKD3DSIH_DCL_INPUT_SGV: -- case VKD3DSIH_DCL_INPUT_SIV: -- case VKD3DSIH_DCL_INTERFACE: -- case VKD3DSIH_DCL_OUTPUT: -- case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT: -- case VKD3DSIH_DCL_OUTPUT_SGV: -- case VKD3DSIH_DCL_OUTPUT_SIV: -- case VKD3DSIH_DCL_OUTPUT_TOPOLOGY: -- case VKD3DSIH_DCL_RESOURCE_RAW: -- case VKD3DSIH_DCL_RESOURCE_STRUCTURED: -- case VKD3DSIH_DCL_SAMPLER: -- case VKD3DSIH_DCL_STREAM: -- case VKD3DSIH_DCL_TEMPS: -- case VKD3DSIH_DCL_TESSELLATOR_DOMAIN: -- case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE: -- case VKD3DSIH_DCL_TESSELLATOR_PARTITIONING: -- case VKD3DSIH_DCL_TGSM_RAW: -- case VKD3DSIH_DCL_TGSM_STRUCTURED: -- case VKD3DSIH_DCL_THREAD_GROUP: -- case VKD3DSIH_DCL_UAV_RAW: -- case VKD3DSIH_DCL_UAV_STRUCTURED: -- case VKD3DSIH_DCL_UAV_TYPED: -- case VKD3DSIH_DCL_VERTICES_OUT: -- case VKD3DSIH_DEF: -- case VKD3DSIH_DEFAULT: -- case VKD3DSIH_DEFB: -- case VKD3DSIH_DEFI: -- case VKD3DSIH_DEQO: -- case VKD3DSIH_DGEO: -- case VKD3DSIH_DISCARD: -- case VKD3DSIH_DLT: -- case VKD3DSIH_DNE: -- case VKD3DSIH_DP2: -- case VKD3DSIH_DP2ADD: -- case VKD3DSIH_DP3: -- case VKD3DSIH_DP4: -- case VKD3DSIH_DST: -- case VKD3DSIH_DTOF: -- case VKD3DSIH_DTOI: -- case VKD3DSIH_DTOU: -- case VKD3DSIH_ELSE: -- case VKD3DSIH_EMIT: -- case VKD3DSIH_EMIT_STREAM: -- case VKD3DSIH_ENDIF: -- case VKD3DSIH_ENDLOOP: -- case VKD3DSIH_ENDREP: -- case VKD3DSIH_ENDSWITCH: -- case VKD3DSIH_FCALL: -- case VKD3DSIH_HS_CONTROL_POINT_PHASE: -- case VKD3DSIH_HS_DECLS: -- case VKD3DSIH_HS_FORK_PHASE: -- case VKD3DSIH_HS_JOIN_PHASE: -- case VKD3DSIH_IF: -- case VKD3DSIH_IFC: ++ return true; ++ ++ /* Atomics can't have a writemask. */ + case VSIR_OP_ATOMIC_AND: + case VSIR_OP_ATOMIC_CMP_STORE: + case VSIR_OP_ATOMIC_IADD: @@ -7269,29 +12897,8 @@ index c26077e43d9..9b44925888b 100644 + case VSIR_OP_HS_JOIN_PHASE: + case VSIR_OP_IF: + case VSIR_OP_IFC: - /* It's unclear if any mapping is done for the source value. - * Does it require replicate swizzle? */ -- case VKD3DSIH_IMM_ATOMIC_ALLOC: -- case VKD3DSIH_IMM_ATOMIC_AND: -- case VKD3DSIH_IMM_ATOMIC_CMP_EXCH: -- case VKD3DSIH_IMM_ATOMIC_CONSUME: -- case VKD3DSIH_IMM_ATOMIC_EXCH: -- case VKD3DSIH_IMM_ATOMIC_IADD: -- case VKD3DSIH_IMM_ATOMIC_IMAX: -- case VKD3DSIH_IMM_ATOMIC_IMIN: -- case VKD3DSIH_IMM_ATOMIC_OR: -- case VKD3DSIH_IMM_ATOMIC_UMAX: -- case VKD3DSIH_IMM_ATOMIC_UMIN: -- case VKD3DSIH_IMM_ATOMIC_XOR: -- case VKD3DSIH_LABEL: -- case VKD3DSIH_LOOP: -- case VKD3DSIH_LIT: -- case VKD3DSIH_M3x2: -- case VKD3DSIH_M3x3: -- case VKD3DSIH_M3x4: -- case VKD3DSIH_M4x3: -- case VKD3DSIH_M4x4: -- case VKD3DSIH_NOP: ++ /* It's unclear if any mapping is done for the source value. ++ * Does it require replicate swizzle? */ + case VSIR_OP_IMM_ATOMIC_ALLOC: + case VSIR_OP_IMM_ATOMIC_AND: + case VSIR_OP_IMM_ATOMIC_CMP_EXCH: @@ -7313,52 +12920,13 @@ index c26077e43d9..9b44925888b 100644 + case VSIR_OP_M4x3: + case VSIR_OP_M4x4: + case VSIR_OP_NOP: - /* NRM writemask must be .xyz or .xyzw. */ -- case VKD3DSIH_NRM: -- case VKD3DSIH_PHASE: -- case VKD3DSIH_REP: -- case VKD3DSIH_RET: -- case VKD3DSIH_RETP: ++ /* NRM writemask must be .xyz or .xyzw. */ + case VSIR_OP_NRM: + case VSIR_OP_PHASE: + case VSIR_OP_REP: + case VSIR_OP_RET: + case VSIR_OP_RETP: - /* Store instructions always require a trivial writemask. */ -- case VKD3DSIH_STORE_RAW: -- case VKD3DSIH_STORE_STRUCTURED: -- case VKD3DSIH_STORE_UAV_TYPED: -- case VKD3DSIH_SWITCH: -- case VKD3DSIH_SWITCH_MONOLITHIC: -- case VKD3DSIH_SYNC: -- case VKD3DSIH_TEX: -- case VKD3DSIH_TEXBEM: -- case VKD3DSIH_TEXBEML: -- case VKD3DSIH_TEXCOORD: -- case VKD3DSIH_TEXCRD: -- case VKD3DSIH_TEXDEPTH: -- case VKD3DSIH_TEXDP3: -- case VKD3DSIH_TEXDP3TEX: -- case VKD3DSIH_TEXKILL: -- case VKD3DSIH_TEXLD: -- case VKD3DSIH_TEXLDD: -- case VKD3DSIH_TEXLDL: -- case VKD3DSIH_TEXM3x2DEPTH: -- case VKD3DSIH_TEXM3x2PAD: -- case VKD3DSIH_TEXM3x2TEX: -- case VKD3DSIH_TEXM3x3: -- case VKD3DSIH_TEXM3x3DIFF: -- case VKD3DSIH_TEXM3x3PAD: -- case VKD3DSIH_TEXM3x3SPEC: -- case VKD3DSIH_TEXM3x3TEX: -- case VKD3DSIH_TEXM3x3VSPEC: -- case VKD3DSIH_TEXREG2AR: -- case VKD3DSIH_TEXREG2GB: -- case VKD3DSIH_TEXREG2RGB: -- case VKD3DSIH_WAVE_ACTIVE_BALLOT: -- case VKD3DSIH_WAVE_ALL_BIT_COUNT: -- case VKD3DSIH_WAVE_IS_FIRST_LANE: -- case VKD3DSIH_WAVE_PREFIX_BIT_COUNT: ++ /* Store instructions always require a trivial writemask. */ + case VSIR_OP_STORE_RAW: + case VSIR_OP_STORE_STRUCTURED: + case VSIR_OP_STORE_UAV_TYPED: @@ -7393,54 +12961,28 @@ index c26077e43d9..9b44925888b 100644 + case VSIR_OP_WAVE_ALL_BIT_COUNT: + case VSIR_OP_WAVE_IS_FIRST_LANE: + case VSIR_OP_WAVE_PREFIX_BIT_COUNT: - return false; - -- case VKD3DSIH_QUAD_READ_LANE_AT: -- case VKD3DSIH_WAVE_READ_LANE_AT: ++ return false; ++ + case VSIR_OP_QUAD_READ_LANE_AT: + case VSIR_OP_WAVE_READ_LANE_AT: - return (src_idx == 0); - - /* sm4 resource instructions are an odd case, since they're not actually -@@ -8124,48 +8231,48 @@ static bool vsir_src_is_masked(enum vkd3d_shader_opcode opcode, unsigned int src - /* FIXME: The documentation seems to say that these instructions behave - * this way, but is it correct? - * (It's silent about EVAL_*, but presumably they behave the same way.) */ -- case VKD3DSIH_EVAL_CENTROID: -- case VKD3DSIH_EVAL_SAMPLE_INDEX: -- case VKD3DSIH_SAMPLE_INFO: -- case VKD3DSIH_SAMPLE_POS: ++ return (src_idx == 0); ++ ++ /* sm4 resource instructions are an odd case, since they're not actually ++ * per-component. However, the "swizzle" placed on the resource allows ++ * arbitrary destination writemasks to be used. ++ * ++ * This means that for the purposes of the "remapping" done by ++ * temp_allocator_set_dst(), we can basically treat those sources as ++ * "mapped", altering them when we reassign the destination writemask. */ ++ ++ /* FIXME: The documentation seems to say that these instructions behave ++ * this way, but is it correct? ++ * (It's silent about EVAL_*, but presumably they behave the same way.) */ + case VSIR_OP_EVAL_CENTROID: + case VSIR_OP_EVAL_SAMPLE_INDEX: + case VSIR_OP_SAMPLE_INFO: + case VSIR_OP_SAMPLE_POS: - return (src_idx == 0); -- case VKD3DSIH_GATHER4: -- case VKD3DSIH_GATHER4_C: -- case VKD3DSIH_GATHER4_C_S: -- case VKD3DSIH_GATHER4_S: -- case VKD3DSIH_LD: -- case VKD3DSIH_LD2DMS: -- case VKD3DSIH_LD2DMS_S: -- case VKD3DSIH_LD_RAW: -- case VKD3DSIH_LD_RAW_S: -- case VKD3DSIH_LD_S: -- case VKD3DSIH_LD_UAV_TYPED: -- case VKD3DSIH_LD_UAV_TYPED_S: -- case VKD3DSIH_LOD: -- case VKD3DSIH_RESINFO: -- case VKD3DSIH_SAMPLE: -- case VKD3DSIH_SAMPLE_B: -- case VKD3DSIH_SAMPLE_B_CL_S: -- case VKD3DSIH_SAMPLE_C: -- case VKD3DSIH_SAMPLE_CL_S: -- case VKD3DSIH_SAMPLE_C_CL_S: -- case VKD3DSIH_SAMPLE_C_LZ: -- case VKD3DSIH_SAMPLE_C_LZ_S: -- case VKD3DSIH_SAMPLE_GRAD: -- case VKD3DSIH_SAMPLE_GRAD_CL_S: -- case VKD3DSIH_SAMPLE_LOD: -- case VKD3DSIH_SAMPLE_LOD_S: ++ return (src_idx == 0); + case VSIR_OP_GATHER4: + case VSIR_OP_GATHER4_C: + case VSIR_OP_GATHER4_C_S: @@ -7467,65 +13009,71 @@ index c26077e43d9..9b44925888b 100644 + case VSIR_OP_SAMPLE_GRAD_CL_S: + case VSIR_OP_SAMPLE_LOD: + case VSIR_OP_SAMPLE_LOD_S: - return (src_idx == 1); -- case VKD3DSIH_GATHER4_PO: -- case VKD3DSIH_GATHER4_PO_C: -- case VKD3DSIH_GATHER4_PO_C_S: -- case VKD3DSIH_GATHER4_PO_S: -- case VKD3DSIH_LD_STRUCTURED: -- case VKD3DSIH_LD_STRUCTURED_S: ++ return (src_idx == 1); + case VSIR_OP_GATHER4_PO: + case VSIR_OP_GATHER4_PO_C: + case VSIR_OP_GATHER4_PO_C_S: + case VSIR_OP_GATHER4_PO_S: + case VSIR_OP_LD_STRUCTURED: + case VSIR_OP_LD_STRUCTURED_S: - return (src_idx == 2); - -- case VKD3DSIH_INVALID: -- case VKD3DSIH_COUNT: ++ return (src_idx == 2); ++ + case VSIR_OP_INVALID: + case VSIR_OP_COUNT: - break; - } - -@@ -8220,47 +8327,46 @@ static void liveness_track_dst(struct liveness_tracker *tracker, struct vkd3d_sh - - switch (opcode) - { -- case VKD3DSIH_BEM: -- case VKD3DSIH_CRS: -- case VKD3DSIH_DST: -- case VKD3DSIH_LIT: -- case VKD3DSIH_M3x2: -- case VKD3DSIH_M3x3: -- case VKD3DSIH_M3x4: -- case VKD3DSIH_M4x3: -- case VKD3DSIH_M4x4: -- case VKD3DSIH_NRM: -- case VKD3DSIH_TEX: -- case VKD3DSIH_TEXBEM: -- case VKD3DSIH_TEXBEML: -- case VKD3DSIH_TEXCOORD: -- case VKD3DSIH_TEXCRD: -- case VKD3DSIH_TEXDEPTH: -- case VKD3DSIH_TEXDP3: -- case VKD3DSIH_TEXDP3TEX: -- case VKD3DSIH_TEXLD: -- case VKD3DSIH_TEXLDD: -- case VKD3DSIH_TEXLDL: -- case VKD3DSIH_TEXM3x2DEPTH: -- case VKD3DSIH_TEXM3x2PAD: -- case VKD3DSIH_TEXM3x2TEX: -- case VKD3DSIH_TEXM3x3: -- case VKD3DSIH_TEXM3x3DIFF: -- case VKD3DSIH_TEXM3x3PAD: -- case VKD3DSIH_TEXM3x3SPEC: -- case VKD3DSIH_TEXM3x3TEX: -- case VKD3DSIH_TEXM3x3VSPEC: -- case VKD3DSIH_TEXREG2AR: -- case VKD3DSIH_TEXREG2GB: -- case VKD3DSIH_TEXREG2RGB: ++ break; ++ } ++ ++ vkd3d_unreachable(); ++} ++ ++struct liveness_tracker ++{ ++ struct liveness_tracker_reg ++ { ++ bool written; ++ bool fixed_mask; ++ uint8_t mask; ++ unsigned int first_write, last_access; ++ } *ssa_regs; ++}; ++ ++static void liveness_track_src(struct liveness_tracker *tracker, ++ struct vkd3d_shader_src_param *src, unsigned int index) ++{ ++ for (unsigned int k = 0; k < src->reg.idx_count; ++k) ++ { ++ if (src->reg.idx[k].rel_addr) ++ liveness_track_src(tracker, src->reg.idx[k].rel_addr, index); ++ } ++ ++ if (src->reg.type == VKD3DSPR_SSA) ++ tracker->ssa_regs[src->reg.idx[0].offset].last_access = index; ++} ++ ++static void liveness_track_dst(struct liveness_tracker *tracker, struct vkd3d_shader_dst_param *dst, ++ unsigned int index, const struct vkd3d_shader_version *version, enum vkd3d_shader_opcode opcode) ++{ ++ struct liveness_tracker_reg *reg; ++ ++ for (unsigned int k = 0; k < dst->reg.idx_count; ++k) ++ { ++ if (dst->reg.idx[k].rel_addr) ++ liveness_track_src(tracker, dst->reg.idx[k].rel_addr, index); ++ } ++ ++ if (dst->reg.type == VKD3DSPR_SSA) ++ reg = &tracker->ssa_regs[dst->reg.idx[0].offset]; ++ else ++ return; ++ ++ if (!reg->written) ++ reg->first_write = index; ++ reg->last_access = index; ++ reg->written = true; ++ reg->mask |= dst->write_mask; ++ ++ switch (opcode) ++ { + case VSIR_OP_BEM: + case VSIR_OP_CRS: + case VSIR_OP_DST: @@ -7559,66 +13107,275 @@ index c26077e43d9..9b44925888b 100644 + case VSIR_OP_TEXREG2AR: + case VSIR_OP_TEXREG2GB: + case VSIR_OP_TEXREG2RGB: - /* All of these instructions have fixed destinations—they can - * in some cases be masked, but the destination cannot be - * reallocated to a different set of components. */ -- case VKD3DSIH_IDIV: -- case VKD3DSIH_IMUL: -- case VKD3DSIH_SWAPC: -- case VKD3DSIH_UDIV: -- case VKD3DSIH_UMUL: ++ /* All of these instructions have fixed destinations—they can ++ * in some cases be masked, but the destination cannot be ++ * reallocated to a different set of components. */ + case VSIR_OP_IMUL: + case VSIR_OP_SWAPC: + case VSIR_OP_UDIV: + case VSIR_OP_UMUL: - /* These instructions don't have fixed destinations, but they have - * multiple destination and are per-component, meaning that the - * destination masks for each component have to match. -@@ -8271,7 +8377,7 @@ static void liveness_track_dst(struct liveness_tracker *tracker, struct vkd3d_sh - reg->fixed_mask = true; - break; - -- case VKD3DSIH_SINCOS: ++ /* These instructions don't have fixed destinations, but they have ++ * multiple destination and are per-component, meaning that the ++ * destination masks for each component have to match. ++ * This is a bit tricky to pull off, so for now we just force ++ * these to have a fixed mask as well. ++ * This assumes that the destination masks are equal to each other ++ * to begin with! */ ++ reg->fixed_mask = true; ++ break; ++ + case VSIR_OP_SINCOS: - /* sm1 has a fixed destination like LIT, NRM. - * sm4 is two-component and masked, like IMUL. */ - if (version->major < 3) -@@ -8310,12 +8416,12 @@ static enum vkd3d_result track_liveness(struct vsir_program *program, struct liv - { - const struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - -- if (ins->opcode == VKD3DSIH_LOOP || ins->opcode == VKD3DSIH_REP) ++ /* sm1 has a fixed destination like LIT, NRM. ++ * sm4 is two-component and masked, like IMUL. */ ++ if (version->major < 3) ++ { ++ /* We have the additional constraint here that sincos scratches ++ * whichever components of .xyz it doesn't write. We can achieve ++ * this by simply adding those components to reg->mask. */ ++ reg->mask |= 0x7; ++ } ++ reg->fixed_mask = true; ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static void liveness_tracker_cleanup(struct liveness_tracker *tracker) ++{ ++ vkd3d_free(tracker->ssa_regs); ++} ++ ++static enum vkd3d_result track_liveness(struct vsir_program *program, struct liveness_tracker *tracker) ++{ ++ struct liveness_tracker_reg *regs; ++ unsigned int loop_depth = 0; ++ unsigned int loop_start = 0; ++ ++ memset(tracker, 0, sizeof(*tracker)); ++ ++ if (!(regs = vkd3d_calloc(program->ssa_count, sizeof(*regs)))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ tracker->ssa_regs = regs; ++ ++ for (unsigned int i = 0; i < program->instructions.count; ++i) ++ { ++ const struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; ++ + if (ins->opcode == VSIR_OP_LOOP || ins->opcode == VSIR_OP_REP) - { - if (!loop_depth++) - loop_start = i; - } -- else if (ins->opcode == VKD3DSIH_ENDLOOP || ins->opcode == VKD3DSIH_ENDREP) ++ { ++ if (!loop_depth++) ++ loop_start = i; ++ } + else if (ins->opcode == VSIR_OP_ENDLOOP || ins->opcode == VSIR_OP_ENDREP) - { - if (!--loop_depth) - { -@@ -8494,23 +8600,23 @@ static bool vsir_opcode_is_double(enum vkd3d_shader_opcode opcode) ++ { ++ if (!--loop_depth) ++ { ++ /* Go through the allocator, find anything that was touched ++ * during the loop, and extend its liveness to the whole range ++ * of the loop. ++ * This isn't very sophisticated (e.g. we could try to avoid ++ * this for registers first written inside a loop body and only ++ * ever read inside one), but many of the cases that matter are ++ * affected by other optimizations such as copy propagation ++ * anyway. ++ * ++ * This is overkill for SSA registers. If an SSA register is ++ * written in loop L and last read in L, we don't need to touch ++ * its liveness. If it's last read in an inferior loop of L, we ++ * only need to extend its last-read to the end of L. (And it ++ * should be illegal for an SSA value to be read in a block ++ * containing L.) ++ * We don't try to perform this optimization yet, in the name of ++ * maximal simplicity, and also because this code is intended to ++ * be extended to non-SSA values. */ ++ for (unsigned int j = 0; j < program->ssa_count; ++j) ++ { ++ struct liveness_tracker_reg *reg = &tracker->ssa_regs[j]; ++ ++ if (reg->first_write > loop_start) ++ reg->first_write = loop_start; ++ if (reg->last_access < i) ++ reg->last_access = i; ++ } ++ } ++ } ++ ++ for (unsigned int j = 0; j < ins->dst_count; ++j) ++ liveness_track_dst(tracker, &ins->dst[j], i, &program->shader_version, ins->opcode); ++ for (unsigned int j = 0; j < ins->src_count; ++j) ++ liveness_track_src(tracker, &ins->src[j], i); ++ } ++ ++ return VKD3D_OK; ++} ++ ++struct temp_allocator ++{ ++ struct vkd3d_shader_message_context *message_context; ++ struct temp_allocator_reg ++ { ++ uint8_t allocated_mask; ++ uint32_t temp_id; ++ } *ssa_regs; ++ size_t allocated_ssa_count; ++ enum vkd3d_result result; ++}; ++ ++static uint8_t get_available_writemask(const struct temp_allocator *allocator, ++ struct liveness_tracker *tracker, unsigned int first_write, unsigned int last_access, uint32_t temp_id) ++{ ++ uint8_t writemask = VKD3DSP_WRITEMASK_ALL; ++ ++ for (size_t i = 0; i < allocator->allocated_ssa_count; ++i) ++ { ++ const struct temp_allocator_reg *reg = &allocator->ssa_regs[i]; ++ const struct liveness_tracker_reg *liveness_reg = &tracker->ssa_regs[i]; ++ ++ /* We do not overlap if first write == last read: ++ * this is the case where we are allocating the result of that ++ * expression, e.g. "add r0, r0, r1". */ ++ ++ if (reg->temp_id == temp_id ++ && first_write < liveness_reg->last_access ++ && last_access > liveness_reg->first_write) ++ writemask &= ~reg->allocated_mask; ++ ++ if (!writemask) ++ return writemask; ++ } ++ ++ return writemask; ++} ++ ++static void temp_allocator_allocate(struct temp_allocator *allocator, struct liveness_tracker *tracker, ++ struct temp_allocator_reg *reg, const struct liveness_tracker_reg *liveness_reg, uint32_t base_id) ++{ ++ if (!liveness_reg->written) ++ return; ++ ++ for (uint32_t id = base_id;; ++id) ++ { ++ uint8_t available_mask = get_available_writemask(allocator, tracker, ++ liveness_reg->first_write, liveness_reg->last_access, id); ++ ++ if (liveness_reg->fixed_mask) ++ { ++ if ((available_mask & liveness_reg->mask) == liveness_reg->mask) ++ { ++ reg->temp_id = id; ++ reg->allocated_mask = liveness_reg->mask; ++ return; ++ } ++ } ++ else ++ { ++ /* For SSA values the mask is always zero-based and contiguous. ++ * We don't correctly handle cases where it's not, currently. */ ++ VKD3D_ASSERT((liveness_reg->mask | (liveness_reg->mask - 1)) == liveness_reg->mask); ++ ++ if (vkd3d_popcount(available_mask) >= vkd3d_popcount(liveness_reg->mask)) ++ { ++ reg->temp_id = id; ++ reg->allocated_mask = vsir_combine_write_masks(available_mask, liveness_reg->mask); ++ return; ++ } ++ } ++ } ++} ++ ++static void temp_allocator_set_src(struct temp_allocator *allocator, struct vkd3d_shader_src_param *src) ++{ ++ struct temp_allocator_reg *reg; ++ ++ for (unsigned int k = 0; k < src->reg.idx_count; ++k) ++ { ++ if (src->reg.idx[k].rel_addr) ++ temp_allocator_set_src(allocator, src->reg.idx[k].rel_addr); ++ } ++ ++ if (src->reg.type == VKD3DSPR_SSA) ++ reg = &allocator->ssa_regs[src->reg.idx[0].offset]; ++ else ++ return; ++ ++ src->reg.type = VKD3DSPR_TEMP; ++ src->reg.idx[0].offset = reg->temp_id; ++ src->swizzle = vsir_combine_swizzles(vsir_swizzle_from_writemask(reg->allocated_mask), src->swizzle); ++} ++ ++static uint32_t vsir_map_swizzle(uint32_t swizzle, unsigned int writemask) ++{ ++ unsigned int src_component = 0; ++ uint32_t ret = 0; + +- if (!shader_instruction_array_insert_at(&program->instructions, pos, 2)) +- return VKD3D_ERROR_OUT_OF_MEMORY; +- ret = NULL; ++ /* Leave replicate swizzles alone; some instructions need them. */ ++ if (swizzle == VKD3D_SHADER_SWIZZLE(X, X, X, X) ++ || swizzle == VKD3D_SHADER_SWIZZLE(Y, Y, Y, Y) ++ || swizzle == VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z) ++ || swizzle == VKD3D_SHADER_SWIZZLE(W, W, W, W)) ++ return swizzle; + +- ins = &program->instructions.elements[pos]; ++ for (unsigned int dst_component = 0; dst_component < VKD3D_VEC4_SIZE; ++dst_component) ++ { ++ if (writemask & (1u << dst_component)) ++ vsir_swizzle_set_component(&ret, dst_component, vsir_swizzle_get_component(swizzle, src_component++)); ++ } ++ return ret; ++} + +- /* Write the fog output. */ +- vsir_instruction_init_with_params(program, ins, &loc, VKD3DSIH_MOV, 1, 1); +- dst_param_init_output(&ins->dst[0], VKD3D_DATA_FLOAT, fog_signature_idx, 0x1); +- src_param_init_temp_float4(&ins->src[0], temp); +- if (source == VKD3D_SHADER_FOG_SOURCE_Z) +- ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z); +- else /* Position or specular W. */ +- ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W); +- ++ins; ++static void vsir_remap_immconst(struct vkd3d_shader_src_param *src, unsigned int writemask) ++{ ++ union vsir_immediate_constant prev = src->reg.u; ++ unsigned int src_component = 0; + +- /* Write the position or specular output. */ +- vsir_instruction_init_with_params(program, ins, &loc, VKD3DSIH_MOV, 1, 1); +- dst_param_init_output(&ins->dst[0], vkd3d_data_type_from_component_type(e->component_type), +- source_signature_idx, e->mask); +- src_param_init_temp_float4(&ins->src[0], temp); +- ++ins; ++ for (unsigned int dst_component = 0; dst_component < VKD3D_VEC4_SIZE; ++dst_component) ++ { ++ if (writemask & (1u << dst_component)) ++ src->reg.u.immconst_u32[dst_component] = prev.immconst_u32[src_component++]; ++ } ++} + +- *ret_pos = pos + 2; +- return VKD3D_OK; ++static void vsir_remap_immconst64(struct vkd3d_shader_src_param *src, unsigned int writemask) ++{ ++ if (writemask == (VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3)) ++ src->reg.u.immconst_u64[1] = src->reg.u.immconst_u64[0]; + } + +-static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *program, +- struct vsir_transformation_context *ctx) ++static bool vsir_opcode_is_double(enum vkd3d_shader_opcode opcode) { - switch (opcode) - { -- case VKD3DSIH_DADD: -- case VKD3DSIH_DDIV: -- case VKD3DSIH_DFMA: -- case VKD3DSIH_DMAX: -- case VKD3DSIH_DMIN: -- case VKD3DSIH_DMOV: -- case VKD3DSIH_DMOVC: -- case VKD3DSIH_DMUL: -- case VKD3DSIH_DRCP: -- case VKD3DSIH_DEQO: -- case VKD3DSIH_DGEO: -- case VKD3DSIH_DLT: -- case VKD3DSIH_DNE: -- case VKD3DSIH_DTOF: -- case VKD3DSIH_DTOI: -- case VKD3DSIH_DTOU: -- case VKD3DSIH_FTOD: +- struct vkd3d_shader_message_context *message_context = ctx->message_context; +- const struct vkd3d_shader_parameter1 *source_parameter = NULL; +- uint32_t fog_signature_idx, source_signature_idx, temp; +- static const struct vkd3d_shader_location no_loc; +- enum vkd3d_shader_fog_source source; +- const struct signature_element *e; ++ switch (opcode) ++ { + case VSIR_OP_DADD: + case VSIR_OP_DDIV: + case VSIR_OP_DFMA: @@ -7636,49 +13393,235 @@ index c26077e43d9..9b44925888b 100644 + case VSIR_OP_DTOI: + case VSIR_OP_DTOU: + case VSIR_OP_FTOD: - return true; ++ return true; - default: -@@ -8622,16 +8728,16 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, +- if (!is_pre_rasterization_shader(program->shader_version.type)) +- return VKD3D_OK; ++ default: ++ return false; ++ } ++} + +- if (!(source_parameter = vsir_program_get_parameter(program, VKD3D_SHADER_PARAMETER_NAME_FOG_SOURCE))) +- return VKD3D_OK; ++static void temp_allocator_set_dst(struct temp_allocator *allocator, ++ struct vkd3d_shader_dst_param *dst, const struct vkd3d_shader_instruction *ins) ++{ ++ struct temp_allocator_reg *reg; + +- if (source_parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) ++ for (unsigned int k = 0; k < dst->reg.idx_count; ++k) + { +- vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, +- "Unsupported fog source parameter type %#x.", source_parameter->type); +- return VKD3D_ERROR_NOT_IMPLEMENTED; ++ if (dst->reg.idx[k].rel_addr) ++ temp_allocator_set_src(allocator, dst->reg.idx[k].rel_addr); + } +- if (source_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) ++ ++ if (dst->reg.type == VKD3DSPR_SSA) ++ reg = &allocator->ssa_regs[dst->reg.idx[0].offset]; ++ else ++ return; ++ ++ dst->reg.type = VKD3DSPR_TEMP; ++ dst->reg.idx[0].offset = reg->temp_id; ++ if (reg->allocated_mask != dst->write_mask) + { +- vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, +- "Invalid fog source parameter data type %#x.", source_parameter->data_type); +- return VKD3D_ERROR_INVALID_ARGUMENT; ++ dst->write_mask = reg->allocated_mask; ++ ++ if (vsir_opcode_is_double(ins->opcode)) ++ { ++ vkd3d_shader_error(allocator->message_context, &ins->location, ++ VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, "Doubles are not currently handled."); ++ allocator->result = VKD3D_ERROR_NOT_IMPLEMENTED; ++ } ++ ++ for (unsigned int i = 0; i < ins->src_count; ++i) ++ { ++ struct vkd3d_shader_src_param *src = &ins->src[i]; ++ ++ if (vsir_src_is_masked(ins->opcode, i)) ++ { ++ if (src->reg.type == VKD3DSPR_IMMCONST) ++ vsir_remap_immconst(src, dst->write_mask); ++ else if (src->reg.type == VKD3DSPR_IMMCONST64) ++ vsir_remap_immconst64(src, dst->write_mask); ++ else ++ src->swizzle = vsir_map_swizzle(src->swizzle, dst->write_mask); ++ } ++ } + } +- source = source_parameter->u.immediate_constant.u.u32; ++} + +- TRACE("Fog source %#x.\n", source); ++enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, ++ struct vkd3d_shader_message_context *message_context) ++{ ++ struct temp_allocator allocator = {0}; ++ struct temp_allocator_reg *regs; ++ struct liveness_tracker tracker; ++ uint32_t temp_count = 0; ++ enum vkd3d_result ret; + +- if (source == VKD3D_SHADER_FOG_SOURCE_FOG) ++ if (!program->ssa_count) + return VKD3D_OK; + +- if (source == VKD3D_SHADER_FOG_SOURCE_FOG_OR_SPECULAR_W) ++ if ((ret = track_liveness(program, &tracker))) ++ return ret; ++ ++ if (!(regs = vkd3d_calloc(program->ssa_count, sizeof(*regs)))) + { +- if (program->has_fog || !(e = vsir_signature_find_element_by_name(&program->output_signature, "COLOR", 1))) +- return VKD3D_OK; +- source_signature_idx = e - program->output_signature.elements; ++ liveness_tracker_cleanup(&tracker); ++ return VKD3D_ERROR_OUT_OF_MEMORY; + } +- else ++ allocator.message_context = message_context; ++ allocator.ssa_regs = regs; ++ ++ for (unsigned int i = 0; i < program->ssa_count; ++i) + { +- if (!vsir_signature_find_sysval(&program->output_signature, +- VKD3D_SHADER_SV_POSITION, 0, &source_signature_idx)) +- { +- vkd3d_shader_error(ctx->message_context, &no_loc, +- VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC, "Shader does not write position."); +- return VKD3D_ERROR_INVALID_SHADER; +- } ++ const struct liveness_tracker_reg *liveness_reg = &tracker.ssa_regs[i]; ++ struct temp_allocator_reg *reg = &allocator.ssa_regs[i]; ++ ++ temp_allocator_allocate(&allocator, &tracker, reg, liveness_reg, program->temp_count); ++ TRACE("Allocated r%u%s to sr%u (liveness %u-%u).\n", ++ reg->temp_id, debug_vsir_writemask(reg->allocated_mask), i, ++ liveness_reg->first_write, liveness_reg->last_access); ++ ++allocator.allocated_ssa_count; + } + +- if (!(e = vsir_signature_find_element_by_name(&program->output_signature, "FOG", 0))) ++ for (unsigned int i = 0; i < program->instructions.count; ++i) + { +- ERR("Fog output not found.\n"); +- return VKD3D_ERROR_INVALID_SHADER; +- } +- fog_signature_idx = e - program->output_signature.elements; ++ const struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; + +- temp = program->temp_count++; ++ /* Make sure we do the srcs first; setting the dst writemask may need ++ * to remap their swizzles. */ ++ for (unsigned int j = 0; j < ins->src_count; ++j) ++ temp_allocator_set_src(&allocator, &ins->src[j]); ++ for (unsigned int j = 0; j < ins->dst_count; ++j) ++ temp_allocator_set_dst(&allocator, &ins->dst[j], ins); ++ } + +- /* Insert a fog write before each ret, and convert either specular or +- * position output to a temp. */ +- for (size_t i = 0; i < program->instructions.count; ++i) ++ /* Rewrite dcl_temps to reflect the new temp count. ++ * Note that dcl_temps appears once per phase, and should reflect only the ++ * number of temps needed by that phase. ++ * Therefore we iterate backwards through the shader, finding the maximum ++ * register used by any instruction, update the dcl_temps at the beginning ++ * of each phase, and then reset the temp count back to 0 for the next ++ * phase (if any). */ ++ for (int i = program->instructions.count - 1; i >= 0; --i) { struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; -- if (ins->opcode == VKD3DSIH_DCL_TEMPS) +- if (vsir_instruction_is_dcl(ins)) + if (ins->opcode == VSIR_OP_DCL_TEMPS) - { - ins->declaration.count = temp_count; - temp_count = 0; ++ { ++ ins->declaration.count = temp_count; ++ temp_count = 0; continue; - } - if (temp_count && program->shader_version.major >= 4 -- && (ins->opcode == VKD3DSIH_HS_CONTROL_POINT_PHASE -- || ins->opcode == VKD3DSIH_HS_FORK_PHASE -- || ins->opcode == VKD3DSIH_HS_JOIN_PHASE)) +- +- if (ins->opcode == VKD3DSIH_RET) ++ } ++ if (temp_count && program->shader_version.major >= 4 + && (ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE + || ins->opcode == VSIR_OP_HS_FORK_PHASE + || ins->opcode == VSIR_OP_HS_JOIN_PHASE)) { - /* The phase didn't have a dcl_temps instruction, but we added - * temps here, so we need to insert one. */ -@@ -8643,7 +8749,7 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, - } +- size_t new_pos; +- int ret; ++ /* The phase didn't have a dcl_temps instruction, but we added ++ * temps here, so we need to insert one. */ ++ if (!shader_instruction_array_insert_at(&program->instructions, i + 1, 1)) ++ { ++ vkd3d_free(regs); ++ liveness_tracker_cleanup(&tracker); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ } - ins = &program->instructions.elements[i + 1]; -- vsir_instruction_init(ins, &program->instructions.elements[i].location, VKD3DSIH_DCL_TEMPS); +- if ((ret = insert_vertex_fog_before_ret(program, ins, source, temp, +- fog_signature_idx, source_signature_idx, &new_pos)) < 0) +- return ret; +- i = new_pos; ++ ins = &program->instructions.elements[i + 1]; + vsir_instruction_init(ins, &program->instructions.elements[i].location, VSIR_OP_DCL_TEMPS); - ins->declaration.count = temp_count; - temp_count = 0; ++ ins->declaration.count = temp_count; ++ temp_count = 0; continue; -@@ -8673,7 +8779,7 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, } - ins = &program->instructions.elements[0]; -- vsir_instruction_init(ins, &program->instructions.elements[1].location, VKD3DSIH_DCL_TEMPS); -+ vsir_instruction_init(ins, &program->instructions.elements[1].location, VSIR_OP_DCL_TEMPS); - ins->declaration.count = temp_count; +- for (size_t j = 0; j < ins->dst_count; ++j) ++ /* No need to check sources. If we've produced an unwritten source then ++ * that's a bug somewhere in this pass. */ ++ for (unsigned int j = 0; j < ins->dst_count; ++j) + { +- struct vkd3d_shader_dst_param *dst = &ins->dst[j]; +- +- /* Note we run after I/O normalization. */ +- if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == source_signature_idx) ++ if (ins->dst[j].reg.type == VKD3DSPR_TEMP) + { +- dst->reg.type = VKD3DSPR_TEMP; +- dst->reg.idx[0].offset = temp; ++ temp_count = max(temp_count, ins->dst[j].reg.idx[0].offset + 1); ++ program->temp_count = max(program->temp_count, temp_count); + } + } } -@@ -8936,10 +9042,10 @@ static const bool vsir_get_io_register_data(struct validation_context *ctx, +- program->has_fog = true; ++ if (temp_count && program->shader_version.major >= 4) ++ { ++ struct vkd3d_shader_instruction *ins; + +- return VKD3D_OK; ++ if (!shader_instruction_array_insert_at(&program->instructions, 0, 1)) ++ { ++ vkd3d_free(regs); ++ liveness_tracker_cleanup(&tracker); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ } ++ ++ ins = &program->instructions.elements[0]; ++ vsir_instruction_init(ins, &program->instructions.elements[1].location, VSIR_OP_DCL_TEMPS); ++ ins->declaration.count = temp_count; ++ } ++ ++ program->ssa_count = 0; ++ ++ vkd3d_free(regs); ++ liveness_tracker_cleanup(&tracker); ++ return allocator.result; + } + + struct validation_context +@@ -7538,10 +9079,10 @@ static const bool vsir_get_io_register_data(struct validation_context *ctx, switch (ctx->phase) { @@ -7693,18 +13636,323 @@ index c26077e43d9..9b44925888b 100644 default: vkd3d_unreachable(); -@@ -10472,6 +10578,7 @@ static void vsir_validate_logic_elementwise_operation(struct validation_context +@@ -7841,10 +9382,6 @@ static void vsir_validate_descriptor_indices(struct validation_context *ctx, + static void vsir_validate_constbuffer_register(struct validation_context *ctx, + const struct vkd3d_shader_register *reg) { - static const bool types[VKD3D_DATA_COUNT] = +- if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, +- "Invalid precision %#x for a CONSTBUFFER register.", reg->precision); +- + if (reg->dimension != VSIR_DIMENSION_VEC4) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, + "Invalid dimension %#x for a CONSTBUFFER register.", reg->dimension); +@@ -8242,15 +9779,37 @@ static void vsir_validate_dst_param(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Destination has invalid modifiers %#x.", + dst->modifiers); + ++ if (dst->modifiers & VKD3DSPDM_SATURATE) ++ { ++ switch (dst->reg.data_type) ++ { ++ case VKD3D_DATA_FLOAT: ++ case VKD3D_DATA_DOUBLE: ++ case VKD3D_DATA_HALF: ++ break; ++ ++ default: ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for destination with saturate modifier.", dst->reg.data_type); ++ break; ++ ++ } ++ } ++ + switch (dst->shift) { -+ [VKD3D_DATA_INT] = true, - [VKD3D_DATA_UINT] = true, - [VKD3D_DATA_UINT64] = true, - [VKD3D_DATA_BOOL] = true, -@@ -10526,6 +10633,17 @@ static void vsir_validate_double_comparison_operation(struct validation_context - vsir_validate_comparison_operation(ctx, instruction, types); + case 0: ++ break; ++ + case 1: + case 2: + case 3: + case 13: + case 14: + case 15: ++ if (dst->reg.data_type != VKD3D_DATA_FLOAT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for destination with shift.", dst->reg.data_type); + break; + + default: +@@ -8332,9 +9891,44 @@ static void vsir_validate_io_src_param(struct validation_context *ctx, + "Invalid register type %#x used as source parameter.", src->reg.type); } ++#define F64_BIT (1u << VKD3D_DATA_DOUBLE) ++#define F32_BIT (1u << VKD3D_DATA_FLOAT) ++#define F16_BIT (1u << VKD3D_DATA_HALF) ++ ++#define I32_BIT (1u << VKD3D_DATA_INT) ++ ++#define U64_BIT (1u << VKD3D_DATA_UINT64) ++#define U32_BIT (1u << VKD3D_DATA_UINT) ++#define U16_BIT (1u << VKD3D_DATA_UINT16) ++ + static void vsir_validate_src_param(struct validation_context *ctx, + const struct vkd3d_shader_src_param *src) + { ++ static const struct ++ { ++ uint32_t data_type_mask; ++ } ++ src_modifier_data[VKD3DSPSM_COUNT] = ++ { ++ [VKD3DSPSM_NEG] = {F64_BIT | F32_BIT | F16_BIT | I32_BIT | U64_BIT | U32_BIT | U16_BIT}, ++ [VKD3DSPSM_BIAS] = {F32_BIT}, ++ [VKD3DSPSM_BIASNEG] = {F32_BIT}, ++ [VKD3DSPSM_SIGN] = {F32_BIT}, ++ [VKD3DSPSM_SIGNNEG] = {F32_BIT}, ++ [VKD3DSPSM_COMP] = {F32_BIT}, ++ [VKD3DSPSM_X2] = {F32_BIT}, ++ [VKD3DSPSM_X2NEG] = {F32_BIT}, ++ [VKD3DSPSM_DZ] = {F32_BIT}, ++ [VKD3DSPSM_DW] = {F32_BIT}, ++ [VKD3DSPSM_ABS] = {F64_BIT | F32_BIT | F16_BIT}, ++ [VKD3DSPSM_ABSNEG] = {F64_BIT | F32_BIT | F16_BIT}, ++ /* This doesn't make a lot of sense. NOT is used only by D3DBC, and ++ * apparently only for IF instructions reading from a CONSTBOOL register. ++ * However, currently the D3DBC parser generates those registers of ++ * type float, so for the moment let's allow that. */ ++ [VKD3DSPSM_NOT] = {F32_BIT}, ++ }; ++ + vsir_validate_register(ctx, &src->reg); + + if (src->swizzle & ~0x03030303u) +@@ -8349,6 +9943,13 @@ static void vsir_validate_src_param(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", + src->modifiers); + ++ if (src->modifiers != VKD3DSPSM_NONE && src->modifiers < ARRAY_SIZE(src_modifier_data)) ++ { ++ if (!(src_modifier_data[src->modifiers].data_type_mask & (1u << src->reg.data_type))) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, ++ "Source has invalid modifier %#x for data type %u.", src->modifiers, src->reg.data_type); ++ } ++ + switch (src->reg.type) + { + case VKD3DSPR_SSA: +@@ -8400,8 +10001,9 @@ static void vsir_validate_dst_count(struct validation_context *ctx, + { + if (instruction->dst_count != count) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, +- "Invalid destination count %u for an instruction of type %#x, expected %u.", +- instruction->dst_count, instruction->opcode, count); ++ "Invalid destination parameter count %u for instruction \"%s\" (%#x); expected %u.", ++ instruction->dst_count, vsir_opcode_get_name(instruction->opcode, ""), ++ instruction->opcode, count); + } + + static void vsir_validate_src_count(struct validation_context *ctx, +@@ -8409,8 +10011,9 @@ static void vsir_validate_src_count(struct validation_context *ctx, + { + if (instruction->src_count != count) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, +- "Invalid source count %u for an instruction of type %#x, expected %u.", +- instruction->src_count, instruction->opcode, count); ++ "Invalid source parameter count %u for instruction \"%s\" (%#x); expected %u.", ++ instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), ++ instruction->opcode, count); + } + + static bool vsir_validate_src_min_count(struct validation_context *ctx, +@@ -8419,8 +10022,9 @@ static bool vsir_validate_src_min_count(struct validation_context *ctx, + if (instruction->src_count < count) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, +- "Invalid source count %u for an instruction of type %#x, expected at least %u.", +- instruction->src_count, instruction->opcode, count); ++ "Invalid source parameter count %u for instruction \"%s\" (%#x); expected at least %u.", ++ instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), ++ instruction->opcode, count); + return false; + } + +@@ -8433,8 +10037,9 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx, + if (instruction->src_count > count) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, +- "Invalid source count %u for an instruction of type %#x, expected at most %u.", +- instruction->src_count, instruction->opcode, count); ++ "Invalid source parameter count %u for instruction \"%s\" (%#x); expected at most %u.", ++ instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), ++ instruction->opcode, count); + return false; + } + +@@ -8922,7 +10527,9 @@ static void vsir_validate_cf_type(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction, enum vsir_control_flow_type expected_type) + { + if (ctx->program->cf_type != expected_type) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x in %s shader.", ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, ++ "Invalid instruction \"%s\" (%#x) in %s shader.", ++ vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, name_from_cf_type(ctx->program->cf_type)); + } + +@@ -8940,17 +10547,171 @@ static void vsir_validate_hull_shader_phase(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) + { + if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, +- "Phase instruction %#x is only valid in a hull shader.", +- instruction->opcode); ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE, ++ "Phase instruction \"%s\" (%#x) is only valid in a hull shader.", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + if (ctx->depth != 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, +- "Phase instruction %#x must appear to top level.", +- instruction->opcode); ++ "Phase instruction \"%s\" (%#x) must appear at the top level.", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + ctx->phase = instruction->opcode; + ctx->dcl_temps_found = false; + } + ++static void vsir_validate_elementwise_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction, const bool types[VKD3D_DATA_COUNT]) ++{ ++ enum vkd3d_data_type dst_data_type; ++ unsigned int i; ++ ++ if (instruction->dst_count < 1) ++ return; ++ ++ dst_data_type = instruction->dst[0].reg.data_type; ++ ++ if (dst_data_type >= VKD3D_DATA_COUNT) ++ return; ++ ++ if (!types[dst_data_type]) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for elementwise operation \"%s\" (%#x).", ++ dst_data_type, vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); ++ ++ for (i = 0; i < instruction->src_count; ++i) ++ { ++ if (instruction->src[i].reg.data_type != dst_data_type) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Data type %#x for operand %u doesn't match the destination data type %#x " ++ "for elementwise operation \"%s\" (%#x).", ++ instruction->src[i].reg.data_type, i, dst_data_type, ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); ++ } ++} ++ ++static void vsir_validate_double_elementwise_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VKD3D_DATA_COUNT] = ++ { ++ [VKD3D_DATA_DOUBLE] = true, ++ }; ++ ++ vsir_validate_elementwise_operation(ctx, instruction, types); ++} ++ ++static void vsir_validate_float_elementwise_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VKD3D_DATA_COUNT] = ++ { ++ [VKD3D_DATA_FLOAT] = true, ++ }; ++ ++ vsir_validate_elementwise_operation(ctx, instruction, types); ++} ++ ++static void vsir_validate_integer_elementwise_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VKD3D_DATA_COUNT] = ++ { ++ [VKD3D_DATA_INT] = true, ++ [VKD3D_DATA_UINT] = true, ++ [VKD3D_DATA_UINT64] = true, ++ }; ++ ++ vsir_validate_elementwise_operation(ctx, instruction, types); ++} ++ ++static void vsir_validate_logic_elementwise_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VKD3D_DATA_COUNT] = ++ { ++ [VKD3D_DATA_INT] = true, ++ [VKD3D_DATA_UINT] = true, ++ [VKD3D_DATA_UINT64] = true, ++ [VKD3D_DATA_BOOL] = true, ++ }; ++ ++ vsir_validate_elementwise_operation(ctx, instruction, types); ++} ++ ++static void vsir_validate_comparison_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction, const bool types[VKD3D_DATA_COUNT]) ++{ ++ enum vkd3d_data_type dst_data_type, src_data_type; ++ unsigned int i; ++ ++ if (instruction->dst_count < 1) ++ return; ++ ++ dst_data_type = instruction->dst[0].reg.data_type; ++ ++ if (dst_data_type != VKD3D_DATA_UINT && dst_data_type != VKD3D_DATA_BOOL) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for result of comparison operation \"%s\" (%#x).", ++ dst_data_type, vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); ++ ++ if (instruction->src_count == 0) ++ return; ++ ++ src_data_type = instruction->src[0].reg.data_type; ++ ++ if (src_data_type >= VKD3D_DATA_COUNT) ++ return; ++ ++ if (!types[src_data_type]) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid data type %#x for comparison operation \"%s\" (%#x).", ++ src_data_type, vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); ++ ++ for (i = 1; i < instruction->src_count; ++i) ++ { ++ if (instruction->src[i].reg.data_type != src_data_type) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Data type %#x for operand %u doesn't match the first operands data type %#x " ++ "for comparison operation \"%s\" (%#x).", ++ instruction->src[i].reg.data_type, i, src_data_type, ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); ++ } ++} ++ ++static void vsir_validate_double_comparison_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VKD3D_DATA_COUNT] = ++ { ++ [VKD3D_DATA_DOUBLE] = true, ++ }; ++ ++ vsir_validate_comparison_operation(ctx, instruction, types); ++} ++ +static void vsir_validate_float_comparison_operation(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) +{ @@ -7715,11 +13963,33 @@ index c26077e43d9..9b44925888b 100644 + + vsir_validate_comparison_operation(ctx, instruction, types); +} ++ ++static void vsir_validate_integer_comparison_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VKD3D_DATA_COUNT] = ++ { ++ [VKD3D_DATA_INT] = true, ++ [VKD3D_DATA_UINT] = true, ++ [VKD3D_DATA_UINT64] = true, ++ }; ++ ++ vsir_validate_comparison_operation(ctx, instruction, types); ++} + static void vsir_validate_branch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) { size_t i; -@@ -10991,18 +11109,18 @@ static void vsir_validate_dcl_vertices_out(struct validation_context *ctx, +@@ -9026,7 +10787,7 @@ static void vsir_validate_dcl_index_range(struct validation_context *ctx, + + if (ctx->program->normalisation_level >= VSIR_NORMALISED_SM6) + { +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE, + "DCL_INDEX_RANGE is not allowed with fully normalised input/output."); + return; + } +@@ -9416,18 +11177,18 @@ static void vsir_validate_dcl_vertices_out(struct validation_context *ctx, static void vsir_validate_else(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) { vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED); @@ -7742,7 +14012,7 @@ index c26077e43d9..9b44925888b 100644 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ENDIF instruction doesn't terminate IF/ELSE block."); else -@@ -11012,7 +11130,7 @@ static void vsir_validate_endif(struct validation_context *ctx, const struct vkd +@@ -9437,7 +11198,7 @@ static void vsir_validate_endif(struct validation_context *ctx, const struct vkd static void vsir_validate_endloop(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) { vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED); @@ -7751,7 +14021,7 @@ index c26077e43d9..9b44925888b 100644 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ENDLOOP instruction doesn't terminate LOOP block."); else -@@ -11022,7 +11140,7 @@ static void vsir_validate_endloop(struct validation_context *ctx, const struct v +@@ -9447,7 +11208,7 @@ static void vsir_validate_endloop(struct validation_context *ctx, const struct v static void vsir_validate_endrep(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) { vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED); @@ -7760,7 +14030,7 @@ index c26077e43d9..9b44925888b 100644 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ENDREP instruction doesn't terminate REP block."); else -@@ -11032,7 +11150,7 @@ static void vsir_validate_endrep(struct validation_context *ctx, const struct vk +@@ -9457,7 +11218,7 @@ static void vsir_validate_endrep(struct validation_context *ctx, const struct vk static void vsir_validate_endswitch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) { vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED); @@ -7769,7 +14039,7 @@ index c26077e43d9..9b44925888b 100644 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ENDSWITCH instruction doesn't terminate SWITCH block."); else -@@ -11042,13 +11160,13 @@ static void vsir_validate_endswitch(struct validation_context *ctx, const struct +@@ -9467,13 +11228,13 @@ static void vsir_validate_endswitch(struct validation_context *ctx, const struct static void vsir_validate_if(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) { vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED); @@ -7785,7 +14055,7 @@ index c26077e43d9..9b44925888b 100644 } static void vsir_validate_label(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) -@@ -11069,7 +11187,7 @@ static void vsir_validate_loop(struct validation_context *ctx, const struct vkd3 +@@ -9494,7 +11255,7 @@ static void vsir_validate_loop(struct validation_context *ctx, const struct vkd3 { vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED); vsir_validate_src_count(ctx, instruction, ctx->program->shader_version.major <= 3 ? 2 : 0); @@ -7794,7 +14064,7 @@ index c26077e43d9..9b44925888b 100644 } static void vsir_validate_nop(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) -@@ -11139,7 +11257,7 @@ static void vsir_validate_phi(struct validation_context *ctx, const struct vkd3d +@@ -9564,7 +11325,7 @@ static void vsir_validate_phi(struct validation_context *ctx, const struct vkd3d static void vsir_validate_rep(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) { vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED); @@ -7803,7 +14073,7 @@ index c26077e43d9..9b44925888b 100644 } static void vsir_validate_ret(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) -@@ -11150,7 +11268,7 @@ static void vsir_validate_ret(struct validation_context *ctx, const struct vkd3d +@@ -9575,7 +11336,7 @@ static void vsir_validate_ret(struct validation_context *ctx, const struct vkd3d static void vsir_validate_switch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) { vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED); @@ -7812,35 +14082,11 @@ index c26077e43d9..9b44925888b 100644 } static void vsir_validate_switch_monolithic(struct validation_context *ctx, -@@ -11211,69 +11329,77 @@ struct vsir_validator_instruction_desc +@@ -9636,45 +11397,84 @@ struct vsir_validator_instruction_desc static const struct vsir_validator_instruction_desc vsir_validator_instructions[] = { -- [VKD3DSIH_ABS] = {1, 1, vsir_validate_float_elementwise_operation}, -- [VKD3DSIH_ACOS] = {1, 1, vsir_validate_float_elementwise_operation}, -- [VKD3DSIH_ADD] = {1, 2, vsir_validate_float_elementwise_operation}, -- [VKD3DSIH_AND] = {1, 2, vsir_validate_logic_elementwise_operation}, -- [VKD3DSIH_ASIN] = {1, 1, vsir_validate_float_elementwise_operation}, -- [VKD3DSIH_ATAN] = {1, 1, vsir_validate_float_elementwise_operation}, - [VKD3DSIH_BRANCH] = {0, ~0u, vsir_validate_branch}, -- [VKD3DSIH_DADD] = {1, 2, vsir_validate_double_elementwise_operation}, -- [VKD3DSIH_DDIV] = {1, 2, vsir_validate_double_elementwise_operation}, -- [VKD3DSIH_DFMA] = {1, 3, vsir_validate_double_elementwise_operation}, -- [VKD3DSIH_DGEO] = {1, 2, vsir_validate_double_comparison_operation}, -- [VKD3DSIH_DIV] = {1, 2, vsir_validate_float_elementwise_operation}, -- [VKD3DSIH_DLT] = {1, 2, vsir_validate_double_comparison_operation}, -- [VKD3DSIH_DMAX] = {1, 2, vsir_validate_double_elementwise_operation}, -- [VKD3DSIH_DMIN] = {1, 2, vsir_validate_double_elementwise_operation}, -- [VKD3DSIH_DMOV] = {1, 1, vsir_validate_double_elementwise_operation}, -- [VKD3DSIH_DMUL] = {1, 2, vsir_validate_double_elementwise_operation}, -- [VKD3DSIH_DNE] = {1, 2, vsir_validate_double_comparison_operation}, -- [VKD3DSIH_DRCP] = {1, 1, vsir_validate_double_elementwise_operation}, -- [VKD3DSIH_DSX] = {1, 1, vsir_validate_float_elementwise_operation}, -- [VKD3DSIH_DSX_COARSE] = {1, 1, vsir_validate_float_elementwise_operation}, -- [VKD3DSIH_DSX_FINE] = {1, 1, vsir_validate_float_elementwise_operation}, -- [VKD3DSIH_DSY] = {1, 1, vsir_validate_float_elementwise_operation}, -- [VKD3DSIH_DSY_COARSE] = {1, 1, vsir_validate_float_elementwise_operation}, -- [VKD3DSIH_DSY_FINE] = {1, 1, vsir_validate_float_elementwise_operation}, - [VKD3DSIH_HS_CONTROL_POINT_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, - [VKD3DSIH_HS_DECLS] = {0, 0, vsir_validate_hull_shader_phase}, - [VKD3DSIH_HS_FORK_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, @@ -7912,10 +14158,17 @@ index c26077e43d9..9b44925888b 100644 + [VSIR_OP_FREM] = {1, 2, vsir_validate_float_elementwise_operation}, + [VSIR_OP_GEO] = {1, 2, vsir_validate_float_comparison_operation}, + [VSIR_OP_GEU] = {1, 2, vsir_validate_float_comparison_operation}, ++ [VSIR_OP_HCOS] = {1, 1, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_HSIN] = {1, 1, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_HTAN] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_HS_CONTROL_POINT_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, + [VSIR_OP_HS_DECLS] = {0, 0, vsir_validate_hull_shader_phase}, + [VSIR_OP_HS_FORK_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, + [VSIR_OP_HS_JOIN_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, ++ [VSIR_OP_IADD] = {1, 2, vsir_validate_integer_elementwise_operation}, ++ [VSIR_OP_IEQ] = {1, 2, vsir_validate_integer_comparison_operation}, ++ [VSIR_OP_IGE] = {1, 2, vsir_validate_integer_comparison_operation}, ++ [VSIR_OP_ILT] = {1, 2, vsir_validate_integer_comparison_operation}, + [VSIR_OP_DCL_GS_INSTANCES] = {0, 0, vsir_validate_dcl_gs_instances}, + [VSIR_OP_DCL_HS_MAX_TESSFACTOR] = {0, 0, vsir_validate_dcl_hs_max_tessfactor}, + [VSIR_OP_DCL_INDEX_RANGE] = {0, 0, vsir_validate_dcl_index_range}, @@ -7953,15 +14206,17 @@ index c26077e43d9..9b44925888b 100644 }; static void vsir_validate_instruction(struct validation_context *ctx) -@@ -11290,21 +11416,21 @@ static void vsir_validate_instruction(struct validation_context *ctx) +@@ -9691,28 +11491,28 @@ static void vsir_validate_instruction(struct validation_context *ctx) for (i = 0; i < instruction->src_count; ++i) vsir_validate_src_param(ctx, &instruction->src[i]); - if (instruction->opcode >= VKD3DSIH_INVALID) + if (instruction->opcode >= VSIR_OP_INVALID) { - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE, - "Invalid opcode %#x.", instruction->opcode); +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Invalid instruction handler %#x.", +- instruction->opcode); ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE, ++ "Invalid opcode %#x.", instruction->opcode); } - if (version->type == VKD3D_SHADER_TYPE_HULL && ctx->phase == VKD3DSIH_INVALID) @@ -7982,7 +14237,17 @@ index c26077e43d9..9b44925888b 100644 break; default: -@@ -11320,12 +11446,12 @@ static void vsir_validate_instruction(struct validation_context *ctx) + if (!vsir_instruction_is_dcl(instruction)) +- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, +- "Instruction %#x appear before any phase instruction in a hull shader.", +- instruction->opcode); ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE, ++ "Instruction \"%s\" (%#x) appears before any phase instruction in a hull shader.", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + break; + } + } +@@ -9721,19 +11521,19 @@ static void vsir_validate_instruction(struct validation_context *ctx) { switch (instruction->opcode) { @@ -8001,7 +14266,16 @@ index c26077e43d9..9b44925888b 100644 break; default: -@@ -11363,7 +11489,7 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c + if (!vsir_instruction_is_dcl(instruction)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, +- "Invalid instruction %#x outside any block.", +- instruction->opcode); ++ "Invalid instruction \"%s\" (%#x) outside any block.", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + break; + } + } +@@ -9764,7 +11564,7 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c .program = program, .null_location = {.source_name = source_name}, .status = VKD3D_OK, @@ -8011,53 +14285,501 @@ index c26077e43d9..9b44925888b 100644 .outer_tess_idxs[0] = ~0u, .outer_tess_idxs[1] = ~0u, diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index 87c9e989ea4..2a209323de7 100644 +index 4f37468af86..032b5504319 100644 --- a/libs/vkd3d/libs/vkd3d-shader/msl.c +++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -836,6 +836,12 @@ static void msl_break(struct msl_generator *gen) - vkd3d_string_buffer_printf(gen->buffer, "break;\n"); +@@ -48,19 +48,29 @@ struct msl_generator + const char *prefix; + bool failed; + +- bool write_depth; ++ bool read_vertex_id; + + const struct vkd3d_shader_interface_info *interface_info; + }; + + struct msl_resource_type_info + { +- size_t read_coord_size; ++ /* The number of coordinates needed to address/sample the resource type. */ ++ size_t coord_size; ++ /* Whether the resource type is an array type. */ + bool array; +- bool lod; ++ /* Whether the resource type has a shadow/comparison variant. */ ++ bool comparison; ++ /* Whether the resource type supports texel sample offsets. */ ++ bool offset; ++ /* The type suffix for the resource type. I.e., the "2d_ms" part of ++ * "texture2d_ms_array" or "depth2d_ms_array". */ + const char *type_suffix; + }; + ++static void msl_print_subscript(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, ++ const struct vkd3d_shader_src_param *rel_addr, unsigned int offset); ++ + static void VKD3D_PRINTF_FUNC(3, 4) msl_compiler_error(struct msl_generator *gen, + enum vkd3d_shader_error error, const char *fmt, ...) + { +@@ -76,17 +86,17 @@ static const struct msl_resource_type_info *msl_get_resource_type_info(enum vkd3 + { + static const struct msl_resource_type_info info[] = + { +- [VKD3D_SHADER_RESOURCE_NONE] = {0, false, false, "none"}, +- [VKD3D_SHADER_RESOURCE_BUFFER] = {1, false, false, "_buffer"}, +- [VKD3D_SHADER_RESOURCE_TEXTURE_1D] = {1, false, false, "1d"}, +- [VKD3D_SHADER_RESOURCE_TEXTURE_2D] = {2, false, true, "2d"}, +- [VKD3D_SHADER_RESOURCE_TEXTURE_2DMS] = {2, false, false, "2d_ms"}, +- [VKD3D_SHADER_RESOURCE_TEXTURE_3D] = {3, false, true, "3d"}, +- [VKD3D_SHADER_RESOURCE_TEXTURE_CUBE] = {2, false, true, "cube"}, +- [VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY] = {1, true, false, "1d_array"}, +- [VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY] = {2, true, true, "2d_array"}, +- [VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY] = {2, true, false, "2d_ms_array"}, +- [VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY] = {2, true, true, "cube_array"}, ++ [VKD3D_SHADER_RESOURCE_NONE] = {0, 0, 0, 0, "none"}, ++ [VKD3D_SHADER_RESOURCE_BUFFER] = {1, 0, 0, 0, "_buffer"}, ++ [VKD3D_SHADER_RESOURCE_TEXTURE_1D] = {1, 0, 0, 0, "1d"}, ++ [VKD3D_SHADER_RESOURCE_TEXTURE_2D] = {2, 0, 1, 1, "2d"}, ++ [VKD3D_SHADER_RESOURCE_TEXTURE_2DMS] = {2, 0, 1, 0, "2d_ms"}, ++ [VKD3D_SHADER_RESOURCE_TEXTURE_3D] = {3, 0, 0, 1, "3d"}, ++ [VKD3D_SHADER_RESOURCE_TEXTURE_CUBE] = {3, 0, 1, 0, "cube"}, ++ [VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY] = {1, 1, 0, 0, "1d"}, ++ [VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY] = {2, 1, 1, 1, "2d"}, ++ [VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY] = {2, 1, 1, 0, "2d_ms"}, ++ [VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY] = {3, 1, 1, 0, "cube"}, + }; + + if (!t || t >= ARRAY_SIZE(info)) +@@ -226,6 +236,35 @@ static const struct vkd3d_shader_descriptor_binding *msl_get_cbv_binding(const s + return NULL; } ++static const struct vkd3d_shader_descriptor_binding *msl_get_sampler_binding(const struct msl_generator *gen, ++ unsigned int register_space, unsigned int register_idx) ++{ ++ const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; ++ const struct vkd3d_shader_resource_binding *binding; ++ unsigned int i; ++ ++ if (!interface_info) ++ return NULL; ++ ++ for (i = 0; i < interface_info->binding_count; ++i) ++ { ++ binding = &interface_info->bindings[i]; ++ ++ if (binding->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) ++ continue; ++ if (binding->register_space != register_space) ++ continue; ++ if (binding->register_index != register_idx) ++ continue; ++ if (!msl_check_shader_visibility(gen, binding->shader_visibility)) ++ continue; ++ ++ return &binding->binding; ++ } ++ ++ return NULL; ++} ++ + static const struct vkd3d_shader_descriptor_binding *msl_get_srv_binding(const struct msl_generator *gen, + unsigned int register_space, unsigned int register_idx, enum vkd3d_shader_resource_type resource_type) + { +@@ -260,20 +299,71 @@ static const struct vkd3d_shader_descriptor_binding *msl_get_srv_binding(const s + return NULL; + } + ++static const struct vkd3d_shader_descriptor_binding *msl_get_uav_binding(const struct msl_generator *gen, ++ unsigned int register_space, unsigned int register_idx, enum vkd3d_shader_resource_type resource_type) ++{ ++ const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; ++ const struct vkd3d_shader_resource_binding *binding; ++ enum vkd3d_shader_binding_flag resource_type_flag; ++ unsigned int i; ++ ++ if (!interface_info) ++ return NULL; ++ ++ resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER ++ ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE; ++ ++ for (i = 0; i < interface_info->binding_count; ++i) ++ { ++ binding = &interface_info->bindings[i]; ++ ++ if (binding->type != VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) ++ continue; ++ if (binding->register_space != register_space) ++ continue; ++ if (binding->register_index != register_idx) ++ continue; ++ if (!msl_check_shader_visibility(gen, binding->shader_visibility)) ++ continue; ++ if (!(binding->flags & resource_type_flag)) ++ continue; ++ ++ return &binding->binding; ++ } ++ ++ return NULL; ++} ++ + static void msl_print_cbv_name(struct vkd3d_string_buffer *buffer, unsigned int binding) + { + vkd3d_string_buffer_printf(buffer, "descriptors[%u].buf()", binding); + } + ++static void msl_print_sampler_name(struct vkd3d_string_buffer *buffer, unsigned int binding) ++{ ++ vkd3d_string_buffer_printf(buffer, "descriptors[%u].as()", binding); ++} ++ + static void msl_print_srv_name(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, unsigned int binding, +- const struct msl_resource_type_info *resource_type_info, enum vkd3d_data_type resource_data_type) ++ const struct msl_resource_type_info *resource_type_info, enum vkd3d_data_type resource_data_type, bool compare) + { +- vkd3d_string_buffer_printf(buffer, "descriptors[%u].textype_suffix); ++ vkd3d_string_buffer_printf(buffer, "descriptors[%u].as<%s%s%s<", ++ binding, compare ? "depth" : "texture", resource_type_info->type_suffix, ++ resource_type_info->array ? "_array" : ""); + msl_print_resource_datatype(gen, buffer, resource_data_type); + vkd3d_string_buffer_printf(buffer, ">>()"); + } + ++static void msl_print_uav_name(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, unsigned int binding, ++ const struct msl_resource_type_info *resource_type_info, enum vkd3d_data_type resource_data_type) ++{ ++ vkd3d_string_buffer_printf(buffer, "descriptors[%u].astype_suffix, ++ resource_type_info->array ? "_array" : ""); ++ msl_print_resource_datatype(gen, buffer, resource_data_type); ++ vkd3d_string_buffer_printf(buffer, ", access::read_write>>()"); ++} ++ + static enum msl_data_type msl_print_register_name(struct vkd3d_string_buffer *buffer, + struct msl_generator *gen, const struct vkd3d_shader_register *reg) + { +@@ -359,25 +449,40 @@ static enum msl_data_type msl_print_register_name(struct vkd3d_string_buffer *bu + vkd3d_string_buffer_printf(buffer, "", reg->type); + return MSL_DATA_UNION; + } +- if (reg->idx[0].rel_addr || reg->idx[1].rel_addr || reg->idx[2].rel_addr) ++ if (reg->idx[0].rel_addr || reg->idx[1].rel_addr) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled constant buffer register indirect addressing."); + vkd3d_string_buffer_printf(buffer, "", reg->type); + return MSL_DATA_UNION; + } ++ /* FIXME: This should use vkd3d_shader_find_descriptor() to ++ * find the resource index/space from the resource ID. */ + if (!(binding = msl_get_cbv_binding(gen, 0, reg->idx[1].offset))) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, +- "Cannot finding binding for CBV register %u.", reg->idx[0].offset); ++ "No descriptor binding specified for CBV %u.", reg->idx[0].offset); + vkd3d_string_buffer_printf(buffer, "", reg->type); + return MSL_DATA_UNION; + } + msl_print_cbv_name(buffer, binding->binding); +- vkd3d_string_buffer_printf(buffer, "[%u]", reg->idx[2].offset); ++ msl_print_subscript(buffer, gen, reg->idx[2].rel_addr, reg->idx[2].offset); + return MSL_DATA_UNION; + } + ++ case VKD3DSPR_IDXTEMP: ++ vkd3d_string_buffer_printf(buffer, "x%u", reg->idx[0].offset); ++ msl_print_subscript(buffer, gen, reg->idx[1].rel_addr, reg->idx[1].offset); ++ return MSL_DATA_UNION; ++ ++ case VKD3DSPR_SAMPLEMASK: ++ if (gen->program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled sample coverage mask in shader type #%x.", ++ gen->program->shader_version.type); ++ vkd3d_string_buffer_printf(buffer, "o_mask"); ++ return MSL_DATA_FLOAT; ++ + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled register type %#x.", reg->type); +@@ -488,6 +593,9 @@ static void msl_print_src_with_type(struct vkd3d_string_buffer *buffer, struct m + case VKD3DSPSM_ABS: + vkd3d_string_buffer_printf(buffer, "abs(%s)", str->buffer); + break; ++ case VKD3DSPSM_ABSNEG: ++ vkd3d_string_buffer_printf(buffer, "-abs(%s)", str->buffer); ++ break; + default: + vkd3d_string_buffer_printf(buffer, "(%s)", + vsir_src->modifiers, str->buffer); +@@ -539,12 +647,34 @@ static uint32_t msl_dst_init(struct msl_dst *msl_dst, struct msl_generator *gen, + return write_mask; + } + ++static void msl_print_subscript(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, ++ const struct vkd3d_shader_src_param *rel_addr, unsigned int offset) ++{ ++ struct msl_src r; ++ ++ if (!rel_addr) ++ { ++ vkd3d_string_buffer_printf(buffer, "[%u]", offset); ++ return; ++ } ++ ++ msl_src_init(&r, gen, rel_addr, VKD3DSP_WRITEMASK_0); ++ vkd3d_string_buffer_printf(buffer, "[%s", r.str->buffer); ++ if (offset) ++ vkd3d_string_buffer_printf(buffer, " + %u", offset); ++ vkd3d_string_buffer_printf(buffer, "]"); ++ msl_src_cleanup(&r, &gen->string_buffers); ++} ++ + static void VKD3D_PRINTF_FUNC(3, 4) msl_print_assignment( + struct msl_generator *gen, struct msl_dst *dst, const char *format, ...) + { + uint32_t modifiers = dst->vsir->modifiers; + va_list args; + ++ /* It is always legitimate to ignore _pp. */ ++ modifiers &= ~VKD3DSPDM_PARTIALPRECISION; ++ + if (dst->vsir->shift) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled destination shift %#x.", dst->vsir->shift); +@@ -570,10 +700,12 @@ static void VKD3D_PRINTF_FUNC(3, 4) msl_print_assignment( + + static void msl_unhandled(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) + { ++ const char *name = vsir_opcode_get_name(ins->opcode, ""); ++ + msl_print_indent(gen->buffer, gen->indent); +- vkd3d_string_buffer_printf(gen->buffer, "/* */\n", ins->opcode); ++ vkd3d_string_buffer_printf(gen->buffer, "/* */\n", name, ins->opcode); + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, +- "Internal compiler error: Unhandled instruction %#x.", ins->opcode); ++ "Internal compiler error: Unhandled instruction \"%s\" (%#x).", name, ins->opcode); + } + + static void msl_binop(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *op) +@@ -695,19 +827,36 @@ static void msl_begin_block(struct msl_generator *gen) + ++gen->indent; + } + +-static void msl_if(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) ++static void msl_print_condition(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, ++ enum vkd3d_shader_conditional_op op, const struct vkd3d_shader_src_param *arg) + { + const char *condition; + struct msl_src src; + +- msl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); ++ msl_src_init(&src, gen, arg, VKD3DSP_WRITEMASK_0); + +- msl_print_indent(gen->buffer, gen->indent); +- condition = ins->flags == VKD3D_SHADER_CONDITIONAL_OP_NZ ? "bool" : "!bool"; +- vkd3d_string_buffer_printf(gen->buffer, "if (%s(%s))\n", condition, src.str->buffer); ++ condition = op == VKD3D_SHADER_CONDITIONAL_OP_NZ ? "bool" : "!bool"; ++ vkd3d_string_buffer_printf(buffer, "if (%s(%s))\n", condition, src.str->buffer); + + msl_src_cleanup(&src, &gen->string_buffers); ++} ++ ++static void msl_discard(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ /* Note that discard_fragment() in Metal 2.2 and earlier behaves like ++ * SPIR-V OpKill, while in Metal 2.3 and later it behaves like ++ * OpDemoteToHelperInvocationEXT. We assume we have at least Metal 3 ++ * here. */ ++ msl_print_indent(gen->buffer, gen->indent); ++ msl_print_condition(gen->buffer, gen, ins->flags, &ins->src[0]); ++ msl_print_indent(gen->buffer, gen->indent + 1); ++ vkd3d_string_buffer_printf(gen->buffer, "discard_fragment();\n"); ++} + ++static void msl_if(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ msl_print_indent(gen->buffer, gen->indent); ++ msl_print_condition(gen->buffer, gen, ins->flags, &ins->src[0]); + msl_begin_block(gen); + } + +@@ -719,6 +868,77 @@ static void msl_else(struct msl_generator *gen) + msl_begin_block(gen); + } + ++static void msl_loop(struct msl_generator *gen) ++{ ++ msl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "for (;;)\n"); ++ msl_begin_block(gen); ++} ++ ++static void msl_break(struct msl_generator *gen) ++{ ++ msl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "break;\n"); ++} ++ +static void msl_continue(struct msl_generator *gen) +{ + msl_print_indent(gen->buffer, gen->indent); + vkd3d_string_buffer_printf(gen->buffer, "continue;\n"); +} + - static void msl_switch(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) ++static void msl_switch(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ struct msl_src src; ++ ++ msl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); ++ ++ msl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "switch (%s)\n", src.str->buffer); ++ msl_begin_block(gen); ++ ++ msl_src_cleanup(&src, &gen->string_buffers); ++} ++ ++static void msl_case(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ struct msl_src src; ++ ++ msl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); ++ ++ msl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "case %s:\n", src.str->buffer); ++ ++ msl_src_cleanup(&src, &gen->string_buffers); ++} ++ ++static void msl_default(struct msl_generator *gen) ++{ ++ msl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "default:\n"); ++} ++ ++static void msl_print_texel_offset(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, ++ unsigned int offset_size, const struct vkd3d_shader_texel_offset *offset) ++{ ++ switch (offset_size) ++ { ++ case 1: ++ vkd3d_string_buffer_printf(buffer, "%d", offset->u); ++ break; ++ case 2: ++ vkd3d_string_buffer_printf(buffer, "int2(%d, %d)", offset->u, offset->v); ++ break; ++ default: ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Invalid texel offset size %u.", offset_size); ++ /* fall through */ ++ case 3: ++ vkd3d_string_buffer_printf(buffer, "int3(%d, %d, %d)", offset->u, offset->v, offset->w); ++ break; ++ } ++} ++ + static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) { - struct msl_src src; -@@ -929,7 +935,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct - - if (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBE - || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY -- || (ins->opcode != VKD3DSIH_LD2DMS -+ || (ins->opcode != VSIR_OP_LD2DMS - && (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS - || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY))) - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, -@@ -970,7 +976,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct - if (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) - { - vkd3d_string_buffer_printf(read, ", "); -- if (ins->opcode != VKD3DSIH_LD2DMS) -+ if (ins->opcode != VSIR_OP_LD2DMS) - msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VKD3D_DATA_UINT); - else - msl_print_src_with_type(read, gen, &ins->src[2], VKD3DSP_WRITEMASK_0, VKD3D_DATA_UINT); -@@ -1001,15 +1007,15 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + const struct msl_resource_type_info *resource_type_info; +@@ -728,6 +948,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct + enum vkd3d_shader_resource_type resource_type; + struct vkd3d_string_buffer *read; + enum vkd3d_data_type data_type; ++ unsigned int srv_binding; uint32_t coord_mask; struct msl_dst dst; -- bias = ins->opcode == VKD3DSIH_SAMPLE_B; -- compare = ins->opcode == VKD3DSIH_GATHER4_C || ins->opcode == VKD3DSIH_SAMPLE_C -- || ins->opcode == VKD3DSIH_SAMPLE_C_LZ; -- dynamic_offset = ins->opcode == VKD3DSIH_GATHER4_PO; -- gather = ins->opcode == VKD3DSIH_GATHER4 || ins->opcode == VKD3DSIH_GATHER4_C -- || ins->opcode == VKD3DSIH_GATHER4_PO; -- grad = ins->opcode == VKD3DSIH_SAMPLE_GRAD; -- lod = ins->opcode == VKD3DSIH_SAMPLE_LOD; -- lod_zero = ins->opcode == VKD3DSIH_SAMPLE_C_LZ; +@@ -757,30 +978,39 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct + data_type = VKD3D_DATA_FLOAT; + } + +- if ((resource_type_info = msl_get_resource_type_info(resource_type))) +- { +- coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->read_coord_size); +- } +- else ++ if (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBE ++ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY ++ || (ins->opcode != VSIR_OP_LD2DMS ++ && (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS ++ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY))) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, ++ "Texel fetches from resource type %#x are not supported.", resource_type); ++ ++ if (!(resource_type_info = msl_get_resource_type_info(resource_type))) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled resource type %#x.", resource_type); +- coord_mask = vkd3d_write_mask_from_component_count(2); ++ resource_type_info = msl_get_resource_type_info(VKD3D_SHADER_RESOURCE_TEXTURE_2D); + } ++ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); + +- if (!(binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) ++ if ((binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) ++ { ++ srv_binding = binding->binding; ++ } ++ else + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, +- "Cannot finding binding for SRV register %u index %u space %u.", ++ "No descriptor binding specified for SRV %u (index %u, space %u).", + resource_id, resource_idx, resource_space); +- return; ++ srv_binding = 0; + } + + msl_dst_init(&dst, gen, ins, &ins->dst[0]); + read = vkd3d_string_buffer_get(&gen->string_buffers); + + vkd3d_string_buffer_printf(read, "as_type("); +- msl_print_srv_name(read, gen, binding->binding, resource_type_info, data_type); ++ msl_print_srv_name(read, gen, srv_binding, resource_type_info, data_type, false); + vkd3d_string_buffer_printf(read, ".read("); + msl_print_src_with_type(read, gen, &ins->src[0], coord_mask, VKD3D_DATA_UINT); + if (resource_type_info->array) +@@ -788,10 +1018,13 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct + vkd3d_string_buffer_printf(read, ", "); + msl_print_src_with_type(read, gen, &ins->src[0], coord_mask + 1, VKD3D_DATA_UINT); + } +- if (resource_type_info->lod) ++ if (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) + { + vkd3d_string_buffer_printf(read, ", "); +- msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VKD3D_DATA_UINT); ++ if (ins->opcode != VSIR_OP_LD2DMS) ++ msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VKD3D_DATA_UINT); ++ else ++ msl_print_src_with_type(read, gen, &ins->src[2], VKD3DSP_WRITEMASK_0, VKD3D_DATA_UINT); + } + vkd3d_string_buffer_printf(read, "))"); + msl_print_swizzle(read, ins->src[1].swizzle, ins->dst[0].write_mask); +@@ -802,6 +1035,310 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct + msl_dst_cleanup(&dst, &gen->string_buffers); + } + ++static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ bool bias, compare, comparison_sampler, dynamic_offset, gather, grad, lod, lod_zero, offset; ++ const struct msl_resource_type_info *resource_type_info; ++ const struct vkd3d_shader_src_param *resource, *sampler; ++ unsigned int resource_id, resource_idx, resource_space; ++ const struct vkd3d_shader_descriptor_binding *binding; ++ unsigned int sampler_id, sampler_idx, sampler_space; ++ const struct vkd3d_shader_descriptor_info1 *d; ++ enum vkd3d_shader_resource_type resource_type; ++ unsigned int srv_binding, sampler_binding; ++ struct vkd3d_string_buffer *sample; ++ enum vkd3d_data_type data_type; ++ unsigned int component_idx; ++ uint32_t coord_mask; ++ struct msl_dst dst; ++ + bias = ins->opcode == VSIR_OP_SAMPLE_B; + compare = ins->opcode == VSIR_OP_GATHER4_C || ins->opcode == VSIR_OP_SAMPLE_C + || ins->opcode == VSIR_OP_SAMPLE_C_LZ; @@ -8067,15 +14789,306 @@ index 87c9e989ea4..2a209323de7 100644 + grad = ins->opcode == VSIR_OP_SAMPLE_GRAD; + lod = ins->opcode == VSIR_OP_SAMPLE_LOD; + lod_zero = ins->opcode == VSIR_OP_SAMPLE_C_LZ; - offset = dynamic_offset || vkd3d_shader_instruction_has_texel_offset(ins); ++ offset = dynamic_offset || vkd3d_shader_instruction_has_texel_offset(ins); ++ ++ resource = &ins->src[1 + dynamic_offset]; ++ sampler = &ins->src[2 + dynamic_offset]; ++ ++ if (resource->reg.idx[0].rel_addr || resource->reg.idx[1].rel_addr ++ || sampler->reg.idx[0].rel_addr || sampler->reg.idx[1].rel_addr) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, ++ "Descriptor indexing is not supported."); ++ ++ resource_id = resource->reg.idx[0].offset; ++ resource_idx = resource->reg.idx[1].offset; ++ if ((d = vkd3d_shader_find_descriptor(&gen->program->descriptors, ++ VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_id))) ++ { ++ resource_space = d->register_space; ++ resource_type = d->resource_type; ++ data_type = d->resource_data_type; ++ } ++ else ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Undeclared resource descriptor %u.", resource_id); ++ resource_space = 0; ++ resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; ++ data_type = VKD3D_DATA_FLOAT; ++ } ++ ++ if (resource_type == VKD3D_SHADER_RESOURCE_BUFFER ++ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS ++ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, ++ "Sampling resource type %#x is not supported.", resource_type); ++ ++ if ((resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_1D || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY) ++ && (bias || grad || lod || lod_zero)) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, ++ "Resource type %#x does not support mipmapping.", resource_type); ++ ++ if ((resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_1D || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY ++ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_3D) && gather) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, ++ "Resource type %#x does not support gather operations.", resource_type); ++ ++ if (!(resource_type_info = msl_get_resource_type_info(resource_type))) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled resource type %#x.", resource_type); ++ resource_type_info = msl_get_resource_type_info(VKD3D_SHADER_RESOURCE_TEXTURE_2D); ++ } ++ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); ++ ++ if ((binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) ++ { ++ srv_binding = binding->binding; ++ } ++ else ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, ++ "No descriptor binding specified for SRV %u (index %u, space %u).", ++ resource_id, resource_idx, resource_space); ++ srv_binding = 0; ++ } ++ ++ sampler_id = sampler->reg.idx[0].offset; ++ sampler_idx = sampler->reg.idx[1].offset; ++ if ((d = vkd3d_shader_find_descriptor(&gen->program->descriptors, ++ VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler_id))) ++ { ++ sampler_space = d->register_space; ++ comparison_sampler = d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE; ++ ++ if (compare) ++ { ++ if (!comparison_sampler) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Sampler %u is not a comparison sampler.", sampler_id); ++ } ++ else ++ { ++ if (comparison_sampler) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Sampler %u is a comparison sampler.", sampler_id); ++ } ++ } ++ else ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Undeclared sampler descriptor %u.", sampler_id); ++ sampler_space = 0; ++ } ++ ++ if ((binding = msl_get_sampler_binding(gen, sampler_space, sampler_idx))) ++ { ++ sampler_binding = binding->binding; ++ } ++ else ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, ++ "No descriptor binding specified for sampler %u (index %u, space %u).", ++ sampler_id, sampler_idx, sampler_space); ++ sampler_binding = 0; ++ } ++ ++ msl_dst_init(&dst, gen, ins, &ins->dst[0]); ++ sample = vkd3d_string_buffer_get(&gen->string_buffers); ++ ++ if (ins->dst[0].reg.data_type == VKD3D_DATA_UINT) ++ vkd3d_string_buffer_printf(sample, "as_type("); ++ msl_print_srv_name(sample, gen, srv_binding, resource_type_info, data_type, compare); ++ if (gather && compare) ++ vkd3d_string_buffer_printf(sample, ".gather_compare("); ++ else if (gather) ++ vkd3d_string_buffer_printf(sample, ".gather("); ++ else if (compare) ++ vkd3d_string_buffer_printf(sample, ".sample_compare("); ++ else ++ vkd3d_string_buffer_printf(sample, ".sample("); ++ msl_print_sampler_name(sample, sampler_binding); ++ vkd3d_string_buffer_printf(sample, ", "); ++ msl_print_src_with_type(sample, gen, &ins->src[0], coord_mask, ins->src[0].reg.data_type); ++ if (resource_type_info->array) ++ { ++ vkd3d_string_buffer_printf(sample, ", uint("); ++ msl_print_src_with_type(sample, gen, &ins->src[0], coord_mask + 1, ins->src[0].reg.data_type); ++ vkd3d_string_buffer_printf(sample, ")"); ++ } ++ if (compare) ++ { ++ if (!resource_type_info->comparison) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, ++ "Comparison samplers are not supported with resource type %#x.", resource_type); ++ vkd3d_string_buffer_printf(sample, ", "); ++ msl_print_src_with_type(sample, gen, &ins->src[3], VKD3DSP_WRITEMASK_0, ins->src[3].reg.data_type); ++ } ++ if (grad) ++ { ++ vkd3d_string_buffer_printf(sample, ", gradient%s(", resource_type_info->type_suffix); ++ msl_print_src_with_type(sample, gen, &ins->src[3], coord_mask, ins->src[3].reg.data_type); ++ vkd3d_string_buffer_printf(sample, ", "); ++ msl_print_src_with_type(sample, gen, &ins->src[4], coord_mask, ins->src[4].reg.data_type); ++ vkd3d_string_buffer_printf(sample, ")"); ++ } ++ if (lod_zero) ++ { ++ vkd3d_string_buffer_printf(sample, ", level(0.0f)"); ++ } ++ else if (lod) ++ { ++ vkd3d_string_buffer_printf(sample, ", level("); ++ msl_print_src_with_type(sample, gen, &ins->src[3], VKD3DSP_WRITEMASK_0, ins->src[3].reg.data_type); ++ vkd3d_string_buffer_printf(sample, ")"); ++ } ++ if (bias) ++ { ++ vkd3d_string_buffer_printf(sample, ", bias("); ++ msl_print_src_with_type(sample, gen, &ins->src[3], VKD3DSP_WRITEMASK_0, ins->src[3].reg.data_type); ++ vkd3d_string_buffer_printf(sample, ")"); ++ } ++ if (offset) ++ { ++ if (!resource_type_info->offset) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, ++ "Texel sample offsets are not supported with resource type %#x.", resource_type); ++ vkd3d_string_buffer_printf(sample, ", "); ++ if (dynamic_offset) ++ msl_print_src_with_type(sample, gen, &ins->src[1], coord_mask, ins->src[1].reg.data_type); ++ else ++ msl_print_texel_offset(sample, gen, resource_type_info->coord_size, &ins->texel_offset); ++ } ++ if (gather && !compare && (component_idx = vsir_swizzle_get_component(sampler->swizzle, 0))) ++ { ++ if (!offset && resource_type_info->offset) ++ vkd3d_string_buffer_printf(sample, ", int2(0)"); ++ vkd3d_string_buffer_printf(sample, ", component::%c", "xyzw"[component_idx]); ++ } ++ vkd3d_string_buffer_printf(sample, ")"); ++ if (ins->dst[0].reg.data_type == VKD3D_DATA_UINT) ++ vkd3d_string_buffer_printf(sample, ")"); ++ if (!compare || gather) ++ msl_print_swizzle(sample, resource->swizzle, ins->dst[0].write_mask); ++ ++ msl_print_assignment(gen, &dst, "%s", sample->buffer); ++ ++ vkd3d_string_buffer_release(&gen->string_buffers, sample); ++ msl_dst_cleanup(&dst, &gen->string_buffers); ++} ++ ++static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ const struct msl_resource_type_info *resource_type_info; ++ const struct vkd3d_shader_descriptor_binding *binding; ++ const struct vkd3d_shader_descriptor_info1 *d; ++ enum vkd3d_shader_resource_type resource_type; ++ unsigned int uav_id, uav_idx, uav_space; ++ struct vkd3d_string_buffer *image_data; ++ enum vkd3d_data_type data_type; ++ unsigned int uav_binding; ++ uint32_t coord_mask; ++ ++ if (ins->dst[0].reg.idx[0].rel_addr || ins->dst[0].reg.idx[1].rel_addr) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, ++ "Descriptor indexing is not supported."); ++ ++ uav_id = ins->dst[0].reg.idx[0].offset; ++ uav_idx = ins->dst[0].reg.idx[1].offset; ++ if ((d = vkd3d_shader_find_descriptor(&gen->program->descriptors, ++ VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, uav_id))) ++ { ++ uav_space = d->register_space; ++ resource_type = d->resource_type; ++ data_type = d->resource_data_type; ++ } ++ else ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Undeclared UAV descriptor %u.", uav_id); ++ uav_space = 0; ++ resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; ++ data_type = VKD3D_DATA_FLOAT; ++ } ++ ++ if (!(resource_type_info = msl_get_resource_type_info(resource_type))) ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled resource type %#x.", resource_type); ++ resource_type_info = msl_get_resource_type_info(VKD3D_SHADER_RESOURCE_TEXTURE_2D); ++ } ++ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); ++ ++ if ((binding = msl_get_uav_binding(gen, uav_space, uav_idx, resource_type))) ++ { ++ uav_binding = binding->binding; ++ } ++ else ++ { ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, ++ "No descriptor binding specified for UAV %u (index %u, space %u).", ++ uav_id, uav_idx, uav_space); ++ uav_binding = 0; ++ } ++ ++ image_data = vkd3d_string_buffer_get(&gen->string_buffers); ++ ++ if (ins->src[1].reg.dimension == VSIR_DIMENSION_SCALAR) ++ { ++ switch (data_type) ++ { ++ case VKD3D_DATA_UINT: ++ vkd3d_string_buffer_printf(image_data, "uint4("); ++ break; ++ case VKD3D_DATA_INT: ++ vkd3d_string_buffer_printf(image_data, "int4("); ++ break; ++ default: ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled data type %#x.", data_type); ++ /* fall through */ ++ case VKD3D_DATA_FLOAT: ++ case VKD3D_DATA_UNORM: ++ case VKD3D_DATA_SNORM: ++ vkd3d_string_buffer_printf(image_data, "float4("); ++ break; ++ } ++ } ++ msl_print_src_with_type(image_data, gen, &ins->src[1], VKD3DSP_WRITEMASK_ALL, data_type); ++ if (ins->src[1].reg.dimension == VSIR_DIMENSION_SCALAR) ++ vkd3d_string_buffer_printf(image_data, ", 0, 0, 0)"); ++ ++ msl_print_indent(gen->buffer, gen->indent); ++ msl_print_uav_name(gen->buffer, gen, uav_binding, resource_type_info, data_type); ++ vkd3d_string_buffer_printf(gen->buffer, ".write(%s, ", image_data->buffer); ++ msl_print_src_with_type(gen->buffer, gen, &ins->src[0], coord_mask, VKD3D_DATA_UINT); ++ vkd3d_string_buffer_printf(gen->buffer, ");\n"); ++ ++ vkd3d_string_buffer_release(&gen->string_buffers, image_data); ++} ++ + static void msl_unary_op(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *op) + { + struct msl_src src; +@@ -863,128 +1400,208 @@ static void msl_ret(struct msl_generator *gen, const struct vkd3d_shader_instruc + vkd3d_string_buffer_printf(gen->buffer, "return;\n"); + } - resource = &ins->src[1 + dynamic_offset]; -@@ -1273,169 +1279,187 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d ++static void msl_dcl_indexable_temp(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) ++{ ++ msl_print_indent(gen->buffer, gen->indent); ++ vkd3d_string_buffer_printf(gen->buffer, "vkd3d_vec4 x%u[%u];\n", ++ ins->declaration.indexable_temp.register_idx, ++ ins->declaration.indexable_temp.register_size); ++} ++ + static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) + { + gen->location = ins->location; switch (ins->opcode) { - case VKD3DSIH_ADD: -- case VKD3DSIH_IADD: + case VSIR_OP_ADD: + case VSIR_OP_IADD: msl_binop(gen, ins, "+"); @@ -8084,33 +15097,28 @@ index 87c9e989ea4..2a209323de7 100644 + case VSIR_OP_AND: msl_binop(gen, ins, "&"); break; -- case VKD3DSIH_BREAK: +- case VKD3DSIH_NOP: + case VSIR_OP_BREAK: - msl_break(gen); - break; -- case VKD3DSIH_CASE: ++ msl_break(gen); ++ break; + case VSIR_OP_CASE: - msl_case(gen, ins); - break; -- case VKD3DSIH_DCL_INDEXABLE_TEMP: ++ msl_case(gen, ins); ++ break; + case VSIR_OP_CONTINUE: + msl_continue(gen); + break; + case VSIR_OP_DCL_INDEXABLE_TEMP: - msl_dcl_indexable_temp(gen, ins); - break; -- case VKD3DSIH_NOP: -+ case VSIR_OP_NOP: - break; -- case VKD3DSIH_DEFAULT: -+ case VSIR_OP_DEFAULT: - msl_default(gen); - break; -- case VKD3DSIH_DISCARD: -+ case VSIR_OP_DISCARD: - msl_discard(gen, ins); ++ msl_dcl_indexable_temp(gen, ins); break; - case VKD3DSIH_DIV: ++ case VSIR_OP_NOP: ++ break; ++ case VSIR_OP_DEFAULT: ++ msl_default(gen); ++ break; ++ case VSIR_OP_DISCARD: ++ msl_discard(gen, ins); ++ break; + case VSIR_OP_DIV: msl_binop(gen, ins, "/"); break; @@ -8145,14 +15153,11 @@ index 87c9e989ea4..2a209323de7 100644 msl_else(gen); break; - case VKD3DSIH_ENDIF: -- case VKD3DSIH_ENDLOOP: -- case VKD3DSIH_ENDSWITCH: + case VSIR_OP_ENDIF: + case VSIR_OP_ENDLOOP: + case VSIR_OP_ENDSWITCH: msl_end_block(gen); break; -- case VKD3DSIH_EQO: - case VKD3DSIH_IEQ: + case VSIR_OP_EQO: + case VSIR_OP_IEQ: @@ -8174,15 +15179,7 @@ index 87c9e989ea4..2a209323de7 100644 + case VSIR_OP_FTOU: msl_cast(gen, ins, "uint"); break; -- case VKD3DSIH_GATHER4: -- case VKD3DSIH_GATHER4_C: -- case VKD3DSIH_GATHER4_PO: -- case VKD3DSIH_SAMPLE: -- case VKD3DSIH_SAMPLE_B: -- case VKD3DSIH_SAMPLE_C: -- case VKD3DSIH_SAMPLE_C_LZ: -- case VKD3DSIH_SAMPLE_GRAD: -- case VKD3DSIH_SAMPLE_LOD: +- case VKD3DSIH_GEO: + case VSIR_OP_GATHER4: + case VSIR_OP_GATHER4_C: + case VSIR_OP_GATHER4_PO: @@ -8192,10 +15189,8 @@ index 87c9e989ea4..2a209323de7 100644 + case VSIR_OP_SAMPLE_C_LZ: + case VSIR_OP_SAMPLE_GRAD: + case VSIR_OP_SAMPLE_LOD: - msl_sample(gen, ins); - break; -- case VKD3DSIH_GEO: -- case VKD3DSIH_IGE: ++ msl_sample(gen, ins); ++ break; + case VSIR_OP_GEO: + case VSIR_OP_IGE: msl_relop(gen, ins, ">="); @@ -8214,9 +15209,7 @@ index 87c9e989ea4..2a209323de7 100644 + case VSIR_OP_USHR: msl_binop(gen, ins, ">>"); break; -- case VKD3DSIH_ILT: - case VKD3DSIH_LTO: -- case VKD3DSIH_ULT: + case VSIR_OP_ILT: + case VSIR_OP_LTO: + case VSIR_OP_ULT: @@ -8229,34 +15222,33 @@ index 87c9e989ea4..2a209323de7 100644 - case VKD3DSIH_MAX: + case VSIR_OP_IMAX: + case VSIR_OP_MAX: ++ case VSIR_OP_UMAX: msl_intrinsic(gen, ins, "max"); break; - case VKD3DSIH_MIN: + case VSIR_OP_MIN: ++ case VSIR_OP_UMIN: msl_intrinsic(gen, ins, "min"); break; -- case VKD3DSIH_IMUL_LOW: -+ case VSIR_OP_IMUL_LOW: - msl_binop(gen, ins, "*"); - break; - case VKD3DSIH_INE: - case VKD3DSIH_NEU: ++ case VSIR_OP_IMUL_LOW: ++ msl_binop(gen, ins, "*"); ++ break; + case VSIR_OP_INE: + case VSIR_OP_NEU: msl_relop(gen, ins, "!="); break; -- case VKD3DSIH_INEG: -+ case VSIR_OP_INEG: - msl_unary_op(gen, ins, "-"); - break; - case VKD3DSIH_ITOF: - case VKD3DSIH_UTOF: ++ case VSIR_OP_INEG: ++ msl_unary_op(gen, ins, "-"); ++ break; + case VSIR_OP_ITOF: + case VSIR_OP_UTOF: msl_cast(gen, ins, "float"); break; - case VKD3DSIH_LD: -- case VKD3DSIH_LD2DMS: + case VSIR_OP_LD: + case VSIR_OP_LD2DMS: msl_ld(gen, ins); @@ -8265,11 +15257,10 @@ index 87c9e989ea4..2a209323de7 100644 + case VSIR_OP_LOG: msl_intrinsic(gen, ins, "log2"); break; -- case VKD3DSIH_LOOP: -+ case VSIR_OP_LOOP: - msl_loop(gen); - break; - case VKD3DSIH_MOV: ++ case VSIR_OP_LOOP: ++ msl_loop(gen); ++ break; + case VSIR_OP_MOV: msl_mov(gen, ins); break; @@ -8317,20 +15308,598 @@ index 87c9e989ea4..2a209323de7 100644 + case VSIR_OP_SQRT: msl_intrinsic(gen, ins, "sqrt"); break; -- case VKD3DSIH_SWITCH: ++ case VSIR_OP_STORE_UAV_TYPED: ++ msl_store_uav_typed(gen, ins); ++ break; + case VSIR_OP_SWITCH: - msl_switch(gen, ins); - break; -- case VKD3DSIH_XOR: ++ msl_switch(gen, ins); ++ break; + case VSIR_OP_XOR: - msl_binop(gen, ins, "^"); ++ msl_binop(gen, ins, "^"); ++ break; + default: + msl_unhandled(gen, ins); + break; +@@ -1008,21 +1625,48 @@ static void msl_generate_input_struct_declarations(struct msl_generator *gen) + if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) + continue; + +- if (e->sysval_semantic) ++ switch (e->sysval_semantic) + { +- if (e->sysval_semantic == VKD3D_SHADER_SV_IS_FRONT_FACE) +- { ++ case VKD3D_SHADER_SV_NONE: ++ break; ++ ++ case VKD3D_SHADER_SV_POSITION: + if (type != VKD3D_SHADER_TYPE_PIXEL) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, +- "Internal compiler error: Unhandled SV_IS_FRONT_FACE in shader type #%x.", type); ++ "Internal compiler error: Unhandled SV_POSITION in shader type #%x.", type); ++ msl_print_indent(gen->buffer, 1); ++ vkd3d_string_buffer_printf(buffer, "float4 position [[position]];\n"); ++ continue; ++ ++ case VKD3D_SHADER_SV_VERTEX_ID: ++ if (type != VKD3D_SHADER_TYPE_VERTEX) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled SV_VERTEX_ID in shader type #%x.", type); ++ gen->read_vertex_id = true; ++ continue; + ++ case VKD3D_SHADER_SV_IS_FRONT_FACE: ++ if (type != VKD3D_SHADER_TYPE_PIXEL) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled SV_IS_FRONT_FACE in shader type #%x.", type); + msl_print_indent(gen->buffer, 1); + vkd3d_string_buffer_printf(buffer, "bool is_front_face [[front_facing]];\n"); + continue; +- } +- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, +- "Internal compiler error: Unhandled system value %#x.", e->sysval_semantic); +- continue; ++ ++ case VKD3D_SHADER_SV_SAMPLE_INDEX: ++ if (type != VKD3D_SHADER_TYPE_PIXEL) ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled SV_SAMPLE_INDEX in shader type #%x.", type); ++ msl_print_indent(gen->buffer, 1); ++ vkd3d_string_buffer_printf(buffer, "uint sample_index [[sample_id]];\n"); ++ continue; ++ ++ default: ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled system value %#x.", e->sysval_semantic); ++ msl_print_indent(gen->buffer, 1); ++ vkd3d_string_buffer_printf(buffer, ";\n", e->sysval_semantic); ++ continue; + } + + if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) +@@ -1059,15 +1703,15 @@ static void msl_generate_input_struct_declarations(struct msl_generator *gen) + break; + } + +- vkd3d_string_buffer_printf(buffer, "shader_in_%u ", i); ++ vkd3d_string_buffer_printf(buffer, "shader_in_%u [[", i); + + switch (type) + { + case VKD3D_SHADER_TYPE_VERTEX: +- vkd3d_string_buffer_printf(gen->buffer, "[[attribute(%u)]]", e->target_location); ++ vkd3d_string_buffer_printf(gen->buffer, "attribute(%u)", e->target_location); + break; + case VKD3D_SHADER_TYPE_PIXEL: +- vkd3d_string_buffer_printf(gen->buffer, "[[user(locn%u)]]", e->target_location); ++ vkd3d_string_buffer_printf(gen->buffer, "user(locn%u)", e->target_location); + break; + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, +@@ -1081,13 +1725,16 @@ static void msl_generate_input_struct_declarations(struct msl_generator *gen) + case VKD3DSIM_LINEAR: + case VKD3DSIM_NONE: + break; ++ case VKD3DSIM_CONSTANT: ++ vkd3d_string_buffer_printf(gen->buffer, ", flat"); ++ break; + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled interpolation mode %#x.", e->interpolation_mode); + break; + } + +- vkd3d_string_buffer_printf(buffer, ";\n"); ++ vkd3d_string_buffer_printf(buffer, "]];\n"); + } + + vkd3d_string_buffer_printf(buffer, "};\n\n"); +@@ -1138,15 +1785,8 @@ static void msl_generate_output_struct_declarations(struct msl_generator *gen) + { + e = &signature->elements[i]; + +- if (e->sysval_semantic == VKD3D_SHADER_SV_DEPTH) +- { +- gen->write_depth = true; +- msl_print_indent(gen->buffer, 1); +- vkd3d_string_buffer_printf(buffer, "float shader_out_depth [[depth(any)]];\n"); +- continue; +- } +- +- if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) ++ if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED ++ || e->sysval_semantic == VKD3D_SHADER_SV_DEPTH) + continue; + + if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) +@@ -1209,6 +1849,18 @@ static void msl_generate_output_struct_declarations(struct msl_generator *gen) + vkd3d_string_buffer_printf(buffer, ";\n"); + } + ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_DEPTHOUT)) ++ { ++ msl_print_indent(gen->buffer, 1); ++ vkd3d_string_buffer_printf(buffer, "float shader_out_depth [[depth(any)]];\n"); ++ } ++ ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) ++ { ++ msl_print_indent(gen->buffer, 1); ++ vkd3d_string_buffer_printf(buffer, "uint shader_out_mask [[sample_mask]];\n"); ++ } ++ + vkd3d_string_buffer_printf(buffer, "};\n\n"); + } + +@@ -1227,23 +1879,45 @@ static void msl_generate_entrypoint_prologue(struct msl_generator *gen) + continue; + + vkd3d_string_buffer_printf(buffer, " %s_in[%u]", gen->prefix, e->register_index); +- if (e->sysval_semantic == VKD3D_SHADER_SV_NONE) +- { +- msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); +- msl_print_write_mask(buffer, e->mask); +- vkd3d_string_buffer_printf(buffer, " = input.shader_in_%u", i); +- msl_print_write_mask(buffer, e->mask); +- } +- else if (e->sysval_semantic == VKD3D_SHADER_SV_IS_FRONT_FACE) +- { +- vkd3d_string_buffer_printf(buffer, ".u = uint4(input.is_front_face ? 0xffffffffu : 0u, 0, 0, 0)"); +- } +- else ++ switch (e->sysval_semantic) + { +- vkd3d_string_buffer_printf(buffer, " = ", e->sysval_semantic); +- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, +- "Internal compiler error: Unhandled system value %#x input.", e->sysval_semantic); ++ case VKD3D_SHADER_SV_NONE: ++ msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); ++ msl_print_write_mask(buffer, e->mask); ++ vkd3d_string_buffer_printf(buffer, " = input.shader_in_%u", i); ++ break; ++ ++ case VKD3D_SHADER_SV_POSITION: ++ msl_print_register_datatype(buffer, gen, VKD3D_DATA_FLOAT); ++ msl_print_write_mask(buffer, e->mask); ++ vkd3d_string_buffer_printf(buffer, " = float4(input.position.xyz, 1.0f / input.position.w)"); ++ break; ++ ++ case VKD3D_SHADER_SV_VERTEX_ID: ++ msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); ++ msl_print_write_mask(buffer, e->mask); ++ vkd3d_string_buffer_printf(buffer, " = uint4(vertex_id, 0u, 0u, 0u)"); ++ break; ++ ++ case VKD3D_SHADER_SV_IS_FRONT_FACE: ++ msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); ++ msl_print_write_mask(buffer, e->mask); ++ vkd3d_string_buffer_printf(buffer, " = uint4(input.is_front_face ? 0xffffffffu : 0u, 0, 0, 0)"); ++ break; ++ ++ case VKD3D_SHADER_SV_SAMPLE_INDEX: ++ msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); ++ msl_print_write_mask(buffer, e->mask); ++ vkd3d_string_buffer_printf(buffer, " = uint4(input.sample_index, 0u, 0u, 0u)"); ++ break; ++ ++ default: ++ vkd3d_string_buffer_printf(buffer, " = ", e->sysval_semantic); ++ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, ++ "Internal compiler error: Unhandled system value %#x input.", e->sysval_semantic); ++ break; + } ++ msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, ";\n"); + } + } +@@ -1259,12 +1933,6 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) + { + e = &signature->elements[i]; + +- if (e->sysval_semantic == VKD3D_SHADER_SV_DEPTH) +- { +- vkd3d_string_buffer_printf(buffer, " output.shader_out_depth = shader_out_depth;\n"); +- continue; +- } +- + if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) + continue; + +@@ -1279,6 +1947,8 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) + msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); + msl_print_write_mask(buffer, e->mask); + break; ++ case VKD3D_SHADER_SV_DEPTH: ++ continue; + default: + vkd3d_string_buffer_printf(buffer, " ", e->sysval_semantic); + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, +@@ -1286,6 +1956,9 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) + } + vkd3d_string_buffer_printf(buffer, ";\n"); + } ++ ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) ++ vkd3d_string_buffer_printf(gen->buffer, " output.shader_out_mask = as_type(o_mask);\n"); + } + + static void msl_generate_entrypoint(struct msl_generator *gen) +@@ -1298,6 +1971,8 @@ static void msl_generate_entrypoint(struct msl_generator *gen) + vkd3d_string_buffer_printf(gen->buffer, "vertex "); + break; + case VKD3D_SHADER_TYPE_PIXEL: ++ if (gen->program->global_flags & VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL) ++ vkd3d_string_buffer_printf(gen->buffer, "[[early_fragment_tests]]\n"); + vkd3d_string_buffer_printf(gen->buffer, "fragment "); break; default: +@@ -1316,6 +1991,12 @@ static void msl_generate_entrypoint(struct msl_generator *gen) + "constant descriptor *descriptors [[buffer(0)]],\n"); + } + ++ if (gen->read_vertex_id) ++ { ++ msl_print_indent(gen->buffer, 2); ++ vkd3d_string_buffer_printf(gen->buffer, "uint vertex_id [[vertex_id]],\n"); ++ } ++ + msl_print_indent(gen->buffer, 2); + vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_in input [[stage_in]])\n{\n", gen->prefix); + +@@ -1323,18 +2004,22 @@ static void msl_generate_entrypoint(struct msl_generator *gen) + vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 %s_in[%u];\n", gen->prefix, 32); + vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 %s_out[%u];\n", gen->prefix, 32); + vkd3d_string_buffer_printf(gen->buffer, " vkd3d_%s_out output;\n", gen->prefix); +- +- if (gen->write_depth) +- vkd3d_string_buffer_printf(gen->buffer, " float shader_out_depth;\n"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) ++ vkd3d_string_buffer_printf(gen->buffer, " float o_mask;\n"); ++ vkd3d_string_buffer_printf(gen->buffer, "\n"); + + msl_generate_entrypoint_prologue(gen); + + vkd3d_string_buffer_printf(gen->buffer, " %s_main(%s_in, %s_out", gen->prefix, gen->prefix, gen->prefix); +- if (gen->write_depth) +- vkd3d_string_buffer_printf(gen->buffer, ", shader_out_depth"); ++ if (gen->read_vertex_id) ++ vkd3d_string_buffer_printf(gen->buffer, ", vertex_id"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_DEPTHOUT)) ++ vkd3d_string_buffer_printf(gen->buffer, ", output.shader_out_depth"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) ++ vkd3d_string_buffer_printf(gen->buffer, ", o_mask"); + if (gen->program->descriptors.descriptor_count) + vkd3d_string_buffer_printf(gen->buffer, ", descriptors"); +- vkd3d_string_buffer_printf(gen->buffer, ");\n"); ++ vkd3d_string_buffer_printf(gen->buffer, ");\n\n"); + + msl_generate_entrypoint_epilogue(gen); + +@@ -1353,7 +2038,7 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader + vkd3d_string_buffer_printf(gen->buffer, "#include \n\n"); + vkd3d_string_buffer_printf(gen->buffer, "using namespace metal;\n\n"); + +- if (gen->program->global_flags) ++ if (gen->program->global_flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL)) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled global flags %#"PRIx64".", (uint64_t)gen->program->global_flags); + +@@ -1370,7 +2055,7 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader + " const device void *ptr;\n" + "\n" + " template\n" +- " constant T &tex() constant\n" ++ " constant T &as() constant\n" + " {\n" + " return reinterpret_cast(this->ptr);\n" + " }\n" +@@ -1388,11 +2073,16 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader + msl_generate_output_struct_declarations(gen); + + vkd3d_string_buffer_printf(gen->buffer, +- "void %s_main(thread vkd3d_vec4 *v, " ++ "static void %s_main(thread vkd3d_vec4 *v, " + "thread vkd3d_vec4 *o", + gen->prefix); +- if (gen->write_depth) +- vkd3d_string_buffer_printf(gen->buffer, ", thread float& o_depth"); ++ ++ if (gen->read_vertex_id) ++ vkd3d_string_buffer_printf(gen->buffer, ", uint vertex_id"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_DEPTHOUT)) ++ vkd3d_string_buffer_printf(gen->buffer, ", thread float &o_depth"); ++ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) ++ vkd3d_string_buffer_printf(gen->buffer, ", thread float &o_mask"); + if (gen->program->descriptors.descriptor_count) + vkd3d_string_buffer_printf(gen->buffer, ", constant descriptor *descriptors"); + vkd3d_string_buffer_printf(gen->buffer, ")\n{\n"); +diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.h b/libs/vkd3d/libs/vkd3d-shader/preproc.h +index a98c8ae3df5..9217237d8d3 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/preproc.h ++++ b/libs/vkd3d/libs/vkd3d-shader/preproc.h +@@ -38,6 +38,7 @@ struct preproc_buffer + { + void *lexer_buffer; + struct vkd3d_shader_location location; ++ bool eof; + }; + + struct preproc_file +@@ -125,7 +126,6 @@ struct preproc_ctx + int lookahead_token; + + bool last_was_newline; +- bool last_was_eof; + bool last_was_defined; + + bool error; +diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l +index 4a8d0fddae1..5c56fba0229 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/preproc.l ++++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l +@@ -20,6 +20,7 @@ + + %{ + ++#include "preproc.h" + #include "preproc.tab.h" + + #undef ERROR /* defined in wingdi.h */ +@@ -71,8 +72,8 @@ INT_SUFFIX [uUlL]{0,2} + + %% + +-"//" {yy_push_state(CXX_COMMENT, yyscanner);} +-"/*" {yy_push_state(C_COMMENT, yyscanner);} ++"//" {yy_push_state(CXX_COMMENT, yyscanner);} ++"/*" {yy_push_state(C_COMMENT, yyscanner);} + \\{NEWLINE} {} + \n { + yy_pop_state(yyscanner); +@@ -80,7 +81,11 @@ INT_SUFFIX [uUlL]{0,2} + return T_NEWLINE; + } + "*/" {yy_pop_state(yyscanner);} +-<> {yy_pop_state(yyscanner);} ++<> { ++ yy_pop_state(yyscanner); ++ BEGIN(INITIAL); ++ yyterminate(); ++ } + . {} + \n {} + +@@ -196,6 +201,10 @@ INT_SUFFIX [uUlL]{0,2} + BEGIN(INITIAL); + return T_NEWLINE; + } ++<> { ++ BEGIN(INITIAL); ++ yyterminate(); ++ } + + {WS}+ {} + [-()\[\]{},+!*/<>&|^?:] {return yytext[0];} +@@ -250,8 +259,19 @@ static bool should_concat(struct preproc_ctx *ctx) + return !macro || macro->arg_count; + } + ++static struct preproc_buffer *preproc_get_top_buffer(struct preproc_ctx *ctx) ++{ ++ if (ctx->expansion_count) ++ return &ctx->expansion_stack[ctx->expansion_count - 1].buffer; ++ if (ctx->file_count) ++ return &ctx->file_stack[ctx->file_count - 1].buffer; ++ return NULL; ++} ++ + static void preproc_pop_buffer(struct preproc_ctx *ctx) + { ++ struct preproc_buffer *buffer; ++ + if (ctx->expansion_count) + { + struct preproc_expansion *exp = &ctx->expansion_stack[ctx->expansion_count - 1]; +@@ -290,10 +310,8 @@ static void preproc_pop_buffer(struct preproc_ctx *ctx) + TRACE("File stack size is now %zu.\n", ctx->file_count); + } + +- if (ctx->expansion_count) +- yy_switch_to_buffer(ctx->expansion_stack[ctx->expansion_count - 1].buffer.lexer_buffer, ctx->scanner); +- else if (ctx->file_count) +- yy_switch_to_buffer(ctx->file_stack[ctx->file_count - 1].buffer.lexer_buffer, ctx->scanner); ++ if ((buffer = preproc_get_top_buffer(ctx))) ++ yy_switch_to_buffer(buffer->lexer_buffer, ctx->scanner); + } + + static int return_token(int token, YYSTYPE *lval, const char *text) +@@ -347,6 +365,7 @@ static bool preproc_push_expansion(struct preproc_ctx *ctx, + exp->text = text; + exp->buffer.lexer_buffer = yy_scan_bytes(text->text.buffer, text->text.content_size, ctx->scanner); + exp->buffer.location = text->location; ++ exp->buffer.eof = false; + exp->macro = macro; + exp->arg_values = arg_values; + TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count); +@@ -407,18 +426,17 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) + } + else + { +- if (ctx->last_was_eof) ++ if (preproc_get_top_buffer(ctx)->eof) + { + preproc_pop_buffer(ctx); + if (!ctx->file_count) + return 0; + } +- ctx->last_was_eof = false; + + VKD3D_ASSERT(ctx->file_count); + if (!(token = preproc_lexer_lex(lval, lloc, scanner))) + { +- ctx->last_was_eof = true; ++ preproc_get_top_buffer(ctx)->eof = true; + + /* If we have reached the end of an included file, inject a newline. */ + if (ctx->expansion_count) +@@ -781,6 +799,7 @@ bool preproc_push_include(struct preproc_ctx *ctx, char *filename, const struct + file->buffer.location.source_name = file->filename; + file->buffer.location.line = 1; + file->buffer.location.column = 1; ++ file->buffer.eof = false; + TRACE("File stack size is now %zu.\n", ctx->file_count); + ctx->last_was_newline = true; + return true; diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 7eddf47151b..c51a6a394c0 100644 +index 1f967c22406..c51a6a394c0 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -3102,17 +3102,17 @@ struct spirv_compiler +@@ -847,57 +847,6 @@ static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, enum vkd3d_s + vkd3d_shader_message_context_cleanup(&message_context); + } + +-enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval, +- unsigned int index) +-{ +- switch (sysval) +- { +- case VKD3D_SHADER_SV_COVERAGE: +- case VKD3D_SHADER_SV_DEPTH: +- case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL: +- case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL: +- case VKD3D_SHADER_SV_NONE: +- case VKD3D_SHADER_SV_STENCIL_REF: +- case VKD3D_SHADER_SV_TARGET: +- return VKD3D_SIV_NONE; +- case VKD3D_SHADER_SV_POSITION: +- return VKD3D_SIV_POSITION; +- case VKD3D_SHADER_SV_CLIP_DISTANCE: +- return VKD3D_SIV_CLIP_DISTANCE; +- case VKD3D_SHADER_SV_CULL_DISTANCE: +- return VKD3D_SIV_CULL_DISTANCE; +- case VKD3D_SHADER_SV_INSTANCE_ID: +- return VKD3D_SIV_INSTANCE_ID; +- case VKD3D_SHADER_SV_IS_FRONT_FACE: +- return VKD3D_SIV_IS_FRONT_FACE; +- case VKD3D_SHADER_SV_PRIMITIVE_ID: +- return VKD3D_SIV_PRIMITIVE_ID; +- case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX: +- return VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX; +- case VKD3D_SHADER_SV_SAMPLE_INDEX: +- return VKD3D_SIV_SAMPLE_INDEX; +- case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: +- return VKD3D_SIV_QUAD_U0_TESS_FACTOR + index; +- case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: +- return VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR + index; +- case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: +- return VKD3D_SIV_TRIANGLE_U_TESS_FACTOR + index; +- case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: +- return VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR; +- case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: +- return VKD3D_SIV_LINE_DETAIL_TESS_FACTOR; +- case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: +- return VKD3D_SIV_LINE_DENSITY_TESS_FACTOR; +- case VKD3D_SHADER_SV_VERTEX_ID: +- return VKD3D_SIV_VERTEX_ID; +- case VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX: +- return VKD3D_SIV_VIEWPORT_ARRAY_INDEX; +- default: +- FIXME("Unhandled sysval %#x, index %u.\n", sysval, index); +- return VKD3D_SIV_NONE; +- } +-} +- + struct vkd3d_spirv_stream + { + uint32_t *words; +@@ -1602,6 +1551,29 @@ static void vkd3d_spirv_build_op_name(struct vkd3d_spirv_builder *builder, + vkd3d_spirv_build_string(stream, name, name_size); + } + ++static uint32_t vkd3d_spirv_build_op_string(struct vkd3d_spirv_builder *builder, const char *s) ++{ ++ struct vkd3d_spirv_stream *stream = &builder->debug_stream; ++ uint32_t result_id = vkd3d_spirv_alloc_id(builder); ++ unsigned int size; ++ ++ size = vkd3d_spirv_string_word_count(s); ++ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(SpvOpString, 2 + size)); ++ vkd3d_spirv_build_word(stream, result_id); ++ vkd3d_spirv_build_string(stream, s, size); ++ ++ return result_id; ++} ++ ++static void vkd3d_spirv_build_op_source(struct vkd3d_spirv_builder *builder, const char *source_name) ++{ ++ struct vkd3d_spirv_stream *stream = &builder->debug_stream; ++ uint32_t source_id; ++ ++ source_id = vkd3d_spirv_build_op_string(builder, source_name ? source_name : ""); ++ vkd3d_spirv_build_op3(stream, SpvOpSource, 0, 0, source_id); ++} ++ + static void vkd3d_spirv_build_op_member_name(struct vkd3d_spirv_builder *builder, + uint32_t type_id, uint32_t member, const char *fmt, ...) + { +@@ -2513,18 +2485,6 @@ static uint32_t vkd3d_spirv_build_op_glsl_std450_fabs(struct vkd3d_spirv_builder + return vkd3d_spirv_build_op_glsl_std450_tr1(builder, GLSLstd450FAbs, result_type, operand); + } + +-static uint32_t vkd3d_spirv_build_op_glsl_std450_sin(struct vkd3d_spirv_builder *builder, +- uint32_t result_type, uint32_t operand) +-{ +- return vkd3d_spirv_build_op_glsl_std450_tr1(builder, GLSLstd450Sin, result_type, operand); +-} +- +-static uint32_t vkd3d_spirv_build_op_glsl_std450_cos(struct vkd3d_spirv_builder *builder, +- uint32_t result_type, uint32_t operand) +-{ +- return vkd3d_spirv_build_op_glsl_std450_tr1(builder, GLSLstd450Cos, result_type, operand); +-} +- + static uint32_t vkd3d_spirv_build_op_glsl_std450_max(struct vkd3d_spirv_builder *builder, + uint32_t result_type, uint32_t x, uint32_t y) + { +@@ -2616,7 +2576,8 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder + return vkd3d_spirv_get_type_id(builder, component_type, component_count); + } + +-static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, const char *entry_point) ++static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, ++ const char *entry_point, const char *source_name) + { + vkd3d_spirv_stream_init(&builder->debug_stream); + vkd3d_spirv_stream_init(&builder->annotation_stream); +@@ -2631,6 +2592,7 @@ static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, const + + rb_init(&builder->declarations, vkd3d_spirv_declaration_compare); + ++ vkd3d_spirv_build_op_source(builder, source_name); + builder->main_function_id = vkd3d_spirv_alloc_id(builder); + vkd3d_spirv_build_op_name(builder, builder->main_function_id, "%s", entry_point); + } +@@ -3140,17 +3102,17 @@ struct spirv_compiler static bool is_in_default_phase(const struct spirv_compiler *compiler) { @@ -8351,7 +15920,17 @@ index 7eddf47151b..c51a6a394c0 100644 } static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *compiler); -@@ -3295,7 +3295,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *p +@@ -3224,7 +3186,8 @@ static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *p + compiler->spirv_target_info = target_info; + } + +- vkd3d_spirv_builder_init(&compiler->spirv_builder, spirv_compiler_get_entry_point_name(compiler)); ++ vkd3d_spirv_builder_init(&compiler->spirv_builder, ++ spirv_compiler_get_entry_point_name(compiler), compile_info->source_name); + + compiler->formatting = VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT + | VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER; +@@ -3332,7 +3295,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *p else if (compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY) compiler->emit_point_size = compiler->xfb_info && compiler->xfb_info->element_count; @@ -8360,7 +15939,143 @@ index 7eddf47151b..c51a6a394c0 100644 vkd3d_string_buffer_cache_init(&compiler->string_buffers); -@@ -5536,13 +5536,13 @@ static void spirv_compiler_emit_shader_phase_name(struct spirv_compiler *compile +@@ -3559,8 +3522,12 @@ static struct vkd3d_shader_descriptor_binding spirv_compiler_get_descriptor_bind + goto done; + } + +- resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER +- ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE; ++ if (resource_type == VKD3D_SHADER_RESOURCE_NONE) ++ resource_type_flag = 0; ++ else if (resource_type == VKD3D_SHADER_RESOURCE_BUFFER) ++ resource_type_flag = VKD3D_SHADER_BINDING_FLAG_BUFFER; ++ else ++ resource_type_flag = VKD3D_SHADER_BINDING_FLAG_IMAGE; + + if (is_uav_counter) + { +@@ -3604,7 +3571,7 @@ static struct vkd3d_shader_descriptor_binding spirv_compiler_get_descriptor_bind + { + const struct vkd3d_shader_resource_binding *current = &shader_interface->bindings[i]; + +- if (!(current->flags & resource_type_flag)) ++ if ((current->flags & resource_type_flag) != resource_type_flag) + continue; + + if (!spirv_compiler_check_shader_visibility(compiler, current->shader_visibility)) +@@ -4239,7 +4206,7 @@ static bool spirv_compiler_get_register_info(struct spirv_compiler *compiler, + if (!(entry = rb_get(&compiler->symbol_table, ®_symbol))) + { + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE, +- "Unrecognized register (%s).\n", debug_vkd3d_symbol(®_symbol)); ++ "Unrecognized register (%s).", debug_vkd3d_symbol(®_symbol)); + memset(register_info, 0, sizeof(*register_info)); + return false; + } +@@ -4578,70 +4545,6 @@ static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compil + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); + } + +-/* Based on the implementation in the OpenGL Mathematics library. */ +-static uint32_t half_to_float(uint16_t value) +-{ +- uint32_t s = (value & 0x8000u) << 16; +- uint32_t e = (value >> 10) & 0x1fu; +- uint32_t m = value & 0x3ffu; +- +- if (!e) +- { +- if (!m) +- { +- /* Plus or minus zero */ +- return s; +- } +- else +- { +- /* Denormalized number -- renormalize it */ +- +- while (!(m & 0x400u)) +- { +- m <<= 1; +- --e; +- } +- +- ++e; +- m &= ~0x400u; +- } +- } +- else if (e == 31u) +- { +- /* Positive or negative infinity for zero 'm'. +- * Nan for non-zero 'm' -- preserve sign and significand bits */ +- return s | 0x7f800000u | (m << 13); +- } +- +- /* Normalized number */ +- e += 127u - 15u; +- m <<= 13; +- +- /* Assemble s, e and m. */ +- return s | (e << 23) | m; +-} +- +-static uint32_t convert_raw_constant32(enum vkd3d_data_type data_type, unsigned int uint_value) +-{ +- int16_t i; +- +- /* TODO: native 16-bit support. */ +- if (data_type != VKD3D_DATA_UINT16 && data_type != VKD3D_DATA_HALF) +- return uint_value; +- +- if (data_type == VKD3D_DATA_HALF) +- return half_to_float(uint_value); +- +- /* Values in DXIL have no signedness, so it is ambiguous whether 16-bit constants should or +- * should not be sign-extended when 16-bit execution is not supported. The AMD RX 580 Windows +- * driver has no 16-bit support, and sign-extends all 16-bit constant ints to 32 bits. These +- * results differ from SM 5. The RX 6750 XT supports 16-bit execution, so constants are not +- * extended, and results match SM 5. It seems best to replicate the sign-extension, and if +- * execution is 16-bit, the values will be truncated. */ +- i = uint_value; +- return (int32_t)i; +-} +- + static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, + const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) + { +@@ -4654,15 +4557,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] = convert_raw_constant32(reg->data_type, reg->u.immconst_u32[0]); ++ values[i] = reg->u.immconst_u32[0]; + } + else + { + for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) + { + if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) +- values[j++] = convert_raw_constant32(reg->data_type, +- reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]); ++ values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]; + } + } + +@@ -4806,13 +4708,6 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil + + switch (icb->data_type) + { +- case VKD3D_DATA_HALF: +- case VKD3D_DATA_UINT16: +- /* Scalar only. */ +- for (i = 0; i < element_count; ++i) +- elements[i] = vkd3d_spirv_get_op_constant(builder, elem_type_id, +- convert_raw_constant32(icb->data_type, icb->data[i])); +- break; + case VKD3D_DATA_FLOAT: + case VKD3D_DATA_INT: + case VKD3D_DATA_UINT: +@@ -5641,13 +5536,13 @@ static void spirv_compiler_emit_shader_phase_name(struct spirv_compiler *compile switch (compiler->phase) { @@ -8377,7 +16092,7 @@ index 7eddf47151b..c51a6a394c0 100644 name = "join"; break; default: -@@ -7405,7 +7405,7 @@ static void spirv_compiler_enter_shader_phase(struct spirv_compiler *compiler, +@@ -7510,7 +7405,7 @@ static void spirv_compiler_enter_shader_phase(struct spirv_compiler *compiler, compiler->phase = instruction->opcode; spirv_compiler_emit_shader_phase_name(compiler, function_id, NULL); @@ -8386,7 +16101,7 @@ index 7eddf47151b..c51a6a394c0 100644 ? &compiler->control_point_phase : &compiler->patch_constant_phase; phase->function_id = function_id; /* The insertion location must be set after the label is emitted. */ -@@ -7419,7 +7419,7 @@ static void spirv_compiler_initialise_block(struct spirv_compiler *compiler) +@@ -7524,7 +7419,7 @@ static void spirv_compiler_initialise_block(struct spirv_compiler *compiler) /* Insertion locations must point immediately after the function's initial label. */ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL) { @@ -8395,7 +16110,7 @@ index 7eddf47151b..c51a6a394c0 100644 ? &compiler->control_point_phase : &compiler->patch_constant_phase; if (!phase->function_location) phase->function_location = vkd3d_spirv_stream_current_location(&builder->function_stream); -@@ -7521,36 +7521,40 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru +@@ -7626,35 +7521,40 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru } alu_ops[] = { @@ -8412,7 +16127,6 @@ index 7eddf47151b..c51a6a394c0 100644 - {VKD3DSIH_FREM, SpvOpFRem}, - {VKD3DSIH_FTOD, SpvOpFConvert}, - {VKD3DSIH_IADD, SpvOpIAdd}, -- {VKD3DSIH_IMUL_LOW, SpvOpIMul}, - {VKD3DSIH_INEG, SpvOpSNegate}, - {VKD3DSIH_ISHL, SpvOpShiftLeftLogical}, - {VKD3DSIH_ISHR, SpvOpShiftRightArithmetic}, @@ -8466,7 +16180,7 @@ index 7eddf47151b..c51a6a394c0 100644 }; unsigned int i; -@@ -7567,11 +7571,11 @@ static SpvOp spirv_compiler_map_logical_instruction(const struct vkd3d_shader_in +@@ -7671,11 +7571,11 @@ static SpvOp spirv_compiler_map_logical_instruction(const struct vkd3d_shader_in { switch (instruction->opcode) { @@ -8481,7 +16195,7 @@ index 7eddf47151b..c51a6a394c0 100644 return SpvOpLogicalNotEqual; default: return SpvOpMax; -@@ -7590,20 +7594,20 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, +@@ -7694,20 +7594,20 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); if (dst->reg.data_type == VKD3D_DATA_HALF || dst->reg.data_type == VKD3D_DATA_FLOAT) { @@ -8506,7 +16220,7 @@ index 7eddf47151b..c51a6a394c0 100644 } else { -@@ -7618,15 +7622,16 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, +@@ -7722,15 +7622,16 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { @@ -8526,7 +16240,7 @@ index 7eddf47151b..c51a6a394c0 100644 { /* At least some drivers support this anyway, but if validation is enabled it will fail. */ FIXME("Unsupported 64-bit source for bit count.\n"); -@@ -7642,8 +7647,8 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil +@@ -7746,8 +7647,8 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil /* VSIR supports logic ops AND/OR/XOR on bool values. */ op = spirv_compiler_map_logical_instruction(instruction); } @@ -8537,7 +16251,15 @@ index 7eddf47151b..c51a6a394c0 100644 { /* VSIR supports cast from bool to signed/unsigned integer types and floating point types, * where bool is treated as a 1-bit integer and a signed 'true' value converts to -1. */ -@@ -7664,14 +7669,44 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil +@@ -7762,20 +7663,50 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil + + if (op == SpvOpMax) + { +- ERR("Unexpected instruction %#x.\n", instruction->opcode); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER, +- "Encountered invalid/unhandled instruction handler %#x.", instruction->opcode); ++ "Encountered invalid/unhandled instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); return VKD3D_ERROR_INVALID_SHADER; } @@ -8582,7 +16304,7 @@ index 7eddf47151b..c51a6a394c0 100644 /* The SPIR-V specification states, "The resulting value is undefined if * Shift is greater than or equal to the bit width of the components of * Base." Direct3D applies only the lowest 5 bits of the shift. -@@ -7679,8 +7714,8 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil +@@ -7783,8 +7714,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. */ @@ -8593,7 +16315,7 @@ index 7eddf47151b..c51a6a394c0 100644 { uint32_t mask_id = spirv_compiler_get_constant_vector(compiler, VKD3D_SHADER_COMPONENT_UINT, vsir_write_mask_component_count(dst->write_mask), 0x1f); -@@ -7692,6 +7727,9 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil +@@ -7796,6 +7727,9 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil if (instruction->flags & VKD3DSI_PRECISE_XYZW) vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); @@ -8603,7 +16325,7 @@ index 7eddf47151b..c51a6a394c0 100644 spirv_compiler_emit_store_dst(compiler, dst, val_id); return VKD3D_OK; } -@@ -7723,38 +7761,38 @@ static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( +@@ -7827,36 +7761,38 @@ static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( } glsl_insts[] = { @@ -8611,7 +16333,6 @@ index 7eddf47151b..c51a6a394c0 100644 - {VKD3DSIH_ACOS, GLSLstd450Acos}, - {VKD3DSIH_ASIN, GLSLstd450Asin}, - {VKD3DSIH_ATAN, GLSLstd450Atan}, -- {VKD3DSIH_COS, GLSLstd450Cos}, - {VKD3DSIH_DFMA, GLSLstd450Fma}, - {VKD3DSIH_DMAX, GLSLstd450NMax}, - {VKD3DSIH_DMIN, GLSLstd450NMin}, @@ -8634,7 +16355,6 @@ index 7eddf47151b..c51a6a394c0 100644 - {VKD3DSIH_ROUND_PI, GLSLstd450Ceil}, - {VKD3DSIH_ROUND_Z, GLSLstd450Trunc}, - {VKD3DSIH_RSQ, GLSLstd450InverseSqrt}, -- {VKD3DSIH_SIN, GLSLstd450Sin}, - {VKD3DSIH_SQRT, GLSLstd450Sqrt}, - {VKD3DSIH_TAN, GLSLstd450Tan}, - {VKD3DSIH_UMAX, GLSLstd450UMax}, @@ -8674,7 +16394,7 @@ index 7eddf47151b..c51a6a394c0 100644 }; unsigned int i; -@@ -7778,8 +7816,8 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp +@@ -7880,20 +7816,22 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp unsigned int i, component_count; enum GLSLstd450 glsl_inst; @@ -8684,8 +16404,25 @@ index 7eddf47151b..c51a6a394c0 100644 + || instruction->opcode == VSIR_OP_FIRSTBIT_LO || instruction->opcode == VSIR_OP_FIRSTBIT_SHI)) { /* At least some drivers support this anyway, but if validation is enabled it will fail. */ +- FIXME("Unsupported 64-bit source for handler %#x.\n", instruction->opcode); spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, -@@ -7810,8 +7848,8 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp +- "64-bit source for handler %#x is not supported.", instruction->opcode); ++ "64-bit source for instruction \"%s\" (%#x) is not supported.", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + return; + } + + glsl_inst = spirv_compiler_map_ext_glsl_instruction(instruction); + if (glsl_inst == GLSLstd450Bad) + { +- ERR("Unexpected instruction %#x.\n", instruction->opcode); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, ++ "Unhandled instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + return; + } + +@@ -7910,8 +7848,8 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id, instr_set_id, glsl_inst, src_id, instruction->src_count); @@ -8696,7 +16433,7 @@ index 7eddf47151b..c51a6a394c0 100644 { /* In D3D bits are numbered from the most significant bit. */ component_count = vsir_write_mask_component_count(dst->write_mask); -@@ -7848,7 +7886,8 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, +@@ -7948,7 +7886,8 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, || dst_reg_info.write_mask != src_reg_info.write_mask) goto general_implementation; @@ -8706,7 +16443,7 @@ index 7eddf47151b..c51a6a394c0 100644 { dst_id = spirv_compiler_get_register_id(compiler, &dst->reg); src_id = spirv_compiler_get_register_id(compiler, &src->reg); -@@ -7919,7 +7958,7 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, +@@ -8019,7 +7958,7 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, if (src[0].reg.data_type != VKD3D_DATA_BOOL) { @@ -8715,7 +16452,7 @@ index 7eddf47151b..c51a6a394c0 100644 condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpFOrdGreaterThanEqual, vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count), condition_id, spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count)); -@@ -7973,9 +8012,9 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, +@@ -8073,9 +8012,9 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, component_count = vsir_write_mask_component_count(dst->write_mask); component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); @@ -8727,7 +16464,73 @@ index 7eddf47151b..c51a6a394c0 100644 write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2; else write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; -@@ -8041,67 +8080,6 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, +@@ -8120,65 +8059,6 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler, + spirv_compiler_emit_store_dst(compiler, dst, val_id); + } + +-static void spirv_compiler_emit_sincos(struct spirv_compiler *compiler, +- const struct vkd3d_shader_instruction *instruction) +-{ +- const struct vkd3d_shader_dst_param *dst_sin = &instruction->dst[0]; +- const struct vkd3d_shader_dst_param *dst_cos = &instruction->dst[1]; +- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- const struct vkd3d_shader_src_param *src = instruction->src; +- uint32_t type_id, src_id, sin_id = 0, cos_id = 0; +- +- if (dst_sin->reg.type != VKD3DSPR_NULL) +- { +- type_id = spirv_compiler_get_type_id_for_dst(compiler, dst_sin); +- src_id = spirv_compiler_emit_load_src(compiler, src, dst_sin->write_mask); +- +- sin_id = vkd3d_spirv_build_op_glsl_std450_sin(builder, type_id, src_id); +- } +- +- if (dst_cos->reg.type != VKD3DSPR_NULL) +- { +- if (dst_sin->reg.type == VKD3DSPR_NULL || dst_cos->write_mask != dst_sin->write_mask) +- { +- type_id = spirv_compiler_get_type_id_for_dst(compiler, dst_cos); +- src_id = spirv_compiler_emit_load_src(compiler, src, dst_cos->write_mask); +- } +- +- cos_id = vkd3d_spirv_build_op_glsl_std450_cos(builder, type_id, src_id); +- } +- +- if (sin_id) +- spirv_compiler_emit_store_dst(compiler, dst_sin, sin_id); +- +- if (cos_id) +- spirv_compiler_emit_store_dst(compiler, dst_cos, cos_id); +-} +- +-static void spirv_compiler_emit_imul(struct spirv_compiler *compiler, +- const struct vkd3d_shader_instruction *instruction) +-{ +- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- const struct vkd3d_shader_dst_param *dst = instruction->dst; +- const struct vkd3d_shader_src_param *src = instruction->src; +- uint32_t type_id, val_id, src0_id, src1_id; +- +- if (dst[0].reg.type != VKD3DSPR_NULL) +- FIXME("Extended multiplies not implemented.\n"); /* SpvOpSMulExtended/SpvOpUMulExtended */ +- +- if (dst[1].reg.type == VKD3DSPR_NULL) +- return; +- +- 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); +- +- val_id = vkd3d_spirv_build_op_imul(builder, type_id, src0_id, src1_id); +- +- spirv_compiler_emit_store_dst(compiler, &dst[1], val_id); +-} +- + static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { +@@ -8200,67 +8080,6 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, spirv_compiler_emit_store_dst(compiler, dst, val_id); } @@ -8795,7 +16598,7 @@ index 7eddf47151b..c51a6a394c0 100644 static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { -@@ -8254,9 +8232,9 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp +@@ -8413,11 +8232,13 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp switch (instruction->opcode) { @@ -8806,9 +16609,14 @@ index 7eddf47151b..c51a6a394c0 100644 + case VSIR_OP_IBFE: op = SpvOpBitFieldSExtract; break; + case VSIR_OP_UBFE: op = SpvOpBitFieldUExtract; break; default: - spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, - "Unhandled instruction \"%s\" (%#x).", -@@ -8374,24 +8352,24 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co +- ERR("Unexpected instruction %#x.\n", instruction->opcode); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, ++ "Unhandled instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + return; + } + +@@ -8531,26 +8352,28 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co switch (instruction->opcode) { @@ -8849,9 +16657,14 @@ index 7eddf47151b..c51a6a394c0 100644 + case VSIR_OP_UGE: op = SpvOpUGreaterThanEqual; break; + case VSIR_OP_ULT: op = SpvOpULessThan; break; default: - spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, - "Unhandled instruction \"%s\" (%#x).", -@@ -8403,10 +8381,10 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co +- ERR("Unexpected instruction %#x.\n", instruction->opcode); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, ++ "Unhandled instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + return; + } + +@@ -8558,10 +8381,10 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co switch (instruction->opcode) { @@ -8866,7 +16679,7 @@ index 7eddf47151b..c51a6a394c0 100644 write_mask = vkd3d_write_mask_from_component_count(component_count); break; -@@ -8441,7 +8419,7 @@ static void spirv_compiler_emit_orderedness_instruction(struct spirv_compiler *c +@@ -8596,7 +8419,7 @@ static void spirv_compiler_emit_orderedness_instruction(struct spirv_compiler *c src0_id = vkd3d_spirv_build_op_is_nan(builder, type_id, src0_id); src1_id = vkd3d_spirv_build_op_is_nan(builder, type_id, src1_id); val_id = vkd3d_spirv_build_op_logical_or(builder, type_id, src0_id, src1_id); @@ -8875,7 +16688,7 @@ index 7eddf47151b..c51a6a394c0 100644 val_id = vkd3d_spirv_build_op_logical_not(builder, type_id, val_id); spirv_compiler_emit_store_dst(compiler, dst, val_id); } -@@ -8458,8 +8436,8 @@ static void spirv_compiler_emit_float_comparison_instruction(struct spirv_compil +@@ -8613,8 +8436,8 @@ static void spirv_compiler_emit_float_comparison_instruction(struct spirv_compil switch (instruction->opcode) { @@ -8886,7 +16699,7 @@ index 7eddf47151b..c51a6a394c0 100644 default: vkd3d_unreachable(); } -@@ -8762,12 +8740,12 @@ static void spirv_compiler_emit_deriv_instruction(struct spirv_compiler *compile +@@ -8917,12 +8740,12 @@ static void spirv_compiler_emit_deriv_instruction(struct spirv_compiler *compile } deriv_instructions[] = { @@ -8905,7 +16718,18 @@ index 7eddf47151b..c51a6a394c0 100644 }; info = NULL; -@@ -8994,7 +8972,7 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, +@@ -8936,7 +8759,9 @@ static void spirv_compiler_emit_deriv_instruction(struct spirv_compiler *compile + } + if (!info) + { +- ERR("Unexpected instruction %#x.\n", instruction->opcode); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, ++ "Unhandled instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + return; + } + +@@ -9147,7 +8972,7 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, uint32_t coordinate_mask; bool multisample; @@ -8914,7 +16738,7 @@ index 7eddf47151b..c51a6a394c0 100644 spirv_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE); -@@ -9075,16 +9053,16 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, +@@ -9228,16 +9053,16 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, switch (instruction->opcode) { @@ -8934,7 +16758,7 @@ index 7eddf47151b..c51a6a394c0 100644 op = SpvOpImageSampleExplicitLod; operands_mask |= SpvImageOperandsGradMask; component_count = image.resource_type_info->coordinate_component_count - image.resource_type_info->arrayed; -@@ -9094,7 +9072,7 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, +@@ -9247,14 +9072,16 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, image_operands[image_operand_count++] = spirv_compiler_emit_load_src(compiler, &src[4], coordinate_mask); break; @@ -8943,7 +16767,17 @@ index 7eddf47151b..c51a6a394c0 100644 op = SpvOpImageSampleExplicitLod; operands_mask |= SpvImageOperandsLodMask; image_operands[image_operand_count++] = spirv_compiler_emit_load_src(compiler, -@@ -9137,7 +9115,7 @@ static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, + &src[3], VKD3DSP_WRITEMASK_0); + break; + default: +- ERR("Unexpected instruction %#x.\n", instruction->opcode); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, ++ "Unhandled instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + return; + } + +@@ -9288,7 +9115,7 @@ static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, uint32_t image_operands[2]; SpvOp op; @@ -8952,7 +16786,7 @@ index 7eddf47151b..c51a6a394c0 100644 { op = SpvOpImageSampleDrefExplicitLod; operands_mask |= SpvImageOperandsLodMask; -@@ -9187,12 +9165,12 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, +@@ -9338,12 +9165,12 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, uint32_t coordinate_mask; bool extended_offset; @@ -8969,7 +16803,7 @@ index 7eddf47151b..c51a6a394c0 100644 addr = &src[0]; offset = extended_offset ? &src[1] : NULL; -@@ -9650,7 +9628,7 @@ static void spirv_compiler_emit_uav_counter_instruction(struct spirv_compiler *c +@@ -9801,7 +9628,7 @@ static void spirv_compiler_emit_uav_counter_instruction(struct spirv_compiler *c uint32_t operands[3]; SpvOp op; @@ -8978,7 +16812,7 @@ index 7eddf47151b..c51a6a394c0 100644 ? SpvOpAtomicIIncrement : SpvOpAtomicIDecrement; resource_symbol = spirv_compiler_find_resource(compiler, &src->reg); -@@ -9721,25 +9699,25 @@ static SpvOp spirv_compiler_map_atomic_instruction(const struct vkd3d_shader_ins +@@ -9872,25 +9699,25 @@ static SpvOp spirv_compiler_map_atomic_instruction(const struct vkd3d_shader_ins } atomic_ops[] = { @@ -9023,7 +16857,7 @@ index 7eddf47151b..c51a6a394c0 100644 }; unsigned int i; -@@ -9754,7 +9732,7 @@ static SpvOp spirv_compiler_map_atomic_instruction(const struct vkd3d_shader_ins +@@ -9905,7 +9732,7 @@ static SpvOp spirv_compiler_map_atomic_instruction(const struct vkd3d_shader_ins static bool is_imm_atomic_instruction(enum vkd3d_shader_opcode opcode) { @@ -9032,7 +16866,30 @@ index 7eddf47151b..c51a6a394c0 100644 } static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compiler, -@@ -10191,13 +10169,13 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, +@@ -9935,7 +9762,9 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + op = spirv_compiler_map_atomic_instruction(instruction); + if (op == SpvOpMax) + { +- ERR("Unexpected instruction %#x.\n", instruction->opcode); ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, ++ "Unhandled instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + return; + } + +@@ -10014,9 +9843,9 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil + + if (instruction->flags & VKD3DARF_VOLATILE) + { +- WARN("Ignoring 'volatile' attribute.\n"); + spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_IGNORING_FLAG, +- "Ignoring the 'volatile' attribute flag for atomic instruction %#x.", instruction->opcode); ++ "Ignoring the 'volatile' attribute flag for atomic instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + } + + memory_semantic = (instruction->flags & VKD3DARF_SEQ_CST) +@@ -10340,13 +10169,13 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, src_ids[src_count++] = register_info.id; @@ -9048,7 +16905,7 @@ index 7eddf47151b..c51a6a394c0 100644 op = GLSLstd450InterpolateAtSample; src_ids[src_count++] = spirv_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0); } -@@ -10279,7 +10257,7 @@ static void spirv_compiler_emit_emit_stream(struct spirv_compiler *compiler, +@@ -10428,7 +10257,7 @@ static void spirv_compiler_emit_emit_stream(struct spirv_compiler *compiler, struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; unsigned int stream_idx; @@ -9057,7 +16914,7 @@ index 7eddf47151b..c51a6a394c0 100644 stream_idx = instruction->src[0].reg.idx[0].offset; else stream_idx = 0; -@@ -10300,7 +10278,7 @@ static void spirv_compiler_emit_cut_stream(struct spirv_compiler *compiler, +@@ -10449,7 +10278,7 @@ static void spirv_compiler_emit_cut_stream(struct spirv_compiler *compiler, struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; unsigned int stream_idx; @@ -9066,7 +16923,7 @@ index 7eddf47151b..c51a6a394c0 100644 stream_idx = instruction->src[0].reg.idx[0].offset; else stream_idx = 0; -@@ -10318,11 +10296,11 @@ static uint32_t map_quad_read_across_direction(enum vkd3d_shader_opcode opcode) +@@ -10467,11 +10296,11 @@ static uint32_t map_quad_read_across_direction(enum vkd3d_shader_opcode opcode) { switch (opcode) { @@ -9081,7 +16938,7 @@ index 7eddf47151b..c51a6a394c0 100644 return 2; default: vkd3d_unreachable(); -@@ -10377,11 +10355,11 @@ static SpvOp map_wave_bool_op(enum vkd3d_shader_opcode opcode) +@@ -10526,11 +10355,11 @@ static SpvOp map_wave_bool_op(enum vkd3d_shader_opcode opcode) { switch (opcode) { @@ -9096,7 +16953,7 @@ index 7eddf47151b..c51a6a394c0 100644 return SpvOpGroupNonUniformAny; default: vkd3d_unreachable(); -@@ -10435,27 +10413,27 @@ static SpvOp map_wave_alu_op(enum vkd3d_shader_opcode opcode, bool is_float) +@@ -10584,27 +10413,27 @@ static SpvOp map_wave_alu_op(enum vkd3d_shader_opcode opcode, bool is_float) { switch (opcode) { @@ -9135,7 +16992,7 @@ index 7eddf47151b..c51a6a394c0 100644 return SpvOpGroupNonUniformUMin; default: vkd3d_unreachable(); -@@ -10494,7 +10472,7 @@ static void spirv_compiler_emit_wave_bit_count(struct spirv_compiler *compiler, +@@ -10643,7 +10472,7 @@ static void spirv_compiler_emit_wave_bit_count(struct spirv_compiler *compiler, SpvGroupOperation group_op; uint32_t type_id, val_id; @@ -9144,7 +17001,7 @@ index 7eddf47151b..c51a6a394c0 100644 : SpvGroupOperationReduce; val_id = spirv_compiler_emit_group_nonuniform_ballot(compiler, instruction->src); -@@ -10582,359 +10560,359 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, +@@ -10731,369 +10560,365 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, switch (instruction->opcode) { @@ -9235,7 +17092,6 @@ index 7eddf47151b..c51a6a394c0 100644 - case VKD3DSIH_FREM: - case VKD3DSIH_FTOD: - case VKD3DSIH_IADD: -- case VKD3DSIH_IMUL_LOW: - case VKD3DSIH_INEG: - case VKD3DSIH_ISHL: - case VKD3DSIH_ISHR: @@ -9294,7 +17150,6 @@ index 7eddf47151b..c51a6a394c0 100644 - case VKD3DSIH_ACOS: - case VKD3DSIH_ASIN: - case VKD3DSIH_ATAN: -- case VKD3DSIH_COS: - case VKD3DSIH_HCOS: - case VKD3DSIH_HSIN: - case VKD3DSIH_HTAN: @@ -9317,7 +17172,6 @@ index 7eddf47151b..c51a6a394c0 100644 - case VKD3DSIH_ROUND_PI: - case VKD3DSIH_ROUND_Z: - case VKD3DSIH_RSQ: -- case VKD3DSIH_SIN: - case VKD3DSIH_SQRT: - case VKD3DSIH_TAN: - case VKD3DSIH_UMAX: @@ -9370,6 +17224,13 @@ index 7eddf47151b..c51a6a394c0 100644 + case VSIR_OP_RCP: spirv_compiler_emit_rcp(compiler, instruction); break; +- case VKD3DSIH_SINCOS: +- spirv_compiler_emit_sincos(compiler, instruction); +- break; +- case VKD3DSIH_IMUL: +- case VKD3DSIH_UMUL: +- spirv_compiler_emit_imul(compiler, instruction); +- break; - case VKD3DSIH_IMAD: + case VSIR_OP_IMAD: spirv_compiler_emit_imad(compiler, instruction); @@ -9723,11 +17584,27 @@ index 7eddf47151b..c51a6a394c0 100644 /* nothing to do */ break; default: +- FIXME("Unhandled instruction %#x.\n", instruction->opcode); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER, +- "Encountered invalid/unhandled instruction handler %#x.", instruction->opcode); ++ "Unhandled instruction \"%s\" (%#x).", ++ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); + break; + } + diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 01af2f6ebbd..c7eafbc79f3 100644 +index 29b03871e05..c7eafbc79f3 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -655,7 +655,7 @@ struct sm4_index_range_array +@@ -261,6 +261,7 @@ enum vkd3d_sm4_opcode + VKD3D_SM4_OP_DCL_INPUT_PS_SGV = 0x63, + VKD3D_SM4_OP_DCL_INPUT_PS_SIV = 0x64, + VKD3D_SM4_OP_DCL_OUTPUT = 0x65, ++ VKD3D_SM4_OP_DCL_OUTPUT_SGV = 0x66, + VKD3D_SM4_OP_DCL_OUTPUT_SIV = 0x67, + VKD3D_SM4_OP_DCL_TEMPS = 0x68, + VKD3D_SM4_OP_DCL_INDEXABLE_TEMP = 0x69, +@@ -654,7 +655,7 @@ struct sm4_index_range_array struct vkd3d_sm4_lookup_tables { const struct vkd3d_sm4_opcode_info *opcode_info_from_sm4[VKD3D_SM4_OP_COUNT]; @@ -9736,7 +17613,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 const struct vkd3d_sm4_register_type_info *register_type_info_from_sm4[VKD3D_SM4_REGISTER_TYPE_COUNT]; const struct vkd3d_sm4_register_type_info *register_type_info_from_vkd3d[VKD3DSPR_COUNT]; const struct vkd3d_sm4_stat_field_info *stat_field_from_sm4[VKD3D_SM4_OP_COUNT]; -@@ -823,7 +823,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui +@@ -822,7 +823,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui if (type != VKD3D_SM4_SHADER_DATA_IMMEDIATE_CONSTANT_BUFFER) { FIXME("Ignoring shader data type %#x.\n", type); @@ -9745,7 +17622,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 return; } -@@ -832,7 +832,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui +@@ -831,7 +832,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui if (icb_size % 4) { FIXME("Unexpected immediate constant buffer size %u.\n", icb_size); @@ -9754,7 +17631,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 return; } -@@ -840,7 +840,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui +@@ -839,7 +840,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui { ERR("Failed to allocate immediate constant buffer, size %u.\n", icb_size); vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory."); @@ -9763,7 +17640,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 return; } icb->register_idx = 0; -@@ -964,7 +964,7 @@ static void shader_sm4_read_dcl_sampler(struct vkd3d_shader_instruction *ins, ui +@@ -963,7 +964,7 @@ static void shader_sm4_read_dcl_sampler(struct vkd3d_shader_instruction *ins, ui static bool sm4_parser_is_in_fork_or_join_phase(const struct vkd3d_shader_sm4_parser *sm4) { @@ -9772,7 +17649,25 @@ index 01af2f6ebbd..c7eafbc79f3 100644 } static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins, uint32_t opcode, -@@ -1441,275 +1441,275 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) +@@ -1168,7 +1169,7 @@ static void shader_sm4_read_dcl_input_ps(struct vkd3d_shader_instruction *ins, u + WARN("No matching signature element for input register %u with mask %#x.\n", + dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); + vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_DCL, +- "No matching signature element for input register %u with mask %#x.\n", ++ "No matching signature element for input register %u with mask %#x.", + dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); + } + else +@@ -1194,7 +1195,7 @@ static void shader_sm4_read_dcl_input_ps_siv(struct vkd3d_shader_instruction *in + WARN("No matching signature element for input register %u with mask %#x.\n", + dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); + vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_DCL, +- "No matching signature element for input register %u with mask %#x.\n", ++ "No matching signature element for input register %u with mask %#x.", + dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); + } + else +@@ -1440,273 +1441,275 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) */ static const struct vkd3d_sm4_opcode_info opcode_table[] = { @@ -9993,13 +17888,12 @@ index 01af2f6ebbd..c7eafbc79f3 100644 - {VKD3D_SM4_OP_DCL_OUTPUT, VKD3DSIH_DCL_OUTPUT, "", "", + {VKD3D_SM4_OP_DCL_OUTPUT, VSIR_OP_DCL_OUTPUT, "", "", shader_sm4_read_declaration_dst}, -- {VKD3D_SM4_OP_DCL_OUTPUT_SGV, VKD3DSIH_DCL_OUTPUT_SGV, "", "", +- {VKD3D_SM4_OP_DCL_OUTPUT_SIV, VKD3DSIH_DCL_OUTPUT_SIV, "", "", + {VKD3D_SM4_OP_DCL_OUTPUT_SGV, VSIR_OP_DCL_OUTPUT_SGV, "", "", shader_sm4_read_declaration_register_semantic}, -- {VKD3D_SM4_OP_DCL_OUTPUT_SIV, VKD3DSIH_DCL_OUTPUT_SIV, "", "", -+ {VKD3D_SM4_OP_DCL_OUTPUT_SIV, VSIR_OP_DCL_OUTPUT_SIV, "", "", - shader_sm4_read_declaration_register_semantic}, - {VKD3D_SM4_OP_DCL_TEMPS, VKD3DSIH_DCL_TEMPS, "", "", ++ {VKD3D_SM4_OP_DCL_OUTPUT_SIV, VSIR_OP_DCL_OUTPUT_SIV, "", "", ++ shader_sm4_read_declaration_register_semantic}, + {VKD3D_SM4_OP_DCL_TEMPS, VSIR_OP_DCL_TEMPS, "", "", shader_sm4_read_declaration_count}, - {VKD3D_SM4_OP_DCL_INDEXABLE_TEMP, VKD3DSIH_DCL_INDEXABLE_TEMP, "", "", @@ -10269,7 +18163,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 }; static const struct vkd3d_sm4_register_type_info register_type_table[] = -@@ -1944,7 +1944,7 @@ static const struct vkd3d_sm4_opcode_info *get_info_from_sm4_opcode( +@@ -1941,7 +1944,7 @@ static const struct vkd3d_sm4_opcode_info *get_info_from_sm4_opcode( static const struct vkd3d_sm4_opcode_info *get_info_from_vsir_opcode( const struct vkd3d_sm4_lookup_tables *lookup, enum vkd3d_shader_opcode vsir_opcode) { @@ -10278,7 +18172,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 return NULL; return lookup->opcode_info_from_vsir[vsir_opcode]; } -@@ -2289,7 +2289,7 @@ static bool register_is_control_point_input(const struct vkd3d_shader_register * +@@ -2286,7 +2289,7 @@ static bool register_is_control_point_input(const struct vkd3d_shader_register * const struct vkd3d_shader_sm4_parser *priv) { return reg->type == VKD3DSPR_INCONTROLPOINT || reg->type == VKD3DSPR_OUTCONTROLPOINT @@ -10287,7 +18181,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 || priv->p.program->shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY)); } -@@ -2656,16 +2656,16 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str +@@ -2653,16 +2656,16 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str if (!(opcode_info = get_info_from_sm4_opcode(&sm4->lookup, opcode))) { FIXME("Unrecognized opcode %#x, opcode_token 0x%08x.\n", opcode, opcode_token); @@ -10308,7 +18202,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 ins->flags = 0; ins->coissue = false; ins->raw = false; -@@ -2678,7 +2678,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str +@@ -2675,7 +2678,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str { ERR("Failed to allocate src parameters.\n"); vkd3d_shader_parser_error(&sm4->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory."); @@ -10317,7 +18211,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 return; } ins->resource_type = VKD3D_SHADER_RESOURCE_NONE; -@@ -2720,7 +2720,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str +@@ -2717,7 +2720,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str { ERR("Failed to allocate dst parameters.\n"); vkd3d_shader_parser_error(&sm4->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory."); @@ -10326,7 +18220,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 return; } for (i = 0; i < ins->dst_count; ++i) -@@ -2728,7 +2728,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str +@@ -2725,7 +2728,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str if (!(shader_sm4_read_dst_param(sm4, &p, *ptr, map_data_type(opcode_info->dst_info[i]), &dst_params[i]))) { @@ -10335,7 +18229,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 return; } dst_params[i].modifiers |= instruction_dst_modifier; -@@ -2739,7 +2739,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str +@@ -2736,7 +2739,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str if (!(shader_sm4_read_src_param(sm4, &p, *ptr, map_data_type(opcode_info->src_info[i]), &src_params[i]))) { @@ -10344,7 +18238,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 return; } } -@@ -2749,7 +2749,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str +@@ -2746,7 +2749,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str fail: *ptr = sm4->end; @@ -10353,7 +18247,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 return; } -@@ -2971,7 +2971,7 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con +@@ -2968,7 +2971,7 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con ins = &instructions->elements[instructions->count]; shader_sm4_read_instruction(&sm4, ins); @@ -10362,7 +18256,89 @@ index 01af2f6ebbd..c7eafbc79f3 100644 { WARN("Encountered unrecognized or invalid instruction.\n"); vsir_program_cleanup(program); -@@ -3868,20 +3868,20 @@ static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_s +@@ -3129,6 +3132,9 @@ bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *s + {"position", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_POSITION}, + {"sv_position", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_POSITION}, + {"sv_primitiveid", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_PRIMITIVE_ID}, ++ {"sv_isfrontface", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_IS_FRONT_FACE}, ++ {"sv_rendertargetarrayindex", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX}, ++ {"sv_viewportarrayindex", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX}, + + {"sv_outputcontrolpointid", false, VKD3D_SHADER_TYPE_HULL, ~0u}, + {"sv_position", false, VKD3D_SHADER_TYPE_HULL, ~0u}, +@@ -3255,6 +3261,8 @@ static int signature_element_pointer_compare(const void *x, const void *y) + const struct signature_element *f = *(const struct signature_element **)y; + int ret; + ++ if ((ret = vkd3d_u32_compare(e->stream_index, f->stream_index))) ++ return ret; + if ((ret = vkd3d_u32_compare(e->register_index, f->register_index))) + return ret; + return vkd3d_u32_compare(e->mask, f->mask); +@@ -3263,12 +3271,17 @@ static int signature_element_pointer_compare(const void *x, const void *y) + static void tpf_write_signature(struct tpf_compiler *tpf, const struct shader_signature *signature, uint32_t tag) + { + bool has_minimum_precision = tpf->program->global_flags & VKD3DSGF_ENABLE_MINIMUM_PRECISION; +- bool output = tag == TAG_OSGN || (tag == TAG_PCSG +- && tpf->program->shader_version.type == VKD3D_SHADER_TYPE_HULL); ++ const struct vkd3d_shader_version *version = &tpf->program->shader_version; + const struct signature_element **sorted_elements; + struct vkd3d_bytecode_buffer buffer = {0}; ++ bool has_stream_index, output; + unsigned int i; + ++ output = tag == TAG_OSGN || (tag == TAG_PCSG && version->type == VKD3D_SHADER_TYPE_HULL); ++ if (output && version->type == VKD3D_SHADER_TYPE_GEOMETRY && version->major >= 5) ++ tag = TAG_OSG5; ++ has_stream_index = tag == TAG_OSG5 || has_minimum_precision; ++ + put_u32(&buffer, signature->element_count); + put_u32(&buffer, 8); /* unknown */ + +@@ -3291,8 +3304,8 @@ static void tpf_write_signature(struct tpf_compiler *tpf, const struct shader_si + if (sysval >= VKD3D_SHADER_SV_TARGET) + sysval = VKD3D_SHADER_SV_NONE; + +- if (has_minimum_precision) +- put_u32(&buffer, 0); /* FIXME: stream index */ ++ if (has_stream_index) ++ put_u32(&buffer, element->stream_index); + put_u32(&buffer, 0); /* name */ + put_u32(&buffer, element->semantic_index); + put_u32(&buffer, sysval); +@@ -3306,13 +3319,16 @@ static void tpf_write_signature(struct tpf_compiler *tpf, const struct shader_si + for (i = 0; i < signature->element_count; ++i) + { + const struct signature_element *element = sorted_elements[i]; ++ size_t name_index = 2 + i * 6; + size_t string_offset; + +- string_offset = put_string(&buffer, element->semantic_name); ++ if (has_stream_index) ++ name_index += i + 1; + if (has_minimum_precision) +- set_u32(&buffer, (2 + i * 8 + 1) * sizeof(uint32_t), string_offset); +- else +- set_u32(&buffer, (2 + i * 6) * sizeof(uint32_t), string_offset); ++ name_index += i; ++ ++ string_offset = put_string(&buffer, element->semantic_name); ++ set_u32(&buffer, name_index * sizeof(uint32_t), string_offset); + } + + if (has_minimum_precision) +@@ -3843,9 +3859,8 @@ static uint32_t pack_resource_data_type(const enum vkd3d_data_type *resource_dat + + static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_shader_instruction *ins) + { +- const struct vkd3d_shader_structured_resource *structured_resource = &ins->declaration.structured_resource; +- const struct vkd3d_shader_semantic *semantic = &ins->declaration.semantic; + const struct vkd3d_shader_version *version = &tpf->program->shader_version; ++ const struct vkd3d_shader_resource *resource; + const struct vkd3d_sm4_opcode_info *info; + struct sm4_instruction instr = {0}; + bool uav; +@@ -3853,33 +3868,44 @@ static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_s info = get_info_from_vsir_opcode(&tpf->lookup, ins->opcode); VKD3D_ASSERT(info); @@ -10375,20 +18351,63 @@ index 01af2f6ebbd..c7eafbc79f3 100644 instr.opcode = info->opcode; +- instr.dsts[0] = semantic->resource.reg; +- instr.dst_count = 1; +- - if (ins->opcode == VKD3DSIH_DCL || ins->opcode == VKD3DSIH_DCL_UAV_TYPED) + if (ins->opcode == VSIR_OP_DCL || ins->opcode == VSIR_OP_DCL_UAV_TYPED) { - instr.idx[0] = pack_resource_data_type(ins->declaration.semantic.resource_data_type); +- instr.idx[0] = pack_resource_data_type(semantic->resource_data_type); ++ instr.idx[0] = pack_resource_data_type(ins->declaration.semantic.resource_data_type); instr.idx_count = 1; - instr.extra_bits |= ins->declaration.semantic.sample_count << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; - resource = &ins->declaration.semantic.resource; - } -- else if (ins->opcode == VKD3DSIH_DCL_RESOURCE_RAW || ins->opcode == VKD3DSIH_DCL_UAV_RAW) ++ instr.extra_bits |= ins->declaration.semantic.sample_count << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; ++ resource = &ins->declaration.semantic.resource; ++ } + else if (ins->opcode == VSIR_OP_DCL_RESOURCE_RAW || ins->opcode == VSIR_OP_DCL_UAV_RAW) - { - resource = &ins->declaration.raw_resource.resource; ++ { ++ resource = &ins->declaration.raw_resource.resource; ++ } ++ else ++ { ++ instr.byte_stride = ins->declaration.structured_resource.byte_stride; ++ resource = &ins->declaration.structured_resource.resource; } -@@ -4046,6 +4046,39 @@ static void tpf_write_dcl_vertices_out(const struct tpf_compiler *tpf, unsigned + ++ instr.dsts[0] = resource->reg; ++ instr.dst_count = 1; ++ + if (vkd3d_shader_ver_ge(version, 5, 1)) + { +- instr.dsts[0].reg.idx[0].offset = semantic->resource.reg.reg.idx[0].offset; +- instr.dsts[0].reg.idx[1].offset = semantic->resource.range.first; +- instr.dsts[0].reg.idx[2].offset = semantic->resource.range.last; ++ instr.dsts[0].reg.idx[0].offset = resource->reg.reg.idx[0].offset; ++ instr.dsts[0].reg.idx[1].offset = resource->range.first; ++ instr.dsts[0].reg.idx[2].offset = resource->range.last; + instr.dsts[0].reg.idx_count = 3; + +- instr.idx[instr.idx_count++] = semantic->resource.range.space; ++ instr.idx[instr.idx_count++] = resource->range.space; + } + else + { +- instr.dsts[0].reg.idx[0].offset = semantic->resource.range.first; ++ instr.dsts[0].reg.idx[0].offset = resource->range.first; + instr.dsts[0].reg.idx_count = 1; + } + +@@ -3887,10 +3913,6 @@ static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_s + instr.extra_bits |= ins->flags << VKD3D_SM5_UAV_FLAGS_SHIFT; + + instr.extra_bits |= (sm4_resource_dimension(ins->resource_type) << VKD3D_SM4_RESOURCE_TYPE_SHIFT); +- instr.extra_bits |= semantic->sample_count << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; +- +- if (ins->structured) +- instr.byte_stride = structured_resource->byte_stride; + + write_sm4_instruction(tpf, &instr); + } +@@ -4024,6 +4046,39 @@ static void tpf_write_dcl_vertices_out(const struct tpf_compiler *tpf, unsigned write_sm4_instruction(tpf, &instr); } @@ -10428,7 +18447,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 static void tpf_simple_instruction(struct tpf_compiler *tpf, const struct vkd3d_shader_instruction *ins) { struct sm4_instruction_modifier *modifier; -@@ -4082,6 +4115,7 @@ static void tpf_simple_instruction(struct tpf_compiler *tpf, const struct vkd3d_ +@@ -4060,6 +4115,7 @@ static void tpf_simple_instruction(struct tpf_compiler *tpf, const struct vkd3d_ for (unsigned int i = 0; i < ins->dst_count; ++i) { instr.dsts[i] = ins->dst[i]; @@ -10436,7 +18455,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 if (instr.dsts[i].modifiers & VKD3DSPDM_SATURATE) { -@@ -4092,7 +4126,10 @@ static void tpf_simple_instruction(struct tpf_compiler *tpf, const struct vkd3d_ +@@ -4070,7 +4126,10 @@ static void tpf_simple_instruction(struct tpf_compiler *tpf, const struct vkd3d_ } } for (unsigned int i = 0; i < ins->src_count; ++i) @@ -10447,7 +18466,7 @@ index 01af2f6ebbd..c7eafbc79f3 100644 if (ins->texel_offset.u || ins->texel_offset.v || ins->texel_offset.w) { -@@ -4117,184 +4154,184 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ +@@ -4095,177 +4154,184 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ { switch (ins->opcode) { @@ -10501,12 +18520,11 @@ index 01af2f6ebbd..c7eafbc79f3 100644 tpf_dcl_semantic(tpf, VKD3D_SM4_OP_DCL_OUTPUT, &ins->declaration.dst, 0); break; -- case VKD3DSIH_DCL_OUTPUT_SGV: -+ case VSIR_OP_DCL_OUTPUT_SGV: - tpf_dcl_siv_semantic(tpf, VKD3D_SM4_OP_DCL_OUTPUT_SGV, &ins->declaration.register_semantic, 0); - break; - - case VKD3DSIH_DCL_OUTPUT_SIV: ++ case VSIR_OP_DCL_OUTPUT_SGV: ++ tpf_dcl_siv_semantic(tpf, VKD3D_SM4_OP_DCL_OUTPUT_SGV, &ins->declaration.register_semantic, 0); ++ break; ++ + case VSIR_OP_DCL_OUTPUT_SIV: tpf_dcl_siv_semantic(tpf, VKD3D_SM4_OP_DCL_OUTPUT_SIV, &ins->declaration.register_semantic, 0); break; @@ -10544,8 +18562,6 @@ index 01af2f6ebbd..c7eafbc79f3 100644 - case VKD3DSIH_CASE: - case VKD3DSIH_CONTINUE: - case VKD3DSIH_CUT: -- case VKD3DSIH_CUT_STREAM: -- case VKD3DSIH_DCL_STREAM: - case VKD3DSIH_DEFAULT: - case VKD3DSIH_DISCARD: - case VKD3DSIH_DIV: @@ -10560,7 +18576,6 @@ index 01af2f6ebbd..c7eafbc79f3 100644 - case VKD3DSIH_DSY_FINE: - case VKD3DSIH_ELSE: - case VKD3DSIH_EMIT: -- case VKD3DSIH_EMIT_STREAM: - case VKD3DSIH_ENDIF: - case VKD3DSIH_ENDLOOP: - case VKD3DSIH_ENDSWITCH: @@ -10768,11 +18783,140 @@ index 01af2f6ebbd..c7eafbc79f3 100644 tpf_simple_instruction(tpf, ins); break; +@@ -4434,6 +4500,9 @@ int tpf_compile(struct vsir_program *program, uint64_t config_flags, const struc + size_t i; + int ret; + ++ if ((ret = vsir_allocate_temp_registers(program, message_context))) ++ return ret; ++ + tpf.program = program; + tpf.buffer = NULL; + tpf.stat = &stat; diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index 2cd23cba1f5..4cda8493696 100644 +index f56608940db..4cda8493696 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -1041,11 +1041,11 @@ static bool vkd3d_shader_instruction_is_uav_read(const struct vkd3d_shader_instr +@@ -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') +@@ -336,7 +338,10 @@ bool vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_cont + 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) + { +- if (context->log_level < level) ++ struct vkd3d_string_buffer *messages = &context->messages; ++ size_t pos = messages->content_size; ++ ++ if (!WARN_ON() && context->log_level < level) + return; + + if (location) +@@ -344,19 +349,26 @@ void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const stru + const char *source_name = location->source_name ? location->source_name : ""; + + if (location->line) +- vkd3d_string_buffer_printf(&context->messages, "%s:%u:%u: ", ++ vkd3d_string_buffer_printf(messages, "%s:%u:%u: ", + source_name, location->line, location->column); + else +- vkd3d_string_buffer_printf(&context->messages, "%s: ", source_name); ++ vkd3d_string_buffer_printf(messages, "%s: ", source_name); + } +- vkd3d_string_buffer_vprintf(&context->messages, format, args); +- vkd3d_string_buffer_printf(&context->messages, "\n"); ++ vkd3d_string_buffer_vprintf(messages, format, args); ++ vkd3d_string_buffer_printf(messages, "\n"); ++ ++ WARN("%.*s", (int)(messages->content_size - pos), &messages->buffer[pos]); ++ if (context->log_level < level) ++ messages->content_size = pos; + } + + 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) + { +- if (context->log_level < VKD3D_SHADER_LOG_WARNING) ++ struct vkd3d_string_buffer *messages = &context->messages; ++ size_t pos = messages->content_size; ++ ++ if (!WARN_ON() && context->log_level < VKD3D_SHADER_LOG_WARNING) + return; + + if (location) +@@ -364,17 +376,21 @@ void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const s + const char *source_name = location->source_name ? location->source_name : ""; + + if (location->line) +- vkd3d_string_buffer_printf(&context->messages, "%s:%u:%u: W%04u: ", ++ vkd3d_string_buffer_printf(messages, "%s:%u:%u: W%04u: ", + source_name, location->line, location->column, error); + else +- vkd3d_string_buffer_printf(&context->messages, "%s: W%04u: ", source_name, error); ++ vkd3d_string_buffer_printf(messages, "%s: W%04u: ", source_name, error); + } + else + { +- vkd3d_string_buffer_printf(&context->messages, "W%04u: ", error); ++ vkd3d_string_buffer_printf(messages, "W%04u: ", error); + } +- vkd3d_string_buffer_vprintf(&context->messages, format, args); +- vkd3d_string_buffer_printf(&context->messages, "\n"); ++ vkd3d_string_buffer_vprintf(messages, format, args); ++ vkd3d_string_buffer_printf(messages, "\n"); ++ ++ WARN("%.*s", (int)(messages->content_size - pos), &messages->buffer[pos]); ++ if (context->log_level < VKD3D_SHADER_LOG_WARNING) ++ messages->content_size = pos; + } + + void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, +@@ -390,7 +406,10 @@ void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const st + 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) + { +- if (context->log_level < VKD3D_SHADER_LOG_ERROR) ++ struct vkd3d_string_buffer *messages = &context->messages; ++ size_t pos = messages->content_size; ++ ++ if (!WARN_ON() && context->log_level < VKD3D_SHADER_LOG_ERROR) + return; + + if (location) +@@ -398,17 +417,21 @@ void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const str + const char *source_name = location->source_name ? location->source_name : ""; + + if (location->line) +- vkd3d_string_buffer_printf(&context->messages, "%s:%u:%u: E%04u: ", ++ vkd3d_string_buffer_printf(messages, "%s:%u:%u: E%04u: ", + source_name, location->line, location->column, error); + else +- vkd3d_string_buffer_printf(&context->messages, "%s: E%04u: ", source_name, error); ++ vkd3d_string_buffer_printf(messages, "%s: E%04u: ", source_name, error); + } + else + { +- vkd3d_string_buffer_printf(&context->messages, "E%04u: ", error); ++ vkd3d_string_buffer_printf(messages, "E%04u: ", error); + } +- vkd3d_string_buffer_vprintf(&context->messages, format, args); +- vkd3d_string_buffer_printf(&context->messages, "\n"); ++ vkd3d_string_buffer_vprintf(messages, format, args); ++ vkd3d_string_buffer_printf(messages, "\n"); ++ ++ WARN("%.*s", (int)(messages->content_size - pos), &messages->buffer[pos]); ++ if (context->log_level < VKD3D_SHADER_LOG_ERROR) ++ messages->content_size = pos; + } + + void vkd3d_shader_error(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, +@@ -1018,11 +1041,11 @@ static bool vkd3d_shader_instruction_is_uav_read(const struct vkd3d_shader_instr { enum vkd3d_shader_opcode opcode = instruction->opcode; @@ -10789,7 +18933,7 @@ index 2cd23cba1f5..4cda8493696 100644 } static void vkd3d_shader_scan_record_uav_read(struct vkd3d_shader_scan_context *context, -@@ -1058,7 +1058,7 @@ static bool vkd3d_shader_instruction_is_uav_counter(const struct vkd3d_shader_in +@@ -1035,7 +1058,7 @@ static bool vkd3d_shader_instruction_is_uav_counter(const struct vkd3d_shader_in { enum vkd3d_shader_opcode opcode = instruction->opcode; @@ -10798,7 +18942,7 @@ index 2cd23cba1f5..4cda8493696 100644 } static void vkd3d_shader_scan_record_uav_counter(struct vkd3d_shader_scan_context *context, -@@ -1071,8 +1071,8 @@ static bool vkd3d_shader_instruction_is_uav_atomic_op(const struct vkd3d_shader_ +@@ -1048,8 +1071,8 @@ static bool vkd3d_shader_instruction_is_uav_atomic_op(const struct vkd3d_shader_ { enum vkd3d_shader_opcode opcode = instruction->opcode; @@ -10809,7 +18953,7 @@ index 2cd23cba1f5..4cda8493696 100644 } static void vkd3d_shader_scan_record_uav_atomic_op(struct vkd3d_shader_scan_context *context, -@@ -1283,13 +1283,13 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1260,13 +1283,13 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte switch (instruction->opcode) { @@ -10826,7 +18970,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (instruction->declaration.semantic.resource_type == VKD3D_SHADER_RESOURCE_NONE) break; -@@ -1299,33 +1299,33 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1276,33 +1299,33 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte break; } /* fall through */ @@ -10870,7 +19014,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_IF) { vkd3d_shader_scan_error(context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF, -@@ -1334,7 +1334,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1311,7 +1334,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte } cf_info->inside_block = true; break; @@ -10879,7 +19023,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_IF) { vkd3d_shader_scan_error(context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF, -@@ -1343,12 +1343,12 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1320,12 +1343,12 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte } vkd3d_shader_scan_pop_cf_info(context); break; @@ -10894,7 +19038,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_LOOP) { vkd3d_shader_scan_error(context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF, -@@ -1357,11 +1357,11 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1334,11 +1357,11 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte } vkd3d_shader_scan_pop_cf_info(context); break; @@ -10908,7 +19052,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_SWITCH || cf_info->inside_block) { -@@ -1371,7 +1371,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1348,7 +1371,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte } vkd3d_shader_scan_pop_cf_info(context); break; @@ -10917,7 +19061,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_SWITCH) { -@@ -1381,7 +1381,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1358,7 +1381,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte } cf_info->inside_block = true; break; @@ -10926,7 +19070,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (!(cf_info = vkd3d_shader_scan_get_current_cf_info(context)) || cf_info->type != VKD3D_SHADER_BLOCK_SWITCH) { -@@ -1398,7 +1398,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1375,7 +1398,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte cf_info->inside_block = true; cf_info->has_default = true; break; @@ -10935,7 +19079,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (!(cf_info = vkd3d_shader_scan_find_innermost_breakable_cf_info(context))) { vkd3d_shader_scan_error(context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF, -@@ -1407,7 +1407,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1384,7 +1407,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte } cf_info->inside_block = false; break; @@ -10944,7 +19088,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (!(cf_info = vkd3d_shader_scan_find_innermost_loop_cf_info(context))) { vkd3d_shader_scan_error(context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF, -@@ -1415,7 +1415,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1392,7 +1415,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte return VKD3D_ERROR_INVALID_SHADER; } break; @@ -10953,7 +19097,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (!(cf_info = vkd3d_shader_scan_find_innermost_loop_cf_info(context))) { vkd3d_shader_scan_error(context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF, -@@ -1424,7 +1424,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1401,7 +1424,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte } cf_info->inside_block = false; break; @@ -10962,7 +19106,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (!(cf_info = vkd3d_shader_scan_find_innermost_loop_cf_info(context))) { vkd3d_shader_scan_error(context, VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF, -@@ -1432,60 +1432,60 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte +@@ -1409,59 +1432,60 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte return VKD3D_ERROR_INVALID_SHADER; } break; @@ -10971,7 +19115,7 @@ index 2cd23cba1f5..4cda8493696 100644 if (context->cf_info_count) context->cf_info[context->cf_info_count - 1].inside_block = false; break; -- case VKD3DSIH_TEXLD: +- case VKD3DSIH_TEX: + case VSIR_OP_TEXLD: if (context->version->major == 1) sampler_reg = &instruction->dst[0].reg; @@ -10979,7 +19123,6 @@ index 2cd23cba1f5..4cda8493696 100644 sampler_reg = &instruction->src[1].reg; vkd3d_shader_scan_combined_sampler_usage(context, sampler_reg, sampler_reg); break; -- case VKD3DSIH_TEX: - case VKD3DSIH_TEXBEM: - case VKD3DSIH_TEXBEML: - case VKD3DSIH_TEXDP3TEX: @@ -11053,11 +19196,86 @@ index 2cd23cba1f5..4cda8493696 100644 if (instruction->src[2].reg.type == VKD3DSPR_RESOURCE) vkd3d_shader_scan_combined_sampler_usage(context, &instruction->src[2].reg, NULL); break; +@@ -1805,6 +1829,10 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, + { + ret = fx_parse(compile_info, out, &message_context); + } ++ else if (compile_info->source_type == VKD3D_SHADER_SOURCE_TX) ++ { ++ ret = tx_parse(compile_info, out, &message_context); ++ } + else + { + uint64_t config_flags = vkd3d_shader_init_config_flags(); +@@ -2013,6 +2041,7 @@ const enum vkd3d_shader_source_type *vkd3d_shader_get_supported_source_types(uns + VKD3D_SHADER_SOURCE_D3D_BYTECODE, + VKD3D_SHADER_SOURCE_DXBC_DXIL, + VKD3D_SHADER_SOURCE_FX, ++ VKD3D_SHADER_SOURCE_TX, + }; + + TRACE("count %p.\n", count); +@@ -2077,6 +2106,11 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( + VKD3D_SHADER_TARGET_D3D_ASM, + }; + ++ static const enum vkd3d_shader_target_type tx_types[] = ++ { ++ VKD3D_SHADER_TARGET_D3D_ASM, ++ }; ++ + TRACE("source_type %#x, count %p.\n", source_type, count); + + switch (source_type) +@@ -2101,6 +2135,10 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( + *count = ARRAY_SIZE(fx_types); + return fx_types; + ++ case VKD3D_SHADER_SOURCE_TX: ++ *count = ARRAY_SIZE(tx_types); ++ return tx_types; ++ + default: + *count = 0; + return NULL; diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 254303f1bbb..5d7fc6e1209 100644 +index 3b4fb626fcc..5d7fc6e1209 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -281,339 +281,342 @@ enum vkd3d_shader_error +@@ -174,6 +174,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_ERROR_HLSL_INVALID_MAX_VERTEX_COUNT = 5042, + VKD3D_SHADER_ERROR_HLSL_MISSING_PRIMITIVE_TYPE = 5043, + VKD3D_SHADER_ERROR_HLSL_MISPLACED_STREAM_OUTPUT = 5044, ++ VKD3D_SHADER_ERROR_HLSL_MISSING_INPUT_PATCH = 5045, + + VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, + VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, +@@ -182,6 +183,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_WARNING_HLSL_NON_FINITE_RESULT = 5304, + VKD3D_SHADER_WARNING_HLSL_IGNORED_ATTRIBUTE = 5305, + VKD3D_SHADER_WARNING_HLSL_IGNORED_DEFAULT_VALUE = 5306, ++ VKD3D_SHADER_WARNING_HLSL_IGNORED_MODIFIER = 5307, + + VKD3D_SHADER_ERROR_GLSL_INTERNAL = 6000, + VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND = 6001, +@@ -222,6 +224,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES = 8017, + VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES = 8018, + VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE = 8019, ++ VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT = 8020, + + VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300, + VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301, +@@ -236,7 +239,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_WARNING_DXIL_UNDEFINED_OPERAND = 8310, + + VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, +- VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001, ++ VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE = 9001, + VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE = 9002, + VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK = 9003, + VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS = 9004, +@@ -278,334 +281,345 @@ enum vkd3d_shader_error enum vkd3d_shader_opcode { @@ -11092,7 +19310,6 @@ index 254303f1bbb..5d7fc6e1209 100644 - VKD3DSIH_CND, - VKD3DSIH_CONTINUE, - VKD3DSIH_CONTINUEP, -- VKD3DSIH_COS, - VKD3DSIH_COUNTBITS, - VKD3DSIH_CRS, - VKD3DSIH_CUT, @@ -11121,7 +19338,6 @@ index 254303f1bbb..5d7fc6e1209 100644 - VKD3DSIH_DCL_INTERFACE, - VKD3DSIH_DCL_OUTPUT, - VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT, -- VKD3DSIH_DCL_OUTPUT_SGV, - VKD3DSIH_DCL_OUTPUT_SIV, - VKD3DSIH_DCL_OUTPUT_TOPOLOGY, - VKD3DSIH_DCL_RESOURCE_RAW, @@ -11236,7 +19452,6 @@ index 254303f1bbb..5d7fc6e1209 100644 - VKD3DSIH_IMM_ATOMIC_UMIN, - VKD3DSIH_IMM_ATOMIC_XOR, - VKD3DSIH_IMUL, -- VKD3DSIH_IMUL_LOW, - VKD3DSIH_INE, - VKD3DSIH_INEG, - VKD3DSIH_ISFINITE, @@ -11320,7 +19535,6 @@ index 254303f1bbb..5d7fc6e1209 100644 - VKD3DSIH_SETP, - VKD3DSIH_SGE, - VKD3DSIH_SGN, -- VKD3DSIH_SIN, - VKD3DSIH_SINCOS, - VKD3DSIH_SLT, - VKD3DSIH_SQRT, @@ -11337,12 +19551,10 @@ index 254303f1bbb..5d7fc6e1209 100644 - VKD3DSIH_TEXBEM, - VKD3DSIH_TEXBEML, - VKD3DSIH_TEXCOORD, -- VKD3DSIH_TEXCRD, - VKD3DSIH_TEXDEPTH, - VKD3DSIH_TEXDP3, - VKD3DSIH_TEXDP3TEX, - VKD3DSIH_TEXKILL, -- VKD3DSIH_TEXLD, - VKD3DSIH_TEXLDD, - VKD3DSIH_TEXLDL, - VKD3DSIH_TEXM3x2DEPTH, @@ -11394,6 +19606,7 @@ index 254303f1bbb..5d7fc6e1209 100644 - VKD3DSIH_INVALID, - - VKD3DSIH_COUNT, +-}; + VSIR_OP_ABS, + VSIR_OP_ACOS, + VSIR_OP_ADD, @@ -11730,11 +19943,104 @@ index 254303f1bbb..5d7fc6e1209 100644 + VSIR_OP_INVALID, + + VSIR_OP_COUNT, ++}; ++ ++const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error); + + enum vkd3d_shader_register_type + { +@@ -964,7 +978,7 @@ struct vkd3d_shader_register + enum vsir_dimension dimension; + /* known address alignment for optimisation, or zero */ + unsigned int alignment; +- union ++ union vsir_immediate_constant + { + uint32_t immconst_u32[VKD3D_VEC4_SIZE]; + float immconst_f32[VKD3D_VEC4_SIZE]; +@@ -1332,12 +1346,6 @@ static inline bool register_is_constant_or_undef(const struct vkd3d_shader_regis + return register_is_constant(reg) || register_is_undef(reg); + } + +-static inline bool register_is_scalar_constant_zero(const struct vkd3d_shader_register *reg) +-{ +- return register_is_constant(reg) && reg->dimension == VSIR_DIMENSION_SCALAR +- && (data_type_is_64_bit(reg->data_type) ? !reg->u.immconst_u64[0] : !reg->u.immconst_u32[0]); +-} +- + static inline bool register_is_numeric_array(const struct vkd3d_shader_register *reg) + { + return (reg->type == VKD3DSPR_IMMCONSTBUFFER || reg->type == VKD3DSPR_IDXTEMP +@@ -1500,6 +1508,8 @@ struct vsir_program + size_t block_name_count; }; - const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error); ++enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, ++ struct vkd3d_shader_message_context *message_context); + void vsir_program_cleanup(struct vsir_program *program); + int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, +@@ -1682,6 +1692,8 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con + struct vkd3d_shader_message_context *message_context, struct vsir_program *program); + int fx_parse(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); ++int tx_parse(const struct vkd3d_shader_compile_info *compile_info, ++ struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); + + void free_dxbc_shader_desc(struct dxbc_shader_desc *desc); + +@@ -1779,14 +1791,6 @@ static inline bool component_type_is_64_bit(enum vkd3d_shader_component_type com + return component_type == VKD3D_SHADER_COMPONENT_DOUBLE || component_type == VKD3D_SHADER_COMPONENT_UINT64; + } + +-enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval, +- unsigned int index); +- +-static inline enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum vkd3d_shader_sysval_semantic sysval) +-{ +- return vkd3d_siv_from_sysval_indexed(sysval, 0); +-} +- + static inline unsigned int vsir_write_mask_get_component_idx(uint32_t write_mask) + { + unsigned int i; +@@ -1853,6 +1857,8 @@ static inline uint32_t vsir_write_mask_32_from_64(uint32_t write_mask64) + } + } + ++const char *debug_vsir_writemask(unsigned int writemask); ++ + static inline uint32_t vsir_swizzle_64_from_32(uint32_t swizzle32) + { + switch (swizzle32) +@@ -1902,6 +1908,12 @@ static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned + return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK; + } + ++static inline void vsir_swizzle_set_component(uint32_t *swizzle, unsigned int idx, unsigned int component) ++{ ++ *swizzle &= ~(VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(idx)); ++ *swizzle |= component << VKD3D_SHADER_SWIZZLE_SHIFT(idx); ++} ++ + static inline unsigned int vkd3d_compact_swizzle(uint32_t swizzle, uint32_t write_mask) + { + unsigned int i, compacted_swizzle = 0; +diff --git a/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c b/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c +index f2b18b665f8..c41f8bae806 100644 +--- a/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c ++++ b/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c +@@ -19,6 +19,8 @@ + #include "vkd3d_utils_private.h" + #undef D3D12CreateDevice + ++/* VKD3D_DEBUG_ENV_NAME("VKD3D_DEBUG"); */ ++ + static const char *debug_d3d_blob_part(D3D_BLOB_PART part) + { + switch (part) diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c -index cb184986f2a..14382103acc 100644 +index cb184986f2a..7946445ad07 100644 --- a/libs/vkd3d/libs/vkd3d/resource.c +++ b/libs/vkd3d/libs/vkd3d/resource.c @@ -310,6 +310,9 @@ static ULONG STDMETHODCALLTYPE d3d12_heap_AddRef(ID3D12Heap *iface) @@ -11817,8 +20123,122 @@ index cb184986f2a..14382103acc 100644 } else { +@@ -2491,20 +2492,41 @@ static void descriptor_writes_free_object_refs(struct descriptor_writes *writes, + writes->held_ref_count = 0; + } + ++static enum vkd3d_vk_descriptor_set_index vkd3d_vk_descriptor_set_index_from_vk_descriptor_type( ++ VkDescriptorType type) ++{ ++ static const enum vkd3d_vk_descriptor_set_index table[] = ++ { ++ [VK_DESCRIPTOR_TYPE_SAMPLER] = VKD3D_SET_INDEX_SAMPLER, ++ [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = VKD3D_SET_INDEX_COUNT, ++ [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = VKD3D_SET_INDEX_SAMPLED_IMAGE, ++ [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = VKD3D_SET_INDEX_STORAGE_IMAGE, ++ [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = VKD3D_SET_INDEX_UNIFORM_TEXEL_BUFFER, ++ [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = VKD3D_SET_INDEX_STORAGE_TEXEL_BUFFER, ++ [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = VKD3D_SET_INDEX_UNIFORM_BUFFER, ++ }; ++ ++ VKD3D_ASSERT(type < ARRAY_SIZE(table)); ++ VKD3D_ASSERT(table[type] < VKD3D_SET_INDEX_COUNT); ++ ++ return table[type]; ++} ++ + static void d3d12_desc_write_vk_heap_null_descriptor(struct d3d12_descriptor_heap *descriptor_heap, +- uint32_t dst_array_element, struct descriptor_writes *writes, struct d3d12_device *device) ++ uint32_t dst_array_element, struct descriptor_writes *writes, struct d3d12_device *device, ++ VkDescriptorType type) + { + 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, end; ++ enum vkd3d_vk_descriptor_set_index set; + unsigned int i = writes->count; + +- end = device->vk_info.EXT_mutable_descriptor_type ? VKD3D_SET_INDEX_MUTABLE +- : 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 <= end; ++set) ++ for (set = VKD3D_SET_INDEX_UNIFORM_BUFFER; set <= VKD3D_SET_INDEX_STORAGE_IMAGE; ++set) + { ++ if (device->vk_info.EXT_mutable_descriptor_type) ++ set = vkd3d_vk_descriptor_set_index_from_vk_descriptor_type(type); + descriptor_set = &descriptor_heap->vk_descriptor_sets[set]; + writes->vk_descriptor_writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes->vk_descriptor_writes[i].pNext = NULL; +@@ -2545,6 +2567,8 @@ static void d3d12_desc_write_vk_heap_null_descriptor(struct d3d12_descriptor_hea + VK_CALL(vkUpdateDescriptorSets(device->vk_device, i, writes->vk_descriptor_writes, 0, NULL)); + descriptor_writes_free_object_refs(writes, device); + i = 0; ++ if (device->vk_info.EXT_mutable_descriptor_type) ++ break; + } + + writes->count = i; +@@ -2609,7 +2633,7 @@ static void d3d12_desc_write_vk_heap(struct d3d12_descriptor_heap *descriptor_he + break; + } + if (is_null && device->vk_info.EXT_robustness2) +- return d3d12_desc_write_vk_heap_null_descriptor(descriptor_heap, dst_array_element, writes, device); ++ return d3d12_desc_write_vk_heap_null_descriptor(descriptor_heap, dst_array_element, writes, device, type); + + ++i; + if (u.header->magic == VKD3D_DESCRIPTOR_MAGIC_UAV && u.view->v.vk_counter_view) +@@ -4223,17 +4247,6 @@ static const struct ID3D12DescriptorHeapVtbl d3d12_descriptor_heap_vtbl = + d3d12_descriptor_heap_GetGPUDescriptorHandleForHeapStart, + }; + +-const enum vkd3d_vk_descriptor_set_index vk_descriptor_set_index_table[] = +-{ +- VKD3D_SET_INDEX_SAMPLER, +- VKD3D_SET_INDEX_COUNT, +- VKD3D_SET_INDEX_SAMPLED_IMAGE, +- VKD3D_SET_INDEX_STORAGE_IMAGE, +- VKD3D_SET_INDEX_UNIFORM_TEXEL_BUFFER, +- VKD3D_SET_INDEX_STORAGE_TEXEL_BUFFER, +- VKD3D_SET_INDEX_UNIFORM_BUFFER, +-}; +- + static HRESULT d3d12_descriptor_heap_create_descriptor_pool(struct d3d12_descriptor_heap *descriptor_heap, + struct d3d12_device *device, const D3D12_DESCRIPTOR_HEAP_DESC *desc) + { +diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c +index 819185796c0..0a5bd1122e3 100644 +--- a/libs/vkd3d/libs/vkd3d/state.c ++++ b/libs/vkd3d/libs/vkd3d/state.c +@@ -2383,7 +2383,9 @@ static HRESULT create_shader_stage(struct d3d12_device *device, + const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + struct vkd3d_shader_compile_info compile_info; + struct VkShaderModuleCreateInfo shader_desc; ++ struct vkd3d_shader_dxbc_desc dxbc_desc; + struct vkd3d_shader_code spirv = {0}; ++ char source_name[33]; + VkResult vr; + int ret; + +@@ -2416,6 +2418,16 @@ static HRESULT create_shader_stage(struct d3d12_device *device, + compile_info.log_level = VKD3D_SHADER_LOG_NONE; + compile_info.source_name = NULL; + ++ if ((ret = vkd3d_shader_parse_dxbc(&(struct vkd3d_shader_code){code->pShaderBytecode, code->BytecodeLength}, ++ 0, &dxbc_desc, NULL)) >= 0) ++ { ++ sprintf(source_name, "%08x%08x%08x%08x", dxbc_desc.checksum[0], ++ dxbc_desc.checksum[1], dxbc_desc.checksum[2], dxbc_desc.checksum[3]); ++ vkd3d_shader_free_dxbc(&dxbc_desc); ++ TRACE("Compiling shader \"%s\".\n", source_name); ++ compile_info.source_name = source_name; ++ } ++ + if ((ret = vkd3d_shader_parse_dxbc_source_type(&compile_info.source, &compile_info.source_type, NULL)) < 0 + || (ret = vkd3d_shader_compile(&compile_info, &spirv, NULL)) < 0) + { diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -index 7e54738b19e..3559d0b0944 100644 +index 7e54738b19e..9fb6834158f 100644 --- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h @@ -436,7 +436,7 @@ struct d3d12_heap @@ -11830,6 +20250,24 @@ index 7e54738b19e..3559d0b0944 100644 bool is_private; D3D12_HEAP_DESC desc; +@@ -827,17 +827,6 @@ enum vkd3d_vk_descriptor_set_index + VKD3D_SET_INDEX_COUNT + }; + +-extern const enum vkd3d_vk_descriptor_set_index vk_descriptor_set_index_table[]; +- +-static inline enum vkd3d_vk_descriptor_set_index vkd3d_vk_descriptor_set_index_from_vk_descriptor_type( +- VkDescriptorType type) +-{ +- VKD3D_ASSERT(type <= VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); +- VKD3D_ASSERT(vk_descriptor_set_index_table[type] < VKD3D_SET_INDEX_COUNT); +- +- return vk_descriptor_set_index_table[type]; +-} +- + struct vkd3d_vk_descriptor_heap_layout + { + VkDescriptorType type; -- 2.47.2 diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch deleted file mode 100644 index 1716755e..00000000 --- a/patches/vkd3d-latest/0001-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch +++ /dev/null @@ -1,6661 +0,0 @@ -From 6bda17c53c7627d3fdabdcc69e2f8daa965c5996 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Mon, 26 May 2025 07:03:34 +1000 -Subject: [PATCH] Updated vkd3d to a8ca1f95c50561a16de5769646dcda0c045b7a46. - ---- - libs/vkd3d/include/private/vkd3d_common.h | 3 +- - libs/vkd3d/include/private/vkd3d_version.h | 2 +- - libs/vkd3d/libs/vkd3d-common/blob.c | 1 + - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 332 +------ - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 26 +- - libs/vkd3d/libs/vkd3d-shader/dxbc.c | 10 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 915 ++++++++++-------- - libs/vkd3d/libs/vkd3d-shader/fx.c | 747 +++++++++----- - libs/vkd3d/libs/vkd3d-shader/glsl.c | 14 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 1 + - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 3 + - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 263 +++-- - libs/vkd3d/libs/vkd3d-shader/ir.c | 431 ++++++++- - libs/vkd3d/libs/vkd3d-shader/msl.c | 440 +++++++-- - libs/vkd3d/libs/vkd3d-shader/preproc.h | 2 +- - libs/vkd3d/libs/vkd3d-shader/preproc.l | 39 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 145 +-- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 79 +- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 60 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 23 +- - .../vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c | 2 + - 21 files changed, 2159 insertions(+), 1379 deletions(-) - -diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h -index beb23257fb7..0501e6a06c2 100644 ---- a/libs/vkd3d/include/private/vkd3d_common.h -+++ b/libs/vkd3d/include/private/vkd3d_common.h -@@ -66,6 +66,7 @@ - - #define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9') - #define TAG_CLI4 VKD3D_MAKE_TAG('C', 'L', 'I', '4') -+#define TAG_CLIT VKD3D_MAKE_TAG('C', 'L', 'I', 'T') - #define TAG_CTAB VKD3D_MAKE_TAG('C', 'T', 'A', 'B') - #define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C') - #define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L') -@@ -278,7 +279,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/private/vkd3d_version.h b/libs/vkd3d/include/private/vkd3d_version.h -index 0edc4428022..687751d6a5f 100644 ---- a/libs/vkd3d/include/private/vkd3d_version.h -+++ b/libs/vkd3d/include/private/vkd3d_version.h -@@ -1 +1 @@ --#define VKD3D_VCS_ID " (Wine bundled)" -+#define VKD3D_VCS_ID " (git a8ca1f95)" -diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c -index f60ef7db769..c2c6ad67804 100644 ---- a/libs/vkd3d/libs/vkd3d-common/blob.c -+++ b/libs/vkd3d/libs/vkd3d-common/blob.c -@@ -20,6 +20,7 @@ - #define WIDL_C_INLINE_WRAPPERS - #endif - #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 4521bfabd8e..af5552635cb 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -27,333 +27,6 @@ - #include - #include - --static const char * const shader_opcode_names[] = --{ -- [VKD3DSIH_ABS ] = "abs", -- [VKD3DSIH_ACOS ] = "acos", -- [VKD3DSIH_ADD ] = "add", -- [VKD3DSIH_AND ] = "and", -- [VKD3DSIH_ASIN ] = "asin", -- [VKD3DSIH_ATAN ] = "atan", -- [VKD3DSIH_ATOMIC_AND ] = "atomic_and", -- [VKD3DSIH_ATOMIC_CMP_STORE ] = "atomic_cmp_store", -- [VKD3DSIH_ATOMIC_IADD ] = "atomic_iadd", -- [VKD3DSIH_ATOMIC_IMAX ] = "atomic_imax", -- [VKD3DSIH_ATOMIC_IMIN ] = "atomic_imin", -- [VKD3DSIH_ATOMIC_OR ] = "atomic_or", -- [VKD3DSIH_ATOMIC_UMAX ] = "atomic_umax", -- [VKD3DSIH_ATOMIC_UMIN ] = "atomic_umin", -- [VKD3DSIH_ATOMIC_XOR ] = "atomic_xor", -- [VKD3DSIH_BEM ] = "bem", -- [VKD3DSIH_BFI ] = "bfi", -- [VKD3DSIH_BFREV ] = "bfrev", -- [VKD3DSIH_BRANCH ] = "branch", -- [VKD3DSIH_BREAK ] = "break", -- [VKD3DSIH_BREAKC ] = "break", -- [VKD3DSIH_BREAKP ] = "breakp", -- [VKD3DSIH_BUFINFO ] = "bufinfo", -- [VKD3DSIH_CALL ] = "call", -- [VKD3DSIH_CALLNZ ] = "callnz", -- [VKD3DSIH_CASE ] = "case", -- [VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED ] = "check_access_fully_mapped", -- [VKD3DSIH_CMP ] = "cmp", -- [VKD3DSIH_CND ] = "cnd", -- [VKD3DSIH_CONTINUE ] = "continue", -- [VKD3DSIH_CONTINUEP ] = "continuec", -- [VKD3DSIH_COUNTBITS ] = "countbits", -- [VKD3DSIH_CRS ] = "crs", -- [VKD3DSIH_CUT ] = "cut", -- [VKD3DSIH_CUT_STREAM ] = "cut_stream", -- [VKD3DSIH_DADD ] = "dadd", -- [VKD3DSIH_DCL ] = "dcl", -- [VKD3DSIH_DCL_CONSTANT_BUFFER ] = "dcl_constantBuffer", -- [VKD3DSIH_DCL_FUNCTION_BODY ] = "dcl_function_body", -- [VKD3DSIH_DCL_FUNCTION_TABLE ] = "dcl_function_table", -- [VKD3DSIH_DCL_GLOBAL_FLAGS ] = "dcl_globalFlags", -- [VKD3DSIH_DCL_GS_INSTANCES ] = "dcl_gs_instances", -- [VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT] = "dcl_hs_fork_phase_instance_count", -- [VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT] = "dcl_hs_join_phase_instance_count", -- [VKD3DSIH_DCL_HS_MAX_TESSFACTOR ] = "dcl_hs_max_tessfactor", -- [VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER ] = "dcl_immediateConstantBuffer", -- [VKD3DSIH_DCL_INDEX_RANGE ] = "dcl_index_range", -- [VKD3DSIH_DCL_INDEXABLE_TEMP ] = "dcl_indexableTemp", -- [VKD3DSIH_DCL_INPUT ] = "dcl_input", -- [VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT ] = "dcl_input_control_point_count", -- [VKD3DSIH_DCL_INPUT_PRIMITIVE ] = "dcl_inputprimitive", -- [VKD3DSIH_DCL_INPUT_PS ] = "dcl_input_ps", -- [VKD3DSIH_DCL_INPUT_PS_SGV ] = "dcl_input_ps_sgv", -- [VKD3DSIH_DCL_INPUT_PS_SIV ] = "dcl_input_ps_siv", -- [VKD3DSIH_DCL_INPUT_SGV ] = "dcl_input_sgv", -- [VKD3DSIH_DCL_INPUT_SIV ] = "dcl_input_siv", -- [VKD3DSIH_DCL_INTERFACE ] = "dcl_interface", -- [VKD3DSIH_DCL_OUTPUT ] = "dcl_output", -- [VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT ] = "dcl_output_control_point_count", -- [VKD3DSIH_DCL_OUTPUT_SIV ] = "dcl_output_siv", -- [VKD3DSIH_DCL_OUTPUT_TOPOLOGY ] = "dcl_outputtopology", -- [VKD3DSIH_DCL_RESOURCE_RAW ] = "dcl_resource_raw", -- [VKD3DSIH_DCL_RESOURCE_STRUCTURED ] = "dcl_resource_structured", -- [VKD3DSIH_DCL_SAMPLER ] = "dcl_sampler", -- [VKD3DSIH_DCL_STREAM ] = "dcl_stream", -- [VKD3DSIH_DCL_TEMPS ] = "dcl_temps", -- [VKD3DSIH_DCL_TESSELLATOR_DOMAIN ] = "dcl_tessellator_domain", -- [VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE] = "dcl_tessellator_output_primitive", -- [VKD3DSIH_DCL_TESSELLATOR_PARTITIONING ] = "dcl_tessellator_partitioning", -- [VKD3DSIH_DCL_TGSM_RAW ] = "dcl_tgsm_raw", -- [VKD3DSIH_DCL_TGSM_STRUCTURED ] = "dcl_tgsm_structured", -- [VKD3DSIH_DCL_THREAD_GROUP ] = "dcl_thread_group", -- [VKD3DSIH_DCL_UAV_RAW ] = "dcl_uav_raw", -- [VKD3DSIH_DCL_UAV_STRUCTURED ] = "dcl_uav_structured", -- [VKD3DSIH_DCL_UAV_TYPED ] = "dcl_uav_typed", -- [VKD3DSIH_DCL_VERTICES_OUT ] = "dcl_maxout", -- [VKD3DSIH_DDIV ] = "ddiv", -- [VKD3DSIH_DEF ] = "def", -- [VKD3DSIH_DEFAULT ] = "default", -- [VKD3DSIH_DEFB ] = "defb", -- [VKD3DSIH_DEFI ] = "defi", -- [VKD3DSIH_DEQO ] = "deq", -- [VKD3DSIH_DFMA ] = "dfma", -- [VKD3DSIH_DGEO ] = "dge", -- [VKD3DSIH_DISCARD ] = "discard", -- [VKD3DSIH_DIV ] = "div", -- [VKD3DSIH_DLT ] = "dlt", -- [VKD3DSIH_DMAX ] = "dmax", -- [VKD3DSIH_DMIN ] = "dmin", -- [VKD3DSIH_DMOV ] = "dmov", -- [VKD3DSIH_DMOVC ] = "dmovc", -- [VKD3DSIH_DMUL ] = "dmul", -- [VKD3DSIH_DNE ] = "dne", -- [VKD3DSIH_DP2 ] = "dp2", -- [VKD3DSIH_DP2ADD ] = "dp2add", -- [VKD3DSIH_DP3 ] = "dp3", -- [VKD3DSIH_DP4 ] = "dp4", -- [VKD3DSIH_DRCP ] = "drcp", -- [VKD3DSIH_DST ] = "dst", -- [VKD3DSIH_DSX ] = "dsx", -- [VKD3DSIH_DSX_COARSE ] = "deriv_rtx_coarse", -- [VKD3DSIH_DSX_FINE ] = "deriv_rtx_fine", -- [VKD3DSIH_DSY ] = "dsy", -- [VKD3DSIH_DSY_COARSE ] = "deriv_rty_coarse", -- [VKD3DSIH_DSY_FINE ] = "deriv_rty_fine", -- [VKD3DSIH_DTOF ] = "dtof", -- [VKD3DSIH_DTOI ] = "dtoi", -- [VKD3DSIH_DTOU ] = "dtou", -- [VKD3DSIH_ELSE ] = "else", -- [VKD3DSIH_EMIT ] = "emit", -- [VKD3DSIH_EMIT_STREAM ] = "emit_stream", -- [VKD3DSIH_ENDIF ] = "endif", -- [VKD3DSIH_ENDLOOP ] = "endloop", -- [VKD3DSIH_ENDREP ] = "endrep", -- [VKD3DSIH_ENDSWITCH ] = "endswitch", -- [VKD3DSIH_EQO ] = "eq", -- [VKD3DSIH_EQU ] = "eq_unord", -- [VKD3DSIH_EVAL_CENTROID ] = "eval_centroid", -- [VKD3DSIH_EVAL_SAMPLE_INDEX ] = "eval_sample_index", -- [VKD3DSIH_EXP ] = "exp", -- [VKD3DSIH_EXPP ] = "expp", -- [VKD3DSIH_F16TOF32 ] = "f16tof32", -- [VKD3DSIH_F32TOF16 ] = "f32tof16", -- [VKD3DSIH_FCALL ] = "fcall", -- [VKD3DSIH_FIRSTBIT_HI ] = "firstbit_hi", -- [VKD3DSIH_FIRSTBIT_LO ] = "firstbit_lo", -- [VKD3DSIH_FIRSTBIT_SHI ] = "firstbit_shi", -- [VKD3DSIH_FRC ] = "frc", -- [VKD3DSIH_FREM ] = "frem", -- [VKD3DSIH_FTOD ] = "ftod", -- [VKD3DSIH_FTOI ] = "ftoi", -- [VKD3DSIH_FTOU ] = "ftou", -- [VKD3DSIH_GATHER4 ] = "gather4", -- [VKD3DSIH_GATHER4_C ] = "gather4_c", -- [VKD3DSIH_GATHER4_C_S ] = "gather4_c_s", -- [VKD3DSIH_GATHER4_PO ] = "gather4_po", -- [VKD3DSIH_GATHER4_PO_C ] = "gather4_po_c", -- [VKD3DSIH_GATHER4_PO_C_S ] = "gather4_po_c_s", -- [VKD3DSIH_GATHER4_PO_S ] = "gather4_po_s", -- [VKD3DSIH_GATHER4_S ] = "gather4_s", -- [VKD3DSIH_GEO ] = "ge", -- [VKD3DSIH_GEU ] = "ge_unord", -- [VKD3DSIH_HCOS ] = "hcos", -- [VKD3DSIH_HS_CONTROL_POINT_PHASE ] = "hs_control_point_phase", -- [VKD3DSIH_HS_DECLS ] = "hs_decls", -- [VKD3DSIH_HS_FORK_PHASE ] = "hs_fork_phase", -- [VKD3DSIH_HS_JOIN_PHASE ] = "hs_join_phase", -- [VKD3DSIH_HSIN ] = "hsin", -- [VKD3DSIH_HTAN ] = "htan", -- [VKD3DSIH_IADD ] = "iadd", -- [VKD3DSIH_IBFE ] = "ibfe", -- [VKD3DSIH_IDIV ] = "idiv", -- [VKD3DSIH_IEQ ] = "ieq", -- [VKD3DSIH_IF ] = "if", -- [VKD3DSIH_IFC ] = "if", -- [VKD3DSIH_IGE ] = "ige", -- [VKD3DSIH_ILT ] = "ilt", -- [VKD3DSIH_IMAD ] = "imad", -- [VKD3DSIH_IMAX ] = "imax", -- [VKD3DSIH_IMIN ] = "imin", -- [VKD3DSIH_IMM_ATOMIC_ALLOC ] = "imm_atomic_alloc", -- [VKD3DSIH_IMM_ATOMIC_AND ] = "imm_atomic_and", -- [VKD3DSIH_IMM_ATOMIC_CMP_EXCH ] = "imm_atomic_cmp_exch", -- [VKD3DSIH_IMM_ATOMIC_CONSUME ] = "imm_atomic_consume", -- [VKD3DSIH_IMM_ATOMIC_EXCH ] = "imm_atomic_exch", -- [VKD3DSIH_IMM_ATOMIC_IADD ] = "imm_atomic_iadd", -- [VKD3DSIH_IMM_ATOMIC_IMAX ] = "imm_atomic_imax", -- [VKD3DSIH_IMM_ATOMIC_IMIN ] = "imm_atomic_imin", -- [VKD3DSIH_IMM_ATOMIC_OR ] = "imm_atomic_or", -- [VKD3DSIH_IMM_ATOMIC_UMAX ] = "imm_atomic_umax", -- [VKD3DSIH_IMM_ATOMIC_UMIN ] = "imm_atomic_umin", -- [VKD3DSIH_IMM_ATOMIC_XOR ] = "imm_atomic_xor", -- [VKD3DSIH_IMUL ] = "imul", -- [VKD3DSIH_INE ] = "ine", -- [VKD3DSIH_INEG ] = "ineg", -- [VKD3DSIH_ISFINITE ] = "isfinite", -- [VKD3DSIH_ISHL ] = "ishl", -- [VKD3DSIH_ISHR ] = "ishr", -- [VKD3DSIH_ISINF ] = "isinf", -- [VKD3DSIH_ISNAN ] = "isnan", -- [VKD3DSIH_ITOD ] = "itod", -- [VKD3DSIH_ITOF ] = "itof", -- [VKD3DSIH_ITOI ] = "itoi", -- [VKD3DSIH_LABEL ] = "label", -- [VKD3DSIH_LD ] = "ld", -- [VKD3DSIH_LD2DMS ] = "ld2dms", -- [VKD3DSIH_LD2DMS_S ] = "ld2dms_s", -- [VKD3DSIH_LD_RAW ] = "ld_raw", -- [VKD3DSIH_LD_RAW_S ] = "ld_raw_s", -- [VKD3DSIH_LD_S ] = "ld_s", -- [VKD3DSIH_LD_STRUCTURED ] = "ld_structured", -- [VKD3DSIH_LD_STRUCTURED_S ] = "ld_structured_s", -- [VKD3DSIH_LD_UAV_TYPED ] = "ld_uav_typed", -- [VKD3DSIH_LD_UAV_TYPED_S ] = "ld_uav_typed_s", -- [VKD3DSIH_LIT ] = "lit", -- [VKD3DSIH_LOD ] = "lod", -- [VKD3DSIH_LOG ] = "log", -- [VKD3DSIH_LOGP ] = "logp", -- [VKD3DSIH_LOOP ] = "loop", -- [VKD3DSIH_LRP ] = "lrp", -- [VKD3DSIH_LTO ] = "lt", -- [VKD3DSIH_LTU ] = "lt_unord", -- [VKD3DSIH_M3x2 ] = "m3x2", -- [VKD3DSIH_M3x3 ] = "m3x3", -- [VKD3DSIH_M3x4 ] = "m3x4", -- [VKD3DSIH_M4x3 ] = "m4x3", -- [VKD3DSIH_M4x4 ] = "m4x4", -- [VKD3DSIH_MAD ] = "mad", -- [VKD3DSIH_MAX ] = "max", -- [VKD3DSIH_MIN ] = "min", -- [VKD3DSIH_MOV ] = "mov", -- [VKD3DSIH_MOVA ] = "mova", -- [VKD3DSIH_MOVC ] = "movc", -- [VKD3DSIH_MSAD ] = "msad", -- [VKD3DSIH_MUL ] = "mul", -- [VKD3DSIH_NEO ] = "ne_ord", -- [VKD3DSIH_NEU ] = "ne", -- [VKD3DSIH_NOP ] = "nop", -- [VKD3DSIH_NOT ] = "not", -- [VKD3DSIH_NRM ] = "nrm", -- [VKD3DSIH_OR ] = "or", -- [VKD3DSIH_ORD ] = "ord", -- [VKD3DSIH_PHASE ] = "phase", -- [VKD3DSIH_PHI ] = "phi", -- [VKD3DSIH_POW ] = "pow", -- [VKD3DSIH_QUAD_READ_ACROSS_D ] = "quad_read_across_d", -- [VKD3DSIH_QUAD_READ_ACROSS_X ] = "quad_read_across_x", -- [VKD3DSIH_QUAD_READ_ACROSS_Y ] = "quad_read_across_y", -- [VKD3DSIH_QUAD_READ_LANE_AT ] = "quad_read_lane_at", -- [VKD3DSIH_RCP ] = "rcp", -- [VKD3DSIH_REP ] = "rep", -- [VKD3DSIH_RESINFO ] = "resinfo", -- [VKD3DSIH_RET ] = "ret", -- [VKD3DSIH_RETP ] = "retp", -- [VKD3DSIH_ROUND_NE ] = "round_ne", -- [VKD3DSIH_ROUND_NI ] = "round_ni", -- [VKD3DSIH_ROUND_PI ] = "round_pi", -- [VKD3DSIH_ROUND_Z ] = "round_z", -- [VKD3DSIH_RSQ ] = "rsq", -- [VKD3DSIH_SAMPLE ] = "sample", -- [VKD3DSIH_SAMPLE_B ] = "sample_b", -- [VKD3DSIH_SAMPLE_B_CL_S ] = "sample_b_cl_s", -- [VKD3DSIH_SAMPLE_C ] = "sample_c", -- [VKD3DSIH_SAMPLE_C_CL_S ] = "sample_c_cl_s", -- [VKD3DSIH_SAMPLE_C_LZ ] = "sample_c_lz", -- [VKD3DSIH_SAMPLE_C_LZ_S ] = "sample_c_lz_s", -- [VKD3DSIH_SAMPLE_CL_S ] = "sample_cl_s", -- [VKD3DSIH_SAMPLE_GRAD ] = "sample_d", -- [VKD3DSIH_SAMPLE_GRAD_CL_S ] = "sample_d_cl_s", -- [VKD3DSIH_SAMPLE_INFO ] = "sample_info", -- [VKD3DSIH_SAMPLE_LOD ] = "sample_l", -- [VKD3DSIH_SAMPLE_LOD_S ] = "sample_l_s", -- [VKD3DSIH_SAMPLE_POS ] = "sample_pos", -- [VKD3DSIH_SETP ] = "setp", -- [VKD3DSIH_SGE ] = "sge", -- [VKD3DSIH_SGN ] = "sgn", -- [VKD3DSIH_SINCOS ] = "sincos", -- [VKD3DSIH_SLT ] = "slt", -- [VKD3DSIH_SQRT ] = "sqrt", -- [VKD3DSIH_STORE_RAW ] = "store_raw", -- [VKD3DSIH_STORE_STRUCTURED ] = "store_structured", -- [VKD3DSIH_STORE_UAV_TYPED ] = "store_uav_typed", -- [VKD3DSIH_SUB ] = "sub", -- [VKD3DSIH_SWAPC ] = "swapc", -- [VKD3DSIH_SWITCH ] = "switch", -- [VKD3DSIH_SWITCH_MONOLITHIC ] = "switch", -- [VKD3DSIH_SYNC ] = "sync", -- [VKD3DSIH_TAN ] = "tan", -- [VKD3DSIH_TEX ] = "texld", -- [VKD3DSIH_TEXBEM ] = "texbem", -- [VKD3DSIH_TEXBEML ] = "texbeml", -- [VKD3DSIH_TEXCOORD ] = "texcrd", -- [VKD3DSIH_TEXDEPTH ] = "texdepth", -- [VKD3DSIH_TEXDP3 ] = "texdp3", -- [VKD3DSIH_TEXDP3TEX ] = "texdp3tex", -- [VKD3DSIH_TEXKILL ] = "texkill", -- [VKD3DSIH_TEXLDD ] = "texldd", -- [VKD3DSIH_TEXLDL ] = "texldl", -- [VKD3DSIH_TEXM3x2DEPTH ] = "texm3x2depth", -- [VKD3DSIH_TEXM3x2PAD ] = "texm3x2pad", -- [VKD3DSIH_TEXM3x2TEX ] = "texm3x2tex", -- [VKD3DSIH_TEXM3x3 ] = "texm3x3", -- [VKD3DSIH_TEXM3x3DIFF ] = "texm3x3diff", -- [VKD3DSIH_TEXM3x3PAD ] = "texm3x3pad", -- [VKD3DSIH_TEXM3x3SPEC ] = "texm3x3spec", -- [VKD3DSIH_TEXM3x3TEX ] = "texm3x3tex", -- [VKD3DSIH_TEXM3x3VSPEC ] = "texm3x3vspec", -- [VKD3DSIH_TEXREG2AR ] = "texreg2ar", -- [VKD3DSIH_TEXREG2GB ] = "texreg2gb", -- [VKD3DSIH_TEXREG2RGB ] = "texreg2rgb", -- [VKD3DSIH_UBFE ] = "ubfe", -- [VKD3DSIH_UDIV ] = "udiv", -- [VKD3DSIH_UGE ] = "uge", -- [VKD3DSIH_ULT ] = "ult", -- [VKD3DSIH_UMAX ] = "umax", -- [VKD3DSIH_UMIN ] = "umin", -- [VKD3DSIH_UMUL ] = "umul", -- [VKD3DSIH_UNO ] = "uno", -- [VKD3DSIH_USHR ] = "ushr", -- [VKD3DSIH_UTOD ] = "utod", -- [VKD3DSIH_UTOF ] = "utof", -- [VKD3DSIH_UTOU ] = "utou", -- [VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL ] = "wave_active_all_equal", -- [VKD3DSIH_WAVE_ACTIVE_BALLOT ] = "wave_active_ballot", -- [VKD3DSIH_WAVE_ACTIVE_BIT_AND ] = "wave_active_bit_and", -- [VKD3DSIH_WAVE_ACTIVE_BIT_OR ] = "wave_active_bit_or", -- [VKD3DSIH_WAVE_ACTIVE_BIT_XOR ] = "wave_active_bit_xor", -- [VKD3DSIH_WAVE_ALL_BIT_COUNT ] = "wave_all_bit_count", -- [VKD3DSIH_WAVE_ALL_TRUE ] = "wave_all_true", -- [VKD3DSIH_WAVE_ANY_TRUE ] = "wave_any_true", -- [VKD3DSIH_WAVE_IS_FIRST_LANE ] = "wave_is_first_lane", -- [VKD3DSIH_WAVE_OP_ADD ] = "wave_op_add", -- [VKD3DSIH_WAVE_OP_IMAX ] = "wave_op_imax", -- [VKD3DSIH_WAVE_OP_IMIN ] = "wave_op_imin", -- [VKD3DSIH_WAVE_OP_MAX ] = "wave_op_max", -- [VKD3DSIH_WAVE_OP_MIN ] = "wave_op_min", -- [VKD3DSIH_WAVE_OP_MUL ] = "wave_op_mul", -- [VKD3DSIH_WAVE_OP_UMAX ] = "wave_op_umax", -- [VKD3DSIH_WAVE_OP_UMIN ] = "wave_op_umin", -- [VKD3DSIH_WAVE_PREFIX_BIT_COUNT ] = "wave_prefix_bit_count", -- [VKD3DSIH_WAVE_READ_LANE_AT ] = "wave_read_lane_at", -- [VKD3DSIH_WAVE_READ_LANE_FIRST ] = "wave_read_lane_first", -- [VKD3DSIH_XOR ] = "xor", --}; -- - static const char * const shader_register_names[] = - { - [VKD3DSPR_ADDR ] = "a", -@@ -1705,7 +1378,7 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile - shader_dump_sync_flags(compiler, ins->flags); - break; - -- case VKD3DSIH_TEX: -+ case VKD3DSIH_TEXLD: - if (vkd3d_shader_ver_ge(&compiler->shader_version, 2, 0)) - { - if (ins->flags & VKD3DSI_TEXLD_PROJECT) -@@ -1747,7 +1420,7 @@ static void shader_dump_register_space(struct vkd3d_d3d_asm_compiler *compiler, - static void shader_print_opcode(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_shader_opcode opcode) - { - vkd3d_string_buffer_printf(&compiler->buffer, "%s%s%s", compiler->colours.opcode, -- shader_opcode_names[opcode], compiler->colours.reset); -+ vsir_opcode_get_name(opcode, ""), compiler->colours.reset); - } - - static void shader_dump_icb(struct vkd3d_d3d_asm_compiler *compiler, -@@ -1865,6 +1538,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, - case VKD3DSIH_DCL_INPUT_PS_SGV: - case VKD3DSIH_DCL_INPUT_SGV: - case VKD3DSIH_DCL_INPUT_SIV: -+ case VKD3DSIH_DCL_OUTPUT_SGV: - case VKD3DSIH_DCL_OUTPUT_SIV: - shader_print_dst_param(compiler, " ", &ins->declaration.register_semantic.reg, true, ""); - shader_print_input_sysval_semantic(compiler, ", ", ins->declaration.register_semantic.sysval_semantic, ""); -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 57d874efe37..c8291afcf6e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -382,11 +382,11 @@ static const struct vkd3d_sm1_opcode_info ps_opcode_table[] = - {VKD3D_SM1_OP_LABEL, 0, 1, VKD3DSIH_LABEL, {2, 1}}, - /* Texture */ - {VKD3D_SM1_OP_TEXCOORD, 1, 0, VKD3DSIH_TEXCOORD, {0, 0}, {1, 3}}, -- {VKD3D_SM1_OP_TEXCOORD, 1, 1, VKD3DSIH_TEXCOORD, {1, 4}, {1, 4}}, -+ {VKD3D_SM1_OP_TEXCOORD, 1, 1, VKD3DSIH_TEXCRD, {1, 4}, {1, 4}}, - {VKD3D_SM1_OP_TEXKILL, 1, 0, VKD3DSIH_TEXKILL, {1, 0}}, - {VKD3D_SM1_OP_TEX, 1, 0, VKD3DSIH_TEX, {0, 0}, {1, 3}}, -- {VKD3D_SM1_OP_TEX, 1, 1, VKD3DSIH_TEX, {1, 4}, {1, 4}}, -- {VKD3D_SM1_OP_TEX, 1, 2, VKD3DSIH_TEX, {2, 0}}, -+ {VKD3D_SM1_OP_TEX, 1, 1, VKD3DSIH_TEXLD, {1, 4}, {1, 4}}, -+ {VKD3D_SM1_OP_TEX, 1, 2, VKD3DSIH_TEXLD, {2, 0}}, - {VKD3D_SM1_OP_TEXBEM, 1, 1, VKD3DSIH_TEXBEM, {0, 0}, {1, 3}}, - {VKD3D_SM1_OP_TEXBEML, 1, 1, VKD3DSIH_TEXBEML, {1, 0}, {1, 3}}, - {VKD3D_SM1_OP_TEXREG2AR, 1, 1, VKD3DSIH_TEXREG2AR, {1, 0}, {1, 3}}, -@@ -1681,7 +1681,8 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir_ - if (!(info = shader_sm1_get_opcode_info_from_vsir(d3dbc, ins->opcode))) - { - vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, -- "Opcode %#x not supported for shader profile.", ins->opcode); -+ "Instruction \"%s\" (%#x) is not supported for the current target.", -+ vsir_opcode_get_name(ins->opcode, ""), ins->opcode); - d3dbc->failed = true; - return NULL; - } -@@ -1689,16 +1690,16 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir_ - if (ins->dst_count != info->dst_count) - { - vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, -- "Invalid destination count %u for vsir instruction %#x (expected %u).", -- ins->dst_count, ins->opcode, info->dst_count); -+ "Invalid destination parameter count %u for instruction \"%s\" (%#x); expected %u.", -+ ins->dst_count, vsir_opcode_get_name(ins->opcode, ""), ins->opcode, info->dst_count); - d3dbc->failed = true; - return NULL; - } - if (ins->src_count != info->src_count) - { - vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, -- "Invalid source count %u for vsir instruction %#x (expected %u).", -- ins->src_count, ins->opcode, info->src_count); -+ "Invalid source parameter count %u for instruction \"%s\" (%#x); expected %u.", -+ ins->src_count, vsir_opcode_get_name(ins->opcode, ""), ins->opcode, info->src_count); - d3dbc->failed = true; - return NULL; - } -@@ -2014,7 +2015,7 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str - case VKD3DSIH_MUL: - case VKD3DSIH_SINCOS: - case VKD3DSIH_SLT: -- case VKD3DSIH_TEX: -+ case VKD3DSIH_TEXLD: - case VKD3DSIH_TEXLDD: - d3dbc_write_instruction(d3dbc, ins); - break; -@@ -2029,8 +2030,8 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str - { - vkd3d_shader_error(d3dbc->message_context, &ins->location, - VKD3D_SHADER_ERROR_D3DBC_INVALID_WRITEMASK, -- "writemask %#x for vsir instruction with opcode %#x is not single component.", -- writemask, ins->opcode); -+ "Writemask %#x for instruction \"%s\" (%#x) is not single component.", -+ writemask, vsir_opcode_get_name(ins->opcode, ""), ins->opcode); - d3dbc->failed = true; - } - d3dbc_write_instruction(d3dbc, ins); -@@ -2038,7 +2039,8 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str - - default: - vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, -- "vsir instruction with opcode %#x.", ins->opcode); -+ "Internal compiler error: Unhandled instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(ins->opcode, ""), ins->opcode); - d3dbc->failed = true; - break; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c -index 9e3a57132a1..45a45c3ad4a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c -@@ -388,7 +388,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s - { - WARN("Invalid data size %#zx.\n", section->data.size); - vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_SIGNATURE, -- "Section size %zu is smaller than the minimum signature header size.\n", section->data.size); -+ "Section size %zu is smaller than the minimum signature header size.", section->data.size); - return VKD3D_ERROR_INVALID_ARGUMENT; - } - -@@ -402,7 +402,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s - { - WARN("Invalid header size %#x.\n", header_size); - vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_SIGNATURE, -- "Signature header size %#x is invalid.\n", header_size); -+ "Signature header size %#x is invalid.", header_size); - return VKD3D_ERROR_INVALID_ARGUMENT; - } - skip_dword_unknown(&ptr, i - 2); -@@ -438,7 +438,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s - || !(e[i].semantic_name = vkd3d_strdup(name))) - { - vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_STRING_REFERENCE, -- "Element %u has invalid semantic name reference %#zx (data size %#zx).\n", -+ "Element %u has invalid semantic name reference %#zx (data size %#zx).", - i, name_offset, section->data.size); - fail = true; - } -@@ -447,7 +447,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s - if ((e[i].component_type = read_u32(&ptr)) > VKD3D_SHADER_COMPONENT_FLOAT) - { - vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_COMPONENT_TYPE, -- "Element %u has invalid component type %#x.\n", i, e[i].component_type); -+ "Element %u has invalid component type %#x.", i, e[i].component_type); - fail = true; - } - e[i].register_index = read_u32(&ptr); -@@ -531,7 +531,7 @@ static int shdr_parse_features(const struct vkd3d_shader_dxbc_section_desc *sect - { - WARN("Invalid data size %#zx.\n", section->data.size); - vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE, -- "SFI0 section size %zu is too small to contain flags.\n", section->data.size); -+ "SFI0 section size %zu is too small to contain flags.", section->data.size); - return VKD3D_ERROR_INVALID_ARGUMENT; - } - flags = read_u64(&ptr); -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index ca79939a39b..53578ce7141 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -644,17 +644,23 @@ struct sm6_type - enum sm6_value_type - { - VALUE_TYPE_FUNCTION, -- VALUE_TYPE_REG, - VALUE_TYPE_DATA, - VALUE_TYPE_HANDLE, - VALUE_TYPE_SSA, - VALUE_TYPE_ICB, - VALUE_TYPE_IDXTEMP, - VALUE_TYPE_GROUPSHAREDMEM, -+ VALUE_TYPE_CONSTANT, - VALUE_TYPE_UNDEFINED, - VALUE_TYPE_INVALID, - }; - -+struct sm6_index -+{ -+ const struct sm6_value *index; -+ bool is_in_bounds; -+}; -+ - struct sm6_function_data - { - const char *name; -@@ -678,16 +684,24 @@ struct sm6_icb_data - { - unsigned int data_id; - unsigned int id; -+ struct sm6_index index; - }; - - struct sm6_idxtemp_data - { - unsigned int id; -+ struct sm6_index index; - }; - - struct sm6_groupsharedmem_data - { - unsigned int id; -+ struct sm6_index index; -+}; -+ -+struct sm6_constant_data -+{ -+ union vsir_immediate_constant immconst; - }; - - struct sm6_value -@@ -696,6 +710,7 @@ struct sm6_value - enum sm6_value_type value_type; - unsigned int structure_stride; - bool is_back_ref; -+ bool non_uniform; - union - { - struct sm6_function_data function; -@@ -705,8 +720,8 @@ struct sm6_value - struct sm6_icb_data icb; - struct sm6_idxtemp_data idxtemp; - struct sm6_groupsharedmem_data groupsharedmem; -+ struct sm6_constant_data constant; - } u; -- struct vkd3d_shader_register reg; - }; - - struct dxil_record -@@ -731,7 +746,7 @@ struct incoming_value - - struct sm6_phi - { -- struct vkd3d_shader_register reg; -+ struct sm6_value value; - struct incoming_value *incoming; - size_t incoming_capacity; - size_t incoming_count; -@@ -2010,11 +2025,6 @@ static inline bool sm6_type_is_handle(const struct sm6_type *type) - return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.Handle"); - } - --static inline const struct sm6_type *sm6_type_get_element_type(const struct sm6_type *type) --{ -- return (type->class == TYPE_CLASS_ARRAY || type->class == TYPE_CLASS_VECTOR) ? type->u.array.elem_type : type; --} -- - static const struct sm6_type *sm6_type_get_pointer_to_type(const struct sm6_type *type, - enum bitcode_address_space addr_space, struct sm6_parser *sm6) - { -@@ -2214,35 +2224,6 @@ static const char *sm6_parser_get_global_symbol_name(const struct sm6_parser *sm - return NULL; - } - --static unsigned int register_get_uint_value(const struct vkd3d_shader_register *reg) --{ -- if (!register_is_constant(reg) || (!data_type_is_integer(reg->data_type) && !data_type_is_bool(reg->data_type))) -- return UINT_MAX; -- -- if (reg->dimension == VSIR_DIMENSION_VEC4) -- WARN("Returning vec4.x.\n"); -- -- if (reg->type == VKD3DSPR_IMMCONST64) -- { -- if (reg->u.immconst_u64[0] > UINT_MAX) -- FIXME("Truncating 64-bit value.\n"); -- return reg->u.immconst_u64[0]; -- } -- -- return reg->u.immconst_u32[0]; --} -- --static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *reg) --{ -- if (!register_is_constant(reg) || !data_type_is_integer(reg->data_type)) -- return UINT64_MAX; -- -- if (reg->dimension == VSIR_DIMENSION_VEC4) -- WARN("Returning vec4.x.\n"); -- -- 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) - { - return value->value_type == VALUE_TYPE_FUNCTION; -@@ -2264,11 +2245,11 @@ static inline bool sm6_value_is_register(const struct sm6_value *value) - { - switch (value->value_type) - { -- case VALUE_TYPE_REG: - case VALUE_TYPE_SSA: - case VALUE_TYPE_ICB: - case VALUE_TYPE_IDXTEMP: - case VALUE_TYPE_GROUPSHAREDMEM: -+ case VALUE_TYPE_CONSTANT: - case VALUE_TYPE_UNDEFINED: - case VALUE_TYPE_INVALID: - return true; -@@ -2285,18 +2266,31 @@ static bool sm6_value_is_handle(const struct sm6_value *value) - - static inline bool sm6_value_is_constant(const struct sm6_value *value) - { -- return sm6_value_is_register(value) && register_is_constant(&value->reg); -+ return value->value_type == VALUE_TYPE_CONSTANT; - } - - static bool sm6_value_is_constant_zero(const struct sm6_value *value) - { -- /* Constant vectors do not occur. */ -- return sm6_value_is_register(value) && register_is_scalar_constant_zero(&value->reg); -+ if (value->value_type != VALUE_TYPE_CONSTANT || value->type->class != TYPE_CLASS_INTEGER) -+ return false; -+ -+ if (value->type->u.width == 64) -+ return value->u.constant.immconst.immconst_u64[0] == 0; -+ else -+ return value->u.constant.immconst.immconst_u32[0] == 0; - } - - static inline bool sm6_value_is_undef(const struct sm6_value *value) - { -- return sm6_value_is_register(value) && value->reg.type == VKD3DSPR_UNDEF; -+ switch (value->value_type) -+ { -+ case VALUE_TYPE_UNDEFINED: -+ case VALUE_TYPE_INVALID: -+ return true; -+ -+ default: -+ return false; -+ } - } - - static bool sm6_value_vector_is_constant_or_undef(const struct sm6_value **values, unsigned int count) -@@ -2315,26 +2309,98 @@ static bool sm6_value_is_data(const struct sm6_value *value) - - static bool sm6_value_is_ssa(const struct sm6_value *value) - { -- return sm6_value_is_register(value) && register_is_ssa(&value->reg); -+ return value->value_type == VALUE_TYPE_SSA; - } - - static bool sm6_value_is_numeric_array(const struct sm6_value *value) - { -- return sm6_value_is_register(value) && register_is_numeric_array(&value->reg); -+ switch (value->value_type) -+ { -+ case VALUE_TYPE_ICB: -+ case VALUE_TYPE_IDXTEMP: -+ case VALUE_TYPE_GROUPSHAREDMEM: -+ return true; -+ -+ default: -+ return false; -+ } - } - --static inline unsigned int sm6_value_get_constant_uint(const struct sm6_value *value) -+static unsigned int sm6_value_get_constant_uint(const struct sm6_value *value, struct sm6_parser *sm6) - { - if (!sm6_value_is_constant(value)) -+ { -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, -+ "Invalid non-constant value."); - return UINT_MAX; -- return register_get_uint_value(&value->reg); -+ } -+ -+ if (value->type->class != TYPE_CLASS_INTEGER) -+ { -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, -+ "Invalid non-integer constant value."); -+ return UINT_MAX; -+ } -+ -+ if (value->type->u.width == 64) -+ { -+ uint64_t val = value->u.constant.immconst.immconst_u64[0]; -+ if (val > UINT_MAX) -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, -+ "Invalid 64-bit constant %"PRIu64" will be truncated do %u.", val, (unsigned int)val); -+ return val; -+ } -+ -+ return value->u.constant.immconst.immconst_u32[0]; - } - --static uint64_t sm6_value_get_constant_uint64(const struct sm6_value *value) -+static uint64_t sm6_value_get_constant_uint64(const struct sm6_value *value, struct sm6_parser *sm6) - { - if (!sm6_value_is_constant(value)) -+ { -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, -+ "Invalid non-constant value."); - return UINT64_MAX; -- return register_get_uint64_value(&value->reg); -+ } -+ -+ if (value->type->class != TYPE_CLASS_INTEGER) -+ { -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, -+ "Invalid non-integer constant value."); -+ return UINT64_MAX; -+ } -+ -+ if (value->type->u.width == 64) -+ return value->u.constant.immconst.immconst_u64[0]; -+ else -+ return value->u.constant.immconst.immconst_u32[0]; -+} -+ -+static float sm6_value_get_constant_float(const struct sm6_value *value, struct sm6_parser *sm6) -+{ -+ if (!sm6_value_is_constant(value)) -+ { -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, -+ "Invalid non-constant value."); -+ return 0.0f; -+ } -+ -+ if (value->type->class != TYPE_CLASS_FLOAT) -+ { -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, -+ "Invalid non-floating-point constant value."); -+ return 0.0f; -+ } -+ -+ if (value->type->u.width == 64) -+ { -+ double val = value->u.constant.immconst.immconst_f64[0]; -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, -+ "Invalid double constant %lf will be truncated do float %f.", val, (float)val); -+ return val; -+ } -+ -+ return value->u.constant.immconst.immconst_f32[0]; - } - - static unsigned int sm6_parser_alloc_ssa_id(struct sm6_parser *sm6) -@@ -2433,33 +2499,127 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type - return VKD3D_DATA_UINT; - } - --static void sm6_register_from_value(struct vkd3d_shader_register *reg, const struct sm6_value *value) -+/* Based on the implementation in the OpenGL Mathematics library. */ -+static uint32_t half_to_float(uint16_t value) - { -- enum vkd3d_data_type data_type; -+ uint32_t s = (value & 0x8000u) << 16; -+ uint32_t e = (value >> 10) & 0x1fu; -+ uint32_t m = value & 0x3ffu; - -- data_type = vkd3d_data_type_from_sm6_type(sm6_type_get_scalar_type(value->type, 0)); -+ if (!e) -+ { -+ if (!m) -+ { -+ /* Plus or minus zero */ -+ return s; -+ } -+ else -+ { -+ /* Denormalized number -- renormalize it */ -+ while (!(m & 0x400u)) -+ { -+ m <<= 1; -+ --e; -+ } - -- switch (value->value_type) -+ ++e; -+ m &= ~0x400u; -+ } -+ } -+ else if (e == 31u) -+ { -+ /* Positive or negative infinity for zero 'm'. -+ * Nan for non-zero 'm' -- preserve sign and significand bits */ -+ return s | 0x7f800000u | (m << 13); -+ } -+ -+ /* Normalized number */ -+ e += 127u - 15u; -+ m <<= 13; -+ -+ /* Assemble s, e and m. */ -+ return s | (e << 23) | m; -+} -+ -+static void register_convert_to_minimum_precision(struct vkd3d_shader_register *reg) -+{ -+ unsigned int i; -+ -+ switch (reg->data_type) - { -- case VALUE_TYPE_REG: -- *reg = value->reg; -+ case VKD3D_DATA_HALF: -+ reg->data_type = VKD3D_DATA_FLOAT; -+ reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_FLOAT_16; -+ if (reg->type == VKD3DSPR_IMMCONST) -+ { -+ for (i = 0; i < VSIR_DIMENSION_VEC4; ++i) -+ reg->u.immconst_u32[i] = half_to_float(reg->u.immconst_u32[i]); -+ } - break; - -+ case VKD3D_DATA_UINT16: -+ reg->data_type = VKD3D_DATA_UINT; -+ reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_UINT_16; -+ if (reg->type == VKD3DSPR_IMMCONST) -+ { -+ for (i = 0; i < VSIR_DIMENSION_VEC4; ++i) -+ reg->u.immconst_u32[i] = (int16_t)reg->u.immconst_u32[i]; -+ } -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+static void register_index_address_init(struct vkd3d_shader_register_index *idx, const struct sm6_value *address, -+ struct sm6_parser *sm6); -+ -+static void sm6_register_from_value(struct vkd3d_shader_register *reg, const struct sm6_value *value, -+ struct sm6_parser *sm6) -+{ -+ const struct sm6_type *scalar_type; -+ enum vkd3d_data_type data_type; -+ -+ scalar_type = sm6_type_get_scalar_type(value->type, 0); -+ data_type = vkd3d_data_type_from_sm6_type(scalar_type); -+ -+ switch (value->value_type) -+ { - case VALUE_TYPE_SSA: - register_init_with_id(reg, VKD3DSPR_SSA, data_type, value->u.ssa.id); - reg->dimension = sm6_type_is_scalar(value->type) ? VSIR_DIMENSION_SCALAR : VSIR_DIMENSION_VEC4; -+ register_convert_to_minimum_precision(reg); - break; - - case VALUE_TYPE_ICB: -- register_init_with_id(reg, VKD3DSPR_IMMCONSTBUFFER, data_type, value->u.icb.id); -+ vsir_register_init(reg, VKD3DSPR_IMMCONSTBUFFER, data_type, 2); -+ reg->idx[0].offset = value->u.icb.id; -+ register_index_address_init(®->idx[1], value->u.icb.index.index, sm6); -+ reg->idx[1].is_in_bounds = value->u.icb.index.is_in_bounds; -+ register_convert_to_minimum_precision(reg); - break; - - case VALUE_TYPE_IDXTEMP: -- register_init_with_id(reg, VKD3DSPR_IDXTEMP, data_type, value->u.idxtemp.id); -+ vsir_register_init(reg, VKD3DSPR_IDXTEMP, data_type, 2); -+ reg->idx[0].offset = value->u.idxtemp.id; -+ register_index_address_init(®->idx[1], value->u.idxtemp.index.index, sm6); -+ reg->idx[1].is_in_bounds = value->u.idxtemp.index.is_in_bounds; -+ register_convert_to_minimum_precision(reg); - break; - - case VALUE_TYPE_GROUPSHAREDMEM: -- register_init_with_id(reg, VKD3DSPR_GROUPSHAREDMEM, data_type, value->u.groupsharedmem.id); -+ vsir_register_init(reg, VKD3DSPR_GROUPSHAREDMEM, data_type, 2); -+ reg->idx[0].offset = value->u.groupsharedmem.id; -+ register_index_address_init(®->idx[1], value->u.groupsharedmem.index.index, sm6); -+ reg->idx[1].is_in_bounds = value->u.groupsharedmem.index.is_in_bounds; -+ break; -+ -+ case VALUE_TYPE_CONSTANT: -+ vsir_register_init(reg, scalar_type->u.width == 64 ? VKD3DSPR_IMMCONST64 : VKD3DSPR_IMMCONST, -+ data_type, 0); -+ reg->u = value->u.constant.immconst; -+ register_convert_to_minimum_precision(reg); - break; - - case VALUE_TYPE_UNDEFINED: -@@ -2472,15 +2632,17 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str - case VALUE_TYPE_DATA: - vkd3d_unreachable(); - } -+ -+ reg->non_uniform = value->non_uniform; - } - - static void sm6_parser_init_ssa_value(struct sm6_parser *sm6, struct sm6_value *value) - { - unsigned int id; - -- if (register_is_ssa(&value->reg) && value->reg.idx[0].offset) -+ if (value->value_type == VALUE_TYPE_SSA && value->u.ssa.id) - { -- id = value->reg.idx[0].offset; -+ id = value->u.ssa.id; - TRACE("Using forward-allocated id %u.\n", id); - } - else -@@ -2490,7 +2652,6 @@ static void sm6_parser_init_ssa_value(struct sm6_parser *sm6, struct sm6_value * - - value->value_type = VALUE_TYPE_SSA; - value->u.ssa.id = id; -- sm6_register_from_value(&value->reg, value); - } - - static void register_make_constant_uint(struct vkd3d_shader_register *reg, unsigned int value) -@@ -2547,10 +2708,11 @@ static void src_param_init_vector(struct vkd3d_shader_src_param *param, unsigned - param->modifiers = VKD3DSPSM_NONE; - } - --static void src_param_init_from_value(struct vkd3d_shader_src_param *param, const struct sm6_value *src) -+static void src_param_init_from_value(struct vkd3d_shader_src_param *param, const struct sm6_value *src, -+ struct sm6_parser *sm6) - { - src_param_init(param); -- sm6_register_from_value(¶m->reg, src); -+ sm6_register_from_value(¶m->reg, src, sm6); - } - - static void src_param_init_vector_from_reg(struct vkd3d_shader_src_param *param, -@@ -2570,12 +2732,12 @@ static void src_param_make_constant_uint(struct vkd3d_shader_src_param *param, u - static void register_index_address_init(struct vkd3d_shader_register_index *idx, const struct sm6_value *address, - struct sm6_parser *sm6) - { -- if (sm6_value_is_constant(address)) -+ if (address && sm6_value_is_constant(address)) - { -- idx->offset = sm6_value_get_constant_uint(address); -+ idx->offset = sm6_value_get_constant_uint(address, sm6); - idx->rel_addr = NULL; - } -- else if (sm6_value_is_undef(address)) -+ else if (!address || sm6_value_is_undef(address)) - { - idx->offset = 0; - idx->rel_addr = NULL; -@@ -2584,7 +2746,7 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, - { - struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(sm6->p.program, 1); - if (rel_addr) -- src_param_init_from_value(rel_addr, address); -+ src_param_init_from_value(rel_addr, address, sm6); - idx->offset = 0; - idx->rel_addr = rel_addr; - } -@@ -2619,7 +2781,7 @@ static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instructio - - dst_param_init(param); - sm6_parser_init_ssa_value(sm6, dst); -- sm6_register_from_value(¶m->reg, dst); -+ sm6_register_from_value(¶m->reg, dst, sm6); - return true; - } - -@@ -2631,22 +2793,20 @@ static void instruction_dst_param_init_ssa_vector(struct vkd3d_shader_instructio - - dst_param_init_vector(param, component_count); - sm6_parser_init_ssa_value(sm6, dst); -- sm6_register_from_value(¶m->reg, dst); -+ sm6_register_from_value(¶m->reg, dst, sm6); - } - --static bool instruction_dst_param_init_temp_vector(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) -+static bool instruction_dst_param_init_uint_temp_vector(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) - { -- struct sm6_value *dst = sm6_parser_get_current_value(sm6); - struct vkd3d_shader_dst_param *param; - - if (!(param = instruction_dst_params_alloc(ins, 1, sm6))) - return false; - -- vsir_dst_param_init(param, VKD3DSPR_TEMP, vkd3d_data_type_from_sm6_type(sm6_type_get_scalar_type(dst->type, 0)), 1); -+ vsir_dst_param_init(param, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); - param->write_mask = VKD3DSP_WRITEMASK_ALL; - param->reg.idx[0].offset = 0; - param->reg.dimension = VSIR_DIMENSION_VEC4; -- dst->reg = param->reg; - - return true; - } -@@ -2928,7 +3088,6 @@ static size_t sm6_parser_get_value_idx_by_ref(struct sm6_parser *sm6, const stru - value->type = fwd_type; - value->value_type = VALUE_TYPE_SSA; - value->u.ssa.id = sm6_parser_alloc_ssa_id(sm6); -- sm6_register_from_value(&value->reg, value); - } - } - -@@ -3017,53 +3176,13 @@ static inline uint64_t decode_rotated_signed_value(uint64_t value) - return value << 63; - } - --static float bitcast_uint_to_float(unsigned int value) --{ -- union -- { -- uint32_t uint32_value; -- float float_value; -- } u; -- -- u.uint32_value = value; -- return u.float_value; --} -- --static inline double bitcast_uint64_to_double(uint64_t value) --{ -- union -- { -- uint64_t uint64_value; -- double double_value; -- } u; -- -- u.uint64_value = value; -- return u.double_value; --} -- --static float register_get_float_value(const struct vkd3d_shader_register *reg) --{ -- if (!register_is_constant(reg) || !data_type_is_floating_point(reg->data_type)) -- return 0.0; -- -- if (reg->dimension == VSIR_DIMENSION_VEC4) -- WARN("Returning vec4.x.\n"); -- -- if (reg->type == VKD3DSPR_IMMCONST64) -- { -- WARN("Truncating double to float.\n"); -- return bitcast_uint64_to_double(reg->u.immconst_u64[0]); -- } -- -- return bitcast_uint_to_float(reg->u.immconst_u32[0]); --} -- - static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, const struct sm6_type *type, - const uint64_t *operands, struct sm6_parser *sm6) - { - struct vkd3d_shader_immediate_constant_buffer *icb; - const struct sm6_type *elem_type; - unsigned int i, size, count; -+ uint64_t *data64; - - elem_type = type->u.array.elem_type; - /* Multidimensional arrays are emitted in flattened form. */ -@@ -3115,28 +3234,70 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - return VKD3D_OK; - - count = type->u.array.count; -- if (size > sizeof(icb->data[0])) -- { -- uint64_t *data = (uint64_t *)icb->data; -- for (i = 0; i < count; ++i) -- data[i] = operands[i]; -- } -- else -+ switch (icb->data_type) - { -- for (i = 0; i < count; ++i) -- icb->data[i] = operands[i]; -+ case VKD3D_DATA_HALF: -+ for (i = 0; i < count; ++i) -+ icb->data[i] = half_to_float(operands[i]); -+ icb->data_type = VKD3D_DATA_FLOAT; -+ break; -+ -+ case VKD3D_DATA_UINT16: -+ for (i = 0; i < count; ++i) -+ icb->data[i] = (int16_t)operands[i]; -+ icb->data_type = VKD3D_DATA_UINT; -+ break; -+ -+ case VKD3D_DATA_FLOAT: -+ case VKD3D_DATA_UINT: -+ for (i = 0; i < count; ++i) -+ icb->data[i] = operands[i]; -+ break; -+ -+ case VKD3D_DATA_DOUBLE: -+ case VKD3D_DATA_UINT64: -+ data64 = (uint64_t *)icb->data; -+ for (i = 0; i < count; ++i) -+ data64[i] = operands[i]; -+ break; -+ -+ default: -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Invalid array of type %u.", icb->data_type); -+ return VKD3D_ERROR_INVALID_SHADER; - } - - return VKD3D_OK; - } - -+static struct sm6_index *sm6_get_value_index(struct sm6_parser *sm6, struct sm6_value *value) -+{ -+ switch (value->value_type) -+ { -+ case VALUE_TYPE_ICB: -+ return &value->u.icb.index; -+ -+ case VALUE_TYPE_IDXTEMP: -+ return &value->u.idxtemp.index; -+ -+ case VALUE_TYPE_GROUPSHAREDMEM: -+ return &value->u.groupsharedmem.index; -+ -+ default: -+ WARN("Cannot index into value of type %#x.\n", value->value_type); -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Cannot index into value of type %#x.", value->value_type); -+ return NULL; -+ } -+} -+ - static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, const struct dxil_record *record, - struct sm6_value *dst) - { - const struct sm6_type *elem_type, *pointee_type, *gep_type, *ptr_type; -- struct vkd3d_shader_register reg; - struct sm6_value *operands[3]; - unsigned int i, j, offset; -+ struct sm6_index *index; - uint64_t value; - - i = 0; -@@ -3178,9 +3339,13 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c - } - } - -- sm6_register_from_value(®, operands[0]); -+ *dst = *operands[0]; -+ index = sm6_get_value_index(sm6, dst); - -- if (reg.idx_count > 1) -+ if (!index) -+ return VKD3D_ERROR_INVALID_SHADER; -+ -+ if (index->index) - { - WARN("Unsupported stacked GEP.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -@@ -3203,8 +3368,6 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c - return VKD3D_ERROR_INVALID_SHADER; - } - -- dst->structure_stride = operands[0]->structure_stride; -- - ptr_type = operands[0]->type; - if (!sm6_type_is_pointer(ptr_type)) - { -@@ -3225,7 +3388,7 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c - "Explicit pointee type for constexpr GEP does not match the element type."); - } - -- offset = sm6_value_get_constant_uint(operands[2]); -+ offset = sm6_value_get_constant_uint(operands[2], sm6); - if (!(gep_type = sm6_type_get_element_type_at_index(pointee_type, offset))) - { - WARN("Failed to get element type.\n"); -@@ -3241,20 +3404,17 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c - "Module does not define a pointer type for a constexpr GEP result."); - return VKD3D_ERROR_INVALID_SHADER; - } -- dst->reg = reg; -- dst->reg.idx[1].offset = offset; -- dst->reg.idx[1].is_in_bounds = record->code == CST_CODE_CE_INBOUNDS_GEP; -- dst->reg.idx_count = 2; -+ -+ index->index = operands[2]; -+ index->is_in_bounds = record->code == CST_CODE_CE_INBOUNDS_GEP; - - return VKD3D_OK; - } - - static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const struct dxil_block *block) - { -- enum vkd3d_shader_register_type reg_type = VKD3DSPR_INVALID; -- const struct sm6_type *type, *elem_type, *ptr_type; -+ const struct sm6_type *type, *ptr_type; - size_t i, base_value_idx, value_idx; -- enum vkd3d_data_type reg_data_type; - const struct dxil_record *record; - const struct sm6_value *src; - enum vkd3d_result ret; -@@ -3275,18 +3435,6 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) - return VKD3D_ERROR_INVALID_SHADER; - -- elem_type = sm6_type_get_element_type(type); -- if (sm6_type_is_numeric(elem_type)) -- { -- reg_data_type = vkd3d_data_type_from_sm6_type(elem_type); -- reg_type = elem_type->u.width > 32 ? VKD3DSPR_IMMCONST64 : VKD3DSPR_IMMCONST; -- } -- else -- { -- reg_data_type = VKD3D_DATA_UNUSED; -- reg_type = VKD3DSPR_INVALID; -- } -- - if (i == block->record_count - 1) - WARN("Unused SETTYPE record.\n"); - -@@ -3301,19 +3449,21 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - - dst = sm6_parser_get_current_value(sm6); - dst->type = type; -- dst->value_type = VALUE_TYPE_REG; - dst->is_back_ref = true; -- vsir_register_init(&dst->reg, reg_type, reg_data_type, 0); - - switch (record->code) - { - case CST_CODE_NULL: -- if (sm6_type_is_array(type) -- && (ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) -+ if (sm6_type_is_array(type)) - { -- return ret; -+ if ((ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) -+ return ret; -+ } -+ else -+ { -+ dst->value_type = VALUE_TYPE_CONSTANT; -+ memset(&dst->u.constant, 0, sizeof(dst->u.constant)); - } -- /* For non-aggregates, register constant data is already zero-filled. */ - break; - - case CST_CODE_INTEGER: -@@ -3326,11 +3476,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - return VKD3D_ERROR_INVALID_SHADER; - } - -+ dst->value_type = VALUE_TYPE_CONSTANT; -+ - value = decode_rotated_signed_value(record->operands[0]); - if (type->u.width <= 32) -- dst->reg.u.immconst_u32[0] = value & ((1ull << type->u.width) - 1); -+ dst->u.constant.immconst.immconst_u32[0] = value & ((1ull << type->u.width) - 1); - else -- dst->reg.u.immconst_u64[0] = value; -+ dst->u.constant.immconst.immconst_u64[0] = value; - - break; - -@@ -3344,14 +3496,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - return VKD3D_ERROR_INVALID_SHADER; - } - -- if (type->u.width == 16) -- dst->reg.u.immconst_u32[0] = record->operands[0]; -- else if (type->u.width == 32) -- dst->reg.u.immconst_f32[0] = bitcast_uint_to_float(record->operands[0]); -- else if (type->u.width == 64) -- dst->reg.u.immconst_f64[0] = bitcast_uint64_to_double(record->operands[0]); -+ dst->value_type = VALUE_TYPE_CONSTANT; -+ -+ value = record->operands[0]; -+ if (type->u.width <= 32) -+ dst->u.constant.immconst.immconst_u32[0] = value & ((1ull << type->u.width) - 1); - else -- vkd3d_unreachable(); -+ dst->u.constant.immconst.immconst_u64[0] = value; - - break; - -@@ -3377,6 +3528,46 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - return ret; - break; - -+ case CST_CODE_CE_CAST: -+ /* Resolve later in case forward refs exist. */ -+ dst->type = type; -+ dst->value_type = VALUE_TYPE_INVALID; -+ break; -+ -+ case CST_CODE_UNDEF: -+ dxil_record_validate_operand_max_count(record, 0, sm6); -+ dst->value_type = VALUE_TYPE_UNDEFINED; -+ break; -+ -+ default: -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Constant code %u is unhandled.", record->code); -+ dst->value_type = VALUE_TYPE_INVALID; -+ break; -+ } -+ -+ if (record->attachment) -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, -+ "Ignoring a metadata attachment for a constant."); -+ -+ ++sm6->value_count; -+ } -+ -+ value_idx = base_value_idx; -+ -+ for (i = 0; i < block->record_count; ++i) -+ { -+ sm6->p.location.column = i; -+ record = block->records[i]; -+ -+ switch (record->code) -+ { -+ case CST_CODE_SETTYPE: -+ continue; -+ -+ default: -+ break; -+ - case CST_CODE_CE_CAST: - if (!dxil_record_validate_operand_count(record, 3, 3, sm6)) - return VKD3D_ERROR_INVALID_SHADER; -@@ -3413,59 +3604,26 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - return VKD3D_ERROR_INVALID_SHADER; - } - -- /* Resolve later in case forward refs exist. */ -- dst->type = type; -- dst->reg.type = VKD3DSPR_COUNT; -- dst->reg.idx[0].offset = value; -- break; -+ dst = &sm6->values[value_idx]; -+ src = &sm6->values[value]; - -- case CST_CODE_UNDEF: -- dxil_record_validate_operand_max_count(record, 0, sm6); -- dst->value_type = VALUE_TYPE_UNDEFINED; -- sm6_register_from_value(&dst->reg, dst); -- break; -+ if (!sm6_value_is_numeric_array(src)) -+ { -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Constexpr cast source value is not a global array element."); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } - -- default: -- FIXME("Unhandled constant code %u.\n", record->code); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -- "Constant code %u is unhandled.", record->code); -- dst->value_type = VALUE_TYPE_INVALID; -- sm6_register_from_value(&dst->reg, dst); -+ type = dst->type; -+ *dst = *src; -+ dst->type = type; - 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; -+ ++value_idx; - } - -- /* Resolve cast forward refs. */ -- for (i = base_value_idx; i < sm6->value_count; ++i) -- { -- dst = &sm6->values[i]; -- if (dst->reg.type != VKD3DSPR_COUNT) -- continue; -- -- type = dst->type; -- -- src = &sm6->values[dst->reg.idx[0].offset]; -- if (!sm6_value_is_numeric_array(src)) -- { -- WARN("Value is not an array.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -- "Constexpr cast source value is not a global array element."); -- return VKD3D_ERROR_INVALID_SHADER; -- } -- -- *dst = *src; -- dst->type = type; -- dst->reg.data_type = vkd3d_data_type_from_sm6_type(type->u.pointer.type); -- } -+ VKD3D_ASSERT(value_idx == sm6->value_count); - - return VKD3D_OK; - } -@@ -3537,7 +3695,6 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const stru - - dst->value_type = VALUE_TYPE_IDXTEMP; - dst->u.idxtemp.id = ins->declaration.indexable_temp.register_idx; -- sm6_register_from_value(&dst->reg, dst); - } - - static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6_type *elem_type, -@@ -3551,8 +3708,7 @@ static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6 - dst->value_type = VALUE_TYPE_GROUPSHAREDMEM; - dst->u.groupsharedmem.id = sm6->tgsm_count++; - dst->structure_stride = 0; -- sm6_register_from_value(&dst->reg, dst); -- sm6_register_from_value(&ins->declaration.tgsm_raw.reg.reg, dst); -+ sm6_register_from_value(&ins->declaration.tgsm_raw.reg.reg, dst, sm6); - ins->declaration.tgsm_raw.alignment = alignment; - byte_count = elem_type->u.width / 8u; - if (byte_count != 4) -@@ -3576,8 +3732,7 @@ static void sm6_parser_declare_tgsm_structured(struct sm6_parser *sm6, const str - dst->value_type = VALUE_TYPE_GROUPSHAREDMEM; - dst->u.groupsharedmem.id = sm6->tgsm_count++; - dst->structure_stride = elem_type->u.width / 8u; -- sm6_register_from_value(&dst->reg, dst); -- sm6_register_from_value(&ins->declaration.tgsm_structured.reg.reg, dst); -+ sm6_register_from_value(&ins->declaration.tgsm_structured.reg.reg, dst, sm6); - if (dst->structure_stride != 4) - { - FIXME("Unsupported structure stride %u.\n", dst->structure_stride); -@@ -3697,7 +3852,6 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ - - dst = sm6_parser_get_current_value(sm6); - dst->type = type; -- dst->value_type = VALUE_TYPE_REG; - dst->is_back_ref = true; - - if (is_constant && !init) -@@ -3891,7 +4045,6 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) - value->u.icb.id = icb->register_idx; - else - value->u.icb.id = 0; -- sm6_register_from_value(&value->reg, value); - } - - return VKD3D_OK; -@@ -3912,12 +4065,12 @@ static void dst_param_io_init(struct vkd3d_shader_dst_param *param, - } - - static void src_params_init_from_operands(struct vkd3d_shader_src_param *src_params, -- const struct sm6_value **operands, unsigned int count) -+ const struct sm6_value **operands, unsigned int count, struct sm6_parser *sm6) - { - unsigned int i; - - for (i = 0; i < count; ++i) -- src_param_init_from_value(&src_params[i], operands[i]); -+ src_param_init_from_value(&src_params[i], operands[i], sm6); - } - - static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( -@@ -4163,7 +4316,7 @@ static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_rec - 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) -+ if (sm6_value_get_constant_uint(size, sm6) != 1) - { - FIXME("Allocation size is not 1.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -@@ -4228,7 +4381,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ - || !sm6_value_validate_is_backward_ref(ptr, sm6)) - return; - -- sm6_register_from_value(®, ptr); -+ sm6_register_from_value(®, ptr, sm6); - - if (reg.type != VKD3DSPR_GROUPSHAREDMEM) - { -@@ -4284,12 +4437,12 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ - src_param_init_vector_from_reg(&src_params[0], &coord); - else - src_param_make_constant_uint(&src_params[0], 0); -- src_param_init_from_value(&src_params[1], src); -+ src_param_init_from_value(&src_params[1], src, sm6); - - sm6_parser_init_ssa_value(sm6, dst); - - dst_params = instruction_dst_params_alloc(ins, 2, sm6); -- sm6_register_from_value(&dst_params[0].reg, dst); -+ sm6_register_from_value(&dst_params[0].reg, dst, sm6); - dst_param_init(&dst_params[0]); - - dst_params[1].reg = reg; -@@ -4459,8 +4612,8 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0], a); -- src_param_init_from_value(&src_params[1], b); -+ src_param_init_from_value(&src_params[0], a, sm6); -+ src_param_init_from_value(&src_params[1], b, sm6); - if (code == BINOP_SUB) - src_params[1].modifiers = VKD3DSPSM_NEG; - -@@ -4474,7 +4627,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - dst_param_init(&dst_params[0]); - dst_param_init(&dst_params[1]); - sm6_parser_init_ssa_value(sm6, dst); -- sm6_register_from_value(&dst_params[index].reg, dst); -+ sm6_register_from_value(&dst_params[index].reg, dst, sm6); - vsir_dst_param_init_null(&dst_params[index ^ 1]); - } - else -@@ -4536,7 +4689,7 @@ static void sm6_parser_emit_br(struct sm6_parser *sm6, const struct dxil_record - dxil_record_validate_operand_max_count(record, i, sm6); - - code_block->terminator.type = TERMINATOR_COND_BR; -- sm6_register_from_value(&code_block->terminator.conditional_reg, value); -+ sm6_register_from_value(&code_block->terminator.conditional_reg, value, sm6); - code_block->terminator.true_block = sm6_function_get_block(function, record->operands[0], sm6); - code_block->terminator.false_block = sm6_function_get_block(function, record->operands[1], sm6); - } -@@ -4607,7 +4760,7 @@ static bool sm6_parser_emit_composite_construct(struct sm6_parser *sm6, const st - unsigned int i; - - for (i = 0; i < component_count; ++i) -- sm6_register_from_value(&operand_regs[i], operands[i]); -+ sm6_register_from_value(&operand_regs[i], operands[i], sm6); - - return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); - } -@@ -4623,11 +4776,11 @@ static bool sm6_parser_emit_coordinate_construct(struct sm6_parser *sm6, const s - { - if (!z_operand && operands[component_count]->value_type == VALUE_TYPE_UNDEFINED) - break; -- sm6_register_from_value(&operand_regs[component_count], operands[component_count]); -+ sm6_register_from_value(&operand_regs[component_count], operands[component_count], sm6); - } - - if (z_operand) -- sm6_register_from_value(&operand_regs[component_count++], z_operand); -+ sm6_register_from_value(&operand_regs[component_count++], z_operand, sm6); - - return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); - } -@@ -4741,7 +4894,7 @@ static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, enum dx_intrinsic_o - vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0]); -+ src_param_init_from_value(src_param, operands[0], sm6); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - } -@@ -4780,15 +4933,15 @@ static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_ - vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type)); - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0], operands[0]); -- src_param_init_from_value(&src_params[1], operands[1]); -+ src_param_init_from_value(&src_params[0], operands[0], sm6); -+ src_param_init_from_value(&src_params[1], operands[1], sm6); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - } - - static enum vkd3d_shader_opcode map_dx_atomic_binop(const struct sm6_value *operand, struct sm6_parser *sm6) - { -- uint64_t code = sm6_value_get_constant_uint(operand); -+ uint64_t code = sm6_value_get_constant_uint(operand, sm6); - - switch (code) - { -@@ -4852,7 +5005,7 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr - } - else - { -- sm6_register_from_value(®, operands[coord_idx]); -+ sm6_register_from_value(®, operands[coord_idx], sm6); - } - - for (i = coord_idx + coord_count; i < coord_idx + 3; ++i) -@@ -4873,14 +5026,14 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr - return; - src_param_init_vector_from_reg(&src_params[0], ®); - if (is_cmp_xchg) -- src_param_init_from_value(&src_params[1], operands[4]); -- src_param_init_from_value(&src_params[1 + is_cmp_xchg], operands[5]); -+ src_param_init_from_value(&src_params[1], operands[4], sm6); -+ src_param_init_from_value(&src_params[1 + is_cmp_xchg], operands[5], sm6); - - sm6_parser_init_ssa_value(sm6, dst); - - dst_params = instruction_dst_params_alloc(ins, 2, sm6); - dst_param_init(&dst_params[0]); -- sm6_register_from_value(&dst_params[0].reg, dst); -+ sm6_register_from_value(&dst_params[0].reg, dst, sm6); - dst_param_init(&dst_params[1]); - sm6_register_from_handle(sm6, &resource->u.handle, &dst_params[1].reg); - } -@@ -4892,7 +5045,7 @@ static void sm6_parser_emit_dx_barrier(struct sm6_parser *sm6, enum dx_intrinsic - enum dxil_sync_flags flags; - - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SYNC); -- flags = sm6_value_get_constant_uint(operands[0]); -+ flags = sm6_value_get_constant_uint(operands[0], sm6); - ins->flags = flags & (SYNC_THREAD_GROUP | SYNC_THREAD_GROUP_UAV); - if (flags & SYNC_GLOBAL_UAV) - ins->flags |= VKD3DSSF_GLOBAL_UAV; -@@ -4926,7 +5079,7 @@ static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enu - "A dynamic update value for a UAV counter operation is not supported."); - return; - } -- i = sm6_value_get_constant_uint(operands[1]); -+ i = sm6_value_get_constant_uint(operands[1], sm6); - if (i != 1 && i != 255) - { - WARN("Unexpected update value %#x.\n", i); -@@ -4963,7 +5116,7 @@ static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_int - if (!sm6_parser_emit_coordinate_construct(sm6, &operands[2], 3, NULL, state, &coord)) - return; - -- clamp = sm6_value_get_constant_uint(operands[5]); -+ clamp = sm6_value_get_constant_uint(operands[5], sm6); - - ins = state->ins; - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_LOD); -@@ -5064,7 +5217,7 @@ static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_pa - if (!sm6_value_is_constant(address)) - return d; - -- register_index = sm6_value_get_constant_uint(address); -+ register_index = sm6_value_get_constant_uint(address, sm6); - if (register_index >= d->range.first && register_index <= d->range.last) - return d; - } -@@ -5081,8 +5234,8 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int - struct sm6_value *dst; - unsigned int id; - -- type = sm6_value_get_constant_uint(operands[0]); -- id = sm6_value_get_constant_uint(operands[1]); -+ type = sm6_value_get_constant_uint(operands[0], sm6); -+ id = sm6_value_get_constant_uint(operands[1], sm6); - if (!(d = sm6_parser_get_descriptor(sm6, type, id, operands[2]))) - { - WARN("Failed to find resource type %#x, id %#x.\n", type, id); -@@ -5095,7 +5248,7 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int - dst->value_type = VALUE_TYPE_HANDLE; - dst->u.handle.d = d; - dst->u.handle.index = operands[2]; -- dst->u.handle.non_uniform = !!sm6_value_get_constant_uint(operands[3]); -+ dst->u.handle.non_uniform = !!sm6_value_get_constant_uint(operands[3], sm6); - - /* NOP is used to flag no instruction emitted. */ - ins->opcode = VKD3DSIH_NOP; -@@ -5113,7 +5266,7 @@ static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_ - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; - -- i = sm6_value_get_constant_uint(operands[0]); -+ i = sm6_value_get_constant_uint(operands[0], sm6); - if (i >= MAX_GS_OUTPUT_STREAMS) - { - WARN("Invalid stream index %u.\n", i); -@@ -5142,7 +5295,7 @@ static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_DISCARD); - - if ((src_param = instruction_src_params_alloc(ins, 1, sm6))) -- src_param_init_from_value(src_param, operands[0]); -+ src_param_init_from_value(src_param, operands[0], sm6); - } - - static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5154,7 +5307,7 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i - - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - -- if ((component_idx = sm6_value_get_constant_uint(operands[0])) >= 3) -+ if ((component_idx = sm6_value_get_constant_uint(operands[0], sm6)) >= 3) - { - WARN("Invalid component index %u.\n", component_idx); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -@@ -5223,8 +5376,8 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri - unsigned int row_index, column_index; - const struct signature_element *e; - -- row_index = sm6_value_get_constant_uint(operands[0]); -- column_index = sm6_value_get_constant_uint(operands[2]); -+ row_index = sm6_value_get_constant_uint(operands[0], sm6); -+ column_index = sm6_value_get_constant_uint(operands[2], sm6); - - signature = &sm6->p.program->input_signature; - if (row_index >= signature->element_count) -@@ -5256,7 +5409,7 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri - register_index_address_init(&src_params[0].reg.idx[0], operands[1], sm6); - - if (op == DX_EVAL_SAMPLE_INDEX) -- src_param_init_from_value(&src_params[1], operands[3]); -+ src_param_init_from_value(&src_params[1], operands[3], sm6); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - } -@@ -5270,7 +5423,7 @@ static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_op - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0]); -+ src_param_init_from_value(src_param, operands[0], sm6); - src_param->modifiers = VKD3DSPSM_ABS; - - instruction_dst_param_init_ssa_scalar(ins, sm6); -@@ -5311,7 +5464,7 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i - if (component_count > 1) - { - src_param->reg.dimension = VSIR_DIMENSION_VEC4; -- component_idx = sm6_value_get_constant_uint(operands[0]); -+ component_idx = sm6_value_get_constant_uint(operands[0], sm6); - } - src_param_init_scalar(src_param, component_idx); - -@@ -5345,7 +5498,7 @@ static void sm6_parser_emit_dx_ma(struct sm6_parser *sm6, enum dx_intrinsic_opco - if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) - return; - for (i = 0; i < 3; ++i) -- src_param_init_from_value(&src_params[i], operands[i]); -+ src_param_init_from_value(&src_params[i], operands[i], sm6); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - } -@@ -5375,12 +5528,12 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in - if (is_texture) - { - ins->flags = VKD3DSI_RESINFO_UINT; -- src_param_init_from_value(&src_params[0], operands[1]); -+ src_param_init_from_value(&src_params[0], operands[1], sm6); - component_count = VKD3D_VEC4_SIZE; - - if (resource_kind_is_multisampled(resource_kind)) - { -- instruction_dst_param_init_temp_vector(ins++, sm6); -+ instruction_dst_param_init_uint_temp_vector(ins++, sm6); - state->temp_idx = 1; - - /* DXIL does not have an intrinsic for sample info, and resinfo is expected to return -@@ -5393,7 +5546,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in - src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); - src_params[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); - -- if (!instruction_dst_param_init_temp_vector(ins, sm6)) -+ if (!instruction_dst_param_init_uint_temp_vector(ins, sm6)) - return; - dst = ins->dst; - dst->write_mask = VKD3DSP_WRITEMASK_3; -@@ -5448,7 +5601,7 @@ static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsi - if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) - return; - for (i = 0; i < 3; ++i) -- src_param_init_from_value(&src_params[i], operands[i]); -+ src_param_init_from_value(&src_params[i], operands[i], sm6); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - } -@@ -5466,8 +5619,8 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin - const struct shader_signature *signature; - const struct signature_element *e; - -- row_index = sm6_value_get_constant_uint(operands[0]); -- column_index = sm6_value_get_constant_uint(operands[2]); -+ row_index = sm6_value_get_constant_uint(operands[0], sm6); -+ column_index = sm6_value_get_constant_uint(operands[2], sm6); - - if (is_control_point && operands[3]->value_type == VALUE_TYPE_UNDEFINED) - { -@@ -5576,7 +5729,7 @@ static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic - enum vkd3d_shader_opcode opcode; - enum dxil_quad_op_kind quad_op; - -- quad_op = sm6_value_get_constant_uint(operands[1]); -+ quad_op = sm6_value_get_constant_uint(operands[1], sm6); - if ((opcode = dx_map_quad_op(quad_op)) == VKD3DSIH_INVALID) - { - FIXME("Unhandled quad op kind %u.\n", quad_op); -@@ -5589,7 +5742,7 @@ static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic - - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0]); -+ src_param_init_from_value(src_param, operands[0], sm6); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - } -@@ -5610,7 +5763,7 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i - - if (op == DX_RAW_BUFFER_LOAD) - { -- write_mask = sm6_value_get_constant_uint(operands[3]); -+ write_mask = sm6_value_get_constant_uint(operands[3], sm6); - if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) - { - WARN("Invalid write mask %#x.\n", write_mask); -@@ -5631,7 +5784,7 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i - operand_count = 2 + !raw; - if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) - return; -- src_params_init_from_operands(src_params, &operands[1], operand_count - 1); -+ src_params_init_from_operands(src_params, &operands[1], operand_count - 1, sm6); - src_param_init_vector_from_handle(sm6, &src_params[operand_count - 1], &resource->u.handle); - - instruction_dst_param_init_ssa_vector(ins, component_count, sm6); -@@ -5653,7 +5806,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ - return; - raw = resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER; - -- write_mask = sm6_value_get_constant_uint(operands[7]); -+ write_mask = sm6_value_get_constant_uint(operands[7], sm6); - if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) - { - WARN("Invalid write mask %#x.\n", write_mask); -@@ -5679,7 +5832,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ - "Resource for a raw buffer store is not a raw or structured buffer."); - } - -- alignment = sm6_value_get_constant_uint(operands[8]); -+ alignment = sm6_value_get_constant_uint(operands[8], sm6); - if (alignment & (alignment - 1)) - { - FIXME("Invalid alignment %#x.\n", alignment); -@@ -5697,7 +5850,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ - - if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) - return; -- src_params_init_from_operands(src_params, &operands[1], operand_count - 1); -+ src_params_init_from_operands(src_params, &operands[1], operand_count - 1, sm6); - data.data_type = VKD3D_DATA_UINT; - src_param_init_vector_from_reg(&src_params[operand_count - 1], &data); - -@@ -5736,7 +5889,7 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri - - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0], operands[1]); -+ src_param_init_from_value(&src_params[0], operands[1], sm6); - if (!sm6_value_is_undef(operands[2])) - { - /* Constant zero would be ok, but is not worth checking for unless it shows up. */ -@@ -5776,7 +5929,7 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr - "Resource for a typed buffer store is not a typed buffer."); - } - -- write_mask = sm6_value_get_constant_uint(operands[7]); -+ write_mask = sm6_value_get_constant_uint(operands[7], sm6); - if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) - { - WARN("Invalid write mask %#x.\n", write_mask); -@@ -5801,7 +5954,7 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr - - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0], operands[1]); -+ src_param_init_from_value(&src_params[0], operands[1], sm6); - if (!sm6_value_is_undef(operands[2])) - { - /* Constant zero would have no effect, but is not worth checking for unless it shows up. */ -@@ -5856,30 +6009,30 @@ static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_in - if (op == DX_TEX2DMS_GET_SAMPLE_POS) - { - src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); -- src_param_init_from_value(&src_params[1], operands[1]); -+ src_param_init_from_value(&src_params[1], operands[1], sm6); - } - else - { - src_param_init_vector(&src_params[0], 2); - vsir_register_init(&src_params[0].reg, VKD3DSPR_RASTERIZER, VKD3D_DATA_FLOAT, 0); - src_params[0].reg.dimension = VSIR_DIMENSION_VEC4; -- src_param_init_from_value(&src_params[1], operands[0]); -+ src_param_init_from_value(&src_params[1], operands[0], sm6); - } - - instruction_dst_param_init_ssa_vector(ins, 2, sm6); - } - --static unsigned int sm6_value_get_texel_offset(const struct sm6_value *value) -+static unsigned int sm6_value_get_texel_offset(const struct sm6_value *value, struct sm6_parser *sm6) - { -- return sm6_value_is_undef(value) ? 0 : sm6_value_get_constant_uint(value); -+ return sm6_value_is_undef(value) ? 0 : sm6_value_get_constant_uint(value, sm6); - } - - static void instruction_set_texel_offset(struct vkd3d_shader_instruction *ins, - const struct sm6_value **operands, struct sm6_parser *sm6) - { -- ins->texel_offset.u = sm6_value_get_texel_offset(operands[0]); -- ins->texel_offset.v = sm6_value_get_texel_offset(operands[1]); -- ins->texel_offset.w = sm6_value_get_texel_offset(operands[2]); -+ ins->texel_offset.u = sm6_value_get_texel_offset(operands[0], sm6); -+ ins->texel_offset.v = sm6_value_get_texel_offset(operands[1], sm6); -+ ins->texel_offset.w = sm6_value_get_texel_offset(operands[2], sm6); - } - - static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -5925,7 +6078,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ - instruction_init_with_resource(ins, (op == DX_SAMPLE_B) ? VKD3DSIH_SAMPLE_B : VKD3DSIH_SAMPLE_LOD, - resource, sm6); - src_params = instruction_src_params_alloc(ins, 4, sm6); -- src_param_init_from_value(&src_params[3], operands[9]); -+ src_param_init_from_value(&src_params[3], operands[9], sm6); - break; - case DX_SAMPLE_C: - clamp_idx = 10; -@@ -5934,7 +6087,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ - instruction_init_with_resource(ins, (op == DX_SAMPLE_C_LZ) ? VKD3DSIH_SAMPLE_C_LZ : VKD3DSIH_SAMPLE_C, - resource, sm6); - src_params = instruction_src_params_alloc(ins, 4, sm6); -- src_param_init_from_value(&src_params[3], operands[9]); -+ src_param_init_from_value(&src_params[3], operands[9], sm6); - component_count = 1; - break; - case DX_SAMPLE_GRAD: -@@ -6003,7 +6156,7 @@ static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsi - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0]); -+ src_param_init_from_value(src_param, operands[0], sm6); - - if (instruction_dst_param_init_ssa_scalar(ins, sm6)) - ins->dst->modifiers = VKD3DSPDM_SATURATE; -@@ -6021,7 +6174,7 @@ static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_ - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SINCOS); - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0]); -+ src_param_init_from_value(src_param, operands[0], sm6); - - sm6_parser_init_ssa_value(sm6, dst); - -@@ -6029,7 +6182,7 @@ static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_ - dst_params = instruction_dst_params_alloc(ins, 2, sm6); - dst_param_init(&dst_params[0]); - dst_param_init(&dst_params[1]); -- sm6_register_from_value(&dst_params[index].reg, dst); -+ sm6_register_from_value(&dst_params[index].reg, dst, sm6); - vsir_dst_param_init_null(&dst_params[index ^ 1]); - } - -@@ -6042,7 +6195,7 @@ static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intr - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0]); -+ src_param_init_from_value(src_param, operands[0], sm6); - - instruction_dst_param_init_ssa_vector(ins, 2, sm6); - } -@@ -6060,8 +6213,8 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr - const struct signature_element *e; - const struct sm6_value *value; - -- row_index = sm6_value_get_constant_uint(operands[0]); -- column_index = sm6_value_get_constant_uint(operands[2]); -+ row_index = sm6_value_get_constant_uint(operands[0], sm6); -+ column_index = sm6_value_get_constant_uint(operands[2], sm6); - - signature = is_patch_constant ? &program->patch_constant_signature : &program->output_signature; - if (row_index >= signature->element_count) -@@ -6108,7 +6261,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr - } - - if ((src_param = instruction_src_params_alloc(ins, 1, sm6))) -- src_param_init_from_value(src_param, value); -+ src_param_init_from_value(src_param, value, sm6); - } - - static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -6150,7 +6303,7 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in - instruction_init_with_resource(ins, extended_offset ? VKD3DSIH_GATHER4_PO_C : VKD3DSIH_GATHER4_C, resource, sm6); - if (!(src_params = instruction_src_params_alloc(ins, 4 + extended_offset, sm6))) - return; -- src_param_init_from_value(&src_params[3 + extended_offset], operands[9]); -+ src_param_init_from_value(&src_params[3 + extended_offset], operands[9], sm6); - } - - src_param_init_vector_from_reg(&src_params[0], &coord); -@@ -6161,7 +6314,7 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in - src_param_init_vector_from_handle(sm6, &src_params[1 + extended_offset], &resource->u.handle); - src_param_init_vector_from_handle(sm6, &src_params[2 + extended_offset], &sampler->u.handle); - /* Swizzle stored in the sampler parameter is the scalar component index to be gathered. */ -- swizzle = sm6_value_get_constant_uint(operands[8]); -+ swizzle = sm6_value_get_constant_uint(operands[8], sm6); - if (swizzle >= VKD3D_VEC4_SIZE) - { - WARN("Invalid swizzle %#x.\n", swizzle); -@@ -6213,7 +6366,7 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr - src_param_init_vector_from_reg(&src_params[0], &coord); - src_param_init_vector_from_handle(sm6, &src_params[1], &resource->u.handle); - if (is_multisample) -- src_param_init_from_value(&src_params[2], mip_level_or_sample_count); -+ src_param_init_from_value(&src_params[2], mip_level_or_sample_count, sm6); - - instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); - } -@@ -6235,7 +6388,7 @@ static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_int - if (!sm6_parser_emit_coordinate_construct(sm6, &operands[1], 3, NULL, state, &coord)) - return; - -- write_mask = sm6_value_get_constant_uint(operands[8]); -+ write_mask = sm6_value_get_constant_uint(operands[8], sm6); - if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) - { - WARN("Invalid write mask %#x.\n", write_mask); -@@ -6277,7 +6430,7 @@ static void sm6_parser_emit_dx_wave_active_ballot(struct sm6_parser *sm6, enum d - vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_WAVE_ACTIVE_BALLOT); - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0]); -+ src_param_init_from_value(src_param, operands[0], sm6); - - instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); - } -@@ -6296,7 +6449,7 @@ static enum vkd3d_shader_opcode sm6_dx_map_wave_bit_op(enum dxil_wave_bit_op_kin - default: - FIXME("Unhandled wave bit op %u.\n", op); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_UNHANDLED_INTRINSIC, -- "Wave bit operation %u is unhandled.\n", op); -+ "Wave bit operation %u is unhandled.", op); - return VKD3DSIH_INVALID; - } - } -@@ -6309,7 +6462,7 @@ static void sm6_parser_emit_dx_wave_active_bit(struct sm6_parser *sm6, enum dx_i - enum dxil_wave_bit_op_kind wave_op; - enum vkd3d_shader_opcode opcode; - -- wave_op = sm6_value_get_constant_uint(operands[1]); -+ wave_op = sm6_value_get_constant_uint(operands[1], sm6); - - if ((opcode = sm6_dx_map_wave_bit_op(wave_op, sm6)) == VKD3DSIH_INVALID) - return; -@@ -6317,7 +6470,7 @@ static void sm6_parser_emit_dx_wave_active_bit(struct sm6_parser *sm6, enum dx_i - - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0]); -+ src_param_init_from_value(src_param, operands[0], sm6); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - } -@@ -6342,7 +6495,7 @@ static enum vkd3d_shader_opcode sm6_dx_map_wave_op(enum dxil_wave_op_kind op, bo - default: - FIXME("Unhandled wave op %u.\n", op); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_UNHANDLED_INTRINSIC, -- "Wave operation %u is unhandled.\n", op); -+ "Wave operation %u is unhandled.", op); - return VKD3DSIH_INVALID; - } - } -@@ -6356,8 +6509,8 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic - enum dxil_wave_op_kind wave_op; - bool is_signed; - -- wave_op = sm6_value_get_constant_uint(operands[1]); -- is_signed = !sm6_value_get_constant_uint(operands[2]); -+ wave_op = sm6_value_get_constant_uint(operands[1], sm6); -+ is_signed = !sm6_value_get_constant_uint(operands[2], sm6); - opcode = sm6_dx_map_wave_op(wave_op, is_signed, sm6_type_is_floating_point(operands[0]->type), sm6); - - if (opcode == VKD3DSIH_INVALID) -@@ -6368,7 +6521,7 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic - - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, operands[0]); -+ src_param_init_from_value(src_param, operands[0], sm6); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - } -@@ -6645,7 +6798,6 @@ static void sm6_parser_emit_unhandled(struct sm6_parser *sm6, struct vkd3d_shade - return; - - dst->value_type = VALUE_TYPE_INVALID; -- sm6_register_from_value(&dst->reg, dst); - } - - static void sm6_parser_decode_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -6750,7 +6902,7 @@ static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_recor - "Expected a constant integer dx intrinsic function id."); - return; - } -- sm6_parser_decode_dx_op(sm6, sm6_value_get_constant_uint(op_value), -+ sm6_parser_decode_dx_op(sm6, sm6_value_get_constant_uint(op_value, sm6), - fn_value->u.function.name, &operands[1], operand_count - 1, state, dst); - } - -@@ -6759,6 +6911,7 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ - { - enum vkd3d_shader_opcode op = VKD3DSIH_INVALID; - bool from_int, to_int, from_fp, to_fp; -+ unsigned int from_width, to_width; - bool is_valid = false; - - from_int = sm6_type_is_integer(from); -@@ -6782,70 +6935,62 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ - return VKD3DSIH_INVALID; - } - -- /* DXC emits minimum precision types as 16-bit. These must be emitted -- * as 32-bit in VSIR, so all width extensions to 32 bits are no-ops. */ - switch (code) - { - case CAST_TRUNC: -- /* nop or min precision. TODO: native 16-bit */ -- if (to->u.width == from->u.width || (to->u.width == 16 && from->u.width == 32)) -- op = VKD3DSIH_NOP; -- else -- op = VKD3DSIH_UTOU; -+ op = VKD3DSIH_UTOU; - is_valid = from_int && to_int && to->u.width <= from->u.width; - break; -+ - case CAST_ZEXT: -+ op = VKD3DSIH_UTOU; -+ is_valid = from_int && to_int && to->u.width >= from->u.width; -+ break; -+ - case CAST_SEXT: -- /* nop or min precision. TODO: native 16-bit. -- * Extension instructions could be emitted for min precision, but in Windows -- * the AMD RX 580 simply drops such instructions, which makes sense as no -- * assumptions should be made about any behaviour which depends on bit width. */ -- if (to->u.width == from->u.width || (to->u.width == 32 && from->u.width == 16)) -- { -- op = VKD3DSIH_NOP; -- is_valid = from_int && to_int; -- } -- else if (to->u.width > from->u.width) -- { -- op = (code == CAST_ZEXT) ? VKD3DSIH_UTOU : VKD3DSIH_ITOI; -- VKD3D_ASSERT(from->u.width == 1 || to->u.width == 64); -- is_valid = from_int && to_int; -- } -+ op = VKD3DSIH_ITOI; -+ is_valid = from_int && to_int && to->u.width >= from->u.width; - break; -+ - case CAST_FPTOUI: - op = VKD3DSIH_FTOU; - is_valid = from_fp && to_int && to->u.width > 1; - break; -+ - case CAST_FPTOSI: - op = VKD3DSIH_FTOI; - is_valid = from_fp && to_int && to->u.width > 1; - break; -+ - case CAST_UITOFP: - op = VKD3DSIH_UTOF; - is_valid = from_int && to_fp; - break; -+ - case CAST_SITOFP: - op = VKD3DSIH_ITOF; - is_valid = from_int && to_fp; - break; -+ - case CAST_FPTRUNC: -- /* TODO: native 16-bit */ -- op = (from->u.width == 64) ? VKD3DSIH_DTOF : VKD3DSIH_NOP; -- is_valid = from_fp && to_fp; -+ op = VKD3DSIH_DTOF; -+ is_valid = from_fp && to_fp && to->u.width <= from->u.width; - break; -+ - case CAST_FPEXT: -- /* TODO: native 16-bit */ -- op = (to->u.width == 64) ? VKD3DSIH_FTOD : VKD3DSIH_NOP; -- is_valid = from_fp && to_fp; -+ op = VKD3DSIH_FTOD; -+ is_valid = from_fp && to_fp && to->u.width >= from->u.width; - break; -+ - case CAST_BITCAST: - op = VKD3DSIH_MOV; - is_valid = to->u.width == from->u.width; - break; -+ - default: - FIXME("Unhandled cast op %"PRIu64".\n", code); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -- "Cast operation %"PRIu64" is unhandled.\n", code); -+ "Cast operation %"PRIu64" is unhandled.", code); - return VKD3DSIH_INVALID; - } - -@@ -6853,11 +6998,25 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ - { - FIXME("Invalid types %u and/or %u for op %"PRIu64".\n", from->class, to->class, code); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -- "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.\n", -+ "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.", - code, from->class, from->u.width, to->class, to->u.width); - return VKD3DSIH_INVALID; - } - -+ /* 16-bit values are currently treated as 32-bit, because 16-bit is -+ * interpreted as a minimum precision hint in SM 6.0, and we don't handle -+ * SM > 6.0 yet. */ -+ from_width = from->u.width; -+ if (from_width == 16) -+ from_width = 32; -+ -+ to_width = to->u.width; -+ if (to_width == 16) -+ to_width = 32; -+ -+ if (from->class == to->class && from_width == to_width) -+ op = VKD3DSIH_NOP; -+ - return op; - } - -@@ -6896,22 +7055,22 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor - - if (handler_idx == VKD3DSIH_NOP) - { -- sm6_register_from_value(&dst->reg, value); -- /* Set the result type for casts from 16-bit min precision. */ -- if (type->u.width != 16) -- dst->reg.data_type = vkd3d_data_type_from_sm6_type(type); -+ *dst = *value; -+ dst->type = type; - return; - } - - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- src_param_init_from_value(src_param, value); -+ src_param_init_from_value(src_param, value, sm6); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - -- /* bitcast */ -+ /* VSIR bitcasts are represented by source registers with types different -+ * from the types they were written with, rather than with different types -+ * for the MOV source and destination. */ - if (handler_idx == VKD3DSIH_MOV) -- src_param->reg.data_type = dst->reg.data_type; -+ src_param->reg.data_type = ins->dst[0].reg.data_type; - } - - struct sm6_cmp_info -@@ -7051,8 +7210,8 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor - - if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) - return; -- src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a); -- src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b); -+ src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a, sm6); -+ src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b, sm6); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - } -@@ -7074,7 +7233,7 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re - || !sm6_value_validate_is_backward_ref(ptr, sm6)) - return; - -- sm6_register_from_value(®, ptr); -+ sm6_register_from_value(®, ptr, sm6); - - if (reg.type != VKD3DSPR_GROUPSHAREDMEM) - { -@@ -7129,14 +7288,14 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re - if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) - return; - src_param_make_constant_uint(&src_params[0], 0); -- src_param_init_from_value(&src_params[1], cmp); -- src_param_init_from_value(&src_params[2], new); -+ src_param_init_from_value(&src_params[1], cmp, sm6); -+ src_param_init_from_value(&src_params[2], new, sm6); - - sm6_parser_init_ssa_value(sm6, dst); - - if (!(dst_params = instruction_dst_params_alloc(ins, 2, sm6))) - return; -- sm6_register_from_value(&dst_params[0].reg, dst); -+ sm6_register_from_value(&dst_params[0].reg, dst, sm6); - dst_param_init(&dst_params[0]); - dst_params[1].reg = reg; - dst_param_init(&dst_params[1]); -@@ -7195,7 +7354,7 @@ static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil - - if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) - return; -- sm6_register_from_value(&src_param->reg, src); -+ sm6_register_from_value(&src_param->reg, src, sm6); - src_param_init_scalar(src_param, elem_idx); - - instruction_dst_param_init_ssa_scalar(ins, sm6); -@@ -7208,9 +7367,8 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record - unsigned int elem_idx, operand_idx = 2; - enum bitcode_address_space addr_space; - const struct sm6_value *elem_value; -- struct vkd3d_shader_register reg; - const struct sm6_value *src; -- bool is_in_bounds; -+ struct sm6_index *index; - - if (!dxil_record_validate_operand_min_count(record, 5, sm6) - || !(type = sm6_parser_get_type(sm6, record->operands[1])) -@@ -7222,9 +7380,13 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record - return; - } - -- sm6_register_from_value(®, src); -+ *dst = *src; -+ index = sm6_get_value_index(sm6, dst); - -- if (reg.idx_count > 1) -+ if (!index) -+ return; -+ -+ if (index->index) - { - WARN("Unsupported stacked GEP.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -@@ -7232,8 +7394,6 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record - return; - } - -- is_in_bounds = record->operands[0]; -- - if ((pointee_type = src->type->u.pointer.type) != type) - { - WARN("Type mismatch, type %u width %u vs type %u width %u.\n", type->class, -@@ -7247,7 +7407,7 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record - return; - - /* The first index is always zero, to form a simple pointer dereference. */ -- if (sm6_value_get_constant_uint(elem_value)) -+ if (sm6_value_get_constant_uint(elem_value, sm6)) - { - WARN("Expected constant zero.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -@@ -7267,7 +7427,7 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record - return; - - /* If indexing is dynamic, just get the type at offset zero. */ -- elem_idx = sm6_value_is_constant(elem_value) ? sm6_value_get_constant_uint(elem_value) : 0; -+ elem_idx = sm6_value_is_constant(elem_value) ? sm6_value_get_constant_uint(elem_value, sm6) : 0; - type = sm6_type_get_element_type_at_index(pointee_type, elem_idx); - if (!type) - { -@@ -7293,13 +7453,8 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record - return; - } - -- reg.idx[1].offset = 0; -- register_index_address_init(®.idx[1], elem_value, sm6); -- reg.idx[1].is_in_bounds = is_in_bounds; -- reg.idx_count = 2; -- -- dst->reg = reg; -- dst->structure_stride = src->structure_stride; -+ index->index = elem_value; -+ index->is_in_bounds = record->operands[0]; - - ins->opcode = VKD3DSIH_NOP; - } -@@ -7348,7 +7503,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor - if (record->operands[i]) - WARN("Ignoring volatile modifier.\n"); - -- sm6_register_from_value(®, ptr); -+ sm6_register_from_value(®, ptr, sm6); - - if (ptr->structure_stride) - { -@@ -7363,7 +7518,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor - src_param_make_constant_uint(&src_params[0], reg.idx[1].offset); - /* Struct offset is always zero as there is no struct, just an array. */ - src_param_make_constant_uint(&src_params[1], 0); -- src_param_init_from_value(&src_params[2], ptr); -+ src_param_init_from_value(&src_params[2], ptr, sm6); - src_params[2].reg.alignment = alignment; - /* The offset is already in src_params[0]. */ - src_params[2].reg.idx_count = 1; -@@ -7377,7 +7532,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor - return; - if (operand_count > 1) - src_param_make_constant_uint(&src_params[0], 0); -- src_param_init_from_value(&src_params[operand_count - 1], ptr); -+ src_param_init_from_value(&src_params[operand_count - 1], ptr, sm6); - src_params[operand_count - 1].reg.alignment = alignment; - } - -@@ -7425,7 +7580,6 @@ static void sm6_parser_emit_phi(struct sm6_parser *sm6, const struct dxil_record - - if (!(phi = sm6_block_phi_require_space(code_block, sm6))) - return; -- sm6_register_from_value(&phi->reg, dst); - phi->incoming_count = record->operand_count / 2u; - - if (!vkd3d_array_reserve((void **)&phi->incoming, &phi->incoming_capacity, phi->incoming_count, -@@ -7536,7 +7690,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco - if (record->operands[i]) - WARN("Ignoring volatile modifier.\n"); - -- sm6_register_from_value(®, ptr); -+ sm6_register_from_value(®, ptr, sm6); - - if (ptr->structure_stride) - { -@@ -7551,7 +7705,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco - src_param_make_constant_uint(&src_params[0], reg.idx[1].offset); - /* Struct offset is always zero as there is no struct, just an array. */ - src_param_make_constant_uint(&src_params[1], 0); -- src_param_init_from_value(&src_params[2], src); -+ src_param_init_from_value(&src_params[2], src, sm6); - } - else - { -@@ -7562,7 +7716,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco - return; - if (operand_count > 1) - src_param_make_constant_uint(&src_params[0], 0); -- src_param_init_from_value(&src_params[operand_count - 1], src); -+ src_param_init_from_value(&src_params[operand_count - 1], src, sm6); - } - - dst_param = instruction_dst_params_alloc(ins, 1, sm6); -@@ -7612,7 +7766,7 @@ static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_rec - return; - } - -- sm6_register_from_value(&terminator->conditional_reg, src); -+ sm6_register_from_value(&terminator->conditional_reg, src, sm6); - terminator->type = TERMINATOR_SWITCH; - - terminator->case_count = record->operand_count / 2u; -@@ -7651,7 +7805,7 @@ static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_rec - "A switch case value is not a constant."); - } - -- terminator->cases[i / 2u].value = sm6_value_get_constant_uint64(src); -+ terminator->cases[i / 2u].value = sm6_value_get_constant_uint64(src, sm6); - } - - ins->opcode = VKD3DSIH_NOP; -@@ -7688,7 +7842,7 @@ static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_re - if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) - return; - for (i = 0; i < 3; ++i) -- src_param_init_from_value(&src_params[i], src[i]); -+ src_param_init_from_value(&src_params[i], src[i], sm6); - - instruction_dst_param_init_ssa_scalar(ins, sm6); - } -@@ -7714,7 +7868,7 @@ static bool sm6_metadata_value_is_zero_or_undef(const struct sm6_metadata_value - && (sm6_value_is_undef(m->u.value) || sm6_value_is_constant_zero(m->u.value)); - } - --static bool sm6_metadata_get_uint_value(const struct sm6_parser *sm6, -+static bool sm6_metadata_get_uint_value(struct sm6_parser *sm6, - const struct sm6_metadata_value *m, unsigned int *u) - { - const struct sm6_value *value; -@@ -7728,12 +7882,12 @@ static bool sm6_metadata_get_uint_value(const struct sm6_parser *sm6, - if (!sm6_type_is_integer(value->type)) - return false; - -- *u = sm6_value_get_constant_uint(value); -+ *u = sm6_value_get_constant_uint(value, sm6); - - return true; - } - --static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, -+static bool sm6_metadata_get_uint64_value(struct sm6_parser *sm6, - const struct sm6_metadata_value *m, uint64_t *u) - { - const struct sm6_value *value; -@@ -7747,12 +7901,12 @@ static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, - if (!sm6_type_is_integer(value->type)) - return false; - -- *u = sm6_value_get_constant_uint(value); -+ *u = sm6_value_get_constant_uint(value, sm6); - - return true; - } - --static bool sm6_metadata_get_float_value(const struct sm6_parser *sm6, -+static bool sm6_metadata_get_float_value(struct sm6_parser *sm6, - const struct sm6_metadata_value *m, float *f) - { - const struct sm6_value *value; -@@ -7766,7 +7920,7 @@ static bool sm6_metadata_get_float_value(const struct sm6_parser *sm6, - if (!sm6_type_is_floating_point(value->type)) - return false; - -- *f = register_get_float_value(&value->reg); -+ *f = sm6_value_get_constant_float(value, sm6); - - return true; - } -@@ -7951,7 +8105,7 @@ static void metadata_attachment_record_apply(const struct dxil_record *record, e - } - else if (metadata_node_get_unary_uint(node, &operand, sm6)) - { -- dst->reg.non_uniform = !!operand; -+ dst->non_uniform = !!operand; - } - } - else -@@ -8023,13 +8177,13 @@ static enum vkd3d_result sm6_function_resolve_phi_incomings(const struct sm6_fun - "A PHI incoming value is not a constant or SSA register."); - return VKD3D_ERROR_INVALID_SHADER; - } -- if (src->reg.data_type != phi->reg.data_type) -+ if (src->type != phi->value.type) - { - WARN("Type mismatch.\n"); - vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, - "The type of a phi incoming value does not match the result type."); - } -- sm6_register_from_value(&phi->incoming[j].reg, src); -+ sm6_register_from_value(&phi->incoming[j].reg, src, sm6); - } - } - } -@@ -8118,7 +8272,6 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - dst = sm6_parser_get_current_value(sm6); - fwd_type = dst->type; - dst->type = NULL; -- dst->value_type = VALUE_TYPE_REG; - dst->is_back_ref = true; - is_terminator = false; - -@@ -8196,6 +8349,10 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - if (record->attachment) - metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); - -+ /* This is specific for PHI nodes, but must happen after attachments have been applied. */ -+ if (record->code == FUNC_CODE_INST_PHI) -+ code_block->phi[code_block->phi_count - 1].value = *dst; -+ - if (is_terminator) - { - ++block_idx; -@@ -8342,7 +8499,7 @@ static void sm6_block_emit_phi(const struct sm6_block *block, struct sm6_parser - } - - dst_param_init(dst_param); -- dst_param->reg = src_phi->reg; -+ sm6_register_from_value(&dst_param->reg, &src_phi->value, sm6); - } - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index a4f1a371299..f7b2e3d7d13 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -54,6 +54,19 @@ enum state_property_component_type - FX_COMPONENT_TYPE_COUNT, - }; - -+enum fxlvm_constants -+{ -+ FX_FXLC_COMP_COUNT_MASK = 0xffff, -+ FX_FXLC_OPCODE_MASK = 0x7ff, -+ FX_FXLC_OPCODE_SHIFT = 20, -+ FX_FXLC_IS_SCALAR_MASK = 0x80000000, -+ -+ FX_FXLC_REG_LITERAL = 1, -+ FX_FXLC_REG_CB = 2, -+ FX_FXLC_REG_OUTPUT = 4, -+ FX_FXLC_REG_TEMP = 7, -+}; -+ - struct rhs_named_value - { - const char *name; -@@ -289,15 +302,6 @@ static void set_status(struct fx_write_context *fx, int status) - fx->status = status; - } - --static void fx_print_string(struct vkd3d_string_buffer *buffer, const char *prefix, -- const char *s, size_t len) --{ -- if (len) -- --len; /* Trim terminating null. */ -- vkd3d_string_buffer_printf(buffer, "%s", prefix); -- vkd3d_string_buffer_print_string_escaped(buffer, s, len); --} -- - static uint32_t write_string(const char *string, struct fx_write_context *fx) - { - return fx->ops->write_string(string, fx); -@@ -369,18 +373,23 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context - name = get_fx_4_type_name(element_type); - modifiers = element_type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK; - -- LIST_FOR_EACH_ENTRY(type_entry, &fx->types, struct type_entry, entry) -+ /* We don't try to reuse nameless types; they will get the same -+ * "" name, but are not available for the type cache. */ -+ if (name) - { -- if (strcmp(type_entry->name, name)) -- continue; -+ LIST_FOR_EACH_ENTRY(type_entry, &fx->types, struct type_entry, entry) -+ { -+ if (strcmp(type_entry->name, name)) -+ continue; - -- if (type_entry->elements_count != elements_count) -- continue; -+ if (type_entry->elements_count != elements_count) -+ continue; - -- if (type_entry->modifiers != modifiers) -- continue; -+ if (type_entry->modifiers != modifiers) -+ continue; - -- return type_entry->offset; -+ return type_entry->offset; -+ } - } - - if (!(type_entry = hlsl_alloc(fx->ctx, sizeof(*type_entry)))) -@@ -391,7 +400,8 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context - type_entry->elements_count = elements_count; - type_entry->modifiers = modifiers; - -- list_add_tail(&fx->types, &type_entry->entry); -+ if (name) -+ list_add_tail(&fx->types, &type_entry->entry); - - return type_entry->offset; - } -@@ -764,7 +774,7 @@ static const struct rhs_named_value fx_2_filter_values[] = - { NULL } - }; - --static const struct fx_2_state -+struct fx_2_state - { - const char *name; - enum hlsl_type_class class; -@@ -773,8 +783,9 @@ static const struct fx_2_state - uint32_t array_size; - uint32_t id; - const struct rhs_named_value *values; --} --fx_2_states[] = -+}; -+ -+static const struct fx_2_state fx_2_pass_states[] = - { - { "ZEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 0, fx_2_zenable_values }, - { "FillMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 1, fx_2_fillmode_values }, -@@ -867,7 +878,7 @@ fx_2_states[] = - { "AdaptiveTess_Y", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 84 }, - { "AdaptiveTess_Z", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 85 }, - { "AdaptiveTess_W", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 86 }, -- { "EnableAdaptiveTesselation", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 87 }, -+ { "EnableAdaptiveTessellation",HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 87 }, - { "TwoSidedStencilMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 88 }, - { "StencilFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 89, fx_2_stencilcaps_values }, - { "StencilZFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 90, fx_2_stencilcaps_values }, -@@ -898,17 +909,17 @@ fx_2_states[] = - { "BumpEnvMat01", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 113 }, - { "BumpEnvMat10", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 114 }, - { "BumpEnvMat11", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 115 }, -- { "TextCoordIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 116 }, -+ { "TexCoordIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 116 }, - { "BumpEnvLScale", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 117 }, - { "BumpEnvLOffset", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 118 }, - { "TextureTransformFlags", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 119, fx_2_texturetransform_values }, - { "Constant", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 120 }, -- { "NPatchMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 121 }, -+ { "PatchSegments", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 121 }, - { "FVF", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 122 }, - - { "ProjectionTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 123 }, - { "ViewTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 124 }, -- { "WorldTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 125 }, -+ { "WorldTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 256, 125 }, - { "TextureTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 8, 126 }, - - { "MaterialAmbient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 127 }, -@@ -917,42 +928,59 @@ fx_2_states[] = - { "MaterialEmissive", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 130 }, - { "MaterialPower", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 131 }, - -- { "LightType", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 132, fx_2_lighttype_values }, -- { "LightDiffuse", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 133 }, -- { "LightSpecular", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 134 }, -- { "LightAmbient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 135 }, -- { "LightPosition", HLSL_CLASS_VECTOR, FX_FLOAT, 3, 1, 136 }, -- { "LightDirection", HLSL_CLASS_VECTOR, FX_FLOAT, 3, 1, 137 }, -- { "LightRange", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 138 }, -- { "LightFalloff", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 139 }, -- { "LightAttenuation0", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 140 }, -- { "LightAttenuation1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 141 }, -- { "LightAttenuation2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 142 }, -- { "LightTheta", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 143 }, -- { "LightPhi", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 144 }, -- { "LightEnable", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 145 }, -+ { "LightType", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 132, fx_2_lighttype_values }, -+ { "LightDiffuse", HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 133 }, -+ { "LightSpecular", HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 134 }, -+ { "LightAmbient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 135 }, -+ { "LightPosition", HLSL_CLASS_VECTOR, FX_FLOAT, 3, ~0u, 136 }, -+ { "LightDirection", HLSL_CLASS_VECTOR, FX_FLOAT, 3, ~0u, 137 }, -+ { "LightRange", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 138 }, -+ { "LightFalloff", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 139 }, -+ { "LightAttenuation0", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 140 }, -+ { "LightAttenuation1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 141 }, -+ { "LightAttenuation2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 142 }, -+ { "LightTheta", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 143 }, -+ { "LightPhi", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 144 }, -+ { "LightEnable", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 145 }, - - { "VertexShader", HLSL_CLASS_SCALAR, FX_VERTEXSHADER, 1, 1, 146 }, - { "PixelShader", HLSL_CLASS_SCALAR, FX_PIXELSHADER, 1, 1, 147 }, - -- { "VertexShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 148 }, -- { "VertexShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u-1, 149 }, -- { "VertexShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u-1, 150 }, -- { "VertexShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 151 }, -- { "VertexShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 152 }, -- { "VertexShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 153 }, -- { "VertexShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 154 }, -- { "VertexShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 155 }, -- -- { "PixelShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 156 }, -- { "PixelShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u-1, 157 }, -- { "PixelShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u-1, 158 }, -- { "PixelShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 159 }, -- { "PixelShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 160 }, -- { "PixelShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 161 }, -- { "PixelShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 162 }, -- { "PixelShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 163 }, -+ { "VertexShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 148 }, -+ { "VertexShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u, 149 }, -+ { "VertexShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 150 }, -+ { "VertexShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 151 }, -+ { "VertexShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 152 }, -+ { "VertexShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 153 }, -+ { "VertexShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 154 }, -+ { "VertexShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 155 }, -+ -+ { "PixelShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 156 }, -+ { "PixelShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u, 157 }, -+ { "PixelShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 158 }, -+ { "PixelShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 159 }, -+ { "PixelShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 160 }, -+ { "PixelShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 161 }, -+ { "PixelShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 162 }, -+ { "PixelShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 163 }, -+ -+ { "Texture", HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 261, 164 }, -+ { "AddressU", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 165, fx_2_address_values }, -+ { "AddressV", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 166, fx_2_address_values }, -+ { "AddressW", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 167, fx_2_address_values }, -+ { "BorderColor", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 168 }, -+ { "MagFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 169, fx_2_filter_values }, -+ { "MinFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 170, fx_2_filter_values }, -+ { "MipFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 171, fx_2_filter_values }, -+ { "MipMapLodBias", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 172 }, -+ { "MaxMipLevel", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 173 }, -+ { "MaxAnisotropy", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 174 }, -+ { "SRGBTexture", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 175 }, -+ { "ElementIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 176 }, -+}; - -+static const struct fx_2_state fx_2_sampler_states[] = -+{ - { "Texture", HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 1, 164 }, - { "AddressU", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 165, fx_2_address_values }, - { "AddressV", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 166, fx_2_address_values }, -@@ -964,7 +992,7 @@ fx_2_states[] = - { "MipMapLodBias", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 172 }, - { "MaxMipLevel", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 173 }, - { "MaxAnisotropy", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 174 }, -- { "SRBTexture", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 175 }, -+ { "SRGBTexture", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 175 }, - { "ElementIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 176 }, - }; - -@@ -988,16 +1016,6 @@ static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx - fx->shader_count++; - } - --static uint32_t get_fx_4_type_size(const struct hlsl_type *type) --{ -- uint32_t elements_count; -- -- elements_count = hlsl_get_multiarray_size(type); -- type = hlsl_get_multiarray_element_type(type); -- -- return type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float) * elements_count; --} -- - enum fx_4_type_constants - { - /* Numeric types encoding */ -@@ -1015,6 +1033,9 @@ enum fx_4_type_constants - FX_4_NUMERIC_COLUMNS_SHIFT = 11, - FX_4_NUMERIC_COLUMN_MAJOR_MASK = 0x4000, - -+ /* Variable flags */ -+ FX_4_HAS_EXPLICIT_BIND_POINT = 0x4, -+ - /* Object types */ - FX_4_OBJECT_TYPE_STRING = 0x1, - FX_4_OBJECT_TYPE_BLEND_STATE = 0x2, -@@ -1071,17 +1092,6 @@ enum fx_4_type_constants - FX_4_ASSIGNMENT_VALUE_EXPRESSION = 0x6, - FX_4_ASSIGNMENT_INLINE_SHADER = 0x7, - FX_5_ASSIGNMENT_INLINE_SHADER = 0x8, -- -- /* FXLVM constants */ -- FX_4_FXLC_COMP_COUNT_MASK = 0xffff, -- FX_4_FXLC_OPCODE_MASK = 0x7ff, -- FX_4_FXLC_OPCODE_SHIFT = 20, -- FX_4_FXLC_IS_SCALAR_MASK = 0x80000000, -- -- FX_4_FXLC_REG_LITERAL = 1, -- FX_4_FXLC_REG_CB = 2, -- FX_4_FXLC_REG_OUTPUT = 4, -- FX_4_FXLC_REG_TEMP = 7, - }; - - static const uint32_t fx_4_numeric_base_types[] = -@@ -1238,7 +1248,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co - - name = get_fx_4_type_name(element_type); - -- name_offset = write_string(name, fx); -+ name_offset = write_string(name ? name : "", fx); - if (element_type->class == HLSL_CLASS_STRUCT) - { - if (!(field_offsets = hlsl_calloc(ctx, element_type->e.record.field_count, sizeof(*field_offsets)))) -@@ -1541,12 +1551,33 @@ static uint32_t get_fx_2_type_class(const struct hlsl_type *type) - return hlsl_sm1_class(type); - } - --static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *name, -- const struct hlsl_semantic *semantic, bool is_combined_sampler, struct fx_write_context *fx) -+struct fx_2_write_type_context - { -- struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; -- uint32_t semantic_offset, offset, elements_count = 0, name_offset; -- size_t i; -+ uint32_t *names; -+ uint32_t *semantics; -+ uint32_t count; -+ -+ uint32_t offset; -+ -+ bool is_combined_sampler; -+ struct fx_write_context *fx; -+}; -+ -+static void count_type_iter(const struct hlsl_type *type, const char *name, -+ const struct hlsl_semantic *semantic, void *context) -+{ -+ struct fx_2_write_type_context *ctx = context; -+ -+ ++ctx->count; -+} -+ -+static void write_fx_2_type_iter(const struct hlsl_type *type, const char *name, -+ const struct hlsl_semantic *semantic, void *context) -+{ -+ struct fx_2_write_type_context *ctx = context; -+ struct fx_write_context *fx = ctx->fx; -+ struct vkd3d_bytecode_buffer *buffer; -+ uint32_t offset, elements_count = 0; - - /* Resolve arrays to element type and number of elements. */ - if (type->class == HLSL_CLASS_ARRAY) -@@ -1555,13 +1586,11 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n - type = hlsl_get_multiarray_element_type(type); - } - -- name_offset = write_string(name, fx); -- semantic_offset = semantic->raw_name ? write_string(semantic->raw_name, fx) : 0; -- -- offset = put_u32(buffer, hlsl_sm1_base_type(type, is_combined_sampler)); -+ buffer = &fx->unstructured; -+ offset = put_u32(buffer, hlsl_sm1_base_type(type, ctx->is_combined_sampler)); - put_u32(buffer, get_fx_2_type_class(type)); -- put_u32(buffer, name_offset); -- put_u32(buffer, semantic_offset); -+ *ctx->names++ = put_u32(buffer, 0); -+ *ctx->semantics++ = put_u32(buffer, 0); - put_u32(buffer, elements_count); - - switch (type->class) -@@ -1586,19 +1615,68 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n - ; - } - -+ /* Save the offset of the top level type. */ -+ if (!ctx->offset) -+ ctx->offset = offset; -+} -+ -+static void write_fx_2_type_strings_iter(const struct hlsl_type *type, const char *name, -+ const struct hlsl_semantic *semantic, void *context) -+{ -+ struct fx_2_write_type_context *ctx = context; -+ struct fx_write_context *fx = ctx->fx; -+ struct vkd3d_bytecode_buffer *buffer; -+ -+ buffer = &fx->unstructured; -+ set_u32(buffer, *ctx->names++, write_string(name, fx)); -+ set_u32(buffer, *ctx->semantics++, semantic->raw_name ? write_string(semantic->raw_name, fx) : 0); -+} -+ -+static void foreach_type(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic, -+ void (*iter_func)(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic, void *context), -+ void *context) -+{ -+ iter_func(type, name, semantic, context); -+ -+ type = hlsl_get_multiarray_element_type(type); - if (type->class == HLSL_CLASS_STRUCT) - { -- for (i = 0; i < type->e.record.field_count; ++i) -+ for (size_t i = 0; i < type->e.record.field_count; ++i) - { - const struct hlsl_struct_field *field = &type->e.record.fields[i]; -- -- /* Validated in check_invalid_object_fields(). */ -- VKD3D_ASSERT(hlsl_is_numeric_type(field->type)); -- write_fx_2_parameter(field->type, field->name, &field->semantic, false, fx); -+ foreach_type(field->type, field->name, &field->semantic, iter_func, context); - } - } -+} - -- return offset; -+static uint32_t write_fx_2_parameter(const struct hlsl_ir_var *var, struct fx_write_context *fx) -+{ -+ struct fx_2_write_type_context ctx = { .fx = fx, .is_combined_sampler = var->is_combined_sampler }; -+ uint32_t *offsets; -+ -+ /* Parameter type information has to be stored in a contiguous segment, so -+ * that any structure fields come right after each other. To achieve that -+ * the variable length string data is written after the type data. */ -+ -+ /* Calculate the number of string entries needed for this type. */ -+ foreach_type(var->data_type, var->name, &var->semantic, count_type_iter, &ctx); -+ -+ if (!(offsets = calloc(ctx.count, 2 * sizeof(*offsets)))) -+ return 0; -+ -+ /* Writing type information also sets string offsets. */ -+ ctx.names = offsets; -+ ctx.semantics = &offsets[ctx.count]; -+ foreach_type(var->data_type, var->name, &var->semantic, write_fx_2_type_iter, &ctx); -+ -+ /* Now the final pass to write the string data. */ -+ ctx.names = offsets; -+ ctx.semantics = &offsets[ctx.count]; -+ foreach_type(var->data_type, var->name, &var->semantic, write_fx_2_type_strings_iter, &ctx); -+ -+ free(offsets); -+ -+ return ctx.offset; - } - - static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) -@@ -1623,6 +1701,15 @@ static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_contex - set_u32(buffer, pass_count_offset, count); - } - -+/* Effects represent bool values as 1/0, as opposed to ~0u/0 as used by -+ * Direct3D shader model 4+. */ -+static uint32_t get_fx_default_numeric_value(const struct hlsl_type *type, uint32_t value) -+{ -+ if (type->e.numeric.type == HLSL_TYPE_BOOL) -+ return !!value; -+ return value; -+} -+ - static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hlsl_default_value *value, - struct fx_write_context *fx) - { -@@ -1656,7 +1743,7 @@ static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hl - - for (j = 0; j < comp_count; ++j) - { -- put_u32(buffer, value->number.u); -+ put_u32(buffer, get_fx_default_numeric_value(type, value->number.u)); - value++; - } - break; -@@ -1673,8 +1760,8 @@ static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hl - - for (j = 0; j < type->e.record.field_count; ++j) - { -- write_fx_2_default_value(fields[i].type, value, fx); -- value += hlsl_type_component_count(fields[i].type); -+ write_fx_2_default_value(fields[j].type, value, fx); -+ value += hlsl_type_component_count(fields[j].type); - } - break; - } -@@ -1861,7 +1948,7 @@ static void write_fx_2_parameters(struct fx_write_context *fx) - if (!is_type_supported_fx_2(ctx, var->data_type, &var->loc)) - continue; - -- desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, var->is_combined_sampler, fx); -+ desc_offset = write_fx_2_parameter(var, fx); - value_offset = write_fx_2_initial_value(var, fx); - - flags = 0; -@@ -1884,7 +1971,7 @@ static void write_fx_2_annotation(struct hlsl_ir_var *var, struct fx_write_conte - struct vkd3d_bytecode_buffer *buffer = &fx->structured; - uint32_t desc_offset, value_offset; - -- desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, var->is_combined_sampler, fx); -+ desc_offset = write_fx_2_parameter(var, fx); - value_offset = write_fx_2_initial_value(var, fx); - - put_u32(buffer, desc_offset); -@@ -2001,7 +2088,7 @@ static uint32_t write_fx_4_default_value(struct hlsl_type *value_type, struct hl - - for (j = 0; j < comp_count; ++j) - { -- put_u32_unaligned(buffer, value->number.u); -+ put_u32_unaligned(buffer, get_fx_default_numeric_value(type, value->number.u)); - value++; - } - break; -@@ -2018,8 +2105,8 @@ static uint32_t write_fx_4_default_value(struct hlsl_type *value_type, struct hl - - for (j = 0; j < type->e.record.field_count; ++j) - { -- write_fx_4_default_value(fields[i].type, value, fx); -- value += hlsl_type_component_count(fields[i].type); -+ write_fx_4_default_value(fields[j].type, value, fx); -+ value += hlsl_type_component_count(fields[j].type); - } - break; - } -@@ -2057,13 +2144,9 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, st - struct vkd3d_bytecode_buffer *buffer = &fx->structured; - uint32_t name_offset, type_offset, value_offset; - uint32_t semantic_offset, flags = 0; -- enum fx_4_numeric_variable_flags -- { -- HAS_EXPLICIT_BIND_POINT = 0x4, -- }; - - if (var->has_explicit_bind_point) -- flags |= HAS_EXPLICIT_BIND_POINT; -+ flags |= FX_4_HAS_EXPLICIT_BIND_POINT; - - type_offset = write_type(var->data_type, fx); - name_offset = write_string(var->name, fx); -@@ -3212,6 +3295,8 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx - size = 0; - LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) - { -+ uint32_t unpacked_size; -+ - if (!is_numeric_fx_4_type(var->data_type)) - continue; - -@@ -3219,7 +3304,9 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx - continue; - - write_fx_4_numeric_variable(var, shared, fx); -- size += get_fx_4_type_size(var->data_type); -+ -+ unpacked_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float); -+ size = max(size, unpacked_size + var->buffer_offset * 4); - ++count; - } - -@@ -3572,20 +3659,43 @@ static void parse_fx_print_indent(struct fx_parser *parser) - vkd3d_string_buffer_printf(&parser->buffer, "%*s", 4 * parser->indent, ""); - } - --static const char *fx_2_get_string(struct fx_parser *parser, uint32_t offset, uint32_t *size) -+static void fx_2_print_string_literal(struct fx_parser *parser, const char *prefix, -+ const char *s, uint32_t max_len, const char *suffix) - { -- const char *ptr; -+ uint32_t len; -+ -+ if (s) -+ len = strnlen(s, max_len); -+ if (!s || len == max_len) -+ { -+ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, "Failed to parse a string entry."); -+ return; -+ } -+ -+ vkd3d_string_buffer_printf(&parser->buffer, "%s", prefix); -+ vkd3d_string_buffer_print_string_escaped(&parser->buffer, s, len); -+ vkd3d_string_buffer_printf(&parser->buffer, "%s", suffix); -+} - -- fx_parser_read_unstructured(parser, size, offset, sizeof(*size)); -- ptr = fx_parser_get_unstructured_ptr(parser, offset + 4, *size); -+static void fx_2_parse_string_literal(struct fx_parser *parser, uint32_t offset, -+ bool unstructured, const char *prefix, const char *suffix) -+{ -+ uint32_t max_len; -+ const char *s; - -- if (!ptr) -+ if (unstructured) - { -- parser->failed = true; -- return ""; -+ fx_parser_read_unstructured(parser, &max_len, offset, sizeof(max_len)); -+ s = fx_parser_get_unstructured_ptr(parser, offset + 4, max_len); -+ } -+ else -+ { -+ max_len = fx_parser_read_u32(parser); -+ s = fx_parser_get_ptr(parser, max_len); -+ fx_parser_skip(parser, align(max_len, 4)); - } - -- return ptr; -+ fx_2_print_string_literal(parser, prefix, s, max_len, suffix); - } - - static unsigned int fx_get_fx_2_type_size(struct fx_parser *parser, uint32_t *offset) -@@ -3742,15 +3852,12 @@ static void fx_parse_fx_2_parameter(struct fx_parser *parser, uint32_t offset) - uint32_t semantic; - uint32_t element_count; - } var; -- const char *name; -- uint32_t size; - - fx_parser_read_unstructured(parser, &var, offset, sizeof(var)); - - fx_parse_fx_2_type(parser, offset); - -- name = fx_2_get_string(parser, var.name, &size); -- fx_print_string(&parser->buffer, " ", name, size); -+ fx_2_parse_string_literal(parser, var.name, true, " ", ""); - if (var.element_count) - vkd3d_string_buffer_printf(&parser->buffer, "[%u]", var.element_count); - } -@@ -3764,7 +3871,8 @@ static bool is_fx_2_sampler(uint32_t type) - || type == D3DXPT_SAMPLERCUBE; - } - --static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_assignment *entry); -+static void fx_parse_fx_2_assignment(struct fx_parser *parser, enum hlsl_type_class container, -+ const struct fx_assignment *entry); - - static void parse_fx_2_sampler(struct fx_parser *parser, uint32_t element_count, - uint32_t offset) -@@ -3789,7 +3897,7 @@ static void parse_fx_2_sampler(struct fx_parser *parser, uint32_t element_count, - fx_parser_read_unstructured(parser, &entry, offset, sizeof(entry)); - - parse_fx_print_indent(parser); -- fx_parse_fx_2_assignment(parser, &entry); -+ fx_parse_fx_2_assignment(parser, HLSL_CLASS_SAMPLER, &entry); - } - parse_fx_end_indent(parser); - parse_fx_print_indent(parser); -@@ -3867,15 +3975,29 @@ static void fx_parse_fx_2_annotations(struct fx_parser *parser, uint32_t count) - vkd3d_string_buffer_printf(&parser->buffer, ">"); - } - --static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_assignment *entry) -+static const struct fx_2_state *fx_2_get_state_by_id(enum hlsl_type_class container, uint32_t id) -+{ -+ const struct fx_2_state *table; -+ unsigned int count; -+ -+ count = container == HLSL_CLASS_PASS ? ARRAY_SIZE(fx_2_pass_states) : ARRAY_SIZE(fx_2_sampler_states); -+ table = container == HLSL_CLASS_PASS ? fx_2_pass_states : fx_2_sampler_states; -+ -+ /* State identifiers are sequential, no gaps */ -+ if (id >= table[0].id && id <= table[count - 1].id) -+ return &table[id - table[0].id]; -+ -+ return NULL; -+} -+ -+static void fx_parse_fx_2_assignment(struct fx_parser *parser, enum hlsl_type_class container, -+ const struct fx_assignment *entry) - { - const struct rhs_named_value *named_value = NULL; -- const struct fx_2_state *state = NULL; -+ const struct fx_2_state *state; - -- if (entry->id <= ARRAY_SIZE(fx_2_states)) -+ if ((state = fx_2_get_state_by_id(container, entry->id))) - { -- state = &fx_2_states[entry->id]; -- - vkd3d_string_buffer_printf(&parser->buffer, "%s", state->name); - if (state->array_size > 1) - vkd3d_string_buffer_printf(&parser->buffer, "[%u]", entry->lhs_index); -@@ -3886,7 +4008,7 @@ static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_a - } - vkd3d_string_buffer_printf(&parser->buffer, " = "); - -- if (state && state->type == FX_UINT) -+ if (state && state->type == FX_UINT && state->values) - { - const struct rhs_named_value *ptr = state->values; - uint32_t value; -@@ -3910,13 +4032,14 @@ static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_a - } - else if (state) - { -- if (state->type == FX_UINT || state->type == FX_FLOAT) -+ if (state->type == FX_UINT || state->type == FX_FLOAT || state->type == FX_BOOL) - { -- uint32_t offset = entry->type; -+ uint32_t offset = entry->type, base_type; - unsigned int size; - - size = fx_get_fx_2_type_size(parser, &offset); -- parse_fx_2_numeric_value(parser, entry->value, size, entry->type); -+ fx_parser_read_unstructured(parser, &base_type, entry->type, sizeof(base_type)); -+ parse_fx_2_numeric_value(parser, entry->value, size, base_type); - } - else if (state->type == FX_VERTEXSHADER || state->type == FX_PIXELSHADER) - { -@@ -3951,18 +4074,14 @@ static void fx_parse_fx_2_technique(struct fx_parser *parser) - uint32_t annotation_count; - uint32_t assignment_count; - } pass; -- const char *name; -- uint32_t size; - - if (parser->failed) - return; - - fx_parser_read_u32s(parser, &technique, sizeof(technique)); - -- name = fx_2_get_string(parser, technique.name, &size); -- - parse_fx_print_indent(parser); -- fx_print_string(&parser->buffer, "technique ", name, size); -+ fx_2_parse_string_literal(parser, technique.name, true, "technique ", ""); - fx_parse_fx_2_annotations(parser, technique.annotation_count); - - vkd3d_string_buffer_printf(&parser->buffer, "\n"); -@@ -3973,10 +4092,9 @@ static void fx_parse_fx_2_technique(struct fx_parser *parser) - for (uint32_t i = 0; i < technique.pass_count; ++i) - { - fx_parser_read_u32s(parser, &pass, sizeof(pass)); -- name = fx_2_get_string(parser, pass.name, &size); - - parse_fx_print_indent(parser); -- fx_print_string(&parser->buffer, "pass ", name, size); -+ fx_2_parse_string_literal(parser, pass.name, true, "pass ", ""); - fx_parse_fx_2_annotations(parser, pass.annotation_count); - - vkd3d_string_buffer_printf(&parser->buffer, "\n"); -@@ -3990,7 +4108,7 @@ static void fx_parse_fx_2_technique(struct fx_parser *parser) - - parse_fx_print_indent(parser); - fx_parser_read_u32s(parser, &entry, sizeof(entry)); -- fx_parse_fx_2_assignment(parser, &entry); -+ fx_parse_fx_2_assignment(parser, HLSL_CLASS_PASS, &entry); - } - parse_fx_end_indent(parser); - -@@ -4112,8 +4230,7 @@ static void fx_parse_fx_2_data_blob(struct fx_parser *parser) - { - parse_fx_start_indent(parser); - parse_fx_print_indent(parser); -- fx_print_string(&parser->buffer, "\"", (const char *)data, size); -- vkd3d_string_buffer_printf(&parser->buffer, "\""); -+ fx_2_print_string_literal(parser, "\"", (const char *)data, size, "\""); - parse_fx_end_indent(parser); - } - else if (type == D3DXPT_PIXELSHADER || type == D3DXPT_VERTEXSHADER) -@@ -4153,20 +4270,18 @@ static void fx_dump_blob(struct fx_parser *parser, const void *blob, uint32_t si - } - } - --static void fx_parse_fx_2_array_selector(struct fx_parser *parser, uint32_t size) -+static void fx_2_parse_fxlvm_expression(struct fx_parser *parser, const uint32_t *blob, uint32_t size); -+ -+static void fx_parse_fx_2_array_selector(struct fx_parser *parser) - { -- const uint8_t *end = parser->ptr + size; -- uint32_t name_size, blob_size = 0; -+ uint32_t size, blob_size = 0; - const void *blob = NULL; -- const char *name; -+ const uint8_t *end; - -- name_size = fx_parser_read_u32(parser); -- name = fx_parser_get_ptr(parser, name_size); -- fx_parser_skip(parser, name_size); -+ size = fx_parser_read_u32(parser); -+ end = parser->ptr + size; - -- if (!name || (uint8_t *)name >= end) -- fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, -- "Malformed name entry in the array selector."); -+ fx_2_parse_string_literal(parser, 0, false, "array \"", "\"\n"); - - if (parser->ptr <= end) - { -@@ -4180,16 +4295,11 @@ static void fx_parse_fx_2_array_selector(struct fx_parser *parser, uint32_t size - "Malformed blob entry in the array selector."); - } - -- if (name) -- { -- fx_print_string(&parser->buffer, "array \"", name, name_size); -- vkd3d_string_buffer_printf(&parser->buffer, "\"\n"); -- } - if (blob) - { - parse_fx_print_indent(parser); - vkd3d_string_buffer_printf(&parser->buffer, "selector blob size %u\n", blob_size); -- fx_dump_blob(parser, blob, blob_size); -+ fx_2_parse_fxlvm_expression(parser, blob, blob_size); - } - } - -@@ -4219,23 +4329,19 @@ static void fx_parse_fx_2_complex_state(struct fx_parser *parser) - state.technique, state.index, state.state); - } - -- size = fx_parser_read_u32(parser); -- - parse_fx_print_indent(parser); - - if (state.assignment_type == FX_2_ASSIGNMENT_PARAMETER) - { -- data = fx_parser_get_ptr(parser, size); -- fx_print_string(&parser->buffer, "parameter \"", data, size); -- vkd3d_string_buffer_printf(&parser->buffer, "\"\n"); -- fx_parser_skip(parser, align(size, 4)); -+ fx_2_parse_string_literal(parser, 0, false, "parameter \"", "\"\n"); - } - else if (state.assignment_type == FX_2_ASSIGNMENT_ARRAY_SELECTOR) - { -- fx_parse_fx_2_array_selector(parser, size); -+ fx_parse_fx_2_array_selector(parser); - } - else - { -+ size = fx_parser_read_u32(parser); - vkd3d_string_buffer_printf(&parser->buffer, "blob size %u\n", size); - data = fx_parser_get_ptr(parser, size); - fx_dump_blob(parser, data, size); -@@ -4457,6 +4563,11 @@ static void fx_parse_fx_4_numeric_variables(struct fx_parser *parser, uint32_t c - semantic = fx_4_get_string(parser, var.semantic); - vkd3d_string_buffer_printf(&parser->buffer, " : %s", semantic); - } -+ if (var.flags & FX_4_HAS_EXPLICIT_BIND_POINT) -+ { -+ vkd3d_string_buffer_printf(&parser->buffer, " : packoffset(c%u.%c)", -+ var.offset / 16, "xyzw"[(var.offset % 16) / 4]); -+ } - fx_parse_fx_4_annotations(parser); - - if (var.value) -@@ -4492,6 +4603,8 @@ static void fx_parse_buffers(struct fx_parser *parser) - name = fx_4_get_string(parser, buffer.name); - - vkd3d_string_buffer_printf(&parser->buffer, "cbuffer %s", name); -+ if (buffer.bind_point != ~0u) -+ vkd3d_string_buffer_printf(&parser->buffer, " : register(b%u)", buffer.bind_point); - fx_parse_fx_4_annotations(parser); - - vkd3d_string_buffer_printf(&parser->buffer, "\n{\n"); -@@ -4609,7 +4722,7 @@ static const struct - uint32_t opcode; - const char *name; - } --fx_4_fxlc_opcodes[] = -+fxlc_opcodes[] = - { - { 0x100, "mov" }, - { 0x101, "neg" }, -@@ -4634,6 +4747,8 @@ fx_4_fxlc_opcodes[] = - { 0x13a, "ceil" }, - { 0x200, "min" }, - { 0x201, "max" }, -+ { 0x202, "lt" }, -+ { 0x203, "ge" }, - { 0x204, "add" }, - { 0x205, "mul" }, - { 0x206, "atan2" }, -@@ -4662,14 +4777,14 @@ fx_4_fxlc_opcodes[] = - { 0x70e, "d3ds_dotswiz" }, - }; - --static const char *fx_4_get_fxlc_opcode_name(uint32_t opcode) -+static const char *get_fxlc_opcode_name(uint32_t opcode) - { - size_t i; - -- for (i = 0; i < ARRAY_SIZE(fx_4_fxlc_opcodes); ++i) -+ for (i = 0; i < ARRAY_SIZE(fxlc_opcodes); ++i) - { -- if (fx_4_fxlc_opcodes[i].opcode == opcode) -- return fx_4_fxlc_opcodes[i].name; -+ if (fxlc_opcodes[i].opcode == opcode) -+ return fxlc_opcodes[i].name; - } - - return ""; -@@ -4693,10 +4808,29 @@ struct fx_4_ctab_entry - uint32_t default_value; - }; - -+struct fxlc_arg -+{ -+ uint32_t reg_type; -+ uint32_t address; -+ bool indexed; -+ struct -+ { -+ uint32_t reg_type; -+ uint32_t address; -+ } index; -+}; -+ - struct fxlvm_code - { -- const float *cli4; -- uint32_t cli4_count; -+ const uint32_t *ptr, *end; -+ bool failed; -+ -+ union -+ { -+ const float *_4; -+ const double *_8; -+ } cli; -+ uint32_t cli_count; - - const struct fx_4_ctab_entry *constants; - uint32_t ctab_offset; -@@ -4707,7 +4841,45 @@ struct fxlvm_code - bool scalar; - }; - --static void fx_4_parse_print_swizzle(struct fx_parser *parser, const struct fxlvm_code *code, unsigned int addr) -+static uint32_t fxlvm_read_u32(struct fxlvm_code *code) -+{ -+ if (code->end == code->ptr) -+ { -+ code->failed = true; -+ return 0; -+ } -+ -+ return *code->ptr++; -+} -+ -+static const uint32_t *find_d3dbc_section(const uint32_t *ptr, uint32_t count, uint32_t tag, uint32_t *size) -+{ -+ if (!count) -+ return NULL; -+ -+ /* Skip version tag */ -+ ptr++; -+ count--; -+ -+ while (count > 2 && (*ptr & 0xffff) == 0xfffe) -+ { -+ unsigned int section_size; -+ -+ section_size = (*ptr >> 16); -+ if (!section_size || section_size + 1 > count) -+ break; -+ if (*(ptr + 1) == tag) -+ { -+ *size = section_size; -+ return ptr + 2; -+ } -+ count -= section_size + 1; -+ ptr += section_size + 1; -+ } -+ return NULL; -+} -+ -+static void fx_parse_print_swizzle(struct fx_parser *parser, const struct fxlvm_code *code, unsigned int addr) - { - unsigned int comp_count = code->scalar ? 1 : code->comp_count; - static const char comp[] = "xyzw"; -@@ -4716,44 +4888,76 @@ static void fx_4_parse_print_swizzle(struct fx_parser *parser, const struct fxlv - vkd3d_string_buffer_printf(&parser->buffer, ".%.*s", comp_count, &comp[addr % 4]); - } - --static void fx_4_parse_fxlc_constant_argument(struct fx_parser *parser, -- const struct fx_4_fxlc_argument *arg, const struct fxlvm_code *code) -+static void fx_parse_fxlc_constant_argument(struct fx_parser *parser, -+ const struct fxlc_arg *arg, const struct fxlvm_code *code) - { -- uint32_t i, offset, register_index = arg->address / 4; /* Address counts in components. */ -+ uint32_t register_index = arg->address / 4; /* Address counts in components. */ - -- for (i = 0; i < code->ctab_count; ++i) -+ if (code->ctab_count) - { -- const struct fx_4_ctab_entry *c = &code->constants[i]; -+ uint32_t i, offset; - -- if (register_index < c->register_index || register_index - c->register_index >= c->register_count) -- continue; -+ for (i = 0; i < code->ctab_count; ++i) -+ { -+ const struct fx_4_ctab_entry *c = &code->constants[i]; - -- vkd3d_string_buffer_printf(&parser->buffer, "%s", &code->ctab[c->name]); -+ if (register_index < c->register_index || register_index - c->register_index >= c->register_count) -+ continue; - -- /* Register offset within variable */ -- offset = arg->address - c->register_index * 4; -+ vkd3d_string_buffer_printf(&parser->buffer, "%s", &code->ctab[c->name]); - -- if (offset / 4) -- vkd3d_string_buffer_printf(&parser->buffer, "[%u]", offset / 4); -- fx_4_parse_print_swizzle(parser, code, offset); -- return; -+ /* Register offset within variable */ -+ offset = arg->address - c->register_index * 4; -+ -+ if (offset / 4) -+ vkd3d_string_buffer_printf(&parser->buffer, "[%u]", offset / 4); -+ fx_parse_print_swizzle(parser, code, offset); -+ return; -+ } -+ -+ vkd3d_string_buffer_printf(&parser->buffer, "(var-not-found)"); -+ } -+ else -+ { -+ vkd3d_string_buffer_printf(&parser->buffer, "c%u", register_index); -+ fx_parse_print_swizzle(parser, code, arg->address); -+ } -+} -+ -+static void fx_parse_fxlc_argument(struct fx_parser *parser, struct fxlc_arg *arg, struct fxlvm_code *code) -+{ -+ uint32_t flags; -+ -+ memset(arg, 0, sizeof(*arg)); -+ -+ flags = fxlvm_read_u32(code); -+ if (flags) -+ { -+ arg->indexed = true; -+ arg->index.reg_type = fxlvm_read_u32(code); -+ arg->index.address = fxlvm_read_u32(code); - } -+ arg->reg_type = fxlvm_read_u32(code); -+ arg->address = fxlvm_read_u32(code); -+} - -- vkd3d_string_buffer_printf(&parser->buffer, "(var-not-found)"); -+static void fx_print_fxlc_literal(struct fx_parser *parser, uint32_t address, struct fxlvm_code *code) -+{ -+ if (parser->version.major >= 4) -+ vkd3d_string_buffer_print_f32(&parser->buffer, code->cli._4[address]); -+ else -+ vkd3d_string_buffer_print_f64(&parser->buffer, code->cli._8[address]); - } - --static void fx_4_parse_fxlc_argument(struct fx_parser *parser, uint32_t offset, const struct fxlvm_code *code) -+static void fx_print_fxlc_argument(struct fx_parser *parser, const struct fxlc_arg *arg, struct fxlvm_code *code) - { -- struct fx_4_fxlc_argument arg; - uint32_t count; - -- fx_parser_read_unstructured(parser, &arg, offset, sizeof(arg)); -- -- switch (arg.reg_type) -+ switch (arg->reg_type) - { -- case FX_4_FXLC_REG_LITERAL: -+ case FX_FXLC_REG_LITERAL: - count = code->scalar ? 1 : code->comp_count; -- if (arg.address >= code->cli4_count || count > code->cli4_count - arg.address) -+ if (arg->address >= code->cli_count || count > code->cli_count - arg->address) - { - vkd3d_string_buffer_printf(&parser->buffer, "()"); - parser->failed = true; -@@ -4761,42 +4965,120 @@ static void fx_4_parse_fxlc_argument(struct fx_parser *parser, uint32_t offset, - } - - vkd3d_string_buffer_printf(&parser->buffer, "("); -- vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg.address]); -+ fx_print_fxlc_literal(parser, arg->address, code); - for (unsigned int i = 1; i < code->comp_count; ++i) - { - vkd3d_string_buffer_printf(&parser->buffer, ", "); -- vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg.address + (code->scalar ? 0 : i)]); -+ fx_print_fxlc_literal(parser, arg->address + (code->scalar ? 0 : i), code); - } - vkd3d_string_buffer_printf(&parser->buffer, ")"); - break; - -- case FX_4_FXLC_REG_CB: -- fx_4_parse_fxlc_constant_argument(parser, &arg, code); -+ case FX_FXLC_REG_CB: -+ fx_parse_fxlc_constant_argument(parser, arg, code); - break; - -- case FX_4_FXLC_REG_OUTPUT: -- case FX_4_FXLC_REG_TEMP: -- if (arg.reg_type == FX_4_FXLC_REG_OUTPUT) -+ case FX_FXLC_REG_OUTPUT: -+ case FX_FXLC_REG_TEMP: -+ if (arg->reg_type == FX_FXLC_REG_OUTPUT) - vkd3d_string_buffer_printf(&parser->buffer, "expr"); - else -- vkd3d_string_buffer_printf(&parser->buffer, "r%u", arg.address / 4); -- fx_4_parse_print_swizzle(parser, code, arg.address); -+ vkd3d_string_buffer_printf(&parser->buffer, "r%u", arg->address / 4); -+ fx_parse_print_swizzle(parser, code, arg->address); - break; - - default: -- vkd3d_string_buffer_printf(&parser->buffer, "", arg.reg_type); -+ vkd3d_string_buffer_printf(&parser->buffer, "", arg->reg_type); - break; - } - } - -+static void fx_parse_fxlvm_expression(struct fx_parser *parser, struct fxlvm_code *code) -+{ -+ struct fxlc_arg args[9]; -+ uint32_t ins_count; -+ size_t i, j; -+ -+ ins_count = fxlvm_read_u32(code); -+ -+ parse_fx_start_indent(parser); -+ -+ for (i = 0; i < ins_count; ++i) -+ { -+ uint32_t instr, opcode, src_count; -+ -+ instr = fxlvm_read_u32(code); -+ src_count = fxlvm_read_u32(code); -+ -+ if (src_count >= ARRAY_SIZE(args)) -+ { -+ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, -+ "Unexpected instruction source count %u.", src_count); -+ break; -+ } -+ -+ /* Sources entries are followed by the destination, first read them all. -+ Output format is "opcode dst, src[0]...src[n]". */ -+ for (j = 0; j < src_count; ++j) -+ fx_parse_fxlc_argument(parser, &args[j], code); -+ fx_parse_fxlc_argument(parser, &args[src_count], code); -+ -+ opcode = (instr >> FX_FXLC_OPCODE_SHIFT) & FX_FXLC_OPCODE_MASK; -+ code->comp_count = instr & FX_FXLC_COMP_COUNT_MASK; -+ -+ parse_fx_print_indent(parser); -+ vkd3d_string_buffer_printf(&parser->buffer, "%s ", get_fxlc_opcode_name(opcode)); -+ -+ code->scalar = false; -+ fx_print_fxlc_argument(parser, &args[src_count], code); -+ vkd3d_string_buffer_printf(&parser->buffer, ", "); -+ -+ for (j = 0; j < src_count; ++j) -+ { -+ /* Scalar modifier applies only to the first source. */ -+ code->scalar = j == 0 && !!(instr & FX_FXLC_IS_SCALAR_MASK); -+ fx_print_fxlc_argument(parser, &args[j], code); -+ if (j < src_count - 1) -+ vkd3d_string_buffer_printf(&parser->buffer, ", "); -+ } -+ -+ vkd3d_string_buffer_printf(&parser->buffer, "\n"); -+ } -+ -+ parse_fx_end_indent(parser); -+} -+ -+static void fx_2_parse_fxlvm_expression(struct fx_parser *parser, const uint32_t *blob, uint32_t size) -+{ -+ uint32_t count = size / sizeof(uint32_t); -+ struct fxlvm_code code = { 0 }; -+ uint32_t section_size; -+ const uint32_t *data; -+ -+ /* Literal constants, using 64-bit floats. */ -+ if ((data = find_d3dbc_section(blob, count, TAG_CLIT, §ion_size))) -+ { -+ code.cli_count = *data++; -+ code.cli._8 = (const double *)data; -+ } -+ -+ /* CTAB does not contain variable names */ -+ -+ /* Code blob */ -+ code.ptr = find_d3dbc_section(blob, count, TAG_FXLC, &count); -+ code.end = code.ptr + count; -+ -+ fx_parse_fxlvm_expression(parser, &code); -+} -+ - static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offset) - { - struct vkd3d_shader_dxbc_section_desc *section, fxlc, cli4, ctab; - struct vkd3d_shader_dxbc_desc dxbc_desc; -+ struct fxlvm_code code = { 0 }; - struct vkd3d_shader_code dxbc; -- uint32_t size, ins_count; -- struct fxlvm_code code; -- size_t i, j; -+ uint32_t size; -+ size_t i; - - offset = fx_parser_read_unstructured(parser, &size, offset, sizeof(size)); - -@@ -4832,8 +5114,8 @@ static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offse - { - uint32_t cli4_offset = offset + (size_t)cli4.data.code - (size_t)dxbc.code; - -- fx_parser_read_unstructured(parser, &code.cli4_count, cli4_offset, sizeof(code.cli4_count)); -- code.cli4 = fx_parser_get_unstructured_ptr(parser, cli4_offset + 4, code.cli4_count * sizeof(float)); -+ fx_parser_read_unstructured(parser, &code.cli_count, cli4_offset, sizeof(code.cli_count)); -+ code.cli._4 = fx_parser_get_unstructured_ptr(parser, cli4_offset + 4, code.cli_count * sizeof(float)); - } - - if (ctab.data.code) -@@ -4849,47 +5131,10 @@ static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offse - ctab_offset + consts_offset, code.ctab_count * sizeof(*code.constants)); - } - -- offset += (size_t)fxlc.data.code - (size_t)dxbc.code; -- offset = fx_parser_read_unstructured(parser, &ins_count, offset, sizeof(ins_count)); -- -- parse_fx_start_indent(parser); -+ code.ptr = fxlc.data.code; -+ code.end = (uint32_t *)((uint8_t *)fxlc.data.code + fxlc.data.size); - -- for (i = 0; i < ins_count; ++i) -- { -- uint32_t instr, opcode, src_count; -- struct fx_4_fxlc_argument arg; -- -- offset = fx_parser_read_unstructured(parser, &instr, offset, sizeof(instr)); -- offset = fx_parser_read_unstructured(parser, &src_count, offset, sizeof(src_count)); -- -- opcode = (instr >> FX_4_FXLC_OPCODE_SHIFT) & FX_4_FXLC_OPCODE_MASK; -- code.comp_count = instr & FX_4_FXLC_COMP_COUNT_MASK; -- code.scalar = false; -- -- parse_fx_print_indent(parser); -- vkd3d_string_buffer_printf(&parser->buffer, "%s ", fx_4_get_fxlc_opcode_name(opcode)); -- -- /* Destination first. */ -- fx_4_parse_fxlc_argument(parser, offset + sizeof(arg) * src_count, &code); -- -- for (j = 0; j < src_count; ++j) -- { -- vkd3d_string_buffer_printf(&parser->buffer, ", "); -- -- /* Scalar modifier applies only to first source. */ -- code.scalar = j == 0 && !!(instr & FX_4_FXLC_IS_SCALAR_MASK); -- fx_4_parse_fxlc_argument(parser, offset, &code); -- -- offset += sizeof(arg); -- } -- -- /* Destination */ -- offset += sizeof(arg); -- -- vkd3d_string_buffer_printf(&parser->buffer, "\n"); -- } -- -- parse_fx_end_indent(parser); -+ fx_parse_fxlvm_expression(parser, &code); - } - - static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32_t count, -diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index e4497b9ac5b..214632c00eb 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/glsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -421,6 +421,9 @@ static void shader_glsl_print_src(struct vkd3d_string_buffer *buffer, struct vkd - case VKD3DSPSM_ABS: - vkd3d_string_buffer_printf(buffer, "abs(%s)", str->buffer); - break; -+ case VKD3DSPSM_ABSNEG: -+ vkd3d_string_buffer_printf(buffer, "-abs(%s)", str->buffer); -+ break; - default: - vkd3d_string_buffer_printf(buffer, "(%s)", - vsir_src->modifiers, str->buffer); -@@ -495,6 +498,9 @@ static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_g - uint32_t modifiers = dst->vsir->modifiers; - bool close = true; - -+ /* It is always legitimate to ignore _pp. */ -+ modifiers &= ~VKD3DSPDM_PARTIALPRECISION; -+ - if (dst->vsir->shift) - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled destination shift %#x.", dst->vsir->shift); -@@ -555,10 +561,12 @@ static void VKD3D_PRINTF_FUNC(4, 5) shader_glsl_print_assignment_ext(struct vkd3 - - static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) - { -+ const char *name = vsir_opcode_get_name(ins->opcode, ""); -+ - shader_glsl_print_indent(gen->buffer, gen->indent); -- vkd3d_string_buffer_printf(gen->buffer, "/* */\n", ins->opcode); -+ vkd3d_string_buffer_printf(gen->buffer, "/* */\n", name, ins->opcode); - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -- "Internal compiler error: Unhandled instruction %#x.", ins->opcode); -+ "Internal compiler error: Unhandled instruction \"%s\" (%#x).", name, ins->opcode); - } - - static void shader_glsl_binop(struct vkd3d_glsl_generator *gen, -@@ -2313,7 +2321,7 @@ static void shader_glsl_handle_global_flags(struct vkd3d_string_buffer *buffer, - flags &= ~VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL; - } - -- if (flags) -+ if (flags & ~VKD3DSGF_REFACTORING_ALLOWED) - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled global flags %#"PRIx64".", (uint64_t)flags); - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index 58f579cd9f9..63c9733ec7b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -245,6 +245,7 @@ struct hlsl_semantic - { - const char *name; - uint32_t index; -+ uint32_t stream_index; - - /* Name exactly as it appears in the sources. */ - const char *raw_name; -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index 5aee1e701cd..bad9d33094b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -2559,6 +2559,9 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, - "Variable '%s' is declared as both \"uniform\" and \"static\".", var->name); - -+ if (modifiers & HLSL_STORAGE_GROUPSHARED) -+ hlsl_fixme(ctx, &var->loc, "Group shared variables."); -+ - /* Mark it as uniform. We need to do this here since synthetic - * variables also get put in the global scope, but shouldn't be - * considered uniforms, and we have no way of telling otherwise. */ -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 38d5c55c26b..d4e29e16b7c 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -288,7 +288,8 @@ 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_function_decl *func, - struct hlsl_ir_var *var, struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic, -- uint32_t index, bool output, bool force_align, bool create, const struct vkd3d_shader_location *loc) -+ uint32_t index, uint32_t stream_index, bool output, bool force_align, bool create, -+ const struct vkd3d_shader_location *loc) - { - struct hlsl_semantic new_semantic; - struct hlsl_ir_var *ext_var; -@@ -300,7 +301,12 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir - else - prefix = output ? "output" : "input"; - -- if (!(new_name = hlsl_sprintf_alloc(ctx, "<%s-%s%u>", prefix, semantic->name, index))) -+ if (stream_index) -+ new_name = hlsl_sprintf_alloc(ctx, "<%s-m%u:%s%u>", prefix, stream_index, semantic->name, index); -+ else -+ new_name = hlsl_sprintf_alloc(ctx, "<%s-%s%u>", prefix, semantic->name, index); -+ -+ if (!new_name) - return NULL; - - LIST_FOR_EACH_ENTRY(ext_var, &func->extern_vars, struct hlsl_ir_var, extern_entry) -@@ -353,6 +359,7 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir - return NULL; - } - new_semantic.index = index; -+ new_semantic.stream_index = stream_index; - if (!(ext_var = hlsl_new_var(ctx, new_name, type, loc, &new_semantic, modifiers, NULL))) - { - vkd3d_free(new_name); -@@ -435,7 +442,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec - prim_type_src->modifiers = var->data_type->modifiers & HLSL_PRIMITIVE_MODIFIERS_MASK; - - if (!(input = add_semantic_var(ctx, func, var, prim_type_src, -- modifiers, semantic, semantic_index + i, false, force_align, true, loc))) -+ modifiers, semantic, semantic_index + i, 0, false, force_align, true, loc))) - return; - hlsl_init_simple_deref_from_var(&prim_deref, input); - -@@ -448,7 +455,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec - else - { - if (!(input = add_semantic_var(ctx, func, var, vector_type_src, -- modifiers, semantic, semantic_index + i, false, force_align, true, loc))) -+ modifiers, semantic, semantic_index + i, 0, false, force_align, true, loc))) - return; - - if (!(load = hlsl_new_var_load(ctx, input, &var->loc))) -@@ -558,7 +565,7 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function - - static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, - struct hlsl_ir_function_decl *func, struct hlsl_ir_load *rhs, uint32_t modifiers, -- struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align, bool create) -+ struct hlsl_semantic *semantic, uint32_t semantic_index, uint32_t stream_index, bool force_align, bool create) - { - struct hlsl_type *type = rhs->node.data_type, *vector_type; - struct vkd3d_shader_location *loc = &rhs->node.loc; -@@ -588,7 +595,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, - struct hlsl_ir_node *load; - - if (!(output = add_semantic_var(ctx, func, var, vector_type, -- modifiers, semantic, semantic_index + i, true, force_align, create, loc))) -+ modifiers, semantic, semantic_index + i, stream_index, true, force_align, create, loc))) - return; - - if (type->class == HLSL_CLASS_MATRIX) -@@ -609,7 +616,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, - - static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, - struct hlsl_ir_function_decl *func, const struct hlsl_type *type, struct hlsl_ir_load *rhs, uint32_t modifiers, -- struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align, bool create) -+ struct hlsl_semantic *semantic, uint32_t semantic_index, uint32_t stream_index, bool force_align, bool create) - { - struct vkd3d_shader_location *loc = &rhs->node.loc; - struct hlsl_ir_var *var = rhs->src.var; -@@ -654,12 +661,13 @@ static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * - hlsl_block_add_instr(block, &element_load->node); - - append_output_copy_recurse(ctx, block, func, element_type, element_load, element_modifiers, semantic, -- elem_semantic_index, force_align, create); -+ elem_semantic_index, stream_index, force_align, create); - } - } - else - { -- append_output_copy(ctx, block, func, rhs, modifiers, semantic, semantic_index, force_align, create); -+ append_output_copy(ctx, block, func, rhs, modifiers, semantic, -+ semantic_index, stream_index, force_align, create); - } - } - -@@ -676,7 +684,7 @@ static void append_output_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function - hlsl_block_add_instr(&func->body, &load->node); - - append_output_copy_recurse(ctx, &func->body, func, var->data_type, load, var->storage_modifiers, -- &var->semantic, var->semantic.index, false, true); -+ &var->semantic, var->semantic.index, 0, false, true); - } - - bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), -@@ -3360,7 +3368,7 @@ static bool split_struct_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr - struct stream_append_ctx - { - struct hlsl_ir_function_decl *func; -- bool created; -+ bool created[VKD3D_MAX_STREAM_COUNT]; - }; - - static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) -@@ -3371,6 +3379,7 @@ static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst - const struct hlsl_type *type; - struct hlsl_ir_var *var; - struct hlsl_block block; -+ uint32_t stream_index; - - if (instr->type != HLSL_IR_RESOURCE_STORE) - return false; -@@ -3390,18 +3399,17 @@ static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst - } - - VKD3D_ASSERT(var->regs[HLSL_REGSET_STREAM_OUTPUTS].allocated); -+ stream_index = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; - -- if (var->regs[HLSL_REGSET_STREAM_OUTPUTS].index) -- { -- hlsl_fixme(ctx, &instr->loc, "Append to an output stream with a nonzero stream index."); -- return false; -- } -+ VKD3D_ASSERT(stream_index < ARRAY_SIZE(append_ctx->created)); - - hlsl_block_init(&block); - -- append_output_copy_recurse(ctx, &block, append_ctx->func, type->e.so.type, hlsl_ir_load(rhs), var->storage_modifiers, -- &var->semantic, var->semantic.index, false, !append_ctx->created); -- append_ctx->created = true; -+ append_output_copy_recurse(ctx, &block, append_ctx->func, type->e.so.type, hlsl_ir_load(rhs), -+ var->storage_modifiers, &var->semantic, var->semantic.index, -+ var->regs[HLSL_REGSET_STREAM_OUTPUTS].index, false, !append_ctx->created[stream_index]); -+ -+ append_ctx->created[stream_index] = true; - - list_move_before(&instr->entry, &block.instrs); - hlsl_src_remove(&store->value); -@@ -3919,7 +3927,7 @@ static bool lower_separate_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *in - if (load->texel_offset.node) - { - hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, -- "Texel offsets are not supported on profiles lower than 4.0.\n"); -+ "Texel offsets are not supported on profiles lower than 4.0."); - return false; - } - -@@ -5754,7 +5762,7 @@ static const char *debug_register(char class, struct hlsl_reg reg, const struct - static const char writemask_offset[] = {'w','x','y','z'}; - unsigned int reg_size = type->reg_size[HLSL_REGSET_NUMERIC]; - -- if (reg_size > 4) -+ if (reg_size > 4 && !hlsl_type_is_patch_array(type)) - { - if (reg_size & 3) - return vkd3d_dbg_sprintf("%c%u-%c%u.%c", class, reg.id, class, reg.id + (reg_size / 4), -@@ -6456,6 +6464,8 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var - - if ((!output && !var->last_read) || (output && !var->first_write)) - return; -+ -+ optimize = false; - } - else - { -@@ -6518,8 +6528,8 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var - static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, - uint32_t *output_reg_count) - { -+ struct register_allocator input_allocator = {0}, output_allocators[VKD3D_MAX_STREAM_COUNT] = {{0}}; - struct register_allocator in_prim_allocator = {0}, patch_constant_out_patch_allocator = {0}; -- struct register_allocator input_allocator = {0}, output_allocator = {0}; - bool is_vertex_shader = ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX; - bool is_pixel_shader = ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL; - struct hlsl_ir_var *var; -@@ -6527,7 +6537,8 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun - in_prim_allocator.prioritize_smaller_writemasks = true; - patch_constant_out_patch_allocator.prioritize_smaller_writemasks = true; - input_allocator.prioritize_smaller_writemasks = true; -- output_allocator.prioritize_smaller_writemasks = true; -+ for (unsigned int i = 0; i < ARRAY_SIZE(output_allocators); ++i) -+ output_allocators[i].prioritize_smaller_writemasks = true; - - LIST_FOR_EACH_ENTRY(var, &entry_func->extern_vars, struct hlsl_ir_var, extern_entry) - { -@@ -6550,15 +6561,22 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun - } - - if (var->is_output_semantic) -- allocate_semantic_register(ctx, var, &output_allocator, true, !is_pixel_shader); -+ { -+ VKD3D_ASSERT(var->semantic.stream_index < ARRAY_SIZE(output_allocators)); -+ allocate_semantic_register(ctx, var, &output_allocators[var->semantic.stream_index], -+ true, !is_pixel_shader); -+ } - } - -- *output_reg_count = output_allocator.reg_count; -+ *output_reg_count = output_allocators[0].reg_count; -+ for (unsigned int i = 1; i < ARRAY_SIZE(output_allocators); ++i) -+ *output_reg_count = max(*output_reg_count, output_allocators[i].reg_count); - - vkd3d_free(in_prim_allocator.allocations); - vkd3d_free(patch_constant_out_patch_allocator.allocations); - vkd3d_free(input_allocator.allocations); -- vkd3d_free(output_allocator.allocations); -+ for (unsigned int i = 0; i < ARRAY_SIZE(output_allocators); ++i) -+ vkd3d_free(output_allocators[i].allocations); - } - - static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, -@@ -8018,6 +8036,7 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog - return; - } - element->semantic_index = var->semantic.index; -+ element->stream_index = var->semantic.stream_index; - element->sysval_semantic = sysval; - element->component_type = component_type; - element->register_index = register_index; -@@ -8485,6 +8504,14 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p - VKD3D_ASSERT(regset == HLSL_REGSET_SAMPLERS); - *writemask = VKD3DSP_WRITEMASK_ALL; - } -+ else if (regset == HLSL_REGSET_STREAM_OUTPUTS) -+ { -+ reg->type = VKD3DSPR_STREAM; -+ reg->dimension = VSIR_DIMENSION_NONE; -+ reg->idx[0].offset = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; -+ reg->idx_count = 1; -+ *writemask = VKD3DSP_WRITEMASK_ALL; -+ } - else - { - unsigned int offset = deref->const_offset + var->buffer_offset; -@@ -9279,16 +9306,16 @@ static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, - switch (load->load_type) - { - case HLSL_RESOURCE_SAMPLE: -- opcode = VKD3DSIH_TEX; -+ opcode = VKD3DSIH_TEXLD; - break; - - case HLSL_RESOURCE_SAMPLE_PROJ: -- opcode = VKD3DSIH_TEX; -+ opcode = VKD3DSIH_TEXLD; - flags |= VKD3DSI_TEXLD_PROJECT; - break; - - case HLSL_RESOURCE_SAMPLE_LOD_BIAS: -- opcode = VKD3DSIH_TEX; -+ opcode = VKD3DSIH_TEXLD; - flags |= VKD3DSI_TEXLD_BIAS; - break; - -@@ -9922,6 +9949,57 @@ static void sm1_generate_ctab(struct hlsl_ctx *ctx, struct vkd3d_shader_code *ct - ctab->size = buffer.size; - } - -+static enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval, -+ unsigned int index) -+{ -+ switch (sysval) -+ { -+ case VKD3D_SHADER_SV_COVERAGE: -+ case VKD3D_SHADER_SV_DEPTH: -+ case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL: -+ case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL: -+ case VKD3D_SHADER_SV_NONE: -+ case VKD3D_SHADER_SV_STENCIL_REF: -+ case VKD3D_SHADER_SV_TARGET: -+ return VKD3D_SIV_NONE; -+ case VKD3D_SHADER_SV_POSITION: -+ return VKD3D_SIV_POSITION; -+ case VKD3D_SHADER_SV_CLIP_DISTANCE: -+ return VKD3D_SIV_CLIP_DISTANCE; -+ case VKD3D_SHADER_SV_CULL_DISTANCE: -+ return VKD3D_SIV_CULL_DISTANCE; -+ case VKD3D_SHADER_SV_INSTANCE_ID: -+ return VKD3D_SIV_INSTANCE_ID; -+ case VKD3D_SHADER_SV_IS_FRONT_FACE: -+ return VKD3D_SIV_IS_FRONT_FACE; -+ case VKD3D_SHADER_SV_PRIMITIVE_ID: -+ return VKD3D_SIV_PRIMITIVE_ID; -+ case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX: -+ return VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX; -+ case VKD3D_SHADER_SV_SAMPLE_INDEX: -+ return VKD3D_SIV_SAMPLE_INDEX; -+ case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: -+ return VKD3D_SIV_QUAD_U0_TESS_FACTOR + index; -+ case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: -+ return VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR + index; -+ case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: -+ return VKD3D_SIV_TRIANGLE_U_TESS_FACTOR + index; -+ case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: -+ return VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR; -+ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: -+ return VKD3D_SIV_LINE_DETAIL_TESS_FACTOR; -+ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: -+ return VKD3D_SIV_LINE_DENSITY_TESS_FACTOR; -+ case VKD3D_SHADER_SV_VERTEX_ID: -+ return VKD3D_SIV_VERTEX_ID; -+ case VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX: -+ return VKD3D_SIV_VIEWPORT_ARRAY_INDEX; -+ default: -+ FIXME("Unhandled sysval %#x, index %u.\n", sysval, index); -+ return VKD3D_SIV_NONE; -+ } -+} -+ - static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vsir_program *program, - const struct hlsl_ir_var *var, struct hlsl_block *block, const struct vkd3d_shader_location *loc) - { -@@ -9983,6 +10061,9 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs - if (semantic == VKD3D_SHADER_SV_NONE || version->type == VKD3D_SHADER_TYPE_PIXEL - || (version->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func)) - opcode = VKD3DSIH_DCL_OUTPUT; -+ else if ((semantic == VKD3D_SHADER_SV_PRIMITIVE_ID || semantic == VKD3D_SHADER_SV_IS_FRONT_FACE) -+ && version->type == VKD3D_SHADER_TYPE_GEOMETRY) -+ opcode = VKD3DSIH_DCL_OUTPUT_SGV; - else - opcode = VKD3DSIH_DCL_OUTPUT_SIV; - } -@@ -10832,20 +10913,27 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, - - if (store->store_type != HLSL_RESOURCE_STORE) - { -- enum vkd3d_shader_opcode opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND -- ? VKD3DSIH_EMIT : VKD3DSIH_CUT; -+ enum vkd3d_shader_opcode opcode; - - VKD3D_ASSERT(!store->value.node && !store->coords.node); - VKD3D_ASSERT(store->resource.var->regs[HLSL_REGSET_STREAM_OUTPUTS].allocated); - -- if (store->resource.var->regs[HLSL_REGSET_STREAM_OUTPUTS].index) -+ if (hlsl_version_lt(ctx, 5, 0)) - { -- hlsl_fixme(ctx, &instr->loc, "Stream output operation with a nonzero stream index."); -- return false; -+ opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND ? VKD3DSIH_EMIT : VKD3DSIH_CUT; -+ ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 0); -+ return !!ins; - } - -- ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 0); -- return !!ins; -+ opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND ? VKD3DSIH_EMIT_STREAM : VKD3DSIH_CUT_STREAM; -+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 1))) -+ return false; -+ -+ if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, &ins->src[0], -+ &store->resource, VKD3DSP_WRITEMASK_ALL, &instr->loc)) -+ return false; -+ -+ return true; - } - - if (!store->resource.var->is_uniform) -@@ -12026,14 +12114,11 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, - bool uav) - { - enum hlsl_regset regset = uav ? HLSL_REGSET_UAVS : HLSL_REGSET_TEXTURES; -- struct vkd3d_shader_structured_resource *structured_resource; -- struct vkd3d_shader_dst_param *dst_param; -- struct vkd3d_shader_semantic *semantic; - struct vkd3d_shader_instruction *ins; - struct hlsl_type *component_type; - enum vkd3d_shader_opcode opcode; - bool multisampled; -- unsigned int i, j; -+ unsigned int i; - - VKD3D_ASSERT(resource->regset == regset); - VKD3D_ASSERT(hlsl_version_lt(ctx, 5, 1) || resource->bind_count == 1); -@@ -12044,6 +12129,7 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, - { - unsigned int array_first = resource->index + i; - unsigned int array_last = resource->index + i; /* FIXME: array end. */ -+ struct vkd3d_shader_resource *vsir_resource; - - if (resource->var && !resource->var->objects_usage[regset][i].used) - continue; -@@ -12081,13 +12167,16 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, - ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; - return; - } -- semantic = &ins->declaration.semantic; -- structured_resource = &ins->declaration.structured_resource; -- dst_param = &semantic->resource.reg; -- vsir_dst_param_init(dst_param, uav ? VKD3DSPR_UAV : VKD3DSPR_RESOURCE, VKD3D_DATA_UNUSED, 0); - -- if (uav && component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) -- structured_resource->byte_stride = 4 * component_type->e.resource.format->reg_size[HLSL_REGSET_NUMERIC]; -+ if (component_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) -+ vsir_resource = &ins->declaration.raw_resource.resource; -+ else if (component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) -+ vsir_resource = &ins->declaration.structured_resource.resource; -+ else -+ vsir_resource = &ins->declaration.semantic.resource; -+ -+ vsir_dst_param_init(&vsir_resource->reg, uav ? VKD3DSPR_UAV : VKD3DSPR_RESOURCE, VKD3D_DATA_UNUSED, 0); -+ - if (uav && component_type->e.resource.rasteriser_ordered) - ins->flags = VKD3DSUF_RASTERISER_ORDERED_VIEW; - -@@ -12101,30 +12190,52 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, - ctx->profile->major_version, ctx->profile->minor_version); - } - -- for (j = 0; j < 4; ++j) -- semantic->resource_data_type[j] = sm4_generate_vsir_get_format_type(component_type); -- -- semantic->resource.range.first = array_first; -- semantic->resource.range.last = array_last; -- semantic->resource.range.space = resource->space; -+ vsir_resource->range.first = array_first; -+ vsir_resource->range.last = array_last; -+ vsir_resource->range.space = resource->space; - -- dst_param->reg.idx[0].offset = resource->id; -- dst_param->reg.idx[1].offset = array_first; -- dst_param->reg.idx[2].offset = array_last; -- dst_param->reg.idx_count = 3; -+ vsir_resource->reg.reg.idx[0].offset = resource->id; -+ vsir_resource->reg.reg.idx[1].offset = array_first; -+ vsir_resource->reg.reg.idx[2].offset = array_last; -+ vsir_resource->reg.reg.idx_count = 3; - - ins->resource_type = sm4_generate_vsir_get_resource_type(resource->component_type); -- if (resource->component_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) -+ -+ if (component_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) -+ { - ins->raw = true; -- if (resource->component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) -+ } -+ else if (component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) - { - ins->structured = true; - ins->resource_stride = 4 * component_type->e.resource.format->reg_size[HLSL_REGSET_NUMERIC]; -+ ins->declaration.structured_resource.byte_stride = ins->resource_stride; -+ } -+ else -+ { -+ for (unsigned int j = 0; j < 4; ++j) -+ ins->declaration.semantic.resource_data_type[j] = sm4_generate_vsir_get_format_type(component_type); -+ -+ if (multisampled) -+ ins->declaration.semantic.sample_count = component_type->sample_count; - } -+ } -+} -+ -+static void sm4_generate_vsir_add_dcl_stream(struct hlsl_ctx *ctx, -+ struct vsir_program *program, const struct hlsl_ir_var *var) -+{ -+ struct vkd3d_shader_instruction *ins; - -- if (multisampled) -- semantic->sample_count = component_type->sample_count; -+ if (!(ins = generate_vsir_add_program_instruction(ctx, program, &var->loc, VKD3DSIH_DCL_STREAM, 0, 1))) -+ { -+ ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; -+ return; - } -+ -+ vsir_src_param_init(&ins->src[0], VKD3DSPR_STREAM, VKD3D_DATA_OPAQUE, 1); -+ ins->src[0].reg.dimension = VSIR_DIMENSION_NONE; -+ ins->src[0].reg.idx[0].offset = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; - } - - /* OBJECTIVE: Translate all the information from ctx and entry_func to the -@@ -12201,6 +12312,17 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl - } - sm4_free_extern_resources(extern_resources, extern_resources_count); - -+ if (version.type == VKD3D_SHADER_TYPE_GEOMETRY && version.major >= 5) -+ { -+ const struct hlsl_ir_var *var; -+ -+ LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) -+ { -+ if (var->bind_count[HLSL_REGSET_STREAM_OUTPUTS]) -+ sm4_generate_vsir_add_dcl_stream(ctx, program, var); -+ } -+ } -+ - if (version.type == VKD3D_SHADER_TYPE_HULL) - generate_vsir_add_program_instruction(ctx, program, - &ctx->patch_constant_func->loc, VKD3DSIH_HS_CONTROL_POINT_PHASE, 0, 0); -@@ -13523,7 +13645,26 @@ static void process_entry_function(struct hlsl_ctx *ctx, - else - { - if (profile->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func) -- hlsl_fixme(ctx, &entry_func->loc, "Passthrough hull shader control point function."); -+ { -+ if (!ctx->input_control_point_type) -+ { -+ hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_INPUT_PATCH, -+ "Pass-through control point function \"%s\" is missing an InputPatch parameter.", -+ entry_func->func->name); -+ } -+ else if (ctx->output_control_point_count -+ && ctx->output_control_point_count != ctx->input_control_point_count) -+ { -+ hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, -+ "Output control point count %u does not match the input control point count %u.", -+ ctx->output_control_point_count, ctx->input_control_point_count); -+ } -+ else -+ { -+ ctx->output_control_point_type = ctx->input_control_point_type; -+ ctx->output_control_point_count = ctx->input_control_point_count; -+ } -+ } - } - - if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY && ctx->input_primitive_type == VKD3D_PT_UNDEFINED) -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 7466f7a2da1..0aebfea2add 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -29,6 +29,344 @@ struct vsir_transformation_context - struct vkd3d_shader_message_context *message_context; - }; - -+const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) -+{ -+ static const char * const names[] = -+ { -+ [VKD3DSIH_ABS ] = "abs", -+ [VKD3DSIH_ACOS ] = "acos", -+ [VKD3DSIH_ADD ] = "add", -+ [VKD3DSIH_AND ] = "and", -+ [VKD3DSIH_ASIN ] = "asin", -+ [VKD3DSIH_ATAN ] = "atan", -+ [VKD3DSIH_ATOMIC_AND ] = "atomic_and", -+ [VKD3DSIH_ATOMIC_CMP_STORE ] = "atomic_cmp_store", -+ [VKD3DSIH_ATOMIC_IADD ] = "atomic_iadd", -+ [VKD3DSIH_ATOMIC_IMAX ] = "atomic_imax", -+ [VKD3DSIH_ATOMIC_IMIN ] = "atomic_imin", -+ [VKD3DSIH_ATOMIC_OR ] = "atomic_or", -+ [VKD3DSIH_ATOMIC_UMAX ] = "atomic_umax", -+ [VKD3DSIH_ATOMIC_UMIN ] = "atomic_umin", -+ [VKD3DSIH_ATOMIC_XOR ] = "atomic_xor", -+ [VKD3DSIH_BEM ] = "bem", -+ [VKD3DSIH_BFI ] = "bfi", -+ [VKD3DSIH_BFREV ] = "bfrev", -+ [VKD3DSIH_BRANCH ] = "branch", -+ [VKD3DSIH_BREAK ] = "break", -+ [VKD3DSIH_BREAKC ] = "break", -+ [VKD3DSIH_BREAKP ] = "breakp", -+ [VKD3DSIH_BUFINFO ] = "bufinfo", -+ [VKD3DSIH_CALL ] = "call", -+ [VKD3DSIH_CALLNZ ] = "callnz", -+ [VKD3DSIH_CASE ] = "case", -+ [VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED ] = "check_access_fully_mapped", -+ [VKD3DSIH_CMP ] = "cmp", -+ [VKD3DSIH_CND ] = "cnd", -+ [VKD3DSIH_CONTINUE ] = "continue", -+ [VKD3DSIH_CONTINUEP ] = "continuec", -+ [VKD3DSIH_COUNTBITS ] = "countbits", -+ [VKD3DSIH_CRS ] = "crs", -+ [VKD3DSIH_CUT ] = "cut", -+ [VKD3DSIH_CUT_STREAM ] = "cut_stream", -+ [VKD3DSIH_DADD ] = "dadd", -+ [VKD3DSIH_DCL ] = "dcl", -+ [VKD3DSIH_DCL_CONSTANT_BUFFER ] = "dcl_constantBuffer", -+ [VKD3DSIH_DCL_FUNCTION_BODY ] = "dcl_function_body", -+ [VKD3DSIH_DCL_FUNCTION_TABLE ] = "dcl_function_table", -+ [VKD3DSIH_DCL_GLOBAL_FLAGS ] = "dcl_globalFlags", -+ [VKD3DSIH_DCL_GS_INSTANCES ] = "dcl_gs_instances", -+ [VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT] = "dcl_hs_fork_phase_instance_count", -+ [VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT] = "dcl_hs_join_phase_instance_count", -+ [VKD3DSIH_DCL_HS_MAX_TESSFACTOR ] = "dcl_hs_max_tessfactor", -+ [VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER ] = "dcl_immediateConstantBuffer", -+ [VKD3DSIH_DCL_INDEX_RANGE ] = "dcl_index_range", -+ [VKD3DSIH_DCL_INDEXABLE_TEMP ] = "dcl_indexableTemp", -+ [VKD3DSIH_DCL_INPUT ] = "dcl_input", -+ [VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT ] = "dcl_input_control_point_count", -+ [VKD3DSIH_DCL_INPUT_PRIMITIVE ] = "dcl_inputprimitive", -+ [VKD3DSIH_DCL_INPUT_PS ] = "dcl_input_ps", -+ [VKD3DSIH_DCL_INPUT_PS_SGV ] = "dcl_input_ps_sgv", -+ [VKD3DSIH_DCL_INPUT_PS_SIV ] = "dcl_input_ps_siv", -+ [VKD3DSIH_DCL_INPUT_SGV ] = "dcl_input_sgv", -+ [VKD3DSIH_DCL_INPUT_SIV ] = "dcl_input_siv", -+ [VKD3DSIH_DCL_INTERFACE ] = "dcl_interface", -+ [VKD3DSIH_DCL_OUTPUT ] = "dcl_output", -+ [VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT ] = "dcl_output_control_point_count", -+ [VKD3DSIH_DCL_OUTPUT_SGV ] = "dcl_output_sgv", -+ [VKD3DSIH_DCL_OUTPUT_SIV ] = "dcl_output_siv", -+ [VKD3DSIH_DCL_OUTPUT_TOPOLOGY ] = "dcl_outputtopology", -+ [VKD3DSIH_DCL_RESOURCE_RAW ] = "dcl_resource_raw", -+ [VKD3DSIH_DCL_RESOURCE_STRUCTURED ] = "dcl_resource_structured", -+ [VKD3DSIH_DCL_SAMPLER ] = "dcl_sampler", -+ [VKD3DSIH_DCL_STREAM ] = "dcl_stream", -+ [VKD3DSIH_DCL_TEMPS ] = "dcl_temps", -+ [VKD3DSIH_DCL_TESSELLATOR_DOMAIN ] = "dcl_tessellator_domain", -+ [VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE] = "dcl_tessellator_output_primitive", -+ [VKD3DSIH_DCL_TESSELLATOR_PARTITIONING ] = "dcl_tessellator_partitioning", -+ [VKD3DSIH_DCL_TGSM_RAW ] = "dcl_tgsm_raw", -+ [VKD3DSIH_DCL_TGSM_STRUCTURED ] = "dcl_tgsm_structured", -+ [VKD3DSIH_DCL_THREAD_GROUP ] = "dcl_thread_group", -+ [VKD3DSIH_DCL_UAV_RAW ] = "dcl_uav_raw", -+ [VKD3DSIH_DCL_UAV_STRUCTURED ] = "dcl_uav_structured", -+ [VKD3DSIH_DCL_UAV_TYPED ] = "dcl_uav_typed", -+ [VKD3DSIH_DCL_VERTICES_OUT ] = "dcl_maxout", -+ [VKD3DSIH_DDIV ] = "ddiv", -+ [VKD3DSIH_DEF ] = "def", -+ [VKD3DSIH_DEFAULT ] = "default", -+ [VKD3DSIH_DEFB ] = "defb", -+ [VKD3DSIH_DEFI ] = "defi", -+ [VKD3DSIH_DEQO ] = "deq", -+ [VKD3DSIH_DFMA ] = "dfma", -+ [VKD3DSIH_DGEO ] = "dge", -+ [VKD3DSIH_DISCARD ] = "discard", -+ [VKD3DSIH_DIV ] = "div", -+ [VKD3DSIH_DLT ] = "dlt", -+ [VKD3DSIH_DMAX ] = "dmax", -+ [VKD3DSIH_DMIN ] = "dmin", -+ [VKD3DSIH_DMOV ] = "dmov", -+ [VKD3DSIH_DMOVC ] = "dmovc", -+ [VKD3DSIH_DMUL ] = "dmul", -+ [VKD3DSIH_DNE ] = "dne", -+ [VKD3DSIH_DP2 ] = "dp2", -+ [VKD3DSIH_DP2ADD ] = "dp2add", -+ [VKD3DSIH_DP3 ] = "dp3", -+ [VKD3DSIH_DP4 ] = "dp4", -+ [VKD3DSIH_DRCP ] = "drcp", -+ [VKD3DSIH_DST ] = "dst", -+ [VKD3DSIH_DSX ] = "dsx", -+ [VKD3DSIH_DSX_COARSE ] = "deriv_rtx_coarse", -+ [VKD3DSIH_DSX_FINE ] = "deriv_rtx_fine", -+ [VKD3DSIH_DSY ] = "dsy", -+ [VKD3DSIH_DSY_COARSE ] = "deriv_rty_coarse", -+ [VKD3DSIH_DSY_FINE ] = "deriv_rty_fine", -+ [VKD3DSIH_DTOF ] = "dtof", -+ [VKD3DSIH_DTOI ] = "dtoi", -+ [VKD3DSIH_DTOU ] = "dtou", -+ [VKD3DSIH_ELSE ] = "else", -+ [VKD3DSIH_EMIT ] = "emit", -+ [VKD3DSIH_EMIT_STREAM ] = "emit_stream", -+ [VKD3DSIH_ENDIF ] = "endif", -+ [VKD3DSIH_ENDLOOP ] = "endloop", -+ [VKD3DSIH_ENDREP ] = "endrep", -+ [VKD3DSIH_ENDSWITCH ] = "endswitch", -+ [VKD3DSIH_EQO ] = "eq", -+ [VKD3DSIH_EQU ] = "eq_unord", -+ [VKD3DSIH_EVAL_CENTROID ] = "eval_centroid", -+ [VKD3DSIH_EVAL_SAMPLE_INDEX ] = "eval_sample_index", -+ [VKD3DSIH_EXP ] = "exp", -+ [VKD3DSIH_EXPP ] = "expp", -+ [VKD3DSIH_F16TOF32 ] = "f16tof32", -+ [VKD3DSIH_F32TOF16 ] = "f32tof16", -+ [VKD3DSIH_FCALL ] = "fcall", -+ [VKD3DSIH_FIRSTBIT_HI ] = "firstbit_hi", -+ [VKD3DSIH_FIRSTBIT_LO ] = "firstbit_lo", -+ [VKD3DSIH_FIRSTBIT_SHI ] = "firstbit_shi", -+ [VKD3DSIH_FRC ] = "frc", -+ [VKD3DSIH_FREM ] = "frem", -+ [VKD3DSIH_FTOD ] = "ftod", -+ [VKD3DSIH_FTOI ] = "ftoi", -+ [VKD3DSIH_FTOU ] = "ftou", -+ [VKD3DSIH_GATHER4 ] = "gather4", -+ [VKD3DSIH_GATHER4_C ] = "gather4_c", -+ [VKD3DSIH_GATHER4_C_S ] = "gather4_c_s", -+ [VKD3DSIH_GATHER4_PO ] = "gather4_po", -+ [VKD3DSIH_GATHER4_PO_C ] = "gather4_po_c", -+ [VKD3DSIH_GATHER4_PO_C_S ] = "gather4_po_c_s", -+ [VKD3DSIH_GATHER4_PO_S ] = "gather4_po_s", -+ [VKD3DSIH_GATHER4_S ] = "gather4_s", -+ [VKD3DSIH_GEO ] = "ge", -+ [VKD3DSIH_GEU ] = "ge_unord", -+ [VKD3DSIH_HCOS ] = "hcos", -+ [VKD3DSIH_HS_CONTROL_POINT_PHASE ] = "hs_control_point_phase", -+ [VKD3DSIH_HS_DECLS ] = "hs_decls", -+ [VKD3DSIH_HS_FORK_PHASE ] = "hs_fork_phase", -+ [VKD3DSIH_HS_JOIN_PHASE ] = "hs_join_phase", -+ [VKD3DSIH_HSIN ] = "hsin", -+ [VKD3DSIH_HTAN ] = "htan", -+ [VKD3DSIH_IADD ] = "iadd", -+ [VKD3DSIH_IBFE ] = "ibfe", -+ [VKD3DSIH_IDIV ] = "idiv", -+ [VKD3DSIH_IEQ ] = "ieq", -+ [VKD3DSIH_IF ] = "if", -+ [VKD3DSIH_IFC ] = "if", -+ [VKD3DSIH_IGE ] = "ige", -+ [VKD3DSIH_ILT ] = "ilt", -+ [VKD3DSIH_IMAD ] = "imad", -+ [VKD3DSIH_IMAX ] = "imax", -+ [VKD3DSIH_IMIN ] = "imin", -+ [VKD3DSIH_IMM_ATOMIC_ALLOC ] = "imm_atomic_alloc", -+ [VKD3DSIH_IMM_ATOMIC_AND ] = "imm_atomic_and", -+ [VKD3DSIH_IMM_ATOMIC_CMP_EXCH ] = "imm_atomic_cmp_exch", -+ [VKD3DSIH_IMM_ATOMIC_CONSUME ] = "imm_atomic_consume", -+ [VKD3DSIH_IMM_ATOMIC_EXCH ] = "imm_atomic_exch", -+ [VKD3DSIH_IMM_ATOMIC_IADD ] = "imm_atomic_iadd", -+ [VKD3DSIH_IMM_ATOMIC_IMAX ] = "imm_atomic_imax", -+ [VKD3DSIH_IMM_ATOMIC_IMIN ] = "imm_atomic_imin", -+ [VKD3DSIH_IMM_ATOMIC_OR ] = "imm_atomic_or", -+ [VKD3DSIH_IMM_ATOMIC_UMAX ] = "imm_atomic_umax", -+ [VKD3DSIH_IMM_ATOMIC_UMIN ] = "imm_atomic_umin", -+ [VKD3DSIH_IMM_ATOMIC_XOR ] = "imm_atomic_xor", -+ [VKD3DSIH_IMUL ] = "imul", -+ [VKD3DSIH_INE ] = "ine", -+ [VKD3DSIH_INEG ] = "ineg", -+ [VKD3DSIH_ISFINITE ] = "isfinite", -+ [VKD3DSIH_ISHL ] = "ishl", -+ [VKD3DSIH_ISHR ] = "ishr", -+ [VKD3DSIH_ISINF ] = "isinf", -+ [VKD3DSIH_ISNAN ] = "isnan", -+ [VKD3DSIH_ITOD ] = "itod", -+ [VKD3DSIH_ITOF ] = "itof", -+ [VKD3DSIH_ITOI ] = "itoi", -+ [VKD3DSIH_LABEL ] = "label", -+ [VKD3DSIH_LD ] = "ld", -+ [VKD3DSIH_LD2DMS ] = "ld2dms", -+ [VKD3DSIH_LD2DMS_S ] = "ld2dms_s", -+ [VKD3DSIH_LD_RAW ] = "ld_raw", -+ [VKD3DSIH_LD_RAW_S ] = "ld_raw_s", -+ [VKD3DSIH_LD_S ] = "ld_s", -+ [VKD3DSIH_LD_STRUCTURED ] = "ld_structured", -+ [VKD3DSIH_LD_STRUCTURED_S ] = "ld_structured_s", -+ [VKD3DSIH_LD_UAV_TYPED ] = "ld_uav_typed", -+ [VKD3DSIH_LD_UAV_TYPED_S ] = "ld_uav_typed_s", -+ [VKD3DSIH_LIT ] = "lit", -+ [VKD3DSIH_LOD ] = "lod", -+ [VKD3DSIH_LOG ] = "log", -+ [VKD3DSIH_LOGP ] = "logp", -+ [VKD3DSIH_LOOP ] = "loop", -+ [VKD3DSIH_LRP ] = "lrp", -+ [VKD3DSIH_LTO ] = "lt", -+ [VKD3DSIH_LTU ] = "lt_unord", -+ [VKD3DSIH_M3x2 ] = "m3x2", -+ [VKD3DSIH_M3x3 ] = "m3x3", -+ [VKD3DSIH_M3x4 ] = "m3x4", -+ [VKD3DSIH_M4x3 ] = "m4x3", -+ [VKD3DSIH_M4x4 ] = "m4x4", -+ [VKD3DSIH_MAD ] = "mad", -+ [VKD3DSIH_MAX ] = "max", -+ [VKD3DSIH_MIN ] = "min", -+ [VKD3DSIH_MOV ] = "mov", -+ [VKD3DSIH_MOVA ] = "mova", -+ [VKD3DSIH_MOVC ] = "movc", -+ [VKD3DSIH_MSAD ] = "msad", -+ [VKD3DSIH_MUL ] = "mul", -+ [VKD3DSIH_NEO ] = "ne_ord", -+ [VKD3DSIH_NEU ] = "ne", -+ [VKD3DSIH_NOP ] = "nop", -+ [VKD3DSIH_NOT ] = "not", -+ [VKD3DSIH_NRM ] = "nrm", -+ [VKD3DSIH_OR ] = "or", -+ [VKD3DSIH_ORD ] = "ord", -+ [VKD3DSIH_PHASE ] = "phase", -+ [VKD3DSIH_PHI ] = "phi", -+ [VKD3DSIH_POW ] = "pow", -+ [VKD3DSIH_QUAD_READ_ACROSS_D ] = "quad_read_across_d", -+ [VKD3DSIH_QUAD_READ_ACROSS_X ] = "quad_read_across_x", -+ [VKD3DSIH_QUAD_READ_ACROSS_Y ] = "quad_read_across_y", -+ [VKD3DSIH_QUAD_READ_LANE_AT ] = "quad_read_lane_at", -+ [VKD3DSIH_RCP ] = "rcp", -+ [VKD3DSIH_REP ] = "rep", -+ [VKD3DSIH_RESINFO ] = "resinfo", -+ [VKD3DSIH_RET ] = "ret", -+ [VKD3DSIH_RETP ] = "retp", -+ [VKD3DSIH_ROUND_NE ] = "round_ne", -+ [VKD3DSIH_ROUND_NI ] = "round_ni", -+ [VKD3DSIH_ROUND_PI ] = "round_pi", -+ [VKD3DSIH_ROUND_Z ] = "round_z", -+ [VKD3DSIH_RSQ ] = "rsq", -+ [VKD3DSIH_SAMPLE ] = "sample", -+ [VKD3DSIH_SAMPLE_B ] = "sample_b", -+ [VKD3DSIH_SAMPLE_B_CL_S ] = "sample_b_cl_s", -+ [VKD3DSIH_SAMPLE_C ] = "sample_c", -+ [VKD3DSIH_SAMPLE_C_CL_S ] = "sample_c_cl_s", -+ [VKD3DSIH_SAMPLE_C_LZ ] = "sample_c_lz", -+ [VKD3DSIH_SAMPLE_C_LZ_S ] = "sample_c_lz_s", -+ [VKD3DSIH_SAMPLE_CL_S ] = "sample_cl_s", -+ [VKD3DSIH_SAMPLE_GRAD ] = "sample_d", -+ [VKD3DSIH_SAMPLE_GRAD_CL_S ] = "sample_d_cl_s", -+ [VKD3DSIH_SAMPLE_INFO ] = "sample_info", -+ [VKD3DSIH_SAMPLE_LOD ] = "sample_l", -+ [VKD3DSIH_SAMPLE_LOD_S ] = "sample_l_s", -+ [VKD3DSIH_SAMPLE_POS ] = "sample_pos", -+ [VKD3DSIH_SETP ] = "setp", -+ [VKD3DSIH_SGE ] = "sge", -+ [VKD3DSIH_SGN ] = "sgn", -+ [VKD3DSIH_SINCOS ] = "sincos", -+ [VKD3DSIH_SLT ] = "slt", -+ [VKD3DSIH_SQRT ] = "sqrt", -+ [VKD3DSIH_STORE_RAW ] = "store_raw", -+ [VKD3DSIH_STORE_STRUCTURED ] = "store_structured", -+ [VKD3DSIH_STORE_UAV_TYPED ] = "store_uav_typed", -+ [VKD3DSIH_SUB ] = "sub", -+ [VKD3DSIH_SWAPC ] = "swapc", -+ [VKD3DSIH_SWITCH ] = "switch", -+ [VKD3DSIH_SWITCH_MONOLITHIC ] = "switch", -+ [VKD3DSIH_SYNC ] = "sync", -+ [VKD3DSIH_TAN ] = "tan", -+ [VKD3DSIH_TEX ] = "tex", -+ [VKD3DSIH_TEXBEM ] = "texbem", -+ [VKD3DSIH_TEXBEML ] = "texbeml", -+ [VKD3DSIH_TEXCOORD ] = "texcoord", -+ [VKD3DSIH_TEXCRD ] = "texcrd", -+ [VKD3DSIH_TEXDEPTH ] = "texdepth", -+ [VKD3DSIH_TEXDP3 ] = "texdp3", -+ [VKD3DSIH_TEXDP3TEX ] = "texdp3tex", -+ [VKD3DSIH_TEXKILL ] = "texkill", -+ [VKD3DSIH_TEXLD ] = "texld", -+ [VKD3DSIH_TEXLDD ] = "texldd", -+ [VKD3DSIH_TEXLDL ] = "texldl", -+ [VKD3DSIH_TEXM3x2DEPTH ] = "texm3x2depth", -+ [VKD3DSIH_TEXM3x2PAD ] = "texm3x2pad", -+ [VKD3DSIH_TEXM3x2TEX ] = "texm3x2tex", -+ [VKD3DSIH_TEXM3x3 ] = "texm3x3", -+ [VKD3DSIH_TEXM3x3DIFF ] = "texm3x3diff", -+ [VKD3DSIH_TEXM3x3PAD ] = "texm3x3pad", -+ [VKD3DSIH_TEXM3x3SPEC ] = "texm3x3spec", -+ [VKD3DSIH_TEXM3x3TEX ] = "texm3x3tex", -+ [VKD3DSIH_TEXM3x3VSPEC ] = "texm3x3vspec", -+ [VKD3DSIH_TEXREG2AR ] = "texreg2ar", -+ [VKD3DSIH_TEXREG2GB ] = "texreg2gb", -+ [VKD3DSIH_TEXREG2RGB ] = "texreg2rgb", -+ [VKD3DSIH_UBFE ] = "ubfe", -+ [VKD3DSIH_UDIV ] = "udiv", -+ [VKD3DSIH_UGE ] = "uge", -+ [VKD3DSIH_ULT ] = "ult", -+ [VKD3DSIH_UMAX ] = "umax", -+ [VKD3DSIH_UMIN ] = "umin", -+ [VKD3DSIH_UMUL ] = "umul", -+ [VKD3DSIH_UNO ] = "uno", -+ [VKD3DSIH_USHR ] = "ushr", -+ [VKD3DSIH_UTOD ] = "utod", -+ [VKD3DSIH_UTOF ] = "utof", -+ [VKD3DSIH_UTOU ] = "utou", -+ [VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL ] = "wave_active_all_equal", -+ [VKD3DSIH_WAVE_ACTIVE_BALLOT ] = "wave_active_ballot", -+ [VKD3DSIH_WAVE_ACTIVE_BIT_AND ] = "wave_active_bit_and", -+ [VKD3DSIH_WAVE_ACTIVE_BIT_OR ] = "wave_active_bit_or", -+ [VKD3DSIH_WAVE_ACTIVE_BIT_XOR ] = "wave_active_bit_xor", -+ [VKD3DSIH_WAVE_ALL_BIT_COUNT ] = "wave_all_bit_count", -+ [VKD3DSIH_WAVE_ALL_TRUE ] = "wave_all_true", -+ [VKD3DSIH_WAVE_ANY_TRUE ] = "wave_any_true", -+ [VKD3DSIH_WAVE_IS_FIRST_LANE ] = "wave_is_first_lane", -+ [VKD3DSIH_WAVE_OP_ADD ] = "wave_op_add", -+ [VKD3DSIH_WAVE_OP_IMAX ] = "wave_op_imax", -+ [VKD3DSIH_WAVE_OP_IMIN ] = "wave_op_imin", -+ [VKD3DSIH_WAVE_OP_MAX ] = "wave_op_max", -+ [VKD3DSIH_WAVE_OP_MIN ] = "wave_op_min", -+ [VKD3DSIH_WAVE_OP_MUL ] = "wave_op_mul", -+ [VKD3DSIH_WAVE_OP_UMAX ] = "wave_op_umax", -+ [VKD3DSIH_WAVE_OP_UMIN ] = "wave_op_umin", -+ [VKD3DSIH_WAVE_PREFIX_BIT_COUNT ] = "wave_prefix_bit_count", -+ [VKD3DSIH_WAVE_READ_LANE_AT ] = "wave_read_lane_at", -+ [VKD3DSIH_WAVE_READ_LANE_FIRST ] = "wave_read_lane_first", -+ [VKD3DSIH_XOR ] = "xor", -+ }; -+ -+ if ((uint32_t)op < ARRAY_SIZE(names)) -+ return names[op] ? names[op] : error; -+ -+ return error; -+} -+ - static int convert_parameter_info(const struct vkd3d_shader_compile_info *compile_info, - unsigned int *ret_count, const struct vkd3d_shader_parameter1 **ret_parameters) - { -@@ -823,7 +1161,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, - div_ins->src[1] = tex->src[0]; - div_ins->src[1].swizzle = vkd3d_shader_create_swizzle(w_comp, w_comp, w_comp, w_comp); - -- if (!vsir_instruction_init_with_params(program, tex_ins, location, VKD3DSIH_TEX, 1, 2)) -+ if (!vsir_instruction_init_with_params(program, tex_ins, location, VKD3DSIH_TEXLD, 1, 2)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - tex_ins->dst[0] = tex->dst[0]; -@@ -838,7 +1176,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, - return VKD3D_OK; - } - --static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, -+static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program, - struct vkd3d_shader_instruction *tex, struct vkd3d_shader_message_context *message_context) - { - unsigned int idx = tex->src[1].reg.idx[0].offset; -@@ -1031,6 +1369,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr - case VKD3DSIH_DCL_INPUT_PS: - case VKD3DSIH_DCL_INPUT_PS_SGV: - case VKD3DSIH_DCL_INPUT_PS_SIV: -+ case VKD3DSIH_DCL_OUTPUT_SGV: - case VKD3DSIH_DCL_OUTPUT_SIV: - vkd3d_shader_instruction_make_nop(ins); - break; -@@ -1040,7 +1379,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr - return ret; - break; - -- case VKD3DSIH_TEX: -+ case VKD3DSIH_TEXLD: - if (ins->flags == VKD3DSI_TEXLD_PROJECT) - { - if ((ret = vsir_program_lower_texldp(program, ins, &tmp_idx)) < 0) -@@ -1048,7 +1387,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr - } - else - { -- if ((ret = vsir_program_lower_tex(program, ins, message_context)) < 0) -+ if ((ret = vsir_program_lower_texld(program, ins, message_context)) < 0) - return ret; - } - break; -@@ -1061,6 +1400,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr - case VKD3DSIH_TEXBEM: - case VKD3DSIH_TEXBEML: - case VKD3DSIH_TEXCOORD: -+ case VKD3DSIH_TEXCRD: - case VKD3DSIH_TEXDEPTH: - case VKD3DSIH_TEXDP3: - case VKD3DSIH_TEXDP3TEX: -@@ -1076,8 +1416,8 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr - case VKD3DSIH_TEXREG2GB: - case VKD3DSIH_TEXREG2RGB: - vkd3d_shader_error(ctx->message_context, &ins->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, -- "Aborting due to unimplemented feature: Combined sampler instruction %#x.", -- ins->opcode); -+ "Aborting due to unimplemented feature: Combined sampler instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(ins->opcode, ""), ins->opcode); - return VKD3D_ERROR_NOT_IMPLEMENTED; - - default: -@@ -1142,15 +1482,15 @@ static enum vkd3d_result vsir_program_ensure_ret(struct vsir_program *program, - return VKD3D_OK; - } - --static bool add_signature_element(struct shader_signature *signature, const char *semantic_name, -- uint32_t semantic_index, uint32_t mask, uint32_t register_index, -+static struct signature_element *add_signature_element(struct shader_signature *signature, -+ const char *semantic_name, uint32_t semantic_index, uint32_t mask, uint32_t register_index, - enum vkd3d_shader_interpolation_mode interpolation_mode) - { - struct signature_element *new_elements, *e; - - if (!(new_elements = vkd3d_realloc(signature->elements, - (signature->element_count + 1) * sizeof(*signature->elements)))) -- return false; -+ return NULL; - signature->elements = new_elements; - e = &signature->elements[signature->element_count++]; - memset(e, 0, sizeof(*e)); -@@ -1164,7 +1504,7 @@ static bool add_signature_element(struct shader_signature *signature, const char - e->register_index = register_index; - e->target_location = register_index; - e->interpolation_mode = interpolation_mode; -- return true; -+ return e; - } - - static enum vkd3d_result vsir_program_add_diffuse_output(struct vsir_program *program, -@@ -6362,9 +6702,9 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr - struct shader_signature *signature = &program->output_signature; - unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u; - const struct vkd3d_shader_parameter1 *mask_parameter = NULL; -- struct signature_element *new_elements, *clip_element; - uint32_t position_signature_idx, position_temp, mask; - static const struct vkd3d_shader_location no_loc; -+ struct signature_element *clip_element; - struct vkd3d_shader_instruction *ins; - unsigned int plane_count; - size_t new_pos; -@@ -6422,33 +6762,20 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr - - plane_count = vkd3d_popcount(mask); - -- if (!(new_elements = vkd3d_realloc(signature->elements, -- (signature->element_count + 2) * sizeof(*signature->elements)))) -+ /* Register mask is ignored since we operate after I/O normalisation. */ -+ if (!(clip_element = add_signature_element(signature, "SV_ClipDistance", 0, -+ vkd3d_write_mask_from_component_count(min(plane_count, 4)), 0, VKD3DSIM_NONE))) - return VKD3D_ERROR_OUT_OF_MEMORY; -- signature->elements = new_elements; -- -- low_signature_idx = signature->element_count; -- clip_element = &signature->elements[signature->element_count++]; -- memset(clip_element, 0, sizeof(*clip_element)); -+ low_signature_idx = clip_element - signature->elements; - clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; -- clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; -- clip_element->register_count = 1; -- clip_element->mask = vkd3d_write_mask_from_component_count(min(plane_count, 4)); -- clip_element->used_mask = clip_element->mask; -- clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; - - if (plane_count > 4) - { -- high_signature_idx = signature->element_count; -- clip_element = &signature->elements[signature->element_count++]; -- memset(clip_element, 0, sizeof(*clip_element)); -+ if (!(clip_element = add_signature_element(signature, "SV_ClipDistance", 1, -+ vkd3d_write_mask_from_component_count(plane_count - 4), 0, VKD3DSIM_NONE))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ high_signature_idx = clip_element - signature->elements; - clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; -- clip_element->semantic_index = 1; -- clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; -- clip_element->register_count = 1; -- clip_element->mask = vkd3d_write_mask_from_component_count(plane_count - 4); -- clip_element->used_mask = clip_element->mask; -- clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; - } - - /* We're going to be reading from the output position, so we need to go -@@ -8400,8 +8727,9 @@ static void vsir_validate_dst_count(struct validation_context *ctx, - { - if (instruction->dst_count != count) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, -- "Invalid destination count %u for an instruction of type %#x, expected %u.", -- instruction->dst_count, instruction->opcode, count); -+ "Invalid destination parameter count %u for instruction \"%s\" (%#x); expected %u.", -+ instruction->dst_count, vsir_opcode_get_name(instruction->opcode, ""), -+ instruction->opcode, count); - } - - static void vsir_validate_src_count(struct validation_context *ctx, -@@ -8409,8 +8737,9 @@ static void vsir_validate_src_count(struct validation_context *ctx, - { - if (instruction->src_count != count) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, -- "Invalid source count %u for an instruction of type %#x, expected %u.", -- instruction->src_count, instruction->opcode, count); -+ "Invalid source parameter count %u for instruction \"%s\" (%#x); expected %u.", -+ instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), -+ instruction->opcode, count); - } - - static bool vsir_validate_src_min_count(struct validation_context *ctx, -@@ -8419,8 +8748,9 @@ static bool vsir_validate_src_min_count(struct validation_context *ctx, - if (instruction->src_count < count) - { - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, -- "Invalid source count %u for an instruction of type %#x, expected at least %u.", -- instruction->src_count, instruction->opcode, count); -+ "Invalid source parameter count %u for instruction \"%s\" (%#x); expected at least %u.", -+ instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), -+ instruction->opcode, count); - return false; - } - -@@ -8433,8 +8763,9 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx, - if (instruction->src_count > count) - { - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, -- "Invalid source count %u for an instruction of type %#x, expected at most %u.", -- instruction->src_count, instruction->opcode, count); -+ "Invalid source parameter count %u for instruction \"%s\" (%#x); expected at most %u.", -+ instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), -+ instruction->opcode, count); - return false; - } - -@@ -8922,7 +9253,9 @@ static void vsir_validate_cf_type(struct validation_context *ctx, - const struct vkd3d_shader_instruction *instruction, enum vsir_control_flow_type expected_type) - { - if (ctx->program->cf_type != expected_type) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x in %s shader.", -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, -+ "Invalid instruction \"%s\" (%#x) in %s shader.", -+ vsir_opcode_get_name(instruction->opcode, ""), - instruction->opcode, name_from_cf_type(ctx->program->cf_type)); - } - -@@ -8941,12 +9274,12 @@ static void vsir_validate_hull_shader_phase(struct validation_context *ctx, - { - if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, -- "Phase instruction %#x is only valid in a hull shader.", -- instruction->opcode); -+ "Phase instruction \"%s\" (%#x) is only valid in a hull shader.", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - if (ctx->depth != 0) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, -- "Phase instruction %#x must appear to top level.", -- instruction->opcode); -+ "Phase instruction \"%s\" (%#x) must appear at the top level.", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - ctx->phase = instruction->opcode; - ctx->dcl_temps_found = false; - } -@@ -9711,8 +10044,8 @@ static void vsir_validate_instruction(struct validation_context *ctx) - default: - if (!vsir_instruction_is_dcl(instruction)) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, -- "Instruction %#x appear before any phase instruction in a hull shader.", -- instruction->opcode); -+ "Instruction \"%s\" (%#x) appears before any phase instruction in a hull shader.", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - break; - } - } -@@ -9732,8 +10065,8 @@ static void vsir_validate_instruction(struct validation_context *ctx) - default: - if (!vsir_instruction_is_dcl(instruction)) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, -- "Invalid instruction %#x outside any block.", -- instruction->opcode); -+ "Invalid instruction \"%s\" (%#x) outside any block.", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - break; - } - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index 4f37468af86..08519787b0a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -48,7 +48,7 @@ struct msl_generator - const char *prefix; - bool failed; - -- bool write_depth; -+ bool read_vertex_id; - - const struct vkd3d_shader_interface_info *interface_info; - }; -@@ -57,10 +57,12 @@ struct msl_resource_type_info - { - size_t read_coord_size; - bool array; -- bool lod; - const char *type_suffix; - }; - -+static void msl_print_subscript(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, -+ const struct vkd3d_shader_src_param *rel_addr, unsigned int offset); -+ - static void VKD3D_PRINTF_FUNC(3, 4) msl_compiler_error(struct msl_generator *gen, - enum vkd3d_shader_error error, const char *fmt, ...) - { -@@ -76,17 +78,17 @@ static const struct msl_resource_type_info *msl_get_resource_type_info(enum vkd3 - { - static const struct msl_resource_type_info info[] = - { -- [VKD3D_SHADER_RESOURCE_NONE] = {0, false, false, "none"}, -- [VKD3D_SHADER_RESOURCE_BUFFER] = {1, false, false, "_buffer"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_1D] = {1, false, false, "1d"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2D] = {2, false, true, "2d"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2DMS] = {2, false, false, "2d_ms"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_3D] = {3, false, true, "3d"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_CUBE] = {2, false, true, "cube"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY] = {1, true, false, "1d_array"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY] = {2, true, true, "2d_array"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY] = {2, true, false, "2d_ms_array"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY] = {2, true, true, "cube_array"}, -+ [VKD3D_SHADER_RESOURCE_NONE] = {0, 0, "none"}, -+ [VKD3D_SHADER_RESOURCE_BUFFER] = {1, 0, "_buffer"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_1D] = {1, 0, "1d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2D] = {2, 0, "2d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2DMS] = {2, 0, "2d_ms"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_3D] = {3, 0, "3d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_CUBE] = {2, 0, "cube"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY] = {1, 1, "1d_array"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY] = {2, 1, "2d_array"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY] = {2, 1, "2d_ms_array"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY] = {2, 1, "cube_array"}, - }; - - if (!t || t >= ARRAY_SIZE(info)) -@@ -359,25 +361,40 @@ static enum msl_data_type msl_print_register_name(struct vkd3d_string_buffer *bu - vkd3d_string_buffer_printf(buffer, "", reg->type); - return MSL_DATA_UNION; - } -- if (reg->idx[0].rel_addr || reg->idx[1].rel_addr || reg->idx[2].rel_addr) -+ if (reg->idx[0].rel_addr || reg->idx[1].rel_addr) - { - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled constant buffer register indirect addressing."); - vkd3d_string_buffer_printf(buffer, "", reg->type); - return MSL_DATA_UNION; - } -+ /* FIXME: This should use vkd3d_shader_find_descriptor() to -+ * find the resource index/space from the resource ID. */ - if (!(binding = msl_get_cbv_binding(gen, 0, reg->idx[1].offset))) - { - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, -- "Cannot finding binding for CBV register %u.", reg->idx[0].offset); -+ "No descriptor binding specified for CBV %u.", reg->idx[0].offset); - vkd3d_string_buffer_printf(buffer, "", reg->type); - return MSL_DATA_UNION; - } - msl_print_cbv_name(buffer, binding->binding); -- vkd3d_string_buffer_printf(buffer, "[%u]", reg->idx[2].offset); -+ msl_print_subscript(buffer, gen, reg->idx[2].rel_addr, reg->idx[2].offset); - return MSL_DATA_UNION; - } - -+ case VKD3DSPR_IDXTEMP: -+ vkd3d_string_buffer_printf(buffer, "x%u", reg->idx[0].offset); -+ msl_print_subscript(buffer, gen, reg->idx[1].rel_addr, reg->idx[1].offset); -+ return MSL_DATA_UNION; -+ -+ case VKD3DSPR_SAMPLEMASK: -+ if (gen->program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled sample coverage mask in shader type #%x.", -+ gen->program->shader_version.type); -+ vkd3d_string_buffer_printf(buffer, "o_mask"); -+ return MSL_DATA_FLOAT; -+ - default: - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled register type %#x.", reg->type); -@@ -488,6 +505,9 @@ static void msl_print_src_with_type(struct vkd3d_string_buffer *buffer, struct m - case VKD3DSPSM_ABS: - vkd3d_string_buffer_printf(buffer, "abs(%s)", str->buffer); - break; -+ case VKD3DSPSM_ABSNEG: -+ vkd3d_string_buffer_printf(buffer, "-abs(%s)", str->buffer); -+ break; - default: - vkd3d_string_buffer_printf(buffer, "(%s)", - vsir_src->modifiers, str->buffer); -@@ -539,12 +559,34 @@ static uint32_t msl_dst_init(struct msl_dst *msl_dst, struct msl_generator *gen, - return write_mask; - } - -+static void msl_print_subscript(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, -+ const struct vkd3d_shader_src_param *rel_addr, unsigned int offset) -+{ -+ struct msl_src r; -+ -+ if (!rel_addr) -+ { -+ vkd3d_string_buffer_printf(buffer, "[%u]", offset); -+ return; -+ } -+ -+ msl_src_init(&r, gen, rel_addr, VKD3DSP_WRITEMASK_0); -+ vkd3d_string_buffer_printf(buffer, "[%s", r.str->buffer); -+ if (offset) -+ vkd3d_string_buffer_printf(buffer, " + %u", offset); -+ vkd3d_string_buffer_printf(buffer, "]"); -+ msl_src_cleanup(&r, &gen->string_buffers); -+} -+ - static void VKD3D_PRINTF_FUNC(3, 4) msl_print_assignment( - struct msl_generator *gen, struct msl_dst *dst, const char *format, ...) - { - uint32_t modifiers = dst->vsir->modifiers; - va_list args; - -+ /* It is always legitimate to ignore _pp. */ -+ modifiers &= ~VKD3DSPDM_PARTIALPRECISION; -+ - if (dst->vsir->shift) - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled destination shift %#x.", dst->vsir->shift); -@@ -570,10 +612,12 @@ static void VKD3D_PRINTF_FUNC(3, 4) msl_print_assignment( - - static void msl_unhandled(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) - { -+ const char *name = vsir_opcode_get_name(ins->opcode, ""); -+ - msl_print_indent(gen->buffer, gen->indent); -- vkd3d_string_buffer_printf(gen->buffer, "/* */\n", ins->opcode); -+ vkd3d_string_buffer_printf(gen->buffer, "/* */\n", name, ins->opcode); - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -- "Internal compiler error: Unhandled instruction %#x.", ins->opcode); -+ "Internal compiler error: Unhandled instruction \"%s\" (%#x).", name, ins->opcode); - } - - static void msl_binop(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *op) -@@ -695,19 +739,36 @@ static void msl_begin_block(struct msl_generator *gen) - ++gen->indent; - } - --static void msl_if(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) -+static void msl_print_condition(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, -+ enum vkd3d_shader_conditional_op op, const struct vkd3d_shader_src_param *arg) - { - const char *condition; - struct msl_src src; - -- msl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); -+ msl_src_init(&src, gen, arg, VKD3DSP_WRITEMASK_0); - -- msl_print_indent(gen->buffer, gen->indent); -- condition = ins->flags == VKD3D_SHADER_CONDITIONAL_OP_NZ ? "bool" : "!bool"; -- vkd3d_string_buffer_printf(gen->buffer, "if (%s(%s))\n", condition, src.str->buffer); -+ condition = op == VKD3D_SHADER_CONDITIONAL_OP_NZ ? "bool" : "!bool"; -+ vkd3d_string_buffer_printf(buffer, "if (%s(%s))\n", condition, src.str->buffer); - - msl_src_cleanup(&src, &gen->string_buffers); -+} - -+static void msl_discard(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ /* Note that discard_fragment() in Metal 2.2 and earlier behaves like -+ * SPIR-V OpKill, while in Metal 2.3 and later it behaves like -+ * OpDemoteToHelperInvocationEXT. We assume we have at least Metal 3 -+ * here. */ -+ msl_print_indent(gen->buffer, gen->indent); -+ msl_print_condition(gen->buffer, gen, ins->flags, &ins->src[0]); -+ msl_print_indent(gen->buffer, gen->indent + 1); -+ vkd3d_string_buffer_printf(gen->buffer, "discard_fragment();\n"); -+} -+ -+static void msl_if(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ msl_print_indent(gen->buffer, gen->indent); -+ msl_print_condition(gen->buffer, gen, ins->flags, &ins->src[0]); - msl_begin_block(gen); - } - -@@ -719,6 +780,50 @@ static void msl_else(struct msl_generator *gen) - msl_begin_block(gen); - } - -+static void msl_loop(struct msl_generator *gen) -+{ -+ msl_print_indent(gen->buffer, gen->indent); -+ vkd3d_string_buffer_printf(gen->buffer, "for (;;)\n"); -+ msl_begin_block(gen); -+} -+ -+static void msl_break(struct msl_generator *gen) -+{ -+ msl_print_indent(gen->buffer, gen->indent); -+ vkd3d_string_buffer_printf(gen->buffer, "break;\n"); -+} -+ -+static void msl_switch(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ struct msl_src src; -+ -+ msl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); -+ -+ msl_print_indent(gen->buffer, gen->indent); -+ vkd3d_string_buffer_printf(gen->buffer, "switch (%s)\n", src.str->buffer); -+ msl_begin_block(gen); -+ -+ msl_src_cleanup(&src, &gen->string_buffers); -+} -+ -+static void msl_case(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ struct msl_src src; -+ -+ msl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); -+ -+ msl_print_indent(gen->buffer, gen->indent); -+ vkd3d_string_buffer_printf(gen->buffer, "case %s:\n", src.str->buffer); -+ -+ msl_src_cleanup(&src, &gen->string_buffers); -+} -+ -+static void msl_default(struct msl_generator *gen) -+{ -+ msl_print_indent(gen->buffer, gen->indent); -+ vkd3d_string_buffer_printf(gen->buffer, "default:\n"); -+} -+ - static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) - { - const struct msl_resource_type_info *resource_type_info; -@@ -728,6 +833,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct - enum vkd3d_shader_resource_type resource_type; - struct vkd3d_string_buffer *read; - enum vkd3d_data_type data_type; -+ unsigned int srv_binding; - uint32_t coord_mask; - struct msl_dst dst; - -@@ -757,30 +863,39 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct - data_type = VKD3D_DATA_FLOAT; - } - -- if ((resource_type_info = msl_get_resource_type_info(resource_type))) -- { -- coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->read_coord_size); -- } -- else -+ if (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBE -+ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY -+ || (ins->opcode != VKD3DSIH_LD2DMS -+ && (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS -+ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY))) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, -+ "Texel fetches from resource type %#x are not supported.", resource_type); -+ -+ if (!(resource_type_info = msl_get_resource_type_info(resource_type))) - { - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled resource type %#x.", resource_type); -- coord_mask = vkd3d_write_mask_from_component_count(2); -+ resource_type_info = msl_get_resource_type_info(VKD3D_SHADER_RESOURCE_TEXTURE_2D); - } -+ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->read_coord_size); - -- if (!(binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) -+ if ((binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) -+ { -+ srv_binding = binding->binding; -+ } -+ else - { - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, -- "Cannot finding binding for SRV register %u index %u space %u.", -+ "No descriptor binding specified for SRV %u (index %u, space %u).", - resource_id, resource_idx, resource_space); -- return; -+ srv_binding = 0; - } - - msl_dst_init(&dst, gen, ins, &ins->dst[0]); - read = vkd3d_string_buffer_get(&gen->string_buffers); - - vkd3d_string_buffer_printf(read, "as_type("); -- msl_print_srv_name(read, gen, binding->binding, resource_type_info, data_type); -+ msl_print_srv_name(read, gen, srv_binding, resource_type_info, data_type); - vkd3d_string_buffer_printf(read, ".read("); - msl_print_src_with_type(read, gen, &ins->src[0], coord_mask, VKD3D_DATA_UINT); - if (resource_type_info->array) -@@ -788,10 +903,13 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct - vkd3d_string_buffer_printf(read, ", "); - msl_print_src_with_type(read, gen, &ins->src[0], coord_mask + 1, VKD3D_DATA_UINT); - } -- if (resource_type_info->lod) -+ if (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) - { - vkd3d_string_buffer_printf(read, ", "); -- msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VKD3D_DATA_UINT); -+ if (ins->opcode != VKD3DSIH_LD2DMS) -+ msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VKD3D_DATA_UINT); -+ else -+ msl_print_src_with_type(read, gen, &ins->src[2], VKD3DSP_WRITEMASK_0, VKD3D_DATA_UINT); - } - vkd3d_string_buffer_printf(read, "))"); - msl_print_swizzle(read, ins->src[1].swizzle, ins->dst[0].write_mask); -@@ -857,12 +975,51 @@ static void msl_movc(struct msl_generator *gen, const struct vkd3d_shader_instru - msl_dst_cleanup(&dst, &gen->string_buffers); - } - -+static void msl_mul64(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ struct msl_src src[2]; -+ struct msl_dst dst; -+ uint32_t mask; -+ -+ if (ins->dst[0].reg.type != VKD3DSPR_NULL) -+ { -+ /* TODO: mulhi(). */ -+ mask = msl_dst_init(&dst, gen, ins, &ins->dst[0]); -+ msl_print_assignment(gen, &dst, ""); -+ msl_dst_cleanup(&dst, &gen->string_buffers); -+ -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled 64-bit integer multiplication."); -+ } -+ -+ if (ins->dst[1].reg.type != VKD3DSPR_NULL) -+ { -+ mask = msl_dst_init(&dst, gen, ins, &ins->dst[1]); -+ msl_src_init(&src[0], gen, &ins->src[0], mask); -+ msl_src_init(&src[1], gen, &ins->src[1], mask); -+ -+ msl_print_assignment(gen, &dst, "%s * %s", src[0].str->buffer, src[1].str->buffer); -+ -+ msl_src_cleanup(&src[1], &gen->string_buffers); -+ msl_src_cleanup(&src[0], &gen->string_buffers); -+ msl_dst_cleanup(&dst, &gen->string_buffers); -+ } -+} -+ - static void msl_ret(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) - { - msl_print_indent(gen->buffer, gen->indent); - vkd3d_string_buffer_printf(gen->buffer, "return;\n"); - } - -+static void msl_dcl_indexable_temp(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ msl_print_indent(gen->buffer, gen->indent); -+ vkd3d_string_buffer_printf(gen->buffer, "vkd3d_vec4 x%u[%u];\n", -+ ins->declaration.indexable_temp.register_idx, -+ ins->declaration.indexable_temp.register_size); -+} -+ - static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) - { - gen->location = ins->location; -@@ -870,13 +1027,29 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - switch (ins->opcode) - { - case VKD3DSIH_ADD: -+ case VKD3DSIH_IADD: - msl_binop(gen, ins, "+"); - break; - case VKD3DSIH_AND: - msl_binop(gen, ins, "&"); - break; -+ case VKD3DSIH_BREAK: -+ msl_break(gen); -+ break; -+ case VKD3DSIH_CASE: -+ msl_case(gen, ins); -+ break; -+ case VKD3DSIH_DCL_INDEXABLE_TEMP: -+ msl_dcl_indexable_temp(gen, ins); -+ break; - case VKD3DSIH_NOP: - break; -+ case VKD3DSIH_DEFAULT: -+ msl_default(gen); -+ break; -+ case VKD3DSIH_DISCARD: -+ msl_discard(gen, ins); -+ break; - case VKD3DSIH_DIV: - msl_binop(gen, ins, "/"); - break; -@@ -893,8 +1066,11 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - msl_else(gen); - break; - case VKD3DSIH_ENDIF: -+ case VKD3DSIH_ENDLOOP: -+ case VKD3DSIH_ENDSWITCH: - msl_end_block(gen); - break; -+ case VKD3DSIH_EQO: - case VKD3DSIH_IEQ: - msl_relop(gen, ins, "=="); - break; -@@ -911,6 +1087,7 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - msl_cast(gen, ins, "uint"); - break; - case VKD3DSIH_GEO: -+ case VKD3DSIH_IGE: - msl_relop(gen, ins, ">="); - break; - case VKD3DSIH_IF: -@@ -923,7 +1100,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VKD3DSIH_USHR: - msl_binop(gen, ins, ">>"); - break; -+ case VKD3DSIH_ILT: - case VKD3DSIH_LTO: -+ case VKD3DSIH_ULT: - msl_relop(gen, ins, "<"); - break; - case VKD3DSIH_MAD: -@@ -935,20 +1114,30 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VKD3DSIH_MIN: - msl_intrinsic(gen, ins, "min"); - break; -+ case VKD3DSIH_IMUL: -+ msl_mul64(gen, ins); -+ break; - case VKD3DSIH_INE: - case VKD3DSIH_NEU: - msl_relop(gen, ins, "!="); - break; -+ case VKD3DSIH_INEG: -+ msl_unary_op(gen, ins, "-"); -+ break; - case VKD3DSIH_ITOF: - case VKD3DSIH_UTOF: - msl_cast(gen, ins, "float"); - break; - case VKD3DSIH_LD: -+ case VKD3DSIH_LD2DMS: - msl_ld(gen, ins); - break; - case VKD3DSIH_LOG: - msl_intrinsic(gen, ins, "log2"); - break; -+ case VKD3DSIH_LOOP: -+ msl_loop(gen); -+ break; - case VKD3DSIH_MOV: - msl_mov(gen, ins); - break; -@@ -985,6 +1174,12 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VKD3DSIH_SQRT: - msl_intrinsic(gen, ins, "sqrt"); - break; -+ case VKD3DSIH_SWITCH: -+ msl_switch(gen, ins); -+ break; -+ case VKD3DSIH_XOR: -+ msl_binop(gen, ins, "^"); -+ break; - default: - msl_unhandled(gen, ins); - break; -@@ -1008,21 +1203,48 @@ static void msl_generate_input_struct_declarations(struct msl_generator *gen) - if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) - continue; - -- if (e->sysval_semantic) -+ switch (e->sysval_semantic) - { -- if (e->sysval_semantic == VKD3D_SHADER_SV_IS_FRONT_FACE) -- { -+ case VKD3D_SHADER_SV_NONE: -+ break; -+ -+ case VKD3D_SHADER_SV_POSITION: - if (type != VKD3D_SHADER_TYPE_PIXEL) - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -- "Internal compiler error: Unhandled SV_IS_FRONT_FACE in shader type #%x.", type); -+ "Internal compiler error: Unhandled SV_POSITION in shader type #%x.", type); -+ msl_print_indent(gen->buffer, 1); -+ vkd3d_string_buffer_printf(buffer, "float4 position [[position]];\n"); -+ continue; -+ -+ case VKD3D_SHADER_SV_VERTEX_ID: -+ if (type != VKD3D_SHADER_TYPE_VERTEX) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled SV_VERTEX_ID in shader type #%x.", type); -+ gen->read_vertex_id = true; -+ continue; - -+ case VKD3D_SHADER_SV_IS_FRONT_FACE: -+ if (type != VKD3D_SHADER_TYPE_PIXEL) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled SV_IS_FRONT_FACE in shader type #%x.", type); - msl_print_indent(gen->buffer, 1); - vkd3d_string_buffer_printf(buffer, "bool is_front_face [[front_facing]];\n"); - continue; -- } -- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -- "Internal compiler error: Unhandled system value %#x.", e->sysval_semantic); -- continue; -+ -+ case VKD3D_SHADER_SV_SAMPLE_INDEX: -+ if (type != VKD3D_SHADER_TYPE_PIXEL) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled SV_SAMPLE_INDEX in shader type #%x.", type); -+ msl_print_indent(gen->buffer, 1); -+ vkd3d_string_buffer_printf(buffer, "uint sample_index [[sample_id]];\n"); -+ continue; -+ -+ default: -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled system value %#x.", e->sysval_semantic); -+ msl_print_indent(gen->buffer, 1); -+ vkd3d_string_buffer_printf(buffer, ";\n", e->sysval_semantic); -+ continue; - } - - if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) -@@ -1059,15 +1281,15 @@ static void msl_generate_input_struct_declarations(struct msl_generator *gen) - break; - } - -- vkd3d_string_buffer_printf(buffer, "shader_in_%u ", i); -+ vkd3d_string_buffer_printf(buffer, "shader_in_%u [[", i); - - switch (type) - { - case VKD3D_SHADER_TYPE_VERTEX: -- vkd3d_string_buffer_printf(gen->buffer, "[[attribute(%u)]]", e->target_location); -+ vkd3d_string_buffer_printf(gen->buffer, "attribute(%u)", e->target_location); - break; - case VKD3D_SHADER_TYPE_PIXEL: -- vkd3d_string_buffer_printf(gen->buffer, "[[user(locn%u)]]", e->target_location); -+ vkd3d_string_buffer_printf(gen->buffer, "user(locn%u)", e->target_location); - break; - default: - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -@@ -1081,13 +1303,16 @@ static void msl_generate_input_struct_declarations(struct msl_generator *gen) - case VKD3DSIM_LINEAR: - case VKD3DSIM_NONE: - break; -+ case VKD3DSIM_CONSTANT: -+ vkd3d_string_buffer_printf(gen->buffer, ", flat"); -+ break; - default: - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled interpolation mode %#x.", e->interpolation_mode); - break; - } - -- vkd3d_string_buffer_printf(buffer, ";\n"); -+ vkd3d_string_buffer_printf(buffer, "]];\n"); - } - - vkd3d_string_buffer_printf(buffer, "};\n\n"); -@@ -1138,15 +1363,8 @@ static void msl_generate_output_struct_declarations(struct msl_generator *gen) - { - e = &signature->elements[i]; - -- if (e->sysval_semantic == VKD3D_SHADER_SV_DEPTH) -- { -- gen->write_depth = true; -- msl_print_indent(gen->buffer, 1); -- vkd3d_string_buffer_printf(buffer, "float shader_out_depth [[depth(any)]];\n"); -- continue; -- } -- -- if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) -+ if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED -+ || e->sysval_semantic == VKD3D_SHADER_SV_DEPTH) - continue; - - if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) -@@ -1209,6 +1427,18 @@ static void msl_generate_output_struct_declarations(struct msl_generator *gen) - vkd3d_string_buffer_printf(buffer, ";\n"); - } - -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_DEPTHOUT)) -+ { -+ msl_print_indent(gen->buffer, 1); -+ vkd3d_string_buffer_printf(buffer, "float shader_out_depth [[depth(any)]];\n"); -+ } -+ -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) -+ { -+ msl_print_indent(gen->buffer, 1); -+ vkd3d_string_buffer_printf(buffer, "uint shader_out_mask [[sample_mask]];\n"); -+ } -+ - vkd3d_string_buffer_printf(buffer, "};\n\n"); - } - -@@ -1227,23 +1457,45 @@ static void msl_generate_entrypoint_prologue(struct msl_generator *gen) - continue; - - vkd3d_string_buffer_printf(buffer, " %s_in[%u]", gen->prefix, e->register_index); -- if (e->sysval_semantic == VKD3D_SHADER_SV_NONE) -- { -- msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); -- msl_print_write_mask(buffer, e->mask); -- vkd3d_string_buffer_printf(buffer, " = input.shader_in_%u", i); -- msl_print_write_mask(buffer, e->mask); -- } -- else if (e->sysval_semantic == VKD3D_SHADER_SV_IS_FRONT_FACE) -- { -- vkd3d_string_buffer_printf(buffer, ".u = uint4(input.is_front_face ? 0xffffffffu : 0u, 0, 0, 0)"); -- } -- else -+ switch (e->sysval_semantic) - { -- vkd3d_string_buffer_printf(buffer, " = ", e->sysval_semantic); -- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -- "Internal compiler error: Unhandled system value %#x input.", e->sysval_semantic); -+ case VKD3D_SHADER_SV_NONE: -+ msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); -+ msl_print_write_mask(buffer, e->mask); -+ vkd3d_string_buffer_printf(buffer, " = input.shader_in_%u", i); -+ break; -+ -+ case VKD3D_SHADER_SV_POSITION: -+ msl_print_register_datatype(buffer, gen, VKD3D_DATA_FLOAT); -+ msl_print_write_mask(buffer, e->mask); -+ vkd3d_string_buffer_printf(buffer, " = float4(input.position.xyz, 1.0f / input.position.w)"); -+ break; -+ -+ case VKD3D_SHADER_SV_VERTEX_ID: -+ msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); -+ msl_print_write_mask(buffer, e->mask); -+ vkd3d_string_buffer_printf(buffer, " = uint4(vertex_id, 0u, 0u, 0u)"); -+ break; -+ -+ case VKD3D_SHADER_SV_IS_FRONT_FACE: -+ msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); -+ msl_print_write_mask(buffer, e->mask); -+ vkd3d_string_buffer_printf(buffer, " = uint4(input.is_front_face ? 0xffffffffu : 0u, 0, 0, 0)"); -+ break; -+ -+ case VKD3D_SHADER_SV_SAMPLE_INDEX: -+ msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); -+ msl_print_write_mask(buffer, e->mask); -+ vkd3d_string_buffer_printf(buffer, " = uint4(input.sample_index, 0u, 0u, 0u)"); -+ break; -+ -+ default: -+ vkd3d_string_buffer_printf(buffer, " = ", e->sysval_semantic); -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled system value %#x input.", e->sysval_semantic); -+ break; - } -+ msl_print_write_mask(buffer, e->mask); - vkd3d_string_buffer_printf(buffer, ";\n"); - } - } -@@ -1259,12 +1511,6 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) - { - e = &signature->elements[i]; - -- if (e->sysval_semantic == VKD3D_SHADER_SV_DEPTH) -- { -- vkd3d_string_buffer_printf(buffer, " output.shader_out_depth = shader_out_depth;\n"); -- continue; -- } -- - if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) - continue; - -@@ -1279,6 +1525,8 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) - msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); - msl_print_write_mask(buffer, e->mask); - break; -+ case VKD3D_SHADER_SV_DEPTH: -+ continue; - default: - vkd3d_string_buffer_printf(buffer, " ", e->sysval_semantic); - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -@@ -1286,6 +1534,9 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) - } - vkd3d_string_buffer_printf(buffer, ";\n"); - } -+ -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) -+ vkd3d_string_buffer_printf(gen->buffer, " output.shader_out_mask = as_type(o_mask);\n"); - } - - static void msl_generate_entrypoint(struct msl_generator *gen) -@@ -1316,6 +1567,12 @@ static void msl_generate_entrypoint(struct msl_generator *gen) - "constant descriptor *descriptors [[buffer(0)]],\n"); - } - -+ if (gen->read_vertex_id) -+ { -+ msl_print_indent(gen->buffer, 2); -+ vkd3d_string_buffer_printf(gen->buffer, "uint vertex_id [[vertex_id]],\n"); -+ } -+ - msl_print_indent(gen->buffer, 2); - vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_in input [[stage_in]])\n{\n", gen->prefix); - -@@ -1323,18 +1580,22 @@ static void msl_generate_entrypoint(struct msl_generator *gen) - vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 %s_in[%u];\n", gen->prefix, 32); - vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 %s_out[%u];\n", gen->prefix, 32); - vkd3d_string_buffer_printf(gen->buffer, " vkd3d_%s_out output;\n", gen->prefix); -- -- if (gen->write_depth) -- vkd3d_string_buffer_printf(gen->buffer, " float shader_out_depth;\n"); -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) -+ vkd3d_string_buffer_printf(gen->buffer, " float o_mask;\n"); -+ vkd3d_string_buffer_printf(gen->buffer, "\n"); - - msl_generate_entrypoint_prologue(gen); - - vkd3d_string_buffer_printf(gen->buffer, " %s_main(%s_in, %s_out", gen->prefix, gen->prefix, gen->prefix); -- if (gen->write_depth) -- vkd3d_string_buffer_printf(gen->buffer, ", shader_out_depth"); -+ if (gen->read_vertex_id) -+ vkd3d_string_buffer_printf(gen->buffer, ", vertex_id"); -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_DEPTHOUT)) -+ vkd3d_string_buffer_printf(gen->buffer, ", output.shader_out_depth"); -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) -+ vkd3d_string_buffer_printf(gen->buffer, ", o_mask"); - if (gen->program->descriptors.descriptor_count) - vkd3d_string_buffer_printf(gen->buffer, ", descriptors"); -- vkd3d_string_buffer_printf(gen->buffer, ");\n"); -+ vkd3d_string_buffer_printf(gen->buffer, ");\n\n"); - - msl_generate_entrypoint_epilogue(gen); - -@@ -1353,7 +1614,7 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader - vkd3d_string_buffer_printf(gen->buffer, "#include \n\n"); - vkd3d_string_buffer_printf(gen->buffer, "using namespace metal;\n\n"); - -- if (gen->program->global_flags) -+ if (gen->program->global_flags & ~VKD3DSGF_REFACTORING_ALLOWED) - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled global flags %#"PRIx64".", (uint64_t)gen->program->global_flags); - -@@ -1388,11 +1649,16 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader - msl_generate_output_struct_declarations(gen); - - vkd3d_string_buffer_printf(gen->buffer, -- "void %s_main(thread vkd3d_vec4 *v, " -+ "static void %s_main(thread vkd3d_vec4 *v, " - "thread vkd3d_vec4 *o", - gen->prefix); -- if (gen->write_depth) -- vkd3d_string_buffer_printf(gen->buffer, ", thread float& o_depth"); -+ -+ if (gen->read_vertex_id) -+ vkd3d_string_buffer_printf(gen->buffer, ", uint vertex_id"); -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_DEPTHOUT)) -+ vkd3d_string_buffer_printf(gen->buffer, ", thread float &o_depth"); -+ if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) -+ vkd3d_string_buffer_printf(gen->buffer, ", thread float &o_mask"); - if (gen->program->descriptors.descriptor_count) - vkd3d_string_buffer_printf(gen->buffer, ", constant descriptor *descriptors"); - vkd3d_string_buffer_printf(gen->buffer, ")\n{\n"); -diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.h b/libs/vkd3d/libs/vkd3d-shader/preproc.h -index a98c8ae3df5..9217237d8d3 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/preproc.h -+++ b/libs/vkd3d/libs/vkd3d-shader/preproc.h -@@ -38,6 +38,7 @@ struct preproc_buffer - { - void *lexer_buffer; - struct vkd3d_shader_location location; -+ bool eof; - }; - - struct preproc_file -@@ -125,7 +126,6 @@ struct preproc_ctx - int lookahead_token; - - bool last_was_newline; -- bool last_was_eof; - bool last_was_defined; - - bool error; -diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l -index 4a8d0fddae1..5c56fba0229 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/preproc.l -+++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l -@@ -20,6 +20,7 @@ - - %{ - -+#include "preproc.h" - #include "preproc.tab.h" - - #undef ERROR /* defined in wingdi.h */ -@@ -71,8 +72,8 @@ INT_SUFFIX [uUlL]{0,2} - - %% - --"//" {yy_push_state(CXX_COMMENT, yyscanner);} --"/*" {yy_push_state(C_COMMENT, yyscanner);} -+"//" {yy_push_state(CXX_COMMENT, yyscanner);} -+"/*" {yy_push_state(C_COMMENT, yyscanner);} - \\{NEWLINE} {} - \n { - yy_pop_state(yyscanner); -@@ -80,7 +81,11 @@ INT_SUFFIX [uUlL]{0,2} - return T_NEWLINE; - } - "*/" {yy_pop_state(yyscanner);} --<> {yy_pop_state(yyscanner);} -+<> { -+ yy_pop_state(yyscanner); -+ BEGIN(INITIAL); -+ yyterminate(); -+ } - . {} - \n {} - -@@ -196,6 +201,10 @@ INT_SUFFIX [uUlL]{0,2} - BEGIN(INITIAL); - return T_NEWLINE; - } -+<> { -+ BEGIN(INITIAL); -+ yyterminate(); -+ } - - {WS}+ {} - [-()\[\]{},+!*/<>&|^?:] {return yytext[0];} -@@ -250,8 +259,19 @@ static bool should_concat(struct preproc_ctx *ctx) - return !macro || macro->arg_count; - } - -+static struct preproc_buffer *preproc_get_top_buffer(struct preproc_ctx *ctx) -+{ -+ if (ctx->expansion_count) -+ return &ctx->expansion_stack[ctx->expansion_count - 1].buffer; -+ if (ctx->file_count) -+ return &ctx->file_stack[ctx->file_count - 1].buffer; -+ return NULL; -+} -+ - static void preproc_pop_buffer(struct preproc_ctx *ctx) - { -+ struct preproc_buffer *buffer; -+ - if (ctx->expansion_count) - { - struct preproc_expansion *exp = &ctx->expansion_stack[ctx->expansion_count - 1]; -@@ -290,10 +310,8 @@ static void preproc_pop_buffer(struct preproc_ctx *ctx) - TRACE("File stack size is now %zu.\n", ctx->file_count); - } - -- if (ctx->expansion_count) -- yy_switch_to_buffer(ctx->expansion_stack[ctx->expansion_count - 1].buffer.lexer_buffer, ctx->scanner); -- else if (ctx->file_count) -- yy_switch_to_buffer(ctx->file_stack[ctx->file_count - 1].buffer.lexer_buffer, ctx->scanner); -+ if ((buffer = preproc_get_top_buffer(ctx))) -+ yy_switch_to_buffer(buffer->lexer_buffer, ctx->scanner); - } - - static int return_token(int token, YYSTYPE *lval, const char *text) -@@ -347,6 +365,7 @@ static bool preproc_push_expansion(struct preproc_ctx *ctx, - exp->text = text; - exp->buffer.lexer_buffer = yy_scan_bytes(text->text.buffer, text->text.content_size, ctx->scanner); - exp->buffer.location = text->location; -+ exp->buffer.eof = false; - exp->macro = macro; - exp->arg_values = arg_values; - TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count); -@@ -407,18 +426,17 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) - } - else - { -- if (ctx->last_was_eof) -+ if (preproc_get_top_buffer(ctx)->eof) - { - preproc_pop_buffer(ctx); - if (!ctx->file_count) - return 0; - } -- ctx->last_was_eof = false; - - VKD3D_ASSERT(ctx->file_count); - if (!(token = preproc_lexer_lex(lval, lloc, scanner))) - { -- ctx->last_was_eof = true; -+ preproc_get_top_buffer(ctx)->eof = true; - - /* If we have reached the end of an included file, inject a newline. */ - if (ctx->expansion_count) -@@ -781,6 +799,7 @@ bool preproc_push_include(struct preproc_ctx *ctx, char *filename, const struct - file->buffer.location.source_name = file->filename; - file->buffer.location.line = 1; - file->buffer.location.column = 1; -+ file->buffer.eof = false; - TRACE("File stack size is now %zu.\n", ctx->file_count); - ctx->last_was_newline = true; - return true; -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 1f967c22406..13ebde5cfd5 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -847,57 +847,6 @@ static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, enum vkd3d_s - vkd3d_shader_message_context_cleanup(&message_context); - } - --enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval, -- unsigned int index) --{ -- switch (sysval) -- { -- case VKD3D_SHADER_SV_COVERAGE: -- case VKD3D_SHADER_SV_DEPTH: -- case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL: -- case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL: -- case VKD3D_SHADER_SV_NONE: -- case VKD3D_SHADER_SV_STENCIL_REF: -- case VKD3D_SHADER_SV_TARGET: -- return VKD3D_SIV_NONE; -- case VKD3D_SHADER_SV_POSITION: -- return VKD3D_SIV_POSITION; -- case VKD3D_SHADER_SV_CLIP_DISTANCE: -- return VKD3D_SIV_CLIP_DISTANCE; -- case VKD3D_SHADER_SV_CULL_DISTANCE: -- return VKD3D_SIV_CULL_DISTANCE; -- case VKD3D_SHADER_SV_INSTANCE_ID: -- return VKD3D_SIV_INSTANCE_ID; -- case VKD3D_SHADER_SV_IS_FRONT_FACE: -- return VKD3D_SIV_IS_FRONT_FACE; -- case VKD3D_SHADER_SV_PRIMITIVE_ID: -- return VKD3D_SIV_PRIMITIVE_ID; -- case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX: -- return VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX; -- case VKD3D_SHADER_SV_SAMPLE_INDEX: -- return VKD3D_SIV_SAMPLE_INDEX; -- case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: -- return VKD3D_SIV_QUAD_U0_TESS_FACTOR + index; -- case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: -- return VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR + index; -- case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: -- return VKD3D_SIV_TRIANGLE_U_TESS_FACTOR + index; -- case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: -- return VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR; -- case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: -- return VKD3D_SIV_LINE_DETAIL_TESS_FACTOR; -- case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: -- return VKD3D_SIV_LINE_DENSITY_TESS_FACTOR; -- case VKD3D_SHADER_SV_VERTEX_ID: -- return VKD3D_SIV_VERTEX_ID; -- case VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX: -- return VKD3D_SIV_VIEWPORT_ARRAY_INDEX; -- default: -- FIXME("Unhandled sysval %#x, index %u.\n", sysval, index); -- return VKD3D_SIV_NONE; -- } --} -- - struct vkd3d_spirv_stream - { - uint32_t *words; -@@ -4239,7 +4188,7 @@ static bool spirv_compiler_get_register_info(struct spirv_compiler *compiler, - if (!(entry = rb_get(&compiler->symbol_table, ®_symbol))) - { - spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE, -- "Unrecognized register (%s).\n", debug_vkd3d_symbol(®_symbol)); -+ "Unrecognized register (%s).", debug_vkd3d_symbol(®_symbol)); - memset(register_info, 0, sizeof(*register_info)); - return false; - } -@@ -4578,70 +4527,6 @@ static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compil - return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); - } - --/* Based on the implementation in the OpenGL Mathematics library. */ --static uint32_t half_to_float(uint16_t value) --{ -- uint32_t s = (value & 0x8000u) << 16; -- uint32_t e = (value >> 10) & 0x1fu; -- uint32_t m = value & 0x3ffu; -- -- if (!e) -- { -- if (!m) -- { -- /* Plus or minus zero */ -- return s; -- } -- else -- { -- /* Denormalized number -- renormalize it */ -- -- while (!(m & 0x400u)) -- { -- m <<= 1; -- --e; -- } -- -- ++e; -- m &= ~0x400u; -- } -- } -- else if (e == 31u) -- { -- /* Positive or negative infinity for zero 'm'. -- * Nan for non-zero 'm' -- preserve sign and significand bits */ -- return s | 0x7f800000u | (m << 13); -- } -- -- /* Normalized number */ -- e += 127u - 15u; -- m <<= 13; -- -- /* Assemble s, e and m. */ -- return s | (e << 23) | m; --} -- --static uint32_t convert_raw_constant32(enum vkd3d_data_type data_type, unsigned int uint_value) --{ -- int16_t i; -- -- /* TODO: native 16-bit support. */ -- if (data_type != VKD3D_DATA_UINT16 && data_type != VKD3D_DATA_HALF) -- return uint_value; -- -- if (data_type == VKD3D_DATA_HALF) -- return half_to_float(uint_value); -- -- /* Values in DXIL have no signedness, so it is ambiguous whether 16-bit constants should or -- * should not be sign-extended when 16-bit execution is not supported. The AMD RX 580 Windows -- * driver has no 16-bit support, and sign-extends all 16-bit constant ints to 32 bits. These -- * results differ from SM 5. The RX 6750 XT supports 16-bit execution, so constants are not -- * extended, and results match SM 5. It seems best to replicate the sign-extension, and if -- * execution is 16-bit, the values will be truncated. */ -- i = uint_value; -- return (int32_t)i; --} -- - static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) - { -@@ -4654,15 +4539,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] = convert_raw_constant32(reg->data_type, reg->u.immconst_u32[0]); -+ values[i] = reg->u.immconst_u32[0]; - } - else - { - for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) - { - if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) -- values[j++] = convert_raw_constant32(reg->data_type, -- reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]); -+ values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]; - } - } - -@@ -4806,13 +4690,6 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil - - switch (icb->data_type) - { -- case VKD3D_DATA_HALF: -- case VKD3D_DATA_UINT16: -- /* Scalar only. */ -- for (i = 0; i < element_count; ++i) -- elements[i] = vkd3d_spirv_get_op_constant(builder, elem_type_id, -- convert_raw_constant32(icb->data_type, icb->data[i])); -- break; - case VKD3D_DATA_FLOAT: - case VKD3D_DATA_INT: - case VKD3D_DATA_UINT: -@@ -9254,7 +9131,9 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, - &src[3], VKD3DSP_WRITEMASK_0); - break; - default: -- ERR("Unexpected instruction %#x.\n", instruction->opcode); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, -+ "Unhandled instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - return; - } - -@@ -9935,7 +9814,9 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil - op = spirv_compiler_map_atomic_instruction(instruction); - if (op == SpvOpMax) - { -- ERR("Unexpected instruction %#x.\n", instruction->opcode); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, -+ "Unhandled instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - return; - } - -@@ -10014,9 +9895,9 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil - - if (instruction->flags & VKD3DARF_VOLATILE) - { -- WARN("Ignoring 'volatile' attribute.\n"); - spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_IGNORING_FLAG, -- "Ignoring the 'volatile' attribute flag for atomic instruction %#x.", instruction->opcode); -+ "Ignoring the 'volatile' attribute flag for atomic instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - } - - memory_semantic = (instruction->flags & VKD3DARF_SEQ_CST) -@@ -11091,9 +10972,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - /* nothing to do */ - break; - default: -- FIXME("Unhandled instruction %#x.\n", instruction->opcode); - spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER, -- "Encountered invalid/unhandled instruction handler %#x.", instruction->opcode); -+ "Unhandled instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - break; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 29b03871e05..ae3fa1650bf 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -261,6 +261,7 @@ enum vkd3d_sm4_opcode - VKD3D_SM4_OP_DCL_INPUT_PS_SGV = 0x63, - VKD3D_SM4_OP_DCL_INPUT_PS_SIV = 0x64, - VKD3D_SM4_OP_DCL_OUTPUT = 0x65, -+ VKD3D_SM4_OP_DCL_OUTPUT_SGV = 0x66, - VKD3D_SM4_OP_DCL_OUTPUT_SIV = 0x67, - VKD3D_SM4_OP_DCL_TEMPS = 0x68, - VKD3D_SM4_OP_DCL_INDEXABLE_TEMP = 0x69, -@@ -1168,7 +1169,7 @@ static void shader_sm4_read_dcl_input_ps(struct vkd3d_shader_instruction *ins, u - WARN("No matching signature element for input register %u with mask %#x.\n", - dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); - vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_DCL, -- "No matching signature element for input register %u with mask %#x.\n", -+ "No matching signature element for input register %u with mask %#x.", - dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); - } - else -@@ -1194,7 +1195,7 @@ static void shader_sm4_read_dcl_input_ps_siv(struct vkd3d_shader_instruction *in - WARN("No matching signature element for input register %u with mask %#x.\n", - dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); - vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_DCL, -- "No matching signature element for input register %u with mask %#x.\n", -+ "No matching signature element for input register %u with mask %#x.", - dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); - } - else -@@ -1559,6 +1560,8 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) - shader_sm4_read_dcl_input_ps_siv}, - {VKD3D_SM4_OP_DCL_OUTPUT, VKD3DSIH_DCL_OUTPUT, "", "", - shader_sm4_read_declaration_dst}, -+ {VKD3D_SM4_OP_DCL_OUTPUT_SGV, VKD3DSIH_DCL_OUTPUT_SGV, "", "", -+ shader_sm4_read_declaration_register_semantic}, - {VKD3D_SM4_OP_DCL_OUTPUT_SIV, VKD3DSIH_DCL_OUTPUT_SIV, "", "", - shader_sm4_read_declaration_register_semantic}, - {VKD3D_SM4_OP_DCL_TEMPS, VKD3DSIH_DCL_TEMPS, "", "", -@@ -3129,6 +3132,9 @@ bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *s - {"position", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_POSITION}, - {"sv_position", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_POSITION}, - {"sv_primitiveid", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_PRIMITIVE_ID}, -+ {"sv_isfrontface", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_IS_FRONT_FACE}, -+ {"sv_rendertargetarrayindex", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX}, -+ {"sv_viewportarrayindex", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX}, - - {"sv_outputcontrolpointid", false, VKD3D_SHADER_TYPE_HULL, ~0u}, - {"sv_position", false, VKD3D_SHADER_TYPE_HULL, ~0u}, -@@ -3255,6 +3261,8 @@ static int signature_element_pointer_compare(const void *x, const void *y) - const struct signature_element *f = *(const struct signature_element **)y; - int ret; - -+ if ((ret = vkd3d_u32_compare(e->stream_index, f->stream_index))) -+ return ret; - if ((ret = vkd3d_u32_compare(e->register_index, f->register_index))) - return ret; - return vkd3d_u32_compare(e->mask, f->mask); -@@ -3263,12 +3271,17 @@ static int signature_element_pointer_compare(const void *x, const void *y) - static void tpf_write_signature(struct tpf_compiler *tpf, const struct shader_signature *signature, uint32_t tag) - { - bool has_minimum_precision = tpf->program->global_flags & VKD3DSGF_ENABLE_MINIMUM_PRECISION; -- bool output = tag == TAG_OSGN || (tag == TAG_PCSG -- && tpf->program->shader_version.type == VKD3D_SHADER_TYPE_HULL); -+ const struct vkd3d_shader_version *version = &tpf->program->shader_version; - const struct signature_element **sorted_elements; - struct vkd3d_bytecode_buffer buffer = {0}; -+ bool has_stream_index, output; - unsigned int i; - -+ output = tag == TAG_OSGN || (tag == TAG_PCSG && version->type == VKD3D_SHADER_TYPE_HULL); -+ if (output && version->type == VKD3D_SHADER_TYPE_GEOMETRY && version->major >= 5) -+ tag = TAG_OSG5; -+ has_stream_index = tag == TAG_OSG5 || has_minimum_precision; -+ - put_u32(&buffer, signature->element_count); - put_u32(&buffer, 8); /* unknown */ - -@@ -3291,8 +3304,8 @@ static void tpf_write_signature(struct tpf_compiler *tpf, const struct shader_si - if (sysval >= VKD3D_SHADER_SV_TARGET) - sysval = VKD3D_SHADER_SV_NONE; - -- if (has_minimum_precision) -- put_u32(&buffer, 0); /* FIXME: stream index */ -+ if (has_stream_index) -+ put_u32(&buffer, element->stream_index); - put_u32(&buffer, 0); /* name */ - put_u32(&buffer, element->semantic_index); - put_u32(&buffer, sysval); -@@ -3306,13 +3319,16 @@ static void tpf_write_signature(struct tpf_compiler *tpf, const struct shader_si - for (i = 0; i < signature->element_count; ++i) - { - const struct signature_element *element = sorted_elements[i]; -+ size_t name_index = 2 + i * 6; - size_t string_offset; - -- string_offset = put_string(&buffer, element->semantic_name); -+ if (has_stream_index) -+ name_index += i + 1; - if (has_minimum_precision) -- set_u32(&buffer, (2 + i * 8 + 1) * sizeof(uint32_t), string_offset); -- else -- set_u32(&buffer, (2 + i * 6) * sizeof(uint32_t), string_offset); -+ name_index += i; -+ -+ string_offset = put_string(&buffer, element->semantic_name); -+ set_u32(&buffer, name_index * sizeof(uint32_t), string_offset); - } - - if (has_minimum_precision) -@@ -3843,9 +3859,8 @@ static uint32_t pack_resource_data_type(const enum vkd3d_data_type *resource_dat - - static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_shader_instruction *ins) - { -- const struct vkd3d_shader_structured_resource *structured_resource = &ins->declaration.structured_resource; -- const struct vkd3d_shader_semantic *semantic = &ins->declaration.semantic; - const struct vkd3d_shader_version *version = &tpf->program->shader_version; -+ const struct vkd3d_shader_resource *resource; - const struct vkd3d_sm4_opcode_info *info; - struct sm4_instruction instr = {0}; - bool uav; -@@ -3859,27 +3874,38 @@ static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_s - - instr.opcode = info->opcode; - -- instr.dsts[0] = semantic->resource.reg; -- instr.dst_count = 1; -- - if (ins->opcode == VKD3DSIH_DCL || ins->opcode == VKD3DSIH_DCL_UAV_TYPED) - { -- instr.idx[0] = pack_resource_data_type(semantic->resource_data_type); -+ instr.idx[0] = pack_resource_data_type(ins->declaration.semantic.resource_data_type); - instr.idx_count = 1; -+ instr.extra_bits |= ins->declaration.semantic.sample_count << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; -+ resource = &ins->declaration.semantic.resource; -+ } -+ else if (ins->opcode == VKD3DSIH_DCL_RESOURCE_RAW || ins->opcode == VKD3DSIH_DCL_UAV_RAW) -+ { -+ resource = &ins->declaration.raw_resource.resource; -+ } -+ else -+ { -+ instr.byte_stride = ins->declaration.structured_resource.byte_stride; -+ resource = &ins->declaration.structured_resource.resource; - } - -+ instr.dsts[0] = resource->reg; -+ instr.dst_count = 1; -+ - if (vkd3d_shader_ver_ge(version, 5, 1)) - { -- instr.dsts[0].reg.idx[0].offset = semantic->resource.reg.reg.idx[0].offset; -- instr.dsts[0].reg.idx[1].offset = semantic->resource.range.first; -- instr.dsts[0].reg.idx[2].offset = semantic->resource.range.last; -+ instr.dsts[0].reg.idx[0].offset = resource->reg.reg.idx[0].offset; -+ instr.dsts[0].reg.idx[1].offset = resource->range.first; -+ instr.dsts[0].reg.idx[2].offset = resource->range.last; - instr.dsts[0].reg.idx_count = 3; - -- instr.idx[instr.idx_count++] = semantic->resource.range.space; -+ instr.idx[instr.idx_count++] = resource->range.space; - } - else - { -- instr.dsts[0].reg.idx[0].offset = semantic->resource.range.first; -+ instr.dsts[0].reg.idx[0].offset = resource->range.first; - instr.dsts[0].reg.idx_count = 1; - } - -@@ -3887,10 +3913,6 @@ static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_s - instr.extra_bits |= ins->flags << VKD3D_SM5_UAV_FLAGS_SHIFT; - - instr.extra_bits |= (sm4_resource_dimension(ins->resource_type) << VKD3D_SM4_RESOURCE_TYPE_SHIFT); -- instr.extra_bits |= semantic->sample_count << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; -- -- if (ins->structured) -- instr.byte_stride = structured_resource->byte_stride; - - write_sm4_instruction(tpf, &instr); - } -@@ -4135,6 +4157,10 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ - tpf_dcl_semantic(tpf, VKD3D_SM4_OP_DCL_OUTPUT, &ins->declaration.dst, 0); - break; - -+ case VKD3DSIH_DCL_OUTPUT_SGV: -+ tpf_dcl_siv_semantic(tpf, VKD3D_SM4_OP_DCL_OUTPUT_SGV, &ins->declaration.register_semantic, 0); -+ break; -+ - case VKD3DSIH_DCL_OUTPUT_SIV: - tpf_dcl_siv_semantic(tpf, VKD3D_SM4_OP_DCL_OUTPUT_SIV, &ins->declaration.register_semantic, 0); - break; -@@ -4166,6 +4192,8 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ - case VKD3DSIH_CASE: - case VKD3DSIH_CONTINUE: - case VKD3DSIH_CUT: -+ case VKD3DSIH_CUT_STREAM: -+ case VKD3DSIH_DCL_STREAM: - case VKD3DSIH_DEFAULT: - case VKD3DSIH_DISCARD: - case VKD3DSIH_DIV: -@@ -4180,6 +4208,7 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ - case VKD3DSIH_DSY_FINE: - case VKD3DSIH_ELSE: - case VKD3DSIH_EMIT: -+ case VKD3DSIH_EMIT_STREAM: - case VKD3DSIH_ENDIF: - case VKD3DSIH_ENDLOOP: - case VKD3DSIH_ENDSWITCH: -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index f56608940db..783f4e6134c 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') -@@ -336,7 +338,10 @@ bool vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_cont - 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) - { -- if (context->log_level < level) -+ struct vkd3d_string_buffer *messages = &context->messages; -+ size_t pos = messages->content_size; -+ -+ if (!WARN_ON() && context->log_level < level) - return; - - if (location) -@@ -344,19 +349,26 @@ void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const stru - const char *source_name = location->source_name ? location->source_name : ""; - - if (location->line) -- vkd3d_string_buffer_printf(&context->messages, "%s:%u:%u: ", -+ vkd3d_string_buffer_printf(messages, "%s:%u:%u: ", - source_name, location->line, location->column); - else -- vkd3d_string_buffer_printf(&context->messages, "%s: ", source_name); -+ vkd3d_string_buffer_printf(messages, "%s: ", source_name); - } -- vkd3d_string_buffer_vprintf(&context->messages, format, args); -- vkd3d_string_buffer_printf(&context->messages, "\n"); -+ vkd3d_string_buffer_vprintf(messages, format, args); -+ vkd3d_string_buffer_printf(messages, "\n"); -+ -+ WARN("%.*s", (int)(messages->content_size - pos), &messages->buffer[pos]); -+ if (context->log_level < level) -+ messages->content_size = pos; - } - - 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) - { -- if (context->log_level < VKD3D_SHADER_LOG_WARNING) -+ struct vkd3d_string_buffer *messages = &context->messages; -+ size_t pos = messages->content_size; -+ -+ if (!WARN_ON() && context->log_level < VKD3D_SHADER_LOG_WARNING) - return; - - if (location) -@@ -364,17 +376,21 @@ void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const s - const char *source_name = location->source_name ? location->source_name : ""; - - if (location->line) -- vkd3d_string_buffer_printf(&context->messages, "%s:%u:%u: W%04u: ", -+ vkd3d_string_buffer_printf(messages, "%s:%u:%u: W%04u: ", - source_name, location->line, location->column, error); - else -- vkd3d_string_buffer_printf(&context->messages, "%s: W%04u: ", source_name, error); -+ vkd3d_string_buffer_printf(messages, "%s: W%04u: ", source_name, error); - } - else - { -- vkd3d_string_buffer_printf(&context->messages, "W%04u: ", error); -+ vkd3d_string_buffer_printf(messages, "W%04u: ", error); - } -- vkd3d_string_buffer_vprintf(&context->messages, format, args); -- vkd3d_string_buffer_printf(&context->messages, "\n"); -+ vkd3d_string_buffer_vprintf(messages, format, args); -+ vkd3d_string_buffer_printf(messages, "\n"); -+ -+ WARN("%.*s", (int)(messages->content_size - pos), &messages->buffer[pos]); -+ if (context->log_level < VKD3D_SHADER_LOG_WARNING) -+ messages->content_size = pos; - } - - void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, -@@ -390,7 +406,10 @@ void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const st - 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) - { -- if (context->log_level < VKD3D_SHADER_LOG_ERROR) -+ struct vkd3d_string_buffer *messages = &context->messages; -+ size_t pos = messages->content_size; -+ -+ if (!WARN_ON() && context->log_level < VKD3D_SHADER_LOG_ERROR) - return; - - if (location) -@@ -398,17 +417,21 @@ void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const str - const char *source_name = location->source_name ? location->source_name : ""; - - if (location->line) -- vkd3d_string_buffer_printf(&context->messages, "%s:%u:%u: E%04u: ", -+ vkd3d_string_buffer_printf(messages, "%s:%u:%u: E%04u: ", - source_name, location->line, location->column, error); - else -- vkd3d_string_buffer_printf(&context->messages, "%s: E%04u: ", source_name, error); -+ vkd3d_string_buffer_printf(messages, "%s: E%04u: ", source_name, error); - } - else - { -- vkd3d_string_buffer_printf(&context->messages, "E%04u: ", error); -+ vkd3d_string_buffer_printf(messages, "E%04u: ", error); - } -- vkd3d_string_buffer_vprintf(&context->messages, format, args); -- vkd3d_string_buffer_printf(&context->messages, "\n"); -+ vkd3d_string_buffer_vprintf(messages, format, args); -+ vkd3d_string_buffer_printf(messages, "\n"); -+ -+ WARN("%.*s", (int)(messages->content_size - pos), &messages->buffer[pos]); -+ if (context->log_level < VKD3D_SHADER_LOG_ERROR) -+ messages->content_size = pos; - } - - void vkd3d_shader_error(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, -@@ -1413,13 +1436,14 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte - if (context->cf_info_count) - context->cf_info[context->cf_info_count - 1].inside_block = false; - break; -- case VKD3DSIH_TEX: -+ case VKD3DSIH_TEXLD: - if (context->version->major == 1) - sampler_reg = &instruction->dst[0].reg; - else - sampler_reg = &instruction->src[1].reg; - vkd3d_shader_scan_combined_sampler_usage(context, sampler_reg, sampler_reg); - break; -+ case VKD3DSIH_TEX: - case VKD3DSIH_TEXBEM: - case VKD3DSIH_TEXBEML: - case VKD3DSIH_TEXDP3TEX: -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 3b4fb626fcc..a5d1b8f4e05 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -174,6 +174,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_ERROR_HLSL_INVALID_MAX_VERTEX_COUNT = 5042, - VKD3D_SHADER_ERROR_HLSL_MISSING_PRIMITIVE_TYPE = 5043, - VKD3D_SHADER_ERROR_HLSL_MISPLACED_STREAM_OUTPUT = 5044, -+ VKD3D_SHADER_ERROR_HLSL_MISSING_INPUT_PATCH = 5045, - - VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, - VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, -@@ -222,6 +223,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES = 8017, - VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES = 8018, - VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE = 8019, -+ VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT = 8020, - - VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300, - VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301, -@@ -337,6 +339,7 @@ enum vkd3d_shader_opcode - VKD3DSIH_DCL_INTERFACE, - VKD3DSIH_DCL_OUTPUT, - VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT, -+ VKD3DSIH_DCL_OUTPUT_SGV, - VKD3DSIH_DCL_OUTPUT_SIV, - VKD3DSIH_DCL_OUTPUT_TOPOLOGY, - VKD3DSIH_DCL_RESOURCE_RAW, -@@ -550,10 +553,12 @@ enum vkd3d_shader_opcode - VKD3DSIH_TEXBEM, - VKD3DSIH_TEXBEML, - VKD3DSIH_TEXCOORD, -+ VKD3DSIH_TEXCRD, - VKD3DSIH_TEXDEPTH, - VKD3DSIH_TEXDP3, - VKD3DSIH_TEXDP3TEX, - VKD3DSIH_TEXKILL, -+ VKD3DSIH_TEXLD, - VKD3DSIH_TEXLDD, - VKD3DSIH_TEXLDL, - VKD3DSIH_TEXM3x2DEPTH, -@@ -607,6 +612,8 @@ enum vkd3d_shader_opcode - VKD3DSIH_COUNT, - }; - -+const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error); -+ - enum vkd3d_shader_register_type - { - VKD3DSPR_TEMP, -@@ -964,7 +971,7 @@ struct vkd3d_shader_register - enum vsir_dimension dimension; - /* known address alignment for optimisation, or zero */ - unsigned int alignment; -- union -+ union vsir_immediate_constant - { - uint32_t immconst_u32[VKD3D_VEC4_SIZE]; - float immconst_f32[VKD3D_VEC4_SIZE]; -@@ -1332,12 +1339,6 @@ static inline bool register_is_constant_or_undef(const struct vkd3d_shader_regis - return register_is_constant(reg) || register_is_undef(reg); - } - --static inline bool register_is_scalar_constant_zero(const struct vkd3d_shader_register *reg) --{ -- return register_is_constant(reg) && reg->dimension == VSIR_DIMENSION_SCALAR -- && (data_type_is_64_bit(reg->data_type) ? !reg->u.immconst_u64[0] : !reg->u.immconst_u32[0]); --} -- - static inline bool register_is_numeric_array(const struct vkd3d_shader_register *reg) - { - return (reg->type == VKD3DSPR_IMMCONSTBUFFER || reg->type == VKD3DSPR_IDXTEMP -@@ -1779,14 +1780,6 @@ static inline bool component_type_is_64_bit(enum vkd3d_shader_component_type com - return component_type == VKD3D_SHADER_COMPONENT_DOUBLE || component_type == VKD3D_SHADER_COMPONENT_UINT64; - } - --enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval, -- unsigned int index); -- --static inline enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum vkd3d_shader_sysval_semantic sysval) --{ -- return vkd3d_siv_from_sysval_indexed(sysval, 0); --} -- - static inline unsigned int vsir_write_mask_get_component_idx(uint32_t write_mask) - { - unsigned int i; -diff --git a/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c b/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c -index f2b18b665f8..c41f8bae806 100644 ---- a/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c -+++ b/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c -@@ -19,6 +19,8 @@ - #include "vkd3d_utils_private.h" - #undef D3D12CreateDevice - -+/* VKD3D_DEBUG_ENV_NAME("VKD3D_DEBUG"); */ -+ - static const char *debug_d3d_blob_part(D3D_BLOB_PART part) - { - switch (part) --- -2.47.2 - diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-7c0da1747a89a8cea27a42ace51b318e9d8.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-7c0da1747a89a8cea27a42ace51b318e9d8.patch deleted file mode 100644 index 0f56e4d8..00000000 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-7c0da1747a89a8cea27a42ace51b318e9d8.patch +++ /dev/null @@ -1,501 +0,0 @@ -From ad3d348b686e70d3109c81e59161ab873fb2271a Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Wed, 18 Jun 2025 08:49:39 +1000 -Subject: [PATCH] Updated vkd3d to 7c0da1747a89a8cea27a42ace51b318e9d843a19. - ---- - libs/vkd3d/include/vkd3d_shader.h | 6 + - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 13 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 12 +- - libs/vkd3d/libs/vkd3d-shader/fx.c | 120 +++++++++++++----- - libs/vkd3d/libs/vkd3d-shader/ir.c | 10 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 24 ++-- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 14 ++ - .../libs/vkd3d-shader/vkd3d_shader_private.h | 4 +- - 8 files changed, 154 insertions(+), 49 deletions(-) - -diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h -index 30b6a070018..b50271ce9bb 100644 ---- a/libs/vkd3d/include/vkd3d_shader.h -+++ b/libs/vkd3d/include/vkd3d_shader.h -@@ -1431,6 +1431,11 @@ enum vkd3d_shader_source_type - * Input is a raw FX section without container. \since 1.14 - */ - VKD3D_SHADER_SOURCE_FX, -+ /** -+ * A D3DX texture shader. This is the format used for the 'tx_1_0' HLSL -+ * target profile. \since 1.17 -+ */ -+ VKD3D_SHADER_SOURCE_TX, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SOURCE_TYPE), - }; -@@ -2761,6 +2766,7 @@ VKD3D_SHADER_API const enum vkd3d_shader_target_type *vkd3d_shader_get_supported - * - VKD3D_SHADER_SOURCE_HLSL to VKD3D_SHADER_TARGET_DXBC_TPF - * - VKD3D_SHADER_SOURCE_HLSL to VKD3D_SHADER_TARGET_FX - * - VKD3D_SHADER_SOURCE_FX to VKD3D_SHADER_TARGET_D3D_ASM -+ * - VKD3D_SHADER_SOURCE_TX to VKD3D_SHADER_TARGET_D3D_ASM - * - * Supported transformations can also be detected at runtime with the functions - * vkd3d_shader_get_supported_source_types() and -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index c8291afcf6e..fbc0235cdd0 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -1830,6 +1830,7 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct v - struct vkd3d_bytecode_buffer *buffer = &d3dbc->buffer; - const struct vkd3d_shader_src_param *src; - const struct vkd3d_sm1_opcode_info *info; -+ size_t size, token_position; - unsigned int i; - uint32_t token; - -@@ -1842,9 +1843,7 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct v - token = info->sm1_opcode; - token |= VKD3D_SM1_INSTRUCTION_FLAGS_MASK & (ins->flags << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT); - -- if (version->major > 1) -- token |= (ins->dst_count + ins->src_count) << VKD3D_SM1_INSTRUCTION_LENGTH_SHIFT; -- put_u32(buffer, token); -+ token_position = put_u32(buffer, 0); - - for (i = 0; i < ins->dst_count; ++i) - { -@@ -1864,6 +1863,14 @@ static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct v - if (src->reg.idx_count && src->reg.idx[0].rel_addr) - write_sm1_src_register(buffer, src->reg.idx[0].rel_addr); - } -+ -+ if (version->major > 1) -+ { -+ size = (bytecode_get_size(buffer) - token_position) / sizeof(uint32_t); -+ token |= ((size - 1) << VKD3D_SM1_INSTRUCTION_LENGTH_SHIFT); -+ } -+ -+ set_u32(buffer, token_position, token); - }; - - static void d3dbc_write_texkill(struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_instruction *ins) -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 53578ce7141..1c7ed0d9e11 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -2271,9 +2271,19 @@ static inline bool sm6_value_is_constant(const struct sm6_value *value) - - static bool sm6_value_is_constant_zero(const struct sm6_value *value) - { -- if (value->value_type != VALUE_TYPE_CONSTANT || value->type->class != TYPE_CLASS_INTEGER) -+ if (value->value_type != VALUE_TYPE_CONSTANT) - return false; - -+ switch (value->type->class) -+ { -+ case TYPE_CLASS_INTEGER: -+ case TYPE_CLASS_FLOAT: -+ break; -+ -+ default: -+ return false; -+ } -+ - if (value->type->u.width == 64) - return value->u.constant.immconst.immconst_u64[0] == 0; - else -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index f7b2e3d7d13..95a172fd827 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -65,6 +65,7 @@ enum fxlvm_constants - FX_FXLC_REG_CB = 2, - FX_FXLC_REG_OUTPUT = 4, - FX_FXLC_REG_TEMP = 7, -+ FX_FXLC_REG_MAX = FX_FXLC_REG_TEMP, - }; - - struct rhs_named_value -@@ -3533,6 +3534,7 @@ int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - - struct fx_parser - { -+ enum vkd3d_shader_source_type source_type; - const uint8_t *ptr, *start, *end; - struct vkd3d_shader_message_context *message_context; - struct vkd3d_string_buffer buffer; -@@ -4252,24 +4254,6 @@ static void fx_parse_fx_2_data_blob(struct fx_parser *parser) - fx_parser_skip(parser, align(size, 4)); - } - --static void fx_dump_blob(struct fx_parser *parser, const void *blob, uint32_t size) --{ -- const uint32_t *data = blob; -- unsigned int i, j, n; -- -- size /= sizeof(*data); -- i = 0; -- while (i < size) -- { -- parse_fx_print_indent(parser); -- n = min(size - i, 8); -- for (j = 0; j < n; ++j) -- vkd3d_string_buffer_printf(&parser->buffer, "0x%08x,", data[i + j]); -- i += n; -- vkd3d_string_buffer_printf(&parser->buffer, "\n"); -- } --} -- - static void fx_2_parse_fxlvm_expression(struct fx_parser *parser, const uint32_t *blob, uint32_t size); - - static void fx_parse_fx_2_array_selector(struct fx_parser *parser) -@@ -4313,7 +4297,7 @@ static void fx_parse_fx_2_complex_state(struct fx_parser *parser) - uint32_t state; - uint32_t assignment_type; - } state; -- const char *data; -+ const uint32_t *data; - uint32_t size; - - fx_parser_read_u32s(parser, &state, sizeof(state)); -@@ -4339,14 +4323,19 @@ static void fx_parse_fx_2_complex_state(struct fx_parser *parser) - { - fx_parse_fx_2_array_selector(parser); - } -- else -+ else if (state.assignment_type == FX_2_ASSIGNMENT_CODE_BLOB) - { - size = fx_parser_read_u32(parser); -- vkd3d_string_buffer_printf(&parser->buffer, "blob size %u\n", size); - data = fx_parser_get_ptr(parser, size); -- fx_dump_blob(parser, data, size); -+ vkd3d_string_buffer_printf(&parser->buffer, "blob size %u\n", size); -+ fx_2_parse_fxlvm_expression(parser, data, size); - fx_parser_skip(parser, align(size, 4)); - } -+ else -+ { -+ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, -+ "Unknown state assignment type %u.", state.assignment_type); -+ } - } - - static void fx_2_parse(struct fx_parser *parser) -@@ -4774,7 +4763,9 @@ fxlc_opcodes[] = - { 0x236, "ushr" }, - { 0x301, "movc" }, - { 0x500, "dot" }, -+ { 0x502, "noise" }, - { 0x70e, "d3ds_dotswiz" }, -+ { 0x711, "d3ds_noiseswiz" }, - }; - - static const char *get_fxlc_opcode_name(uint32_t opcode) -@@ -4790,13 +4781,6 @@ static const char *get_fxlc_opcode_name(uint32_t opcode) - return ""; - } - --struct fx_4_fxlc_argument --{ -- uint32_t flags; -- uint32_t reg_type; -- uint32_t address; --}; -- - struct fx_4_ctab_entry - { - uint32_t name; -@@ -4951,8 +4935,38 @@ static void fx_print_fxlc_literal(struct fx_parser *parser, uint32_t address, st - - static void fx_print_fxlc_argument(struct fx_parser *parser, const struct fxlc_arg *arg, struct fxlvm_code *code) - { -+ static const char *table_names[FX_FXLC_REG_MAX + 1] = -+ { -+ [FX_FXLC_REG_LITERAL] = "imm", -+ [FX_FXLC_REG_CB] = "cb", -+ [FX_FXLC_REG_OUTPUT] = "o", -+ [FX_FXLC_REG_TEMP] = "r", -+ }; - uint32_t count; - -+ if (arg->reg_type > FX_FXLC_REG_MAX) -+ { -+ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, -+ "Unexpected register type %u.", arg->reg_type); -+ return; -+ } -+ -+ if (arg->index.reg_type > FX_FXLC_REG_MAX) -+ { -+ fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, -+ "Unexpected index register type %u.", arg->index.reg_type); -+ return; -+ } -+ -+ if (arg->indexed) -+ { -+ vkd3d_string_buffer_printf(&parser->buffer, "%s[%u + %s%u.%c]", table_names[arg->reg_type], -+ arg->address, table_names[arg->index.reg_type], arg->index.address, -+ "xyzw"[arg->index.address % 4]); -+ fx_parse_print_swizzle(parser, code, arg->address); -+ return; -+ } -+ - switch (arg->reg_type) - { - case FX_FXLC_REG_LITERAL: -@@ -4999,9 +5013,14 @@ static void fx_parse_fxlvm_expression(struct fx_parser *parser, struct fxlvm_cod - uint32_t ins_count; - size_t i, j; - -- ins_count = fxlvm_read_u32(code); -- - parse_fx_start_indent(parser); -+ if (parser->source_type == VKD3D_SHADER_SOURCE_TX) -+ { -+ parse_fx_print_indent(parser); -+ vkd3d_string_buffer_printf(&parser->buffer, "tx_1_0\n"); -+ } -+ -+ ins_count = fxlvm_read_u32(code); - - for (i = 0; i < ins_count; ++i) - { -@@ -5055,6 +5074,9 @@ static void fx_2_parse_fxlvm_expression(struct fx_parser *parser, const uint32_t - uint32_t section_size; - const uint32_t *data; - -+ if (!blob) -+ return; -+ - /* Literal constants, using 64-bit floats. */ - if ((data = find_d3dbc_section(blob, count, TAG_CLIT, §ion_size))) - { -@@ -5619,6 +5641,7 @@ static void fx_parser_init(struct fx_parser *parser, const struct vkd3d_shader_c - struct vkd3d_shader_message_context *message_context) - { - memset(parser, 0, sizeof(*parser)); -+ parser->source_type = compile_info->source_type; - parser->start = compile_info->source.code; - parser->ptr = compile_info->source.code; - parser->end = (uint8_t *)compile_info->source.code + compile_info->source.size; -@@ -5679,3 +5702,38 @@ int fx_parse(const struct vkd3d_shader_compile_info *compile_info, - return VKD3D_ERROR_INVALID_SHADER; - return VKD3D_OK; - } -+ -+int tx_parse(const struct vkd3d_shader_compile_info *compile_info, -+ struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) -+{ -+ struct fx_parser parser; -+ uint32_t version; -+ -+ fx_parser_init(&parser, compile_info, message_context); -+ -+ if (parser.end - parser.start < sizeof(version)) -+ { -+ fx_parser_error(&parser, VKD3D_SHADER_ERROR_FX_INVALID_SIZE, -+ "Source size %zu is smaller than the TX header size.", compile_info->source.size); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ version = *(uint32_t *)parser.ptr; -+ -+ switch (version) -+ { -+ case 0x54580100: -+ fx_2_parse_fxlvm_expression(&parser, (const uint32_t *)parser.ptr, parser.end - parser.ptr); -+ break; -+ default: -+ fx_parser_error(&parser, VKD3D_SHADER_ERROR_FX_INVALID_VERSION, -+ "Invalid texture shader binary version value 0x%08x.", version); -+ break; -+ } -+ -+ vkd3d_shader_code_from_string_buffer(out, &parser.buffer); -+ fx_parser_cleanup(&parser); -+ -+ if (parser.failed) -+ return VKD3D_ERROR_INVALID_SHADER; -+ return VKD3D_OK; -+} -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 0aebfea2add..7546a1f557b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -9273,7 +9273,7 @@ static void vsir_validate_hull_shader_phase(struct validation_context *ctx, - const struct vkd3d_shader_instruction *instruction) - { - if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE, - "Phase instruction \"%s\" (%#x) is only valid in a hull shader.", - vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - if (ctx->depth != 0) -@@ -9359,7 +9359,7 @@ static void vsir_validate_dcl_index_range(struct validation_context *ctx, - - if (ctx->program->normalisation_level >= VSIR_NORMALISED_SM6) - { -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE, - "DCL_INDEX_RANGE is not allowed with fully normalised input/output."); - return; - } -@@ -10026,8 +10026,8 @@ static void vsir_validate_instruction(struct validation_context *ctx) - - if (instruction->opcode >= VKD3DSIH_INVALID) - { -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Invalid instruction handler %#x.", -- instruction->opcode); -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE, -+ "Invalid opcode %#x.", instruction->opcode); - } - - if (version->type == VKD3D_SHADER_TYPE_HULL && ctx->phase == VKD3DSIH_INVALID) -@@ -10043,7 +10043,7 @@ static void vsir_validate_instruction(struct validation_context *ctx) - - default: - if (!vsir_instruction_is_dcl(instruction)) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE, - "Instruction \"%s\" (%#x) appears before any phase instruction in a hull shader.", - vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 13ebde5cfd5..debf7ac29f5 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -7639,9 +7639,9 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil - - if (op == SpvOpMax) - { -- ERR("Unexpected instruction %#x.\n", instruction->opcode); - spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER, -- "Encountered invalid/unhandled instruction handler %#x.", instruction->opcode); -+ "Encountered invalid/unhandled instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - return VKD3D_ERROR_INVALID_SHADER; - } - -@@ -7761,16 +7761,18 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp - || instruction->opcode == VKD3DSIH_FIRSTBIT_LO || instruction->opcode == VKD3DSIH_FIRSTBIT_SHI)) - { - /* At least some drivers support this anyway, but if validation is enabled it will fail. */ -- FIXME("Unsupported 64-bit source for handler %#x.\n", instruction->opcode); - spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, -- "64-bit source for handler %#x is not supported.", instruction->opcode); -+ "64-bit source for instruction \"%s\" (%#x) is not supported.", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - return; - } - - glsl_inst = spirv_compiler_map_ext_glsl_instruction(instruction); - if (glsl_inst == GLSLstd450Bad) - { -- ERR("Unexpected instruction %#x.\n", instruction->opcode); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, -+ "Unhandled instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - return; - } - -@@ -8294,7 +8296,9 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp - case VKD3DSIH_IBFE: op = SpvOpBitFieldSExtract; break; - case VKD3DSIH_UBFE: op = SpvOpBitFieldUExtract; break; - default: -- ERR("Unexpected instruction %#x.\n", instruction->opcode); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, -+ "Unhandled instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - return; - } - -@@ -8427,7 +8431,9 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co - case VKD3DSIH_UGE: op = SpvOpUGreaterThanEqual; break; - case VKD3DSIH_ULT: op = SpvOpULessThan; break; - default: -- ERR("Unexpected instruction %#x.\n", instruction->opcode); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, -+ "Unhandled instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - return; - } - -@@ -8813,7 +8819,9 @@ static void spirv_compiler_emit_deriv_instruction(struct spirv_compiler *compile - } - if (!info) - { -- ERR("Unexpected instruction %#x.\n", instruction->opcode); -+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, -+ "Unhandled instruction \"%s\" (%#x).", -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); - return; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index 783f4e6134c..2cd23cba1f5 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -1829,6 +1829,10 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, - { - ret = fx_parse(compile_info, out, &message_context); - } -+ else if (compile_info->source_type == VKD3D_SHADER_SOURCE_TX) -+ { -+ ret = tx_parse(compile_info, out, &message_context); -+ } - else - { - uint64_t config_flags = vkd3d_shader_init_config_flags(); -@@ -2037,6 +2041,7 @@ const enum vkd3d_shader_source_type *vkd3d_shader_get_supported_source_types(uns - VKD3D_SHADER_SOURCE_D3D_BYTECODE, - VKD3D_SHADER_SOURCE_DXBC_DXIL, - VKD3D_SHADER_SOURCE_FX, -+ VKD3D_SHADER_SOURCE_TX, - }; - - TRACE("count %p.\n", count); -@@ -2101,6 +2106,11 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( - VKD3D_SHADER_TARGET_D3D_ASM, - }; - -+ static const enum vkd3d_shader_target_type tx_types[] = -+ { -+ VKD3D_SHADER_TARGET_D3D_ASM, -+ }; -+ - TRACE("source_type %#x, count %p.\n", source_type, count); - - switch (source_type) -@@ -2125,6 +2135,10 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( - *count = ARRAY_SIZE(fx_types); - return fx_types; - -+ case VKD3D_SHADER_SOURCE_TX: -+ *count = ARRAY_SIZE(tx_types); -+ return tx_types; -+ - default: - *count = 0; - return NULL; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index a5d1b8f4e05..2ae0a57d237 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -238,7 +238,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_WARNING_DXIL_UNDEFINED_OPERAND = 8310, - - VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, -- VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001, -+ VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE = 9001, - VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE = 9002, - VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK = 9003, - VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS = 9004, -@@ -1683,6 +1683,8 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con - struct vkd3d_shader_message_context *message_context, struct vsir_program *program); - int fx_parse(const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); -+int tx_parse(const struct vkd3d_shader_compile_info *compile_info, -+ struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); - - void free_dxbc_shader_desc(struct dxbc_shader_desc *desc); - --- -2.47.2 - diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-ba545669cd09682960f5da17b9131780642.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-ba545669cd09682960f5da17b9131780642.patch new file mode 100644 index 00000000..108a01fd --- /dev/null +++ b/patches/vkd3d-latest/0002-Updated-vkd3d-to-ba545669cd09682960f5da17b9131780642.patch @@ -0,0 +1,135 @@ +From 627c38f9a349c433c1b5c886e5cb966f80dc4700 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Thu, 17 Jul 2025 07:20:27 +1000 +Subject: [PATCH] Updated vkd3d to ba545669cd09682960f5da17b9131780642daf8e. + +--- + libs/vkd3d/libs/vkd3d-shader/ir.c | 46 +++++++++++++++++++ + .../libs/vkd3d-shader/vkd3d_shader_private.h | 1 + + libs/vkd3d/libs/vkd3d/state.c | 20 ++------ + 3 files changed, 51 insertions(+), 16 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index fe7e8c54dfb..b060ccbb2bc 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -10479,6 +10479,7 @@ static void vsir_validate_descriptors(struct validation_context *ctx) + for (i = 0; i < descriptors->descriptor_count; ++i) + { + const struct vkd3d_shader_descriptor_info1 *descriptor = &descriptors->descriptors[i]; ++ uint32_t flags_mask = 0, uav_flags_mask = 0; + + if (descriptor->type >= VKD3D_SHADER_DESCRIPTOR_TYPE_COUNT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DESCRIPTOR_TYPE, +@@ -10507,6 +10508,43 @@ static void vsir_validate_descriptors(struct validation_context *ctx) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DESCRIPTOR_COUNT, + "Descriptor %u has invalid descriptor count %u starting at index %u.", + i, descriptor->count, descriptor->register_index); ++ ++ switch (descriptor->type) ++ { ++ case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV: ++ flags_mask = VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_RAW_BUFFER; ++ break; ++ ++ case VKD3D_SHADER_DESCRIPTOR_TYPE_UAV: ++ flags_mask = VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER ++ | VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ ++ | VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_ATOMICS ++ | VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_RAW_BUFFER; ++ uav_flags_mask = VKD3DSUF_GLOBALLY_COHERENT ++ | VKD3DSUF_RASTERISER_ORDERED_VIEW ++ | VKD3DSUF_ORDER_PRESERVING_COUNTER; ++ break; ++ ++ case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV: ++ break; ++ ++ case VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER: ++ flags_mask = VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE; ++ break; ++ ++ case VKD3D_SHADER_DESCRIPTOR_TYPE_FORCE_32BIT: ++ break; ++ } ++ ++ if (descriptor->flags & ~flags_mask) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_FLAGS, ++ "Descriptor %u of type %#x has invalid flags %#x.", ++ i, descriptor->type, descriptor->flags); ++ ++ if (descriptor->uav_flags & ~uav_flags_mask) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_FLAGS, ++ "Descriptor %u of type %#x has invalid UAV flags %#x.", ++ i, descriptor->type, descriptor->uav_flags); + } + } + +@@ -11441,6 +11479,14 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_IEQ] = {1, 2, vsir_validate_integer_comparison_operation}, + [VSIR_OP_IGE] = {1, 2, vsir_validate_integer_comparison_operation}, + [VSIR_OP_ILT] = {1, 2, vsir_validate_integer_comparison_operation}, ++ [VSIR_OP_IMAD] = {1, 3, vsir_validate_integer_elementwise_operation}, ++ [VSIR_OP_IMAX] = {1, 2, vsir_validate_integer_elementwise_operation}, ++ [VSIR_OP_IMIN] = {1, 2, vsir_validate_integer_elementwise_operation}, ++ [VSIR_OP_INE] = {1, 2, vsir_validate_integer_comparison_operation}, ++ [VSIR_OP_INEG] = {1, 1, vsir_validate_integer_elementwise_operation}, ++ [VSIR_OP_IREM] = {1, 2, vsir_validate_integer_elementwise_operation}, ++ [VSIR_OP_ISHL] = {1, 2, vsir_validate_integer_elementwise_operation}, ++ [VSIR_OP_ISHR] = {1, 2, vsir_validate_integer_elementwise_operation}, + [VSIR_OP_DCL_GS_INSTANCES] = {0, 0, vsir_validate_dcl_gs_instances}, + [VSIR_OP_DCL_HS_MAX_TESSFACTOR] = {0, 0, vsir_validate_dcl_hs_max_tessfactor}, + [VSIR_OP_DCL_INDEX_RANGE] = {0, 0, vsir_validate_dcl_index_range}, +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 5d7fc6e1209..978af0a2d17 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -265,6 +265,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_ERROR_VSIR_INVALID_DESCRIPTOR_TYPE = 9024, + VKD3D_SHADER_ERROR_VSIR_INVALID_RESOURCE_TYPE = 9025, + VKD3D_SHADER_ERROR_VSIR_INVALID_DESCRIPTOR_COUNT = 9026, ++ VKD3D_SHADER_ERROR_VSIR_INVALID_FLAGS = 9027, + + VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300, + +diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c +index 0a5bd1122e3..9e9811bf922 100644 +--- a/libs/vkd3d/libs/vkd3d/state.c ++++ b/libs/vkd3d/libs/vkd3d/state.c +@@ -3232,17 +3232,6 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s + uint32_t mask; + HRESULT hr; + +- static const DWORD default_ps_code[] = +- { +-#if 0 +- ps_4_0 +- ret +-#endif +- 0x43425844, 0x19cbf606, 0x18f562b9, 0xdaeed4db, 0xc324aa46, 0x00000001, 0x00000060, 0x00000003, +- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, +- 0x00000008, 0x00000000, 0x00000008, 0x52444853, 0x0000000c, 0x00000040, 0x00000003, 0x0100003e, +- }; +- static const D3D12_SHADER_BYTECODE default_ps = {default_ps_code, sizeof(default_ps_code)}; + static const struct + { + enum VkShaderStageFlagBits stage; +@@ -3401,11 +3390,10 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s + + if (!desc->ps.pShaderBytecode) + { +- if (FAILED(hr = create_shader_stage(device, &graphics->stages[graphics->stage_count], +- VK_SHADER_STAGE_FRAGMENT_BIT, &default_ps, NULL))) +- goto fail; +- +- ++graphics->stage_count; ++ for (i = 0; i < rt_count; i++) ++ { ++ graphics->blend_attachments[i].colorWriteMask = 0; ++ } + } + } + +-- +2.47.2 + diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-9d490b83d4d6c9b8cbb5bcfa5a2e6aadf25.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-9d490b83d4d6c9b8cbb5bcfa5a2e6aadf25.patch deleted file mode 100644 index 7f23b191..00000000 --- a/patches/vkd3d-latest/0003-Updated-vkd3d-to-9d490b83d4d6c9b8cbb5bcfa5a2e6aadf25.patch +++ /dev/null @@ -1,931 +0,0 @@ -From 9b348f0918e5577947f1341c8be0e6137bb99d14 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Fri, 20 Jun 2025 07:18:12 +1000 -Subject: [PATCH] Updated vkd3d to 9d490b83d4d6c9b8cbb5bcfa5a2e6aadf25e558b. - ---- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 92 +++--- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 1 + - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 1 + - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 23 ++ - libs/vkd3d/libs/vkd3d-shader/ir.c | 263 +++++++++++++++--- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 84 +++--- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 2 + - libs/vkd3d/libs/vkd3d/state.c | 12 + - 8 files changed, 346 insertions(+), 132 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 1c7ed0d9e11..9ebcb6870e9 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -643,6 +643,7 @@ struct sm6_type - - enum sm6_value_type - { -+ VALUE_TYPE_INVALID, - VALUE_TYPE_FUNCTION, - VALUE_TYPE_DATA, - VALUE_TYPE_HANDLE, -@@ -652,7 +653,6 @@ enum sm6_value_type - VALUE_TYPE_GROUPSHAREDMEM, - VALUE_TYPE_CONSTANT, - VALUE_TYPE_UNDEFINED, -- VALUE_TYPE_INVALID, - }; - - struct sm6_index -@@ -2229,6 +2229,11 @@ static inline bool sm6_value_is_function_dcl(const struct sm6_value *value) - return value->value_type == VALUE_TYPE_FUNCTION; - } - -+static bool sm6_value_is_invalid(const struct sm6_value *value) -+{ -+ return value->value_type == VALUE_TYPE_INVALID; -+} -+ - static inline bool sm6_value_is_dx_intrinsic_dcl(const struct sm6_value *fn) - { - VKD3D_ASSERT(sm6_value_is_function_dcl(fn)); -@@ -2599,7 +2604,6 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str - case VALUE_TYPE_SSA: - register_init_with_id(reg, VKD3DSPR_SSA, data_type, value->u.ssa.id); - reg->dimension = sm6_type_is_scalar(value->type) ? VSIR_DIMENSION_SCALAR : VSIR_DIMENSION_VEC4; -- register_convert_to_minimum_precision(reg); - break; - - case VALUE_TYPE_ICB: -@@ -2607,7 +2611,6 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str - reg->idx[0].offset = value->u.icb.id; - register_index_address_init(®->idx[1], value->u.icb.index.index, sm6); - reg->idx[1].is_in_bounds = value->u.icb.index.is_in_bounds; -- register_convert_to_minimum_precision(reg); - break; - - case VALUE_TYPE_IDXTEMP: -@@ -2615,7 +2618,6 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str - reg->idx[0].offset = value->u.idxtemp.id; - register_index_address_init(®->idx[1], value->u.idxtemp.index.index, sm6); - reg->idx[1].is_in_bounds = value->u.idxtemp.index.is_in_bounds; -- register_convert_to_minimum_precision(reg); - break; - - case VALUE_TYPE_GROUPSHAREDMEM: -@@ -2629,7 +2631,6 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str - vsir_register_init(reg, scalar_type->u.width == 64 ? VKD3DSPR_IMMCONST64 : VKD3DSPR_IMMCONST, - data_type, 0); - reg->u = value->u.constant.immconst; -- register_convert_to_minimum_precision(reg); - break; - - case VALUE_TYPE_UNDEFINED: -@@ -2643,6 +2644,7 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str - vkd3d_unreachable(); - } - -+ register_convert_to_minimum_precision(reg); - reg->non_uniform = value->non_uniform; - } - -@@ -3720,7 +3722,10 @@ static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6 - dst->structure_stride = 0; - sm6_register_from_value(&ins->declaration.tgsm_raw.reg.reg, dst, sm6); - ins->declaration.tgsm_raw.alignment = alignment; -- byte_count = elem_type->u.width / 8u; -+ byte_count = elem_type->u.width / CHAR_BIT; -+ /* Convert minimum precision types to their 32-bit equivalent. */ -+ if (byte_count == 2) -+ byte_count = 4; - if (byte_count != 4) - { - FIXME("Unsupported byte count %u.\n", byte_count); -@@ -3741,7 +3746,10 @@ static void sm6_parser_declare_tgsm_structured(struct sm6_parser *sm6, const str - dst_param_init(&ins->declaration.tgsm_structured.reg); - dst->value_type = VALUE_TYPE_GROUPSHAREDMEM; - dst->u.groupsharedmem.id = sm6->tgsm_count++; -- dst->structure_stride = elem_type->u.width / 8u; -+ dst->structure_stride = elem_type->u.width / CHAR_BIT; -+ /* Convert minimum precision types to their 32-bit equivalent. */ -+ if (dst->structure_stride == 2) -+ dst->structure_stride = 4; - sm6_register_from_value(&ins->declaration.tgsm_structured.reg.reg, dst, sm6); - if (dst->structure_stride != 4) - { -@@ -4824,6 +4832,10 @@ static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) - return VKD3DSIH_ISINF; - case DX_ISFINITE: - return VKD3DSIH_ISFINITE; -+ case DX_COS: -+ return VKD3DSIH_COS; -+ case DX_SIN: -+ return VKD3DSIH_SIN; - case DX_TAN: - return VKD3DSIH_TAN; - case DX_ACOS: -@@ -6172,30 +6184,6 @@ static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsi - ins->dst->modifiers = VKD3DSPDM_SATURATE; - } - --static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -- const struct sm6_value **operands, struct function_emission_state *state) --{ -- struct sm6_value *dst = sm6_parser_get_current_value(sm6); -- struct vkd3d_shader_instruction *ins = state->ins; -- struct vkd3d_shader_dst_param *dst_params; -- struct vkd3d_shader_src_param *src_param; -- unsigned int index; -- -- vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SINCOS); -- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -- return; -- src_param_init_from_value(src_param, operands[0], sm6); -- -- sm6_parser_init_ssa_value(sm6, dst); -- -- index = op == DX_COS; -- dst_params = instruction_dst_params_alloc(ins, 2, sm6); -- dst_param_init(&dst_params[0]); -- dst_param_init(&dst_params[1]); -- sm6_register_from_value(&dst_params[index].reg, dst, sm6); -- vsir_dst_param_init_null(&dst_params[index ^ 1]); --} -- - static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, - const struct sm6_value **operands, struct function_emission_state *state) - { -@@ -6599,7 +6587,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = - [DX_BUFFER_UPDATE_COUNTER ] = {"i", "H8", sm6_parser_emit_dx_buffer_update_counter}, - [DX_CALCULATE_LOD ] = {"f", "HHfffb", sm6_parser_emit_dx_calculate_lod}, - [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, -- [DX_COS ] = {"g", "R", sm6_parser_emit_dx_sincos}, -+ [DX_COS ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, - [DX_COVERAGE ] = {"i", "", sm6_parser_emit_dx_coverage}, - [DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle}, -@@ -6668,7 +6656,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = - [DX_SAMPLE_INDEX ] = {"i", "", sm6_parser_emit_dx_sample_index}, - [DX_SAMPLE_LOD ] = {"o", "HHffffiiif", sm6_parser_emit_dx_sample}, - [DX_SATURATE ] = {"g", "R", sm6_parser_emit_dx_saturate}, -- [DX_SIN ] = {"g", "R", sm6_parser_emit_dx_sincos}, -+ [DX_SIN ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_SPLIT_DOUBLE ] = {"S", "d", sm6_parser_emit_dx_split_double}, - [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, - [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, -@@ -6702,11 +6690,13 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = - }; - - static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type, -- const struct sm6_type *ret_type, bool is_return) -+ const struct sm6_type *ret_type) - { - const struct sm6_type *type = value->type; - -- if (info_type != 'H' && !sm6_value_is_register(value)) -+ if (info_type != 'H' && info_type != 'v' && !sm6_value_is_register(value)) -+ return false; -+ if (!type && info_type != 'v') - return false; - - switch (info_type) -@@ -6741,7 +6731,7 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc - case 'g': - return sm6_type_is_floating_point(type); - case 'H': -- return (is_return || sm6_value_is_handle(value)) && type == sm6->handle_type; -+ return sm6_value_is_handle(value) && type == sm6->handle_type; - case 'D': - return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.Dimensions"); - case 'S': -@@ -6749,7 +6739,7 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc - case 'V': - return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.fouri32"); - case 'v': -- return !type; -+ return sm6_value_is_invalid(value) && !type; - case 'o': - /* TODO: some type checking may be possible */ - return true; -@@ -6769,18 +6759,10 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ - - info = &sm6_dx_op_table[op]; - -- VKD3D_ASSERT(info->ret_type[0]); -- if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type[0], NULL, true)) -- { -- 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 -- * a data type for the SSA result. */ -- } -- - for (i = 0; i < operand_count; ++i) - { - const struct sm6_value *value = operands[i]; -- if (!sm6_parser_validate_operand_type(sm6, value, info->operand_info[i], dst->type, false)) -+ if (!sm6_parser_validate_operand_type(sm6, value, info->operand_info[i], dst->type)) - { - WARN("Failed to validate operand %u for dx intrinsic id %u, '%s'.\n", i + 1, op, name); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -@@ -6823,10 +6805,22 @@ static void sm6_parser_decode_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_op - return; - } - -- if (sm6_parser_validate_dx_op(sm6, op, name, operands, operand_count, dst)) -- sm6_dx_op_table[op].handler(sm6, op, operands, state); -- else -+ if (!sm6_parser_validate_dx_op(sm6, op, name, operands, operand_count, dst)) -+ { - sm6_parser_emit_unhandled(sm6, state->ins, dst); -+ return; -+ } -+ -+ sm6_dx_op_table[op].handler(sm6, op, operands, state); -+ -+ VKD3D_ASSERT(sm6_dx_op_table[op].ret_type[0]); -+ if (!sm6_parser_validate_operand_type(sm6, dst, sm6_dx_op_table[op].ret_type[0], NULL)) -+ { -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Failed to validate return type for dx intrinsic id %u, '%s'.", op, name); -+ /* Return type validation failure is not so critical. We only need to set -+ * a data type for the SSA result. */ -+ } - } - - static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_record *record, -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index 653ddd2e8be..2b88a04a120 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -3652,6 +3652,7 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op) - [HLSL_OP1_LOG2] = "log2", - [HLSL_OP1_LOGIC_NOT] = "!", - [HLSL_OP1_NEG] = "-", -+ [HLSL_OP1_NOISE] = "noise", - [HLSL_OP1_RCP] = "rcp", - [HLSL_OP1_REINTERPRET] = "reinterpret", - [HLSL_OP1_ROUND] = "round", -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index 63c9733ec7b..bb37f0be6cf 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -734,6 +734,7 @@ enum hlsl_ir_expr_op - HLSL_OP1_ISINF, - HLSL_OP1_LOG2, - HLSL_OP1_LOGIC_NOT, -+ HLSL_OP1_NOISE, - HLSL_OP1_NEG, - HLSL_OP1_RCP, - HLSL_OP1_REINTERPRET, -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index bad9d33094b..fa3688fad18 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -4294,6 +4294,28 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, - return true; - } - -+static bool intrinsic_noise(struct hlsl_ctx *ctx, -+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_type *type = params->args[0]->data_type, *ret_type; -+ struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; -+ -+ type = params->args[0]->data_type; -+ if (type->class == HLSL_CLASS_MATRIX) -+ { -+ struct vkd3d_string_buffer *string; -+ if ((string = hlsl_type_to_string(ctx, type))) -+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, -+ "Wrong argument type for noise(): expected vector or scalar, but got '%s'.", string->buffer); -+ hlsl_release_string_buffer(ctx, string); -+ } -+ -+ args[0] = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); -+ ret_type = hlsl_get_scalar_type(ctx, args[0]->data_type->e.numeric.type); -+ -+ return !!add_expr(ctx, params->instrs, HLSL_OP1_NOISE, args, ret_type, loc); -+} -+ - static bool intrinsic_normalize(struct hlsl_ctx *ctx, - const struct parse_initializer *params, const struct vkd3d_shader_location *loc) - { -@@ -5258,6 +5280,7 @@ intrinsic_functions[] = - {"min", 2, true, intrinsic_min}, - {"modf", 2, true, intrinsic_modf}, - {"mul", 2, true, intrinsic_mul}, -+ {"noise", 1, true, intrinsic_noise}, - {"normalize", 1, true, intrinsic_normalize}, - {"pow", 2, true, intrinsic_pow}, - {"radians", 1, true, intrinsic_radians}, -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 7546a1f557b..1429c3a8778 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -62,6 +62,7 @@ const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) - [VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED ] = "check_access_fully_mapped", - [VKD3DSIH_CMP ] = "cmp", - [VKD3DSIH_CND ] = "cnd", -+ [VKD3DSIH_COS ] = "cos", - [VKD3DSIH_CONTINUE ] = "continue", - [VKD3DSIH_CONTINUEP ] = "continuec", - [VKD3DSIH_COUNTBITS ] = "countbits", -@@ -290,6 +291,7 @@ const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) - [VKD3DSIH_SETP ] = "setp", - [VKD3DSIH_SGE ] = "sge", - [VKD3DSIH_SGN ] = "sgn", -+ [VKD3DSIH_SIN ] = "sin", - [VKD3DSIH_SINCOS ] = "sincos", - [VKD3DSIH_SLT ] = "slt", - [VKD3DSIH_SQRT ] = "sqrt", -@@ -587,26 +589,37 @@ static void vsir_src_param_init_sampler(struct vkd3d_shader_src_param *src, unsi - src->reg.dimension = VSIR_DIMENSION_NONE; - } - --static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned int idx) -+static void src_param_init_ssa_scalar(struct vkd3d_shader_src_param *src, unsigned int idx, -+ enum vkd3d_data_type data_type) - { -- vsir_src_param_init(src, VKD3DSPR_SSA, VKD3D_DATA_BOOL, 1); -+ vsir_src_param_init(src, VKD3DSPR_SSA, data_type, 1); - src->reg.idx[0].offset = idx; - } - -+static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned int idx) -+{ -+ src_param_init_ssa_scalar(src, idx, VKD3D_DATA_BOOL); -+} -+ - static void src_param_init_ssa_float(struct vkd3d_shader_src_param *src, unsigned int idx) - { -- vsir_src_param_init(src, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1); -- src->reg.idx[0].offset = idx; -+ src_param_init_ssa_scalar(src, idx, VKD3D_DATA_FLOAT); - } - --static void src_param_init_ssa_float4(struct vkd3d_shader_src_param *src, unsigned int idx) -+static void src_param_init_ssa_vec4(struct vkd3d_shader_src_param *src, unsigned int idx, -+ enum vkd3d_data_type data_type) - { -- vsir_src_param_init(src, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1); -+ vsir_src_param_init(src, VKD3DSPR_SSA, data_type, 1); - src->reg.idx[0].offset = idx; - src->reg.dimension = VSIR_DIMENSION_VEC4; - src->swizzle = VKD3D_SHADER_NO_SWIZZLE; - } - -+static void src_param_init_ssa_float4(struct vkd3d_shader_src_param *src, unsigned int idx) -+{ -+ src_param_init_ssa_vec4(src, idx, VKD3D_DATA_FLOAT); -+} -+ - static void src_param_init_temp_bool(struct vkd3d_shader_src_param *src, unsigned int idx) - { - vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_BOOL, 1); -@@ -657,26 +670,37 @@ void vsir_dst_param_init_null(struct vkd3d_shader_dst_param *dst) - dst->write_mask = 0; - } - --static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) -+static void dst_param_init_ssa_scalar(struct vkd3d_shader_dst_param *dst, unsigned int idx, -+ enum vkd3d_data_type data_type) - { -- vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_BOOL, 1); -+ vsir_dst_param_init(dst, VKD3DSPR_SSA, data_type, 1); - dst->reg.idx[0].offset = idx; - } - -+static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) -+{ -+ dst_param_init_ssa_scalar(dst, idx, VKD3D_DATA_BOOL); -+} -+ - static void dst_param_init_ssa_float(struct vkd3d_shader_dst_param *dst, unsigned int idx) - { -- vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1); -- dst->reg.idx[0].offset = idx; -+ dst_param_init_ssa_scalar(dst, idx, VKD3D_DATA_FLOAT); - } - --static void dst_param_init_ssa_float4(struct vkd3d_shader_dst_param *dst, unsigned int idx) -+static void dst_param_init_ssa_vec4(struct vkd3d_shader_dst_param *dst, unsigned int idx, -+ enum vkd3d_data_type data_type) - { -- vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_FLOAT, 1); -+ vsir_dst_param_init(dst, VKD3DSPR_SSA, data_type, 1); - dst->reg.idx[0].offset = idx; - dst->reg.dimension = VSIR_DIMENSION_VEC4; - dst->write_mask = VKD3DSP_WRITEMASK_ALL; - } - -+static void dst_param_init_ssa_float4(struct vkd3d_shader_dst_param *dst, unsigned int idx) -+{ -+ dst_param_init_ssa_vec4(dst, idx, VKD3D_DATA_FLOAT); -+} -+ - static void dst_param_init_temp_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) - { - vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_BOOL, 1); -@@ -1079,50 +1103,130 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog - { - struct vkd3d_shader_instruction_array *instructions = &program->instructions; - size_t pos = sincos - instructions->elements; -- struct vkd3d_shader_instruction *ins; -- unsigned int s; -+ struct vkd3d_shader_instruction *ins, *mov; -+ unsigned int s, count; - -- if (sincos->dst_count != 1) -- return VKD3D_OK; -+ count = 1 + vkd3d_popcount(sincos->dst[0].write_mask & (VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1)); - -- if (!shader_instruction_array_insert_at(instructions, pos + 1, 1)) -+ if (!shader_instruction_array_insert_at(instructions, pos + 1, count)) - return VKD3D_ERROR_OUT_OF_MEMORY; - sincos = &instructions->elements[pos]; - - ins = &instructions->elements[pos + 1]; - -- if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VKD3DSIH_SINCOS, 2, 1))) -+ /* Save the source in a SSA in case a destination collides with the source. */ -+ mov = ins++; -+ if (!(vsir_instruction_init_with_params(program, mov, &sincos->location, VKD3DSIH_MOV, 1, 1))) - return VKD3D_ERROR_OUT_OF_MEMORY; - -- ins->flags = sincos->flags; -+ mov->src[0] = sincos->src[0]; - -- *ins->src = *sincos->src; - /* Set the source swizzle to replicate the first component. */ - s = vsir_swizzle_get_component(sincos->src->swizzle, 0); -- ins->src->swizzle = vkd3d_shader_create_swizzle(s, s, s, s); -+ mov->src[0].swizzle = vkd3d_shader_create_swizzle(s, s, s, s); -+ -+ dst_param_init_ssa_scalar(&mov->dst[0], program->ssa_count, sincos->src[0].reg.data_type); - - if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_1) - { -+ if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VKD3DSIH_SIN, 1, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ ins->flags = sincos->flags; -+ -+ src_param_init_ssa_scalar(&ins->src[0], program->ssa_count, sincos->src[0].reg.data_type); -+ - ins->dst[0] = *sincos->dst; - ins->dst[0].write_mask = VKD3DSP_WRITEMASK_1; -+ -+ ++ins; - } -- else -+ -+ if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_0) - { -- vsir_dst_param_init_null(&ins->dst[0]); -+ if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VKD3DSIH_COS, 1, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ ins->flags = sincos->flags; -+ -+ src_param_init_ssa_scalar(&ins->src[0], program->ssa_count, sincos->src[0].reg.data_type); -+ -+ ins->dst[0] = *sincos->dst; -+ ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; -+ -+ ++ins; - } - -- if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_0) -+ vkd3d_shader_instruction_make_nop(sincos); -+ ++program->ssa_count; -+ -+ return VKD3D_OK; -+} -+ -+static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *program, -+ struct vkd3d_shader_instruction *sincos, struct vsir_transformation_context *ctx) -+{ -+ struct vkd3d_shader_instruction_array *instructions = &program->instructions; -+ size_t pos = sincos - instructions->elements; -+ struct vkd3d_shader_instruction *ins, *mov; -+ unsigned int count = 1; -+ -+ if (sincos->dst_count != 2) - { -- ins->dst[1] = *sincos->dst; -- ins->dst[1].write_mask = VKD3DSP_WRITEMASK_0; -+ vkd3d_shader_error(ctx->message_context, &sincos->location, -+ VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, -+ "Internal compiler error: invalid destination count %u for SINCOS.", -+ sincos->dst_count); -+ return VKD3D_ERROR; - } -- else -+ -+ if (sincos->dst[0].reg.type != VKD3DSPR_NULL) -+ ++count; -+ if (sincos->dst[1].reg.type != VKD3DSPR_NULL) -+ ++count; -+ -+ if (!shader_instruction_array_insert_at(instructions, pos + 1, count)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ sincos = &instructions->elements[pos]; -+ -+ ins = &instructions->elements[pos + 1]; -+ -+ /* Save the source in a SSA in case a destination collides with the source. */ -+ mov = ins++; -+ if (!(vsir_instruction_init_with_params(program, mov, &sincos->location, VKD3DSIH_MOV, 1, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ mov->src[0] = sincos->src[0]; -+ dst_param_init_ssa_vec4(&mov->dst[0], program->ssa_count, sincos->src[0].reg.data_type); -+ -+ if (sincos->dst[0].reg.type != VKD3DSPR_NULL) - { -- vsir_dst_param_init_null(&ins->dst[1]); -+ if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VKD3DSIH_SIN, 1, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ ins->flags = sincos->flags; -+ -+ src_param_init_ssa_vec4(&ins->src[0], program->ssa_count, sincos->src[0].reg.data_type); -+ ins->dst[0] = sincos->dst[0]; -+ -+ ++ins; -+ } -+ -+ if (sincos->dst[1].reg.type != VKD3DSPR_NULL) -+ { -+ if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VKD3DSIH_COS, 1, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ ins->flags = sincos->flags; -+ -+ src_param_init_ssa_vec4(&ins->src[0], program->ssa_count, sincos->src[0].reg.data_type); -+ ins->dst[0] = sincos->dst[1]; -+ -+ ++ins; - } - -- /* Make the original instruction no-op */ - vkd3d_shader_instruction_make_nop(sincos); -+ ++program->ssa_count; - - return VKD3D_OK; - } -@@ -1375,8 +1479,16 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr - break; - - case VKD3DSIH_SINCOS: -- if ((ret = vsir_program_lower_sm1_sincos(program, ins)) < 0) -- return ret; -+ if (ins->dst_count == 1) -+ { -+ if ((ret = vsir_program_lower_sm1_sincos(program, ins)) < 0) -+ return ret; -+ } -+ else -+ { -+ if ((ret = vsir_program_lower_sm4_sincos(program, ins, ctx)) < 0) -+ return ret; -+ } - break; - - case VKD3DSIH_TEXLD: -@@ -8659,9 +8771,31 @@ static void vsir_validate_io_src_param(struct validation_context *ctx, - "Invalid register type %#x used as source parameter.", src->reg.type); - } - -+#define F64_BIT (1u << VKD3D_DATA_DOUBLE) -+#define F32_BIT (1u << VKD3D_DATA_FLOAT) -+#define F16_BIT (1u << VKD3D_DATA_HALF) -+ -+#define I32_BIT (1u << VKD3D_DATA_INT) -+ -+#define U64_BIT (1u << VKD3D_DATA_UINT64) -+#define U32_BIT (1u << VKD3D_DATA_UINT) -+#define U16_BIT (1u << VKD3D_DATA_UINT16) -+ - static void vsir_validate_src_param(struct validation_context *ctx, - const struct vkd3d_shader_src_param *src) - { -+ static const struct -+ { -+ uint32_t data_type_mask; -+ } -+ src_modifier_data[] = -+ { -+ [VKD3DSPSM_NEG] = {F64_BIT | F32_BIT | F16_BIT | I32_BIT | U64_BIT | U32_BIT | U16_BIT}, -+ [VKD3DSPSM_BIAS] = {F32_BIT}, -+ [VKD3DSPSM_BIASNEG] = {F32_BIT}, -+ [VKD3DSPSM_SIGN] = {F32_BIT}, -+ [VKD3DSPSM_SIGNNEG] = {F32_BIT}, -+ }; - vsir_validate_register(ctx, &src->reg); - - if (src->swizzle & ~0x03030303u) -@@ -8676,6 +8810,13 @@ static void vsir_validate_src_param(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", - src->modifiers); - -+ if (src->modifiers < ARRAY_SIZE(src_modifier_data) && src_modifier_data[src->modifiers].data_type_mask) -+ { -+ if (!(src_modifier_data[src->modifiers].data_type_mask & (1u << src->reg.data_type))) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, -+ "Source has invalid modifier %#x for data type %u.", src->modifiers, src->reg.data_type); -+ } -+ - switch (src->reg.type) - { - case VKD3DSPR_SSA: -@@ -9284,6 +9425,60 @@ static void vsir_validate_hull_shader_phase(struct validation_context *ctx, - ctx->dcl_temps_found = false; - } - -+static void vsir_validate_elementwise_operation(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction, const bool types[VKD3D_DATA_COUNT]) -+{ -+ enum vkd3d_data_type dst_data_type; -+ unsigned int i; -+ -+ if (instruction->dst_count < 1) -+ return; -+ -+ dst_data_type = instruction->dst[0].reg.data_type; -+ -+ if (dst_data_type >= VKD3D_DATA_COUNT) -+ return; -+ -+ if (!types[dst_data_type]) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -+ "Invalid data type %#x for elementwise operation \"%s\" (%#x).", -+ dst_data_type, vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); -+ -+ for (i = 0; i < instruction->src_count; ++i) -+ { -+ if (instruction->src[i].reg.data_type != dst_data_type) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -+ "Data type %#x for operand %u doesn't match the destination data type %#x " -+ "for elementwise operation \"%s\" (%#x).", -+ instruction->src[i].reg.data_type, i, dst_data_type, -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); -+ } -+} -+ -+static void vsir_validate_float_elementwise_operation(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ static const bool types[VKD3D_DATA_COUNT] = -+ { -+ [VKD3D_DATA_FLOAT] = true, -+ }; -+ -+ vsir_validate_elementwise_operation(ctx, instruction, types); -+} -+ -+static void vsir_validate_logic_elementwise_operation(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ static const bool types[VKD3D_DATA_COUNT] = -+ { -+ [VKD3D_DATA_UINT] = true, -+ [VKD3D_DATA_UINT64] = true, -+ [VKD3D_DATA_BOOL] = true, -+ }; -+ -+ vsir_validate_elementwise_operation(ctx, instruction, types); -+} -+ - static void vsir_validate_branch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) - { - size_t i; -@@ -9969,6 +10164,12 @@ struct vsir_validator_instruction_desc - - static const struct vsir_validator_instruction_desc vsir_validator_instructions[] = - { -+ [VKD3DSIH_ABS] = {1, 1, vsir_validate_float_elementwise_operation}, -+ [VKD3DSIH_ACOS] = {1, 1, vsir_validate_float_elementwise_operation}, -+ [VKD3DSIH_ADD] = {1, 2, vsir_validate_float_elementwise_operation}, -+ [VKD3DSIH_AND] = {1, 2, vsir_validate_logic_elementwise_operation}, -+ [VKD3DSIH_ASIN] = {1, 1, vsir_validate_float_elementwise_operation}, -+ [VKD3DSIH_ATAN] = {1, 1, vsir_validate_float_elementwise_operation}, - [VKD3DSIH_BRANCH] = {0, ~0u, vsir_validate_branch}, - [VKD3DSIH_HS_CONTROL_POINT_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, - [VKD3DSIH_HS_DECLS] = {0, 0, vsir_validate_hull_shader_phase}, -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index debf7ac29f5..0413cd7c344 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -1551,6 +1551,29 @@ static void vkd3d_spirv_build_op_name(struct vkd3d_spirv_builder *builder, - vkd3d_spirv_build_string(stream, name, name_size); - } - -+static uint32_t vkd3d_spirv_build_op_string(struct vkd3d_spirv_builder *builder, const char *s) -+{ -+ struct vkd3d_spirv_stream *stream = &builder->debug_stream; -+ uint32_t result_id = vkd3d_spirv_alloc_id(builder); -+ unsigned int size; -+ -+ size = vkd3d_spirv_string_word_count(s); -+ vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(SpvOpString, 2 + size)); -+ vkd3d_spirv_build_word(stream, result_id); -+ vkd3d_spirv_build_string(stream, s, size); -+ -+ return result_id; -+} -+ -+static void vkd3d_spirv_build_op_source(struct vkd3d_spirv_builder *builder, const char *source_name) -+{ -+ struct vkd3d_spirv_stream *stream = &builder->debug_stream; -+ uint32_t source_id; -+ -+ source_id = vkd3d_spirv_build_op_string(builder, source_name ? source_name : ""); -+ vkd3d_spirv_build_op3(stream, SpvOpSource, 0, 0, source_id); -+} -+ - static void vkd3d_spirv_build_op_member_name(struct vkd3d_spirv_builder *builder, - uint32_t type_id, uint32_t member, const char *fmt, ...) - { -@@ -2462,18 +2485,6 @@ static uint32_t vkd3d_spirv_build_op_glsl_std450_fabs(struct vkd3d_spirv_builder - return vkd3d_spirv_build_op_glsl_std450_tr1(builder, GLSLstd450FAbs, result_type, operand); - } - --static uint32_t vkd3d_spirv_build_op_glsl_std450_sin(struct vkd3d_spirv_builder *builder, -- uint32_t result_type, uint32_t operand) --{ -- return vkd3d_spirv_build_op_glsl_std450_tr1(builder, GLSLstd450Sin, result_type, operand); --} -- --static uint32_t vkd3d_spirv_build_op_glsl_std450_cos(struct vkd3d_spirv_builder *builder, -- uint32_t result_type, uint32_t operand) --{ -- return vkd3d_spirv_build_op_glsl_std450_tr1(builder, GLSLstd450Cos, result_type, operand); --} -- - static uint32_t vkd3d_spirv_build_op_glsl_std450_max(struct vkd3d_spirv_builder *builder, - uint32_t result_type, uint32_t x, uint32_t y) - { -@@ -2565,7 +2576,8 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder - return vkd3d_spirv_get_type_id(builder, component_type, component_count); - } - --static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, const char *entry_point) -+static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, -+ const char *entry_point, const char *source_name) - { - vkd3d_spirv_stream_init(&builder->debug_stream); - vkd3d_spirv_stream_init(&builder->annotation_stream); -@@ -2580,6 +2592,7 @@ static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, const - - rb_init(&builder->declarations, vkd3d_spirv_declaration_compare); - -+ vkd3d_spirv_build_op_source(builder, source_name); - builder->main_function_id = vkd3d_spirv_alloc_id(builder); - vkd3d_spirv_build_op_name(builder, builder->main_function_id, "%s", entry_point); - } -@@ -3173,7 +3186,8 @@ static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *p - compiler->spirv_target_info = target_info; - } - -- vkd3d_spirv_builder_init(&compiler->spirv_builder, spirv_compiler_get_entry_point_name(compiler)); -+ vkd3d_spirv_builder_init(&compiler->spirv_builder, -+ spirv_compiler_get_entry_point_name(compiler), compile_info->source_name); - - compiler->formatting = VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT - | VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER; -@@ -7708,6 +7722,7 @@ static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( - {VKD3DSIH_ACOS, GLSLstd450Acos}, - {VKD3DSIH_ASIN, GLSLstd450Asin}, - {VKD3DSIH_ATAN, GLSLstd450Atan}, -+ {VKD3DSIH_COS, GLSLstd450Cos}, - {VKD3DSIH_DFMA, GLSLstd450Fma}, - {VKD3DSIH_DMAX, GLSLstd450NMax}, - {VKD3DSIH_DMIN, GLSLstd450NMin}, -@@ -7730,6 +7745,7 @@ static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( - {VKD3DSIH_ROUND_PI, GLSLstd450Ceil}, - {VKD3DSIH_ROUND_Z, GLSLstd450Trunc}, - {VKD3DSIH_RSQ, GLSLstd450InverseSqrt}, -+ {VKD3DSIH_SIN, GLSLstd450Sin}, - {VKD3DSIH_SQRT, GLSLstd450Sqrt}, - {VKD3DSIH_TAN, GLSLstd450Tan}, - {VKD3DSIH_UMAX, GLSLstd450UMax}, -@@ -7999,41 +8015,6 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler, - spirv_compiler_emit_store_dst(compiler, dst, val_id); - } - --static void spirv_compiler_emit_sincos(struct spirv_compiler *compiler, -- const struct vkd3d_shader_instruction *instruction) --{ -- const struct vkd3d_shader_dst_param *dst_sin = &instruction->dst[0]; -- const struct vkd3d_shader_dst_param *dst_cos = &instruction->dst[1]; -- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- const struct vkd3d_shader_src_param *src = instruction->src; -- uint32_t type_id, src_id, sin_id = 0, cos_id = 0; -- -- if (dst_sin->reg.type != VKD3DSPR_NULL) -- { -- type_id = spirv_compiler_get_type_id_for_dst(compiler, dst_sin); -- src_id = spirv_compiler_emit_load_src(compiler, src, dst_sin->write_mask); -- -- sin_id = vkd3d_spirv_build_op_glsl_std450_sin(builder, type_id, src_id); -- } -- -- if (dst_cos->reg.type != VKD3DSPR_NULL) -- { -- if (dst_sin->reg.type == VKD3DSPR_NULL || dst_cos->write_mask != dst_sin->write_mask) -- { -- type_id = spirv_compiler_get_type_id_for_dst(compiler, dst_cos); -- src_id = spirv_compiler_emit_load_src(compiler, src, dst_cos->write_mask); -- } -- -- cos_id = vkd3d_spirv_build_op_glsl_std450_cos(builder, type_id, src_id); -- } -- -- if (sin_id) -- spirv_compiler_emit_store_dst(compiler, dst_sin, sin_id); -- -- if (cos_id) -- spirv_compiler_emit_store_dst(compiler, dst_cos, cos_id); --} -- - static void spirv_compiler_emit_imul(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { -@@ -10711,6 +10692,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_ACOS: - case VKD3DSIH_ASIN: - case VKD3DSIH_ATAN: -+ case VKD3DSIH_COS: - case VKD3DSIH_HCOS: - case VKD3DSIH_HSIN: - case VKD3DSIH_HTAN: -@@ -10733,6 +10715,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_ROUND_PI: - case VKD3DSIH_ROUND_Z: - case VKD3DSIH_RSQ: -+ case VKD3DSIH_SIN: - case VKD3DSIH_SQRT: - case VKD3DSIH_TAN: - case VKD3DSIH_UMAX: -@@ -10748,9 +10731,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_RCP: - spirv_compiler_emit_rcp(compiler, instruction); - break; -- case VKD3DSIH_SINCOS: -- spirv_compiler_emit_sincos(compiler, instruction); -- break; - case VKD3DSIH_IMUL: - case VKD3DSIH_UMUL: - spirv_compiler_emit_imul(compiler, instruction); -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 2ae0a57d237..cefd9f753a1 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -311,6 +311,7 @@ enum vkd3d_shader_opcode - VKD3DSIH_CND, - VKD3DSIH_CONTINUE, - VKD3DSIH_CONTINUEP, -+ VKD3DSIH_COS, - VKD3DSIH_COUNTBITS, - VKD3DSIH_CRS, - VKD3DSIH_CUT, -@@ -537,6 +538,7 @@ enum vkd3d_shader_opcode - VKD3DSIH_SETP, - VKD3DSIH_SGE, - VKD3DSIH_SGN, -+ VKD3DSIH_SIN, - VKD3DSIH_SINCOS, - VKD3DSIH_SLT, - VKD3DSIH_SQRT, -diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c -index 819185796c0..0a5bd1122e3 100644 ---- a/libs/vkd3d/libs/vkd3d/state.c -+++ b/libs/vkd3d/libs/vkd3d/state.c -@@ -2383,7 +2383,9 @@ static HRESULT create_shader_stage(struct d3d12_device *device, - const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; - struct vkd3d_shader_compile_info compile_info; - struct VkShaderModuleCreateInfo shader_desc; -+ struct vkd3d_shader_dxbc_desc dxbc_desc; - struct vkd3d_shader_code spirv = {0}; -+ char source_name[33]; - VkResult vr; - int ret; - -@@ -2416,6 +2418,16 @@ static HRESULT create_shader_stage(struct d3d12_device *device, - compile_info.log_level = VKD3D_SHADER_LOG_NONE; - compile_info.source_name = NULL; - -+ if ((ret = vkd3d_shader_parse_dxbc(&(struct vkd3d_shader_code){code->pShaderBytecode, code->BytecodeLength}, -+ 0, &dxbc_desc, NULL)) >= 0) -+ { -+ sprintf(source_name, "%08x%08x%08x%08x", dxbc_desc.checksum[0], -+ dxbc_desc.checksum[1], dxbc_desc.checksum[2], dxbc_desc.checksum[3]); -+ vkd3d_shader_free_dxbc(&dxbc_desc); -+ TRACE("Compiling shader \"%s\".\n", source_name); -+ compile_info.source_name = source_name; -+ } -+ - if ((ret = vkd3d_shader_parse_dxbc_source_type(&compile_info.source, &compile_info.source_type, NULL)) < 0 - || (ret = vkd3d_shader_compile(&compile_info, &spirv, NULL)) < 0) - { --- -2.47.2 - diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-decc155cca45d7c4a60699990452b921a6e.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-decc155cca45d7c4a60699990452b921a6e.patch new file mode 100644 index 00000000..e574dba0 --- /dev/null +++ b/patches/vkd3d-latest/0003-Updated-vkd3d-to-decc155cca45d7c4a60699990452b921a6e.patch @@ -0,0 +1,3953 @@ +From 5b7b35ffd27cb5f72982f4d298995f7ace9ae55f Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Tue, 22 Jul 2025 07:27:52 +1000 +Subject: [PATCH] Updated vkd3d to decc155cca45d7c4a60699990452b921a6e0fa65. + +--- + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 24 +- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 25 +- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 128 ++-- + libs/vkd3d/libs/vkd3d-shader/glsl.c | 44 +- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 219 +++--- + libs/vkd3d/libs/vkd3d-shader/ir.c | 639 ++++++++++-------- + libs/vkd3d/libs/vkd3d-shader/msl.c | 40 +- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 60 +- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 75 +- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 16 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 109 ++- + 11 files changed, 806 insertions(+), 573 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +index ae9278f68b1..7d10cf98f71 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +@@ -384,25 +384,25 @@ static void shader_print_resource_type(struct vkd3d_d3d_asm_compiler *compiler, + compiler->colours.error, type, compiler->colours.reset); + } + +-static void shader_print_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_data_type type) ++static void shader_print_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum vsir_data_type type) + { + static const char *const data_type_names[] = + { +- [VKD3D_DATA_FLOAT ] = "float", + [VKD3D_DATA_INT ] = "int", + [VKD3D_DATA_UINT ] = "uint", + [VKD3D_DATA_UNORM ] = "unorm", + [VKD3D_DATA_SNORM ] = "snorm", + [VKD3D_DATA_OPAQUE ] = "opaque", + [VKD3D_DATA_MIXED ] = "mixed", +- [VKD3D_DATA_DOUBLE ] = "double", + [VKD3D_DATA_CONTINUED] = "", + [VKD3D_DATA_UNUSED ] = "", + [VKD3D_DATA_UINT8 ] = "uint8", + [VKD3D_DATA_UINT64 ] = "uint64", + [VKD3D_DATA_BOOL ] = "bool", + [VKD3D_DATA_UINT16 ] = "uint16", +- [VKD3D_DATA_HALF ] = "half", ++ [VSIR_DATA_F16 ] = "half", ++ [VSIR_DATA_F32 ] = "float", ++ [VSIR_DATA_F64 ] = "double", + }; + + if (type < ARRAY_SIZE(data_type_names)) +@@ -412,7 +412,7 @@ static void shader_print_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum + compiler->colours.error, type, compiler->colours.reset); + } + +-static void shader_dump_resource_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type) ++static void shader_dump_resource_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vsir_data_type *type) + { + int i; + +@@ -730,7 +730,7 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const + case VSIR_DIMENSION_SCALAR: + switch (reg->data_type) + { +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + if (untyped) + shader_print_untyped_literal(compiler, "", reg->u.immconst_u32[0], ""); + else +@@ -752,7 +752,7 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const + case VSIR_DIMENSION_VEC4: + switch (reg->data_type) + { +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + if (untyped) + { + shader_print_untyped_literal(compiler, "", reg->u.immconst_u32[0], ""); +@@ -800,7 +800,7 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const + /* A double2 vector is treated as a float4 vector in enum vsir_dimension. */ + if (reg->dimension == VSIR_DIMENSION_SCALAR || reg->dimension == VSIR_DIMENSION_VEC4) + { +- if (reg->data_type == VKD3D_DATA_DOUBLE) ++ if (reg->data_type == VSIR_DATA_F64) + { + shader_print_double_literal(compiler, "", reg->u.immconst_f64[0], ""); + if (reg->dimension == VSIR_DIMENSION_VEC4) +@@ -1684,10 +1684,10 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, + shader_print_int_literal(compiler, ",", ins->texel_offset.w, ")"); + } + +- if (ins->resource_data_type[0] != VKD3D_DATA_FLOAT +- || ins->resource_data_type[1] != VKD3D_DATA_FLOAT +- || ins->resource_data_type[2] != VKD3D_DATA_FLOAT +- || ins->resource_data_type[3] != VKD3D_DATA_FLOAT) ++ if (ins->resource_data_type[0] != VSIR_DATA_F32 ++ || ins->resource_data_type[1] != VSIR_DATA_F32 ++ || ins->resource_data_type[2] != VSIR_DATA_F32 ++ || ins->resource_data_type[3] != VSIR_DATA_F32) + shader_dump_resource_data_type(compiler, ins->resource_data_type); + + for (i = 0; i < ins->dst_count; ++i) +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index eeb4deff61f..2dd9c731010 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -563,7 +563,7 @@ static void d3dbc_parse_register(struct vkd3d_shader_sm1_parser *d3dbc, + + reg_type = parse_register_type(d3dbc, param, &index_offset); + idx_count = idx_count_from_reg_type(reg_type); +- vsir_register_init(reg, reg_type, VKD3D_DATA_FLOAT, idx_count); ++ vsir_register_init(reg, reg_type, VSIR_DATA_F32, idx_count); + reg->precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT; + reg->non_uniform = false; + if (idx_count == 1) +@@ -1088,10 +1088,10 @@ static void shader_sm1_read_semantic(struct vkd3d_shader_sm1_parser *sm1, + { + semantic->resource_type = resource_type_table[resource_type]; + } +- semantic->resource_data_type[0] = VKD3D_DATA_FLOAT; +- semantic->resource_data_type[1] = VKD3D_DATA_FLOAT; +- semantic->resource_data_type[2] = VKD3D_DATA_FLOAT; +- semantic->resource_data_type[3] = VKD3D_DATA_FLOAT; ++ semantic->resource_data_type[0] = VSIR_DATA_F32; ++ semantic->resource_data_type[1] = VSIR_DATA_F32; ++ semantic->resource_data_type[2] = VSIR_DATA_F32; ++ semantic->resource_data_type[3] = VSIR_DATA_F32; + shader_sm1_parse_dst_param(sm1, dst_token, NULL, &semantic->resource.reg); + range = &semantic->resource.range; + range->space = 0; +@@ -1101,7 +1101,7 @@ static void shader_sm1_read_semantic(struct vkd3d_shader_sm1_parser *sm1, + } + + static void shader_sm1_read_immconst(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr, +- struct vkd3d_shader_src_param *src_param, enum vsir_dimension dimension, enum vkd3d_data_type data_type) ++ struct vkd3d_shader_src_param *src_param, enum vsir_dimension dimension, enum vsir_data_type data_type) + { + unsigned int count = dimension == VSIR_DIMENSION_VEC4 ? 4 : 1; + +@@ -1272,10 +1272,10 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str + + ins->resource_type = VKD3D_SHADER_RESOURCE_NONE; + ins->resource_stride = 0; +- ins->resource_data_type[0] = VKD3D_DATA_FLOAT; +- ins->resource_data_type[1] = VKD3D_DATA_FLOAT; +- ins->resource_data_type[2] = VKD3D_DATA_FLOAT; +- ins->resource_data_type[3] = VKD3D_DATA_FLOAT; ++ ins->resource_data_type[0] = VSIR_DATA_F32; ++ ins->resource_data_type[1] = VSIR_DATA_F32; ++ ins->resource_data_type[2] = VSIR_DATA_F32; ++ ins->resource_data_type[3] = VSIR_DATA_F32; + memset(&ins->texel_offset, 0, sizeof(ins->texel_offset)); + + p = *ptr; +@@ -1295,7 +1295,7 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str + else if (ins->opcode == VSIR_OP_DEF) + { + shader_sm1_read_dst_param(sm1, &p, dst_param); +- shader_sm1_read_immconst(sm1, &p, &src_params[0], VSIR_DIMENSION_VEC4, VKD3D_DATA_FLOAT); ++ shader_sm1_read_immconst(sm1, &p, &src_params[0], VSIR_DIMENSION_VEC4, VSIR_DATA_F32); + shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask, true); + } + else if (ins->opcode == VSIR_OP_DEFB) +@@ -2147,6 +2147,9 @@ int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, + if ((result = vsir_allocate_temp_registers(program, message_context))) + return result; + ++ if ((result = vsir_update_dcl_temps(program, message_context))) ++ return result; ++ + d3dbc.program = program; + d3dbc.message_context = message_context; + switch (version->type) +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index db74a7bfbcc..f8f0d2543bd 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -882,9 +882,9 @@ struct sm6_descriptor_info + struct vkd3d_shader_register_range range; + enum vkd3d_shader_resource_type resource_type; + enum dxil_resource_kind kind; +- enum vkd3d_data_type resource_data_type; ++ enum vsir_data_type resource_data_type; + enum vkd3d_shader_register_type reg_type; +- enum vkd3d_data_type reg_data_type; ++ enum vsir_data_type reg_data_type; + }; + + struct sm6_parser +@@ -2467,13 +2467,13 @@ static struct vkd3d_shader_dst_param *instruction_dst_params_alloc(struct vkd3d_ + } + + static void register_init_with_id(struct vkd3d_shader_register *reg, +- enum vkd3d_shader_register_type reg_type, enum vkd3d_data_type data_type, unsigned int id) ++ enum vkd3d_shader_register_type reg_type, enum vsir_data_type data_type, unsigned int id) + { + vsir_register_init(reg, reg_type, data_type, 1); + reg->idx[0].offset = id; + } + +-static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type *type) ++static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type) + { + if (type->class == TYPE_CLASS_INTEGER) + { +@@ -2499,14 +2499,14 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type + switch (type->u.width) + { + case 16: +- return VKD3D_DATA_HALF; ++ return VSIR_DATA_F16; + case 32: +- return VKD3D_DATA_FLOAT; ++ return VSIR_DATA_F32; + case 64: +- return VKD3D_DATA_DOUBLE; ++ return VSIR_DATA_F64; + default: + FIXME("Unhandled width %u.\n", type->u.width); +- return VKD3D_DATA_FLOAT; ++ return VSIR_DATA_F32; + } + } + +@@ -2562,8 +2562,8 @@ static void register_convert_to_minimum_precision(struct vkd3d_shader_register * + + switch (reg->data_type) + { +- case VKD3D_DATA_HALF: +- reg->data_type = VKD3D_DATA_FLOAT; ++ case VSIR_DATA_F16: ++ reg->data_type = VSIR_DATA_F32; + reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_FLOAT_16; + if (reg->type == VKD3DSPR_IMMCONST) + { +@@ -2594,10 +2594,10 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str + struct sm6_parser *sm6) + { + const struct sm6_type *scalar_type; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + + scalar_type = sm6_type_get_scalar_type(value->type, 0); +- data_type = vkd3d_data_type_from_sm6_type(scalar_type); ++ data_type = vsir_data_type_from_dxil(scalar_type); + + switch (value->value_type) + { +@@ -3237,7 +3237,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + dst->u.data = icb; + + icb->register_idx = sm6->icb_count++; +- icb->data_type = vkd3d_data_type_from_sm6_type(elem_type); ++ icb->data_type = vsir_data_type_from_dxil(elem_type); + icb->element_count = type->u.array.count; + icb->component_count = 1; + icb->is_null = !operands; +@@ -3248,10 +3248,10 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + count = type->u.array.count; + switch (icb->data_type) + { +- case VKD3D_DATA_HALF: ++ case VSIR_DATA_F16: + for (i = 0; i < count; ++i) + icb->data[i] = half_to_float(operands[i]); +- icb->data_type = VKD3D_DATA_FLOAT; ++ icb->data_type = VSIR_DATA_F32; + break; + + case VKD3D_DATA_UINT16: +@@ -3260,13 +3260,13 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + icb->data_type = VKD3D_DATA_UINT; + break; + +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + case VKD3D_DATA_UINT: + for (i = 0; i < count; ++i) + icb->data[i] = operands[i]; + break; + +- case VKD3D_DATA_DOUBLE: ++ case VSIR_DATA_F64: + case VKD3D_DATA_UINT64: + data64 = (uint64_t *)icb->data; + for (i = 0; i < count; ++i) +@@ -3690,7 +3690,7 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const stru + unsigned int count, unsigned int alignment, bool has_function_scope, unsigned int init, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst) + { +- enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); ++ enum vsir_data_type data_type = vsir_data_type_from_dxil(elem_type); + + if (ins) + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_DCL_INDEXABLE_TEMP); +@@ -4068,8 +4068,8 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) + return VKD3D_OK; + } + +-static void dst_param_io_init(struct vkd3d_shader_dst_param *param, +- const struct signature_element *e, enum vkd3d_shader_register_type reg_type) ++static void dst_param_io_init(struct vkd3d_shader_dst_param *param, const struct signature_element *e, ++ enum vkd3d_shader_register_type reg_type, enum vsir_dimension dimension) + { + enum vkd3d_shader_component_type component_type; + +@@ -4078,8 +4078,8 @@ static void dst_param_io_init(struct vkd3d_shader_dst_param *param, + param->shift = 0; + /* DXIL types do not have signedness. Load signed elements as unsigned. */ + component_type = e->component_type == VKD3D_SHADER_COMPONENT_INT ? VKD3D_SHADER_COMPONENT_UINT : e->component_type; +- vsir_register_init(¶m->reg, reg_type, vkd3d_data_type_from_component_type(component_type), 0); +- param->reg.dimension = VSIR_DIMENSION_VEC4; ++ vsir_register_init(¶m->reg, reg_type, vsir_data_type_from_component_type(component_type), 0); ++ param->reg.dimension = dimension; + } + + static void src_params_init_from_operands(struct vkd3d_shader_src_param *src_params, +@@ -4092,8 +4092,10 @@ static void src_params_init_from_operands(struct vkd3d_shader_src_param *src_par + } + + static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( +- enum vkd3d_shader_sysval_semantic sysval_semantic, bool is_input) ++ enum vkd3d_shader_sysval_semantic sysval_semantic, bool is_input, enum vsir_dimension *dimension) + { ++ *dimension = VSIR_DIMENSION_VEC4; ++ + switch (sysval_semantic) + { + /* VSIR does not use an I/O register for SV_SampleIndex, but its +@@ -4104,10 +4106,13 @@ static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( + case VKD3D_SHADER_SV_COVERAGE: + return is_input ? VKD3DSPR_COVERAGE : VKD3DSPR_SAMPLEMASK; + case VKD3D_SHADER_SV_DEPTH: ++ *dimension = VSIR_DIMENSION_SCALAR; + return VKD3DSPR_DEPTHOUT; + case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL: ++ *dimension = VSIR_DIMENSION_SCALAR; + return VKD3DSPR_DEPTHOUTGE; + case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL: ++ *dimension = VSIR_DIMENSION_SCALAR; + return VKD3DSPR_DEPTHOUTLE; + default: + return VKD3DSPR_INVALID; +@@ -4147,18 +4152,21 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade + + for (i = 0; i < s->element_count; ++i) + { ++ enum vsir_dimension dimension; ++ + e = &s->elements[i]; + + param = ¶ms[i]; + + if (e->register_index == UINT_MAX +- && (io_reg_type = register_type_from_dxil_semantic_kind(e->sysval_semantic, is_input)) != VKD3DSPR_NULL) ++ && (io_reg_type = register_type_from_dxil_semantic_kind( ++ e->sysval_semantic, is_input, &dimension)) != VKD3DSPR_NULL) + { +- dst_param_io_init(param, e, io_reg_type); ++ dst_param_io_init(param, e, io_reg_type, dimension); + continue; + } + +- dst_param_io_init(param, e, reg_type); ++ dst_param_io_init(param, e, reg_type, VSIR_DIMENSION_VEC4); + count = 0; + + if (is_control_point) +@@ -5169,7 +5177,7 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr + + type = sm6_type_get_scalar_type(dst->type, 0); + VKD3D_ASSERT(type); +- src_param->reg.data_type = vkd3d_data_type_from_sm6_type(type); ++ src_param->reg.data_type = vsir_data_type_from_dxil(type); + if (data_type_is_64_bit(src_param->reg.data_type)) + src_param->swizzle = vsir_swizzle_64_from_32(src_param->swizzle); + else +@@ -5179,7 +5187,7 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr + } + + static void sm6_parser_dcl_register_builtin(struct sm6_parser *sm6, enum vkd3d_shader_opcode handler_idx, +- enum vkd3d_shader_register_type reg_type, enum vkd3d_data_type data_type, unsigned int component_count) ++ enum vkd3d_shader_register_type reg_type, enum vsir_data_type data_type, unsigned int component_count) + { + struct vkd3d_shader_dst_param *dst_param; + struct vkd3d_shader_instruction *ins; +@@ -5194,8 +5202,8 @@ static void sm6_parser_dcl_register_builtin(struct sm6_parser *sm6, enum vkd3d_s + } + } + +-static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, +- struct vkd3d_shader_instruction *ins, enum vkd3d_shader_register_type reg_type, enum vkd3d_data_type data_type) ++static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, struct vkd3d_shader_instruction *ins, ++ enum vkd3d_shader_register_type reg_type, enum vsir_data_type data_type, bool scalar) + { + struct vkd3d_shader_src_param *src_param; + +@@ -5205,6 +5213,8 @@ static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, + return; + sm6_parser_dcl_register_builtin(sm6, VSIR_OP_DCL_INPUT, reg_type, data_type, 1); + vsir_register_init(&src_param->reg, reg_type, data_type, 0); ++ if (!scalar) ++ src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init(src_param); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +@@ -5213,7 +5223,7 @@ static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, + static void sm6_parser_emit_dx_coverage(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_COVERAGE, VKD3D_DATA_UINT); ++ sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_COVERAGE, VKD3D_DATA_UINT, false); + } + + static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_parser *sm6, +@@ -5333,8 +5343,8 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- sm6_parser_dcl_register_builtin(sm6, VSIR_OP_DCL_INPUT, VKD3DSPR_TESSCOORD, VKD3D_DATA_FLOAT, 3); +- vsir_register_init(&src_param->reg, VKD3DSPR_TESSCOORD, VKD3D_DATA_FLOAT, 0); ++ sm6_parser_dcl_register_builtin(sm6, VSIR_OP_DCL_INPUT, VKD3DSPR_TESSCOORD, VSIR_DATA_F32, 3); ++ vsir_register_init(&src_param->reg, VKD3DSPR_TESSCOORD, VSIR_DATA_F32, 0); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init_scalar(src_param, component_idx); + +@@ -5477,11 +5487,9 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; + vsir_register_init(&src_param->reg, reg_type, VKD3D_DATA_UINT, 0); ++ src_param->reg.dimension = VSIR_DIMENSION_VEC4; + if (component_count > 1) +- { +- src_param->reg.dimension = VSIR_DIMENSION_VEC4; + component_idx = sm6_value_get_constant_uint(operands[0], sm6); +- } + src_param_init_scalar(src_param, component_idx); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +@@ -5713,13 +5721,13 @@ static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intri + static void sm6_parser_emit_dx_output_control_point_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_OUTPOINTID, VKD3D_DATA_UINT); ++ sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_OUTPOINTID, VKD3D_DATA_UINT, true); + } + + static void sm6_parser_emit_dx_primitive_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_PRIMID, VKD3D_DATA_UINT); ++ sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_PRIMID, VKD3D_DATA_UINT, true); + } + + static enum vkd3d_shader_opcode dx_map_quad_op(enum dxil_quad_op_kind op) +@@ -5996,12 +6004,12 @@ static void sm6_parser_emit_dx_get_sample_count(struct sm6_parser *sm6, enum dx_ + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- vsir_register_init(&src_param->reg, VKD3DSPR_RASTERIZER, VKD3D_DATA_FLOAT, 0); ++ vsir_register_init(&src_param->reg, VKD3DSPR_RASTERIZER, VSIR_DATA_F32, 0); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init(src_param); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +- ins->dst->reg.data_type = VKD3D_DATA_FLOAT; ++ ins->dst->reg.data_type = VSIR_DATA_F32; + } + + static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -6030,7 +6038,7 @@ static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_in + else + { + src_param_init_vector(&src_params[0], 2); +- vsir_register_init(&src_params[0].reg, VKD3DSPR_RASTERIZER, VKD3D_DATA_FLOAT, 0); ++ vsir_register_init(&src_params[0].reg, VKD3DSPR_RASTERIZER, VSIR_DATA_F32, 0); + src_params[0].reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init_from_value(&src_params[1], operands[0], sm6); + } +@@ -6535,7 +6543,7 @@ static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *sm6, enum dx_intr + vkd3d_unreachable(); + } + +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, type, VKD3D_DATA_UINT); ++ sm6_parser_emit_dx_input_register_mov(sm6, state->ins, type, VKD3D_DATA_UINT, true); + } + + struct sm6_dx_opcode_info +@@ -9031,7 +9039,7 @@ static enum vkd3d_shader_resource_type shader_resource_type_from_dxil_resource_k + } + } + +-static const enum vkd3d_data_type data_type_table[] = ++static const enum vsir_data_type data_type_table[] = + { + [COMPONENT_TYPE_INVALID] = VKD3D_DATA_UNUSED, + [COMPONENT_TYPE_I1] = VKD3D_DATA_UNUSED, +@@ -9041,30 +9049,30 @@ static const enum vkd3d_data_type data_type_table[] = + [COMPONENT_TYPE_U32] = VKD3D_DATA_UINT, + [COMPONENT_TYPE_I64] = VKD3D_DATA_UNUSED, + [COMPONENT_TYPE_U64] = VKD3D_DATA_UNUSED, +- [COMPONENT_TYPE_F16] = VKD3D_DATA_FLOAT, +- [COMPONENT_TYPE_F32] = VKD3D_DATA_FLOAT, +- [COMPONENT_TYPE_F64] = VKD3D_DATA_DOUBLE, ++ [COMPONENT_TYPE_F16] = VSIR_DATA_F32, ++ [COMPONENT_TYPE_F32] = VSIR_DATA_F32, ++ [COMPONENT_TYPE_F64] = VSIR_DATA_F64, + [COMPONENT_TYPE_SNORMF16] = VKD3D_DATA_SNORM, + [COMPONENT_TYPE_UNORMF16] = VKD3D_DATA_UNORM, + [COMPONENT_TYPE_SNORMF32] = VKD3D_DATA_SNORM, + [COMPONENT_TYPE_UNORMF32] = VKD3D_DATA_UNORM, +- [COMPONENT_TYPE_SNORMF64] = VKD3D_DATA_DOUBLE, +- [COMPONENT_TYPE_UNORMF64] = VKD3D_DATA_DOUBLE, ++ [COMPONENT_TYPE_SNORMF64] = VSIR_DATA_F64, ++ [COMPONENT_TYPE_UNORMF64] = VSIR_DATA_F64, + [COMPONENT_TYPE_PACKEDS8X32] = VKD3D_DATA_UNUSED, + [COMPONENT_TYPE_PACKEDU8X32] = VKD3D_DATA_UNUSED, + }; + +-static enum vkd3d_data_type vkd3d_data_type_from_dxil_component_type(enum dxil_component_type type, ++static enum vsir_data_type vsir_data_type_from_dxil_component_type(enum dxil_component_type type, + struct sm6_parser *sm6) + { +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + + if (type >= ARRAY_SIZE(data_type_table) || (data_type = data_type_table[type]) == VKD3D_DATA_UNUSED) + { + FIXME("Unhandled component type %u.\n", type); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "Resource descriptor component type %u is unhandled.", type); +- return VKD3D_DATA_FLOAT; ++ return VSIR_DATA_F32; + } + + return data_type; +@@ -9072,7 +9080,7 @@ static enum vkd3d_data_type vkd3d_data_type_from_dxil_component_type(enum dxil_c + + struct resource_additional_values + { +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + unsigned int byte_stride; + }; + +@@ -9113,7 +9121,7 @@ static bool resources_load_additional_values(struct resource_additional_values * + "An untyped resource has type %u.", value); + return false; + } +- info->data_type = vkd3d_data_type_from_dxil_component_type(value, sm6); ++ info->data_type = vsir_data_type_from_dxil_component_type(value, sm6); + break; + + case RESOURCE_TAG_ELEMENT_STRIDE: +@@ -9241,8 +9249,8 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc + } + + static void init_resource_declaration(struct vkd3d_shader_resource *resource, +- enum vkd3d_shader_register_type reg_type, enum vkd3d_data_type data_type, unsigned int id, +- const struct vkd3d_shader_register_range *range) ++ enum vkd3d_shader_register_type reg_type, enum vsir_data_type data_type, ++ unsigned int id, const struct vkd3d_shader_register_range *range) + { + struct vkd3d_shader_dst_param *param = &resource->reg; + +@@ -9413,7 +9421,7 @@ static enum vkd3d_result sm6_parser_resources_load_cbv(struct sm6_parser *sm6, + ins->declaration.cb.src.modifiers = VKD3DSPSM_NONE; + + reg = &ins->declaration.cb.src.reg; +- vsir_register_init(reg, VKD3DSPR_CONSTBUFFER, VKD3D_DATA_FLOAT, 3); ++ vsir_register_init(reg, VKD3DSPR_CONSTBUFFER, VSIR_DATA_F32, 3); + reg->idx[0].offset = d->id; + reg->idx[1].offset = d->range.first; + reg->idx[2].offset = d->range.last; +@@ -9421,8 +9429,8 @@ static enum vkd3d_result sm6_parser_resources_load_cbv(struct sm6_parser *sm6, + ins->declaration.cb.range = d->range; + + d->reg_type = VKD3DSPR_CONSTBUFFER; +- d->reg_data_type = VKD3D_DATA_FLOAT; +- d->resource_data_type = VKD3D_DATA_FLOAT; ++ d->reg_data_type = VSIR_DATA_F32; ++ d->resource_data_type = VSIR_DATA_F32; + + return VKD3D_OK; + } +@@ -9815,7 +9823,9 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const + + if ((is_register = e->register_index == UINT_MAX)) + { +- if (register_type_from_dxil_semantic_kind(e->sysval_semantic, is_input) == VKD3DSPR_INVALID) ++ enum vsir_dimension dimension; ++ ++ if (register_type_from_dxil_semantic_kind(e->sysval_semantic, is_input, &dimension) == VKD3DSPR_INVALID) + { + WARN("Unhandled I/O register semantic kind %u.\n", j); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE, +diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c +index b3e3d10791d..bf407f0fc9c 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c +@@ -328,12 +328,12 @@ static void glsl_src_cleanup(struct glsl_src *src, struct vkd3d_string_buffer_ca + } + + static void shader_glsl_print_bitcast(struct vkd3d_string_buffer *dst, struct vkd3d_glsl_generator *gen, +- const char *src, enum vkd3d_data_type dst_data_type, enum vkd3d_data_type src_data_type, unsigned int size) ++ const char *src, enum vsir_data_type dst_data_type, enum vsir_data_type src_data_type, unsigned int size) + { + if (dst_data_type == VKD3D_DATA_UNORM || dst_data_type == VKD3D_DATA_SNORM) +- dst_data_type = VKD3D_DATA_FLOAT; ++ dst_data_type = VSIR_DATA_F32; + if (src_data_type == VKD3D_DATA_UNORM || src_data_type == VKD3D_DATA_SNORM) +- src_data_type = VKD3D_DATA_FLOAT; ++ src_data_type = VSIR_DATA_F32; + + if (dst_data_type == src_data_type) + { +@@ -341,7 +341,7 @@ static void shader_glsl_print_bitcast(struct vkd3d_string_buffer *dst, struct vk + return; + } + +- if (src_data_type == VKD3D_DATA_FLOAT) ++ if (src_data_type == VSIR_DATA_F32) + { + switch (dst_data_type) + { +@@ -360,7 +360,7 @@ static void shader_glsl_print_bitcast(struct vkd3d_string_buffer *dst, struct vk + { + switch (dst_data_type) + { +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + vkd3d_string_buffer_printf(dst, "uintBitsToFloat(%s)", src); + return; + case VKD3D_DATA_INT: +@@ -381,11 +381,11 @@ static void shader_glsl_print_bitcast(struct vkd3d_string_buffer *dst, struct vk + } + + static void shader_glsl_print_src(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, +- const struct vkd3d_shader_src_param *vsir_src, uint32_t mask, enum vkd3d_data_type data_type) ++ const struct vkd3d_shader_src_param *vsir_src, uint32_t mask, enum vsir_data_type data_type) + { + const struct vkd3d_shader_register *reg = &vsir_src->reg; + struct vkd3d_string_buffer *register_name, *str; +- enum vkd3d_data_type src_data_type; ++ enum vsir_data_type src_data_type; + unsigned int size; + + register_name = vkd3d_string_buffer_get(&gen->string_buffers); +@@ -397,7 +397,7 @@ static void shader_glsl_print_src(struct vkd3d_string_buffer *buffer, struct vkd + if (reg->type == VKD3DSPR_IMMCONST || reg->type == VKD3DSPR_THREADID) + src_data_type = VKD3D_DATA_UINT; + else +- src_data_type = VKD3D_DATA_FLOAT; ++ src_data_type = VSIR_DATA_F32; + + shader_glsl_print_register_name(register_name, gen, reg); + +@@ -492,7 +492,7 @@ static void shader_glsl_print_subscript(struct vkd3d_string_buffer *buffer, stru + } + + static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_glsl_generator *gen, +- struct glsl_dst *dst, enum vkd3d_data_type data_type, const char *format, va_list args) ++ struct glsl_dst *dst, enum vsir_data_type data_type, const char *format, va_list args) + { + struct vkd3d_string_buffer *buffer = gen->buffer; + uint32_t modifiers = dst->vsir->modifiers; +@@ -519,7 +519,7 @@ static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_g + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled destination register data type %#x.", data_type); + /* fall through */ +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + close = false; + break; + case VKD3D_DATA_INT: +@@ -550,7 +550,7 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( + } + + static void VKD3D_PRINTF_FUNC(4, 5) shader_glsl_print_assignment_ext(struct vkd3d_glsl_generator *gen, +- struct glsl_dst *dst, enum vkd3d_data_type data_type, const char *format, ...) ++ struct glsl_dst *dst, enum vsir_data_type data_type, const char *format, ...) + { + va_list args; + +@@ -797,7 +797,7 @@ static void shader_glsl_ld(struct vkd3d_glsl_generator *gen, const struct vkd3d_ + const struct vkd3d_shader_descriptor_info1 *d; + enum vkd3d_shader_resource_type resource_type; + struct vkd3d_string_buffer *fetch; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + struct glsl_src coord; + struct glsl_dst dst; + uint32_t coord_mask; +@@ -826,7 +826,7 @@ static void shader_glsl_ld(struct vkd3d_glsl_generator *gen, const struct vkd3d_ + resource_space = 0; + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; + sample_count = 1; +- data_type = VKD3D_DATA_FLOAT; ++ data_type = VSIR_DATA_F32; + } + + if ((resource_type_info = shader_glsl_get_resource_type_info(resource_type))) +@@ -912,7 +912,7 @@ static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vk + enum vkd3d_shader_resource_type resource_type; + unsigned int component_idx, coord_size; + struct vkd3d_string_buffer *sample; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + struct glsl_dst dst; + + bias = ins->opcode == VSIR_OP_SAMPLE_B; +@@ -946,7 +946,7 @@ static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vk + "Internal compiler error: Undeclared resource descriptor %u.", resource_id); + resource_space = 0; + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; +- data_type = VKD3D_DATA_FLOAT; ++ data_type = VSIR_DATA_F32; + } + + if ((resource_type_info = shader_glsl_get_resource_type_info(resource_type))) +@@ -1061,7 +1061,7 @@ static void shader_glsl_load_uav_typed(struct vkd3d_glsl_generator *gen, const s + enum vkd3d_shader_resource_type resource_type; + unsigned int uav_id, uav_idx, uav_space; + struct vkd3d_string_buffer *load; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + struct glsl_src coord; + struct glsl_dst dst; + uint32_t coord_mask; +@@ -1084,7 +1084,7 @@ static void shader_glsl_load_uav_typed(struct vkd3d_glsl_generator *gen, const s + "Internal compiler error: Undeclared UAV descriptor %u.", uav_id); + uav_space = 0; + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; +- data_type = VKD3D_DATA_FLOAT; ++ data_type = VSIR_DATA_F32; + } + + if ((resource_type_info = shader_glsl_get_resource_type_info(resource_type))) +@@ -1121,7 +1121,7 @@ static void shader_glsl_store_uav_typed(struct vkd3d_glsl_generator *gen, const + enum vkd3d_shader_resource_type resource_type; + unsigned int uav_id, uav_idx, uav_space; + struct vkd3d_string_buffer *image_data; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + struct glsl_src image_coord; + uint32_t coord_mask; + +@@ -1143,7 +1143,7 @@ static void shader_glsl_store_uav_typed(struct vkd3d_glsl_generator *gen, const + "Internal compiler error: Undeclared UAV descriptor %u.", uav_id); + uav_space = 0; + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; +- data_type = VKD3D_DATA_FLOAT; ++ data_type = VSIR_DATA_F32; + } + + if ((resource_type_info = shader_glsl_get_resource_type_info(resource_type))) +@@ -1174,7 +1174,7 @@ static void shader_glsl_store_uav_typed(struct vkd3d_glsl_generator *gen, const + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled data type %#x.", data_type); + /* fall through */ +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + case VKD3D_DATA_UNORM: + case VKD3D_DATA_SNORM: + vkd3d_string_buffer_printf(image_data, "vec4("); +@@ -1779,7 +1779,7 @@ static void shader_glsl_generate_uav_declaration(struct vkd3d_glsl_generator *ge + "Internal compiler error: Unhandled data type %#x for UAV %u.", + uav->resource_data_type, uav->register_id); + /* fall through */ +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + case VKD3D_DATA_UNORM: + case VKD3D_DATA_SNORM: + image_type_prefix = ""; +@@ -2001,7 +2001,7 @@ static void shader_glsl_generate_sampler_declaration(struct vkd3d_glsl_generator + case VKD3D_DATA_INT: + sampler_type_prefix = "i"; + break; +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + case VKD3D_DATA_UNORM: + case VKD3D_DATA_SNORM: + sampler_type_prefix = ""; +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index afd6169514f..86198ce548f 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -233,6 +233,20 @@ static bool divert_written_uniform_derefs_to_temp(struct hlsl_ctx *ctx, struct h + return true; + } + ++static void warn_on_field_semantic(struct hlsl_ctx *ctx, ++ const struct hlsl_struct_field *field, const struct hlsl_semantic *outer) ++{ ++ if (!field->semantic.name) ++ return; ++ ++ if (!ascii_strcasecmp(field->semantic.name, outer->name) && field->semantic.index == outer->index) ++ return; ++ ++ hlsl_warning(ctx, &field->loc, VKD3D_SHADER_WARNING_HLSL_OVERRIDDEN_SEMANTIC, ++ "Field semantic %s%u is overridden by outer semantic %s%u.\n", ++ field->semantic.name, field->semantic.index, outer->name, outer->index); ++} ++ + static void validate_field_semantic(struct hlsl_ctx *ctx, struct hlsl_struct_field *field) + { + if (!field->semantic.name && hlsl_is_numeric_type(hlsl_get_multiarray_element_type(field->type)) +@@ -288,10 +302,10 @@ 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_function_decl *func, + struct hlsl_ir_var *var, struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic, +- uint32_t index, uint32_t stream_index, bool output, bool force_align, bool create, +- const struct vkd3d_shader_location *loc) ++ uint32_t stream_index, bool output, bool force_align, bool create, const struct vkd3d_shader_location *loc) + { + struct hlsl_semantic new_semantic; ++ uint32_t index = semantic->index; + struct hlsl_ir_var *ext_var; + const char *prefix; + char *new_name; +@@ -397,7 +411,7 @@ static uint32_t combine_field_storage_modifiers(uint32_t modifiers, uint32_t fie + + static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, + struct hlsl_block *block, uint32_t prim_index, struct hlsl_ir_load *lhs, +- uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align) ++ uint32_t modifiers, struct hlsl_semantic *semantic, bool force_align) + { + struct hlsl_type *type = lhs->node.data_type, *vector_type_src, *vector_type_dst; + struct vkd3d_shader_location *loc = &lhs->node.loc; +@@ -442,8 +456,9 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec + prim_type_src->modifiers = var->data_type->modifiers & HLSL_PRIMITIVE_MODIFIERS_MASK; + + if (!(input = add_semantic_var(ctx, func, var, prim_type_src, +- modifiers, semantic, semantic_index + i, 0, false, force_align, true, loc))) ++ modifiers, semantic, 0, false, force_align, true, loc))) + return; ++ ++semantic->index; + hlsl_init_simple_deref_from_var(&prim_deref, input); + + idx = hlsl_block_add_uint_constant(ctx, block, prim_index, &var->loc); +@@ -455,8 +470,9 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec + else + { + if (!(input = add_semantic_var(ctx, func, var, vector_type_src, +- modifiers, semantic, semantic_index + i, 0, false, force_align, true, loc))) ++ modifiers, semantic, 0, false, force_align, true, loc))) + return; ++ ++semantic->index; + + if (!(load = hlsl_new_var_load(ctx, input, &var->loc))) + return; +@@ -482,7 +498,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec + + static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, + struct hlsl_block *block, uint32_t prim_index, struct hlsl_ir_load *lhs, +- uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align) ++ uint32_t modifiers, struct hlsl_semantic *semantic, bool force_align) + { + struct vkd3d_shader_location *loc = &lhs->node.loc; + struct hlsl_type *type = lhs->node.data_type; +@@ -494,21 +510,31 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_func + { + struct hlsl_ir_load *element_load; + struct hlsl_struct_field *field; +- uint32_t elem_semantic_index; + + for (i = 0; i < hlsl_type_element_count(type); ++i) + { + uint32_t element_modifiers; + ++ if (type->class == HLSL_CLASS_STRUCT) ++ loc = &type->e.record.fields[i].loc; ++ ++ c = hlsl_block_add_uint_constant(ctx, block, i, &var->loc); ++ ++ /* This redundant load is expected to be deleted later by DCE. */ ++ if (!(element_load = hlsl_new_load_index(ctx, &lhs->src, c, loc))) ++ return; ++ hlsl_block_add_instr(block, &element_load->node); ++ + if (type->class == HLSL_CLASS_ARRAY) + { +- elem_semantic_index = semantic_index +- + i * hlsl_type_get_array_element_reg_size(type->e.array.type, HLSL_REGSET_NUMERIC) / 4; + element_modifiers = modifiers; + force_align = true; + + if (hlsl_type_is_primitive_array(type)) + prim_index = i; ++ ++ prepend_input_copy_recurse(ctx, func, block, prim_index, ++ element_load, element_modifiers, semantic, force_align); + } + else + { +@@ -518,28 +544,33 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_func + hlsl_fixme(ctx, &field->loc, "Prepend uniform copies for resource components within structs."); + continue; + } +- validate_field_semantic(ctx, field); +- semantic = &field->semantic; +- elem_semantic_index = semantic->index; +- loc = &field->loc; + element_modifiers = combine_field_storage_modifiers(modifiers, field->storage_modifiers); + force_align = (i == 0); +- } + +- c = hlsl_block_add_uint_constant(ctx, block, i, &var->loc); ++ if (semantic->name) ++ { ++ warn_on_field_semantic(ctx, field, semantic); ++ prepend_input_copy_recurse(ctx, func, block, prim_index, ++ element_load, element_modifiers, semantic, force_align); ++ } ++ else ++ { ++ struct hlsl_semantic semantic_copy; + +- /* This redundant load is expected to be deleted later by DCE. */ +- if (!(element_load = hlsl_new_load_index(ctx, &lhs->src, c, loc))) +- return; +- hlsl_block_add_instr(block, &element_load->node); ++ validate_field_semantic(ctx, field); + +- prepend_input_copy_recurse(ctx, func, block, prim_index, element_load, +- element_modifiers, semantic, elem_semantic_index, force_align); ++ if (!(hlsl_clone_semantic(ctx, &semantic_copy, &field->semantic))) ++ return; ++ prepend_input_copy_recurse(ctx, func, block, prim_index, ++ element_load, element_modifiers, &semantic_copy, force_align); ++ hlsl_cleanup_semantic(&semantic_copy); ++ } ++ } + } + } + else + { +- prepend_input_copy(ctx, func, block, prim_index, lhs, modifiers, semantic, semantic_index, force_align); ++ prepend_input_copy(ctx, func, block, prim_index, lhs, modifiers, semantic, force_align); + } + } + +@@ -547,6 +578,7 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_func + * and copy the former to the latter, so that writes to input variables work. */ + static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_var *var) + { ++ struct hlsl_semantic semantic_copy; + struct hlsl_ir_load *load; + struct hlsl_block block; + +@@ -557,15 +589,20 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function + return; + hlsl_block_add_instr(&block, &load->node); + +- prepend_input_copy_recurse(ctx, func, &block, 0, load, var->storage_modifiers, +- &var->semantic, var->semantic.index, false); ++ if (!hlsl_clone_semantic(ctx, &semantic_copy, &var->semantic)) ++ { ++ hlsl_block_cleanup(&block); ++ return; ++ } ++ prepend_input_copy_recurse(ctx, func, &block, 0, load, var->storage_modifiers, &semantic_copy, false); ++ hlsl_cleanup_semantic(&semantic_copy); + + list_move_head(&func->body.instrs, &block.instrs); + } + + static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_ir_function_decl *func, struct hlsl_ir_load *rhs, uint32_t modifiers, +- struct hlsl_semantic *semantic, uint32_t semantic_index, uint32_t stream_index, bool force_align, bool create) ++ struct hlsl_semantic *semantic, uint32_t stream_index, bool force_align, bool create) + { + struct hlsl_type *type = rhs->node.data_type, *vector_type; + struct vkd3d_shader_location *loc = &rhs->node.loc; +@@ -594,9 +631,10 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_ir_var *output; + struct hlsl_ir_node *load; + +- if (!(output = add_semantic_var(ctx, func, var, vector_type, +- modifiers, semantic, semantic_index + i, stream_index, true, force_align, create, loc))) ++ if (!(output = add_semantic_var(ctx, func, var, vector_type, modifiers, ++ semantic, stream_index, true, force_align, create, loc))) + return; ++ ++semantic->index; + + if (type->class == HLSL_CLASS_MATRIX) + { +@@ -615,8 +653,8 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, + } + + static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, +- struct hlsl_ir_function_decl *func, const struct hlsl_type *type, struct hlsl_ir_load *rhs, uint32_t modifiers, +- struct hlsl_semantic *semantic, uint32_t semantic_index, uint32_t stream_index, bool force_align, bool create) ++ struct hlsl_ir_function_decl *func, const struct hlsl_type *type, struct hlsl_ir_load *rhs, ++ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t stream_index, bool force_align, bool create) + { + struct vkd3d_shader_location *loc = &rhs->node.loc; + struct hlsl_ir_var *var = rhs->src.var; +@@ -627,47 +665,62 @@ static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * + { + for (i = 0; i < hlsl_type_element_count(type); ++i) + { +- uint32_t element_modifiers, elem_semantic_index; + const struct hlsl_type *element_type; + struct hlsl_ir_load *element_load; + struct hlsl_struct_field *field; ++ uint32_t element_modifiers; ++ ++ if (type->class == HLSL_CLASS_STRUCT) ++ loc = &type->e.record.fields[i].loc; ++ ++ c = hlsl_block_add_uint_constant(ctx, block, i, &var->loc); ++ if (!(element_load = hlsl_new_load_index(ctx, &rhs->src, c, loc))) ++ return; ++ hlsl_block_add_instr(block, &element_load->node); + + if (type->class == HLSL_CLASS_ARRAY) + { +- elem_semantic_index = semantic_index +- + i * hlsl_type_get_array_element_reg_size(type->e.array.type, HLSL_REGSET_NUMERIC) / 4; + element_type = type->e.array.type; + element_modifiers = modifiers; + force_align = true; ++ ++ append_output_copy_recurse(ctx, block, func, element_type, element_load, ++ element_modifiers, semantic, stream_index, force_align, create); + } + else + { + field = &type->e.record.fields[i]; + if (hlsl_type_is_resource(field->type)) + continue; +- validate_field_semantic(ctx, field); +- semantic = &field->semantic; +- elem_semantic_index = semantic->index; +- loc = &field->loc; + element_type = field->type; + element_modifiers = combine_field_storage_modifiers(modifiers, field->storage_modifiers); + force_align = (i == 0); +- } + +- c = hlsl_block_add_uint_constant(ctx, block, i, &var->loc); ++ if (semantic->name) ++ { ++ warn_on_field_semantic(ctx, field, semantic); + +- if (!(element_load = hlsl_new_load_index(ctx, &rhs->src, c, loc))) +- return; +- hlsl_block_add_instr(block, &element_load->node); ++ append_output_copy_recurse(ctx, block, func, element_type, element_load, ++ element_modifiers, semantic, stream_index, force_align, create); ++ } ++ else ++ { ++ struct hlsl_semantic semantic_copy; ++ ++ validate_field_semantic(ctx, field); + +- append_output_copy_recurse(ctx, block, func, element_type, element_load, element_modifiers, semantic, +- elem_semantic_index, stream_index, force_align, create); ++ if (!hlsl_clone_semantic(ctx, &semantic_copy, &field->semantic)) ++ continue; ++ append_output_copy_recurse(ctx, block, func, element_type, element_load, ++ element_modifiers, &semantic_copy, stream_index, force_align, create); ++ hlsl_cleanup_semantic(&semantic_copy); ++ } ++ } + } + } + else + { +- append_output_copy(ctx, block, func, rhs, modifiers, semantic, +- semantic_index, stream_index, force_align, create); ++ append_output_copy(ctx, block, func, rhs, modifiers, semantic, stream_index, force_align, create); + } + } + +@@ -676,6 +729,7 @@ static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * + * variables work. */ + static void append_output_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_var *var) + { ++ struct hlsl_semantic semantic_copy; + struct hlsl_ir_load *load; + + /* This redundant load is expected to be deleted later by DCE. */ +@@ -683,8 +737,11 @@ static void append_output_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function + return; + hlsl_block_add_instr(&func->body, &load->node); + +- append_output_copy_recurse(ctx, &func->body, func, var->data_type, load, var->storage_modifiers, +- &var->semantic, var->semantic.index, 0, false, true); ++ if (!hlsl_clone_semantic(ctx, &semantic_copy, &var->semantic)) ++ return; ++ append_output_copy_recurse(ctx, &func->body, func, var->data_type, ++ load, var->storage_modifiers, &semantic_copy, 0, false, true); ++ hlsl_cleanup_semantic(&semantic_copy); + } + + bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), +@@ -3375,6 +3432,7 @@ static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst + { + struct stream_append_ctx *append_ctx = context; + struct hlsl_ir_resource_store *store; ++ struct hlsl_semantic semantic_copy; + const struct hlsl_ir_node *rhs; + const struct hlsl_type *type; + struct hlsl_ir_var *var; +@@ -3405,9 +3463,12 @@ static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst + + hlsl_block_init(&block); + ++ if (!hlsl_clone_semantic(ctx, &semantic_copy, &var->semantic)) ++ return false; + append_output_copy_recurse(ctx, &block, append_ctx->func, type->e.so.type, hlsl_ir_load(rhs), +- var->storage_modifiers, &var->semantic, var->semantic.index, +- var->regs[HLSL_REGSET_STREAM_OUTPUTS].index, false, !append_ctx->created[stream_index]); ++ var->storage_modifiers, &semantic_copy, var->regs[HLSL_REGSET_STREAM_OUTPUTS].index, ++ false, !append_ctx->created[stream_index]); ++ hlsl_cleanup_semantic(&semantic_copy); + + append_ctx->created[stream_index] = true; + +@@ -8164,10 +8225,10 @@ static void generate_vsir_signature(struct hlsl_ctx *ctx, + } + } + +-static enum vkd3d_data_type vsir_data_type_from_hlsl_type(struct hlsl_ctx *ctx, const struct hlsl_type *type) ++static enum vsir_data_type vsir_data_type_from_hlsl_type(struct hlsl_ctx *ctx, const struct hlsl_type *type) + { + if (hlsl_version_lt(ctx, 4, 0)) +- return VKD3D_DATA_FLOAT; ++ return VSIR_DATA_F32; + + if (type->class == HLSL_CLASS_ARRAY) + return vsir_data_type_from_hlsl_type(ctx, type->e.array.type); +@@ -8178,11 +8239,11 @@ static enum vkd3d_data_type vsir_data_type_from_hlsl_type(struct hlsl_ctx *ctx, + switch (type->e.numeric.type) + { + case HLSL_TYPE_DOUBLE: +- return VKD3D_DATA_DOUBLE; ++ return VSIR_DATA_F64; + case HLSL_TYPE_FLOAT: +- return VKD3D_DATA_FLOAT; ++ return VSIR_DATA_F32; + case HLSL_TYPE_HALF: +- return VKD3D_DATA_HALF; ++ return VSIR_DATA_F16; + case HLSL_TYPE_INT: + return VKD3D_DATA_INT; + case HLSL_TYPE_UINT: +@@ -8195,7 +8256,7 @@ static enum vkd3d_data_type vsir_data_type_from_hlsl_type(struct hlsl_ctx *ctx, + return VKD3D_DATA_UNUSED; + } + +-static enum vkd3d_data_type vsir_data_type_from_hlsl_instruction(struct hlsl_ctx *ctx, ++static enum vsir_data_type vsir_data_type_from_hlsl_instruction(struct hlsl_ctx *ctx, + const struct hlsl_ir_node *instr) + { + return vsir_data_type_from_hlsl_type(ctx, instr->data_type); +@@ -8238,17 +8299,17 @@ static void sm1_generate_vsir_constant_defs(struct hlsl_ctx *ctx, struct vsir_pr + ++instructions->count; + + dst_param = &ins->dst[0]; +- vsir_register_init(&dst_param->reg, VKD3DSPR_CONST, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&dst_param->reg, VKD3DSPR_CONST, VSIR_DATA_F32, 1); + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].reg.idx[0].offset = constant_reg->index; + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; + + src_param = &ins->src[0]; +- vsir_register_init(&src_param->reg, VKD3DSPR_IMMCONST, VKD3D_DATA_FLOAT, 0); ++ vsir_register_init(&src_param->reg, VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); + src_param->reg.type = VKD3DSPR_IMMCONST; + src_param->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT; + src_param->reg.non_uniform = false; +- src_param->reg.data_type = VKD3D_DATA_FLOAT; ++ src_param->reg.data_type = VSIR_DATA_F32; + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + for (x = 0; x < 4; ++x) + src_param->reg.u.immconst_f32[x] = constant_reg->value.f[x]; +@@ -8324,7 +8385,7 @@ static void sm1_generate_vsir_sampler_dcls(struct hlsl_ctx *ctx, + semantic->resource_type = resource_type; + + dst_param = &semantic->resource.reg; +- vsir_register_init(&dst_param->reg, VKD3DSPR_SAMPLER, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&dst_param->reg, VKD3DSPR_SAMPLER, VSIR_DATA_F32, 1); + dst_param->reg.dimension = VSIR_DIMENSION_NONE; + dst_param->reg.idx[0].offset = var->regs[HLSL_REGSET_SAMPLERS].index + i; + dst_param->write_mask = 0; +@@ -8394,7 +8455,7 @@ static struct vkd3d_shader_instruction *generate_vsir_add_program_instruction( + + static void vsir_src_from_hlsl_constant_value(struct vkd3d_shader_src_param *src, + struct hlsl_ctx *ctx, const struct hlsl_constant_value *value, +- enum vkd3d_data_type type, unsigned int width, unsigned int map_writemask) ++ enum vsir_data_type type, unsigned int width, unsigned int map_writemask) + { + unsigned int i, j; + +@@ -8699,7 +8760,7 @@ static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, + return; + + src_param = &ins->src[0]; +- vsir_register_init(&src_param->reg, VKD3DSPR_CONST, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&src_param->reg, VKD3DSPR_CONST, VSIR_DATA_F32, 1); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param->reg.idx[0].offset = constant->reg.id; + src_param->swizzle = generate_vsir_get_src_swizzle(constant->reg.writemask, instr->reg.writemask); +@@ -8789,13 +8850,13 @@ static void sm1_generate_vsir_instr_expr_per_component_instr_op(struct hlsl_ctx + return; + + dst_param = &ins->dst[0]; +- vsir_register_init(&dst_param->reg, instr->reg.type, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&dst_param->reg, instr->reg.type, VSIR_DATA_F32, 1); + dst_param->reg.idx[0].offset = instr->reg.id; + dst_param->reg.dimension = VSIR_DIMENSION_VEC4; + dst_param->write_mask = 1u << i; + + src_param = &ins->src[0]; +- vsir_register_init(&src_param->reg, operand->reg.type, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&src_param->reg, operand->reg.type, VSIR_DATA_F32, 1); + src_param->reg.idx[0].offset = operand->reg.id; + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + c = vsir_swizzle_get_component(src_swizzle, i); +@@ -8825,13 +8886,13 @@ static void sm1_generate_vsir_instr_expr_sincos(struct hlsl_ctx *ctx, struct vsi + if (ctx->profile->major_version < 3) + { + src_param = &ins->src[1]; +- vsir_register_init(&src_param->reg, VKD3DSPR_CONST, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&src_param->reg, VKD3DSPR_CONST, VSIR_DATA_F32, 1); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param->reg.idx[0].offset = ctx->d3dsincosconst1.id; + src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE; + + src_param = &ins->src[2]; +- vsir_register_init(&src_param->reg, VKD3DSPR_CONST, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&src_param->reg, VKD3DSPR_CONST, VSIR_DATA_F32, 1); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param->reg.idx[0].offset = ctx->d3dsincosconst2.id; + src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE; +@@ -9156,12 +9217,12 @@ static void sm1_generate_vsir_init_dst_param_from_deref(struct hlsl_ctx *ctx, + + if (type == VKD3DSPR_DEPTHOUT) + { +- vsir_register_init(&dst_param->reg, type, VKD3D_DATA_FLOAT, 0); ++ vsir_register_init(&dst_param->reg, type, VSIR_DATA_F32, 0); + dst_param->reg.dimension = VSIR_DIMENSION_SCALAR; + } + else + { +- vsir_register_init(&dst_param->reg, type, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&dst_param->reg, type, VSIR_DATA_F32, 1); + dst_param->reg.idx[0].offset = register_index; + dst_param->reg.dimension = VSIR_DIMENSION_VEC4; + } +@@ -9184,7 +9245,7 @@ static void sm1_generate_vsir_instr_mova(struct hlsl_ctx *ctx, + return; + + dst_param = &ins->dst[0]; +- vsir_register_init(&dst_param->reg, VKD3DSPR_ADDR, VKD3D_DATA_FLOAT, 0); ++ vsir_register_init(&dst_param->reg, VKD3DSPR_ADDR, VSIR_DATA_F32, 0); + dst_param->write_mask = VKD3DSP_WRITEMASK_0; + + VKD3D_ASSERT(instr->data_type->class <= HLSL_CLASS_VECTOR); +@@ -9204,7 +9265,7 @@ static struct vkd3d_shader_src_param *sm1_generate_vsir_new_address_src(struct h + } + + memset(idx_src, 0, sizeof(*idx_src)); +- vsir_register_init(&idx_src->reg, VKD3DSPR_ADDR, VKD3D_DATA_FLOAT, 0); ++ vsir_register_init(&idx_src->reg, VKD3DSPR_ADDR, VSIR_DATA_F32, 0); + idx_src->reg.dimension = VSIR_DIMENSION_VEC4; + idx_src->swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); + return idx_src; +@@ -9283,7 +9344,7 @@ static void sm1_generate_vsir_init_src_param_from_deref(struct hlsl_ctx *ctx, + writemask = reg.writemask; + } + +- vsir_register_init(&src_param->reg, type, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&src_param->reg, type, VSIR_DATA_F32, 1); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param->reg.idx[0].offset = register_index; + src_param->reg.idx[0].rel_addr = src_rel_addr; +@@ -10132,18 +10193,18 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs + if (is_primitive) + { + VKD3D_ASSERT(has_idx); +- vsir_register_init(&dst_param->reg, type, VKD3D_DATA_FLOAT, 2); ++ vsir_register_init(&dst_param->reg, type, VSIR_DATA_F32, 2); + dst_param->reg.idx[0].offset = var->data_type->e.array.elements_count; + dst_param->reg.idx[1].offset = idx; + } + else if (has_idx) + { +- vsir_register_init(&dst_param->reg, type, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&dst_param->reg, type, VSIR_DATA_F32, 1); + dst_param->reg.idx[0].offset = idx; + } + else + { +- vsir_register_init(&dst_param->reg, type, VKD3D_DATA_FLOAT, 0); ++ vsir_register_init(&dst_param->reg, type, VSIR_DATA_F32, 0); + } + + if (shader_sm4_is_scalar_register(&dst_param->reg)) +@@ -10180,7 +10241,7 @@ static void sm4_generate_vsir_instr_dcl_indexable_temp(struct hlsl_ctx *ctx, + ins->declaration.indexable_temp.register_idx = idx; + ins->declaration.indexable_temp.register_size = size; + ins->declaration.indexable_temp.alignment = 0; +- ins->declaration.indexable_temp.data_type = VKD3D_DATA_FLOAT; ++ ins->declaration.indexable_temp.data_type = VSIR_DATA_F32; + ins->declaration.indexable_temp.component_count = comp_count; + ins->declaration.indexable_temp.has_function_scope = false; + } +@@ -10371,7 +10432,7 @@ static void sm4_generate_vsir_rcp_using_div(struct hlsl_ctx *ctx, + value.u[2].f = 1.0f; + value.u[3].f = 1.0f; + vsir_src_from_hlsl_constant_value(&ins->src[0], ctx, &value, +- VKD3D_DATA_FLOAT, instr->data_type->e.numeric.dimx, dst_param->write_mask); ++ VSIR_DATA_F32, instr->data_type->e.numeric.dimx, dst_param->write_mask); + + vsir_src_from_hlsl_node(&ins->src[1], ctx, operand, dst_param->write_mask); + } +@@ -12020,7 +12081,7 @@ static void sm4_generate_vsir_add_dcl_constant_buffer(struct hlsl_ctx *ctx, + ins->declaration.cb.size = cbuffer->size; + + src_param = &ins->declaration.cb.src; +- vsir_src_param_init(src_param, VKD3DSPR_CONSTBUFFER, VKD3D_DATA_FLOAT, 0); ++ vsir_src_param_init(src_param, VKD3DSPR_CONSTBUFFER, VSIR_DATA_F32, 0); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE; + +@@ -12106,14 +12167,14 @@ static enum vkd3d_shader_resource_type sm4_generate_vsir_get_resource_type(const + } + } + +-static enum vkd3d_data_type sm4_generate_vsir_get_format_type(const struct hlsl_type *type) ++static enum vsir_data_type sm4_generate_vsir_get_format_type(const struct hlsl_type *type) + { + const struct hlsl_type *format = type->e.resource.format; + + switch (format->e.numeric.type) + { + case HLSL_TYPE_DOUBLE: +- return VKD3D_DATA_DOUBLE; ++ return VSIR_DATA_F64; + + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: +@@ -12121,7 +12182,7 @@ static enum vkd3d_data_type sm4_generate_vsir_get_format_type(const struct hlsl_ + return VKD3D_DATA_UNORM; + if (format->modifiers & HLSL_MODIFIER_SNORM) + return VKD3D_DATA_SNORM; +- return VKD3D_DATA_FLOAT; ++ return VSIR_DATA_F32; + + case HLSL_TYPE_INT: + return VKD3D_DATA_INT; +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index b060ccbb2bc..18cda0269af 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -555,7 +555,7 @@ static uint32_t vsir_combine_swizzles(uint32_t first, uint32_t second) + } + + void vsir_register_init(struct vkd3d_shader_register *reg, enum vkd3d_shader_register_type reg_type, +- enum vkd3d_data_type data_type, unsigned int idx_count) ++ enum vsir_data_type data_type, unsigned int idx_count) + { + reg->type = reg_type; + reg->precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT; +@@ -581,7 +581,7 @@ static inline bool shader_register_is_phase_instance_id(const struct vkd3d_shade + } + + 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) ++ enum vsir_data_type data_type, unsigned int idx_count) + { + vsir_register_init(¶m->reg, reg_type, data_type, idx_count); + param->swizzle = 0; +@@ -597,7 +597,7 @@ static void src_param_init_const_uint(struct vkd3d_shader_src_param *src, uint32 + static void vsir_src_param_init_io(struct vkd3d_shader_src_param *src, + enum vkd3d_shader_register_type reg_type, const struct signature_element *e, unsigned int idx_count) + { +- vsir_src_param_init(src, reg_type, vkd3d_data_type_from_component_type(e->component_type), idx_count); ++ vsir_src_param_init(src, reg_type, vsir_data_type_from_component_type(e->component_type), idx_count); + src->reg.dimension = VSIR_DIMENSION_VEC4; + src->swizzle = vsir_swizzle_from_writemask(e->mask); + } +@@ -609,13 +609,13 @@ void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned in + param->reg.idx[0].offset = label_id; + } + +-static void src_param_init_parameter(struct vkd3d_shader_src_param *src, uint32_t idx, enum vkd3d_data_type type) ++static void src_param_init_parameter(struct vkd3d_shader_src_param *src, uint32_t idx, enum vsir_data_type type) + { + vsir_src_param_init(src, VKD3DSPR_PARAMETER, type, 1); + src->reg.idx[0].offset = idx; + } + +-static void src_param_init_parameter_vec4(struct vkd3d_shader_src_param *src, uint32_t idx, enum vkd3d_data_type type) ++static void src_param_init_parameter_vec4(struct vkd3d_shader_src_param *src, uint32_t idx, enum vsir_data_type type) + { + vsir_src_param_init(src, VKD3DSPR_PARAMETER, type, 1); + src->reg.idx[0].offset = idx; +@@ -641,7 +641,7 @@ static void vsir_src_param_init_sampler(struct vkd3d_shader_src_param *src, unsi + } + + static void src_param_init_ssa(struct vkd3d_shader_src_param *src, unsigned int idx, +- enum vkd3d_data_type data_type, enum vsir_dimension dimension) ++ enum vsir_data_type data_type, enum vsir_dimension dimension) + { + vsir_src_param_init(src, VKD3DSPR_SSA, data_type, 1); + src->reg.idx[0].offset = idx; +@@ -653,8 +653,8 @@ static void src_param_init_ssa(struct vkd3d_shader_src_param *src, unsigned int + } + } + +-static void src_param_init_ssa_scalar(struct vkd3d_shader_src_param *src, unsigned int idx, +- enum vkd3d_data_type data_type) ++static void src_param_init_ssa_scalar(struct vkd3d_shader_src_param *src, ++ unsigned int idx, enum vsir_data_type data_type) + { + src_param_init_ssa(src, idx, data_type, VSIR_DIMENSION_SCALAR); + } +@@ -666,12 +666,12 @@ static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned + + static void src_param_init_ssa_float(struct vkd3d_shader_src_param *src, unsigned int idx) + { +- src_param_init_ssa_scalar(src, idx, VKD3D_DATA_FLOAT); ++ src_param_init_ssa_scalar(src, idx, VSIR_DATA_F32); + } + + static void src_param_init_ssa_float4(struct vkd3d_shader_src_param *src, unsigned int idx) + { +- src_param_init_ssa(src, idx, VKD3D_DATA_FLOAT, VSIR_DIMENSION_VEC4); ++ src_param_init_ssa(src, idx, VSIR_DATA_F32, VSIR_DIMENSION_VEC4); + } + + static void src_param_init_temp_bool(struct vkd3d_shader_src_param *src, unsigned int idx) +@@ -682,13 +682,13 @@ static void src_param_init_temp_bool(struct vkd3d_shader_src_param *src, unsigne + + static void src_param_init_temp_float(struct vkd3d_shader_src_param *src, unsigned int idx) + { +- vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); ++ vsir_src_param_init(src, VKD3DSPR_TEMP, VSIR_DATA_F32, 1); + src->reg.idx[0].offset = idx; + } + + static void src_param_init_temp_float4(struct vkd3d_shader_src_param *src, unsigned int idx) + { +- vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); ++ vsir_src_param_init(src, VKD3DSPR_TEMP, VSIR_DATA_F32, 1); + src->reg.dimension = VSIR_DIMENSION_VEC4; + src->swizzle = VKD3D_SHADER_NO_SWIZZLE; + src->reg.idx[0].offset = idx; +@@ -701,7 +701,7 @@ static void src_param_init_temp_uint(struct vkd3d_shader_src_param *src, unsigne + } + + void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, +- enum vkd3d_data_type data_type, unsigned int idx_count) ++ enum vsir_data_type data_type, unsigned int idx_count) + { + vsir_register_init(¶m->reg, reg_type, data_type, idx_count); + param->write_mask = VKD3DSP_WRITEMASK_0; +@@ -712,7 +712,7 @@ void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader + static void vsir_dst_param_init_io(struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_register_type reg_type, + const struct signature_element *e, unsigned int idx_count) + { +- vsir_dst_param_init(dst, reg_type, vkd3d_data_type_from_component_type(e->component_type), idx_count); ++ vsir_dst_param_init(dst, reg_type, vsir_data_type_from_component_type(e->component_type), idx_count); + dst->reg.dimension = VSIR_DIMENSION_VEC4; + dst->write_mask = e->mask; + } +@@ -725,7 +725,7 @@ void vsir_dst_param_init_null(struct vkd3d_shader_dst_param *dst) + } + + static void dst_param_init_ssa(struct vkd3d_shader_dst_param *dst, unsigned int idx, +- enum vkd3d_data_type data_type, enum vsir_dimension dimension) ++ enum vsir_data_type data_type, enum vsir_dimension dimension) + { + vsir_dst_param_init(dst, VKD3DSPR_SSA, data_type, 1); + dst->reg.idx[0].offset = idx; +@@ -737,8 +737,8 @@ static void dst_param_init_ssa(struct vkd3d_shader_dst_param *dst, unsigned int + } + } + +-static void dst_param_init_ssa_scalar(struct vkd3d_shader_dst_param *dst, unsigned int idx, +- enum vkd3d_data_type data_type) ++static void dst_param_init_ssa_scalar(struct vkd3d_shader_dst_param *dst, ++ unsigned int idx, enum vsir_data_type data_type) + { + dst_param_init_ssa(dst, idx, data_type, VSIR_DIMENSION_SCALAR); + } +@@ -750,12 +750,12 @@ static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned + + static void dst_param_init_ssa_float(struct vkd3d_shader_dst_param *dst, unsigned int idx) + { +- dst_param_init_ssa_scalar(dst, idx, VKD3D_DATA_FLOAT); ++ dst_param_init_ssa_scalar(dst, idx, VSIR_DATA_F32); + } + + static void dst_param_init_ssa_float4(struct vkd3d_shader_dst_param *dst, unsigned int idx) + { +- dst_param_init_ssa(dst, idx, VKD3D_DATA_FLOAT, VSIR_DIMENSION_VEC4); ++ dst_param_init_ssa(dst, idx, VSIR_DATA_F32, VSIR_DIMENSION_VEC4); + } + + static void dst_param_init_temp_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) +@@ -766,7 +766,7 @@ static void dst_param_init_temp_bool(struct vkd3d_shader_dst_param *dst, unsigne + + static void dst_param_init_temp_float4(struct vkd3d_shader_dst_param *dst, unsigned int idx) + { +- vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); ++ vsir_dst_param_init(dst, VKD3DSPR_TEMP, VSIR_DATA_F32, 1); + dst->reg.idx[0].offset = idx; + dst->reg.dimension = VSIR_DIMENSION_VEC4; + } +@@ -778,7 +778,7 @@ static void dst_param_init_temp_uint(struct vkd3d_shader_dst_param *dst, unsigne + } + + static void dst_param_init_output(struct vkd3d_shader_dst_param *dst, +- enum vkd3d_data_type data_type, uint32_t idx, uint32_t write_mask) ++ enum vsir_data_type data_type, uint32_t idx, uint32_t write_mask) + { + vsir_dst_param_init(dst, VKD3DSPR_OUTPUT, data_type, 1); + dst->reg.idx[0].offset = idx; +@@ -850,15 +850,15 @@ static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *i + vsir_instruction_init(ins, &location, VSIR_OP_NOP); + } + +-static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_data_type data_type, +- enum vkd3d_shader_opcode *opcode, bool *requires_swap) ++static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, ++ enum vsir_data_type data_type, enum vkd3d_shader_opcode *opcode, bool *requires_swap) + { + switch (rel_op) + { + case VKD3D_SHADER_REL_OP_LT: + case VKD3D_SHADER_REL_OP_GT: + *requires_swap = (rel_op == VKD3D_SHADER_REL_OP_GT); +- if (data_type == VKD3D_DATA_FLOAT) ++ if (data_type == VSIR_DATA_F32) + { + *opcode = VSIR_OP_LTO; + return true; +@@ -868,7 +868,7 @@ static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_d + case VKD3D_SHADER_REL_OP_GE: + case VKD3D_SHADER_REL_OP_LE: + *requires_swap = (rel_op == VKD3D_SHADER_REL_OP_LE); +- if (data_type == VKD3D_DATA_FLOAT) ++ if (data_type == VSIR_DATA_F32) + { + *opcode = VSIR_OP_GEO; + return true; +@@ -877,7 +877,7 @@ static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_d + + case VKD3D_SHADER_REL_OP_EQ: + *requires_swap = false; +- if (data_type == VKD3D_DATA_FLOAT) ++ if (data_type == VSIR_DATA_F32) + { + *opcode = VSIR_OP_EQO; + return true; +@@ -886,7 +886,7 @@ static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_d + + case VKD3D_SHADER_REL_OP_NE: + *requires_swap = false; +- if (data_type == VKD3D_DATA_FLOAT) ++ if (data_type == VSIR_DATA_F32) + { + *opcode = VSIR_OP_NEO; + return true; +@@ -928,7 +928,7 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra + ins2 = &program->instructions.elements[i + 1]; + + ins->opcode = VSIR_OP_ROUND_NE; +- vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VSIR_DATA_F32, 1); + ins->dst[0].reg.idx[0].offset = tmp_idx; + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + +@@ -940,7 +940,7 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra + ins2->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins2->dst[0].write_mask = ins->dst[0].write_mask; + +- vsir_register_init(&ins2->src[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&ins2->src[0].reg, VKD3DSPR_TEMP, VSIR_DATA_F32, 1); + ins2->src[0].reg.idx[0].offset = tmp_idx; + ins2->src[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins2->src[0].swizzle = vsir_swizzle_from_writemask(ins2->dst[0].write_mask); +@@ -971,18 +971,16 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra + } + + static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, +- struct vkd3d_shader_instruction *ifc, unsigned int *tmp_idx, ++ struct vsir_program_iterator *it, unsigned int *tmp_idx, + struct vkd3d_shader_message_context *message_context) + { +- struct vkd3d_shader_instruction_array *instructions = &program->instructions; +- size_t pos = ifc - instructions->elements; +- struct vkd3d_shader_instruction *ins; ++ struct vkd3d_shader_instruction *ifc, *ins; + enum vkd3d_shader_opcode opcode; + bool swap; + +- if (!shader_instruction_array_insert_at(instructions, pos + 1, 2)) ++ if (!vsir_program_iterator_insert_after(it, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; +- ifc = &instructions->elements[pos]; ++ ifc = vsir_program_iterator_current(it); + + if (*tmp_idx == ~0u) + *tmp_idx = program->temp_count++; +@@ -996,7 +994,7 @@ static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + +- ins = &instructions->elements[pos + 1]; ++ ins = vsir_program_iterator_next(it); + if (!vsir_instruction_init_with_params(program, ins, &ifc->location, opcode, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1009,7 +1007,7 @@ static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, + ins->src[1] = ifc->src[!swap]; + + /* Create new if instruction using the previous result. */ +- ins = &instructions->elements[pos + 2]; ++ ins = vsir_program_iterator_next(it); + if (!vsir_instruction_init_with_params(program, ins, &ifc->location, VSIR_OP_IF, 0, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ; +@@ -1026,24 +1024,22 @@ static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, + } + + static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program, +- struct vkd3d_shader_instruction *texkill, unsigned int *tmp_idx) ++ struct vsir_program_iterator *it, unsigned int *tmp_idx) + { + const unsigned int components_read = 3 + (program->shader_version.major >= 2); +- struct vkd3d_shader_instruction_array *instructions = &program->instructions; +- size_t pos = texkill - instructions->elements; +- struct vkd3d_shader_instruction *ins; ++ struct vkd3d_shader_instruction *ins, *texkill; + unsigned int j; + +- if (!shader_instruction_array_insert_at(instructions, pos + 1, components_read + 1)) ++ if (!vsir_program_iterator_insert_after(it, components_read + 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; +- texkill = &instructions->elements[pos]; ++ texkill = vsir_program_iterator_current(it); + + if (*tmp_idx == ~0u) + *tmp_idx = program->temp_count++; + + /* tmp = ins->src[0] < 0 */ + +- ins = &instructions->elements[pos + 1]; ++ ins = vsir_program_iterator_next(it); + if (!vsir_instruction_init_with_params(program, ins, &texkill->location, VSIR_OP_LTO, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1054,7 +1050,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program + + ins->src[0].reg = texkill->src[0].reg; + ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; +- vsir_register_init(&ins->src[1].reg, VKD3DSPR_IMMCONST, VKD3D_DATA_FLOAT, 0); ++ vsir_register_init(&ins->src[1].reg, VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); + ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[1].reg.u.immconst_f32[0] = 0.0f; + ins->src[1].reg.u.immconst_f32[1] = 0.0f; +@@ -1067,7 +1063,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program + + for (j = 1; j < components_read; ++j) + { +- ins = &instructions->elements[pos + 1 + j]; ++ ins = vsir_program_iterator_next(it); + if (!(vsir_instruction_init_with_params(program, ins, &texkill->location, VSIR_OP_OR, 1, 2))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1088,7 +1084,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program + + /* discard_nz tmp.x */ + +- ins = &instructions->elements[pos + 1 + components_read]; ++ ins = vsir_program_iterator_next(it); + if (!(vsir_instruction_init_with_params(program, ins, &texkill->location, VSIR_OP_DISCARD, 0, 1))) + return VKD3D_ERROR_OUT_OF_MEMORY; + ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ; +@@ -1111,25 +1107,24 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program + * not fused for "precise" operations." + * Windows drivers seem to conform with the latter, for SM 4-5 and SM 6. */ + static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *program, +- struct vkd3d_shader_instruction *mad, unsigned int *tmp_idx) ++ struct vsir_program_iterator *it, unsigned int *tmp_idx) + { +- struct vkd3d_shader_instruction_array *instructions = &program->instructions; +- struct vkd3d_shader_instruction *mul_ins, *add_ins; +- size_t pos = mad - instructions->elements; ++ struct vkd3d_shader_instruction *mad, *mul_ins, *add_ins; + struct vkd3d_shader_dst_param *mul_dst; + ++ mad = vsir_program_iterator_current(it); ++ + if (!(mad->flags & VKD3DSI_PRECISE_XYZW)) + return VKD3D_OK; + +- if (!shader_instruction_array_insert_at(instructions, pos + 1, 1)) ++ if (!vsir_program_iterator_insert_after(it, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; +- mad = &instructions->elements[pos]; + + if (*tmp_idx == ~0u) + *tmp_idx = program->temp_count++; + +- mul_ins = &instructions->elements[pos]; +- add_ins = &instructions->elements[pos + 1]; ++ mul_ins = vsir_program_iterator_current(it); ++ add_ins = vsir_program_iterator_next(it); + + mul_ins->opcode = VSIR_OP_MUL; + mul_ins->src_count = 2; +@@ -1174,13 +1169,13 @@ static enum vkd3d_result vsir_program_lower_imul(struct vsir_program *program, + } + + static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, +- struct vkd3d_shader_instruction *udiv, struct vsir_transformation_context *ctx) ++ struct vsir_program_iterator *it, struct vsir_transformation_context *ctx) + { +- struct vkd3d_shader_instruction_array *instructions = &program->instructions; +- size_t pos = udiv - instructions->elements; +- struct vkd3d_shader_instruction *ins, *mov; ++ struct vkd3d_shader_instruction *udiv, *ins, *mov; + unsigned int count = 2; + ++ udiv = vsir_program_iterator_current(it); ++ + if (udiv->dst_count != 2) + { + vkd3d_shader_error(ctx->message_context, &udiv->location, +@@ -1195,21 +1190,19 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, + if (udiv->dst[1].reg.type != VKD3DSPR_NULL) + ++count; + +- if (!shader_instruction_array_insert_at(instructions, pos + 1, count)) ++ if (!vsir_program_iterator_insert_after(it, count)) + return VKD3D_ERROR_OUT_OF_MEMORY; +- udiv = &instructions->elements[pos]; +- +- ins = &instructions->elements[pos + 1]; ++ udiv = vsir_program_iterator_current(it); + + /* Save the sources in a SSA in case a destination collides with a source. */ +- mov = ins++; ++ mov = vsir_program_iterator_next(it); + if (!(vsir_instruction_init_with_params(program, mov, &udiv->location, VSIR_OP_MOV, 1, 1))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + mov->src[0] = udiv->src[0]; + dst_param_init_ssa(&mov->dst[0], program->ssa_count, udiv->src[0].reg.data_type, udiv->src[0].reg.dimension); + +- mov = ins++; ++ mov = vsir_program_iterator_next(it); + if (!(vsir_instruction_init_with_params(program, mov, &udiv->location, VSIR_OP_MOV, 1, 1))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1218,6 +1211,8 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, + + if (udiv->dst[0].reg.type != VKD3DSPR_NULL) + { ++ ins = vsir_program_iterator_next(it); ++ + if (!(vsir_instruction_init_with_params(program, ins, &udiv->location, VSIR_OP_UDIV_SIMPLE, 1, 2))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1228,12 +1223,12 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, + src_param_init_ssa(&ins->src[1], program->ssa_count + 1, + udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); + ins->dst[0] = udiv->dst[0]; +- +- ++ins; + } + + if (udiv->dst[1].reg.type != VKD3DSPR_NULL) + { ++ ins = vsir_program_iterator_next(it); ++ + if (!(vsir_instruction_init_with_params(program, ins, &udiv->location, VSIR_OP_UREM, 1, 2))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1244,8 +1239,6 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, + src_param_init_ssa(&ins->src[1], program->ssa_count + 1, + udiv->src[1].reg.data_type, udiv->src[1].reg.dimension); + ins->dst[0] = udiv->dst[1]; +- +- ++ins; + } + + vkd3d_shader_instruction_make_nop(udiv); +@@ -1255,23 +1248,20 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, + } + + static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *program, +- struct vkd3d_shader_instruction *sincos) ++ struct vsir_program_iterator *it) + { +- struct vkd3d_shader_instruction_array *instructions = &program->instructions; +- size_t pos = sincos - instructions->elements; +- struct vkd3d_shader_instruction *ins, *mov; ++ struct vkd3d_shader_instruction *ins, *mov, *sincos; + unsigned int s, count; + ++ sincos = vsir_program_iterator_current(it); + count = 1 + vkd3d_popcount(sincos->dst[0].write_mask & (VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1)); + +- if (!shader_instruction_array_insert_at(instructions, pos + 1, count)) ++ if (!vsir_program_iterator_insert_after(it, count)) + return VKD3D_ERROR_OUT_OF_MEMORY; +- sincos = &instructions->elements[pos]; +- +- ins = &instructions->elements[pos + 1]; ++ sincos = vsir_program_iterator_current(it); + + /* Save the source in a SSA in case a destination collides with the source. */ +- mov = ins++; ++ mov = vsir_program_iterator_next(it); + if (!(vsir_instruction_init_with_params(program, mov, &sincos->location, VSIR_OP_MOV, 1, 1))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1285,6 +1275,8 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog + + if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_1) + { ++ ins = vsir_program_iterator_next(it); ++ + if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VSIR_OP_SIN, 1, 1))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1294,12 +1286,12 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog + + ins->dst[0] = *sincos->dst; + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_1; +- +- ++ins; + } + + if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_0) + { ++ ins = vsir_program_iterator_next(it); ++ + if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VSIR_OP_COS, 1, 1))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1309,8 +1301,6 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog + + ins->dst[0] = *sincos->dst; + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; +- +- ++ins; + } + + vkd3d_shader_instruction_make_nop(sincos); +@@ -1320,13 +1310,13 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog + } + + static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *program, +- struct vkd3d_shader_instruction *sincos, struct vsir_transformation_context *ctx) ++ struct vsir_program_iterator *it, struct vsir_transformation_context *ctx) + { +- struct vkd3d_shader_instruction_array *instructions = &program->instructions; +- size_t pos = sincos - instructions->elements; +- struct vkd3d_shader_instruction *ins, *mov; ++ struct vkd3d_shader_instruction *ins, *mov, *sincos; + unsigned int count = 1; + ++ sincos = vsir_program_iterator_current(it); ++ + if (sincos->dst_count != 2) + { + vkd3d_shader_error(ctx->message_context, &sincos->location, +@@ -1341,14 +1331,12 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog + if (sincos->dst[1].reg.type != VKD3DSPR_NULL) + ++count; + +- if (!shader_instruction_array_insert_at(instructions, pos + 1, count)) ++ if (!vsir_program_iterator_insert_after(it, count)) + return VKD3D_ERROR_OUT_OF_MEMORY; +- sincos = &instructions->elements[pos]; +- +- ins = &instructions->elements[pos + 1]; ++ sincos = vsir_program_iterator_current(it); + + /* Save the source in a SSA in case a destination collides with the source. */ +- mov = ins++; ++ mov = vsir_program_iterator_next(it); + if (!(vsir_instruction_init_with_params(program, mov, &sincos->location, VSIR_OP_MOV, 1, 1))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1357,6 +1345,8 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog + + if (sincos->dst[0].reg.type != VKD3DSPR_NULL) + { ++ ins = vsir_program_iterator_next(it); ++ + if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VSIR_OP_SIN, 1, 1))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1365,12 +1355,12 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog + src_param_init_ssa(&ins->src[0], program->ssa_count, + sincos->src[0].reg.data_type, sincos->src[0].reg.dimension); + ins->dst[0] = sincos->dst[0]; +- +- ++ins; + } + + if (sincos->dst[1].reg.type != VKD3DSPR_NULL) + { ++ ins = vsir_program_iterator_next(it); ++ + if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VSIR_OP_COS, 1, 1))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +@@ -1379,8 +1369,6 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog + src_param_init_ssa(&ins->src[0], program->ssa_count, + sincos->src[0].reg.data_type, sincos->src[0].reg.dimension); + ins->dst[0] = sincos->dst[1]; +- +- ++ins; + } + + vkd3d_shader_instruction_make_nop(sincos); +@@ -1390,30 +1378,33 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog + } + + static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, +- struct vkd3d_shader_instruction *tex, unsigned int *tmp_idx) ++ struct vsir_program_iterator *it, unsigned int *tmp_idx) + { +- struct vkd3d_shader_instruction_array *instructions = &program->instructions; +- struct vkd3d_shader_location *location = &tex->location; +- struct vkd3d_shader_instruction *div_ins, *tex_ins; +- size_t pos = tex - instructions->elements; ++ struct vkd3d_shader_instruction *div_ins, *tex, *tex_ins; ++ struct vsir_program_iterator it2; + unsigned int w_comp; + ++ tex = vsir_program_iterator_current(it); ++ + w_comp = vsir_swizzle_get_component(tex->src[0].swizzle, 3); + +- if (!shader_instruction_array_insert_at(instructions, pos + 1, 2)) ++ if (!vsir_program_iterator_insert_after(it, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; +- tex = &instructions->elements[pos]; ++ tex = vsir_program_iterator_current(it); + + if (*tmp_idx == ~0u) + *tmp_idx = program->temp_count++; + +- div_ins = &instructions->elements[pos + 1]; +- tex_ins = &instructions->elements[pos + 2]; ++ /* Do not increment `it', because we need to scan the generated instructions ++ * again to lower TEXLD. */ ++ it2 = *it; ++ div_ins = vsir_program_iterator_next(&it2); ++ tex_ins = vsir_program_iterator_next(&it2); + +- if (!vsir_instruction_init_with_params(program, div_ins, location, VSIR_OP_DIV, 1, 2)) ++ if (!vsir_instruction_init_with_params(program, div_ins, &tex->location, VSIR_OP_DIV, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- vsir_dst_param_init(&div_ins->dst[0], VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); ++ vsir_dst_param_init(&div_ins->dst[0], VKD3DSPR_TEMP, VSIR_DATA_F32, 1); + div_ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + div_ins->dst[0].reg.idx[0].offset = *tmp_idx; + div_ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; +@@ -1423,7 +1414,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, + div_ins->src[1] = tex->src[0]; + div_ins->src[1].swizzle = vkd3d_shader_create_swizzle(w_comp, w_comp, w_comp, w_comp); + +- if (!vsir_instruction_init_with_params(program, tex_ins, location, VSIR_OP_TEXLD, 1, 2)) ++ if (!vsir_instruction_init_with_params(program, tex_ins, &tex->location, VSIR_OP_TEXLD, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + tex_ins->dst[0] = tex->dst[0]; +@@ -1579,29 +1570,28 @@ static enum vkd3d_result vsir_program_lower_dcl_output(struct vsir_program *prog + static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *program, + struct vsir_transformation_context *ctx) + { +- struct vkd3d_shader_instruction_array *instructions = &program->instructions; ++ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); + struct vkd3d_shader_message_context *message_context = ctx->message_context; +- unsigned int tmp_idx = ~0u, i; ++ struct vkd3d_shader_instruction *ins; ++ unsigned int tmp_idx = ~0u; + enum vkd3d_result ret; + +- for (i = 0; i < instructions->count; ++i) ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) + { +- struct vkd3d_shader_instruction *ins = &instructions->elements[i]; +- + switch (ins->opcode) + { + case VSIR_OP_IFC: +- if ((ret = vsir_program_lower_ifc(program, ins, &tmp_idx, message_context)) < 0) ++ if ((ret = vsir_program_lower_ifc(program, &it, &tmp_idx, message_context)) < 0) + return ret; + break; + + case VSIR_OP_TEXKILL: +- if ((ret = vsir_program_lower_texkill(program, ins, &tmp_idx)) < 0) ++ if ((ret = vsir_program_lower_texkill(program, &it, &tmp_idx)) < 0) + return ret; + break; + + case VSIR_OP_MAD: +- if ((ret = vsir_program_lower_precise_mad(program, ins, &tmp_idx)) < 0) ++ if ((ret = vsir_program_lower_precise_mad(program, &it, &tmp_idx)) < 0) + return ret; + break; + +@@ -1643,19 +1633,19 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr + break; + + case VSIR_OP_UDIV: +- if ((ret = vsir_program_lower_udiv(program, ins, ctx)) < 0) ++ if ((ret = vsir_program_lower_udiv(program, &it, ctx)) < 0) + return ret; + break; + + case VSIR_OP_SINCOS: + if (ins->dst_count == 1) + { +- if ((ret = vsir_program_lower_sm1_sincos(program, ins)) < 0) ++ if ((ret = vsir_program_lower_sm1_sincos(program, &it)) < 0) + return ret; + } + else + { +- if ((ret = vsir_program_lower_sm4_sincos(program, ins, ctx)) < 0) ++ if ((ret = vsir_program_lower_sm4_sincos(program, &it, ctx)) < 0) + return ret; + } + break; +@@ -1663,7 +1653,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr + case VSIR_OP_TEXLD: + if (ins->flags == VKD3DSI_TEXLD_PROJECT) + { +- if ((ret = vsir_program_lower_texldp(program, ins, &tmp_idx)) < 0) ++ if ((ret = vsir_program_lower_texldp(program, &it, &tmp_idx)) < 0) + return ret; + } + else +@@ -1802,11 +1792,11 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra + ins = &program->instructions.elements[i]; + + vsir_instruction_init_with_params(program, ins, &no_loc, VSIR_OP_MOV, 1, 1); +- vsir_dst_param_init(&ins->dst[0], VKD3DSPR_ATTROUT, VKD3D_DATA_FLOAT, 1); ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_ATTROUT, VSIR_DATA_F32, 1); + ins->dst[0].reg.idx[0].offset = 0; + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL & ~program->diffuse_written_mask; +- vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VKD3D_DATA_FLOAT, 0); ++ vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; + for (i = 0; i < 4; ++i) + ins->src[0].reg.u.immconst_f32[i] = 1.0f; +@@ -2026,8 +2016,8 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program + e = &signature->elements[j]; + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); +- dst_param_init_output(&ins->dst[0], VKD3D_DATA_FLOAT, e->register_index, e->mask); +- vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VKD3D_DATA_FLOAT, 0); ++ dst_param_init_output(&ins->dst[0], VSIR_DATA_F32, e->register_index, e->mask); ++ vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; + ++ins; + } +@@ -6842,7 +6832,7 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr + vsir_instruction_init_with_params(program, ins, &loc, opcodes[compare_func].float_opcode, 1, 2); + src_param_init_temp_float(&ins->src[opcodes[compare_func].swap ? 1 : 0], colour_temp); + src_param_init_parameter(&ins->src[opcodes[compare_func].swap ? 0 : 1], +- VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF, VKD3D_DATA_FLOAT); ++ VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF, VSIR_DATA_F32); + break; + + case VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32: +@@ -6875,7 +6865,7 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr + + ++ins; + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); +- vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VSIR_DATA_F32, 1); + ins->dst[0].reg.idx[0].offset = colour_signature_idx; + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].write_mask = program->output_signature.elements[colour_signature_idx].mask; +@@ -6992,11 +6982,11 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_DP4, 1, 2); + src_param_init_temp_float4(&ins->src[0], position_temp); +- src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 + i, VKD3D_DATA_FLOAT); ++ src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0 + i, VSIR_DATA_F32); + ins->src[1].swizzle = VKD3D_SHADER_NO_SWIZZLE; + ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; + +- vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VSIR_DATA_F32, 1); + if (output_idx < 4) + ins->dst[0].reg.idx[0].offset = low_signature_idx; + else +@@ -7009,7 +6999,7 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog + } + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); +- vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_OUTPUT, VSIR_DATA_F32, 1); + ins->dst[0].reg.idx[0].offset = position_signature_idx; + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].write_mask = program->output_signature.elements[position_signature_idx].mask; +@@ -7162,9 +7152,9 @@ static enum vkd3d_result insert_point_size_before_ret(struct vsir_program *progr + ins = &program->instructions.elements[pos]; + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); +- vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VSIR_DATA_F32, 1); + ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; +- src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE, VKD3D_DATA_FLOAT); ++ src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE, VSIR_DATA_F32); + + *ret_pos = pos + 1; + return VKD3D_OK; +@@ -7298,7 +7288,7 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra + { + vsir_instruction_init_with_params(program, ins, loc, VSIR_OP_MAX, 1, 2); + src_param_init_ssa_float(&ins->src[0], ssa_value); +- src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN, VKD3D_DATA_FLOAT); ++ src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN, VSIR_DATA_F32); + if (max_parameter) + { + dst_param_init_ssa_float(&ins->dst[0], program->ssa_count); +@@ -7306,7 +7296,7 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra + } + else + { +- vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VSIR_DATA_F32, 1); + ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; + } + ++ins; +@@ -7317,8 +7307,8 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra + { + vsir_instruction_init_with_params(program, ins, loc, VSIR_OP_MIN, 1, 2); + src_param_init_ssa_float(&ins->src[0], ssa_value); +- src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX, VKD3D_DATA_FLOAT); +- vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); ++ src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX, VSIR_DATA_F32); ++ vsir_dst_param_init(&ins->dst[0], VKD3DSPR_RASTOUT, VSIR_DATA_F32, 1); + ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; + + ++i; +@@ -7495,7 +7485,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr + vsir_instruction_init_with_params(program, ins, &no_loc, VSIR_OP_MOV, 1, 1); + dst_param_init_temp_float4(&ins->dst[0], coord_temp); + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; +- vsir_src_param_init(&ins->src[0], VKD3DSPR_POINT_COORD, VKD3D_DATA_FLOAT, 0); ++ vsir_src_param_init(&ins->src[0], VKD3DSPR_POINT_COORD, VSIR_DATA_F32, 0); + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; + ++ins; +@@ -7503,7 +7493,7 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr + vsir_instruction_init_with_params(program, ins, &no_loc, VSIR_OP_MOV, 1, 1); + dst_param_init_temp_float4(&ins->dst[0], coord_temp); + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; +- vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VKD3D_DATA_FLOAT, 0); ++ vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VSIR_DATA_F32, 0); + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; + ++ins; + +@@ -7573,8 +7563,8 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_ADD, 1, 2); + dst_param_init_ssa_float(&ins->dst[0], ssa_temp); +- src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_END, VKD3D_DATA_FLOAT); +- vsir_src_param_init(&ins->src[1], VKD3DSPR_INPUT, VKD3D_DATA_FLOAT, 1); ++ src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_END, VSIR_DATA_F32); ++ vsir_src_param_init(&ins->src[1], VKD3DSPR_INPUT, VSIR_DATA_F32, 1); + ins->src[1].reg.idx[0].offset = fog_signature_idx; + ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); +@@ -7584,7 +7574,7 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + dst_param_init_ssa_float(&ins->dst[0], ssa_factor); + ins->dst[0].modifiers = VKD3DSPDM_SATURATE; + src_param_init_ssa_float(&ins->src[0], ssa_temp); +- src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VKD3D_DATA_FLOAT); ++ src_param_init_parameter(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VSIR_DATA_F32); + break; + + case VKD3D_SHADER_FOG_FRAGMENT_EXP: +@@ -7605,8 +7595,8 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MUL, 1, 2); + dst_param_init_ssa_float(&ins->dst[0], ssa_temp); +- src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VKD3D_DATA_FLOAT); +- vsir_src_param_init(&ins->src[1], VKD3DSPR_INPUT, VKD3D_DATA_FLOAT, 1); ++ src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VSIR_DATA_F32); ++ vsir_src_param_init(&ins->src[1], VKD3DSPR_INPUT, VSIR_DATA_F32, 1); + ins->src[1].reg.idx[0].offset = fog_signature_idx; + ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); +@@ -7638,8 +7628,8 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MUL, 1, 2); + dst_param_init_ssa_float(&ins->dst[0], ssa_temp); +- src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VKD3D_DATA_FLOAT); +- vsir_src_param_init(&ins->src[1], VKD3DSPR_INPUT, VKD3D_DATA_FLOAT, 1); ++ src_param_init_parameter(&ins->src[0], VKD3D_SHADER_PARAMETER_NAME_FOG_SCALE, VSIR_DATA_F32); ++ vsir_src_param_init(&ins->src[1], VKD3DSPR_INPUT, VSIR_DATA_F32, 1); + ins->src[1].reg.idx[0].offset = fog_signature_idx; + ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); +@@ -7669,15 +7659,15 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro + vsir_instruction_init_with_params(program, ++ins, &loc, VSIR_OP_ADD, 1, 2); + dst_param_init_ssa_float4(&ins->dst[0], program->ssa_count++); + src_param_init_temp_float4(&ins->src[0], colour_temp); +- src_param_init_parameter_vec4(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_FOG_COLOUR, VKD3D_DATA_FLOAT); ++ src_param_init_parameter_vec4(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_FOG_COLOUR, VSIR_DATA_F32); + ins->src[1].modifiers = VKD3DSPSM_NEG; + + vsir_instruction_init_with_params(program, ++ins, &loc, VSIR_OP_MAD, 1, 3); +- dst_param_init_output(&ins->dst[0], VKD3D_DATA_FLOAT, colour_signature_idx, ++ dst_param_init_output(&ins->dst[0], VSIR_DATA_F32, colour_signature_idx, + program->output_signature.elements[colour_signature_idx].mask); + src_param_init_ssa_float4(&ins->src[0], program->ssa_count - 1); + src_param_init_ssa_float(&ins->src[1], ssa_factor); +- src_param_init_parameter_vec4(&ins->src[2], VKD3D_SHADER_PARAMETER_NAME_FOG_COLOUR, VKD3D_DATA_FLOAT); ++ src_param_init_parameter_vec4(&ins->src[2], VKD3D_SHADER_PARAMETER_NAME_FOG_COLOUR, VSIR_DATA_F32); + + return VKD3D_OK; + } +@@ -7819,7 +7809,7 @@ static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *progr + + /* Write the fog output. */ + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); +- dst_param_init_output(&ins->dst[0], VKD3D_DATA_FLOAT, fog_signature_idx, 0x1); ++ dst_param_init_output(&ins->dst[0], VSIR_DATA_F32, fog_signature_idx, 0x1); + src_param_init_temp_float4(&ins->src[0], temp); + if (source == VKD3D_SHADER_FOG_SOURCE_Z) + ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z); +@@ -7829,7 +7819,7 @@ static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *progr + + /* Write the position or specular output. */ + vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); +- dst_param_init_output(&ins->dst[0], vkd3d_data_type_from_component_type(e->component_type), ++ dst_param_init_output(&ins->dst[0], vsir_data_type_from_component_type(e->component_type), + source_signature_idx, e->mask); + src_param_init_temp_float4(&ins->src[0], temp); + ++ins; +@@ -8539,11 +8529,11 @@ static uint8_t get_available_writemask(const struct temp_allocator *allocator, + return writemask; + } + +-static void temp_allocator_allocate(struct temp_allocator *allocator, struct liveness_tracker *tracker, ++static bool temp_allocator_allocate(struct temp_allocator *allocator, struct liveness_tracker *tracker, + struct temp_allocator_reg *reg, const struct liveness_tracker_reg *liveness_reg, uint32_t base_id) + { + if (!liveness_reg->written) +- return; ++ return false; + + for (uint32_t id = base_id;; ++id) + { +@@ -8556,7 +8546,7 @@ static void temp_allocator_allocate(struct temp_allocator *allocator, struct liv + { + reg->temp_id = id; + reg->allocated_mask = liveness_reg->mask; +- return; ++ return true; + } + } + else +@@ -8569,7 +8559,7 @@ static void temp_allocator_allocate(struct temp_allocator *allocator, struct liv + { + reg->temp_id = id; + reg->allocated_mask = vsir_combine_write_masks(available_mask, liveness_reg->mask); +- return; ++ return true; + } + } + } +@@ -8591,6 +8581,7 @@ static void temp_allocator_set_src(struct temp_allocator *allocator, struct vkd3 + return; + + src->reg.type = VKD3DSPR_TEMP; ++ src->reg.dimension = VSIR_DIMENSION_VEC4; + src->reg.idx[0].offset = reg->temp_id; + src->swizzle = vsir_combine_swizzles(vsir_swizzle_from_writemask(reg->allocated_mask), src->swizzle); + } +@@ -8678,6 +8669,7 @@ static void temp_allocator_set_dst(struct temp_allocator *allocator, + return; + + dst->reg.type = VKD3DSPR_TEMP; ++ dst->reg.dimension = VSIR_DIMENSION_VEC4; + dst->reg.idx[0].offset = reg->temp_id; + if (reg->allocated_mask != dst->write_mask) + { +@@ -8713,7 +8705,6 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, + struct temp_allocator allocator = {0}; + struct temp_allocator_reg *regs; + struct liveness_tracker tracker; +- uint32_t temp_count = 0; + enum vkd3d_result ret; + + if (!program->ssa_count) +@@ -8733,12 +8724,16 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, + for (unsigned int i = 0; i < program->ssa_count; ++i) + { + const struct liveness_tracker_reg *liveness_reg = &tracker.ssa_regs[i]; ++ const unsigned int prev_temp_count = program->temp_count; + struct temp_allocator_reg *reg = &allocator.ssa_regs[i]; + +- temp_allocator_allocate(&allocator, &tracker, reg, liveness_reg, program->temp_count); +- TRACE("Allocated r%u%s to sr%u (liveness %u-%u).\n", +- reg->temp_id, debug_vsir_writemask(reg->allocated_mask), i, +- liveness_reg->first_write, liveness_reg->last_access); ++ if (temp_allocator_allocate(&allocator, &tracker, reg, liveness_reg, prev_temp_count)) ++ { ++ TRACE("Allocated r%u%s to sr%u (liveness %u-%u).\n", ++ reg->temp_id, debug_vsir_writemask(reg->allocated_mask), i, ++ liveness_reg->first_write, liveness_reg->last_access); ++ program->temp_count = max(program->temp_count, reg->temp_id + 1); ++ } + ++allocator.allocated_ssa_count; + } + +@@ -8754,13 +8749,25 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, + temp_allocator_set_dst(&allocator, &ins->dst[j], ins); + } + +- /* Rewrite dcl_temps to reflect the new temp count. +- * Note that dcl_temps appears once per phase, and should reflect only the +- * number of temps needed by that phase. +- * Therefore we iterate backwards through the shader, finding the maximum +- * register used by any instruction, update the dcl_temps at the beginning +- * of each phase, and then reset the temp count back to 0 for the next +- * phase (if any). */ ++ program->ssa_count = 0; ++ ++ vkd3d_free(regs); ++ liveness_tracker_cleanup(&tracker); ++ return allocator.result; ++} ++ ++/* Rewrite dcl_temps to reflect the new temp count. ++ * Note that dcl_temps appears once per phase, and should reflect only the ++ * number of temps needed by that phase. ++ * Therefore we iterate backwards through the shader, finding the maximum ++ * register used by any instruction, update the dcl_temps at the beginning ++ * of each phase, and then reset the temp count back to 0 for the next ++ * phase (if any). */ ++enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, ++ struct vkd3d_shader_message_context *message_context) ++{ ++ unsigned int temp_count = 0; ++ + for (int i = program->instructions.count - 1; i >= 0; --i) + { + struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; +@@ -8771,6 +8778,7 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, + temp_count = 0; + continue; + } ++ + if (temp_count && program->shader_version.major >= 4 + && (ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE + || ins->opcode == VSIR_OP_HS_FORK_PHASE +@@ -8779,11 +8787,7 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, + /* The phase didn't have a dcl_temps instruction, but we added + * temps here, so we need to insert one. */ + if (!shader_instruction_array_insert_at(&program->instructions, i + 1, 1)) +- { +- vkd3d_free(regs); +- liveness_tracker_cleanup(&tracker); + return VKD3D_ERROR_OUT_OF_MEMORY; +- } + + ins = &program->instructions.elements[i + 1]; + vsir_instruction_init(ins, &program->instructions.elements[i].location, VSIR_OP_DCL_TEMPS); +@@ -8792,15 +8796,16 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, + continue; + } + +- /* No need to check sources. If we've produced an unwritten source then +- * that's a bug somewhere in this pass. */ ++ for (unsigned int j = 0; j < ins->src_count; ++j) ++ { ++ if (ins->src[j].reg.type == VKD3DSPR_TEMP) ++ temp_count = max(temp_count, ins->src[j].reg.idx[0].offset + 1); ++ } ++ + for (unsigned int j = 0; j < ins->dst_count; ++j) + { + if (ins->dst[j].reg.type == VKD3DSPR_TEMP) +- { + temp_count = max(temp_count, ins->dst[j].reg.idx[0].offset + 1); +- program->temp_count = max(program->temp_count, temp_count); +- } + } + } + +@@ -8809,22 +8814,14 @@ enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, + struct vkd3d_shader_instruction *ins; + + if (!shader_instruction_array_insert_at(&program->instructions, 0, 1)) +- { +- vkd3d_free(regs); +- liveness_tracker_cleanup(&tracker); + return VKD3D_ERROR_OUT_OF_MEMORY; +- } + + ins = &program->instructions.elements[0]; + vsir_instruction_init(ins, &program->instructions.elements[1].location, VSIR_OP_DCL_TEMPS); + ins->declaration.count = temp_count; + } + +- program->ssa_count = 0; +- +- vkd3d_free(regs); +- liveness_tracker_cleanup(&tracker); +- return allocator.result; ++ return VKD3D_OK; + } + + struct validation_context +@@ -8848,7 +8845,7 @@ struct validation_context + struct validation_context_ssa_data + { + enum vsir_dimension dimension; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + size_t first_seen; + uint32_t write_mask; + uint32_t read_mask; +@@ -9542,6 +9539,24 @@ static void vsir_validate_src_param(struct validation_context *ctx, + static void vsir_validate_register(struct validation_context *ctx, + const struct vkd3d_shader_register *reg) + { ++ static const struct register_validation_data ++ { ++ bool valid; ++ unsigned int idx_count; ++ enum vsir_dimension dimension; ++ } ++ register_validation_data[] = ++ { ++ [VKD3DSPR_DEPTHOUT] = {true, 0, VSIR_DIMENSION_SCALAR}, ++ [VKD3DSPR_THREADGROUPID] = {true, 0, VSIR_DIMENSION_VEC4}, ++ [VKD3DSPR_LOCALTHREADID] = {true, 0, VSIR_DIMENSION_VEC4}, ++ [VKD3DSPR_LOCALTHREADINDEX] = {true, 0, VSIR_DIMENSION_VEC4}, ++ [VKD3DSPR_COVERAGE] = {true, 0, VSIR_DIMENSION_VEC4}, ++ [VKD3DSPR_DEPTHOUTGE] = {true, 0, VSIR_DIMENSION_SCALAR}, ++ [VKD3DSPR_DEPTHOUTLE] = {true, 0, VSIR_DIMENSION_SCALAR}, ++ }; ++ ++ const struct register_validation_data *validation_data; + unsigned int i; + + if (reg->type >= VKD3DSPR_COUNT) +@@ -9552,7 +9567,7 @@ static void vsir_validate_register(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, "Invalid register precision %#x.", + reg->precision); + +- if (reg->data_type >= VKD3D_DATA_COUNT) ++ if (reg->data_type >= VSIR_DATA_TYPE_COUNT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid register data type %#x.", + reg->data_type); + +@@ -9607,10 +9622,6 @@ static void vsir_validate_register(struct validation_context *ctx, + vsir_validate_io_register(ctx, reg); + break; + +- case VKD3DSPR_DEPTHOUT: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- + case VKD3DSPR_MISCTYPE: + vsir_validate_misctype_register(ctx, reg); + break; +@@ -9683,22 +9694,6 @@ static void vsir_validate_register(struct validation_context *ctx, + vsir_validate_register_without_indices(ctx, reg); + break; + +- case VKD3DSPR_THREADGROUPID: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- +- case VKD3DSPR_LOCALTHREADID: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- +- case VKD3DSPR_LOCALTHREADINDEX: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- +- case VKD3DSPR_COVERAGE: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- + case VKD3DSPR_SAMPLEMASK: + vsir_validate_register_without_indices(ctx, reg); + break; +@@ -9707,14 +9702,6 @@ static void vsir_validate_register(struct validation_context *ctx, + vsir_validate_register_without_indices(ctx, reg); + break; + +- case VKD3DSPR_DEPTHOUTGE: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- +- case VKD3DSPR_DEPTHOUTLE: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- + case VKD3DSPR_OUTSTENCILREF: + vsir_validate_register_without_indices(ctx, reg); + break; +@@ -9734,6 +9721,24 @@ static void vsir_validate_register(struct validation_context *ctx, + default: + break; + } ++ ++ if (reg->type >= ARRAY_SIZE(register_validation_data)) ++ return; ++ ++ validation_data = ®ister_validation_data[reg->type]; ++ ++ if (!validation_data->valid) ++ return; ++ ++ if (reg->idx_count != validation_data->idx_count) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid index count %u for a register of type %#x, expected %u.", ++ reg->idx_count, reg->type, validation_data->idx_count); ++ ++ if (reg->dimension != validation_data->dimension) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, ++ "Invalid dimension %#x for a register of type %#x, expected %#x.", ++ reg->dimension, reg->type, validation_data->dimension); + } + + static void vsir_validate_io_dst_param(struct validation_context *ctx, +@@ -9783,9 +9788,9 @@ static void vsir_validate_dst_param(struct validation_context *ctx, + { + switch (dst->reg.data_type) + { +- case VKD3D_DATA_FLOAT: +- case VKD3D_DATA_DOUBLE: +- case VKD3D_DATA_HALF: ++ case VSIR_DATA_F16: ++ case VSIR_DATA_F32: ++ case VSIR_DATA_F64: + break; + + default: +@@ -9807,7 +9812,7 @@ static void vsir_validate_dst_param(struct validation_context *ctx, + case 13: + case 14: + case 15: +- if (dst->reg.data_type != VKD3D_DATA_FLOAT) ++ if (dst->reg.data_type != VSIR_DATA_F32) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Invalid data type %#x for destination with shift.", dst->reg.data_type); + break; +@@ -9891,9 +9896,9 @@ static void vsir_validate_io_src_param(struct validation_context *ctx, + "Invalid register type %#x used as source parameter.", src->reg.type); + } + +-#define F64_BIT (1u << VKD3D_DATA_DOUBLE) +-#define F32_BIT (1u << VKD3D_DATA_FLOAT) +-#define F16_BIT (1u << VKD3D_DATA_HALF) ++#define F64_BIT (1u << VSIR_DATA_F64) ++#define F32_BIT (1u << VSIR_DATA_F32) ++#define F16_BIT (1u << VSIR_DATA_F16) + + #define I32_BIT (1u << VKD3D_DATA_INT) + +@@ -10494,7 +10499,7 @@ static void vsir_validate_descriptors(struct validation_context *ctx) + "Descriptor %u has invalid resource type %#x for descriptor type %#x.", + i, descriptor->resource_type, descriptor->type); + +- if (descriptor->resource_data_type >= VKD3D_DATA_COUNT) ++ if (descriptor->resource_data_type >= VSIR_DATA_TYPE_COUNT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Descriptor %u has invalid resource data type %#x.", i, descriptor->resource_data_type); + else if ((descriptor->resource_data_type == VKD3D_DATA_UNUSED) +@@ -10597,9 +10602,9 @@ static void vsir_validate_hull_shader_phase(struct validation_context *ctx, + } + + static void vsir_validate_elementwise_operation(struct validation_context *ctx, +- const struct vkd3d_shader_instruction *instruction, const bool types[VKD3D_DATA_COUNT]) ++ const struct vkd3d_shader_instruction *instruction, const bool types[VSIR_DATA_TYPE_COUNT]) + { +- enum vkd3d_data_type dst_data_type; ++ enum vsir_data_type dst_data_type; + unsigned int i; + + if (instruction->dst_count < 1) +@@ -10607,7 +10612,7 @@ static void vsir_validate_elementwise_operation(struct validation_context *ctx, + + dst_data_type = instruction->dst[0].reg.data_type; + +- if (dst_data_type >= VKD3D_DATA_COUNT) ++ if (dst_data_type >= VSIR_DATA_TYPE_COUNT) + return; + + if (!types[dst_data_type]) +@@ -10629,9 +10634,9 @@ static void vsir_validate_elementwise_operation(struct validation_context *ctx, + static void vsir_validate_double_elementwise_operation(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) + { +- static const bool types[VKD3D_DATA_COUNT] = ++ static const bool types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_DOUBLE] = true, ++ [VSIR_DATA_F64] = true, + }; + + vsir_validate_elementwise_operation(ctx, instruction, types); +@@ -10640,9 +10645,9 @@ static void vsir_validate_double_elementwise_operation(struct validation_context + static void vsir_validate_float_elementwise_operation(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) + { +- static const bool types[VKD3D_DATA_COUNT] = ++ static const bool types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_FLOAT] = true, ++ [VSIR_DATA_F32] = true, + }; + + vsir_validate_elementwise_operation(ctx, instruction, types); +@@ -10651,7 +10656,7 @@ static void vsir_validate_float_elementwise_operation(struct validation_context + static void vsir_validate_integer_elementwise_operation(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) + { +- static const bool types[VKD3D_DATA_COUNT] = ++ static const bool types[VSIR_DATA_TYPE_COUNT] = + { + [VKD3D_DATA_INT] = true, + [VKD3D_DATA_UINT] = true, +@@ -10664,7 +10669,7 @@ static void vsir_validate_integer_elementwise_operation(struct validation_contex + static void vsir_validate_logic_elementwise_operation(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) + { +- static const bool types[VKD3D_DATA_COUNT] = ++ static const bool types[VSIR_DATA_TYPE_COUNT] = + { + [VKD3D_DATA_INT] = true, + [VKD3D_DATA_UINT] = true, +@@ -10676,9 +10681,9 @@ static void vsir_validate_logic_elementwise_operation(struct validation_context + } + + static void vsir_validate_comparison_operation(struct validation_context *ctx, +- const struct vkd3d_shader_instruction *instruction, const bool types[VKD3D_DATA_COUNT]) ++ const struct vkd3d_shader_instruction *instruction, const bool types[VSIR_DATA_TYPE_COUNT]) + { +- enum vkd3d_data_type dst_data_type, src_data_type; ++ enum vsir_data_type dst_data_type, src_data_type; + unsigned int i; + + if (instruction->dst_count < 1) +@@ -10696,7 +10701,7 @@ static void vsir_validate_comparison_operation(struct validation_context *ctx, + + src_data_type = instruction->src[0].reg.data_type; + +- if (src_data_type >= VKD3D_DATA_COUNT) ++ if (src_data_type >= VSIR_DATA_TYPE_COUNT) + return; + + if (!types[src_data_type]) +@@ -10718,9 +10723,9 @@ static void vsir_validate_comparison_operation(struct validation_context *ctx, + static void vsir_validate_double_comparison_operation(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) + { +- static const bool types[VKD3D_DATA_COUNT] = ++ static const bool types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_DOUBLE] = true, ++ [VSIR_DATA_F64] = true, + }; + + vsir_validate_comparison_operation(ctx, instruction, types); +@@ -10729,9 +10734,10 @@ static void vsir_validate_double_comparison_operation(struct validation_context + static void vsir_validate_float_comparison_operation(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) + { +- static const bool types[VKD3D_DATA_COUNT] = ++ static const bool types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_FLOAT] = true, ++ [VSIR_DATA_F32] = true, ++ [VSIR_DATA_F64] = true, + }; + + vsir_validate_comparison_operation(ctx, instruction, types); +@@ -10740,7 +10746,7 @@ static void vsir_validate_float_comparison_operation(struct validation_context * + static void vsir_validate_integer_comparison_operation(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction) + { +- static const bool types[VKD3D_DATA_COUNT] = ++ static const bool types[VSIR_DATA_TYPE_COUNT] = + { + [VKD3D_DATA_INT] = true, + [VKD3D_DATA_UINT] = true, +@@ -10750,6 +10756,32 @@ static void vsir_validate_integer_comparison_operation(struct validation_context + vsir_validate_comparison_operation(ctx, instruction, types); + } + ++static void vsir_validate_cast_operation(struct validation_context *ctx, ++ const struct vkd3d_shader_instruction *instruction, ++ const bool src_types[VSIR_DATA_TYPE_COUNT], const bool dst_types[VSIR_DATA_TYPE_COUNT]) ++{ ++ enum vsir_data_type dst_data_type, src_data_type; ++ ++ if (instruction->dst_count < 1 || instruction->src_count < 1) ++ return; ++ ++ dst_data_type = instruction->dst[0].reg.data_type; ++ src_data_type = instruction->src[0].reg.data_type; ++ ++ if (src_data_type >= VSIR_DATA_TYPE_COUNT || dst_data_type >= VSIR_DATA_TYPE_COUNT) ++ return; ++ ++ if (!src_types[src_data_type]) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid source data type %#x for cast operation \"%s\" (%#x).", ++ src_data_type, vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); ++ ++ if (!dst_types[dst_data_type]) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid destination data type %#x for cast operation \"%s\" (%#x).", ++ dst_data_type, vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); ++} ++ + static void vsir_validate_branch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) + { + size_t i; +@@ -11263,6 +11295,39 @@ static void vsir_validate_endswitch(struct validation_context *ctx, const struct + --ctx->depth; + } + ++static void vsir_validate_ftoi(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool src_types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VSIR_DATA_F16] = true, ++ [VSIR_DATA_F32] = true, ++ [VSIR_DATA_F64] = true, ++ }; ++ static const bool dst_types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VKD3D_DATA_INT] = true, ++ [VKD3D_DATA_UINT] = true, ++ }; ++ ++ vsir_validate_cast_operation(ctx, instruction, src_types, dst_types); ++} ++ ++static void vsir_validate_ftou(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool src_types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VSIR_DATA_F16] = true, ++ [VSIR_DATA_F32] = true, ++ [VSIR_DATA_F64] = true, ++ }; ++ static const bool dst_types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VKD3D_DATA_UINT] = true, ++ }; ++ ++ vsir_validate_cast_operation(ctx, instruction, src_types, dst_types); ++} ++ + static void vsir_validate_if(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) + { + vsir_validate_cf_type(ctx, instruction, VSIR_CF_STRUCTURED); +@@ -11275,6 +11340,38 @@ static void vsir_validate_ifc(struct validation_context *ctx, const struct vkd3d + vsir_validator_push_block(ctx, VSIR_OP_IF); + } + ++static void vsir_validate_itof(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool src_types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VKD3D_DATA_INT] = true, ++ [VKD3D_DATA_UINT] = true, ++ [VKD3D_DATA_UINT64] = true, ++ [VKD3D_DATA_BOOL] = true, ++ }; ++ static const bool dst_types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VSIR_DATA_F16] = true, ++ [VSIR_DATA_F32] = true, ++ [VSIR_DATA_F64] = true, ++ }; ++ ++ vsir_validate_cast_operation(ctx, instruction, src_types, dst_types); ++} ++ ++static void vsir_validate_itoi(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) ++{ ++ static const bool types[VSIR_DATA_TYPE_COUNT] = ++ { ++ [VKD3D_DATA_INT] = true, ++ [VKD3D_DATA_UINT] = true, ++ [VKD3D_DATA_UINT64] = true, ++ [VKD3D_DATA_BOOL] = true, ++ }; ++ ++ vsir_validate_cast_operation(ctx, instruction, types, types); ++} ++ + static void vsir_validate_label(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) + { + vsir_validate_cf_type(ctx, instruction, VSIR_CF_BLOCKS); +@@ -11443,6 +11540,25 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_ATAN] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_BRANCH] = {0, ~0u, vsir_validate_branch}, + [VSIR_OP_DADD] = {1, 2, vsir_validate_double_elementwise_operation}, ++ [VSIR_OP_DCL_GS_INSTANCES] = {0, 0, vsir_validate_dcl_gs_instances}, ++ [VSIR_OP_DCL_HS_MAX_TESSFACTOR] = {0, 0, vsir_validate_dcl_hs_max_tessfactor}, ++ [VSIR_OP_DCL_INDEX_RANGE] = {0, 0, vsir_validate_dcl_index_range}, ++ [VSIR_OP_DCL_INPUT] = {0, 0, vsir_validate_dcl_input}, ++ [VSIR_OP_DCL_INPUT_PRIMITIVE] = {0, 0, vsir_validate_dcl_input_primitive}, ++ [VSIR_OP_DCL_INPUT_PS] = {0, 0, vsir_validate_dcl_input_ps}, ++ [VSIR_OP_DCL_INPUT_PS_SGV] = {0, 0, vsir_validate_dcl_input_ps_sgv}, ++ [VSIR_OP_DCL_INPUT_PS_SIV] = {0, 0, vsir_validate_dcl_input_ps_siv}, ++ [VSIR_OP_DCL_INPUT_SGV] = {0, 0, vsir_validate_dcl_input_sgv}, ++ [VSIR_OP_DCL_INPUT_SIV] = {0, 0, vsir_validate_dcl_input_siv}, ++ [VSIR_OP_DCL_OUTPUT] = {0, 0, vsir_validate_dcl_output}, ++ [VSIR_OP_DCL_OUTPUT_CONTROL_POINT_COUNT] = {0, 0, vsir_validate_dcl_output_control_point_count}, ++ [VSIR_OP_DCL_OUTPUT_SIV] = {0, 0, vsir_validate_dcl_output_siv}, ++ [VSIR_OP_DCL_OUTPUT_TOPOLOGY] = {0, 0, vsir_validate_dcl_output_topology}, ++ [VSIR_OP_DCL_TEMPS] = {0, 0, vsir_validate_dcl_temps}, ++ [VSIR_OP_DCL_TESSELLATOR_DOMAIN] = {0, 0, vsir_validate_dcl_tessellator_domain}, ++ [VSIR_OP_DCL_TESSELLATOR_OUTPUT_PRIMITIVE] = {0, 0, vsir_validate_dcl_tessellator_output_primitive}, ++ [VSIR_OP_DCL_TESSELLATOR_PARTITIONING] = {0, 0, vsir_validate_dcl_tessellator_partitioning}, ++ [VSIR_OP_DCL_VERTICES_OUT] = {0, 0, vsir_validate_dcl_vertices_out}, + [VSIR_OP_DDIV] = {1, 2, vsir_validate_double_elementwise_operation}, + [VSIR_OP_DEQO] = {1, 2, vsir_validate_double_comparison_operation}, + [VSIR_OP_DFMA] = {1, 3, vsir_validate_double_elementwise_operation}, +@@ -11461,22 +11577,31 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_DSY] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_DSY_COARSE] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_DSY_FINE] = {1, 1, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_ELSE] = {0, 0, vsir_validate_else}, ++ [VSIR_OP_ENDIF] = {0, 0, vsir_validate_endif}, ++ [VSIR_OP_ENDLOOP] = {0, 0, vsir_validate_endloop}, ++ [VSIR_OP_ENDREP] = {0, 0, vsir_validate_endrep}, ++ [VSIR_OP_ENDSWITCH] = {0, 0, vsir_validate_endswitch}, + [VSIR_OP_EQO] = {1, 2, vsir_validate_float_comparison_operation}, + [VSIR_OP_EQU] = {1, 2, vsir_validate_float_comparison_operation}, + [VSIR_OP_EXP] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_FRC] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_FREM] = {1, 2, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_FTOI] = {1, 1, vsir_validate_ftoi}, ++ [VSIR_OP_FTOU] = {1, 1, vsir_validate_ftou}, + [VSIR_OP_GEO] = {1, 2, vsir_validate_float_comparison_operation}, + [VSIR_OP_GEU] = {1, 2, vsir_validate_float_comparison_operation}, + [VSIR_OP_HCOS] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_HSIN] = {1, 1, vsir_validate_float_elementwise_operation}, +- [VSIR_OP_HTAN] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_HS_CONTROL_POINT_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, + [VSIR_OP_HS_DECLS] = {0, 0, vsir_validate_hull_shader_phase}, + [VSIR_OP_HS_FORK_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, + [VSIR_OP_HS_JOIN_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, ++ [VSIR_OP_HTAN] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_IADD] = {1, 2, vsir_validate_integer_elementwise_operation}, + [VSIR_OP_IEQ] = {1, 2, vsir_validate_integer_comparison_operation}, ++ [VSIR_OP_IF] = {0, 1, vsir_validate_if}, ++ [VSIR_OP_IFC] = {0, 2, vsir_validate_ifc}, + [VSIR_OP_IGE] = {1, 2, vsir_validate_integer_comparison_operation}, + [VSIR_OP_ILT] = {1, 2, vsir_validate_integer_comparison_operation}, + [VSIR_OP_IMAD] = {1, 3, vsir_validate_integer_elementwise_operation}, +@@ -11485,36 +11610,22 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_INE] = {1, 2, vsir_validate_integer_comparison_operation}, + [VSIR_OP_INEG] = {1, 1, vsir_validate_integer_elementwise_operation}, + [VSIR_OP_IREM] = {1, 2, vsir_validate_integer_elementwise_operation}, ++ [VSIR_OP_ISFINITE] = {1, 1, vsir_validate_float_comparison_operation}, + [VSIR_OP_ISHL] = {1, 2, vsir_validate_integer_elementwise_operation}, + [VSIR_OP_ISHR] = {1, 2, vsir_validate_integer_elementwise_operation}, +- [VSIR_OP_DCL_GS_INSTANCES] = {0, 0, vsir_validate_dcl_gs_instances}, +- [VSIR_OP_DCL_HS_MAX_TESSFACTOR] = {0, 0, vsir_validate_dcl_hs_max_tessfactor}, +- [VSIR_OP_DCL_INDEX_RANGE] = {0, 0, vsir_validate_dcl_index_range}, +- [VSIR_OP_DCL_INPUT] = {0, 0, vsir_validate_dcl_input}, +- [VSIR_OP_DCL_INPUT_PRIMITIVE] = {0, 0, vsir_validate_dcl_input_primitive}, +- [VSIR_OP_DCL_INPUT_PS] = {0, 0, vsir_validate_dcl_input_ps}, +- [VSIR_OP_DCL_INPUT_PS_SGV] = {0, 0, vsir_validate_dcl_input_ps_sgv}, +- [VSIR_OP_DCL_INPUT_PS_SIV] = {0, 0, vsir_validate_dcl_input_ps_siv}, +- [VSIR_OP_DCL_INPUT_SGV] = {0, 0, vsir_validate_dcl_input_sgv}, +- [VSIR_OP_DCL_INPUT_SIV] = {0, 0, vsir_validate_dcl_input_siv}, +- [VSIR_OP_DCL_OUTPUT] = {0, 0, vsir_validate_dcl_output}, +- [VSIR_OP_DCL_OUTPUT_CONTROL_POINT_COUNT] = {0, 0, vsir_validate_dcl_output_control_point_count}, +- [VSIR_OP_DCL_OUTPUT_SIV] = {0, 0, vsir_validate_dcl_output_siv}, +- [VSIR_OP_DCL_OUTPUT_TOPOLOGY] = {0, 0, vsir_validate_dcl_output_topology}, +- [VSIR_OP_DCL_TEMPS] = {0, 0, vsir_validate_dcl_temps}, +- [VSIR_OP_DCL_TESSELLATOR_DOMAIN] = {0, 0, vsir_validate_dcl_tessellator_domain}, +- [VSIR_OP_DCL_TESSELLATOR_OUTPUT_PRIMITIVE] = {0, 0, vsir_validate_dcl_tessellator_output_primitive}, +- [VSIR_OP_DCL_TESSELLATOR_PARTITIONING] = {0, 0, vsir_validate_dcl_tessellator_partitioning}, +- [VSIR_OP_DCL_VERTICES_OUT] = {0, 0, vsir_validate_dcl_vertices_out}, +- [VSIR_OP_ELSE] = {0, 0, vsir_validate_else}, +- [VSIR_OP_ENDIF] = {0, 0, vsir_validate_endif}, +- [VSIR_OP_ENDLOOP] = {0, 0, vsir_validate_endloop}, +- [VSIR_OP_ENDREP] = {0, 0, vsir_validate_endrep}, +- [VSIR_OP_ENDSWITCH] = {0, 0, vsir_validate_endswitch}, +- [VSIR_OP_IF] = {0, 1, vsir_validate_if}, +- [VSIR_OP_IFC] = {0, 2, vsir_validate_ifc}, ++ [VSIR_OP_ISINF] = {1, 1, vsir_validate_float_comparison_operation}, ++ [VSIR_OP_ISNAN] = {1, 1, vsir_validate_float_comparison_operation}, ++ [VSIR_OP_ITOF] = {1, 1, vsir_validate_itof}, ++ [VSIR_OP_ITOI] = {1, 1, vsir_validate_itoi}, + [VSIR_OP_LABEL] = {0, 1, vsir_validate_label}, ++ [VSIR_OP_LOG] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_LOOP] = {0, ~0u, vsir_validate_loop}, ++ [VSIR_OP_LTO] = {1, 2, vsir_validate_float_comparison_operation}, ++ [VSIR_OP_LTU] = {1, 2, vsir_validate_float_comparison_operation}, ++ [VSIR_OP_MAD] = {1, 3, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_MAX] = {1, 2, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_MIN] = {1, 2, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_MUL] = {1, 2, vsir_validate_float_elementwise_operation}, + [VSIR_OP_NOP] = {0, 0, vsir_validate_nop}, + [VSIR_OP_PHI] = {1, ~0u, vsir_validate_phi}, + [VSIR_OP_REP] = {0, 1, vsir_validate_rep}, +diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c +index 032b5504319..83cdf9feea0 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/msl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/msl.c +@@ -133,11 +133,11 @@ static void msl_print_indent(struct vkd3d_string_buffer *buffer, unsigned int in + } + + static void msl_print_resource_datatype(struct msl_generator *gen, +- struct vkd3d_string_buffer *buffer, enum vkd3d_data_type data_type) ++ struct vkd3d_string_buffer *buffer, enum vsir_data_type data_type) + { + switch (data_type) + { +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + case VKD3D_DATA_UNORM: + case VKD3D_DATA_SNORM: + vkd3d_string_buffer_printf(buffer, "float"); +@@ -157,12 +157,12 @@ static void msl_print_resource_datatype(struct msl_generator *gen, + } + + static void msl_print_register_datatype(struct vkd3d_string_buffer *buffer, +- struct msl_generator *gen, enum vkd3d_data_type data_type) ++ struct msl_generator *gen, enum vsir_data_type data_type) + { + vkd3d_string_buffer_printf(buffer, "."); + switch (data_type) + { +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + vkd3d_string_buffer_printf(buffer, "f"); + break; + case VKD3D_DATA_INT: +@@ -345,7 +345,7 @@ static void msl_print_sampler_name(struct vkd3d_string_buffer *buffer, unsigned + } + + static void msl_print_srv_name(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, unsigned int binding, +- const struct msl_resource_type_info *resource_type_info, enum vkd3d_data_type resource_data_type, bool compare) ++ const struct msl_resource_type_info *resource_type_info, enum vsir_data_type resource_data_type, bool compare) + { + vkd3d_string_buffer_printf(buffer, "descriptors[%u].as<%s%s%s<", + binding, compare ? "depth" : "texture", resource_type_info->type_suffix, +@@ -355,7 +355,7 @@ static void msl_print_srv_name(struct vkd3d_string_buffer *buffer, struct msl_ge + } + + static void msl_print_uav_name(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, unsigned int binding, +- const struct msl_resource_type_info *resource_type_info, enum vkd3d_data_type resource_data_type) ++ const struct msl_resource_type_info *resource_type_info, enum vsir_data_type resource_data_type) + { + vkd3d_string_buffer_printf(buffer, "descriptors[%u].astype_suffix, +@@ -523,17 +523,17 @@ static void msl_src_cleanup(struct msl_src *src, struct vkd3d_string_buffer_cach + } + + static void msl_print_bitcast(struct vkd3d_string_buffer *dst, struct msl_generator *gen, const char *src, +- enum vkd3d_data_type dst_data_type, enum msl_data_type src_data_type, enum vsir_dimension dimension) ++ enum vsir_data_type dst_data_type, enum msl_data_type src_data_type, enum vsir_dimension dimension) + { + bool write_cast = false; + + if (dst_data_type == VKD3D_DATA_UNORM || dst_data_type == VKD3D_DATA_SNORM) +- dst_data_type = VKD3D_DATA_FLOAT; ++ dst_data_type = VSIR_DATA_F32; + + switch (src_data_type) + { + case MSL_DATA_FLOAT: +- write_cast = dst_data_type != VKD3D_DATA_FLOAT; ++ write_cast = dst_data_type != VSIR_DATA_F32; + break; + + case MSL_DATA_UINT: +@@ -561,7 +561,7 @@ static void msl_print_bitcast(struct vkd3d_string_buffer *dst, struct msl_genera + } + + static void msl_print_src_with_type(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, +- const struct vkd3d_shader_src_param *vsir_src, uint32_t mask, enum vkd3d_data_type data_type) ++ const struct vkd3d_shader_src_param *vsir_src, uint32_t mask, enum vsir_data_type data_type) + { + const struct vkd3d_shader_register *reg = &vsir_src->reg; + struct vkd3d_string_buffer *register_name, *str; +@@ -947,7 +947,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct + const struct vkd3d_shader_descriptor_binding *binding; + enum vkd3d_shader_resource_type resource_type; + struct vkd3d_string_buffer *read; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + unsigned int srv_binding; + uint32_t coord_mask; + struct msl_dst dst; +@@ -975,7 +975,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct + "Internal compiler error: Undeclared resource descriptor %u.", resource_id); + resource_space = 0; + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; +- data_type = VKD3D_DATA_FLOAT; ++ data_type = VSIR_DATA_F32; + } + + if (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBE +@@ -1047,7 +1047,7 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + enum vkd3d_shader_resource_type resource_type; + unsigned int srv_binding, sampler_binding; + struct vkd3d_string_buffer *sample; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + unsigned int component_idx; + uint32_t coord_mask; + struct msl_dst dst; +@@ -1086,7 +1086,7 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + "Internal compiler error: Undeclared resource descriptor %u.", resource_id); + resource_space = 0; + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; +- data_type = VKD3D_DATA_FLOAT; ++ data_type = VSIR_DATA_F32; + } + + if (resource_type == VKD3D_SHADER_RESOURCE_BUFFER +@@ -1257,7 +1257,7 @@ static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_sh + enum vkd3d_shader_resource_type resource_type; + unsigned int uav_id, uav_idx, uav_space; + struct vkd3d_string_buffer *image_data; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + unsigned int uav_binding; + uint32_t coord_mask; + +@@ -1280,7 +1280,7 @@ static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_sh + "Internal compiler error: Undeclared UAV descriptor %u.", uav_id); + uav_space = 0; + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; +- data_type = VKD3D_DATA_FLOAT; ++ data_type = VSIR_DATA_F32; + } + + if (!(resource_type_info = msl_get_resource_type_info(resource_type))) +@@ -1319,7 +1319,7 @@ static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_sh + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled data type %#x.", data_type); + /* fall through */ +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + case VKD3D_DATA_UNORM: + case VKD3D_DATA_SNORM: + vkd3d_string_buffer_printf(image_data, "float4("); +@@ -1882,13 +1882,13 @@ static void msl_generate_entrypoint_prologue(struct msl_generator *gen) + switch (e->sysval_semantic) + { + case VKD3D_SHADER_SV_NONE: +- msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); ++ msl_print_register_datatype(buffer, gen, vsir_data_type_from_component_type(e->component_type)); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = input.shader_in_%u", i); + break; + + case VKD3D_SHADER_SV_POSITION: +- msl_print_register_datatype(buffer, gen, VKD3D_DATA_FLOAT); ++ msl_print_register_datatype(buffer, gen, VSIR_DATA_F32); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = float4(input.position.xyz, 1.0f / input.position.w)"); + break; +@@ -1944,7 +1944,7 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) + vkd3d_string_buffer_printf(buffer, " output.shader_out_%u", i); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = %s_out[%u]", gen->prefix, e->register_index); +- msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); ++ msl_print_register_datatype(buffer, gen, vsir_data_type_from_component_type(e->component_type)); + msl_print_write_mask(buffer, e->mask); + break; + case VKD3D_SHADER_SV_DEPTH: +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index c51a6a394c0..eb9a90e8b44 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -2568,7 +2568,7 @@ static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder, + } + + static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder *builder, +- enum vkd3d_data_type data_type, unsigned int component_count) ++ enum vsir_data_type data_type, unsigned int component_count) + { + enum vkd3d_shader_component_type component_type; + +@@ -3012,7 +3012,7 @@ struct vkd3d_hull_shader_variables + + struct ssa_register_info + { +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + uint8_t write_mask; + uint32_t id; + }; +@@ -3985,7 +3985,7 @@ static uint32_t spirv_compiler_alloc_spec_constant_id(struct spirv_compiler *com + + static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compiler, + enum vkd3d_shader_parameter_name name, uint32_t spec_id, +- enum vkd3d_data_type type, unsigned int component_count) ++ enum vsir_data_type type, unsigned int component_count) + { + uint32_t scalar_type_id, vector_type_id, id, default_value, components[4]; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +@@ -4024,7 +4024,7 @@ static uint32_t spirv_compiler_emit_spec_constant(struct spirv_compiler *compile + + static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler, + enum vkd3d_shader_parameter_name name, uint32_t spec_id, +- enum vkd3d_data_type type, unsigned int component_count) ++ enum vsir_data_type type, unsigned int component_count) + { + unsigned int i; + +@@ -4038,7 +4038,7 @@ static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler + } + + static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compiler, +- const struct vkd3d_shader_parameter1 *parameter, enum vkd3d_data_type type, unsigned int component_count) ++ const struct vkd3d_shader_parameter1 *parameter, enum vsir_data_type type, unsigned int component_count) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + unsigned int index = parameter - compiler->program->parameters; +@@ -4054,18 +4054,18 @@ static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compi + + static const struct + { +- enum vkd3d_data_type type; ++ enum vsir_data_type type; + unsigned int component_count; + } + parameter_data_type_map[] = + { +- [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32] = {VKD3D_DATA_FLOAT, 1}, ++ [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32] = {VSIR_DATA_F32, 1}, + [VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32] = {VKD3D_DATA_UINT, 1}, +- [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4] = {VKD3D_DATA_FLOAT, 4}, ++ [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4] = {VSIR_DATA_F32, 4}, + }; + + static uint32_t spirv_compiler_emit_shader_parameter(struct spirv_compiler *compiler, +- enum vkd3d_shader_parameter_name name, enum vkd3d_data_type type, unsigned int component_count) ++ enum vkd3d_shader_parameter_name name, enum vsir_data_type type, unsigned int component_count) + { + const struct vkd3d_shader_parameter1 *parameter; + +@@ -4479,7 +4479,7 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil + } + + static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, +- enum vkd3d_shader_conditional_op condition, enum vkd3d_data_type data_type, ++ enum vkd3d_shader_conditional_op condition, enum vsir_data_type data_type, + unsigned int component_count, uint32_t val_id) + { + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +@@ -4708,14 +4708,14 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil + + switch (icb->data_type) + { +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F32: + 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 VSIR_DATA_F64: + case VKD3D_DATA_UINT64: + { + uint64_t *data = (uint64_t *)icb->data; +@@ -4903,7 +4903,7 @@ static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *co + { + struct vkd3d_shader_src_param src_param = *src; + +- src_param.reg.data_type = vkd3d_data_type_from_component_type(component_type); ++ src_param.reg.data_type = vsir_data_type_from_component_type(component_type); + return spirv_compiler_emit_load_src(compiler, &src_param, write_mask); + } + +@@ -5029,7 +5029,7 @@ static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler, + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, zero_id, one_id; + +- if (reg->data_type == VKD3D_DATA_DOUBLE) ++ if (reg->data_type == VSIR_DATA_F64) + { + zero_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count); + one_id = spirv_compiler_get_constant_double_vector(compiler, 1.0, component_count); +@@ -5083,7 +5083,7 @@ static void spirv_compiler_emit_store_dst_swizzled(struct spirv_compiler *compil + /* XXX: The register data type could be fixed by the shader parser. For SM5 + * shaders the data types are stored in instructions modifiers. + */ +- typed_dst.reg.data_type = vkd3d_data_type_from_component_type(component_type); ++ typed_dst.reg.data_type = vsir_data_type_from_component_type(component_type); + spirv_compiler_emit_store_dst(compiler, &typed_dst, val_id); + } + +@@ -5511,7 +5511,7 @@ static uint32_t spirv_compiler_get_invocation_id(struct spirv_compiler *compiler + + VKD3D_ASSERT(compiler->shader_type == VKD3D_SHADER_TYPE_HULL); + +- vsir_register_init(&r, VKD3DSPR_OUTPOINTID, VKD3D_DATA_FLOAT, 0); ++ vsir_register_init(&r, VKD3DSPR_OUTPOINTID, VSIR_DATA_F32, 0); + return spirv_compiler_get_register_id(compiler, &r); + } + +@@ -5800,7 +5800,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + { + struct vkd3d_shader_register dst_reg; + +- vsir_register_init(&dst_reg, reg_type, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(&dst_reg, reg_type, VSIR_DATA_F32, 1); + dst_reg.idx[0].offset = element_idx; + + type_id = vkd3d_spirv_get_type_id(builder, component_type, input_component_count); +@@ -6502,7 +6502,7 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil + * scope is specified, e.g. DXIL alloca. */ + storage_class = temp->has_function_scope ? SpvStorageClassFunction : SpvStorageClassPrivate; + +- vsir_register_init(®, VKD3DSPR_IDXTEMP, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(®, VKD3DSPR_IDXTEMP, VSIR_DATA_F32, 1); + reg.idx[0].offset = temp->register_idx; + + /* Alignment is supported only in the Kernel execution model and is an optimisation only. */ +@@ -6742,7 +6742,7 @@ static void spirv_compiler_emit_cbv_declaration(struct spirv_compiler *compiler, + struct vkd3d_symbol reg_symbol; + unsigned int size; + +- vsir_register_init(®, VKD3DSPR_CONSTBUFFER, VKD3D_DATA_FLOAT, 3); ++ vsir_register_init(®, VKD3DSPR_CONSTBUFFER, VSIR_DATA_F32, 3); + reg.idx[0].offset = descriptor->register_id; + reg.idx[1].offset = range->first; + reg.idx[2].offset = range->last; +@@ -6802,7 +6802,7 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi + vkd3d_spirv_build_op_name(builder, icb_id, "icb"); + + /* Set an index count of 2 so vkd3d_symbol_make_register() uses idx[0] as a buffer id. */ +- vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 2); ++ vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VSIR_DATA_F32, 2); + reg.idx[0].offset = icb->register_idx; + vkd3d_symbol_make_register(®_symbol, ®); + vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate, +@@ -6821,7 +6821,7 @@ static void spirv_compiler_emit_sampler_declaration(struct spirv_compiler *compi + struct vkd3d_symbol reg_symbol; + uint32_t type_id, var_id; + +- vsir_register_init(®, VKD3DSPR_SAMPLER, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(®, VKD3DSPR_SAMPLER, VSIR_DATA_F32, 1); + reg.idx[0].offset = descriptor->register_id; + + vkd3d_symbol_make_sampler(®_symbol, ®); +@@ -7002,7 +7002,7 @@ static void spirv_compiler_emit_resource_declaration(struct spirv_compiler *comp + struct vkd3d_symbol resource_symbol; + struct vkd3d_shader_register reg; + +- vsir_register_init(®, is_uav ? VKD3DSPR_UAV : VKD3DSPR_RESOURCE, VKD3D_DATA_FLOAT, 1); ++ vsir_register_init(®, is_uav ? VKD3DSPR_UAV : VKD3DSPR_RESOURCE, VSIR_DATA_F32, 1); + reg.idx[0].offset = descriptor->register_id; + + if (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS && sample_count == 1) +@@ -7592,11 +7592,11 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, + VKD3D_ASSERT(src->reg.data_type == VKD3D_DATA_BOOL && dst->reg.data_type != VKD3D_DATA_BOOL); + + val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); +- if (dst->reg.data_type == VKD3D_DATA_HALF || dst->reg.data_type == VKD3D_DATA_FLOAT) ++ if (dst->reg.data_type == VSIR_DATA_F16 || dst->reg.data_type == VSIR_DATA_F32) + { + val_id = spirv_compiler_emit_bool_to_float(compiler, 1, val_id, instruction->opcode == VSIR_OP_ITOF); + } +- else if (dst->reg.data_type == VKD3D_DATA_DOUBLE) ++ else if (dst->reg.data_type == VSIR_DATA_F64) + { + /* ITOD is not supported. Frontends which emit bool casts must use ITOF for double. */ + val_id = spirv_compiler_emit_bool_to_double(compiler, 1, val_id, instruction->opcode == VSIR_OP_ITOF); +@@ -8051,7 +8051,7 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler, + type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); + + src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); +- if (src->reg.data_type == VKD3D_DATA_DOUBLE) ++ if (src->reg.data_type == VSIR_DATA_F64) + div_id = spirv_compiler_get_constant_double_vector(compiler, 1.0, component_count); + else + div_id = spirv_compiler_get_constant_float_vector(compiler, 1.0f, component_count); +@@ -8101,7 +8101,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, + + component_count = vsir_write_mask_component_count(dst->write_mask); + +- if (src->reg.data_type == VKD3D_DATA_DOUBLE) ++ if (src->reg.data_type == VSIR_DATA_F64) + { + write_mask = vkd3d_write_mask_from_component_count(component_count); + int_min_id = spirv_compiler_get_constant_double_vector(compiler, -2147483648.0, component_count); +@@ -8157,7 +8157,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, + + component_count = vsir_write_mask_component_count(dst->write_mask); + +- if (src->reg.data_type == VKD3D_DATA_DOUBLE) ++ if (src->reg.data_type == VSIR_DATA_F64) + { + write_mask = vkd3d_write_mask_from_component_count(component_count); + zero_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count); +@@ -10952,14 +10952,14 @@ static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) + + if (compiler->program->has_point_size) + { +- vsir_dst_param_init(&dst, VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); ++ vsir_dst_param_init(&dst, VKD3DSPR_RASTOUT, VSIR_DATA_F32, 1); + dst.reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; + spirv_compiler_emit_io_register(compiler, &dst); + } + + if (compiler->program->has_point_coord) + { +- vsir_dst_param_init(&dst, VKD3DSPR_POINT_COORD, VKD3D_DATA_FLOAT, 0); ++ vsir_dst_param_init(&dst, VKD3DSPR_POINT_COORD, VSIR_DATA_F32, 0); + spirv_compiler_emit_io_register(compiler, &dst); + } + +@@ -10970,7 +10970,7 @@ static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) + if (bitmap_is_set(compiler->program->io_dcls, i) + || (compiler->program->shader_version.type == VKD3D_SHADER_TYPE_HULL && i == VKD3DSPR_OUTPOINTID)) + { +- vsir_dst_param_init(&dst, i, VKD3D_DATA_FLOAT, 0); ++ vsir_dst_param_init(&dst, i, VSIR_DATA_F32, 0); + spirv_compiler_emit_io_register(compiler, &dst); + } + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index c7eafbc79f3..26c41a902d2 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -748,16 +748,16 @@ static const enum vkd3d_shader_resource_type resource_type_table[] = + /* VKD3D_SM4_RESOURCE_STRUCTURED_BUFFER */ VKD3D_SHADER_RESOURCE_BUFFER, + }; + +-static const enum vkd3d_data_type data_type_table[] = ++static const enum vsir_data_type data_type_table[] = + { +- /* 0 */ VKD3D_DATA_FLOAT, ++ /* 0 */ VSIR_DATA_F32, + /* VKD3D_SM4_DATA_UNORM */ VKD3D_DATA_UNORM, + /* VKD3D_SM4_DATA_SNORM */ VKD3D_DATA_SNORM, + /* VKD3D_SM4_DATA_INT */ VKD3D_DATA_INT, + /* VKD3D_SM4_DATA_UINT */ VKD3D_DATA_UINT, +- /* VKD3D_SM4_DATA_FLOAT */ VKD3D_DATA_FLOAT, ++ /* VKD3D_SM4_DATA_FLOAT */ VSIR_DATA_F32, + /* VKD3D_SM4_DATA_MIXED */ VKD3D_DATA_MIXED, +- /* VKD3D_SM4_DATA_DOUBLE */ VKD3D_DATA_DOUBLE, ++ /* VKD3D_SM4_DATA_DOUBLE */ VSIR_DATA_F64, + /* VKD3D_SM4_DATA_CONTINUED */ VKD3D_DATA_CONTINUED, + /* VKD3D_SM4_DATA_UNUSED */ VKD3D_DATA_UNUSED, + }; +@@ -770,9 +770,9 @@ static bool shader_is_sm_5_1(const struct vkd3d_shader_sm4_parser *sm4) + } + + static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, const uint32_t **ptr, +- const uint32_t *end, enum vkd3d_data_type data_type, struct vkd3d_shader_src_param *src_param); ++ const uint32_t *end, enum vsir_data_type data_type, struct vkd3d_shader_src_param *src_param); + static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, const uint32_t **ptr, +- const uint32_t *end, enum vkd3d_data_type data_type, struct vkd3d_shader_dst_param *dst_param); ++ const uint32_t *end, enum vsir_data_type data_type, struct vkd3d_shader_dst_param *dst_param); + + static bool shader_sm4_read_register_space(struct vkd3d_shader_sm4_parser *priv, + const uint32_t **ptr, const uint32_t *end, unsigned int *register_space) +@@ -844,7 +844,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui + return; + } + icb->register_idx = 0; +- icb->data_type = VKD3D_DATA_FLOAT; ++ icb->data_type = VSIR_DATA_F32; + icb->component_count = VKD3D_VEC4_SIZE; + icb->element_count = icb_size / VKD3D_VEC4_SIZE; + icb->is_null = false; +@@ -873,7 +873,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u + enum vkd3d_sm4_resource_type resource_type; + const uint32_t *end = &tokens[token_count]; + enum vkd3d_sm4_data_type data_type; +- enum vkd3d_data_type reg_data_type; ++ enum vsir_data_type reg_data_type; + uint32_t components; + unsigned int i; + +@@ -907,7 +907,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u + if (!data_type || (data_type >= ARRAY_SIZE(data_type_table))) + { + FIXME("Unhandled data type %#x.\n", data_type); +- semantic->resource_data_type[i] = VKD3D_DATA_FLOAT; ++ semantic->resource_data_type[i] = VSIR_DATA_F32; + } + else + { +@@ -926,7 +926,7 @@ static void shader_sm4_read_dcl_constant_buffer(struct vkd3d_shader_instruction + { + const uint32_t *end = &tokens[token_count]; + +- shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_FLOAT, &ins->declaration.cb.src); ++ shader_sm4_read_src_param(priv, &tokens, end, VSIR_DATA_F32, &ins->declaration.cb.src); + shader_sm4_set_descriptor_register_range(priv, &ins->declaration.cb.src.reg, &ins->declaration.cb.range); + if (opcode_token & VKD3D_SM4_INDEX_TYPE_MASK) + ins->flags |= VKD3DSI_INDEXED_DYNAMIC; +@@ -1142,14 +1142,14 @@ static void shader_sm4_read_declaration_count(struct vkd3d_shader_instruction *i + static void shader_sm4_read_declaration_dst(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_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, &ins->declaration.dst); ++ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VSIR_DATA_F32, &ins->declaration.dst); + } + + static void shader_sm4_read_declaration_register_semantic(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_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, +- &ins->declaration.register_semantic.reg); ++ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], ++ VSIR_DATA_F32, &ins->declaration.register_semantic.reg); + ins->declaration.register_semantic.sysval_semantic = *tokens; + } + +@@ -1159,7 +1159,7 @@ static void shader_sm4_read_dcl_input_ps(struct vkd3d_shader_instruction *ins, u + struct vkd3d_shader_dst_param *dst = &ins->declaration.dst; + + ins->flags = (opcode_token & VKD3D_SM4_INTERPOLATION_MODE_MASK) >> VKD3D_SM4_INTERPOLATION_MODE_SHIFT; +- if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, dst)) ++ if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VSIR_DATA_F32, dst)) + { + struct signature_element *e = vsir_signature_find_element_for_reg( + &priv->p.program->input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); +@@ -1185,7 +1185,7 @@ static void shader_sm4_read_dcl_input_ps_siv(struct vkd3d_shader_instruction *in + struct vkd3d_shader_dst_param *dst = &ins->declaration.register_semantic.reg; + + ins->flags = (opcode_token & VKD3D_SM4_INTERPOLATION_MODE_MASK) >> VKD3D_SM4_INTERPOLATION_MODE_SHIFT; +- if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, dst)) ++ if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VSIR_DATA_F32, dst)) + { + struct signature_element *e = vsir_signature_find_element_for_reg( + &priv->p.program->input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); +@@ -1212,7 +1212,7 @@ static void shader_sm4_read_dcl_indexable_temp(struct vkd3d_shader_instruction * + ins->declaration.indexable_temp.register_idx = *tokens++; + ins->declaration.indexable_temp.register_size = *tokens++; + ins->declaration.indexable_temp.alignment = 0; +- ins->declaration.indexable_temp.data_type = VKD3D_DATA_FLOAT; ++ ins->declaration.indexable_temp.data_type = VSIR_DATA_F32; + ins->declaration.indexable_temp.component_count = *tokens; + ins->declaration.indexable_temp.has_function_scope = false; + } +@@ -1339,7 +1339,7 @@ static void shader_sm5_read_dcl_uav_structured(struct vkd3d_shader_instruction * + static void shader_sm5_read_dcl_tgsm_raw(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_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, &ins->declaration.tgsm_raw.reg); ++ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VSIR_DATA_F32, &ins->declaration.tgsm_raw.reg); + ins->declaration.tgsm_raw.byte_count = *tokens; + if (ins->declaration.tgsm_raw.byte_count % 4) + FIXME("Byte count %u is not multiple of 4.\n", ins->declaration.tgsm_raw.byte_count); +@@ -1349,8 +1349,8 @@ static void shader_sm5_read_dcl_tgsm_raw(struct vkd3d_shader_instruction *ins, u + static void shader_sm5_read_dcl_tgsm_structured(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_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, +- &ins->declaration.tgsm_structured.reg); ++ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], ++ VSIR_DATA_F32, &ins->declaration.tgsm_structured.reg); + ins->declaration.tgsm_structured.byte_stride = *tokens++; + ins->declaration.tgsm_structured.structure_count = *tokens; + if (ins->declaration.tgsm_structured.byte_stride % 4) +@@ -1430,8 +1430,8 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + unsigned int i; + + /* +- * d -> VKD3D_DATA_DOUBLE +- * f -> VKD3D_DATA_FLOAT ++ * d -> VSIR_DATA_F64 ++ * f -> VSIR_DATA_F32 + * i -> VKD3D_DATA_INT + * u -> VKD3D_DATA_UINT + * O -> VKD3D_DATA_OPAQUE +@@ -1985,14 +1985,14 @@ static enum vkd3d_sm4_stat_field get_stat_field_from_sm4_opcode( + return field_info->field; + } + +-static enum vkd3d_data_type map_data_type(char t) ++static enum vsir_data_type map_data_type(char t) + { + switch (t) + { + case 'd': +- return VKD3D_DATA_DOUBLE; ++ return VSIR_DATA_F64; + case 'f': +- return VKD3D_DATA_FLOAT; ++ return VSIR_DATA_F32; + case 'i': + return VKD3D_DATA_INT; + case 'u': +@@ -2003,7 +2003,7 @@ static enum vkd3d_data_type map_data_type(char t) + return VKD3D_DATA_UNUSED; + default: + ERR("Invalid data type '%c'.\n", t); +- return VKD3D_DATA_FLOAT; ++ return VSIR_DATA_F32; + } + } + +@@ -2036,7 +2036,7 @@ static bool shader_sm4_read_reg_idx(struct vkd3d_shader_sm4_parser *priv, const + } + + static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const uint32_t **ptr, const uint32_t *end, +- enum vkd3d_data_type data_type, struct vkd3d_shader_register *param, enum vkd3d_shader_src_modifier *modifier) ++ enum vsir_data_type data_type, struct vkd3d_shader_register *param, enum vkd3d_shader_src_modifier *modifier) + { + const struct vkd3d_sm4_register_type_info *register_type_info; + enum vkd3d_shader_register_type vsir_register_type; +@@ -2237,12 +2237,10 @@ bool shader_sm4_is_scalar_register(const struct vkd3d_shader_register *reg) + { + switch (reg->type) + { +- case VKD3DSPR_COVERAGE: + case VKD3DSPR_DEPTHOUT: + case VKD3DSPR_DEPTHOUTGE: + case VKD3DSPR_DEPTHOUTLE: + case VKD3DSPR_GSINSTID: +- case VKD3DSPR_LOCALTHREADINDEX: + case VKD3DSPR_OUTPOINTID: + case VKD3DSPR_PRIMID: + case VKD3DSPR_SAMPLEMASK: +@@ -2354,7 +2352,7 @@ static bool shader_sm4_validate_input_output_register(struct vkd3d_shader_sm4_pa + } + + static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, const uint32_t **ptr, +- const uint32_t *end, enum vkd3d_data_type data_type, struct vkd3d_shader_src_param *src_param) ++ const uint32_t *end, enum vsir_data_type data_type, struct vkd3d_shader_src_param *src_param) + { + unsigned int dimension, mask; + uint32_t token; +@@ -2442,7 +2440,7 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons + } + + static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, const uint32_t **ptr, +- const uint32_t *end, enum vkd3d_data_type data_type, struct vkd3d_shader_dst_param *dst_param) ++ const uint32_t *end, enum vsir_data_type data_type, struct vkd3d_shader_dst_param *dst_param) + { + enum vkd3d_sm4_swizzle_type swizzle_type; + enum vkd3d_shader_src_modifier modifier; +@@ -2512,7 +2510,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons + break; + } + +- if (data_type == VKD3D_DATA_DOUBLE) ++ if (data_type == VSIR_DATA_F64) + 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)) +@@ -2573,7 +2571,7 @@ static void shader_sm4_read_instruction_modifier(uint32_t modifier, struct vkd3d + if (!data_type || (data_type >= ARRAY_SIZE(data_type_table))) + { + FIXME("Unhandled data type %#x.\n", data_type); +- ins->resource_data_type[i] = VKD3D_DATA_FLOAT; ++ ins->resource_data_type[i] = VSIR_DATA_F32; + } + else + { +@@ -2683,10 +2681,10 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str + } + ins->resource_type = VKD3D_SHADER_RESOURCE_NONE; + ins->resource_stride = 0; +- ins->resource_data_type[0] = VKD3D_DATA_FLOAT; +- ins->resource_data_type[1] = VKD3D_DATA_FLOAT; +- ins->resource_data_type[2] = VKD3D_DATA_FLOAT; +- ins->resource_data_type[3] = VKD3D_DATA_FLOAT; ++ ins->resource_data_type[0] = VSIR_DATA_F32; ++ ins->resource_data_type[1] = VSIR_DATA_F32; ++ ins->resource_data_type[2] = VSIR_DATA_F32; ++ ins->resource_data_type[3] = VSIR_DATA_F32; + memset(&ins->texel_offset, 0, sizeof(ins->texel_offset)); + + p = *ptr; +@@ -3838,7 +3836,7 @@ static void tpf_dcl_sampler(const struct tpf_compiler *tpf, const struct vkd3d_s + write_sm4_instruction(tpf, &instr); + } + +-static uint32_t pack_resource_data_type(const enum vkd3d_data_type *resource_data_type) ++static uint32_t pack_resource_data_type(const enum vsir_data_type *resource_data_type) + { + unsigned int i, k, type = 0; + +@@ -4503,6 +4501,9 @@ int tpf_compile(struct vsir_program *program, uint64_t config_flags, const struc + if ((ret = vsir_allocate_temp_registers(program, message_context))) + return ret; + ++ if ((ret = vsir_update_dcl_temps(program, message_context))) ++ return ret; ++ + tpf.program = program; + tpf.buffer = NULL; + tpf.stat = &stat; +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index 4cda8493696..c60feec4aa2 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -1084,7 +1084,7 @@ static void vkd3d_shader_scan_record_uav_atomic_op(struct vkd3d_shader_scan_cont + static struct vkd3d_shader_descriptor_info1 *vkd3d_shader_scan_add_descriptor(struct vkd3d_shader_scan_context *context, + enum vkd3d_shader_descriptor_type type, const struct vkd3d_shader_register *reg, + const struct vkd3d_shader_register_range *range, enum vkd3d_shader_resource_type resource_type, +- enum vkd3d_data_type resource_data_type) ++ enum vsir_data_type resource_data_type) + { + struct vkd3d_shader_scan_descriptor_info1 *info = context->scan_descriptor_info; + struct vkd3d_shader_descriptor_info1 *d; +@@ -1145,7 +1145,7 @@ static void vkd3d_shader_scan_combined_sampler_declaration( + vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, &semantic->resource.reg.reg, + &semantic->resource.range, VKD3D_SHADER_RESOURCE_NONE, VKD3D_DATA_UNUSED); + vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, &semantic->resource.reg.reg, +- &semantic->resource.range, semantic->resource_type, VKD3D_DATA_FLOAT); ++ &semantic->resource.range, semantic->resource_type, VSIR_DATA_F32); + } + + const struct vkd3d_shader_descriptor_info1 *vkd3d_shader_find_descriptor( +@@ -1235,7 +1235,7 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co + + static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_context *context, + const struct vkd3d_shader_resource *resource, enum vkd3d_shader_resource_type resource_type, +- enum vkd3d_data_type resource_data_type, unsigned int sample_count, ++ enum vsir_data_type resource_data_type, unsigned int sample_count, + unsigned int structure_stride, bool raw, uint32_t flags) + { + struct vkd3d_shader_descriptor_info1 *d; +@@ -1522,7 +1522,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte + return VKD3D_OK; + } + +-static enum vkd3d_shader_resource_data_type vkd3d_resource_data_type_from_data_type(enum vkd3d_data_type data_type) ++static enum vkd3d_shader_resource_data_type vkd3d_resource_data_type_from_data_type(enum vsir_data_type data_type) + { + switch (data_type) + { +@@ -1534,16 +1534,16 @@ static enum vkd3d_shader_resource_data_type vkd3d_resource_data_type_from_data_t + return VKD3D_SHADER_RESOURCE_DATA_INT; + case VKD3D_DATA_UINT: + return VKD3D_SHADER_RESOURCE_DATA_UINT; +- case VKD3D_DATA_FLOAT: +- return VKD3D_SHADER_RESOURCE_DATA_FLOAT; + case VKD3D_DATA_MIXED: + return VKD3D_SHADER_RESOURCE_DATA_MIXED; +- case VKD3D_DATA_DOUBLE: +- return VKD3D_SHADER_RESOURCE_DATA_DOUBLE; + case VKD3D_DATA_CONTINUED: + return VKD3D_SHADER_RESOURCE_DATA_CONTINUED; + case VKD3D_DATA_UNUSED: + return VKD3D_SHADER_RESOURCE_DATA_NONE; ++ case VSIR_DATA_F32: ++ return VKD3D_SHADER_RESOURCE_DATA_FLOAT; ++ case VSIR_DATA_F64: ++ return VKD3D_SHADER_RESOURCE_DATA_DOUBLE; + default: + ERR("Invalid resource data type %#x.\n", data_type); + return VKD3D_SHADER_RESOURCE_DATA_FLOAT; +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 978af0a2d17..f7bbadac3df 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -184,6 +184,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_WARNING_HLSL_IGNORED_ATTRIBUTE = 5305, + VKD3D_SHADER_WARNING_HLSL_IGNORED_DEFAULT_VALUE = 5306, + VKD3D_SHADER_WARNING_HLSL_IGNORED_MODIFIER = 5307, ++ VKD3D_SHADER_WARNING_HLSL_OVERRIDDEN_SEMANTIC = 5308, + + VKD3D_SHADER_ERROR_GLSL_INTERNAL = 6000, + VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND = 6001, +@@ -707,46 +708,47 @@ enum vkd3d_shader_register_precision + VKD3D_SHADER_REGISTER_PRECISION_INVALID = ~0u, + }; + +-enum vkd3d_data_type ++enum vsir_data_type + { +- VKD3D_DATA_FLOAT, + VKD3D_DATA_INT, + VKD3D_DATA_UINT, + VKD3D_DATA_UNORM, + VKD3D_DATA_SNORM, + VKD3D_DATA_OPAQUE, + VKD3D_DATA_MIXED, +- VKD3D_DATA_DOUBLE, + VKD3D_DATA_CONTINUED, + VKD3D_DATA_UNUSED, + VKD3D_DATA_UINT8, + VKD3D_DATA_UINT64, + VKD3D_DATA_BOOL, + VKD3D_DATA_UINT16, +- VKD3D_DATA_HALF, + +- VKD3D_DATA_COUNT, ++ VSIR_DATA_F16, ++ VSIR_DATA_F32, ++ VSIR_DATA_F64, ++ ++ VSIR_DATA_TYPE_COUNT, + }; + +-static inline bool data_type_is_integer(enum vkd3d_data_type data_type) ++static inline bool data_type_is_integer(enum vsir_data_type data_type) + { + return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT16 + || data_type == VKD3D_DATA_UINT || data_type == VKD3D_DATA_UINT64; + } + +-static inline bool data_type_is_bool(enum vkd3d_data_type data_type) ++static inline bool data_type_is_bool(enum vsir_data_type data_type) + { + return data_type == VKD3D_DATA_BOOL; + } + +-static inline bool data_type_is_floating_point(enum vkd3d_data_type data_type) ++static inline bool data_type_is_floating_point(enum vsir_data_type data_type) + { +- return data_type == VKD3D_DATA_HALF || data_type == VKD3D_DATA_FLOAT || data_type == VKD3D_DATA_DOUBLE; ++ return data_type == VSIR_DATA_F16 || data_type == VSIR_DATA_F32 || data_type == VSIR_DATA_F64; + } + +-static inline bool data_type_is_64_bit(enum vkd3d_data_type data_type) ++static inline bool data_type_is_64_bit(enum vsir_data_type data_type) + { +- return data_type == VKD3D_DATA_DOUBLE || data_type == VKD3D_DATA_UINT64; ++ return data_type == VSIR_DATA_F64 || data_type == VKD3D_DATA_UINT64; + } + + enum vsir_dimension +@@ -941,7 +943,7 @@ struct vkd3d_shader_version + struct vkd3d_shader_immediate_constant_buffer + { + unsigned int register_idx; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + /* total count is element_count * component_count */ + unsigned int element_count; + unsigned int component_count; +@@ -954,7 +956,7 @@ struct vkd3d_shader_indexable_temp + unsigned int register_idx; + unsigned int register_size; + unsigned int alignment; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + unsigned int component_count; + bool has_function_scope; + const struct vkd3d_shader_immediate_constant_buffer *initialiser; +@@ -973,7 +975,7 @@ struct vkd3d_shader_register + enum vkd3d_shader_register_type type; + enum vkd3d_shader_register_precision precision; + bool non_uniform; +- enum vkd3d_data_type data_type; ++ enum vsir_data_type data_type; + struct vkd3d_shader_register_index idx[3]; + unsigned int idx_count; + enum vsir_dimension dimension; +@@ -990,7 +992,7 @@ struct vkd3d_shader_register + }; + + void vsir_register_init(struct vkd3d_shader_register *reg, enum vkd3d_shader_register_type reg_type, +- enum vkd3d_data_type data_type, unsigned int idx_count); ++ enum vsir_data_type data_type, unsigned int idx_count); + + static inline bool vsir_register_is_descriptor(const struct vkd3d_shader_register *reg) + { +@@ -1023,9 +1025,9 @@ struct vkd3d_shader_src_param + }; + + 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); ++ enum vsir_data_type data_type, unsigned int idx_count); + void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, +- enum vkd3d_data_type data_type, unsigned int idx_count); ++ enum vsir_data_type data_type, unsigned int idx_count); + void vsir_dst_param_init_null(struct vkd3d_shader_dst_param *dst); + void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id); + +@@ -1071,7 +1073,7 @@ struct vkd3d_shader_semantic + unsigned int usage_idx; + enum vkd3d_shader_resource_type resource_type; + unsigned int sample_count; +- enum vkd3d_data_type resource_data_type[VKD3D_VEC4_SIZE]; ++ enum vsir_data_type resource_data_type[VKD3D_VEC4_SIZE]; + struct vkd3d_shader_resource resource; + }; + +@@ -1284,7 +1286,7 @@ struct vkd3d_shader_instruction + struct vkd3d_shader_texel_offset texel_offset; + enum vkd3d_shader_resource_type resource_type; + unsigned int resource_stride; +- enum vkd3d_data_type resource_data_type[VKD3D_VEC4_SIZE]; ++ enum vsir_data_type resource_data_type[VKD3D_VEC4_SIZE]; + bool coissue, structured, raw; + const struct vkd3d_shader_src_param *predicate; + union +@@ -1419,6 +1421,51 @@ bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_ + unsigned int dst, unsigned int src); + void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions); + ++struct vsir_program_iterator ++{ ++ struct vkd3d_shader_instruction_array *array; ++ size_t idx; ++}; ++ ++static inline struct vsir_program_iterator vsir_program_iterator(struct vkd3d_shader_instruction_array *array) ++{ ++ return (struct vsir_program_iterator){ .array = array }; ++} ++ ++static inline struct vkd3d_shader_instruction *vsir_program_iterator_current( ++ struct vsir_program_iterator *iterator) ++{ ++ if (iterator->idx >= iterator->array->count) ++ return NULL; ++ ++ return &iterator->array->elements[iterator->idx]; ++} ++ ++static inline struct vkd3d_shader_instruction *vsir_program_iterator_head( ++ struct vsir_program_iterator *iterator) ++{ ++ iterator->idx = 0; ++ ++ return vsir_program_iterator_current(iterator); ++} ++ ++static inline struct vkd3d_shader_instruction *vsir_program_iterator_next( ++ struct vsir_program_iterator *iterator) ++{ ++ if (iterator->idx < iterator->array->count) ++ ++iterator->idx; ++ ++ return vsir_program_iterator_current(iterator); ++} ++ ++/* When insertion takes place, argument `it' is updated to point to the same ++ * instruction as before the insertion, but all other iterators and pointers ++ * to the same container are invalidated and cannot be used any more. */ ++static inline bool vsir_program_iterator_insert_after(struct vsir_program_iterator *it, unsigned int count) ++{ ++ return shader_instruction_array_insert_at(it->array, it->idx + 1, count); ++} ++ + enum vkd3d_shader_config_flags + { + VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION = 0x00000001, +@@ -1445,7 +1492,7 @@ struct vkd3d_shader_descriptor_info1 + unsigned int register_index; + unsigned int register_id; + enum vkd3d_shader_resource_type resource_type; +- enum vkd3d_data_type resource_data_type; ++ enum vsir_data_type resource_data_type; + unsigned int flags; + unsigned int sample_count; + unsigned int buffer_size; +@@ -1511,6 +1558,8 @@ struct vsir_program + + enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, + struct vkd3d_shader_message_context *message_context); ++enum vkd3d_result vsir_update_dcl_temps(struct vsir_program *program, ++ struct vkd3d_shader_message_context *message_context); + void vsir_program_cleanup(struct vsir_program *program); + int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, +@@ -1739,23 +1788,22 @@ 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); + +-static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type( +- enum vkd3d_data_type data_type) ++static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type( enum vsir_data_type data_type) + { + switch (data_type) + { +- case VKD3D_DATA_HALF: /* Minimum precision. TODO: native 16-bit */ +- case VKD3D_DATA_FLOAT: ++ case VSIR_DATA_F16: /* Minimum precision. TODO: native 16-bit */ ++ case VSIR_DATA_F32: + case VKD3D_DATA_UNORM: + case VKD3D_DATA_SNORM: + return VKD3D_SHADER_COMPONENT_FLOAT; ++ case VSIR_DATA_F64: ++ return VKD3D_SHADER_COMPONENT_DOUBLE; + case VKD3D_DATA_UINT16: /* Minimum precision. TODO: native 16-bit */ + case VKD3D_DATA_UINT: + return VKD3D_SHADER_COMPONENT_UINT; + case VKD3D_DATA_INT: + 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: +@@ -1768,22 +1816,21 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty + } + } + +-static inline enum vkd3d_data_type vkd3d_data_type_from_component_type( +- enum vkd3d_shader_component_type component_type) ++static inline enum vsir_data_type vsir_data_type_from_component_type(enum vkd3d_shader_component_type component_type) + { + switch (component_type) + { + case VKD3D_SHADER_COMPONENT_FLOAT: +- return VKD3D_DATA_FLOAT; ++ return VSIR_DATA_F32; + case VKD3D_SHADER_COMPONENT_UINT: + return VKD3D_DATA_UINT; + case VKD3D_SHADER_COMPONENT_INT: + return VKD3D_DATA_INT; + case VKD3D_SHADER_COMPONENT_DOUBLE: +- return VKD3D_DATA_DOUBLE; ++ return VSIR_DATA_F64; + default: + FIXME("Unhandled component type %#x.\n", component_type); +- return VKD3D_DATA_FLOAT; ++ return VSIR_DATA_F32; + } + } + +-- +2.47.2 + diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-68cd72c7fc7a364ecce87a19617acb382c7.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-68cd72c7fc7a364ecce87a19617acb382c7.patch new file mode 100644 index 00000000..ff662e92 --- /dev/null +++ b/patches/vkd3d-latest/0004-Updated-vkd3d-to-68cd72c7fc7a364ecce87a19617acb382c7.patch @@ -0,0 +1,1701 @@ +From bde94d21a682ec4cd30860b2bd293bb158910006 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Wed, 23 Jul 2025 07:16:58 +1000 +Subject: [PATCH] Updated vkd3d to 68cd72c7fc7a364ecce87a19617acb382c70762f. + +--- + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 33 ++--- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 21 ++-- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 60 ++++----- + libs/vkd3d/libs/vkd3d-shader/glsl.c | 54 ++++---- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 22 ++-- + libs/vkd3d/libs/vkd3d-shader/ir.c | 116 ++++++++---------- + libs/vkd3d/libs/vkd3d-shader/msl.c | 43 +++---- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 63 +++++----- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 44 ++++--- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 18 +-- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 46 ++++--- + 11 files changed, 260 insertions(+), 260 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +index 7d10cf98f71..5e3e7daab83 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +@@ -388,21 +388,21 @@ static void shader_print_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum + { + static const char *const data_type_names[] = + { +- [VKD3D_DATA_INT ] = "int", +- [VKD3D_DATA_UINT ] = "uint", + [VKD3D_DATA_UNORM ] = "unorm", + [VKD3D_DATA_SNORM ] = "snorm", + [VKD3D_DATA_OPAQUE ] = "opaque", + [VKD3D_DATA_MIXED ] = "mixed", + [VKD3D_DATA_CONTINUED] = "", + [VKD3D_DATA_UNUSED ] = "", +- [VKD3D_DATA_UINT8 ] = "uint8", +- [VKD3D_DATA_UINT64 ] = "uint64", + [VKD3D_DATA_BOOL ] = "bool", +- [VKD3D_DATA_UINT16 ] = "uint16", + [VSIR_DATA_F16 ] = "half", + [VSIR_DATA_F32 ] = "float", + [VSIR_DATA_F64 ] = "double", ++ [VSIR_DATA_I32 ] = "int", ++ [VSIR_DATA_U8 ] = "uint8", ++ [VSIR_DATA_U16 ] = "uint16", ++ [VSIR_DATA_U32 ] = "uint", ++ [VSIR_DATA_U64 ] = "uint64", + }; + + if (type < ARRAY_SIZE(data_type_names)) +@@ -736,10 +736,10 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const + else + shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); + break; +- case VKD3D_DATA_INT: ++ case VSIR_DATA_I32: + shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); + break; +- case VKD3D_DATA_UINT: ++ case VSIR_DATA_U32: + shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); + break; + default: +@@ -768,13 +768,13 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const + shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[3], ""); + } + break; +- case VKD3D_DATA_INT: ++ case VSIR_DATA_I32: + 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_UINT: ++ case VSIR_DATA_U32: + 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], ""); +@@ -806,7 +806,7 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const + if (reg->dimension == VSIR_DIMENSION_VEC4) + shader_print_double_literal(compiler, ", ", reg->u.immconst_f64[1], ""); + } +- else if (reg->data_type == VKD3D_DATA_UINT64) ++ else if (reg->data_type == VSIR_DATA_U64) + { + shader_print_uint64_literal(compiler, "", reg->u.immconst_u64[0], ""); + if (reg->dimension == VSIR_DIMENSION_VEC4) +@@ -1951,8 +1951,7 @@ static void shader_print_descriptors(struct vkd3d_d3d_asm_compiler *compiler, + } + } + +-enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, +- const struct vkd3d_shader_compile_info *compile_info, ++enum vkd3d_result d3d_asm_compile(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_code *out, enum vsir_asm_flags flags) + { + const struct vkd3d_shader_version *shader_version = &program->shader_version; +@@ -1961,8 +1960,10 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, + { + .flags = flags, + }; ++ struct vkd3d_shader_instruction *ins; + enum vkd3d_result result = VKD3D_OK; + struct vkd3d_string_buffer *buffer; ++ struct vsir_program_iterator it; + unsigned int indent, i, j; + const char *indent_str; + +@@ -2042,10 +2043,10 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, + vkd3d_string_buffer_printf(buffer, "%s.text%s\n", compiler.colours.opcode, compiler.colours.reset); + + indent = 0; +- for (i = 0; i < program->instructions.count; ++i) +- { +- struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; + ++ it = vsir_program_iterator(&program->instructions); ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) ++ { + switch (ins->opcode) + { + case VSIR_OP_ELSE: +@@ -2236,7 +2237,7 @@ static void trace_io_declarations(const struct vsir_program *program) + vkd3d_string_buffer_cleanup(&buffer); + } + +-void vsir_program_trace(const struct vsir_program *program) ++void vsir_program_trace(struct vsir_program *program) + { + const unsigned int flags = VSIR_ASM_FLAG_DUMP_TYPES | VSIR_ASM_FLAG_DUMP_ALL_INDICES + | VSIR_ASM_FLAG_DUMP_SIGNATURES | VSIR_ASM_FLAG_DUMP_DESCRIPTORS; +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index 2dd9c731010..49e1a529369 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -1301,13 +1301,13 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str + else if (ins->opcode == VSIR_OP_DEFB) + { + shader_sm1_read_dst_param(sm1, &p, dst_param); +- shader_sm1_read_immconst(sm1, &p, &src_params[0], VSIR_DIMENSION_SCALAR, VKD3D_DATA_UINT); ++ shader_sm1_read_immconst(sm1, &p, &src_params[0], VSIR_DIMENSION_SCALAR, VSIR_DATA_U32); + shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask, true); + } + else if (ins->opcode == VSIR_OP_DEFI) + { + shader_sm1_read_dst_param(sm1, &p, dst_param); +- shader_sm1_read_immconst(sm1, &p, &src_params[0], VSIR_DIMENSION_VEC4, VKD3D_DATA_INT); ++ shader_sm1_read_immconst(sm1, &p, &src_params[0], VSIR_DIMENSION_VEC4, VSIR_DATA_I32); + shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask, true); + } + else if (ins->opcode == VSIR_OP_TEXKILL) +@@ -1472,7 +1472,6 @@ static uint32_t get_external_constant_count(struct vkd3d_shader_sm1_parser *sm1, + int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags, + struct vkd3d_shader_message_context *message_context, struct vsir_program *program) + { +- struct vkd3d_shader_instruction_array *instructions; + struct vkd3d_shader_sm1_parser sm1 = {0}; + struct vkd3d_shader_instruction *ins; + unsigned int i; +@@ -1484,17 +1483,14 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c + return ret; + } + +- instructions = &program->instructions; + while (!shader_sm1_is_end(&sm1)) + { +- if (!shader_instruction_array_reserve(instructions, instructions->count + 1)) ++ if (!(ins = vsir_program_append(program))) + { +- ERR("Failed to allocate instructions.\n"); + vkd3d_shader_parser_error(&sm1.p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory."); + vsir_program_cleanup(program); + return VKD3D_ERROR_OUT_OF_MEMORY; + } +- ins = &instructions->elements[instructions->count]; + shader_sm1_read_instruction(&sm1, ins); + + if (ins->opcode == VSIR_OP_INVALID) +@@ -1503,7 +1499,6 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c + vsir_program_cleanup(program); + return VKD3D_ERROR_INVALID_SHADER; + } +- ++instructions->count; + } + + for (i = 0; i < ARRAY_SIZE(program->flat_constant_count); ++i) +@@ -2128,11 +2123,13 @@ static void d3dbc_write_semantic_dcls(struct d3dbc_compiler *d3dbc) + + static void d3dbc_write_program_instructions(struct d3dbc_compiler *d3dbc) + { +- struct vsir_program *program = d3dbc->program; +- unsigned int i; ++ struct vsir_program_iterator it = vsir_program_iterator(&d3dbc->program->instructions); ++ struct vkd3d_shader_instruction *ins; + +- for (i = 0; i < program->instructions.count; ++i) +- d3dbc_write_vsir_instruction(d3dbc, &program->instructions.elements[i]); ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) ++ { ++ d3dbc_write_vsir_instruction(d3dbc, ins); ++ } + } + + int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index f8f0d2543bd..c3dd606f00f 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -2482,16 +2482,16 @@ static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type) + case 1: + return VKD3D_DATA_BOOL; + case 8: +- return VKD3D_DATA_UINT8; ++ return VSIR_DATA_U8; + case 16: +- return VKD3D_DATA_UINT16; ++ return VSIR_DATA_U16; + case 32: +- return VKD3D_DATA_UINT; ++ return VSIR_DATA_U32; + case 64: +- return VKD3D_DATA_UINT64; ++ return VSIR_DATA_U64; + default: + FIXME("Unhandled width %u.\n", type->u.width); +- return VKD3D_DATA_UINT; ++ return VSIR_DATA_U32; + } + } + else if (type->class == TYPE_CLASS_FLOAT) +@@ -2511,7 +2511,7 @@ static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type) + } + + FIXME("Unhandled type %u.\n", type->class); +- return VKD3D_DATA_UINT; ++ return VSIR_DATA_U32; + } + + /* Based on the implementation in the OpenGL Mathematics library. */ +@@ -2572,8 +2572,8 @@ static void register_convert_to_minimum_precision(struct vkd3d_shader_register * + } + break; + +- case VKD3D_DATA_UINT16: +- reg->data_type = VKD3D_DATA_UINT; ++ case VSIR_DATA_U16: ++ reg->data_type = VSIR_DATA_U32; + reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_UINT_16; + if (reg->type == VKD3DSPR_IMMCONST) + { +@@ -2668,7 +2668,7 @@ static void sm6_parser_init_ssa_value(struct sm6_parser *sm6, struct sm6_value * + + static void register_make_constant_uint(struct vkd3d_shader_register *reg, unsigned int value) + { +- vsir_register_init(reg, VKD3DSPR_IMMCONST, VKD3D_DATA_UINT, 0); ++ vsir_register_init(reg, VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); + reg->u.immconst_u32[0] = value; + } + +@@ -2815,7 +2815,7 @@ static bool instruction_dst_param_init_uint_temp_vector(struct vkd3d_shader_inst + if (!(param = instruction_dst_params_alloc(ins, 1, sm6))) + return false; + +- vsir_dst_param_init(param, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_dst_param_init(param, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + param->write_mask = VKD3DSP_WRITEMASK_ALL; + param->reg.idx[0].offset = 0; + param->reg.dimension = VSIR_DIMENSION_VEC4; +@@ -3254,20 +3254,20 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co + icb->data_type = VSIR_DATA_F32; + break; + +- case VKD3D_DATA_UINT16: ++ case VSIR_DATA_U16: + for (i = 0; i < count; ++i) + icb->data[i] = (int16_t)operands[i]; +- icb->data_type = VKD3D_DATA_UINT; ++ icb->data_type = VSIR_DATA_U32; + break; + + case VSIR_DATA_F32: +- case VKD3D_DATA_UINT: ++ case VSIR_DATA_U32: + for (i = 0; i < count; ++i) + icb->data[i] = operands[i]; + break; + + case VSIR_DATA_F64: +- case VKD3D_DATA_UINT64: ++ case VSIR_DATA_U64: + data64 = (uint64_t *)icb->data; + for (i = 0; i < count; ++i) + data64[i] = operands[i]; +@@ -4104,6 +4104,7 @@ static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( + case VKD3D_SHADER_SV_SAMPLE_INDEX: + return VKD3DSPR_NULL; + case VKD3D_SHADER_SV_COVERAGE: ++ *dimension = is_input ? VSIR_DIMENSION_VEC4 : VSIR_DIMENSION_SCALAR; + return is_input ? VKD3DSPR_COVERAGE : VKD3DSPR_SAMPLEMASK; + case VKD3D_SHADER_SV_DEPTH: + *dimension = VSIR_DIMENSION_SCALAR; +@@ -5223,7 +5224,7 @@ static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, struct + static void sm6_parser_emit_dx_coverage(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_COVERAGE, VKD3D_DATA_UINT, false); ++ sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_COVERAGE, VSIR_DATA_U32, false); + } + + static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_parser *sm6, +@@ -5300,8 +5301,7 @@ static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_ + "Output stream index %u is invalid.", i); + } + +- /* VKD3D_DATA_UNUSED would be more reasonable, but TPF uses data type 0 here. */ +- register_init_with_id(&src_param->reg, VKD3DSPR_STREAM, 0, i); ++ register_init_with_id(&src_param->reg, VKD3DSPR_STREAM, VKD3D_DATA_UNUSED, i); + src_param_init(src_param); + + if (op == DX_EMIT_THEN_CUT_STREAM) +@@ -5482,11 +5482,11 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i + vkd3d_unreachable(); + } + +- sm6_parser_dcl_register_builtin(sm6, VSIR_OP_DCL_INPUT, reg_type, VKD3D_DATA_UINT, component_count); ++ sm6_parser_dcl_register_builtin(sm6, VSIR_OP_DCL_INPUT, reg_type, VSIR_DATA_U32, component_count); + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; +- vsir_register_init(&src_param->reg, reg_type, VKD3D_DATA_UINT, 0); ++ vsir_register_init(&src_param->reg, reg_type, VSIR_DATA_U32, 0); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + if (component_count > 1) + component_idx = sm6_value_get_constant_uint(operands[0], sm6); +@@ -5721,13 +5721,13 @@ static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intri + static void sm6_parser_emit_dx_output_control_point_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_OUTPOINTID, VKD3D_DATA_UINT, true); ++ sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_OUTPOINTID, VSIR_DATA_U32, true); + } + + static void sm6_parser_emit_dx_primitive_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_PRIMID, VKD3D_DATA_UINT, true); ++ sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_PRIMID, VSIR_DATA_U32, true); + } + + static enum vkd3d_shader_opcode dx_map_quad_op(enum dxil_quad_op_kind op) +@@ -5875,7 +5875,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ + if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) + return; + src_params_init_from_operands(src_params, &operands[1], operand_count - 1, sm6); +- data.data_type = VKD3D_DATA_UINT; ++ data.data_type = VSIR_DATA_U32; + src_param_init_vector_from_reg(&src_params[operand_count - 1], &data); + + dst_param = instruction_dst_params_alloc(ins, 1, sm6); +@@ -6543,7 +6543,7 @@ static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *sm6, enum dx_intr + vkd3d_unreachable(); + } + +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, type, VKD3D_DATA_UINT, true); ++ sm6_parser_emit_dx_input_register_mov(sm6, state->ins, type, VSIR_DATA_U32, true); + } + + struct sm6_dx_opcode_info +@@ -8441,9 +8441,9 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ + continue; + } + +- if (src_params[0].reg.data_type == VKD3D_DATA_UINT64) ++ if (src_params[0].reg.data_type == VSIR_DATA_U64) + { +- vsir_src_param_init(&src_params[count], VKD3DSPR_IMMCONST64, VKD3D_DATA_UINT64, 0); ++ vsir_src_param_init(&src_params[count], VKD3DSPR_IMMCONST64, VSIR_DATA_U64, 0); + src_params[count++].reg.u.immconst_u64[0] = switch_case->value; + } + else +@@ -8454,7 +8454,7 @@ static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_ + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "Truncating 64-bit switch case value %"PRIx64" to 32 bits.", switch_case->value); + } +- vsir_src_param_init(&src_params[count], VKD3DSPR_IMMCONST, VKD3D_DATA_UINT, 0); ++ vsir_src_param_init(&src_params[count], VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); + src_params[count++].reg.u.immconst_u32[0] = switch_case->value; + } + vsir_src_param_init_label(&src_params[count++], case_block->id); +@@ -9043,10 +9043,10 @@ static const enum vsir_data_type data_type_table[] = + { + [COMPONENT_TYPE_INVALID] = VKD3D_DATA_UNUSED, + [COMPONENT_TYPE_I1] = VKD3D_DATA_UNUSED, +- [COMPONENT_TYPE_I16] = VKD3D_DATA_INT, +- [COMPONENT_TYPE_U16] = VKD3D_DATA_UINT, +- [COMPONENT_TYPE_I32] = VKD3D_DATA_INT, +- [COMPONENT_TYPE_U32] = VKD3D_DATA_UINT, ++ [COMPONENT_TYPE_I16] = VSIR_DATA_I32, ++ [COMPONENT_TYPE_U16] = VSIR_DATA_U32, ++ [COMPONENT_TYPE_I32] = VSIR_DATA_I32, ++ [COMPONENT_TYPE_U32] = VSIR_DATA_U32, + [COMPONENT_TYPE_I64] = VKD3D_DATA_UNUSED, + [COMPONENT_TYPE_U64] = VKD3D_DATA_UNUSED, + [COMPONENT_TYPE_F16] = VSIR_DATA_F32, +diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c +index bf407f0fc9c..dc68e1792d9 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c +@@ -345,10 +345,10 @@ static void shader_glsl_print_bitcast(struct vkd3d_string_buffer *dst, struct vk + { + switch (dst_data_type) + { +- case VKD3D_DATA_INT: ++ case VSIR_DATA_I32: + vkd3d_string_buffer_printf(dst, "floatBitsToInt(%s)", src); + return; +- case VKD3D_DATA_UINT: ++ case VSIR_DATA_U32: + vkd3d_string_buffer_printf(dst, "floatBitsToUint(%s)", src); + return; + default: +@@ -356,14 +356,14 @@ static void shader_glsl_print_bitcast(struct vkd3d_string_buffer *dst, struct vk + } + } + +- if (src_data_type == VKD3D_DATA_UINT) ++ if (src_data_type == VSIR_DATA_U32) + { + switch (dst_data_type) + { + case VSIR_DATA_F32: + vkd3d_string_buffer_printf(dst, "uintBitsToFloat(%s)", src); + return; +- case VKD3D_DATA_INT: ++ case VSIR_DATA_I32: + if (size == 1) + vkd3d_string_buffer_printf(dst, "int(%s)", src); + else +@@ -395,7 +395,7 @@ static void shader_glsl_print_src(struct vkd3d_string_buffer *buffer, struct vkd + "Internal compiler error: Unhandled 'non-uniform' modifier."); + + if (reg->type == VKD3DSPR_IMMCONST || reg->type == VKD3DSPR_THREADID) +- src_data_type = VKD3D_DATA_UINT; ++ src_data_type = VSIR_DATA_U32; + else + src_data_type = VSIR_DATA_F32; + +@@ -522,10 +522,10 @@ static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_g + case VSIR_DATA_F32: + close = false; + break; +- case VKD3D_DATA_INT: ++ case VSIR_DATA_I32: + vkd3d_string_buffer_printf(buffer, "intBitsToFloat("); + break; +- case VKD3D_DATA_UINT: ++ case VSIR_DATA_U32: + vkd3d_string_buffer_printf(buffer, "uintBitsToFloat("); + break; + } +@@ -1164,12 +1164,12 @@ static void shader_glsl_store_uav_typed(struct vkd3d_glsl_generator *gen, const + { + switch (data_type) + { +- case VKD3D_DATA_UINT: +- vkd3d_string_buffer_printf(image_data, "uvec4("); +- break; +- case VKD3D_DATA_INT: ++ case VSIR_DATA_I32: + vkd3d_string_buffer_printf(image_data, "ivec4("); + break; ++ case VSIR_DATA_U32: ++ vkd3d_string_buffer_printf(image_data, "uvec4("); ++ break; + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled data type %#x.", data_type); +@@ -1766,14 +1766,14 @@ static void shader_glsl_generate_uav_declaration(struct vkd3d_glsl_generator *ge + + switch (uav->resource_data_type) + { +- case VKD3D_DATA_UINT: +- image_type_prefix = "u"; +- read_format = "r32ui"; +- break; +- case VKD3D_DATA_INT: ++ case VSIR_DATA_I32: + image_type_prefix = "i"; + read_format = "r32i"; + break; ++ case VSIR_DATA_U32: ++ image_type_prefix = "u"; ++ read_format = "r32ui"; ++ break; + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled data type %#x for UAV %u.", +@@ -1995,17 +1995,17 @@ static void shader_glsl_generate_sampler_declaration(struct vkd3d_glsl_generator + + switch (srv->resource_data_type) + { +- case VKD3D_DATA_UINT: +- sampler_type_prefix = "u"; +- break; +- case VKD3D_DATA_INT: +- sampler_type_prefix = "i"; +- break; + case VSIR_DATA_F32: + case VKD3D_DATA_UNORM: + case VKD3D_DATA_SNORM: + sampler_type_prefix = ""; + break; ++ case VSIR_DATA_I32: ++ sampler_type_prefix = "i"; ++ break; ++ case VSIR_DATA_U32: ++ sampler_type_prefix = "u"; ++ break; + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled data type %#x for combined resource/sampler " +@@ -2325,9 +2325,9 @@ static void shader_glsl_generate_declarations(struct vkd3d_glsl_generator *gen) + + static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *gen, struct vkd3d_shader_code *out) + { +- const struct vkd3d_shader_instruction_array *instructions = &gen->program->instructions; + struct vkd3d_string_buffer *buffer = gen->buffer; +- unsigned int i; ++ struct vkd3d_shader_instruction *ins; ++ struct vsir_program_iterator it; + void *code; + + MESSAGE("Generating a GLSL shader. This is unsupported; you get to keep all the pieces if it breaks.\n"); +@@ -2342,9 +2342,11 @@ static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *gen, struc + + ++gen->indent; + shader_glsl_shader_prologue(gen); +- for (i = 0; i < instructions->count; ++i) ++ ++ it = vsir_program_iterator(&gen->program->instructions); ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) + { +- vkd3d_glsl_handle_instruction(gen, &instructions->elements[i]); ++ vkd3d_glsl_handle_instruction(gen, ins); + } + + vkd3d_string_buffer_printf(buffer, "}\n"); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index 86198ce548f..7707412bf57 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -8245,11 +8245,11 @@ static enum vsir_data_type vsir_data_type_from_hlsl_type(struct hlsl_ctx *ctx, c + case HLSL_TYPE_HALF: + return VSIR_DATA_F16; + case HLSL_TYPE_INT: +- return VKD3D_DATA_INT; ++ return VSIR_DATA_I32; + case HLSL_TYPE_UINT: + case HLSL_TYPE_BOOL: + case HLSL_TYPE_MIN16UINT: +- return VKD3D_DATA_UINT; ++ return VSIR_DATA_U32; + } + } + +@@ -10267,12 +10267,12 @@ static void sm4_generate_vsir_cast_from_bool(struct hlsl_ctx *ctx, struct vsir_p + + dst_param = &ins->dst[0]; + vsir_dst_from_hlsl_node(dst_param, ctx, instr); +- ins->dst[0].reg.data_type = VKD3D_DATA_UINT; ++ ins->dst[0].reg.data_type = VSIR_DATA_U32; + + vsir_src_from_hlsl_node(&ins->src[0], ctx, operand, dst_param->write_mask); + + value.u[0].u = bits; +- vsir_src_from_hlsl_constant_value(&ins->src[1], ctx, &value, VKD3D_DATA_UINT, 1, 0); ++ vsir_src_from_hlsl_constant_value(&ins->src[1], ctx, &value, VSIR_DATA_U32, 1, 0); + } + + static bool sm4_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, +@@ -10969,10 +10969,10 @@ static bool sm4_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr + + memset(&value, 0xff, sizeof(value)); + vsir_src_from_hlsl_constant_value(&ins->src[1], ctx, &value, +- VKD3D_DATA_UINT, type->e.numeric.dimx, dst_param->write_mask); ++ VSIR_DATA_U32, type->e.numeric.dimx, dst_param->write_mask); + memset(&value, 0x00, sizeof(value)); + vsir_src_from_hlsl_constant_value(&ins->src[2], ctx, &value, +- VKD3D_DATA_UINT, type->e.numeric.dimx, dst_param->write_mask); ++ VSIR_DATA_U32, type->e.numeric.dimx, dst_param->write_mask); + } + else + { +@@ -11163,7 +11163,7 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, + { + if (sample_index->type == HLSL_IR_CONSTANT) + vsir_src_from_hlsl_constant_value(&ins->src[2], ctx, +- &hlsl_ir_constant(sample_index)->value, VKD3D_DATA_INT, 1, 0); ++ &hlsl_ir_constant(sample_index)->value, VSIR_DATA_I32, 1, 0); + else if (version->major == 4 && version->minor == 0) + hlsl_error(ctx, &sample_index->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Expected literal sample index."); + else +@@ -11646,7 +11646,7 @@ static void sm4_generate_vsir_instr_switch(struct hlsl_ctx *ctx, + + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VSIR_OP_CASE, 0, 1))) + return; +- vsir_src_from_hlsl_constant_value(&ins->src[0], ctx, &value, VKD3D_DATA_UINT, 1, VKD3DSP_WRITEMASK_ALL); ++ vsir_src_from_hlsl_constant_value(&ins->src[0], ctx, &value, VSIR_DATA_U32, 1, VKD3DSP_WRITEMASK_ALL); + } + + sm4_generate_vsir_block(ctx, &cas->body, program); +@@ -12185,12 +12185,12 @@ static enum vsir_data_type sm4_generate_vsir_get_format_type(const struct hlsl_t + return VSIR_DATA_F32; + + case HLSL_TYPE_INT: +- return VKD3D_DATA_INT; ++ return VSIR_DATA_I32; + + case HLSL_TYPE_BOOL: + case HLSL_TYPE_MIN16UINT: + case HLSL_TYPE_UINT: +- return VKD3D_DATA_UINT; ++ return VSIR_DATA_U32; + } + + vkd3d_unreachable(); +@@ -12320,7 +12320,7 @@ static void sm4_generate_vsir_add_dcl_stream(struct hlsl_ctx *ctx, + return; + } + +- vsir_src_param_init(&ins->src[0], VKD3DSPR_STREAM, VKD3D_DATA_OPAQUE, 1); ++ vsir_src_param_init(&ins->src[0], VKD3DSPR_STREAM, VKD3D_DATA_UNUSED, 1); + ins->src[0].reg.dimension = VSIR_DIMENSION_NONE; + ins->src[0].reg.idx[0].offset = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 18cda0269af..c322d9dde01 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -590,7 +590,7 @@ void vsir_src_param_init(struct vkd3d_shader_src_param *param, enum vkd3d_shader + + static void src_param_init_const_uint(struct vkd3d_shader_src_param *src, uint32_t value) + { +- vsir_src_param_init(src, VKD3DSPR_IMMCONST, VKD3D_DATA_UINT, 0); ++ vsir_src_param_init(src, VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); + src->reg.u.immconst_u32[0] = value; + } + +@@ -696,7 +696,7 @@ static void src_param_init_temp_float4(struct vkd3d_shader_src_param *src, unsig + + static void src_param_init_temp_uint(struct vkd3d_shader_src_param *src, unsigned int idx) + { +- vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_src_param_init(src, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + src->reg.idx[0].offset = idx; + } + +@@ -773,7 +773,7 @@ static void dst_param_init_temp_float4(struct vkd3d_shader_dst_param *dst, unsig + + static void dst_param_init_temp_uint(struct vkd3d_shader_dst_param *dst, unsigned int idx) + { +- vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_dst_param_init(dst, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + dst->reg.idx[0].offset = idx; + } + +@@ -913,7 +913,7 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra + tmp_idx = program->temp_count++; + + ins->opcode = VSIR_OP_FTOU; +- vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + ins->dst[0].reg.idx[0].offset = tmp_idx; + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + } +@@ -935,7 +935,7 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra + if (!vsir_instruction_init_with_params(program, ins2, &ins->location, VSIR_OP_FTOU, 1, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- vsir_register_init(&ins2->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_register_init(&ins2->dst[0].reg, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + ins2->dst[0].reg.idx[0].offset = tmp_idx; + ins2->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins2->dst[0].write_mask = ins->dst[0].write_mask; +@@ -959,7 +959,7 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra + if (tmp_idx == ~0u) + tmp_idx = program->temp_count++; + +- vsir_register_init(&rel->reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_register_init(&rel->reg, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + rel->reg.idx[0].offset = tmp_idx; + rel->reg.dimension = VSIR_DIMENSION_VEC4; + } +@@ -998,7 +998,7 @@ static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, + if (!vsir_instruction_init_with_params(program, ins, &ifc->location, opcode, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].reg.idx[0].offset = *tmp_idx; + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; +@@ -1012,7 +1012,7 @@ static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, + return VKD3D_ERROR_OUT_OF_MEMORY; + ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ; + +- vsir_register_init(&ins->src[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_register_init(&ins->src[0].reg, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[0].reg.idx[0].offset = *tmp_idx; + ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); +@@ -1043,7 +1043,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program + if (!vsir_instruction_init_with_params(program, ins, &texkill->location, VSIR_OP_LTO, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].reg.idx[0].offset = *tmp_idx; + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; +@@ -1067,16 +1067,16 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program + if (!(vsir_instruction_init_with_params(program, ins, &texkill->location, VSIR_OP_OR, 1, 2))) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->dst[0].reg.idx[0].offset = *tmp_idx; + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; + +- vsir_register_init(&ins->src[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_register_init(&ins->src[0].reg, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[0].reg.idx[0].offset = *tmp_idx; + ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); +- vsir_register_init(&ins->src[1].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_register_init(&ins->src[1].reg, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[1].reg.idx[0].offset = *tmp_idx; + ins->src[1].swizzle = vkd3d_shader_create_swizzle(j, j, j, j); +@@ -1089,7 +1089,7 @@ static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program + return VKD3D_ERROR_OUT_OF_MEMORY; + ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ; + +- vsir_register_init(&ins->src[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); ++ vsir_register_init(&ins->src[0].reg, VKD3DSPR_TEMP, VSIR_DATA_U32, 1); + ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[0].reg.idx[0].offset = *tmp_idx; + ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); +@@ -2301,7 +2301,7 @@ struct vkd3d_shader_src_param *vsir_program_create_outpointid_param(struct vsir_ + if (!(rel_addr = shader_src_param_allocator_get(&instructions->src_params, 1))) + return NULL; + +- vsir_register_init(&rel_addr->reg, VKD3DSPR_OUTPOINTID, VKD3D_DATA_UINT, 0); ++ vsir_register_init(&rel_addr->reg, VKD3DSPR_OUTPOINTID, VSIR_DATA_U32, 0); + rel_addr->swizzle = 0; + rel_addr->modifiers = 0; + +@@ -3862,7 +3862,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte + 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); ++ vsir_src_param_init(&src_params[index], VKD3DSPR_IMMCONST, VSIR_DATA_U32, 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); + } +@@ -6839,7 +6839,7 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr + vsir_instruction_init_with_params(program, ins, &loc, opcodes[compare_func].uint_opcode, 1, 2); + src_param_init_temp_uint(&ins->src[opcodes[compare_func].swap ? 1 : 0], colour_temp); + src_param_init_parameter(&ins->src[opcodes[compare_func].swap ? 0 : 1], +- VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF, VKD3D_DATA_UINT); ++ VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF, VSIR_DATA_U32); + break; + + case VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4: +@@ -9548,12 +9548,18 @@ static void vsir_validate_register(struct validation_context *ctx, + register_validation_data[] = + { + [VKD3DSPR_DEPTHOUT] = {true, 0, VSIR_DIMENSION_SCALAR}, ++ [VKD3DSPR_PRIMID] = {true, 0, VSIR_DIMENSION_SCALAR}, ++ [VKD3DSPR_OUTPOINTID] = {true, 0, VSIR_DIMENSION_SCALAR}, ++ [VKD3DSPR_THREADID] = {true, 0, VSIR_DIMENSION_VEC4}, + [VKD3DSPR_THREADGROUPID] = {true, 0, VSIR_DIMENSION_VEC4}, + [VKD3DSPR_LOCALTHREADID] = {true, 0, VSIR_DIMENSION_VEC4}, + [VKD3DSPR_LOCALTHREADINDEX] = {true, 0, VSIR_DIMENSION_VEC4}, + [VKD3DSPR_COVERAGE] = {true, 0, VSIR_DIMENSION_VEC4}, ++ [VKD3DSPR_SAMPLEMASK] = {true, 0, VSIR_DIMENSION_SCALAR}, ++ [VKD3DSPR_GSINSTID] = {true, 0, VSIR_DIMENSION_SCALAR}, + [VKD3DSPR_DEPTHOUTGE] = {true, 0, VSIR_DIMENSION_SCALAR}, + [VKD3DSPR_DEPTHOUTLE] = {true, 0, VSIR_DIMENSION_SCALAR}, ++ [VKD3DSPR_OUTSTENCILREF] = {true, 0, VSIR_DIMENSION_SCALAR}, + }; + + const struct register_validation_data *validation_data; +@@ -9642,10 +9648,6 @@ static void vsir_validate_register(struct validation_context *ctx, + vsir_validate_constbuffer_register(ctx, reg); + break; + +- case VKD3DSPR_PRIMID: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- + case VKD3DSPR_NULL: + vsir_validate_register_without_indices(ctx, reg); + break; +@@ -9662,10 +9664,6 @@ static void vsir_validate_register(struct validation_context *ctx, + vsir_validate_uav_register(ctx, reg); + break; + +- case VKD3DSPR_OUTPOINTID: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- + case VKD3DSPR_FORKINSTID: + vsir_validate_register_without_indices(ctx, reg); + break; +@@ -9690,22 +9688,6 @@ static void vsir_validate_register(struct validation_context *ctx, + vsir_validate_register_without_indices(ctx, reg); + break; + +- case VKD3DSPR_THREADID: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- +- case VKD3DSPR_SAMPLEMASK: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- +- case VKD3DSPR_GSINSTID: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- +- case VKD3DSPR_OUTSTENCILREF: +- vsir_validate_register_without_indices(ctx, reg); +- break; +- + case VKD3DSPR_SSA: + vsir_validate_ssa_register(ctx, reg); + break; +@@ -9900,11 +9882,11 @@ static void vsir_validate_io_src_param(struct validation_context *ctx, + #define F32_BIT (1u << VSIR_DATA_F32) + #define F16_BIT (1u << VSIR_DATA_F16) + +-#define I32_BIT (1u << VKD3D_DATA_INT) ++#define I32_BIT (1u << VSIR_DATA_I32) + +-#define U64_BIT (1u << VKD3D_DATA_UINT64) +-#define U32_BIT (1u << VKD3D_DATA_UINT) +-#define U16_BIT (1u << VKD3D_DATA_UINT16) ++#define U64_BIT (1u << VSIR_DATA_U64) ++#define U32_BIT (1u << VSIR_DATA_U32) ++#define U16_BIT (1u << VSIR_DATA_U16) + + static void vsir_validate_src_param(struct validation_context *ctx, + const struct vkd3d_shader_src_param *src) +@@ -10658,9 +10640,9 @@ static void vsir_validate_integer_elementwise_operation(struct validation_contex + { + static const bool types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_INT] = true, +- [VKD3D_DATA_UINT] = true, +- [VKD3D_DATA_UINT64] = true, ++ [VSIR_DATA_I32] = true, ++ [VSIR_DATA_U32] = true, ++ [VSIR_DATA_U64] = true, + }; + + vsir_validate_elementwise_operation(ctx, instruction, types); +@@ -10671,10 +10653,10 @@ static void vsir_validate_logic_elementwise_operation(struct validation_context + { + static const bool types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_INT] = true, +- [VKD3D_DATA_UINT] = true, +- [VKD3D_DATA_UINT64] = true, + [VKD3D_DATA_BOOL] = true, ++ [VSIR_DATA_I32] = true, ++ [VSIR_DATA_U32] = true, ++ [VSIR_DATA_U64] = true, + }; + + vsir_validate_elementwise_operation(ctx, instruction, types); +@@ -10691,7 +10673,7 @@ static void vsir_validate_comparison_operation(struct validation_context *ctx, + + dst_data_type = instruction->dst[0].reg.data_type; + +- if (dst_data_type != VKD3D_DATA_UINT && dst_data_type != VKD3D_DATA_BOOL) ++ if (dst_data_type != VSIR_DATA_U32 && dst_data_type != VKD3D_DATA_BOOL) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Invalid data type %#x for result of comparison operation \"%s\" (%#x).", + dst_data_type, vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); +@@ -10748,9 +10730,9 @@ static void vsir_validate_integer_comparison_operation(struct validation_context + { + static const bool types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_INT] = true, +- [VKD3D_DATA_UINT] = true, +- [VKD3D_DATA_UINT64] = true, ++ [VSIR_DATA_I32] = true, ++ [VSIR_DATA_U32] = true, ++ [VSIR_DATA_U64] = true, + }; + + vsir_validate_comparison_operation(ctx, instruction, types); +@@ -11305,8 +11287,8 @@ static void vsir_validate_ftoi(struct validation_context *ctx, const struct vkd3 + }; + static const bool dst_types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_INT] = true, +- [VKD3D_DATA_UINT] = true, ++ [VSIR_DATA_I32] = true, ++ [VSIR_DATA_U32] = true, + }; + + vsir_validate_cast_operation(ctx, instruction, src_types, dst_types); +@@ -11322,7 +11304,7 @@ static void vsir_validate_ftou(struct validation_context *ctx, const struct vkd3 + }; + static const bool dst_types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_UINT] = true, ++ [VSIR_DATA_U32] = true, + }; + + vsir_validate_cast_operation(ctx, instruction, src_types, dst_types); +@@ -11344,10 +11326,10 @@ static void vsir_validate_itof(struct validation_context *ctx, const struct vkd3 + { + static const bool src_types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_INT] = true, +- [VKD3D_DATA_UINT] = true, +- [VKD3D_DATA_UINT64] = true, + [VKD3D_DATA_BOOL] = true, ++ [VSIR_DATA_I32] = true, ++ [VSIR_DATA_U32] = true, ++ [VSIR_DATA_U64] = true, + }; + static const bool dst_types[VSIR_DATA_TYPE_COUNT] = + { +@@ -11363,10 +11345,10 @@ static void vsir_validate_itoi(struct validation_context *ctx, const struct vkd3 + { + static const bool types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_INT] = true, +- [VKD3D_DATA_UINT] = true, +- [VKD3D_DATA_UINT64] = true, + [VKD3D_DATA_BOOL] = true, ++ [VSIR_DATA_I32] = true, ++ [VSIR_DATA_U32] = true, ++ [VSIR_DATA_U64] = true, + }; + + vsir_validate_cast_operation(ctx, instruction, types, types); +@@ -11626,10 +11608,18 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ + [VSIR_OP_MAX] = {1, 2, vsir_validate_float_elementwise_operation}, + [VSIR_OP_MIN] = {1, 2, vsir_validate_float_elementwise_operation}, + [VSIR_OP_MUL] = {1, 2, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_NEO] = {1, 2, vsir_validate_float_comparison_operation}, ++ [VSIR_OP_NEU] = {1, 2, vsir_validate_float_comparison_operation}, + [VSIR_OP_NOP] = {0, 0, vsir_validate_nop}, ++ [VSIR_OP_NOT] = {1, 1, vsir_validate_logic_elementwise_operation}, ++ [VSIR_OP_OR] = {1, 2, vsir_validate_logic_elementwise_operation}, ++ [VSIR_OP_ORD] = {1, 2, vsir_validate_float_comparison_operation}, + [VSIR_OP_PHI] = {1, ~0u, vsir_validate_phi}, ++ [VSIR_OP_RCP] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_REP] = {0, 1, vsir_validate_rep}, + [VSIR_OP_RET] = {0, 0, vsir_validate_ret}, ++ [VSIR_OP_ROUND_NE] = {1, 1, vsir_validate_float_elementwise_operation}, ++ [VSIR_OP_ROUND_NI] = {1, 1, vsir_validate_float_elementwise_operation}, + [VSIR_OP_SWITCH] = {0, 1, vsir_validate_switch}, + [VSIR_OP_SWITCH_MONOLITHIC] = {0, ~0u, vsir_validate_switch_monolithic}, + }; +diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c +index 83cdf9feea0..ccfce0f4591 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/msl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/msl.c +@@ -142,10 +142,10 @@ static void msl_print_resource_datatype(struct msl_generator *gen, + case VKD3D_DATA_SNORM: + vkd3d_string_buffer_printf(buffer, "float"); + break; +- case VKD3D_DATA_INT: ++ case VSIR_DATA_I32: + vkd3d_string_buffer_printf(buffer, "int"); + break; +- case VKD3D_DATA_UINT: ++ case VSIR_DATA_U32: + vkd3d_string_buffer_printf(buffer, "uint"); + break; + default: +@@ -165,10 +165,10 @@ static void msl_print_register_datatype(struct vkd3d_string_buffer *buffer, + case VSIR_DATA_F32: + vkd3d_string_buffer_printf(buffer, "f"); + break; +- case VKD3D_DATA_INT: ++ case VSIR_DATA_I32: + vkd3d_string_buffer_printf(buffer, "i"); + break; +- case VKD3D_DATA_UINT: ++ case VSIR_DATA_U32: + vkd3d_string_buffer_printf(buffer, "u"); + break; + default: +@@ -537,7 +537,7 @@ static void msl_print_bitcast(struct vkd3d_string_buffer *dst, struct msl_genera + break; + + case MSL_DATA_UINT: +- write_cast = dst_data_type != VKD3D_DATA_UINT; ++ write_cast = dst_data_type != VSIR_DATA_U32; + break; + + case MSL_DATA_UNION: +@@ -1012,19 +1012,19 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct + vkd3d_string_buffer_printf(read, "as_type("); + msl_print_srv_name(read, gen, srv_binding, resource_type_info, data_type, false); + vkd3d_string_buffer_printf(read, ".read("); +- msl_print_src_with_type(read, gen, &ins->src[0], coord_mask, VKD3D_DATA_UINT); ++ msl_print_src_with_type(read, gen, &ins->src[0], coord_mask, VSIR_DATA_U32); + if (resource_type_info->array) + { + vkd3d_string_buffer_printf(read, ", "); +- msl_print_src_with_type(read, gen, &ins->src[0], coord_mask + 1, VKD3D_DATA_UINT); ++ msl_print_src_with_type(read, gen, &ins->src[0], coord_mask + 1, VSIR_DATA_U32); + } + if (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) + { + vkd3d_string_buffer_printf(read, ", "); + if (ins->opcode != VSIR_OP_LD2DMS) +- msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VKD3D_DATA_UINT); ++ msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VSIR_DATA_U32); + else +- msl_print_src_with_type(read, gen, &ins->src[2], VKD3DSP_WRITEMASK_0, VKD3D_DATA_UINT); ++ msl_print_src_with_type(read, gen, &ins->src[2], VKD3DSP_WRITEMASK_0, VSIR_DATA_U32); + } + vkd3d_string_buffer_printf(read, "))"); + msl_print_swizzle(read, ins->src[1].swizzle, ins->dst[0].write_mask); +@@ -1168,7 +1168,7 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + msl_dst_init(&dst, gen, ins, &ins->dst[0]); + sample = vkd3d_string_buffer_get(&gen->string_buffers); + +- if (ins->dst[0].reg.data_type == VKD3D_DATA_UINT) ++ if (ins->dst[0].reg.data_type == VSIR_DATA_U32) + vkd3d_string_buffer_printf(sample, "as_type("); + msl_print_srv_name(sample, gen, srv_binding, resource_type_info, data_type, compare); + if (gather && compare) +@@ -1238,7 +1238,7 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst + vkd3d_string_buffer_printf(sample, ", component::%c", "xyzw"[component_idx]); + } + vkd3d_string_buffer_printf(sample, ")"); +- if (ins->dst[0].reg.data_type == VKD3D_DATA_UINT) ++ if (ins->dst[0].reg.data_type == VSIR_DATA_U32) + vkd3d_string_buffer_printf(sample, ")"); + if (!compare || gather) + msl_print_swizzle(sample, resource->swizzle, ins->dst[0].write_mask); +@@ -1309,10 +1309,10 @@ static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_sh + { + switch (data_type) + { +- case VKD3D_DATA_UINT: ++ case VSIR_DATA_U32: + vkd3d_string_buffer_printf(image_data, "uint4("); + break; +- case VKD3D_DATA_INT: ++ case VSIR_DATA_I32: + vkd3d_string_buffer_printf(image_data, "int4("); + break; + default: +@@ -1333,7 +1333,7 @@ static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_sh + msl_print_indent(gen->buffer, gen->indent); + msl_print_uav_name(gen->buffer, gen, uav_binding, resource_type_info, data_type); + vkd3d_string_buffer_printf(gen->buffer, ".write(%s, ", image_data->buffer); +- msl_print_src_with_type(gen->buffer, gen, &ins->src[0], coord_mask, VKD3D_DATA_UINT); ++ msl_print_src_with_type(gen->buffer, gen, &ins->src[0], coord_mask, VSIR_DATA_U32); + vkd3d_string_buffer_printf(gen->buffer, ");\n"); + + vkd3d_string_buffer_release(&gen->string_buffers, image_data); +@@ -1894,19 +1894,19 @@ static void msl_generate_entrypoint_prologue(struct msl_generator *gen) + break; + + case VKD3D_SHADER_SV_VERTEX_ID: +- msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); ++ msl_print_register_datatype(buffer, gen, VSIR_DATA_U32); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = uint4(vertex_id, 0u, 0u, 0u)"); + break; + + case VKD3D_SHADER_SV_IS_FRONT_FACE: +- msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); ++ msl_print_register_datatype(buffer, gen, VSIR_DATA_U32); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = uint4(input.is_front_face ? 0xffffffffu : 0u, 0, 0, 0)"); + break; + + case VKD3D_SHADER_SV_SAMPLE_INDEX: +- msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); ++ msl_print_register_datatype(buffer, gen, VSIR_DATA_U32); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = uint4(input.sample_index, 0u, 0u, 0u)"); + break; +@@ -2028,8 +2028,8 @@ static void msl_generate_entrypoint(struct msl_generator *gen) + + static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader_code *out) + { +- const struct vkd3d_shader_instruction_array *instructions = &gen->program->instructions; +- unsigned int i; ++ struct vkd3d_shader_instruction *ins; ++ struct vsir_program_iterator it; + + MESSAGE("Generating a MSL shader. This is unsupported; you get to keep all the pieces if it breaks.\n"); + +@@ -2095,9 +2095,10 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader + vkd3d_string_buffer_printf(gen->buffer, "vkd3d_vec4 r[%u];\n\n", gen->program->temp_count); + } + +- for (i = 0; i < instructions->count; ++i) ++ it = vsir_program_iterator(&gen->program->instructions); ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) + { +- msl_handle_instruction(gen, &instructions->elements[i]); ++ msl_handle_instruction(gen, ins); + } + + --gen->indent; +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index eb9a90e8b44..d99c7ee27ff 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -3020,7 +3020,7 @@ struct ssa_register_info + struct spirv_compiler + { + struct vkd3d_spirv_builder spirv_builder; +- const struct vsir_program *program; ++ struct vsir_program *program; + + struct vkd3d_shader_message_context *message_context; + struct vkd3d_shader_location location; +@@ -3150,7 +3150,7 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler) + vkd3d_free(compiler); + } + +-static struct spirv_compiler *spirv_compiler_create(const struct vsir_program *program, ++static struct spirv_compiler *spirv_compiler_create(struct vsir_program *program, + const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_message_context *message_context, uint64_t config_flags) + { +@@ -4060,7 +4060,7 @@ static const struct + parameter_data_type_map[] = + { + [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32] = {VSIR_DATA_F32, 1}, +- [VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32] = {VKD3D_DATA_UINT, 1}, ++ [VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32] = {VSIR_DATA_U32, 1}, + [VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4] = {VSIR_DATA_F32, 4}, + }; + +@@ -4491,7 +4491,7 @@ 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, +- data_type == VKD3D_DATA_UINT64 ++ data_type == VSIR_DATA_U64 + ? spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count) + : spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); + } +@@ -4660,8 +4660,8 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } +- val_id = spirv_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, +- VKD3D_DATA_UINT, 1, val_id); ++ val_id = spirv_compiler_emit_int_to_bool(compiler, ++ VKD3D_SHADER_CONDITIONAL_OP_NZ, VSIR_DATA_U32, 1, val_id); + } + else + { +@@ -4709,14 +4709,14 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil + switch (icb->data_type) + { + case VSIR_DATA_F32: +- case VKD3D_DATA_INT: +- case VKD3D_DATA_UINT: ++ case VSIR_DATA_I32: ++ case VSIR_DATA_U32: + for (i = 0; i < element_count; ++i) + elements[i] = spirv_compiler_get_constant(compiler, component_type, component_count, + &icb->data[component_count * i]); + break; + case VSIR_DATA_F64: +- case VKD3D_DATA_UINT64: ++ case VSIR_DATA_U64: + { + uint64_t *data = (uint64_t *)icb->data; + for (i = 0; i < element_count; ++i) +@@ -4808,8 +4808,8 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } +- val_id = spirv_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, +- VKD3D_DATA_UINT, component_count, val_id); ++ val_id = spirv_compiler_emit_int_to_bool(compiler, ++ VKD3D_SHADER_CONDITIONAL_OP_NZ, VSIR_DATA_U32, component_count, val_id); + } + else + { +@@ -5718,15 +5718,15 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + { + component_type = builtin->component_type; + input_component_count = builtin->component_count; +- component_idx = 0; + } + else + { + component_type = signature_element->component_type; + input_component_count = vsir_write_mask_component_count(signature_element->mask); +- component_idx = vsir_write_mask_get_component_idx(signature_element->mask); + } + ++ component_idx = vsir_write_mask_get_component_idx(write_mask); ++ + if (needs_private_io_variable(builtin)) + { + use_private_var = true; +@@ -5734,7 +5734,6 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + } + else + { +- component_idx = vsir_write_mask_get_component_idx(write_mask); + reg_write_mask = write_mask >> component_idx; + } + +@@ -5820,7 +5819,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + vkd3d_write_mask_from_component_count(input_component_count), + VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, signature_element->mask >> component_idx); + +- spirv_compiler_emit_store_reg(compiler, &dst_reg, signature_element->mask, val_id); ++ spirv_compiler_emit_store_reg(compiler, &dst_reg, signature_element->mask >> component_idx, val_id); + } + } + +@@ -7601,11 +7600,11 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, + /* ITOD is not supported. Frontends which emit bool casts must use ITOF for double. */ + val_id = spirv_compiler_emit_bool_to_double(compiler, 1, val_id, instruction->opcode == VSIR_OP_ITOF); + } +- else if (dst->reg.data_type == VKD3D_DATA_UINT16 || dst->reg.data_type == VKD3D_DATA_UINT) ++ else if (dst->reg.data_type == VSIR_DATA_U16 || dst->reg.data_type == VSIR_DATA_U32) + { + val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->opcode == VSIR_OP_ITOI); + } +- else if (dst->reg.data_type == VKD3D_DATA_UINT64) ++ else if (dst->reg.data_type == VSIR_DATA_U64) + { + val_id = spirv_compiler_emit_bool_to_int64(compiler, 1, val_id, instruction->opcode == VSIR_OP_ITOI); + } +@@ -7631,7 +7630,7 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil + SpvOp op = SpvOpMax; + bool check_zero; + +- if (src->reg.data_type == VKD3D_DATA_UINT64 && instruction->opcode == VSIR_OP_COUNTBITS) ++ if (src->reg.data_type == VSIR_DATA_U64 && instruction->opcode == VSIR_OP_COUNTBITS) + { + /* At least some drivers support this anyway, but if validation is enabled it will fail. */ + FIXME("Unsupported 64-bit source for bit count.\n"); +@@ -7701,7 +7700,7 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil + condition_id = spirv_compiler_emit_int_to_bool(compiler, + VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src_ids[1]); + +- if (dst[0].reg.data_type == VKD3D_DATA_UINT64) ++ if (dst[0].reg.data_type == VSIR_DATA_U64) + uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count); + else + uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT_MAX, component_count); +@@ -7816,7 +7815,7 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp + unsigned int i, component_count; + enum GLSLstd450 glsl_inst; + +- if (src[0].reg.data_type == VKD3D_DATA_UINT64 && (instruction->opcode == VSIR_OP_FIRSTBIT_HI ++ if (src[0].reg.data_type == VSIR_DATA_U64 && (instruction->opcode == VSIR_OP_FIRSTBIT_HI + || instruction->opcode == VSIR_OP_FIRSTBIT_LO || instruction->opcode == VSIR_OP_FIRSTBIT_SHI)) + { + /* At least some drivers support this anyway, but if validation is enabled it will fail. */ +@@ -8226,7 +8225,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); +- size = (src[src_count - 1].reg.data_type == VKD3D_DATA_UINT64) ? 0x40 : 0x20; ++ size = (src[src_count - 1].reg.data_type == VSIR_DATA_U64) ? 0x40 : 0x20; + mask_id = spirv_compiler_get_constant_uint(compiler, size - 1); + size_id = spirv_compiler_get_constant_uint(compiler, size); + +@@ -9424,7 +9423,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * + &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); + + data = &src[instruction->src_count - 1]; +- VKD3D_ASSERT(data->reg.data_type == VKD3D_DATA_UINT); ++ VKD3D_ASSERT(data->reg.data_type == VSIR_DATA_U32); + val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); + + component_count = vsir_write_mask_component_count(dst->write_mask); +@@ -9452,7 +9451,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * + type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); + + data = &src[instruction->src_count - 1]; +- VKD3D_ASSERT(data->reg.data_type == VKD3D_DATA_UINT); ++ VKD3D_ASSERT(data->reg.data_type == VSIR_DATA_U32); + val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); + + component_count = vsir_write_mask_component_count(dst->write_mask); +@@ -9495,7 +9494,7 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, + type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); + + data = src[instruction->src_count - 1]; +- data.reg.data_type = VKD3D_DATA_UINT; ++ data.reg.data_type = VSIR_DATA_U32; + val_id = spirv_compiler_emit_load_src(compiler, &data, dst->write_mask); + + component_count = vsir_write_mask_component_count(dst->write_mask); +@@ -9997,7 +9996,7 @@ static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *co + if (src->reg.type == VKD3DSPR_RASTERIZER) + { + val_id = spirv_compiler_emit_shader_parameter(compiler, +- VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, VKD3D_DATA_UINT, 1); ++ VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT, VSIR_DATA_U32, 1); + } + else + { +@@ -10317,7 +10316,7 @@ static void spirv_compiler_emit_quad_read_across(struct spirv_compiler *compiler + + type_id = vkd3d_spirv_get_type_id_for_data_type(builder, dst->reg.data_type, + vsir_write_mask_component_count(dst->write_mask)); +- direction_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, VKD3D_DATA_UINT, 1); ++ direction_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, VSIR_DATA_U32, 1); + val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); + direction_id = map_quad_read_across_direction(instruction->opcode); + direction_id = vkd3d_spirv_get_op_constant(builder, direction_type_id, direction_id); +@@ -11020,11 +11019,12 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info; + const struct vkd3d_shader_spirv_domain_shader_target_info *ds_info; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- const struct vsir_program *program = compiler->program; +- struct vkd3d_shader_instruction_array instructions; ++ struct vsir_program *program = compiler->program; + enum vkd3d_shader_spirv_environment environment; ++ struct vkd3d_shader_instruction *ins; + enum vkd3d_result result = VKD3D_OK; + unsigned int i, max_element_count; ++ struct vsir_program_iterator it; + + max_element_count = max(program->output_signature.element_count, program->patch_constant_signature.element_count); + if (!(compiler->output_info = vkd3d_calloc(max_element_count, sizeof(*compiler->output_info)))) +@@ -11072,8 +11072,6 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + if (program->block_count && !spirv_compiler_init_blocks(compiler, program->block_count)) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- instructions = program->instructions; +- + compiler->use_vocp = program->use_vocp; + compiler->block_names = program->block_names; + compiler->block_name_count = program->block_name_count; +@@ -11088,9 +11086,10 @@ 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); + +- for (i = 0; i < instructions.count && result >= 0; ++i) ++ it = vsir_program_iterator(&program->instructions); ++ for (ins = vsir_program_iterator_head(&it); ins && result >= 0; ins = vsir_program_iterator_next(&it)) + { +- result = spirv_compiler_handle_instruction(compiler, &instructions.elements[i]); ++ result = spirv_compiler_handle_instruction(compiler, ins); + } + + if (result < 0) +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index 26c41a902d2..8acd7bc0db5 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -753,8 +753,8 @@ static const enum vsir_data_type data_type_table[] = + /* 0 */ VSIR_DATA_F32, + /* VKD3D_SM4_DATA_UNORM */ VKD3D_DATA_UNORM, + /* VKD3D_SM4_DATA_SNORM */ VKD3D_DATA_SNORM, +- /* VKD3D_SM4_DATA_INT */ VKD3D_DATA_INT, +- /* VKD3D_SM4_DATA_UINT */ VKD3D_DATA_UINT, ++ /* VKD3D_SM4_DATA_INT */ VSIR_DATA_I32, ++ /* VKD3D_SM4_DATA_UINT */ VSIR_DATA_U32, + /* VKD3D_SM4_DATA_FLOAT */ VSIR_DATA_F32, + /* VKD3D_SM4_DATA_MIXED */ VKD3D_DATA_MIXED, + /* VKD3D_SM4_DATA_DOUBLE */ VSIR_DATA_F64, +@@ -795,7 +795,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, &ins->src[0]); ++ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VSIR_DATA_U32, &ins->src[0]); + ins->flags = (opcode_token & VKD3D_SM4_CONDITIONAL_NZ) ? + VKD3D_SHADER_CONDITIONAL_OP_NZ : VKD3D_SHADER_CONDITIONAL_OP_Z; + } +@@ -803,7 +803,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, &ins->src[0]); ++ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VSIR_DATA_U32, &ins->src[0]); + if (ins->src[0].reg.type != VKD3DSPR_IMMCONST) + { + FIXME("Switch case value is not a 32-bit constant.\n"); +@@ -1432,8 +1432,8 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + /* + * d -> VSIR_DATA_F64 + * f -> VSIR_DATA_F32 +- * i -> VKD3D_DATA_INT +- * u -> VKD3D_DATA_UINT ++ * i -> VSIR_DATA_I32 ++ * u -> VSIR_DATA_U32 + * O -> VKD3D_DATA_OPAQUE + * R -> VKD3D_DATA_RESOURCE + * S -> VKD3D_DATA_SAMPLER +@@ -1578,8 +1578,8 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + {VKD3D_SM5_OP_HS_CONTROL_POINT_PHASE, VSIR_OP_HS_CONTROL_POINT_PHASE, "", ""}, + {VKD3D_SM5_OP_HS_FORK_PHASE, VSIR_OP_HS_FORK_PHASE, "", ""}, + {VKD3D_SM5_OP_HS_JOIN_PHASE, VSIR_OP_HS_JOIN_PHASE, "", ""}, +- {VKD3D_SM5_OP_EMIT_STREAM, VSIR_OP_EMIT_STREAM, "", "f"}, +- {VKD3D_SM5_OP_CUT_STREAM, VSIR_OP_CUT_STREAM, "", "f"}, ++ {VKD3D_SM5_OP_EMIT_STREAM, VSIR_OP_EMIT_STREAM, "", "*"}, ++ {VKD3D_SM5_OP_CUT_STREAM, VSIR_OP_CUT_STREAM, "", "*"}, + {VKD3D_SM5_OP_FCALL, VSIR_OP_FCALL, "", "O", + shader_sm5_read_fcall}, + {VKD3D_SM5_OP_BUFINFO, VSIR_OP_BUFINFO, "i", "*"}, +@@ -1602,7 +1602,7 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + {VKD3D_SM5_OP_BFI, VSIR_OP_BFI, "u", "iiuu"}, + {VKD3D_SM5_OP_BFREV, VSIR_OP_BFREV, "u", "u"}, + {VKD3D_SM5_OP_SWAPC, VSIR_OP_SWAPC, "ff", "uff"}, +- {VKD3D_SM5_OP_DCL_STREAM, VSIR_OP_DCL_STREAM, "", "O"}, ++ {VKD3D_SM5_OP_DCL_STREAM, VSIR_OP_DCL_STREAM, "", "*"}, + {VKD3D_SM5_OP_DCL_FUNCTION_BODY, VSIR_OP_DCL_FUNCTION_BODY, "", "", + shader_sm5_read_dcl_function_body}, + {VKD3D_SM5_OP_DCL_FUNCTION_TABLE, VSIR_OP_DCL_FUNCTION_TABLE, "", "", +@@ -1994,9 +1994,9 @@ static enum vsir_data_type map_data_type(char t) + case 'f': + return VSIR_DATA_F32; + case 'i': +- return VKD3D_DATA_INT; ++ return VSIR_DATA_I32; + case 'u': +- return VKD3D_DATA_UINT; ++ return VSIR_DATA_U32; + case 'O': + return VKD3D_DATA_OPAQUE; + case '*': +@@ -2024,7 +2024,7 @@ static bool shader_sm4_read_reg_idx(struct vkd3d_shader_sm4_parser *priv, const + reg_idx->offset = *(*ptr)++; + else + reg_idx->offset = 0; +- shader_sm4_read_src_param(priv, ptr, end, VKD3D_DATA_INT, rel_addr); ++ shader_sm4_read_src_param(priv, ptr, end, VSIR_DATA_I32, rel_addr); + } + else + { +@@ -2896,7 +2896,6 @@ static void shader_sm4_validate_default_phase_index_ranges(struct vkd3d_shader_s + int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags, + struct vkd3d_shader_message_context *message_context, struct vsir_program *program) + { +- struct vkd3d_shader_instruction_array *instructions; + struct vkd3d_shader_sm4_parser sm4 = {0}; + struct dxbc_shader_desc dxbc_desc = {0}; + struct vkd3d_shader_instruction *ins; +@@ -2956,17 +2955,14 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con + return VKD3D_ERROR_INVALID_SHADER; + } + +- instructions = &program->instructions; + while (sm4.ptr != sm4.end) + { +- if (!shader_instruction_array_reserve(instructions, instructions->count + 1)) ++ if (!(ins = vsir_program_append(program))) + { +- ERR("Failed to allocate instructions.\n"); + vkd3d_shader_parser_error(&sm4.p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory."); + vsir_program_cleanup(program); + return VKD3D_ERROR_OUT_OF_MEMORY; + } +- ins = &instructions->elements[instructions->count]; + shader_sm4_read_instruction(&sm4, ins); + + if (ins->opcode == VSIR_OP_INVALID) +@@ -2975,7 +2971,6 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con + vsir_program_cleanup(program); + return VKD3D_ERROR_OUT_OF_MEMORY; + } +- ++instructions->count; + } + if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL + && !sm4.has_control_point_phase && !sm4.p.failed) +@@ -4339,20 +4334,23 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ + } + } + +-static void tpf_write_program(struct tpf_compiler *tpf, const struct vsir_program *program) ++static void tpf_write_program(struct tpf_compiler *tpf, struct vsir_program *program) + { +- unsigned int i; ++ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); ++ struct vkd3d_shader_instruction *ins; + + if (tpf->program->shader_version.type == VKD3D_SHADER_TYPE_COMPUTE) + tpf_dcl_thread_group(tpf, &tpf->program->thread_group_size); + +- for (i = 0; i < program->instructions.count; ++i) +- tpf_handle_instruction(tpf, &program->instructions.elements[i]); ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) ++ { ++ tpf_handle_instruction(tpf, ins); ++ } + } + + static void tpf_write_shdr(struct tpf_compiler *tpf) + { +- const struct vsir_program *program = tpf->program; ++ struct vsir_program *program = tpf->program; + const struct vkd3d_shader_version *version; + struct vkd3d_bytecode_buffer buffer = {0}; + size_t token_count_position; +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index c60feec4aa2..9c615c116e9 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -1120,7 +1120,7 @@ static void vkd3d_shader_scan_constant_buffer_declaration(struct vkd3d_shader_sc + struct vkd3d_shader_descriptor_info1 *d; + + if (!(d = vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, +- &cb->src.reg, &cb->range, VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_DATA_UINT))) ++ &cb->src.reg, &cb->range, VKD3D_SHADER_RESOURCE_BUFFER, VSIR_DATA_U32))) + return; + d->buffer_size = cb->size; + } +@@ -1305,12 +1305,12 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte + case VSIR_OP_DCL_RESOURCE_RAW: + case VSIR_OP_DCL_UAV_RAW: + vkd3d_shader_scan_resource_declaration(context, &instruction->declaration.raw_resource.resource, +- VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_DATA_UINT, 0, 0, true, instruction->flags); ++ VKD3D_SHADER_RESOURCE_BUFFER, VSIR_DATA_U32, 0, 0, true, instruction->flags); + break; + case VSIR_OP_DCL_RESOURCE_STRUCTURED: + case VSIR_OP_DCL_UAV_STRUCTURED: + vkd3d_shader_scan_resource_declaration(context, &instruction->declaration.structured_resource.resource, +- VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_DATA_UINT, 0, ++ VKD3D_SHADER_RESOURCE_BUFFER, VSIR_DATA_U32, 0, + instruction->declaration.structured_resource.byte_stride, false, instruction->flags); + break; + case VSIR_OP_DCL_TESSELLATOR_OUTPUT_PRIMITIVE: +@@ -1530,10 +1530,6 @@ static enum vkd3d_shader_resource_data_type vkd3d_resource_data_type_from_data_t + return VKD3D_SHADER_RESOURCE_DATA_UNORM; + case VKD3D_DATA_SNORM: + return VKD3D_SHADER_RESOURCE_DATA_SNORM; +- case VKD3D_DATA_INT: +- return VKD3D_SHADER_RESOURCE_DATA_INT; +- case VKD3D_DATA_UINT: +- return VKD3D_SHADER_RESOURCE_DATA_UINT; + case VKD3D_DATA_MIXED: + return VKD3D_SHADER_RESOURCE_DATA_MIXED; + case VKD3D_DATA_CONTINUED: +@@ -1544,6 +1540,10 @@ static enum vkd3d_shader_resource_data_type vkd3d_resource_data_type_from_data_t + return VKD3D_SHADER_RESOURCE_DATA_FLOAT; + case VSIR_DATA_F64: + return VKD3D_SHADER_RESOURCE_DATA_DOUBLE; ++ case VSIR_DATA_I32: ++ return VKD3D_SHADER_RESOURCE_DATA_INT; ++ case VSIR_DATA_U32: ++ return VKD3D_SHADER_RESOURCE_DATA_UINT; + default: + ERR("Invalid resource data type %#x.\n", data_type); + return VKD3D_SHADER_RESOURCE_DATA_FLOAT; +@@ -1647,8 +1647,8 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh + + if (size) + { +- if ((d = vkd3d_shader_scan_add_descriptor(&context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, ®, +- &range, VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_DATA_UINT))) ++ if ((d = vkd3d_shader_scan_add_descriptor(&context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, ++ ®, &range, VKD3D_SHADER_RESOURCE_BUFFER, VSIR_DATA_U32))) + d->buffer_size = size * 16; + } + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index f7bbadac3df..42f3c42033f 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -710,30 +710,32 @@ enum vkd3d_shader_register_precision + + enum vsir_data_type + { +- VKD3D_DATA_INT, +- VKD3D_DATA_UINT, + VKD3D_DATA_UNORM, + VKD3D_DATA_SNORM, + VKD3D_DATA_OPAQUE, + VKD3D_DATA_MIXED, + VKD3D_DATA_CONTINUED, + VKD3D_DATA_UNUSED, +- VKD3D_DATA_UINT8, +- VKD3D_DATA_UINT64, + VKD3D_DATA_BOOL, +- VKD3D_DATA_UINT16, + + VSIR_DATA_F16, + VSIR_DATA_F32, + VSIR_DATA_F64, + ++ VSIR_DATA_I32, ++ ++ VSIR_DATA_U8, ++ VSIR_DATA_U16, ++ VSIR_DATA_U32, ++ VSIR_DATA_U64, ++ + VSIR_DATA_TYPE_COUNT, + }; + + static inline bool data_type_is_integer(enum vsir_data_type data_type) + { +- return data_type == VKD3D_DATA_INT || data_type == VKD3D_DATA_UINT8 || data_type == VKD3D_DATA_UINT16 +- || data_type == VKD3D_DATA_UINT || data_type == VKD3D_DATA_UINT64; ++ return data_type == VSIR_DATA_I32 || data_type == VSIR_DATA_U8 || data_type == VSIR_DATA_U16 ++ || data_type == VSIR_DATA_U32 || data_type == VSIR_DATA_U64; + } + + static inline bool data_type_is_bool(enum vsir_data_type data_type) +@@ -748,7 +750,7 @@ static inline bool data_type_is_floating_point(enum vsir_data_type data_type) + + static inline bool data_type_is_64_bit(enum vsir_data_type data_type) + { +- return data_type == VSIR_DATA_F64 || data_type == VKD3D_DATA_UINT64; ++ return data_type == VSIR_DATA_F64 || data_type == VSIR_DATA_U64; + } + + enum vsir_dimension +@@ -1581,6 +1583,16 @@ bool vsir_instruction_init_with_params(struct vsir_program *program, + struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, + enum vkd3d_shader_opcode opcode, unsigned int dst_count, unsigned int src_count); + ++static inline struct vkd3d_shader_instruction *vsir_program_append(struct vsir_program *program) ++{ ++ struct vkd3d_shader_instruction_array *array = &program->instructions; ++ ++ if (!shader_instruction_array_insert_at(array, array->count, 1)) ++ return NULL; ++ ++ return &array->elements[array->count - 1]; ++} ++ + static inline struct vkd3d_shader_dst_param *vsir_program_get_dst_params( + struct vsir_program *program, unsigned int count) + { +@@ -1608,7 +1620,7 @@ void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, struct vsir_pr + void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser, + enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4); + +-void vsir_program_trace(const struct vsir_program *program); ++void vsir_program_trace(struct vsir_program *program); + + const char *shader_get_type_prefix(enum vkd3d_shader_type type); + +@@ -1633,7 +1645,7 @@ enum vsir_asm_flags + VSIR_ASM_FLAG_DUMP_DESCRIPTORS = 0x8, + }; + +-enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, ++enum vkd3d_result d3d_asm_compile(struct vsir_program *program, + const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_code *out, enum vsir_asm_flags flags); + void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer); +@@ -1799,12 +1811,12 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty + return VKD3D_SHADER_COMPONENT_FLOAT; + case VSIR_DATA_F64: + return VKD3D_SHADER_COMPONENT_DOUBLE; +- case VKD3D_DATA_UINT16: /* Minimum precision. TODO: native 16-bit */ +- case VKD3D_DATA_UINT: +- return VKD3D_SHADER_COMPONENT_UINT; +- case VKD3D_DATA_INT: ++ case VSIR_DATA_I32: + return VKD3D_SHADER_COMPONENT_INT; +- case VKD3D_DATA_UINT64: ++ case VSIR_DATA_U16: /* Minimum precision. TODO: native 16-bit */ ++ case VSIR_DATA_U32: ++ return VKD3D_SHADER_COMPONENT_UINT; ++ case VSIR_DATA_U64: + return VKD3D_SHADER_COMPONENT_UINT64; + case VKD3D_DATA_BOOL: + return VKD3D_SHADER_COMPONENT_BOOL; +@@ -1823,9 +1835,9 @@ static inline enum vsir_data_type vsir_data_type_from_component_type(enum vkd3d_ + case VKD3D_SHADER_COMPONENT_FLOAT: + return VSIR_DATA_F32; + case VKD3D_SHADER_COMPONENT_UINT: +- return VKD3D_DATA_UINT; ++ return VSIR_DATA_U32; + case VKD3D_SHADER_COMPONENT_INT: +- return VKD3D_DATA_INT; ++ return VSIR_DATA_I32; + case VKD3D_SHADER_COMPONENT_DOUBLE: + return VSIR_DATA_F64; + default: +-- +2.47.2 + diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-d8edf20c2b4224384d8e206c620bfbd61c5.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-d8edf20c2b4224384d8e206c620bfbd61c5.patch deleted file mode 100644 index 3263ac02..00000000 --- a/patches/vkd3d-latest/0004-Updated-vkd3d-to-d8edf20c2b4224384d8e206c620bfbd61c5.patch +++ /dev/null @@ -1,2731 +0,0 @@ -From 6d0c679f28b976983d6ea925d9adc5dff37bcb56 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 24 Jun 2025 13:36:03 +1000 -Subject: [PATCH] Updated vkd3d to d8edf20c2b4224384d8e206c620bfbd61c56219d. - ---- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 5 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 2 + - libs/vkd3d/libs/vkd3d-shader/fx.c | 574 +++++----- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 16 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 7 +- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 129 ++- - libs/vkd3d/libs/vkd3d-shader/ir.c | 1009 ++++++++++++++++- - libs/vkd3d/libs/vkd3d-shader/msl.c | 259 ++++- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 10 +- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 3 + - .../libs/vkd3d-shader/vkd3d_shader_private.h | 10 + - 11 files changed, 1680 insertions(+), 344 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index fbc0235cdd0..f19a6283197 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -2137,6 +2137,9 @@ int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, - struct vkd3d_bytecode_buffer *buffer = &d3dbc.buffer; - int result; - -+ if ((result = vsir_allocate_temp_registers(program, message_context))) -+ return result; -+ - d3dbc.program = program; - d3dbc.message_context = message_context; - switch (version->type) -@@ -2156,7 +2159,7 @@ int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, - } - - put_u32(buffer, sm1_version(version->type, version->major, version->minor)); -- d3dbc_write_comment(&d3dbc, VKD3D_MAKE_TAG('C','T','A','B'), ctab); -+ d3dbc_write_comment(&d3dbc, TAG_CTAB, ctab); - d3dbc_write_semantic_dcls(&d3dbc); - d3dbc_write_program_instructions(&d3dbc); - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 9ebcb6870e9..71fa81ec163 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -5180,6 +5180,8 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr - src_param->reg.data_type = vkd3d_data_type_from_sm6_type(type); - if (data_type_is_64_bit(src_param->reg.data_type)) - src_param->swizzle = vsir_swizzle_64_from_32(src_param->swizzle); -+ else -+ register_convert_to_minimum_precision(&src_param->reg); - - instruction_dst_param_init_ssa_vector(ins, sm6_type_max_vector_size(type), sm6); - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index 95a172fd827..0ab1a676400 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -251,6 +251,8 @@ struct fx_write_context_ops - void (*write_technique)(struct hlsl_ir_var *var, struct fx_write_context *fx); - void (*write_pass)(struct hlsl_ir_var *var, struct fx_write_context *fx); - void (*write_annotation)(struct hlsl_ir_var *var, struct fx_write_context *fx); -+ void (*write_state_assignment)(const struct hlsl_ir_var *var, -+ struct hlsl_state_block_entry *entry, struct fx_write_context *fx); - bool are_child_effects_supported; - }; - -@@ -313,6 +315,15 @@ static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) - fx->ops->write_pass(var, fx); - } - -+static void write_state_assignment(const struct hlsl_ir_var *var, -+ struct hlsl_state_block_entry *entry, struct fx_write_context *fx) -+{ -+ fx->ops->write_state_assignment(var, entry, fx); -+} -+ -+static uint32_t write_state_block(struct hlsl_ir_var *var, -+ unsigned int block_index, struct fx_write_context *fx); -+ - static uint32_t write_annotations(struct hlsl_scope *scope, struct fx_write_context *fx) - { - struct hlsl_ctx *ctx = fx->ctx; -@@ -348,8 +359,6 @@ static void write_fx_4_annotations(struct hlsl_scope *scope, struct fx_write_con - static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx); - static const char * get_fx_4_type_name(const struct hlsl_type *type); - static void write_fx_4_annotation(struct hlsl_ir_var *var, struct fx_write_context *fx); --static void write_fx_4_state_block(struct hlsl_ir_var *var, unsigned int block_index, -- uint32_t count_offset, struct fx_write_context *fx); - - static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context *fx) - { -@@ -502,17 +511,22 @@ static uint32_t write_fx_4_string(const char *string, struct fx_write_context *f - return string_entry->offset; - } - -+static void fx_4_decompose_state_blocks(struct hlsl_ir_var *var, struct fx_write_context *fx); -+ - static void write_fx_4_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) - { - struct vkd3d_bytecode_buffer *buffer = &fx->structured; -- uint32_t name_offset, count_offset; -+ uint32_t name_offset, count_offset, count; - - name_offset = write_string(var->name, fx); - put_u32(buffer, name_offset); - count_offset = put_u32(buffer, 0); - -+ fx_4_decompose_state_blocks(var, fx); -+ - write_fx_4_annotations(var->annotations, fx); -- write_fx_4_state_block(var, 0, count_offset, fx); -+ count = write_state_block(var, 0, fx); -+ set_u32(buffer, count_offset, count); - } - - static void write_fx_2_annotations(struct hlsl_ir_var *var, uint32_t count_offset, struct fx_write_context *fx) -@@ -775,9 +789,10 @@ static const struct rhs_named_value fx_2_filter_values[] = - { NULL } - }; - --struct fx_2_state -+struct fx_state - { - const char *name; -+ enum hlsl_type_class container; - enum hlsl_type_class class; - enum state_property_component_type type; - unsigned int dimx; -@@ -786,215 +801,215 @@ struct fx_2_state - const struct rhs_named_value *values; - }; - --static const struct fx_2_state fx_2_pass_states[] = --{ -- { "ZEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 0, fx_2_zenable_values }, -- { "FillMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 1, fx_2_fillmode_values }, -- { "ShadeMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 2, fx_2_shademode_values }, -- { "ZWriteEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 3 }, -- { "AlphaTestEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 4 }, -- { "LastPixel", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 5 }, -- { "SrcBlend", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 6, fx_2_blendmode_values }, -- { "DestBlend", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 7, fx_2_blendmode_values }, -- { "CullMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 8, fx_2_cullmode_values }, -- { "ZFunc", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 9, fx_2_cmpfunc_values }, -- { "AlphaRef", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 10 }, -- { "AlphaFunc", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 11, fx_2_cmpfunc_values }, -- { "DitherEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 12 }, -- { "AlphaBlendEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 13 }, -- { "FogEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 14 }, -- { "SpecularEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 15 }, -- { "FogColor", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 16 }, -- { "FogTableMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 17, fx_2_fogmode_values }, -- { "FogStart", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 18 }, -- { "FogEnd", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 19 }, -- { "FogDensity", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 20 }, -- { "RangeFogEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 21 }, -- { "StencilEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 22 }, -- { "StencilFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 23, fx_2_stencilcaps_values }, -- { "StencilZFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 24, fx_2_stencilcaps_values }, -- { "StencilPass", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 25, fx_2_stencilcaps_values }, -- { "StencilFunc", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 26, fx_2_cmpfunc_values }, -- { "StencilRef", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 27 }, -- { "StencilMask", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 28 }, -- { "StencilWriteMask", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 29 }, -- { "TextureFactor", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 30 }, -- { "Wrap0", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 31, fx_2_wrap_values }, -- { "Wrap1", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 32, fx_2_wrap_values }, -- { "Wrap2", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 33, fx_2_wrap_values }, -- { "Wrap3", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 34, fx_2_wrap_values }, -- { "Wrap4", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 35, fx_2_wrap_values }, -- { "Wrap5", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 36, fx_2_wrap_values }, -- { "Wrap6", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 37, fx_2_wrap_values }, -- { "Wrap7", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 38, fx_2_wrap_values }, -- { "Wrap8", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 39, fx_2_wrap_values }, -- { "Wrap9", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 40, fx_2_wrap_values }, -- { "Wrap10", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 41, fx_2_wrap_values }, -- { "Wrap11", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 42, fx_2_wrap_values }, -- { "Wrap12", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 43, fx_2_wrap_values }, -- { "Wrap13", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 44, fx_2_wrap_values }, -- { "Wrap14", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 45, fx_2_wrap_values }, -- { "Wrap15", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 46, fx_2_wrap_values }, -- { "Clipping", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 47 }, -- { "Lighting", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 48 }, -- { "Ambient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 49 }, -- { "FogVertexMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 50, fx_2_fogmode_values }, -- { "ColorVertex", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 51 }, -- { "LocalViewer", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 52 }, -- { "NormalizeNormals", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 53 }, -- -- { "DiffuseMaterialSource", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 54, fx_2_materialcolorsource_values }, -- { "SpecularMaterialSource", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 55, fx_2_materialcolorsource_values }, -- { "AmbientMaterialSource", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 56, fx_2_materialcolorsource_values }, -- { "EmissiveMaterialSource", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 57, fx_2_materialcolorsource_values }, -- -- { "VertexBlend", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 58, fx_2_vertexblend_values }, -- { "ClipPlaneEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 59, fx_2_clipplane_values }, -- { "PointSize", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 60 }, -- { "PointSize_Min", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 61 }, -- { "PointSize_Max", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 62 }, -- { "PointSpriteEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 63 }, -- { "PointScaleEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 64 }, -- { "PointScale_A", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 65 }, -- { "PointScale_B", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 66 }, -- { "PointScale_C", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 67 }, -- -- { "MultiSampleAntialias", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 68 }, -- { "MultiSampleMask", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 69 }, -- { "PatchEdgeStyle", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 70, fx_2_patchedgestyle_values }, -- { "DebugMonitorToken", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 71 }, -- { "IndexedVertexBlendEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 72 }, -- { "ColorWriteEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 73, fx_2_colorwriteenable_values }, -- { "TweenFactor", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 74 }, -- { "BlendOp", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 75, fx_2_blendop_values }, -- { "PositionDegree", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 76, fx_2_degree_values }, -- { "NormalDegree", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 77, fx_2_degree_values }, -- { "ScissorTestEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 78 }, -- { "SlopeScaleDepthBias", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 79 }, -- -- { "AntialiasedLineEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 80 }, -- { "MinTessellationLevel", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 81 }, -- { "MaxTessellationLevel", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 82 }, -- { "AdaptiveTess_X", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 83 }, -- { "AdaptiveTess_Y", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 84 }, -- { "AdaptiveTess_Z", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 85 }, -- { "AdaptiveTess_W", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 86 }, -- { "EnableAdaptiveTessellation",HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 87 }, -- { "TwoSidedStencilMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 88 }, -- { "StencilFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 89, fx_2_stencilcaps_values }, -- { "StencilZFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 90, fx_2_stencilcaps_values }, -- { "StencilPass", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 91, fx_2_stencilcaps_values }, -- { "StencilFunc", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 92, fx_2_cmpfunc_values }, -- -- { "ColorWriteEnable1", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 93, fx_2_colorwriteenable_values }, -- { "ColorWriteEnable2", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 94, fx_2_colorwriteenable_values }, -- { "ColorWriteEnable3", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 95, fx_2_colorwriteenable_values }, -- { "BlendFactor", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 96 }, -- { "SRGBWriteEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 97 }, -- { "DepthBias", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 98 }, -- { "SeparateAlphaBlendEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 99 }, -- { "SrcBlendAlpha", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 100, fx_2_blendmode_values }, -- { "DestBlendAlpha", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 101, fx_2_blendmode_values }, -- { "BlendOpAlpha", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 102, fx_2_blendmode_values }, -- -- { "ColorOp", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 103, fx_2_textureop_values }, -- { "ColorArg0", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 104, fx_2_colorarg_values }, -- { "ColorArg1", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 105, fx_2_colorarg_values }, -- { "ColorArg2", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 106, fx_2_colorarg_values }, -- { "AlphaOp", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 107, fx_2_textureop_values }, -- { "AlphaArg0", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 108, fx_2_colorarg_values }, -- { "AlphaArg1", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 109, fx_2_colorarg_values }, -- { "AlphaArg2", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 110, fx_2_colorarg_values }, -- { "ResultArg", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 111, fx_2_colorarg_values }, -- { "BumpEnvMat00", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 112 }, -- { "BumpEnvMat01", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 113 }, -- { "BumpEnvMat10", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 114 }, -- { "BumpEnvMat11", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 115 }, -- { "TexCoordIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 116 }, -- { "BumpEnvLScale", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 117 }, -- { "BumpEnvLOffset", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 118 }, -- { "TextureTransformFlags", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 119, fx_2_texturetransform_values }, -- { "Constant", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 120 }, -- { "PatchSegments", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 121 }, -- { "FVF", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 122 }, -- -- { "ProjectionTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 123 }, -- { "ViewTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 124 }, -- { "WorldTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 256, 125 }, -- { "TextureTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 8, 126 }, -- -- { "MaterialAmbient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 127 }, -- { "MaterialDiffuse", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 128 }, -- { "MaterialSpecular", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 129 }, -- { "MaterialEmissive", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 130 }, -- { "MaterialPower", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 131 }, -- -- { "LightType", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 132, fx_2_lighttype_values }, -- { "LightDiffuse", HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 133 }, -- { "LightSpecular", HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 134 }, -- { "LightAmbient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 135 }, -- { "LightPosition", HLSL_CLASS_VECTOR, FX_FLOAT, 3, ~0u, 136 }, -- { "LightDirection", HLSL_CLASS_VECTOR, FX_FLOAT, 3, ~0u, 137 }, -- { "LightRange", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 138 }, -- { "LightFalloff", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 139 }, -- { "LightAttenuation0", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 140 }, -- { "LightAttenuation1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 141 }, -- { "LightAttenuation2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 142 }, -- { "LightTheta", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 143 }, -- { "LightPhi", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 144 }, -- { "LightEnable", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 145 }, -- -- { "VertexShader", HLSL_CLASS_SCALAR, FX_VERTEXSHADER, 1, 1, 146 }, -- { "PixelShader", HLSL_CLASS_SCALAR, FX_PIXELSHADER, 1, 1, 147 }, -- -- { "VertexShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 148 }, -- { "VertexShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u, 149 }, -- { "VertexShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 150 }, -- { "VertexShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 151 }, -- { "VertexShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 152 }, -- { "VertexShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 153 }, -- { "VertexShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 154 }, -- { "VertexShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 155 }, -- -- { "PixelShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 156 }, -- { "PixelShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u, 157 }, -- { "PixelShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 158 }, -- { "PixelShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 159 }, -- { "PixelShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 160 }, -- { "PixelShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 161 }, -- { "PixelShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 162 }, -- { "PixelShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 163 }, -- -- { "Texture", HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 261, 164 }, -- { "AddressU", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 165, fx_2_address_values }, -- { "AddressV", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 166, fx_2_address_values }, -- { "AddressW", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 167, fx_2_address_values }, -- { "BorderColor", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 168 }, -- { "MagFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 169, fx_2_filter_values }, -- { "MinFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 170, fx_2_filter_values }, -- { "MipFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 171, fx_2_filter_values }, -- { "MipMapLodBias", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 172 }, -- { "MaxMipLevel", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 173 }, -- { "MaxAnisotropy", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 174 }, -- { "SRGBTexture", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 175 }, -- { "ElementIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 176 }, -+static const struct fx_state fx_2_pass_states[] = -+{ -+ { "ZEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 0, fx_2_zenable_values }, -+ { "FillMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 1, fx_2_fillmode_values }, -+ { "ShadeMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 2, fx_2_shademode_values }, -+ { "ZWriteEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 3 }, -+ { "AlphaTestEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 4 }, -+ { "LastPixel", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 5 }, -+ { "SrcBlend", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 6, fx_2_blendmode_values }, -+ { "DestBlend", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 7, fx_2_blendmode_values }, -+ { "CullMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 8, fx_2_cullmode_values }, -+ { "ZFunc", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 9, fx_2_cmpfunc_values }, -+ { "AlphaRef", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 10 }, -+ { "AlphaFunc", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 11, fx_2_cmpfunc_values }, -+ { "DitherEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 12 }, -+ { "AlphaBlendEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 13 }, -+ { "FogEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 14 }, -+ { "SpecularEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 15 }, -+ { "FogColor", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 16 }, -+ { "FogTableMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 17, fx_2_fogmode_values }, -+ { "FogStart", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 18 }, -+ { "FogEnd", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 19 }, -+ { "FogDensity", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 20 }, -+ { "RangeFogEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 21 }, -+ { "StencilEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 22 }, -+ { "StencilFail", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 23, fx_2_stencilcaps_values }, -+ { "StencilZFail", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 24, fx_2_stencilcaps_values }, -+ { "StencilPass", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 25, fx_2_stencilcaps_values }, -+ { "StencilFunc", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 26, fx_2_cmpfunc_values }, -+ { "StencilRef", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 27 }, -+ { "StencilMask", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 28 }, -+ { "StencilWriteMask", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 29 }, -+ { "TextureFactor", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 30 }, -+ { "Wrap0", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 31, fx_2_wrap_values }, -+ { "Wrap1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 32, fx_2_wrap_values }, -+ { "Wrap2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 33, fx_2_wrap_values }, -+ { "Wrap3", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 34, fx_2_wrap_values }, -+ { "Wrap4", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 35, fx_2_wrap_values }, -+ { "Wrap5", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 36, fx_2_wrap_values }, -+ { "Wrap6", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 37, fx_2_wrap_values }, -+ { "Wrap7", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 38, fx_2_wrap_values }, -+ { "Wrap8", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 39, fx_2_wrap_values }, -+ { "Wrap9", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 40, fx_2_wrap_values }, -+ { "Wrap10", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 41, fx_2_wrap_values }, -+ { "Wrap11", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 42, fx_2_wrap_values }, -+ { "Wrap12", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 43, fx_2_wrap_values }, -+ { "Wrap13", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 44, fx_2_wrap_values }, -+ { "Wrap14", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 45, fx_2_wrap_values }, -+ { "Wrap15", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 46, fx_2_wrap_values }, -+ { "Clipping", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 47 }, -+ { "Lighting", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 48 }, -+ { "Ambient", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 49 }, -+ { "FogVertexMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 50, fx_2_fogmode_values }, -+ { "ColorVertex", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 51 }, -+ { "LocalViewer", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 52 }, -+ { "NormalizeNormals", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 53 }, -+ -+ { "DiffuseMaterialSource", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 54, fx_2_materialcolorsource_values }, -+ { "SpecularMaterialSource", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 55, fx_2_materialcolorsource_values }, -+ { "AmbientMaterialSource", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 56, fx_2_materialcolorsource_values }, -+ { "EmissiveMaterialSource", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 57, fx_2_materialcolorsource_values }, -+ -+ { "VertexBlend", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 58, fx_2_vertexblend_values }, -+ { "ClipPlaneEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 59, fx_2_clipplane_values }, -+ { "PointSize", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 60 }, -+ { "PointSize_Min", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 61 }, -+ { "PointSize_Max", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 62 }, -+ { "PointSpriteEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 63 }, -+ { "PointScaleEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 64 }, -+ { "PointScale_A", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 65 }, -+ { "PointScale_B", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 66 }, -+ { "PointScale_C", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 67 }, -+ -+ { "MultiSampleAntialias", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 68 }, -+ { "MultiSampleMask", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 69 }, -+ { "PatchEdgeStyle", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 70, fx_2_patchedgestyle_values }, -+ { "DebugMonitorToken", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 71 }, -+ { "IndexedVertexBlendEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 72 }, -+ { "ColorWriteEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 73, fx_2_colorwriteenable_values }, -+ { "TweenFactor", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 74 }, -+ { "BlendOp", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 75, fx_2_blendop_values }, -+ { "PositionDegree", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 76, fx_2_degree_values }, -+ { "NormalDegree", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 77, fx_2_degree_values }, -+ { "ScissorTestEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 78 }, -+ { "SlopeScaleDepthBias", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 79 }, -+ -+ { "AntialiasedLineEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 80 }, -+ { "MinTessellationLevel", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 81 }, -+ { "MaxTessellationLevel", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 82 }, -+ { "AdaptiveTess_X", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 83 }, -+ { "AdaptiveTess_Y", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 84 }, -+ { "AdaptiveTess_Z", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 85 }, -+ { "AdaptiveTess_W", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 86 }, -+ { "EnableAdaptiveTessellation",HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 87 }, -+ { "TwoSidedStencilMode", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 88 }, -+ { "StencilFail", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 89, fx_2_stencilcaps_values }, -+ { "StencilZFail", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 90, fx_2_stencilcaps_values }, -+ { "StencilPass", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 91, fx_2_stencilcaps_values }, -+ { "StencilFunc", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 92, fx_2_cmpfunc_values }, -+ -+ { "ColorWriteEnable1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 93, fx_2_colorwriteenable_values }, -+ { "ColorWriteEnable2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 94, fx_2_colorwriteenable_values }, -+ { "ColorWriteEnable3", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 95, fx_2_colorwriteenable_values }, -+ { "BlendFactor", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 96 }, -+ { "SRGBWriteEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 97 }, -+ { "DepthBias", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 98 }, -+ { "SeparateAlphaBlendEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 99 }, -+ { "SrcBlendAlpha", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 100, fx_2_blendmode_values }, -+ { "DestBlendAlpha", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 101, fx_2_blendmode_values }, -+ { "BlendOpAlpha", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 102, fx_2_blendmode_values }, -+ -+ { "ColorOp", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 103, fx_2_textureop_values }, -+ { "ColorArg0", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 104, fx_2_colorarg_values }, -+ { "ColorArg1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 105, fx_2_colorarg_values }, -+ { "ColorArg2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 106, fx_2_colorarg_values }, -+ { "AlphaOp", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 107, fx_2_textureop_values }, -+ { "AlphaArg0", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 108, fx_2_colorarg_values }, -+ { "AlphaArg1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 109, fx_2_colorarg_values }, -+ { "AlphaArg2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 110, fx_2_colorarg_values }, -+ { "ResultArg", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 111, fx_2_colorarg_values }, -+ { "BumpEnvMat00", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 112 }, -+ { "BumpEnvMat01", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 113 }, -+ { "BumpEnvMat10", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 114 }, -+ { "BumpEnvMat11", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 115 }, -+ { "TexCoordIndex", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 116 }, -+ { "BumpEnvLScale", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 117 }, -+ { "BumpEnvLOffset", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 118 }, -+ { "TextureTransformFlags", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 119, fx_2_texturetransform_values }, -+ { "Constant", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 120 }, -+ { "PatchSegments", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 121 }, -+ { "FVF", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 122 }, -+ -+ { "ProjectionTransform", HLSL_CLASS_PASS, HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 123 }, -+ { "ViewTransform", HLSL_CLASS_PASS, HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 124 }, -+ { "WorldTransform", HLSL_CLASS_PASS, HLSL_CLASS_MATRIX, FX_FLOAT, 4, 256, 125 }, -+ { "TextureTransform", HLSL_CLASS_PASS, HLSL_CLASS_MATRIX, FX_FLOAT, 4, 8, 126 }, -+ -+ { "MaterialDiffuse", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 127 }, -+ { "MaterialAmbient", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 128 }, -+ { "MaterialSpecular", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 129 }, -+ { "MaterialEmissive", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 130 }, -+ { "MaterialPower", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 131 }, -+ -+ { "LightType", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 132, fx_2_lighttype_values }, -+ { "LightDiffuse", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 133 }, -+ { "LightSpecular", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 134 }, -+ { "LightAmbient", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 135 }, -+ { "LightPosition", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 3, ~0u, 136 }, -+ { "LightDirection", HLSL_CLASS_PASS, HLSL_CLASS_VECTOR, FX_FLOAT, 3, ~0u, 137 }, -+ { "LightRange", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 138 }, -+ { "LightFalloff", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 139 }, -+ { "LightAttenuation0", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 140 }, -+ { "LightAttenuation1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 141 }, -+ { "LightAttenuation2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 142 }, -+ { "LightTheta", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 143 }, -+ { "LightPhi", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 144 }, -+ { "LightEnable", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 145 }, -+ -+ { "VertexShader", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_VERTEXSHADER, 1, 1, 146 }, -+ { "PixelShader", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_PIXELSHADER, 1, 1, 147 }, -+ -+ { "VertexShaderConstantF", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 148 }, -+ { "VertexShaderConstantB", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u, 149 }, -+ { "VertexShaderConstantI", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 150 }, -+ { "VertexShaderConstant", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 151 }, -+ { "VertexShaderConstant1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 152 }, -+ { "VertexShaderConstant2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 153 }, -+ { "VertexShaderConstant3", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 154 }, -+ { "VertexShaderConstant4", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 155 }, -+ -+ { "PixelShaderConstantF", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 156 }, -+ { "PixelShaderConstantB", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u, 157 }, -+ { "PixelShaderConstantI", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 158 }, -+ { "PixelShaderConstant", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 159 }, -+ { "PixelShaderConstant1", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 160 }, -+ { "PixelShaderConstant2", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 161 }, -+ { "PixelShaderConstant3", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 162 }, -+ { "PixelShaderConstant4", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 163 }, -+ -+ { "Texture", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 261, 164 }, -+ { "AddressU", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 165, fx_2_address_values }, -+ { "AddressV", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 166, fx_2_address_values }, -+ { "AddressW", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 167, fx_2_address_values }, -+ { "BorderColor", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 168 }, -+ { "MagFilter", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 169, fx_2_filter_values }, -+ { "MinFilter", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 170, fx_2_filter_values }, -+ { "MipFilter", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 171, fx_2_filter_values }, -+ { "MipMapLodBias", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 172 }, -+ { "MaxMipLevel", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 173 }, -+ { "MaxAnisotropy", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 174 }, -+ { "SRGBTexture", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 175 }, -+ { "ElementIndex", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 176 }, - }; - --static const struct fx_2_state fx_2_sampler_states[] = --{ -- { "Texture", HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 1, 164 }, -- { "AddressU", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 165, fx_2_address_values }, -- { "AddressV", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 166, fx_2_address_values }, -- { "AddressW", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 167, fx_2_address_values }, -- { "BorderColor", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 168 }, -- { "MagFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 169, fx_2_filter_values }, -- { "MinFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 170, fx_2_filter_values }, -- { "MipFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 171, fx_2_filter_values }, -- { "MipMapLodBias", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 172 }, -- { "MaxMipLevel", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 173 }, -- { "MaxAnisotropy", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 174 }, -- { "SRGBTexture", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 175 }, -- { "ElementIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 176 }, -+static const struct fx_state fx_2_sampler_states[] = -+{ -+ { "Texture", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 1, 164 }, -+ { "AddressU", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 165, fx_2_address_values }, -+ { "AddressV", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 166, fx_2_address_values }, -+ { "AddressW", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 167, fx_2_address_values }, -+ { "BorderColor", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 168 }, -+ { "MagFilter", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 169, fx_2_filter_values }, -+ { "MinFilter", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 170, fx_2_filter_values }, -+ { "MipFilter", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 171, fx_2_filter_values }, -+ { "MipMapLodBias", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 172 }, -+ { "MaxMipLevel", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 173 }, -+ { "MaxAnisotropy", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 174 }, -+ { "SRGBTexture", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 175 }, -+ { "ElementIndex", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 176 }, - }; - - static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) -@@ -1979,12 +1994,21 @@ static void write_fx_2_annotation(struct hlsl_ir_var *var, struct fx_write_conte - put_u32(buffer, value_offset); - } - -+static void write_fx_2_state_assignment(const struct hlsl_ir_var *var, -+ struct hlsl_state_block_entry *entry, struct fx_write_context *fx) -+{ -+ struct hlsl_ctx *ctx = fx->ctx; -+ -+ hlsl_fixme(ctx, &var->loc, "Writing fx_2_0 state assignments is not implemented."); -+} -+ - static const struct fx_write_context_ops fx_2_ops = - { - .write_string = write_fx_2_string, - .write_technique = write_fx_2_technique, - .write_pass = write_fx_2_pass, - .write_annotation = write_fx_2_annotation, -+ .write_state_assignment = write_fx_2_state_assignment, - }; - - static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) -@@ -2047,12 +2071,16 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) - return fx_write_context_cleanup(&fx); - } - -+static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, -+ struct hlsl_state_block_entry *entry, struct fx_write_context *fx); -+ - static const struct fx_write_context_ops fx_4_ops = - { - .write_string = write_fx_4_string, - .write_technique = write_fx_4_technique, - .write_pass = write_fx_4_pass, - .write_annotation = write_fx_4_annotation, -+ .write_state_assignment = write_fx_4_state_assignment, - .are_child_effects_supported = true, - }; - -@@ -2660,18 +2688,7 @@ static const struct rhs_named_value null_values[] = - { NULL } - }; - --static const struct fx_4_state --{ -- const char *name; -- enum hlsl_type_class container; -- enum hlsl_type_class class; -- enum state_property_component_type type; -- unsigned int dimx; -- unsigned int array_size; -- int id; -- const struct rhs_named_value *values; --} --fx_4_states[] = -+static const struct fx_state fx_4_states[] = - { - { "RasterizerState", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_RASTERIZER, 1, 1, 0 }, - { "DepthStencilState", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_DEPTHSTENCIL, 1, 1, 1 }, -@@ -2739,7 +2756,7 @@ fx_4_states[] = - { "ComputeShader", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_COMPUTESHADER, 1, 1, 58 }, - }; - --static const struct fx_4_state fx_5_blend_states[] = -+static const struct fx_state fx_5_blend_states[] = - { - { "AlphaToCoverageEnable", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 1, 36, bool_values }, - { "BlendEnable", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 8, 37, bool_values }, -@@ -2752,45 +2769,61 @@ static const struct fx_4_state fx_5_blend_states[] = - { "RenderTargetWriteMask", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT8, 1, 8, 44 }, - }; - --struct fx_4_state_table -+struct fx_state_table - { -- const struct fx_4_state *ptr; -+ const struct fx_state *ptr; - unsigned int count; - }; - --static struct fx_4_state_table fx_4_get_state_table(enum hlsl_type_class type_class, -+static struct fx_state_table fx_get_state_table(enum hlsl_type_class type_class, - unsigned int major, unsigned int minor) - { -- struct fx_4_state_table table; -+ struct fx_state_table table; - -- if (type_class == HLSL_CLASS_BLEND_STATE && (major == 5 || (major == 4 && minor == 1))) -+ if (major == 2) - { -- table.ptr = fx_5_blend_states; -- table.count = ARRAY_SIZE(fx_5_blend_states); -+ if (type_class == HLSL_CLASS_PASS) -+ { -+ table.ptr = fx_2_pass_states; -+ table.count = ARRAY_SIZE(fx_2_pass_states); -+ } -+ else -+ { -+ table.ptr = fx_2_sampler_states; -+ table.count = ARRAY_SIZE(fx_2_sampler_states); -+ } - } - else - { -- table.ptr = fx_4_states; -- table.count = ARRAY_SIZE(fx_4_states); -+ if (type_class == HLSL_CLASS_BLEND_STATE && (major == 5 || (major == 4 && minor == 1))) -+ { -+ table.ptr = fx_5_blend_states; -+ table.count = ARRAY_SIZE(fx_5_blend_states); -+ } -+ else -+ { -+ table.ptr = fx_4_states; -+ table.count = ARRAY_SIZE(fx_4_states); -+ } - } - - return table; - } - --static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, -+static void resolve_fx_state_block_values(struct hlsl_ir_var *var, - struct hlsl_state_block_entry *entry, struct fx_write_context *fx) - { - const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); - struct replace_state_context replace_context; -- const struct fx_4_state *state = NULL; -+ const struct fx_state *state = NULL; - struct hlsl_type *state_type = NULL; - struct hlsl_ctx *ctx = fx->ctx; - enum hlsl_base_type base_type; -- struct fx_4_state_table table; -+ struct fx_state_table table; - struct hlsl_ir_node *node; - unsigned int i; - -- table = fx_4_get_state_table(type->class, ctx->profile->major_version, ctx->profile->minor_version); -+ table = fx_get_state_table(type->class, ctx->profile->major_version, ctx->profile->minor_version); - - for (i = 0; i < table.count; ++i) - { -@@ -3076,21 +3109,34 @@ static unsigned int decompose_fx_4_state_block(struct hlsl_ir_var *var, struct h - return decompose_fx_4_state_block_expand_array(var, block, entry_index, fx); - } - --static void write_fx_4_state_block(struct hlsl_ir_var *var, unsigned int block_index, -- uint32_t count_offset, struct fx_write_context *fx) -+static void fx_4_decompose_state_blocks(struct hlsl_ir_var *var, struct fx_write_context *fx) - { -- struct vkd3d_bytecode_buffer *buffer = &fx->structured; -+ unsigned int block_count = hlsl_get_multiarray_size(var->data_type); - struct hlsl_state_block *block; -- uint32_t i, count = 0; - -- if (var->state_blocks) -+ if (!var->state_blocks) -+ return; -+ -+ for (unsigned int i = 0; i < block_count; ++i) - { -- block = var->state_blocks[block_index]; -+ block = var->state_blocks[i]; - -- for (i = 0; i < block->count;) -+ for (unsigned int j = 0; j < block->count;) - { -- i += decompose_fx_4_state_block(var, block, i, fx); -+ j += decompose_fx_4_state_block(var, block, j, fx); - } -+ } -+} -+ -+static uint32_t write_state_block(struct hlsl_ir_var *var, unsigned int block_index, -+ struct fx_write_context *fx) -+{ -+ struct hlsl_state_block *block; -+ uint32_t i, count = 0; -+ -+ if (var->state_blocks) -+ { -+ block = var->state_blocks[block_index]; - - for (i = 0; i < block->count; ++i) - { -@@ -3101,27 +3147,29 @@ static void write_fx_4_state_block(struct hlsl_ir_var *var, unsigned int block_i - continue; - - /* Resolve special constant names and property names. */ -- resolve_fx_4_state_block_values(var, entry, fx); -+ resolve_fx_state_block_values(var, entry, fx); - -- write_fx_4_state_assignment(var, entry, fx); -+ write_state_assignment(var, entry, fx); - ++count; - } - } - -- set_u32(buffer, count_offset, count); -+ return count; - } - - static void write_fx_4_state_object_initializer(struct hlsl_ir_var *var, struct fx_write_context *fx) - { - uint32_t elements_count = hlsl_get_multiarray_size(var->data_type), i; - struct vkd3d_bytecode_buffer *buffer = &fx->structured; -- uint32_t count_offset; -+ uint32_t count_offset, count; -+ -+ fx_4_decompose_state_blocks(var, fx); - - for (i = 0; i < elements_count; ++i) - { - count_offset = put_u32(buffer, 0); -- -- write_fx_4_state_block(var, i, count_offset, fx); -+ count = write_state_block(var, i, fx); -+ set_u32(buffer, count_offset, count); - } - } - -@@ -3977,17 +4025,13 @@ static void fx_parse_fx_2_annotations(struct fx_parser *parser, uint32_t count) - vkd3d_string_buffer_printf(&parser->buffer, ">"); - } - --static const struct fx_2_state *fx_2_get_state_by_id(enum hlsl_type_class container, uint32_t id) -+static const struct fx_state *fx_2_get_state_by_id(enum hlsl_type_class container, uint32_t id) - { -- const struct fx_2_state *table; -- unsigned int count; -- -- count = container == HLSL_CLASS_PASS ? ARRAY_SIZE(fx_2_pass_states) : ARRAY_SIZE(fx_2_sampler_states); -- table = container == HLSL_CLASS_PASS ? fx_2_pass_states : fx_2_sampler_states; -+ struct fx_state_table table = fx_get_state_table(container, 2, 0); - - /* State identifiers are sequential, no gaps */ -- if (id >= table[0].id && id <= table[count - 1].id) -- return &table[id - table[0].id]; -+ if (id >= table.ptr[0].id && id <= table.ptr[table.count - 1].id) -+ return &table.ptr[id - table.ptr[0].id]; - - return NULL; - } -@@ -3996,7 +4040,7 @@ static void fx_parse_fx_2_assignment(struct fx_parser *parser, enum hlsl_type_cl - const struct fx_assignment *entry) - { - const struct rhs_named_value *named_value = NULL; -- const struct fx_2_state *state; -+ const struct fx_state *state; - - if ((state = fx_2_get_state_by_id(container, entry->id))) - { -@@ -4700,7 +4744,7 @@ static bool fx_4_object_has_initializer(const struct fx_4_binary_type *type) - - static int fx_4_state_id_compare(const void *a, const void *b) - { -- const struct fx_4_state *state = b; -+ const struct fx_state *state = b; - int id = *(int *)a; - - return id - state->id; -@@ -5186,12 +5230,12 @@ static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32 - }; - const struct rhs_named_value *named_value; - struct fx_5_shader shader = { 0 }; -- struct fx_4_state_table table; -+ struct fx_state_table table; - unsigned int shader_type = 0; - uint32_t i, j, comp_count; -- struct fx_4_state *state; -+ struct fx_state *state; - -- table = fx_4_get_state_table(type_class, parser->version.major, parser->version.minor); -+ table = fx_get_state_table(type_class, parser->version.major, parser->version.minor); - - for (i = 0; i < count; ++i) - { -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index 2b88a04a120..73cd4da906a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -3531,21 +3531,7 @@ static void dump_deref(struct vkd3d_string_buffer *buffer, const struct hlsl_der - - const char *debug_hlsl_writemask(unsigned int writemask) - { -- static const char components[] = {'x', 'y', 'z', 'w'}; -- char string[5]; -- unsigned int i = 0, pos = 0; -- -- VKD3D_ASSERT(!(writemask & ~VKD3DSP_WRITEMASK_ALL)); -- -- while (writemask) -- { -- if (writemask & 1) -- string[pos++] = components[i]; -- writemask >>= 1; -- i++; -- } -- string[pos] = '\0'; -- return vkd3d_dbg_sprintf(".%s", string); -+ return debug_vsir_writemask(writemask); - } - - const char *debug_hlsl_swizzle(uint32_t swizzle, unsigned int size) -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -index bb37f0be6cf..369181cada8 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h -@@ -59,8 +59,7 @@ static inline unsigned int hlsl_swizzle_get_component(uint32_t swizzle, unsigned - - static inline void hlsl_swizzle_set_component(uint32_t *swizzle, unsigned int idx, unsigned int component) - { -- *swizzle &= ~(VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(idx)); -- *swizzle |= component << VKD3D_SHADER_SWIZZLE_SHIFT(idx); -+ vsir_swizzle_set_component(swizzle, idx, component); - } - - enum hlsl_type_class -@@ -309,6 +308,8 @@ struct hlsl_reg - unsigned int writemask; - /* Whether the register has been allocated. */ - bool allocated; -+ /* Currently only used for numeric registers. */ -+ enum vkd3d_shader_register_type type; - }; - - /* Types of instruction nodes for the IR. -@@ -1187,6 +1188,8 @@ struct hlsl_ctx - } constant_defs; - /* 'c' registers where the constants expected by SM2 sincos are stored. */ - struct hlsl_reg d3dsincosconst1, d3dsincosconst2; -+ /* Number of allocated SSA IDs, used in translation to vsir. */ -+ unsigned int ssa_count; - - /* Number of threads to be executed (on the X, Y, and Z dimensions) in a single thread group in - * compute shader profiles. It is set using the numthreads() attribute in the entry point. */ -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index d4e29e16b7c..04bb2d98b26 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -5656,6 +5656,7 @@ static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_a - unsigned int writemask = hlsl_combine_writemasks(available_writemask, - vkd3d_write_mask_from_component_count(reg_size)); - -+ ret.type = VKD3DSPR_TEMP; - ret.id = reg_idx; - ret.writemask = hlsl_combine_writemasks(writemask, - vkd3d_write_mask_from_component_count(component_count)); -@@ -5666,6 +5667,7 @@ static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_a - } - } - -+ ret.type = VKD3DSPR_TEMP; - ret.id = allocator->reg_count; - ret.writemask = vkd3d_write_mask_from_component_count(component_count); - record_allocation(ctx, allocator, allocator->reg_count, -@@ -5692,6 +5694,7 @@ static struct hlsl_reg allocate_register_with_masks(struct hlsl_ctx *ctx, - - record_allocation(ctx, allocator, reg_idx, reg_writemask, first_write, last_read, mode, vip); - -+ ret.type = VKD3DSPR_TEMP; - ret.id = reg_idx; - ret.allocation_size = 1; - ret.writemask = writemask; -@@ -5737,6 +5740,7 @@ static struct hlsl_reg allocate_range(struct hlsl_ctx *ctx, struct register_allo - record_allocation(ctx, allocator, reg_idx + (reg_size / 4), - (1u << (reg_size % 4)) - 1, first_write, last_read, mode, vip); - -+ ret.type = VKD3DSPR_TEMP; - ret.id = reg_idx; - ret.allocation_size = align(reg_size, 4) / 4; - ret.allocated = true; -@@ -5757,20 +5761,30 @@ static struct hlsl_reg allocate_numeric_registers_for_type(struct hlsl_ctx *ctx, - return allocate_range(ctx, allocator, first_write, last_read, reg_size, 0, false); - } - --static const char *debug_register(char class, struct hlsl_reg reg, const struct hlsl_type *type) -+static const char *debug_register(struct hlsl_reg reg, const struct hlsl_type *type) - { - static const char writemask_offset[] = {'w','x','y','z'}; - unsigned int reg_size = type->reg_size[HLSL_REGSET_NUMERIC]; -+ const char *class = "r"; -+ -+ if (reg.type == VKD3DSPR_CONST) -+ class = "c"; -+ else if (reg.type == VKD3DSPR_INPUT) -+ class = "v"; -+ else if (reg.type == VKD3DSPR_OUTPUT) -+ class = "o"; -+ else if (reg.type == VKD3DSPR_SSA) -+ class = "sr"; - - if (reg_size > 4 && !hlsl_type_is_patch_array(type)) - { - if (reg_size & 3) -- return vkd3d_dbg_sprintf("%c%u-%c%u.%c", class, reg.id, class, reg.id + (reg_size / 4), -+ return vkd3d_dbg_sprintf("%s%u-%s%u.%c", class, reg.id, class, reg.id + (reg_size / 4), - writemask_offset[reg_size & 3]); - -- return vkd3d_dbg_sprintf("%c%u-%c%u", class, reg.id, class, reg.id + (reg_size / 4) - 1); -+ return vkd3d_dbg_sprintf("%s%u-%s%u", class, reg.id, class, reg.id + (reg_size / 4) - 1); - } -- return vkd3d_dbg_sprintf("%c%u%s", class, reg.id, debug_hlsl_writemask(reg.writemask)); -+ return vkd3d_dbg_sprintf("%s%u%s", class, reg.id, debug_hlsl_writemask(reg.writemask)); - } - - static bool track_object_components_sampler_dim(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) -@@ -5910,11 +5924,12 @@ static void allocate_instr_temp_register(struct hlsl_ctx *ctx, - struct hlsl_ir_node *instr, struct register_allocator *allocator) - { - unsigned int reg_writemask = 0, dst_writemask = 0; -+ bool is_per_component = false; - - if (instr->reg.allocated || !instr->last_read) - return; - -- if (instr->type == HLSL_IR_EXPR) -+ if (instr->type == HLSL_IR_EXPR && ctx->profile->major_version < 4) - { - switch (hlsl_ir_expr(instr)->op) - { -@@ -5928,20 +5943,42 @@ static void allocate_instr_temp_register(struct hlsl_ctx *ctx, - reg_writemask = ctx->profile->major_version < 3 ? (1 << 3) - 1 : VKD3DSP_WRITEMASK_1; - break; - -+ case HLSL_OP1_EXP2: -+ case HLSL_OP1_LOG2: -+ case HLSL_OP1_RCP: -+ case HLSL_OP1_RSQ: -+ /* These ops can only be written one component at a time in sm1, -+ * so it'll take more than one instruction to fill the variable -+ * and thus we can't use an SSA. -+ * FIXME: We should probably handle this by splitting at the vsir -+ * level instead. */ -+ is_per_component = true; -+ break; -+ - default: - break; - } - } - -+ VKD3D_ASSERT(instr->data_type->class <= HLSL_CLASS_VECTOR); -+ - if (reg_writemask) -- instr->reg = allocate_register_with_masks(ctx, allocator, instr->index, -- instr->last_read, reg_writemask, dst_writemask, 0, false); -- else -+ instr->reg = allocate_register_with_masks(ctx, allocator, -+ instr->index, instr->last_read, reg_writemask, dst_writemask, 0, false); -+ else if (is_per_component) - instr->reg = allocate_numeric_registers_for_type(ctx, allocator, - instr->index, instr->last_read, instr->data_type); -+ else -+ { -+ instr->reg.writemask = vkd3d_write_mask_from_component_count(instr->data_type->e.numeric.dimx); -+ instr->reg.allocation_size = 1; -+ instr->reg.allocated = true; -+ instr->reg.type = VKD3DSPR_SSA; -+ instr->reg.id = ctx->ssa_count++; -+ } - - TRACE("Allocated anonymous expression @%u to %s (liveness %u-%u).\n", instr->index, -- debug_register('r', instr->reg, instr->data_type), instr->index, instr->last_read); -+ debug_register(instr->reg, instr->data_type), instr->index, instr->last_read); - } - - static void allocate_variable_temp_register(struct hlsl_ctx *ctx, -@@ -5966,8 +6003,8 @@ static void allocate_variable_temp_register(struct hlsl_ctx *ctx, - var->regs[HLSL_REGSET_NUMERIC] = allocate_numeric_registers_for_type(ctx, allocator, - var->first_write, var->last_read, var->data_type); - -- TRACE("Allocated %s to %s (liveness %u-%u).\n", var->name, debug_register('r', -- var->regs[HLSL_REGSET_NUMERIC], var->data_type), var->first_write, var->last_read); -+ TRACE("Allocated %s to %s (liveness %u-%u).\n", var->name, -+ debug_register(var->regs[HLSL_REGSET_NUMERIC], var->data_type), var->first_write, var->last_read); - } - } - } -@@ -6051,6 +6088,7 @@ static bool find_constant(struct hlsl_ctx *ctx, const float *f, unsigned int cou - if ((reg->allocated_mask & writemask) == writemask - && !memcmp(f, ®->value.f[j], count * sizeof(float))) - { -+ ret->type = VKD3DSPR_CONST; - ret->id = reg->index; - ret->allocation_size = 1; - ret->writemask = writemask; -@@ -6144,12 +6182,13 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, - if (find_constant(ctx, f, type->e.numeric.dimx, &constant->reg)) - { - TRACE("Reusing already allocated constant %s for @%u.\n", -- debug_register('c', constant->reg, type), instr->index); -+ debug_register(constant->reg, type), instr->index); - break; - } - - constant->reg = allocate_numeric_registers_for_type(ctx, allocator, 1, UINT_MAX, type); -- TRACE("Allocated constant @%u to %s.\n", instr->index, debug_register('c', constant->reg, type)); -+ constant->reg.type = VKD3DSPR_CONST; -+ TRACE("Allocated constant @%u to %s.\n", instr->index, debug_register(constant->reg, type)); - - for (unsigned int x = 0, i = 0; x < 4; ++x) - { -@@ -6246,14 +6285,16 @@ static void allocate_sincos_const_registers(struct hlsl_ctx *ctx, struct hlsl_bl - type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4); - - ctx->d3dsincosconst1 = allocate_numeric_registers_for_type(ctx, allocator, 1, UINT_MAX, type); -- TRACE("Allocated D3DSINCOSCONST1 to %s.\n", debug_register('c', ctx->d3dsincosconst1, type)); -+ ctx->d3dsincosconst1.type = VKD3DSPR_CONST; -+ TRACE("Allocated D3DSINCOSCONST1 to %s.\n", debug_register(ctx->d3dsincosconst1, type)); - record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 0, -1.55009923e-06f, &instr->loc); - record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 1, -2.17013894e-05f, &instr->loc); - record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 2, 2.60416674e-03f, &instr->loc); - record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 3, 2.60416680e-04f, &instr->loc); - - ctx->d3dsincosconst2 = allocate_numeric_registers_for_type(ctx, allocator, 1, UINT_MAX, type); -- TRACE("Allocated D3DSINCOSCONST2 to %s.\n", debug_register('c', ctx->d3dsincosconst2, type)); -+ ctx->d3dsincosconst2.type = VKD3DSPR_CONST; -+ TRACE("Allocated D3DSINCOSCONST2 to %s.\n", debug_register(ctx->d3dsincosconst2, type)); - record_constant(ctx, ctx->d3dsincosconst2.id * 4 + 0, -2.08333340e-02f, &instr->loc); - record_constant(ctx, ctx->d3dsincosconst2.id * 4 + 1, -1.25000000e-01f, &instr->loc); - record_constant(ctx, ctx->d3dsincosconst2.id * 4 + 2, 1.00000000e+00f, &instr->loc); -@@ -6301,12 +6342,13 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi - record_allocation(ctx, &allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX, 0, false); - } - -+ var->regs[HLSL_REGSET_NUMERIC].type = VKD3DSPR_CONST; - var->regs[HLSL_REGSET_NUMERIC].id = reg_idx; - var->regs[HLSL_REGSET_NUMERIC].allocation_size = reg_size / 4; - var->regs[HLSL_REGSET_NUMERIC].writemask = VKD3DSP_WRITEMASK_ALL; - var->regs[HLSL_REGSET_NUMERIC].allocated = true; - TRACE("Allocated reserved %s to %s.\n", var->name, -- debug_register('c', var->regs[HLSL_REGSET_NUMERIC], var->data_type)); -+ debug_register(var->regs[HLSL_REGSET_NUMERIC], var->data_type)); - } - } - -@@ -6322,8 +6364,9 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi - if (!var->regs[HLSL_REGSET_NUMERIC].allocated) - { - var->regs[HLSL_REGSET_NUMERIC] = allocate_range(ctx, &allocator, 1, UINT_MAX, alloc_size, 0, false); -+ var->regs[HLSL_REGSET_NUMERIC].type = VKD3DSPR_CONST; - TRACE("Allocated %s to %s.\n", var->name, -- debug_register('c', var->regs[HLSL_REGSET_NUMERIC], var->data_type)); -+ debug_register(var->regs[HLSL_REGSET_NUMERIC], var->data_type)); - } - } - -@@ -6519,9 +6562,10 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var - - var->regs[HLSL_REGSET_NUMERIC] = allocate_register(ctx, allocator, 1, UINT_MAX, - reg_size, component_count, mode, var->force_align, vip_allocation); -+ var->regs[HLSL_REGSET_NUMERIC].type = output ? VKD3DSPR_OUTPUT : VKD3DSPR_INPUT; - -- TRACE("Allocated %s to %s (mode %d).\n", var->name, debug_register(output ? 'o' : 'v', -- var->regs[HLSL_REGSET_NUMERIC], var->data_type), mode); -+ TRACE("Allocated %s to %s (mode %d).\n", var->name, -+ debug_register(var->regs[HLSL_REGSET_NUMERIC], var->data_type), mode); - } - } - -@@ -7733,8 +7777,6 @@ static void validate_and_record_stream_outputs(struct hlsl_ctx *ctx) - reported_invalid_index = true; - } - } -- -- /* TODO: check that maxvertexcount * outputdatasize <= 1024. */ - } - - static void validate_max_output_size(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, -@@ -8376,7 +8418,7 @@ static void vsir_src_from_hlsl_node(struct vkd3d_shader_src_param *src, - } - else - { -- vsir_register_init(&src->reg, VKD3DSPR_TEMP, vsir_data_type_from_hlsl_instruction(ctx, instr), 1); -+ vsir_register_init(&src->reg, instr->reg.type, vsir_data_type_from_hlsl_instruction(ctx, instr), 1); - src->reg.idx[0].offset = instr->reg.id; - src->reg.dimension = VSIR_DIMENSION_VEC4; - src->swizzle = generate_vsir_get_src_swizzle(instr->reg.writemask, map_writemask); -@@ -8657,7 +8699,7 @@ static void vsir_dst_from_hlsl_node(struct vkd3d_shader_dst_param *dst, - struct hlsl_ctx *ctx, const struct hlsl_ir_node *instr) - { - VKD3D_ASSERT(instr->reg.allocated); -- vsir_dst_param_init(dst, VKD3DSPR_TEMP, vsir_data_type_from_hlsl_instruction(ctx, instr), 1); -+ vsir_dst_param_init(dst, instr->reg.type, vsir_data_type_from_hlsl_instruction(ctx, instr), 1); - dst->reg.idx[0].offset = instr->reg.id; - dst->reg.dimension = VSIR_DIMENSION_VEC4; - dst->write_mask = instr->reg.writemask; -@@ -8767,13 +8809,13 @@ static void sm1_generate_vsir_instr_expr_per_component_instr_op(struct hlsl_ctx - return; - - dst_param = &ins->dst[0]; -- vsir_register_init(&dst_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); -+ vsir_register_init(&dst_param->reg, instr->reg.type, VKD3D_DATA_FLOAT, 1); - dst_param->reg.idx[0].offset = instr->reg.id; - dst_param->reg.dimension = VSIR_DIMENSION_VEC4; - dst_param->write_mask = 1u << i; - - src_param = &ins->src[0]; -- vsir_register_init(&src_param->reg, VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); -+ vsir_register_init(&src_param->reg, operand->reg.type, VKD3D_DATA_FLOAT, 1); - src_param->reg.idx[0].offset = operand->reg.id; - src_param->reg.dimension = VSIR_DIMENSION_VEC4; - c = vsir_swizzle_get_component(src_swizzle, i); -@@ -9372,7 +9414,7 @@ static void generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, - - src_param = &ins->src[0]; - VKD3D_ASSERT(val->type != HLSL_IR_CONSTANT); -- vsir_register_init(&src_param->reg, VKD3DSPR_TEMP, vsir_data_type_from_hlsl_instruction(ctx, val), 1); -+ vsir_register_init(&src_param->reg, val->reg.type, vsir_data_type_from_hlsl_instruction(ctx, val), 1); - src_param->reg.idx[0].offset = val->reg.id; - src_param->reg.dimension = VSIR_DIMENSION_VEC4; - src_param->swizzle = swizzle; -@@ -9528,6 +9570,7 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl - return; - } - -+ program->ssa_count = 0; - program->temp_count = allocate_temp_registers(ctx, entry_func); - if (ctx->result) - return; -@@ -9540,6 +9583,8 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl - list_move_head(&entry_func->body.instrs, &block.instrs); - - sm1_generate_vsir_block(ctx, &entry_func->body, program); -+ -+ program->ssa_count = ctx->ssa_count; - } - - D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) -@@ -12323,6 +12368,8 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl - } - } - -+ program->ssa_count = 0; -+ - if (version.type == VKD3D_SHADER_TYPE_HULL) - generate_vsir_add_program_instruction(ctx, program, - &ctx->patch_constant_func->loc, VKD3DSIH_HS_CONTROL_POINT_PHASE, 0, 0); -@@ -12336,6 +12383,8 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl - - generate_vsir_scan_required_features(ctx, program); - generate_vsir_scan_global_flags(ctx, program, func); -+ -+ program->ssa_count = ctx->ssa_count; - } - - /* For some reason, for matrices, values from default value initializers end -@@ -13523,6 +13572,19 @@ static void process_entry_function(struct hlsl_ctx *ctx, - lower_ir(ctx, lower_matrix_swizzles, body); - lower_ir(ctx, lower_index_loads, body); - -+ if (entry_func->return_var) -+ { -+ if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY) -+ hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, -+ "Geometry shaders cannot return values."); -+ else if (entry_func->return_var->data_type->class != HLSL_CLASS_STRUCT -+ && !entry_func->return_var->semantic.name) -+ hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, -+ "Entry point \"%s\" is missing a return value semantic.", entry_func->func->name); -+ -+ append_output_var_copy(ctx, entry_func, entry_func->return_var); -+ } -+ - for (i = 0; i < entry_func->parameters.count; ++i) - { - var = entry_func->parameters.vars[i]; -@@ -13627,18 +13689,9 @@ static void process_entry_function(struct hlsl_ctx *ctx, - } - } - } -+ - if (entry_func->return_var) - { -- if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY) -- hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, -- "Geometry shaders cannot return values."); -- else if (entry_func->return_var->data_type->class != HLSL_CLASS_STRUCT -- && !entry_func->return_var->semantic.name) -- hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, -- "Entry point \"%s\" is missing a return value semantic.", entry_func->func->name); -- -- append_output_var_copy(ctx, entry_func, entry_func->return_var); -- - if (profile->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func) - ctx->output_control_point_type = entry_func->return_var->data_type; - } -@@ -13882,6 +13935,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry - return ctx->result; - } - -+ vsir_program_trace(&program); -+ - result = d3dbc_compile(&program, config_flags, NULL, &ctab, out, ctx->message_context); - vsir_program_cleanup(&program); - vkd3d_shader_free_shader_code(&ctab); -@@ -13907,6 +13962,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry - return ctx->result; - } - -+ vsir_program_trace(&program); -+ - result = tpf_compile(&program, config_flags, &rdef, out, ctx->message_context); - vsir_program_cleanup(&program); - vkd3d_shader_free_shader_code(&rdef); -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 1429c3a8778..8489d0b5ecb 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -503,6 +503,53 @@ bool vsir_signature_find_sysval(const struct shader_signature *signature, - return false; - } - -+const char *debug_vsir_writemask(unsigned int writemask) -+{ -+ static const char components[] = {'x', 'y', 'z', 'w'}; -+ char string[5]; -+ unsigned int i = 0, pos = 0; -+ -+ VKD3D_ASSERT(!(writemask & ~VKD3DSP_WRITEMASK_ALL)); -+ -+ while (writemask) -+ { -+ if (writemask & 1) -+ string[pos++] = components[i]; -+ writemask >>= 1; -+ i++; -+ } -+ string[pos] = '\0'; -+ return vkd3d_dbg_sprintf(".%s", string); -+} -+ -+static unsigned int vsir_combine_write_masks(unsigned int first, unsigned int second) -+{ -+ unsigned int ret = 0, j = 0; -+ -+ for (unsigned int i = 0; i < VKD3D_VEC4_SIZE; ++i) -+ { -+ if (first & (1u << i)) -+ { -+ if (second & (1u << j++)) -+ ret |= (1u << i); -+ } -+ } -+ -+ return ret; -+} -+ -+static uint32_t vsir_combine_swizzles(uint32_t first, uint32_t second) -+{ -+ uint32_t ret = 0; -+ -+ for (unsigned int i = 0; i < VKD3D_VEC4_SIZE; ++i) -+ { -+ unsigned int s = vsir_swizzle_get_component(second, i); -+ vsir_swizzle_set_component(&ret, i, vsir_swizzle_get_component(first, s)); -+ } -+ return ret; -+} -+ - void vsir_register_init(struct vkd3d_shader_register *reg, enum vkd3d_shader_register_type reg_type, - enum vkd3d_data_type data_type, unsigned int idx_count) - { -@@ -7725,6 +7772,892 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro - return VKD3D_OK; - } - -+ -+/* Distinguishes between instruction sources which are masked, where the used -+ * components of the source are determined by the write mask, and sources which -+ * are not masked, where the used components are pre-defined. -+ * -+ * E.g. "add r0.yz, r1.xyzw, r2.xyzw" uses the .yz components of r1 and r2, and -+ * therefore those sources are considered "masked", but -+ * "dp3 r0.y, r1.xyzw, r2.xyzw" uses the .xyz components. */ -+static bool vsir_src_is_masked(enum vkd3d_shader_opcode opcode, unsigned int src_idx) -+{ -+ switch (opcode) -+ { -+ case VKD3DSIH_ABS: -+ case VKD3DSIH_ACOS: -+ case VKD3DSIH_ADD: -+ case VKD3DSIH_AND: -+ case VKD3DSIH_ASIN: -+ case VKD3DSIH_ATAN: -+ case VKD3DSIH_BFI: -+ case VKD3DSIH_BFREV: -+ case VKD3DSIH_CMP: -+ case VKD3DSIH_CND: -+ case VKD3DSIH_COS: -+ case VKD3DSIH_COUNTBITS: -+ case VKD3DSIH_DADD: /* NB: These are masked, but the mask is double-sized. */ -+ case VKD3DSIH_DDIV: -+ case VKD3DSIH_DFMA: -+ case VKD3DSIH_DIV: -+ case VKD3DSIH_DMAX: -+ case VKD3DSIH_DMIN: -+ case VKD3DSIH_DMOV: -+ case VKD3DSIH_DMOVC: -+ case VKD3DSIH_DMUL: -+ case VKD3DSIH_DRCP: -+ case VKD3DSIH_DSX: -+ case VKD3DSIH_DSX_COARSE: -+ case VKD3DSIH_DSX_FINE: -+ case VKD3DSIH_DSY: -+ case VKD3DSIH_DSY_COARSE: -+ case VKD3DSIH_DSY_FINE: -+ case VKD3DSIH_EQO: -+ case VKD3DSIH_EQU: -+ case VKD3DSIH_EXP: -+ case VKD3DSIH_EXPP: -+ case VKD3DSIH_F16TOF32: -+ case VKD3DSIH_F32TOF16: -+ case VKD3DSIH_FIRSTBIT_HI: -+ case VKD3DSIH_FIRSTBIT_LO: -+ case VKD3DSIH_FIRSTBIT_SHI: -+ case VKD3DSIH_FRC: -+ case VKD3DSIH_FREM: -+ case VKD3DSIH_FTOD: -+ case VKD3DSIH_FTOI: -+ case VKD3DSIH_FTOU: -+ case VKD3DSIH_GEO: -+ case VKD3DSIH_GEU: -+ case VKD3DSIH_HCOS: -+ case VKD3DSIH_HSIN: -+ case VKD3DSIH_HTAN: -+ case VKD3DSIH_IADD: -+ case VKD3DSIH_IBFE: -+ case VKD3DSIH_IDIV: -+ case VKD3DSIH_IEQ: -+ case VKD3DSIH_IGE: -+ case VKD3DSIH_ILT: -+ case VKD3DSIH_IMAD: -+ case VKD3DSIH_IMAX: -+ case VKD3DSIH_IMIN: -+ case VKD3DSIH_IMUL: -+ case VKD3DSIH_INE: -+ case VKD3DSIH_INEG: -+ case VKD3DSIH_ISFINITE: -+ case VKD3DSIH_ISHL: -+ case VKD3DSIH_ISHR: -+ case VKD3DSIH_ISINF: -+ case VKD3DSIH_ISNAN: -+ case VKD3DSIH_ITOD: -+ case VKD3DSIH_ITOF: -+ case VKD3DSIH_ITOI: -+ case VKD3DSIH_LOG: -+ case VKD3DSIH_LOGP: -+ case VKD3DSIH_LRP: -+ case VKD3DSIH_LTO: -+ case VKD3DSIH_LTU: -+ case VKD3DSIH_MAD: -+ case VKD3DSIH_MAX: -+ case VKD3DSIH_MIN: -+ case VKD3DSIH_MOV: -+ case VKD3DSIH_MOVA: -+ case VKD3DSIH_MOVC: -+ case VKD3DSIH_MSAD: /* FIXME: Is this correct? */ -+ case VKD3DSIH_MUL: -+ case VKD3DSIH_NEO: -+ case VKD3DSIH_NEU: -+ case VKD3DSIH_NOT: -+ case VKD3DSIH_OR: -+ case VKD3DSIH_ORD: -+ case VKD3DSIH_PHI: -+ case VKD3DSIH_POW: -+ case VKD3DSIH_QUAD_READ_ACROSS_D: -+ case VKD3DSIH_QUAD_READ_ACROSS_X: -+ case VKD3DSIH_QUAD_READ_ACROSS_Y: -+ case VKD3DSIH_RCP: -+ case VKD3DSIH_ROUND_NE: -+ case VKD3DSIH_ROUND_NI: -+ case VKD3DSIH_ROUND_PI: -+ case VKD3DSIH_ROUND_Z: -+ case VKD3DSIH_RSQ: -+ case VKD3DSIH_SETP: -+ case VKD3DSIH_SGE: -+ case VKD3DSIH_SGN: -+ case VKD3DSIH_SIN: -+ case VKD3DSIH_SINCOS: /* FIXME: Only for sm4. */ -+ case VKD3DSIH_SLT: -+ case VKD3DSIH_SQRT: -+ case VKD3DSIH_SUB: -+ case VKD3DSIH_SWAPC: -+ case VKD3DSIH_TAN: -+ case VKD3DSIH_UBFE: -+ case VKD3DSIH_UDIV: -+ case VKD3DSIH_UGE: -+ case VKD3DSIH_ULT: -+ case VKD3DSIH_UMAX: -+ case VKD3DSIH_UMIN: -+ case VKD3DSIH_UMUL: -+ case VKD3DSIH_UNO: -+ case VKD3DSIH_USHR: -+ case VKD3DSIH_UTOD: -+ case VKD3DSIH_UTOF: -+ case VKD3DSIH_UTOU: -+ case VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL: -+ case VKD3DSIH_WAVE_ACTIVE_BIT_AND: -+ case VKD3DSIH_WAVE_ACTIVE_BIT_OR: -+ case VKD3DSIH_WAVE_ACTIVE_BIT_XOR: -+ case VKD3DSIH_WAVE_ALL_TRUE: -+ case VKD3DSIH_WAVE_ANY_TRUE: -+ case VKD3DSIH_WAVE_OP_ADD: -+ case VKD3DSIH_WAVE_OP_IMAX: -+ case VKD3DSIH_WAVE_OP_IMIN: -+ case VKD3DSIH_WAVE_OP_MAX: -+ case VKD3DSIH_WAVE_OP_MIN: -+ case VKD3DSIH_WAVE_OP_MUL: -+ case VKD3DSIH_WAVE_OP_UMAX: -+ case VKD3DSIH_WAVE_OP_UMIN: -+ case VKD3DSIH_WAVE_READ_LANE_FIRST: -+ case VKD3DSIH_XOR: -+ return true; -+ -+ /* Atomics can't have a writemask. */ -+ case VKD3DSIH_ATOMIC_AND: -+ case VKD3DSIH_ATOMIC_CMP_STORE: -+ case VKD3DSIH_ATOMIC_IADD: -+ case VKD3DSIH_ATOMIC_IMAX: -+ case VKD3DSIH_ATOMIC_IMIN: -+ case VKD3DSIH_ATOMIC_OR: -+ case VKD3DSIH_ATOMIC_UMAX: -+ case VKD3DSIH_ATOMIC_UMIN: -+ case VKD3DSIH_ATOMIC_XOR: -+ case VKD3DSIH_BEM: -+ case VKD3DSIH_BRANCH: -+ case VKD3DSIH_BREAK: -+ case VKD3DSIH_BREAKC: -+ case VKD3DSIH_BREAKP: -+ case VKD3DSIH_BUFINFO: -+ case VKD3DSIH_CALL: -+ case VKD3DSIH_CALLNZ: -+ case VKD3DSIH_CASE: -+ case VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED: /* FIXME: Is this correct? */ -+ case VKD3DSIH_CONTINUE: -+ case VKD3DSIH_CONTINUEP: -+ case VKD3DSIH_CRS: -+ case VKD3DSIH_CUT: -+ case VKD3DSIH_CUT_STREAM: -+ case VKD3DSIH_DCL: -+ case VKD3DSIH_DCL_CONSTANT_BUFFER: -+ case VKD3DSIH_DCL_FUNCTION_BODY: -+ case VKD3DSIH_DCL_FUNCTION_TABLE: -+ case VKD3DSIH_DCL_GLOBAL_FLAGS: -+ case VKD3DSIH_DCL_GS_INSTANCES: -+ case VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT: -+ case VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT: -+ case VKD3DSIH_DCL_HS_MAX_TESSFACTOR: -+ case VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER: -+ case VKD3DSIH_DCL_INDEXABLE_TEMP: -+ case VKD3DSIH_DCL_INDEX_RANGE: -+ case VKD3DSIH_DCL_INPUT: -+ case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT: -+ case VKD3DSIH_DCL_INPUT_PRIMITIVE: -+ case VKD3DSIH_DCL_INPUT_PS: -+ case VKD3DSIH_DCL_INPUT_PS_SGV: -+ case VKD3DSIH_DCL_INPUT_PS_SIV: -+ case VKD3DSIH_DCL_INPUT_SGV: -+ case VKD3DSIH_DCL_INPUT_SIV: -+ case VKD3DSIH_DCL_INTERFACE: -+ case VKD3DSIH_DCL_OUTPUT: -+ case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT: -+ case VKD3DSIH_DCL_OUTPUT_SGV: -+ case VKD3DSIH_DCL_OUTPUT_SIV: -+ case VKD3DSIH_DCL_OUTPUT_TOPOLOGY: -+ case VKD3DSIH_DCL_RESOURCE_RAW: -+ case VKD3DSIH_DCL_RESOURCE_STRUCTURED: -+ case VKD3DSIH_DCL_SAMPLER: -+ case VKD3DSIH_DCL_STREAM: -+ case VKD3DSIH_DCL_TEMPS: -+ case VKD3DSIH_DCL_TESSELLATOR_DOMAIN: -+ case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE: -+ case VKD3DSIH_DCL_TESSELLATOR_PARTITIONING: -+ case VKD3DSIH_DCL_TGSM_RAW: -+ case VKD3DSIH_DCL_TGSM_STRUCTURED: -+ case VKD3DSIH_DCL_THREAD_GROUP: -+ case VKD3DSIH_DCL_UAV_RAW: -+ case VKD3DSIH_DCL_UAV_STRUCTURED: -+ case VKD3DSIH_DCL_UAV_TYPED: -+ case VKD3DSIH_DCL_VERTICES_OUT: -+ case VKD3DSIH_DEF: -+ case VKD3DSIH_DEFAULT: -+ case VKD3DSIH_DEFB: -+ case VKD3DSIH_DEFI: -+ case VKD3DSIH_DEQO: -+ case VKD3DSIH_DGEO: -+ case VKD3DSIH_DISCARD: -+ case VKD3DSIH_DLT: -+ case VKD3DSIH_DNE: -+ case VKD3DSIH_DP2: -+ case VKD3DSIH_DP2ADD: -+ case VKD3DSIH_DP3: -+ case VKD3DSIH_DP4: -+ case VKD3DSIH_DST: -+ case VKD3DSIH_DTOF: -+ case VKD3DSIH_DTOI: -+ case VKD3DSIH_DTOU: -+ case VKD3DSIH_ELSE: -+ case VKD3DSIH_EMIT: -+ case VKD3DSIH_EMIT_STREAM: -+ case VKD3DSIH_ENDIF: -+ case VKD3DSIH_ENDLOOP: -+ case VKD3DSIH_ENDREP: -+ case VKD3DSIH_ENDSWITCH: -+ case VKD3DSIH_FCALL: -+ case VKD3DSIH_HS_CONTROL_POINT_PHASE: -+ case VKD3DSIH_HS_DECLS: -+ case VKD3DSIH_HS_FORK_PHASE: -+ case VKD3DSIH_HS_JOIN_PHASE: -+ case VKD3DSIH_IF: -+ case VKD3DSIH_IFC: -+ /* It's unclear if any mapping is done for the source value. -+ * Does it require replicate swizzle? */ -+ case VKD3DSIH_IMM_ATOMIC_ALLOC: -+ case VKD3DSIH_IMM_ATOMIC_AND: -+ case VKD3DSIH_IMM_ATOMIC_CMP_EXCH: -+ case VKD3DSIH_IMM_ATOMIC_CONSUME: -+ case VKD3DSIH_IMM_ATOMIC_EXCH: -+ case VKD3DSIH_IMM_ATOMIC_IADD: -+ case VKD3DSIH_IMM_ATOMIC_IMAX: -+ case VKD3DSIH_IMM_ATOMIC_IMIN: -+ case VKD3DSIH_IMM_ATOMIC_OR: -+ case VKD3DSIH_IMM_ATOMIC_UMAX: -+ case VKD3DSIH_IMM_ATOMIC_UMIN: -+ case VKD3DSIH_IMM_ATOMIC_XOR: -+ case VKD3DSIH_LABEL: -+ case VKD3DSIH_LOOP: -+ case VKD3DSIH_LIT: -+ case VKD3DSIH_M3x2: -+ case VKD3DSIH_M3x3: -+ case VKD3DSIH_M3x4: -+ case VKD3DSIH_M4x3: -+ case VKD3DSIH_M4x4: -+ case VKD3DSIH_NOP: -+ /* NRM writemask must be .xyz or .xyzw. */ -+ case VKD3DSIH_NRM: -+ case VKD3DSIH_PHASE: -+ case VKD3DSIH_REP: -+ case VKD3DSIH_RET: -+ case VKD3DSIH_RETP: -+ /* Store instructions always require a trivial writemask. */ -+ case VKD3DSIH_STORE_RAW: -+ case VKD3DSIH_STORE_STRUCTURED: -+ case VKD3DSIH_STORE_UAV_TYPED: -+ case VKD3DSIH_SWITCH: -+ case VKD3DSIH_SWITCH_MONOLITHIC: -+ case VKD3DSIH_SYNC: -+ case VKD3DSIH_TEX: -+ case VKD3DSIH_TEXBEM: -+ case VKD3DSIH_TEXBEML: -+ case VKD3DSIH_TEXCOORD: -+ case VKD3DSIH_TEXCRD: -+ case VKD3DSIH_TEXDEPTH: -+ case VKD3DSIH_TEXDP3: -+ case VKD3DSIH_TEXDP3TEX: -+ case VKD3DSIH_TEXKILL: -+ case VKD3DSIH_TEXLD: -+ case VKD3DSIH_TEXLDD: -+ case VKD3DSIH_TEXLDL: -+ case VKD3DSIH_TEXM3x2DEPTH: -+ case VKD3DSIH_TEXM3x2PAD: -+ case VKD3DSIH_TEXM3x2TEX: -+ case VKD3DSIH_TEXM3x3: -+ case VKD3DSIH_TEXM3x3DIFF: -+ case VKD3DSIH_TEXM3x3PAD: -+ case VKD3DSIH_TEXM3x3SPEC: -+ case VKD3DSIH_TEXM3x3TEX: -+ case VKD3DSIH_TEXM3x3VSPEC: -+ case VKD3DSIH_TEXREG2AR: -+ case VKD3DSIH_TEXREG2GB: -+ case VKD3DSIH_TEXREG2RGB: -+ case VKD3DSIH_WAVE_ACTIVE_BALLOT: -+ case VKD3DSIH_WAVE_ALL_BIT_COUNT: -+ case VKD3DSIH_WAVE_IS_FIRST_LANE: -+ case VKD3DSIH_WAVE_PREFIX_BIT_COUNT: -+ return false; -+ -+ case VKD3DSIH_QUAD_READ_LANE_AT: -+ case VKD3DSIH_WAVE_READ_LANE_AT: -+ return (src_idx == 0); -+ -+ /* sm4 resource instructions are an odd case, since they're not actually -+ * per-component. However, the "swizzle" placed on the resource allows -+ * arbitrary destination writemasks to be used. -+ * -+ * This means that for the purposes of the "remapping" done by -+ * temp_allocator_set_dst(), we can basically treat those sources as -+ * "mapped", altering them when we reassign the destination writemask. */ -+ -+ /* FIXME: The documentation seems to say that these instructions behave -+ * this way, but is it correct? -+ * (It's silent about EVAL_*, but presumably they behave the same way.) */ -+ case VKD3DSIH_EVAL_CENTROID: -+ case VKD3DSIH_EVAL_SAMPLE_INDEX: -+ case VKD3DSIH_SAMPLE_INFO: -+ case VKD3DSIH_SAMPLE_POS: -+ return (src_idx == 0); -+ case VKD3DSIH_GATHER4: -+ case VKD3DSIH_GATHER4_C: -+ case VKD3DSIH_GATHER4_C_S: -+ case VKD3DSIH_GATHER4_S: -+ case VKD3DSIH_LD: -+ case VKD3DSIH_LD2DMS: -+ case VKD3DSIH_LD2DMS_S: -+ case VKD3DSIH_LD_RAW: -+ case VKD3DSIH_LD_RAW_S: -+ case VKD3DSIH_LD_S: -+ case VKD3DSIH_LD_UAV_TYPED: -+ case VKD3DSIH_LD_UAV_TYPED_S: -+ case VKD3DSIH_LOD: -+ case VKD3DSIH_RESINFO: -+ case VKD3DSIH_SAMPLE: -+ case VKD3DSIH_SAMPLE_B: -+ case VKD3DSIH_SAMPLE_B_CL_S: -+ case VKD3DSIH_SAMPLE_C: -+ case VKD3DSIH_SAMPLE_CL_S: -+ case VKD3DSIH_SAMPLE_C_CL_S: -+ case VKD3DSIH_SAMPLE_C_LZ: -+ case VKD3DSIH_SAMPLE_C_LZ_S: -+ case VKD3DSIH_SAMPLE_GRAD: -+ case VKD3DSIH_SAMPLE_GRAD_CL_S: -+ case VKD3DSIH_SAMPLE_LOD: -+ case VKD3DSIH_SAMPLE_LOD_S: -+ return (src_idx == 1); -+ case VKD3DSIH_GATHER4_PO: -+ case VKD3DSIH_GATHER4_PO_C: -+ case VKD3DSIH_GATHER4_PO_C_S: -+ case VKD3DSIH_GATHER4_PO_S: -+ case VKD3DSIH_LD_STRUCTURED: -+ case VKD3DSIH_LD_STRUCTURED_S: -+ return (src_idx == 2); -+ -+ case VKD3DSIH_INVALID: -+ case VKD3DSIH_COUNT: -+ break; -+ } -+ -+ vkd3d_unreachable(); -+} -+ -+struct liveness_tracker -+{ -+ struct liveness_tracker_reg -+ { -+ bool written; -+ bool fixed_mask; -+ uint8_t mask; -+ unsigned int first_write, last_access; -+ } *ssa_regs; -+}; -+ -+static void liveness_track_src(struct liveness_tracker *tracker, -+ struct vkd3d_shader_src_param *src, unsigned int index) -+{ -+ for (unsigned int k = 0; k < src->reg.idx_count; ++k) -+ { -+ if (src->reg.idx[k].rel_addr) -+ liveness_track_src(tracker, src->reg.idx[k].rel_addr, index); -+ } -+ -+ if (src->reg.type == VKD3DSPR_SSA) -+ tracker->ssa_regs[src->reg.idx[0].offset].last_access = index; -+} -+ -+static void liveness_track_dst(struct liveness_tracker *tracker, struct vkd3d_shader_dst_param *dst, -+ unsigned int index, const struct vkd3d_shader_version *version, enum vkd3d_shader_opcode opcode) -+{ -+ struct liveness_tracker_reg *reg; -+ -+ for (unsigned int k = 0; k < dst->reg.idx_count; ++k) -+ { -+ if (dst->reg.idx[k].rel_addr) -+ liveness_track_src(tracker, dst->reg.idx[k].rel_addr, index); -+ } -+ -+ if (dst->reg.type == VKD3DSPR_SSA) -+ reg = &tracker->ssa_regs[dst->reg.idx[0].offset]; -+ else -+ return; -+ -+ if (!reg->written) -+ reg->first_write = index; -+ reg->last_access = index; -+ reg->written = true; -+ reg->mask |= dst->write_mask; -+ -+ switch (opcode) -+ { -+ case VKD3DSIH_BEM: -+ case VKD3DSIH_CRS: -+ case VKD3DSIH_DST: -+ case VKD3DSIH_LIT: -+ case VKD3DSIH_M3x2: -+ case VKD3DSIH_M3x3: -+ case VKD3DSIH_M3x4: -+ case VKD3DSIH_M4x3: -+ case VKD3DSIH_M4x4: -+ case VKD3DSIH_NRM: -+ case VKD3DSIH_TEX: -+ case VKD3DSIH_TEXBEM: -+ case VKD3DSIH_TEXBEML: -+ case VKD3DSIH_TEXCOORD: -+ case VKD3DSIH_TEXCRD: -+ case VKD3DSIH_TEXDEPTH: -+ case VKD3DSIH_TEXDP3: -+ case VKD3DSIH_TEXDP3TEX: -+ case VKD3DSIH_TEXLD: -+ case VKD3DSIH_TEXLDD: -+ case VKD3DSIH_TEXLDL: -+ case VKD3DSIH_TEXM3x2DEPTH: -+ case VKD3DSIH_TEXM3x2PAD: -+ case VKD3DSIH_TEXM3x2TEX: -+ case VKD3DSIH_TEXM3x3: -+ case VKD3DSIH_TEXM3x3DIFF: -+ case VKD3DSIH_TEXM3x3PAD: -+ case VKD3DSIH_TEXM3x3SPEC: -+ case VKD3DSIH_TEXM3x3TEX: -+ case VKD3DSIH_TEXM3x3VSPEC: -+ case VKD3DSIH_TEXREG2AR: -+ case VKD3DSIH_TEXREG2GB: -+ case VKD3DSIH_TEXREG2RGB: -+ /* All of these instructions have fixed destinations—they can -+ * in some cases be masked, but the destination cannot be -+ * reallocated to a different set of components. */ -+ case VKD3DSIH_IDIV: -+ case VKD3DSIH_IMUL: -+ case VKD3DSIH_SWAPC: -+ case VKD3DSIH_UDIV: -+ case VKD3DSIH_UMUL: -+ /* These instructions don't have fixed destinations, but they have -+ * multiple destination and are per-component, meaning that the -+ * destination masks for each component have to match. -+ * This is a bit tricky to pull off, so for now we just force -+ * these to have a fixed mask as well. -+ * This assumes that the destination masks are equal to each other -+ * to begin with! */ -+ reg->fixed_mask = true; -+ break; -+ -+ case VKD3DSIH_SINCOS: -+ /* sm1 has a fixed destination like LIT, NRM. -+ * sm4 is two-component and masked, like IMUL. */ -+ if (version->major < 3) -+ { -+ /* We have the additional constraint here that sincos scratches -+ * whichever components of .xyz it doesn't write. We can achieve -+ * this by simply adding those components to reg->mask. */ -+ reg->mask |= 0x7; -+ } -+ reg->fixed_mask = true; -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+static void liveness_tracker_cleanup(struct liveness_tracker *tracker) -+{ -+ vkd3d_free(tracker->ssa_regs); -+} -+ -+static enum vkd3d_result track_liveness(struct vsir_program *program, struct liveness_tracker *tracker) -+{ -+ struct liveness_tracker_reg *regs; -+ unsigned int loop_depth = 0; -+ unsigned int loop_start = 0; -+ -+ memset(tracker, 0, sizeof(*tracker)); -+ -+ if (!(regs = vkd3d_calloc(program->ssa_count, sizeof(*regs)))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ tracker->ssa_regs = regs; -+ -+ for (unsigned int i = 0; i < program->instructions.count; ++i) -+ { -+ const struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; -+ -+ if (ins->opcode == VKD3DSIH_LOOP || ins->opcode == VKD3DSIH_REP) -+ { -+ if (!loop_depth++) -+ loop_start = i; -+ } -+ else if (ins->opcode == VKD3DSIH_ENDLOOP || ins->opcode == VKD3DSIH_ENDREP) -+ { -+ if (!--loop_depth) -+ { -+ /* Go through the allocator, find anything that was touched -+ * during the loop, and extend its liveness to the whole range -+ * of the loop. -+ * This isn't very sophisticated (e.g. we could try to avoid -+ * this for registers first written inside a loop body and only -+ * ever read inside one), but many of the cases that matter are -+ * affected by other optimizations such as copy propagation -+ * anyway. -+ * -+ * This is overkill for SSA registers. If an SSA register is -+ * written in loop L and last read in L, we don't need to touch -+ * its liveness. If it's last read in an inferior loop of L, we -+ * only need to extend its last-read to the end of L. (And it -+ * should be illegal for an SSA value to be read in a block -+ * containing L.) -+ * We don't try to perform this optimization yet, in the name of -+ * maximal simplicity, and also because this code is intended to -+ * be extended to non-SSA values. */ -+ for (unsigned int j = 0; j < program->ssa_count; ++j) -+ { -+ struct liveness_tracker_reg *reg = &tracker->ssa_regs[j]; -+ -+ if (reg->first_write > loop_start) -+ reg->first_write = loop_start; -+ if (reg->last_access < i) -+ reg->last_access = i; -+ } -+ } -+ } -+ -+ for (unsigned int j = 0; j < ins->dst_count; ++j) -+ liveness_track_dst(tracker, &ins->dst[j], i, &program->shader_version, ins->opcode); -+ for (unsigned int j = 0; j < ins->src_count; ++j) -+ liveness_track_src(tracker, &ins->src[j], i); -+ } -+ -+ return VKD3D_OK; -+} -+ -+struct temp_allocator -+{ -+ struct vkd3d_shader_message_context *message_context; -+ struct temp_allocator_reg -+ { -+ uint8_t allocated_mask; -+ uint32_t temp_id; -+ } *ssa_regs; -+ size_t allocated_ssa_count; -+ enum vkd3d_result result; -+}; -+ -+static uint8_t get_available_writemask(const struct temp_allocator *allocator, -+ struct liveness_tracker *tracker, unsigned int first_write, unsigned int last_access, uint32_t temp_id) -+{ -+ uint8_t writemask = VKD3DSP_WRITEMASK_ALL; -+ -+ for (size_t i = 0; i < allocator->allocated_ssa_count; ++i) -+ { -+ const struct temp_allocator_reg *reg = &allocator->ssa_regs[i]; -+ const struct liveness_tracker_reg *liveness_reg = &tracker->ssa_regs[i]; -+ -+ /* We do not overlap if first write == last read: -+ * this is the case where we are allocating the result of that -+ * expression, e.g. "add r0, r0, r1". */ -+ -+ if (reg->temp_id == temp_id -+ && first_write < liveness_reg->last_access -+ && last_access > liveness_reg->first_write) -+ writemask &= ~reg->allocated_mask; -+ -+ if (!writemask) -+ return writemask; -+ } -+ -+ return writemask; -+} -+ -+static void temp_allocator_allocate(struct temp_allocator *allocator, struct liveness_tracker *tracker, -+ struct temp_allocator_reg *reg, const struct liveness_tracker_reg *liveness_reg, uint32_t base_id) -+{ -+ if (!liveness_reg->written) -+ return; -+ -+ for (uint32_t id = base_id;; ++id) -+ { -+ uint8_t available_mask = get_available_writemask(allocator, tracker, -+ liveness_reg->first_write, liveness_reg->last_access, id); -+ -+ if (liveness_reg->fixed_mask) -+ { -+ if ((available_mask & liveness_reg->mask) == liveness_reg->mask) -+ { -+ reg->temp_id = id; -+ reg->allocated_mask = liveness_reg->mask; -+ return; -+ } -+ } -+ else -+ { -+ /* For SSA values the mask is always zero-based and contiguous. -+ * We don't correctly handle cases where it's not, currently. */ -+ VKD3D_ASSERT((liveness_reg->mask | (liveness_reg->mask - 1)) == liveness_reg->mask); -+ -+ if (vkd3d_popcount(available_mask) >= vkd3d_popcount(liveness_reg->mask)) -+ { -+ reg->temp_id = id; -+ reg->allocated_mask = vsir_combine_write_masks(available_mask, liveness_reg->mask); -+ return; -+ } -+ } -+ } -+} -+ -+static void temp_allocator_set_src(struct temp_allocator *allocator, struct vkd3d_shader_src_param *src) -+{ -+ struct temp_allocator_reg *reg; -+ -+ for (unsigned int k = 0; k < src->reg.idx_count; ++k) -+ { -+ if (src->reg.idx[k].rel_addr) -+ temp_allocator_set_src(allocator, src->reg.idx[k].rel_addr); -+ } -+ -+ if (src->reg.type == VKD3DSPR_SSA) -+ reg = &allocator->ssa_regs[src->reg.idx[0].offset]; -+ else -+ return; -+ -+ src->reg.type = VKD3DSPR_TEMP; -+ src->reg.idx[0].offset = reg->temp_id; -+ src->swizzle = vsir_combine_swizzles(vsir_swizzle_from_writemask(reg->allocated_mask), src->swizzle); -+} -+ -+static uint32_t vsir_map_swizzle(uint32_t swizzle, unsigned int writemask) -+{ -+ unsigned int src_component = 0; -+ uint32_t ret = 0; -+ -+ /* Leave replicate swizzles alone; some instructions need them. */ -+ if (swizzle == VKD3D_SHADER_SWIZZLE(X, X, X, X) -+ || swizzle == VKD3D_SHADER_SWIZZLE(Y, Y, Y, Y) -+ || swizzle == VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z) -+ || swizzle == VKD3D_SHADER_SWIZZLE(W, W, W, W)) -+ return swizzle; -+ -+ for (unsigned int dst_component = 0; dst_component < VKD3D_VEC4_SIZE; ++dst_component) -+ { -+ if (writemask & (1u << dst_component)) -+ vsir_swizzle_set_component(&ret, dst_component, vsir_swizzle_get_component(swizzle, src_component++)); -+ } -+ return ret; -+} -+ -+static void vsir_remap_immconst(struct vkd3d_shader_src_param *src, unsigned int writemask) -+{ -+ union vsir_immediate_constant prev = src->reg.u; -+ unsigned int src_component = 0; -+ -+ for (unsigned int dst_component = 0; dst_component < VKD3D_VEC4_SIZE; ++dst_component) -+ { -+ if (writemask & (1u << dst_component)) -+ src->reg.u.immconst_u32[dst_component] = prev.immconst_u32[src_component++]; -+ } -+} -+ -+static void vsir_remap_immconst64(struct vkd3d_shader_src_param *src, unsigned int writemask) -+{ -+ if (writemask == (VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3)) -+ src->reg.u.immconst_u64[1] = src->reg.u.immconst_u64[0]; -+} -+ -+static bool vsir_opcode_is_double(enum vkd3d_shader_opcode opcode) -+{ -+ switch (opcode) -+ { -+ case VKD3DSIH_DADD: -+ case VKD3DSIH_DDIV: -+ case VKD3DSIH_DFMA: -+ case VKD3DSIH_DMAX: -+ case VKD3DSIH_DMIN: -+ case VKD3DSIH_DMOV: -+ case VKD3DSIH_DMOVC: -+ case VKD3DSIH_DMUL: -+ case VKD3DSIH_DRCP: -+ case VKD3DSIH_DEQO: -+ case VKD3DSIH_DGEO: -+ case VKD3DSIH_DLT: -+ case VKD3DSIH_DNE: -+ case VKD3DSIH_DTOF: -+ case VKD3DSIH_DTOI: -+ case VKD3DSIH_DTOU: -+ case VKD3DSIH_FTOD: -+ return true; -+ -+ default: -+ return false; -+ } -+} -+ -+static void temp_allocator_set_dst(struct temp_allocator *allocator, -+ struct vkd3d_shader_dst_param *dst, const struct vkd3d_shader_instruction *ins) -+{ -+ struct temp_allocator_reg *reg; -+ -+ for (unsigned int k = 0; k < dst->reg.idx_count; ++k) -+ { -+ if (dst->reg.idx[k].rel_addr) -+ temp_allocator_set_src(allocator, dst->reg.idx[k].rel_addr); -+ } -+ -+ if (dst->reg.type == VKD3DSPR_SSA) -+ reg = &allocator->ssa_regs[dst->reg.idx[0].offset]; -+ else -+ return; -+ -+ dst->reg.type = VKD3DSPR_TEMP; -+ dst->reg.idx[0].offset = reg->temp_id; -+ if (reg->allocated_mask != dst->write_mask) -+ { -+ dst->write_mask = reg->allocated_mask; -+ -+ if (vsir_opcode_is_double(ins->opcode)) -+ { -+ vkd3d_shader_error(allocator->message_context, &ins->location, -+ VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, "Doubles are not currently handled."); -+ allocator->result = VKD3D_ERROR_NOT_IMPLEMENTED; -+ } -+ -+ for (unsigned int i = 0; i < ins->src_count; ++i) -+ { -+ struct vkd3d_shader_src_param *src = &ins->src[i]; -+ -+ if (vsir_src_is_masked(ins->opcode, i)) -+ { -+ if (src->reg.type == VKD3DSPR_IMMCONST) -+ vsir_remap_immconst(src, dst->write_mask); -+ else if (src->reg.type == VKD3DSPR_IMMCONST64) -+ vsir_remap_immconst64(src, dst->write_mask); -+ else -+ src->swizzle = vsir_map_swizzle(src->swizzle, dst->write_mask); -+ } -+ } -+ } -+} -+ -+enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, -+ struct vkd3d_shader_message_context *message_context) -+{ -+ struct temp_allocator allocator = {0}; -+ struct temp_allocator_reg *regs; -+ struct liveness_tracker tracker; -+ uint32_t temp_count = 0; -+ enum vkd3d_result ret; -+ -+ if (!program->ssa_count) -+ return VKD3D_OK; -+ -+ if ((ret = track_liveness(program, &tracker))) -+ return ret; -+ -+ if (!(regs = vkd3d_calloc(program->ssa_count, sizeof(*regs)))) -+ { -+ liveness_tracker_cleanup(&tracker); -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ } -+ allocator.message_context = message_context; -+ allocator.ssa_regs = regs; -+ -+ for (unsigned int i = 0; i < program->ssa_count; ++i) -+ { -+ const struct liveness_tracker_reg *liveness_reg = &tracker.ssa_regs[i]; -+ struct temp_allocator_reg *reg = &allocator.ssa_regs[i]; -+ -+ temp_allocator_allocate(&allocator, &tracker, reg, liveness_reg, program->temp_count); -+ TRACE("Allocated r%u%s to sr%u (liveness %u-%u).\n", -+ reg->temp_id, debug_vsir_writemask(reg->allocated_mask), i, -+ liveness_reg->first_write, liveness_reg->last_access); -+ ++allocator.allocated_ssa_count; -+ } -+ -+ for (unsigned int i = 0; i < program->instructions.count; ++i) -+ { -+ const struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; -+ -+ /* Make sure we do the srcs first; setting the dst writemask may need -+ * to remap their swizzles. */ -+ for (unsigned int j = 0; j < ins->src_count; ++j) -+ temp_allocator_set_src(&allocator, &ins->src[j]); -+ for (unsigned int j = 0; j < ins->dst_count; ++j) -+ temp_allocator_set_dst(&allocator, &ins->dst[j], ins); -+ } -+ -+ /* Rewrite dcl_temps to reflect the new temp count. -+ * Note that dcl_temps appears once per phase, and should reflect only the -+ * number of temps needed by that phase. -+ * Therefore we iterate backwards through the shader, finding the maximum -+ * register used by any instruction, update the dcl_temps at the beginning -+ * of each phase, and then reset the temp count back to 0 for the next -+ * phase (if any). */ -+ for (int i = program->instructions.count - 1; i >= 0; --i) -+ { -+ struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; -+ -+ if (ins->opcode == VKD3DSIH_DCL_TEMPS) -+ { -+ ins->declaration.count = temp_count; -+ temp_count = 0; -+ continue; -+ } -+ if (temp_count && program->shader_version.major >= 4 -+ && (ins->opcode == VKD3DSIH_HS_CONTROL_POINT_PHASE -+ || ins->opcode == VKD3DSIH_HS_FORK_PHASE -+ || ins->opcode == VKD3DSIH_HS_JOIN_PHASE)) -+ { -+ /* The phase didn't have a dcl_temps instruction, but we added -+ * temps here, so we need to insert one. */ -+ if (!shader_instruction_array_insert_at(&program->instructions, i + 1, 1)) -+ { -+ vkd3d_free(regs); -+ liveness_tracker_cleanup(&tracker); -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ } -+ -+ ins = &program->instructions.elements[i + 1]; -+ vsir_instruction_init(ins, &program->instructions.elements[i].location, VKD3DSIH_DCL_TEMPS); -+ ins->declaration.count = temp_count; -+ temp_count = 0; -+ continue; -+ } -+ -+ /* No need to check sources. If we've produced an unwritten source then -+ * that's a bug somewhere in this pass. */ -+ for (unsigned int j = 0; j < ins->dst_count; ++j) -+ { -+ if (ins->dst[j].reg.type == VKD3DSPR_TEMP) -+ { -+ temp_count = max(temp_count, ins->dst[j].reg.idx[0].offset + 1); -+ program->temp_count = max(program->temp_count, temp_count); -+ } -+ } -+ } -+ -+ if (temp_count && program->shader_version.major >= 4) -+ { -+ struct vkd3d_shader_instruction *ins; -+ -+ if (!shader_instruction_array_insert_at(&program->instructions, 0, 1)) -+ { -+ vkd3d_free(regs); -+ liveness_tracker_cleanup(&tracker); -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ } -+ -+ ins = &program->instructions.elements[0]; -+ vsir_instruction_init(ins, &program->instructions.elements[1].location, VKD3DSIH_DCL_TEMPS); -+ ins->declaration.count = temp_count; -+ } -+ -+ program->ssa_count = 0; -+ -+ vkd3d_free(regs); -+ liveness_tracker_cleanup(&tracker); -+ return allocator.result; -+} -+ - struct validation_context - { - struct vkd3d_shader_message_context *message_context; -@@ -8280,10 +9213,6 @@ static void vsir_validate_descriptor_indices(struct validation_context *ctx, - static void vsir_validate_constbuffer_register(struct validation_context *ctx, - const struct vkd3d_shader_register *reg) - { -- if (reg->precision != VKD3D_SHADER_REGISTER_PRECISION_DEFAULT) -- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, -- "Invalid precision %#x for a CONSTBUFFER register.", reg->precision); -- - if (reg->dimension != VSIR_DIMENSION_VEC4) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, - "Invalid dimension %#x for a CONSTBUFFER register.", reg->dimension); -@@ -8795,6 +9724,11 @@ static void vsir_validate_src_param(struct validation_context *ctx, - [VKD3DSPSM_BIASNEG] = {F32_BIT}, - [VKD3DSPSM_SIGN] = {F32_BIT}, - [VKD3DSPSM_SIGNNEG] = {F32_BIT}, -+ [VKD3DSPSM_COMP] = {F32_BIT}, -+ [VKD3DSPSM_X2] = {F32_BIT}, -+ [VKD3DSPSM_X2NEG] = {F32_BIT}, -+ [VKD3DSPSM_DZ] = {F32_BIT}, -+ [VKD3DSPSM_DW] = {F32_BIT}, - }; - vsir_validate_register(ctx, &src->reg); - -@@ -9455,6 +10389,17 @@ static void vsir_validate_elementwise_operation(struct validation_context *ctx, - } - } - -+static void vsir_validate_double_elementwise_operation(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ static const bool types[VKD3D_DATA_COUNT] = -+ { -+ [VKD3D_DATA_DOUBLE] = true, -+ }; -+ -+ vsir_validate_elementwise_operation(ctx, instruction, types); -+} -+ - static void vsir_validate_float_elementwise_operation(struct validation_context *ctx, - const struct vkd3d_shader_instruction *instruction) - { -@@ -9479,6 +10424,52 @@ static void vsir_validate_logic_elementwise_operation(struct validation_context - vsir_validate_elementwise_operation(ctx, instruction, types); - } - -+static void vsir_validate_comparison_operation(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction, const bool types[VKD3D_DATA_COUNT]) -+{ -+ enum vkd3d_data_type dst_data_type, src_data_type; -+ unsigned int i; -+ -+ if (instruction->dst_count < 1) -+ return; -+ -+ dst_data_type = instruction->dst[0].reg.data_type; -+ -+ if (dst_data_type != VKD3D_DATA_UINT && dst_data_type != VKD3D_DATA_BOOL) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -+ "Invalid data type %#x for result of comparison operation \"%s\" (%#x).", -+ dst_data_type, vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); -+ -+ if (instruction->src_count < 1) -+ return; -+ -+ src_data_type = instruction->src[0].reg.data_type; -+ -+ if (src_data_type >= VKD3D_DATA_COUNT) -+ return; -+ -+ for (i = 1; i < instruction->src_count; ++i) -+ { -+ if (instruction->src[i].reg.data_type != src_data_type) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -+ "Data type %#x for operand %u doesn't match the first operands data type %#x " -+ "for comparison operation \"%s\" (%#x).", -+ instruction->src[i].reg.data_type, i, src_data_type, -+ vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); -+ } -+} -+ -+static void vsir_validate_double_comparison_operation(struct validation_context *ctx, -+ const struct vkd3d_shader_instruction *instruction) -+{ -+ static const bool types[VKD3D_DATA_COUNT] = -+ { -+ [VKD3D_DATA_DOUBLE] = true, -+ }; -+ -+ vsir_validate_comparison_operation(ctx, instruction, types); -+} -+ - static void vsir_validate_branch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction) - { - size_t i; -@@ -10171,6 +11162,16 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ - [VKD3DSIH_ASIN] = {1, 1, vsir_validate_float_elementwise_operation}, - [VKD3DSIH_ATAN] = {1, 1, vsir_validate_float_elementwise_operation}, - [VKD3DSIH_BRANCH] = {0, ~0u, vsir_validate_branch}, -+ [VKD3DSIH_DADD] = {1, 2, vsir_validate_double_elementwise_operation}, -+ [VKD3DSIH_DDIV] = {1, 2, vsir_validate_double_elementwise_operation}, -+ [VKD3DSIH_DFMA] = {1, 3, vsir_validate_double_elementwise_operation}, -+ [VKD3DSIH_DGEO] = {1, 2, vsir_validate_double_comparison_operation}, -+ [VKD3DSIH_DIV] = {1, 2, vsir_validate_float_elementwise_operation}, -+ [VKD3DSIH_DLT] = {1, 2, vsir_validate_double_comparison_operation}, -+ [VKD3DSIH_DMAX] = {1, 2, vsir_validate_double_elementwise_operation}, -+ [VKD3DSIH_DMIN] = {1, 2, vsir_validate_double_elementwise_operation}, -+ [VKD3DSIH_DMOV] = {1, 1, vsir_validate_double_elementwise_operation}, -+ [VKD3DSIH_DMUL] = {1, 2, vsir_validate_double_elementwise_operation}, - [VKD3DSIH_HS_CONTROL_POINT_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, - [VKD3DSIH_HS_DECLS] = {0, 0, vsir_validate_hull_shader_phase}, - [VKD3DSIH_HS_FORK_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, -diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index 08519787b0a..ac9f7412d56 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -55,8 +55,14 @@ struct msl_generator - - struct msl_resource_type_info - { -- size_t read_coord_size; -+ /* The number of coordinates needed to address/sample the resource type. */ -+ size_t coord_size; -+ /* Whether the resource type is an array type. */ - bool array; -+ /* Whether the resource type has a shadow/comparison variant. */ -+ bool comparison; -+ /* The type suffix for the resource type. I.e., the "2d_ms" part of -+ * "texture2d_ms_array" or "depth2d_ms_array". */ - const char *type_suffix; - }; - -@@ -78,17 +84,17 @@ static const struct msl_resource_type_info *msl_get_resource_type_info(enum vkd3 - { - static const struct msl_resource_type_info info[] = - { -- [VKD3D_SHADER_RESOURCE_NONE] = {0, 0, "none"}, -- [VKD3D_SHADER_RESOURCE_BUFFER] = {1, 0, "_buffer"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_1D] = {1, 0, "1d"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2D] = {2, 0, "2d"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2DMS] = {2, 0, "2d_ms"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_3D] = {3, 0, "3d"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_CUBE] = {2, 0, "cube"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY] = {1, 1, "1d_array"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY] = {2, 1, "2d_array"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY] = {2, 1, "2d_ms_array"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY] = {2, 1, "cube_array"}, -+ [VKD3D_SHADER_RESOURCE_NONE] = {0, 0, 0, "none"}, -+ [VKD3D_SHADER_RESOURCE_BUFFER] = {1, 0, 0, "_buffer"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_1D] = {1, 0, 0, "1d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2D] = {2, 0, 1, "2d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2DMS] = {2, 0, 1, "2d_ms"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_3D] = {3, 0, 0, "3d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_CUBE] = {3, 0, 1, "cube"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY] = {1, 1, 0, "1d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY] = {2, 1, 1, "2d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY] = {2, 1, 1, "2d_ms"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY] = {3, 1, 1, "cube"}, - }; - - if (!t || t >= ARRAY_SIZE(info)) -@@ -228,6 +234,35 @@ static const struct vkd3d_shader_descriptor_binding *msl_get_cbv_binding(const s - return NULL; - } - -+static const struct vkd3d_shader_descriptor_binding *msl_get_sampler_binding(const struct msl_generator *gen, -+ unsigned int register_space, unsigned int register_idx) -+{ -+ const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; -+ const struct vkd3d_shader_resource_binding *binding; -+ unsigned int i; -+ -+ if (!interface_info) -+ return NULL; -+ -+ for (i = 0; i < interface_info->binding_count; ++i) -+ { -+ binding = &interface_info->bindings[i]; -+ -+ if (binding->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) -+ continue; -+ if (binding->register_space != register_space) -+ continue; -+ if (binding->register_index != register_idx) -+ continue; -+ if (!msl_check_shader_visibility(gen, binding->shader_visibility)) -+ continue; -+ -+ return &binding->binding; -+ } -+ -+ return NULL; -+} -+ - static const struct vkd3d_shader_descriptor_binding *msl_get_srv_binding(const struct msl_generator *gen, - unsigned int register_space, unsigned int register_idx, enum vkd3d_shader_resource_type resource_type) - { -@@ -267,11 +302,17 @@ static void msl_print_cbv_name(struct vkd3d_string_buffer *buffer, unsigned int - vkd3d_string_buffer_printf(buffer, "descriptors[%u].buf()", binding); - } - -+static void msl_print_sampler_name(struct vkd3d_string_buffer *buffer, unsigned int binding) -+{ -+ vkd3d_string_buffer_printf(buffer, "descriptors[%u].as()", binding); -+} -+ - static void msl_print_srv_name(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, unsigned int binding, -- const struct msl_resource_type_info *resource_type_info, enum vkd3d_data_type resource_data_type) -+ const struct msl_resource_type_info *resource_type_info, enum vkd3d_data_type resource_data_type, bool compare) - { -- vkd3d_string_buffer_printf(buffer, "descriptors[%u].textype_suffix); -+ vkd3d_string_buffer_printf(buffer, "descriptors[%u].as<%s%s%s<", -+ binding, compare ? "depth" : "texture", resource_type_info->type_suffix, -+ resource_type_info->array ? "_array" : ""); - msl_print_resource_datatype(gen, buffer, resource_data_type); - vkd3d_string_buffer_printf(buffer, ">>()"); - } -@@ -877,7 +918,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct - "Internal compiler error: Unhandled resource type %#x.", resource_type); - resource_type_info = msl_get_resource_type_info(VKD3D_SHADER_RESOURCE_TEXTURE_2D); - } -- coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->read_coord_size); -+ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); - - if ((binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) - { -@@ -895,7 +936,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct - read = vkd3d_string_buffer_get(&gen->string_buffers); - - vkd3d_string_buffer_printf(read, "as_type("); -- msl_print_srv_name(read, gen, srv_binding, resource_type_info, data_type); -+ msl_print_srv_name(read, gen, srv_binding, resource_type_info, data_type, false); - vkd3d_string_buffer_printf(read, ".read("); - msl_print_src_with_type(read, gen, &ins->src[0], coord_mask, VKD3D_DATA_UINT); - if (resource_type_info->array) -@@ -920,6 +961,181 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct - msl_dst_cleanup(&dst, &gen->string_buffers); - } - -+static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) -+{ -+ const struct msl_resource_type_info *resource_type_info; -+ unsigned int resource_id, resource_idx, resource_space; -+ bool bias, compare, comparison_sampler, grad, lod_zero; -+ const struct vkd3d_shader_descriptor_binding *binding; -+ unsigned int sampler_id, sampler_idx, sampler_space; -+ const struct vkd3d_shader_descriptor_info1 *d; -+ enum vkd3d_shader_resource_type resource_type; -+ unsigned int srv_binding, sampler_binding; -+ struct vkd3d_string_buffer *sample; -+ enum vkd3d_data_type data_type; -+ uint32_t coord_mask; -+ struct msl_dst dst; -+ -+ bias = ins->opcode == VKD3DSIH_SAMPLE_B; -+ compare = ins->opcode == VKD3DSIH_SAMPLE_C || ins->opcode == VKD3DSIH_SAMPLE_C_LZ; -+ grad = ins->opcode == VKD3DSIH_SAMPLE_GRAD; -+ lod_zero = ins->opcode == VKD3DSIH_SAMPLE_C_LZ; -+ -+ if (vkd3d_shader_instruction_has_texel_offset(ins)) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled texel sample offset."); -+ -+ if (ins->src[1].reg.idx[0].rel_addr || ins->src[1].reg.idx[1].rel_addr -+ || ins->src[2].reg.idx[0].rel_addr || ins->src[2].reg.idx[1].rel_addr) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, -+ "Descriptor indexing is not supported."); -+ -+ resource_id = ins->src[1].reg.idx[0].offset; -+ resource_idx = ins->src[1].reg.idx[1].offset; -+ if ((d = vkd3d_shader_find_descriptor(&gen->program->descriptors, -+ VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_id))) -+ { -+ resource_space = d->register_space; -+ resource_type = d->resource_type; -+ data_type = d->resource_data_type; -+ } -+ else -+ { -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Undeclared resource descriptor %u.", resource_id); -+ resource_space = 0; -+ resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; -+ data_type = VKD3D_DATA_FLOAT; -+ } -+ -+ if (resource_type == VKD3D_SHADER_RESOURCE_BUFFER -+ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS -+ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, -+ "Sampling resource type %#x is not supported.", resource_type); -+ -+ if ((resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_1D || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY) -+ && (bias || grad || lod_zero)) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, -+ "Resource type %#x does not support mipmapping.", resource_type); -+ -+ if (!(resource_type_info = msl_get_resource_type_info(resource_type))) -+ { -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Unhandled resource type %#x.", resource_type); -+ resource_type_info = msl_get_resource_type_info(VKD3D_SHADER_RESOURCE_TEXTURE_2D); -+ } -+ coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); -+ -+ if ((binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) -+ { -+ srv_binding = binding->binding; -+ } -+ else -+ { -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, -+ "No descriptor binding specified for SRV %u (index %u, space %u).", -+ resource_id, resource_idx, resource_space); -+ srv_binding = 0; -+ } -+ -+ sampler_id = ins->src[2].reg.idx[0].offset; -+ sampler_idx = ins->src[2].reg.idx[1].offset; -+ if ((d = vkd3d_shader_find_descriptor(&gen->program->descriptors, -+ VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler_id))) -+ { -+ sampler_space = d->register_space; -+ comparison_sampler = d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE; -+ -+ if (compare) -+ { -+ if (!comparison_sampler) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Sampler %u is not a comparison sampler.", sampler_id); -+ } -+ else -+ { -+ if (comparison_sampler) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Sampler %u is a comparison sampler.", sampler_id); -+ } -+ } -+ else -+ { -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Undeclared sampler descriptor %u.", sampler_id); -+ sampler_space = 0; -+ } -+ -+ if ((binding = msl_get_sampler_binding(gen, sampler_space, sampler_idx))) -+ { -+ sampler_binding = binding->binding; -+ } -+ else -+ { -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, -+ "No descriptor binding specified for sampler %u (index %u, space %u).", -+ sampler_id, sampler_idx, sampler_space); -+ sampler_binding = 0; -+ } -+ -+ msl_dst_init(&dst, gen, ins, &ins->dst[0]); -+ sample = vkd3d_string_buffer_get(&gen->string_buffers); -+ -+ if (ins->dst[0].reg.data_type == VKD3D_DATA_UINT) -+ vkd3d_string_buffer_printf(sample, "as_type("); -+ msl_print_srv_name(sample, gen, srv_binding, resource_type_info, data_type, compare); -+ if (compare) -+ vkd3d_string_buffer_printf(sample, ".sample_compare("); -+ else -+ vkd3d_string_buffer_printf(sample, ".sample("); -+ msl_print_sampler_name(sample, sampler_binding); -+ vkd3d_string_buffer_printf(sample, ", "); -+ msl_print_src_with_type(sample, gen, &ins->src[0], coord_mask, ins->src[0].reg.data_type); -+ if (resource_type_info->array) -+ { -+ vkd3d_string_buffer_printf(sample, ", uint("); -+ msl_print_src_with_type(sample, gen, &ins->src[0], coord_mask + 1, ins->src[0].reg.data_type); -+ vkd3d_string_buffer_printf(sample, ")"); -+ } -+ if (compare) -+ { -+ if (!resource_type_info->comparison) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, -+ "Comparison samplers are not supported with resource type %#x.", resource_type); -+ vkd3d_string_buffer_printf(sample, ", "); -+ msl_print_src_with_type(sample, gen, &ins->src[3], VKD3DSP_WRITEMASK_0, ins->src[3].reg.data_type); -+ } -+ if (grad) -+ { -+ vkd3d_string_buffer_printf(sample, ", gradient%s(", resource_type_info->type_suffix); -+ msl_print_src_with_type(sample, gen, &ins->src[3], coord_mask, ins->src[3].reg.data_type); -+ vkd3d_string_buffer_printf(sample, ", "); -+ msl_print_src_with_type(sample, gen, &ins->src[4], coord_mask, ins->src[4].reg.data_type); -+ vkd3d_string_buffer_printf(sample, ")"); -+ } -+ if (lod_zero) -+ { -+ vkd3d_string_buffer_printf(sample, ", level(0.0f)"); -+ } -+ if (bias) -+ { -+ vkd3d_string_buffer_printf(sample, ", bias("); -+ msl_print_src_with_type(sample, gen, &ins->src[3], VKD3DSP_WRITEMASK_0, ins->src[3].reg.data_type); -+ vkd3d_string_buffer_printf(sample, ")"); -+ } -+ vkd3d_string_buffer_printf(sample, ")"); -+ if (ins->dst[0].reg.data_type == VKD3D_DATA_UINT) -+ vkd3d_string_buffer_printf(sample, ")"); -+ if (!compare) -+ msl_print_swizzle(sample, ins->src[1].swizzle, ins->dst[0].write_mask); -+ -+ msl_print_assignment(gen, &dst, "%s", sample->buffer); -+ -+ vkd3d_string_buffer_release(&gen->string_buffers, sample); -+ msl_dst_cleanup(&dst, &gen->string_buffers); -+} -+ - static void msl_unary_op(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *op) - { - struct msl_src src; -@@ -1086,6 +1302,13 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VKD3DSIH_FTOU: - msl_cast(gen, ins, "uint"); - break; -+ case VKD3DSIH_SAMPLE: -+ case VKD3DSIH_SAMPLE_B: -+ case VKD3DSIH_SAMPLE_C: -+ case VKD3DSIH_SAMPLE_C_LZ: -+ case VKD3DSIH_SAMPLE_GRAD: -+ msl_sample(gen, ins); -+ break; - case VKD3DSIH_GEO: - case VKD3DSIH_IGE: - msl_relop(gen, ins, ">="); -@@ -1631,7 +1854,7 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader - " const device void *ptr;\n" - "\n" - " template\n" -- " constant T &tex() constant\n" -+ " constant T &as() constant\n" - " {\n" - " return reinterpret_cast(this->ptr);\n" - " }\n" -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 0413cd7c344..2bf6f5d9363 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -3522,8 +3522,12 @@ static struct vkd3d_shader_descriptor_binding spirv_compiler_get_descriptor_bind - goto done; - } - -- resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER -- ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE; -+ if (resource_type == VKD3D_SHADER_RESOURCE_NONE) -+ resource_type_flag = 0; -+ else if (resource_type == VKD3D_SHADER_RESOURCE_BUFFER) -+ resource_type_flag = VKD3D_SHADER_BINDING_FLAG_BUFFER; -+ else -+ resource_type_flag = VKD3D_SHADER_BINDING_FLAG_IMAGE; - - if (is_uav_counter) - { -@@ -3567,7 +3571,7 @@ static struct vkd3d_shader_descriptor_binding spirv_compiler_get_descriptor_bind - { - const struct vkd3d_shader_resource_binding *current = &shader_interface->bindings[i]; - -- if (!(current->flags & resource_type_flag)) -+ if ((current->flags & resource_type_flag) != resource_type_flag) - continue; - - if (!spirv_compiler_check_shader_visibility(compiler, current->shader_visibility)) -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index ae3fa1650bf..01af2f6ebbd 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -4463,6 +4463,9 @@ int tpf_compile(struct vsir_program *program, uint64_t config_flags, const struc - size_t i; - int ret; - -+ if ((ret = vsir_allocate_temp_registers(program, message_context))) -+ return ret; -+ - tpf.program = program; - tpf.buffer = NULL; - tpf.stat = &stat; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index cefd9f753a1..07e4b913e6f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -1503,6 +1503,8 @@ struct vsir_program - size_t block_name_count; - }; - -+enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, -+ struct vkd3d_shader_message_context *message_context); - void vsir_program_cleanup(struct vsir_program *program); - int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, - const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, -@@ -1850,6 +1852,8 @@ static inline uint32_t vsir_write_mask_32_from_64(uint32_t write_mask64) - } - } - -+const char *debug_vsir_writemask(unsigned int writemask); -+ - static inline uint32_t vsir_swizzle_64_from_32(uint32_t swizzle32) - { - switch (swizzle32) -@@ -1899,6 +1903,12 @@ static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned - return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK; - } - -+static inline void vsir_swizzle_set_component(uint32_t *swizzle, unsigned int idx, unsigned int component) -+{ -+ *swizzle &= ~(VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(idx)); -+ *swizzle |= component << VKD3D_SHADER_SWIZZLE_SHIFT(idx); -+} -+ - static inline unsigned int vkd3d_compact_swizzle(uint32_t swizzle, uint32_t write_mask) - { - unsigned int i, compacted_swizzle = 0; --- -2.47.2 - diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-5452e79a19c0b895d0c2ac22d3da5595a57.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-5452e79a19c0b895d0c2ac22d3da5595a57.patch deleted file mode 100644 index 7f77dd0d..00000000 --- a/patches/vkd3d-latest/0005-Updated-vkd3d-to-5452e79a19c0b895d0c2ac22d3da5595a57.patch +++ /dev/null @@ -1,699 +0,0 @@ -From d1f9ee11fa62c2f885a6e0c696621fff2961f796 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Wed, 25 Jun 2025 07:27:01 +1000 -Subject: [PATCH] Updated vkd3d to 5452e79a19c0b895d0c2ac22d3da5595a57425eb. - ---- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 5 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 6 +- - libs/vkd3d/libs/vkd3d-shader/glsl.c | 35 +--- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 8 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 15 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 68 +++++++- - libs/vkd3d/libs/vkd3d-shader/msl.c | 153 +++++++++++------- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 30 +--- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 2 + - 9 files changed, 187 insertions(+), 135 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index af5552635cb..21feb75d639 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -590,9 +590,10 @@ static void shader_print_double_literal(struct vkd3d_d3d_asm_compiler *compiler, - static void shader_print_int_literal(struct vkd3d_d3d_asm_compiler *compiler, - const char *prefix, int i, const char *suffix) - { -+ /* Note that we need to handle INT_MIN here as well. */ - if (i < 0) -- vkd3d_string_buffer_printf(&compiler->buffer, "%s-%s%d%s%s", -- prefix, compiler->colours.literal, -i, compiler->colours.reset, suffix); -+ vkd3d_string_buffer_printf(&compiler->buffer, "%s-%s%u%s%s", -+ prefix, compiler->colours.literal, -(unsigned int)i, compiler->colours.reset, suffix); - else - vkd3d_string_buffer_printf(&compiler->buffer, "%s%s%d%s%s", - prefix, compiler->colours.literal, i, compiler->colours.reset, suffix); -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 71fa81ec163..194c51a6ffd 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -4516,7 +4516,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty - is_valid = is_int && !is_bool; - break; - case BINOP_MUL: -- op = is_int ? VKD3DSIH_UMUL : (is_double ? VKD3DSIH_DMUL : VKD3DSIH_MUL); -+ op = is_int ? VKD3DSIH_IMUL_LOW : (is_double ? VKD3DSIH_DMUL : VKD3DSIH_MUL); - is_valid = !is_bool; - break; - case BINOP_OR: -@@ -4603,7 +4603,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - silence_warning = !(flags & ~(FP_NO_NAN | FP_NO_INF | FP_NO_SIGNED_ZEROS | FP_ALLOW_RECIPROCAL)); - break; - case VKD3DSIH_IADD: -- case VKD3DSIH_UMUL: -+ case VKD3DSIH_IMUL_LOW: - case VKD3DSIH_ISHL: - silence_warning = !(flags & ~(OB_NO_UNSIGNED_WRAP | OB_NO_SIGNED_WRAP)); - break; -@@ -4637,7 +4637,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - - dst->type = a->type; - -- if (handler_idx == VKD3DSIH_UMUL || handler_idx == VKD3DSIH_UDIV || handler_idx == VKD3DSIH_IDIV) -+ if (handler_idx == VKD3DSIH_UDIV || handler_idx == VKD3DSIH_IDIV) - { - struct vkd3d_shader_dst_param *dst_params = instruction_dst_params_alloc(ins, 2, sm6); - unsigned int index = code != BINOP_UDIV && code != BINOP_SDIV; -diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index 214632c00eb..40865d842f1 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/glsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -1250,37 +1250,6 @@ static void shader_glsl_movc(struct vkd3d_glsl_generator *gen, const struct vkd3 - glsl_dst_cleanup(&dst, &gen->string_buffers); - } - --static void shader_glsl_mul_extended(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) --{ -- struct glsl_src src[2]; -- struct glsl_dst dst; -- uint32_t mask; -- -- if (ins->dst[0].reg.type != VKD3DSPR_NULL) -- { -- /* FIXME: imulExtended()/umulExtended() from ARB_gpu_shader5/GLSL 4.00+. */ -- mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); -- shader_glsl_print_assignment(gen, &dst, ""); -- glsl_dst_cleanup(&dst, &gen->string_buffers); -- -- vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, -- "Internal compiler error: Unhandled 64-bit integer multiplication."); -- } -- -- if (ins->dst[1].reg.type != VKD3DSPR_NULL) -- { -- mask = glsl_dst_init(&dst, gen, ins, &ins->dst[1]); -- glsl_src_init(&src[0], gen, &ins->src[0], mask); -- glsl_src_init(&src[1], gen, &ins->src[1], mask); -- -- shader_glsl_print_assignment(gen, &dst, "%s * %s", src[0].str->buffer, src[1].str->buffer); -- -- glsl_src_cleanup(&src[1], &gen->string_buffers); -- glsl_src_cleanup(&src[0], &gen->string_buffers); -- glsl_dst_cleanup(&dst, &gen->string_buffers); -- } --} -- - static void shader_glsl_print_sysval_name(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, - enum vkd3d_shader_sysval_semantic sysval, unsigned int idx) - { -@@ -1584,8 +1553,8 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, - case VKD3DSIH_UMIN: - shader_glsl_intrinsic(gen, ins, "min"); - break; -- case VKD3DSIH_IMUL: -- shader_glsl_mul_extended(gen, ins); -+ case VKD3DSIH_IMUL_LOW: -+ shader_glsl_binop(gen, ins, "*"); - break; - case VKD3DSIH_INE: - case VKD3DSIH_NEU: -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -index 73cd4da906a..678ed324919 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c -@@ -3831,11 +3831,11 @@ static void dump_ir_string(struct vkd3d_string_buffer *buffer, const struct hlsl - vkd3d_string_buffer_printf(buffer, "\"%s\"", debugstr_a(string->string)); - } - --static void dump_ir_store(struct vkd3d_string_buffer *buffer, const struct hlsl_ir_store *store) -+static void dump_ir_store(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, const struct hlsl_ir_store *store) - { - vkd3d_string_buffer_printf(buffer, "= ("); - dump_deref(buffer, &store->lhs); -- if (store->writemask != VKD3DSP_WRITEMASK_ALL) -+ if (store->writemask != VKD3DSP_WRITEMASK_ALL && type_is_single_reg(hlsl_deref_get_type(ctx, &store->lhs))) - vkd3d_string_buffer_printf(buffer, "%s", debug_hlsl_writemask(store->writemask)); - vkd3d_string_buffer_printf(buffer, " "); - dump_src(buffer, &store->rhs); -@@ -4033,7 +4033,7 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, - break; - - case HLSL_IR_STORE: -- dump_ir_store(buffer, hlsl_ir_store(instr)); -+ dump_ir_store(ctx, buffer, hlsl_ir_store(instr)); - break; - - case HLSL_IR_SWITCH: -@@ -4124,7 +4124,7 @@ void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new) - const struct hlsl_type *old_type = old->data_type, *new_type = new->data_type; - struct hlsl_src *src, *next; - -- if (hlsl_is_numeric_type(old_type)) -+ if (old_type && hlsl_is_numeric_type(old_type)) - { - VKD3D_ASSERT(hlsl_is_numeric_type(new_type)); - VKD3D_ASSERT(old_type->e.numeric.dimx == new_type->e.numeric.dimx); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index fa3688fad18..40353abd81b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -2559,6 +2559,13 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, - "Variable '%s' is declared as both \"uniform\" and \"static\".", var->name); - -+ if ((modifiers & HLSL_STORAGE_GROUPSHARED) && ctx->profile->type != VKD3D_SHADER_TYPE_COMPUTE) -+ { -+ modifiers &= ~HLSL_STORAGE_GROUPSHARED; -+ hlsl_warning(ctx, &var->loc, VKD3D_SHADER_WARNING_HLSL_IGNORED_MODIFIER, -+ "Ignoring the 'groupshared' modifier in a non-compute shader."); -+ } -+ - if (modifiers & HLSL_STORAGE_GROUPSHARED) - hlsl_fixme(ctx, &var->loc, "Group shared variables."); - -@@ -5144,10 +5151,10 @@ static bool intrinsic_InterlockedXor(struct hlsl_ctx *ctx, - - static void validate_group_barrier_profile(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc) - { -- if (ctx->profile->type != VKD3D_SHADER_TYPE_COMPUTE || hlsl_version_lt(ctx, 5, 0)) -+ if (ctx->profile->type != VKD3D_SHADER_TYPE_COMPUTE) - { - hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, -- "Group barriers can only be used in compute shaders 5.0 or higher."); -+ "Group barriers can only be used in compute shaders."); - } - } - -@@ -5171,10 +5178,10 @@ static bool intrinsic_DeviceMemoryBarrier(struct hlsl_ctx *ctx, - const struct parse_initializer *params, const struct vkd3d_shader_location *loc) - { - if ((ctx->profile->type != VKD3D_SHADER_TYPE_COMPUTE && ctx->profile->type != VKD3D_SHADER_TYPE_PIXEL) -- || hlsl_version_lt(ctx, 5, 0)) -+ || hlsl_version_lt(ctx, 4, 0)) - { - hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, -- "DeviceMemoryBarrier() can only be used in pixel and compute shaders 5.0 or higher."); -+ "DeviceMemoryBarrier() can only be used in compute and pixel shaders 4.0 or higher."); - } - return !!hlsl_block_add_sync(ctx, params->instrs, VKD3DSSF_GLOBAL_UAV, loc); - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 8489d0b5ecb..c26077e43d9 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -208,6 +208,7 @@ const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) - [VKD3DSIH_IMM_ATOMIC_UMIN ] = "imm_atomic_umin", - [VKD3DSIH_IMM_ATOMIC_XOR ] = "imm_atomic_xor", - [VKD3DSIH_IMUL ] = "imul", -+ [VKD3DSIH_IMUL_LOW ] = "imul_low", - [VKD3DSIH_INE ] = "ine", - [VKD3DSIH_INEG ] = "ineg", - [VKD3DSIH_ISFINITE ] = "isfinite", -@@ -1145,6 +1146,24 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro - return VKD3D_OK; - } - -+static enum vkd3d_result vsir_program_lower_imul(struct vsir_program *program, -+ struct vkd3d_shader_instruction *imul, struct vsir_transformation_context *ctx) -+{ -+ if (imul->dst[0].reg.type != VKD3DSPR_NULL) -+ { -+ vkd3d_shader_error(ctx->message_context, &imul->location, -+ VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, -+ "Extended multiplication is not implemented."); -+ return VKD3D_ERROR_NOT_IMPLEMENTED; -+ } -+ -+ imul->dst[0] = imul->dst[1]; -+ imul->dst_count = 1; -+ imul->opcode = VKD3DSIH_IMUL_LOW; -+ -+ return VKD3D_OK; -+} -+ - static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *program, - struct vkd3d_shader_instruction *sincos) - { -@@ -1525,6 +1544,12 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr - vkd3d_shader_instruction_make_nop(ins); - break; - -+ case VKD3DSIH_IMUL: -+ case VKD3DSIH_UMUL: -+ if ((ret = vsir_program_lower_imul(program, ins, ctx)) < 0) -+ return ret; -+ break; -+ - case VKD3DSIH_SINCOS: - if (ins->dst_count == 1) - { -@@ -7841,6 +7866,7 @@ static bool vsir_src_is_masked(enum vkd3d_shader_opcode opcode, unsigned int src - case VKD3DSIH_IMAX: - case VKD3DSIH_IMIN: - case VKD3DSIH_IMUL: -+ case VKD3DSIH_IMUL_LOW: - case VKD3DSIH_INE: - case VKD3DSIH_INEG: - case VKD3DSIH_ISFINITE: -@@ -9610,15 +9636,37 @@ static void vsir_validate_dst_param(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Destination has invalid modifiers %#x.", - dst->modifiers); - -+ if (dst->modifiers & VKD3DSPDM_SATURATE) -+ { -+ switch (dst->reg.data_type) -+ { -+ case VKD3D_DATA_FLOAT: -+ case VKD3D_DATA_DOUBLE: -+ case VKD3D_DATA_HALF: -+ break; -+ -+ default: -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -+ "Invalid data type %#x for destination with saturate modifier.", dst->reg.data_type); -+ break; -+ -+ } -+ } -+ - switch (dst->shift) - { - case 0: -+ break; -+ - case 1: - case 2: - case 3: - case 13: - case 14: - case 15: -+ if (dst->reg.data_type != VKD3D_DATA_FLOAT) -+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -+ "Invalid data type %#x for destination with shift.", dst->reg.data_type); - break; - - default: -@@ -9717,7 +9765,7 @@ static void vsir_validate_src_param(struct validation_context *ctx, - { - uint32_t data_type_mask; - } -- src_modifier_data[] = -+ src_modifier_data[VKD3DSPSM_COUNT] = - { - [VKD3DSPSM_NEG] = {F64_BIT | F32_BIT | F16_BIT | I32_BIT | U64_BIT | U32_BIT | U16_BIT}, - [VKD3DSPSM_BIAS] = {F32_BIT}, -@@ -9729,7 +9777,15 @@ static void vsir_validate_src_param(struct validation_context *ctx, - [VKD3DSPSM_X2NEG] = {F32_BIT}, - [VKD3DSPSM_DZ] = {F32_BIT}, - [VKD3DSPSM_DW] = {F32_BIT}, -+ [VKD3DSPSM_ABS] = {F64_BIT | F32_BIT | F16_BIT}, -+ [VKD3DSPSM_ABSNEG] = {F64_BIT | F32_BIT | F16_BIT}, -+ /* This doesn't make a lot of sense. NOT is used only by D3DBC, and -+ * apparently only for IF instructions reading from a CONSTBOOL register. -+ * However, currently the D3DBC parser generates those registers of -+ * type float, so for the moment let's allow that. */ -+ [VKD3DSPSM_NOT] = {F32_BIT}, - }; -+ - vsir_validate_register(ctx, &src->reg); - - if (src->swizzle & ~0x03030303u) -@@ -9744,7 +9800,7 @@ static void vsir_validate_src_param(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", - src->modifiers); - -- if (src->modifiers < ARRAY_SIZE(src_modifier_data) && src_modifier_data[src->modifiers].data_type_mask) -+ if (src->modifiers != VKD3DSPSM_NONE && src->modifiers < ARRAY_SIZE(src_modifier_data)) - { - if (!(src_modifier_data[src->modifiers].data_type_mask & (1u << src->reg.data_type))) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, -@@ -11172,6 +11228,14 @@ static const struct vsir_validator_instruction_desc vsir_validator_instructions[ - [VKD3DSIH_DMIN] = {1, 2, vsir_validate_double_elementwise_operation}, - [VKD3DSIH_DMOV] = {1, 1, vsir_validate_double_elementwise_operation}, - [VKD3DSIH_DMUL] = {1, 2, vsir_validate_double_elementwise_operation}, -+ [VKD3DSIH_DNE] = {1, 2, vsir_validate_double_comparison_operation}, -+ [VKD3DSIH_DRCP] = {1, 1, vsir_validate_double_elementwise_operation}, -+ [VKD3DSIH_DSX] = {1, 1, vsir_validate_float_elementwise_operation}, -+ [VKD3DSIH_DSX_COARSE] = {1, 1, vsir_validate_float_elementwise_operation}, -+ [VKD3DSIH_DSX_FINE] = {1, 1, vsir_validate_float_elementwise_operation}, -+ [VKD3DSIH_DSY] = {1, 1, vsir_validate_float_elementwise_operation}, -+ [VKD3DSIH_DSY_COARSE] = {1, 1, vsir_validate_float_elementwise_operation}, -+ [VKD3DSIH_DSY_FINE] = {1, 1, vsir_validate_float_elementwise_operation}, - [VKD3DSIH_HS_CONTROL_POINT_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, - [VKD3DSIH_HS_DECLS] = {0, 0, vsir_validate_hull_shader_phase}, - [VKD3DSIH_HS_FORK_PHASE] = {0, 0, vsir_validate_hull_shader_phase}, -diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index ac9f7412d56..87c9e989ea4 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -61,6 +61,8 @@ struct msl_resource_type_info - bool array; - /* Whether the resource type has a shadow/comparison variant. */ - bool comparison; -+ /* Whether the resource type supports texel sample offsets. */ -+ bool offset; - /* The type suffix for the resource type. I.e., the "2d_ms" part of - * "texture2d_ms_array" or "depth2d_ms_array". */ - const char *type_suffix; -@@ -84,17 +86,17 @@ static const struct msl_resource_type_info *msl_get_resource_type_info(enum vkd3 - { - static const struct msl_resource_type_info info[] = - { -- [VKD3D_SHADER_RESOURCE_NONE] = {0, 0, 0, "none"}, -- [VKD3D_SHADER_RESOURCE_BUFFER] = {1, 0, 0, "_buffer"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_1D] = {1, 0, 0, "1d"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2D] = {2, 0, 1, "2d"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2DMS] = {2, 0, 1, "2d_ms"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_3D] = {3, 0, 0, "3d"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_CUBE] = {3, 0, 1, "cube"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY] = {1, 1, 0, "1d"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY] = {2, 1, 1, "2d"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY] = {2, 1, 1, "2d_ms"}, -- [VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY] = {3, 1, 1, "cube"}, -+ [VKD3D_SHADER_RESOURCE_NONE] = {0, 0, 0, 0, "none"}, -+ [VKD3D_SHADER_RESOURCE_BUFFER] = {1, 0, 0, 0, "_buffer"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_1D] = {1, 0, 0, 0, "1d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2D] = {2, 0, 1, 1, "2d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2DMS] = {2, 0, 1, 0, "2d_ms"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_3D] = {3, 0, 0, 1, "3d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_CUBE] = {3, 0, 1, 0, "cube"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY] = {1, 1, 0, 0, "1d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY] = {2, 1, 1, 1, "2d"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY] = {2, 1, 1, 0, "2d_ms"}, -+ [VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY] = {3, 1, 1, 0, "cube"}, - }; - - if (!t || t >= ARRAY_SIZE(info)) -@@ -865,6 +867,27 @@ static void msl_default(struct msl_generator *gen) - vkd3d_string_buffer_printf(gen->buffer, "default:\n"); - } - -+static void msl_print_texel_offset(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, -+ unsigned int offset_size, const struct vkd3d_shader_texel_offset *offset) -+{ -+ switch (offset_size) -+ { -+ case 1: -+ vkd3d_string_buffer_printf(buffer, "%d", offset->u); -+ break; -+ case 2: -+ vkd3d_string_buffer_printf(buffer, "int2(%d, %d)", offset->u, offset->v); -+ break; -+ default: -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -+ "Internal compiler error: Invalid texel offset size %u.", offset_size); -+ /* fall through */ -+ case 3: -+ vkd3d_string_buffer_printf(buffer, "int3(%d, %d, %d)", offset->u, offset->v, offset->w); -+ break; -+ } -+} -+ - static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) - { - const struct msl_resource_type_info *resource_type_info; -@@ -963,9 +986,10 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct - - static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) - { -+ bool bias, compare, comparison_sampler, dynamic_offset, gather, grad, lod, lod_zero, offset; - const struct msl_resource_type_info *resource_type_info; -+ const struct vkd3d_shader_src_param *resource, *sampler; - unsigned int resource_id, resource_idx, resource_space; -- bool bias, compare, comparison_sampler, grad, lod_zero; - const struct vkd3d_shader_descriptor_binding *binding; - unsigned int sampler_id, sampler_idx, sampler_space; - const struct vkd3d_shader_descriptor_info1 *d; -@@ -973,25 +997,31 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst - unsigned int srv_binding, sampler_binding; - struct vkd3d_string_buffer *sample; - enum vkd3d_data_type data_type; -+ unsigned int component_idx; - uint32_t coord_mask; - struct msl_dst dst; - - bias = ins->opcode == VKD3DSIH_SAMPLE_B; -- compare = ins->opcode == VKD3DSIH_SAMPLE_C || ins->opcode == VKD3DSIH_SAMPLE_C_LZ; -+ compare = ins->opcode == VKD3DSIH_GATHER4_C || ins->opcode == VKD3DSIH_SAMPLE_C -+ || ins->opcode == VKD3DSIH_SAMPLE_C_LZ; -+ dynamic_offset = ins->opcode == VKD3DSIH_GATHER4_PO; -+ gather = ins->opcode == VKD3DSIH_GATHER4 || ins->opcode == VKD3DSIH_GATHER4_C -+ || ins->opcode == VKD3DSIH_GATHER4_PO; - grad = ins->opcode == VKD3DSIH_SAMPLE_GRAD; -+ lod = ins->opcode == VKD3DSIH_SAMPLE_LOD; - lod_zero = ins->opcode == VKD3DSIH_SAMPLE_C_LZ; -+ offset = dynamic_offset || vkd3d_shader_instruction_has_texel_offset(ins); - -- if (vkd3d_shader_instruction_has_texel_offset(ins)) -- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -- "Internal compiler error: Unhandled texel sample offset."); -+ resource = &ins->src[1 + dynamic_offset]; -+ sampler = &ins->src[2 + dynamic_offset]; - -- if (ins->src[1].reg.idx[0].rel_addr || ins->src[1].reg.idx[1].rel_addr -- || ins->src[2].reg.idx[0].rel_addr || ins->src[2].reg.idx[1].rel_addr) -+ if (resource->reg.idx[0].rel_addr || resource->reg.idx[1].rel_addr -+ || sampler->reg.idx[0].rel_addr || sampler->reg.idx[1].rel_addr) - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, - "Descriptor indexing is not supported."); - -- resource_id = ins->src[1].reg.idx[0].offset; -- resource_idx = ins->src[1].reg.idx[1].offset; -+ resource_id = resource->reg.idx[0].offset; -+ resource_idx = resource->reg.idx[1].offset; - if ((d = vkd3d_shader_find_descriptor(&gen->program->descriptors, - VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_id))) - { -@@ -1015,10 +1045,15 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst - "Sampling resource type %#x is not supported.", resource_type); - - if ((resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_1D || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY) -- && (bias || grad || lod_zero)) -+ && (bias || grad || lod || lod_zero)) - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, - "Resource type %#x does not support mipmapping.", resource_type); - -+ if ((resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_1D || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY -+ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_3D) && gather) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, -+ "Resource type %#x does not support gather operations.", resource_type); -+ - if (!(resource_type_info = msl_get_resource_type_info(resource_type))) - { - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -@@ -1039,8 +1074,8 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst - srv_binding = 0; - } - -- sampler_id = ins->src[2].reg.idx[0].offset; -- sampler_idx = ins->src[2].reg.idx[1].offset; -+ sampler_id = sampler->reg.idx[0].offset; -+ sampler_idx = sampler->reg.idx[1].offset; - if ((d = vkd3d_shader_find_descriptor(&gen->program->descriptors, - VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler_id))) - { -@@ -1085,7 +1120,11 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst - if (ins->dst[0].reg.data_type == VKD3D_DATA_UINT) - vkd3d_string_buffer_printf(sample, "as_type("); - msl_print_srv_name(sample, gen, srv_binding, resource_type_info, data_type, compare); -- if (compare) -+ if (gather && compare) -+ vkd3d_string_buffer_printf(sample, ".gather_compare("); -+ else if (gather) -+ vkd3d_string_buffer_printf(sample, ".gather("); -+ else if (compare) - vkd3d_string_buffer_printf(sample, ".sample_compare("); - else - vkd3d_string_buffer_printf(sample, ".sample("); -@@ -1118,17 +1157,40 @@ static void msl_sample(struct msl_generator *gen, const struct vkd3d_shader_inst - { - vkd3d_string_buffer_printf(sample, ", level(0.0f)"); - } -+ else if (lod) -+ { -+ vkd3d_string_buffer_printf(sample, ", level("); -+ msl_print_src_with_type(sample, gen, &ins->src[3], VKD3DSP_WRITEMASK_0, ins->src[3].reg.data_type); -+ vkd3d_string_buffer_printf(sample, ")"); -+ } - if (bias) - { - vkd3d_string_buffer_printf(sample, ", bias("); - msl_print_src_with_type(sample, gen, &ins->src[3], VKD3DSP_WRITEMASK_0, ins->src[3].reg.data_type); - vkd3d_string_buffer_printf(sample, ")"); - } -+ if (offset) -+ { -+ if (!resource_type_info->offset) -+ msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, -+ "Texel sample offsets are not supported with resource type %#x.", resource_type); -+ vkd3d_string_buffer_printf(sample, ", "); -+ if (dynamic_offset) -+ msl_print_src_with_type(sample, gen, &ins->src[1], coord_mask, ins->src[1].reg.data_type); -+ else -+ msl_print_texel_offset(sample, gen, resource_type_info->coord_size, &ins->texel_offset); -+ } -+ if (gather && !compare && (component_idx = vsir_swizzle_get_component(sampler->swizzle, 0))) -+ { -+ if (!offset && resource_type_info->offset) -+ vkd3d_string_buffer_printf(sample, ", int2(0)"); -+ vkd3d_string_buffer_printf(sample, ", component::%c", "xyzw"[component_idx]); -+ } - vkd3d_string_buffer_printf(sample, ")"); - if (ins->dst[0].reg.data_type == VKD3D_DATA_UINT) - vkd3d_string_buffer_printf(sample, ")"); -- if (!compare) -- msl_print_swizzle(sample, ins->src[1].swizzle, ins->dst[0].write_mask); -+ if (!compare || gather) -+ msl_print_swizzle(sample, resource->swizzle, ins->dst[0].write_mask); - - msl_print_assignment(gen, &dst, "%s", sample->buffer); - -@@ -1191,37 +1253,6 @@ static void msl_movc(struct msl_generator *gen, const struct vkd3d_shader_instru - msl_dst_cleanup(&dst, &gen->string_buffers); - } - --static void msl_mul64(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) --{ -- struct msl_src src[2]; -- struct msl_dst dst; -- uint32_t mask; -- -- if (ins->dst[0].reg.type != VKD3DSPR_NULL) -- { -- /* TODO: mulhi(). */ -- mask = msl_dst_init(&dst, gen, ins, &ins->dst[0]); -- msl_print_assignment(gen, &dst, ""); -- msl_dst_cleanup(&dst, &gen->string_buffers); -- -- msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, -- "Internal compiler error: Unhandled 64-bit integer multiplication."); -- } -- -- if (ins->dst[1].reg.type != VKD3DSPR_NULL) -- { -- mask = msl_dst_init(&dst, gen, ins, &ins->dst[1]); -- msl_src_init(&src[0], gen, &ins->src[0], mask); -- msl_src_init(&src[1], gen, &ins->src[1], mask); -- -- msl_print_assignment(gen, &dst, "%s * %s", src[0].str->buffer, src[1].str->buffer); -- -- msl_src_cleanup(&src[1], &gen->string_buffers); -- msl_src_cleanup(&src[0], &gen->string_buffers); -- msl_dst_cleanup(&dst, &gen->string_buffers); -- } --} -- - static void msl_ret(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) - { - msl_print_indent(gen->buffer, gen->indent); -@@ -1302,11 +1333,15 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VKD3DSIH_FTOU: - msl_cast(gen, ins, "uint"); - break; -+ case VKD3DSIH_GATHER4: -+ case VKD3DSIH_GATHER4_C: -+ case VKD3DSIH_GATHER4_PO: - case VKD3DSIH_SAMPLE: - case VKD3DSIH_SAMPLE_B: - case VKD3DSIH_SAMPLE_C: - case VKD3DSIH_SAMPLE_C_LZ: - case VKD3DSIH_SAMPLE_GRAD: -+ case VKD3DSIH_SAMPLE_LOD: - msl_sample(gen, ins); - break; - case VKD3DSIH_GEO: -@@ -1337,8 +1372,8 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VKD3DSIH_MIN: - msl_intrinsic(gen, ins, "min"); - break; -- case VKD3DSIH_IMUL: -- msl_mul64(gen, ins); -+ case VKD3DSIH_IMUL_LOW: -+ msl_binop(gen, ins, "*"); - break; - case VKD3DSIH_INE: - case VKD3DSIH_NEU: -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 2bf6f5d9363..7eddf47151b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -7534,6 +7534,7 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru - {VKD3DSIH_FREM, SpvOpFRem}, - {VKD3DSIH_FTOD, SpvOpFConvert}, - {VKD3DSIH_IADD, SpvOpIAdd}, -+ {VKD3DSIH_IMUL_LOW, SpvOpIMul}, - {VKD3DSIH_INEG, SpvOpSNegate}, - {VKD3DSIH_ISHL, SpvOpShiftLeftLogical}, - {VKD3DSIH_ISHR, SpvOpShiftRightArithmetic}, -@@ -8019,30 +8020,6 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler, - spirv_compiler_emit_store_dst(compiler, dst, val_id); - } - --static void spirv_compiler_emit_imul(struct spirv_compiler *compiler, -- const struct vkd3d_shader_instruction *instruction) --{ -- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- const struct vkd3d_shader_dst_param *dst = instruction->dst; -- const struct vkd3d_shader_src_param *src = instruction->src; -- uint32_t type_id, val_id, src0_id, src1_id; -- -- if (dst[0].reg.type != VKD3DSPR_NULL) -- FIXME("Extended multiplies not implemented.\n"); /* SpvOpSMulExtended/SpvOpUMulExtended */ -- -- if (dst[1].reg.type == VKD3DSPR_NULL) -- return; -- -- 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); -- -- val_id = vkd3d_spirv_build_op_imul(builder, type_id, src0_id, src1_id); -- -- spirv_compiler_emit_store_dst(compiler, &dst[1], val_id); --} -- - static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) - { -@@ -10671,6 +10648,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_FREM: - case VKD3DSIH_FTOD: - case VKD3DSIH_IADD: -+ case VKD3DSIH_IMUL_LOW: - case VKD3DSIH_INEG: - case VKD3DSIH_ISHL: - case VKD3DSIH_ISHR: -@@ -10735,10 +10713,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - case VKD3DSIH_RCP: - spirv_compiler_emit_rcp(compiler, instruction); - break; -- case VKD3DSIH_IMUL: -- case VKD3DSIH_UMUL: -- spirv_compiler_emit_imul(compiler, instruction); -- break; - case VKD3DSIH_IMAD: - spirv_compiler_emit_imad(compiler, instruction); - break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 07e4b913e6f..254303f1bbb 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -183,6 +183,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_WARNING_HLSL_NON_FINITE_RESULT = 5304, - VKD3D_SHADER_WARNING_HLSL_IGNORED_ATTRIBUTE = 5305, - VKD3D_SHADER_WARNING_HLSL_IGNORED_DEFAULT_VALUE = 5306, -+ VKD3D_SHADER_WARNING_HLSL_IGNORED_MODIFIER = 5307, - - VKD3D_SHADER_ERROR_GLSL_INTERNAL = 6000, - VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND = 6001, -@@ -455,6 +456,7 @@ enum vkd3d_shader_opcode - VKD3DSIH_IMM_ATOMIC_UMIN, - VKD3DSIH_IMM_ATOMIC_XOR, - VKD3DSIH_IMUL, -+ VKD3DSIH_IMUL_LOW, - VKD3DSIH_INE, - VKD3DSIH_INEG, - VKD3DSIH_ISFINITE, --- -2.47.2 - diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-a4c25b81c59ae783a94c1b25714eb080231.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-a4c25b81c59ae783a94c1b25714eb080231.patch new file mode 100644 index 00000000..f06a61df --- /dev/null +++ b/patches/vkd3d-latest/0005-Updated-vkd3d-to-a4c25b81c59ae783a94c1b25714eb080231.patch @@ -0,0 +1,2302 @@ +From e6ab84026593ccbecd92360d0af855ed727039da Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Thu, 24 Jul 2025 06:52:52 +1000 +Subject: [PATCH] Updated vkd3d to a4c25b81c59ae783a94c1b25714eb080231b86bd. + +--- + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 16 +- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 5 +- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 50 ++- + libs/vkd3d/libs/vkd3d-shader/glsl.c | 16 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 16 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 9 +- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 287 ++++++++++-------- + libs/vkd3d/libs/vkd3d-shader/ir.c | 88 ++++-- + libs/vkd3d/libs/vkd3d-shader/msl.c | 10 +- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 60 ++-- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 41 +-- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 59 ++-- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 58 ++-- + 13 files changed, 384 insertions(+), 331 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +index 5e3e7daab83..c213007f2b4 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +@@ -388,13 +388,7 @@ static void shader_print_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum + { + static const char *const data_type_names[] = + { +- [VKD3D_DATA_UNORM ] = "unorm", +- [VKD3D_DATA_SNORM ] = "snorm", +- [VKD3D_DATA_OPAQUE ] = "opaque", +- [VKD3D_DATA_MIXED ] = "mixed", +- [VKD3D_DATA_CONTINUED] = "", +- [VKD3D_DATA_UNUSED ] = "", +- [VKD3D_DATA_BOOL ] = "bool", ++ [VSIR_DATA_BOOL ] = "bool", + [VSIR_DATA_F16 ] = "half", + [VSIR_DATA_F32 ] = "float", + [VSIR_DATA_F64 ] = "double", +@@ -403,6 +397,12 @@ static void shader_print_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum + [VSIR_DATA_U16 ] = "uint16", + [VSIR_DATA_U32 ] = "uint", + [VSIR_DATA_U64 ] = "uint64", ++ [VSIR_DATA_SNORM ] = "snorm", ++ [VSIR_DATA_UNORM ] = "unorm", ++ [VSIR_DATA_OPAQUE ] = "opaque", ++ [VSIR_DATA_MIXED ] = "mixed", ++ [VSIR_DATA_CONTINUED] = "", ++ [VSIR_DATA_UNUSED ] = "", + }; + + if (type < ARRAY_SIZE(data_type_names)) +@@ -957,7 +957,7 @@ static void shader_print_reg_type(struct vkd3d_d3d_asm_compiler *compiler, + return; + } + +- if (reg->data_type == VKD3D_DATA_UNUSED) ++ if (reg->data_type == VSIR_DATA_UNUSED) + return; + + if (reg->dimension < ARRAY_SIZE(dimensions)) +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index 49e1a529369..dd13757bf59 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -1685,7 +1685,7 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir_ + if (ins->dst_count != info->dst_count) + { + vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, +- "Invalid destination parameter count %u for instruction \"%s\" (%#x); expected %u.", ++ "Invalid destination parameter count %zu for instruction \"%s\" (%#x); expected %u.", + ins->dst_count, vsir_opcode_get_name(ins->opcode, ""), ins->opcode, info->dst_count); + d3dbc->failed = true; + return NULL; +@@ -1693,7 +1693,7 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir_ + if (ins->src_count != info->src_count) + { + vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, +- "Invalid source parameter count %u for instruction \"%s\" (%#x); expected %u.", ++ "Invalid source parameter count %zu for instruction \"%s\" (%#x); expected %u.", + ins->src_count, vsir_opcode_get_name(ins->opcode, ""), ins->opcode, info->src_count); + d3dbc->failed = true; + return NULL; +@@ -2018,6 +2018,7 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str + case VSIR_OP_SINCOS: + case VSIR_OP_SLT: + case VSIR_OP_TEXLD: ++ case VSIR_OP_TEXLDL: + case VSIR_OP_TEXLDD: + d3dbc_write_instruction(d3dbc, ins); + break; +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index c3dd606f00f..66e3c1ecd36 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -2480,7 +2480,7 @@ static enum vsir_data_type vsir_data_type_from_dxil(const struct sm6_type *type) + switch (type->u.width) + { + case 1: +- return VKD3D_DATA_BOOL; ++ return VSIR_DATA_BOOL; + case 8: + return VSIR_DATA_U8; + case 16: +@@ -4473,7 +4473,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ + dst_param_init(&dst_params[0]); + + dst_params[1].reg = reg; +- dst_params[1].reg.data_type = VKD3D_DATA_UNUSED; ++ dst_params[1].reg.data_type = VSIR_DATA_UNUSED; + dst_params[1].reg.idx[1].rel_addr = NULL; + dst_params[1].reg.idx[1].offset = ~0u; + dst_params[1].reg.idx_count = 1; +@@ -5301,7 +5301,7 @@ static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_ + "Output stream index %u is invalid.", i); + } + +- register_init_with_id(&src_param->reg, VKD3DSPR_STREAM, VKD3D_DATA_UNUSED, i); ++ register_init_with_id(&src_param->reg, VKD3DSPR_STREAM, VSIR_DATA_UNUSED, i); + src_param_init(src_param); + + if (op == DX_EMIT_THEN_CUT_STREAM) +@@ -6009,7 +6009,7 @@ static void sm6_parser_emit_dx_get_sample_count(struct sm6_parser *sm6, enum dx_ + src_param_init(src_param); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +- ins->dst->reg.data_type = VSIR_DATA_F32; ++ ins->dst->reg.data_type = VSIR_DATA_U32; + } + + static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -9041,25 +9041,25 @@ static enum vkd3d_shader_resource_type shader_resource_type_from_dxil_resource_k + + static const enum vsir_data_type data_type_table[] = + { +- [COMPONENT_TYPE_INVALID] = VKD3D_DATA_UNUSED, +- [COMPONENT_TYPE_I1] = VKD3D_DATA_UNUSED, ++ [COMPONENT_TYPE_INVALID] = VSIR_DATA_UNUSED, ++ [COMPONENT_TYPE_I1] = VSIR_DATA_UNUSED, + [COMPONENT_TYPE_I16] = VSIR_DATA_I32, + [COMPONENT_TYPE_U16] = VSIR_DATA_U32, + [COMPONENT_TYPE_I32] = VSIR_DATA_I32, + [COMPONENT_TYPE_U32] = VSIR_DATA_U32, +- [COMPONENT_TYPE_I64] = VKD3D_DATA_UNUSED, +- [COMPONENT_TYPE_U64] = VKD3D_DATA_UNUSED, ++ [COMPONENT_TYPE_I64] = VSIR_DATA_UNUSED, ++ [COMPONENT_TYPE_U64] = VSIR_DATA_UNUSED, + [COMPONENT_TYPE_F16] = VSIR_DATA_F32, + [COMPONENT_TYPE_F32] = VSIR_DATA_F32, + [COMPONENT_TYPE_F64] = VSIR_DATA_F64, +- [COMPONENT_TYPE_SNORMF16] = VKD3D_DATA_SNORM, +- [COMPONENT_TYPE_UNORMF16] = VKD3D_DATA_UNORM, +- [COMPONENT_TYPE_SNORMF32] = VKD3D_DATA_SNORM, +- [COMPONENT_TYPE_UNORMF32] = VKD3D_DATA_UNORM, ++ [COMPONENT_TYPE_SNORMF16] = VSIR_DATA_SNORM, ++ [COMPONENT_TYPE_UNORMF16] = VSIR_DATA_UNORM, ++ [COMPONENT_TYPE_SNORMF32] = VSIR_DATA_SNORM, ++ [COMPONENT_TYPE_UNORMF32] = VSIR_DATA_UNORM, + [COMPONENT_TYPE_SNORMF64] = VSIR_DATA_F64, + [COMPONENT_TYPE_UNORMF64] = VSIR_DATA_F64, +- [COMPONENT_TYPE_PACKEDS8X32] = VKD3D_DATA_UNUSED, +- [COMPONENT_TYPE_PACKEDU8X32] = VKD3D_DATA_UNUSED, ++ [COMPONENT_TYPE_PACKEDS8X32] = VSIR_DATA_UNUSED, ++ [COMPONENT_TYPE_PACKEDU8X32] = VSIR_DATA_UNUSED, + }; + + static enum vsir_data_type vsir_data_type_from_dxil_component_type(enum dxil_component_type type, +@@ -9067,9 +9067,8 @@ static enum vsir_data_type vsir_data_type_from_dxil_component_type(enum dxil_com + { + enum vsir_data_type data_type; + +- if (type >= ARRAY_SIZE(data_type_table) || (data_type = data_type_table[type]) == VKD3D_DATA_UNUSED) ++ if (type >= ARRAY_SIZE(data_type_table) || (data_type = data_type_table[type]) == VSIR_DATA_UNUSED) + { +- FIXME("Unhandled component type %u.\n", type); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "Resource descriptor component type %u is unhandled.", type); + return VSIR_DATA_F32; +@@ -9089,7 +9088,7 @@ static bool resources_load_additional_values(struct resource_additional_values * + { + unsigned int i, operand_count, tag, value; + +- info->data_type = VKD3D_DATA_UNUSED; ++ info->data_type = VSIR_DATA_UNUSED; + info->byte_stride = 0; + + if (node->operand_count & 1) +@@ -9199,9 +9198,8 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc + + if (kind == RESOURCE_KIND_TYPEDBUFFER || resource_kind_is_texture(kind)) + { +- if (resource_values.data_type == VKD3D_DATA_UNUSED) ++ if (resource_values.data_type == VSIR_DATA_UNUSED) + { +- WARN("No data type defined.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "A typed resource has no data type."); + } +@@ -9303,9 +9301,9 @@ static enum vkd3d_result sm6_parser_resources_load_srv(struct sm6_parser *sm6, + d->resource_type = ins->resource_type; + d->kind = kind; + d->reg_type = VKD3DSPR_RESOURCE; +- d->reg_data_type = VKD3D_DATA_UNUSED; ++ d->reg_data_type = VSIR_DATA_UNUSED; + d->resource_data_type = (ins->opcode == VSIR_OP_DCL) +- ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; ++ ? ins->declaration.semantic.resource_data_type[0] : VSIR_DATA_UNUSED; + + init_resource_declaration(resource, VKD3DSPR_RESOURCE, d->reg_data_type, d->id, &d->range); + +@@ -9377,9 +9375,9 @@ static enum vkd3d_result sm6_parser_resources_load_uav(struct sm6_parser *sm6, + d->resource_type = ins->resource_type; + d->kind = values[0]; + d->reg_type = VKD3DSPR_UAV; +- d->reg_data_type = VKD3D_DATA_UNUSED; ++ d->reg_data_type = VSIR_DATA_UNUSED; + d->resource_data_type = (ins->opcode == VSIR_OP_DCL_UAV_TYPED) +- ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; ++ ? ins->declaration.semantic.resource_data_type[0] : VSIR_DATA_UNUSED; + + init_resource_declaration(resource, VKD3DSPR_UAV, d->reg_data_type, d->id, &d->range); + +@@ -9483,7 +9481,7 @@ static enum vkd3d_result sm6_parser_resources_load_sampler(struct sm6_parser *sm + ins->declaration.sampler.src.modifiers = VKD3DSPSM_NONE; + + reg = &ins->declaration.sampler.src.reg; +- vsir_register_init(reg, VKD3DSPR_SAMPLER, VKD3D_DATA_UNUSED, 3); ++ vsir_register_init(reg, VKD3DSPR_SAMPLER, VSIR_DATA_UNUSED, 3); + reg->idx[0].offset = d->id; + reg->idx[1].offset = d->range.first; + reg->idx[2].offset = d->range.last; +@@ -9493,8 +9491,8 @@ static enum vkd3d_result sm6_parser_resources_load_sampler(struct sm6_parser *sm + d->resource_type = ins->resource_type; + d->kind = RESOURCE_KIND_SAMPLER; + d->reg_type = VKD3DSPR_SAMPLER; +- d->reg_data_type = VKD3D_DATA_UNUSED; +- d->resource_data_type = VKD3D_DATA_UNUSED; ++ d->reg_data_type = VSIR_DATA_UNUSED; ++ d->resource_data_type = VSIR_DATA_UNUSED; + + return VKD3D_OK; + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c +index dc68e1792d9..e57a4aa2731 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/glsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c +@@ -330,9 +330,9 @@ static void glsl_src_cleanup(struct glsl_src *src, struct vkd3d_string_buffer_ca + static void shader_glsl_print_bitcast(struct vkd3d_string_buffer *dst, struct vkd3d_glsl_generator *gen, + const char *src, enum vsir_data_type dst_data_type, enum vsir_data_type src_data_type, unsigned int size) + { +- if (dst_data_type == VKD3D_DATA_UNORM || dst_data_type == VKD3D_DATA_SNORM) ++ if (dst_data_type == VSIR_DATA_UNORM || dst_data_type == VSIR_DATA_SNORM) + dst_data_type = VSIR_DATA_F32; +- if (src_data_type == VKD3D_DATA_UNORM || src_data_type == VKD3D_DATA_SNORM) ++ if (src_data_type == VSIR_DATA_UNORM || src_data_type == VSIR_DATA_SNORM) + src_data_type = VSIR_DATA_F32; + + if (dst_data_type == src_data_type) +@@ -1175,8 +1175,8 @@ static void shader_glsl_store_uav_typed(struct vkd3d_glsl_generator *gen, const + "Internal compiler error: Unhandled data type %#x.", data_type); + /* fall through */ + case VSIR_DATA_F32: +- case VKD3D_DATA_UNORM: +- case VKD3D_DATA_SNORM: ++ case VSIR_DATA_SNORM: ++ case VSIR_DATA_UNORM: + vkd3d_string_buffer_printf(image_data, "vec4("); + break; + } +@@ -1780,8 +1780,8 @@ static void shader_glsl_generate_uav_declaration(struct vkd3d_glsl_generator *ge + uav->resource_data_type, uav->register_id); + /* fall through */ + case VSIR_DATA_F32: +- case VKD3D_DATA_UNORM: +- case VKD3D_DATA_SNORM: ++ case VSIR_DATA_SNORM: ++ case VSIR_DATA_UNORM: + image_type_prefix = ""; + read_format = "r32f"; + break; +@@ -1996,8 +1996,8 @@ static void shader_glsl_generate_sampler_declaration(struct vkd3d_glsl_generator + switch (srv->resource_data_type) + { + case VSIR_DATA_F32: +- case VKD3D_DATA_UNORM: +- case VKD3D_DATA_SNORM: ++ case VSIR_DATA_SNORM: ++ case VSIR_DATA_UNORM: + sampler_type_prefix = ""; + break; + case VSIR_DATA_I32: +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +index 678ed324919..e2c68d4afb5 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +@@ -2998,7 +2998,6 @@ struct hlsl_ir_function_decl *hlsl_new_func_decl(struct hlsl_ctx *ctx, + decl->return_type = return_type; + decl->parameters = *parameters; + decl->loc = *loc; +- list_init(&decl->extern_vars); + + if (!hlsl_types_are_equal(return_type, ctx->builtin_types.Void)) + { +@@ -4066,20 +4065,23 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, + } + } + +-void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func) ++void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func, ++ const char *description, const struct hlsl_block *processed_block) + { + struct vkd3d_string_buffer buffer; + size_t i; + + vkd3d_string_buffer_init(&buffer); +- vkd3d_string_buffer_printf(&buffer, "Dumping function %s.\n", func->func->name); ++ vkd3d_string_buffer_printf(&buffer, "Dumping %s \"%s\".\n", description, func->func->name); + vkd3d_string_buffer_printf(&buffer, "Function parameters:\n"); + for (i = 0; i < func->parameters.count; ++i) + { + dump_ir_var(ctx, &buffer, func->parameters.vars[i]); + vkd3d_string_buffer_printf(&buffer, "\n"); + } +- if (func->has_body) ++ if (processed_block) ++ dump_block(ctx, &buffer, processed_block); ++ else if (func->has_body) + dump_block(ctx, &buffer, &func->body); + + vkd3d_string_buffer_trace(&buffer); +@@ -5009,8 +5011,8 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) + vkd3d_free(ctx->constant_defs.regs); + } + +-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) ++int hlsl_compile_shader(const struct vkd3d_shader_compile_info *compile_info, ++ struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_code *out) + { + enum vkd3d_shader_target_type target_type = compile_info->target_type; + const struct vkd3d_shader_hlsl_source_info *hlsl_source_info; +@@ -5062,7 +5064,7 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d + if (!hlsl_ctx_init(&ctx, compile_info, profile, message_context)) + return VKD3D_ERROR_OUT_OF_MEMORY; + +- if ((ret = hlsl_lexer_compile(&ctx, hlsl)) == 2) ++ if ((ret = hlsl_lexer_compile(&ctx, &compile_info->source)) == 2) + { + hlsl_ctx_cleanup(&ctx); + return VKD3D_ERROR_OUT_OF_MEMORY; +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +index 0dce2831c3e..47cc361a48a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +@@ -645,12 +645,6 @@ struct hlsl_ir_function_decl + * executed. Needed to deal with return statements in non-uniform control + * flow, since some backends can't handle them. */ + struct hlsl_ir_var *early_return_var; +- +- /* List of all the extern semantic variables; linked by the +- * hlsl_ir_var.extern_entry fields. This exists as a convenience because +- * it is often necessary to iterate all extern variables and these can be +- * declared in as function parameters, or as the function return value. */ +- struct list extern_vars; + }; + + struct hlsl_ir_call +@@ -1615,7 +1609,8 @@ struct hlsl_ir_node *hlsl_block_add_unary_expr(struct hlsl_ctx *ctx, struct hlsl + void hlsl_block_cleanup(struct hlsl_block *block); + bool hlsl_clone_block(struct hlsl_ctx *ctx, struct hlsl_block *dst_block, const struct hlsl_block *src_block); + +-void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func); ++void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func, ++ const char *description, const struct hlsl_block *processed_block); + void hlsl_dump_ir_function_decl(struct hlsl_ctx *ctx, + struct vkd3d_string_buffer *buffer, const struct hlsl_ir_function_decl *f); + void hlsl_dump_var_default_values(const struct hlsl_ir_var *var); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index 7707412bf57..8bfa157a12b 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -186,30 +186,34 @@ static void prepend_uniform_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, + { + struct hlsl_ir_node *store; + struct hlsl_ir_load *load; +- struct hlsl_ir_var *temp; +- char *new_name; + + uniform->is_uniform = 1; + list_add_tail(&ctx->extern_vars, &uniform->extern_entry); + +- if (!(new_name = hlsl_sprintf_alloc(ctx, "", uniform->name))) +- return; +- +- if (!(temp = hlsl_new_var(ctx, new_name, uniform->data_type, +- &uniform->loc, NULL, uniform->storage_modifiers, NULL))) ++ if (!uniform->temp_copy) + { +- vkd3d_free(new_name); +- return; +- } +- list_add_before(&uniform->scope_entry, &temp->scope_entry); ++ struct hlsl_ir_var *temp; ++ char *new_name; + +- uniform->temp_copy = temp; ++ if (!(new_name = hlsl_sprintf_alloc(ctx, "", uniform->name))) ++ return; ++ ++ if (!(temp = hlsl_new_var(ctx, new_name, uniform->data_type, ++ &uniform->loc, NULL, uniform->storage_modifiers, NULL))) ++ { ++ vkd3d_free(new_name); ++ return; ++ } ++ list_add_tail(&ctx->dummy_scope->vars, &temp->scope_entry); ++ ++ uniform->temp_copy = temp; ++ } + + if (!(load = hlsl_new_var_load(ctx, uniform, &uniform->loc))) + return; + list_add_head(&block->instrs, &load->node.entry); + +- if (!(store = hlsl_new_simple_store(ctx, temp, &load->node))) ++ if (!(store = hlsl_new_simple_store(ctx, uniform->temp_copy, &load->node))) + return; + list_add_after(&load->node.entry, &store->entry); + } +@@ -300,9 +304,9 @@ static bool types_are_semantic_equivalent(struct hlsl_ctx *ctx, const struct hls + == base_type_get_semantic_equivalent(type2->e.numeric.type); + } + +-static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, +- struct hlsl_ir_var *var, struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic, +- uint32_t stream_index, bool output, bool force_align, bool create, const struct vkd3d_shader_location *loc) ++static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct list *semantic_vars, struct hlsl_ir_var *var, ++ struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t stream_index, bool output, ++ bool force_align, bool create, const struct vkd3d_shader_location *loc) + { + struct hlsl_semantic new_semantic; + uint32_t index = semantic->index; +@@ -323,7 +327,7 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir + if (!new_name) + return NULL; + +- LIST_FOR_EACH_ENTRY(ext_var, &func->extern_vars, struct hlsl_ir_var, extern_entry) ++ LIST_FOR_EACH_ENTRY(ext_var, semantic_vars, struct hlsl_ir_var, extern_entry) + { + if (!ascii_strcasecmp(ext_var->name, new_name)) + { +@@ -387,7 +391,7 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir + ext_var->is_param = var->is_param; + ext_var->force_align = force_align; + list_add_before(&var->scope_entry, &ext_var->scope_entry); +- list_add_tail(&func->extern_vars, &ext_var->extern_entry); ++ list_add_tail(semantic_vars, &ext_var->extern_entry); + + return ext_var; + } +@@ -409,7 +413,7 @@ static uint32_t combine_field_storage_modifiers(uint32_t modifiers, uint32_t fie + return field_modifiers; + } + +-static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, ++static void prepend_input_copy(struct hlsl_ctx *ctx, struct list *semantic_vars, + struct hlsl_block *block, uint32_t prim_index, struct hlsl_ir_load *lhs, + uint32_t modifiers, struct hlsl_semantic *semantic, bool force_align) + { +@@ -455,7 +459,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec + return; + prim_type_src->modifiers = var->data_type->modifiers & HLSL_PRIMITIVE_MODIFIERS_MASK; + +- if (!(input = add_semantic_var(ctx, func, var, prim_type_src, ++ if (!(input = add_semantic_var(ctx, semantic_vars, var, prim_type_src, + modifiers, semantic, 0, false, force_align, true, loc))) + return; + ++semantic->index; +@@ -469,7 +473,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec + } + else + { +- if (!(input = add_semantic_var(ctx, func, var, vector_type_src, ++ if (!(input = add_semantic_var(ctx, semantic_vars, var, vector_type_src, + modifiers, semantic, 0, false, force_align, true, loc))) + return; + ++semantic->index; +@@ -496,7 +500,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec + } + } + +-static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, ++static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct list *semantic_vars, + struct hlsl_block *block, uint32_t prim_index, struct hlsl_ir_load *lhs, + uint32_t modifiers, struct hlsl_semantic *semantic, bool force_align) + { +@@ -533,7 +537,7 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_func + if (hlsl_type_is_primitive_array(type)) + prim_index = i; + +- prepend_input_copy_recurse(ctx, func, block, prim_index, ++ prepend_input_copy_recurse(ctx, semantic_vars, block, prim_index, + element_load, element_modifiers, semantic, force_align); + } + else +@@ -550,7 +554,7 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_func + if (semantic->name) + { + warn_on_field_semantic(ctx, field, semantic); +- prepend_input_copy_recurse(ctx, func, block, prim_index, ++ prepend_input_copy_recurse(ctx, semantic_vars, block, prim_index, + element_load, element_modifiers, semantic, force_align); + } + else +@@ -561,7 +565,7 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_func + + if (!(hlsl_clone_semantic(ctx, &semantic_copy, &field->semantic))) + return; +- prepend_input_copy_recurse(ctx, func, block, prim_index, ++ prepend_input_copy_recurse(ctx, semantic_vars, block, prim_index, + element_load, element_modifiers, &semantic_copy, force_align); + hlsl_cleanup_semantic(&semantic_copy); + } +@@ -570,13 +574,14 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_func + } + else + { +- prepend_input_copy(ctx, func, block, prim_index, lhs, modifiers, semantic, force_align); ++ prepend_input_copy(ctx, semantic_vars, block, prim_index, lhs, modifiers, semantic, force_align); + } + } + + /* Split inputs into two variables representing the semantic and temp registers, + * and copy the former to the latter, so that writes to input variables work. */ +-static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_var *var) ++static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_block *body, ++ struct list *semantic_vars, struct hlsl_ir_var *var) + { + struct hlsl_semantic semantic_copy; + struct hlsl_ir_load *load; +@@ -594,14 +599,14 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function + hlsl_block_cleanup(&block); + return; + } +- prepend_input_copy_recurse(ctx, func, &block, 0, load, var->storage_modifiers, &semantic_copy, false); ++ prepend_input_copy_recurse(ctx, semantic_vars, &block, 0, load, var->storage_modifiers, &semantic_copy, false); + hlsl_cleanup_semantic(&semantic_copy); + +- list_move_head(&func->body.instrs, &block.instrs); ++ list_move_head(&body->instrs, &block.instrs); + } + + static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, +- struct hlsl_ir_function_decl *func, struct hlsl_ir_load *rhs, uint32_t modifiers, ++ struct list *semantic_vars, struct hlsl_ir_load *rhs, uint32_t modifiers, + struct hlsl_semantic *semantic, uint32_t stream_index, bool force_align, bool create) + { + struct hlsl_type *type = rhs->node.data_type, *vector_type; +@@ -631,7 +636,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_ir_var *output; + struct hlsl_ir_node *load; + +- if (!(output = add_semantic_var(ctx, func, var, vector_type, modifiers, ++ if (!(output = add_semantic_var(ctx, semantic_vars, var, vector_type, modifiers, + semantic, stream_index, true, force_align, create, loc))) + return; + ++semantic->index; +@@ -652,9 +657,9 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, + } + } + +-static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, +- struct hlsl_ir_function_decl *func, const struct hlsl_type *type, struct hlsl_ir_load *rhs, +- uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t stream_index, bool force_align, bool create) ++static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct list *semantic_vars, ++ const struct hlsl_type *type, struct hlsl_ir_load *rhs, uint32_t modifiers, struct hlsl_semantic *semantic, ++ uint32_t stream_index, bool force_align, bool create) + { + struct vkd3d_shader_location *loc = &rhs->node.loc; + struct hlsl_ir_var *var = rhs->src.var; +@@ -684,7 +689,7 @@ static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * + element_modifiers = modifiers; + force_align = true; + +- append_output_copy_recurse(ctx, block, func, element_type, element_load, ++ append_output_copy_recurse(ctx, block, semantic_vars, element_type, element_load, + element_modifiers, semantic, stream_index, force_align, create); + } + else +@@ -700,7 +705,7 @@ static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * + { + warn_on_field_semantic(ctx, field, semantic); + +- append_output_copy_recurse(ctx, block, func, element_type, element_load, ++ append_output_copy_recurse(ctx, block, semantic_vars, element_type, element_load, + element_modifiers, semantic, stream_index, force_align, create); + } + else +@@ -711,7 +716,7 @@ static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * + + if (!hlsl_clone_semantic(ctx, &semantic_copy, &field->semantic)) + continue; +- append_output_copy_recurse(ctx, block, func, element_type, element_load, ++ append_output_copy_recurse(ctx, block, semantic_vars, element_type, element_load, + element_modifiers, &semantic_copy, stream_index, force_align, create); + hlsl_cleanup_semantic(&semantic_copy); + } +@@ -720,14 +725,15 @@ static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * + } + else + { +- append_output_copy(ctx, block, func, rhs, modifiers, semantic, stream_index, force_align, create); ++ append_output_copy(ctx, block, semantic_vars, rhs, modifiers, semantic, stream_index, force_align, create); + } + } + + /* Split outputs into two variables representing the temp and semantic + * registers, and copy the former to the latter, so that reads from output + * variables work. */ +-static void append_output_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_var *var) ++static void append_output_var_copy(struct hlsl_ctx *ctx, struct hlsl_block *body, ++ struct list *semantic_vars, struct hlsl_ir_var *var) + { + struct hlsl_semantic semantic_copy; + struct hlsl_ir_load *load; +@@ -735,11 +741,11 @@ static void append_output_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function + /* This redundant load is expected to be deleted later by DCE. */ + if (!(load = hlsl_new_var_load(ctx, var, &var->loc))) + return; +- hlsl_block_add_instr(&func->body, &load->node); ++ hlsl_block_add_instr(body, &load->node); + + if (!hlsl_clone_semantic(ctx, &semantic_copy, &var->semantic)) + return; +- append_output_copy_recurse(ctx, &func->body, func, var->data_type, ++ append_output_copy_recurse(ctx, body, semantic_vars, var->data_type, + load, var->storage_modifiers, &semantic_copy, 0, false, true); + hlsl_cleanup_semantic(&semantic_copy); + } +@@ -3424,7 +3430,7 @@ static bool split_struct_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + + struct stream_append_ctx + { +- struct hlsl_ir_function_decl *func; ++ struct list *semantic_vars; + bool created[VKD3D_MAX_STREAM_COUNT]; + }; + +@@ -3465,7 +3471,7 @@ static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst + + if (!hlsl_clone_semantic(ctx, &semantic_copy, &var->semantic)) + return false; +- append_output_copy_recurse(ctx, &block, append_ctx->func, type->e.so.type, hlsl_ir_load(rhs), ++ append_output_copy_recurse(ctx, &block, append_ctx->semantic_vars, type->e.so.type, hlsl_ir_load(rhs), + var->storage_modifiers, &semantic_copy, var->regs[HLSL_REGSET_STREAM_OUTPUTS].index, + false, !append_ctx->created[stream_index]); + hlsl_cleanup_semantic(&semantic_copy); +@@ -5292,7 +5298,7 @@ static void dump_function(struct rb_entry *entry, void *context) + LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry) + { + if (decl->has_body) +- hlsl_dump_function(ctx, decl); ++ hlsl_dump_function(ctx, decl, "function", NULL); + } + } + +@@ -5309,7 +5315,7 @@ static bool mark_indexable_var(struct hlsl_ctx *ctx, struct hlsl_deref *deref, + return true; + } + +-static void mark_indexable_vars(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) ++static void mark_indexable_vars(struct hlsl_ctx *ctx, struct hlsl_block *body) + { + struct hlsl_scope *scope; + struct hlsl_ir_var *var; +@@ -5320,7 +5326,7 @@ static void mark_indexable_vars(struct hlsl_ctx *ctx, struct hlsl_ir_function_de + var->indexable = false; + } + +- transform_derefs(ctx, mark_indexable_var, &entry_func->body); ++ transform_derefs(ctx, mark_indexable_var, body); + } + + static char get_regset_name(enum hlsl_regset regset) +@@ -5567,7 +5573,7 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop + } + } + +-static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) ++static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_block *body) + { + struct hlsl_scope *scope; + struct hlsl_ir_var *var; +@@ -5575,7 +5581,7 @@ static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl + if (ctx->result) + return; + +- index_instructions(&entry_func->body, 1); ++ index_instructions(body, 1); + + LIST_FOR_EACH_ENTRY(scope, &ctx->scopes, struct hlsl_scope, entry) + { +@@ -5583,7 +5589,7 @@ static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl + var->first_write = var->last_read = 0; + } + +- compute_liveness_recurse(&entry_func->body, 0, 0); ++ compute_liveness_recurse(body, 0, 0); + } + + static void mark_vars_usage(struct hlsl_ctx *ctx) +@@ -6366,7 +6372,7 @@ static void allocate_sincos_const_registers(struct hlsl_ctx *ctx, struct hlsl_bl + } + } + +-static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) ++static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_block *body) + { + struct register_allocator allocator_used = {0}; + struct register_allocator allocator = {0}; +@@ -6431,9 +6437,9 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi + } + } + +- allocate_const_registers_recurse(ctx, &entry_func->body, &allocator); ++ allocate_const_registers_recurse(ctx, body, &allocator); + +- allocate_sincos_const_registers(ctx, &entry_func->body, &allocator); ++ allocate_sincos_const_registers(ctx, body, &allocator); + + vkd3d_free(allocator.allocations); + } +@@ -6442,7 +6448,7 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi + * index to all (simultaneously live) variables or intermediate values. Agnostic + * as to how many registers are actually available for the current backend, and + * does not handle constants. */ +-static uint32_t allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) ++static uint32_t allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_block *body, struct list *semantic_vars) + { + struct register_allocator allocator = {0}; + struct hlsl_scope *scope; +@@ -6461,7 +6467,7 @@ static uint32_t allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun + /* ps_1_* outputs are special and go in temp register 0. */ + if (ctx->profile->major_version == 1 && ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL) + { +- LIST_FOR_EACH_ENTRY(var, &entry_func->extern_vars, struct hlsl_ir_var, extern_entry) ++ LIST_FOR_EACH_ENTRY(var, semantic_vars, struct hlsl_ir_var, extern_entry) + { + if (var->is_output_semantic) + { +@@ -6472,15 +6478,16 @@ static uint32_t allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun + } + } + +- allocate_temp_registers_recurse(ctx, &entry_func->body, &allocator); ++ allocate_temp_registers_recurse(ctx, body, &allocator); + vkd3d_free(allocator.allocations); + + if (allocator.indexable_count) +- TRACE("Declaration of function \"%s\" required %u temp registers, and %u indexable temps.\n", +- entry_func->func->name, allocator.reg_count, allocator.indexable_count); ++ TRACE("Declaration of %s function required %u temp registers, and %u indexable temps.\n", ++ ctx->is_patch_constant_func ? "patch constant" : "main", ++ allocator.reg_count, allocator.indexable_count); + else +- TRACE("Declaration of function \"%s\" required %u temp registers.\n", +- entry_func->func->name, allocator.reg_count); ++ TRACE("Declaration of %s function required %u temp registers.\n", ++ ctx->is_patch_constant_func ? "patch constant" : "main", allocator.reg_count); + + return allocator.reg_count; + } +@@ -6630,8 +6637,7 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var + } + } + +-static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, +- uint32_t *output_reg_count) ++static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct list *semantic_vars, uint32_t *output_reg_count) + { + struct register_allocator input_allocator = {0}, output_allocators[VKD3D_MAX_STREAM_COUNT] = {{0}}; + struct register_allocator in_prim_allocator = {0}, patch_constant_out_patch_allocator = {0}; +@@ -6645,7 +6651,7 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun + for (unsigned int i = 0; i < ARRAY_SIZE(output_allocators); ++i) + output_allocators[i].prioritize_smaller_writemasks = true; + +- LIST_FOR_EACH_ENTRY(var, &entry_func->extern_vars, struct hlsl_ir_var, extern_entry) ++ LIST_FOR_EACH_ENTRY(var, semantic_vars, struct hlsl_ir_var, extern_entry) + { + if (var->is_input_semantic) + { +@@ -6986,7 +6992,7 @@ static const struct hlsl_ir_var *get_allocated_object(struct hlsl_ctx *ctx, enum + return NULL; + } + +-static void allocate_objects(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, enum hlsl_regset regset) ++static void allocate_objects(struct hlsl_ctx *ctx, struct list *semantic_vars, enum hlsl_regset regset) + { + char regset_name = get_regset_name(regset); + uint32_t min_index = 0, id = 0; +@@ -6994,7 +7000,7 @@ static void allocate_objects(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl + + if (regset == HLSL_REGSET_UAVS && ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL) + { +- LIST_FOR_EACH_ENTRY(var, &func->extern_vars, struct hlsl_ir_var, extern_entry) ++ LIST_FOR_EACH_ENTRY(var, semantic_vars, struct hlsl_ir_var, extern_entry) + { + if (var->semantic.name && (!ascii_strcasecmp(var->semantic.name, "color") + || !ascii_strcasecmp(var->semantic.name, "sv_target"))) +@@ -7840,8 +7846,8 @@ static void validate_and_record_stream_outputs(struct hlsl_ctx *ctx) + } + } + +-static void validate_max_output_size(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, +- uint32_t output_reg_count) ++static void validate_max_output_size(struct hlsl_ctx *ctx, struct list *semantic_vars, ++ uint32_t output_reg_count, const struct vkd3d_shader_location *loc) + { + unsigned int max_output_size, comp_count = 0; + unsigned int *reg_comp_count; +@@ -7854,7 +7860,7 @@ static void validate_max_output_size(struct hlsl_ctx *ctx, struct hlsl_ir_functi + if (!(reg_comp_count = hlsl_calloc(ctx, output_reg_count, sizeof(*reg_comp_count)))) + return; + +- LIST_FOR_EACH_ENTRY(var, &entry_func->extern_vars, struct hlsl_ir_var, extern_entry) ++ LIST_FOR_EACH_ENTRY(var, semantic_vars, struct hlsl_ir_var, extern_entry) + { + if (!var->is_output_semantic) + continue; +@@ -7869,7 +7875,7 @@ static void validate_max_output_size(struct hlsl_ctx *ctx, struct hlsl_ir_functi + + max_output_size = ctx->max_vertex_count * comp_count; + if (max_output_size > 1024) +- hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MAX_VERTEX_COUNT, ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MAX_VERTEX_COUNT, + "Max vertex count (%u) * output data component count (%u) = %u, which is greater than 1024.", + ctx->max_vertex_count, comp_count, max_output_size); + +@@ -8183,15 +8189,15 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog + } + } + +-static void generate_vsir_signature(struct hlsl_ctx *ctx, +- struct vsir_program *program, struct hlsl_ir_function_decl *func) ++static void generate_vsir_signature(struct hlsl_ctx *ctx, struct vsir_program *program, ++ struct hlsl_ir_function_decl *func, struct list *semantic_vars) + { + bool is_domain = program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN; + struct hlsl_ir_var *var; + + ctx->is_patch_constant_func = func == ctx->patch_constant_func; + +- LIST_FOR_EACH_ENTRY(var, &func->extern_vars, struct hlsl_ir_var, extern_entry) ++ LIST_FOR_EACH_ENTRY(var, semantic_vars, struct hlsl_ir_var, extern_entry) + { + if (var->is_input_semantic) + { +@@ -8233,7 +8239,7 @@ static enum vsir_data_type vsir_data_type_from_hlsl_type(struct hlsl_ctx *ctx, c + if (type->class == HLSL_CLASS_ARRAY) + return vsir_data_type_from_hlsl_type(ctx, type->e.array.type); + if (type->class == HLSL_CLASS_STRUCT) +- return VKD3D_DATA_MIXED; ++ return VSIR_DATA_MIXED; + if (type->class <= HLSL_CLASS_LAST_NUMERIC) + { + switch (type->e.numeric.type) +@@ -8253,7 +8259,7 @@ static enum vsir_data_type vsir_data_type_from_hlsl_type(struct hlsl_ctx *ctx, c + } + } + +- return VKD3D_DATA_UNUSED; ++ return VSIR_DATA_UNUSED; + } + + static enum vsir_data_type vsir_data_type_from_hlsl_instruction(struct hlsl_ctx *ctx, +@@ -8782,7 +8788,7 @@ static void sm4_generate_vsir_rasterizer_sample_count(struct hlsl_ctx *ctx, + vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); + + src_param = &ins->src[0]; +- vsir_src_param_init(src_param, VKD3DSPR_RASTERIZER, VKD3D_DATA_UNUSED, 0); ++ vsir_src_param_init(src_param, VKD3DSPR_RASTERIZER, VSIR_DATA_UNUSED, 0); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param->swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); + } +@@ -9397,6 +9403,10 @@ static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, + flags |= VKD3DSI_TEXLD_PROJECT; + break; + ++ case HLSL_RESOURCE_SAMPLE_LOD: ++ opcode = VSIR_OP_TEXLDL; ++ break; ++ + case HLSL_RESOURCE_SAMPLE_LOD_BIAS: + opcode = VSIR_OP_TEXLD; + flags |= VKD3DSI_TEXLD_BIAS; +@@ -9596,8 +9606,8 @@ static void sm1_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *blo + } + } + +-static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, +- uint64_t config_flags, struct vsir_program *program) ++static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, ++ struct list *semantic_vars, struct hlsl_block *body, uint64_t config_flags, struct vsir_program *program) + { + struct vkd3d_shader_version version = {0}; + struct hlsl_block block; +@@ -9612,18 +9622,18 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl + } + + program->ssa_count = 0; +- program->temp_count = allocate_temp_registers(ctx, entry_func); ++ program->temp_count = allocate_temp_registers(ctx, body, semantic_vars); + if (ctx->result) + return; + +- generate_vsir_signature(ctx, program, entry_func); ++ generate_vsir_signature(ctx, program, func, semantic_vars); + + hlsl_block_init(&block); + sm1_generate_vsir_constant_defs(ctx, program, &block); + sm1_generate_vsir_sampler_dcls(ctx, program, &block); +- list_move_head(&entry_func->body.instrs, &block.instrs); ++ list_move_head(&body->instrs, &block.instrs); + +- sm1_generate_vsir_block(ctx, &entry_func->body, program); ++ sm1_generate_vsir_block(ctx, body, program); + + program->ssa_count = ctx->ssa_count; + } +@@ -11738,8 +11748,9 @@ static void sm4_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *blo + } + } + +-static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, +- struct hlsl_ir_function_decl *func, uint64_t config_flags, struct vsir_program *program) ++static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, struct list *semantic_vars, ++ struct hlsl_ir_function_decl *func, struct hlsl_block *body, uint64_t config_flags, ++ struct vsir_program *program) + { + struct hlsl_block block = {0}; + struct hlsl_scope *scope; +@@ -11748,16 +11759,16 @@ static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, + + ctx->is_patch_constant_func = func == ctx->patch_constant_func; + +- compute_liveness(ctx, func); +- mark_indexable_vars(ctx, func); +- temp_count = allocate_temp_registers(ctx, func); ++ compute_liveness(ctx, body); ++ mark_indexable_vars(ctx, body); ++ temp_count = allocate_temp_registers(ctx, body, semantic_vars); + if (ctx->result) + return; + program->temp_count = max(program->temp_count, temp_count); + + hlsl_block_init(&block); + +- LIST_FOR_EACH_ENTRY(var, &func->extern_vars, struct hlsl_ir_var, extern_entry) ++ LIST_FOR_EACH_ENTRY(var, semantic_vars, struct hlsl_ir_var, extern_entry) + { + if ((var->is_input_semantic && var->last_read) + || (var->is_output_semantic && var->first_write)) +@@ -11786,11 +11797,11 @@ static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, + } + } + +- list_move_head(&func->body.instrs, &block.instrs); ++ list_move_head(&body->instrs, &block.instrs); + + hlsl_block_cleanup(&block); + +- sm4_generate_vsir_block(ctx, &func->body, program); ++ sm4_generate_vsir_block(ctx, body, program); + + generate_vsir_add_program_instruction(ctx, program, &func->loc, VSIR_OP_RET, 0, 0); + } +@@ -12014,8 +12025,8 @@ static void generate_vsir_scan_required_features(struct hlsl_ctx *ctx, struct vs + * STENCIL_REF, and TYPED_UAV_LOAD_ADDITIONAL_FORMATS. */ + } + +-static void generate_vsir_scan_global_flags(struct hlsl_ctx *ctx, +- struct vsir_program *program, const struct hlsl_ir_function_decl *entry_func) ++static void generate_vsir_scan_global_flags(struct hlsl_ctx *ctx, struct vsir_program *program, ++ const struct list *semantic_vars, const struct hlsl_ir_function_decl *entry_func) + { + const struct vkd3d_shader_version *version = &program->shader_version; + struct extern_resource *extern_resources; +@@ -12041,7 +12052,7 @@ static void generate_vsir_scan_global_flags(struct hlsl_ctx *ctx, + + sm4_free_extern_resources(extern_resources, extern_resources_count); + +- LIST_FOR_EACH_ENTRY(var, &entry_func->extern_vars, struct hlsl_ir_var, extern_entry) ++ LIST_FOR_EACH_ENTRY(var, semantic_vars, struct hlsl_ir_var, extern_entry) + { + const struct hlsl_type *type = var->data_type; + +@@ -12123,7 +12134,7 @@ static void sm4_generate_vsir_add_dcl_sampler(struct hlsl_ctx *ctx, + ins->flags |= VKD3DSI_SAMPLER_COMPARISON_MODE; + + src_param = &ins->declaration.sampler.src; +- vsir_src_param_init(src_param, VKD3DSPR_SAMPLER, VKD3D_DATA_UNUSED, 0); ++ vsir_src_param_init(src_param, VKD3DSPR_SAMPLER, VSIR_DATA_UNUSED, 0); + + ins->declaration.sampler.range.first = array_first; + ins->declaration.sampler.range.last = array_last; +@@ -12179,9 +12190,9 @@ static enum vsir_data_type sm4_generate_vsir_get_format_type(const struct hlsl_t + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: + if (format->modifiers & HLSL_MODIFIER_UNORM) +- return VKD3D_DATA_UNORM; ++ return VSIR_DATA_UNORM; + if (format->modifiers & HLSL_MODIFIER_SNORM) +- return VKD3D_DATA_SNORM; ++ return VSIR_DATA_SNORM; + return VSIR_DATA_F32; + + case HLSL_TYPE_INT: +@@ -12262,7 +12273,7 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, + else + vsir_resource = &ins->declaration.semantic.resource; + +- vsir_dst_param_init(&vsir_resource->reg, uav ? VKD3DSPR_UAV : VKD3DSPR_RESOURCE, VKD3D_DATA_UNUSED, 0); ++ vsir_dst_param_init(&vsir_resource->reg, uav ? VKD3DSPR_UAV : VKD3DSPR_RESOURCE, VSIR_DATA_UNUSED, 0); + + if (uav && component_type->e.resource.rasteriser_ordered) + ins->flags = VKD3DSUF_RASTERISER_ORDERED_VIEW; +@@ -12320,7 +12331,7 @@ static void sm4_generate_vsir_add_dcl_stream(struct hlsl_ctx *ctx, + return; + } + +- vsir_src_param_init(&ins->src[0], VKD3DSPR_STREAM, VKD3D_DATA_UNUSED, 1); ++ vsir_src_param_init(&ins->src[0], VKD3DSPR_STREAM, VSIR_DATA_UNUSED, 1); + ins->src[0].reg.dimension = VSIR_DIMENSION_NONE; + ins->src[0].reg.idx[0].offset = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; + } +@@ -12329,7 +12340,8 @@ static void sm4_generate_vsir_add_dcl_stream(struct hlsl_ctx *ctx, + * vsir_program, so it can be used as input to tpf_compile() without relying + * on ctx and entry_func. */ + static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, +- uint64_t config_flags, struct vsir_program *program) ++ struct list *semantic_vars, struct hlsl_block *body, struct list *patch_semantic_vars, ++ struct hlsl_block *patch_body, uint64_t config_flags, struct vsir_program *program) + { + struct vkd3d_shader_version version = {0}; + struct extern_resource *extern_resources; +@@ -12346,9 +12358,9 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl + return; + } + +- generate_vsir_signature(ctx, program, func); ++ generate_vsir_signature(ctx, program, func, semantic_vars); + if (version.type == VKD3D_SHADER_TYPE_HULL) +- generate_vsir_signature(ctx, program, ctx->patch_constant_func); ++ generate_vsir_signature(ctx, program, ctx->patch_constant_func, patch_semantic_vars); + + if (version.type == VKD3D_SHADER_TYPE_COMPUTE) + { +@@ -12415,16 +12427,17 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl + if (version.type == VKD3D_SHADER_TYPE_HULL) + generate_vsir_add_program_instruction(ctx, program, + &ctx->patch_constant_func->loc, VSIR_OP_HS_CONTROL_POINT_PHASE, 0, 0); +- sm4_generate_vsir_add_function(ctx, func, config_flags, program); ++ sm4_generate_vsir_add_function(ctx, semantic_vars, func, body, config_flags, program); + if (version.type == VKD3D_SHADER_TYPE_HULL) + { + generate_vsir_add_program_instruction(ctx, program, + &ctx->patch_constant_func->loc, VSIR_OP_HS_FORK_PHASE, 0, 0); +- sm4_generate_vsir_add_function(ctx, ctx->patch_constant_func, config_flags, program); ++ sm4_generate_vsir_add_function(ctx, patch_semantic_vars, ++ ctx->patch_constant_func, patch_body, config_flags, program); + } + + generate_vsir_scan_required_features(ctx, program); +- generate_vsir_scan_global_flags(ctx, program, func); ++ generate_vsir_scan_global_flags(ctx, program, semantic_vars, func); + + program->ssa_count = ctx->ssa_count; + } +@@ -13565,15 +13578,14 @@ static bool lower_isinf(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct + return true; + } + +-static void process_entry_function(struct hlsl_ctx *ctx, ++static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_vars, struct hlsl_block *body, + const struct hlsl_block *global_uniform_block, struct hlsl_ir_function_decl *entry_func) + { ++ struct stream_append_ctx stream_append_ctx = { .semantic_vars = semantic_vars }; + const struct hlsl_ir_var *input_patch = NULL, *output_patch = NULL; + const struct hlsl_profile_info *profile = ctx->profile; + struct hlsl_block static_initializers, global_uniforms; +- struct hlsl_block *const body = &entry_func->body; + struct recursive_call_ctx recursive_call_ctx; +- struct stream_append_ctx stream_append_ctx; + uint32_t output_reg_count; + struct hlsl_ir_var *var; + unsigned int i; +@@ -13581,6 +13593,8 @@ static void process_entry_function(struct hlsl_ctx *ctx, + + ctx->is_patch_constant_func = entry_func == ctx->patch_constant_func; + ++ hlsl_clone_block(ctx, body, &entry_func->body); ++ + if (!hlsl_clone_block(ctx, &static_initializers, &ctx->static_initializers)) + return; + list_move_head(&body->instrs, &static_initializers.instrs); +@@ -13624,7 +13638,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, + "Entry point \"%s\" is missing a return value semantic.", entry_func->func->name); + +- append_output_var_copy(ctx, entry_func, entry_func->return_var); ++ append_output_var_copy(ctx, body, semantic_vars, entry_func->return_var); + } + + for (i = 0; i < entry_func->parameters.count; ++i) +@@ -13680,7 +13694,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, + } + + validate_and_record_prim_type(ctx, var); +- prepend_input_var_copy(ctx, entry_func, var); ++ prepend_input_var_copy(ctx, body, semantic_vars, var); + } + else if (var->data_type->reg_size[HLSL_REGSET_STREAM_OUTPUTS]) + { +@@ -13716,7 +13730,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, + continue; + } + +- prepend_input_var_copy(ctx, entry_func, var); ++ prepend_input_var_copy(ctx, body, semantic_vars, var); + } + if (var->storage_modifiers & HLSL_STORAGE_OUT) + { +@@ -13727,7 +13741,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Output parameters are not allowed in geometry shaders."); + else +- append_output_var_copy(ctx, entry_func, var); ++ append_output_var_copy(ctx, body, semantic_vars, var); + } + } + } +@@ -13776,8 +13790,8 @@ static void process_entry_function(struct hlsl_ctx *ctx, + hlsl_transform_ir(ctx, lower_resource_load_bias, body, NULL); + } + +- compute_liveness(ctx, entry_func); +- transform_derefs(ctx, divert_written_uniform_derefs_to_temp, &entry_func->body); ++ compute_liveness(ctx, body); ++ transform_derefs(ctx, divert_written_uniform_derefs_to_temp, body); + + loop_unrolling_execute(ctx, body); + hlsl_run_const_passes(ctx, body); +@@ -13797,7 +13811,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, + do + { + progress = vectorize_exprs(ctx, body); +- compute_liveness(ctx, entry_func); ++ compute_liveness(ctx, body); + progress |= hlsl_transform_ir(ctx, dce, body, NULL); + progress |= hlsl_transform_ir(ctx, fold_swizzle_chains, body, NULL); + progress |= hlsl_transform_ir(ctx, remove_trivial_swizzles, body, NULL); +@@ -13810,7 +13824,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, + hlsl_transform_ir(ctx, lower_combined_samples, body, NULL); + + do +- compute_liveness(ctx, entry_func); ++ compute_liveness(ctx, body); + while (hlsl_transform_ir(ctx, dce, body, NULL)); + + hlsl_transform_ir(ctx, track_components_usage, body, NULL); +@@ -13823,9 +13837,6 @@ static void process_entry_function(struct hlsl_ctx *ctx, + { + allocate_stream_outputs(ctx); + validate_and_record_stream_outputs(ctx); +- +- memset(&stream_append_ctx, 0, sizeof(stream_append_ctx)); +- stream_append_ctx.func = entry_func; + hlsl_transform_ir(ctx, lower_stream_appends, body, &stream_append_ctx); + } + +@@ -13866,7 +13877,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, + hlsl_run_folding_passes(ctx, body); + + do +- compute_liveness(ctx, entry_func); ++ compute_liveness(ctx, body); + while (hlsl_transform_ir(ctx, dce, body, NULL)); + + /* TODO: move forward, remove when no longer needed */ +@@ -13875,27 +13886,28 @@ static void process_entry_function(struct hlsl_ctx *ctx, + transform_derefs(ctx, clean_constant_deref_offset_srcs, body); + + do +- compute_liveness(ctx, entry_func); ++ compute_liveness(ctx, body); + while (hlsl_transform_ir(ctx, dce, body, NULL)); + +- compute_liveness(ctx, entry_func); ++ compute_liveness(ctx, body); + mark_vars_usage(ctx); + + calculate_resource_register_counts(ctx); + + allocate_register_reservations(ctx, &ctx->extern_vars); +- allocate_register_reservations(ctx, &entry_func->extern_vars); +- allocate_semantic_registers(ctx, entry_func, &output_reg_count); ++ allocate_register_reservations(ctx, semantic_vars); ++ allocate_semantic_registers(ctx, semantic_vars, &output_reg_count); + + if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY) +- validate_max_output_size(ctx, entry_func, output_reg_count); ++ validate_max_output_size(ctx, semantic_vars, output_reg_count, &entry_func->loc); + } + + 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) + { ++ struct hlsl_block global_uniform_block, body, patch_body; + const struct hlsl_profile_info *profile = ctx->profile; +- struct hlsl_block global_uniform_block; ++ struct list semantic_vars, patch_semantic_vars; + struct hlsl_ir_var *var; + + parse_entry_function_attributes(ctx, entry_func); +@@ -13914,6 +13926,9 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE, + "Entry point \"%s\" is missing a [maxvertexcount] attribute.", entry_func->func->name); + ++ list_init(&ctx->extern_vars); ++ list_init(&semantic_vars); ++ list_init(&patch_semantic_vars); + hlsl_block_init(&global_uniform_block); + + LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) +@@ -13922,13 +13937,13 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry + prepend_uniform_copy(ctx, &global_uniform_block, var); + } + +- process_entry_function(ctx, &global_uniform_block, entry_func); ++ process_entry_function(ctx, &semantic_vars, &body, &global_uniform_block, entry_func); + if (ctx->result) + return ctx->result; + + if (profile->type == VKD3D_SHADER_TYPE_HULL) + { +- process_entry_function(ctx, &global_uniform_block, ctx->patch_constant_func); ++ process_entry_function(ctx, &patch_semantic_vars, &patch_body, &global_uniform_block, ctx->patch_constant_func); + if (ctx->result) + return ctx->result; + } +@@ -13937,21 +13952,26 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry + + if (profile->major_version < 4) + { +- mark_indexable_vars(ctx, entry_func); +- allocate_const_registers(ctx, entry_func); ++ mark_indexable_vars(ctx, &body); ++ allocate_const_registers(ctx, &body); + sort_uniforms_by_bind_count(ctx, HLSL_REGSET_SAMPLERS); +- allocate_objects(ctx, entry_func, HLSL_REGSET_SAMPLERS); ++ allocate_objects(ctx, &semantic_vars, HLSL_REGSET_SAMPLERS); + } + else + { + allocate_buffers(ctx); +- allocate_objects(ctx, entry_func, HLSL_REGSET_TEXTURES); +- allocate_objects(ctx, entry_func, HLSL_REGSET_UAVS); +- allocate_objects(ctx, entry_func, HLSL_REGSET_SAMPLERS); ++ allocate_objects(ctx, &semantic_vars, HLSL_REGSET_TEXTURES); ++ allocate_objects(ctx, &semantic_vars, HLSL_REGSET_UAVS); ++ allocate_objects(ctx, &semantic_vars, HLSL_REGSET_SAMPLERS); + } + + if (TRACE_ON()) ++ { + rb_for_each_entry(&ctx->functions, dump_function, ctx); ++ hlsl_dump_function(ctx, entry_func, "processed entry point", &body); ++ if (profile->type == VKD3D_SHADER_TYPE_HULL) ++ hlsl_dump_function(ctx, ctx->patch_constant_func, "processed patch-constant function", &patch_body); ++ } + + if (ctx->result) + return ctx->result; +@@ -13969,7 +13989,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry + if (ctx->result) + return ctx->result; + +- sm1_generate_vsir(ctx, entry_func, config_flags, &program); ++ sm1_generate_vsir(ctx, entry_func, &semantic_vars, &body, config_flags, &program); + if (ctx->result) + { + vsir_program_cleanup(&program); +@@ -13996,7 +14016,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry + if (ctx->result) + return ctx->result; + +- sm4_generate_vsir(ctx, entry_func, config_flags, &program); ++ sm4_generate_vsir(ctx, entry_func, &semantic_vars, &body, ++ &patch_semantic_vars, &patch_body, config_flags, &program); + if (ctx->result) + { + vsir_program_cleanup(&program); +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index c322d9dde01..92580a6a2df 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -604,7 +604,7 @@ static void vsir_src_param_init_io(struct vkd3d_shader_src_param *src, + + void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id) + { +- vsir_src_param_init(param, VKD3DSPR_LABEL, VKD3D_DATA_UNUSED, 1); ++ vsir_src_param_init(param, VKD3DSPR_LABEL, VSIR_DATA_UNUSED, 1); + param->reg.dimension = VSIR_DIMENSION_NONE; + param->reg.idx[0].offset = label_id; + } +@@ -625,7 +625,7 @@ static void src_param_init_parameter_vec4(struct vkd3d_shader_src_param *src, ui + + static void vsir_src_param_init_resource(struct vkd3d_shader_src_param *src, unsigned int id, unsigned int idx) + { +- vsir_src_param_init(src, VKD3DSPR_RESOURCE, VKD3D_DATA_UNUSED, 2); ++ vsir_src_param_init(src, VKD3DSPR_RESOURCE, VSIR_DATA_UNUSED, 2); + src->reg.idx[0].offset = id; + src->reg.idx[1].offset = idx; + src->reg.dimension = VSIR_DIMENSION_VEC4; +@@ -634,7 +634,7 @@ static void vsir_src_param_init_resource(struct vkd3d_shader_src_param *src, uns + + static void vsir_src_param_init_sampler(struct vkd3d_shader_src_param *src, unsigned int id, unsigned int idx) + { +- vsir_src_param_init(src, VKD3DSPR_SAMPLER, VKD3D_DATA_UNUSED, 2); ++ vsir_src_param_init(src, VKD3DSPR_SAMPLER, VSIR_DATA_UNUSED, 2); + src->reg.idx[0].offset = id; + src->reg.idx[1].offset = idx; + src->reg.dimension = VSIR_DIMENSION_NONE; +@@ -661,7 +661,7 @@ static void src_param_init_ssa_scalar(struct vkd3d_shader_src_param *src, + + static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned int idx) + { +- src_param_init_ssa_scalar(src, idx, VKD3D_DATA_BOOL); ++ src_param_init_ssa_scalar(src, idx, VSIR_DATA_BOOL); + } + + static void src_param_init_ssa_float(struct vkd3d_shader_src_param *src, unsigned int idx) +@@ -676,7 +676,7 @@ static void src_param_init_ssa_float4(struct vkd3d_shader_src_param *src, unsign + + static void src_param_init_temp_bool(struct vkd3d_shader_src_param *src, unsigned int idx) + { +- vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_BOOL, 1); ++ vsir_src_param_init(src, VKD3DSPR_TEMP, VSIR_DATA_BOOL, 1); + src->reg.idx[0].offset = idx; + } + +@@ -719,7 +719,7 @@ static void vsir_dst_param_init_io(struct vkd3d_shader_dst_param *dst, enum vkd3 + + void vsir_dst_param_init_null(struct vkd3d_shader_dst_param *dst) + { +- vsir_dst_param_init(dst, VKD3DSPR_NULL, VKD3D_DATA_UNUSED, 0); ++ vsir_dst_param_init(dst, VKD3DSPR_NULL, VSIR_DATA_UNUSED, 0); + dst->reg.dimension = VSIR_DIMENSION_NONE; + dst->write_mask = 0; + } +@@ -745,7 +745,7 @@ static void dst_param_init_ssa_scalar(struct vkd3d_shader_dst_param *dst, + + static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) + { +- dst_param_init_ssa_scalar(dst, idx, VKD3D_DATA_BOOL); ++ dst_param_init_ssa_scalar(dst, idx, VSIR_DATA_BOOL); + } + + static void dst_param_init_ssa_float(struct vkd3d_shader_dst_param *dst, unsigned int idx) +@@ -760,7 +760,7 @@ static void dst_param_init_ssa_float4(struct vkd3d_shader_dst_param *dst, unsign + + static void dst_param_init_temp_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) + { +- vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_BOOL, 1); ++ vsir_dst_param_init(dst, VKD3DSPR_TEMP, VSIR_DATA_BOOL, 1); + dst->reg.idx[0].offset = idx; + } + +@@ -792,6 +792,10 @@ void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vk + memset(ins, 0, sizeof(*ins)); + ins->location = *location; + ins->opcode = opcode; ++ ins->resource_data_type[0] = VSIR_DATA_F32; ++ ins->resource_data_type[1] = VSIR_DATA_F32; ++ ins->resource_data_type[2] = VSIR_DATA_F32; ++ ins->resource_data_type[3] = VSIR_DATA_F32; + } + + bool vsir_instruction_init_with_params(struct vsir_program *program, +@@ -1180,7 +1184,7 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, + { + vkd3d_shader_error(ctx->message_context, &udiv->location, + VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, +- "Internal compiler error: invalid destination count %u for UDIV.", ++ "Internal compiler error: invalid destination count %zu for UDIV.", + udiv->dst_count); + return VKD3D_ERROR; + } +@@ -1321,7 +1325,7 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog + { + vkd3d_shader_error(ctx->message_context, &sincos->location, + VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, +- "Internal compiler error: invalid destination count %u for SINCOS.", ++ "Internal compiler error: invalid destination count %zu for SINCOS.", + sincos->dst_count); + return VKD3D_ERROR; + } +@@ -1497,6 +1501,34 @@ static enum vkd3d_result vsir_program_lower_texldd(struct vsir_program *program, + return VKD3D_OK; + } + ++static enum vkd3d_result vsir_program_lower_texldl(struct vsir_program *program, ++ struct vkd3d_shader_instruction *texldl) ++{ ++ unsigned int idx = texldl->src[1].reg.idx[0].offset; ++ enum vkd3d_shader_swizzle_component w; ++ struct vkd3d_shader_src_param *srcs; ++ ++ VKD3D_ASSERT(texldl->src[1].reg.idx_count == 1); ++ VKD3D_ASSERT(!texldl->src[1].reg.idx[0].rel_addr); ++ ++ if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 4))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ srcs[0] = texldl->src[0]; ++ vsir_src_param_init_resource(&srcs[1], idx, idx); ++ vsir_src_param_init_sampler(&srcs[2], idx, idx); ++ ++ texldl->opcode = VSIR_OP_SAMPLE_LOD; ++ texldl->src = srcs; ++ texldl->src_count = 4; ++ ++ w = vsir_swizzle_get_component(srcs[0].swizzle, 3); ++ srcs[3] = texldl->src[0]; ++ srcs[3].swizzle = vkd3d_shader_create_swizzle(w, w, w, w); ++ ++ return VKD3D_OK; ++} ++ + static enum vkd3d_result vsir_program_lower_dcl_input(struct vsir_program *program, + struct vkd3d_shader_instruction *ins, struct vsir_transformation_context *ctx) + { +@@ -1668,6 +1700,11 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr + return ret; + break; + ++ case VSIR_OP_TEXLDL: ++ if ((ret = vsir_program_lower_texldl(program, ins)) < 0) ++ return ret; ++ break; ++ + case VSIR_OP_TEXBEM: + case VSIR_OP_TEXBEML: + case VSIR_OP_TEXCOORD: +@@ -1675,7 +1712,6 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr + case VSIR_OP_TEXDEPTH: + case VSIR_OP_TEXDP3: + case VSIR_OP_TEXDP3TEX: +- case VSIR_OP_TEXLDL: + case VSIR_OP_TEXM3x2PAD: + case VSIR_OP_TEXM3x2TEX: + case VSIR_OP_TEXM3x3DIFF: +@@ -9321,7 +9357,7 @@ static void vsir_validate_label_register(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, + "Invalid precision %#x for a LABEL register.", reg->precision); + +- if (reg->data_type != VKD3D_DATA_UNUSED) ++ if (reg->data_type != VSIR_DATA_UNUSED) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Invalid data type %#x for a LABEL register.", reg->data_type); + +@@ -9400,7 +9436,7 @@ static void vsir_validate_sampler_register(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, + "Invalid precision %#x for a SAMPLER register.", reg->precision); + +- if (reg->data_type != VKD3D_DATA_UNUSED) ++ if (reg->data_type != VSIR_DATA_UNUSED) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Invalid data type %#x for a SAMPLER register.", reg->data_type); + +@@ -9426,7 +9462,7 @@ static void vsir_validate_resource_register(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, + "Invalid precision %#x for a RESOURCE register.", reg->precision); + +- if (reg->data_type != VKD3D_DATA_UNUSED) ++ if (reg->data_type != VSIR_DATA_UNUSED) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Invalid data type %#x for a RESOURCE register.", reg->data_type); + +@@ -9452,7 +9488,7 @@ static void vsir_validate_uav_register(struct validation_context *ctx, + "Invalid precision %#x for a UAV register.", + reg->precision); + +- if (reg->data_type != VKD3D_DATA_UNUSED) ++ if (reg->data_type != VSIR_DATA_UNUSED) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Invalid data type %#x for a UAV register.", + reg->data_type); +@@ -9988,7 +10024,7 @@ static void vsir_validate_dst_count(struct validation_context *ctx, + { + if (instruction->dst_count != count) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, +- "Invalid destination parameter count %u for instruction \"%s\" (%#x); expected %u.", ++ "Invalid destination parameter count %zu for instruction \"%s\" (%#x); expected %u.", + instruction->dst_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); + } +@@ -9998,7 +10034,7 @@ static void vsir_validate_src_count(struct validation_context *ctx, + { + if (instruction->src_count != count) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, +- "Invalid source parameter count %u for instruction \"%s\" (%#x); expected %u.", ++ "Invalid source parameter count %zu for instruction \"%s\" (%#x); expected %u.", + instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); + } +@@ -10009,7 +10045,7 @@ static bool vsir_validate_src_min_count(struct validation_context *ctx, + if (instruction->src_count < count) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, +- "Invalid source parameter count %u for instruction \"%s\" (%#x); expected at least %u.", ++ "Invalid source parameter count %zu for instruction \"%s\" (%#x); expected at least %u.", + instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); + return false; +@@ -10024,7 +10060,7 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx, + if (instruction->src_count > count) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, +- "Invalid source parameter count %u for instruction \"%s\" (%#x); expected at most %u.", ++ "Invalid source parameter count %zu for instruction \"%s\" (%#x); expected at most %u.", + instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); + return false; +@@ -10484,7 +10520,7 @@ static void vsir_validate_descriptors(struct validation_context *ctx) + if (descriptor->resource_data_type >= VSIR_DATA_TYPE_COUNT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Descriptor %u has invalid resource data type %#x.", i, descriptor->resource_data_type); +- else if ((descriptor->resource_data_type == VKD3D_DATA_UNUSED) ++ else if ((descriptor->resource_data_type == VSIR_DATA_UNUSED) + != (descriptor->type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Descriptor %u has invalid resource data type %#x for descriptor type %#x.", +@@ -10653,7 +10689,7 @@ static void vsir_validate_logic_elementwise_operation(struct validation_context + { + static const bool types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_BOOL] = true, ++ [VSIR_DATA_BOOL] = true, + [VSIR_DATA_I32] = true, + [VSIR_DATA_U32] = true, + [VSIR_DATA_U64] = true, +@@ -10673,7 +10709,7 @@ static void vsir_validate_comparison_operation(struct validation_context *ctx, + + dst_data_type = instruction->dst[0].reg.data_type; + +- if (dst_data_type != VSIR_DATA_U32 && dst_data_type != VKD3D_DATA_BOOL) ++ if (dst_data_type != VSIR_DATA_U32 && dst_data_type != VSIR_DATA_BOOL) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Invalid data type %#x for result of comparison operation \"%s\" (%#x).", + dst_data_type, vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); +@@ -11326,7 +11362,7 @@ static void vsir_validate_itof(struct validation_context *ctx, const struct vkd3 + { + static const bool src_types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_BOOL] = true, ++ [VSIR_DATA_BOOL] = true, + [VSIR_DATA_I32] = true, + [VSIR_DATA_U32] = true, + [VSIR_DATA_U64] = true, +@@ -11345,7 +11381,7 @@ static void vsir_validate_itoi(struct validation_context *ctx, const struct vkd3 + { + static const bool types[VSIR_DATA_TYPE_COUNT] = + { +- [VKD3D_DATA_BOOL] = true, ++ [VSIR_DATA_BOOL] = true, + [VSIR_DATA_I32] = true, + [VSIR_DATA_U32] = true, + [VSIR_DATA_U64] = true, +@@ -11389,7 +11425,7 @@ static void vsir_validate_phi(struct validation_context *ctx, const struct vkd3d + + if (instruction->src_count % 2 != 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, +- "Invalid source count %u for a PHI instruction, it must be an even number.", ++ "Invalid source count %zu for a PHI instruction, it must be an even number.", + instruction->src_count); + incoming_count = instruction->src_count / 2; + +@@ -11471,7 +11507,7 @@ static void vsir_validate_switch_monolithic(struct validation_context *ctx, + + if (instruction->src_count % 2 != 1) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, +- "Invalid source count %u for a monolithic SWITCH instruction, it must be an odd number.", ++ "Invalid source count %zu for a monolithic SWITCH instruction, it must be an odd number.", + instruction->src_count); + + if (!vsir_register_is_label(&instruction->src[1].reg)) +diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c +index ccfce0f4591..d95b95f9738 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/msl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/msl.c +@@ -138,8 +138,8 @@ static void msl_print_resource_datatype(struct msl_generator *gen, + switch (data_type) + { + case VSIR_DATA_F32: +- case VKD3D_DATA_UNORM: +- case VKD3D_DATA_SNORM: ++ case VSIR_DATA_SNORM: ++ case VSIR_DATA_UNORM: + vkd3d_string_buffer_printf(buffer, "float"); + break; + case VSIR_DATA_I32: +@@ -527,7 +527,7 @@ static void msl_print_bitcast(struct vkd3d_string_buffer *dst, struct msl_genera + { + bool write_cast = false; + +- if (dst_data_type == VKD3D_DATA_UNORM || dst_data_type == VKD3D_DATA_SNORM) ++ if (dst_data_type == VSIR_DATA_UNORM || dst_data_type == VSIR_DATA_SNORM) + dst_data_type = VSIR_DATA_F32; + + switch (src_data_type) +@@ -1320,8 +1320,8 @@ static void msl_store_uav_typed(struct msl_generator *gen, const struct vkd3d_sh + "Internal compiler error: Unhandled data type %#x.", data_type); + /* fall through */ + case VSIR_DATA_F32: +- case VKD3D_DATA_UNORM: +- case VKD3D_DATA_SNORM: ++ case VSIR_DATA_SNORM: ++ case VSIR_DATA_UNORM: + vkd3d_string_buffer_printf(image_data, "float4("); + break; + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index d99c7ee27ff..2e6d0c786d0 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -7588,7 +7588,7 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t val_id; + +- VKD3D_ASSERT(src->reg.data_type == VKD3D_DATA_BOOL && dst->reg.data_type != VKD3D_DATA_BOOL); ++ VKD3D_ASSERT(src->reg.data_type == VSIR_DATA_BOOL && dst->reg.data_type != VSIR_DATA_BOOL); + + val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); + if (dst->reg.data_type == VSIR_DATA_F16 || dst->reg.data_type == VSIR_DATA_F32) +@@ -7639,9 +7639,9 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil + return VKD3D_ERROR_INVALID_SHADER; + } + +- if (src->reg.data_type == VKD3D_DATA_BOOL) ++ if (src->reg.data_type == VSIR_DATA_BOOL) + { +- if (dst->reg.data_type == VKD3D_DATA_BOOL) ++ if (dst->reg.data_type == VSIR_DATA_BOOL) + { + /* VSIR supports logic ops AND/OR/XOR on bool values. */ + op = spirv_compiler_map_logical_instruction(instruction); +@@ -7955,7 +7955,7 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, + 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) ++ if (src[0].reg.data_type != VSIR_DATA_BOOL) + { + if (instruction->opcode == VSIR_OP_CMP) + condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpFOrdGreaterThanEqual, +@@ -8398,7 +8398,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co + result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, + op, type_id, src0_id, src1_id); + +- if (dst->reg.data_type != VKD3D_DATA_BOOL) ++ if (dst->reg.data_type != VSIR_DATA_BOOL) + result_id = spirv_compiler_emit_bool_to_int(compiler, component_count, result_id, true); + spirv_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, result_id); + } +@@ -8579,7 +8579,7 @@ static void spirv_compiler_emit_discard(struct spirv_compiler *compiler, + * a mismatch between the VSIR structure and the SPIR-V one, which would cause problems if + * structurisation is necessary. Therefore we emit it as a function call. */ + condition_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); +- if (src->reg.data_type != VKD3D_DATA_BOOL) ++ if (src->reg.data_type != VSIR_DATA_BOOL) + condition_id = spirv_compiler_emit_int_to_bool(compiler, + instruction->flags, src->reg.data_type, 1, condition_id); + else if (instruction->flags & VKD3D_SHADER_CONDITIONAL_OP_Z) +@@ -8652,7 +8652,7 @@ static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, + if (instruction->src_count == 3) + spirv_compiler_emit_merge(compiler, src[1].reg.idx[0].offset, src[2].reg.idx[0].offset); + else +- ERR("Invalid branch with %u sources.\n", instruction->src_count); ++ ERR("Invalid branch with %zu sources.\n", instruction->src_count); + } + vkd3d_spirv_build_op_branch(builder, spirv_compiler_get_label_id(compiler, src[0].reg.idx[0].offset)); + return; +@@ -8666,7 +8666,7 @@ static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, + } + + condition_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); +- if (src[0].reg.data_type != VKD3D_DATA_BOOL) ++ if (src[0].reg.data_type != VSIR_DATA_BOOL) + 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. */ +@@ -8674,7 +8674,7 @@ static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, + spirv_compiler_emit_merge(compiler, src[3].reg.idx[0].offset, + (instruction->src_count > 4) ? src[4].reg.idx[0].offset : 0); + else +- ERR("Invalid branch with %u sources.\n", instruction->src_count); ++ ERR("Invalid branch with %zu sources.\n", instruction->src_count); + 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)); +@@ -9922,16 +9922,20 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, + static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { ++ enum vkd3d_shader_component_type component_type = VKD3D_SHADER_COMPONENT_UINT; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t type_id, lod_id, val_id, miplevel_count_id; +- enum vkd3d_shader_component_type component_type; + uint32_t constituents[VKD3D_VEC4_SIZE]; + unsigned int i, size_component_count; + struct vkd3d_shader_image image; + bool supports_mipmaps; + ++ if (instruction->flags & ~VKD3DSI_RESINFO_UINT) ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, ++ "Unhandled resinfo flags %#x.\n", instruction->flags & ~VKD3DSI_RESINFO_UINT); ++ + vkd3d_spirv_enable_capability(builder, SpvCapabilityImageQuery); + + spirv_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE); +@@ -9963,21 +9967,10 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, + val_id = vkd3d_spirv_build_op_composite_construct(builder, + type_id, constituents, i + 2); + +- component_type = VKD3D_SHADER_COMPONENT_FLOAT; +- +- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); +- if (instruction->flags == VKD3DSI_RESINFO_UINT) +- { +- /* SSA registers must match the specified result type. */ +- if (!register_is_ssa(&dst->reg)) +- val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); +- else +- component_type = VKD3D_SHADER_COMPONENT_UINT; +- } +- else ++ if (!(instruction->flags & VKD3DSI_RESINFO_UINT)) + { +- if (instruction->flags) +- FIXME("Unhandled flags %#x.\n", instruction->flags); ++ component_type = VKD3D_SHADER_COMPONENT_FLOAT; ++ type_id = vkd3d_spirv_get_type_id(builder, component_type, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id); + } + val_id = spirv_compiler_emit_swizzle(compiler, val_id, VKD3DSP_WRITEMASK_ALL, +@@ -10013,6 +10006,7 @@ static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *co + static void spirv_compiler_emit_sample_info(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) + { ++ enum vkd3d_shader_component_type component_type = VKD3D_SHADER_COMPONENT_UINT; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; +@@ -10020,6 +10014,10 @@ static void spirv_compiler_emit_sample_info(struct spirv_compiler *compiler, + uint32_t type_id, val_id; + unsigned int i; + ++ if (instruction->flags & ~VKD3DSI_SAMPLE_INFO_UINT) ++ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, ++ "Unhandled sample info flags %#x.\n", instruction->flags & ~VKD3DSI_SAMPLE_INFO_UINT); ++ + val_id = spirv_compiler_emit_query_sample_count(compiler, src); + + constituents[0] = val_id; +@@ -10028,20 +10026,14 @@ static void spirv_compiler_emit_sample_info(struct spirv_compiler *compiler, + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_composite_construct(builder, type_id, constituents, VKD3D_VEC4_SIZE); + +- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); +- if (instruction->flags == VKD3DSI_SAMPLE_INFO_UINT) ++ if (!(instruction->flags & VKD3DSI_SAMPLE_INFO_UINT)) + { +- val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); +- } +- else +- { +- if (instruction->flags) +- FIXME("Unhandled flags %#x.\n", instruction->flags); ++ component_type = VKD3D_SHADER_COMPONENT_FLOAT; ++ type_id = vkd3d_spirv_get_type_id(builder, component_type, VKD3D_VEC4_SIZE); + val_id = vkd3d_spirv_build_op_convert_utof(builder, type_id, val_id); + } +- + val_id = spirv_compiler_emit_swizzle(compiler, val_id, VKD3DSP_WRITEMASK_ALL, +- VKD3D_SHADER_COMPONENT_FLOAT, src->swizzle, dst->write_mask); ++ component_type, src->swizzle, dst->write_mask); + + spirv_compiler_emit_store_dst(compiler, dst, val_id); + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index 8acd7bc0db5..2175298a0db 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -751,15 +751,15 @@ static const enum vkd3d_shader_resource_type resource_type_table[] = + static const enum vsir_data_type data_type_table[] = + { + /* 0 */ VSIR_DATA_F32, +- /* VKD3D_SM4_DATA_UNORM */ VKD3D_DATA_UNORM, +- /* VKD3D_SM4_DATA_SNORM */ VKD3D_DATA_SNORM, ++ /* VKD3D_SM4_DATA_UNORM */ VSIR_DATA_UNORM, ++ /* VKD3D_SM4_DATA_SNORM */ VSIR_DATA_SNORM, + /* VKD3D_SM4_DATA_INT */ VSIR_DATA_I32, + /* VKD3D_SM4_DATA_UINT */ VSIR_DATA_U32, + /* VKD3D_SM4_DATA_FLOAT */ VSIR_DATA_F32, +- /* VKD3D_SM4_DATA_MIXED */ VKD3D_DATA_MIXED, ++ /* VKD3D_SM4_DATA_MIXED */ VSIR_DATA_MIXED, + /* VKD3D_SM4_DATA_DOUBLE */ VSIR_DATA_F64, +- /* VKD3D_SM4_DATA_CONTINUED */ VKD3D_DATA_CONTINUED, +- /* VKD3D_SM4_DATA_UNUSED */ VKD3D_DATA_UNUSED, ++ /* VKD3D_SM4_DATA_CONTINUED */ VSIR_DATA_CONTINUED, ++ /* VKD3D_SM4_DATA_UNUSED */ VSIR_DATA_UNUSED, + }; + + static bool shader_is_sm_5_1(const struct vkd3d_shader_sm4_parser *sm4) +@@ -895,7 +895,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u + >> VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; + } + +- reg_data_type = VKD3D_DATA_UNUSED; ++ reg_data_type = VSIR_DATA_UNUSED; + shader_sm4_read_dst_param(priv, &tokens, end, reg_data_type, &semantic->resource.reg); + shader_sm4_set_descriptor_register_range(priv, &semantic->resource.reg.reg, &semantic->resource.range); + +@@ -957,7 +957,7 @@ static void shader_sm4_read_dcl_sampler(struct vkd3d_shader_instruction *ins, ui + ins->flags = (opcode_token & VKD3D_SM4_SAMPLER_MODE_MASK) >> VKD3D_SM4_SAMPLER_MODE_SHIFT; + if (ins->flags & ~VKD3D_SM4_SAMPLER_COMPARISON) + FIXME("Unhandled sampler mode %#x.\n", ins->flags); +- shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &ins->declaration.sampler.src); ++ shader_sm4_read_src_param(priv, &tokens, end, VSIR_DATA_UNUSED, &ins->declaration.sampler.src); + shader_sm4_set_descriptor_register_range(priv, &ins->declaration.sampler.src.reg, &ins->declaration.sampler.range); + shader_sm4_read_register_space(priv, &tokens, end, &ins->declaration.sampler.range.space); + } +@@ -979,8 +979,7 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins + unsigned int *io_masks; + uint32_t write_mask; + +- shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, +- &index_range->dst); ++ shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VSIR_DATA_OPAQUE, &index_range->dst); + index_range->register_count = *tokens; + + register_idx = index_range->dst.reg.idx[index_range->dst.reg.idx_count - 1].offset; +@@ -1228,7 +1227,7 @@ static void shader_sm5_read_fcall(struct vkd3d_shader_instruction *ins, uint32_t + const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) + { + 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]); ++ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VSIR_DATA_OPAQUE, &ins->src[0]); + } + + static void shader_sm5_read_dcl_function_body(struct vkd3d_shader_instruction *ins, uint32_t opcode, +@@ -1315,7 +1314,7 @@ static void shader_sm5_read_dcl_uav_raw(struct vkd3d_shader_instruction *ins, ui + struct vkd3d_shader_raw_resource *resource = &ins->declaration.raw_resource; + const uint32_t *end = &tokens[token_count]; + +- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); ++ shader_sm4_read_dst_param(priv, &tokens, end, VSIR_DATA_UNUSED, &resource->resource.reg); + shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); + ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT; + shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.range.space); +@@ -1327,7 +1326,7 @@ static void shader_sm5_read_dcl_uav_structured(struct vkd3d_shader_instruction * + struct vkd3d_shader_structured_resource *resource = &ins->declaration.structured_resource; + const uint32_t *end = &tokens[token_count]; + +- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); ++ shader_sm4_read_dst_param(priv, &tokens, end, VSIR_DATA_UNUSED, &resource->resource.reg); + shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); + ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT; + resource->byte_stride = *tokens++; +@@ -1364,7 +1363,7 @@ static void shader_sm5_read_dcl_resource_structured(struct vkd3d_shader_instruct + struct vkd3d_shader_structured_resource *resource = &ins->declaration.structured_resource; + const uint32_t *end = &tokens[token_count]; + +- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); ++ shader_sm4_read_dst_param(priv, &tokens, end, VSIR_DATA_UNUSED, &resource->resource.reg); + shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); + resource->byte_stride = *tokens++; + if (resource->byte_stride % 4) +@@ -1378,7 +1377,7 @@ static void shader_sm5_read_dcl_resource_raw(struct vkd3d_shader_instruction *in + struct vkd3d_shader_raw_resource *resource = &ins->declaration.raw_resource; + const uint32_t *end = &tokens[token_count]; + +- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UNUSED, &resource->resource.reg); ++ shader_sm4_read_dst_param(priv, &tokens, end, VSIR_DATA_UNUSED, &resource->resource.reg); + shader_sm4_set_descriptor_register_range(priv, &resource->resource.reg.reg, &resource->resource.range); + shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.range.space); + } +@@ -1434,7 +1433,7 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) + * f -> VSIR_DATA_F32 + * i -> VSIR_DATA_I32 + * u -> VSIR_DATA_U32 +- * O -> VKD3D_DATA_OPAQUE ++ * O -> VSIR_DATA_OPAQUE + * R -> VKD3D_DATA_RESOURCE + * S -> VKD3D_DATA_SAMPLER + * U -> VKD3D_DATA_UAV +@@ -1998,9 +1997,9 @@ static enum vsir_data_type map_data_type(char t) + case 'u': + return VSIR_DATA_U32; + case 'O': +- return VKD3D_DATA_OPAQUE; ++ return VSIR_DATA_OPAQUE; + case '*': +- return VKD3D_DATA_UNUSED; ++ return VSIR_DATA_UNUSED; + default: + ERR("Invalid data type '%c'.\n", t); + return VSIR_DATA_F32; +@@ -2743,6 +2742,10 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str + } + } + ++ if ((ins->opcode == VSIR_OP_SAMPLE_INFO && ins->flags & VKD3DSI_SAMPLE_INFO_UINT) ++ || (ins->opcode == VSIR_OP_RESINFO && ins->flags & VKD3DSI_RESINFO_UINT)) ++ ins->dst[0].reg.data_type = VSIR_DATA_U32; ++ + return; + + fail: +@@ -4087,14 +4090,14 @@ static void tpf_simple_instruction(struct tpf_compiler *tpf, const struct vkd3d_ + + if (ins->dst_count != dst_count) + { +- ERR("Invalid destination count %u for vsir instruction %#x (expected %u).\n", ++ ERR("Invalid destination count %zu for vsir instruction %#x (expected %u).\n", + ins->dst_count, ins->opcode, dst_count); + tpf->result = VKD3D_ERROR_INVALID_SHADER; + return; + } + if (ins->src_count != src_count) + { +- ERR("Invalid source count %u for vsir instruction %#x (expected %u).\n", ++ ERR("Invalid source count %zu for vsir instruction %#x (expected %u).\n", + ins->src_count, ins->opcode, src_count); + tpf->result = VKD3D_ERROR_INVALID_SHADER; + return; +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index 9c615c116e9..a3c00af5d8b 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -87,7 +87,7 @@ void vkd3d_string_buffer_truncate(struct vkd3d_string_buffer *buffer, size_t siz + + static bool vkd3d_string_buffer_resize(struct vkd3d_string_buffer *buffer, int rc) + { +- unsigned int new_buffer_size = rc >= 0 ? buffer->content_size + rc + 1 : buffer->buffer_size * 2; ++ size_t new_buffer_size = rc >= 0 ? buffer->content_size + rc + 1 : buffer->buffer_size * 2; + + if (!vkd3d_array_reserve((void **)&buffer->buffer, &buffer->buffer_size, new_buffer_size, 1)) + { +@@ -100,7 +100,7 @@ static bool vkd3d_string_buffer_resize(struct vkd3d_string_buffer *buffer, int r + + int vkd3d_string_buffer_vprintf(struct vkd3d_string_buffer *buffer, const char *format, va_list args) + { +- unsigned int rem; ++ size_t rem; + va_list a; + int rc; + +@@ -135,7 +135,7 @@ int vkd3d_string_buffer_printf(struct vkd3d_string_buffer *buffer, const char *f + + int vkd3d_string_buffer_print_f32(struct vkd3d_string_buffer *buffer, float f) + { +- unsigned int idx = buffer->content_size + 1; ++ size_t idx = buffer->content_size + 1; + int ret; + + if (!(ret = vkd3d_string_buffer_printf(buffer, "%.8e", f)) && isfinite(f)) +@@ -150,7 +150,7 @@ int vkd3d_string_buffer_print_f32(struct vkd3d_string_buffer *buffer, float f) + + int vkd3d_string_buffer_print_f64(struct vkd3d_string_buffer *buffer, double d) + { +- unsigned int idx = buffer->content_size + 1; ++ size_t idx = buffer->content_size + 1; + int ret; + + if (!(ret = vkd3d_string_buffer_printf(buffer, "%.16e", d)) && isfinite(d)) +@@ -1132,7 +1132,7 @@ static void vkd3d_shader_scan_sampler_declaration(struct vkd3d_shader_scan_conte + struct vkd3d_shader_descriptor_info1 *d; + + if (!(d = vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, +- &sampler->src.reg, &sampler->range, VKD3D_SHADER_RESOURCE_NONE, VKD3D_DATA_UNUSED))) ++ &sampler->src.reg, &sampler->range, VKD3D_SHADER_RESOURCE_NONE, VSIR_DATA_UNUSED))) + return; + + if (instruction->flags & VKD3DSI_SAMPLER_COMPARISON_MODE) +@@ -1143,7 +1143,7 @@ static void vkd3d_shader_scan_combined_sampler_declaration( + struct vkd3d_shader_scan_context *context, const struct vkd3d_shader_semantic *semantic) + { + vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, &semantic->resource.reg.reg, +- &semantic->resource.range, VKD3D_SHADER_RESOURCE_NONE, VKD3D_DATA_UNUSED); ++ &semantic->resource.range, VKD3D_SHADER_RESOURCE_NONE, VSIR_DATA_UNUSED); + vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, &semantic->resource.reg.reg, + &semantic->resource.range, semantic->resource_type, VSIR_DATA_F32); + } +@@ -1526,16 +1526,6 @@ static enum vkd3d_shader_resource_data_type vkd3d_resource_data_type_from_data_t + { + switch (data_type) + { +- case VKD3D_DATA_UNORM: +- return VKD3D_SHADER_RESOURCE_DATA_UNORM; +- case VKD3D_DATA_SNORM: +- return VKD3D_SHADER_RESOURCE_DATA_SNORM; +- case VKD3D_DATA_MIXED: +- return VKD3D_SHADER_RESOURCE_DATA_MIXED; +- case VKD3D_DATA_CONTINUED: +- return VKD3D_SHADER_RESOURCE_DATA_CONTINUED; +- case VKD3D_DATA_UNUSED: +- return VKD3D_SHADER_RESOURCE_DATA_NONE; + case VSIR_DATA_F32: + return VKD3D_SHADER_RESOURCE_DATA_FLOAT; + case VSIR_DATA_F64: +@@ -1544,6 +1534,16 @@ static enum vkd3d_shader_resource_data_type vkd3d_resource_data_type_from_data_t + return VKD3D_SHADER_RESOURCE_DATA_INT; + case VSIR_DATA_U32: + return VKD3D_SHADER_RESOURCE_DATA_UINT; ++ case VSIR_DATA_SNORM: ++ return VKD3D_SHADER_RESOURCE_DATA_SNORM; ++ case VSIR_DATA_UNORM: ++ return VKD3D_SHADER_RESOURCE_DATA_UNORM; ++ case VSIR_DATA_MIXED: ++ return VKD3D_SHADER_RESOURCE_DATA_MIXED; ++ case VSIR_DATA_CONTINUED: ++ return VKD3D_SHADER_RESOURCE_DATA_CONTINUED; ++ case VSIR_DATA_UNUSED: ++ return VKD3D_SHADER_RESOURCE_DATA_NONE; + default: + ERR("Invalid resource data type %#x.\n", data_type); + return VKD3D_SHADER_RESOURCE_DATA_FLOAT; +@@ -1785,6 +1785,7 @@ static int compile_hlsl(const struct vkd3d_shader_compile_info *compile_info, + const struct shader_dump_data *dump_data, struct vkd3d_shader_code *out, + struct vkd3d_shader_message_context *message_context) + { ++ struct vkd3d_shader_compile_info preprocessed_info; + struct vkd3d_shader_code preprocessed; + int ret; + +@@ -1793,7 +1794,9 @@ static int compile_hlsl(const struct vkd3d_shader_compile_info *compile_info, + + vkd3d_shader_dump_shader(dump_data, preprocessed.code, preprocessed.size, SHADER_DUMP_TYPE_PREPROC); + +- ret = hlsl_compile_shader(&preprocessed, compile_info, out, message_context); ++ preprocessed_info = *compile_info; ++ preprocessed_info.source = preprocessed; ++ ret = hlsl_compile_shader(&preprocessed_info, message_context, out); + + vkd3d_shader_free_shader_code(&preprocessed); + return ret; +@@ -2187,7 +2190,7 @@ static struct vkd3d_shader_param_node *shader_param_allocator_node_create( + } + + static void shader_param_allocator_init(struct vkd3d_shader_param_allocator *allocator, +- unsigned int count, unsigned int stride) ++ size_t count, size_t stride) + { + allocator->count = max(count, MAX_REG_OUTPUT); + allocator->stride = stride; +@@ -2208,7 +2211,7 @@ static void shader_param_allocator_destroy(struct vkd3d_shader_param_allocator * + } + } + +-void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, unsigned int count) ++void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, size_t count) + { + void *params; + +@@ -2234,7 +2237,7 @@ void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, + return params; + } + +-bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve) ++bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, size_t reserve) + { + memset(instructions, 0, sizeof(*instructions)); + /* Size the parameter initial allocations so they are large enough for most shaders. The +@@ -2245,7 +2248,7 @@ bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instru + return shader_instruction_array_reserve(instructions, reserve); + } + +-bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve) ++bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, size_t reserve) + { + if (!vkd3d_array_reserve((void **)&instructions->elements, &instructions->capacity, reserve, + sizeof(*instructions->elements))) +@@ -2257,7 +2260,7 @@ bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *ins + } + + bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, +- unsigned int idx, unsigned int count) ++ size_t idx, size_t count) + { + VKD3D_ASSERT(idx <= instructions->count); + +@@ -2285,7 +2288,7 @@ bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *ins + + static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( + struct vkd3d_shader_instruction_array *instructions, const struct vkd3d_shader_src_param *params, +- unsigned int count); ++ size_t count); + + static bool shader_register_clone_relative_addresses(struct vkd3d_shader_register *reg, + struct vkd3d_shader_instruction_array *instructions) +@@ -2306,10 +2309,10 @@ static bool shader_register_clone_relative_addresses(struct vkd3d_shader_registe + + static struct vkd3d_shader_dst_param *shader_instruction_array_clone_dst_params( + struct vkd3d_shader_instruction_array *instructions, const struct vkd3d_shader_dst_param *params, +- unsigned int count) ++ size_t count) + { + struct vkd3d_shader_dst_param *dst_params; +- unsigned int i; ++ size_t i; + + if (!(dst_params = shader_dst_param_allocator_get(&instructions->dst_params, count))) + return NULL; +@@ -2326,10 +2329,10 @@ static struct vkd3d_shader_dst_param *shader_instruction_array_clone_dst_params( + + static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( + struct vkd3d_shader_instruction_array *instructions, const struct vkd3d_shader_src_param *params, +- unsigned int count) ++ size_t count) + { + struct vkd3d_shader_src_param *src_params; +- unsigned int i; ++ size_t i; + + if (!(src_params = shader_src_param_allocator_get(&instructions->src_params, count))) + return NULL; +@@ -2347,7 +2350,7 @@ static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( + /* NOTE: Immediate constant buffers are not cloned, so the source must not be destroyed while the + * destination is in use. This seems like a reasonable requirement given how this is currently used. */ + bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions, +- unsigned int dst, unsigned int src) ++ size_t dst, size_t src) + { + struct vkd3d_shader_instruction *ins = &instructions->elements[dst]; + +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 42f3c42033f..a0d7faaa407 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -710,13 +710,7 @@ enum vkd3d_shader_register_precision + + enum vsir_data_type + { +- VKD3D_DATA_UNORM, +- VKD3D_DATA_SNORM, +- VKD3D_DATA_OPAQUE, +- VKD3D_DATA_MIXED, +- VKD3D_DATA_CONTINUED, +- VKD3D_DATA_UNUSED, +- VKD3D_DATA_BOOL, ++ VSIR_DATA_BOOL, + + VSIR_DATA_F16, + VSIR_DATA_F32, +@@ -729,6 +723,14 @@ enum vsir_data_type + VSIR_DATA_U32, + VSIR_DATA_U64, + ++ VSIR_DATA_SNORM, ++ VSIR_DATA_UNORM, ++ ++ VSIR_DATA_OPAQUE, ++ VSIR_DATA_MIXED, ++ VSIR_DATA_CONTINUED, ++ VSIR_DATA_UNUSED, ++ + VSIR_DATA_TYPE_COUNT, + }; + +@@ -740,7 +742,7 @@ static inline bool data_type_is_integer(enum vsir_data_type data_type) + + static inline bool data_type_is_bool(enum vsir_data_type data_type) + { +- return data_type == VKD3D_DATA_BOOL; ++ return data_type == VSIR_DATA_BOOL; + } + + static inline bool data_type_is_floating_point(enum vsir_data_type data_type) +@@ -1281,8 +1283,8 @@ struct vkd3d_shader_instruction + struct vkd3d_shader_location location; + enum vkd3d_shader_opcode opcode; + uint32_t flags; +- unsigned int dst_count; +- unsigned int src_count; ++ size_t dst_count; ++ size_t src_count; + struct vkd3d_shader_dst_param *dst; + struct vkd3d_shader_src_param *src; + struct vkd3d_shader_texel_offset texel_offset; +@@ -1377,22 +1379,22 @@ struct vkd3d_shader_param_allocator + { + struct vkd3d_shader_param_node *head; + struct vkd3d_shader_param_node *current; +- unsigned int count; +- unsigned int stride; +- unsigned int index; ++ size_t count; ++ size_t stride; ++ size_t index; + }; + +-void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, unsigned int count); ++void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, size_t count); + + static inline struct vkd3d_shader_src_param *shader_src_param_allocator_get( +- struct vkd3d_shader_param_allocator *allocator, unsigned int count) ++ struct vkd3d_shader_param_allocator *allocator, size_t count) + { + VKD3D_ASSERT(allocator->stride == sizeof(struct vkd3d_shader_src_param)); + return shader_param_allocator_get(allocator, count); + } + + static inline struct vkd3d_shader_dst_param *shader_dst_param_allocator_get( +- struct vkd3d_shader_param_allocator *allocator, unsigned int count) ++ struct vkd3d_shader_param_allocator *allocator, size_t count) + { + VKD3D_ASSERT(allocator->stride == sizeof(struct vkd3d_shader_dst_param)); + return shader_param_allocator_get(allocator, count); +@@ -1413,14 +1415,14 @@ struct vkd3d_shader_instruction_array + struct vkd3d_shader_src_param *outpointid_param; + }; + +-bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); +-bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); ++bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, size_t reserve); ++bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, size_t reserve); + bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, +- unsigned int idx, unsigned int count); ++ size_t idx, size_t count); + bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, + struct vkd3d_shader_immediate_constant_buffer *icb); + bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions, +- unsigned int dst, unsigned int src); ++ size_t dst, size_t src); + void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions); + + struct vsir_program_iterator +@@ -1463,7 +1465,7 @@ static inline struct vkd3d_shader_instruction *vsir_program_iterator_next( + /* When insertion takes place, argument `it' is updated to point to the same + * instruction as before the insertion, but all other iterators and pointers + * to the same container are invalidated and cannot be used any more. */ +-static inline bool vsir_program_iterator_insert_after(struct vsir_program_iterator *it, unsigned int count) ++static inline bool vsir_program_iterator_insert_after(struct vsir_program_iterator *it, size_t count) + { + return shader_instruction_array_insert_at(it->array, it->idx + 1, count); + } +@@ -1797,17 +1799,19 @@ void vkd3d_compute_md5(const void *dxbc, size_t size, uint32_t checksum[4], enum + int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); + +-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); ++int hlsl_compile_shader(const struct vkd3d_shader_compile_info *compile_info, ++ struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_code *out); + + static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type( enum vsir_data_type data_type) + { + switch (data_type) + { ++ case VSIR_DATA_BOOL: ++ return VKD3D_SHADER_COMPONENT_BOOL; + case VSIR_DATA_F16: /* Minimum precision. TODO: native 16-bit */ + case VSIR_DATA_F32: +- case VKD3D_DATA_UNORM: +- case VKD3D_DATA_SNORM: ++ case VSIR_DATA_SNORM: ++ case VSIR_DATA_UNORM: + return VKD3D_SHADER_COMPONENT_FLOAT; + case VSIR_DATA_F64: + return VKD3D_SHADER_COMPONENT_DOUBLE; +@@ -1818,12 +1822,10 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty + return VKD3D_SHADER_COMPONENT_UINT; + case VSIR_DATA_U64: + return VKD3D_SHADER_COMPONENT_UINT64; +- case VKD3D_DATA_BOOL: +- return VKD3D_SHADER_COMPONENT_BOOL; + default: + FIXME("Unhandled data type %#x.\n", data_type); + /* fall-through */ +- case VKD3D_DATA_MIXED: ++ case VSIR_DATA_MIXED: + return VKD3D_SHADER_COMPONENT_UINT; + } + } +-- +2.47.2 + diff --git a/patches/vkd3d-latest/definition b/patches/vkd3d-latest/definition deleted file mode 100644 index 03864942..00000000 --- a/patches/vkd3d-latest/definition +++ /dev/null @@ -1 +0,0 @@ -# Keeping vkd3d to the latest git