Files
wine-staging/patches/vkd3d-latest/0001-Updated-vkd3d-to-a8ca1f95c50561a16de5769646dcda0c045.patch

6662 lines
297 KiB
Diff
Raw Permalink Normal View History

2025-06-27 08:23:40 +10:00
From 6bda17c53c7627d3fdabdcc69e2f8daa965c5996 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
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 <stdio.h>
#include <math.h>
-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, "<unknown>"), 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, "<unknown>"), 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, "<unknown>"), 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, "<unknown>"), 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, "<unknown>"), 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, "<unknown>"), 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(&reg->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(&reg->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(&reg->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(&param->reg, src);
+ sm6_register_from_value(&param->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(&param->reg, dst);
+ sm6_register_from_value(&param->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(&param->reg, dst);
+ sm6_register_from_value(&param->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(&reg, 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(&reg, ptr);
+ sm6_register_from_value(&reg, 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(&reg, operands[coord_idx]);
+ sm6_register_from_value(&reg, 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], &reg);
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(&reg, ptr);
+ sm6_register_from_value(&reg, 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(&reg, 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(&reg.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(&reg, ptr);
+ sm6_register_from_value(&reg, 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(&reg, ptr);
+ sm6_register_from_value(&reg, 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
+ * "<unnamed>" 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 : "<unnamed>", 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 "<invalid>";
+ 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 "<unrecognized>";
@@ -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, "(<out-of-bounds>)");
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, "<unknown register %u>", arg.reg_type);
+ vkd3d_string_buffer_printf(&parser->buffer, "<unknown register %u>", 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, &section_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, "<unhandled modifier %#x>(%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, "<unknown>");
+
shader_glsl_print_indent(gen->buffer, gen->indent);
- vkd3d_string_buffer_printf(gen->buffer, "/* <unhandled instruction %#x> */\n", ins->opcode);
+ vkd3d_string_buffer_printf(gen->buffer, "/* <unhandled instruction \"%s\" (%#x)> */\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, "<unknown>"), 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, "<unknown>"),
+ 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, "<unknown>"),
+ 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, "<unknown>"),
+ 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, "<unknown>"),
+ 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, "<unknown>"),
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, "<unknown>"), 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, "<unknown>"), 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, "<unknown>"), 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, "<unknown>"), 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, "<unhandled register %#x>", 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, "<unhandled register %#x>", 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, "<unhandled register %#x>", 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, "<unhandled modifier %#x>(%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, "<unknown>");
+
msl_print_indent(gen->buffer, gen->indent);
- vkd3d_string_buffer_printf(gen->buffer, "/* <unhandled instruction %#x> */\n", ins->opcode);
+ vkd3d_string_buffer_printf(gen->buffer, "/* <unhandled instruction \"%s\" (%#x)> */\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<uint4>(");
- 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, "<unhandled 64-bit multiplication>");
+ 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, "<unhandled sysval %#x>;\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, " = <unhandled sysval %#x>", 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, " = <unhandled sysval %#x>", 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, " <unhandled sysval %#x>", 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<uint>(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 <metal_texture>\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}
%%
-<INITIAL>"//" {yy_push_state(CXX_COMMENT, yyscanner);}
-<INITIAL>"/*" {yy_push_state(C_COMMENT, yyscanner);}
+<INITIAL,INCLUDE,LINE>"//" {yy_push_state(CXX_COMMENT, yyscanner);}
+<INITIAL,INCLUDE,LINE>"/*" {yy_push_state(C_COMMENT, yyscanner);}
<CXX_COMMENT>\\{NEWLINE} {}
<CXX_COMMENT>\n {
yy_pop_state(yyscanner);
@@ -80,7 +81,11 @@ INT_SUFFIX [uUlL]{0,2}
return T_NEWLINE;
}
<C_COMMENT>"*/" {yy_pop_state(yyscanner);}
-<C_COMMENT,CXX_COMMENT><<EOF>> {yy_pop_state(yyscanner);}
+<C_COMMENT,CXX_COMMENT><<EOF>> {
+ yy_pop_state(yyscanner);
+ BEGIN(INITIAL);
+ yyterminate();
+ }
<C_COMMENT,CXX_COMMENT>. {}
<C_COMMENT>\n {}
@@ -196,6 +201,10 @@ INT_SUFFIX [uUlL]{0,2}
BEGIN(INITIAL);
return T_NEWLINE;
}
+<INITIAL,INCLUDE,ERROR,LINE><<EOF>> {
+ BEGIN(INITIAL);
+ yyterminate();
+ }
<INITIAL,INCLUDE,LINE>{WS}+ {}
<INITIAL>[-()\[\]{},+!*/<>&|^?:] {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, &reg_symbol)))
{
spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE,
- "Unrecognized register (%s).\n", debug_vkd3d_symbol(&reg_symbol));
+ "Unrecognized register (%s).", debug_vkd3d_symbol(&reg_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, "<unknown>"), 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, "<unknown>"), 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, "<unknown>"), 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, "<unknown>"), 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 <stdio.h>
#include <math.h>
+/* 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 : "<anonymous>";
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 : "<anonymous>";
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 : "<anonymous>";
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