From 6bda17c53c7627d3fdabdcc69e2f8daa965c5996 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Mon, 26 May 2025 07:03:34 +1000 Subject: [PATCH] Updated vkd3d to a8ca1f95c50561a16de5769646dcda0c045b7a46. --- libs/vkd3d/include/private/vkd3d_common.h | 3 +- libs/vkd3d/include/private/vkd3d_version.h | 2 +- libs/vkd3d/libs/vkd3d-common/blob.c | 1 + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 332 +------ libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 26 +- libs/vkd3d/libs/vkd3d-shader/dxbc.c | 10 +- libs/vkd3d/libs/vkd3d-shader/dxil.c | 915 ++++++++++-------- libs/vkd3d/libs/vkd3d-shader/fx.c | 747 +++++++++----- libs/vkd3d/libs/vkd3d-shader/glsl.c | 14 +- libs/vkd3d/libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 3 + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 263 +++-- libs/vkd3d/libs/vkd3d-shader/ir.c | 431 ++++++++- libs/vkd3d/libs/vkd3d-shader/msl.c | 440 +++++++-- libs/vkd3d/libs/vkd3d-shader/preproc.h | 2 +- libs/vkd3d/libs/vkd3d-shader/preproc.l | 39 +- libs/vkd3d/libs/vkd3d-shader/spirv.c | 145 +-- libs/vkd3d/libs/vkd3d-shader/tpf.c | 79 +- .../libs/vkd3d-shader/vkd3d_shader_main.c | 60 +- .../libs/vkd3d-shader/vkd3d_shader_private.h | 23 +- .../vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c | 2 + 21 files changed, 2159 insertions(+), 1379 deletions(-) diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h index beb23257fb7..0501e6a06c2 100644 --- a/libs/vkd3d/include/private/vkd3d_common.h +++ b/libs/vkd3d/include/private/vkd3d_common.h @@ -66,6 +66,7 @@ #define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9') #define TAG_CLI4 VKD3D_MAKE_TAG('C', 'L', 'I', '4') +#define TAG_CLIT VKD3D_MAKE_TAG('C', 'L', 'I', 'T') #define TAG_CTAB VKD3D_MAKE_TAG('C', 'T', 'A', 'B') #define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C') #define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L') @@ -278,7 +279,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v) { #ifdef _MSC_VER return __popcnt(v); -#elif defined(__MINGW32__) +#elif defined(HAVE_BUILTIN_POPCOUNT) return __builtin_popcount(v); #else v -= (v >> 1) & 0x55555555; diff --git a/libs/vkd3d/include/private/vkd3d_version.h b/libs/vkd3d/include/private/vkd3d_version.h index 0edc4428022..687751d6a5f 100644 --- a/libs/vkd3d/include/private/vkd3d_version.h +++ b/libs/vkd3d/include/private/vkd3d_version.h @@ -1 +1 @@ -#define VKD3D_VCS_ID " (Wine bundled)" +#define VKD3D_VCS_ID " (git a8ca1f95)" diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c index f60ef7db769..c2c6ad67804 100644 --- a/libs/vkd3d/libs/vkd3d-common/blob.c +++ b/libs/vkd3d/libs/vkd3d-common/blob.c @@ -20,6 +20,7 @@ #define WIDL_C_INLINE_WRAPPERS #endif #define COBJMACROS + #define CONST_VTABLE #include "vkd3d.h" #include "vkd3d_blob.h" diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c index 4521bfabd8e..af5552635cb 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -27,333 +27,6 @@ #include #include -static const char * const shader_opcode_names[] = -{ - [VKD3DSIH_ABS ] = "abs", - [VKD3DSIH_ACOS ] = "acos", - [VKD3DSIH_ADD ] = "add", - [VKD3DSIH_AND ] = "and", - [VKD3DSIH_ASIN ] = "asin", - [VKD3DSIH_ATAN ] = "atan", - [VKD3DSIH_ATOMIC_AND ] = "atomic_and", - [VKD3DSIH_ATOMIC_CMP_STORE ] = "atomic_cmp_store", - [VKD3DSIH_ATOMIC_IADD ] = "atomic_iadd", - [VKD3DSIH_ATOMIC_IMAX ] = "atomic_imax", - [VKD3DSIH_ATOMIC_IMIN ] = "atomic_imin", - [VKD3DSIH_ATOMIC_OR ] = "atomic_or", - [VKD3DSIH_ATOMIC_UMAX ] = "atomic_umax", - [VKD3DSIH_ATOMIC_UMIN ] = "atomic_umin", - [VKD3DSIH_ATOMIC_XOR ] = "atomic_xor", - [VKD3DSIH_BEM ] = "bem", - [VKD3DSIH_BFI ] = "bfi", - [VKD3DSIH_BFREV ] = "bfrev", - [VKD3DSIH_BRANCH ] = "branch", - [VKD3DSIH_BREAK ] = "break", - [VKD3DSIH_BREAKC ] = "break", - [VKD3DSIH_BREAKP ] = "breakp", - [VKD3DSIH_BUFINFO ] = "bufinfo", - [VKD3DSIH_CALL ] = "call", - [VKD3DSIH_CALLNZ ] = "callnz", - [VKD3DSIH_CASE ] = "case", - [VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED ] = "check_access_fully_mapped", - [VKD3DSIH_CMP ] = "cmp", - [VKD3DSIH_CND ] = "cnd", - [VKD3DSIH_CONTINUE ] = "continue", - [VKD3DSIH_CONTINUEP ] = "continuec", - [VKD3DSIH_COUNTBITS ] = "countbits", - [VKD3DSIH_CRS ] = "crs", - [VKD3DSIH_CUT ] = "cut", - [VKD3DSIH_CUT_STREAM ] = "cut_stream", - [VKD3DSIH_DADD ] = "dadd", - [VKD3DSIH_DCL ] = "dcl", - [VKD3DSIH_DCL_CONSTANT_BUFFER ] = "dcl_constantBuffer", - [VKD3DSIH_DCL_FUNCTION_BODY ] = "dcl_function_body", - [VKD3DSIH_DCL_FUNCTION_TABLE ] = "dcl_function_table", - [VKD3DSIH_DCL_GLOBAL_FLAGS ] = "dcl_globalFlags", - [VKD3DSIH_DCL_GS_INSTANCES ] = "dcl_gs_instances", - [VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT] = "dcl_hs_fork_phase_instance_count", - [VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT] = "dcl_hs_join_phase_instance_count", - [VKD3DSIH_DCL_HS_MAX_TESSFACTOR ] = "dcl_hs_max_tessfactor", - [VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER ] = "dcl_immediateConstantBuffer", - [VKD3DSIH_DCL_INDEX_RANGE ] = "dcl_index_range", - [VKD3DSIH_DCL_INDEXABLE_TEMP ] = "dcl_indexableTemp", - [VKD3DSIH_DCL_INPUT ] = "dcl_input", - [VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT ] = "dcl_input_control_point_count", - [VKD3DSIH_DCL_INPUT_PRIMITIVE ] = "dcl_inputprimitive", - [VKD3DSIH_DCL_INPUT_PS ] = "dcl_input_ps", - [VKD3DSIH_DCL_INPUT_PS_SGV ] = "dcl_input_ps_sgv", - [VKD3DSIH_DCL_INPUT_PS_SIV ] = "dcl_input_ps_siv", - [VKD3DSIH_DCL_INPUT_SGV ] = "dcl_input_sgv", - [VKD3DSIH_DCL_INPUT_SIV ] = "dcl_input_siv", - [VKD3DSIH_DCL_INTERFACE ] = "dcl_interface", - [VKD3DSIH_DCL_OUTPUT ] = "dcl_output", - [VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT ] = "dcl_output_control_point_count", - [VKD3DSIH_DCL_OUTPUT_SIV ] = "dcl_output_siv", - [VKD3DSIH_DCL_OUTPUT_TOPOLOGY ] = "dcl_outputtopology", - [VKD3DSIH_DCL_RESOURCE_RAW ] = "dcl_resource_raw", - [VKD3DSIH_DCL_RESOURCE_STRUCTURED ] = "dcl_resource_structured", - [VKD3DSIH_DCL_SAMPLER ] = "dcl_sampler", - [VKD3DSIH_DCL_STREAM ] = "dcl_stream", - [VKD3DSIH_DCL_TEMPS ] = "dcl_temps", - [VKD3DSIH_DCL_TESSELLATOR_DOMAIN ] = "dcl_tessellator_domain", - [VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE] = "dcl_tessellator_output_primitive", - [VKD3DSIH_DCL_TESSELLATOR_PARTITIONING ] = "dcl_tessellator_partitioning", - [VKD3DSIH_DCL_TGSM_RAW ] = "dcl_tgsm_raw", - [VKD3DSIH_DCL_TGSM_STRUCTURED ] = "dcl_tgsm_structured", - [VKD3DSIH_DCL_THREAD_GROUP ] = "dcl_thread_group", - [VKD3DSIH_DCL_UAV_RAW ] = "dcl_uav_raw", - [VKD3DSIH_DCL_UAV_STRUCTURED ] = "dcl_uav_structured", - [VKD3DSIH_DCL_UAV_TYPED ] = "dcl_uav_typed", - [VKD3DSIH_DCL_VERTICES_OUT ] = "dcl_maxout", - [VKD3DSIH_DDIV ] = "ddiv", - [VKD3DSIH_DEF ] = "def", - [VKD3DSIH_DEFAULT ] = "default", - [VKD3DSIH_DEFB ] = "defb", - [VKD3DSIH_DEFI ] = "defi", - [VKD3DSIH_DEQO ] = "deq", - [VKD3DSIH_DFMA ] = "dfma", - [VKD3DSIH_DGEO ] = "dge", - [VKD3DSIH_DISCARD ] = "discard", - [VKD3DSIH_DIV ] = "div", - [VKD3DSIH_DLT ] = "dlt", - [VKD3DSIH_DMAX ] = "dmax", - [VKD3DSIH_DMIN ] = "dmin", - [VKD3DSIH_DMOV ] = "dmov", - [VKD3DSIH_DMOVC ] = "dmovc", - [VKD3DSIH_DMUL ] = "dmul", - [VKD3DSIH_DNE ] = "dne", - [VKD3DSIH_DP2 ] = "dp2", - [VKD3DSIH_DP2ADD ] = "dp2add", - [VKD3DSIH_DP3 ] = "dp3", - [VKD3DSIH_DP4 ] = "dp4", - [VKD3DSIH_DRCP ] = "drcp", - [VKD3DSIH_DST ] = "dst", - [VKD3DSIH_DSX ] = "dsx", - [VKD3DSIH_DSX_COARSE ] = "deriv_rtx_coarse", - [VKD3DSIH_DSX_FINE ] = "deriv_rtx_fine", - [VKD3DSIH_DSY ] = "dsy", - [VKD3DSIH_DSY_COARSE ] = "deriv_rty_coarse", - [VKD3DSIH_DSY_FINE ] = "deriv_rty_fine", - [VKD3DSIH_DTOF ] = "dtof", - [VKD3DSIH_DTOI ] = "dtoi", - [VKD3DSIH_DTOU ] = "dtou", - [VKD3DSIH_ELSE ] = "else", - [VKD3DSIH_EMIT ] = "emit", - [VKD3DSIH_EMIT_STREAM ] = "emit_stream", - [VKD3DSIH_ENDIF ] = "endif", - [VKD3DSIH_ENDLOOP ] = "endloop", - [VKD3DSIH_ENDREP ] = "endrep", - [VKD3DSIH_ENDSWITCH ] = "endswitch", - [VKD3DSIH_EQO ] = "eq", - [VKD3DSIH_EQU ] = "eq_unord", - [VKD3DSIH_EVAL_CENTROID ] = "eval_centroid", - [VKD3DSIH_EVAL_SAMPLE_INDEX ] = "eval_sample_index", - [VKD3DSIH_EXP ] = "exp", - [VKD3DSIH_EXPP ] = "expp", - [VKD3DSIH_F16TOF32 ] = "f16tof32", - [VKD3DSIH_F32TOF16 ] = "f32tof16", - [VKD3DSIH_FCALL ] = "fcall", - [VKD3DSIH_FIRSTBIT_HI ] = "firstbit_hi", - [VKD3DSIH_FIRSTBIT_LO ] = "firstbit_lo", - [VKD3DSIH_FIRSTBIT_SHI ] = "firstbit_shi", - [VKD3DSIH_FRC ] = "frc", - [VKD3DSIH_FREM ] = "frem", - [VKD3DSIH_FTOD ] = "ftod", - [VKD3DSIH_FTOI ] = "ftoi", - [VKD3DSIH_FTOU ] = "ftou", - [VKD3DSIH_GATHER4 ] = "gather4", - [VKD3DSIH_GATHER4_C ] = "gather4_c", - [VKD3DSIH_GATHER4_C_S ] = "gather4_c_s", - [VKD3DSIH_GATHER4_PO ] = "gather4_po", - [VKD3DSIH_GATHER4_PO_C ] = "gather4_po_c", - [VKD3DSIH_GATHER4_PO_C_S ] = "gather4_po_c_s", - [VKD3DSIH_GATHER4_PO_S ] = "gather4_po_s", - [VKD3DSIH_GATHER4_S ] = "gather4_s", - [VKD3DSIH_GEO ] = "ge", - [VKD3DSIH_GEU ] = "ge_unord", - [VKD3DSIH_HCOS ] = "hcos", - [VKD3DSIH_HS_CONTROL_POINT_PHASE ] = "hs_control_point_phase", - [VKD3DSIH_HS_DECLS ] = "hs_decls", - [VKD3DSIH_HS_FORK_PHASE ] = "hs_fork_phase", - [VKD3DSIH_HS_JOIN_PHASE ] = "hs_join_phase", - [VKD3DSIH_HSIN ] = "hsin", - [VKD3DSIH_HTAN ] = "htan", - [VKD3DSIH_IADD ] = "iadd", - [VKD3DSIH_IBFE ] = "ibfe", - [VKD3DSIH_IDIV ] = "idiv", - [VKD3DSIH_IEQ ] = "ieq", - [VKD3DSIH_IF ] = "if", - [VKD3DSIH_IFC ] = "if", - [VKD3DSIH_IGE ] = "ige", - [VKD3DSIH_ILT ] = "ilt", - [VKD3DSIH_IMAD ] = "imad", - [VKD3DSIH_IMAX ] = "imax", - [VKD3DSIH_IMIN ] = "imin", - [VKD3DSIH_IMM_ATOMIC_ALLOC ] = "imm_atomic_alloc", - [VKD3DSIH_IMM_ATOMIC_AND ] = "imm_atomic_and", - [VKD3DSIH_IMM_ATOMIC_CMP_EXCH ] = "imm_atomic_cmp_exch", - [VKD3DSIH_IMM_ATOMIC_CONSUME ] = "imm_atomic_consume", - [VKD3DSIH_IMM_ATOMIC_EXCH ] = "imm_atomic_exch", - [VKD3DSIH_IMM_ATOMIC_IADD ] = "imm_atomic_iadd", - [VKD3DSIH_IMM_ATOMIC_IMAX ] = "imm_atomic_imax", - [VKD3DSIH_IMM_ATOMIC_IMIN ] = "imm_atomic_imin", - [VKD3DSIH_IMM_ATOMIC_OR ] = "imm_atomic_or", - [VKD3DSIH_IMM_ATOMIC_UMAX ] = "imm_atomic_umax", - [VKD3DSIH_IMM_ATOMIC_UMIN ] = "imm_atomic_umin", - [VKD3DSIH_IMM_ATOMIC_XOR ] = "imm_atomic_xor", - [VKD3DSIH_IMUL ] = "imul", - [VKD3DSIH_INE ] = "ine", - [VKD3DSIH_INEG ] = "ineg", - [VKD3DSIH_ISFINITE ] = "isfinite", - [VKD3DSIH_ISHL ] = "ishl", - [VKD3DSIH_ISHR ] = "ishr", - [VKD3DSIH_ISINF ] = "isinf", - [VKD3DSIH_ISNAN ] = "isnan", - [VKD3DSIH_ITOD ] = "itod", - [VKD3DSIH_ITOF ] = "itof", - [VKD3DSIH_ITOI ] = "itoi", - [VKD3DSIH_LABEL ] = "label", - [VKD3DSIH_LD ] = "ld", - [VKD3DSIH_LD2DMS ] = "ld2dms", - [VKD3DSIH_LD2DMS_S ] = "ld2dms_s", - [VKD3DSIH_LD_RAW ] = "ld_raw", - [VKD3DSIH_LD_RAW_S ] = "ld_raw_s", - [VKD3DSIH_LD_S ] = "ld_s", - [VKD3DSIH_LD_STRUCTURED ] = "ld_structured", - [VKD3DSIH_LD_STRUCTURED_S ] = "ld_structured_s", - [VKD3DSIH_LD_UAV_TYPED ] = "ld_uav_typed", - [VKD3DSIH_LD_UAV_TYPED_S ] = "ld_uav_typed_s", - [VKD3DSIH_LIT ] = "lit", - [VKD3DSIH_LOD ] = "lod", - [VKD3DSIH_LOG ] = "log", - [VKD3DSIH_LOGP ] = "logp", - [VKD3DSIH_LOOP ] = "loop", - [VKD3DSIH_LRP ] = "lrp", - [VKD3DSIH_LTO ] = "lt", - [VKD3DSIH_LTU ] = "lt_unord", - [VKD3DSIH_M3x2 ] = "m3x2", - [VKD3DSIH_M3x3 ] = "m3x3", - [VKD3DSIH_M3x4 ] = "m3x4", - [VKD3DSIH_M4x3 ] = "m4x3", - [VKD3DSIH_M4x4 ] = "m4x4", - [VKD3DSIH_MAD ] = "mad", - [VKD3DSIH_MAX ] = "max", - [VKD3DSIH_MIN ] = "min", - [VKD3DSIH_MOV ] = "mov", - [VKD3DSIH_MOVA ] = "mova", - [VKD3DSIH_MOVC ] = "movc", - [VKD3DSIH_MSAD ] = "msad", - [VKD3DSIH_MUL ] = "mul", - [VKD3DSIH_NEO ] = "ne_ord", - [VKD3DSIH_NEU ] = "ne", - [VKD3DSIH_NOP ] = "nop", - [VKD3DSIH_NOT ] = "not", - [VKD3DSIH_NRM ] = "nrm", - [VKD3DSIH_OR ] = "or", - [VKD3DSIH_ORD ] = "ord", - [VKD3DSIH_PHASE ] = "phase", - [VKD3DSIH_PHI ] = "phi", - [VKD3DSIH_POW ] = "pow", - [VKD3DSIH_QUAD_READ_ACROSS_D ] = "quad_read_across_d", - [VKD3DSIH_QUAD_READ_ACROSS_X ] = "quad_read_across_x", - [VKD3DSIH_QUAD_READ_ACROSS_Y ] = "quad_read_across_y", - [VKD3DSIH_QUAD_READ_LANE_AT ] = "quad_read_lane_at", - [VKD3DSIH_RCP ] = "rcp", - [VKD3DSIH_REP ] = "rep", - [VKD3DSIH_RESINFO ] = "resinfo", - [VKD3DSIH_RET ] = "ret", - [VKD3DSIH_RETP ] = "retp", - [VKD3DSIH_ROUND_NE ] = "round_ne", - [VKD3DSIH_ROUND_NI ] = "round_ni", - [VKD3DSIH_ROUND_PI ] = "round_pi", - [VKD3DSIH_ROUND_Z ] = "round_z", - [VKD3DSIH_RSQ ] = "rsq", - [VKD3DSIH_SAMPLE ] = "sample", - [VKD3DSIH_SAMPLE_B ] = "sample_b", - [VKD3DSIH_SAMPLE_B_CL_S ] = "sample_b_cl_s", - [VKD3DSIH_SAMPLE_C ] = "sample_c", - [VKD3DSIH_SAMPLE_C_CL_S ] = "sample_c_cl_s", - [VKD3DSIH_SAMPLE_C_LZ ] = "sample_c_lz", - [VKD3DSIH_SAMPLE_C_LZ_S ] = "sample_c_lz_s", - [VKD3DSIH_SAMPLE_CL_S ] = "sample_cl_s", - [VKD3DSIH_SAMPLE_GRAD ] = "sample_d", - [VKD3DSIH_SAMPLE_GRAD_CL_S ] = "sample_d_cl_s", - [VKD3DSIH_SAMPLE_INFO ] = "sample_info", - [VKD3DSIH_SAMPLE_LOD ] = "sample_l", - [VKD3DSIH_SAMPLE_LOD_S ] = "sample_l_s", - [VKD3DSIH_SAMPLE_POS ] = "sample_pos", - [VKD3DSIH_SETP ] = "setp", - [VKD3DSIH_SGE ] = "sge", - [VKD3DSIH_SGN ] = "sgn", - [VKD3DSIH_SINCOS ] = "sincos", - [VKD3DSIH_SLT ] = "slt", - [VKD3DSIH_SQRT ] = "sqrt", - [VKD3DSIH_STORE_RAW ] = "store_raw", - [VKD3DSIH_STORE_STRUCTURED ] = "store_structured", - [VKD3DSIH_STORE_UAV_TYPED ] = "store_uav_typed", - [VKD3DSIH_SUB ] = "sub", - [VKD3DSIH_SWAPC ] = "swapc", - [VKD3DSIH_SWITCH ] = "switch", - [VKD3DSIH_SWITCH_MONOLITHIC ] = "switch", - [VKD3DSIH_SYNC ] = "sync", - [VKD3DSIH_TAN ] = "tan", - [VKD3DSIH_TEX ] = "texld", - [VKD3DSIH_TEXBEM ] = "texbem", - [VKD3DSIH_TEXBEML ] = "texbeml", - [VKD3DSIH_TEXCOORD ] = "texcrd", - [VKD3DSIH_TEXDEPTH ] = "texdepth", - [VKD3DSIH_TEXDP3 ] = "texdp3", - [VKD3DSIH_TEXDP3TEX ] = "texdp3tex", - [VKD3DSIH_TEXKILL ] = "texkill", - [VKD3DSIH_TEXLDD ] = "texldd", - [VKD3DSIH_TEXLDL ] = "texldl", - [VKD3DSIH_TEXM3x2DEPTH ] = "texm3x2depth", - [VKD3DSIH_TEXM3x2PAD ] = "texm3x2pad", - [VKD3DSIH_TEXM3x2TEX ] = "texm3x2tex", - [VKD3DSIH_TEXM3x3 ] = "texm3x3", - [VKD3DSIH_TEXM3x3DIFF ] = "texm3x3diff", - [VKD3DSIH_TEXM3x3PAD ] = "texm3x3pad", - [VKD3DSIH_TEXM3x3SPEC ] = "texm3x3spec", - [VKD3DSIH_TEXM3x3TEX ] = "texm3x3tex", - [VKD3DSIH_TEXM3x3VSPEC ] = "texm3x3vspec", - [VKD3DSIH_TEXREG2AR ] = "texreg2ar", - [VKD3DSIH_TEXREG2GB ] = "texreg2gb", - [VKD3DSIH_TEXREG2RGB ] = "texreg2rgb", - [VKD3DSIH_UBFE ] = "ubfe", - [VKD3DSIH_UDIV ] = "udiv", - [VKD3DSIH_UGE ] = "uge", - [VKD3DSIH_ULT ] = "ult", - [VKD3DSIH_UMAX ] = "umax", - [VKD3DSIH_UMIN ] = "umin", - [VKD3DSIH_UMUL ] = "umul", - [VKD3DSIH_UNO ] = "uno", - [VKD3DSIH_USHR ] = "ushr", - [VKD3DSIH_UTOD ] = "utod", - [VKD3DSIH_UTOF ] = "utof", - [VKD3DSIH_UTOU ] = "utou", - [VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL ] = "wave_active_all_equal", - [VKD3DSIH_WAVE_ACTIVE_BALLOT ] = "wave_active_ballot", - [VKD3DSIH_WAVE_ACTIVE_BIT_AND ] = "wave_active_bit_and", - [VKD3DSIH_WAVE_ACTIVE_BIT_OR ] = "wave_active_bit_or", - [VKD3DSIH_WAVE_ACTIVE_BIT_XOR ] = "wave_active_bit_xor", - [VKD3DSIH_WAVE_ALL_BIT_COUNT ] = "wave_all_bit_count", - [VKD3DSIH_WAVE_ALL_TRUE ] = "wave_all_true", - [VKD3DSIH_WAVE_ANY_TRUE ] = "wave_any_true", - [VKD3DSIH_WAVE_IS_FIRST_LANE ] = "wave_is_first_lane", - [VKD3DSIH_WAVE_OP_ADD ] = "wave_op_add", - [VKD3DSIH_WAVE_OP_IMAX ] = "wave_op_imax", - [VKD3DSIH_WAVE_OP_IMIN ] = "wave_op_imin", - [VKD3DSIH_WAVE_OP_MAX ] = "wave_op_max", - [VKD3DSIH_WAVE_OP_MIN ] = "wave_op_min", - [VKD3DSIH_WAVE_OP_MUL ] = "wave_op_mul", - [VKD3DSIH_WAVE_OP_UMAX ] = "wave_op_umax", - [VKD3DSIH_WAVE_OP_UMIN ] = "wave_op_umin", - [VKD3DSIH_WAVE_PREFIX_BIT_COUNT ] = "wave_prefix_bit_count", - [VKD3DSIH_WAVE_READ_LANE_AT ] = "wave_read_lane_at", - [VKD3DSIH_WAVE_READ_LANE_FIRST ] = "wave_read_lane_first", - [VKD3DSIH_XOR ] = "xor", -}; - static const char * const shader_register_names[] = { [VKD3DSPR_ADDR ] = "a", @@ -1705,7 +1378,7 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile shader_dump_sync_flags(compiler, ins->flags); break; - case VKD3DSIH_TEX: + case VKD3DSIH_TEXLD: if (vkd3d_shader_ver_ge(&compiler->shader_version, 2, 0)) { if (ins->flags & VKD3DSI_TEXLD_PROJECT) @@ -1747,7 +1420,7 @@ static void shader_dump_register_space(struct vkd3d_d3d_asm_compiler *compiler, static void shader_print_opcode(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_shader_opcode opcode) { vkd3d_string_buffer_printf(&compiler->buffer, "%s%s%s", compiler->colours.opcode, - shader_opcode_names[opcode], compiler->colours.reset); + vsir_opcode_get_name(opcode, ""), compiler->colours.reset); } static void shader_dump_icb(struct vkd3d_d3d_asm_compiler *compiler, @@ -1865,6 +1538,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, case VKD3DSIH_DCL_INPUT_PS_SGV: case VKD3DSIH_DCL_INPUT_SGV: case VKD3DSIH_DCL_INPUT_SIV: + case VKD3DSIH_DCL_OUTPUT_SGV: case VKD3DSIH_DCL_OUTPUT_SIV: shader_print_dst_param(compiler, " ", &ins->declaration.register_semantic.reg, true, ""); shader_print_input_sysval_semantic(compiler, ", ", ins->declaration.register_semantic.sysval_semantic, ""); diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c index 57d874efe37..c8291afcf6e 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -382,11 +382,11 @@ static const struct vkd3d_sm1_opcode_info ps_opcode_table[] = {VKD3D_SM1_OP_LABEL, 0, 1, VKD3DSIH_LABEL, {2, 1}}, /* Texture */ {VKD3D_SM1_OP_TEXCOORD, 1, 0, VKD3DSIH_TEXCOORD, {0, 0}, {1, 3}}, - {VKD3D_SM1_OP_TEXCOORD, 1, 1, VKD3DSIH_TEXCOORD, {1, 4}, {1, 4}}, + {VKD3D_SM1_OP_TEXCOORD, 1, 1, VKD3DSIH_TEXCRD, {1, 4}, {1, 4}}, {VKD3D_SM1_OP_TEXKILL, 1, 0, VKD3DSIH_TEXKILL, {1, 0}}, {VKD3D_SM1_OP_TEX, 1, 0, VKD3DSIH_TEX, {0, 0}, {1, 3}}, - {VKD3D_SM1_OP_TEX, 1, 1, VKD3DSIH_TEX, {1, 4}, {1, 4}}, - {VKD3D_SM1_OP_TEX, 1, 2, VKD3DSIH_TEX, {2, 0}}, + {VKD3D_SM1_OP_TEX, 1, 1, VKD3DSIH_TEXLD, {1, 4}, {1, 4}}, + {VKD3D_SM1_OP_TEX, 1, 2, VKD3DSIH_TEXLD, {2, 0}}, {VKD3D_SM1_OP_TEXBEM, 1, 1, VKD3DSIH_TEXBEM, {0, 0}, {1, 3}}, {VKD3D_SM1_OP_TEXBEML, 1, 1, VKD3DSIH_TEXBEML, {1, 0}, {1, 3}}, {VKD3D_SM1_OP_TEXREG2AR, 1, 1, VKD3DSIH_TEXREG2AR, {1, 0}, {1, 3}}, @@ -1681,7 +1681,8 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir_ if (!(info = shader_sm1_get_opcode_info_from_vsir(d3dbc, ins->opcode))) { vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, - "Opcode %#x not supported for shader profile.", ins->opcode); + "Instruction \"%s\" (%#x) is not supported for the current target.", + vsir_opcode_get_name(ins->opcode, ""), ins->opcode); d3dbc->failed = true; return NULL; } @@ -1689,16 +1690,16 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info_from_vsir_ if (ins->dst_count != info->dst_count) { vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, - "Invalid destination count %u for vsir instruction %#x (expected %u).", - ins->dst_count, ins->opcode, info->dst_count); + "Invalid destination parameter count %u for instruction \"%s\" (%#x); expected %u.", + ins->dst_count, vsir_opcode_get_name(ins->opcode, ""), ins->opcode, info->dst_count); d3dbc->failed = true; return NULL; } if (ins->src_count != info->src_count) { vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_COUNT, - "Invalid source count %u for vsir instruction %#x (expected %u).", - ins->src_count, ins->opcode, info->src_count); + "Invalid source parameter count %u for instruction \"%s\" (%#x); expected %u.", + ins->src_count, vsir_opcode_get_name(ins->opcode, ""), ins->opcode, info->src_count); d3dbc->failed = true; return NULL; } @@ -2014,7 +2015,7 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str case VKD3DSIH_MUL: case VKD3DSIH_SINCOS: case VKD3DSIH_SLT: - case VKD3DSIH_TEX: + case VKD3DSIH_TEXLD: case VKD3DSIH_TEXLDD: d3dbc_write_instruction(d3dbc, ins); break; @@ -2029,8 +2030,8 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str { vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_WRITEMASK, - "writemask %#x for vsir instruction with opcode %#x is not single component.", - writemask, ins->opcode); + "Writemask %#x for instruction \"%s\" (%#x) is not single component.", + writemask, vsir_opcode_get_name(ins->opcode, ""), ins->opcode); d3dbc->failed = true; } d3dbc_write_instruction(d3dbc, ins); @@ -2038,7 +2039,8 @@ static void d3dbc_write_vsir_instruction(struct d3dbc_compiler *d3dbc, const str default: vkd3d_shader_error(d3dbc->message_context, &ins->location, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, - "vsir instruction with opcode %#x.", ins->opcode); + "Internal compiler error: Unhandled instruction \"%s\" (%#x).", + vsir_opcode_get_name(ins->opcode, ""), ins->opcode); d3dbc->failed = true; break; } diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c index 9e3a57132a1..45a45c3ad4a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c @@ -388,7 +388,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s { WARN("Invalid data size %#zx.\n", section->data.size); vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_SIGNATURE, - "Section size %zu is smaller than the minimum signature header size.\n", section->data.size); + "Section size %zu is smaller than the minimum signature header size.", section->data.size); return VKD3D_ERROR_INVALID_ARGUMENT; } @@ -402,7 +402,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s { WARN("Invalid header size %#x.\n", header_size); vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_SIGNATURE, - "Signature header size %#x is invalid.\n", header_size); + "Signature header size %#x is invalid.", header_size); return VKD3D_ERROR_INVALID_ARGUMENT; } skip_dword_unknown(&ptr, i - 2); @@ -438,7 +438,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s || !(e[i].semantic_name = vkd3d_strdup(name))) { vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_STRING_REFERENCE, - "Element %u has invalid semantic name reference %#zx (data size %#zx).\n", + "Element %u has invalid semantic name reference %#zx (data size %#zx).", i, name_offset, section->data.size); fail = true; } @@ -447,7 +447,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s if ((e[i].component_type = read_u32(&ptr)) > VKD3D_SHADER_COMPONENT_FLOAT) { vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_COMPONENT_TYPE, - "Element %u has invalid component type %#x.\n", i, e[i].component_type); + "Element %u has invalid component type %#x.", i, e[i].component_type); fail = true; } e[i].register_index = read_u32(&ptr); @@ -531,7 +531,7 @@ static int shdr_parse_features(const struct vkd3d_shader_dxbc_section_desc *sect { WARN("Invalid data size %#zx.\n", section->data.size); vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE, - "SFI0 section size %zu is too small to contain flags.\n", section->data.size); + "SFI0 section size %zu is too small to contain flags.", section->data.size); return VKD3D_ERROR_INVALID_ARGUMENT; } flags = read_u64(&ptr); diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index ca79939a39b..53578ce7141 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -644,17 +644,23 @@ struct sm6_type enum sm6_value_type { VALUE_TYPE_FUNCTION, - VALUE_TYPE_REG, VALUE_TYPE_DATA, VALUE_TYPE_HANDLE, VALUE_TYPE_SSA, VALUE_TYPE_ICB, VALUE_TYPE_IDXTEMP, VALUE_TYPE_GROUPSHAREDMEM, + VALUE_TYPE_CONSTANT, VALUE_TYPE_UNDEFINED, VALUE_TYPE_INVALID, }; +struct sm6_index +{ + const struct sm6_value *index; + bool is_in_bounds; +}; + struct sm6_function_data { const char *name; @@ -678,16 +684,24 @@ struct sm6_icb_data { unsigned int data_id; unsigned int id; + struct sm6_index index; }; struct sm6_idxtemp_data { unsigned int id; + struct sm6_index index; }; struct sm6_groupsharedmem_data { unsigned int id; + struct sm6_index index; +}; + +struct sm6_constant_data +{ + union vsir_immediate_constant immconst; }; struct sm6_value @@ -696,6 +710,7 @@ struct sm6_value enum sm6_value_type value_type; unsigned int structure_stride; bool is_back_ref; + bool non_uniform; union { struct sm6_function_data function; @@ -705,8 +720,8 @@ struct sm6_value struct sm6_icb_data icb; struct sm6_idxtemp_data idxtemp; struct sm6_groupsharedmem_data groupsharedmem; + struct sm6_constant_data constant; } u; - struct vkd3d_shader_register reg; }; struct dxil_record @@ -731,7 +746,7 @@ struct incoming_value struct sm6_phi { - struct vkd3d_shader_register reg; + struct sm6_value value; struct incoming_value *incoming; size_t incoming_capacity; size_t incoming_count; @@ -2010,11 +2025,6 @@ static inline bool sm6_type_is_handle(const struct sm6_type *type) return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.Handle"); } -static inline const struct sm6_type *sm6_type_get_element_type(const struct sm6_type *type) -{ - return (type->class == TYPE_CLASS_ARRAY || type->class == TYPE_CLASS_VECTOR) ? type->u.array.elem_type : type; -} - static const struct sm6_type *sm6_type_get_pointer_to_type(const struct sm6_type *type, enum bitcode_address_space addr_space, struct sm6_parser *sm6) { @@ -2214,35 +2224,6 @@ static const char *sm6_parser_get_global_symbol_name(const struct sm6_parser *sm return NULL; } -static unsigned int register_get_uint_value(const struct vkd3d_shader_register *reg) -{ - if (!register_is_constant(reg) || (!data_type_is_integer(reg->data_type) && !data_type_is_bool(reg->data_type))) - return UINT_MAX; - - if (reg->dimension == VSIR_DIMENSION_VEC4) - WARN("Returning vec4.x.\n"); - - if (reg->type == VKD3DSPR_IMMCONST64) - { - if (reg->u.immconst_u64[0] > UINT_MAX) - FIXME("Truncating 64-bit value.\n"); - return reg->u.immconst_u64[0]; - } - - return reg->u.immconst_u32[0]; -} - -static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *reg) -{ - if (!register_is_constant(reg) || !data_type_is_integer(reg->data_type)) - return UINT64_MAX; - - if (reg->dimension == VSIR_DIMENSION_VEC4) - WARN("Returning vec4.x.\n"); - - return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_u64[0] : reg->u.immconst_u32[0]; -} - static inline bool sm6_value_is_function_dcl(const struct sm6_value *value) { return value->value_type == VALUE_TYPE_FUNCTION; @@ -2264,11 +2245,11 @@ static inline bool sm6_value_is_register(const struct sm6_value *value) { switch (value->value_type) { - case VALUE_TYPE_REG: case VALUE_TYPE_SSA: case VALUE_TYPE_ICB: case VALUE_TYPE_IDXTEMP: case VALUE_TYPE_GROUPSHAREDMEM: + case VALUE_TYPE_CONSTANT: case VALUE_TYPE_UNDEFINED: case VALUE_TYPE_INVALID: return true; @@ -2285,18 +2266,31 @@ static bool sm6_value_is_handle(const struct sm6_value *value) static inline bool sm6_value_is_constant(const struct sm6_value *value) { - return sm6_value_is_register(value) && register_is_constant(&value->reg); + return value->value_type == VALUE_TYPE_CONSTANT; } static bool sm6_value_is_constant_zero(const struct sm6_value *value) { - /* Constant vectors do not occur. */ - return sm6_value_is_register(value) && register_is_scalar_constant_zero(&value->reg); + if (value->value_type != VALUE_TYPE_CONSTANT || value->type->class != TYPE_CLASS_INTEGER) + return false; + + if (value->type->u.width == 64) + return value->u.constant.immconst.immconst_u64[0] == 0; + else + return value->u.constant.immconst.immconst_u32[0] == 0; } static inline bool sm6_value_is_undef(const struct sm6_value *value) { - return sm6_value_is_register(value) && value->reg.type == VKD3DSPR_UNDEF; + switch (value->value_type) + { + case VALUE_TYPE_UNDEFINED: + case VALUE_TYPE_INVALID: + return true; + + default: + return false; + } } static bool sm6_value_vector_is_constant_or_undef(const struct sm6_value **values, unsigned int count) @@ -2315,26 +2309,98 @@ static bool sm6_value_is_data(const struct sm6_value *value) static bool sm6_value_is_ssa(const struct sm6_value *value) { - return sm6_value_is_register(value) && register_is_ssa(&value->reg); + return value->value_type == VALUE_TYPE_SSA; } static bool sm6_value_is_numeric_array(const struct sm6_value *value) { - return sm6_value_is_register(value) && register_is_numeric_array(&value->reg); + switch (value->value_type) + { + case VALUE_TYPE_ICB: + case VALUE_TYPE_IDXTEMP: + case VALUE_TYPE_GROUPSHAREDMEM: + return true; + + default: + return false; + } } -static inline unsigned int sm6_value_get_constant_uint(const struct sm6_value *value) +static unsigned int sm6_value_get_constant_uint(const struct sm6_value *value, struct sm6_parser *sm6) { if (!sm6_value_is_constant(value)) + { + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, + "Invalid non-constant value."); return UINT_MAX; - return register_get_uint_value(&value->reg); + } + + if (value->type->class != TYPE_CLASS_INTEGER) + { + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, + "Invalid non-integer constant value."); + return UINT_MAX; + } + + if (value->type->u.width == 64) + { + uint64_t val = value->u.constant.immconst.immconst_u64[0]; + if (val > UINT_MAX) + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, + "Invalid 64-bit constant %"PRIu64" will be truncated do %u.", val, (unsigned int)val); + return val; + } + + return value->u.constant.immconst.immconst_u32[0]; } -static uint64_t sm6_value_get_constant_uint64(const struct sm6_value *value) +static uint64_t sm6_value_get_constant_uint64(const struct sm6_value *value, struct sm6_parser *sm6) { if (!sm6_value_is_constant(value)) + { + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, + "Invalid non-constant value."); return UINT64_MAX; - return register_get_uint64_value(&value->reg); + } + + if (value->type->class != TYPE_CLASS_INTEGER) + { + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, + "Invalid non-integer constant value."); + return UINT64_MAX; + } + + if (value->type->u.width == 64) + return value->u.constant.immconst.immconst_u64[0]; + else + return value->u.constant.immconst.immconst_u32[0]; +} + +static float sm6_value_get_constant_float(const struct sm6_value *value, struct sm6_parser *sm6) +{ + if (!sm6_value_is_constant(value)) + { + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, + "Invalid non-constant value."); + return 0.0f; + } + + if (value->type->class != TYPE_CLASS_FLOAT) + { + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, + "Invalid non-floating-point constant value."); + return 0.0f; + } + + if (value->type->u.width == 64) + { + double val = value->u.constant.immconst.immconst_f64[0]; + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, + "Invalid double constant %lf will be truncated do float %f.", val, (float)val); + return val; + } + + return value->u.constant.immconst.immconst_f32[0]; } static unsigned int sm6_parser_alloc_ssa_id(struct sm6_parser *sm6) @@ -2433,33 +2499,127 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type return VKD3D_DATA_UINT; } -static void sm6_register_from_value(struct vkd3d_shader_register *reg, const struct sm6_value *value) +/* Based on the implementation in the OpenGL Mathematics library. */ +static uint32_t half_to_float(uint16_t value) { - enum vkd3d_data_type data_type; + uint32_t s = (value & 0x8000u) << 16; + uint32_t e = (value >> 10) & 0x1fu; + uint32_t m = value & 0x3ffu; - data_type = vkd3d_data_type_from_sm6_type(sm6_type_get_scalar_type(value->type, 0)); + if (!e) + { + if (!m) + { + /* Plus or minus zero */ + return s; + } + else + { + /* Denormalized number -- renormalize it */ + while (!(m & 0x400u)) + { + m <<= 1; + --e; + } - switch (value->value_type) + ++e; + m &= ~0x400u; + } + } + else if (e == 31u) + { + /* Positive or negative infinity for zero 'm'. + * Nan for non-zero 'm' -- preserve sign and significand bits */ + return s | 0x7f800000u | (m << 13); + } + + /* Normalized number */ + e += 127u - 15u; + m <<= 13; + + /* Assemble s, e and m. */ + return s | (e << 23) | m; +} + +static void register_convert_to_minimum_precision(struct vkd3d_shader_register *reg) +{ + unsigned int i; + + switch (reg->data_type) { - case VALUE_TYPE_REG: - *reg = value->reg; + case VKD3D_DATA_HALF: + reg->data_type = VKD3D_DATA_FLOAT; + reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_FLOAT_16; + if (reg->type == VKD3DSPR_IMMCONST) + { + for (i = 0; i < VSIR_DIMENSION_VEC4; ++i) + reg->u.immconst_u32[i] = half_to_float(reg->u.immconst_u32[i]); + } break; + case VKD3D_DATA_UINT16: + reg->data_type = VKD3D_DATA_UINT; + reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_UINT_16; + if (reg->type == VKD3DSPR_IMMCONST) + { + for (i = 0; i < VSIR_DIMENSION_VEC4; ++i) + reg->u.immconst_u32[i] = (int16_t)reg->u.immconst_u32[i]; + } + break; + + default: + break; + } +} + +static void register_index_address_init(struct vkd3d_shader_register_index *idx, const struct sm6_value *address, + struct sm6_parser *sm6); + +static void sm6_register_from_value(struct vkd3d_shader_register *reg, const struct sm6_value *value, + struct sm6_parser *sm6) +{ + const struct sm6_type *scalar_type; + enum vkd3d_data_type data_type; + + scalar_type = sm6_type_get_scalar_type(value->type, 0); + data_type = vkd3d_data_type_from_sm6_type(scalar_type); + + switch (value->value_type) + { case VALUE_TYPE_SSA: register_init_with_id(reg, VKD3DSPR_SSA, data_type, value->u.ssa.id); reg->dimension = sm6_type_is_scalar(value->type) ? VSIR_DIMENSION_SCALAR : VSIR_DIMENSION_VEC4; + register_convert_to_minimum_precision(reg); break; case VALUE_TYPE_ICB: - register_init_with_id(reg, VKD3DSPR_IMMCONSTBUFFER, data_type, value->u.icb.id); + vsir_register_init(reg, VKD3DSPR_IMMCONSTBUFFER, data_type, 2); + reg->idx[0].offset = value->u.icb.id; + register_index_address_init(®->idx[1], value->u.icb.index.index, sm6); + reg->idx[1].is_in_bounds = value->u.icb.index.is_in_bounds; + register_convert_to_minimum_precision(reg); break; case VALUE_TYPE_IDXTEMP: - register_init_with_id(reg, VKD3DSPR_IDXTEMP, data_type, value->u.idxtemp.id); + vsir_register_init(reg, VKD3DSPR_IDXTEMP, data_type, 2); + reg->idx[0].offset = value->u.idxtemp.id; + register_index_address_init(®->idx[1], value->u.idxtemp.index.index, sm6); + reg->idx[1].is_in_bounds = value->u.idxtemp.index.is_in_bounds; + register_convert_to_minimum_precision(reg); break; case VALUE_TYPE_GROUPSHAREDMEM: - register_init_with_id(reg, VKD3DSPR_GROUPSHAREDMEM, data_type, value->u.groupsharedmem.id); + vsir_register_init(reg, VKD3DSPR_GROUPSHAREDMEM, data_type, 2); + reg->idx[0].offset = value->u.groupsharedmem.id; + register_index_address_init(®->idx[1], value->u.groupsharedmem.index.index, sm6); + reg->idx[1].is_in_bounds = value->u.groupsharedmem.index.is_in_bounds; + break; + + case VALUE_TYPE_CONSTANT: + vsir_register_init(reg, scalar_type->u.width == 64 ? VKD3DSPR_IMMCONST64 : VKD3DSPR_IMMCONST, + data_type, 0); + reg->u = value->u.constant.immconst; + register_convert_to_minimum_precision(reg); break; case VALUE_TYPE_UNDEFINED: @@ -2472,15 +2632,17 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str case VALUE_TYPE_DATA: vkd3d_unreachable(); } + + reg->non_uniform = value->non_uniform; } static void sm6_parser_init_ssa_value(struct sm6_parser *sm6, struct sm6_value *value) { unsigned int id; - if (register_is_ssa(&value->reg) && value->reg.idx[0].offset) + if (value->value_type == VALUE_TYPE_SSA && value->u.ssa.id) { - id = value->reg.idx[0].offset; + id = value->u.ssa.id; TRACE("Using forward-allocated id %u.\n", id); } else @@ -2490,7 +2652,6 @@ static void sm6_parser_init_ssa_value(struct sm6_parser *sm6, struct sm6_value * value->value_type = VALUE_TYPE_SSA; value->u.ssa.id = id; - sm6_register_from_value(&value->reg, value); } static void register_make_constant_uint(struct vkd3d_shader_register *reg, unsigned int value) @@ -2547,10 +2708,11 @@ static void src_param_init_vector(struct vkd3d_shader_src_param *param, unsigned param->modifiers = VKD3DSPSM_NONE; } -static void src_param_init_from_value(struct vkd3d_shader_src_param *param, const struct sm6_value *src) +static void src_param_init_from_value(struct vkd3d_shader_src_param *param, const struct sm6_value *src, + struct sm6_parser *sm6) { src_param_init(param); - sm6_register_from_value(¶m->reg, src); + sm6_register_from_value(¶m->reg, src, sm6); } static void src_param_init_vector_from_reg(struct vkd3d_shader_src_param *param, @@ -2570,12 +2732,12 @@ static void src_param_make_constant_uint(struct vkd3d_shader_src_param *param, u static void register_index_address_init(struct vkd3d_shader_register_index *idx, const struct sm6_value *address, struct sm6_parser *sm6) { - if (sm6_value_is_constant(address)) + if (address && sm6_value_is_constant(address)) { - idx->offset = sm6_value_get_constant_uint(address); + idx->offset = sm6_value_get_constant_uint(address, sm6); idx->rel_addr = NULL; } - else if (sm6_value_is_undef(address)) + else if (!address || sm6_value_is_undef(address)) { idx->offset = 0; idx->rel_addr = NULL; @@ -2584,7 +2746,7 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, { struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(sm6->p.program, 1); if (rel_addr) - src_param_init_from_value(rel_addr, address); + src_param_init_from_value(rel_addr, address, sm6); idx->offset = 0; idx->rel_addr = rel_addr; } @@ -2619,7 +2781,7 @@ static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instructio dst_param_init(param); sm6_parser_init_ssa_value(sm6, dst); - sm6_register_from_value(¶m->reg, dst); + sm6_register_from_value(¶m->reg, dst, sm6); return true; } @@ -2631,22 +2793,20 @@ static void instruction_dst_param_init_ssa_vector(struct vkd3d_shader_instructio dst_param_init_vector(param, component_count); sm6_parser_init_ssa_value(sm6, dst); - sm6_register_from_value(¶m->reg, dst); + sm6_register_from_value(¶m->reg, dst, sm6); } -static bool instruction_dst_param_init_temp_vector(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) +static bool instruction_dst_param_init_uint_temp_vector(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) { - struct sm6_value *dst = sm6_parser_get_current_value(sm6); struct vkd3d_shader_dst_param *param; if (!(param = instruction_dst_params_alloc(ins, 1, sm6))) return false; - vsir_dst_param_init(param, VKD3DSPR_TEMP, vkd3d_data_type_from_sm6_type(sm6_type_get_scalar_type(dst->type, 0)), 1); + vsir_dst_param_init(param, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); param->write_mask = VKD3DSP_WRITEMASK_ALL; param->reg.idx[0].offset = 0; param->reg.dimension = VSIR_DIMENSION_VEC4; - dst->reg = param->reg; return true; } @@ -2928,7 +3088,6 @@ static size_t sm6_parser_get_value_idx_by_ref(struct sm6_parser *sm6, const stru value->type = fwd_type; value->value_type = VALUE_TYPE_SSA; value->u.ssa.id = sm6_parser_alloc_ssa_id(sm6); - sm6_register_from_value(&value->reg, value); } } @@ -3017,53 +3176,13 @@ static inline uint64_t decode_rotated_signed_value(uint64_t value) return value << 63; } -static float bitcast_uint_to_float(unsigned int value) -{ - union - { - uint32_t uint32_value; - float float_value; - } u; - - u.uint32_value = value; - return u.float_value; -} - -static inline double bitcast_uint64_to_double(uint64_t value) -{ - union - { - uint64_t uint64_value; - double double_value; - } u; - - u.uint64_value = value; - return u.double_value; -} - -static float register_get_float_value(const struct vkd3d_shader_register *reg) -{ - if (!register_is_constant(reg) || !data_type_is_floating_point(reg->data_type)) - return 0.0; - - if (reg->dimension == VSIR_DIMENSION_VEC4) - WARN("Returning vec4.x.\n"); - - if (reg->type == VKD3DSPR_IMMCONST64) - { - WARN("Truncating double to float.\n"); - return bitcast_uint64_to_double(reg->u.immconst_u64[0]); - } - - return bitcast_uint_to_float(reg->u.immconst_u32[0]); -} - static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, const struct sm6_type *type, const uint64_t *operands, struct sm6_parser *sm6) { struct vkd3d_shader_immediate_constant_buffer *icb; const struct sm6_type *elem_type; unsigned int i, size, count; + uint64_t *data64; elem_type = type->u.array.elem_type; /* Multidimensional arrays are emitted in flattened form. */ @@ -3115,28 +3234,70 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co return VKD3D_OK; count = type->u.array.count; - if (size > sizeof(icb->data[0])) - { - uint64_t *data = (uint64_t *)icb->data; - for (i = 0; i < count; ++i) - data[i] = operands[i]; - } - else + switch (icb->data_type) { - for (i = 0; i < count; ++i) - icb->data[i] = operands[i]; + case VKD3D_DATA_HALF: + for (i = 0; i < count; ++i) + icb->data[i] = half_to_float(operands[i]); + icb->data_type = VKD3D_DATA_FLOAT; + break; + + case VKD3D_DATA_UINT16: + for (i = 0; i < count; ++i) + icb->data[i] = (int16_t)operands[i]; + icb->data_type = VKD3D_DATA_UINT; + break; + + case VKD3D_DATA_FLOAT: + case VKD3D_DATA_UINT: + for (i = 0; i < count; ++i) + icb->data[i] = operands[i]; + break; + + case VKD3D_DATA_DOUBLE: + case VKD3D_DATA_UINT64: + data64 = (uint64_t *)icb->data; + for (i = 0; i < count; ++i) + data64[i] = operands[i]; + break; + + default: + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid array of type %u.", icb->data_type); + return VKD3D_ERROR_INVALID_SHADER; } return VKD3D_OK; } +static struct sm6_index *sm6_get_value_index(struct sm6_parser *sm6, struct sm6_value *value) +{ + switch (value->value_type) + { + case VALUE_TYPE_ICB: + return &value->u.icb.index; + + case VALUE_TYPE_IDXTEMP: + return &value->u.idxtemp.index; + + case VALUE_TYPE_GROUPSHAREDMEM: + return &value->u.groupsharedmem.index; + + default: + WARN("Cannot index into value of type %#x.\n", value->value_type); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Cannot index into value of type %#x.", value->value_type); + return NULL; + } +} + static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, const struct dxil_record *record, struct sm6_value *dst) { const struct sm6_type *elem_type, *pointee_type, *gep_type, *ptr_type; - struct vkd3d_shader_register reg; struct sm6_value *operands[3]; unsigned int i, j, offset; + struct sm6_index *index; uint64_t value; i = 0; @@ -3178,9 +3339,13 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c } } - sm6_register_from_value(®, operands[0]); + *dst = *operands[0]; + index = sm6_get_value_index(sm6, dst); - if (reg.idx_count > 1) + if (!index) + return VKD3D_ERROR_INVALID_SHADER; + + if (index->index) { WARN("Unsupported stacked GEP.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, @@ -3203,8 +3368,6 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c return VKD3D_ERROR_INVALID_SHADER; } - dst->structure_stride = operands[0]->structure_stride; - ptr_type = operands[0]->type; if (!sm6_type_is_pointer(ptr_type)) { @@ -3225,7 +3388,7 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c "Explicit pointee type for constexpr GEP does not match the element type."); } - offset = sm6_value_get_constant_uint(operands[2]); + offset = sm6_value_get_constant_uint(operands[2], sm6); if (!(gep_type = sm6_type_get_element_type_at_index(pointee_type, offset))) { WARN("Failed to get element type.\n"); @@ -3241,20 +3404,17 @@ static enum vkd3d_result sm6_parser_init_constexpr_gep(struct sm6_parser *sm6, c "Module does not define a pointer type for a constexpr GEP result."); return VKD3D_ERROR_INVALID_SHADER; } - dst->reg = reg; - dst->reg.idx[1].offset = offset; - dst->reg.idx[1].is_in_bounds = record->code == CST_CODE_CE_INBOUNDS_GEP; - dst->reg.idx_count = 2; + + index->index = operands[2]; + index->is_in_bounds = record->code == CST_CODE_CE_INBOUNDS_GEP; return VKD3D_OK; } static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const struct dxil_block *block) { - enum vkd3d_shader_register_type reg_type = VKD3DSPR_INVALID; - const struct sm6_type *type, *elem_type, *ptr_type; + const struct sm6_type *type, *ptr_type; size_t i, base_value_idx, value_idx; - enum vkd3d_data_type reg_data_type; const struct dxil_record *record; const struct sm6_value *src; enum vkd3d_result ret; @@ -3275,18 +3435,6 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) return VKD3D_ERROR_INVALID_SHADER; - elem_type = sm6_type_get_element_type(type); - if (sm6_type_is_numeric(elem_type)) - { - reg_data_type = vkd3d_data_type_from_sm6_type(elem_type); - reg_type = elem_type->u.width > 32 ? VKD3DSPR_IMMCONST64 : VKD3DSPR_IMMCONST; - } - else - { - reg_data_type = VKD3D_DATA_UNUSED; - reg_type = VKD3DSPR_INVALID; - } - if (i == block->record_count - 1) WARN("Unused SETTYPE record.\n"); @@ -3301,19 +3449,21 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const dst = sm6_parser_get_current_value(sm6); dst->type = type; - dst->value_type = VALUE_TYPE_REG; dst->is_back_ref = true; - vsir_register_init(&dst->reg, reg_type, reg_data_type, 0); switch (record->code) { case CST_CODE_NULL: - if (sm6_type_is_array(type) - && (ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) + if (sm6_type_is_array(type)) { - return ret; + if ((ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) + return ret; + } + else + { + dst->value_type = VALUE_TYPE_CONSTANT; + memset(&dst->u.constant, 0, sizeof(dst->u.constant)); } - /* For non-aggregates, register constant data is already zero-filled. */ break; case CST_CODE_INTEGER: @@ -3326,11 +3476,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const return VKD3D_ERROR_INVALID_SHADER; } + dst->value_type = VALUE_TYPE_CONSTANT; + value = decode_rotated_signed_value(record->operands[0]); if (type->u.width <= 32) - dst->reg.u.immconst_u32[0] = value & ((1ull << type->u.width) - 1); + dst->u.constant.immconst.immconst_u32[0] = value & ((1ull << type->u.width) - 1); else - dst->reg.u.immconst_u64[0] = value; + dst->u.constant.immconst.immconst_u64[0] = value; break; @@ -3344,14 +3496,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const return VKD3D_ERROR_INVALID_SHADER; } - if (type->u.width == 16) - dst->reg.u.immconst_u32[0] = record->operands[0]; - else if (type->u.width == 32) - dst->reg.u.immconst_f32[0] = bitcast_uint_to_float(record->operands[0]); - else if (type->u.width == 64) - dst->reg.u.immconst_f64[0] = bitcast_uint64_to_double(record->operands[0]); + dst->value_type = VALUE_TYPE_CONSTANT; + + value = record->operands[0]; + if (type->u.width <= 32) + dst->u.constant.immconst.immconst_u32[0] = value & ((1ull << type->u.width) - 1); else - vkd3d_unreachable(); + dst->u.constant.immconst.immconst_u64[0] = value; break; @@ -3377,6 +3528,46 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const return ret; break; + case CST_CODE_CE_CAST: + /* Resolve later in case forward refs exist. */ + dst->type = type; + dst->value_type = VALUE_TYPE_INVALID; + break; + + case CST_CODE_UNDEF: + dxil_record_validate_operand_max_count(record, 0, sm6); + dst->value_type = VALUE_TYPE_UNDEFINED; + break; + + default: + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Constant code %u is unhandled.", record->code); + dst->value_type = VALUE_TYPE_INVALID; + break; + } + + if (record->attachment) + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring a metadata attachment for a constant."); + + ++sm6->value_count; + } + + value_idx = base_value_idx; + + for (i = 0; i < block->record_count; ++i) + { + sm6->p.location.column = i; + record = block->records[i]; + + switch (record->code) + { + case CST_CODE_SETTYPE: + continue; + + default: + break; + case CST_CODE_CE_CAST: if (!dxil_record_validate_operand_count(record, 3, 3, sm6)) return VKD3D_ERROR_INVALID_SHADER; @@ -3413,59 +3604,26 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const return VKD3D_ERROR_INVALID_SHADER; } - /* Resolve later in case forward refs exist. */ - dst->type = type; - dst->reg.type = VKD3DSPR_COUNT; - dst->reg.idx[0].offset = value; - break; + dst = &sm6->values[value_idx]; + src = &sm6->values[value]; - case CST_CODE_UNDEF: - dxil_record_validate_operand_max_count(record, 0, sm6); - dst->value_type = VALUE_TYPE_UNDEFINED; - sm6_register_from_value(&dst->reg, dst); - break; + if (!sm6_value_is_numeric_array(src)) + { + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Constexpr cast source value is not a global array element."); + return VKD3D_ERROR_INVALID_SHADER; + } - default: - FIXME("Unhandled constant code %u.\n", record->code); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Constant code %u is unhandled.", record->code); - dst->value_type = VALUE_TYPE_INVALID; - sm6_register_from_value(&dst->reg, dst); + type = dst->type; + *dst = *src; + dst->type = type; break; } - if (record->attachment) - { - WARN("Ignoring metadata attachment.\n"); - vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, - "Ignoring a metadata attachment for a constant."); - } - - ++sm6->value_count; + ++value_idx; } - /* Resolve cast forward refs. */ - for (i = base_value_idx; i < sm6->value_count; ++i) - { - dst = &sm6->values[i]; - if (dst->reg.type != VKD3DSPR_COUNT) - continue; - - type = dst->type; - - src = &sm6->values[dst->reg.idx[0].offset]; - if (!sm6_value_is_numeric_array(src)) - { - WARN("Value is not an array.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Constexpr cast source value is not a global array element."); - return VKD3D_ERROR_INVALID_SHADER; - } - - *dst = *src; - dst->type = type; - dst->reg.data_type = vkd3d_data_type_from_sm6_type(type->u.pointer.type); - } + VKD3D_ASSERT(value_idx == sm6->value_count); return VKD3D_OK; } @@ -3537,7 +3695,6 @@ static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const stru dst->value_type = VALUE_TYPE_IDXTEMP; dst->u.idxtemp.id = ins->declaration.indexable_temp.register_idx; - sm6_register_from_value(&dst->reg, dst); } static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6_type *elem_type, @@ -3551,8 +3708,7 @@ static void sm6_parser_declare_tgsm_raw(struct sm6_parser *sm6, const struct sm6 dst->value_type = VALUE_TYPE_GROUPSHAREDMEM; dst->u.groupsharedmem.id = sm6->tgsm_count++; dst->structure_stride = 0; - sm6_register_from_value(&dst->reg, dst); - sm6_register_from_value(&ins->declaration.tgsm_raw.reg.reg, dst); + sm6_register_from_value(&ins->declaration.tgsm_raw.reg.reg, dst, sm6); ins->declaration.tgsm_raw.alignment = alignment; byte_count = elem_type->u.width / 8u; if (byte_count != 4) @@ -3576,8 +3732,7 @@ static void sm6_parser_declare_tgsm_structured(struct sm6_parser *sm6, const str dst->value_type = VALUE_TYPE_GROUPSHAREDMEM; dst->u.groupsharedmem.id = sm6->tgsm_count++; dst->structure_stride = elem_type->u.width / 8u; - sm6_register_from_value(&dst->reg, dst); - sm6_register_from_value(&ins->declaration.tgsm_structured.reg.reg, dst); + sm6_register_from_value(&ins->declaration.tgsm_structured.reg.reg, dst, sm6); if (dst->structure_stride != 4) { FIXME("Unsupported structure stride %u.\n", dst->structure_stride); @@ -3697,7 +3852,6 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ dst = sm6_parser_get_current_value(sm6); dst->type = type; - dst->value_type = VALUE_TYPE_REG; dst->is_back_ref = true; if (is_constant && !init) @@ -3891,7 +4045,6 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) value->u.icb.id = icb->register_idx; else value->u.icb.id = 0; - sm6_register_from_value(&value->reg, value); } return VKD3D_OK; @@ -3912,12 +4065,12 @@ static void dst_param_io_init(struct vkd3d_shader_dst_param *param, } static void src_params_init_from_operands(struct vkd3d_shader_src_param *src_params, - const struct sm6_value **operands, unsigned int count) + const struct sm6_value **operands, unsigned int count, struct sm6_parser *sm6) { unsigned int i; for (i = 0; i < count; ++i) - src_param_init_from_value(&src_params[i], operands[i]); + src_param_init_from_value(&src_params[i], operands[i], sm6); } static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( @@ -4163,7 +4316,7 @@ static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_rec if (!(size = sm6_parser_get_value_safe(sm6, record->operands[2]))) return; /* A size of 1 means one instance of type[0], i.e. one array. */ - if (sm6_value_get_constant_uint(size) != 1) + if (sm6_value_get_constant_uint(size, sm6) != 1) { FIXME("Allocation size is not 1.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, @@ -4228,7 +4381,7 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ || !sm6_value_validate_is_backward_ref(ptr, sm6)) return; - sm6_register_from_value(®, ptr); + sm6_register_from_value(®, ptr, sm6); if (reg.type != VKD3DSPR_GROUPSHAREDMEM) { @@ -4284,12 +4437,12 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ src_param_init_vector_from_reg(&src_params[0], &coord); else src_param_make_constant_uint(&src_params[0], 0); - src_param_init_from_value(&src_params[1], src); + src_param_init_from_value(&src_params[1], src, sm6); sm6_parser_init_ssa_value(sm6, dst); dst_params = instruction_dst_params_alloc(ins, 2, sm6); - sm6_register_from_value(&dst_params[0].reg, dst); + sm6_register_from_value(&dst_params[0].reg, dst, sm6); dst_param_init(&dst_params[0]); dst_params[1].reg = reg; @@ -4459,8 +4612,8 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) return; - src_param_init_from_value(&src_params[0], a); - src_param_init_from_value(&src_params[1], b); + src_param_init_from_value(&src_params[0], a, sm6); + src_param_init_from_value(&src_params[1], b, sm6); if (code == BINOP_SUB) src_params[1].modifiers = VKD3DSPSM_NEG; @@ -4474,7 +4627,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco dst_param_init(&dst_params[0]); dst_param_init(&dst_params[1]); sm6_parser_init_ssa_value(sm6, dst); - sm6_register_from_value(&dst_params[index].reg, dst); + sm6_register_from_value(&dst_params[index].reg, dst, sm6); vsir_dst_param_init_null(&dst_params[index ^ 1]); } else @@ -4536,7 +4689,7 @@ static void sm6_parser_emit_br(struct sm6_parser *sm6, const struct dxil_record dxil_record_validate_operand_max_count(record, i, sm6); code_block->terminator.type = TERMINATOR_COND_BR; - sm6_register_from_value(&code_block->terminator.conditional_reg, value); + sm6_register_from_value(&code_block->terminator.conditional_reg, value, sm6); code_block->terminator.true_block = sm6_function_get_block(function, record->operands[0], sm6); code_block->terminator.false_block = sm6_function_get_block(function, record->operands[1], sm6); } @@ -4607,7 +4760,7 @@ static bool sm6_parser_emit_composite_construct(struct sm6_parser *sm6, const st unsigned int i; for (i = 0; i < component_count; ++i) - sm6_register_from_value(&operand_regs[i], operands[i]); + sm6_register_from_value(&operand_regs[i], operands[i], sm6); return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); } @@ -4623,11 +4776,11 @@ static bool sm6_parser_emit_coordinate_construct(struct sm6_parser *sm6, const s { if (!z_operand && operands[component_count]->value_type == VALUE_TYPE_UNDEFINED) break; - sm6_register_from_value(&operand_regs[component_count], operands[component_count]); + sm6_register_from_value(&operand_regs[component_count], operands[component_count], sm6); } if (z_operand) - sm6_register_from_value(&operand_regs[component_count++], z_operand); + sm6_register_from_value(&operand_regs[component_count++], z_operand, sm6); return sm6_parser_emit_reg_composite_construct(sm6, operand_regs, component_count, state, reg); } @@ -4741,7 +4894,7 @@ static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, enum dx_intrinsic_o vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0]); + src_param_init_from_value(src_param, operands[0], sm6); instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -4780,15 +4933,15 @@ static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_ vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type)); if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) return; - src_param_init_from_value(&src_params[0], operands[0]); - src_param_init_from_value(&src_params[1], operands[1]); + src_param_init_from_value(&src_params[0], operands[0], sm6); + src_param_init_from_value(&src_params[1], operands[1], sm6); instruction_dst_param_init_ssa_scalar(ins, sm6); } static enum vkd3d_shader_opcode map_dx_atomic_binop(const struct sm6_value *operand, struct sm6_parser *sm6) { - uint64_t code = sm6_value_get_constant_uint(operand); + uint64_t code = sm6_value_get_constant_uint(operand, sm6); switch (code) { @@ -4852,7 +5005,7 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr } else { - sm6_register_from_value(®, operands[coord_idx]); + sm6_register_from_value(®, operands[coord_idx], sm6); } for (i = coord_idx + coord_count; i < coord_idx + 3; ++i) @@ -4873,14 +5026,14 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr return; src_param_init_vector_from_reg(&src_params[0], ®); if (is_cmp_xchg) - src_param_init_from_value(&src_params[1], operands[4]); - src_param_init_from_value(&src_params[1 + is_cmp_xchg], operands[5]); + src_param_init_from_value(&src_params[1], operands[4], sm6); + src_param_init_from_value(&src_params[1 + is_cmp_xchg], operands[5], sm6); sm6_parser_init_ssa_value(sm6, dst); dst_params = instruction_dst_params_alloc(ins, 2, sm6); dst_param_init(&dst_params[0]); - sm6_register_from_value(&dst_params[0].reg, dst); + sm6_register_from_value(&dst_params[0].reg, dst, sm6); dst_param_init(&dst_params[1]); sm6_register_from_handle(sm6, &resource->u.handle, &dst_params[1].reg); } @@ -4892,7 +5045,7 @@ static void sm6_parser_emit_dx_barrier(struct sm6_parser *sm6, enum dx_intrinsic enum dxil_sync_flags flags; vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SYNC); - flags = sm6_value_get_constant_uint(operands[0]); + flags = sm6_value_get_constant_uint(operands[0], sm6); ins->flags = flags & (SYNC_THREAD_GROUP | SYNC_THREAD_GROUP_UAV); if (flags & SYNC_GLOBAL_UAV) ins->flags |= VKD3DSSF_GLOBAL_UAV; @@ -4926,7 +5079,7 @@ static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enu "A dynamic update value for a UAV counter operation is not supported."); return; } - i = sm6_value_get_constant_uint(operands[1]); + i = sm6_value_get_constant_uint(operands[1], sm6); if (i != 1 && i != 255) { WARN("Unexpected update value %#x.\n", i); @@ -4963,7 +5116,7 @@ static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_int if (!sm6_parser_emit_coordinate_construct(sm6, &operands[2], 3, NULL, state, &coord)) return; - clamp = sm6_value_get_constant_uint(operands[5]); + clamp = sm6_value_get_constant_uint(operands[5], sm6); ins = state->ins; vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_LOD); @@ -5064,7 +5217,7 @@ static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_pa if (!sm6_value_is_constant(address)) return d; - register_index = sm6_value_get_constant_uint(address); + register_index = sm6_value_get_constant_uint(address, sm6); if (register_index >= d->range.first && register_index <= d->range.last) return d; } @@ -5081,8 +5234,8 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int struct sm6_value *dst; unsigned int id; - type = sm6_value_get_constant_uint(operands[0]); - id = sm6_value_get_constant_uint(operands[1]); + type = sm6_value_get_constant_uint(operands[0], sm6); + id = sm6_value_get_constant_uint(operands[1], sm6); if (!(d = sm6_parser_get_descriptor(sm6, type, id, operands[2]))) { WARN("Failed to find resource type %#x, id %#x.\n", type, id); @@ -5095,7 +5248,7 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int dst->value_type = VALUE_TYPE_HANDLE; dst->u.handle.d = d; dst->u.handle.index = operands[2]; - dst->u.handle.non_uniform = !!sm6_value_get_constant_uint(operands[3]); + dst->u.handle.non_uniform = !!sm6_value_get_constant_uint(operands[3], sm6); /* NOP is used to flag no instruction emitted. */ ins->opcode = VKD3DSIH_NOP; @@ -5113,7 +5266,7 @@ static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - i = sm6_value_get_constant_uint(operands[0]); + i = sm6_value_get_constant_uint(operands[0], sm6); if (i >= MAX_GS_OUTPUT_STREAMS) { WARN("Invalid stream index %u.\n", i); @@ -5142,7 +5295,7 @@ static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_DISCARD); if ((src_param = instruction_src_params_alloc(ins, 1, sm6))) - src_param_init_from_value(src_param, operands[0]); + src_param_init_from_value(src_param, operands[0], sm6); } static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, @@ -5154,7 +5307,7 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - if ((component_idx = sm6_value_get_constant_uint(operands[0])) >= 3) + if ((component_idx = sm6_value_get_constant_uint(operands[0], sm6)) >= 3) { WARN("Invalid component index %u.\n", component_idx); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, @@ -5223,8 +5376,8 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri unsigned int row_index, column_index; const struct signature_element *e; - row_index = sm6_value_get_constant_uint(operands[0]); - column_index = sm6_value_get_constant_uint(operands[2]); + row_index = sm6_value_get_constant_uint(operands[0], sm6); + column_index = sm6_value_get_constant_uint(operands[2], sm6); signature = &sm6->p.program->input_signature; if (row_index >= signature->element_count) @@ -5256,7 +5409,7 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri register_index_address_init(&src_params[0].reg.idx[0], operands[1], sm6); if (op == DX_EVAL_SAMPLE_INDEX) - src_param_init_from_value(&src_params[1], operands[3]); + src_param_init_from_value(&src_params[1], operands[3], sm6); instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -5270,7 +5423,7 @@ static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_op vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0]); + src_param_init_from_value(src_param, operands[0], sm6); src_param->modifiers = VKD3DSPSM_ABS; instruction_dst_param_init_ssa_scalar(ins, sm6); @@ -5311,7 +5464,7 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i if (component_count > 1) { src_param->reg.dimension = VSIR_DIMENSION_VEC4; - component_idx = sm6_value_get_constant_uint(operands[0]); + component_idx = sm6_value_get_constant_uint(operands[0], sm6); } src_param_init_scalar(src_param, component_idx); @@ -5345,7 +5498,7 @@ static void sm6_parser_emit_dx_ma(struct sm6_parser *sm6, enum dx_intrinsic_opco if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) return; for (i = 0; i < 3; ++i) - src_param_init_from_value(&src_params[i], operands[i]); + src_param_init_from_value(&src_params[i], operands[i], sm6); instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -5375,12 +5528,12 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in if (is_texture) { ins->flags = VKD3DSI_RESINFO_UINT; - src_param_init_from_value(&src_params[0], operands[1]); + src_param_init_from_value(&src_params[0], operands[1], sm6); component_count = VKD3D_VEC4_SIZE; if (resource_kind_is_multisampled(resource_kind)) { - instruction_dst_param_init_temp_vector(ins++, sm6); + instruction_dst_param_init_uint_temp_vector(ins++, sm6); state->temp_idx = 1; /* DXIL does not have an intrinsic for sample info, and resinfo is expected to return @@ -5393,7 +5546,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); src_params[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); - if (!instruction_dst_param_init_temp_vector(ins, sm6)) + if (!instruction_dst_param_init_uint_temp_vector(ins, sm6)) return; dst = ins->dst; dst->write_mask = VKD3DSP_WRITEMASK_3; @@ -5448,7 +5601,7 @@ static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsi if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) return; for (i = 0; i < 3; ++i) - src_param_init_from_value(&src_params[i], operands[i]); + src_param_init_from_value(&src_params[i], operands[i], sm6); instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -5466,8 +5619,8 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin const struct shader_signature *signature; const struct signature_element *e; - row_index = sm6_value_get_constant_uint(operands[0]); - column_index = sm6_value_get_constant_uint(operands[2]); + row_index = sm6_value_get_constant_uint(operands[0], sm6); + column_index = sm6_value_get_constant_uint(operands[2], sm6); if (is_control_point && operands[3]->value_type == VALUE_TYPE_UNDEFINED) { @@ -5576,7 +5729,7 @@ static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic enum vkd3d_shader_opcode opcode; enum dxil_quad_op_kind quad_op; - quad_op = sm6_value_get_constant_uint(operands[1]); + quad_op = sm6_value_get_constant_uint(operands[1], sm6); if ((opcode = dx_map_quad_op(quad_op)) == VKD3DSIH_INVALID) { FIXME("Unhandled quad op kind %u.\n", quad_op); @@ -5589,7 +5742,7 @@ static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0]); + src_param_init_from_value(src_param, operands[0], sm6); instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -5610,7 +5763,7 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i if (op == DX_RAW_BUFFER_LOAD) { - write_mask = sm6_value_get_constant_uint(operands[3]); + write_mask = sm6_value_get_constant_uint(operands[3], sm6); if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) { WARN("Invalid write mask %#x.\n", write_mask); @@ -5631,7 +5784,7 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i operand_count = 2 + !raw; if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) return; - src_params_init_from_operands(src_params, &operands[1], operand_count - 1); + src_params_init_from_operands(src_params, &operands[1], operand_count - 1, sm6); src_param_init_vector_from_handle(sm6, &src_params[operand_count - 1], &resource->u.handle); instruction_dst_param_init_ssa_vector(ins, component_count, sm6); @@ -5653,7 +5806,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ return; raw = resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER; - write_mask = sm6_value_get_constant_uint(operands[7]); + write_mask = sm6_value_get_constant_uint(operands[7], sm6); if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) { WARN("Invalid write mask %#x.\n", write_mask); @@ -5679,7 +5832,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ "Resource for a raw buffer store is not a raw or structured buffer."); } - alignment = sm6_value_get_constant_uint(operands[8]); + alignment = sm6_value_get_constant_uint(operands[8], sm6); if (alignment & (alignment - 1)) { FIXME("Invalid alignment %#x.\n", alignment); @@ -5697,7 +5850,7 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) return; - src_params_init_from_operands(src_params, &operands[1], operand_count - 1); + src_params_init_from_operands(src_params, &operands[1], operand_count - 1, sm6); data.data_type = VKD3D_DATA_UINT; src_param_init_vector_from_reg(&src_params[operand_count - 1], &data); @@ -5736,7 +5889,7 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) return; - src_param_init_from_value(&src_params[0], operands[1]); + src_param_init_from_value(&src_params[0], operands[1], sm6); if (!sm6_value_is_undef(operands[2])) { /* Constant zero would be ok, but is not worth checking for unless it shows up. */ @@ -5776,7 +5929,7 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr "Resource for a typed buffer store is not a typed buffer."); } - write_mask = sm6_value_get_constant_uint(operands[7]); + write_mask = sm6_value_get_constant_uint(operands[7], sm6); if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) { WARN("Invalid write mask %#x.\n", write_mask); @@ -5801,7 +5954,7 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) return; - src_param_init_from_value(&src_params[0], operands[1]); + src_param_init_from_value(&src_params[0], operands[1], sm6); if (!sm6_value_is_undef(operands[2])) { /* Constant zero would have no effect, but is not worth checking for unless it shows up. */ @@ -5856,30 +6009,30 @@ static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_in if (op == DX_TEX2DMS_GET_SAMPLE_POS) { src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); - src_param_init_from_value(&src_params[1], operands[1]); + src_param_init_from_value(&src_params[1], operands[1], sm6); } else { src_param_init_vector(&src_params[0], 2); vsir_register_init(&src_params[0].reg, VKD3DSPR_RASTERIZER, VKD3D_DATA_FLOAT, 0); src_params[0].reg.dimension = VSIR_DIMENSION_VEC4; - src_param_init_from_value(&src_params[1], operands[0]); + src_param_init_from_value(&src_params[1], operands[0], sm6); } instruction_dst_param_init_ssa_vector(ins, 2, sm6); } -static unsigned int sm6_value_get_texel_offset(const struct sm6_value *value) +static unsigned int sm6_value_get_texel_offset(const struct sm6_value *value, struct sm6_parser *sm6) { - return sm6_value_is_undef(value) ? 0 : sm6_value_get_constant_uint(value); + return sm6_value_is_undef(value) ? 0 : sm6_value_get_constant_uint(value, sm6); } static void instruction_set_texel_offset(struct vkd3d_shader_instruction *ins, const struct sm6_value **operands, struct sm6_parser *sm6) { - ins->texel_offset.u = sm6_value_get_texel_offset(operands[0]); - ins->texel_offset.v = sm6_value_get_texel_offset(operands[1]); - ins->texel_offset.w = sm6_value_get_texel_offset(operands[2]); + ins->texel_offset.u = sm6_value_get_texel_offset(operands[0], sm6); + ins->texel_offset.v = sm6_value_get_texel_offset(operands[1], sm6); + ins->texel_offset.w = sm6_value_get_texel_offset(operands[2], sm6); } static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, @@ -5925,7 +6078,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ instruction_init_with_resource(ins, (op == DX_SAMPLE_B) ? VKD3DSIH_SAMPLE_B : VKD3DSIH_SAMPLE_LOD, resource, sm6); src_params = instruction_src_params_alloc(ins, 4, sm6); - src_param_init_from_value(&src_params[3], operands[9]); + src_param_init_from_value(&src_params[3], operands[9], sm6); break; case DX_SAMPLE_C: clamp_idx = 10; @@ -5934,7 +6087,7 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ instruction_init_with_resource(ins, (op == DX_SAMPLE_C_LZ) ? VKD3DSIH_SAMPLE_C_LZ : VKD3DSIH_SAMPLE_C, resource, sm6); src_params = instruction_src_params_alloc(ins, 4, sm6); - src_param_init_from_value(&src_params[3], operands[9]); + src_param_init_from_value(&src_params[3], operands[9], sm6); component_count = 1; break; case DX_SAMPLE_GRAD: @@ -6003,7 +6156,7 @@ static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsi vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0]); + src_param_init_from_value(src_param, operands[0], sm6); if (instruction_dst_param_init_ssa_scalar(ins, sm6)) ins->dst->modifiers = VKD3DSPDM_SATURATE; @@ -6021,7 +6174,7 @@ static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_SINCOS); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0]); + src_param_init_from_value(src_param, operands[0], sm6); sm6_parser_init_ssa_value(sm6, dst); @@ -6029,7 +6182,7 @@ static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_ dst_params = instruction_dst_params_alloc(ins, 2, sm6); dst_param_init(&dst_params[0]); dst_param_init(&dst_params[1]); - sm6_register_from_value(&dst_params[index].reg, dst); + sm6_register_from_value(&dst_params[index].reg, dst, sm6); vsir_dst_param_init_null(&dst_params[index ^ 1]); } @@ -6042,7 +6195,7 @@ static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intr vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0]); + src_param_init_from_value(src_param, operands[0], sm6); instruction_dst_param_init_ssa_vector(ins, 2, sm6); } @@ -6060,8 +6213,8 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr const struct signature_element *e; const struct sm6_value *value; - row_index = sm6_value_get_constant_uint(operands[0]); - column_index = sm6_value_get_constant_uint(operands[2]); + row_index = sm6_value_get_constant_uint(operands[0], sm6); + column_index = sm6_value_get_constant_uint(operands[2], sm6); signature = is_patch_constant ? &program->patch_constant_signature : &program->output_signature; if (row_index >= signature->element_count) @@ -6108,7 +6261,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr } if ((src_param = instruction_src_params_alloc(ins, 1, sm6))) - src_param_init_from_value(src_param, value); + src_param_init_from_value(src_param, value, sm6); } static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, @@ -6150,7 +6303,7 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in instruction_init_with_resource(ins, extended_offset ? VKD3DSIH_GATHER4_PO_C : VKD3DSIH_GATHER4_C, resource, sm6); if (!(src_params = instruction_src_params_alloc(ins, 4 + extended_offset, sm6))) return; - src_param_init_from_value(&src_params[3 + extended_offset], operands[9]); + src_param_init_from_value(&src_params[3 + extended_offset], operands[9], sm6); } src_param_init_vector_from_reg(&src_params[0], &coord); @@ -6161,7 +6314,7 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in src_param_init_vector_from_handle(sm6, &src_params[1 + extended_offset], &resource->u.handle); src_param_init_vector_from_handle(sm6, &src_params[2 + extended_offset], &sampler->u.handle); /* Swizzle stored in the sampler parameter is the scalar component index to be gathered. */ - swizzle = sm6_value_get_constant_uint(operands[8]); + swizzle = sm6_value_get_constant_uint(operands[8], sm6); if (swizzle >= VKD3D_VEC4_SIZE) { WARN("Invalid swizzle %#x.\n", swizzle); @@ -6213,7 +6366,7 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr src_param_init_vector_from_reg(&src_params[0], &coord); src_param_init_vector_from_handle(sm6, &src_params[1], &resource->u.handle); if (is_multisample) - src_param_init_from_value(&src_params[2], mip_level_or_sample_count); + src_param_init_from_value(&src_params[2], mip_level_or_sample_count, sm6); instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); } @@ -6235,7 +6388,7 @@ static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_int if (!sm6_parser_emit_coordinate_construct(sm6, &operands[1], 3, NULL, state, &coord)) return; - write_mask = sm6_value_get_constant_uint(operands[8]); + write_mask = sm6_value_get_constant_uint(operands[8], sm6); if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) { WARN("Invalid write mask %#x.\n", write_mask); @@ -6277,7 +6430,7 @@ static void sm6_parser_emit_dx_wave_active_ballot(struct sm6_parser *sm6, enum d vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_WAVE_ACTIVE_BALLOT); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0]); + src_param_init_from_value(src_param, operands[0], sm6); instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); } @@ -6296,7 +6449,7 @@ static enum vkd3d_shader_opcode sm6_dx_map_wave_bit_op(enum dxil_wave_bit_op_kin default: FIXME("Unhandled wave bit op %u.\n", op); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_UNHANDLED_INTRINSIC, - "Wave bit operation %u is unhandled.\n", op); + "Wave bit operation %u is unhandled.", op); return VKD3DSIH_INVALID; } } @@ -6309,7 +6462,7 @@ static void sm6_parser_emit_dx_wave_active_bit(struct sm6_parser *sm6, enum dx_i enum dxil_wave_bit_op_kind wave_op; enum vkd3d_shader_opcode opcode; - wave_op = sm6_value_get_constant_uint(operands[1]); + wave_op = sm6_value_get_constant_uint(operands[1], sm6); if ((opcode = sm6_dx_map_wave_bit_op(wave_op, sm6)) == VKD3DSIH_INVALID) return; @@ -6317,7 +6470,7 @@ static void sm6_parser_emit_dx_wave_active_bit(struct sm6_parser *sm6, enum dx_i if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0]); + src_param_init_from_value(src_param, operands[0], sm6); instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -6342,7 +6495,7 @@ static enum vkd3d_shader_opcode sm6_dx_map_wave_op(enum dxil_wave_op_kind op, bo default: FIXME("Unhandled wave op %u.\n", op); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_UNHANDLED_INTRINSIC, - "Wave operation %u is unhandled.\n", op); + "Wave operation %u is unhandled.", op); return VKD3DSIH_INVALID; } } @@ -6356,8 +6509,8 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic enum dxil_wave_op_kind wave_op; bool is_signed; - wave_op = sm6_value_get_constant_uint(operands[1]); - is_signed = !sm6_value_get_constant_uint(operands[2]); + wave_op = sm6_value_get_constant_uint(operands[1], sm6); + is_signed = !sm6_value_get_constant_uint(operands[2], sm6); opcode = sm6_dx_map_wave_op(wave_op, is_signed, sm6_type_is_floating_point(operands[0]->type), sm6); if (opcode == VKD3DSIH_INVALID) @@ -6368,7 +6521,7 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, operands[0]); + src_param_init_from_value(src_param, operands[0], sm6); instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -6645,7 +6798,6 @@ static void sm6_parser_emit_unhandled(struct sm6_parser *sm6, struct vkd3d_shade return; dst->value_type = VALUE_TYPE_INVALID; - sm6_register_from_value(&dst->reg, dst); } static void sm6_parser_decode_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, @@ -6750,7 +6902,7 @@ static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_recor "Expected a constant integer dx intrinsic function id."); return; } - sm6_parser_decode_dx_op(sm6, sm6_value_get_constant_uint(op_value), + sm6_parser_decode_dx_op(sm6, sm6_value_get_constant_uint(op_value, sm6), fn_value->u.function.name, &operands[1], operand_count - 1, state, dst); } @@ -6759,6 +6911,7 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ { enum vkd3d_shader_opcode op = VKD3DSIH_INVALID; bool from_int, to_int, from_fp, to_fp; + unsigned int from_width, to_width; bool is_valid = false; from_int = sm6_type_is_integer(from); @@ -6782,70 +6935,62 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ return VKD3DSIH_INVALID; } - /* DXC emits minimum precision types as 16-bit. These must be emitted - * as 32-bit in VSIR, so all width extensions to 32 bits are no-ops. */ switch (code) { case CAST_TRUNC: - /* nop or min precision. TODO: native 16-bit */ - if (to->u.width == from->u.width || (to->u.width == 16 && from->u.width == 32)) - op = VKD3DSIH_NOP; - else - op = VKD3DSIH_UTOU; + op = VKD3DSIH_UTOU; is_valid = from_int && to_int && to->u.width <= from->u.width; break; + case CAST_ZEXT: + op = VKD3DSIH_UTOU; + is_valid = from_int && to_int && to->u.width >= from->u.width; + break; + case CAST_SEXT: - /* nop or min precision. TODO: native 16-bit. - * Extension instructions could be emitted for min precision, but in Windows - * the AMD RX 580 simply drops such instructions, which makes sense as no - * assumptions should be made about any behaviour which depends on bit width. */ - if (to->u.width == from->u.width || (to->u.width == 32 && from->u.width == 16)) - { - op = VKD3DSIH_NOP; - is_valid = from_int && to_int; - } - else if (to->u.width > from->u.width) - { - op = (code == CAST_ZEXT) ? VKD3DSIH_UTOU : VKD3DSIH_ITOI; - VKD3D_ASSERT(from->u.width == 1 || to->u.width == 64); - is_valid = from_int && to_int; - } + op = VKD3DSIH_ITOI; + is_valid = from_int && to_int && to->u.width >= from->u.width; break; + case CAST_FPTOUI: op = VKD3DSIH_FTOU; is_valid = from_fp && to_int && to->u.width > 1; break; + case CAST_FPTOSI: op = VKD3DSIH_FTOI; is_valid = from_fp && to_int && to->u.width > 1; break; + case CAST_UITOFP: op = VKD3DSIH_UTOF; is_valid = from_int && to_fp; break; + case CAST_SITOFP: op = VKD3DSIH_ITOF; is_valid = from_int && to_fp; break; + case CAST_FPTRUNC: - /* TODO: native 16-bit */ - op = (from->u.width == 64) ? VKD3DSIH_DTOF : VKD3DSIH_NOP; - is_valid = from_fp && to_fp; + op = VKD3DSIH_DTOF; + is_valid = from_fp && to_fp && to->u.width <= from->u.width; break; + case CAST_FPEXT: - /* TODO: native 16-bit */ - op = (to->u.width == 64) ? VKD3DSIH_FTOD : VKD3DSIH_NOP; - is_valid = from_fp && to_fp; + op = VKD3DSIH_FTOD; + is_valid = from_fp && to_fp && to->u.width >= from->u.width; break; + case CAST_BITCAST: op = VKD3DSIH_MOV; is_valid = to->u.width == from->u.width; break; + default: FIXME("Unhandled cast op %"PRIu64".\n", code); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Cast operation %"PRIu64" is unhandled.\n", code); + "Cast operation %"PRIu64" is unhandled.", code); return VKD3DSIH_INVALID; } @@ -6853,11 +6998,25 @@ static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_ { FIXME("Invalid types %u and/or %u for op %"PRIu64".\n", from->class, to->class, code); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.\n", + "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.", code, from->class, from->u.width, to->class, to->u.width); return VKD3DSIH_INVALID; } + /* 16-bit values are currently treated as 32-bit, because 16-bit is + * interpreted as a minimum precision hint in SM 6.0, and we don't handle + * SM > 6.0 yet. */ + from_width = from->u.width; + if (from_width == 16) + from_width = 32; + + to_width = to->u.width; + if (to_width == 16) + to_width = 32; + + if (from->class == to->class && from_width == to_width) + op = VKD3DSIH_NOP; + return op; } @@ -6896,22 +7055,22 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor if (handler_idx == VKD3DSIH_NOP) { - sm6_register_from_value(&dst->reg, value); - /* Set the result type for casts from 16-bit min precision. */ - if (type->u.width != 16) - dst->reg.data_type = vkd3d_data_type_from_sm6_type(type); + *dst = *value; + dst->type = type; return; } if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param_init_from_value(src_param, value); + src_param_init_from_value(src_param, value, sm6); instruction_dst_param_init_ssa_scalar(ins, sm6); - /* bitcast */ + /* VSIR bitcasts are represented by source registers with types different + * from the types they were written with, rather than with different types + * for the MOV source and destination. */ if (handler_idx == VKD3DSIH_MOV) - src_param->reg.data_type = dst->reg.data_type; + src_param->reg.data_type = ins->dst[0].reg.data_type; } struct sm6_cmp_info @@ -7051,8 +7210,8 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) return; - src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a); - src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b); + src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a, sm6); + src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b, sm6); instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -7074,7 +7233,7 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re || !sm6_value_validate_is_backward_ref(ptr, sm6)) return; - sm6_register_from_value(®, ptr); + sm6_register_from_value(®, ptr, sm6); if (reg.type != VKD3DSPR_GROUPSHAREDMEM) { @@ -7129,14 +7288,14 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) return; src_param_make_constant_uint(&src_params[0], 0); - src_param_init_from_value(&src_params[1], cmp); - src_param_init_from_value(&src_params[2], new); + src_param_init_from_value(&src_params[1], cmp, sm6); + src_param_init_from_value(&src_params[2], new, sm6); sm6_parser_init_ssa_value(sm6, dst); if (!(dst_params = instruction_dst_params_alloc(ins, 2, sm6))) return; - sm6_register_from_value(&dst_params[0].reg, dst); + sm6_register_from_value(&dst_params[0].reg, dst, sm6); dst_param_init(&dst_params[0]); dst_params[1].reg = reg; dst_param_init(&dst_params[1]); @@ -7195,7 +7354,7 @@ static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - sm6_register_from_value(&src_param->reg, src); + sm6_register_from_value(&src_param->reg, src, sm6); src_param_init_scalar(src_param, elem_idx); instruction_dst_param_init_ssa_scalar(ins, sm6); @@ -7208,9 +7367,8 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record unsigned int elem_idx, operand_idx = 2; enum bitcode_address_space addr_space; const struct sm6_value *elem_value; - struct vkd3d_shader_register reg; const struct sm6_value *src; - bool is_in_bounds; + struct sm6_index *index; if (!dxil_record_validate_operand_min_count(record, 5, sm6) || !(type = sm6_parser_get_type(sm6, record->operands[1])) @@ -7222,9 +7380,13 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record return; } - sm6_register_from_value(®, src); + *dst = *src; + index = sm6_get_value_index(sm6, dst); - if (reg.idx_count > 1) + if (!index) + return; + + if (index->index) { WARN("Unsupported stacked GEP.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, @@ -7232,8 +7394,6 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record return; } - is_in_bounds = record->operands[0]; - if ((pointee_type = src->type->u.pointer.type) != type) { WARN("Type mismatch, type %u width %u vs type %u width %u.\n", type->class, @@ -7247,7 +7407,7 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record return; /* The first index is always zero, to form a simple pointer dereference. */ - if (sm6_value_get_constant_uint(elem_value)) + if (sm6_value_get_constant_uint(elem_value, sm6)) { WARN("Expected constant zero.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, @@ -7267,7 +7427,7 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record return; /* If indexing is dynamic, just get the type at offset zero. */ - elem_idx = sm6_value_is_constant(elem_value) ? sm6_value_get_constant_uint(elem_value) : 0; + elem_idx = sm6_value_is_constant(elem_value) ? sm6_value_get_constant_uint(elem_value, sm6) : 0; type = sm6_type_get_element_type_at_index(pointee_type, elem_idx); if (!type) { @@ -7293,13 +7453,8 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record return; } - reg.idx[1].offset = 0; - register_index_address_init(®.idx[1], elem_value, sm6); - reg.idx[1].is_in_bounds = is_in_bounds; - reg.idx_count = 2; - - dst->reg = reg; - dst->structure_stride = src->structure_stride; + index->index = elem_value; + index->is_in_bounds = record->operands[0]; ins->opcode = VKD3DSIH_NOP; } @@ -7348,7 +7503,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor if (record->operands[i]) WARN("Ignoring volatile modifier.\n"); - sm6_register_from_value(®, ptr); + sm6_register_from_value(®, ptr, sm6); if (ptr->structure_stride) { @@ -7363,7 +7518,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor src_param_make_constant_uint(&src_params[0], reg.idx[1].offset); /* Struct offset is always zero as there is no struct, just an array. */ src_param_make_constant_uint(&src_params[1], 0); - src_param_init_from_value(&src_params[2], ptr); + src_param_init_from_value(&src_params[2], ptr, sm6); src_params[2].reg.alignment = alignment; /* The offset is already in src_params[0]. */ src_params[2].reg.idx_count = 1; @@ -7377,7 +7532,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor return; if (operand_count > 1) src_param_make_constant_uint(&src_params[0], 0); - src_param_init_from_value(&src_params[operand_count - 1], ptr); + src_param_init_from_value(&src_params[operand_count - 1], ptr, sm6); src_params[operand_count - 1].reg.alignment = alignment; } @@ -7425,7 +7580,6 @@ static void sm6_parser_emit_phi(struct sm6_parser *sm6, const struct dxil_record if (!(phi = sm6_block_phi_require_space(code_block, sm6))) return; - sm6_register_from_value(&phi->reg, dst); phi->incoming_count = record->operand_count / 2u; if (!vkd3d_array_reserve((void **)&phi->incoming, &phi->incoming_capacity, phi->incoming_count, @@ -7536,7 +7690,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco if (record->operands[i]) WARN("Ignoring volatile modifier.\n"); - sm6_register_from_value(®, ptr); + sm6_register_from_value(®, ptr, sm6); if (ptr->structure_stride) { @@ -7551,7 +7705,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco src_param_make_constant_uint(&src_params[0], reg.idx[1].offset); /* Struct offset is always zero as there is no struct, just an array. */ src_param_make_constant_uint(&src_params[1], 0); - src_param_init_from_value(&src_params[2], src); + src_param_init_from_value(&src_params[2], src, sm6); } else { @@ -7562,7 +7716,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco return; if (operand_count > 1) src_param_make_constant_uint(&src_params[0], 0); - src_param_init_from_value(&src_params[operand_count - 1], src); + src_param_init_from_value(&src_params[operand_count - 1], src, sm6); } dst_param = instruction_dst_params_alloc(ins, 1, sm6); @@ -7612,7 +7766,7 @@ static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_rec return; } - sm6_register_from_value(&terminator->conditional_reg, src); + sm6_register_from_value(&terminator->conditional_reg, src, sm6); terminator->type = TERMINATOR_SWITCH; terminator->case_count = record->operand_count / 2u; @@ -7651,7 +7805,7 @@ static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_rec "A switch case value is not a constant."); } - terminator->cases[i / 2u].value = sm6_value_get_constant_uint64(src); + terminator->cases[i / 2u].value = sm6_value_get_constant_uint64(src, sm6); } ins->opcode = VKD3DSIH_NOP; @@ -7688,7 +7842,7 @@ static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_re if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) return; for (i = 0; i < 3; ++i) - src_param_init_from_value(&src_params[i], src[i]); + src_param_init_from_value(&src_params[i], src[i], sm6); instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -7714,7 +7868,7 @@ static bool sm6_metadata_value_is_zero_or_undef(const struct sm6_metadata_value && (sm6_value_is_undef(m->u.value) || sm6_value_is_constant_zero(m->u.value)); } -static bool sm6_metadata_get_uint_value(const struct sm6_parser *sm6, +static bool sm6_metadata_get_uint_value(struct sm6_parser *sm6, const struct sm6_metadata_value *m, unsigned int *u) { const struct sm6_value *value; @@ -7728,12 +7882,12 @@ static bool sm6_metadata_get_uint_value(const struct sm6_parser *sm6, if (!sm6_type_is_integer(value->type)) return false; - *u = sm6_value_get_constant_uint(value); + *u = sm6_value_get_constant_uint(value, sm6); return true; } -static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, +static bool sm6_metadata_get_uint64_value(struct sm6_parser *sm6, const struct sm6_metadata_value *m, uint64_t *u) { const struct sm6_value *value; @@ -7747,12 +7901,12 @@ static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, if (!sm6_type_is_integer(value->type)) return false; - *u = sm6_value_get_constant_uint(value); + *u = sm6_value_get_constant_uint(value, sm6); return true; } -static bool sm6_metadata_get_float_value(const struct sm6_parser *sm6, +static bool sm6_metadata_get_float_value(struct sm6_parser *sm6, const struct sm6_metadata_value *m, float *f) { const struct sm6_value *value; @@ -7766,7 +7920,7 @@ static bool sm6_metadata_get_float_value(const struct sm6_parser *sm6, if (!sm6_type_is_floating_point(value->type)) return false; - *f = register_get_float_value(&value->reg); + *f = sm6_value_get_constant_float(value, sm6); return true; } @@ -7951,7 +8105,7 @@ static void metadata_attachment_record_apply(const struct dxil_record *record, e } else if (metadata_node_get_unary_uint(node, &operand, sm6)) { - dst->reg.non_uniform = !!operand; + dst->non_uniform = !!operand; } } else @@ -8023,13 +8177,13 @@ static enum vkd3d_result sm6_function_resolve_phi_incomings(const struct sm6_fun "A PHI incoming value is not a constant or SSA register."); return VKD3D_ERROR_INVALID_SHADER; } - if (src->reg.data_type != phi->reg.data_type) + if (src->type != phi->value.type) { WARN("Type mismatch.\n"); vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, "The type of a phi incoming value does not match the result type."); } - sm6_register_from_value(&phi->incoming[j].reg, src); + sm6_register_from_value(&phi->incoming[j].reg, src, sm6); } } } @@ -8118,7 +8272,6 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const dst = sm6_parser_get_current_value(sm6); fwd_type = dst->type; dst->type = NULL; - dst->value_type = VALUE_TYPE_REG; dst->is_back_ref = true; is_terminator = false; @@ -8196,6 +8349,10 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const if (record->attachment) metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); + /* This is specific for PHI nodes, but must happen after attachments have been applied. */ + if (record->code == FUNC_CODE_INST_PHI) + code_block->phi[code_block->phi_count - 1].value = *dst; + if (is_terminator) { ++block_idx; @@ -8342,7 +8499,7 @@ static void sm6_block_emit_phi(const struct sm6_block *block, struct sm6_parser } dst_param_init(dst_param); - dst_param->reg = src_phi->reg; + sm6_register_from_value(&dst_param->reg, &src_phi->value, sm6); } } diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c index a4f1a371299..f7b2e3d7d13 100644 --- a/libs/vkd3d/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d/libs/vkd3d-shader/fx.c @@ -54,6 +54,19 @@ enum state_property_component_type FX_COMPONENT_TYPE_COUNT, }; +enum fxlvm_constants +{ + FX_FXLC_COMP_COUNT_MASK = 0xffff, + FX_FXLC_OPCODE_MASK = 0x7ff, + FX_FXLC_OPCODE_SHIFT = 20, + FX_FXLC_IS_SCALAR_MASK = 0x80000000, + + FX_FXLC_REG_LITERAL = 1, + FX_FXLC_REG_CB = 2, + FX_FXLC_REG_OUTPUT = 4, + FX_FXLC_REG_TEMP = 7, +}; + struct rhs_named_value { const char *name; @@ -289,15 +302,6 @@ static void set_status(struct fx_write_context *fx, int status) fx->status = status; } -static void fx_print_string(struct vkd3d_string_buffer *buffer, const char *prefix, - const char *s, size_t len) -{ - if (len) - --len; /* Trim terminating null. */ - vkd3d_string_buffer_printf(buffer, "%s", prefix); - vkd3d_string_buffer_print_string_escaped(buffer, s, len); -} - static uint32_t write_string(const char *string, struct fx_write_context *fx) { return fx->ops->write_string(string, fx); @@ -369,18 +373,23 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context name = get_fx_4_type_name(element_type); modifiers = element_type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK; - LIST_FOR_EACH_ENTRY(type_entry, &fx->types, struct type_entry, entry) + /* We don't try to reuse nameless types; they will get the same + * "" name, but are not available for the type cache. */ + if (name) { - if (strcmp(type_entry->name, name)) - continue; + LIST_FOR_EACH_ENTRY(type_entry, &fx->types, struct type_entry, entry) + { + if (strcmp(type_entry->name, name)) + continue; - if (type_entry->elements_count != elements_count) - continue; + if (type_entry->elements_count != elements_count) + continue; - if (type_entry->modifiers != modifiers) - continue; + if (type_entry->modifiers != modifiers) + continue; - return type_entry->offset; + return type_entry->offset; + } } if (!(type_entry = hlsl_alloc(fx->ctx, sizeof(*type_entry)))) @@ -391,7 +400,8 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context type_entry->elements_count = elements_count; type_entry->modifiers = modifiers; - list_add_tail(&fx->types, &type_entry->entry); + if (name) + list_add_tail(&fx->types, &type_entry->entry); return type_entry->offset; } @@ -764,7 +774,7 @@ static const struct rhs_named_value fx_2_filter_values[] = { NULL } }; -static const struct fx_2_state +struct fx_2_state { const char *name; enum hlsl_type_class class; @@ -773,8 +783,9 @@ static const struct fx_2_state uint32_t array_size; uint32_t id; const struct rhs_named_value *values; -} -fx_2_states[] = +}; + +static const struct fx_2_state fx_2_pass_states[] = { { "ZEnable", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 0, fx_2_zenable_values }, { "FillMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 1, fx_2_fillmode_values }, @@ -867,7 +878,7 @@ fx_2_states[] = { "AdaptiveTess_Y", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 84 }, { "AdaptiveTess_Z", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 85 }, { "AdaptiveTess_W", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 86 }, - { "EnableAdaptiveTesselation", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 87 }, + { "EnableAdaptiveTessellation",HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 87 }, { "TwoSidedStencilMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 88 }, { "StencilFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 89, fx_2_stencilcaps_values }, { "StencilZFail", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 90, fx_2_stencilcaps_values }, @@ -898,17 +909,17 @@ fx_2_states[] = { "BumpEnvMat01", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 113 }, { "BumpEnvMat10", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 114 }, { "BumpEnvMat11", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 115 }, - { "TextCoordIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 116 }, + { "TexCoordIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 116 }, { "BumpEnvLScale", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 117 }, { "BumpEnvLOffset", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 118 }, { "TextureTransformFlags", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 119, fx_2_texturetransform_values }, { "Constant", HLSL_CLASS_SCALAR, FX_UINT, 1, 8, 120 }, - { "NPatchMode", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 121 }, + { "PatchSegments", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 121 }, { "FVF", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 122 }, { "ProjectionTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 123 }, { "ViewTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 124 }, - { "WorldTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 1, 125 }, + { "WorldTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 256, 125 }, { "TextureTransform", HLSL_CLASS_MATRIX, FX_FLOAT, 4, 8, 126 }, { "MaterialAmbient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 127 }, @@ -917,42 +928,59 @@ fx_2_states[] = { "MaterialEmissive", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 130 }, { "MaterialPower", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 131 }, - { "LightType", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 132, fx_2_lighttype_values }, - { "LightDiffuse", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 133 }, - { "LightSpecular", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 134 }, - { "LightAmbient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, 1, 135 }, - { "LightPosition", HLSL_CLASS_VECTOR, FX_FLOAT, 3, 1, 136 }, - { "LightDirection", HLSL_CLASS_VECTOR, FX_FLOAT, 3, 1, 137 }, - { "LightRange", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 138 }, - { "LightFalloff", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 139 }, - { "LightAttenuation0", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 140 }, - { "LightAttenuation1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 141 }, - { "LightAttenuation2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 142 }, - { "LightTheta", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 143 }, - { "LightPhi", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 1, 144 }, - { "LightEnable", HLSL_CLASS_SCALAR, FX_FLOAT, 1, 8, 145 }, + { "LightType", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 132, fx_2_lighttype_values }, + { "LightDiffuse", HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 133 }, + { "LightSpecular", HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 134 }, + { "LightAmbient", HLSL_CLASS_VECTOR, FX_FLOAT, 4, ~0u, 135 }, + { "LightPosition", HLSL_CLASS_VECTOR, FX_FLOAT, 3, ~0u, 136 }, + { "LightDirection", HLSL_CLASS_VECTOR, FX_FLOAT, 3, ~0u, 137 }, + { "LightRange", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 138 }, + { "LightFalloff", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 139 }, + { "LightAttenuation0", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 140 }, + { "LightAttenuation1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 141 }, + { "LightAttenuation2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 142 }, + { "LightTheta", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 143 }, + { "LightPhi", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 144 }, + { "LightEnable", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 145 }, { "VertexShader", HLSL_CLASS_SCALAR, FX_VERTEXSHADER, 1, 1, 146 }, { "PixelShader", HLSL_CLASS_SCALAR, FX_PIXELSHADER, 1, 1, 147 }, - { "VertexShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 148 }, - { "VertexShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u-1, 149 }, - { "VertexShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u-1, 150 }, - { "VertexShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 151 }, - { "VertexShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 152 }, - { "VertexShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 153 }, - { "VertexShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 154 }, - { "VertexShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 155 }, - - { "PixelShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 156 }, - { "PixelShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u-1, 157 }, - { "PixelShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u-1, 158 }, - { "PixelShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 159 }, - { "PixelShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 160 }, - { "PixelShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 161 }, - { "PixelShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 162 }, - { "PixelShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 163 }, + { "VertexShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 148 }, + { "VertexShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u, 149 }, + { "VertexShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 150 }, + { "VertexShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 151 }, + { "VertexShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 152 }, + { "VertexShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 153 }, + { "VertexShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 154 }, + { "VertexShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 155 }, + + { "PixelShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 156 }, + { "PixelShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u, 157 }, + { "PixelShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u, 158 }, + { "PixelShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 159 }, + { "PixelShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 160 }, + { "PixelShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 161 }, + { "PixelShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 162 }, + { "PixelShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u, 163 }, + + { "Texture", HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 261, 164 }, + { "AddressU", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 165, fx_2_address_values }, + { "AddressV", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 166, fx_2_address_values }, + { "AddressW", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 167, fx_2_address_values }, + { "BorderColor", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 168 }, + { "MagFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 169, fx_2_filter_values }, + { "MinFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 170, fx_2_filter_values }, + { "MipFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 171, fx_2_filter_values }, + { "MipMapLodBias", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 172 }, + { "MaxMipLevel", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 173 }, + { "MaxAnisotropy", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 174 }, + { "SRGBTexture", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 175 }, + { "ElementIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 261, 176 }, +}; +static const struct fx_2_state fx_2_sampler_states[] = +{ { "Texture", HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 1, 164 }, { "AddressU", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 165, fx_2_address_values }, { "AddressV", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 166, fx_2_address_values }, @@ -964,7 +992,7 @@ fx_2_states[] = { "MipMapLodBias", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 172 }, { "MaxMipLevel", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 173 }, { "MaxAnisotropy", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 174 }, - { "SRBTexture", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 175 }, + { "SRGBTexture", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 175 }, { "ElementIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 176 }, }; @@ -988,16 +1016,6 @@ static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx fx->shader_count++; } -static uint32_t get_fx_4_type_size(const struct hlsl_type *type) -{ - uint32_t elements_count; - - elements_count = hlsl_get_multiarray_size(type); - type = hlsl_get_multiarray_element_type(type); - - return type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float) * elements_count; -} - enum fx_4_type_constants { /* Numeric types encoding */ @@ -1015,6 +1033,9 @@ enum fx_4_type_constants FX_4_NUMERIC_COLUMNS_SHIFT = 11, FX_4_NUMERIC_COLUMN_MAJOR_MASK = 0x4000, + /* Variable flags */ + FX_4_HAS_EXPLICIT_BIND_POINT = 0x4, + /* Object types */ FX_4_OBJECT_TYPE_STRING = 0x1, FX_4_OBJECT_TYPE_BLEND_STATE = 0x2, @@ -1071,17 +1092,6 @@ enum fx_4_type_constants FX_4_ASSIGNMENT_VALUE_EXPRESSION = 0x6, FX_4_ASSIGNMENT_INLINE_SHADER = 0x7, FX_5_ASSIGNMENT_INLINE_SHADER = 0x8, - - /* FXLVM constants */ - FX_4_FXLC_COMP_COUNT_MASK = 0xffff, - FX_4_FXLC_OPCODE_MASK = 0x7ff, - FX_4_FXLC_OPCODE_SHIFT = 20, - FX_4_FXLC_IS_SCALAR_MASK = 0x80000000, - - FX_4_FXLC_REG_LITERAL = 1, - FX_4_FXLC_REG_CB = 2, - FX_4_FXLC_REG_OUTPUT = 4, - FX_4_FXLC_REG_TEMP = 7, }; static const uint32_t fx_4_numeric_base_types[] = @@ -1238,7 +1248,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co name = get_fx_4_type_name(element_type); - name_offset = write_string(name, fx); + name_offset = write_string(name ? name : "", fx); if (element_type->class == HLSL_CLASS_STRUCT) { if (!(field_offsets = hlsl_calloc(ctx, element_type->e.record.field_count, sizeof(*field_offsets)))) @@ -1541,12 +1551,33 @@ static uint32_t get_fx_2_type_class(const struct hlsl_type *type) return hlsl_sm1_class(type); } -static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *name, - const struct hlsl_semantic *semantic, bool is_combined_sampler, struct fx_write_context *fx) +struct fx_2_write_type_context { - struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; - uint32_t semantic_offset, offset, elements_count = 0, name_offset; - size_t i; + uint32_t *names; + uint32_t *semantics; + uint32_t count; + + uint32_t offset; + + bool is_combined_sampler; + struct fx_write_context *fx; +}; + +static void count_type_iter(const struct hlsl_type *type, const char *name, + const struct hlsl_semantic *semantic, void *context) +{ + struct fx_2_write_type_context *ctx = context; + + ++ctx->count; +} + +static void write_fx_2_type_iter(const struct hlsl_type *type, const char *name, + const struct hlsl_semantic *semantic, void *context) +{ + struct fx_2_write_type_context *ctx = context; + struct fx_write_context *fx = ctx->fx; + struct vkd3d_bytecode_buffer *buffer; + uint32_t offset, elements_count = 0; /* Resolve arrays to element type and number of elements. */ if (type->class == HLSL_CLASS_ARRAY) @@ -1555,13 +1586,11 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n type = hlsl_get_multiarray_element_type(type); } - name_offset = write_string(name, fx); - semantic_offset = semantic->raw_name ? write_string(semantic->raw_name, fx) : 0; - - offset = put_u32(buffer, hlsl_sm1_base_type(type, is_combined_sampler)); + buffer = &fx->unstructured; + offset = put_u32(buffer, hlsl_sm1_base_type(type, ctx->is_combined_sampler)); put_u32(buffer, get_fx_2_type_class(type)); - put_u32(buffer, name_offset); - put_u32(buffer, semantic_offset); + *ctx->names++ = put_u32(buffer, 0); + *ctx->semantics++ = put_u32(buffer, 0); put_u32(buffer, elements_count); switch (type->class) @@ -1586,19 +1615,68 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n ; } + /* Save the offset of the top level type. */ + if (!ctx->offset) + ctx->offset = offset; +} + +static void write_fx_2_type_strings_iter(const struct hlsl_type *type, const char *name, + const struct hlsl_semantic *semantic, void *context) +{ + struct fx_2_write_type_context *ctx = context; + struct fx_write_context *fx = ctx->fx; + struct vkd3d_bytecode_buffer *buffer; + + buffer = &fx->unstructured; + set_u32(buffer, *ctx->names++, write_string(name, fx)); + set_u32(buffer, *ctx->semantics++, semantic->raw_name ? write_string(semantic->raw_name, fx) : 0); +} + +static void foreach_type(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic, + void (*iter_func)(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic, void *context), + void *context) +{ + iter_func(type, name, semantic, context); + + type = hlsl_get_multiarray_element_type(type); if (type->class == HLSL_CLASS_STRUCT) { - for (i = 0; i < type->e.record.field_count; ++i) + for (size_t i = 0; i < type->e.record.field_count; ++i) { const struct hlsl_struct_field *field = &type->e.record.fields[i]; - - /* Validated in check_invalid_object_fields(). */ - VKD3D_ASSERT(hlsl_is_numeric_type(field->type)); - write_fx_2_parameter(field->type, field->name, &field->semantic, false, fx); + foreach_type(field->type, field->name, &field->semantic, iter_func, context); } } +} - return offset; +static uint32_t write_fx_2_parameter(const struct hlsl_ir_var *var, struct fx_write_context *fx) +{ + struct fx_2_write_type_context ctx = { .fx = fx, .is_combined_sampler = var->is_combined_sampler }; + uint32_t *offsets; + + /* Parameter type information has to be stored in a contiguous segment, so + * that any structure fields come right after each other. To achieve that + * the variable length string data is written after the type data. */ + + /* Calculate the number of string entries needed for this type. */ + foreach_type(var->data_type, var->name, &var->semantic, count_type_iter, &ctx); + + if (!(offsets = calloc(ctx.count, 2 * sizeof(*offsets)))) + return 0; + + /* Writing type information also sets string offsets. */ + ctx.names = offsets; + ctx.semantics = &offsets[ctx.count]; + foreach_type(var->data_type, var->name, &var->semantic, write_fx_2_type_iter, &ctx); + + /* Now the final pass to write the string data. */ + ctx.names = offsets; + ctx.semantics = &offsets[ctx.count]; + foreach_type(var->data_type, var->name, &var->semantic, write_fx_2_type_strings_iter, &ctx); + + free(offsets); + + return ctx.offset; } static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) @@ -1623,6 +1701,15 @@ static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_contex set_u32(buffer, pass_count_offset, count); } +/* Effects represent bool values as 1/0, as opposed to ~0u/0 as used by + * Direct3D shader model 4+. */ +static uint32_t get_fx_default_numeric_value(const struct hlsl_type *type, uint32_t value) +{ + if (type->e.numeric.type == HLSL_TYPE_BOOL) + return !!value; + return value; +} + static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hlsl_default_value *value, struct fx_write_context *fx) { @@ -1656,7 +1743,7 @@ static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hl for (j = 0; j < comp_count; ++j) { - put_u32(buffer, value->number.u); + put_u32(buffer, get_fx_default_numeric_value(type, value->number.u)); value++; } break; @@ -1673,8 +1760,8 @@ static uint32_t write_fx_2_default_value(struct hlsl_type *value_type, struct hl for (j = 0; j < type->e.record.field_count; ++j) { - write_fx_2_default_value(fields[i].type, value, fx); - value += hlsl_type_component_count(fields[i].type); + write_fx_2_default_value(fields[j].type, value, fx); + value += hlsl_type_component_count(fields[j].type); } break; } @@ -1861,7 +1948,7 @@ static void write_fx_2_parameters(struct fx_write_context *fx) if (!is_type_supported_fx_2(ctx, var->data_type, &var->loc)) continue; - desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, var->is_combined_sampler, fx); + desc_offset = write_fx_2_parameter(var, fx); value_offset = write_fx_2_initial_value(var, fx); flags = 0; @@ -1884,7 +1971,7 @@ static void write_fx_2_annotation(struct hlsl_ir_var *var, struct fx_write_conte struct vkd3d_bytecode_buffer *buffer = &fx->structured; uint32_t desc_offset, value_offset; - desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, var->is_combined_sampler, fx); + desc_offset = write_fx_2_parameter(var, fx); value_offset = write_fx_2_initial_value(var, fx); put_u32(buffer, desc_offset); @@ -2001,7 +2088,7 @@ static uint32_t write_fx_4_default_value(struct hlsl_type *value_type, struct hl for (j = 0; j < comp_count; ++j) { - put_u32_unaligned(buffer, value->number.u); + put_u32_unaligned(buffer, get_fx_default_numeric_value(type, value->number.u)); value++; } break; @@ -2018,8 +2105,8 @@ static uint32_t write_fx_4_default_value(struct hlsl_type *value_type, struct hl for (j = 0; j < type->e.record.field_count; ++j) { - write_fx_4_default_value(fields[i].type, value, fx); - value += hlsl_type_component_count(fields[i].type); + write_fx_4_default_value(fields[j].type, value, fx); + value += hlsl_type_component_count(fields[j].type); } break; } @@ -2057,13 +2144,9 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, st struct vkd3d_bytecode_buffer *buffer = &fx->structured; uint32_t name_offset, type_offset, value_offset; uint32_t semantic_offset, flags = 0; - enum fx_4_numeric_variable_flags - { - HAS_EXPLICIT_BIND_POINT = 0x4, - }; if (var->has_explicit_bind_point) - flags |= HAS_EXPLICIT_BIND_POINT; + flags |= FX_4_HAS_EXPLICIT_BIND_POINT; type_offset = write_type(var->data_type, fx); name_offset = write_string(var->name, fx); @@ -3212,6 +3295,8 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx size = 0; LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { + uint32_t unpacked_size; + if (!is_numeric_fx_4_type(var->data_type)) continue; @@ -3219,7 +3304,9 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx continue; write_fx_4_numeric_variable(var, shared, fx); - size += get_fx_4_type_size(var->data_type); + + unpacked_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float); + size = max(size, unpacked_size + var->buffer_offset * 4); ++count; } @@ -3572,20 +3659,43 @@ static void parse_fx_print_indent(struct fx_parser *parser) vkd3d_string_buffer_printf(&parser->buffer, "%*s", 4 * parser->indent, ""); } -static const char *fx_2_get_string(struct fx_parser *parser, uint32_t offset, uint32_t *size) +static void fx_2_print_string_literal(struct fx_parser *parser, const char *prefix, + const char *s, uint32_t max_len, const char *suffix) { - const char *ptr; + uint32_t len; + + if (s) + len = strnlen(s, max_len); + if (!s || len == max_len) + { + fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, "Failed to parse a string entry."); + return; + } + + vkd3d_string_buffer_printf(&parser->buffer, "%s", prefix); + vkd3d_string_buffer_print_string_escaped(&parser->buffer, s, len); + vkd3d_string_buffer_printf(&parser->buffer, "%s", suffix); +} - fx_parser_read_unstructured(parser, size, offset, sizeof(*size)); - ptr = fx_parser_get_unstructured_ptr(parser, offset + 4, *size); +static void fx_2_parse_string_literal(struct fx_parser *parser, uint32_t offset, + bool unstructured, const char *prefix, const char *suffix) +{ + uint32_t max_len; + const char *s; - if (!ptr) + if (unstructured) { - parser->failed = true; - return ""; + fx_parser_read_unstructured(parser, &max_len, offset, sizeof(max_len)); + s = fx_parser_get_unstructured_ptr(parser, offset + 4, max_len); + } + else + { + max_len = fx_parser_read_u32(parser); + s = fx_parser_get_ptr(parser, max_len); + fx_parser_skip(parser, align(max_len, 4)); } - return ptr; + fx_2_print_string_literal(parser, prefix, s, max_len, suffix); } static unsigned int fx_get_fx_2_type_size(struct fx_parser *parser, uint32_t *offset) @@ -3742,15 +3852,12 @@ static void fx_parse_fx_2_parameter(struct fx_parser *parser, uint32_t offset) uint32_t semantic; uint32_t element_count; } var; - const char *name; - uint32_t size; fx_parser_read_unstructured(parser, &var, offset, sizeof(var)); fx_parse_fx_2_type(parser, offset); - name = fx_2_get_string(parser, var.name, &size); - fx_print_string(&parser->buffer, " ", name, size); + fx_2_parse_string_literal(parser, var.name, true, " ", ""); if (var.element_count) vkd3d_string_buffer_printf(&parser->buffer, "[%u]", var.element_count); } @@ -3764,7 +3871,8 @@ static bool is_fx_2_sampler(uint32_t type) || type == D3DXPT_SAMPLERCUBE; } -static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_assignment *entry); +static void fx_parse_fx_2_assignment(struct fx_parser *parser, enum hlsl_type_class container, + const struct fx_assignment *entry); static void parse_fx_2_sampler(struct fx_parser *parser, uint32_t element_count, uint32_t offset) @@ -3789,7 +3897,7 @@ static void parse_fx_2_sampler(struct fx_parser *parser, uint32_t element_count, fx_parser_read_unstructured(parser, &entry, offset, sizeof(entry)); parse_fx_print_indent(parser); - fx_parse_fx_2_assignment(parser, &entry); + fx_parse_fx_2_assignment(parser, HLSL_CLASS_SAMPLER, &entry); } parse_fx_end_indent(parser); parse_fx_print_indent(parser); @@ -3867,15 +3975,29 @@ static void fx_parse_fx_2_annotations(struct fx_parser *parser, uint32_t count) vkd3d_string_buffer_printf(&parser->buffer, ">"); } -static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_assignment *entry) +static const struct fx_2_state *fx_2_get_state_by_id(enum hlsl_type_class container, uint32_t id) +{ + const struct fx_2_state *table; + unsigned int count; + + count = container == HLSL_CLASS_PASS ? ARRAY_SIZE(fx_2_pass_states) : ARRAY_SIZE(fx_2_sampler_states); + table = container == HLSL_CLASS_PASS ? fx_2_pass_states : fx_2_sampler_states; + + /* State identifiers are sequential, no gaps */ + if (id >= table[0].id && id <= table[count - 1].id) + return &table[id - table[0].id]; + + return NULL; +} + +static void fx_parse_fx_2_assignment(struct fx_parser *parser, enum hlsl_type_class container, + const struct fx_assignment *entry) { const struct rhs_named_value *named_value = NULL; - const struct fx_2_state *state = NULL; + const struct fx_2_state *state; - if (entry->id <= ARRAY_SIZE(fx_2_states)) + if ((state = fx_2_get_state_by_id(container, entry->id))) { - state = &fx_2_states[entry->id]; - vkd3d_string_buffer_printf(&parser->buffer, "%s", state->name); if (state->array_size > 1) vkd3d_string_buffer_printf(&parser->buffer, "[%u]", entry->lhs_index); @@ -3886,7 +4008,7 @@ static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_a } vkd3d_string_buffer_printf(&parser->buffer, " = "); - if (state && state->type == FX_UINT) + if (state && state->type == FX_UINT && state->values) { const struct rhs_named_value *ptr = state->values; uint32_t value; @@ -3910,13 +4032,14 @@ static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_a } else if (state) { - if (state->type == FX_UINT || state->type == FX_FLOAT) + if (state->type == FX_UINT || state->type == FX_FLOAT || state->type == FX_BOOL) { - uint32_t offset = entry->type; + uint32_t offset = entry->type, base_type; unsigned int size; size = fx_get_fx_2_type_size(parser, &offset); - parse_fx_2_numeric_value(parser, entry->value, size, entry->type); + fx_parser_read_unstructured(parser, &base_type, entry->type, sizeof(base_type)); + parse_fx_2_numeric_value(parser, entry->value, size, base_type); } else if (state->type == FX_VERTEXSHADER || state->type == FX_PIXELSHADER) { @@ -3951,18 +4074,14 @@ static void fx_parse_fx_2_technique(struct fx_parser *parser) uint32_t annotation_count; uint32_t assignment_count; } pass; - const char *name; - uint32_t size; if (parser->failed) return; fx_parser_read_u32s(parser, &technique, sizeof(technique)); - name = fx_2_get_string(parser, technique.name, &size); - parse_fx_print_indent(parser); - fx_print_string(&parser->buffer, "technique ", name, size); + fx_2_parse_string_literal(parser, technique.name, true, "technique ", ""); fx_parse_fx_2_annotations(parser, technique.annotation_count); vkd3d_string_buffer_printf(&parser->buffer, "\n"); @@ -3973,10 +4092,9 @@ static void fx_parse_fx_2_technique(struct fx_parser *parser) for (uint32_t i = 0; i < technique.pass_count; ++i) { fx_parser_read_u32s(parser, &pass, sizeof(pass)); - name = fx_2_get_string(parser, pass.name, &size); parse_fx_print_indent(parser); - fx_print_string(&parser->buffer, "pass ", name, size); + fx_2_parse_string_literal(parser, pass.name, true, "pass ", ""); fx_parse_fx_2_annotations(parser, pass.annotation_count); vkd3d_string_buffer_printf(&parser->buffer, "\n"); @@ -3990,7 +4108,7 @@ static void fx_parse_fx_2_technique(struct fx_parser *parser) parse_fx_print_indent(parser); fx_parser_read_u32s(parser, &entry, sizeof(entry)); - fx_parse_fx_2_assignment(parser, &entry); + fx_parse_fx_2_assignment(parser, HLSL_CLASS_PASS, &entry); } parse_fx_end_indent(parser); @@ -4112,8 +4230,7 @@ static void fx_parse_fx_2_data_blob(struct fx_parser *parser) { parse_fx_start_indent(parser); parse_fx_print_indent(parser); - fx_print_string(&parser->buffer, "\"", (const char *)data, size); - vkd3d_string_buffer_printf(&parser->buffer, "\""); + fx_2_print_string_literal(parser, "\"", (const char *)data, size, "\""); parse_fx_end_indent(parser); } else if (type == D3DXPT_PIXELSHADER || type == D3DXPT_VERTEXSHADER) @@ -4153,20 +4270,18 @@ static void fx_dump_blob(struct fx_parser *parser, const void *blob, uint32_t si } } -static void fx_parse_fx_2_array_selector(struct fx_parser *parser, uint32_t size) +static void fx_2_parse_fxlvm_expression(struct fx_parser *parser, const uint32_t *blob, uint32_t size); + +static void fx_parse_fx_2_array_selector(struct fx_parser *parser) { - const uint8_t *end = parser->ptr + size; - uint32_t name_size, blob_size = 0; + uint32_t size, blob_size = 0; const void *blob = NULL; - const char *name; + const uint8_t *end; - name_size = fx_parser_read_u32(parser); - name = fx_parser_get_ptr(parser, name_size); - fx_parser_skip(parser, name_size); + size = fx_parser_read_u32(parser); + end = parser->ptr + size; - if (!name || (uint8_t *)name >= end) - fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, - "Malformed name entry in the array selector."); + fx_2_parse_string_literal(parser, 0, false, "array \"", "\"\n"); if (parser->ptr <= end) { @@ -4180,16 +4295,11 @@ static void fx_parse_fx_2_array_selector(struct fx_parser *parser, uint32_t size "Malformed blob entry in the array selector."); } - if (name) - { - fx_print_string(&parser->buffer, "array \"", name, name_size); - vkd3d_string_buffer_printf(&parser->buffer, "\"\n"); - } if (blob) { parse_fx_print_indent(parser); vkd3d_string_buffer_printf(&parser->buffer, "selector blob size %u\n", blob_size); - fx_dump_blob(parser, blob, blob_size); + fx_2_parse_fxlvm_expression(parser, blob, blob_size); } } @@ -4219,23 +4329,19 @@ static void fx_parse_fx_2_complex_state(struct fx_parser *parser) state.technique, state.index, state.state); } - size = fx_parser_read_u32(parser); - parse_fx_print_indent(parser); if (state.assignment_type == FX_2_ASSIGNMENT_PARAMETER) { - data = fx_parser_get_ptr(parser, size); - fx_print_string(&parser->buffer, "parameter \"", data, size); - vkd3d_string_buffer_printf(&parser->buffer, "\"\n"); - fx_parser_skip(parser, align(size, 4)); + fx_2_parse_string_literal(parser, 0, false, "parameter \"", "\"\n"); } else if (state.assignment_type == FX_2_ASSIGNMENT_ARRAY_SELECTOR) { - fx_parse_fx_2_array_selector(parser, size); + fx_parse_fx_2_array_selector(parser); } else { + size = fx_parser_read_u32(parser); vkd3d_string_buffer_printf(&parser->buffer, "blob size %u\n", size); data = fx_parser_get_ptr(parser, size); fx_dump_blob(parser, data, size); @@ -4457,6 +4563,11 @@ static void fx_parse_fx_4_numeric_variables(struct fx_parser *parser, uint32_t c semantic = fx_4_get_string(parser, var.semantic); vkd3d_string_buffer_printf(&parser->buffer, " : %s", semantic); } + if (var.flags & FX_4_HAS_EXPLICIT_BIND_POINT) + { + vkd3d_string_buffer_printf(&parser->buffer, " : packoffset(c%u.%c)", + var.offset / 16, "xyzw"[(var.offset % 16) / 4]); + } fx_parse_fx_4_annotations(parser); if (var.value) @@ -4492,6 +4603,8 @@ static void fx_parse_buffers(struct fx_parser *parser) name = fx_4_get_string(parser, buffer.name); vkd3d_string_buffer_printf(&parser->buffer, "cbuffer %s", name); + if (buffer.bind_point != ~0u) + vkd3d_string_buffer_printf(&parser->buffer, " : register(b%u)", buffer.bind_point); fx_parse_fx_4_annotations(parser); vkd3d_string_buffer_printf(&parser->buffer, "\n{\n"); @@ -4609,7 +4722,7 @@ static const struct uint32_t opcode; const char *name; } -fx_4_fxlc_opcodes[] = +fxlc_opcodes[] = { { 0x100, "mov" }, { 0x101, "neg" }, @@ -4634,6 +4747,8 @@ fx_4_fxlc_opcodes[] = { 0x13a, "ceil" }, { 0x200, "min" }, { 0x201, "max" }, + { 0x202, "lt" }, + { 0x203, "ge" }, { 0x204, "add" }, { 0x205, "mul" }, { 0x206, "atan2" }, @@ -4662,14 +4777,14 @@ fx_4_fxlc_opcodes[] = { 0x70e, "d3ds_dotswiz" }, }; -static const char *fx_4_get_fxlc_opcode_name(uint32_t opcode) +static const char *get_fxlc_opcode_name(uint32_t opcode) { size_t i; - for (i = 0; i < ARRAY_SIZE(fx_4_fxlc_opcodes); ++i) + for (i = 0; i < ARRAY_SIZE(fxlc_opcodes); ++i) { - if (fx_4_fxlc_opcodes[i].opcode == opcode) - return fx_4_fxlc_opcodes[i].name; + if (fxlc_opcodes[i].opcode == opcode) + return fxlc_opcodes[i].name; } return ""; @@ -4693,10 +4808,29 @@ struct fx_4_ctab_entry uint32_t default_value; }; +struct fxlc_arg +{ + uint32_t reg_type; + uint32_t address; + bool indexed; + struct + { + uint32_t reg_type; + uint32_t address; + } index; +}; + struct fxlvm_code { - const float *cli4; - uint32_t cli4_count; + const uint32_t *ptr, *end; + bool failed; + + union + { + const float *_4; + const double *_8; + } cli; + uint32_t cli_count; const struct fx_4_ctab_entry *constants; uint32_t ctab_offset; @@ -4707,7 +4841,45 @@ struct fxlvm_code bool scalar; }; -static void fx_4_parse_print_swizzle(struct fx_parser *parser, const struct fxlvm_code *code, unsigned int addr) +static uint32_t fxlvm_read_u32(struct fxlvm_code *code) +{ + if (code->end == code->ptr) + { + code->failed = true; + return 0; + } + + return *code->ptr++; +} + +static const uint32_t *find_d3dbc_section(const uint32_t *ptr, uint32_t count, uint32_t tag, uint32_t *size) +{ + if (!count) + return NULL; + + /* Skip version tag */ + ptr++; + count--; + + while (count > 2 && (*ptr & 0xffff) == 0xfffe) + { + unsigned int section_size; + + section_size = (*ptr >> 16); + if (!section_size || section_size + 1 > count) + break; + if (*(ptr + 1) == tag) + { + *size = section_size; + return ptr + 2; + } + count -= section_size + 1; + ptr += section_size + 1; + } + return NULL; +} + +static void fx_parse_print_swizzle(struct fx_parser *parser, const struct fxlvm_code *code, unsigned int addr) { unsigned int comp_count = code->scalar ? 1 : code->comp_count; static const char comp[] = "xyzw"; @@ -4716,44 +4888,76 @@ static void fx_4_parse_print_swizzle(struct fx_parser *parser, const struct fxlv vkd3d_string_buffer_printf(&parser->buffer, ".%.*s", comp_count, &comp[addr % 4]); } -static void fx_4_parse_fxlc_constant_argument(struct fx_parser *parser, - const struct fx_4_fxlc_argument *arg, const struct fxlvm_code *code) +static void fx_parse_fxlc_constant_argument(struct fx_parser *parser, + const struct fxlc_arg *arg, const struct fxlvm_code *code) { - uint32_t i, offset, register_index = arg->address / 4; /* Address counts in components. */ + uint32_t register_index = arg->address / 4; /* Address counts in components. */ - for (i = 0; i < code->ctab_count; ++i) + if (code->ctab_count) { - const struct fx_4_ctab_entry *c = &code->constants[i]; + uint32_t i, offset; - if (register_index < c->register_index || register_index - c->register_index >= c->register_count) - continue; + for (i = 0; i < code->ctab_count; ++i) + { + const struct fx_4_ctab_entry *c = &code->constants[i]; - vkd3d_string_buffer_printf(&parser->buffer, "%s", &code->ctab[c->name]); + if (register_index < c->register_index || register_index - c->register_index >= c->register_count) + continue; - /* Register offset within variable */ - offset = arg->address - c->register_index * 4; + vkd3d_string_buffer_printf(&parser->buffer, "%s", &code->ctab[c->name]); - if (offset / 4) - vkd3d_string_buffer_printf(&parser->buffer, "[%u]", offset / 4); - fx_4_parse_print_swizzle(parser, code, offset); - return; + /* Register offset within variable */ + offset = arg->address - c->register_index * 4; + + if (offset / 4) + vkd3d_string_buffer_printf(&parser->buffer, "[%u]", offset / 4); + fx_parse_print_swizzle(parser, code, offset); + return; + } + + vkd3d_string_buffer_printf(&parser->buffer, "(var-not-found)"); + } + else + { + vkd3d_string_buffer_printf(&parser->buffer, "c%u", register_index); + fx_parse_print_swizzle(parser, code, arg->address); + } +} + +static void fx_parse_fxlc_argument(struct fx_parser *parser, struct fxlc_arg *arg, struct fxlvm_code *code) +{ + uint32_t flags; + + memset(arg, 0, sizeof(*arg)); + + flags = fxlvm_read_u32(code); + if (flags) + { + arg->indexed = true; + arg->index.reg_type = fxlvm_read_u32(code); + arg->index.address = fxlvm_read_u32(code); } + arg->reg_type = fxlvm_read_u32(code); + arg->address = fxlvm_read_u32(code); +} - vkd3d_string_buffer_printf(&parser->buffer, "(var-not-found)"); +static void fx_print_fxlc_literal(struct fx_parser *parser, uint32_t address, struct fxlvm_code *code) +{ + if (parser->version.major >= 4) + vkd3d_string_buffer_print_f32(&parser->buffer, code->cli._4[address]); + else + vkd3d_string_buffer_print_f64(&parser->buffer, code->cli._8[address]); } -static void fx_4_parse_fxlc_argument(struct fx_parser *parser, uint32_t offset, const struct fxlvm_code *code) +static void fx_print_fxlc_argument(struct fx_parser *parser, const struct fxlc_arg *arg, struct fxlvm_code *code) { - struct fx_4_fxlc_argument arg; uint32_t count; - fx_parser_read_unstructured(parser, &arg, offset, sizeof(arg)); - - switch (arg.reg_type) + switch (arg->reg_type) { - case FX_4_FXLC_REG_LITERAL: + case FX_FXLC_REG_LITERAL: count = code->scalar ? 1 : code->comp_count; - if (arg.address >= code->cli4_count || count > code->cli4_count - arg.address) + if (arg->address >= code->cli_count || count > code->cli_count - arg->address) { vkd3d_string_buffer_printf(&parser->buffer, "()"); parser->failed = true; @@ -4761,42 +4965,120 @@ static void fx_4_parse_fxlc_argument(struct fx_parser *parser, uint32_t offset, } vkd3d_string_buffer_printf(&parser->buffer, "("); - vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg.address]); + fx_print_fxlc_literal(parser, arg->address, code); for (unsigned int i = 1; i < code->comp_count; ++i) { vkd3d_string_buffer_printf(&parser->buffer, ", "); - vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg.address + (code->scalar ? 0 : i)]); + fx_print_fxlc_literal(parser, arg->address + (code->scalar ? 0 : i), code); } vkd3d_string_buffer_printf(&parser->buffer, ")"); break; - case FX_4_FXLC_REG_CB: - fx_4_parse_fxlc_constant_argument(parser, &arg, code); + case FX_FXLC_REG_CB: + fx_parse_fxlc_constant_argument(parser, arg, code); break; - case FX_4_FXLC_REG_OUTPUT: - case FX_4_FXLC_REG_TEMP: - if (arg.reg_type == FX_4_FXLC_REG_OUTPUT) + case FX_FXLC_REG_OUTPUT: + case FX_FXLC_REG_TEMP: + if (arg->reg_type == FX_FXLC_REG_OUTPUT) vkd3d_string_buffer_printf(&parser->buffer, "expr"); else - vkd3d_string_buffer_printf(&parser->buffer, "r%u", arg.address / 4); - fx_4_parse_print_swizzle(parser, code, arg.address); + vkd3d_string_buffer_printf(&parser->buffer, "r%u", arg->address / 4); + fx_parse_print_swizzle(parser, code, arg->address); break; default: - vkd3d_string_buffer_printf(&parser->buffer, "", arg.reg_type); + vkd3d_string_buffer_printf(&parser->buffer, "", arg->reg_type); break; } } +static void fx_parse_fxlvm_expression(struct fx_parser *parser, struct fxlvm_code *code) +{ + struct fxlc_arg args[9]; + uint32_t ins_count; + size_t i, j; + + ins_count = fxlvm_read_u32(code); + + parse_fx_start_indent(parser); + + for (i = 0; i < ins_count; ++i) + { + uint32_t instr, opcode, src_count; + + instr = fxlvm_read_u32(code); + src_count = fxlvm_read_u32(code); + + if (src_count >= ARRAY_SIZE(args)) + { + fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, + "Unexpected instruction source count %u.", src_count); + break; + } + + /* Sources entries are followed by the destination, first read them all. + Output format is "opcode dst, src[0]...src[n]". */ + for (j = 0; j < src_count; ++j) + fx_parse_fxlc_argument(parser, &args[j], code); + fx_parse_fxlc_argument(parser, &args[src_count], code); + + opcode = (instr >> FX_FXLC_OPCODE_SHIFT) & FX_FXLC_OPCODE_MASK; + code->comp_count = instr & FX_FXLC_COMP_COUNT_MASK; + + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "%s ", get_fxlc_opcode_name(opcode)); + + code->scalar = false; + fx_print_fxlc_argument(parser, &args[src_count], code); + vkd3d_string_buffer_printf(&parser->buffer, ", "); + + for (j = 0; j < src_count; ++j) + { + /* Scalar modifier applies only to the first source. */ + code->scalar = j == 0 && !!(instr & FX_FXLC_IS_SCALAR_MASK); + fx_print_fxlc_argument(parser, &args[j], code); + if (j < src_count - 1) + vkd3d_string_buffer_printf(&parser->buffer, ", "); + } + + vkd3d_string_buffer_printf(&parser->buffer, "\n"); + } + + parse_fx_end_indent(parser); +} + +static void fx_2_parse_fxlvm_expression(struct fx_parser *parser, const uint32_t *blob, uint32_t size) +{ + uint32_t count = size / sizeof(uint32_t); + struct fxlvm_code code = { 0 }; + uint32_t section_size; + const uint32_t *data; + + /* Literal constants, using 64-bit floats. */ + if ((data = find_d3dbc_section(blob, count, TAG_CLIT, §ion_size))) + { + code.cli_count = *data++; + code.cli._8 = (const double *)data; + } + + /* CTAB does not contain variable names */ + + /* Code blob */ + code.ptr = find_d3dbc_section(blob, count, TAG_FXLC, &count); + code.end = code.ptr + count; + + fx_parse_fxlvm_expression(parser, &code); +} + static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offset) { struct vkd3d_shader_dxbc_section_desc *section, fxlc, cli4, ctab; struct vkd3d_shader_dxbc_desc dxbc_desc; + struct fxlvm_code code = { 0 }; struct vkd3d_shader_code dxbc; - uint32_t size, ins_count; - struct fxlvm_code code; - size_t i, j; + uint32_t size; + size_t i; offset = fx_parser_read_unstructured(parser, &size, offset, sizeof(size)); @@ -4832,8 +5114,8 @@ static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offse { uint32_t cli4_offset = offset + (size_t)cli4.data.code - (size_t)dxbc.code; - fx_parser_read_unstructured(parser, &code.cli4_count, cli4_offset, sizeof(code.cli4_count)); - code.cli4 = fx_parser_get_unstructured_ptr(parser, cli4_offset + 4, code.cli4_count * sizeof(float)); + fx_parser_read_unstructured(parser, &code.cli_count, cli4_offset, sizeof(code.cli_count)); + code.cli._4 = fx_parser_get_unstructured_ptr(parser, cli4_offset + 4, code.cli_count * sizeof(float)); } if (ctab.data.code) @@ -4849,47 +5131,10 @@ static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offse ctab_offset + consts_offset, code.ctab_count * sizeof(*code.constants)); } - offset += (size_t)fxlc.data.code - (size_t)dxbc.code; - offset = fx_parser_read_unstructured(parser, &ins_count, offset, sizeof(ins_count)); - - parse_fx_start_indent(parser); + code.ptr = fxlc.data.code; + code.end = (uint32_t *)((uint8_t *)fxlc.data.code + fxlc.data.size); - for (i = 0; i < ins_count; ++i) - { - uint32_t instr, opcode, src_count; - struct fx_4_fxlc_argument arg; - - offset = fx_parser_read_unstructured(parser, &instr, offset, sizeof(instr)); - offset = fx_parser_read_unstructured(parser, &src_count, offset, sizeof(src_count)); - - opcode = (instr >> FX_4_FXLC_OPCODE_SHIFT) & FX_4_FXLC_OPCODE_MASK; - code.comp_count = instr & FX_4_FXLC_COMP_COUNT_MASK; - code.scalar = false; - - parse_fx_print_indent(parser); - vkd3d_string_buffer_printf(&parser->buffer, "%s ", fx_4_get_fxlc_opcode_name(opcode)); - - /* Destination first. */ - fx_4_parse_fxlc_argument(parser, offset + sizeof(arg) * src_count, &code); - - for (j = 0; j < src_count; ++j) - { - vkd3d_string_buffer_printf(&parser->buffer, ", "); - - /* Scalar modifier applies only to first source. */ - code.scalar = j == 0 && !!(instr & FX_4_FXLC_IS_SCALAR_MASK); - fx_4_parse_fxlc_argument(parser, offset, &code); - - offset += sizeof(arg); - } - - /* Destination */ - offset += sizeof(arg); - - vkd3d_string_buffer_printf(&parser->buffer, "\n"); - } - - parse_fx_end_indent(parser); + fx_parse_fxlvm_expression(parser, &code); } static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32_t count, diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c index e4497b9ac5b..214632c00eb 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -421,6 +421,9 @@ static void shader_glsl_print_src(struct vkd3d_string_buffer *buffer, struct vkd case VKD3DSPSM_ABS: vkd3d_string_buffer_printf(buffer, "abs(%s)", str->buffer); break; + case VKD3DSPSM_ABSNEG: + vkd3d_string_buffer_printf(buffer, "-abs(%s)", str->buffer); + break; default: vkd3d_string_buffer_printf(buffer, "(%s)", vsir_src->modifiers, str->buffer); @@ -495,6 +498,9 @@ static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_g uint32_t modifiers = dst->vsir->modifiers; bool close = true; + /* It is always legitimate to ignore _pp. */ + modifiers &= ~VKD3DSPDM_PARTIALPRECISION; + if (dst->vsir->shift) vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, "Internal compiler error: Unhandled destination shift %#x.", dst->vsir->shift); @@ -555,10 +561,12 @@ static void VKD3D_PRINTF_FUNC(4, 5) shader_glsl_print_assignment_ext(struct vkd3 static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) { + const char *name = vsir_opcode_get_name(ins->opcode, ""); + shader_glsl_print_indent(gen->buffer, gen->indent); - vkd3d_string_buffer_printf(gen->buffer, "/* */\n", ins->opcode); + vkd3d_string_buffer_printf(gen->buffer, "/* */\n", name, ins->opcode); vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled instruction %#x.", ins->opcode); + "Internal compiler error: Unhandled instruction \"%s\" (%#x).", name, ins->opcode); } static void shader_glsl_binop(struct vkd3d_glsl_generator *gen, @@ -2313,7 +2321,7 @@ static void shader_glsl_handle_global_flags(struct vkd3d_string_buffer *buffer, flags &= ~VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL; } - if (flags) + if (flags & ~VKD3DSGF_REFACTORING_ALLOWED) vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, "Internal compiler error: Unhandled global flags %#"PRIx64".", (uint64_t)flags); } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h index 58f579cd9f9..63c9733ec7b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -245,6 +245,7 @@ struct hlsl_semantic { const char *name; uint32_t index; + uint32_t stream_index; /* Name exactly as it appears in the sources. */ const char *raw_name; diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index 5aee1e701cd..bad9d33094b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -2559,6 +2559,9 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, "Variable '%s' is declared as both \"uniform\" and \"static\".", var->name); + if (modifiers & HLSL_STORAGE_GROUPSHARED) + hlsl_fixme(ctx, &var->loc, "Group shared variables."); + /* Mark it as uniform. We need to do this here since synthetic * variables also get put in the global scope, but shouldn't be * considered uniforms, and we have no way of telling otherwise. */ diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index 38d5c55c26b..d4e29e16b7c 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -288,7 +288,8 @@ static bool types_are_semantic_equivalent(struct hlsl_ctx *ctx, const struct hls static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_var *var, struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic, - uint32_t index, bool output, bool force_align, bool create, const struct vkd3d_shader_location *loc) + uint32_t index, uint32_t stream_index, bool output, bool force_align, bool create, + const struct vkd3d_shader_location *loc) { struct hlsl_semantic new_semantic; struct hlsl_ir_var *ext_var; @@ -300,7 +301,12 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir else prefix = output ? "output" : "input"; - if (!(new_name = hlsl_sprintf_alloc(ctx, "<%s-%s%u>", prefix, semantic->name, index))) + if (stream_index) + new_name = hlsl_sprintf_alloc(ctx, "<%s-m%u:%s%u>", prefix, stream_index, semantic->name, index); + else + new_name = hlsl_sprintf_alloc(ctx, "<%s-%s%u>", prefix, semantic->name, index); + + if (!new_name) return NULL; LIST_FOR_EACH_ENTRY(ext_var, &func->extern_vars, struct hlsl_ir_var, extern_entry) @@ -353,6 +359,7 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir return NULL; } new_semantic.index = index; + new_semantic.stream_index = stream_index; if (!(ext_var = hlsl_new_var(ctx, new_name, type, loc, &new_semantic, modifiers, NULL))) { vkd3d_free(new_name); @@ -435,7 +442,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec prim_type_src->modifiers = var->data_type->modifiers & HLSL_PRIMITIVE_MODIFIERS_MASK; if (!(input = add_semantic_var(ctx, func, var, prim_type_src, - modifiers, semantic, semantic_index + i, false, force_align, true, loc))) + modifiers, semantic, semantic_index + i, 0, false, force_align, true, loc))) return; hlsl_init_simple_deref_from_var(&prim_deref, input); @@ -448,7 +455,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_dec else { if (!(input = add_semantic_var(ctx, func, var, vector_type_src, - modifiers, semantic, semantic_index + i, false, force_align, true, loc))) + modifiers, semantic, semantic_index + i, 0, false, force_align, true, loc))) return; if (!(load = hlsl_new_var_load(ctx, input, &var->loc))) @@ -558,7 +565,7 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_function_decl *func, struct hlsl_ir_load *rhs, uint32_t modifiers, - struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align, bool create) + struct hlsl_semantic *semantic, uint32_t semantic_index, uint32_t stream_index, bool force_align, bool create) { struct hlsl_type *type = rhs->node.data_type, *vector_type; struct vkd3d_shader_location *loc = &rhs->node.loc; @@ -588,7 +595,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *load; if (!(output = add_semantic_var(ctx, func, var, vector_type, - modifiers, semantic, semantic_index + i, true, force_align, create, loc))) + modifiers, semantic, semantic_index + i, stream_index, true, force_align, create, loc))) return; if (type->class == HLSL_CLASS_MATRIX) @@ -609,7 +616,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_function_decl *func, const struct hlsl_type *type, struct hlsl_ir_load *rhs, uint32_t modifiers, - struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align, bool create) + struct hlsl_semantic *semantic, uint32_t semantic_index, uint32_t stream_index, bool force_align, bool create) { struct vkd3d_shader_location *loc = &rhs->node.loc; struct hlsl_ir_var *var = rhs->src.var; @@ -654,12 +661,13 @@ static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block * hlsl_block_add_instr(block, &element_load->node); append_output_copy_recurse(ctx, block, func, element_type, element_load, element_modifiers, semantic, - elem_semantic_index, force_align, create); + elem_semantic_index, stream_index, force_align, create); } } else { - append_output_copy(ctx, block, func, rhs, modifiers, semantic, semantic_index, force_align, create); + append_output_copy(ctx, block, func, rhs, modifiers, semantic, + semantic_index, stream_index, force_align, create); } } @@ -676,7 +684,7 @@ static void append_output_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function hlsl_block_add_instr(&func->body, &load->node); append_output_copy_recurse(ctx, &func->body, func, var->data_type, load, var->storage_modifiers, - &var->semantic, var->semantic.index, false, true); + &var->semantic, var->semantic.index, 0, false, true); } bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), @@ -3360,7 +3368,7 @@ static bool split_struct_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr struct stream_append_ctx { struct hlsl_ir_function_decl *func; - bool created; + bool created[VKD3D_MAX_STREAM_COUNT]; }; static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) @@ -3371,6 +3379,7 @@ static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst const struct hlsl_type *type; struct hlsl_ir_var *var; struct hlsl_block block; + uint32_t stream_index; if (instr->type != HLSL_IR_RESOURCE_STORE) return false; @@ -3390,18 +3399,17 @@ static bool lower_stream_appends(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst } VKD3D_ASSERT(var->regs[HLSL_REGSET_STREAM_OUTPUTS].allocated); + stream_index = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; - if (var->regs[HLSL_REGSET_STREAM_OUTPUTS].index) - { - hlsl_fixme(ctx, &instr->loc, "Append to an output stream with a nonzero stream index."); - return false; - } + VKD3D_ASSERT(stream_index < ARRAY_SIZE(append_ctx->created)); hlsl_block_init(&block); - append_output_copy_recurse(ctx, &block, append_ctx->func, type->e.so.type, hlsl_ir_load(rhs), var->storage_modifiers, - &var->semantic, var->semantic.index, false, !append_ctx->created); - append_ctx->created = true; + append_output_copy_recurse(ctx, &block, append_ctx->func, type->e.so.type, hlsl_ir_load(rhs), + var->storage_modifiers, &var->semantic, var->semantic.index, + var->regs[HLSL_REGSET_STREAM_OUTPUTS].index, false, !append_ctx->created[stream_index]); + + append_ctx->created[stream_index] = true; list_move_before(&instr->entry, &block.instrs); hlsl_src_remove(&store->value); @@ -3919,7 +3927,7 @@ static bool lower_separate_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *in if (load->texel_offset.node) { hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, - "Texel offsets are not supported on profiles lower than 4.0.\n"); + "Texel offsets are not supported on profiles lower than 4.0."); return false; } @@ -5754,7 +5762,7 @@ static const char *debug_register(char class, struct hlsl_reg reg, const struct static const char writemask_offset[] = {'w','x','y','z'}; unsigned int reg_size = type->reg_size[HLSL_REGSET_NUMERIC]; - if (reg_size > 4) + if (reg_size > 4 && !hlsl_type_is_patch_array(type)) { if (reg_size & 3) return vkd3d_dbg_sprintf("%c%u-%c%u.%c", class, reg.id, class, reg.id + (reg_size / 4), @@ -6456,6 +6464,8 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var if ((!output && !var->last_read) || (output && !var->first_write)) return; + + optimize = false; } else { @@ -6518,8 +6528,8 @@ static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, uint32_t *output_reg_count) { + struct register_allocator input_allocator = {0}, output_allocators[VKD3D_MAX_STREAM_COUNT] = {{0}}; struct register_allocator in_prim_allocator = {0}, patch_constant_out_patch_allocator = {0}; - struct register_allocator input_allocator = {0}, output_allocator = {0}; bool is_vertex_shader = ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX; bool is_pixel_shader = ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL; struct hlsl_ir_var *var; @@ -6527,7 +6537,8 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun in_prim_allocator.prioritize_smaller_writemasks = true; patch_constant_out_patch_allocator.prioritize_smaller_writemasks = true; input_allocator.prioritize_smaller_writemasks = true; - output_allocator.prioritize_smaller_writemasks = true; + for (unsigned int i = 0; i < ARRAY_SIZE(output_allocators); ++i) + output_allocators[i].prioritize_smaller_writemasks = true; LIST_FOR_EACH_ENTRY(var, &entry_func->extern_vars, struct hlsl_ir_var, extern_entry) { @@ -6550,15 +6561,22 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_fun } if (var->is_output_semantic) - allocate_semantic_register(ctx, var, &output_allocator, true, !is_pixel_shader); + { + VKD3D_ASSERT(var->semantic.stream_index < ARRAY_SIZE(output_allocators)); + allocate_semantic_register(ctx, var, &output_allocators[var->semantic.stream_index], + true, !is_pixel_shader); + } } - *output_reg_count = output_allocator.reg_count; + *output_reg_count = output_allocators[0].reg_count; + for (unsigned int i = 1; i < ARRAY_SIZE(output_allocators); ++i) + *output_reg_count = max(*output_reg_count, output_allocators[i].reg_count); vkd3d_free(in_prim_allocator.allocations); vkd3d_free(patch_constant_out_patch_allocator.allocations); vkd3d_free(input_allocator.allocations); - vkd3d_free(output_allocator.allocations); + for (unsigned int i = 0; i < ARRAY_SIZE(output_allocators); ++i) + vkd3d_free(output_allocators[i].allocations); } static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, @@ -8018,6 +8036,7 @@ static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_prog return; } element->semantic_index = var->semantic.index; + element->stream_index = var->semantic.stream_index; element->sysval_semantic = sysval; element->component_type = component_type; element->register_index = register_index; @@ -8485,6 +8504,14 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p VKD3D_ASSERT(regset == HLSL_REGSET_SAMPLERS); *writemask = VKD3DSP_WRITEMASK_ALL; } + else if (regset == HLSL_REGSET_STREAM_OUTPUTS) + { + reg->type = VKD3DSPR_STREAM; + reg->dimension = VSIR_DIMENSION_NONE; + reg->idx[0].offset = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; + reg->idx_count = 1; + *writemask = VKD3DSP_WRITEMASK_ALL; + } else { unsigned int offset = deref->const_offset + var->buffer_offset; @@ -9279,16 +9306,16 @@ static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, switch (load->load_type) { case HLSL_RESOURCE_SAMPLE: - opcode = VKD3DSIH_TEX; + opcode = VKD3DSIH_TEXLD; break; case HLSL_RESOURCE_SAMPLE_PROJ: - opcode = VKD3DSIH_TEX; + opcode = VKD3DSIH_TEXLD; flags |= VKD3DSI_TEXLD_PROJECT; break; case HLSL_RESOURCE_SAMPLE_LOD_BIAS: - opcode = VKD3DSIH_TEX; + opcode = VKD3DSIH_TEXLD; flags |= VKD3DSI_TEXLD_BIAS; break; @@ -9922,6 +9949,57 @@ static void sm1_generate_ctab(struct hlsl_ctx *ctx, struct vkd3d_shader_code *ct ctab->size = buffer.size; } +static enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval, + unsigned int index) +{ + switch (sysval) + { + case VKD3D_SHADER_SV_COVERAGE: + case VKD3D_SHADER_SV_DEPTH: + case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL: + case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL: + case VKD3D_SHADER_SV_NONE: + case VKD3D_SHADER_SV_STENCIL_REF: + case VKD3D_SHADER_SV_TARGET: + return VKD3D_SIV_NONE; + case VKD3D_SHADER_SV_POSITION: + return VKD3D_SIV_POSITION; + case VKD3D_SHADER_SV_CLIP_DISTANCE: + return VKD3D_SIV_CLIP_DISTANCE; + case VKD3D_SHADER_SV_CULL_DISTANCE: + return VKD3D_SIV_CULL_DISTANCE; + case VKD3D_SHADER_SV_INSTANCE_ID: + return VKD3D_SIV_INSTANCE_ID; + case VKD3D_SHADER_SV_IS_FRONT_FACE: + return VKD3D_SIV_IS_FRONT_FACE; + case VKD3D_SHADER_SV_PRIMITIVE_ID: + return VKD3D_SIV_PRIMITIVE_ID; + case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX: + return VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX; + case VKD3D_SHADER_SV_SAMPLE_INDEX: + return VKD3D_SIV_SAMPLE_INDEX; + case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: + return VKD3D_SIV_QUAD_U0_TESS_FACTOR + index; + case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: + return VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR + index; + case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: + return VKD3D_SIV_TRIANGLE_U_TESS_FACTOR + index; + case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: + return VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR; + case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: + return VKD3D_SIV_LINE_DETAIL_TESS_FACTOR; + case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: + return VKD3D_SIV_LINE_DENSITY_TESS_FACTOR; + case VKD3D_SHADER_SV_VERTEX_ID: + return VKD3D_SIV_VERTEX_ID; + case VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX: + return VKD3D_SIV_VIEWPORT_ARRAY_INDEX; + default: + FIXME("Unhandled sysval %#x, index %u.\n", sysval, index); + return VKD3D_SIV_NONE; + } +} + static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vsir_program *program, const struct hlsl_ir_var *var, struct hlsl_block *block, const struct vkd3d_shader_location *loc) { @@ -9983,6 +10061,9 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs if (semantic == VKD3D_SHADER_SV_NONE || version->type == VKD3D_SHADER_TYPE_PIXEL || (version->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func)) opcode = VKD3DSIH_DCL_OUTPUT; + else if ((semantic == VKD3D_SHADER_SV_PRIMITIVE_ID || semantic == VKD3D_SHADER_SV_IS_FRONT_FACE) + && version->type == VKD3D_SHADER_TYPE_GEOMETRY) + opcode = VKD3DSIH_DCL_OUTPUT_SGV; else opcode = VKD3DSIH_DCL_OUTPUT_SIV; } @@ -10832,20 +10913,27 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, if (store->store_type != HLSL_RESOURCE_STORE) { - enum vkd3d_shader_opcode opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND - ? VKD3DSIH_EMIT : VKD3DSIH_CUT; + enum vkd3d_shader_opcode opcode; VKD3D_ASSERT(!store->value.node && !store->coords.node); VKD3D_ASSERT(store->resource.var->regs[HLSL_REGSET_STREAM_OUTPUTS].allocated); - if (store->resource.var->regs[HLSL_REGSET_STREAM_OUTPUTS].index) + if (hlsl_version_lt(ctx, 5, 0)) { - hlsl_fixme(ctx, &instr->loc, "Stream output operation with a nonzero stream index."); - return false; + opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND ? VKD3DSIH_EMIT : VKD3DSIH_CUT; + ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 0); + return !!ins; } - ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 0); - return !!ins; + opcode = store->store_type == HLSL_RESOURCE_STREAM_APPEND ? VKD3DSIH_EMIT_STREAM : VKD3DSIH_CUT_STREAM; + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 1))) + return false; + + if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, &ins->src[0], + &store->resource, VKD3DSP_WRITEMASK_ALL, &instr->loc)) + return false; + + return true; } if (!store->resource.var->is_uniform) @@ -12026,14 +12114,11 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, bool uav) { enum hlsl_regset regset = uav ? HLSL_REGSET_UAVS : HLSL_REGSET_TEXTURES; - struct vkd3d_shader_structured_resource *structured_resource; - struct vkd3d_shader_dst_param *dst_param; - struct vkd3d_shader_semantic *semantic; struct vkd3d_shader_instruction *ins; struct hlsl_type *component_type; enum vkd3d_shader_opcode opcode; bool multisampled; - unsigned int i, j; + unsigned int i; VKD3D_ASSERT(resource->regset == regset); VKD3D_ASSERT(hlsl_version_lt(ctx, 5, 1) || resource->bind_count == 1); @@ -12044,6 +12129,7 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, { unsigned int array_first = resource->index + i; unsigned int array_last = resource->index + i; /* FIXME: array end. */ + struct vkd3d_shader_resource *vsir_resource; if (resource->var && !resource->var->objects_usage[regset][i].used) continue; @@ -12081,13 +12167,16 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; return; } - semantic = &ins->declaration.semantic; - structured_resource = &ins->declaration.structured_resource; - dst_param = &semantic->resource.reg; - vsir_dst_param_init(dst_param, uav ? VKD3DSPR_UAV : VKD3DSPR_RESOURCE, VKD3D_DATA_UNUSED, 0); - if (uav && component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) - structured_resource->byte_stride = 4 * component_type->e.resource.format->reg_size[HLSL_REGSET_NUMERIC]; + if (component_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) + vsir_resource = &ins->declaration.raw_resource.resource; + else if (component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) + vsir_resource = &ins->declaration.structured_resource.resource; + else + vsir_resource = &ins->declaration.semantic.resource; + + vsir_dst_param_init(&vsir_resource->reg, uav ? VKD3DSPR_UAV : VKD3DSPR_RESOURCE, VKD3D_DATA_UNUSED, 0); + if (uav && component_type->e.resource.rasteriser_ordered) ins->flags = VKD3DSUF_RASTERISER_ORDERED_VIEW; @@ -12101,30 +12190,52 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, ctx->profile->major_version, ctx->profile->minor_version); } - for (j = 0; j < 4; ++j) - semantic->resource_data_type[j] = sm4_generate_vsir_get_format_type(component_type); - - semantic->resource.range.first = array_first; - semantic->resource.range.last = array_last; - semantic->resource.range.space = resource->space; + vsir_resource->range.first = array_first; + vsir_resource->range.last = array_last; + vsir_resource->range.space = resource->space; - dst_param->reg.idx[0].offset = resource->id; - dst_param->reg.idx[1].offset = array_first; - dst_param->reg.idx[2].offset = array_last; - dst_param->reg.idx_count = 3; + vsir_resource->reg.reg.idx[0].offset = resource->id; + vsir_resource->reg.reg.idx[1].offset = array_first; + vsir_resource->reg.reg.idx[2].offset = array_last; + vsir_resource->reg.reg.idx_count = 3; ins->resource_type = sm4_generate_vsir_get_resource_type(resource->component_type); - if (resource->component_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) + + if (component_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) + { ins->raw = true; - if (resource->component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) + } + else if (component_type->sampler_dim == HLSL_SAMPLER_DIM_STRUCTURED_BUFFER) { ins->structured = true; ins->resource_stride = 4 * component_type->e.resource.format->reg_size[HLSL_REGSET_NUMERIC]; + ins->declaration.structured_resource.byte_stride = ins->resource_stride; + } + else + { + for (unsigned int j = 0; j < 4; ++j) + ins->declaration.semantic.resource_data_type[j] = sm4_generate_vsir_get_format_type(component_type); + + if (multisampled) + ins->declaration.semantic.sample_count = component_type->sample_count; } + } +} + +static void sm4_generate_vsir_add_dcl_stream(struct hlsl_ctx *ctx, + struct vsir_program *program, const struct hlsl_ir_var *var) +{ + struct vkd3d_shader_instruction *ins; - if (multisampled) - semantic->sample_count = component_type->sample_count; + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &var->loc, VKD3DSIH_DCL_STREAM, 0, 1))) + { + ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; + return; } + + vsir_src_param_init(&ins->src[0], VKD3DSPR_STREAM, VKD3D_DATA_OPAQUE, 1); + ins->src[0].reg.dimension = VSIR_DIMENSION_NONE; + ins->src[0].reg.idx[0].offset = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; } /* OBJECTIVE: Translate all the information from ctx and entry_func to the @@ -12201,6 +12312,17 @@ static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl } sm4_free_extern_resources(extern_resources, extern_resources_count); + if (version.type == VKD3D_SHADER_TYPE_GEOMETRY && version.major >= 5) + { + const struct hlsl_ir_var *var; + + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + if (var->bind_count[HLSL_REGSET_STREAM_OUTPUTS]) + sm4_generate_vsir_add_dcl_stream(ctx, program, var); + } + } + if (version.type == VKD3D_SHADER_TYPE_HULL) generate_vsir_add_program_instruction(ctx, program, &ctx->patch_constant_func->loc, VKD3DSIH_HS_CONTROL_POINT_PHASE, 0, 0); @@ -13523,7 +13645,26 @@ static void process_entry_function(struct hlsl_ctx *ctx, else { if (profile->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func) - hlsl_fixme(ctx, &entry_func->loc, "Passthrough hull shader control point function."); + { + if (!ctx->input_control_point_type) + { + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_INPUT_PATCH, + "Pass-through control point function \"%s\" is missing an InputPatch parameter.", + entry_func->func->name); + } + else if (ctx->output_control_point_count + && ctx->output_control_point_count != ctx->input_control_point_count) + { + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, + "Output control point count %u does not match the input control point count %u.", + ctx->output_control_point_count, ctx->input_control_point_count); + } + else + { + ctx->output_control_point_type = ctx->input_control_point_type; + ctx->output_control_point_count = ctx->input_control_point_count; + } + } } if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY && ctx->input_primitive_type == VKD3D_PT_UNDEFINED) diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index 7466f7a2da1..0aebfea2add 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -29,6 +29,344 @@ struct vsir_transformation_context struct vkd3d_shader_message_context *message_context; }; +const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) +{ + static const char * const names[] = + { + [VKD3DSIH_ABS ] = "abs", + [VKD3DSIH_ACOS ] = "acos", + [VKD3DSIH_ADD ] = "add", + [VKD3DSIH_AND ] = "and", + [VKD3DSIH_ASIN ] = "asin", + [VKD3DSIH_ATAN ] = "atan", + [VKD3DSIH_ATOMIC_AND ] = "atomic_and", + [VKD3DSIH_ATOMIC_CMP_STORE ] = "atomic_cmp_store", + [VKD3DSIH_ATOMIC_IADD ] = "atomic_iadd", + [VKD3DSIH_ATOMIC_IMAX ] = "atomic_imax", + [VKD3DSIH_ATOMIC_IMIN ] = "atomic_imin", + [VKD3DSIH_ATOMIC_OR ] = "atomic_or", + [VKD3DSIH_ATOMIC_UMAX ] = "atomic_umax", + [VKD3DSIH_ATOMIC_UMIN ] = "atomic_umin", + [VKD3DSIH_ATOMIC_XOR ] = "atomic_xor", + [VKD3DSIH_BEM ] = "bem", + [VKD3DSIH_BFI ] = "bfi", + [VKD3DSIH_BFREV ] = "bfrev", + [VKD3DSIH_BRANCH ] = "branch", + [VKD3DSIH_BREAK ] = "break", + [VKD3DSIH_BREAKC ] = "break", + [VKD3DSIH_BREAKP ] = "breakp", + [VKD3DSIH_BUFINFO ] = "bufinfo", + [VKD3DSIH_CALL ] = "call", + [VKD3DSIH_CALLNZ ] = "callnz", + [VKD3DSIH_CASE ] = "case", + [VKD3DSIH_CHECK_ACCESS_FULLY_MAPPED ] = "check_access_fully_mapped", + [VKD3DSIH_CMP ] = "cmp", + [VKD3DSIH_CND ] = "cnd", + [VKD3DSIH_CONTINUE ] = "continue", + [VKD3DSIH_CONTINUEP ] = "continuec", + [VKD3DSIH_COUNTBITS ] = "countbits", + [VKD3DSIH_CRS ] = "crs", + [VKD3DSIH_CUT ] = "cut", + [VKD3DSIH_CUT_STREAM ] = "cut_stream", + [VKD3DSIH_DADD ] = "dadd", + [VKD3DSIH_DCL ] = "dcl", + [VKD3DSIH_DCL_CONSTANT_BUFFER ] = "dcl_constantBuffer", + [VKD3DSIH_DCL_FUNCTION_BODY ] = "dcl_function_body", + [VKD3DSIH_DCL_FUNCTION_TABLE ] = "dcl_function_table", + [VKD3DSIH_DCL_GLOBAL_FLAGS ] = "dcl_globalFlags", + [VKD3DSIH_DCL_GS_INSTANCES ] = "dcl_gs_instances", + [VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT] = "dcl_hs_fork_phase_instance_count", + [VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT] = "dcl_hs_join_phase_instance_count", + [VKD3DSIH_DCL_HS_MAX_TESSFACTOR ] = "dcl_hs_max_tessfactor", + [VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER ] = "dcl_immediateConstantBuffer", + [VKD3DSIH_DCL_INDEX_RANGE ] = "dcl_index_range", + [VKD3DSIH_DCL_INDEXABLE_TEMP ] = "dcl_indexableTemp", + [VKD3DSIH_DCL_INPUT ] = "dcl_input", + [VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT ] = "dcl_input_control_point_count", + [VKD3DSIH_DCL_INPUT_PRIMITIVE ] = "dcl_inputprimitive", + [VKD3DSIH_DCL_INPUT_PS ] = "dcl_input_ps", + [VKD3DSIH_DCL_INPUT_PS_SGV ] = "dcl_input_ps_sgv", + [VKD3DSIH_DCL_INPUT_PS_SIV ] = "dcl_input_ps_siv", + [VKD3DSIH_DCL_INPUT_SGV ] = "dcl_input_sgv", + [VKD3DSIH_DCL_INPUT_SIV ] = "dcl_input_siv", + [VKD3DSIH_DCL_INTERFACE ] = "dcl_interface", + [VKD3DSIH_DCL_OUTPUT ] = "dcl_output", + [VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT ] = "dcl_output_control_point_count", + [VKD3DSIH_DCL_OUTPUT_SGV ] = "dcl_output_sgv", + [VKD3DSIH_DCL_OUTPUT_SIV ] = "dcl_output_siv", + [VKD3DSIH_DCL_OUTPUT_TOPOLOGY ] = "dcl_outputtopology", + [VKD3DSIH_DCL_RESOURCE_RAW ] = "dcl_resource_raw", + [VKD3DSIH_DCL_RESOURCE_STRUCTURED ] = "dcl_resource_structured", + [VKD3DSIH_DCL_SAMPLER ] = "dcl_sampler", + [VKD3DSIH_DCL_STREAM ] = "dcl_stream", + [VKD3DSIH_DCL_TEMPS ] = "dcl_temps", + [VKD3DSIH_DCL_TESSELLATOR_DOMAIN ] = "dcl_tessellator_domain", + [VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE] = "dcl_tessellator_output_primitive", + [VKD3DSIH_DCL_TESSELLATOR_PARTITIONING ] = "dcl_tessellator_partitioning", + [VKD3DSIH_DCL_TGSM_RAW ] = "dcl_tgsm_raw", + [VKD3DSIH_DCL_TGSM_STRUCTURED ] = "dcl_tgsm_structured", + [VKD3DSIH_DCL_THREAD_GROUP ] = "dcl_thread_group", + [VKD3DSIH_DCL_UAV_RAW ] = "dcl_uav_raw", + [VKD3DSIH_DCL_UAV_STRUCTURED ] = "dcl_uav_structured", + [VKD3DSIH_DCL_UAV_TYPED ] = "dcl_uav_typed", + [VKD3DSIH_DCL_VERTICES_OUT ] = "dcl_maxout", + [VKD3DSIH_DDIV ] = "ddiv", + [VKD3DSIH_DEF ] = "def", + [VKD3DSIH_DEFAULT ] = "default", + [VKD3DSIH_DEFB ] = "defb", + [VKD3DSIH_DEFI ] = "defi", + [VKD3DSIH_DEQO ] = "deq", + [VKD3DSIH_DFMA ] = "dfma", + [VKD3DSIH_DGEO ] = "dge", + [VKD3DSIH_DISCARD ] = "discard", + [VKD3DSIH_DIV ] = "div", + [VKD3DSIH_DLT ] = "dlt", + [VKD3DSIH_DMAX ] = "dmax", + [VKD3DSIH_DMIN ] = "dmin", + [VKD3DSIH_DMOV ] = "dmov", + [VKD3DSIH_DMOVC ] = "dmovc", + [VKD3DSIH_DMUL ] = "dmul", + [VKD3DSIH_DNE ] = "dne", + [VKD3DSIH_DP2 ] = "dp2", + [VKD3DSIH_DP2ADD ] = "dp2add", + [VKD3DSIH_DP3 ] = "dp3", + [VKD3DSIH_DP4 ] = "dp4", + [VKD3DSIH_DRCP ] = "drcp", + [VKD3DSIH_DST ] = "dst", + [VKD3DSIH_DSX ] = "dsx", + [VKD3DSIH_DSX_COARSE ] = "deriv_rtx_coarse", + [VKD3DSIH_DSX_FINE ] = "deriv_rtx_fine", + [VKD3DSIH_DSY ] = "dsy", + [VKD3DSIH_DSY_COARSE ] = "deriv_rty_coarse", + [VKD3DSIH_DSY_FINE ] = "deriv_rty_fine", + [VKD3DSIH_DTOF ] = "dtof", + [VKD3DSIH_DTOI ] = "dtoi", + [VKD3DSIH_DTOU ] = "dtou", + [VKD3DSIH_ELSE ] = "else", + [VKD3DSIH_EMIT ] = "emit", + [VKD3DSIH_EMIT_STREAM ] = "emit_stream", + [VKD3DSIH_ENDIF ] = "endif", + [VKD3DSIH_ENDLOOP ] = "endloop", + [VKD3DSIH_ENDREP ] = "endrep", + [VKD3DSIH_ENDSWITCH ] = "endswitch", + [VKD3DSIH_EQO ] = "eq", + [VKD3DSIH_EQU ] = "eq_unord", + [VKD3DSIH_EVAL_CENTROID ] = "eval_centroid", + [VKD3DSIH_EVAL_SAMPLE_INDEX ] = "eval_sample_index", + [VKD3DSIH_EXP ] = "exp", + [VKD3DSIH_EXPP ] = "expp", + [VKD3DSIH_F16TOF32 ] = "f16tof32", + [VKD3DSIH_F32TOF16 ] = "f32tof16", + [VKD3DSIH_FCALL ] = "fcall", + [VKD3DSIH_FIRSTBIT_HI ] = "firstbit_hi", + [VKD3DSIH_FIRSTBIT_LO ] = "firstbit_lo", + [VKD3DSIH_FIRSTBIT_SHI ] = "firstbit_shi", + [VKD3DSIH_FRC ] = "frc", + [VKD3DSIH_FREM ] = "frem", + [VKD3DSIH_FTOD ] = "ftod", + [VKD3DSIH_FTOI ] = "ftoi", + [VKD3DSIH_FTOU ] = "ftou", + [VKD3DSIH_GATHER4 ] = "gather4", + [VKD3DSIH_GATHER4_C ] = "gather4_c", + [VKD3DSIH_GATHER4_C_S ] = "gather4_c_s", + [VKD3DSIH_GATHER4_PO ] = "gather4_po", + [VKD3DSIH_GATHER4_PO_C ] = "gather4_po_c", + [VKD3DSIH_GATHER4_PO_C_S ] = "gather4_po_c_s", + [VKD3DSIH_GATHER4_PO_S ] = "gather4_po_s", + [VKD3DSIH_GATHER4_S ] = "gather4_s", + [VKD3DSIH_GEO ] = "ge", + [VKD3DSIH_GEU ] = "ge_unord", + [VKD3DSIH_HCOS ] = "hcos", + [VKD3DSIH_HS_CONTROL_POINT_PHASE ] = "hs_control_point_phase", + [VKD3DSIH_HS_DECLS ] = "hs_decls", + [VKD3DSIH_HS_FORK_PHASE ] = "hs_fork_phase", + [VKD3DSIH_HS_JOIN_PHASE ] = "hs_join_phase", + [VKD3DSIH_HSIN ] = "hsin", + [VKD3DSIH_HTAN ] = "htan", + [VKD3DSIH_IADD ] = "iadd", + [VKD3DSIH_IBFE ] = "ibfe", + [VKD3DSIH_IDIV ] = "idiv", + [VKD3DSIH_IEQ ] = "ieq", + [VKD3DSIH_IF ] = "if", + [VKD3DSIH_IFC ] = "if", + [VKD3DSIH_IGE ] = "ige", + [VKD3DSIH_ILT ] = "ilt", + [VKD3DSIH_IMAD ] = "imad", + [VKD3DSIH_IMAX ] = "imax", + [VKD3DSIH_IMIN ] = "imin", + [VKD3DSIH_IMM_ATOMIC_ALLOC ] = "imm_atomic_alloc", + [VKD3DSIH_IMM_ATOMIC_AND ] = "imm_atomic_and", + [VKD3DSIH_IMM_ATOMIC_CMP_EXCH ] = "imm_atomic_cmp_exch", + [VKD3DSIH_IMM_ATOMIC_CONSUME ] = "imm_atomic_consume", + [VKD3DSIH_IMM_ATOMIC_EXCH ] = "imm_atomic_exch", + [VKD3DSIH_IMM_ATOMIC_IADD ] = "imm_atomic_iadd", + [VKD3DSIH_IMM_ATOMIC_IMAX ] = "imm_atomic_imax", + [VKD3DSIH_IMM_ATOMIC_IMIN ] = "imm_atomic_imin", + [VKD3DSIH_IMM_ATOMIC_OR ] = "imm_atomic_or", + [VKD3DSIH_IMM_ATOMIC_UMAX ] = "imm_atomic_umax", + [VKD3DSIH_IMM_ATOMIC_UMIN ] = "imm_atomic_umin", + [VKD3DSIH_IMM_ATOMIC_XOR ] = "imm_atomic_xor", + [VKD3DSIH_IMUL ] = "imul", + [VKD3DSIH_INE ] = "ine", + [VKD3DSIH_INEG ] = "ineg", + [VKD3DSIH_ISFINITE ] = "isfinite", + [VKD3DSIH_ISHL ] = "ishl", + [VKD3DSIH_ISHR ] = "ishr", + [VKD3DSIH_ISINF ] = "isinf", + [VKD3DSIH_ISNAN ] = "isnan", + [VKD3DSIH_ITOD ] = "itod", + [VKD3DSIH_ITOF ] = "itof", + [VKD3DSIH_ITOI ] = "itoi", + [VKD3DSIH_LABEL ] = "label", + [VKD3DSIH_LD ] = "ld", + [VKD3DSIH_LD2DMS ] = "ld2dms", + [VKD3DSIH_LD2DMS_S ] = "ld2dms_s", + [VKD3DSIH_LD_RAW ] = "ld_raw", + [VKD3DSIH_LD_RAW_S ] = "ld_raw_s", + [VKD3DSIH_LD_S ] = "ld_s", + [VKD3DSIH_LD_STRUCTURED ] = "ld_structured", + [VKD3DSIH_LD_STRUCTURED_S ] = "ld_structured_s", + [VKD3DSIH_LD_UAV_TYPED ] = "ld_uav_typed", + [VKD3DSIH_LD_UAV_TYPED_S ] = "ld_uav_typed_s", + [VKD3DSIH_LIT ] = "lit", + [VKD3DSIH_LOD ] = "lod", + [VKD3DSIH_LOG ] = "log", + [VKD3DSIH_LOGP ] = "logp", + [VKD3DSIH_LOOP ] = "loop", + [VKD3DSIH_LRP ] = "lrp", + [VKD3DSIH_LTO ] = "lt", + [VKD3DSIH_LTU ] = "lt_unord", + [VKD3DSIH_M3x2 ] = "m3x2", + [VKD3DSIH_M3x3 ] = "m3x3", + [VKD3DSIH_M3x4 ] = "m3x4", + [VKD3DSIH_M4x3 ] = "m4x3", + [VKD3DSIH_M4x4 ] = "m4x4", + [VKD3DSIH_MAD ] = "mad", + [VKD3DSIH_MAX ] = "max", + [VKD3DSIH_MIN ] = "min", + [VKD3DSIH_MOV ] = "mov", + [VKD3DSIH_MOVA ] = "mova", + [VKD3DSIH_MOVC ] = "movc", + [VKD3DSIH_MSAD ] = "msad", + [VKD3DSIH_MUL ] = "mul", + [VKD3DSIH_NEO ] = "ne_ord", + [VKD3DSIH_NEU ] = "ne", + [VKD3DSIH_NOP ] = "nop", + [VKD3DSIH_NOT ] = "not", + [VKD3DSIH_NRM ] = "nrm", + [VKD3DSIH_OR ] = "or", + [VKD3DSIH_ORD ] = "ord", + [VKD3DSIH_PHASE ] = "phase", + [VKD3DSIH_PHI ] = "phi", + [VKD3DSIH_POW ] = "pow", + [VKD3DSIH_QUAD_READ_ACROSS_D ] = "quad_read_across_d", + [VKD3DSIH_QUAD_READ_ACROSS_X ] = "quad_read_across_x", + [VKD3DSIH_QUAD_READ_ACROSS_Y ] = "quad_read_across_y", + [VKD3DSIH_QUAD_READ_LANE_AT ] = "quad_read_lane_at", + [VKD3DSIH_RCP ] = "rcp", + [VKD3DSIH_REP ] = "rep", + [VKD3DSIH_RESINFO ] = "resinfo", + [VKD3DSIH_RET ] = "ret", + [VKD3DSIH_RETP ] = "retp", + [VKD3DSIH_ROUND_NE ] = "round_ne", + [VKD3DSIH_ROUND_NI ] = "round_ni", + [VKD3DSIH_ROUND_PI ] = "round_pi", + [VKD3DSIH_ROUND_Z ] = "round_z", + [VKD3DSIH_RSQ ] = "rsq", + [VKD3DSIH_SAMPLE ] = "sample", + [VKD3DSIH_SAMPLE_B ] = "sample_b", + [VKD3DSIH_SAMPLE_B_CL_S ] = "sample_b_cl_s", + [VKD3DSIH_SAMPLE_C ] = "sample_c", + [VKD3DSIH_SAMPLE_C_CL_S ] = "sample_c_cl_s", + [VKD3DSIH_SAMPLE_C_LZ ] = "sample_c_lz", + [VKD3DSIH_SAMPLE_C_LZ_S ] = "sample_c_lz_s", + [VKD3DSIH_SAMPLE_CL_S ] = "sample_cl_s", + [VKD3DSIH_SAMPLE_GRAD ] = "sample_d", + [VKD3DSIH_SAMPLE_GRAD_CL_S ] = "sample_d_cl_s", + [VKD3DSIH_SAMPLE_INFO ] = "sample_info", + [VKD3DSIH_SAMPLE_LOD ] = "sample_l", + [VKD3DSIH_SAMPLE_LOD_S ] = "sample_l_s", + [VKD3DSIH_SAMPLE_POS ] = "sample_pos", + [VKD3DSIH_SETP ] = "setp", + [VKD3DSIH_SGE ] = "sge", + [VKD3DSIH_SGN ] = "sgn", + [VKD3DSIH_SINCOS ] = "sincos", + [VKD3DSIH_SLT ] = "slt", + [VKD3DSIH_SQRT ] = "sqrt", + [VKD3DSIH_STORE_RAW ] = "store_raw", + [VKD3DSIH_STORE_STRUCTURED ] = "store_structured", + [VKD3DSIH_STORE_UAV_TYPED ] = "store_uav_typed", + [VKD3DSIH_SUB ] = "sub", + [VKD3DSIH_SWAPC ] = "swapc", + [VKD3DSIH_SWITCH ] = "switch", + [VKD3DSIH_SWITCH_MONOLITHIC ] = "switch", + [VKD3DSIH_SYNC ] = "sync", + [VKD3DSIH_TAN ] = "tan", + [VKD3DSIH_TEX ] = "tex", + [VKD3DSIH_TEXBEM ] = "texbem", + [VKD3DSIH_TEXBEML ] = "texbeml", + [VKD3DSIH_TEXCOORD ] = "texcoord", + [VKD3DSIH_TEXCRD ] = "texcrd", + [VKD3DSIH_TEXDEPTH ] = "texdepth", + [VKD3DSIH_TEXDP3 ] = "texdp3", + [VKD3DSIH_TEXDP3TEX ] = "texdp3tex", + [VKD3DSIH_TEXKILL ] = "texkill", + [VKD3DSIH_TEXLD ] = "texld", + [VKD3DSIH_TEXLDD ] = "texldd", + [VKD3DSIH_TEXLDL ] = "texldl", + [VKD3DSIH_TEXM3x2DEPTH ] = "texm3x2depth", + [VKD3DSIH_TEXM3x2PAD ] = "texm3x2pad", + [VKD3DSIH_TEXM3x2TEX ] = "texm3x2tex", + [VKD3DSIH_TEXM3x3 ] = "texm3x3", + [VKD3DSIH_TEXM3x3DIFF ] = "texm3x3diff", + [VKD3DSIH_TEXM3x3PAD ] = "texm3x3pad", + [VKD3DSIH_TEXM3x3SPEC ] = "texm3x3spec", + [VKD3DSIH_TEXM3x3TEX ] = "texm3x3tex", + [VKD3DSIH_TEXM3x3VSPEC ] = "texm3x3vspec", + [VKD3DSIH_TEXREG2AR ] = "texreg2ar", + [VKD3DSIH_TEXREG2GB ] = "texreg2gb", + [VKD3DSIH_TEXREG2RGB ] = "texreg2rgb", + [VKD3DSIH_UBFE ] = "ubfe", + [VKD3DSIH_UDIV ] = "udiv", + [VKD3DSIH_UGE ] = "uge", + [VKD3DSIH_ULT ] = "ult", + [VKD3DSIH_UMAX ] = "umax", + [VKD3DSIH_UMIN ] = "umin", + [VKD3DSIH_UMUL ] = "umul", + [VKD3DSIH_UNO ] = "uno", + [VKD3DSIH_USHR ] = "ushr", + [VKD3DSIH_UTOD ] = "utod", + [VKD3DSIH_UTOF ] = "utof", + [VKD3DSIH_UTOU ] = "utou", + [VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL ] = "wave_active_all_equal", + [VKD3DSIH_WAVE_ACTIVE_BALLOT ] = "wave_active_ballot", + [VKD3DSIH_WAVE_ACTIVE_BIT_AND ] = "wave_active_bit_and", + [VKD3DSIH_WAVE_ACTIVE_BIT_OR ] = "wave_active_bit_or", + [VKD3DSIH_WAVE_ACTIVE_BIT_XOR ] = "wave_active_bit_xor", + [VKD3DSIH_WAVE_ALL_BIT_COUNT ] = "wave_all_bit_count", + [VKD3DSIH_WAVE_ALL_TRUE ] = "wave_all_true", + [VKD3DSIH_WAVE_ANY_TRUE ] = "wave_any_true", + [VKD3DSIH_WAVE_IS_FIRST_LANE ] = "wave_is_first_lane", + [VKD3DSIH_WAVE_OP_ADD ] = "wave_op_add", + [VKD3DSIH_WAVE_OP_IMAX ] = "wave_op_imax", + [VKD3DSIH_WAVE_OP_IMIN ] = "wave_op_imin", + [VKD3DSIH_WAVE_OP_MAX ] = "wave_op_max", + [VKD3DSIH_WAVE_OP_MIN ] = "wave_op_min", + [VKD3DSIH_WAVE_OP_MUL ] = "wave_op_mul", + [VKD3DSIH_WAVE_OP_UMAX ] = "wave_op_umax", + [VKD3DSIH_WAVE_OP_UMIN ] = "wave_op_umin", + [VKD3DSIH_WAVE_PREFIX_BIT_COUNT ] = "wave_prefix_bit_count", + [VKD3DSIH_WAVE_READ_LANE_AT ] = "wave_read_lane_at", + [VKD3DSIH_WAVE_READ_LANE_FIRST ] = "wave_read_lane_first", + [VKD3DSIH_XOR ] = "xor", + }; + + if ((uint32_t)op < ARRAY_SIZE(names)) + return names[op] ? names[op] : error; + + return error; +} + static int convert_parameter_info(const struct vkd3d_shader_compile_info *compile_info, unsigned int *ret_count, const struct vkd3d_shader_parameter1 **ret_parameters) { @@ -823,7 +1161,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, div_ins->src[1] = tex->src[0]; div_ins->src[1].swizzle = vkd3d_shader_create_swizzle(w_comp, w_comp, w_comp, w_comp); - if (!vsir_instruction_init_with_params(program, tex_ins, location, VKD3DSIH_TEX, 1, 2)) + if (!vsir_instruction_init_with_params(program, tex_ins, location, VKD3DSIH_TEXLD, 1, 2)) return VKD3D_ERROR_OUT_OF_MEMORY; tex_ins->dst[0] = tex->dst[0]; @@ -838,7 +1176,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, return VKD3D_OK; } -static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, +static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program, struct vkd3d_shader_instruction *tex, struct vkd3d_shader_message_context *message_context) { unsigned int idx = tex->src[1].reg.idx[0].offset; @@ -1031,6 +1369,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr case VKD3DSIH_DCL_INPUT_PS: case VKD3DSIH_DCL_INPUT_PS_SGV: case VKD3DSIH_DCL_INPUT_PS_SIV: + case VKD3DSIH_DCL_OUTPUT_SGV: case VKD3DSIH_DCL_OUTPUT_SIV: vkd3d_shader_instruction_make_nop(ins); break; @@ -1040,7 +1379,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr return ret; break; - case VKD3DSIH_TEX: + case VKD3DSIH_TEXLD: if (ins->flags == VKD3DSI_TEXLD_PROJECT) { if ((ret = vsir_program_lower_texldp(program, ins, &tmp_idx)) < 0) @@ -1048,7 +1387,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr } else { - if ((ret = vsir_program_lower_tex(program, ins, message_context)) < 0) + if ((ret = vsir_program_lower_texld(program, ins, message_context)) < 0) return ret; } break; @@ -1061,6 +1400,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr case VKD3DSIH_TEXBEM: case VKD3DSIH_TEXBEML: case VKD3DSIH_TEXCOORD: + case VKD3DSIH_TEXCRD: case VKD3DSIH_TEXDEPTH: case VKD3DSIH_TEXDP3: case VKD3DSIH_TEXDP3TEX: @@ -1076,8 +1416,8 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr case VKD3DSIH_TEXREG2GB: case VKD3DSIH_TEXREG2RGB: vkd3d_shader_error(ctx->message_context, &ins->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, - "Aborting due to unimplemented feature: Combined sampler instruction %#x.", - ins->opcode); + "Aborting due to unimplemented feature: Combined sampler instruction \"%s\" (%#x).", + vsir_opcode_get_name(ins->opcode, ""), ins->opcode); return VKD3D_ERROR_NOT_IMPLEMENTED; default: @@ -1142,15 +1482,15 @@ static enum vkd3d_result vsir_program_ensure_ret(struct vsir_program *program, return VKD3D_OK; } -static bool add_signature_element(struct shader_signature *signature, const char *semantic_name, - uint32_t semantic_index, uint32_t mask, uint32_t register_index, +static struct signature_element *add_signature_element(struct shader_signature *signature, + const char *semantic_name, uint32_t semantic_index, uint32_t mask, uint32_t register_index, enum vkd3d_shader_interpolation_mode interpolation_mode) { struct signature_element *new_elements, *e; if (!(new_elements = vkd3d_realloc(signature->elements, (signature->element_count + 1) * sizeof(*signature->elements)))) - return false; + return NULL; signature->elements = new_elements; e = &signature->elements[signature->element_count++]; memset(e, 0, sizeof(*e)); @@ -1164,7 +1504,7 @@ static bool add_signature_element(struct shader_signature *signature, const char e->register_index = register_index; e->target_location = register_index; e->interpolation_mode = interpolation_mode; - return true; + return e; } static enum vkd3d_result vsir_program_add_diffuse_output(struct vsir_program *program, @@ -6362,9 +6702,9 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr struct shader_signature *signature = &program->output_signature; unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u; const struct vkd3d_shader_parameter1 *mask_parameter = NULL; - struct signature_element *new_elements, *clip_element; uint32_t position_signature_idx, position_temp, mask; static const struct vkd3d_shader_location no_loc; + struct signature_element *clip_element; struct vkd3d_shader_instruction *ins; unsigned int plane_count; size_t new_pos; @@ -6422,33 +6762,20 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr plane_count = vkd3d_popcount(mask); - if (!(new_elements = vkd3d_realloc(signature->elements, - (signature->element_count + 2) * sizeof(*signature->elements)))) + /* Register mask is ignored since we operate after I/O normalisation. */ + if (!(clip_element = add_signature_element(signature, "SV_ClipDistance", 0, + vkd3d_write_mask_from_component_count(min(plane_count, 4)), 0, VKD3DSIM_NONE))) return VKD3D_ERROR_OUT_OF_MEMORY; - signature->elements = new_elements; - - low_signature_idx = signature->element_count; - clip_element = &signature->elements[signature->element_count++]; - memset(clip_element, 0, sizeof(*clip_element)); + low_signature_idx = clip_element - signature->elements; clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; - clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; - clip_element->register_count = 1; - clip_element->mask = vkd3d_write_mask_from_component_count(min(plane_count, 4)); - clip_element->used_mask = clip_element->mask; - clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; if (plane_count > 4) { - high_signature_idx = signature->element_count; - clip_element = &signature->elements[signature->element_count++]; - memset(clip_element, 0, sizeof(*clip_element)); + if (!(clip_element = add_signature_element(signature, "SV_ClipDistance", 1, + vkd3d_write_mask_from_component_count(plane_count - 4), 0, VKD3DSIM_NONE))) + return VKD3D_ERROR_OUT_OF_MEMORY; + high_signature_idx = clip_element - signature->elements; clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; - clip_element->semantic_index = 1; - clip_element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; - clip_element->register_count = 1; - clip_element->mask = vkd3d_write_mask_from_component_count(plane_count - 4); - clip_element->used_mask = clip_element->mask; - clip_element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; } /* We're going to be reading from the output position, so we need to go @@ -8400,8 +8727,9 @@ static void vsir_validate_dst_count(struct validation_context *ctx, { if (instruction->dst_count != count) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, - "Invalid destination count %u for an instruction of type %#x, expected %u.", - instruction->dst_count, instruction->opcode, count); + "Invalid destination parameter count %u for instruction \"%s\" (%#x); expected %u.", + instruction->dst_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); } static void vsir_validate_src_count(struct validation_context *ctx, @@ -8409,8 +8737,9 @@ static void vsir_validate_src_count(struct validation_context *ctx, { if (instruction->src_count != count) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, - "Invalid source count %u for an instruction of type %#x, expected %u.", - instruction->src_count, instruction->opcode, count); + "Invalid source parameter count %u for instruction \"%s\" (%#x); expected %u.", + instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); } static bool vsir_validate_src_min_count(struct validation_context *ctx, @@ -8419,8 +8748,9 @@ static bool vsir_validate_src_min_count(struct validation_context *ctx, if (instruction->src_count < count) { validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, - "Invalid source count %u for an instruction of type %#x, expected at least %u.", - instruction->src_count, instruction->opcode, count); + "Invalid source parameter count %u for instruction \"%s\" (%#x); expected at least %u.", + instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); return false; } @@ -8433,8 +8763,9 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx, if (instruction->src_count > count) { validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, - "Invalid source count %u for an instruction of type %#x, expected at most %u.", - instruction->src_count, instruction->opcode, count); + "Invalid source parameter count %u for instruction \"%s\" (%#x); expected at most %u.", + instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); return false; } @@ -8922,7 +9253,9 @@ static void vsir_validate_cf_type(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction, enum vsir_control_flow_type expected_type) { if (ctx->program->cf_type != expected_type) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x in %s shader.", + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, + "Invalid instruction \"%s\" (%#x) in %s shader.", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode, name_from_cf_type(ctx->program->cf_type)); } @@ -8941,12 +9274,12 @@ static void vsir_validate_hull_shader_phase(struct validation_context *ctx, { if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, - "Phase instruction %#x is only valid in a hull shader.", - instruction->opcode); + "Phase instruction \"%s\" (%#x) is only valid in a hull shader.", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); if (ctx->depth != 0) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, - "Phase instruction %#x must appear to top level.", - instruction->opcode); + "Phase instruction \"%s\" (%#x) must appear at the top level.", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); ctx->phase = instruction->opcode; ctx->dcl_temps_found = false; } @@ -9711,8 +10044,8 @@ static void vsir_validate_instruction(struct validation_context *ctx) default: if (!vsir_instruction_is_dcl(instruction)) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, - "Instruction %#x appear before any phase instruction in a hull shader.", - instruction->opcode); + "Instruction \"%s\" (%#x) appears before any phase instruction in a hull shader.", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); break; } } @@ -9732,8 +10065,8 @@ static void vsir_validate_instruction(struct validation_context *ctx) default: if (!vsir_instruction_is_dcl(instruction)) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, - "Invalid instruction %#x outside any block.", - instruction->opcode); + "Invalid instruction \"%s\" (%#x) outside any block.", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); break; } } diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c index 4f37468af86..08519787b0a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/msl.c +++ b/libs/vkd3d/libs/vkd3d-shader/msl.c @@ -48,7 +48,7 @@ struct msl_generator const char *prefix; bool failed; - bool write_depth; + bool read_vertex_id; const struct vkd3d_shader_interface_info *interface_info; }; @@ -57,10 +57,12 @@ struct msl_resource_type_info { size_t read_coord_size; bool array; - bool lod; const char *type_suffix; }; +static void msl_print_subscript(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, + const struct vkd3d_shader_src_param *rel_addr, unsigned int offset); + static void VKD3D_PRINTF_FUNC(3, 4) msl_compiler_error(struct msl_generator *gen, enum vkd3d_shader_error error, const char *fmt, ...) { @@ -76,17 +78,17 @@ static const struct msl_resource_type_info *msl_get_resource_type_info(enum vkd3 { static const struct msl_resource_type_info info[] = { - [VKD3D_SHADER_RESOURCE_NONE] = {0, false, false, "none"}, - [VKD3D_SHADER_RESOURCE_BUFFER] = {1, false, false, "_buffer"}, - [VKD3D_SHADER_RESOURCE_TEXTURE_1D] = {1, false, false, "1d"}, - [VKD3D_SHADER_RESOURCE_TEXTURE_2D] = {2, false, true, "2d"}, - [VKD3D_SHADER_RESOURCE_TEXTURE_2DMS] = {2, false, false, "2d_ms"}, - [VKD3D_SHADER_RESOURCE_TEXTURE_3D] = {3, false, true, "3d"}, - [VKD3D_SHADER_RESOURCE_TEXTURE_CUBE] = {2, false, true, "cube"}, - [VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY] = {1, true, false, "1d_array"}, - [VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY] = {2, true, true, "2d_array"}, - [VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY] = {2, true, false, "2d_ms_array"}, - [VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY] = {2, true, true, "cube_array"}, + [VKD3D_SHADER_RESOURCE_NONE] = {0, 0, "none"}, + [VKD3D_SHADER_RESOURCE_BUFFER] = {1, 0, "_buffer"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_1D] = {1, 0, "1d"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_2D] = {2, 0, "2d"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_2DMS] = {2, 0, "2d_ms"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_3D] = {3, 0, "3d"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_CUBE] = {2, 0, "cube"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY] = {1, 1, "1d_array"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY] = {2, 1, "2d_array"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY] = {2, 1, "2d_ms_array"}, + [VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY] = {2, 1, "cube_array"}, }; if (!t || t >= ARRAY_SIZE(info)) @@ -359,25 +361,40 @@ static enum msl_data_type msl_print_register_name(struct vkd3d_string_buffer *bu vkd3d_string_buffer_printf(buffer, "", reg->type); return MSL_DATA_UNION; } - if (reg->idx[0].rel_addr || reg->idx[1].rel_addr || reg->idx[2].rel_addr) + if (reg->idx[0].rel_addr || reg->idx[1].rel_addr) { msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled constant buffer register indirect addressing."); vkd3d_string_buffer_printf(buffer, "", reg->type); return MSL_DATA_UNION; } + /* FIXME: This should use vkd3d_shader_find_descriptor() to + * find the resource index/space from the resource ID. */ if (!(binding = msl_get_cbv_binding(gen, 0, reg->idx[1].offset))) { msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, - "Cannot finding binding for CBV register %u.", reg->idx[0].offset); + "No descriptor binding specified for CBV %u.", reg->idx[0].offset); vkd3d_string_buffer_printf(buffer, "", reg->type); return MSL_DATA_UNION; } msl_print_cbv_name(buffer, binding->binding); - vkd3d_string_buffer_printf(buffer, "[%u]", reg->idx[2].offset); + msl_print_subscript(buffer, gen, reg->idx[2].rel_addr, reg->idx[2].offset); return MSL_DATA_UNION; } + case VKD3DSPR_IDXTEMP: + vkd3d_string_buffer_printf(buffer, "x%u", reg->idx[0].offset); + msl_print_subscript(buffer, gen, reg->idx[1].rel_addr, reg->idx[1].offset); + return MSL_DATA_UNION; + + case VKD3DSPR_SAMPLEMASK: + if (gen->program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled sample coverage mask in shader type #%x.", + gen->program->shader_version.type); + vkd3d_string_buffer_printf(buffer, "o_mask"); + return MSL_DATA_FLOAT; + default: msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled register type %#x.", reg->type); @@ -488,6 +505,9 @@ static void msl_print_src_with_type(struct vkd3d_string_buffer *buffer, struct m case VKD3DSPSM_ABS: vkd3d_string_buffer_printf(buffer, "abs(%s)", str->buffer); break; + case VKD3DSPSM_ABSNEG: + vkd3d_string_buffer_printf(buffer, "-abs(%s)", str->buffer); + break; default: vkd3d_string_buffer_printf(buffer, "(%s)", vsir_src->modifiers, str->buffer); @@ -539,12 +559,34 @@ static uint32_t msl_dst_init(struct msl_dst *msl_dst, struct msl_generator *gen, return write_mask; } +static void msl_print_subscript(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, + const struct vkd3d_shader_src_param *rel_addr, unsigned int offset) +{ + struct msl_src r; + + if (!rel_addr) + { + vkd3d_string_buffer_printf(buffer, "[%u]", offset); + return; + } + + msl_src_init(&r, gen, rel_addr, VKD3DSP_WRITEMASK_0); + vkd3d_string_buffer_printf(buffer, "[%s", r.str->buffer); + if (offset) + vkd3d_string_buffer_printf(buffer, " + %u", offset); + vkd3d_string_buffer_printf(buffer, "]"); + msl_src_cleanup(&r, &gen->string_buffers); +} + static void VKD3D_PRINTF_FUNC(3, 4) msl_print_assignment( struct msl_generator *gen, struct msl_dst *dst, const char *format, ...) { uint32_t modifiers = dst->vsir->modifiers; va_list args; + /* It is always legitimate to ignore _pp. */ + modifiers &= ~VKD3DSPDM_PARTIALPRECISION; + if (dst->vsir->shift) msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled destination shift %#x.", dst->vsir->shift); @@ -570,10 +612,12 @@ static void VKD3D_PRINTF_FUNC(3, 4) msl_print_assignment( static void msl_unhandled(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) { + const char *name = vsir_opcode_get_name(ins->opcode, ""); + msl_print_indent(gen->buffer, gen->indent); - vkd3d_string_buffer_printf(gen->buffer, "/* */\n", ins->opcode); + vkd3d_string_buffer_printf(gen->buffer, "/* */\n", name, ins->opcode); msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled instruction %#x.", ins->opcode); + "Internal compiler error: Unhandled instruction \"%s\" (%#x).", name, ins->opcode); } static void msl_binop(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *op) @@ -695,19 +739,36 @@ static void msl_begin_block(struct msl_generator *gen) ++gen->indent; } -static void msl_if(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) +static void msl_print_condition(struct vkd3d_string_buffer *buffer, struct msl_generator *gen, + enum vkd3d_shader_conditional_op op, const struct vkd3d_shader_src_param *arg) { const char *condition; struct msl_src src; - msl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); + msl_src_init(&src, gen, arg, VKD3DSP_WRITEMASK_0); - msl_print_indent(gen->buffer, gen->indent); - condition = ins->flags == VKD3D_SHADER_CONDITIONAL_OP_NZ ? "bool" : "!bool"; - vkd3d_string_buffer_printf(gen->buffer, "if (%s(%s))\n", condition, src.str->buffer); + condition = op == VKD3D_SHADER_CONDITIONAL_OP_NZ ? "bool" : "!bool"; + vkd3d_string_buffer_printf(buffer, "if (%s(%s))\n", condition, src.str->buffer); msl_src_cleanup(&src, &gen->string_buffers); +} +static void msl_discard(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) +{ + /* Note that discard_fragment() in Metal 2.2 and earlier behaves like + * SPIR-V OpKill, while in Metal 2.3 and later it behaves like + * OpDemoteToHelperInvocationEXT. We assume we have at least Metal 3 + * here. */ + msl_print_indent(gen->buffer, gen->indent); + msl_print_condition(gen->buffer, gen, ins->flags, &ins->src[0]); + msl_print_indent(gen->buffer, gen->indent + 1); + vkd3d_string_buffer_printf(gen->buffer, "discard_fragment();\n"); +} + +static void msl_if(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) +{ + msl_print_indent(gen->buffer, gen->indent); + msl_print_condition(gen->buffer, gen, ins->flags, &ins->src[0]); msl_begin_block(gen); } @@ -719,6 +780,50 @@ static void msl_else(struct msl_generator *gen) msl_begin_block(gen); } +static void msl_loop(struct msl_generator *gen) +{ + msl_print_indent(gen->buffer, gen->indent); + vkd3d_string_buffer_printf(gen->buffer, "for (;;)\n"); + msl_begin_block(gen); +} + +static void msl_break(struct msl_generator *gen) +{ + msl_print_indent(gen->buffer, gen->indent); + vkd3d_string_buffer_printf(gen->buffer, "break;\n"); +} + +static void msl_switch(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) +{ + struct msl_src src; + + msl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); + + msl_print_indent(gen->buffer, gen->indent); + vkd3d_string_buffer_printf(gen->buffer, "switch (%s)\n", src.str->buffer); + msl_begin_block(gen); + + msl_src_cleanup(&src, &gen->string_buffers); +} + +static void msl_case(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) +{ + struct msl_src src; + + msl_src_init(&src, gen, &ins->src[0], VKD3DSP_WRITEMASK_0); + + msl_print_indent(gen->buffer, gen->indent); + vkd3d_string_buffer_printf(gen->buffer, "case %s:\n", src.str->buffer); + + msl_src_cleanup(&src, &gen->string_buffers); +} + +static void msl_default(struct msl_generator *gen) +{ + msl_print_indent(gen->buffer, gen->indent); + vkd3d_string_buffer_printf(gen->buffer, "default:\n"); +} + static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) { const struct msl_resource_type_info *resource_type_info; @@ -728,6 +833,7 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct enum vkd3d_shader_resource_type resource_type; struct vkd3d_string_buffer *read; enum vkd3d_data_type data_type; + unsigned int srv_binding; uint32_t coord_mask; struct msl_dst dst; @@ -757,30 +863,39 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct data_type = VKD3D_DATA_FLOAT; } - if ((resource_type_info = msl_get_resource_type_info(resource_type))) - { - coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->read_coord_size); - } - else + if (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBE + || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY + || (ins->opcode != VKD3DSIH_LD2DMS + && (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS + || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY))) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, + "Texel fetches from resource type %#x are not supported.", resource_type); + + if (!(resource_type_info = msl_get_resource_type_info(resource_type))) { msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled resource type %#x.", resource_type); - coord_mask = vkd3d_write_mask_from_component_count(2); + resource_type_info = msl_get_resource_type_info(VKD3D_SHADER_RESOURCE_TEXTURE_2D); } + coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->read_coord_size); - if (!(binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) + if ((binding = msl_get_srv_binding(gen, resource_space, resource_idx, resource_type))) + { + srv_binding = binding->binding; + } + else { msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_BINDING_NOT_FOUND, - "Cannot finding binding for SRV register %u index %u space %u.", + "No descriptor binding specified for SRV %u (index %u, space %u).", resource_id, resource_idx, resource_space); - return; + srv_binding = 0; } msl_dst_init(&dst, gen, ins, &ins->dst[0]); read = vkd3d_string_buffer_get(&gen->string_buffers); vkd3d_string_buffer_printf(read, "as_type("); - msl_print_srv_name(read, gen, binding->binding, resource_type_info, data_type); + msl_print_srv_name(read, gen, srv_binding, resource_type_info, data_type); vkd3d_string_buffer_printf(read, ".read("); msl_print_src_with_type(read, gen, &ins->src[0], coord_mask, VKD3D_DATA_UINT); if (resource_type_info->array) @@ -788,10 +903,13 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct vkd3d_string_buffer_printf(read, ", "); msl_print_src_with_type(read, gen, &ins->src[0], coord_mask + 1, VKD3D_DATA_UINT); } - if (resource_type_info->lod) + if (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) { vkd3d_string_buffer_printf(read, ", "); - msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VKD3D_DATA_UINT); + if (ins->opcode != VKD3DSIH_LD2DMS) + msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VKD3D_DATA_UINT); + else + msl_print_src_with_type(read, gen, &ins->src[2], VKD3DSP_WRITEMASK_0, VKD3D_DATA_UINT); } vkd3d_string_buffer_printf(read, "))"); msl_print_swizzle(read, ins->src[1].swizzle, ins->dst[0].write_mask); @@ -857,12 +975,51 @@ static void msl_movc(struct msl_generator *gen, const struct vkd3d_shader_instru msl_dst_cleanup(&dst, &gen->string_buffers); } +static void msl_mul64(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) +{ + struct msl_src src[2]; + struct msl_dst dst; + uint32_t mask; + + if (ins->dst[0].reg.type != VKD3DSPR_NULL) + { + /* TODO: mulhi(). */ + mask = msl_dst_init(&dst, gen, ins, &ins->dst[0]); + msl_print_assignment(gen, &dst, ""); + msl_dst_cleanup(&dst, &gen->string_buffers); + + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled 64-bit integer multiplication."); + } + + if (ins->dst[1].reg.type != VKD3DSPR_NULL) + { + mask = msl_dst_init(&dst, gen, ins, &ins->dst[1]); + msl_src_init(&src[0], gen, &ins->src[0], mask); + msl_src_init(&src[1], gen, &ins->src[1], mask); + + msl_print_assignment(gen, &dst, "%s * %s", src[0].str->buffer, src[1].str->buffer); + + msl_src_cleanup(&src[1], &gen->string_buffers); + msl_src_cleanup(&src[0], &gen->string_buffers); + msl_dst_cleanup(&dst, &gen->string_buffers); + } +} + static void msl_ret(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) { msl_print_indent(gen->buffer, gen->indent); vkd3d_string_buffer_printf(gen->buffer, "return;\n"); } +static void msl_dcl_indexable_temp(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) +{ + msl_print_indent(gen->buffer, gen->indent); + vkd3d_string_buffer_printf(gen->buffer, "vkd3d_vec4 x%u[%u];\n", + ins->declaration.indexable_temp.register_idx, + ins->declaration.indexable_temp.register_size); +} + static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) { gen->location = ins->location; @@ -870,13 +1027,29 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d switch (ins->opcode) { case VKD3DSIH_ADD: + case VKD3DSIH_IADD: msl_binop(gen, ins, "+"); break; case VKD3DSIH_AND: msl_binop(gen, ins, "&"); break; + case VKD3DSIH_BREAK: + msl_break(gen); + break; + case VKD3DSIH_CASE: + msl_case(gen, ins); + break; + case VKD3DSIH_DCL_INDEXABLE_TEMP: + msl_dcl_indexable_temp(gen, ins); + break; case VKD3DSIH_NOP: break; + case VKD3DSIH_DEFAULT: + msl_default(gen); + break; + case VKD3DSIH_DISCARD: + msl_discard(gen, ins); + break; case VKD3DSIH_DIV: msl_binop(gen, ins, "/"); break; @@ -893,8 +1066,11 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d msl_else(gen); break; case VKD3DSIH_ENDIF: + case VKD3DSIH_ENDLOOP: + case VKD3DSIH_ENDSWITCH: msl_end_block(gen); break; + case VKD3DSIH_EQO: case VKD3DSIH_IEQ: msl_relop(gen, ins, "=="); break; @@ -911,6 +1087,7 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d msl_cast(gen, ins, "uint"); break; case VKD3DSIH_GEO: + case VKD3DSIH_IGE: msl_relop(gen, ins, ">="); break; case VKD3DSIH_IF: @@ -923,7 +1100,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d case VKD3DSIH_USHR: msl_binop(gen, ins, ">>"); break; + case VKD3DSIH_ILT: case VKD3DSIH_LTO: + case VKD3DSIH_ULT: msl_relop(gen, ins, "<"); break; case VKD3DSIH_MAD: @@ -935,20 +1114,30 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d case VKD3DSIH_MIN: msl_intrinsic(gen, ins, "min"); break; + case VKD3DSIH_IMUL: + msl_mul64(gen, ins); + break; case VKD3DSIH_INE: case VKD3DSIH_NEU: msl_relop(gen, ins, "!="); break; + case VKD3DSIH_INEG: + msl_unary_op(gen, ins, "-"); + break; case VKD3DSIH_ITOF: case VKD3DSIH_UTOF: msl_cast(gen, ins, "float"); break; case VKD3DSIH_LD: + case VKD3DSIH_LD2DMS: msl_ld(gen, ins); break; case VKD3DSIH_LOG: msl_intrinsic(gen, ins, "log2"); break; + case VKD3DSIH_LOOP: + msl_loop(gen); + break; case VKD3DSIH_MOV: msl_mov(gen, ins); break; @@ -985,6 +1174,12 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d case VKD3DSIH_SQRT: msl_intrinsic(gen, ins, "sqrt"); break; + case VKD3DSIH_SWITCH: + msl_switch(gen, ins); + break; + case VKD3DSIH_XOR: + msl_binop(gen, ins, "^"); + break; default: msl_unhandled(gen, ins); break; @@ -1008,21 +1203,48 @@ static void msl_generate_input_struct_declarations(struct msl_generator *gen) if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) continue; - if (e->sysval_semantic) + switch (e->sysval_semantic) { - if (e->sysval_semantic == VKD3D_SHADER_SV_IS_FRONT_FACE) - { + case VKD3D_SHADER_SV_NONE: + break; + + case VKD3D_SHADER_SV_POSITION: if (type != VKD3D_SHADER_TYPE_PIXEL) msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled SV_IS_FRONT_FACE in shader type #%x.", type); + "Internal compiler error: Unhandled SV_POSITION in shader type #%x.", type); + msl_print_indent(gen->buffer, 1); + vkd3d_string_buffer_printf(buffer, "float4 position [[position]];\n"); + continue; + + case VKD3D_SHADER_SV_VERTEX_ID: + if (type != VKD3D_SHADER_TYPE_VERTEX) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled SV_VERTEX_ID in shader type #%x.", type); + gen->read_vertex_id = true; + continue; + case VKD3D_SHADER_SV_IS_FRONT_FACE: + if (type != VKD3D_SHADER_TYPE_PIXEL) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled SV_IS_FRONT_FACE in shader type #%x.", type); msl_print_indent(gen->buffer, 1); vkd3d_string_buffer_printf(buffer, "bool is_front_face [[front_facing]];\n"); continue; - } - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled system value %#x.", e->sysval_semantic); - continue; + + case VKD3D_SHADER_SV_SAMPLE_INDEX: + if (type != VKD3D_SHADER_TYPE_PIXEL) + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled SV_SAMPLE_INDEX in shader type #%x.", type); + msl_print_indent(gen->buffer, 1); + vkd3d_string_buffer_printf(buffer, "uint sample_index [[sample_id]];\n"); + continue; + + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled system value %#x.", e->sysval_semantic); + msl_print_indent(gen->buffer, 1); + vkd3d_string_buffer_printf(buffer, ";\n", e->sysval_semantic); + continue; } if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) @@ -1059,15 +1281,15 @@ static void msl_generate_input_struct_declarations(struct msl_generator *gen) break; } - vkd3d_string_buffer_printf(buffer, "shader_in_%u ", i); + vkd3d_string_buffer_printf(buffer, "shader_in_%u [[", i); switch (type) { case VKD3D_SHADER_TYPE_VERTEX: - vkd3d_string_buffer_printf(gen->buffer, "[[attribute(%u)]]", e->target_location); + vkd3d_string_buffer_printf(gen->buffer, "attribute(%u)", e->target_location); break; case VKD3D_SHADER_TYPE_PIXEL: - vkd3d_string_buffer_printf(gen->buffer, "[[user(locn%u)]]", e->target_location); + vkd3d_string_buffer_printf(gen->buffer, "user(locn%u)", e->target_location); break; default: msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, @@ -1081,13 +1303,16 @@ static void msl_generate_input_struct_declarations(struct msl_generator *gen) case VKD3DSIM_LINEAR: case VKD3DSIM_NONE: break; + case VKD3DSIM_CONSTANT: + vkd3d_string_buffer_printf(gen->buffer, ", flat"); + break; default: msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled interpolation mode %#x.", e->interpolation_mode); break; } - vkd3d_string_buffer_printf(buffer, ";\n"); + vkd3d_string_buffer_printf(buffer, "]];\n"); } vkd3d_string_buffer_printf(buffer, "};\n\n"); @@ -1138,15 +1363,8 @@ static void msl_generate_output_struct_declarations(struct msl_generator *gen) { e = &signature->elements[i]; - if (e->sysval_semantic == VKD3D_SHADER_SV_DEPTH) - { - gen->write_depth = true; - msl_print_indent(gen->buffer, 1); - vkd3d_string_buffer_printf(buffer, "float shader_out_depth [[depth(any)]];\n"); - continue; - } - - if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) + if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED + || e->sysval_semantic == VKD3D_SHADER_SV_DEPTH) continue; if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) @@ -1209,6 +1427,18 @@ static void msl_generate_output_struct_declarations(struct msl_generator *gen) vkd3d_string_buffer_printf(buffer, ";\n"); } + if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_DEPTHOUT)) + { + msl_print_indent(gen->buffer, 1); + vkd3d_string_buffer_printf(buffer, "float shader_out_depth [[depth(any)]];\n"); + } + + if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) + { + msl_print_indent(gen->buffer, 1); + vkd3d_string_buffer_printf(buffer, "uint shader_out_mask [[sample_mask]];\n"); + } + vkd3d_string_buffer_printf(buffer, "};\n\n"); } @@ -1227,23 +1457,45 @@ static void msl_generate_entrypoint_prologue(struct msl_generator *gen) continue; vkd3d_string_buffer_printf(buffer, " %s_in[%u]", gen->prefix, e->register_index); - if (e->sysval_semantic == VKD3D_SHADER_SV_NONE) - { - msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); - msl_print_write_mask(buffer, e->mask); - vkd3d_string_buffer_printf(buffer, " = input.shader_in_%u", i); - msl_print_write_mask(buffer, e->mask); - } - else if (e->sysval_semantic == VKD3D_SHADER_SV_IS_FRONT_FACE) - { - vkd3d_string_buffer_printf(buffer, ".u = uint4(input.is_front_face ? 0xffffffffu : 0u, 0, 0, 0)"); - } - else + switch (e->sysval_semantic) { - vkd3d_string_buffer_printf(buffer, " = ", e->sysval_semantic); - msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled system value %#x input.", e->sysval_semantic); + case VKD3D_SHADER_SV_NONE: + msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = input.shader_in_%u", i); + break; + + case VKD3D_SHADER_SV_POSITION: + msl_print_register_datatype(buffer, gen, VKD3D_DATA_FLOAT); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = float4(input.position.xyz, 1.0f / input.position.w)"); + break; + + case VKD3D_SHADER_SV_VERTEX_ID: + msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = uint4(vertex_id, 0u, 0u, 0u)"); + break; + + case VKD3D_SHADER_SV_IS_FRONT_FACE: + msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = uint4(input.is_front_face ? 0xffffffffu : 0u, 0, 0, 0)"); + break; + + case VKD3D_SHADER_SV_SAMPLE_INDEX: + msl_print_register_datatype(buffer, gen, VKD3D_DATA_UINT); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = uint4(input.sample_index, 0u, 0u, 0u)"); + break; + + default: + vkd3d_string_buffer_printf(buffer, " = ", e->sysval_semantic); + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled system value %#x input.", e->sysval_semantic); + break; } + msl_print_write_mask(buffer, e->mask); vkd3d_string_buffer_printf(buffer, ";\n"); } } @@ -1259,12 +1511,6 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) { e = &signature->elements[i]; - if (e->sysval_semantic == VKD3D_SHADER_SV_DEPTH) - { - vkd3d_string_buffer_printf(buffer, " output.shader_out_depth = shader_out_depth;\n"); - continue; - } - if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) continue; @@ -1279,6 +1525,8 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); msl_print_write_mask(buffer, e->mask); break; + case VKD3D_SHADER_SV_DEPTH: + continue; default: vkd3d_string_buffer_printf(buffer, " ", e->sysval_semantic); msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, @@ -1286,6 +1534,9 @@ static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) } vkd3d_string_buffer_printf(buffer, ";\n"); } + + if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) + vkd3d_string_buffer_printf(gen->buffer, " output.shader_out_mask = as_type(o_mask);\n"); } static void msl_generate_entrypoint(struct msl_generator *gen) @@ -1316,6 +1567,12 @@ static void msl_generate_entrypoint(struct msl_generator *gen) "constant descriptor *descriptors [[buffer(0)]],\n"); } + if (gen->read_vertex_id) + { + msl_print_indent(gen->buffer, 2); + vkd3d_string_buffer_printf(gen->buffer, "uint vertex_id [[vertex_id]],\n"); + } + msl_print_indent(gen->buffer, 2); vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_in input [[stage_in]])\n{\n", gen->prefix); @@ -1323,18 +1580,22 @@ static void msl_generate_entrypoint(struct msl_generator *gen) vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 %s_in[%u];\n", gen->prefix, 32); vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 %s_out[%u];\n", gen->prefix, 32); vkd3d_string_buffer_printf(gen->buffer, " vkd3d_%s_out output;\n", gen->prefix); - - if (gen->write_depth) - vkd3d_string_buffer_printf(gen->buffer, " float shader_out_depth;\n"); + if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) + vkd3d_string_buffer_printf(gen->buffer, " float o_mask;\n"); + vkd3d_string_buffer_printf(gen->buffer, "\n"); msl_generate_entrypoint_prologue(gen); vkd3d_string_buffer_printf(gen->buffer, " %s_main(%s_in, %s_out", gen->prefix, gen->prefix, gen->prefix); - if (gen->write_depth) - vkd3d_string_buffer_printf(gen->buffer, ", shader_out_depth"); + if (gen->read_vertex_id) + vkd3d_string_buffer_printf(gen->buffer, ", vertex_id"); + if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_DEPTHOUT)) + vkd3d_string_buffer_printf(gen->buffer, ", output.shader_out_depth"); + if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) + vkd3d_string_buffer_printf(gen->buffer, ", o_mask"); if (gen->program->descriptors.descriptor_count) vkd3d_string_buffer_printf(gen->buffer, ", descriptors"); - vkd3d_string_buffer_printf(gen->buffer, ");\n"); + vkd3d_string_buffer_printf(gen->buffer, ");\n\n"); msl_generate_entrypoint_epilogue(gen); @@ -1353,7 +1614,7 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader vkd3d_string_buffer_printf(gen->buffer, "#include \n\n"); vkd3d_string_buffer_printf(gen->buffer, "using namespace metal;\n\n"); - if (gen->program->global_flags) + if (gen->program->global_flags & ~VKD3DSGF_REFACTORING_ALLOWED) msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, "Internal compiler error: Unhandled global flags %#"PRIx64".", (uint64_t)gen->program->global_flags); @@ -1388,11 +1649,16 @@ static int msl_generator_generate(struct msl_generator *gen, struct vkd3d_shader msl_generate_output_struct_declarations(gen); vkd3d_string_buffer_printf(gen->buffer, - "void %s_main(thread vkd3d_vec4 *v, " + "static void %s_main(thread vkd3d_vec4 *v, " "thread vkd3d_vec4 *o", gen->prefix); - if (gen->write_depth) - vkd3d_string_buffer_printf(gen->buffer, ", thread float& o_depth"); + + if (gen->read_vertex_id) + vkd3d_string_buffer_printf(gen->buffer, ", uint vertex_id"); + if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_DEPTHOUT)) + vkd3d_string_buffer_printf(gen->buffer, ", thread float &o_depth"); + if (bitmap_is_set(gen->program->io_dcls, VKD3DSPR_SAMPLEMASK)) + vkd3d_string_buffer_printf(gen->buffer, ", thread float &o_mask"); if (gen->program->descriptors.descriptor_count) vkd3d_string_buffer_printf(gen->buffer, ", constant descriptor *descriptors"); vkd3d_string_buffer_printf(gen->buffer, ")\n{\n"); diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.h b/libs/vkd3d/libs/vkd3d-shader/preproc.h index a98c8ae3df5..9217237d8d3 100644 --- a/libs/vkd3d/libs/vkd3d-shader/preproc.h +++ b/libs/vkd3d/libs/vkd3d-shader/preproc.h @@ -38,6 +38,7 @@ struct preproc_buffer { void *lexer_buffer; struct vkd3d_shader_location location; + bool eof; }; struct preproc_file @@ -125,7 +126,6 @@ struct preproc_ctx int lookahead_token; bool last_was_newline; - bool last_was_eof; bool last_was_defined; bool error; diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l index 4a8d0fddae1..5c56fba0229 100644 --- a/libs/vkd3d/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l @@ -20,6 +20,7 @@ %{ +#include "preproc.h" #include "preproc.tab.h" #undef ERROR /* defined in wingdi.h */ @@ -71,8 +72,8 @@ INT_SUFFIX [uUlL]{0,2} %% -"//" {yy_push_state(CXX_COMMENT, yyscanner);} -"/*" {yy_push_state(C_COMMENT, yyscanner);} +"//" {yy_push_state(CXX_COMMENT, yyscanner);} +"/*" {yy_push_state(C_COMMENT, yyscanner);} \\{NEWLINE} {} \n { yy_pop_state(yyscanner); @@ -80,7 +81,11 @@ INT_SUFFIX [uUlL]{0,2} return T_NEWLINE; } "*/" {yy_pop_state(yyscanner);} -<> {yy_pop_state(yyscanner);} +<> { + yy_pop_state(yyscanner); + BEGIN(INITIAL); + yyterminate(); + } . {} \n {} @@ -196,6 +201,10 @@ INT_SUFFIX [uUlL]{0,2} BEGIN(INITIAL); return T_NEWLINE; } +<> { + BEGIN(INITIAL); + yyterminate(); + } {WS}+ {} [-()\[\]{},+!*/<>&|^?:] {return yytext[0];} @@ -250,8 +259,19 @@ static bool should_concat(struct preproc_ctx *ctx) return !macro || macro->arg_count; } +static struct preproc_buffer *preproc_get_top_buffer(struct preproc_ctx *ctx) +{ + if (ctx->expansion_count) + return &ctx->expansion_stack[ctx->expansion_count - 1].buffer; + if (ctx->file_count) + return &ctx->file_stack[ctx->file_count - 1].buffer; + return NULL; +} + static void preproc_pop_buffer(struct preproc_ctx *ctx) { + struct preproc_buffer *buffer; + if (ctx->expansion_count) { struct preproc_expansion *exp = &ctx->expansion_stack[ctx->expansion_count - 1]; @@ -290,10 +310,8 @@ static void preproc_pop_buffer(struct preproc_ctx *ctx) TRACE("File stack size is now %zu.\n", ctx->file_count); } - if (ctx->expansion_count) - yy_switch_to_buffer(ctx->expansion_stack[ctx->expansion_count - 1].buffer.lexer_buffer, ctx->scanner); - else if (ctx->file_count) - yy_switch_to_buffer(ctx->file_stack[ctx->file_count - 1].buffer.lexer_buffer, ctx->scanner); + if ((buffer = preproc_get_top_buffer(ctx))) + yy_switch_to_buffer(buffer->lexer_buffer, ctx->scanner); } static int return_token(int token, YYSTYPE *lval, const char *text) @@ -347,6 +365,7 @@ static bool preproc_push_expansion(struct preproc_ctx *ctx, exp->text = text; exp->buffer.lexer_buffer = yy_scan_bytes(text->text.buffer, text->text.content_size, ctx->scanner); exp->buffer.location = text->location; + exp->buffer.eof = false; exp->macro = macro; exp->arg_values = arg_values; TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count); @@ -407,18 +426,17 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) } else { - if (ctx->last_was_eof) + if (preproc_get_top_buffer(ctx)->eof) { preproc_pop_buffer(ctx); if (!ctx->file_count) return 0; } - ctx->last_was_eof = false; VKD3D_ASSERT(ctx->file_count); if (!(token = preproc_lexer_lex(lval, lloc, scanner))) { - ctx->last_was_eof = true; + preproc_get_top_buffer(ctx)->eof = true; /* If we have reached the end of an included file, inject a newline. */ if (ctx->expansion_count) @@ -781,6 +799,7 @@ bool preproc_push_include(struct preproc_ctx *ctx, char *filename, const struct file->buffer.location.source_name = file->filename; file->buffer.location.line = 1; file->buffer.location.column = 1; + file->buffer.eof = false; TRACE("File stack size is now %zu.\n", ctx->file_count); ctx->last_was_newline = true; return true; diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index 1f967c22406..13ebde5cfd5 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -847,57 +847,6 @@ static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, enum vkd3d_s vkd3d_shader_message_context_cleanup(&message_context); } -enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval, - unsigned int index) -{ - switch (sysval) - { - case VKD3D_SHADER_SV_COVERAGE: - case VKD3D_SHADER_SV_DEPTH: - case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL: - case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL: - case VKD3D_SHADER_SV_NONE: - case VKD3D_SHADER_SV_STENCIL_REF: - case VKD3D_SHADER_SV_TARGET: - return VKD3D_SIV_NONE; - case VKD3D_SHADER_SV_POSITION: - return VKD3D_SIV_POSITION; - case VKD3D_SHADER_SV_CLIP_DISTANCE: - return VKD3D_SIV_CLIP_DISTANCE; - case VKD3D_SHADER_SV_CULL_DISTANCE: - return VKD3D_SIV_CULL_DISTANCE; - case VKD3D_SHADER_SV_INSTANCE_ID: - return VKD3D_SIV_INSTANCE_ID; - case VKD3D_SHADER_SV_IS_FRONT_FACE: - return VKD3D_SIV_IS_FRONT_FACE; - case VKD3D_SHADER_SV_PRIMITIVE_ID: - return VKD3D_SIV_PRIMITIVE_ID; - case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX: - return VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX; - case VKD3D_SHADER_SV_SAMPLE_INDEX: - return VKD3D_SIV_SAMPLE_INDEX; - case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: - return VKD3D_SIV_QUAD_U0_TESS_FACTOR + index; - case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: - return VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR + index; - case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: - return VKD3D_SIV_TRIANGLE_U_TESS_FACTOR + index; - case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: - return VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR; - case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: - return VKD3D_SIV_LINE_DETAIL_TESS_FACTOR; - case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: - return VKD3D_SIV_LINE_DENSITY_TESS_FACTOR; - case VKD3D_SHADER_SV_VERTEX_ID: - return VKD3D_SIV_VERTEX_ID; - case VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX: - return VKD3D_SIV_VIEWPORT_ARRAY_INDEX; - default: - FIXME("Unhandled sysval %#x, index %u.\n", sysval, index); - return VKD3D_SIV_NONE; - } -} - struct vkd3d_spirv_stream { uint32_t *words; @@ -4239,7 +4188,7 @@ static bool spirv_compiler_get_register_info(struct spirv_compiler *compiler, if (!(entry = rb_get(&compiler->symbol_table, ®_symbol))) { spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE, - "Unrecognized register (%s).\n", debug_vkd3d_symbol(®_symbol)); + "Unrecognized register (%s).", debug_vkd3d_symbol(®_symbol)); memset(register_info, 0, sizeof(*register_info)); return false; } @@ -4578,70 +4527,6 @@ static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compil return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); } -/* Based on the implementation in the OpenGL Mathematics library. */ -static uint32_t half_to_float(uint16_t value) -{ - uint32_t s = (value & 0x8000u) << 16; - uint32_t e = (value >> 10) & 0x1fu; - uint32_t m = value & 0x3ffu; - - if (!e) - { - if (!m) - { - /* Plus or minus zero */ - return s; - } - else - { - /* Denormalized number -- renormalize it */ - - while (!(m & 0x400u)) - { - m <<= 1; - --e; - } - - ++e; - m &= ~0x400u; - } - } - else if (e == 31u) - { - /* Positive or negative infinity for zero 'm'. - * Nan for non-zero 'm' -- preserve sign and significand bits */ - return s | 0x7f800000u | (m << 13); - } - - /* Normalized number */ - e += 127u - 15u; - m <<= 13; - - /* Assemble s, e and m. */ - return s | (e << 23) | m; -} - -static uint32_t convert_raw_constant32(enum vkd3d_data_type data_type, unsigned int uint_value) -{ - int16_t i; - - /* TODO: native 16-bit support. */ - if (data_type != VKD3D_DATA_UINT16 && data_type != VKD3D_DATA_HALF) - return uint_value; - - if (data_type == VKD3D_DATA_HALF) - return half_to_float(uint_value); - - /* Values in DXIL have no signedness, so it is ambiguous whether 16-bit constants should or - * should not be sign-extended when 16-bit execution is not supported. The AMD RX 580 Windows - * driver has no 16-bit support, and sign-extends all 16-bit constant ints to 32 bits. These - * results differ from SM 5. The RX 6750 XT supports 16-bit execution, so constants are not - * extended, and results match SM 5. It seems best to replicate the sign-extension, and if - * execution is 16-bit, the values will be truncated. */ - i = uint_value; - return (int32_t)i; -} - static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) { @@ -4654,15 +4539,14 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile if (reg->dimension == VSIR_DIMENSION_SCALAR) { for (i = 0; i < component_count; ++i) - values[i] = convert_raw_constant32(reg->data_type, reg->u.immconst_u32[0]); + values[i] = reg->u.immconst_u32[0]; } else { for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) { if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - values[j++] = convert_raw_constant32(reg->data_type, - reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]); + values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]; } } @@ -4806,13 +4690,6 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil switch (icb->data_type) { - case VKD3D_DATA_HALF: - case VKD3D_DATA_UINT16: - /* Scalar only. */ - for (i = 0; i < element_count; ++i) - elements[i] = vkd3d_spirv_get_op_constant(builder, elem_type_id, - convert_raw_constant32(icb->data_type, icb->data[i])); - break; case VKD3D_DATA_FLOAT: case VKD3D_DATA_INT: case VKD3D_DATA_UINT: @@ -9254,7 +9131,9 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, &src[3], VKD3DSP_WRITEMASK_0); break; default: - ERR("Unexpected instruction %#x.\n", instruction->opcode); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, + "Unhandled instruction \"%s\" (%#x).", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); return; } @@ -9935,7 +9814,9 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil op = spirv_compiler_map_atomic_instruction(instruction); if (op == SpvOpMax) { - ERR("Unexpected instruction %#x.\n", instruction->opcode); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, + "Unhandled instruction \"%s\" (%#x).", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); return; } @@ -10014,9 +9895,9 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil if (instruction->flags & VKD3DARF_VOLATILE) { - WARN("Ignoring 'volatile' attribute.\n"); spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_IGNORING_FLAG, - "Ignoring the 'volatile' attribute flag for atomic instruction %#x.", instruction->opcode); + "Ignoring the 'volatile' attribute flag for atomic instruction \"%s\" (%#x).", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); } memory_semantic = (instruction->flags & VKD3DARF_SEQ_CST) @@ -11091,9 +10972,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, /* nothing to do */ break; default: - FIXME("Unhandled instruction %#x.\n", instruction->opcode); spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER, - "Encountered invalid/unhandled instruction handler %#x.", instruction->opcode); + "Unhandled instruction \"%s\" (%#x).", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); break; } diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c index 29b03871e05..ae3fa1650bf 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -261,6 +261,7 @@ enum vkd3d_sm4_opcode VKD3D_SM4_OP_DCL_INPUT_PS_SGV = 0x63, VKD3D_SM4_OP_DCL_INPUT_PS_SIV = 0x64, VKD3D_SM4_OP_DCL_OUTPUT = 0x65, + VKD3D_SM4_OP_DCL_OUTPUT_SGV = 0x66, VKD3D_SM4_OP_DCL_OUTPUT_SIV = 0x67, VKD3D_SM4_OP_DCL_TEMPS = 0x68, VKD3D_SM4_OP_DCL_INDEXABLE_TEMP = 0x69, @@ -1168,7 +1169,7 @@ static void shader_sm4_read_dcl_input_ps(struct vkd3d_shader_instruction *ins, u WARN("No matching signature element for input register %u with mask %#x.\n", dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_DCL, - "No matching signature element for input register %u with mask %#x.\n", + "No matching signature element for input register %u with mask %#x.", dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); } else @@ -1194,7 +1195,7 @@ static void shader_sm4_read_dcl_input_ps_siv(struct vkd3d_shader_instruction *in WARN("No matching signature element for input register %u with mask %#x.\n", dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_DCL, - "No matching signature element for input register %u with mask %#x.\n", + "No matching signature element for input register %u with mask %#x.", dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask); } else @@ -1559,6 +1560,8 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup) shader_sm4_read_dcl_input_ps_siv}, {VKD3D_SM4_OP_DCL_OUTPUT, VKD3DSIH_DCL_OUTPUT, "", "", shader_sm4_read_declaration_dst}, + {VKD3D_SM4_OP_DCL_OUTPUT_SGV, VKD3DSIH_DCL_OUTPUT_SGV, "", "", + shader_sm4_read_declaration_register_semantic}, {VKD3D_SM4_OP_DCL_OUTPUT_SIV, VKD3DSIH_DCL_OUTPUT_SIV, "", "", shader_sm4_read_declaration_register_semantic}, {VKD3D_SM4_OP_DCL_TEMPS, VKD3DSIH_DCL_TEMPS, "", "", @@ -3129,6 +3132,9 @@ bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *s {"position", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_POSITION}, {"sv_position", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_POSITION}, {"sv_primitiveid", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_PRIMITIVE_ID}, + {"sv_isfrontface", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_IS_FRONT_FACE}, + {"sv_rendertargetarrayindex", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX}, + {"sv_viewportarrayindex", true, VKD3D_SHADER_TYPE_GEOMETRY, VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX}, {"sv_outputcontrolpointid", false, VKD3D_SHADER_TYPE_HULL, ~0u}, {"sv_position", false, VKD3D_SHADER_TYPE_HULL, ~0u}, @@ -3255,6 +3261,8 @@ static int signature_element_pointer_compare(const void *x, const void *y) const struct signature_element *f = *(const struct signature_element **)y; int ret; + if ((ret = vkd3d_u32_compare(e->stream_index, f->stream_index))) + return ret; if ((ret = vkd3d_u32_compare(e->register_index, f->register_index))) return ret; return vkd3d_u32_compare(e->mask, f->mask); @@ -3263,12 +3271,17 @@ static int signature_element_pointer_compare(const void *x, const void *y) static void tpf_write_signature(struct tpf_compiler *tpf, const struct shader_signature *signature, uint32_t tag) { bool has_minimum_precision = tpf->program->global_flags & VKD3DSGF_ENABLE_MINIMUM_PRECISION; - bool output = tag == TAG_OSGN || (tag == TAG_PCSG - && tpf->program->shader_version.type == VKD3D_SHADER_TYPE_HULL); + const struct vkd3d_shader_version *version = &tpf->program->shader_version; const struct signature_element **sorted_elements; struct vkd3d_bytecode_buffer buffer = {0}; + bool has_stream_index, output; unsigned int i; + output = tag == TAG_OSGN || (tag == TAG_PCSG && version->type == VKD3D_SHADER_TYPE_HULL); + if (output && version->type == VKD3D_SHADER_TYPE_GEOMETRY && version->major >= 5) + tag = TAG_OSG5; + has_stream_index = tag == TAG_OSG5 || has_minimum_precision; + put_u32(&buffer, signature->element_count); put_u32(&buffer, 8); /* unknown */ @@ -3291,8 +3304,8 @@ static void tpf_write_signature(struct tpf_compiler *tpf, const struct shader_si if (sysval >= VKD3D_SHADER_SV_TARGET) sysval = VKD3D_SHADER_SV_NONE; - if (has_minimum_precision) - put_u32(&buffer, 0); /* FIXME: stream index */ + if (has_stream_index) + put_u32(&buffer, element->stream_index); put_u32(&buffer, 0); /* name */ put_u32(&buffer, element->semantic_index); put_u32(&buffer, sysval); @@ -3306,13 +3319,16 @@ static void tpf_write_signature(struct tpf_compiler *tpf, const struct shader_si for (i = 0; i < signature->element_count; ++i) { const struct signature_element *element = sorted_elements[i]; + size_t name_index = 2 + i * 6; size_t string_offset; - string_offset = put_string(&buffer, element->semantic_name); + if (has_stream_index) + name_index += i + 1; if (has_minimum_precision) - set_u32(&buffer, (2 + i * 8 + 1) * sizeof(uint32_t), string_offset); - else - set_u32(&buffer, (2 + i * 6) * sizeof(uint32_t), string_offset); + name_index += i; + + string_offset = put_string(&buffer, element->semantic_name); + set_u32(&buffer, name_index * sizeof(uint32_t), string_offset); } if (has_minimum_precision) @@ -3843,9 +3859,8 @@ static uint32_t pack_resource_data_type(const enum vkd3d_data_type *resource_dat static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_shader_instruction *ins) { - const struct vkd3d_shader_structured_resource *structured_resource = &ins->declaration.structured_resource; - const struct vkd3d_shader_semantic *semantic = &ins->declaration.semantic; const struct vkd3d_shader_version *version = &tpf->program->shader_version; + const struct vkd3d_shader_resource *resource; const struct vkd3d_sm4_opcode_info *info; struct sm4_instruction instr = {0}; bool uav; @@ -3859,27 +3874,38 @@ static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_s instr.opcode = info->opcode; - instr.dsts[0] = semantic->resource.reg; - instr.dst_count = 1; - if (ins->opcode == VKD3DSIH_DCL || ins->opcode == VKD3DSIH_DCL_UAV_TYPED) { - instr.idx[0] = pack_resource_data_type(semantic->resource_data_type); + instr.idx[0] = pack_resource_data_type(ins->declaration.semantic.resource_data_type); instr.idx_count = 1; + instr.extra_bits |= ins->declaration.semantic.sample_count << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; + resource = &ins->declaration.semantic.resource; + } + else if (ins->opcode == VKD3DSIH_DCL_RESOURCE_RAW || ins->opcode == VKD3DSIH_DCL_UAV_RAW) + { + resource = &ins->declaration.raw_resource.resource; + } + else + { + instr.byte_stride = ins->declaration.structured_resource.byte_stride; + resource = &ins->declaration.structured_resource.resource; } + instr.dsts[0] = resource->reg; + instr.dst_count = 1; + if (vkd3d_shader_ver_ge(version, 5, 1)) { - instr.dsts[0].reg.idx[0].offset = semantic->resource.reg.reg.idx[0].offset; - instr.dsts[0].reg.idx[1].offset = semantic->resource.range.first; - instr.dsts[0].reg.idx[2].offset = semantic->resource.range.last; + instr.dsts[0].reg.idx[0].offset = resource->reg.reg.idx[0].offset; + instr.dsts[0].reg.idx[1].offset = resource->range.first; + instr.dsts[0].reg.idx[2].offset = resource->range.last; instr.dsts[0].reg.idx_count = 3; - instr.idx[instr.idx_count++] = semantic->resource.range.space; + instr.idx[instr.idx_count++] = resource->range.space; } else { - instr.dsts[0].reg.idx[0].offset = semantic->resource.range.first; + instr.dsts[0].reg.idx[0].offset = resource->range.first; instr.dsts[0].reg.idx_count = 1; } @@ -3887,10 +3913,6 @@ static void tpf_dcl_texture(const struct tpf_compiler *tpf, const struct vkd3d_s instr.extra_bits |= ins->flags << VKD3D_SM5_UAV_FLAGS_SHIFT; instr.extra_bits |= (sm4_resource_dimension(ins->resource_type) << VKD3D_SM4_RESOURCE_TYPE_SHIFT); - instr.extra_bits |= semantic->sample_count << VKD3D_SM4_RESOURCE_SAMPLE_COUNT_SHIFT; - - if (ins->structured) - instr.byte_stride = structured_resource->byte_stride; write_sm4_instruction(tpf, &instr); } @@ -4135,6 +4157,10 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ tpf_dcl_semantic(tpf, VKD3D_SM4_OP_DCL_OUTPUT, &ins->declaration.dst, 0); break; + case VKD3DSIH_DCL_OUTPUT_SGV: + tpf_dcl_siv_semantic(tpf, VKD3D_SM4_OP_DCL_OUTPUT_SGV, &ins->declaration.register_semantic, 0); + break; + case VKD3DSIH_DCL_OUTPUT_SIV: tpf_dcl_siv_semantic(tpf, VKD3D_SM4_OP_DCL_OUTPUT_SIV, &ins->declaration.register_semantic, 0); break; @@ -4166,6 +4192,8 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ case VKD3DSIH_CASE: case VKD3DSIH_CONTINUE: case VKD3DSIH_CUT: + case VKD3DSIH_CUT_STREAM: + case VKD3DSIH_DCL_STREAM: case VKD3DSIH_DEFAULT: case VKD3DSIH_DISCARD: case VKD3DSIH_DIV: @@ -4180,6 +4208,7 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ case VKD3DSIH_DSY_FINE: case VKD3DSIH_ELSE: case VKD3DSIH_EMIT: + case VKD3DSIH_EMIT_STREAM: case VKD3DSIH_ENDIF: case VKD3DSIH_ENDLOOP: case VKD3DSIH_ENDSWITCH: diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c index f56608940db..783f4e6134c 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c @@ -23,6 +23,8 @@ #include #include +/* VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG"); */ + static inline int char_to_int(char c) { if ('0' <= c && c <= '9') @@ -336,7 +338,10 @@ bool vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_cont void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, enum vkd3d_shader_log_level level, const char *format, va_list args) { - if (context->log_level < level) + struct vkd3d_string_buffer *messages = &context->messages; + size_t pos = messages->content_size; + + if (!WARN_ON() && context->log_level < level) return; if (location) @@ -344,19 +349,26 @@ void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const stru const char *source_name = location->source_name ? location->source_name : ""; if (location->line) - vkd3d_string_buffer_printf(&context->messages, "%s:%u:%u: ", + vkd3d_string_buffer_printf(messages, "%s:%u:%u: ", source_name, location->line, location->column); else - vkd3d_string_buffer_printf(&context->messages, "%s: ", source_name); + vkd3d_string_buffer_printf(messages, "%s: ", source_name); } - vkd3d_string_buffer_vprintf(&context->messages, format, args); - vkd3d_string_buffer_printf(&context->messages, "\n"); + vkd3d_string_buffer_vprintf(messages, format, args); + vkd3d_string_buffer_printf(messages, "\n"); + + WARN("%.*s", (int)(messages->content_size - pos), &messages->buffer[pos]); + if (context->log_level < level) + messages->content_size = pos; } void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, enum vkd3d_shader_error error, const char *format, va_list args) { - if (context->log_level < VKD3D_SHADER_LOG_WARNING) + struct vkd3d_string_buffer *messages = &context->messages; + size_t pos = messages->content_size; + + if (!WARN_ON() && context->log_level < VKD3D_SHADER_LOG_WARNING) return; if (location) @@ -364,17 +376,21 @@ void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const s const char *source_name = location->source_name ? location->source_name : ""; if (location->line) - vkd3d_string_buffer_printf(&context->messages, "%s:%u:%u: W%04u: ", + vkd3d_string_buffer_printf(messages, "%s:%u:%u: W%04u: ", source_name, location->line, location->column, error); else - vkd3d_string_buffer_printf(&context->messages, "%s: W%04u: ", source_name, error); + vkd3d_string_buffer_printf(messages, "%s: W%04u: ", source_name, error); } else { - vkd3d_string_buffer_printf(&context->messages, "W%04u: ", error); + vkd3d_string_buffer_printf(messages, "W%04u: ", error); } - vkd3d_string_buffer_vprintf(&context->messages, format, args); - vkd3d_string_buffer_printf(&context->messages, "\n"); + vkd3d_string_buffer_vprintf(messages, format, args); + vkd3d_string_buffer_printf(messages, "\n"); + + WARN("%.*s", (int)(messages->content_size - pos), &messages->buffer[pos]); + if (context->log_level < VKD3D_SHADER_LOG_WARNING) + messages->content_size = pos; } void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, @@ -390,7 +406,10 @@ void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const st void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, enum vkd3d_shader_error error, const char *format, va_list args) { - if (context->log_level < VKD3D_SHADER_LOG_ERROR) + struct vkd3d_string_buffer *messages = &context->messages; + size_t pos = messages->content_size; + + if (!WARN_ON() && context->log_level < VKD3D_SHADER_LOG_ERROR) return; if (location) @@ -398,17 +417,21 @@ void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const str const char *source_name = location->source_name ? location->source_name : ""; if (location->line) - vkd3d_string_buffer_printf(&context->messages, "%s:%u:%u: E%04u: ", + vkd3d_string_buffer_printf(messages, "%s:%u:%u: E%04u: ", source_name, location->line, location->column, error); else - vkd3d_string_buffer_printf(&context->messages, "%s: E%04u: ", source_name, error); + vkd3d_string_buffer_printf(messages, "%s: E%04u: ", source_name, error); } else { - vkd3d_string_buffer_printf(&context->messages, "E%04u: ", error); + vkd3d_string_buffer_printf(messages, "E%04u: ", error); } - vkd3d_string_buffer_vprintf(&context->messages, format, args); - vkd3d_string_buffer_printf(&context->messages, "\n"); + vkd3d_string_buffer_vprintf(messages, format, args); + vkd3d_string_buffer_printf(messages, "\n"); + + WARN("%.*s", (int)(messages->content_size - pos), &messages->buffer[pos]); + if (context->log_level < VKD3D_SHADER_LOG_ERROR) + messages->content_size = pos; } void vkd3d_shader_error(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, @@ -1413,13 +1436,14 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte if (context->cf_info_count) context->cf_info[context->cf_info_count - 1].inside_block = false; break; - case VKD3DSIH_TEX: + case VKD3DSIH_TEXLD: if (context->version->major == 1) sampler_reg = &instruction->dst[0].reg; else sampler_reg = &instruction->src[1].reg; vkd3d_shader_scan_combined_sampler_usage(context, sampler_reg, sampler_reg); break; + case VKD3DSIH_TEX: case VKD3DSIH_TEXBEM: case VKD3DSIH_TEXBEML: case VKD3DSIH_TEXDP3TEX: diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index 3b4fb626fcc..a5d1b8f4e05 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -174,6 +174,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_HLSL_INVALID_MAX_VERTEX_COUNT = 5042, VKD3D_SHADER_ERROR_HLSL_MISSING_PRIMITIVE_TYPE = 5043, VKD3D_SHADER_ERROR_HLSL_MISPLACED_STREAM_OUTPUT = 5044, + VKD3D_SHADER_ERROR_HLSL_MISSING_INPUT_PATCH = 5045, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, @@ -222,6 +223,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES = 8017, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES = 8018, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE = 8019, + VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT = 8020, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301, @@ -337,6 +339,7 @@ enum vkd3d_shader_opcode VKD3DSIH_DCL_INTERFACE, VKD3DSIH_DCL_OUTPUT, VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT, + VKD3DSIH_DCL_OUTPUT_SGV, VKD3DSIH_DCL_OUTPUT_SIV, VKD3DSIH_DCL_OUTPUT_TOPOLOGY, VKD3DSIH_DCL_RESOURCE_RAW, @@ -550,10 +553,12 @@ enum vkd3d_shader_opcode VKD3DSIH_TEXBEM, VKD3DSIH_TEXBEML, VKD3DSIH_TEXCOORD, + VKD3DSIH_TEXCRD, VKD3DSIH_TEXDEPTH, VKD3DSIH_TEXDP3, VKD3DSIH_TEXDP3TEX, VKD3DSIH_TEXKILL, + VKD3DSIH_TEXLD, VKD3DSIH_TEXLDD, VKD3DSIH_TEXLDL, VKD3DSIH_TEXM3x2DEPTH, @@ -607,6 +612,8 @@ enum vkd3d_shader_opcode VKD3DSIH_COUNT, }; +const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error); + enum vkd3d_shader_register_type { VKD3DSPR_TEMP, @@ -964,7 +971,7 @@ struct vkd3d_shader_register enum vsir_dimension dimension; /* known address alignment for optimisation, or zero */ unsigned int alignment; - union + union vsir_immediate_constant { uint32_t immconst_u32[VKD3D_VEC4_SIZE]; float immconst_f32[VKD3D_VEC4_SIZE]; @@ -1332,12 +1339,6 @@ static inline bool register_is_constant_or_undef(const struct vkd3d_shader_regis return register_is_constant(reg) || register_is_undef(reg); } -static inline bool register_is_scalar_constant_zero(const struct vkd3d_shader_register *reg) -{ - return register_is_constant(reg) && reg->dimension == VSIR_DIMENSION_SCALAR - && (data_type_is_64_bit(reg->data_type) ? !reg->u.immconst_u64[0] : !reg->u.immconst_u32[0]); -} - static inline bool register_is_numeric_array(const struct vkd3d_shader_register *reg) { return (reg->type == VKD3DSPR_IMMCONSTBUFFER || reg->type == VKD3DSPR_IDXTEMP @@ -1779,14 +1780,6 @@ static inline bool component_type_is_64_bit(enum vkd3d_shader_component_type com return component_type == VKD3D_SHADER_COMPONENT_DOUBLE || component_type == VKD3D_SHADER_COMPONENT_UINT64; } -enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval, - unsigned int index); - -static inline enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum vkd3d_shader_sysval_semantic sysval) -{ - return vkd3d_siv_from_sysval_indexed(sysval, 0); -} - static inline unsigned int vsir_write_mask_get_component_idx(uint32_t write_mask) { unsigned int i; diff --git a/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c b/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c index f2b18b665f8..c41f8bae806 100644 --- a/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c +++ b/libs/vkd3d/libs/vkd3d-utils/vkd3d_utils_main.c @@ -19,6 +19,8 @@ #include "vkd3d_utils_private.h" #undef D3D12CreateDevice +/* VKD3D_DEBUG_ENV_NAME("VKD3D_DEBUG"); */ + static const char *debug_d3d_blob_part(D3D_BLOB_PART part) { switch (part) -- 2.47.2