From f76ea979dbfee9845c108a03c2238b02dce9d1a0 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Mon, 13 May 2024 09:30:19 +1000 Subject: [PATCH] Updated vkd3d-latest patchset --- ...-4a209efb6278586d412ceb0a7cbe21e6769.patch | 2 +- ...-7b4a1fdfbc192cfd02ffb6cf18c0a86b2f6.patch | 2 +- ...-46fca3f9f4a9b47b32e9dfbacda0f3d1953.patch | 2 +- ...-13e1491941a1af32ddfc1019fa304231fd1.patch | 2 +- ...-62a512c4f8c4070f0f4f3ed8e70b6f0bc88.patch | 2 +- ...-4b3a948edcb5e83074b63aad25ecf450dca.patch | 3631 +++++++++++++++++ 6 files changed, 3636 insertions(+), 5 deletions(-) create mode 100644 patches/vkd3d-latest/0006-Updated-vkd3d-to-4b3a948edcb5e83074b63aad25ecf450dca.patch diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-4a209efb6278586d412ceb0a7cbe21e6769.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-4a209efb6278586d412ceb0a7cbe21e6769.patch index 77b0aa75..3f3b6928 100644 --- a/patches/vkd3d-latest/0001-Updated-vkd3d-to-4a209efb6278586d412ceb0a7cbe21e6769.patch +++ b/patches/vkd3d-latest/0001-Updated-vkd3d-to-4a209efb6278586d412ceb0a7cbe21e6769.patch @@ -1,4 +1,4 @@ -From fef220fc5d2e7bfae4b08bf0c6c5fb75aab4cf3d Mon Sep 17 00:00:00 2001 +From fe4f6075b7b5ec6e9bb86bd41c8f62e547d78e9e Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 7 Mar 2024 10:40:41 +1100 Subject: [PATCH] Updated vkd3d to 4a209efb6278586d412ceb0a7cbe21e6769a7367. diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-7b4a1fdfbc192cfd02ffb6cf18c0a86b2f6.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-7b4a1fdfbc192cfd02ffb6cf18c0a86b2f6.patch index 72143828..be760f2e 100644 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-7b4a1fdfbc192cfd02ffb6cf18c0a86b2f6.patch +++ b/patches/vkd3d-latest/0002-Updated-vkd3d-to-7b4a1fdfbc192cfd02ffb6cf18c0a86b2f6.patch @@ -1,4 +1,4 @@ -From f9c536f34a5158f0039748e5ef5f08afecbc67cf Mon Sep 17 00:00:00 2001 +From ea3477f55df517065cc716c27e2df7ea68f6760e Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Tue, 23 Apr 2024 08:01:19 +1000 Subject: [PATCH] Updated vkd3d to 7b4a1fdfbc192cfd02ffb6cf18c0a86b2f6eaeb4. diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-46fca3f9f4a9b47b32e9dfbacda0f3d1953.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-46fca3f9f4a9b47b32e9dfbacda0f3d1953.patch index a7aeeacd..2a67c42a 100644 --- a/patches/vkd3d-latest/0003-Updated-vkd3d-to-46fca3f9f4a9b47b32e9dfbacda0f3d1953.patch +++ b/patches/vkd3d-latest/0003-Updated-vkd3d-to-46fca3f9f4a9b47b32e9dfbacda0f3d1953.patch @@ -1,4 +1,4 @@ -From b0a4c2becfa8f65d1751256d5297cd4319a2605d Mon Sep 17 00:00:00 2001 +From 417a497121a93250fa896b536dd56af55f562cba Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Wed, 24 Apr 2024 09:05:20 +1000 Subject: [PATCH] Updated vkd3d to 46fca3f9f4a9b47b32e9dfbacda0f3d19536c02c. diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-13e1491941a1af32ddfc1019fa304231fd1.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-13e1491941a1af32ddfc1019fa304231fd1.patch index 8d944114..3e14a505 100644 --- a/patches/vkd3d-latest/0004-Updated-vkd3d-to-13e1491941a1af32ddfc1019fa304231fd1.patch +++ b/patches/vkd3d-latest/0004-Updated-vkd3d-to-13e1491941a1af32ddfc1019fa304231fd1.patch @@ -1,4 +1,4 @@ -From 669446d32104b9a4b879f5cb2ad46a964606fa70 Mon Sep 17 00:00:00 2001 +From 22ce76c9299aa5cd9b6df4244fb7614e322818fa Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Sun, 28 Apr 2024 09:46:44 +1000 Subject: [PATCH] Updated vkd3d to 13e1491941a1af32ddfc1019fa304231fd121c4d. diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-62a512c4f8c4070f0f4f3ed8e70b6f0bc88.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-62a512c4f8c4070f0f4f3ed8e70b6f0bc88.patch index 7d13a011..c1f02e8e 100644 --- a/patches/vkd3d-latest/0005-Updated-vkd3d-to-62a512c4f8c4070f0f4f3ed8e70b6f0bc88.patch +++ b/patches/vkd3d-latest/0005-Updated-vkd3d-to-62a512c4f8c4070f0f4f3ed8e70b6f0bc88.patch @@ -1,4 +1,4 @@ -From f34d3681ed967342322403d4c62eb9d1d72cdf06 Mon Sep 17 00:00:00 2001 +From 64c8a6f765bc07221a5b9d0b78bb12db0eae898e Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 3 May 2024 07:31:39 +1000 Subject: [PATCH] Updated vkd3d to 62a512c4f8c4070f0f4f3ed8e70b6f0bc885da30. diff --git a/patches/vkd3d-latest/0006-Updated-vkd3d-to-4b3a948edcb5e83074b63aad25ecf450dca.patch b/patches/vkd3d-latest/0006-Updated-vkd3d-to-4b3a948edcb5e83074b63aad25ecf450dca.patch new file mode 100644 index 00000000..a962258e --- /dev/null +++ b/patches/vkd3d-latest/0006-Updated-vkd3d-to-4b3a948edcb5e83074b63aad25ecf450dca.patch @@ -0,0 +1,3631 @@ +From 9db69085387899436ec12182c76ea25b4c773219 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Mon, 13 May 2024 09:29:08 +1000 +Subject: [PATCH] Updated vkd3d to 4b3a948edcb5e83074b63aad25ecf450dcae4130. + +--- + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 23 + + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 31 +- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 321 +++++++++++ + libs/vkd3d/libs/vkd3d-shader/fx.c | 506 ++++++++++++++---- + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 168 +++--- + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 19 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 66 +-- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 84 ++- + .../libs/vkd3d-shader/hlsl_constant_ops.c | 170 +++--- + libs/vkd3d/libs/vkd3d-shader/ir.c | 26 + + libs/vkd3d/libs/vkd3d-shader/spirv.c | 94 ++++ + libs/vkd3d/libs/vkd3d-shader/tpf.c | 79 +-- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 16 + + libs/vkd3d/libs/vkd3d/device.c | 177 +++--- + libs/vkd3d/libs/vkd3d/utils.c | 24 + + 15 files changed, 1335 insertions(+), 469 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +index b2f329cd199..f2ad39f2f07 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +@@ -328,8 +328,20 @@ static const char * const shader_opcode_names[] = + [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_TRUE ] = "wave_all_true", + [VKD3DSIH_WAVE_ANY_TRUE ] = "wave_any_true", ++ [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_XOR ] = "xor", + }; + +@@ -1840,6 +1852,17 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile + vkd3d_string_buffer_printf(buffer, "p"); + break; + ++ case VKD3DSIH_WAVE_OP_ADD: ++ case VKD3DSIH_WAVE_OP_IMAX: ++ case VKD3DSIH_WAVE_OP_IMIN: ++ case VKD3DSIH_WAVE_OP_MAX: ++ case VKD3DSIH_WAVE_OP_MIN: ++ case VKD3DSIH_WAVE_OP_MUL: ++ case VKD3DSIH_WAVE_OP_UMAX: ++ case VKD3DSIH_WAVE_OP_UMIN: ++ vkd3d_string_buffer_printf(&compiler->buffer, (ins->flags & VKD3DSI_WAVE_PREFIX) ? "_prefix" : "_active"); ++ break; ++ + case VKD3DSIH_ISHL: + case VKD3DSIH_ISHR: + case VKD3DSIH_USHR: +diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +index aa2358440e5..24a95224349 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +@@ -1514,10 +1514,11 @@ D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) + return D3DXPC_STRUCT; + case HLSL_CLASS_VECTOR: + return D3DXPC_VECTOR; +- case HLSL_CLASS_OBJECT: ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: + case HLSL_CLASS_TEXTURE: ++ case HLSL_CLASS_VERTEX_SHADER: + return D3DXPC_OBJECT; + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: +@@ -1539,7 +1540,7 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type) + case HLSL_CLASS_SCALAR: + case HLSL_CLASS_VECTOR: + case HLSL_CLASS_MATRIX: +- switch (type->base_type) ++ switch (type->e.numeric.type) + { + case HLSL_TYPE_BOOL: + return D3DXPT_BOOL; +@@ -1600,18 +1601,6 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type) + } + break; + +- case HLSL_CLASS_OBJECT: +- switch (type->base_type) +- { +- case HLSL_TYPE_PIXELSHADER: +- return D3DXPT_PIXELSHADER; +- case HLSL_TYPE_VERTEXSHADER: +- return D3DXPT_VERTEXSHADER; +- default: +- vkd3d_unreachable(); +- } +- vkd3d_unreachable(); +- + case HLSL_CLASS_ARRAY: + return hlsl_sm1_base_type(type->e.array.type); + +@@ -1621,6 +1610,12 @@ D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type) + case HLSL_CLASS_STRING: + return D3DXPT_STRING; + ++ case HLSL_CLASS_PIXEL_SHADER: ++ return D3DXPT_PIXELSHADER; ++ ++ case HLSL_CLASS_VERTEX_SHADER: ++ return D3DXPT_VERTEXSHADER; ++ + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: + case HLSL_CLASS_PASS: +@@ -2020,11 +2015,11 @@ static void write_sm1_cast(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b + /* Narrowing casts were already lowered. */ + assert(src_type->dimx == dst_type->dimx); + +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_HALF: + case HLSL_TYPE_FLOAT: +- switch (src_type->base_type) ++ switch (src_type->e.numeric.type) + { + case HLSL_TYPE_INT: + case HLSL_TYPE_UINT: +@@ -2046,7 +2041,7 @@ static void write_sm1_cast(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b + + case HLSL_TYPE_INT: + case HLSL_TYPE_UINT: +- switch(src_type->base_type) ++ switch(src_type->e.numeric.type) + { + case HLSL_TYPE_HALF: + case HLSL_TYPE_FLOAT: +@@ -2308,7 +2303,7 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b + return; + } + +- if (instr->data_type->base_type != HLSL_TYPE_FLOAT) ++ if (instr->data_type->e.numeric.type != HLSL_TYPE_FLOAT) + { + /* These need to be lowered. */ + hlsl_fixme(ctx, &instr->loc, "SM1 non-float expression."); +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index e636ad917db..29f736364dc 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -37,6 +37,10 @@ static const size_t MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION = 11; + + static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64}; + ++static const unsigned int MAX_GS_INSTANCE_COUNT = 32; /* kMaxGSInstanceCount */ ++static const unsigned int MAX_GS_OUTPUT_TOTAL_SCALARS = 1024; /* kMaxGSOutputTotalScalars */ ++static const unsigned int MAX_GS_OUTPUT_STREAMS = 4; ++ + #define VKD3D_SHADER_SWIZZLE_64_MASK \ + (VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(0) \ + | VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(1)) +@@ -283,6 +287,18 @@ enum dxil_element_additional_tag + ADDITIONAL_TAG_USED_MASK = 3, + }; + ++enum dxil_input_primitive ++{ ++ INPUT_PRIMITIVE_UNDEFINED = 0, ++ INPUT_PRIMITIVE_POINT = 1, ++ INPUT_PRIMITIVE_LINE = 2, ++ INPUT_PRIMITIVE_TRIANGLE = 3, ++ INPUT_PRIMITIVE_LINEWITHADJACENCY = 6, ++ INPUT_PRIMITIVE_TRIANGLEWITHADJACENY = 7, ++ INPUT_PRIMITIVE_PATCH1 = 8, ++ INPUT_PRIMITIVE_PATCH32 = 39, ++}; ++ + enum dxil_shader_properties_tag + { + SHADER_PROPERTIES_FLAGS = 0, +@@ -419,6 +435,9 @@ enum dx_intrinsic_opcode + DX_GROUP_ID = 94, + DX_THREAD_ID_IN_GROUP = 95, + DX_FLATTENED_THREAD_ID_IN_GROUP = 96, ++ DX_EMIT_STREAM = 97, ++ DX_CUT_STREAM = 98, ++ DX_EMIT_THEN_CUT_STREAM = 99, + DX_MAKE_DOUBLE = 101, + DX_SPLIT_DOUBLE = 102, + DX_LOAD_OUTPUT_CONTROL_POINT = 103, +@@ -432,6 +451,10 @@ enum dx_intrinsic_opcode + DX_WAVE_ANY_TRUE = 113, + DX_WAVE_ALL_TRUE = 114, + DX_WAVE_ACTIVE_ALL_EQUAL = 115, ++ DX_WAVE_ACTIVE_BALLOT = 116, ++ DX_WAVE_ACTIVE_OP = 119, ++ DX_WAVE_ACTIVE_BIT = 120, ++ DX_WAVE_PREFIX_OP = 121, + DX_LEGACY_F32TOF16 = 130, + DX_LEGACY_F16TOF32 = 131, + DX_RAW_BUFFER_LOAD = 139, +@@ -533,6 +556,21 @@ enum dxil_sync_flags + SYNC_GROUP_SHARED_MEMORY = 0x8, + }; + ++enum dxil_wave_bit_op_kind ++{ ++ WAVE_BIT_OP_AND = 0, ++ WAVE_BIT_OP_OR = 1, ++ WAVE_BIT_OP_XOR = 2, ++}; ++ ++enum dxil_wave_op_kind ++{ ++ WAVE_OP_ADD = 0, ++ WAVE_OP_MUL = 1, ++ WAVE_OP_MIN = 2, ++ WAVE_OP_MAX = 3, ++}; ++ + struct sm6_pointer_info + { + const struct sm6_type *type; +@@ -4896,6 +4934,38 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int + ins->handler_idx = VKD3DSIH_NOP; + } + ++static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++ const struct sm6_value **operands, struct function_emission_state *state) ++{ ++ struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_src_param *src_param; ++ unsigned int i; ++ ++ vsir_instruction_init(ins, &sm6->p.location, (op == DX_CUT_STREAM) ? VKD3DSIH_CUT_STREAM : VKD3DSIH_EMIT_STREAM); ++ ++ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ return; ++ ++ i = sm6_value_get_constant_uint(operands[0]); ++ if (i >= MAX_GS_OUTPUT_STREAMS) ++ { ++ WARN("Invalid stream index %u.\n", i); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Output stream index %u is invalid.", i); ++ } ++ ++ /* VKD3D_DATA_UNUSED would be more reasonable, but TPF uses data type 0 here. */ ++ register_init_with_id(&src_param->reg, VKD3DSPR_STREAM, 0, i); ++ src_param_init(src_param); ++ ++ if (op == DX_EMIT_THEN_CUT_STREAM) ++ { ++ ++state->ins; ++ ++state->code_block->instruction_count; ++ sm6_parser_emit_dx_stream(sm6, DX_CUT_STREAM, operands, state); ++ } ++} ++ + static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +@@ -5910,6 +5980,111 @@ static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_int + dst_param_init_with_mask(dst_param, write_mask); + } + ++static void sm6_parser_emit_dx_wave_active_ballot(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++ const struct sm6_value **operands, struct function_emission_state *state) ++{ ++ struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_src_param *src_param; ++ ++ 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]); ++ ++ instruction_dst_param_init_ssa_vector(ins, VKD3D_VEC4_SIZE, sm6); ++} ++ ++static enum vkd3d_shader_opcode sm6_dx_map_wave_bit_op(enum dxil_wave_bit_op_kind op, ++ struct sm6_parser *sm6) ++{ ++ switch (op) ++ { ++ case WAVE_BIT_OP_AND: ++ return VKD3DSIH_WAVE_ACTIVE_BIT_AND; ++ case WAVE_BIT_OP_OR: ++ return VKD3DSIH_WAVE_ACTIVE_BIT_OR; ++ case WAVE_BIT_OP_XOR: ++ return VKD3DSIH_WAVE_ACTIVE_BIT_XOR; ++ 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); ++ return VKD3DSIH_INVALID; ++ } ++} ++ ++static void sm6_parser_emit_dx_wave_active_bit(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++ const struct sm6_value **operands, struct function_emission_state *state) ++{ ++ struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_src_param *src_param; ++ enum dxil_wave_bit_op_kind wave_op; ++ enum vkd3d_shader_opcode opcode; ++ ++ wave_op = sm6_value_get_constant_uint(operands[1]); ++ ++ if ((opcode = sm6_dx_map_wave_bit_op(wave_op, sm6)) == VKD3DSIH_INVALID) ++ return; ++ vsir_instruction_init(ins, &sm6->p.location, opcode); ++ ++ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ return; ++ src_param_init_from_value(src_param, operands[0]); ++ ++ instruction_dst_param_init_ssa_scalar(ins, sm6); ++} ++ ++static enum vkd3d_shader_opcode sm6_dx_map_wave_op(enum dxil_wave_op_kind op, bool is_signed, bool is_float, ++ struct sm6_parser *sm6) ++{ ++ switch (op) ++ { ++ case WAVE_OP_ADD: ++ return VKD3DSIH_WAVE_OP_ADD; ++ case WAVE_OP_MUL: ++ return VKD3DSIH_WAVE_OP_MUL; ++ case WAVE_OP_MIN: ++ if (is_float) ++ return VKD3DSIH_WAVE_OP_MIN; ++ return is_signed ? VKD3DSIH_WAVE_OP_IMIN : VKD3DSIH_WAVE_OP_UMIN; ++ case WAVE_OP_MAX: ++ if (is_float) ++ return VKD3DSIH_WAVE_OP_MAX; ++ return is_signed ? VKD3DSIH_WAVE_OP_IMAX : VKD3DSIH_WAVE_OP_UMAX; ++ 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); ++ return VKD3DSIH_INVALID; ++ } ++} ++ ++static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++ const struct sm6_value **operands, struct function_emission_state *state) ++{ ++ struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_src_param *src_param; ++ enum vkd3d_shader_opcode opcode; ++ 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]); ++ opcode = sm6_dx_map_wave_op(wave_op, is_signed, sm6_type_is_floating_point(operands[0]->type), sm6); ++ ++ if (opcode == VKD3DSIH_INVALID) ++ return; ++ ++ vsir_instruction_init(ins, &sm6->p.location, opcode); ++ ins->flags = (op == DX_WAVE_PREFIX_OP) ? VKD3DSI_WAVE_PREFIX : 0; ++ ++ if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ return; ++ src_param_init_from_value(src_param, operands[0]); ++ ++ instruction_dst_param_init_ssa_scalar(ins, sm6); ++} ++ + static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +@@ -5954,6 +6129,7 @@ struct sm6_dx_opcode_info + H -> handle + D -> Dimensions + S -> splitdouble ++ V -> 4 x i32 + v -> void + o -> overloaded + R -> matches the return type +@@ -5976,6 +6152,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = + [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, + [DX_COVERAGE ] = {"i", "", sm6_parser_emit_dx_coverage}, + [DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle}, ++ [DX_CUT_STREAM ] = {"v", "c", sm6_parser_emit_dx_stream}, + [DX_DERIV_COARSEX ] = {"e", "R", sm6_parser_emit_dx_unary}, + [DX_DERIV_COARSEY ] = {"e", "R", sm6_parser_emit_dx_unary}, + [DX_DERIV_FINEX ] = {"e", "R", sm6_parser_emit_dx_unary}, +@@ -5985,6 +6162,8 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = + [DX_DOT2 ] = {"g", "RRRR", sm6_parser_emit_dx_dot}, + [DX_DOT3 ] = {"g", "RRRRRR", sm6_parser_emit_dx_dot}, + [DX_DOT4 ] = {"g", "RRRRRRRR", sm6_parser_emit_dx_dot}, ++ [DX_EMIT_STREAM ] = {"v", "c", sm6_parser_emit_dx_stream}, ++ [DX_EMIT_THEN_CUT_STREAM ] = {"v", "c", sm6_parser_emit_dx_stream}, + [DX_EXP ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_FABS ] = {"g", "R", sm6_parser_emit_dx_fabs}, + [DX_FIRST_BIT_HI ] = {"i", "m", sm6_parser_emit_dx_unary}, +@@ -6051,10 +6230,14 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = + [DX_UMAX ] = {"m", "RR", sm6_parser_emit_dx_binary}, + [DX_UMIN ] = {"m", "RR", sm6_parser_emit_dx_binary}, + [DX_WAVE_ACTIVE_ALL_EQUAL ] = {"1", "n", sm6_parser_emit_dx_unary}, ++ [DX_WAVE_ACTIVE_BALLOT ] = {"V", "1", sm6_parser_emit_dx_wave_active_ballot}, ++ [DX_WAVE_ACTIVE_BIT ] = {"m", "Rc", sm6_parser_emit_dx_wave_active_bit}, ++ [DX_WAVE_ACTIVE_OP ] = {"n", "Rcc", sm6_parser_emit_dx_wave_op}, + [DX_WAVE_ALL_TRUE ] = {"1", "1", sm6_parser_emit_dx_unary}, + [DX_WAVE_ANY_TRUE ] = {"1", "1", sm6_parser_emit_dx_unary}, + [DX_WAVE_GET_LANE_COUNT ] = {"i", "", sm6_parser_emit_dx_wave_builtin}, + [DX_WAVE_GET_LANE_INDEX ] = {"i", "", sm6_parser_emit_dx_wave_builtin}, ++ [DX_WAVE_PREFIX_OP ] = {"n", "Rcc", sm6_parser_emit_dx_wave_op}, + }; + + static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type, +@@ -6102,6 +6285,8 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc + return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.Dimensions"); + case 'S': + return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.splitdouble"); ++ case 'V': ++ return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.fouri32"); + case 'v': + return !type; + case 'o': +@@ -9336,6 +9521,17 @@ static void sm6_parser_emit_dcl_count(struct sm6_parser *sm6, enum vkd3d_shader_ + ins->declaration.count = count; + } + ++static void sm6_parser_emit_dcl_primitive_topology(struct sm6_parser *sm6, ++ enum vkd3d_shader_opcode handler_idx, enum vkd3d_primitive_type primitive_type, ++ unsigned int patch_vertex_count) ++{ ++ struct vkd3d_shader_instruction *ins; ++ ++ ins = sm6_parser_add_instruction(sm6, handler_idx); ++ ins->declaration.primitive_type.type = primitive_type; ++ ins->declaration.primitive_type.patch_vertex_count = patch_vertex_count; ++} ++ + static void sm6_parser_emit_dcl_tessellator_domain(struct sm6_parser *sm6, + enum vkd3d_tessellator_domain tessellator_domain) + { +@@ -9420,6 +9616,128 @@ static void sm6_parser_emit_dcl_max_tessellation_factor(struct sm6_parser *sm6, + ins->declaration.max_tessellation_factor = max_tessellation_factor; + } + ++static void sm6_parser_gs_properties_init(struct sm6_parser *sm6, const struct sm6_metadata_value *m) ++{ ++ enum vkd3d_primitive_type input_primitive = VKD3D_PT_TRIANGLELIST, output_primitive; ++ unsigned int i, input_control_point_count = 1, patch_vertex_count = 0; ++ const struct sm6_metadata_node *node; ++ unsigned int operands[5] = {0}; ++ ++ if (!m || !sm6_metadata_value_is_node(m)) ++ { ++ WARN("Missing or invalid GS properties.\n"); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, ++ "Geometry shader properties node is missing or invalid."); ++ return; ++ } ++ ++ node = m->u.node; ++ if (node->operand_count < ARRAY_SIZE(operands)) ++ { ++ WARN("Invalid operand count %u.\n", node->operand_count); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, ++ "Geometry shader properties operand count %u is invalid.", node->operand_count); ++ return; ++ } ++ if (node->operand_count > ARRAY_SIZE(operands)) ++ { ++ WARN("Ignoring %zu extra operands.\n", node->operand_count - ARRAY_SIZE(operands)); ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, ++ "Ignoring %zu extra operands for geometry shader properties.", ++ node->operand_count - ARRAY_SIZE(operands)); ++ } ++ ++ for (i = 0; i < node->operand_count; ++i) ++ { ++ if (!sm6_metadata_get_uint_value(sm6, node->operands[i], &operands[i])) ++ { ++ WARN("GS property at index %u is not a uint value.\n", i); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, ++ "Geometry shader properties operand at index %u is not an integer.", i); ++ } ++ } ++ ++ switch (i = operands[0]) ++ { ++ case INPUT_PRIMITIVE_POINT: ++ input_primitive = VKD3D_PT_POINTLIST; ++ input_control_point_count = 1; ++ break; ++ ++ case INPUT_PRIMITIVE_LINE: ++ input_primitive = VKD3D_PT_LINELIST; ++ input_control_point_count = 2; ++ break; ++ ++ case INPUT_PRIMITIVE_TRIANGLE: ++ input_primitive = VKD3D_PT_TRIANGLELIST; ++ input_control_point_count = 3; ++ break; ++ ++ case INPUT_PRIMITIVE_LINEWITHADJACENCY: ++ input_primitive = VKD3D_PT_LINELIST_ADJ; ++ input_control_point_count = 4; ++ break; ++ ++ case INPUT_PRIMITIVE_TRIANGLEWITHADJACENY: ++ input_primitive = VKD3D_PT_TRIANGLELIST_ADJ; ++ input_control_point_count = 6; ++ break; ++ ++ default: ++ if (i >= INPUT_PRIMITIVE_PATCH1 && i <= INPUT_PRIMITIVE_PATCH32) ++ { ++ input_primitive = VKD3D_PT_PATCH; ++ patch_vertex_count = i - INPUT_PRIMITIVE_PATCH1 + 1; ++ break; ++ } ++ ++ WARN("Unhandled input primitive %u.\n", i); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, ++ "Geometry shader input primitive %u is unhandled.", i); ++ break; ++ } ++ ++ sm6_parser_emit_dcl_primitive_topology(sm6, VKD3DSIH_DCL_INPUT_PRIMITIVE, input_primitive, patch_vertex_count); ++ sm6->p.program.input_control_point_count = input_control_point_count; ++ ++ i = operands[1]; ++ /* Max total scalar count sets an upper limit. We would need to scan outputs to be more precise. */ ++ if (i > MAX_GS_OUTPUT_TOTAL_SCALARS) ++ { ++ WARN("GS output vertex count %u invalid.\n", i); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, ++ "Geometry shader output vertex count %u is invalid.", i); ++ } ++ sm6_parser_emit_dcl_count(sm6, VKD3DSIH_DCL_VERTICES_OUT, i); ++ ++ if (operands[2] > 1) ++ { ++ FIXME("Unhandled stream mask %#x.\n", operands[2]); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, ++ "Geometry shader stream mask %#x is unhandled.", operands[2]); ++ } ++ ++ output_primitive = operands[3]; ++ if (output_primitive == VKD3D_PT_UNDEFINED || output_primitive >= VKD3D_PT_COUNT) ++ { ++ WARN("Unhandled output primitive %u.\n", output_primitive); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, ++ "Geometry shader output primitive %u is unhandled.", output_primitive); ++ output_primitive = VKD3D_PT_TRIANGLELIST; ++ } ++ sm6_parser_emit_dcl_primitive_topology(sm6, VKD3DSIH_DCL_OUTPUT_TOPOLOGY, output_primitive, 0); ++ ++ i = operands[4]; ++ if (!i || i > MAX_GS_INSTANCE_COUNT) ++ { ++ WARN("GS instance count %u invalid.\n", i); ++ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES, ++ "Geometry shader instance count %u is invalid.", i); ++ } ++ sm6_parser_emit_dcl_count(sm6, VKD3DSIH_DCL_GS_INSTANCES, i); ++} ++ + static enum vkd3d_tessellator_domain sm6_parser_ds_properties_init(struct sm6_parser *sm6, + const struct sm6_metadata_value *m) + { +@@ -9610,6 +9928,9 @@ static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6) + case SHADER_PROPERTIES_FLAGS: + sm6_parser_emit_global_flags(sm6, node->operands[i + 1]); + break; ++ case SHADER_PROPERTIES_GEOMETRY: ++ sm6_parser_gs_properties_init(sm6, node->operands[i + 1]); ++ break; + case SHADER_PROPERTIES_DOMAIN: + tessellator_domain = sm6_parser_ds_properties_init(sm6, node->operands[i + 1]); + break; +diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c +index 168378e6b42..6fb2e8a0f0b 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/fx.c ++++ b/libs/vkd3d/libs/vkd3d-shader/fx.c +@@ -85,8 +85,13 @@ struct fx_write_context + uint32_t numeric_variable_count; + uint32_t object_variable_count; + uint32_t shared_object_count; +- uint32_t shader_variable_count; ++ uint32_t shader_count; + uint32_t parameter_count; ++ uint32_t dsv_count; ++ uint32_t rtv_count; ++ uint32_t texture_count; ++ uint32_t uav_count; ++ uint32_t sampler_state_count; + int status; + + bool child_effect; +@@ -169,7 +174,7 @@ static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_co + struct fx_write_context *fx) + { + unsigned int version = ctx->profile->major_version; +- struct hlsl_block block; ++ struct hlsl_ir_var *var; + + memset(fx, 0, sizeof(*fx)); + +@@ -197,9 +202,15 @@ static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_co + fx->child_effect = fx->ops->are_child_effects_supported && ctx->child_effect; + fx->include_empty_buffers = version == 4 && ctx->include_empty_buffers; + +- hlsl_block_init(&block); +- hlsl_prepend_global_uniform_copy(fx->ctx, &block); +- hlsl_block_cleanup(&block); ++ LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) ++ { ++ if (var->storage_modifiers & HLSL_STORAGE_UNIFORM) ++ { ++ list_add_tail(&ctx->extern_vars, &var->extern_entry); ++ var->is_uniform = 1; ++ } ++ } ++ + hlsl_calculate_buffer_offsets(fx->ctx); + } + +@@ -292,6 +303,14 @@ static uint32_t get_fx_4_type_size(const struct hlsl_type *type) + return type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float) * elements_count; + } + ++static const uint32_t fx_4_numeric_base_type[] = ++{ ++ [HLSL_TYPE_FLOAT] = 1, ++ [HLSL_TYPE_INT ] = 2, ++ [HLSL_TYPE_UINT ] = 3, ++ [HLSL_TYPE_BOOL ] = 4, ++}; ++ + static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, struct fx_write_context *fx) + { + static const unsigned int NUMERIC_BASE_TYPE_SHIFT = 3; +@@ -304,13 +323,6 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, + [HLSL_CLASS_VECTOR] = 2, + [HLSL_CLASS_MATRIX] = 3, + }; +- static const uint32_t numeric_base_type[] = +- { +- [HLSL_TYPE_FLOAT] = 1, +- [HLSL_TYPE_INT ] = 2, +- [HLSL_TYPE_UINT ] = 3, +- [HLSL_TYPE_BOOL ] = 4, +- }; + struct hlsl_ctx *ctx = fx->ctx; + uint32_t value = 0; + +@@ -326,16 +338,16 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, + return 0; + } + +- switch (type->base_type) ++ switch (type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_INT: + case HLSL_TYPE_UINT: + case HLSL_TYPE_BOOL: +- value |= (numeric_base_type[type->base_type] << NUMERIC_BASE_TYPE_SHIFT); ++ value |= (fx_4_numeric_base_type[type->e.numeric.type] << NUMERIC_BASE_TYPE_SHIFT); + break; + default: +- hlsl_fixme(ctx, &ctx->location, "Not implemented for base type %u.", type->base_type); ++ hlsl_fixme(ctx, &ctx->location, "Not implemented for base type %u.", type->e.numeric.type); + return 0; + } + +@@ -349,11 +361,6 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, + + static const char * get_fx_4_type_name(const struct hlsl_type *type) + { +- static const char * const object_type_names[] = +- { +- [HLSL_TYPE_PIXELSHADER] = "PixelShader", +- [HLSL_TYPE_VERTEXSHADER] = "VertexShader", +- }; + static const char * const texture_type_names[] = + { + [HLSL_SAMPLER_DIM_GENERIC] = "texture", +@@ -380,6 +387,9 @@ static const char * get_fx_4_type_name(const struct hlsl_type *type) + + switch (type->class) + { ++ case HLSL_CLASS_SAMPLER: ++ return "SamplerState"; ++ + case HLSL_CLASS_TEXTURE: + return texture_type_names[type->sampler_dim]; + +@@ -392,15 +402,11 @@ static const char * get_fx_4_type_name(const struct hlsl_type *type) + case HLSL_CLASS_RENDER_TARGET_VIEW: + return "RenderTargetView"; + +- case HLSL_CLASS_OBJECT: +- switch (type->base_type) +- { +- case HLSL_TYPE_PIXELSHADER: +- case HLSL_TYPE_VERTEXSHADER: +- return object_type_names[type->base_type]; +- default: +- return type->name; +- } ++ case HLSL_CLASS_VERTEX_SHADER: ++ return "VertexShader"; ++ ++ case HLSL_CLASS_PIXEL_SHADER: ++ return "PixelShader"; + + default: + return type->name; +@@ -413,7 +419,6 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + uint32_t name_offset, offset, size, stride, numeric_desc; + uint32_t elements_count = 0; + const char *name; +- struct hlsl_ctx *ctx = fx->ctx; + + /* Resolve arrays to element type and number of elements. */ + if (type->class == HLSL_CLASS_ARRAY) +@@ -436,10 +441,12 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + break; + + case HLSL_CLASS_DEPTH_STENCIL_VIEW: +- case HLSL_CLASS_OBJECT: ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_RENDER_TARGET_VIEW: ++ case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_TEXTURE: + case HLSL_CLASS_UAV: ++ case HLSL_CLASS_VERTEX_SHADER: + put_u32_unaligned(buffer, 2); + break; + +@@ -453,7 +460,6 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + case HLSL_CLASS_TECHNIQUE: + vkd3d_unreachable(); + +- case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: + case HLSL_CLASS_VOID: + FIXME("Writing type class %u is not implemented.\n", type->class); +@@ -509,6 +515,10 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + + put_u32_unaligned(buffer, texture_type[type->sampler_dim]); + } ++ else if (type->class == HLSL_CLASS_SAMPLER) ++ { ++ put_u32_unaligned(buffer, 21); ++ } + else if (type->class == HLSL_CLASS_UAV) + { + static const uint32_t uav_type[] = +@@ -532,24 +542,13 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + { + put_u32_unaligned(buffer, 19); + } +- else if (type->class == HLSL_CLASS_OBJECT) ++ else if (type->class == HLSL_CLASS_PIXEL_SHADER) + { +- static const uint32_t object_type[] = +- { +- [HLSL_TYPE_PIXELSHADER] = 5, +- [HLSL_TYPE_VERTEXSHADER] = 6, +- }; +- +- switch (type->base_type) +- { +- case HLSL_TYPE_PIXELSHADER: +- case HLSL_TYPE_VERTEXSHADER: +- put_u32_unaligned(buffer, object_type[type->base_type]); +- break; +- default: +- hlsl_fixme(ctx, &ctx->location, "Object type %u is not supported.", type->base_type); +- return 0; +- } ++ put_u32_unaligned(buffer, 5); ++ } ++ else if (type->class == HLSL_CLASS_VERTEX_SHADER) ++ { ++ put_u32_unaligned(buffer, 6); + } + else if (hlsl_is_numeric_type(type)) + { +@@ -838,20 +837,10 @@ static bool is_type_supported_fx_2(struct hlsl_ctx *ctx, const struct hlsl_type + } + break; + +- case HLSL_CLASS_OBJECT: +- switch (type->base_type) +- { +- case HLSL_TYPE_PIXELSHADER: +- case HLSL_TYPE_VERTEXSHADER: +- hlsl_fixme(ctx, loc, "Write fx 2.0 parameter object type %#x.", type->base_type); +- return false; +- +- default: +- return false; +- } +- ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: ++ case HLSL_CLASS_VERTEX_SHADER: + hlsl_fixme(ctx, loc, "Write fx 2.0 parameter class %#x.", type->class); + return false; + +@@ -1012,6 +1001,317 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write + hlsl_fixme(ctx, &ctx->location, "Writing annotations for numeric variables is not implemented."); + } + ++struct rhs_named_value ++{ ++ const char *name; ++ unsigned int value; ++}; ++ ++static bool get_fx_4_state_enum_value(const struct rhs_named_value *pairs, ++ const char *name, unsigned int *value) ++{ ++ while (pairs->name) ++ { ++ if (!ascii_strcasecmp(pairs->name, name)) ++ { ++ *value = pairs->value; ++ return true; ++ } ++ ++ pairs++; ++ } ++ ++ return false; ++} ++ ++static uint32_t write_fx_4_state_numeric_value(struct hlsl_ir_constant *value, struct fx_write_context *fx) ++{ ++ struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; ++ struct hlsl_type *data_type = value->node.data_type; ++ struct hlsl_ctx *ctx = fx->ctx; ++ uint32_t i, type, offset; ++ unsigned int count = hlsl_type_component_count(data_type); ++ ++ offset = put_u32_unaligned(buffer, count); ++ ++ for (i = 0; i < count; ++i) ++ { ++ if (hlsl_is_numeric_type(data_type)) ++ { ++ switch (data_type->e.numeric.type) ++ { ++ case HLSL_TYPE_FLOAT: ++ case HLSL_TYPE_INT: ++ case HLSL_TYPE_UINT: ++ case HLSL_TYPE_BOOL: ++ type = fx_4_numeric_base_type[data_type->e.numeric.type]; ++ break; ++ default: ++ type = 0; ++ hlsl_fixme(ctx, &ctx->location, "Unsupported numeric state value type %u.", data_type->e.numeric.type); ++ } ++ } ++ ++ put_u32_unaligned(buffer, type); ++ put_u32_unaligned(buffer, value->value.u[i].u); ++ } ++ ++ return offset; ++} ++ ++static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry, ++ struct fx_write_context *fx) ++{ ++ uint32_t value_offset = 0, assignment_type = 0, rhs_offset; ++ uint32_t type_offset; ++ struct vkd3d_bytecode_buffer *buffer = &fx->structured; ++ struct hlsl_ctx *ctx = fx->ctx; ++ struct hlsl_ir_node *value = entry->args->node; ++ ++ if (entry->lhs_has_index) ++ hlsl_fixme(ctx, &var->loc, "Unsupported assignment to array element."); ++ ++ put_u32(buffer, entry->name_id); ++ put_u32(buffer, 0); /* TODO: destination index */ ++ type_offset = put_u32(buffer, 0); ++ rhs_offset = put_u32(buffer, 0); ++ ++ switch (value->type) ++ { ++ case HLSL_IR_CONSTANT: ++ { ++ struct hlsl_ir_constant *c = hlsl_ir_constant(value); ++ ++ value_offset = write_fx_4_state_numeric_value(c, fx); ++ assignment_type = 1; ++ break; ++ } ++ default: ++ hlsl_fixme(ctx, &var->loc, "Unsupported assignment type for state %s.", entry->name); ++ } ++ ++ set_u32(buffer, type_offset, assignment_type); ++ set_u32(buffer, rhs_offset, value_offset); ++} ++ ++static bool state_block_contains_state(const char *name, unsigned int start, struct hlsl_state_block *block) ++{ ++ unsigned int i; ++ ++ for (i = start; i < block->count; ++i) ++ { ++ if (!ascii_strcasecmp(block->entries[i]->name, name)) ++ return true; ++ } ++ ++ return false; ++} ++ ++struct replace_state_context ++{ ++ const struct rhs_named_value *values; ++ struct hlsl_ir_var *var; ++}; ++ ++static bool replace_state_block_constant(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) ++{ ++ struct replace_state_context *replace_context = context; ++ struct hlsl_ir_stateblock_constant *state_constant; ++ struct hlsl_ir_node *c; ++ unsigned int value; ++ ++ if (!replace_context->values) ++ return false; ++ if (instr->type != HLSL_IR_STATEBLOCK_CONSTANT) ++ return false; ++ ++ state_constant = hlsl_ir_stateblock_constant(instr); ++ if (!get_fx_4_state_enum_value(replace_context->values, state_constant->name, &value)) ++ { ++ hlsl_error(ctx, &replace_context->var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, ++ "Unrecognized state constant %s.", state_constant->name); ++ return false; ++ } ++ ++ if (!(c = hlsl_new_uint_constant(ctx, value, &replace_context->var->loc))) ++ return false; ++ ++ list_add_before(&state_constant->node.entry, &c->entry); ++ hlsl_replace_node(&state_constant->node, c); ++ ++ return true; ++} ++ ++static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry, ++ struct fx_write_context *fx) ++{ ++ static const struct rhs_named_value filter_values[] = ++ { ++ { "MIN_MAG_MIP_POINT", 0x00 }, ++ { "MIN_MAG_POINT_MIP_LINEAR", 0x01 }, ++ { "MIN_POINT_MAG_LINEAR_MIP_POINT", 0x04 }, ++ { "MIN_POINT_MAG_MIP_LINEAR", 0x05 }, ++ { "MIN_LINEAR_MAG_MIP_POINT", 0x10 }, ++ { "MIN_LINEAR_MAG_POINT_MIP_LINEAR", 0x11 }, ++ { "MIN_MAG_LINEAR_MIP_POINT", 0x14 }, ++ { "MIN_MAG_MIP_LINEAR", 0x15 }, ++ { "ANISOTROPIC", 0x55 }, ++ { "COMPARISON_MIN_MAG_MIP_POINT", 0x80 }, ++ { "COMPARISON_MIN_MAG_POINT_MIP_LINEAR", 0x81 }, ++ { "COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT", 0x84 }, ++ { "COMPARISON_MIN_POINT_MAG_MIP_LINEAR", 0x85 }, ++ { "COMPARISON_MIN_LINEAR_MAG_MIP_POINT", 0x90 }, ++ { "COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR", 0x91 }, ++ { "COMPARISON_MIN_MAG_LINEAR_MIP_POINT", 0x94 }, ++ { "COMPARISON_MIN_MAG_MIP_LINEAR", 0x95 }, ++ { "COMPARISON_ANISOTROPIC", 0xd5 }, ++ { NULL }, ++ }; ++ ++ static const struct rhs_named_value address_values[] = ++ { ++ { "WRAP", 1 }, ++ { "MIRROR", 2 }, ++ { "CLAMP", 3 }, ++ { "BORDER", 4 }, ++ { "MIRROR_ONCE", 5 }, ++ { NULL }, ++ }; ++ ++ static const struct rhs_named_value compare_func_values[] = ++ { ++ { "NEVER", 1 }, ++ { "LESS", 2 }, ++ { "EQUAL", 3 }, ++ { "LESS_EQUAL", 4 }, ++ { "GREATER", 5 }, ++ { "NOT_EQUAL", 6 }, ++ { "GREATER_EQUAL", 7 }, ++ { "ALWAYS", 8 }, ++ { NULL } ++ }; ++ ++ static const struct state ++ { ++ const char *name; ++ enum hlsl_type_class container; ++ enum hlsl_base_type type; ++ unsigned int dimx; ++ uint32_t id; ++ const struct rhs_named_value *values; ++ } ++ states[] = ++ { ++ { "Filter", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 45, filter_values }, ++ { "AddressU", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 46, address_values }, ++ { "AddressV", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 47, address_values }, ++ { "AddressW", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 48, address_values }, ++ { "MipLODBias", HLSL_CLASS_SAMPLER, HLSL_TYPE_FLOAT, 1, 49 }, ++ { "MaxAnisotropy", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 50 }, ++ { "ComparisonFunc", HLSL_CLASS_SAMPLER, HLSL_TYPE_UINT, 1, 51, compare_func_values }, ++ { "BorderColor", HLSL_CLASS_SAMPLER, HLSL_TYPE_FLOAT, 4, 52 }, ++ { "MinLOD", HLSL_CLASS_SAMPLER, HLSL_TYPE_FLOAT, 1, 53 }, ++ { "MaxLOD", HLSL_CLASS_SAMPLER, HLSL_TYPE_FLOAT, 1, 54 }, ++ /* TODO: "Texture" field */ ++ }; ++ const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); ++ struct replace_state_context replace_context; ++ struct hlsl_ir_node *node, *cast; ++ const struct state *state = NULL; ++ struct hlsl_ctx *ctx = fx->ctx; ++ struct hlsl_type *state_type; ++ unsigned int i; ++ bool progress; ++ ++ for (i = 0; i < ARRAY_SIZE(states); ++i) ++ { ++ if (type->class == states[i].container ++ && !ascii_strcasecmp(entry->name, states[i].name)) ++ { ++ state = &states[i]; ++ break; ++ } ++ } ++ ++ if (!state) ++ { ++ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Unrecognized state name %s.", entry->name); ++ return; ++ } ++ ++ if (entry->args_count != 1) ++ { ++ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Unrecognized initializer for the state %s.", ++ entry->name); ++ return; ++ } ++ ++ entry->name_id = state->id; ++ ++ replace_context.values = state->values; ++ replace_context.var = var; ++ ++ /* Turned named constants to actual constants. */ ++ hlsl_transform_ir(ctx, replace_state_block_constant, entry->instrs, &replace_context); ++ ++ if (state->dimx) ++ state_type = hlsl_get_vector_type(ctx, state->type, state->dimx); ++ else ++ state_type = hlsl_get_scalar_type(ctx, state->type); ++ ++ /* Cast to expected property type. */ ++ node = entry->args->node; ++ if (!(cast = hlsl_new_cast(ctx, node, state_type, &var->loc))) ++ return; ++ list_add_after(&node->entry, &cast->entry); ++ ++ hlsl_src_remove(entry->args); ++ hlsl_src_from_node(entry->args, cast); ++ ++ do ++ { ++ progress = hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, entry->instrs, NULL); ++ progress |= hlsl_copy_propagation_execute(ctx, entry->instrs); ++ } while (progress); ++} ++ ++static void write_fx_4_state_object_initializer(struct hlsl_ir_var *var, struct fx_write_context *fx) ++{ ++ uint32_t elements_count = hlsl_get_multiarray_size(var->data_type), i, j; ++ struct vkd3d_bytecode_buffer *buffer = &fx->structured; ++ uint32_t count_offset, count; ++ ++ for (i = 0; i < elements_count; ++i) ++ { ++ struct hlsl_state_block *block; ++ ++ count_offset = put_u32(buffer, 0); ++ ++ count = 0; ++ if (var->state_blocks) ++ { ++ block = var->state_blocks[i]; ++ ++ for (j = 0; j < block->count; ++j) ++ { ++ struct hlsl_state_block_entry *entry = block->entries[j]; ++ ++ /* Skip if property is reassigned later. This will use the last assignment. */ ++ if (state_block_contains_state(entry->name, j + 1, block)) ++ continue; ++ ++ /* Resolve special constant names and property names. */ ++ resolve_fx_4_state_block_values(var, entry, fx); ++ ++ write_fx_4_state_assignment(var, entry, fx); ++ ++count; ++ } ++ } ++ ++ set_u32(buffer, count_offset, count); ++ } ++} ++ + static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_context *fx) + { + const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); +@@ -1044,29 +1344,35 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_ + switch (type->class) + { + case HLSL_CLASS_RENDER_TARGET_VIEW: ++ fx->rtv_count += elements_count; ++ break; + case HLSL_CLASS_TEXTURE: ++ fx->texture_count += elements_count; ++ break; + case HLSL_CLASS_UAV: ++ fx->uav_count += elements_count; + break; + +- case HLSL_CLASS_OBJECT: +- switch (type->base_type) +- { +- case HLSL_TYPE_PIXELSHADER: +- case HLSL_TYPE_VERTEXSHADER: +- /* FIXME: write shader blobs, once parser support works. */ +- for (i = 0; i < elements_count; ++i) +- put_u32(buffer, 0); +- ++fx->shader_variable_count; +- break; +- default: +- hlsl_fixme(ctx, &ctx->location, "Writing initializer for object type %u is not implemented.", +- type->base_type); +- } ++ case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_VERTEX_SHADER: ++ /* FIXME: write shader blobs, once parser support works. */ ++ for (i = 0; i < elements_count; ++i) ++ put_u32(buffer, 0); ++ fx->shader_count += elements_count; ++ break; ++ ++ case HLSL_CLASS_DEPTH_STENCIL_VIEW: ++ fx->dsv_count += elements_count; ++ break; ++ ++ case HLSL_CLASS_SAMPLER: ++ write_fx_4_state_object_initializer(var, fx); ++ fx->sampler_state_count += elements_count; + break; + + default: + hlsl_fixme(ctx, &ctx->location, "Writing initializer for object type %u is not implemented.", +- type->base_type); ++ type->e.numeric.type); + } + + put_u32(buffer, 0); /* Annotations count */ +@@ -1143,27 +1449,26 @@ static void write_buffers(struct fx_write_context *fx) + } + } + +-static bool is_object_variable(const struct hlsl_ir_var *var) ++static bool is_supported_object_variable(const struct hlsl_ctx *ctx, const struct hlsl_ir_var *var) + { + const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); + + switch (type->class) + { ++ case HLSL_CLASS_DEPTH_STENCIL_VIEW: ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_TEXTURE: ++ return true; + case HLSL_CLASS_UAV: ++ if (ctx->profile->major_version < 5) ++ return false; ++ if (type->e.resource.rasteriser_ordered) ++ return false; ++ return true; ++ case HLSL_CLASS_VERTEX_SHADER: + return true; +- +- case HLSL_CLASS_OBJECT: +- switch (type->base_type) +- { +- case HLSL_TYPE_PIXELSHADER: +- case HLSL_TYPE_VERTEXSHADER: +- return true; +- default: +- return false; +- } + + default: + return false; +@@ -1172,14 +1477,15 @@ static bool is_object_variable(const struct hlsl_ir_var *var) + + static void write_objects(struct fx_write_context *fx, bool shared) + { ++ struct hlsl_ctx *ctx = fx->ctx; + struct hlsl_ir_var *var; + + if (shared && !fx->child_effect) + return; + +- LIST_FOR_EACH_ENTRY(var, &fx->ctx->extern_vars, struct hlsl_ir_var, extern_entry) ++ LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { +- if (!is_object_variable(var)) ++ if (!is_supported_object_variable(ctx, var)) + continue; + + if (fx->child_effect && (shared != !!(var->storage_modifiers & HLSL_STORAGE_SHARED))) +@@ -1216,14 +1522,14 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) + put_u32(&buffer, fx.technique_count); + size_offset = put_u32(&buffer, 0); /* Unstructured size. */ + put_u32(&buffer, 0); /* String count. */ +- put_u32(&buffer, 0); /* Texture object count. */ ++ put_u32(&buffer, fx.texture_count); + put_u32(&buffer, 0); /* Depth stencil state count. */ + put_u32(&buffer, 0); /* Blend state count. */ + put_u32(&buffer, 0); /* Rasterizer state count. */ +- put_u32(&buffer, 0); /* Sampler state count. */ +- put_u32(&buffer, 0); /* Rendertarget view count. */ +- put_u32(&buffer, 0); /* Depth stencil view count. */ +- put_u32(&buffer, fx.shader_variable_count); /* Shader count. */ ++ put_u32(&buffer, fx.sampler_state_count); ++ put_u32(&buffer, fx.rtv_count); ++ put_u32(&buffer, fx.dsv_count); ++ put_u32(&buffer, fx.shader_count); + put_u32(&buffer, 0); /* Inline shader count. */ + + set_u32(&buffer, size_offset, fx.unstructured.size); +@@ -1274,17 +1580,17 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) + put_u32(&buffer, fx.technique_count); + size_offset = put_u32(&buffer, 0); /* Unstructured size. */ + put_u32(&buffer, 0); /* String count. */ +- put_u32(&buffer, 0); /* Texture object count. */ ++ put_u32(&buffer, fx.texture_count); + put_u32(&buffer, 0); /* Depth stencil state count. */ + put_u32(&buffer, 0); /* Blend state count. */ + put_u32(&buffer, 0); /* Rasterizer state count. */ +- put_u32(&buffer, 0); /* Sampler state count. */ +- put_u32(&buffer, 0); /* Rendertarget view count. */ +- put_u32(&buffer, 0); /* Depth stencil view count. */ +- put_u32(&buffer, fx.shader_variable_count); /* Shader count. */ ++ put_u32(&buffer, fx.sampler_state_count); ++ put_u32(&buffer, fx.rtv_count); ++ put_u32(&buffer, fx.dsv_count); ++ put_u32(&buffer, fx.shader_count); + put_u32(&buffer, 0); /* Inline shader count. */ + put_u32(&buffer, fx.group_count); /* Group count. */ +- put_u32(&buffer, 0); /* UAV count. */ ++ put_u32(&buffer, fx.uav_count); + put_u32(&buffer, 0); /* Interface variables count. */ + put_u32(&buffer, 0); /* Interface variable element count. */ + put_u32(&buffer, 0); /* Class instance elements count. */ +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +index 0b48b17d21c..96e73d23d72 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +@@ -136,7 +136,11 @@ struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name) + + static void free_state_block_entry(struct hlsl_state_block_entry *entry) + { ++ unsigned int i; ++ + vkd3d_free(entry->name); ++ for (i = 0; i < entry->args_count; ++i) ++ hlsl_src_remove(&entry->args[i]); + vkd3d_free(entry->args); + hlsl_block_cleanup(entry->instrs); + vkd3d_free(entry->instrs); +@@ -365,11 +369,12 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type + + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: +- case HLSL_CLASS_OBJECT: + case HLSL_CLASS_PASS: ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_STRING: + case HLSL_CLASS_TECHNIQUE: ++ case HLSL_CLASS_VERTEX_SHADER: + case HLSL_CLASS_VOID: + break; + } +@@ -416,7 +421,7 @@ static struct hlsl_type *hlsl_new_type(struct hlsl_ctx *ctx, const char *name, e + return NULL; + } + type->class = type_class; +- type->base_type = base_type; ++ type->e.numeric.type = base_type; + type->dimx = dimx; + type->dimy = dimy; + hlsl_type_calculate_reg_size(ctx, type); +@@ -431,13 +436,14 @@ static bool type_is_single_component(const struct hlsl_type *type) + switch (type->class) + { + case HLSL_CLASS_DEPTH_STENCIL_VIEW: ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_SCALAR: +- case HLSL_CLASS_OBJECT: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_TEXTURE: + case HLSL_CLASS_UAV: ++ case HLSL_CLASS_VERTEX_SHADER: + return true; + + case HLSL_CLASS_VECTOR: +@@ -475,7 +481,7 @@ static unsigned int traverse_path_from_component_index(struct hlsl_ctx *ctx, + { + case HLSL_CLASS_VECTOR: + assert(index < type->dimx); +- *type_ptr = hlsl_get_scalar_type(ctx, type->base_type); ++ *type_ptr = hlsl_get_scalar_type(ctx, type->e.numeric.type); + *index_ptr = 0; + return index; + +@@ -485,7 +491,7 @@ static unsigned int traverse_path_from_component_index(struct hlsl_ctx *ctx, + bool row_major = hlsl_type_is_row_major(type); + + assert(index < type->dimx * type->dimy); +- *type_ptr = hlsl_get_vector_type(ctx, type->base_type, row_major ? type->dimx : type->dimy); ++ *type_ptr = hlsl_get_vector_type(ctx, type->e.numeric.type, row_major ? type->dimx : type->dimy); + *index_ptr = row_major ? x : y; + return row_major ? y : x; + } +@@ -572,12 +578,13 @@ unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_ty + break; + + case HLSL_CLASS_DEPTH_STENCIL_VIEW: +- case HLSL_CLASS_OBJECT: ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: + case HLSL_CLASS_TEXTURE: + case HLSL_CLASS_UAV: ++ case HLSL_CLASS_VERTEX_SHADER: + assert(idx == 0); + break; + +@@ -758,13 +765,13 @@ struct hlsl_type *hlsl_get_element_type_from_path_index(struct hlsl_ctx *ctx, co + switch (type->class) + { + case HLSL_CLASS_VECTOR: +- return hlsl_get_scalar_type(ctx, type->base_type); ++ return hlsl_get_scalar_type(ctx, type->e.numeric.type); + + case HLSL_CLASS_MATRIX: + if (hlsl_type_is_row_major(type)) +- return hlsl_get_vector_type(ctx, type->base_type, type->dimx); ++ return hlsl_get_vector_type(ctx, type->e.numeric.type, type->dimx); + else +- return hlsl_get_vector_type(ctx, type->base_type, type->dimy); ++ return hlsl_get_vector_type(ctx, type->e.numeric.type, type->dimy); + + case HLSL_CLASS_ARRAY: + return type->e.array.type; +@@ -950,12 +957,13 @@ unsigned int hlsl_type_component_count(const struct hlsl_type *type) + return hlsl_type_component_count(type->e.array.type) * type->e.array.elements_count; + + case HLSL_CLASS_DEPTH_STENCIL_VIEW: +- case HLSL_CLASS_OBJECT: ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: + case HLSL_CLASS_TEXTURE: + case HLSL_CLASS_UAV: ++ case HLSL_CLASS_VERTEX_SHADER: + return 1; + + case HLSL_CLASS_EFFECT_GROUP: +@@ -975,55 +983,73 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 + + if (t1->class != t2->class) + return false; +- if (t1->base_type != t2->base_type) +- return false; +- if (t1->class == HLSL_CLASS_SAMPLER || t1->class == HLSL_CLASS_TEXTURE || t1->class == HLSL_CLASS_UAV) +- { +- if (t1->sampler_dim != t2->sampler_dim) +- return false; +- if ((t1->class == HLSL_CLASS_TEXTURE || t1->class == HLSL_CLASS_UAV) +- && t1->sampler_dim != HLSL_SAMPLER_DIM_GENERIC +- && !hlsl_types_are_equal(t1->e.resource.format, t2->e.resource.format)) +- return false; +- if (t1->class == HLSL_CLASS_UAV && t1->e.resource.rasteriser_ordered != t2->e.resource.rasteriser_ordered) +- return false; +- } +- if ((t1->modifiers & HLSL_MODIFIER_ROW_MAJOR) +- != (t2->modifiers & HLSL_MODIFIER_ROW_MAJOR)) +- return false; +- if (t1->dimx != t2->dimx) +- return false; +- if (t1->dimy != t2->dimy) +- return false; +- if (t1->class == HLSL_CLASS_STRUCT) +- { +- size_t i; + +- if (t1->e.record.field_count != t2->e.record.field_count) +- return false; +- +- for (i = 0; i < t1->e.record.field_count; ++i) +- { +- const struct hlsl_struct_field *field1 = &t1->e.record.fields[i]; +- const struct hlsl_struct_field *field2 = &t2->e.record.fields[i]; ++ switch (t1->class) ++ { ++ case HLSL_CLASS_SCALAR: ++ case HLSL_CLASS_VECTOR: ++ case HLSL_CLASS_MATRIX: ++ if (t1->e.numeric.type != t2->e.numeric.type) ++ return false; ++ if ((t1->modifiers & HLSL_MODIFIER_ROW_MAJOR) ++ != (t2->modifiers & HLSL_MODIFIER_ROW_MAJOR)) ++ return false; ++ if (t1->dimx != t2->dimx) ++ return false; ++ if (t1->dimy != t2->dimy) ++ return false; ++ return true; + +- if (!hlsl_types_are_equal(field1->type, field2->type)) ++ case HLSL_CLASS_UAV: ++ if (t1->e.resource.rasteriser_ordered != t2->e.resource.rasteriser_ordered) ++ return false; ++ /* fall through */ ++ case HLSL_CLASS_TEXTURE: ++ if (t1->sampler_dim != HLSL_SAMPLER_DIM_GENERIC ++ && !hlsl_types_are_equal(t1->e.resource.format, t2->e.resource.format)) + return false; ++ /* fall through */ ++ case HLSL_CLASS_SAMPLER: ++ if (t1->sampler_dim != t2->sampler_dim) ++ return false; ++ return true; + +- if (strcmp(field1->name, field2->name)) ++ case HLSL_CLASS_STRUCT: ++ if (t1->e.record.field_count != t2->e.record.field_count) + return false; +- } +- } +- if (t1->class == HLSL_CLASS_ARRAY) +- return t1->e.array.elements_count == t2->e.array.elements_count +- && hlsl_types_are_equal(t1->e.array.type, t2->e.array.type); +- if (t1->class == HLSL_CLASS_TECHNIQUE) +- { +- if (t1->e.version != t2->e.version) +- return false; ++ ++ for (size_t i = 0; i < t1->e.record.field_count; ++i) ++ { ++ const struct hlsl_struct_field *field1 = &t1->e.record.fields[i]; ++ const struct hlsl_struct_field *field2 = &t2->e.record.fields[i]; ++ ++ if (!hlsl_types_are_equal(field1->type, field2->type)) ++ return false; ++ ++ if (strcmp(field1->name, field2->name)) ++ return false; ++ } ++ return true; ++ ++ case HLSL_CLASS_ARRAY: ++ return t1->e.array.elements_count == t2->e.array.elements_count ++ && hlsl_types_are_equal(t1->e.array.type, t2->e.array.type); ++ ++ case HLSL_CLASS_TECHNIQUE: ++ return t1->e.version == t2->e.version; ++ ++ case HLSL_CLASS_DEPTH_STENCIL_VIEW: ++ case HLSL_CLASS_EFFECT_GROUP: ++ case HLSL_CLASS_PASS: ++ case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_RENDER_TARGET_VIEW: ++ case HLSL_CLASS_STRING: ++ case HLSL_CLASS_VERTEX_SHADER: ++ case HLSL_CLASS_VOID: ++ return true; + } + +- return true; ++ vkd3d_unreachable(); + } + + struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, +@@ -1044,7 +1070,6 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, + } + } + type->class = old->class; +- type->base_type = old->base_type; + type->dimx = old->dimx; + type->dimy = old->dimy; + type->modifiers = old->modifiers | modifiers; +@@ -1056,6 +1081,12 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, + + switch (old->class) + { ++ case HLSL_CLASS_SCALAR: ++ case HLSL_CLASS_VECTOR: ++ case HLSL_CLASS_MATRIX: ++ type->e.numeric.type = old->e.numeric.type; ++ break; ++ + case HLSL_CLASS_ARRAY: + if (!(type->e.array.type = hlsl_type_clone(ctx, old->e.array.type, default_majority, modifiers))) + { +@@ -1643,10 +1674,11 @@ struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned + + if (!(swizzle = hlsl_alloc(ctx, sizeof(*swizzle)))) + return NULL; ++ assert(hlsl_is_numeric_type(val->data_type)); + if (components == 1) +- type = hlsl_get_scalar_type(ctx, val->data_type->base_type); ++ type = hlsl_get_scalar_type(ctx, val->data_type->e.numeric.type); + else +- type = hlsl_get_vector_type(ctx, val->data_type->base_type, components); ++ type = hlsl_get_vector_type(ctx, val->data_type->e.numeric.type, components); + init_node(&swizzle->node, HLSL_IR_SWIZZLE, type, loc); + hlsl_src_from_node(&swizzle->val, val); + swizzle->swizzle = s; +@@ -1709,7 +1741,7 @@ struct hlsl_ir_node *hlsl_new_index(struct hlsl_ctx *ctx, struct hlsl_ir_node *v + if (type->class == HLSL_CLASS_TEXTURE || type->class == HLSL_CLASS_UAV) + type = type->e.resource.format; + else if (type->class == HLSL_CLASS_MATRIX) +- type = hlsl_get_vector_type(ctx, type->base_type, type->dimx); ++ type = hlsl_get_vector_type(ctx, type->e.numeric.type, type->dimx); + else + type = hlsl_get_element_type_from_path_index(ctx, type, idx); + +@@ -2295,18 +2327,18 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru + switch (type->class) + { + case HLSL_CLASS_SCALAR: +- assert(type->base_type < ARRAY_SIZE(base_types)); +- vkd3d_string_buffer_printf(string, "%s", base_types[type->base_type]); ++ assert(type->e.numeric.type < ARRAY_SIZE(base_types)); ++ vkd3d_string_buffer_printf(string, "%s", base_types[type->e.numeric.type]); + return string; + + case HLSL_CLASS_VECTOR: +- assert(type->base_type < ARRAY_SIZE(base_types)); +- vkd3d_string_buffer_printf(string, "%s%u", base_types[type->base_type], type->dimx); ++ assert(type->e.numeric.type < ARRAY_SIZE(base_types)); ++ vkd3d_string_buffer_printf(string, "%s%u", base_types[type->e.numeric.type], type->dimx); + return string; + + case HLSL_CLASS_MATRIX: +- assert(type->base_type < ARRAY_SIZE(base_types)); +- vkd3d_string_buffer_printf(string, "%s%ux%u", base_types[type->base_type], type->dimy, type->dimx); ++ assert(type->e.numeric.type < ARRAY_SIZE(base_types)); ++ vkd3d_string_buffer_printf(string, "%s%ux%u", base_types[type->e.numeric.type], type->dimy, type->dimx); + return string; + + case HLSL_CLASS_ARRAY: +@@ -2343,7 +2375,8 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru + return string; + } + +- assert(type->e.resource.format->base_type < ARRAY_SIZE(base_types)); ++ assert(hlsl_is_numeric_type(type->e.resource.format)); ++ assert(type->e.resource.format->e.numeric.type < ARRAY_SIZE(base_types)); + if (type->sampler_dim == HLSL_SAMPLER_DIM_BUFFER) + { + vkd3d_string_buffer_printf(string, "Buffer"); +@@ -2376,12 +2409,13 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru + + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: +- case HLSL_CLASS_OBJECT: + case HLSL_CLASS_PASS: ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: + case HLSL_CLASS_TECHNIQUE: ++ case HLSL_CLASS_VERTEX_SHADER: + case HLSL_CLASS_VOID: + break; + } +@@ -2665,7 +2699,7 @@ static void dump_ir_constant(struct vkd3d_string_buffer *buffer, const struct hl + { + const union hlsl_constant_value_component *value = &constant->value.u[x]; + +- switch (type->base_type) ++ switch (type->e.numeric.type) + { + case HLSL_TYPE_BOOL: + vkd3d_string_buffer_printf(buffer, "%s ", value->u ? "true" : "false"); +@@ -3557,8 +3591,6 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) + {"dword", HLSL_CLASS_SCALAR, HLSL_TYPE_UINT, 1, 1}, + {"vector", HLSL_CLASS_VECTOR, HLSL_TYPE_FLOAT, 4, 1}, + {"matrix", HLSL_CLASS_MATRIX, HLSL_TYPE_FLOAT, 4, 4}, +- {"pixelshader", HLSL_CLASS_OBJECT, HLSL_TYPE_PIXELSHADER, 1, 1}, +- {"vertexshader", HLSL_CLASS_OBJECT, HLSL_TYPE_VERTEXSHADER, 1, 1}, + }; + + static const struct +@@ -3682,9 +3714,11 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) + hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "DepthStencilView", HLSL_CLASS_DEPTH_STENCIL_VIEW)); + hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "fxgroup", HLSL_CLASS_EFFECT_GROUP)); + hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "pass", HLSL_CLASS_PASS)); ++ hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "pixelshader", HLSL_CLASS_PIXEL_SHADER)); + hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "RenderTargetView", HLSL_CLASS_RENDER_TARGET_VIEW)); + hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "STRING", HLSL_CLASS_STRING)); + hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "texture", HLSL_CLASS_TEXTURE)); ++ hlsl_scope_add_type(ctx->globals, hlsl_new_simple_type(ctx, "vertexshader", HLSL_CLASS_VERTEX_SHADER)); + + for (i = 0; i < ARRAY_SIZE(effect_types); ++i) + { +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +index c3a4c6bd291..a89e43f9bf2 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +@@ -78,16 +78,17 @@ enum hlsl_type_class + HLSL_CLASS_LAST_NUMERIC = HLSL_CLASS_MATRIX, + HLSL_CLASS_STRUCT, + HLSL_CLASS_ARRAY, +- HLSL_CLASS_OBJECT, + HLSL_CLASS_DEPTH_STENCIL_VIEW, + HLSL_CLASS_EFFECT_GROUP, + HLSL_CLASS_PASS, ++ HLSL_CLASS_PIXEL_SHADER, + HLSL_CLASS_RENDER_TARGET_VIEW, + HLSL_CLASS_SAMPLER, + HLSL_CLASS_STRING, + HLSL_CLASS_TECHNIQUE, + HLSL_CLASS_TEXTURE, + HLSL_CLASS_UAV, ++ HLSL_CLASS_VERTEX_SHADER, + HLSL_CLASS_VOID, + }; + +@@ -100,8 +101,6 @@ enum hlsl_base_type + HLSL_TYPE_UINT, + HLSL_TYPE_BOOL, + HLSL_TYPE_LAST_SCALAR = HLSL_TYPE_BOOL, +- HLSL_TYPE_PIXELSHADER, +- HLSL_TYPE_VERTEXSHADER, + }; + + enum hlsl_sampler_dim +@@ -143,10 +142,6 @@ struct hlsl_type + struct rb_entry scope_entry; + + enum hlsl_type_class class; +- /* If class is <= HLSL_CLASS_LAST_NUMERIC, then base_type is <= HLSL_TYPE_LAST_SCALAR. +- * If class is HLSL_CLASS_OBJECT, then base_type is > HLSL_TYPE_LAST_SCALAR. +- * Otherwise, base_type is not used. */ +- enum hlsl_base_type base_type; + + /* If class is HLSL_CLASS_SAMPLER, then sampler_dim is <= HLSL_SAMPLER_DIM_LAST_SAMPLER. + * If class is HLSL_CLASS_TEXTURE, then sampler_dim can be any value of the enum except +@@ -177,6 +172,11 @@ struct hlsl_type + + union + { ++ /* Additional information if type is numeric. */ ++ struct ++ { ++ enum hlsl_base_type type; ++ } numeric; + /* Additional information if type is HLSL_CLASS_STRUCT. */ + struct + { +@@ -474,6 +474,8 @@ struct hlsl_state_block_entry + { + /* For assignments, the name in the lhs. */ + char *name; ++ /* Resolved format-specific property identifier. */ ++ unsigned int name_id; + + /* Whether the lhs in the assignment is indexed and, in that case, its index. */ + bool lhs_has_index; +@@ -483,7 +485,7 @@ struct hlsl_state_block_entry + struct hlsl_block *instrs; + + /* For assignments, arguments of the rhs initializer. */ +- struct hlsl_ir_node **args; ++ struct hlsl_src *args; + unsigned int args_count; + }; + +@@ -1400,7 +1402,6 @@ unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int + bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2); + + void hlsl_calculate_buffer_offsets(struct hlsl_ctx *ctx); +-void hlsl_prepend_global_uniform_copy(struct hlsl_ctx *ctx, struct hlsl_block *block); + + const struct hlsl_type *hlsl_get_multiarray_element_type(const struct hlsl_type *type); + unsigned int hlsl_get_multiarray_size(const struct hlsl_type *type); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index 0eed15c5a91..79317bb0545 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -1352,9 +1352,6 @@ static unsigned int evaluate_static_expression_as_uint(struct hlsl_ctx *ctx, str + + static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) + { +- if (t1->base_type > HLSL_TYPE_LAST_SCALAR || t2->base_type > HLSL_TYPE_LAST_SCALAR) +- return false; +- + /* Scalar vars can be converted to pretty much everything */ + if ((t1->dimx == 1 && t1->dimy == 1) || (t2->dimx == 1 && t2->dimy == 1)) + return true; +@@ -1386,10 +1383,6 @@ static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t + + static enum hlsl_base_type expr_common_base_type(enum hlsl_base_type t1, enum hlsl_base_type t2) + { +- if (t1 > HLSL_TYPE_LAST_SCALAR || t2 > HLSL_TYPE_LAST_SCALAR) { +- FIXME("Unexpected base type.\n"); +- return HLSL_TYPE_FLOAT; +- } + if (t1 == t2) + return t1 == HLSL_TYPE_BOOL ? HLSL_TYPE_INT : t1; + if (t1 == HLSL_TYPE_DOUBLE || t2 == HLSL_TYPE_DOUBLE) +@@ -1493,7 +1486,7 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct hlsl_block *bl + struct hlsl_ir_node *load; + struct hlsl_ir_var *var; + +- scalar_type = hlsl_get_scalar_type(ctx, type->base_type); ++ scalar_type = hlsl_get_scalar_type(ctx, type->e.numeric.type); + + if (!(var = hlsl_new_synthetic_var(ctx, "split_op", type, loc))) + return NULL; +@@ -1543,7 +1536,7 @@ static void check_integer_type(struct hlsl_ctx *ctx, const struct hlsl_ir_node * + const struct hlsl_type *type = instr->data_type; + struct vkd3d_string_buffer *string; + +- switch (type->base_type) ++ switch (type->e.numeric.type) + { + case HLSL_TYPE_BOOL: + case HLSL_TYPE_INT: +@@ -1593,13 +1586,13 @@ static struct hlsl_ir_node *add_unary_logical_expr(struct hlsl_ctx *ctx, struct + static struct hlsl_type *get_common_numeric_type(struct hlsl_ctx *ctx, const struct hlsl_ir_node *arg1, + const struct hlsl_ir_node *arg2, const struct vkd3d_shader_location *loc) + { +- enum hlsl_base_type base = expr_common_base_type(arg1->data_type->base_type, arg2->data_type->base_type); + enum hlsl_type_class type; ++ enum hlsl_base_type base; + unsigned int dimx, dimy; + + if (!expr_common_shape(ctx, arg1->data_type, arg2->data_type, loc, &type, &dimx, &dimy)) + return NULL; +- ++ base = expr_common_base_type(arg1->data_type->e.numeric.type, arg2->data_type->e.numeric.type); + return hlsl_get_numeric_type(ctx, type, base, dimx, dimy); + } + +@@ -1636,14 +1629,15 @@ static struct hlsl_ir_node *add_binary_comparison_expr(struct hlsl_ctx *ctx, str + const struct vkd3d_shader_location *loc) + { + struct hlsl_type *common_type, *return_type; +- enum hlsl_base_type base = expr_common_base_type(arg1->data_type->base_type, arg2->data_type->base_type); + enum hlsl_type_class type; ++ enum hlsl_base_type base; + unsigned int dimx, dimy; + struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; + + if (!expr_common_shape(ctx, arg1->data_type, arg2->data_type, loc, &type, &dimx, &dimy)) + return NULL; + ++ base = expr_common_base_type(arg1->data_type->e.numeric.type, arg2->data_type->e.numeric.type); + common_type = hlsl_get_numeric_type(ctx, type, base, dimx, dimy); + return_type = hlsl_get_numeric_type(ctx, type, HLSL_TYPE_BOOL, dimx, dimy); + +@@ -1683,7 +1677,7 @@ static struct hlsl_ir_node *add_binary_shift_expr(struct hlsl_ctx *ctx, struct h + enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2, + const struct vkd3d_shader_location *loc) + { +- enum hlsl_base_type base = arg1->data_type->base_type; ++ enum hlsl_base_type base = arg1->data_type->e.numeric.type; + struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; + struct hlsl_type *return_type, *integer_type; + enum hlsl_type_class type; +@@ -1713,7 +1707,7 @@ static struct hlsl_ir_node *add_binary_shift_expr(struct hlsl_ctx *ctx, struct h + static struct hlsl_ir_node *add_binary_dot_expr(struct hlsl_ctx *ctx, struct hlsl_block *instrs, + struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2, const struct vkd3d_shader_location *loc) + { +- enum hlsl_base_type base = expr_common_base_type(arg1->data_type->base_type, arg2->data_type->base_type); ++ enum hlsl_base_type base = expr_common_base_type(arg1->data_type->e.numeric.type, arg2->data_type->e.numeric.type); + struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; + struct hlsl_type *common_type, *ret_type; + enum hlsl_ir_expr_op op; +@@ -1964,7 +1958,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo + "Resource store expressions must write to all components."); + + assert(coords->data_type->class == HLSL_CLASS_VECTOR); +- assert(coords->data_type->base_type == HLSL_TYPE_UINT); ++ assert(coords->data_type->e.numeric.type == HLSL_TYPE_UINT); + assert(coords->data_type->dimx == dim_count); + + if (!(store = hlsl_new_resource_store(ctx, &resource_deref, coords, rhs, &lhs->loc))) +@@ -2603,7 +2597,7 @@ static struct hlsl_ir_node *intrinsic_float_convert_arg(struct hlsl_ctx *ctx, + { + struct hlsl_type *type = arg->data_type; + +- if (type->base_type == HLSL_TYPE_FLOAT || type->base_type == HLSL_TYPE_HALF) ++ if (type->e.numeric.type == HLSL_TYPE_FLOAT || type->e.numeric.type == HLSL_TYPE_HALF) + return arg; + + type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_FLOAT, type->dimx, type->dimy); +@@ -2630,7 +2624,7 @@ static bool convert_args(struct hlsl_ctx *ctx, const struct parse_initializer *p + static struct hlsl_type *elementwise_intrinsic_get_common_type(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +- enum hlsl_base_type base = params->args[0]->data_type->base_type; ++ enum hlsl_base_type base = params->args[0]->data_type->e.numeric.type; + bool vectors = false, matrices = false; + unsigned int dimx = 4, dimy = 4; + struct hlsl_type *common_type; +@@ -2640,7 +2634,7 @@ static struct hlsl_type *elementwise_intrinsic_get_common_type(struct hlsl_ctx * + { + struct hlsl_type *arg_type = params->args[i]->data_type; + +- base = expr_common_base_type(base, arg_type->base_type); ++ base = expr_common_base_type(base, arg_type->e.numeric.type); + + if (arg_type->class == HLSL_CLASS_VECTOR) + { +@@ -2697,7 +2691,7 @@ static bool elementwise_intrinsic_float_convert_args(struct hlsl_ctx *ctx, + if (!(type = elementwise_intrinsic_get_common_type(ctx, params, loc))) + return false; + +- base_type = type->base_type == HLSL_TYPE_HALF ? HLSL_TYPE_HALF : HLSL_TYPE_FLOAT; ++ base_type = type->e.numeric.type == HLSL_TYPE_HALF ? HLSL_TYPE_HALF : HLSL_TYPE_FLOAT; + type = hlsl_get_numeric_type(ctx, type->class, base_type, type->dimx, type->dimy); + + return convert_args(ctx, params, type, loc); +@@ -2921,7 +2915,7 @@ static bool intrinsic_asfloat(struct hlsl_ctx *ctx, + struct hlsl_type *data_type; + + data_type = params->args[0]->data_type; +- if (data_type->base_type == HLSL_TYPE_BOOL || data_type->base_type == HLSL_TYPE_DOUBLE) ++ if (data_type->e.numeric.type == HLSL_TYPE_BOOL || data_type->e.numeric.type == HLSL_TYPE_DOUBLE) + { + struct vkd3d_string_buffer *string; + +@@ -2957,7 +2951,7 @@ static bool intrinsic_asuint(struct hlsl_ctx *ctx, + } + + data_type = params->args[0]->data_type; +- if (data_type->base_type == HLSL_TYPE_BOOL || data_type->base_type == HLSL_TYPE_DOUBLE) ++ if (data_type->e.numeric.type == HLSL_TYPE_BOOL || data_type->e.numeric.type == HLSL_TYPE_DOUBLE) + { + struct vkd3d_string_buffer *string; + +@@ -3086,7 +3080,7 @@ static bool intrinsic_cross(struct hlsl_ctx *ctx, + struct hlsl_type *cast_type; + enum hlsl_base_type base; + +- if (arg1->data_type->base_type == HLSL_TYPE_HALF && arg2->data_type->base_type == HLSL_TYPE_HALF) ++ if (arg1->data_type->e.numeric.type == HLSL_TYPE_HALF && arg2->data_type->e.numeric.type == HLSL_TYPE_HALF) + base = HLSL_TYPE_HALF; + else + base = HLSL_TYPE_FLOAT; +@@ -3267,7 +3261,7 @@ static bool intrinsic_determinant(struct hlsl_ctx *ctx, + return hlsl_add_load_component(ctx, params->instrs, arg, 0, loc); + } + +- typename = type->base_type == HLSL_TYPE_HALF ? "half" : "float"; ++ typename = type->e.numeric.type == HLSL_TYPE_HALF ? "half" : "float"; + template = templates[dim]; + + switch (dim) +@@ -3621,7 +3615,7 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { + struct hlsl_ir_node *arg1 = params->args[0], *arg2 = params->args[1], *cast1, *cast2; +- enum hlsl_base_type base = expr_common_base_type(arg1->data_type->base_type, arg2->data_type->base_type); ++ enum hlsl_base_type base = expr_common_base_type(arg1->data_type->e.numeric.type, arg2->data_type->e.numeric.type); + struct hlsl_type *cast_type1 = arg1->data_type, *cast_type2 = arg2->data_type, *matrix_type, *ret_type; + unsigned int i, j, k, vect_count = 0; + struct hlsl_deref var_deref; +@@ -3824,7 +3818,7 @@ static bool intrinsic_refract(struct hlsl_ctx *ctx, + if (!(res_type = elementwise_intrinsic_get_common_type(ctx, &mut_params, loc))) + return false; + +- base = expr_common_base_type(res_type->base_type, i_type->base_type); ++ base = expr_common_base_type(res_type->e.numeric.type, i_type->e.numeric.type); + base = base == HLSL_TYPE_HALF ? HLSL_TYPE_HALF : HLSL_TYPE_FLOAT; + res_type = convert_numeric_type(ctx, res_type, base); + idx_type = convert_numeric_type(ctx, i_type, base); +@@ -3884,7 +3878,7 @@ static bool intrinsic_sign(struct hlsl_ctx *ctx, + struct hlsl_type *int_type = hlsl_get_numeric_type(ctx, arg->data_type->class, HLSL_TYPE_INT, + arg->data_type->dimx, arg->data_type->dimy); + +- if (!(zero = hlsl_new_constant(ctx, hlsl_get_scalar_type(ctx, arg->data_type->base_type), &zero_value, loc))) ++ if (!(zero = hlsl_new_constant(ctx, hlsl_get_scalar_type(ctx, arg->data_type->e.numeric.type), &zero_value, loc))) + return false; + hlsl_block_add_instr(params->instrs, zero); + +@@ -4257,7 +4251,7 @@ static bool intrinsic_transpose(struct hlsl_ctx *ctx, + return true; + } + +- mat_type = hlsl_get_matrix_type(ctx, arg_type->base_type, arg_type->dimy, arg_type->dimx); ++ mat_type = hlsl_get_matrix_type(ctx, arg_type->e.numeric.type, arg_type->dimy, arg_type->dimx); + + if (!(var = hlsl_new_synthetic_var(ctx, "transpose", mat_type, loc))) + return false; +@@ -4553,7 +4547,7 @@ static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, + if (common_type->dimx == 1 && common_type->dimy == 1) + { + common_type = hlsl_get_numeric_type(ctx, cond_type->class, +- common_type->base_type, cond_type->dimx, cond_type->dimy); ++ common_type->e.numeric.type, cond_type->dimx, cond_type->dimy); + } + else if (cond_type->dimx != common_type->dimx || cond_type->dimy != common_type->dimy) + { +@@ -4603,7 +4597,7 @@ static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, + common_type = first->data_type; + } + +- assert(cond->data_type->base_type == HLSL_TYPE_BOOL); ++ assert(cond->data_type->e.numeric.type == HLSL_TYPE_BOOL); + + args[0] = cond; + args[1] = first; +@@ -4926,7 +4920,7 @@ static bool add_gather_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) + return false; + +- load_params.format = hlsl_get_vector_type(ctx, object_type->e.resource.format->base_type, 4); ++ load_params.format = hlsl_get_vector_type(ctx, object_type->e.resource.format->e.numeric.type, 4); + load_params.resource = object; + load_params.sampler = params->args[0]; + +@@ -6585,7 +6579,7 @@ type_no_void: + YYABORT; + } + +- $$ = hlsl_type_clone(ctx, hlsl_get_vector_type(ctx, $3->base_type, $5), 0, 0); ++ $$ = hlsl_type_clone(ctx, hlsl_get_vector_type(ctx, $3->e.numeric.type, $5), 0, 0); + $$->is_minimum_precision = $3->is_minimum_precision; + } + | KW_VECTOR +@@ -6618,7 +6612,7 @@ type_no_void: + YYABORT; + } + +- $$ = hlsl_type_clone(ctx, hlsl_get_matrix_type(ctx, $3->base_type, $7, $5), 0, 0); ++ $$ = hlsl_type_clone(ctx, hlsl_get_matrix_type(ctx, $3->e.numeric.type, $7, $5), 0, 0); + $$->is_minimum_precision = $3->is_minimum_precision; + } + | KW_MATRIX +@@ -6918,6 +6912,7 @@ state_block: + | state_block stateblock_lhs_identifier state_block_index_opt '=' complex_initializer ';' + { + struct hlsl_state_block_entry *entry; ++ unsigned int i; + + if (!(entry = hlsl_alloc(ctx, sizeof(*entry)))) + YYABORT; +@@ -6927,8 +6922,13 @@ state_block: + entry->lhs_index = $3.index; + + entry->instrs = $5.instrs; +- entry->args = $5.args; ++ + entry->args_count = $5.args_count; ++ if (!(entry->args = hlsl_alloc(ctx, sizeof(*entry->args) * entry->args_count))) ++ YYABORT; ++ for (i = 0; i < entry->args_count; ++i) ++ hlsl_src_from_node(&entry->args[i], $5.args[i]); ++ vkd3d_free($5.args); + + $$ = $1; + state_block_add_entry($$, entry); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index 94acb70fff9..8882deaf6cd 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -263,8 +263,8 @@ static bool types_are_semantic_equivalent(struct hlsl_ctx *ctx, const struct hls + if (type1->dimx != type2->dimx) + return false; + +- return base_type_get_semantic_equivalent(type1->base_type) +- == base_type_get_semantic_equivalent(type2->base_type); ++ return base_type_get_semantic_equivalent(type1->e.numeric.type) ++ == base_type_get_semantic_equivalent(type2->e.numeric.type); + } + + static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, +@@ -355,10 +355,10 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, s + if (!semantic->name) + return; + +- vector_type_dst = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type)); ++ vector_type_dst = hlsl_get_vector_type(ctx, type->e.numeric.type, hlsl_type_minor_size(type)); + vector_type_src = vector_type_dst; + if (ctx->profile->major_version < 4 && ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX) +- vector_type_src = hlsl_get_vector_type(ctx, type->base_type, 4); ++ vector_type_src = hlsl_get_vector_type(ctx, type->e.numeric.type, 4); + + for (i = 0; i < hlsl_type_major_size(type); ++i) + { +@@ -500,7 +500,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, s + if (!semantic->name) + return; + +- vector_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type)); ++ vector_type = hlsl_get_vector_type(ctx, type->e.numeric.type, hlsl_type_minor_size(type)); + + for (i = 0; i < hlsl_type_major_size(type); ++i) + { +@@ -1101,7 +1101,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + struct hlsl_ir_node *resource_load; + + assert(coords->data_type->class == HLSL_CLASS_VECTOR); +- assert(coords->data_type->base_type == HLSL_TYPE_UINT); ++ assert(coords->data_type->e.numeric.type == HLSL_TYPE_UINT); + assert(coords->data_type->dimx == dim_count); + + if (!(coords = add_zero_mipmap_level(ctx, coords, &instr->loc))) +@@ -1191,7 +1191,7 @@ static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, s + { + struct hlsl_ir_node *new_cast, *swizzle; + +- dst_scalar_type = hlsl_get_scalar_type(ctx, dst_type->base_type); ++ dst_scalar_type = hlsl_get_scalar_type(ctx, dst_type->e.numeric.type); + /* We need to preserve the cast since it might be doing more than just + * turning the scalar into a vector. */ + if (!(new_cast = hlsl_new_cast(ctx, cast->operands[0].node, dst_scalar_type, &cast->node.loc))) +@@ -1625,10 +1625,11 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, + { + case HLSL_CLASS_SCALAR: + case HLSL_CLASS_VECTOR: ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_TEXTURE: + case HLSL_CLASS_UAV: +- case HLSL_CLASS_OBJECT: ++ case HLSL_CLASS_VERTEX_SHADER: + break; + + case HLSL_CLASS_MATRIX: +@@ -2064,7 +2065,7 @@ static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst + src_type = expr->operands[0].node->data_type; + + if (hlsl_types_are_equal(src_type, dst_type) +- || (src_type->base_type == dst_type->base_type && is_vec1(src_type) && is_vec1(dst_type))) ++ || (src_type->e.numeric.type == dst_type->e.numeric.type && is_vec1(src_type) && is_vec1(dst_type))) + { + hlsl_replace_node(&expr->node, expr->operands[0].node); + return true; +@@ -2191,7 +2192,7 @@ static bool split_matrix_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + type = rhs->data_type; + if (type->class != HLSL_CLASS_MATRIX) + return false; +- element_type = hlsl_get_vector_type(ctx, type->base_type, hlsl_type_minor_size(type)); ++ element_type = hlsl_get_vector_type(ctx, type->e.numeric.type, hlsl_type_minor_size(type)); + + if (rhs->type != HLSL_IR_LOAD) + { +@@ -2228,7 +2229,7 @@ static bool lower_narrowing_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins + { + struct hlsl_ir_node *new_cast, *swizzle; + +- dst_vector_type = hlsl_get_vector_type(ctx, dst_type->base_type, src_type->dimx); ++ dst_vector_type = hlsl_get_vector_type(ctx, dst_type->e.numeric.type, src_type->dimx); + /* We need to preserve the cast since it might be doing more than just + * narrowing the vector. */ + if (!(new_cast = hlsl_new_cast(ctx, cast->operands[0].node, dst_vector_type, &cast->node.loc))) +@@ -2482,7 +2483,7 @@ static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir + + op = HLSL_OP2_DOT; + if (type->dimx == 1) +- op = type->base_type == HLSL_TYPE_BOOL ? HLSL_OP2_LOGIC_AND : HLSL_OP2_MUL; ++ op = type->e.numeric.type == HLSL_TYPE_BOOL ? HLSL_OP2_LOGIC_AND : HLSL_OP2_MUL; + + /* Note: We may be creating a DOT for bool vectors here, which we need to lower to + * LOGIC_OR + LOGIC_AND. */ +@@ -2676,9 +2677,9 @@ static bool lower_casts_to_int(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + return false; + + arg = expr->operands[0].node; +- if (instr->data_type->base_type != HLSL_TYPE_INT && instr->data_type->base_type != HLSL_TYPE_UINT) ++ if (instr->data_type->e.numeric.type != HLSL_TYPE_INT && instr->data_type->e.numeric.type != HLSL_TYPE_UINT) + return false; +- if (arg->data_type->base_type != HLSL_TYPE_FLOAT && arg->data_type->base_type != HLSL_TYPE_HALF) ++ if (arg->data_type->e.numeric.type != HLSL_TYPE_FLOAT && arg->data_type->e.numeric.type != HLSL_TYPE_HALF) + return false; + + if (!(floor = hlsl_new_unary_expr(ctx, HLSL_OP1_FLOOR, arg, &instr->loc))) +@@ -2935,7 +2936,7 @@ static bool lower_logic_not(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, st + float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, arg->data_type->dimx); + + /* If this is happens, it means we failed to cast the argument to boolean somewhere. */ +- assert(arg->data_type->base_type == HLSL_TYPE_BOOL); ++ assert(arg->data_type->e.numeric.type == HLSL_TYPE_BOOL); + + if (!(arg_cast = hlsl_new_cast(ctx, arg, float_type, &arg->loc))) + return false; +@@ -2991,7 +2992,7 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru + return false; + } + +- assert(cond->data_type->base_type == HLSL_TYPE_BOOL); ++ assert(cond->data_type->e.numeric.type == HLSL_TYPE_BOOL); + + type = hlsl_get_numeric_type(ctx, instr->data_type->class, HLSL_TYPE_FLOAT, + instr->data_type->dimx, instr->data_type->dimy); +@@ -3285,7 +3286,7 @@ static bool lower_casts_to_bool(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + arg_type = expr->operands[0].node->data_type; + if (type->class > HLSL_CLASS_VECTOR || arg_type->class > HLSL_CLASS_VECTOR) + return false; +- if (type->base_type != HLSL_TYPE_BOOL) ++ if (type->e.numeric.type != HLSL_TYPE_BOOL) + return false; + + /* Narrowing casts should have already been lowered. */ +@@ -3313,7 +3314,7 @@ struct hlsl_ir_node *hlsl_add_conditional(struct hlsl_ctx *ctx, struct hlsl_bloc + + assert(hlsl_types_are_equal(if_true->data_type, if_false->data_type)); + +- if (cond_type->base_type != HLSL_TYPE_BOOL) ++ if (cond_type->e.numeric.type != HLSL_TYPE_BOOL) + { + cond_type = hlsl_get_numeric_type(ctx, cond_type->class, HLSL_TYPE_BOOL, cond_type->dimx, cond_type->dimy); + +@@ -3349,7 +3350,7 @@ static bool lower_int_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + return false; + if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR) + return false; +- if (type->base_type != HLSL_TYPE_INT) ++ if (type->e.numeric.type != HLSL_TYPE_INT) + return false; + utype = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_UINT, type->dimx, type->dimy); + +@@ -3415,7 +3416,7 @@ static bool lower_int_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + return false; + if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR) + return false; +- if (type->base_type != HLSL_TYPE_INT) ++ if (type->e.numeric.type != HLSL_TYPE_INT) + return false; + utype = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_UINT, type->dimx, type->dimy); + +@@ -3474,7 +3475,7 @@ static bool lower_int_abs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru + return false; + if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR) + return false; +- if (type->base_type != HLSL_TYPE_INT) ++ if (type->e.numeric.type != HLSL_TYPE_INT) + return false; + + arg = expr->operands[0].node; +@@ -3505,14 +3506,14 @@ static bool lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru + if (expr->op != HLSL_OP2_DOT) + return false; + +- if (type->base_type == HLSL_TYPE_INT || type->base_type == HLSL_TYPE_UINT +- || type->base_type == HLSL_TYPE_BOOL) ++ if (type->e.numeric.type == HLSL_TYPE_INT || type->e.numeric.type == HLSL_TYPE_UINT ++ || type->e.numeric.type == HLSL_TYPE_BOOL) + { + arg1 = expr->operands[0].node; + arg2 = expr->operands[1].node; + assert(arg1->data_type->dimx == arg2->data_type->dimx); + dimx = arg1->data_type->dimx; +- is_bool = type->base_type == HLSL_TYPE_BOOL; ++ is_bool = type->e.numeric.type == HLSL_TYPE_BOOL; + + if (!(mult = hlsl_new_binary_expr(ctx, is_bool ? HLSL_OP2_LOGIC_AND : HLSL_OP2_MUL, arg1, arg2))) + return false; +@@ -3558,7 +3559,7 @@ static bool lower_float_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + return false; + if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR) + return false; +- if (type->base_type != HLSL_TYPE_FLOAT) ++ if (type->e.numeric.type != HLSL_TYPE_FLOAT) + return false; + btype = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_BOOL, type->dimx, type->dimy); + +@@ -3614,7 +3615,7 @@ static bool lower_nonfloat_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst + if (instr->type != HLSL_IR_EXPR) + return false; + expr = hlsl_ir_expr(instr); +- if (expr->op == HLSL_OP1_CAST || instr->data_type->base_type == HLSL_TYPE_FLOAT) ++ if (expr->op == HLSL_OP1_CAST || instr->data_type->e.numeric.type == HLSL_TYPE_FLOAT) + return false; + + switch (expr->op) +@@ -4453,7 +4454,7 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, + continue; + value = &constant->value.u[i++]; + +- switch (type->base_type) ++ switch (type->e.numeric.type) + { + case HLSL_TYPE_BOOL: + f = !!value->u; +@@ -5046,7 +5047,7 @@ bool hlsl_component_index_range_from_deref(struct hlsl_ctx *ctx, const struct hl + + /* We should always have generated a cast to UINT. */ + assert(path_node->data_type->class == HLSL_CLASS_SCALAR +- && path_node->data_type->base_type == HLSL_TYPE_UINT); ++ && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT); + + idx = hlsl_ir_constant(path_node)->value.u[0].u; + +@@ -5122,7 +5123,7 @@ bool hlsl_regset_index_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref + + /* We should always have generated a cast to UINT. */ + assert(path_node->data_type->class == HLSL_CLASS_SCALAR +- && path_node->data_type->base_type == HLSL_TYPE_UINT); ++ && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT); + + idx = hlsl_ir_constant(path_node)->value.u[0].u; + +@@ -5162,7 +5163,7 @@ bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref + { + /* We should always have generated a cast to UINT. */ + assert(offset_node->data_type->class == HLSL_CLASS_SCALAR +- && offset_node->data_type->base_type == HLSL_TYPE_UINT); ++ && offset_node->data_type->e.numeric.type == HLSL_TYPE_UINT); + assert(offset_node->type != HLSL_IR_CONSTANT); + return false; + } +@@ -5229,7 +5230,7 @@ static void parse_numthreads_attribute(struct hlsl_ctx *ctx, const struct hlsl_a + const struct hlsl_ir_constant *constant; + + if (type->class != HLSL_CLASS_SCALAR +- || (type->base_type != HLSL_TYPE_INT && type->base_type != HLSL_TYPE_UINT)) ++ || (type->e.numeric.type != HLSL_TYPE_INT && type->e.numeric.type != HLSL_TYPE_UINT)) + { + struct vkd3d_string_buffer *string; + +@@ -5248,8 +5249,8 @@ static void parse_numthreads_attribute(struct hlsl_ctx *ctx, const struct hlsl_a + } + constant = hlsl_ir_constant(instr); + +- if ((type->base_type == HLSL_TYPE_INT && constant->value.u[0].i <= 0) +- || (type->base_type == HLSL_TYPE_UINT && !constant->value.u[0].u)) ++ if ((type->e.numeric.type == HLSL_TYPE_INT && constant->value.u[0].i <= 0) ++ || (type->e.numeric.type == HLSL_TYPE_UINT && !constant->value.u[0].u)) + hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_THREAD_COUNT, + "Thread count must be a positive integer."); + +@@ -5313,17 +5314,6 @@ static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *bod + } + } + +-void hlsl_prepend_global_uniform_copy(struct hlsl_ctx *ctx, struct hlsl_block *body) +-{ +- struct hlsl_ir_var *var; +- +- LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) +- { +- if (var->storage_modifiers & HLSL_STORAGE_UNIFORM) +- prepend_uniform_copy(ctx, body, var); +- } +-} +- + int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, + enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out) + { +@@ -5352,7 +5342,11 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry + lower_ir(ctx, lower_matrix_swizzles, body); + lower_ir(ctx, lower_index_loads, body); + +- hlsl_prepend_global_uniform_copy(ctx, body); ++ LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) ++ { ++ if (var->storage_modifiers & HLSL_STORAGE_UNIFORM) ++ prepend_uniform_copy(ctx, body, var); ++ } + + for (i = 0; i < entry_func->parameters.count; ++i) + { +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c +index 51f2f9cc050..16015fa8a81 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c +@@ -25,10 +25,10 @@ + static bool fold_abs(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -116,10 +116,10 @@ static int32_t double_to_int(double x) + static bool fold_bit_not(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -158,7 +158,7 @@ static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + + for (k = 0; k < dst_type->dimx; ++k) + { +- switch (src->node.data_type->base_type) ++ switch (src->node.data_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: +@@ -200,7 +200,7 @@ static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + vkd3d_unreachable(); + } + +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: +@@ -231,10 +231,10 @@ static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + static bool fold_ceil(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -257,10 +257,10 @@ static bool fold_ceil(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + static bool fold_exp2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -283,10 +283,10 @@ static bool fold_exp2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + static bool fold_floor(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -309,11 +309,11 @@ static bool fold_floor(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + static bool fold_fract(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + float i; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -336,10 +336,10 @@ static bool fold_fract(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + static bool fold_log2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -381,10 +381,10 @@ static bool fold_log2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, con + static bool fold_neg(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -415,10 +415,10 @@ static bool fold_neg(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + static bool fold_not(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + const struct hlsl_type *dst_type, const struct hlsl_ir_constant *src) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -439,10 +439,10 @@ static bool fold_not(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + static bool fold_rcp(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -484,10 +484,10 @@ static bool fold_rcp(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons + static bool fold_rsq(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -524,10 +524,10 @@ static bool fold_rsq(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons + static bool fold_sat(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -550,10 +550,10 @@ static bool fold_sat(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons + static bool fold_sqrt(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src, const struct vkd3d_shader_location *loc) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src->node.data_type->base_type); ++ assert(type == src->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -595,11 +595,11 @@ static bool fold_sqrt(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, con + static bool fold_add(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src1->node.data_type->base_type); +- assert(type == src2->node.data_type->base_type); ++ assert(type == src1->node.data_type->e.numeric.type); ++ assert(type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -632,11 +632,11 @@ static bool fold_add(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons + static bool fold_and(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src1->node.data_type->base_type); +- assert(type == src2->node.data_type->base_type); ++ assert(type == src1->node.data_type->e.numeric.type); ++ assert(type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -659,11 +659,11 @@ static bool fold_and(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons + static bool fold_or(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src1->node.data_type->base_type); +- assert(type == src2->node.data_type->base_type); ++ assert(type == src1->node.data_type->e.numeric.type); ++ assert(type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -686,11 +686,11 @@ static bool fold_or(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const + static bool fold_bit_xor(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src1->node.data_type->base_type); +- assert(type == src2->node.data_type->base_type); ++ assert(type == src1->node.data_type->e.numeric.type); ++ assert(type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -712,11 +712,11 @@ static bool fold_bit_xor(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + static bool fold_dot(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src1->node.data_type->base_type); +- assert(type == src2->node.data_type->base_type); ++ assert(type == src1->node.data_type->e.numeric.type); ++ assert(type == src2->node.data_type->e.numeric.type); + assert(src1->node.data_type->dimx == src2->node.data_type->dimx); + + dst->u[0].f = 0.0f; +@@ -740,12 +740,12 @@ static bool fold_dot(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons + static bool fold_dp2add(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2, const struct hlsl_ir_constant *src3) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src1->node.data_type->base_type); +- assert(type == src2->node.data_type->base_type); +- assert(type == src3->node.data_type->base_type); ++ assert(type == src1->node.data_type->e.numeric.type); ++ assert(type == src2->node.data_type->e.numeric.type); ++ assert(type == src3->node.data_type->e.numeric.type); + assert(src1->node.data_type->dimx == src2->node.data_type->dimx); + assert(src3->node.data_type->dimx == 1); + +@@ -771,11 +771,11 @@ static bool fold_div(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons + const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2, + const struct vkd3d_shader_location *loc) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src1->node.data_type->base_type); +- assert(type == src2->node.data_type->base_type); ++ assert(type == src1->node.data_type->e.numeric.type); ++ assert(type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -841,12 +841,12 @@ static bool fold_equal(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, co + { + unsigned int k; + +- assert(dst_type->base_type == HLSL_TYPE_BOOL); +- assert(src1->node.data_type->base_type == src2->node.data_type->base_type); ++ assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL); ++ assert(src1->node.data_type->e.numeric.type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +- switch (src1->node.data_type->base_type) ++ switch (src1->node.data_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: +@@ -877,12 +877,12 @@ static bool fold_gequal(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c + { + unsigned int k; + +- assert(dst_type->base_type == HLSL_TYPE_BOOL); +- assert(src1->node.data_type->base_type == src2->node.data_type->base_type); ++ assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL); ++ assert(src1->node.data_type->e.numeric.type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +- switch (src1->node.data_type->base_type) ++ switch (src1->node.data_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: +@@ -916,12 +916,12 @@ static bool fold_less(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, con + { + unsigned int k; + +- assert(dst_type->base_type == HLSL_TYPE_BOOL); +- assert(src1->node.data_type->base_type == src2->node.data_type->base_type); ++ assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL); ++ assert(src1->node.data_type->e.numeric.type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +- switch (src1->node.data_type->base_type) ++ switch (src1->node.data_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: +@@ -955,14 +955,14 @@ static bool fold_lshift(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c + { + unsigned int k; + +- assert(dst_type->base_type == src1->node.data_type->base_type); +- assert(src2->node.data_type->base_type == HLSL_TYPE_INT); ++ assert(dst_type->e.numeric.type == src1->node.data_type->e.numeric.type); ++ assert(src2->node.data_type->e.numeric.type == HLSL_TYPE_INT); + + for (k = 0; k < dst_type->dimx; ++k) + { + unsigned int shift = src2->value.u[k].u % 32; + +- switch (src1->node.data_type->base_type) ++ switch (src1->node.data_type->e.numeric.type) + { + case HLSL_TYPE_INT: + dst->u[k].i = src1->value.u[k].i << shift; +@@ -983,11 +983,11 @@ static bool fold_lshift(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c + static bool fold_max(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src1->node.data_type->base_type); +- assert(type == src2->node.data_type->base_type); ++ assert(type == src1->node.data_type->e.numeric.type); ++ assert(type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -1021,11 +1021,11 @@ static bool fold_max(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons + static bool fold_min(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src1->node.data_type->base_type); +- assert(type == src2->node.data_type->base_type); ++ assert(type == src1->node.data_type->e.numeric.type); ++ assert(type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -1060,11 +1060,11 @@ static bool fold_mod(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons + const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2, + const struct vkd3d_shader_location *loc) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src1->node.data_type->base_type); +- assert(type == src2->node.data_type->base_type); ++ assert(type == src1->node.data_type->e.numeric.type); ++ assert(type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -1102,11 +1102,11 @@ static bool fold_mod(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, cons + static bool fold_mul(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, const struct hlsl_type *dst_type, + const struct hlsl_ir_constant *src1, const struct hlsl_ir_constant *src2) + { +- enum hlsl_base_type type = dst_type->base_type; ++ enum hlsl_base_type type = dst_type->e.numeric.type; + unsigned int k; + +- assert(type == src1->node.data_type->base_type); +- assert(type == src2->node.data_type->base_type); ++ assert(type == src1->node.data_type->e.numeric.type); ++ assert(type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +@@ -1139,12 +1139,12 @@ static bool fold_nequal(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c + { + unsigned int k; + +- assert(dst_type->base_type == HLSL_TYPE_BOOL); +- assert(src1->node.data_type->base_type == src2->node.data_type->base_type); ++ assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL); ++ assert(src1->node.data_type->e.numeric.type == src2->node.data_type->e.numeric.type); + + for (k = 0; k < dst_type->dimx; ++k) + { +- switch (src1->node.data_type->base_type) ++ switch (src1->node.data_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: +@@ -1175,9 +1175,9 @@ static bool fold_ternary(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, + { + unsigned int k; + +- assert(dst_type->base_type == src2->node.data_type->base_type); +- assert(dst_type->base_type == src3->node.data_type->base_type); +- assert(src1->node.data_type->base_type == HLSL_TYPE_BOOL); ++ assert(dst_type->e.numeric.type == src2->node.data_type->e.numeric.type); ++ assert(dst_type->e.numeric.type == src3->node.data_type->e.numeric.type); ++ assert(src1->node.data_type->e.numeric.type == HLSL_TYPE_BOOL); + + for (k = 0; k < dst_type->dimx; ++k) + dst->u[k] = src1->value.u[k].u ? src2->value.u[k] : src3->value.u[k]; +@@ -1190,14 +1190,14 @@ static bool fold_rshift(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst, c + { + unsigned int k; + +- assert(dst_type->base_type == src1->node.data_type->base_type); +- assert(src2->node.data_type->base_type == HLSL_TYPE_INT); ++ assert(dst_type->e.numeric.type == src1->node.data_type->e.numeric.type); ++ assert(src2->node.data_type->e.numeric.type == HLSL_TYPE_INT); + + for (k = 0; k < dst_type->dimx; ++k) + { + unsigned int shift = src2->value.u[k].u % 32; + +- switch (src1->node.data_type->base_type) ++ switch (src1->node.data_type->e.numeric.type) + { + case HLSL_TYPE_INT: + dst->u[k].i = src1->value.u[k].i >> shift; +@@ -1403,7 +1403,7 @@ static bool constant_is_zero(struct hlsl_ir_constant *const_arg) + + for (k = 0; k < data_type->dimx; ++k) + { +- switch (data_type->base_type) ++ switch (data_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: +@@ -1437,7 +1437,7 @@ static bool constant_is_one(struct hlsl_ir_constant *const_arg) + + for (k = 0; k < data_type->dimx; ++k) + { +- switch (data_type->base_type) ++ switch (data_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 121b0fe3a6c..c6ecbdd9e46 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -5753,6 +5753,32 @@ static void vsir_validate_instruction(struct validation_context *ctx) + case VKD3DSIH_DCL_OUTPUT: + return; + ++ case VKD3DSIH_DCL_INPUT_PRIMITIVE: ++ if (instruction->declaration.primitive_type.type == VKD3D_PT_UNDEFINED ++ || instruction->declaration.primitive_type.type >= VKD3D_PT_COUNT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS input primitive %u is invalid.", ++ instruction->declaration.primitive_type.type); ++ return; ++ ++ case VKD3DSIH_DCL_VERTICES_OUT: ++ if (instruction->declaration.count > 1024) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS output vertex count %u is invalid.", ++ instruction->declaration.count); ++ return; ++ ++ case VKD3DSIH_DCL_OUTPUT_TOPOLOGY: ++ if (instruction->declaration.primitive_type.type == VKD3D_PT_UNDEFINED ++ || instruction->declaration.primitive_type.type >= VKD3D_PT_COUNT) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS output primitive %u is invalid.", ++ instruction->declaration.primitive_type.type); ++ return; ++ ++ case VKD3DSIH_DCL_GS_INSTANCES: ++ if (!instruction->declaration.count || instruction->declaration.count > 32) ++ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS instance count %u is invalid.", ++ instruction->declaration.count); ++ return; ++ + case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT: + if (!instruction->declaration.count || instruction->declaration.count > 32) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, "Output control point count %u is invalid.", +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index dc9e8c06a5e..813e20fdcd7 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -1752,6 +1752,14 @@ static uint32_t vkd3d_spirv_get_op_scope_subgroup(struct vkd3d_spirv_builder *bu + return vkd3d_spirv_build_once(builder, &builder->scope_subgroup_id, vkd3d_spirv_build_op_scope_subgroup); + } + ++static uint32_t vkd3d_spirv_build_op_group_nonuniform_ballot(struct vkd3d_spirv_builder *builder, ++ uint32_t result_type, uint32_t val_id) ++{ ++ vkd3d_spirv_enable_capability(builder, SpvCapabilityGroupNonUniformBallot); ++ return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpGroupNonUniformBallot, ++ result_type, vkd3d_spirv_get_op_scope_subgroup(builder), val_id); ++} ++ + static uint32_t vkd3d_spirv_build_op_glsl_std450_tr1(struct vkd3d_spirv_builder *builder, + enum GLSLstd450 op, uint32_t result_type, uint32_t operand) + { +@@ -9793,6 +9801,76 @@ static void spirv_compiler_emit_wave_bool_op(struct spirv_compiler *compiler, + spirv_compiler_emit_store_dst(compiler, dst, val_id); + } + ++static void spirv_compiler_emit_wave_active_ballot(struct spirv_compiler *compiler, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ const struct vkd3d_shader_dst_param *dst = instruction->dst; ++ const struct vkd3d_shader_src_param *src = instruction->src; ++ uint32_t type_id, val_id; ++ ++ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, VKD3D_VEC4_SIZE); ++ val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); ++ val_id = vkd3d_spirv_build_op_group_nonuniform_ballot(builder, type_id, val_id); ++ ++ spirv_compiler_emit_store_dst(compiler, dst, val_id); ++} ++ ++static SpvOp map_wave_alu_op(enum vkd3d_shader_opcode handler_idx, bool is_float) ++{ ++ switch (handler_idx) ++ { ++ case VKD3DSIH_WAVE_ACTIVE_BIT_AND: ++ return SpvOpGroupNonUniformBitwiseAnd; ++ case VKD3DSIH_WAVE_ACTIVE_BIT_OR: ++ return SpvOpGroupNonUniformBitwiseOr; ++ case VKD3DSIH_WAVE_ACTIVE_BIT_XOR: ++ return SpvOpGroupNonUniformBitwiseXor; ++ case VKD3DSIH_WAVE_OP_ADD: ++ return is_float ? SpvOpGroupNonUniformFAdd : SpvOpGroupNonUniformIAdd; ++ case VKD3DSIH_WAVE_OP_IMAX: ++ return SpvOpGroupNonUniformSMax; ++ case VKD3DSIH_WAVE_OP_IMIN: ++ return SpvOpGroupNonUniformSMin; ++ case VKD3DSIH_WAVE_OP_MAX: ++ return SpvOpGroupNonUniformFMax; ++ case VKD3DSIH_WAVE_OP_MIN: ++ return SpvOpGroupNonUniformFMin; ++ case VKD3DSIH_WAVE_OP_MUL: ++ return is_float ? SpvOpGroupNonUniformFMul : SpvOpGroupNonUniformIMul; ++ case VKD3DSIH_WAVE_OP_UMAX: ++ return SpvOpGroupNonUniformUMax; ++ case VKD3DSIH_WAVE_OP_UMIN: ++ return SpvOpGroupNonUniformUMin; ++ default: ++ vkd3d_unreachable(); ++ } ++} ++ ++static void spirv_compiler_emit_wave_alu_op(struct spirv_compiler *compiler, ++ const struct vkd3d_shader_instruction *instruction) ++{ ++ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; ++ const struct vkd3d_shader_dst_param *dst = instruction->dst; ++ const struct vkd3d_shader_src_param *src = instruction->src; ++ uint32_t type_id, val_id; ++ SpvOp op; ++ ++ op = map_wave_alu_op(instruction->handler_idx, data_type_is_floating_point(src->reg.data_type)); ++ ++ type_id = vkd3d_spirv_get_type_id_for_data_type(builder, dst->reg.data_type, ++ vsir_write_mask_component_count(dst->write_mask)); ++ val_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); ++ ++ vkd3d_spirv_enable_capability(builder, SpvCapabilityGroupNonUniformArithmetic); ++ val_id = vkd3d_spirv_build_op_tr3(builder, &builder->function_stream, op, type_id, ++ vkd3d_spirv_get_op_scope_subgroup(builder), ++ (instruction->flags & VKD3DSI_WAVE_PREFIX) ? SpvGroupOperationExclusiveScan : SpvGroupOperationReduce, ++ val_id); ++ ++ spirv_compiler_emit_store_dst(compiler, dst, val_id); ++} ++ + /* This function is called after declarations are processed. */ + static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler) + { +@@ -10142,6 +10220,22 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, + case VKD3DSIH_WAVE_ANY_TRUE: + spirv_compiler_emit_wave_bool_op(compiler, instruction); + break; ++ case VKD3DSIH_WAVE_ACTIVE_BALLOT: ++ spirv_compiler_emit_wave_active_ballot(compiler, instruction); ++ break; ++ case VKD3DSIH_WAVE_ACTIVE_BIT_AND: ++ case VKD3DSIH_WAVE_ACTIVE_BIT_OR: ++ case VKD3DSIH_WAVE_ACTIVE_BIT_XOR: ++ case VKD3DSIH_WAVE_OP_ADD: ++ case VKD3DSIH_WAVE_OP_IMAX: ++ case VKD3DSIH_WAVE_OP_IMIN: ++ case VKD3DSIH_WAVE_OP_MAX: ++ case VKD3DSIH_WAVE_OP_MIN: ++ case VKD3DSIH_WAVE_OP_MUL: ++ case VKD3DSIH_WAVE_OP_UMAX: ++ case VKD3DSIH_WAVE_OP_UMIN: ++ spirv_compiler_emit_wave_alu_op(compiler, instruction); ++ break; + case VKD3DSIH_DCL: + case VKD3DSIH_DCL_HS_MAX_TESSFACTOR: + case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT: +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index 708ab6268a7..4e3bef9640c 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c ++++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c +@@ -2744,7 +2744,7 @@ static void write_sm4_block(const struct tpf_writer *tpf, const struct hlsl_bloc + + static bool type_is_integer(const struct hlsl_type *type) + { +- switch (type->base_type) ++ switch (type->e.numeric.type) + { + case HLSL_TYPE_BOOL: + case HLSL_TYPE_INT: +@@ -2933,7 +2933,7 @@ static void write_sm4_signature(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc, + put_u32(&buffer, 0); /* name */ + put_u32(&buffer, usage_idx); + put_u32(&buffer, usage); +- switch (var->data_type->base_type) ++ switch (var->data_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_HALF: +@@ -3009,14 +3009,15 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type) + case HLSL_CLASS_DEPTH_STENCIL_VIEW: + case HLSL_CLASS_EFFECT_GROUP: + case HLSL_CLASS_STRUCT: +- case HLSL_CLASS_OBJECT: + case HLSL_CLASS_PASS: ++ case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_RENDER_TARGET_VIEW: + case HLSL_CLASS_SAMPLER: + case HLSL_CLASS_STRING: + case HLSL_CLASS_TECHNIQUE: + case HLSL_CLASS_TEXTURE: + case HLSL_CLASS_UAV: ++ case HLSL_CLASS_VERTEX_SHADER: + case HLSL_CLASS_VOID: + break; + } +@@ -3025,7 +3026,7 @@ static D3D_SHADER_VARIABLE_CLASS sm4_class(const struct hlsl_type *type) + + static D3D_SHADER_VARIABLE_TYPE sm4_base_type(const struct hlsl_type *type) + { +- switch (type->base_type) ++ switch (type->e.numeric.type) + { + case HLSL_TYPE_BOOL: + return D3D_SVT_BOOL; +@@ -3089,7 +3090,7 @@ static void write_sm4_type(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b + + put_u32(buffer, field->name_bytecode_offset); + put_u32(buffer, field->type->bytecode_offset); +- put_u32(buffer, field->reg_offset[HLSL_REGSET_NUMERIC]); ++ put_u32(buffer, field->reg_offset[HLSL_REGSET_NUMERIC] * sizeof(float)); + } + type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(D3D_SVC_STRUCT, D3D_SVT_VOID)); + put_u32(buffer, vkd3d_make_u32(1, hlsl_type_component_count(array_type))); +@@ -3139,7 +3140,7 @@ static D3D_RESOURCE_RETURN_TYPE sm4_resource_format(const struct hlsl_type *type + if (type->class == HLSL_CLASS_ARRAY) + return sm4_resource_format(type->e.array.type); + +- switch (type->e.resource.format->base_type) ++ switch (type->e.resource.format->e.numeric.type) + { + case HLSL_TYPE_DOUBLE: + return D3D_RETURN_TYPE_DOUBLE; +@@ -4727,11 +4728,11 @@ static void write_sm4_sampleinfo(const struct tpf_writer *tpf, const struct hlsl + const struct hlsl_ir_node *dst = &load->node; + struct sm4_instruction instr; + +- assert(dst->data_type->base_type == HLSL_TYPE_UINT || dst->data_type->base_type == HLSL_TYPE_FLOAT); ++ assert(dst->data_type->e.numeric.type == HLSL_TYPE_UINT || dst->data_type->e.numeric.type == HLSL_TYPE_FLOAT); + + memset(&instr, 0, sizeof(instr)); + instr.opcode = VKD3D_SM4_OP_SAMPLE_INFO; +- if (dst->data_type->base_type == HLSL_TYPE_UINT) ++ if (dst->data_type->e.numeric.type == HLSL_TYPE_UINT) + instr.extra_bits |= VKD3DSI_SAMPLE_INFO_UINT << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT; + + sm4_dst_from_node(&instr.dsts[0], dst); +@@ -4756,11 +4757,11 @@ static void write_sm4_resinfo(const struct tpf_writer *tpf, const struct hlsl_ir + return; + } + +- assert(dst->data_type->base_type == HLSL_TYPE_UINT || dst->data_type->base_type == HLSL_TYPE_FLOAT); ++ assert(dst->data_type->e.numeric.type == HLSL_TYPE_UINT || dst->data_type->e.numeric.type == HLSL_TYPE_FLOAT); + + memset(&instr, 0, sizeof(instr)); + instr.opcode = VKD3D_SM4_OP_RESINFO; +- if (dst->data_type->base_type == HLSL_TYPE_UINT) ++ if (dst->data_type->e.numeric.type == HLSL_TYPE_UINT) + instr.extra_bits |= VKD3DSI_RESINFO_UINT << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT; + + sm4_dst_from_node(&instr.dsts[0], dst); +@@ -4775,7 +4776,7 @@ static void write_sm4_resinfo(const struct tpf_writer *tpf, const struct hlsl_ir + + static bool type_is_float(const struct hlsl_type *type) + { +- return type->base_type == HLSL_TYPE_FLOAT || type->base_type == HLSL_TYPE_HALF; ++ return type->e.numeric.type == HLSL_TYPE_FLOAT || type->e.numeric.type == HLSL_TYPE_HALF; + } + + static void write_sm4_cast_from_bool(const struct tpf_writer *tpf, const struct hlsl_ir_expr *expr, +@@ -4812,11 +4813,11 @@ static void write_sm4_cast(const struct tpf_writer *tpf, const struct hlsl_ir_ex + /* Narrowing casts were already lowered. */ + assert(src_type->dimx == dst_type->dimx); + +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_HALF: + case HLSL_TYPE_FLOAT: +- switch (src_type->base_type) ++ switch (src_type->e.numeric.type) + { + case HLSL_TYPE_HALF: + case HLSL_TYPE_FLOAT: +@@ -4845,7 +4846,7 @@ static void write_sm4_cast(const struct tpf_writer *tpf, const struct hlsl_ir_ex + break; + + case HLSL_TYPE_INT: +- switch (src_type->base_type) ++ switch (src_type->e.numeric.type) + { + case HLSL_TYPE_HALF: + case HLSL_TYPE_FLOAT: +@@ -4871,7 +4872,7 @@ static void write_sm4_cast(const struct tpf_writer *tpf, const struct hlsl_ir_ex + break; + + case HLSL_TYPE_UINT: +- switch (src_type->base_type) ++ switch (src_type->e.numeric.type) + { + case HLSL_TYPE_HALF: + case HLSL_TYPE_FLOAT: +@@ -4941,7 +4942,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + switch (expr->op) + { + case HLSL_OP1_ABS: +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + write_sm4_unary_op(tpf, VKD3D_SM4_OP_MOV, &expr->node, arg1, VKD3DSPSM_ABS); +@@ -5022,12 +5023,12 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + break; + + case HLSL_OP1_LOGIC_NOT: +- assert(dst_type->base_type == HLSL_TYPE_BOOL); ++ assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL); + write_sm4_unary_op(tpf, VKD3D_SM4_OP_NOT, &expr->node, arg1, 0); + break; + + case HLSL_OP1_NEG: +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + write_sm4_unary_op(tpf, VKD3D_SM4_OP_MOV, &expr->node, arg1, VKD3DSPSM_NEG); +@@ -5080,7 +5081,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + break; + + case HLSL_OP2_ADD: +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + write_sm4_binary_op(tpf, VKD3D_SM4_OP_ADD, &expr->node, arg1, arg2); +@@ -5112,7 +5113,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + break; + + case HLSL_OP2_DIV: +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + write_sm4_binary_op(tpf, VKD3D_SM4_OP_DIV, &expr->node, arg1, arg2); +@@ -5128,7 +5129,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + break; + + case HLSL_OP2_DOT: +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + switch (arg1->data_type->dimx) +@@ -5160,9 +5161,9 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + { + const struct hlsl_type *src_type = arg1->data_type; + +- assert(dst_type->base_type == HLSL_TYPE_BOOL); ++ assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL); + +- switch (src_type->base_type) ++ switch (src_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + write_sm4_binary_op(tpf, VKD3D_SM4_OP_EQ, &expr->node, arg1, arg2); +@@ -5186,9 +5187,9 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + { + const struct hlsl_type *src_type = arg1->data_type; + +- assert(dst_type->base_type == HLSL_TYPE_BOOL); ++ assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL); + +- switch (src_type->base_type) ++ switch (src_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + write_sm4_binary_op(tpf, VKD3D_SM4_OP_GE, &expr->node, arg1, arg2); +@@ -5215,9 +5216,9 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + { + const struct hlsl_type *src_type = arg1->data_type; + +- assert(dst_type->base_type == HLSL_TYPE_BOOL); ++ assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL); + +- switch (src_type->base_type) ++ switch (src_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + write_sm4_binary_op(tpf, VKD3D_SM4_OP_LT, &expr->node, arg1, arg2); +@@ -5241,23 +5242,23 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + } + + case HLSL_OP2_LOGIC_AND: +- assert(dst_type->base_type == HLSL_TYPE_BOOL); ++ assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL); + write_sm4_binary_op(tpf, VKD3D_SM4_OP_AND, &expr->node, arg1, arg2); + break; + + case HLSL_OP2_LOGIC_OR: +- assert(dst_type->base_type == HLSL_TYPE_BOOL); ++ assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL); + write_sm4_binary_op(tpf, VKD3D_SM4_OP_OR, &expr->node, arg1, arg2); + break; + + case HLSL_OP2_LSHIFT: + assert(type_is_integer(dst_type)); +- assert(dst_type->base_type != HLSL_TYPE_BOOL); ++ assert(dst_type->e.numeric.type != HLSL_TYPE_BOOL); + write_sm4_binary_op(tpf, VKD3D_SM4_OP_ISHL, &expr->node, arg1, arg2); + break; + + case HLSL_OP2_MAX: +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + write_sm4_binary_op(tpf, VKD3D_SM4_OP_MAX, &expr->node, arg1, arg2); +@@ -5277,7 +5278,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + break; + + case HLSL_OP2_MIN: +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + write_sm4_binary_op(tpf, VKD3D_SM4_OP_MIN, &expr->node, arg1, arg2); +@@ -5297,7 +5298,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + break; + + case HLSL_OP2_MOD: +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_UINT: + write_sm4_binary_op_with_two_destinations(tpf, VKD3D_SM4_OP_UDIV, &expr->node, 1, arg1, arg2); +@@ -5309,7 +5310,7 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + break; + + case HLSL_OP2_MUL: +- switch (dst_type->base_type) ++ switch (dst_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + write_sm4_binary_op(tpf, VKD3D_SM4_OP_MUL, &expr->node, arg1, arg2); +@@ -5331,9 +5332,9 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + { + const struct hlsl_type *src_type = arg1->data_type; + +- assert(dst_type->base_type == HLSL_TYPE_BOOL); ++ assert(dst_type->e.numeric.type == HLSL_TYPE_BOOL); + +- switch (src_type->base_type) ++ switch (src_type->e.numeric.type) + { + case HLSL_TYPE_FLOAT: + write_sm4_binary_op(tpf, VKD3D_SM4_OP_NE, &expr->node, arg1, arg2); +@@ -5355,8 +5356,8 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex + + case HLSL_OP2_RSHIFT: + assert(type_is_integer(dst_type)); +- assert(dst_type->base_type != HLSL_TYPE_BOOL); +- write_sm4_binary_op(tpf, dst_type->base_type == HLSL_TYPE_INT ? VKD3D_SM4_OP_ISHR : VKD3D_SM4_OP_USHR, ++ assert(dst_type->e.numeric.type != HLSL_TYPE_BOOL); ++ write_sm4_binary_op(tpf, dst_type->e.numeric.type == HLSL_TYPE_INT ? VKD3D_SM4_OP_ISHR : VKD3D_SM4_OP_USHR, + &expr->node, arg1, arg2); + break; + +@@ -5458,7 +5459,7 @@ static void write_sm4_load(const struct tpf_writer *tpf, const struct hlsl_ir_lo + instr.dst_count = 1; + + assert(hlsl_is_numeric_type(type)); +- if (type->base_type == HLSL_TYPE_BOOL && var_is_user_input(tpf->ctx, load->src.var)) ++ if (type->e.numeric.type == HLSL_TYPE_BOOL && var_is_user_input(tpf->ctx, load->src.var)) + { + struct hlsl_constant_value value; + +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 07b5818cba9..bf9d3038f08 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -223,6 +223,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW = 9016, + VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE = 9017, + VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION = 9018, ++ VKD3D_SHADER_ERROR_VSIR_INVALID_GS = 9019, + + VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300, + }; +@@ -528,8 +529,20 @@ enum vkd3d_shader_opcode + VKD3DSIH_UTOF, + VKD3DSIH_UTOU, + VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL, ++ VKD3DSIH_WAVE_ACTIVE_BALLOT, ++ VKD3DSIH_WAVE_ACTIVE_BIT_AND, ++ VKD3DSIH_WAVE_ACTIVE_BIT_OR, ++ VKD3DSIH_WAVE_ACTIVE_BIT_XOR, + VKD3DSIH_WAVE_ALL_TRUE, + VKD3DSIH_WAVE_ANY_TRUE, ++ VKD3DSIH_WAVE_OP_ADD, ++ VKD3DSIH_WAVE_OP_IMAX, ++ VKD3DSIH_WAVE_OP_IMIN, ++ VKD3DSIH_WAVE_OP_MAX, ++ VKD3DSIH_WAVE_OP_MIN, ++ VKD3DSIH_WAVE_OP_MUL, ++ VKD3DSIH_WAVE_OP_UMAX, ++ VKD3DSIH_WAVE_OP_UMIN, + VKD3DSIH_XOR, + + VKD3DSIH_INVALID, +@@ -793,6 +806,7 @@ enum vkd3d_tessellator_domain + #define VKD3DSI_SAMPLE_INFO_UINT 0x1 + #define VKD3DSI_SAMPLER_COMPARISON_MODE 0x1 + #define VKD3DSI_SHIFT_UNMASKED 0x1 ++#define VKD3DSI_WAVE_PREFIX 0x1 + + #define VKD3DSI_PRECISE_X 0x100 + #define VKD3DSI_PRECISE_Y 0x200 +@@ -1151,6 +1165,8 @@ enum vkd3d_primitive_type + VKD3D_PT_TRIANGLELIST_ADJ = 12, + VKD3D_PT_TRIANGLESTRIP_ADJ = 13, + VKD3D_PT_PATCH = 14, ++ ++ VKD3D_PT_COUNT = 15, + }; + + struct vkd3d_shader_primitive_type +diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c +index 3f3332dd3e3..36d8433939a 100644 +--- a/libs/vkd3d/libs/vkd3d/device.c ++++ b/libs/vkd3d/libs/vkd3d/device.c +@@ -272,13 +272,15 @@ static bool has_extension(const VkExtensionProperties *extensions, + + for (i = 0; i < count; ++i) + { +- if (is_extension_disabled(extension_name)) +- { +- WARN("Extension %s is disabled.\n", debugstr_a(extension_name)); +- continue; +- } + if (!strcmp(extensions[i].extensionName, extension_name)) ++ { ++ if (is_extension_disabled(extension_name)) ++ { ++ WARN("Extension %s is disabled.\n", debugstr_a(extension_name)); ++ return false; ++ } + return true; ++ } + } + return false; + } +@@ -422,8 +424,6 @@ static HRESULT vkd3d_init_instance_caps(struct vkd3d_instance *instance, + ERR("Failed to enumerate instance extensions, vr %d.\n", vr); + return hresult_from_vk_result(vr); + } +- if (!count) +- return S_OK; + + if (!(vk_extensions = vkd3d_calloc(count, sizeof(*vk_extensions)))) + return E_OUTOFMEMORY; +@@ -869,29 +869,41 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i + info->features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + + conditional_rendering_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT; +- vk_prepend_struct(&info->features2, conditional_rendering_features); ++ if (vulkan_info->EXT_conditional_rendering) ++ vk_prepend_struct(&info->features2, conditional_rendering_features); + depth_clip_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT; +- vk_prepend_struct(&info->features2, depth_clip_features); ++ if (vulkan_info->EXT_depth_clip_enable) ++ vk_prepend_struct(&info->features2, depth_clip_features); + descriptor_indexing_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; +- vk_prepend_struct(&info->features2, descriptor_indexing_features); ++ if (vulkan_info->EXT_descriptor_indexing) ++ vk_prepend_struct(&info->features2, descriptor_indexing_features); + fragment_shader_interlock_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT; +- vk_prepend_struct(&info->features2, fragment_shader_interlock_features); ++ if (vulkan_info->EXT_fragment_shader_interlock) ++ vk_prepend_struct(&info->features2, fragment_shader_interlock_features); + robustness2_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; +- vk_prepend_struct(&info->features2, robustness2_features); ++ if (vulkan_info->EXT_robustness2) ++ vk_prepend_struct(&info->features2, robustness2_features); + demote_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT; +- vk_prepend_struct(&info->features2, demote_features); ++ if (vulkan_info->EXT_shader_demote_to_helper_invocation) ++ vk_prepend_struct(&info->features2, demote_features); + buffer_alignment_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT; +- vk_prepend_struct(&info->features2, buffer_alignment_features); ++ if (vulkan_info->EXT_texel_buffer_alignment) ++ vk_prepend_struct(&info->features2, buffer_alignment_features); + xfb_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; +- vk_prepend_struct(&info->features2, xfb_features); ++ if (vulkan_info->EXT_transform_feedback) ++ vk_prepend_struct(&info->features2, xfb_features); + vertex_divisor_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT; +- vk_prepend_struct(&info->features2, vertex_divisor_features); ++ if (vulkan_info->EXT_vertex_attribute_divisor) ++ vk_prepend_struct(&info->features2, vertex_divisor_features); + timeline_semaphore_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR; +- vk_prepend_struct(&info->features2, timeline_semaphore_features); ++ if (vulkan_info->KHR_timeline_semaphore) ++ vk_prepend_struct(&info->features2, timeline_semaphore_features); + mutable_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT; +- vk_prepend_struct(&info->features2, mutable_features); ++ if (vulkan_info->EXT_mutable_descriptor_type) ++ vk_prepend_struct(&info->features2, mutable_features); + formats4444_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT; +- vk_prepend_struct(&info->features2, formats4444_features); ++ if (vulkan_info->EXT_4444_formats) ++ vk_prepend_struct(&info->features2, formats4444_features); + + if (vulkan_info->KHR_get_physical_device_properties2) + VK_CALL(vkGetPhysicalDeviceFeatures2KHR(physical_device, &info->features2)); +@@ -901,15 +913,20 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i + info->properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + + maintenance3_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES; +- vk_prepend_struct(&info->properties2, maintenance3_properties); ++ if (vulkan_info->KHR_maintenance3) ++ vk_prepend_struct(&info->properties2, maintenance3_properties); + descriptor_indexing_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT; +- vk_prepend_struct(&info->properties2, descriptor_indexing_properties); ++ if (vulkan_info->EXT_descriptor_indexing) ++ vk_prepend_struct(&info->properties2, descriptor_indexing_properties); + buffer_alignment_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT; +- vk_prepend_struct(&info->properties2, buffer_alignment_properties); ++ if (vulkan_info->EXT_texel_buffer_alignment) ++ vk_prepend_struct(&info->properties2, buffer_alignment_properties); + xfb_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT; +- vk_prepend_struct(&info->properties2, xfb_properties); ++ if (vulkan_info->EXT_transform_feedback) ++ vk_prepend_struct(&info->properties2, xfb_properties); + vertex_divisor_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT; +- vk_prepend_struct(&info->properties2, vertex_divisor_properties); ++ if (vulkan_info->EXT_vertex_attribute_divisor) ++ vk_prepend_struct(&info->properties2, vertex_divisor_properties); + subgroup_properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; + if (d3d12_device_environment_is_vulkan_min_1_1(device)) + vk_prepend_struct(&info->properties2, subgroup_properties); +@@ -1515,6 +1532,61 @@ static bool d3d12_device_supports_typed_uav_load_additional_formats(const struct + return true; + } + ++static HRESULT vkd3d_check_device_extensions(struct d3d12_device *device, ++ const struct vkd3d_device_create_info *create_info, VkExtensionProperties **vk_extensions, ++ uint32_t *vk_extension_count, uint32_t *device_extension_count, bool **user_extension_supported) ++{ ++ const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs; ++ const struct vkd3d_optional_device_extensions_info *optional_extensions; ++ VkPhysicalDevice physical_device = device->vk_physical_device; ++ struct vkd3d_vulkan_info *vulkan_info = &device->vk_info; ++ VkResult vr; ++ ++ *device_extension_count = 0; ++ ++ if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, vk_extension_count, NULL))) < 0) ++ { ++ ERR("Failed to enumerate device extensions, vr %d.\n", vr); ++ return hresult_from_vk_result(vr); ++ } ++ ++ if (!(*vk_extensions = vkd3d_calloc(*vk_extension_count, sizeof(**vk_extensions)))) ++ return E_OUTOFMEMORY; ++ ++ TRACE("Enumerating %u device extensions.\n", *vk_extension_count); ++ if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, vk_extension_count, *vk_extensions))) < 0) ++ { ++ ERR("Failed to enumerate device extensions, vr %d.\n", vr); ++ vkd3d_free(*vk_extensions); ++ return hresult_from_vk_result(vr); ++ } ++ ++ optional_extensions = vkd3d_find_struct(create_info->next, OPTIONAL_DEVICE_EXTENSIONS_INFO); ++ if (optional_extensions && optional_extensions->extension_count) ++ { ++ if (!(*user_extension_supported = vkd3d_calloc(optional_extensions->extension_count, sizeof(bool)))) ++ { ++ vkd3d_free(*vk_extensions); ++ return E_OUTOFMEMORY; ++ } ++ } ++ else ++ { ++ *user_extension_supported = NULL; ++ } ++ ++ *device_extension_count = vkd3d_check_extensions(*vk_extensions, *vk_extension_count, ++ required_device_extensions, ARRAY_SIZE(required_device_extensions), ++ optional_device_extensions, ARRAY_SIZE(optional_device_extensions), ++ create_info->device_extensions, create_info->device_extension_count, ++ optional_extensions ? optional_extensions->extensions : NULL, ++ optional_extensions ? optional_extensions->extension_count : 0, ++ *user_extension_supported, vulkan_info, "device", ++ device->vkd3d_instance->config_flags & VKD3D_CONFIG_FLAG_VULKAN_DEBUG); ++ ++ return S_OK; ++} ++ + static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, + const struct vkd3d_device_create_info *create_info, + struct vkd3d_physical_device_info *physical_device_info, +@@ -1523,14 +1595,13 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, + const VkPhysicalDeviceSubgroupProperties *subgroup_properties = &physical_device_info->subgroup_properties; + const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs; + VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT *fragment_shader_interlock; +- const struct vkd3d_optional_device_extensions_info *optional_extensions; + VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing; + VkPhysicalDevice physical_device = device->vk_physical_device; + struct vkd3d_vulkan_info *vulkan_info = &device->vk_info; + VkExtensionProperties *vk_extensions; + VkPhysicalDeviceFeatures *features; +- uint32_t count; +- VkResult vr; ++ uint32_t vk_extension_count; ++ HRESULT hr; + + /* SHUFFLE is required to implement WaveReadLaneAt with dynamically uniform index before SPIR-V 1.5 / Vulkan 1.2. */ + static const VkSubgroupFeatureFlags required_subgroup_features = VK_SUBGROUP_FEATURE_ARITHMETIC_BIT +@@ -1542,7 +1613,11 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, + + static const VkSubgroupFeatureFlags required_stages = VK_SHADER_STAGE_COMPUTE_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; + +- *device_extension_count = 0; ++ if (FAILED(hr = vkd3d_check_device_extensions(device, create_info, &vk_extensions, &vk_extension_count, ++ device_extension_count, user_extension_supported))) ++ return hr; ++ ++ vkd3d_physical_device_info_init(physical_device_info, device); + + vkd3d_trace_physical_device(physical_device, physical_device_info, vk_procs); + vkd3d_trace_physical_device_features(physical_device_info); +@@ -1634,48 +1709,6 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, + device->feature_options5.RenderPassesTier = D3D12_RENDER_PASS_TIER_0; + device->feature_options5.RaytracingTier = D3D12_RAYTRACING_TIER_NOT_SUPPORTED; + +- if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, NULL))) < 0) +- { +- ERR("Failed to enumerate device extensions, vr %d.\n", vr); +- return hresult_from_vk_result(vr); +- } +- if (!count) +- return S_OK; +- +- if (!(vk_extensions = vkd3d_calloc(count, sizeof(*vk_extensions)))) +- return E_OUTOFMEMORY; +- +- TRACE("Enumerating %u device extensions.\n", count); +- if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, &count, vk_extensions))) < 0) +- { +- ERR("Failed to enumerate device extensions, vr %d.\n", vr); +- vkd3d_free(vk_extensions); +- return hresult_from_vk_result(vr); +- } +- +- optional_extensions = vkd3d_find_struct(create_info->next, OPTIONAL_DEVICE_EXTENSIONS_INFO); +- if (optional_extensions && optional_extensions->extension_count) +- { +- if (!(*user_extension_supported = vkd3d_calloc(optional_extensions->extension_count, sizeof(bool)))) +- { +- vkd3d_free(vk_extensions); +- return E_OUTOFMEMORY; +- } +- } +- else +- { +- *user_extension_supported = NULL; +- } +- +- *device_extension_count = vkd3d_check_extensions(vk_extensions, count, +- required_device_extensions, ARRAY_SIZE(required_device_extensions), +- optional_device_extensions, ARRAY_SIZE(optional_device_extensions), +- create_info->device_extensions, create_info->device_extension_count, +- optional_extensions ? optional_extensions->extensions : NULL, +- optional_extensions ? optional_extensions->extension_count : 0, +- *user_extension_supported, vulkan_info, "device", +- device->vkd3d_instance->config_flags & VKD3D_CONFIG_FLAG_VULKAN_DEBUG); +- + fragment_shader_interlock = &physical_device_info->fragment_shader_interlock_features; + if (!fragment_shader_interlock->fragmentShaderSampleInterlock + || !fragment_shader_interlock->fragmentShaderPixelInterlock) +@@ -1701,7 +1734,7 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, + + vulkan_info->texel_buffer_alignment_properties = physical_device_info->texel_buffer_alignment_properties; + +- if (get_spec_version(vk_extensions, count, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) >= 3) ++ if (get_spec_version(vk_extensions, vk_extension_count, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) >= 3) + { + const VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *divisor_features; + divisor_features = &physical_device_info->vertex_divisor_features; +@@ -2098,8 +2131,6 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, + + VK_CALL(vkGetPhysicalDeviceMemoryProperties(physical_device, &device->memory_properties)); + +- vkd3d_physical_device_info_init(&physical_device_info, device); +- + if (FAILED(hr = vkd3d_init_device_caps(device, create_info, &physical_device_info, + &extension_count, &user_extension_supported))) + return hr; +diff --git a/libs/vkd3d/libs/vkd3d/utils.c b/libs/vkd3d/libs/vkd3d/utils.c +index 58747342b5c..11029c9f5f9 100644 +--- a/libs/vkd3d/libs/vkd3d/utils.c ++++ b/libs/vkd3d/libs/vkd3d/utils.c +@@ -901,6 +901,30 @@ bool vkd3d_get_program_name(char program_name[PATH_MAX]) + return true; + } + ++#elif defined(WIN32) ++ ++bool vkd3d_get_program_name(char program_name[PATH_MAX]) ++{ ++ char buffer[MAX_PATH]; ++ char *p, *name; ++ size_t len; ++ ++ *program_name = '\0'; ++ len = GetModuleFileNameA(NULL, buffer, ARRAY_SIZE(buffer)); ++ if (!(len && len < MAX_PATH)) ++ return false; ++ ++ name = buffer; ++ if ((p = strrchr(name, '/'))) ++ name = p + 1; ++ if ((p = strrchr(name, '\\'))) ++ name = p + 1; ++ ++ len = strlen(name) + 1; ++ memcpy(program_name, name, len); ++ return true; ++} ++ + #else + + bool vkd3d_get_program_name(char program_name[PATH_MAX]) +-- +2.43.0 +