From a0441666519aaf7b98e71c682488d5a02cc37de3 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Wed, 18 Jun 2025 10:25:18 +1000 Subject: [PATCH] Updated vkd3d-latest patchset Squash and rebase. --- ...-a8ca1f95c50561a16de5769646dcda0c045.patch | 6661 +++++++++++++++++ ...-c4c7f10d99daa5d3efc036d74d5e09b6f13.patch | 1416 ---- ...-7c0da1747a89a8cea27a42ace51b318e9d8.patch | 501 ++ ...-87ec2d98973432531d7d9d08dfc837376f9.patch | 308 - ...-2b257caea94fce2a5ef58dd303de9d73563.patch | 1454 ---- ...-f1b36edc076117970b5a6d05a924b6c4248.patch | 323 - ...-d65be3d0c5698a1b0df7c39ec0eaa485a8b.patch | 723 -- ...-8da518f2cd4021ef8d642bbb8050881d7ff.patch | 138 - ...-14477b1066cfd4d12ce044f98fea09507f3.patch | 2055 ----- ...-a8ca1f95c50561a16de5769646dcda0c045.patch | 1006 --- 10 files changed, 7162 insertions(+), 7423 deletions(-) create mode 100644 patches/vkd3d-latest/0001-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch delete mode 100644 patches/vkd3d-latest/0001-Updated-vkd3d-to-c4c7f10d99daa5d3efc036d74d5e09b6f13.patch create mode 100644 patches/vkd3d-latest/0002-Updated-vkd3d-to-7c0da1747a89a8cea27a42ace51b318e9d8.patch delete mode 100644 patches/vkd3d-latest/0002-Updated-vkd3d-to-87ec2d98973432531d7d9d08dfc837376f9.patch delete mode 100644 patches/vkd3d-latest/0003-Updated-vkd3d-to-2b257caea94fce2a5ef58dd303de9d73563.patch delete mode 100644 patches/vkd3d-latest/0004-Updated-vkd3d-to-f1b36edc076117970b5a6d05a924b6c4248.patch delete mode 100644 patches/vkd3d-latest/0005-Updated-vkd3d-to-d65be3d0c5698a1b0df7c39ec0eaa485a8b.patch delete mode 100644 patches/vkd3d-latest/0006-Updated-vkd3d-to-8da518f2cd4021ef8d642bbb8050881d7ff.patch delete mode 100644 patches/vkd3d-latest/0007-Updated-vkd3d-to-14477b1066cfd4d12ce044f98fea09507f3.patch delete mode 100644 patches/vkd3d-latest/0008-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch new file mode 100644 index 00000000..c7f56b6d --- /dev/null +++ b/patches/vkd3d-latest/0001-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch @@ -0,0 +1,6661 @@ +From 714c260cf3d63ad5a7f8b39e111af9aa81cf2768 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/0001-Updated-vkd3d-to-c4c7f10d99daa5d3efc036d74d5e09b6f13.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-c4c7f10d99daa5d3efc036d74d5e09b6f13.patch deleted file mode 100644 index d9e75091..00000000 --- a/patches/vkd3d-latest/0001-Updated-vkd3d-to-c4c7f10d99daa5d3efc036d74d5e09b6f13.patch +++ /dev/null @@ -1,1416 +0,0 @@ -From 352ffa600188ae9a71129323febe30d5905e794c 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 c4c7f10d99daa5d3efc036d74d5e09b6f1342407. - ---- - libs/vkd3d/include/private/vkd3d_common.h | 2 +- - libs/vkd3d/include/private/vkd3d_version.h | 2 +- - libs/vkd3d/libs/vkd3d-common/blob.c | 1 + - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 2 + - libs/vkd3d/libs/vkd3d-shader/dxil.c | 257 ++++++++++-------- - libs/vkd3d/libs/vkd3d-shader/fx.c | 49 ++-- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 26 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 40 +-- - libs/vkd3d/libs/vkd3d-shader/preproc.l | 1 + - libs/vkd3d/libs/vkd3d-shader/tpf.c | 10 + - .../libs/vkd3d-shader/vkd3d_shader_main.c | 57 ++-- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 2 + - .../vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c | 2 + - 13 files changed, 281 insertions(+), 170 deletions(-) - -diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h -index beb23257fb7..93c8a0bec7c 100644 ---- a/libs/vkd3d/include/private/vkd3d_common.h -+++ b/libs/vkd3d/include/private/vkd3d_common.h -@@ -278,7 +278,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..ae34ff97e25 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 379b297d)" -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..dc1678795e8 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -88,6 +88,7 @@ static const char * const shader_opcode_names[] = - [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", -@@ -1865,6 +1866,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/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index ca79939a39b..c9e99c6a9ba 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -655,6 +655,12 @@ enum sm6_value_type - 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,19 @@ 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_value -@@ -2433,7 +2442,11 @@ 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) -+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) - { - enum vkd3d_data_type data_type; - -@@ -2451,15 +2464,24 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str - 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_UNDEFINED: -@@ -2490,7 +2512,7 @@ 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); -+ sm6_register_from_value(&value->reg, value, sm6); - } - - static void register_make_constant_uint(struct vkd3d_shader_register *reg, unsigned int value) -@@ -2547,10 +2569,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 +2593,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->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 +2607,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 +2642,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,7 +2654,7 @@ 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) -@@ -2928,7 +2951,7 @@ 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); -+ sm6_register_from_value(&value->reg, value, sm6); - } - } - -@@ -3130,13 +3153,34 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - 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 +3222,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 (!index) -+ return VKD3D_ERROR_INVALID_SHADER; - -- if (reg.idx_count > 1) -+ if (index->index) - { - WARN("Unsupported stacked GEP.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -@@ -3203,8 +3251,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)) - { -@@ -3241,10 +3287,11 @@ 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; -+ -+ sm6_register_from_value(&dst->reg, dst, sm6); - - return VKD3D_OK; - } -@@ -3422,7 +3469,7 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - 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); -+ sm6_register_from_value(&dst->reg, dst, sm6); - break; - - default: -@@ -3430,7 +3477,7 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - 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); -+ sm6_register_from_value(&dst->reg, dst, sm6); - break; - } - -@@ -3537,7 +3584,7 @@ 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); -+ sm6_register_from_value(&dst->reg, dst, sm6); - } - - static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6_type *elem_type, -@@ -3551,8 +3598,8 @@ 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(&dst->reg, dst, sm6); -+ 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 +3623,8 @@ 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(&dst->reg, dst, sm6); -+ 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); -@@ -3891,7 +3938,7 @@ 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); -+ sm6_register_from_value(&value->reg, value, sm6); - } - - return VKD3D_OK; -@@ -3912,12 +3959,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( -@@ -4228,7 +4275,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 +4331,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 +4506,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 +4521,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 +4583,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 +4654,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 +4670,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 +4788,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,8 +4827,8 @@ 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); - } -@@ -4852,7 +4899,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 +4920,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); - } -@@ -5142,7 +5189,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, -@@ -5256,7 +5303,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 +5317,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); -@@ -5345,7 +5392,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,7 +5422,7 @@ 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)) -@@ -5448,7 +5495,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); - } -@@ -5589,7 +5636,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); - } -@@ -5631,7 +5678,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); -@@ -5697,7 +5744,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 +5783,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. */ -@@ -5801,7 +5848,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,14 +5903,14 @@ 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); -@@ -5925,7 +5972,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 +5981,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 +6050,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 +6068,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 +6076,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 +6089,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); - } -@@ -6108,7 +6155,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 +6197,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); -@@ -6213,7 +6260,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); - } -@@ -6277,7 +6324,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); - } -@@ -6317,7 +6364,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); - } -@@ -6368,7 +6415,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 +6692,7 @@ 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); -+ sm6_register_from_value(&dst->reg, dst, sm6); - } - - static void sm6_parser_decode_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -6896,7 +6943,7 @@ 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); -+ sm6_register_from_value(&dst->reg, value, sm6); - /* 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); -@@ -6905,7 +6952,7 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor - - 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); - -@@ -7051,8 +7098,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 +7121,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 +7176,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 +7242,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 +7255,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 +7268,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 +7282,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, -@@ -7293,13 +7341,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; -+ sm6_register_from_value(&dst->reg, dst, sm6); - - ins->opcode = VKD3DSIH_NOP; - } -@@ -7348,7 +7393,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 +7408,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 +7422,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 +7470,7 @@ 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); -+ sm6_register_from_value(&phi->reg, dst, sm6); - phi->incoming_count = record->operand_count / 2u; - - if (!vkd3d_array_reserve((void **)&phi->incoming, &phi->incoming_capacity, phi->incoming_count, -@@ -7536,7 +7581,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 +7596,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 +7607,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 +7657,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; -@@ -7688,7 +7733,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); - } -@@ -8029,7 +8074,7 @@ static enum vkd3d_result sm6_function_resolve_phi_incomings(const struct sm6_fun - 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); - } - } - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index a4f1a371299..c475a46da42 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -369,18 +369,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 +396,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; - } -@@ -1238,7 +1244,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)))) -@@ -1623,6 +1629,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 +1671,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 +1688,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; - } -@@ -2001,7 +2016,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 +2033,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; - } -@@ -3219,7 +3234,7 @@ 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); -+ size = max(size, get_fx_4_type_size(var->data_type) + var->buffer_offset * 4); - ++count; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 38d5c55c26b..f8f5f65517b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -5754,7 +5754,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), -@@ -9983,6 +9983,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; - } -@@ -13523,7 +13526,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..a6f17d4a834 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -1031,6 +1031,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; -@@ -1142,15 +1143,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 +1165,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 +6363,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 +6423,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 -diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l -index 4a8d0fddae1..d167415c356 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 */ -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 29b03871e05..59dca87c57d 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, -@@ -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}, -@@ -4135,6 +4141,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; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index f56608940db..4f625e3fae5 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, -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 3b4fb626fcc..d4d76266df2 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, -@@ -337,6 +338,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, -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 new file mode 100644 index 00000000..799efb04 --- /dev/null +++ b/patches/vkd3d-latest/0002-Updated-vkd3d-to-7c0da1747a89a8cea27a42ace51b318e9d8.patch @@ -0,0 +1,501 @@ +From 9b68296a60ed1150298f9638098765d0e92d406a 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-87ec2d98973432531d7d9d08dfc837376f9.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-87ec2d98973432531d7d9d08dfc837376f9.patch deleted file mode 100644 index 2a16621d..00000000 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-87ec2d98973432531d7d9d08dfc837376f9.patch +++ /dev/null @@ -1,308 +0,0 @@ -From 96b79c613055cef6f2da2015081adf61bd88becd Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Wed, 28 May 2025 07:14:59 +1000 -Subject: [PATCH] Updated vkd3d to 87ec2d98973432531d7d9d08dfc837376f91844c. - ---- - libs/vkd3d/libs/vkd3d-shader/dxbc.c | 10 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 8 +- - libs/vkd3d/libs/vkd3d-shader/fx.c | 106 ++++++++++++++++---- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 2 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 2 +- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 4 +- - 6 files changed, 100 insertions(+), 32 deletions(-) - -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 c9e99c6a9ba..9a4d194586b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -6343,7 +6343,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; - } - } -@@ -6389,7 +6389,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; - } - } -@@ -6892,7 +6892,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.\n", code); -+ "Cast operation %"PRIu64" is unhandled.", code); - return VKD3DSIH_INVALID; - } - -@@ -6900,7 +6900,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.\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; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index c475a46da42..1d5f95fa988 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -1547,12 +1547,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) -@@ -1561,13 +1582,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) -@@ -1592,19 +1611,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) -@@ -1876,7 +1944,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; -@@ -1899,7 +1967,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); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index f8f5f65517b..e9d3d2ec8dd 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -3919,7 +3919,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; - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 1f967c22406..a6f34703c2d 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -4239,7 +4239,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; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 59dca87c57d..6042a76c3c4 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -1169,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 -@@ -1195,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 --- -2.47.2 - diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-2b257caea94fce2a5ef58dd303de9d73563.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-2b257caea94fce2a5ef58dd303de9d73563.patch deleted file mode 100644 index b1dac027..00000000 --- a/patches/vkd3d-latest/0003-Updated-vkd3d-to-2b257caea94fce2a5ef58dd303de9d73563.patch +++ /dev/null @@ -1,1454 +0,0 @@ -From 1bb8646ffba747c1dd8fe298e6b9e98595d28198 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 3 Jun 2025 07:40:14 +1000 -Subject: [PATCH] Updated vkd3d to 2b257caea94fce2a5ef58dd303de9d73563b9126. - ---- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 8 +- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 8 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 227 +++++++++--------- - libs/vkd3d/libs/vkd3d-shader/fx.c | 139 +++++------ - libs/vkd3d/libs/vkd3d-shader/glsl.c | 8 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.h | 1 + - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 180 +++++++++++--- - libs/vkd3d/libs/vkd3d-shader/ir.c | 9 +- - libs/vkd3d/libs/vkd3d-shader/msl.c | 10 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 51 ---- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 29 ++- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 3 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 12 +- - 13 files changed, 385 insertions(+), 300 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index dc1678795e8..db60883f2a3 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -298,14 +298,16 @@ static const char * const shader_opcode_names[] = - [VKD3DSIH_SWITCH_MONOLITHIC ] = "switch", - [VKD3DSIH_SYNC ] = "sync", - [VKD3DSIH_TAN ] = "tan", -- [VKD3DSIH_TEX ] = "texld", -+ [VKD3DSIH_TEX ] = "tex", - [VKD3DSIH_TEXBEM ] = "texbem", - [VKD3DSIH_TEXBEML ] = "texbeml", -- [VKD3DSIH_TEXCOORD ] = "texcrd", -+ [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", -@@ -1706,7 +1708,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) -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 57d874efe37..05f46e264b9 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}}, -@@ -2014,7 +2014,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; -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 9a4d194586b..c85b644df15 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -651,6 +651,7 @@ enum sm6_value_type - VALUE_TYPE_ICB, - VALUE_TYPE_IDXTEMP, - VALUE_TYPE_GROUPSHAREDMEM, -+ VALUE_TYPE_CONSTANT, - VALUE_TYPE_UNDEFINED, - VALUE_TYPE_INVALID, - }; -@@ -699,6 +700,11 @@ struct sm6_groupsharedmem_data - struct sm6_index index; - }; - -+struct sm6_constant_data -+{ -+ union vsir_immediate_constant immconst; -+}; -+ - struct sm6_value - { - const struct sm6_type *type; -@@ -714,6 +720,7 @@ 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; - }; -@@ -2019,11 +2026,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) - { -@@ -2278,6 +2280,7 @@ static inline bool sm6_value_is_register(const struct sm6_value *value) - 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; -@@ -2329,7 +2332,16 @@ static bool sm6_value_is_ssa(const struct sm6_value *value) - - 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) -@@ -2448,9 +2460,11 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, - 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; - -- data_type = vkd3d_data_type_from_sm6_type(sm6_type_get_scalar_type(value->type, 0)); -+ scalar_type = sm6_type_get_scalar_type(value->type, 0); -+ data_type = vkd3d_data_type_from_sm6_type(scalar_type); - - switch (value->value_type) - { -@@ -2484,6 +2498,12 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str - 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: - case VALUE_TYPE_INVALID: - vsir_register_init(reg, VKD3DSPR_UNDEF, data_type, 0); -@@ -2657,19 +2677,17 @@ static void instruction_dst_param_init_ssa_vector(struct vkd3d_shader_instructio - 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; - } -@@ -3040,30 +3058,6 @@ 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)) -@@ -3075,10 +3069,10 @@ static float register_get_float_value(const struct vkd3d_shader_register *reg) - if (reg->type == VKD3DSPR_IMMCONST64) - { - WARN("Truncating double to float.\n"); -- return bitcast_uint64_to_double(reg->u.immconst_u64[0]); -+ return reg->u.immconst_f64[0]; - } - -- return bitcast_uint_to_float(reg->u.immconst_u32[0]); -+ return reg->u.immconst_f32[0]; - } - - static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, const struct sm6_type *type, -@@ -3298,10 +3292,8 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c - - 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; -@@ -3322,18 +3314,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"); - -@@ -3348,19 +3328,22 @@ 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)); -+ sm6_register_from_value(&dst->reg, dst, sm6); - } -- /* For non-aggregates, register constant data is already zero-filled. */ - break; - - case CST_CODE_INTEGER: -@@ -3373,11 +3356,15 @@ 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; -+ -+ sm6_register_from_value(&dst->reg, dst, sm6); - - break; - -@@ -3391,14 +3378,15 @@ 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; -+ -+ sm6_register_from_value(&dst->reg, dst, sm6); - - break; - -@@ -3424,6 +3412,48 @@ 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; -+ sm6_register_from_value(&dst->reg, dst, sm6); -+ 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; -+ sm6_register_from_value(&dst->reg, dst, sm6); -+ 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; -@@ -3460,59 +3490,28 @@ 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, sm6); -- 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; -+ } -+ -+ type = dst->type; -+ *dst = *src; -+ dst->type = type; - -- 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, sm6); - 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; - } -@@ -5427,7 +5426,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in - - 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 -@@ -5440,7 +5439,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; -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index 1d5f95fa988..90da8048b8e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -873,7 +873,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 }, -@@ -904,17 +904,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 }, -@@ -923,55 +923,55 @@ 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 }, -- -- { "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 }, -+ { "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 void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) -@@ -994,16 +994,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 */ -@@ -1021,6 +1011,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, -@@ -2140,13 +2133,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); -@@ -3295,6 +3284,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; - -@@ -3302,7 +3293,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 = max(size, get_fx_4_type_size(var->data_type) + var->buffer_offset * 4); -+ -+ unpacked_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float); -+ size = max(size, unpacked_size + var->buffer_offset * 4); - ++count; - } - -@@ -3969,7 +3962,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; -@@ -3993,13 +3986,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) - { -@@ -4540,6 +4534,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) -@@ -4575,6 +4574,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"); -diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index e4497b9ac5b..0a91024a8d1 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); -@@ -2313,7 +2319,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_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index e9d3d2ec8dd..d4cd338f15a 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); -@@ -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) - { -@@ -10835,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) -@@ -12130,6 +12215,22 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, - } - } - -+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 (!(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 - * vsir_program, so it can be used as input to tpf_compile() without relying - * on ctx and entry_func. */ -@@ -12204,6 +12305,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); -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index a6f17d4a834..4abf6a65dbb 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -823,7 +823,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 +838,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; -@@ -1041,7 +1041,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) -@@ -1049,7 +1049,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; -@@ -1062,6 +1062,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: -diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index 4f37468af86..d354c7efcb1 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -488,6 +488,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); -@@ -545,6 +548,9 @@ static void VKD3D_PRINTF_FUNC(3, 4) msl_print_assignment( - 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); -@@ -1353,7 +1359,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,7 +1394,7 @@ 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) -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index a6f34703c2d..3e58718afa1 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; -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 6042a76c3c4..08bdc3e645a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -3261,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); -@@ -3269,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 */ - -@@ -3297,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); -@@ -3312,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) -@@ -4176,6 +4186,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: -@@ -4190,6 +4202,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 4f625e3fae5..783f4e6134c 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -1436,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 d4d76266df2..5dd00f00fe8 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -552,10 +552,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, -@@ -966,7 +968,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]; -@@ -1781,14 +1783,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; --- -2.47.2 - diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-f1b36edc076117970b5a6d05a924b6c4248.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-f1b36edc076117970b5a6d05a924b6c4248.patch deleted file mode 100644 index 953eb340..00000000 --- a/patches/vkd3d-latest/0004-Updated-vkd3d-to-f1b36edc076117970b5a6d05a924b6c4248.patch +++ /dev/null @@ -1,323 +0,0 @@ -From e30c5257409bcdeb321524dc3459cb9e64165a91 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Thu, 5 Jun 2025 07:25:40 +1000 -Subject: [PATCH] Updated vkd3d to f1b36edc076117970b5a6d05a924b6c4248e082f. - ---- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 69 ++++++++++++--------- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 55 +++++++++------- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 36 ++++++----- - 3 files changed, 91 insertions(+), 69 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index c85b644df15..ff56cd6284f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -6805,6 +6805,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); -@@ -6828,66 +6829,58 @@ 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, -@@ -6904,6 +6897,20 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ - 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; - } - -@@ -6955,9 +6962,11 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor - - 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 -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index d4cd338f15a..d4e29e16b7c 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -12114,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); -@@ -12132,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; -@@ -12169,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; - -@@ -12189,29 +12190,35 @@ 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); -+ vsir_resource->range.first = array_first; -+ vsir_resource->range.last = array_last; -+ vsir_resource->range.space = resource->space; - -- semantic->resource.range.first = array_first; -- semantic->resource.range.last = array_last; -- semantic->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) -- semantic->sample_count = component_type->sample_count; -+ if (multisampled) -+ ins->declaration.semantic.sample_count = component_type->sample_count; -+ } - } - } - -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 08bdc3e645a..ae3fa1650bf 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -3859,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; -@@ -3875,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; - } - -@@ -3903,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); - } --- -2.47.2 - diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-d65be3d0c5698a1b0df7c39ec0eaa485a8b.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-d65be3d0c5698a1b0df7c39ec0eaa485a8b.patch deleted file mode 100644 index 310b7f9a..00000000 --- a/patches/vkd3d-latest/0005-Updated-vkd3d-to-d65be3d0c5698a1b0df7c39ec0eaa485a8b.patch +++ /dev/null @@ -1,723 +0,0 @@ -From e26c2e6860b1d6d6fe8573d9b4654e4405407757 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Fri, 6 Jun 2025 07:10:30 +1000 -Subject: [PATCH] Updated vkd3d to d65be3d0c5698a1b0df7c39ec0eaa485a8bd35de. - ---- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 32 ++-- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 3 + - libs/vkd3d/libs/vkd3d-shader/msl.c | 239 +++++++++++++++++-------- - libs/vkd3d/libs/vkd3d-shader/preproc.h | 2 +- - libs/vkd3d/libs/vkd3d-shader/preproc.l | 38 ++-- - 5 files changed, 210 insertions(+), 104 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index ff56cd6284f..8c71176fb0b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -644,7 +644,6 @@ struct sm6_type - enum sm6_value_type - { - VALUE_TYPE_FUNCTION, -- VALUE_TYPE_REG, - VALUE_TYPE_DATA, - VALUE_TYPE_HANDLE, - VALUE_TYPE_SSA, -@@ -711,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; -@@ -747,7 +747,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; -@@ -2275,7 +2275,6 @@ 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: -@@ -2468,10 +2467,6 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str - - switch (value->value_type) - { -- case VALUE_TYPE_REG: -- *reg = value->reg; -- break; -- - 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; -@@ -2514,6 +2509,8 @@ 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) -@@ -3743,7 +3740,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) -@@ -6949,10 +6945,9 @@ 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, sm6); -- /* 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; -+ sm6_register_from_value(&dst->reg, dst, sm6); - return; - } - -@@ -7478,7 +7473,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, sm6); - phi->incoming_count = record->operand_count / 2u; - - if (!vkd3d_array_reserve((void **)&phi->incoming, &phi->incoming_capacity, phi->incoming_count, -@@ -8004,7 +7998,8 @@ 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; -+ sm6_register_from_value(&dst->reg, dst, sm6); - } - } - else -@@ -8076,7 +8071,7 @@ 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, -@@ -8171,7 +8166,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; - -@@ -8249,6 +8243,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; -@@ -8395,7 +8393,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/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/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index d354c7efcb1..62981811ee4 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,22 +361,24 @@ 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; - } - -@@ -542,6 +546,25 @@ 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, ...) - { -@@ -734,6 +757,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; - -@@ -763,30 +787,38 @@ 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_2DMS -+ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBE -+ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY -+ || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY) -+ 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) -@@ -794,7 +826,7 @@ 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); -@@ -1014,21 +1046,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) -@@ -1065,15 +1124,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, -@@ -1087,13 +1146,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"); -@@ -1144,15 +1206,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) -@@ -1215,6 +1270,12 @@ 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"); -+ } -+ - vkd3d_string_buffer_printf(buffer, "};\n\n"); - } - -@@ -1233,23 +1294,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"); - } - } -@@ -1265,12 +1348,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; - -@@ -1285,6 +1362,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, -@@ -1322,6 +1401,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); - -@@ -1330,14 +1415,13 @@ static void msl_generate_entrypoint(struct msl_generator *gen) - 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"); -- - 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 (gen->program->descriptors.descriptor_count) - vkd3d_string_buffer_printf(gen->buffer, ", descriptors"); - vkd3d_string_buffer_printf(gen->buffer, ");\n"); -@@ -1397,8 +1481,11 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader - "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 (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 d167415c356..5c56fba0229 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/preproc.l -+++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l -@@ -72,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); -@@ -81,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 {} - -@@ -197,6 +201,10 @@ INT_SUFFIX [uUlL]{0,2} - BEGIN(INITIAL); - return T_NEWLINE; - } -+<> { -+ BEGIN(INITIAL); -+ yyterminate(); -+ } - - {WS}+ {} - [-()\[\]{},+!*/<>&|^?:] {return yytext[0];} -@@ -251,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]; -@@ -291,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) -@@ -348,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); -@@ -408,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) -@@ -782,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; --- -2.47.2 - diff --git a/patches/vkd3d-latest/0006-Updated-vkd3d-to-8da518f2cd4021ef8d642bbb8050881d7ff.patch b/patches/vkd3d-latest/0006-Updated-vkd3d-to-8da518f2cd4021ef8d642bbb8050881d7ff.patch deleted file mode 100644 index e9eb4522..00000000 --- a/patches/vkd3d-latest/0006-Updated-vkd3d-to-8da518f2cd4021ef8d642bbb8050881d7ff.patch +++ /dev/null @@ -1,138 +0,0 @@ -From ec08bb5bfc8d67b975516a5a2dc34e9eaf7306ae Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 10 Jun 2025 07:48:09 +1000 -Subject: [PATCH] Updated vkd3d to 8da518f2cd4021ef8d642bbb8050881d7ff490c1. - ---- - libs/vkd3d/libs/vkd3d-shader/msl.c | 45 +++++++++++++++++++++++++++++- - 1 file changed, 44 insertions(+), 1 deletion(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index 62981811ee4..b3e251eff28 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -382,6 +382,19 @@ static enum msl_data_type msl_print_register_name(struct vkd3d_string_buffer *bu - 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); -@@ -901,6 +914,14 @@ static void msl_ret(struct msl_generator *gen, const struct vkd3d_shader_instruc - 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; -@@ -908,11 +929,15 @@ 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_DCL_INDEXABLE_TEMP: -+ msl_dcl_indexable_temp(gen, ins); -+ break; - case VKD3DSIH_NOP: - break; - case VKD3DSIH_DIV: -@@ -933,6 +958,7 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VKD3DSIH_ENDIF: - msl_end_block(gen); - break; -+ case VKD3DSIH_EQO: - case VKD3DSIH_IEQ: - msl_relop(gen, ins, "=="); - break; -@@ -949,6 +975,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: -@@ -1276,6 +1303,12 @@ static void msl_generate_output_struct_declarations(struct msl_generator *gen) - 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"); - } - -@@ -1371,6 +1404,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) -@@ -1414,6 +1450,9 @@ 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 (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); - -@@ -1422,9 +1461,11 @@ static void msl_generate_entrypoint(struct msl_generator *gen) - 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); - -@@ -1486,6 +1527,8 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader - 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"); --- -2.47.2 - diff --git a/patches/vkd3d-latest/0007-Updated-vkd3d-to-14477b1066cfd4d12ce044f98fea09507f3.patch b/patches/vkd3d-latest/0007-Updated-vkd3d-to-14477b1066cfd4d12ce044f98fea09507f3.patch deleted file mode 100644 index e0e62a66..00000000 --- a/patches/vkd3d-latest/0007-Updated-vkd3d-to-14477b1066cfd4d12ce044f98fea09507f3.patch +++ /dev/null @@ -1,2055 +0,0 @@ -From bc2380830ccf29787be590fd59ef4acae4bfd243 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Wed, 11 Jun 2025 07:52:20 +1000 -Subject: [PATCH] Updated vkd3d to 14477b1066cfd4d12ce044f98fea09507f320251. - ---- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 332 +---------------- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 18 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 257 ++++++------- - libs/vkd3d/libs/vkd3d-shader/fx.c | 153 ++++---- - libs/vkd3d/libs/vkd3d-shader/glsl.c | 6 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 342 +++++++++++++++++- - libs/vkd3d/libs/vkd3d-shader/msl.c | 126 ++++++- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 9 +- - 8 files changed, 701 insertions(+), 542 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -index db60883f2a3..af5552635cb 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c -@@ -27,336 +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_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", --}; -- - static const char * const shader_register_names[] = - { - [VKD3DSPR_ADDR ] = "a", -@@ -1750,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, -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 05f46e264b9..c8291afcf6e 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -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; - } -@@ -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/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 8c71176fb0b..1cbef387260 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -722,7 +722,6 @@ struct sm6_value - struct sm6_groupsharedmem_data groupsharedmem; - struct sm6_constant_data constant; - } u; -- struct vkd3d_shader_register reg; - }; - - struct dxil_record -@@ -2225,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; -@@ -2296,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) -@@ -2326,7 +2309,7 @@ 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) -@@ -2343,18 +2326,81 @@ static bool sm6_value_is_numeric_array(const struct sm6_value *value) - } - } - --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) -@@ -2517,9 +2563,9 @@ static void sm6_parser_init_ssa_value(struct sm6_parser *sm6, struct sm6_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 -@@ -2529,7 +2575,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, sm6); - } - - static void register_make_constant_uint(struct vkd3d_shader_register *reg, unsigned int value) -@@ -2612,7 +2657,7 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, - { - 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 (!address || sm6_value_is_undef(address)) -@@ -2966,7 +3011,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, sm6); - } - } - -@@ -3055,23 +3099,6 @@ static inline uint64_t decode_rotated_signed_value(uint64_t value) - return value << 63; - } - --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 reg->u.immconst_f64[0]; -- } -- -- return reg->u.immconst_f32[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) - { -@@ -3262,7 +3289,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"); -@@ -3282,8 +3309,6 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c - index->index = operands[2]; - index->is_in_bounds = record->code == CST_CODE_CE_INBOUNDS_GEP; - -- sm6_register_from_value(&dst->reg, dst, sm6); -- - return VKD3D_OK; - } - -@@ -3339,7 +3364,6 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - { - dst->value_type = VALUE_TYPE_CONSTANT; - memset(&dst->u.constant, 0, sizeof(dst->u.constant)); -- sm6_register_from_value(&dst->reg, dst, sm6); - } - break; - -@@ -3361,8 +3385,6 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - else - dst->u.constant.immconst.immconst_u64[0] = value; - -- sm6_register_from_value(&dst->reg, dst, sm6); -- - break; - - case CST_CODE_FLOAT: -@@ -3383,8 +3405,6 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - else - dst->u.constant.immconst.immconst_u64[0] = value; - -- sm6_register_from_value(&dst->reg, dst, sm6); -- - break; - - case CST_CODE_DATA: -@@ -3418,14 +3438,12 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - 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, sm6); - 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; -- sm6_register_from_value(&dst->reg, dst, sm6); - break; - } - -@@ -3500,8 +3518,6 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const - type = dst->type; - *dst = *src; - dst->type = type; -- -- sm6_register_from_value(&dst->reg, dst, sm6); - break; - } - -@@ -3580,7 +3596,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, sm6); - } - - static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6_type *elem_type, -@@ -3594,7 +3609,6 @@ 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); - 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; -@@ -3619,7 +3633,6 @@ 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); - sm6_register_from_value(&ins->declaration.tgsm_structured.reg.reg, dst, sm6); - if (dst->structure_stride != 4) - { -@@ -3933,7 +3946,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, sm6); - } - - return VKD3D_OK; -@@ -4205,7 +4217,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, -@@ -4830,7 +4842,7 @@ static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_ - - 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) - { -@@ -4934,7 +4946,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; -@@ -4968,7 +4980,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); -@@ -5005,7 +5017,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); -@@ -5106,7 +5118,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; - } -@@ -5123,8 +5135,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); -@@ -5137,7 +5149,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; -@@ -5155,7 +5167,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); -@@ -5196,7 +5208,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, -@@ -5265,8 +5277,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) -@@ -5353,7 +5365,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); - -@@ -5508,8 +5520,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) - { -@@ -5618,7 +5630,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); -@@ -5652,7 +5664,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); -@@ -5695,7 +5707,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); -@@ -5721,7 +5733,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); -@@ -5818,7 +5830,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); -@@ -5911,17 +5923,17 @@ static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_in - 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, -@@ -6102,8 +6114,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) -@@ -6203,7 +6215,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); -@@ -6277,7 +6289,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); -@@ -6351,7 +6363,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; -@@ -6398,8 +6410,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) -@@ -6687,7 +6699,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, sm6); - } - - static void sm6_parser_decode_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, -@@ -6792,7 +6803,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); - } - -@@ -6947,7 +6958,6 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor - { - *dst = *value; - dst->type = type; -- sm6_register_from_value(&dst->reg, dst, sm6); - return; - } - -@@ -7298,7 +7308,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, -@@ -7318,7 +7328,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) - { -@@ -7347,8 +7357,6 @@ 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(&dst->reg, dst, sm6); -- - ins->opcode = VKD3DSIH_NOP; - } - -@@ -7698,7 +7706,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; -@@ -7761,7 +7769,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; -@@ -7775,12 +7783,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; -@@ -7794,12 +7802,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; -@@ -7813,7 +7821,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; - } -@@ -7999,7 +8007,6 @@ static void metadata_attachment_record_apply(const struct dxil_record *record, e - else if (metadata_node_get_unary_uint(node, &operand, sm6)) - { - dst->non_uniform = !!operand; -- sm6_register_from_value(&dst->reg, dst, sm6); - } - } - else -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index 90da8048b8e..9efaa0bc1fa 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/fx.c -+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c -@@ -289,15 +289,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); -@@ -770,7 +761,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; -@@ -779,8 +770,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 }, -@@ -974,6 +966,23 @@ fx_2_states[] = - { "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 }, -+ { "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 void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) - { - struct vkd3d_bytecode_buffer *buffer = &fx->structured; -@@ -3648,20 +3657,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) -@@ -3818,15 +3850,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); - } -@@ -3840,7 +3869,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) -@@ -3865,7 +3895,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); -@@ -3943,15 +3973,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); -@@ -4028,18 +4072,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"); -@@ -4050,10 +4090,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"); -@@ -4067,7 +4106,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); - -@@ -4189,8 +4228,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) -@@ -4230,20 +4268,16 @@ 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_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) - { -@@ -4257,11 +4291,6 @@ 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); -@@ -4296,23 +4325,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); -@@ -4718,6 +4743,8 @@ fx_4_fxlc_opcodes[] = - { 0x13a, "ceil" }, - { 0x200, "min" }, - { 0x201, "max" }, -+ { 0x202, "lt" }, -+ { 0x203, "ge" }, - { 0x204, "add" }, - { 0x205, "mul" }, - { 0x206, "atan2" }, -diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index 0a91024a8d1..214632c00eb 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/glsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -561,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, -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 4abf6a65dbb..1925e20c685 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) - { -@@ -1078,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: -diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index b3e251eff28..47ea6ce1f4b 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -737,19 +737,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); - } - -@@ -761,6 +778,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; -@@ -908,6 +969,37 @@ 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); -@@ -935,11 +1027,23 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - 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; -@@ -956,6 +1060,8 @@ 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: -@@ -988,6 +1094,7 @@ 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: - msl_relop(gen, ins, "<"); - break; -@@ -1000,6 +1107,9 @@ 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, "!="); -@@ -1014,6 +1124,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VKD3DSIH_LOG: - msl_intrinsic(gen, ins, "log2"); - break; -+ case VKD3DSIH_LOOP: -+ msl_loop(gen); -+ break; - case VKD3DSIH_MOV: - msl_mov(gen, ins); - break; -@@ -1050,6 +1163,9 @@ 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; - default: - msl_unhandled(gen, ins); - break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 5dd00f00fe8..a5d1b8f4e05 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -223,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, -@@ -611,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, -@@ -1336,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 --- -2.47.2 - diff --git a/patches/vkd3d-latest/0008-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch b/patches/vkd3d-latest/0008-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch deleted file mode 100644 index aaf96e9a..00000000 --- a/patches/vkd3d-latest/0008-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch +++ /dev/null @@ -1,1006 +0,0 @@ -From 0806cca6d0c3d59da09a8b7a429165261710a047 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Fri, 13 Jun 2025 07:50:21 +1000 -Subject: [PATCH] Updated vkd3d to a8ca1f95c50561a16de5769646dcda0c045b7a46. - ---- - libs/vkd3d/include/private/vkd3d_common.h | 1 + - libs/vkd3d/include/private/vkd3d_version.h | 2 +- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 117 +++++++- - libs/vkd3d/libs/vkd3d-shader/fx.c | 328 +++++++++++++++------ - libs/vkd3d/libs/vkd3d-shader/ir.c | 40 +-- - libs/vkd3d/libs/vkd3d-shader/msl.c | 28 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 92 +----- - 7 files changed, 397 insertions(+), 211 deletions(-) - -diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h -index 93c8a0bec7c..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') -diff --git a/libs/vkd3d/include/private/vkd3d_version.h b/libs/vkd3d/include/private/vkd3d_version.h -index ae34ff97e25..687751d6a5f 100644 ---- a/libs/vkd3d/include/private/vkd3d_version.h -+++ b/libs/vkd3d/include/private/vkd3d_version.h -@@ -1 +1 @@ --#define VKD3D_VCS_ID " (git 379b297d)" -+#define VKD3D_VCS_ID " (git a8ca1f95)" -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 1cbef387260..53578ce7141 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -2499,6 +2499,79 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type - return VKD3D_DATA_UINT; - } - -+/* 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 void register_convert_to_minimum_precision(struct vkd3d_shader_register *reg) -+{ -+ unsigned int i; -+ -+ switch (reg->data_type) -+ { -+ 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); - -@@ -2516,6 +2589,7 @@ 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: -@@ -2523,6 +2597,7 @@ 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: -@@ -2530,6 +2605,7 @@ 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: -@@ -2543,6 +2619,7 @@ 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: -@@ -3105,6 +3182,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co - 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. */ -@@ -3156,16 +3234,37 @@ 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; -diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c -index 9efaa0bc1fa..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; -@@ -1079,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[] = -@@ -4268,6 +4270,8 @@ static void fx_dump_blob(struct fx_parser *parser, const void *blob, uint32_t si - } - } - -+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, blob_size = 0; -@@ -4295,7 +4299,7 @@ static void fx_parse_fx_2_array_selector(struct fx_parser *parser) - { - 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); - } - } - -@@ -4718,7 +4722,7 @@ static const struct - uint32_t opcode; - const char *name; - } --fx_4_fxlc_opcodes[] = -+fxlc_opcodes[] = - { - { 0x100, "mov" }, - { 0x101, "neg" }, -@@ -4773,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 ""; -@@ -4804,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; -@@ -4818,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"; -@@ -4827,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; -@@ -4872,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)); - -@@ -4943,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) -@@ -4960,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); -- -- 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)); -+ code.ptr = fxlc.data.code; -+ code.end = (uint32_t *)((uint8_t *)fxlc.data.code + fxlc.data.size); - -- 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/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 1925e20c685..0aebfea2add 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -8727,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, -@@ -8736,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, -@@ -8746,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; - } - -@@ -8760,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; - } - -@@ -9249,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)); - } - -@@ -9268,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; - } -@@ -10038,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; - } - } -@@ -10059,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 47ea6ce1f4b..08519787b0a 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -612,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) -@@ -861,10 +863,11 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct - data_type = VKD3D_DATA_FLOAT; - } - -- if (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS -- || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBE -- || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY -- || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY) -+ 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); - -@@ -903,7 +906,10 @@ 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, ", "); -- 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); -@@ -1096,6 +1102,7 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - break; - case VKD3DSIH_ILT: - case VKD3DSIH_LTO: -+ case VKD3DSIH_ULT: - msl_relop(gen, ins, "<"); - break; - case VKD3DSIH_MAD: -@@ -1114,11 +1121,15 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - 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: -@@ -1166,6 +1177,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d - case VKD3DSIH_SWITCH: - msl_switch(gen, ins); - break; -+ case VKD3DSIH_XOR: -+ msl_binop(gen, ins, "^"); -+ break; - default: - msl_unhandled(gen, ins); - break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 3e58718afa1..13ebde5cfd5 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -4527,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) - { -@@ -4603,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)]; - } - } - -@@ -4755,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: -@@ -9203,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; - } - -@@ -9884,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; - } - -@@ -9963,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) -@@ -11040,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; - } - --- -2.47.2 -