wine-staging/patches/vkd3d-latest/0004-Updated-vkd3d-to-22960753e94967888bada0d7e7731295b38.patch
2023-11-11 09:57:14 +11:00

3863 lines
167 KiB
Diff

From 1672d57bb241d2db0267a0edb411017c2bcbf60f Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Sat, 11 Nov 2023 09:51:47 +1100
Subject: [PATCH] Updated vkd3d to 22960753e94967888bada0d7e7731295b3823acd.
---
libs/vkd3d/include/vkd3d_shader.h | 25 +
libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 18 +-
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 37 ++
libs/vkd3d/libs/vkd3d-shader/dxil.c | 347 ++++++++++++-
libs/vkd3d/libs/vkd3d-shader/hlsl.c | 109 ++--
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 17 +-
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 195 +++++---
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 148 ++++--
.../libs/vkd3d-shader/hlsl_constant_ops.c | 60 +++
libs/vkd3d/libs/vkd3d-shader/ir.c | 209 ++++++--
libs/vkd3d/libs/vkd3d-shader/spirv.c | 467 +++++++++++-------
libs/vkd3d/libs/vkd3d-shader/tpf.c | 303 ++++++++----
.../libs/vkd3d-shader/vkd3d_shader_private.h | 46 +-
libs/vkd3d/libs/vkd3d/device.c | 15 +-
libs/vkd3d/libs/vkd3d/resource.c | 87 ++--
libs/vkd3d/libs/vkd3d/vkd3d_private.h | 9 +-
16 files changed, 1539 insertions(+), 553 deletions(-)
diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h
index 94f79c7c7c2..1d6cbbf8855 100644
--- a/libs/vkd3d/include/vkd3d_shader.h
+++ b/libs/vkd3d/include/vkd3d_shader.h
@@ -173,6 +173,21 @@ enum vkd3d_shader_compile_option_backward_compatibility
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY),
};
+/**
+ * Determines the origin of fragment coordinates.
+ *
+ * \since 1.10
+ */
+enum vkd3d_shader_compile_option_fragment_coordinate_origin
+{
+ /** Fragment coordinates originate from the upper-left. This is the
+ * default; it's also the only value supported by Vulkan environments. */
+ VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN_UPPER_LEFT = 0x00000000,
+ /** Fragment coordinates originate from the lower-left. This matches the
+ * traditional behaviour of OpenGL environments. */
+ VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN_LOWER_LEFT = 0x00000001,
+};
+
enum vkd3d_shader_compile_option_name
{
/**
@@ -220,6 +235,16 @@ enum vkd3d_shader_compile_option_name
* \since 1.10
*/
VKD3D_SHADER_COMPILE_OPTION_BACKWARD_COMPATIBILITY = 0x00000008,
+ /**
+ * This option specifies the origin of fragment coordinates for SPIR-V
+ * targets.
+ *
+ * \a value is a member of enum
+ * vkd3d_shader_compile_option_fragment_coordinate_origin.
+ *
+ * \since 1.10
+ */
+ VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN = 0x00000009,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME),
};
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
index 5cea0c0c260..442c1e414cd 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
@@ -106,9 +106,9 @@ static const char * const shader_opcode_names[] =
[VKD3DSIH_DEFAULT ] = "default",
[VKD3DSIH_DEFB ] = "defb",
[VKD3DSIH_DEFI ] = "defi",
- [VKD3DSIH_DEQ ] = "deq",
+ [VKD3DSIH_DEQO ] = "deq",
[VKD3DSIH_DFMA ] = "dfma",
- [VKD3DSIH_DGE ] = "dge",
+ [VKD3DSIH_DGEO ] = "dge",
[VKD3DSIH_DISCARD ] = "discard",
[VKD3DSIH_DIV ] = "div",
[VKD3DSIH_DLT ] = "dlt",
@@ -140,7 +140,8 @@ static const char * const shader_opcode_names[] =
[VKD3DSIH_ENDLOOP ] = "endloop",
[VKD3DSIH_ENDREP ] = "endrep",
[VKD3DSIH_ENDSWITCH ] = "endswitch",
- [VKD3DSIH_EQ ] = "eq",
+ [VKD3DSIH_EQO ] = "eq",
+ [VKD3DSIH_EQU ] = "eq_unord",
[VKD3DSIH_EVAL_CENTROID ] = "eval_centroid",
[VKD3DSIH_EVAL_SAMPLE_INDEX ] = "eval_sample_index",
[VKD3DSIH_EXP ] = "exp",
@@ -164,7 +165,8 @@ static const char * const shader_opcode_names[] =
[VKD3DSIH_GATHER4_PO_C_S ] = "gather4_po_c_s",
[VKD3DSIH_GATHER4_PO_S ] = "gather4_po_s",
[VKD3DSIH_GATHER4_S ] = "gather4_s",
- [VKD3DSIH_GE ] = "ge",
+ [VKD3DSIH_GEO ] = "ge",
+ [VKD3DSIH_GEU ] = "ge_unord",
[VKD3DSIH_HS_CONTROL_POINT_PHASE ] = "hs_control_point_phase",
[VKD3DSIH_HS_DECLS ] = "hs_decls",
[VKD3DSIH_HS_FORK_PHASE ] = "hs_fork_phase",
@@ -199,6 +201,7 @@ static const char * const shader_opcode_names[] =
[VKD3DSIH_ISHR ] = "ishr",
[VKD3DSIH_ITOD ] = "itod",
[VKD3DSIH_ITOF ] = "itof",
+ [VKD3DSIH_ITOI ] = "itoi",
[VKD3DSIH_LABEL ] = "label",
[VKD3DSIH_LD ] = "ld",
[VKD3DSIH_LD2DMS ] = "ld2dms",
@@ -216,7 +219,8 @@ static const char * const shader_opcode_names[] =
[VKD3DSIH_LOGP ] = "logp",
[VKD3DSIH_LOOP ] = "loop",
[VKD3DSIH_LRP ] = "lrp",
- [VKD3DSIH_LT ] = "lt",
+ [VKD3DSIH_LTO ] = "lt",
+ [VKD3DSIH_LTU ] = "lt_unord",
[VKD3DSIH_M3x2 ] = "m3x2",
[VKD3DSIH_M3x3 ] = "m3x3",
[VKD3DSIH_M3x4 ] = "m3x4",
@@ -230,7 +234,8 @@ static const char * const shader_opcode_names[] =
[VKD3DSIH_MOVC ] = "movc",
[VKD3DSIH_MSAD ] = "msad",
[VKD3DSIH_MUL ] = "mul",
- [VKD3DSIH_NE ] = "ne",
+ [VKD3DSIH_NEO ] = "ne_ord",
+ [VKD3DSIH_NEU ] = "ne",
[VKD3DSIH_NOP ] = "nop",
[VKD3DSIH_NOT ] = "not",
[VKD3DSIH_NRM ] = "nrm",
@@ -306,6 +311,7 @@ static const char * const shader_opcode_names[] =
[VKD3DSIH_USHR ] = "ushr",
[VKD3DSIH_UTOD ] = "utod",
[VKD3DSIH_UTOF ] = "utof",
+ [VKD3DSIH_UTOU ] = "utou",
[VKD3DSIH_XOR ] = "xor",
};
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
index b1e2dc91d94..7e0eac6c1aa 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
@@ -1824,6 +1824,37 @@ static void write_sm1_dp2add(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer
write_sm1_instruction(ctx, buffer, &instr);
}
+static void write_sm1_ternary_op(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
+ D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode, const struct hlsl_reg *dst, const struct hlsl_reg *src1,
+ const struct hlsl_reg *src2, const struct hlsl_reg *src3)
+{
+ struct sm1_instruction instr =
+ {
+ .opcode = opcode,
+
+ .dst.type = D3DSPR_TEMP,
+ .dst.writemask = dst->writemask,
+ .dst.reg = dst->id,
+ .has_dst = 1,
+
+ .srcs[0].type = D3DSPR_TEMP,
+ .srcs[0].swizzle = hlsl_swizzle_from_writemask(src1->writemask),
+ .srcs[0].reg = src1->id,
+ .srcs[1].type = D3DSPR_TEMP,
+ .srcs[1].swizzle = hlsl_swizzle_from_writemask(src2->writemask),
+ .srcs[1].reg = src2->id,
+ .srcs[2].type = D3DSPR_TEMP,
+ .srcs[2].swizzle = hlsl_swizzle_from_writemask(src3->writemask),
+ .srcs[2].reg = src3->id,
+ .src_count = 3,
+ };
+
+ sm1_map_src_swizzle(&instr.srcs[0], instr.dst.writemask);
+ sm1_map_src_swizzle(&instr.srcs[1], instr.dst.writemask);
+ sm1_map_src_swizzle(&instr.srcs[2], instr.dst.writemask);
+ write_sm1_instruction(ctx, buffer, &instr);
+}
+
static void write_sm1_binary_op(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode, const struct hlsl_reg *dst,
const struct hlsl_reg *src1, const struct hlsl_reg *src2)
@@ -2190,6 +2221,10 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
}
break;
+ case HLSL_OP3_CMP:
+ write_sm1_ternary_op(ctx, buffer, D3DSIO_CMP, &instr->reg, &arg1->reg, &arg2->reg, &arg3->reg);
+ break;
+
case HLSL_OP3_DP2ADD:
write_sm1_dp2add(ctx, buffer, &instr->reg, &arg1->reg, &arg2->reg, &arg3->reg);
break;
@@ -2302,6 +2337,8 @@ static void write_sm1_resource_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_
.src_count = 2,
};
+ if (load->load_type == HLSL_RESOURCE_SAMPLE_PROJ)
+ sm1_instr.opcode |= VKD3DSI_TEXLD_PROJECT << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT;
assert(instr->reg.allocated);
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
index e0e242cb788..2174ba52cd7 100644
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
@@ -289,6 +289,53 @@ enum dx_intrinsic_opcode
DX_CBUFFER_LOAD_LEGACY = 59,
};
+enum dxil_cast_code
+{
+ CAST_TRUNC = 0,
+ CAST_ZEXT = 1,
+ CAST_SEXT = 2,
+ CAST_FPTOUI = 3,
+ CAST_FPTOSI = 4,
+ CAST_UITOFP = 5,
+ CAST_SITOFP = 6,
+ CAST_FPTRUNC = 7,
+ CAST_FPEXT = 8,
+ CAST_PTRTOINT = 9,
+ CAST_INTTOPTR = 10,
+ CAST_BITCAST = 11,
+ CAST_ADDRSPACECAST = 12,
+};
+
+enum dxil_predicate
+{
+ FCMP_FALSE = 0,
+ FCMP_OEQ = 1,
+ FCMP_OGT = 2,
+ FCMP_OGE = 3,
+ FCMP_OLT = 4,
+ FCMP_OLE = 5,
+ FCMP_ONE = 6,
+ FCMP_ORD = 7,
+ FCMP_UNO = 8,
+ FCMP_UEQ = 9,
+ FCMP_UGT = 10,
+ FCMP_UGE = 11,
+ FCMP_ULT = 12,
+ FCMP_ULE = 13,
+ FCMP_UNE = 14,
+ FCMP_TRUE = 15,
+ ICMP_EQ = 32,
+ ICMP_NE = 33,
+ ICMP_UGT = 34,
+ ICMP_UGE = 35,
+ ICMP_ULT = 36,
+ ICMP_ULE = 37,
+ ICMP_SGT = 38,
+ ICMP_SGE = 39,
+ ICMP_SLT = 40,
+ ICMP_SLE = 41,
+};
+
struct sm6_pointer_info
{
const struct sm6_type *type;
@@ -497,6 +544,7 @@ struct sm6_parser
struct sm6_type *types;
size_t type_count;
+ struct sm6_type *bool_type;
struct sm6_type *metadata_type;
struct sm6_type *handle_type;
@@ -1371,6 +1419,8 @@ static enum vkd3d_result sm6_parser_type_table_init(struct sm6_parser *sm6)
switch ((width = record->operands[0]))
{
case 1:
+ sm6->bool_type = type;
+ break;
case 8:
case 16:
case 32:
@@ -2633,9 +2683,7 @@ static void sm6_parser_emit_signature(struct sm6_parser *sm6, const struct shade
static void sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature)
{
- sm6_parser_init_signature(sm6, output_signature,
- (sm6->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3DSPR_COLOROUT : VKD3DSPR_OUTPUT,
- sm6->output_params);
+ sm6_parser_init_signature(sm6, output_signature, VKD3DSPR_OUTPUT, sm6->output_params);
}
static void sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct shader_signature *input_signature)
@@ -3248,6 +3296,293 @@ static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_recor
fn_value->u.function.name, &operands[1], operand_count - 1, ins, dst);
}
+static enum vkd3d_shader_opcode sm6_map_cast_op(uint64_t code, const struct sm6_type *from,
+ const struct sm6_type *to, struct sm6_parser *sm6)
+{
+ enum vkd3d_shader_opcode op = VKD3DSIH_INVALID;
+ bool from_int, to_int, from_fp, to_fp;
+ bool is_valid = false;
+
+ from_int = sm6_type_is_integer(from);
+ to_int = sm6_type_is_integer(to);
+ from_fp = sm6_type_is_floating_point(from);
+ to_fp = sm6_type_is_floating_point(to);
+
+ /* NOTE: DXIL currently doesn't use vectors here. */
+ if ((!from_int && !from_fp) || (!to_int && !to_fp))
+ {
+ FIXME("Unhandled cast of type class %u to type class %u.\n", from->class, to->class);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Cast of type class %u to type class %u is not implemented.", from->class, to->class);
+ return VKD3DSIH_INVALID;
+ }
+ if (to->u.width == 8 || from->u.width == 8)
+ {
+ FIXME("Unhandled 8-bit value.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Cast to/from an 8-bit type is not implemented.");
+ return VKD3DSIH_INVALID;
+ }
+
+ /* DXC emits minimum precision types as 16-bit. These must be emitted
+ * as 32-bit in VSIR, so all width extensions to 32 bits are no-ops. */
+ switch (code)
+ {
+ case CAST_TRUNC:
+ /* nop or min precision. TODO: native 16-bit */
+ if (to->u.width == from->u.width || (to->u.width == 16 && from->u.width == 32))
+ op = VKD3DSIH_NOP;
+ else
+ op = VKD3DSIH_UTOU;
+ is_valid = from_int && to_int && to->u.width <= from->u.width;
+ break;
+ case CAST_ZEXT:
+ case CAST_SEXT:
+ /* nop or min precision. TODO: native 16-bit */
+ if (to->u.width == from->u.width || (to->u.width == 32 && from->u.width == 16))
+ {
+ op = VKD3DSIH_NOP;
+ is_valid = from_int && to_int;
+ }
+ else if (to->u.width > from->u.width)
+ {
+ op = (code == CAST_ZEXT) ? VKD3DSIH_UTOU : VKD3DSIH_ITOI;
+ assert(from->u.width == 1 || to->u.width == 64);
+ is_valid = from_int && to_int;
+ }
+ break;
+ case CAST_FPTOUI:
+ op = VKD3DSIH_FTOU;
+ is_valid = from_fp && to_int && to->u.width > 1;
+ break;
+ case CAST_FPTOSI:
+ op = VKD3DSIH_FTOI;
+ is_valid = from_fp && to_int && to->u.width > 1;
+ break;
+ case CAST_UITOFP:
+ op = VKD3DSIH_UTOF;
+ is_valid = from_int && to_fp;
+ break;
+ case CAST_SITOFP:
+ op = VKD3DSIH_ITOF;
+ is_valid = from_int && to_fp;
+ break;
+ case CAST_FPTRUNC:
+ /* TODO: native 16-bit */
+ op = (from->u.width == 64) ? VKD3DSIH_DTOF : VKD3DSIH_NOP;
+ is_valid = from_fp && to_fp;
+ break;
+ case CAST_FPEXT:
+ /* TODO: native 16-bit */
+ op = (to->u.width == 64) ? VKD3DSIH_FTOD : VKD3DSIH_NOP;
+ is_valid = from_fp && to_fp;
+ break;
+ case CAST_BITCAST:
+ op = VKD3DSIH_MOV;
+ is_valid = to->u.width == from->u.width;
+ break;
+ default:
+ FIXME("Unhandled cast op %"PRIu64".\n", code);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Cast operation %"PRIu64" is unhandled.\n", code);
+ return VKD3DSIH_INVALID;
+ }
+
+ if (!is_valid)
+ {
+ FIXME("Invalid types %u and/or %u for op %"PRIu64".\n", from->class, to->class, code);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Cast operation %"PRIu64" from type class %u, width %u to type class %u, width %u is invalid.\n",
+ code, from->class, from->u.width, to->class, to->u.width);
+ return VKD3DSIH_INVALID;
+ }
+
+ return op;
+}
+
+static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_record *record,
+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst)
+{
+ struct vkd3d_shader_src_param *src_param;
+ enum vkd3d_shader_opcode handler_idx;
+ const struct sm6_value *value;
+ const struct sm6_type *type;
+ unsigned int i = 0;
+
+ if (!(value = sm6_parser_get_value_by_ref(sm6, record, NULL, &i)))
+ return;
+
+ if (!dxil_record_validate_operand_count(record, i + 2, i + 2, sm6))
+ return;
+
+ if (!(type = sm6_parser_get_type(sm6, record->operands[i++])))
+ return;
+
+ dst->type = type;
+
+ if (sm6_type_is_pointer(type))
+ {
+ *dst = *value;
+ dst->type = type;
+ ins->handler_idx = VKD3DSIH_NOP;
+ return;
+ }
+
+ if ((handler_idx = sm6_map_cast_op(record->operands[i], value->type, type, sm6)) == VKD3DSIH_INVALID)
+ return;
+
+ vsir_instruction_init(ins, &sm6->p.location, handler_idx);
+
+ if (handler_idx == VKD3DSIH_NOP)
+ {
+ dst->u.reg = value->u.reg;
+ return;
+ }
+
+ src_param = instruction_src_params_alloc(ins, 1, sm6);
+ src_param_init_from_value(src_param, value);
+
+ instruction_dst_param_init_ssa_scalar(ins, sm6);
+
+ /* bitcast */
+ if (handler_idx == VKD3DSIH_MOV)
+ src_param->reg.data_type = dst->u.reg.data_type;
+}
+
+struct sm6_cmp_info
+{
+ enum vkd3d_shader_opcode handler_idx;
+ bool src_swap;
+};
+
+static const struct sm6_cmp_info *sm6_map_cmp2_op(uint64_t code)
+{
+ static const struct sm6_cmp_info cmp_op_table[] =
+ {
+ [FCMP_FALSE] = {VKD3DSIH_INVALID},
+ [FCMP_OEQ] = {VKD3DSIH_EQO},
+ [FCMP_OGT] = {VKD3DSIH_LTO, true},
+ [FCMP_OGE] = {VKD3DSIH_GEO},
+ [FCMP_OLT] = {VKD3DSIH_LTO},
+ [FCMP_OLE] = {VKD3DSIH_GEO, true},
+ [FCMP_ONE] = {VKD3DSIH_NEO},
+ [FCMP_ORD] = {VKD3DSIH_INVALID},
+ [FCMP_UNO] = {VKD3DSIH_INVALID},
+ [FCMP_UEQ] = {VKD3DSIH_EQU},
+ [FCMP_UGT] = {VKD3DSIH_LTU, true},
+ [FCMP_UGE] = {VKD3DSIH_GEU},
+ [FCMP_ULT] = {VKD3DSIH_LTU},
+ [FCMP_ULE] = {VKD3DSIH_GEU, true},
+ [FCMP_UNE] = {VKD3DSIH_NEU},
+ [FCMP_TRUE] = {VKD3DSIH_INVALID},
+
+ [ICMP_EQ] = {VKD3DSIH_IEQ},
+ [ICMP_NE] = {VKD3DSIH_INE},
+ [ICMP_UGT] = {VKD3DSIH_ULT, true},
+ [ICMP_UGE] = {VKD3DSIH_UGE},
+ [ICMP_ULT] = {VKD3DSIH_ULT},
+ [ICMP_ULE] = {VKD3DSIH_UGE, true},
+ [ICMP_SGT] = {VKD3DSIH_ILT, true},
+ [ICMP_SGE] = {VKD3DSIH_IGE},
+ [ICMP_SLT] = {VKD3DSIH_ILT},
+ [ICMP_SLE] = {VKD3DSIH_IGE, true},
+ };
+
+ return (code < ARRAY_SIZE(cmp_op_table)) ? &cmp_op_table[code] : NULL;
+}
+
+static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_record *record,
+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst)
+{
+ struct vkd3d_shader_src_param *src_params;
+ const struct sm6_type *type_a, *type_b;
+ const struct sm6_cmp_info *cmp;
+ const struct sm6_value *a, *b;
+ unsigned int i = 0;
+ bool is_int, is_fp;
+ uint64_t code;
+
+ if (!(dst->type = sm6->bool_type))
+ {
+ WARN("Bool type not found.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE,
+ "Module does not define a boolean type for comparison results.");
+ return;
+ }
+
+ a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i);
+ b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i);
+ if (!a || !b)
+ return;
+
+ if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6))
+ return;
+
+ type_a = a->type;
+ type_b = b->type;
+ is_int = sm6_type_is_bool_i16_i32_i64(type_a);
+ is_fp = sm6_type_is_floating_point(type_a);
+
+ code = record->operands[i++];
+
+ if ((!is_int && !is_fp) || is_int != (code >= ICMP_EQ))
+ {
+ FIXME("Invalid operation %"PRIu64" on type class %u.\n", code, type_a->class);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Comparison operation %"PRIu64" on type class %u is invalid.", code, type_a->class);
+ return;
+ }
+
+ if (type_a != type_b)
+ {
+ WARN("Type mismatch, type %u width %u vs type %u width %u.\n", type_a->class,
+ type_a->u.width, type_b->class, type_b->u.width);
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH,
+ "Type mismatch in comparison operation arguments.");
+ }
+
+ if (!(cmp = sm6_map_cmp2_op(code)) || !cmp->handler_idx || cmp->handler_idx == VKD3DSIH_INVALID)
+ {
+ FIXME("Unhandled operation %"PRIu64".\n", code);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Comparison operation %"PRIu64" is unhandled.", code);
+ return;
+ }
+
+ vsir_instruction_init(ins, &sm6->p.location, cmp->handler_idx);
+
+ if (record->operand_count > i)
+ {
+ uint64_t flags = record->operands[i];
+ bool silence_warning = false;
+
+ if (is_fp)
+ {
+ if (!(flags & FP_ALLOW_UNSAFE_ALGEBRA))
+ ins->flags |= VKD3DSI_PRECISE_X;
+ flags &= ~FP_ALLOW_UNSAFE_ALGEBRA;
+ /* SPIR-V FPFastMathMode is only available in the Kernel executon model. */
+ silence_warning = !(flags & ~(FP_NO_NAN | FP_NO_INF | FP_NO_SIGNED_ZEROS | FP_ALLOW_RECIPROCAL));
+ }
+ if (flags && silence_warning)
+ {
+ TRACE("Ignoring fast FP modifier %#"PRIx64".\n", flags);
+ }
+ else if (flags)
+ {
+ WARN("Ignoring flags %#"PRIx64".\n", flags);
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS,
+ "Ignoring flags %#"PRIx64" for a comparison operation.", flags);
+ }
+ }
+
+ src_params = instruction_src_params_alloc(ins, 2, sm6);
+ src_param_init_from_value(&src_params[0 ^ cmp->src_swap], a);
+ src_param_init_from_value(&src_params[1 ^ cmp->src_swap], b);
+
+ instruction_dst_param_init_ssa_scalar(ins, sm6);
+}
+
static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil_record *record,
struct vkd3d_shader_instruction *ins, struct sm6_value *dst)
{
@@ -3464,6 +3799,12 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const
case FUNC_CODE_INST_CALL:
sm6_parser_emit_call(sm6, record, code_block, ins, dst);
break;
+ case FUNC_CODE_INST_CAST:
+ sm6_parser_emit_cast(sm6, record, ins, dst);
+ break;
+ case FUNC_CODE_INST_CMP2:
+ sm6_parser_emit_cmp2(sm6, record, ins, dst);
+ break;
case FUNC_CODE_INST_EXTRACTVAL:
sm6_parser_emit_extractval(sm6, record, ins, dst);
break;
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
index 1d3fd0f7d83..593ca0a3df2 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
@@ -825,17 +825,15 @@ struct hlsl_ir_function *hlsl_get_function(struct hlsl_ctx *ctx, const char *nam
return NULL;
}
-struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const char *name)
+struct hlsl_ir_function_decl *hlsl_get_first_func_decl(struct hlsl_ctx *ctx, const char *name)
{
- struct hlsl_ir_function_decl *decl;
struct hlsl_ir_function *func;
struct rb_entry *entry;
if ((entry = rb_get(&ctx->functions, name)))
{
func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry);
- RB_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry)
- return decl;
+ return LIST_ENTRY(list_head(&func->overloads), struct hlsl_ir_function_decl, entry);
}
return NULL;
@@ -2050,76 +2048,38 @@ void hlsl_pop_scope(struct hlsl_ctx *ctx)
ctx->cur_scope = prev_scope;
}
-static int compare_param_hlsl_types(const struct hlsl_type *t1, const struct hlsl_type *t2)
+static bool func_decl_matches(const struct hlsl_ir_function_decl *decl,
+ const struct hlsl_func_parameters *parameters)
{
- int r;
-
- if ((r = vkd3d_u32_compare(t1->class, t2->class)))
- {
- if (!((t1->class == HLSL_CLASS_SCALAR && t2->class == HLSL_CLASS_VECTOR)
- || (t1->class == HLSL_CLASS_VECTOR && t2->class == HLSL_CLASS_SCALAR)))
- return r;
- }
- if ((r = vkd3d_u32_compare(t1->base_type, t2->base_type)))
- return r;
- if (t1->base_type == HLSL_TYPE_SAMPLER || t1->base_type == HLSL_TYPE_TEXTURE)
- {
- if ((r = vkd3d_u32_compare(t1->sampler_dim, t2->sampler_dim)))
- return r;
- if (t1->base_type == HLSL_TYPE_TEXTURE && t1->sampler_dim != HLSL_SAMPLER_DIM_GENERIC
- && (r = compare_param_hlsl_types(t1->e.resource_format, t2->e.resource_format)))
- return r;
- }
- if ((r = vkd3d_u32_compare(t1->dimx, t2->dimx)))
- return r;
- if ((r = vkd3d_u32_compare(t1->dimy, t2->dimy)))
- return r;
- if (t1->class == HLSL_CLASS_STRUCT)
- {
- size_t i;
-
- if (t1->e.record.field_count != t2->e.record.field_count)
- return t1->e.record.field_count - t2->e.record.field_count;
-
- 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];
+ size_t i;
- if ((r = compare_param_hlsl_types(field1->type, field2->type)))
- return r;
+ if (parameters->count != decl->parameters.count)
+ return false;
- if ((r = strcmp(field1->name, field2->name)))
- return r;
- }
- return 0;
- }
- if (t1->class == HLSL_CLASS_ARRAY)
+ for (i = 0; i < parameters->count; ++i)
{
- if ((r = vkd3d_u32_compare(t1->e.array.elements_count, t2->e.array.elements_count)))
- return r;
- return compare_param_hlsl_types(t1->e.array.type, t2->e.array.type);
+ if (!hlsl_types_are_equal(parameters->vars[i]->data_type, decl->parameters.vars[i]->data_type))
+ return false;
}
-
- return 0;
+ return true;
}
-static int compare_function_decl_rb(const void *key, const struct rb_entry *entry)
+struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const char *name,
+ const struct hlsl_func_parameters *parameters)
{
- const struct hlsl_ir_function_decl *decl = RB_ENTRY_VALUE(entry, const struct hlsl_ir_function_decl, entry);
- const struct hlsl_func_parameters *parameters = key;
- size_t i;
- int r;
+ struct hlsl_ir_function_decl *decl;
+ struct hlsl_ir_function *func;
- if ((r = vkd3d_u32_compare(parameters->count, decl->parameters.count)))
- return r;
+ if (!(func = hlsl_get_function(ctx, name)))
+ return NULL;
- for (i = 0; i < parameters->count; ++i)
+ LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry)
{
- if ((r = compare_param_hlsl_types(parameters->vars[i]->data_type, decl->parameters.vars[i]->data_type)))
- return r;
+ if (func_decl_matches(decl, parameters))
+ return decl;
}
- return 0;
+
+ return NULL;
}
struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const struct hlsl_type *type)
@@ -2562,6 +2522,7 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op)
[HLSL_OP1_ABS] = "abs",
[HLSL_OP1_BIT_NOT] = "~",
[HLSL_OP1_CAST] = "cast",
+ [HLSL_OP1_CEIL] = "ceil",
[HLSL_OP1_COS] = "cos",
[HLSL_OP1_COS_REDUCED] = "cos_reduced",
[HLSL_OP1_DSX] = "dsx",
@@ -2571,6 +2532,7 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op)
[HLSL_OP1_DSY_COARSE] = "dsy_coarse",
[HLSL_OP1_DSY_FINE] = "dsy_fine",
[HLSL_OP1_EXP2] = "exp2",
+ [HLSL_OP1_FLOOR] = "floor",
[HLSL_OP1_FRACT] = "fract",
[HLSL_OP1_LOG2] = "log2",
[HLSL_OP1_LOGIC_NOT] = "!",
@@ -2607,6 +2569,7 @@ const char *debug_hlsl_expr_op(enum hlsl_ir_expr_op op)
[HLSL_OP2_NEQUAL] = "!=",
[HLSL_OP2_RSHIFT] = ">>",
+ [HLSL_OP3_CMP] = "cmp",
[HLSL_OP3_DP2ADD] = "dp2add",
[HLSL_OP3_MOVC] = "movc",
[HLSL_OP3_TERNARY] = "ternary",
@@ -3135,14 +3098,12 @@ static void free_function_decl(struct hlsl_ir_function_decl *decl)
vkd3d_free(decl);
}
-static void free_function_decl_rb(struct rb_entry *entry, void *context)
-{
- free_function_decl(RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry));
-}
-
static void free_function(struct hlsl_ir_function *func)
{
- rb_destroy(&func->overloads, free_function_decl_rb, NULL);
+ struct hlsl_ir_function_decl *decl, *next;
+
+ LIST_FOR_EACH_ENTRY_SAFE(decl, next, &func->overloads, struct hlsl_ir_function_decl, entry)
+ free_function_decl(decl);
vkd3d_free((void *)func->name);
vkd3d_free(func);
}
@@ -3172,17 +3133,15 @@ void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function
{
func = RB_ENTRY_VALUE(func_entry, struct hlsl_ir_function, entry);
decl->func = func;
-
- if (rb_put(&func->overloads, &decl->parameters, &decl->entry) == -1)
- ERR("Failed to insert function overload.\n");
+ list_add_tail(&func->overloads, &decl->entry);
vkd3d_free(name);
return;
}
func = hlsl_alloc(ctx, sizeof(*func));
func->name = name;
- rb_init(&func->overloads, compare_function_decl_rb);
+ list_init(&func->overloads);
decl->func = func;
- rb_put(&func->overloads, &decl->parameters, &decl->entry);
+ list_add_tail(&func->overloads, &decl->entry);
rb_put(&ctx->functions, func->name, &func->entry);
}
@@ -3671,7 +3630,7 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d
if ((func = hlsl_get_function(&ctx, entry_point)))
{
- RB_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry)
+ LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry)
{
if (!decl->has_body)
continue;
@@ -3737,7 +3696,7 @@ struct hlsl_ir_function_decl *hlsl_compile_internal_function(struct hlsl_ctx *ct
hlsl_release_string_buffer(ctx, internal_name);
return NULL;
}
- func = hlsl_get_func_decl(ctx, internal_name->buffer);
+ func = hlsl_get_first_func_decl(ctx, internal_name->buffer);
hlsl_release_string_buffer(ctx, internal_name);
return func;
}
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
index 3d8f5aed174..20fb7b392a1 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
@@ -450,7 +450,7 @@ struct hlsl_ir_function
const char *name;
/* Tree containing function definitions, stored as hlsl_ir_function_decl structures, which would
* be more than one in case of function overloading. */
- struct rb_tree overloads;
+ struct list overloads;
};
struct hlsl_ir_function_decl
@@ -460,8 +460,8 @@ struct hlsl_ir_function_decl
struct hlsl_ir_var *return_var;
struct vkd3d_shader_location loc;
- /* Item entry in hlsl_ir_function.overloads. The parameters' types are used as key. */
- struct rb_entry entry;
+ /* Item entry in hlsl_ir_function.overloads. */
+ struct list entry;
/* Function to which this declaration corresponds. */
struct hlsl_ir_function *func;
@@ -526,6 +526,7 @@ enum hlsl_ir_expr_op
HLSL_OP1_ABS,
HLSL_OP1_BIT_NOT,
HLSL_OP1_CAST,
+ HLSL_OP1_CEIL,
HLSL_OP1_COS,
HLSL_OP1_COS_REDUCED, /* Reduced range [-pi, pi] */
HLSL_OP1_DSX,
@@ -578,7 +579,10 @@ enum hlsl_ir_expr_op
/* MOVC(a, b, c) returns c if a is bitwise zero and b otherwise.
* TERNARY(a, b, c) returns c if a == 0 and b otherwise.
* They differ for floating point numbers, because
- * -0.0 == 0.0, but it is not bitwise zero. */
+ * -0.0 == 0.0, but it is not bitwise zero. CMP(a, b, c) returns b
+ if a >= 0, and c otherwise. It's used only for SM1-SM3 targets, while
+ SM4+ is using MOVC in such cases. */
+ HLSL_OP3_CMP,
HLSL_OP3_MOVC,
HLSL_OP3_TERNARY,
};
@@ -675,6 +679,7 @@ enum hlsl_resource_load_type
HLSL_RESOURCE_SAMPLE_LOD,
HLSL_RESOURCE_SAMPLE_LOD_BIAS,
HLSL_RESOURCE_SAMPLE_GRAD,
+ HLSL_RESOURCE_SAMPLE_PROJ,
HLSL_RESOURCE_GATHER_RED,
HLSL_RESOURCE_GATHER_GREEN,
HLSL_RESOURCE_GATHER_BLUE,
@@ -1168,7 +1173,9 @@ void hlsl_free_type(struct hlsl_type *type);
void hlsl_free_var(struct hlsl_ir_var *decl);
struct hlsl_ir_function *hlsl_get_function(struct hlsl_ctx *ctx, const char *name);
-struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const char *name);
+struct hlsl_ir_function_decl *hlsl_get_first_func_decl(struct hlsl_ctx *ctx, const char *name);
+struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const char *name,
+ const struct hlsl_func_parameters *parameters);
const struct hlsl_profile_info *hlsl_get_target_info(const char *target);
struct hlsl_type *hlsl_get_type(struct hlsl_scope *scope, const char *name, bool recursive, bool case_insensitive);
struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name);
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
index 0e72a539e3f..e8f84fe6467 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
@@ -1158,22 +1158,6 @@ static struct hlsl_reg_reservation parse_packoffset(struct hlsl_ctx *ctx, const
return reservation;
}
-static struct hlsl_ir_function_decl *get_func_decl(struct rb_tree *funcs,
- const char *name, const struct hlsl_func_parameters *parameters)
-{
- struct hlsl_ir_function *func;
- struct rb_entry *entry;
-
- if ((entry = rb_get(funcs, name)))
- {
- func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry);
-
- if ((entry = rb_get(&func->overloads, parameters)))
- return RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry);
- }
- return NULL;
-}
-
static struct hlsl_block *make_block(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr)
{
struct hlsl_block *block;
@@ -2186,7 +2170,7 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v)
"Target profile doesn't support objects as struct members in uniform variables.");
}
- if ((func = hlsl_get_func_decl(ctx, var->name)))
+ if ((func = hlsl_get_first_func_decl(ctx, var->name)))
{
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
"'%s' is already defined as a function.", var->name);
@@ -2341,56 +2325,27 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var
return initializers;
}
-struct find_function_call_args
-{
- struct hlsl_ctx *ctx;
- const struct parse_initializer *params;
- struct hlsl_ir_function_decl *decl;
- unsigned int compatible_overloads_count;
-};
-
-static void find_function_call_exact(struct rb_entry *entry, void *context)
-{
- struct hlsl_ir_function_decl *decl = RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry);
- struct find_function_call_args *args = context;
- unsigned int i;
-
- if (decl->parameters.count != args->params->args_count)
- return;
-
- for (i = 0; i < decl->parameters.count; ++i)
- {
- if (!hlsl_types_are_equal(decl->parameters.vars[i]->data_type, args->params->args[i]->data_type))
- return;
- }
- args->decl = decl;
-}
-
-static void find_function_call_compatible(struct rb_entry *entry, void *context)
+static bool func_is_compatible_match(struct hlsl_ctx *ctx,
+ const struct hlsl_ir_function_decl *decl, const struct parse_initializer *args)
{
- struct hlsl_ir_function_decl *decl = RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry);
- struct find_function_call_args *args = context;
unsigned int i;
- if (decl->parameters.count != args->params->args_count)
- return;
+ if (decl->parameters.count != args->args_count)
+ return false;
for (i = 0; i < decl->parameters.count; ++i)
{
- if (!implicit_compatible_data_types(args->ctx, args->params->args[i]->data_type,
- decl->parameters.vars[i]->data_type))
- return;
+ if (!implicit_compatible_data_types(ctx, args->args[i]->data_type, decl->parameters.vars[i]->data_type))
+ return false;
}
-
- args->compatible_overloads_count++;
- args->decl = decl;
+ return true;
}
static struct hlsl_ir_function_decl *find_function_call(struct hlsl_ctx *ctx,
- const char *name, const struct parse_initializer *params,
+ const char *name, const struct parse_initializer *args,
const struct vkd3d_shader_location *loc)
{
- struct find_function_call_args args = {.ctx = ctx, .params = params};
+ struct hlsl_ir_function_decl *decl, *compatible_match = NULL;
struct hlsl_ir_function *func;
struct rb_entry *entry;
@@ -2398,16 +2353,20 @@ static struct hlsl_ir_function_decl *find_function_call(struct hlsl_ctx *ctx,
return NULL;
func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry);
- rb_for_each_entry(&func->overloads, find_function_call_exact, &args);
- if (!args.decl)
+ LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry)
{
- rb_for_each_entry(&func->overloads, find_function_call_compatible, &args);
- if (args.compatible_overloads_count > 1)
+ if (func_is_compatible_match(ctx, decl, args))
{
- hlsl_fixme(ctx, loc, "Prioritize between multiple compatible function overloads.");
+ if (compatible_match)
+ {
+ hlsl_fixme(ctx, loc, "Prioritize between multiple compatible function overloads.");
+ break;
+ }
+ compatible_match = decl;
}
}
- return args.decl;
+
+ return compatible_match;
}
static struct hlsl_ir_node *hlsl_new_void_expr(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc)
@@ -2749,6 +2708,17 @@ static bool intrinsic_asuint(struct hlsl_ctx *ctx,
return add_expr(ctx, params->instrs, HLSL_OP1_REINTERPRET, operands, data_type, loc);
}
+static bool intrinsic_ceil(struct hlsl_ctx *ctx,
+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
+{
+ struct hlsl_ir_node *arg;
+
+ if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc)))
+ return false;
+
+ return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_CEIL, arg, loc);
+}
+
static bool intrinsic_clamp(struct hlsl_ctx *ctx,
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
{
@@ -3547,7 +3517,7 @@ static bool intrinsic_tan(struct hlsl_ctx *ctx,
static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *params,
const struct vkd3d_shader_location *loc, const char *name, enum hlsl_sampler_dim dim)
{
- struct hlsl_resource_load_params load_params = {.type = HLSL_RESOURCE_SAMPLE};
+ struct hlsl_resource_load_params load_params = { 0 };
const struct hlsl_type *sampler_type;
struct hlsl_ir_node *coords, *load;
@@ -3576,10 +3546,74 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *
hlsl_release_string_buffer(ctx, string);
}
- if (!(coords = add_implicit_conversion(ctx, params->instrs, params->args[1],
- hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, hlsl_sampler_dim_count(dim)), loc)))
+ if (!strcmp(name, "tex2Dlod"))
{
- return false;
+ struct hlsl_ir_node *lod, *c;
+
+ load_params.type = HLSL_RESOURCE_SAMPLE_LOD;
+
+ if (!(c = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), hlsl_sampler_dim_count(dim), params->args[1], loc)))
+ return false;
+ hlsl_block_add_instr(params->instrs, c);
+
+ if (!(coords = add_implicit_conversion(ctx, params->instrs, c, hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT,
+ hlsl_sampler_dim_count(dim)), loc)))
+ {
+ return false;
+ }
+
+ if (!(lod = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(W, W, W, W), 1, params->args[1], loc)))
+ return false;
+ hlsl_block_add_instr(params->instrs, lod);
+
+ if (!(load_params.lod = add_implicit_conversion(ctx, params->instrs, lod,
+ hlsl_get_scalar_type(ctx, HLSL_TYPE_FLOAT), loc)))
+ {
+ return false;
+ }
+ }
+ else if (!strcmp(name, "tex2Dproj")
+ || !strcmp(name, "tex3Dproj")
+ || !strcmp(name, "texCUBEproj"))
+ {
+ if (!(coords = add_implicit_conversion(ctx, params->instrs, params->args[1],
+ hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4), loc)))
+ {
+ return false;
+ }
+
+ if (shader_profile_version_ge(ctx, 4, 0))
+ {
+ unsigned int count = hlsl_sampler_dim_count(dim);
+ struct hlsl_ir_node *divisor;
+
+ if (!(divisor = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(W, W, W, W), count, coords, loc)))
+ return false;
+ hlsl_block_add_instr(params->instrs, divisor);
+
+ if (!(coords = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), count, coords, loc)))
+ return false;
+ hlsl_block_add_instr(params->instrs, coords);
+
+ if (!(coords = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_DIV, coords, divisor, loc)))
+ return false;
+
+ load_params.type = HLSL_RESOURCE_SAMPLE;
+ }
+ else
+ {
+ load_params.type = HLSL_RESOURCE_SAMPLE_PROJ;
+ }
+ }
+ else
+ {
+ load_params.type = HLSL_RESOURCE_SAMPLE;
+
+ if (!(coords = add_implicit_conversion(ctx, params->instrs, params->args[1],
+ hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, hlsl_sampler_dim_count(dim)), loc)))
+ {
+ return false;
+ }
}
/* tex1D() functions never produce 1D resource declarations. For newer profiles half offset
@@ -3638,18 +3672,42 @@ static bool intrinsic_tex2D(struct hlsl_ctx *ctx,
return intrinsic_tex(ctx, params, loc, "tex2D", HLSL_SAMPLER_DIM_2D);
}
+static bool intrinsic_tex2Dlod(struct hlsl_ctx *ctx,
+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
+{
+ return intrinsic_tex(ctx, params, loc, "tex2Dlod", HLSL_SAMPLER_DIM_2D);
+}
+
+static bool intrinsic_tex2Dproj(struct hlsl_ctx *ctx,
+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
+{
+ return intrinsic_tex(ctx, params, loc, "tex2Dproj", HLSL_SAMPLER_DIM_2D);
+}
+
static bool intrinsic_tex3D(struct hlsl_ctx *ctx,
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
{
return intrinsic_tex(ctx, params, loc, "tex3D", HLSL_SAMPLER_DIM_3D);
}
+static bool intrinsic_tex3Dproj(struct hlsl_ctx *ctx,
+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
+{
+ return intrinsic_tex(ctx, params, loc, "tex3Dproj", HLSL_SAMPLER_DIM_3D);
+}
+
static bool intrinsic_texCUBE(struct hlsl_ctx *ctx,
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
{
return intrinsic_tex(ctx, params, loc, "texCUBE", HLSL_SAMPLER_DIM_CUBE);
}
+static bool intrinsic_texCUBEproj(struct hlsl_ctx *ctx,
+ const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
+{
+ return intrinsic_tex(ctx, params, loc, "texCUBEproj", HLSL_SAMPLER_DIM_CUBE);
+}
+
static bool intrinsic_transpose(struct hlsl_ctx *ctx,
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
{
@@ -3780,6 +3838,7 @@ intrinsic_functions[] =
{"any", 1, true, intrinsic_any},
{"asfloat", 1, true, intrinsic_asfloat},
{"asuint", -1, true, intrinsic_asuint},
+ {"ceil", 1, true, intrinsic_ceil},
{"clamp", 3, true, intrinsic_clamp},
{"clip", 1, true, intrinsic_clip},
{"cos", 1, true, intrinsic_cos},
@@ -3822,8 +3881,12 @@ intrinsic_functions[] =
{"tan", 1, true, intrinsic_tan},
{"tex1D", -1, false, intrinsic_tex1D},
{"tex2D", -1, false, intrinsic_tex2D},
+ {"tex2Dlod", 2, false, intrinsic_tex2Dlod},
+ {"tex2Dproj", 2, false, intrinsic_tex2Dproj},
{"tex3D", -1, false, intrinsic_tex3D},
+ {"tex3Dproj", 2, false, intrinsic_tex3Dproj},
{"texCUBE", -1, false, intrinsic_texCUBE},
+ {"texCUBEproj", 2, false, intrinsic_texCUBEproj},
{"transpose", 1, true, intrinsic_transpose},
{"trunc", 1, true, intrinsic_trunc},
};
@@ -5365,7 +5428,7 @@ func_prototype_no_attrs:
hlsl_error(ctx, &@5, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION,
"packoffset() is not allowed on functions.");
- if (($$.decl = get_func_decl(&ctx->functions, $3, &$5)))
+ if (($$.decl = hlsl_get_func_decl(ctx, $3, &$5)))
{
const struct hlsl_func_parameters *params = &$$.decl->parameters;
size_t i;
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
index 6eac5d490c3..598d6c66eb2 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
@@ -2419,6 +2419,7 @@ static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *in
case HLSL_RESOURCE_SAMPLE:
case HLSL_RESOURCE_SAMPLE_LOD:
case HLSL_RESOURCE_SAMPLE_LOD_BIAS:
+ case HLSL_RESOURCE_SAMPLE_PROJ:
break;
}
if (load->sampler.var)
@@ -2685,10 +2686,68 @@ static bool lower_round(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct
return true;
}
+/* Lower CEIL to FRC */
+static bool lower_ceil(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
+{
+ struct hlsl_ir_node *arg, *neg, *sum, *frc;
+ struct hlsl_ir_expr *expr;
+
+ if (instr->type != HLSL_IR_EXPR)
+ return false;
+
+ expr = hlsl_ir_expr(instr);
+ arg = expr->operands[0].node;
+ if (expr->op != HLSL_OP1_CEIL)
+ return false;
+
+ if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, arg, &instr->loc)))
+ return false;
+ hlsl_block_add_instr(block, neg);
+
+ if (!(frc = hlsl_new_unary_expr(ctx, HLSL_OP1_FRACT, neg, &instr->loc)))
+ return false;
+ hlsl_block_add_instr(block, frc);
+
+ if (!(sum = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, frc, arg)))
+ return false;
+ hlsl_block_add_instr(block, sum);
+
+ return true;
+}
+
+/* Lower FLOOR to FRC */
+static bool lower_floor(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
+{
+ struct hlsl_ir_node *arg, *neg, *sum, *frc;
+ struct hlsl_ir_expr *expr;
+
+ if (instr->type != HLSL_IR_EXPR)
+ return false;
+
+ expr = hlsl_ir_expr(instr);
+ arg = expr->operands[0].node;
+ if (expr->op != HLSL_OP1_FLOOR)
+ return false;
+
+ if (!(frc = hlsl_new_unary_expr(ctx, HLSL_OP1_FRACT, arg, &instr->loc)))
+ return false;
+ hlsl_block_add_instr(block, frc);
+
+ if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, frc, &instr->loc)))
+ return false;
+ hlsl_block_add_instr(block, neg);
+
+ if (!(sum = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, neg, arg)))
+ return false;
+ hlsl_block_add_instr(block, sum);
+
+ return true;
+}
+
/* Use 'movc' for the ternary operator. */
static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
{
- struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS], *replacement;
+ struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = { 0 }, *replacement;
struct hlsl_ir_node *zero, *cond, *first, *second;
struct hlsl_constant_value zero_value = { 0 };
struct hlsl_ir_expr *expr;
@@ -2705,28 +2764,54 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru
first = expr->operands[1].node;
second = expr->operands[2].node;
- if (cond->data_type->base_type == HLSL_TYPE_FLOAT)
+ if (ctx->profile->major_version < 4 && ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL)
{
- if (!(zero = hlsl_new_constant(ctx, cond->data_type, &zero_value, &instr->loc)))
+ struct hlsl_ir_node *abs, *neg;
+
+ if (!(abs = hlsl_new_unary_expr(ctx, HLSL_OP1_ABS, cond, &instr->loc)))
return false;
- hlsl_block_add_instr(block, zero);
+ hlsl_block_add_instr(block, abs);
+
+ if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, abs, &instr->loc)))
+ return false;
+ hlsl_block_add_instr(block, neg);
+
+ operands[0] = neg;
+ operands[1] = second;
+ operands[2] = first;
+ if (!(replacement = hlsl_new_expr(ctx, HLSL_OP3_CMP, operands, first->data_type, &instr->loc)))
+ return false;
+ }
+ else if (ctx->profile->major_version < 4 && ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX)
+ {
+ hlsl_fixme(ctx, &instr->loc, "Ternary operator is not implemented for %s profile.", ctx->profile->name);
+ return false;
+ }
+ else
+ {
+ if (cond->data_type->base_type == HLSL_TYPE_FLOAT)
+ {
+ if (!(zero = hlsl_new_constant(ctx, cond->data_type, &zero_value, &instr->loc)))
+ return false;
+ hlsl_block_add_instr(block, zero);
+
+ operands[0] = zero;
+ operands[1] = cond;
+ type = cond->data_type;
+ type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_BOOL, type->dimx, type->dimy);
+ if (!(cond = hlsl_new_expr(ctx, HLSL_OP2_NEQUAL, operands, type, &instr->loc)))
+ return false;
+ hlsl_block_add_instr(block, cond);
+ }
memset(operands, 0, sizeof(operands));
- operands[0] = zero;
- operands[1] = cond;
- type = cond->data_type;
- type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_BOOL, type->dimx, type->dimy);
- if (!(cond = hlsl_new_expr(ctx, HLSL_OP2_NEQUAL, operands, type, &instr->loc)))
+ operands[0] = cond;
+ operands[1] = first;
+ operands[2] = second;
+ if (!(replacement = hlsl_new_expr(ctx, HLSL_OP3_MOVC, operands, first->data_type, &instr->loc)))
return false;
- hlsl_block_add_instr(block, cond);
}
- memset(operands, 0, sizeof(operands));
- operands[0] = cond;
- operands[1] = first;
- operands[2] = second;
- if (!(replacement = hlsl_new_expr(ctx, HLSL_OP3_MOVC, operands, first->data_type, &instr->loc)))
- return false;
hlsl_block_add_instr(block, replacement);
return true;
}
@@ -3193,21 +3278,17 @@ static unsigned int index_instructions(struct hlsl_block *block, unsigned int in
return index;
}
-static void dump_function_decl(struct rb_entry *entry, void *context)
-{
- struct hlsl_ir_function_decl *func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function_decl, entry);
- struct hlsl_ctx *ctx = context;
-
- if (func->has_body)
- hlsl_dump_function(ctx, func);
-}
-
static void dump_function(struct rb_entry *entry, void *context)
{
struct hlsl_ir_function *func = RB_ENTRY_VALUE(entry, struct hlsl_ir_function, entry);
+ struct hlsl_ir_function_decl *decl;
struct hlsl_ctx *ctx = context;
- rb_for_each_entry(&func->overloads, dump_function_decl, ctx);
+ LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry)
+ {
+ if (decl->has_body)
+ hlsl_dump_function(ctx, decl);
+ }
}
static bool mark_indexable_vars(struct hlsl_ctx *ctx, struct hlsl_deref *deref,
@@ -3556,13 +3637,19 @@ static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_a
static bool is_range_available(const struct register_allocator *allocator,
unsigned int first_write, unsigned int last_read, uint32_t reg_idx, unsigned int reg_size)
{
+ unsigned int last_reg_mask = (1u << (reg_size % 4)) - 1;
+ unsigned int writemask;
uint32_t i;
for (i = 0; i < (reg_size / 4); ++i)
{
- if (get_available_writemask(allocator, first_write, last_read, reg_idx + i) != VKD3DSP_WRITEMASK_ALL)
+ writemask = get_available_writemask(allocator, first_write, last_read, reg_idx + i);
+ if (writemask != VKD3DSP_WRITEMASK_ALL)
return false;
}
+ writemask = get_available_writemask(allocator, first_write, last_read, reg_idx + (reg_size / 4));
+ if ((writemask & last_reg_mask) != last_reg_mask)
+ return false;
return true;
}
@@ -3581,6 +3668,8 @@ static struct hlsl_reg allocate_range(struct hlsl_ctx *ctx, struct register_allo
for (i = 0; i < reg_size / 4; ++i)
record_allocation(ctx, allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, first_write, last_read);
+ if (reg_size % 4)
+ record_allocation(ctx, allocator, reg_idx + (reg_size / 4), (1u << (reg_size % 4)) - 1, first_write, last_read);
ret.id = reg_idx;
ret.allocation_size = align(reg_size, 4) / 4;
@@ -4810,14 +4899,15 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
hlsl_transform_ir(ctx, track_object_components_usage, body, NULL);
sort_synthetic_separated_samplers_first(ctx);
- if (profile->major_version >= 4)
- lower_ir(ctx, lower_ternary, body);
+ lower_ir(ctx, lower_ternary, body);
if (profile->major_version < 4)
{
lower_ir(ctx, lower_division, body);
lower_ir(ctx, lower_sqrt, body);
lower_ir(ctx, lower_dot, body);
lower_ir(ctx, lower_round, body);
+ lower_ir(ctx, lower_ceil, body);
+ lower_ir(ctx, lower_floor, body);
}
if (profile->major_version < 2)
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c
index 64629dc2959..b76b1fce507 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c
@@ -228,6 +228,32 @@ static bool fold_cast(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
return true;
}
+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;
+ unsigned int k;
+
+ assert(type == src->node.data_type->base_type);
+
+ for (k = 0; k < dst_type->dimx; ++k)
+ {
+ switch (type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ dst->u[k].f = ceilf(src->value.u[k].f);
+ break;
+
+ default:
+ FIXME("Fold 'ceil' for type %s.\n", debug_hlsl_type(ctx, dst_type));
+ return false;
+ }
+ }
+
+ return true;
+}
+
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)
{
@@ -254,6 +280,32 @@ static bool fold_exp2(struct hlsl_ctx *ctx, struct hlsl_constant_value *dst,
return true;
}
+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;
+ unsigned int k;
+
+ assert(type == src->node.data_type->base_type);
+
+ for (k = 0; k < dst_type->dimx; ++k)
+ {
+ switch (type)
+ {
+ case HLSL_TYPE_FLOAT:
+ case HLSL_TYPE_HALF:
+ dst->u[k].f = floorf(src->value.u[k].f);
+ break;
+
+ default:
+ FIXME("Fold 'floor' for type %s.\n", debug_hlsl_type(ctx, dst_type));
+ return false;
+ }
+ }
+
+ return true;
+}
+
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)
{
@@ -1229,10 +1281,18 @@ bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
success = fold_cast(ctx, &res, instr->data_type, arg1);
break;
+ case HLSL_OP1_CEIL:
+ success = fold_ceil(ctx, &res, instr->data_type, arg1);
+ break;
+
case HLSL_OP1_EXP2:
success = fold_exp2(ctx, &res, instr->data_type, arg1);
break;
+ case HLSL_OP1_FLOOR:
+ success = fold_floor(ctx, &res, instr->data_type, arg1);
+ break;
+
case HLSL_OP1_FRACT:
success = fold_fract(ctx, &res, instr->data_type, arg1);
break;
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
index 758b594b330..2a334399441 100644
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
@@ -62,17 +62,7 @@ static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_i
reg = (struct vkd3d_shader_register *)&ins->src[i].reg;
if (shader_register_is_phase_instance_id(reg))
{
- reg->type = VKD3DSPR_IMMCONST;
- reg->precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT;
- reg->non_uniform = false;
- reg->idx[0].offset = ~0u;
- reg->idx[0].rel_addr = NULL;
- reg->idx[1].offset = ~0u;
- reg->idx[1].rel_addr = NULL;
- reg->idx[2].offset = ~0u;
- reg->idx[2].rel_addr = NULL;
- reg->idx_count = 0;
- reg->dimension = VSIR_DIMENSION_SCALAR;
+ vsir_register_init(reg, VKD3DSPR_IMMCONST, reg->data_type, 0);
reg->u.immconst_uint[0] = instance_id;
continue;
}
@@ -449,7 +439,8 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p
shader_dst_param_io_init(param, e, VKD3DSPR_INPUT, 2);
param->reg.idx[0].offset = input_control_point_count;
- param->reg.idx[1].offset = i;
+ param->reg.idx[1].offset = e->register_index;
+ param->write_mask = e->mask;
++ins;
}
@@ -827,12 +818,6 @@ static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map
return true;
}
-static bool sysval_semantic_is_tess_factor(enum vkd3d_shader_sysval_semantic sysval_semantic)
-{
- return sysval_semantic >= VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE
- && sysval_semantic <= VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN;
-}
-
static unsigned int shader_register_normalise_arrayed_addressing(struct vkd3d_shader_register *reg,
unsigned int id_idx, unsigned int register_index)
{
@@ -881,11 +866,13 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par
else if (reg->type == VKD3DSPR_OUTPUT || dst_param->reg.type == VKD3DSPR_COLOROUT)
{
signature = normaliser->output_signature;
+ reg->type = VKD3DSPR_OUTPUT;
dcl_params = normaliser->output_dcl_params;
}
else if (dst_param->reg.type == VKD3DSPR_INCONTROLPOINT || dst_param->reg.type == VKD3DSPR_INPUT)
{
signature = normaliser->input_signature;
+ reg->type = VKD3DSPR_INPUT;
dcl_params = normaliser->input_dcl_params;
}
else
@@ -933,7 +920,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par
id_idx = 1;
}
- if ((e->register_count > 1 || sysval_semantic_is_tess_factor(e->sysval_semantic)))
+ if ((e->register_count > 1 || vsir_sysval_semantic_is_tess_factor(e->sysval_semantic)))
{
if (is_io_dcl)
{
@@ -985,15 +972,13 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par
signature = normaliser->patch_constant_signature;
break;
case VKD3DSPR_INCONTROLPOINT:
- if (normaliser->shader_type == VKD3D_SHADER_TYPE_HULL)
- reg->type = VKD3DSPR_INPUT;
+ reg->type = VKD3DSPR_INPUT;
/* fall through */
case VKD3DSPR_INPUT:
signature = normaliser->input_signature;
break;
case VKD3DSPR_OUTCONTROLPOINT:
- if (normaliser->shader_type == VKD3D_SHADER_TYPE_HULL)
- reg->type = VKD3DSPR_OUTPUT;
+ reg->type = VKD3DSPR_OUTPUT;
/* fall through */
case VKD3DSPR_OUTPUT:
signature = normaliser->output_signature;
@@ -1008,7 +993,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par
element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask);
e = &signature->elements[element_idx];
- if ((e->register_count > 1 || sysval_semantic_is_tess_factor(e->sysval_semantic)))
+ if ((e->register_count > 1 || vsir_sysval_semantic_is_tess_factor(e->sysval_semantic)))
id_idx = shader_register_normalise_arrayed_addressing(reg, id_idx, e->register_index);
reg->idx[id_idx].offset = element_idx;
reg->idx_count = id_idx + 1;
@@ -1300,9 +1285,9 @@ static void remove_dead_code(struct vkd3d_shader_parser *parser)
{
if (depth > 0)
{
- vkd3d_shader_instruction_make_nop(ins);
if (ins->handler_idx != VKD3DSIH_ELSE)
--depth;
+ vkd3d_shader_instruction_make_nop(ins);
}
else
{
@@ -1477,6 +1462,12 @@ struct validation_context
struct vkd3d_shader_parser *parser;
size_t instruction_idx;
bool dcl_temps_found;
+ unsigned int temp_count;
+ enum vkd3d_shader_opcode phase;
+
+ enum vkd3d_shader_opcode *blocks;
+ size_t depth;
+ size_t blocks_capacity;
};
static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *ctx,
@@ -1492,13 +1483,23 @@ static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *c
va_end(args);
vkd3d_shader_parser_error(ctx->parser, error, "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer);
+ ERR("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer);
vkd3d_string_buffer_cleanup(&buf);
}
+static void vsir_validate_src_param(struct validation_context *ctx,
+ const struct vkd3d_shader_src_param *src);
+
static void vsir_validate_register(struct validation_context *ctx,
const struct vkd3d_shader_register *reg)
{
+ unsigned int i, temp_count = ctx->temp_count;
+
+ /* SM1-3 shaders do not include a DCL_TEMPS instruction. */
+ if (ctx->parser->shader_version.major <= 3)
+ temp_count = ctx->parser->shader_desc.temp_count;
+
if (reg->type >= VKD3DSPR_COUNT)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, "Invalid register type %#x.",
reg->type);
@@ -1519,6 +1520,13 @@ static void vsir_validate_register(struct validation_context *ctx,
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid register index count %u.",
reg->idx_count);
+ for (i = 0; i < min(reg->idx_count, ARRAY_SIZE(reg->idx)); ++i)
+ {
+ const struct vkd3d_shader_src_param *param = reg->idx[i].rel_addr;
+ if (reg->idx[i].rel_addr)
+ vsir_validate_src_param(ctx, param);
+ }
+
switch (reg->type)
{
case VKD3DSPR_TEMP:
@@ -1529,9 +1537,27 @@ static void vsir_validate_register(struct validation_context *ctx,
if (reg->idx_count >= 1 && reg->idx[0].rel_addr)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Non-NULL relative address for a TEMP register.");
- if (reg->idx_count >= 1 && reg->idx[0].offset >= ctx->parser->shader_desc.temp_count)
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "TEMP register index %u exceeds the declared count %u.",
- reg->idx[0].offset, ctx->parser->shader_desc.temp_count);
+ if (reg->idx_count >= 1 && reg->idx[0].offset >= temp_count)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "TEMP register index %u exceeds the maximum count %u.",
+ reg->idx[0].offset, temp_count);
+ break;
+
+ case VKD3DSPR_NULL:
+ if (reg->idx_count != 0)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a NULL register.",
+ reg->idx_count);
+ break;
+
+ case VKD3DSPR_IMMCONST:
+ if (reg->idx_count != 0)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a IMMCONST register.",
+ reg->idx_count);
+ break;
+
+ case VKD3DSPR_IMMCONST64:
+ if (reg->idx_count != 0)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a IMMCONST64 register.",
+ reg->idx_count);
break;
default:
@@ -1620,19 +1646,123 @@ static void vsir_validate_instruction(struct validation_context *ctx)
instruction->handler_idx);
}
+ switch (instruction->handler_idx)
+ {
+ case VKD3DSIH_HS_DECLS:
+ case VKD3DSIH_HS_CONTROL_POINT_PHASE:
+ case VKD3DSIH_HS_FORK_PHASE:
+ case VKD3DSIH_HS_JOIN_PHASE:
+ vsir_validate_dst_count(ctx, instruction, 0);
+ vsir_validate_src_count(ctx, instruction, 0);
+ if (ctx->parser->shader_version.type != VKD3D_SHADER_TYPE_HULL)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Phase instruction %#x is only valid in a hull shader.",
+ instruction->handler_idx);
+ if (ctx->depth != 0)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "Phase instruction %#x must appear to top level.",
+ instruction->handler_idx);
+ ctx->phase = instruction->handler_idx;
+ ctx->dcl_temps_found = false;
+ ctx->temp_count = 0;
+ return;
+
+ default:
+ break;
+ }
+
+ if (ctx->parser->shader_version.type == VKD3D_SHADER_TYPE_HULL &&
+ ctx->phase == VKD3DSIH_INVALID)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Instruction %#x appear before any phase instruction in a hull shader.",
+ instruction->handler_idx);
+
switch (instruction->handler_idx)
{
case VKD3DSIH_DCL_TEMPS:
vsir_validate_dst_count(ctx, instruction, 0);
vsir_validate_src_count(ctx, instruction, 0);
- /* TODO Check that each phase in a hull shader has at most
- * one occurrence. */
- if (ctx->dcl_temps_found && ctx->parser->shader_version.type != VKD3D_SHADER_TYPE_HULL)
+ if (ctx->dcl_temps_found)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS, "Duplicate DCL_TEMPS instruction.");
- ctx->dcl_temps_found = true;
- if (instruction->declaration.count != ctx->parser->shader_desc.temp_count)
- validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS, "Invalid DCL_TEMPS count %u, expected %u.",
+ if (instruction->declaration.count > ctx->parser->shader_desc.temp_count)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS, "Invalid DCL_TEMPS count %u, expected at most %u.",
instruction->declaration.count, ctx->parser->shader_desc.temp_count);
+ ctx->dcl_temps_found = true;
+ ctx->temp_count = instruction->declaration.count;
+ break;
+
+ case VKD3DSIH_IF:
+ vsir_validate_dst_count(ctx, instruction, 0);
+ vsir_validate_src_count(ctx, instruction, 1);
+ if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
+ return;
+ ctx->blocks[ctx->depth++] = instruction->handler_idx;
+ break;
+
+ case VKD3DSIH_ELSE:
+ vsir_validate_dst_count(ctx, instruction, 0);
+ vsir_validate_src_count(ctx, instruction, 0);
+ if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_IF)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "ELSE instruction doesn't terminate IF block.");
+ else
+ ctx->blocks[ctx->depth - 1] = instruction->handler_idx;
+ break;
+
+ case VKD3DSIH_ENDIF:
+ vsir_validate_dst_count(ctx, instruction, 0);
+ vsir_validate_src_count(ctx, instruction, 0);
+ if (ctx->depth == 0 || (ctx->blocks[ctx->depth - 1] != VKD3DSIH_IF && ctx->blocks[ctx->depth - 1] != VKD3DSIH_ELSE))
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "ENDIF instruction doesn't terminate IF/ELSE block.");
+ else
+ --ctx->depth;
+ break;
+
+ case VKD3DSIH_LOOP:
+ vsir_validate_dst_count(ctx, instruction, 0);
+ vsir_validate_src_count(ctx, instruction, 0);
+ if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
+ return;
+ ctx->blocks[ctx->depth++] = instruction->handler_idx;
+ break;
+
+ case VKD3DSIH_ENDLOOP:
+ vsir_validate_dst_count(ctx, instruction, 0);
+ vsir_validate_src_count(ctx, instruction, 0);
+ if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_LOOP)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "ENDLOOP instruction doesn't terminate LOOP block.");
+ else
+ --ctx->depth;
+ break;
+
+ case VKD3DSIH_REP:
+ vsir_validate_dst_count(ctx, instruction, 0);
+ vsir_validate_src_count(ctx, instruction, 1);
+ if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
+ return;
+ ctx->blocks[ctx->depth++] = instruction->handler_idx;
+ break;
+
+ case VKD3DSIH_ENDREP:
+ vsir_validate_dst_count(ctx, instruction, 0);
+ vsir_validate_src_count(ctx, instruction, 0);
+ if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_REP)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "ENDREP instruction doesn't terminate REP block.");
+ else
+ --ctx->depth;
+ break;
+
+ case VKD3DSIH_SWITCH:
+ vsir_validate_dst_count(ctx, instruction, 0);
+ vsir_validate_src_count(ctx, instruction, 1);
+ if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
+ return;
+ ctx->blocks[ctx->depth++] = instruction->handler_idx;
+ break;
+
+ case VKD3DSIH_ENDSWITCH:
+ vsir_validate_dst_count(ctx, instruction, 0);
+ vsir_validate_src_count(ctx, instruction, 0);
+ if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_SWITCH)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "ENDSWITCH instruction doesn't terminate SWITCH block.");
+ else
+ --ctx->depth;
break;
default:
@@ -1642,11 +1772,20 @@ static void vsir_validate_instruction(struct validation_context *ctx)
void vsir_validate(struct vkd3d_shader_parser *parser)
{
- struct validation_context ctx = { .parser = parser };
+ struct validation_context ctx =
+ {
+ .parser = parser,
+ .phase = VKD3DSIH_INVALID,
+ };
if (!(parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION))
return;
for (ctx.instruction_idx = 0; ctx.instruction_idx < parser->instructions.count; ++ctx.instruction_idx)
vsir_validate_instruction(&ctx);
+
+ if (ctx.depth != 0)
+ validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "%zu nested blocks were not closed.", ctx.depth);
+
+ free(ctx.blocks);
}
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
index a25edb64491..d2621ffa1fd 100644
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
@@ -1150,6 +1150,20 @@ static uint32_t vkd3d_spirv_get_op_type_pointer(struct vkd3d_spirv_builder *buil
vkd3d_spirv_build_op_type_pointer);
}
+static uint32_t vkd3d_spirv_build_op_constant_bool(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t value)
+{
+ return vkd3d_spirv_build_op_tr(builder, &builder->global_stream,
+ value ? SpvOpConstantTrue : SpvOpConstantFalse, result_type);
+}
+
+static uint32_t vkd3d_spirv_get_op_constant_bool(struct vkd3d_spirv_builder *builder,
+ uint32_t result_type, uint32_t value)
+{
+ return vkd3d_spirv_build_once2(builder, value ? SpvOpConstantTrue : SpvOpConstantFalse, result_type, value,
+ vkd3d_spirv_build_op_constant_bool);
+}
+
/* Types larger than 32-bits are not supported. */
static uint32_t vkd3d_spirv_build_op_constant(struct vkd3d_spirv_builder *builder,
uint32_t result_type, uint32_t value)
@@ -1802,6 +1816,8 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder
break;
case VKD3D_DATA_DOUBLE:
return vkd3d_spirv_get_op_type_float(builder, 64);
+ case VKD3D_DATA_BOOL:
+ return vkd3d_spirv_get_op_type_bool(builder);
default:
FIXME("Unhandled data type %#x.\n", data_type);
return 0;
@@ -2125,14 +2141,22 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol,
symbol->type = VKD3D_SYMBOL_REGISTER;
memset(&symbol->key, 0, sizeof(symbol->key));
symbol->key.reg.type = reg->type;
- if (vkd3d_shader_register_is_input(reg) || vkd3d_shader_register_is_output(reg)
- || vkd3d_shader_register_is_patch_constant(reg))
+
+ switch (reg->type)
{
- symbol->key.reg.idx = reg->idx_count ? reg->idx[reg->idx_count - 1].offset : ~0u;
- assert(!reg->idx_count || symbol->key.reg.idx != ~0u);
+ case VKD3DSPR_INPUT:
+ case VKD3DSPR_OUTPUT:
+ case VKD3DSPR_PATCHCONST:
+ symbol->key.reg.idx = reg->idx_count ? reg->idx[reg->idx_count - 1].offset : ~0u;
+ assert(!reg->idx_count || symbol->key.reg.idx != ~0u);
+ break;
+
+ case VKD3DSPR_IMMCONSTBUFFER:
+ break;
+
+ default:
+ symbol->key.reg.idx = reg->idx_count ? reg->idx[0].offset : ~0u;
}
- else if (reg->type != VKD3DSPR_IMMCONSTBUFFER)
- symbol->key.reg.idx = reg->idx_count ? reg->idx[0].offset : ~0u;
}
static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol,
@@ -2277,6 +2301,12 @@ struct vkd3d_hull_shader_variables
uint32_t patch_constants_id;
};
+struct ssa_register_info
+{
+ enum vkd3d_data_type data_type;
+ uint32_t id;
+};
+
struct spirv_compiler
{
struct vkd3d_spirv_builder spirv_builder;
@@ -2288,6 +2318,7 @@ struct spirv_compiler
bool strip_debug;
bool ssbo_uavs;
bool uav_read_without_format;
+ SpvExecutionMode fragment_coordinate_origin;
struct rb_tree symbol_table;
uint32_t temp_id;
@@ -2325,7 +2356,6 @@ struct spirv_compiler
uint32_t array_element_mask;
} *output_info;
uint32_t private_output_variable[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */
- uint32_t private_output_variable_array_idx[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */
uint32_t private_output_variable_write_mask[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */
uint32_t epilogue_function_id;
@@ -2350,7 +2380,7 @@ struct spirv_compiler
struct vkd3d_string_buffer_cache string_buffers;
- uint32_t *ssa_register_ids;
+ struct ssa_register_info *ssa_register_info;
unsigned int ssa_register_count;
};
@@ -2399,7 +2429,7 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler)
shader_signature_cleanup(&compiler->output_signature);
shader_signature_cleanup(&compiler->patch_constant_signature);
- vkd3d_free(compiler->ssa_register_ids);
+ vkd3d_free(compiler->ssa_register_info);
vkd3d_free(compiler);
}
@@ -2453,6 +2483,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve
compiler->formatting = VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT
| VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER;
compiler->write_tess_geom_point_size = true;
+ compiler->fragment_coordinate_origin = SpvExecutionModeOriginUpperLeft;
for (i = 0; i < compile_info->option_count; ++i)
{
@@ -2493,6 +2524,15 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve
compiler->write_tess_geom_point_size = option->value;
break;
+ case VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN:
+ if (option->value == VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN_UPPER_LEFT)
+ compiler->fragment_coordinate_origin = SpvExecutionModeOriginUpperLeft;
+ else if (option->value == VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN_LOWER_LEFT)
+ compiler->fragment_coordinate_origin = SpvExecutionModeOriginLowerLeft;
+ else
+ WARN("Ignoring unrecognised value %#x for option %#x.\n", option->value, option->name);
+ break;
+
default:
WARN("Ignoring unrecognised option %#x with value %#x.\n", option->name, option->value);
break;
@@ -2880,6 +2920,13 @@ static uint32_t spirv_compiler_get_constant(struct spirv_compiler *compiler,
case VKD3D_SHADER_COMPONENT_INT:
case VKD3D_SHADER_COMPONENT_FLOAT:
break;
+ case VKD3D_SHADER_COMPONENT_BOOL:
+ if (component_count == 1)
+ return vkd3d_spirv_get_op_constant_bool(builder, type_id, *values);
+ FIXME("Unsupported vector of bool.\n");
+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE,
+ "Vectors of bool type are not supported.");
+ return vkd3d_spirv_get_op_undef(builder, type_id);
default:
FIXME("Unhandled component_type %#x.\n", component_type);
return vkd3d_spirv_get_op_undef(builder, type_id);
@@ -2946,12 +2993,6 @@ static uint32_t spirv_compiler_get_constant_vector(struct spirv_compiler *compil
return spirv_compiler_get_constant(compiler, component_type, component_count, values);
}
-static uint32_t spirv_compiler_get_constant_int_vector(struct spirv_compiler *compiler,
- uint32_t value, unsigned int component_count)
-{
- return spirv_compiler_get_constant_vector(compiler, VKD3D_SHADER_COMPONENT_INT, component_count, value);
-}
-
static uint32_t spirv_compiler_get_constant_uint_vector(struct spirv_compiler *compiler,
uint32_t value, unsigned int component_count)
{
@@ -3013,9 +3054,6 @@ static bool spirv_compiler_get_register_name(char *buffer, unsigned int buffer_s
case VKD3DSPR_INPUT:
snprintf(buffer, buffer_size, "v%u", idx);
break;
- case VKD3DSPR_INCONTROLPOINT:
- snprintf(buffer, buffer_size, "vicp%u", idx);
- break;
case VKD3DSPR_OUTPUT:
snprintf(buffer, buffer_size, "o%u", idx);
break;
@@ -3730,20 +3768,21 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler,
return val_id;
}
-static uint32_t spirv_compiler_get_ssa_register_id(const struct spirv_compiler *compiler,
+static const struct ssa_register_info *spirv_compiler_get_ssa_register_info(const struct spirv_compiler *compiler,
const struct vkd3d_shader_register *reg)
{
assert(reg->idx[0].offset < compiler->ssa_register_count);
assert(reg->idx_count == 1);
- return compiler->ssa_register_ids[reg->idx[0].offset];
+ return &compiler->ssa_register_info[reg->idx[0].offset];
}
-static void spirv_compiler_set_ssa_register_id(const struct spirv_compiler *compiler,
+static void spirv_compiler_set_ssa_register_info(const struct spirv_compiler *compiler,
const struct vkd3d_shader_register *reg, uint32_t val_id)
{
unsigned int i = reg->idx[0].offset;
assert(i < compiler->ssa_register_count);
- compiler->ssa_register_ids[i] = val_id;
+ compiler->ssa_register_info[i].data_type = reg->data_type;
+ compiler->ssa_register_info[i].id = val_id;
}
static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler,
@@ -3751,15 +3790,27 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler
unsigned int swizzle)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ enum vkd3d_shader_component_type reg_component_type;
+ const struct ssa_register_info *ssa;
unsigned int component_idx;
uint32_t type_id, val_id;
- val_id = spirv_compiler_get_ssa_register_id(compiler, reg);
+ ssa = spirv_compiler_get_ssa_register_info(compiler, reg);
+ val_id = ssa->id;
assert(val_id);
assert(vkd3d_swizzle_is_scalar(swizzle));
if (reg->dimension == VSIR_DIMENSION_SCALAR)
+ {
+ reg_component_type = vkd3d_component_type_from_data_type(ssa->data_type);
+ if (component_type != reg_component_type)
+ {
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
+ val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id);
+ }
+
return val_id;
+ }
type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
component_idx = vkd3d_swizzle_get_component(swizzle, 0);
@@ -4002,7 +4053,7 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler,
if (reg->type == VKD3DSPR_SSA)
{
- spirv_compiler_set_ssa_register_id(compiler, reg, val_id);
+ spirv_compiler_set_ssa_register_info(compiler, reg, val_id);
return;
}
@@ -4202,17 +4253,41 @@ static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler,
}
static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler,
- unsigned int component_count, uint32_t val_id)
+ unsigned int component_count, uint32_t val_id, bool signedness)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id, true_id, false_id;
- true_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count);
+ true_id = spirv_compiler_get_constant_uint_vector(compiler, signedness ? 0xffffffff : 1, component_count);
false_id = spirv_compiler_get_constant_uint_vector(compiler, 0, component_count);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count);
return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id);
}
+static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compiler,
+ unsigned int component_count, uint32_t val_id, bool signedness)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, true_id, false_id;
+
+ true_id = spirv_compiler_get_constant_float_vector(compiler, signedness ? -1.0f : 1.0f, component_count);
+ false_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count);
+ return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id);
+}
+
+static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compiler,
+ unsigned int component_count, uint32_t val_id, bool signedness)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ uint32_t type_id, true_id, false_id;
+
+ true_id = spirv_compiler_get_constant_double_vector(compiler, signedness ? -1.0 : 1.0, component_count);
+ false_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_DOUBLE, component_count);
+ return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id);
+}
+
typedef uint32_t (*vkd3d_spirv_builtin_fixup_pfn)(struct spirv_compiler *compiler,
uint32_t val_id);
@@ -4255,7 +4330,7 @@ static uint32_t sv_instance_id_fixup(struct spirv_compiler *compiler,
static uint32_t sv_front_face_fixup(struct spirv_compiler *compiler,
uint32_t front_facing_id)
{
- return spirv_compiler_emit_bool_to_int(compiler, 1, front_facing_id);
+ return spirv_compiler_emit_bool_to_int(compiler, 1, front_facing_id, true);
}
/* frag_coord.w = 1.0f / frag_coord.w */
@@ -4289,47 +4364,41 @@ struct vkd3d_spirv_builtin
*/
static const struct
{
- enum vkd3d_shader_input_sysval_semantic sysval;
+ enum vkd3d_shader_sysval_semantic sysval;
struct vkd3d_spirv_builtin builtin;
enum vkd3d_shader_spirv_environment environment;
}
vkd3d_system_value_builtins[] =
{
- {VKD3D_SIV_VERTEX_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInVertexId},
+ {VKD3D_SHADER_SV_VERTEX_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInVertexId},
VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5},
- {VKD3D_SIV_INSTANCE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInstanceId},
+ {VKD3D_SHADER_SV_INSTANCE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInstanceId},
VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5},
- {VKD3D_SIV_POSITION, {VKD3D_SHADER_COMPONENT_FLOAT, 4, SpvBuiltInPosition}},
- {VKD3D_SIV_VERTEX_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInVertexIndex, sv_vertex_id_fixup}},
- {VKD3D_SIV_INSTANCE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInstanceIndex, sv_instance_id_fixup}},
+ {VKD3D_SHADER_SV_POSITION, {VKD3D_SHADER_COMPONENT_FLOAT, 4, SpvBuiltInPosition}},
+ {VKD3D_SHADER_SV_VERTEX_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInVertexIndex, sv_vertex_id_fixup}},
+ {VKD3D_SHADER_SV_INSTANCE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInInstanceIndex, sv_instance_id_fixup}},
- {VKD3D_SIV_PRIMITIVE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInPrimitiveId}},
+ {VKD3D_SHADER_SV_PRIMITIVE_ID, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInPrimitiveId}},
- {VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInLayer}},
- {VKD3D_SIV_VIEWPORT_ARRAY_INDEX, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInViewportIndex}},
+ {VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInLayer}},
+ {VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX, {VKD3D_SHADER_COMPONENT_INT, 1, SpvBuiltInViewportIndex}},
- {VKD3D_SIV_IS_FRONT_FACE, {VKD3D_SHADER_COMPONENT_BOOL, 1, SpvBuiltInFrontFacing, sv_front_face_fixup}},
+ {VKD3D_SHADER_SV_IS_FRONT_FACE, {VKD3D_SHADER_COMPONENT_BOOL, 1, SpvBuiltInFrontFacing, sv_front_face_fixup}},
- {VKD3D_SIV_SAMPLE_INDEX, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSampleId}},
+ {VKD3D_SHADER_SV_SAMPLE_INDEX, {VKD3D_SHADER_COMPONENT_UINT, 1, SpvBuiltInSampleId}},
- {VKD3D_SIV_CLIP_DISTANCE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInClipDistance, NULL, 1}},
- {VKD3D_SIV_CULL_DISTANCE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInCullDistance, NULL, 1}},
+ {VKD3D_SHADER_SV_CLIP_DISTANCE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInClipDistance, NULL, 1}},
+ {VKD3D_SHADER_SV_CULL_DISTANCE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInCullDistance, NULL, 1}},
- {VKD3D_SIV_QUAD_U0_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 0}},
- {VKD3D_SIV_QUAD_V0_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 1}},
- {VKD3D_SIV_QUAD_U1_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 2}},
- {VKD3D_SIV_QUAD_V1_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 3}},
- {VKD3D_SIV_QUAD_U_INNER_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelInner, NULL, 2, 0}},
- {VKD3D_SIV_QUAD_V_INNER_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelInner, NULL, 2, 1}},
+ {VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4}},
+ {VKD3D_SHADER_SV_TESS_FACTOR_QUADINT, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelInner, NULL, 2}},
- {VKD3D_SIV_TRIANGLE_U_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 0}},
- {VKD3D_SIV_TRIANGLE_V_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 1}},
- {VKD3D_SIV_TRIANGLE_W_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 2}},
- {VKD3D_SIV_TRIANGLE_INNER_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelInner, NULL, 2, 0}},
+ {VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4}},
+ {VKD3D_SHADER_SV_TESS_FACTOR_TRIINT, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelInner, NULL, 2}},
- {VKD3D_SIV_LINE_DENSITY_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 0}},
- {VKD3D_SIV_LINE_DETAIL_TESS_FACTOR, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 1}},
+ {VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 0}},
+ {VKD3D_SHADER_SV_TESS_FACTOR_LINEDET, {VKD3D_SHADER_COMPONENT_FLOAT, 1, SpvBuiltInTessLevelOuter, NULL, 4, 1}},
};
static const struct vkd3d_spirv_builtin vkd3d_pixel_shader_position_builtin =
{
@@ -4393,7 +4462,7 @@ static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *c
}
static const struct vkd3d_spirv_builtin *get_spirv_builtin_for_sysval(
- const struct spirv_compiler *compiler, enum vkd3d_shader_input_sysval_semantic sysval)
+ const struct spirv_compiler *compiler, enum vkd3d_shader_sysval_semantic sysval)
{
enum vkd3d_shader_spirv_environment environment;
unsigned int i;
@@ -4402,7 +4471,7 @@ static const struct vkd3d_spirv_builtin *get_spirv_builtin_for_sysval(
return NULL;
/* In pixel shaders, SV_Position is mapped to SpvBuiltInFragCoord. */
- if (sysval == VKD3D_SIV_POSITION && compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL)
+ if (sysval == VKD3D_SHADER_SV_POSITION && compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL)
return &vkd3d_pixel_shader_position_builtin;
environment = spirv_compiler_get_target_environment(compiler);
@@ -4434,7 +4503,7 @@ static const struct vkd3d_spirv_builtin *get_spirv_builtin_for_register(
}
static const struct vkd3d_spirv_builtin *vkd3d_get_spirv_builtin(const struct spirv_compiler *compiler,
- enum vkd3d_shader_register_type reg_type, enum vkd3d_shader_input_sysval_semantic sysval)
+ enum vkd3d_shader_register_type reg_type, enum vkd3d_shader_sysval_semantic sysval)
{
const struct vkd3d_spirv_builtin *builtin;
@@ -4443,8 +4512,7 @@ static const struct vkd3d_spirv_builtin *vkd3d_get_spirv_builtin(const struct sp
if ((builtin = get_spirv_builtin_for_register(reg_type)))
return builtin;
- if (sysval != VKD3D_SIV_NONE || (reg_type != VKD3DSPR_OUTPUT && reg_type != VKD3DSPR_COLOROUT
- && reg_type != VKD3DSPR_PATCHCONST))
+ if (sysval != VKD3D_SHADER_SV_NONE || (reg_type != VKD3DSPR_OUTPUT && reg_type != VKD3DSPR_PATCHCONST))
FIXME("Unhandled builtin (register type %#x, sysval %#x).\n", reg_type, sysval);
return NULL;
}
@@ -4576,7 +4644,7 @@ static uint32_t spirv_compiler_emit_builtin_variable_v(struct spirv_compiler *co
assert(size_count <= ARRAY_SIZE(sizes));
memcpy(sizes, array_sizes, size_count * sizeof(sizes[0]));
array_sizes = sizes;
- sizes[0] = max(sizes[0], builtin->spirv_array_size);
+ sizes[size_count - 1] = max(sizes[size_count - 1], builtin->spirv_array_size);
id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, storage_class,
builtin->component_type, builtin->component_count, array_sizes, size_count);
@@ -4614,24 +4682,6 @@ static unsigned int shader_signature_next_location(const struct shader_signature
return max_row;
}
-static unsigned int shader_register_get_io_indices(const struct vkd3d_shader_register *reg,
- unsigned int *array_sizes)
-{
- unsigned int i, element_idx;
-
- array_sizes[0] = 0;
- array_sizes[1] = 0;
- element_idx = reg->idx[0].offset;
- for (i = 1; i < reg->idx_count; ++i)
- {
- array_sizes[1] = array_sizes[0];
- array_sizes[0] = element_idx;
- element_idx = reg->idx[i].offset;
- }
-
- return element_idx;
-}
-
static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
const struct vkd3d_shader_dst_param *dst)
{
@@ -4641,8 +4691,8 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
const struct signature_element *signature_element;
const struct shader_signature *shader_signature;
enum vkd3d_shader_component_type component_type;
- enum vkd3d_shader_input_sysval_semantic sysval;
const struct vkd3d_spirv_builtin *builtin;
+ enum vkd3d_shader_sysval_semantic sysval;
unsigned int write_mask, reg_write_mask;
struct vkd3d_symbol *symbol = NULL;
uint32_t val_id, input_id, var_id;
@@ -4660,17 +4710,22 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
shader_signature = reg->type == VKD3DSPR_PATCHCONST
? &compiler->patch_constant_signature : &compiler->input_signature;
- element_idx = shader_register_get_io_indices(reg, array_sizes);
+ element_idx = reg->idx[reg->idx_count - 1].offset;
signature_element = &shader_signature->elements[element_idx];
- sysval = vkd3d_siv_from_sysval(signature_element->sysval_semantic);
+ sysval = signature_element->sysval_semantic;
/* The Vulkan spec does not explicitly forbid passing varyings from the
* TCS to the TES via builtins. However, Mesa doesn't seem to handle it
* well, and we don't actually need them to be in builtins. */
if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN && reg->type != VKD3DSPR_PATCHCONST)
- sysval = VKD3D_SIV_NONE;
+ sysval = VKD3D_SHADER_SV_NONE;
builtin = get_spirv_builtin_for_sysval(compiler, sysval);
+ array_sizes[0] = (reg->type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count);
+ array_sizes[1] = signature_element->register_count;
+ if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic))
+ array_sizes[1] = 0;
+
write_mask = signature_element->mask;
if (builtin)
@@ -4818,29 +4873,6 @@ static void spirv_compiler_emit_input_register(struct spirv_compiler *compiler,
spirv_compiler_emit_register_debug_name(builder, input_id, reg);
}
-static void spirv_compiler_emit_shader_phase_input(struct spirv_compiler *compiler,
- const struct vkd3d_shader_dst_param *dst)
-{
- const struct vkd3d_shader_register *reg = &dst->reg;
-
- switch (reg->type)
- {
- case VKD3DSPR_INPUT:
- case VKD3DSPR_INCONTROLPOINT:
- case VKD3DSPR_PATCHCONST:
- spirv_compiler_emit_input(compiler, dst);
- return;
- case VKD3DSPR_PRIMID:
- spirv_compiler_emit_input_register(compiler, dst);
- return;
- case VKD3DSPR_OUTPOINTID: /* Emitted in spirv_compiler_emit_initial_declarations(). */
- return;
- default:
- FIXME("Unhandled shader phase input register %#x.\n", reg->type);
- return;
- }
-}
-
static unsigned int get_shader_output_swizzle(const struct spirv_compiler *compiler,
unsigned int register_idx)
{
@@ -4905,7 +4937,7 @@ static void spirv_compiler_emit_shader_signature_outputs(struct spirv_compiler *
if (clip_distance_mask)
{
count = vkd3d_popcount(clip_distance_mask);
- builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SIV_CLIP_DISTANCE);
+ builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SHADER_SV_CLIP_DISTANCE);
clip_distance_id = spirv_compiler_emit_builtin_variable(compiler,
builtin, SpvStorageClassOutput, count);
}
@@ -4913,7 +4945,7 @@ static void spirv_compiler_emit_shader_signature_outputs(struct spirv_compiler *
if (cull_distance_mask)
{
count = vkd3d_popcount(cull_distance_mask);
- builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SIV_CULL_DISTANCE);
+ builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SHADER_SV_CULL_DISTANCE);
cull_distance_id = spirv_compiler_emit_builtin_variable(compiler,
builtin, SpvStorageClassOutput, count);
}
@@ -4974,7 +5006,7 @@ static void spirv_compiler_emit_output_register(struct spirv_compiler *compiler,
}
static uint32_t spirv_compiler_emit_shader_phase_builtin_variable(struct spirv_compiler *compiler,
- const struct vkd3d_spirv_builtin *builtin)
+ const struct vkd3d_spirv_builtin *builtin, const unsigned int *array_sizes, unsigned int size_count)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t *variable_id, id;
@@ -4989,7 +5021,7 @@ static uint32_t spirv_compiler_emit_shader_phase_builtin_variable(struct spirv_c
if (variable_id && *variable_id)
return *variable_id;
- id = spirv_compiler_emit_builtin_variable(compiler, builtin, SpvStorageClassOutput, 0);
+ id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, SpvStorageClassOutput, array_sizes, size_count);
if (is_in_fork_or_join_phase(compiler))
vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationPatch, NULL, 0);
@@ -5006,8 +5038,8 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st
const struct signature_element *signature_element;
enum vkd3d_shader_component_type component_type;
const struct shader_signature *shader_signature;
- enum vkd3d_shader_input_sysval_semantic sysval;
const struct vkd3d_spirv_builtin *builtin;
+ enum vkd3d_shader_sysval_semantic sysval;
unsigned int write_mask, reg_write_mask;
bool use_private_variable = false;
struct vkd3d_symbol reg_symbol;
@@ -5021,12 +5053,16 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st
shader_signature = is_patch_constant ? &compiler->patch_constant_signature : &compiler->output_signature;
- element_idx = shader_register_get_io_indices(reg, array_sizes);
+ element_idx = reg->idx[reg->idx_count - 1].offset;
signature_element = &shader_signature->elements[element_idx];
- sysval = vkd3d_siv_from_sysval(signature_element->sysval_semantic);
+ sysval = signature_element->sysval_semantic;
/* Don't use builtins for TCS -> TES varyings. See spirv_compiler_emit_input(). */
if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && !is_patch_constant)
- sysval = VKD3D_SIV_NONE;
+ sysval = VKD3D_SHADER_SV_NONE;
+ array_sizes[0] = (reg->type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count);
+ array_sizes[1] = signature_element->register_count;
+ if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic))
+ array_sizes[1] = 0;
builtin = vkd3d_get_spirv_builtin(compiler, dst->reg.type, sysval);
@@ -5071,7 +5107,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st
else if (builtin)
{
if (spirv_compiler_get_current_shader_phase(compiler))
- id = spirv_compiler_emit_shader_phase_builtin_variable(compiler, builtin);
+ id = spirv_compiler_emit_shader_phase_builtin_variable(compiler, builtin, array_sizes, 2);
else
id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, storage_class, array_sizes, 2);
@@ -5150,16 +5186,15 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st
static uint32_t spirv_compiler_get_output_array_index(struct spirv_compiler *compiler,
const struct signature_element *e)
{
- enum vkd3d_shader_input_sysval_semantic sysval;
+ enum vkd3d_shader_sysval_semantic sysval = e->sysval_semantic;
const struct vkd3d_spirv_builtin *builtin;
- sysval = vkd3d_siv_from_sysval_indexed(e->sysval_semantic, e->semantic_index);
builtin = get_spirv_builtin_for_sysval(compiler, sysval);
switch (sysval)
{
- case VKD3D_SIV_LINE_DETAIL_TESS_FACTOR:
- case VKD3D_SIV_LINE_DENSITY_TESS_FACTOR:
+ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN:
+ case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET:
return builtin->member_idx;
default:
return e->semantic_index;
@@ -5273,7 +5308,6 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler *
STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(param_id));
STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(param_type_id));
- STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(compiler->private_output_variable_array_idx));
STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(compiler->private_output_variable_write_mask));
is_patch_constant = is_in_fork_or_join_phase(compiler);
@@ -5329,7 +5363,6 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler *
vkd3d_spirv_build_op_function_end(builder);
memset(compiler->private_output_variable, 0, sizeof(compiler->private_output_variable));
- memset(compiler->private_output_variable_array_idx, 0, sizeof(compiler->private_output_variable_array_idx));
memset(compiler->private_output_variable_write_mask, 0, sizeof(compiler->private_output_variable_write_mask));
compiler->epilogue_function_id = 0;
}
@@ -5367,7 +5400,7 @@ static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *comp
break;
case VKD3D_SHADER_TYPE_PIXEL:
vkd3d_spirv_set_execution_model(builder, SpvExecutionModelFragment);
- spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeOriginUpperLeft, NULL, 0);
+ spirv_compiler_emit_execution_mode(compiler, compiler->fragment_coordinate_origin, NULL, 0);
break;
case VKD3D_SHADER_TYPE_COMPUTE:
vkd3d_spirv_set_execution_model(builder, SpvExecutionModelGLCompute);
@@ -5451,8 +5484,8 @@ static void spirv_compiler_emit_temps(struct spirv_compiler *compiler, uint32_t
static void spirv_compiler_allocate_ssa_register_ids(struct spirv_compiler *compiler, unsigned int count)
{
- assert(!compiler->ssa_register_ids);
- if (!(compiler->ssa_register_ids = vkd3d_calloc(count, sizeof(*compiler->ssa_register_ids))))
+ assert(!compiler->ssa_register_info);
+ if (!(compiler->ssa_register_info = vkd3d_calloc(count, sizeof(*compiler->ssa_register_info))))
{
ERR("Failed to allocate SSA register value id array, count %u.\n", count);
spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY,
@@ -6111,11 +6144,10 @@ static void spirv_compiler_emit_dcl_input(struct spirv_compiler *compiler,
{
const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst;
- if (spirv_compiler_get_current_shader_phase(compiler))
- spirv_compiler_emit_shader_phase_input(compiler, dst);
- else if (vkd3d_shader_register_is_input(&dst->reg) || dst->reg.type == VKD3DSPR_PATCHCONST)
+ /* OUTPOINTID is handled in spirv_compiler_emit_hull_shader_builtins(). */
+ if (dst->reg.type == VKD3DSPR_INPUT || dst->reg.type == VKD3DSPR_PATCHCONST)
spirv_compiler_emit_input(compiler, dst);
- else
+ else if (dst->reg.type != VKD3DSPR_OUTPOINTID)
spirv_compiler_emit_input_register(compiler, dst);
}
@@ -6130,8 +6162,8 @@ static void spirv_compiler_emit_dcl_output(struct spirv_compiler *compiler,
{
const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst;
- if (vkd3d_shader_register_is_output(&dst->reg)
- || (is_in_fork_or_join_phase(compiler) && vkd3d_shader_register_is_patch_constant(&dst->reg)))
+ if (dst->reg.type == VKD3DSPR_OUTPUT
+ || (is_in_fork_or_join_phase(compiler) && dst->reg.type == VKD3DSPR_PATCHCONST))
spirv_compiler_emit_output(compiler, dst);
else
spirv_compiler_emit_output_register(compiler, dst);
@@ -6362,7 +6394,6 @@ static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler)
* Control point phase has separate output registers. */
memset(compiler->output_info, 0, signature->element_count * sizeof(*compiler->output_info));
memset(compiler->private_output_variable, 0, sizeof(compiler->private_output_variable));
- memset(compiler->private_output_variable_array_idx, 0, sizeof(compiler->private_output_variable_array_idx));
memset(compiler->private_output_variable_write_mask, 0, sizeof(compiler->private_output_variable_write_mask));
}
}
@@ -6491,36 +6522,17 @@ static void spirv_compiler_emit_hull_shader_barrier(struct spirv_compiler *compi
static void spirv_compiler_emit_shader_epilogue_invocation(struct spirv_compiler *compiler)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
- uint32_t void_id, type_id, ptr_type_id, function_id;
uint32_t arguments[MAX_REG_OUTPUT];
+ uint32_t void_id, function_id;
unsigned int i, count;
if ((function_id = compiler->epilogue_function_id))
{
void_id = vkd3d_spirv_get_op_type_void(builder);
- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 4);
- ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id);
for (i = 0, count = 0; i < ARRAY_SIZE(compiler->private_output_variable); ++i)
{
if (compiler->private_output_variable[i])
- {
- uint32_t argument_id = compiler->private_output_variable[i];
- unsigned int argument_idx = count++;
-
- if (compiler->private_output_variable_array_idx[i])
- {
- uint32_t tmp_id;
-
- tmp_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id,
- argument_id, compiler->private_output_variable_array_idx[i]);
- tmp_id = vkd3d_spirv_build_op_load(builder, type_id, tmp_id, SpvMemoryAccessMaskNone);
- argument_id = vkd3d_spirv_build_op_variable(builder,
- &builder->global_stream, ptr_type_id, SpvStorageClassPrivate, 0);
- vkd3d_spirv_build_op_store(builder, argument_id, tmp_id, SpvMemoryAccessMaskNone);
- }
-
- arguments[argument_idx] = argument_id;
- }
+ arguments[count++] = compiler->private_output_variable[i];
}
vkd3d_spirv_build_op_function_call(builder, void_id, function_id, arguments, count);
@@ -6597,6 +6609,54 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru
return SpvOpMax;
}
+static SpvOp spirv_compiler_map_logical_instruction(const struct vkd3d_shader_instruction *instruction)
+{
+ switch (instruction->handler_idx)
+ {
+ case VKD3DSIH_AND:
+ return SpvOpLogicalAnd;
+ case VKD3DSIH_OR:
+ return SpvOpLogicalOr;
+ case VKD3DSIH_XOR:
+ return SpvOpLogicalNotEqual;
+ default:
+ return SpvOpMax;
+ }
+}
+
+static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler,
+ const struct vkd3d_shader_instruction *instruction)
+{
+ const struct vkd3d_shader_dst_param *dst = instruction->dst;
+ const struct vkd3d_shader_src_param *src = instruction->src;
+ uint32_t val_id;
+
+ assert(src->reg.data_type == VKD3D_DATA_BOOL && dst->reg.data_type != VKD3D_DATA_BOOL);
+
+ val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
+ if (dst->reg.data_type == VKD3D_DATA_FLOAT)
+ {
+ val_id = spirv_compiler_emit_bool_to_float(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF);
+ }
+ else if (dst->reg.data_type == VKD3D_DATA_DOUBLE)
+ {
+ /* ITOD is not supported. Frontends which emit bool casts must use ITOF for double. */
+ val_id = spirv_compiler_emit_bool_to_double(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF);
+ }
+ else if (dst->reg.data_type == VKD3D_DATA_UINT)
+ {
+ val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI);
+ }
+ else
+ {
+ WARN("Unhandled data type %u.\n", dst->reg.data_type);
+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE,
+ "Register data type %u is unhandled.", dst->reg.data_type);
+ }
+
+ spirv_compiler_emit_store_dst(compiler, dst, val_id);
+}
+
static void spirv_compiler_emit_alu_instruction(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
@@ -6605,13 +6665,35 @@ static void spirv_compiler_emit_alu_instruction(struct spirv_compiler *compiler,
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t src_ids[SPIRV_MAX_SRC_COUNT];
uint32_t type_id, val_id;
+ SpvOp op = SpvOpMax;
unsigned int i;
- SpvOp op;
- op = spirv_compiler_map_alu_instruction(instruction);
+ if (src->reg.data_type == VKD3D_DATA_BOOL)
+ {
+ if (dst->reg.data_type == VKD3D_DATA_BOOL)
+ {
+ /* VSIR supports logic ops AND/OR/XOR on bool values. */
+ op = spirv_compiler_map_logical_instruction(instruction);
+ }
+ else if (instruction->handler_idx == VKD3DSIH_ITOF || instruction->handler_idx == VKD3DSIH_UTOF
+ || instruction->handler_idx == VKD3DSIH_ITOI || instruction->handler_idx == VKD3DSIH_UTOU)
+ {
+ /* VSIR supports cast from bool to signed/unsigned integer types and floating point types,
+ * where bool is treated as a 1-bit integer and a signed 'true' value converts to -1. */
+ spirv_compiler_emit_bool_cast(compiler, instruction);
+ return;
+ }
+ }
+ else
+ {
+ op = spirv_compiler_map_alu_instruction(instruction);
+ }
+
if (op == SpvOpMax)
{
ERR("Unexpected instruction %#x.\n", instruction->handler_idx);
+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER,
+ "Encountered invalid/unhandled instruction handler %#x.", instruction->handler_idx);
return;
}
@@ -7050,6 +7132,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler,
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
uint32_t src_type_id, dst_type_id, condition_type_id;
+ enum vkd3d_shader_component_type component_type;
unsigned int component_count;
assert(instruction->dst_count == 1);
@@ -7064,11 +7147,23 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler,
dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst);
src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
- int_min_id = spirv_compiler_get_constant_float_vector(compiler, -2147483648.0f, component_count);
+ if (src->reg.data_type == VKD3D_DATA_DOUBLE)
+ {
+ int_min_id = spirv_compiler_get_constant_double_vector(compiler, -2147483648.0, component_count);
+ float_max_id = spirv_compiler_get_constant_double_vector(compiler, 2147483648.0, component_count);
+ }
+ else
+ {
+ int_min_id = spirv_compiler_get_constant_float_vector(compiler, -2147483648.0f, component_count);
+ float_max_id = spirv_compiler_get_constant_float_vector(compiler, 2147483648.0f, component_count);
+ }
+
val_id = vkd3d_spirv_build_op_glsl_std450_max(builder, src_type_id, src_id, int_min_id);
- float_max_id = spirv_compiler_get_constant_float_vector(compiler, 2147483648.0f, component_count);
- int_max_id = spirv_compiler_get_constant_int_vector(compiler, INT_MAX, component_count);
+ /* VSIR allows the destination of a signed conversion to be unsigned. */
+ component_type = vkd3d_component_type_from_data_type(dst->reg.data_type);
+
+ int_max_id = spirv_compiler_get_constant_vector(compiler, component_type, component_count, INT_MAX);
condition_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count);
condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
SpvOpFOrdGreaterThanEqual, condition_type_id, val_id, float_max_id);
@@ -7076,7 +7171,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler,
val_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpConvertFToS, dst_type_id, val_id);
val_id = vkd3d_spirv_build_op_select(builder, dst_type_id, condition_id, int_max_id, val_id);
- zero_id = spirv_compiler_get_constant_int_vector(compiler, 0, component_count);
+ zero_id = spirv_compiler_get_constant_vector(compiler, component_type, component_count, 0);
condition_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpIsNan, condition_type_id, src_id);
val_id = vkd3d_spirv_build_op_select(builder, dst_type_id, condition_id, zero_id, val_id);
@@ -7105,10 +7200,19 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler,
dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst);
src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
- zero_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count);
+ if (src->reg.data_type == VKD3D_DATA_DOUBLE)
+ {
+ zero_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count);
+ float_max_id = spirv_compiler_get_constant_double_vector(compiler, 4294967296.0, component_count);
+ }
+ else
+ {
+ zero_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count);
+ float_max_id = spirv_compiler_get_constant_float_vector(compiler, 4294967296.0f, component_count);
+ }
+
val_id = vkd3d_spirv_build_op_glsl_std450_max(builder, src_type_id, src_id, zero_id);
- float_max_id = spirv_compiler_get_constant_float_vector(compiler, 4294967296.0f, component_count);
uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT_MAX, component_count);
condition_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count);
condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
@@ -7255,18 +7359,22 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co
switch (instruction->handler_idx)
{
- case VKD3DSIH_DEQ:
- case VKD3DSIH_EQ: op = SpvOpFOrdEqual; break;
- case VKD3DSIH_DGE:
- case VKD3DSIH_GE: op = SpvOpFOrdGreaterThanEqual; break;
+ case VKD3DSIH_DEQO:
+ case VKD3DSIH_EQO: op = SpvOpFOrdEqual; break;
+ case VKD3DSIH_EQU: op = SpvOpFUnordEqual; break;
+ case VKD3DSIH_DGEO:
+ case VKD3DSIH_GEO: op = SpvOpFOrdGreaterThanEqual; break;
+ case VKD3DSIH_GEU: op = SpvOpFUnordGreaterThanEqual; break;
case VKD3DSIH_IEQ: op = SpvOpIEqual; break;
case VKD3DSIH_IGE: op = SpvOpSGreaterThanEqual; break;
case VKD3DSIH_ILT: op = SpvOpSLessThan; break;
case VKD3DSIH_INE: op = SpvOpINotEqual; break;
case VKD3DSIH_DLT:
- case VKD3DSIH_LT: op = SpvOpFOrdLessThan; break;
+ case VKD3DSIH_LTO: op = SpvOpFOrdLessThan; break;
+ case VKD3DSIH_LTU: op = SpvOpFUnordLessThan; break;
+ case VKD3DSIH_NEO: op = SpvOpFOrdNotEqual; break;
case VKD3DSIH_DNE:
- case VKD3DSIH_NE: op = SpvOpFUnordNotEqual; break;
+ case VKD3DSIH_NEU: op = SpvOpFUnordNotEqual; break;
case VKD3DSIH_UGE: op = SpvOpUGreaterThanEqual; break;
case VKD3DSIH_ULT: op = SpvOpULessThan; break;
default:
@@ -7283,7 +7391,8 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co
result_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
op, type_id, src0_id, src1_id);
- result_id = spirv_compiler_emit_bool_to_int(compiler, component_count, result_id);
+ if (dst->reg.data_type != VKD3D_DATA_BOOL)
+ result_id = spirv_compiler_emit_bool_to_int(compiler, component_count, result_id, true);
spirv_compiler_emit_store_reg(compiler, &dst->reg, dst->write_mask, result_id);
}
@@ -9338,11 +9447,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_DCL_GS_INSTANCES:
spirv_compiler_emit_dcl_gs_instances(compiler, instruction);
break;
- case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT:
- compiler->input_control_point_count = instruction->declaration.count;
- break;
case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT:
- compiler->output_control_point_count = instruction->declaration.count;
spirv_compiler_emit_output_vertex_count(compiler, instruction);
break;
case VKD3DSIH_DCL_TESSELLATOR_DOMAIN:
@@ -9384,8 +9489,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_DIV:
case VKD3DSIH_DMUL:
case VKD3DSIH_DTOF:
- case VKD3DSIH_DTOI:
- case VKD3DSIH_DTOU:
case VKD3DSIH_FREM:
case VKD3DSIH_FTOD:
case VKD3DSIH_IADD:
@@ -9394,12 +9497,14 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_ISHR:
case VKD3DSIH_ITOD:
case VKD3DSIH_ITOF:
+ case VKD3DSIH_ITOI:
case VKD3DSIH_MUL:
case VKD3DSIH_NOT:
case VKD3DSIH_OR:
case VKD3DSIH_USHR:
case VKD3DSIH_UTOD:
case VKD3DSIH_UTOF:
+ case VKD3DSIH_UTOU:
case VKD3DSIH_XOR:
spirv_compiler_emit_alu_instruction(compiler, instruction);
break;
@@ -9450,24 +9555,30 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_UDIV:
spirv_compiler_emit_int_div(compiler, instruction);
break;
+ case VKD3DSIH_DTOI:
case VKD3DSIH_FTOI:
spirv_compiler_emit_ftoi(compiler, instruction);
break;
+ case VKD3DSIH_DTOU:
case VKD3DSIH_FTOU:
spirv_compiler_emit_ftou(compiler, instruction);
break;
- case VKD3DSIH_DEQ:
- case VKD3DSIH_DGE:
+ case VKD3DSIH_DEQO:
+ case VKD3DSIH_DGEO:
case VKD3DSIH_DLT:
case VKD3DSIH_DNE:
- case VKD3DSIH_EQ:
- case VKD3DSIH_GE:
+ case VKD3DSIH_EQO:
+ case VKD3DSIH_EQU:
+ case VKD3DSIH_GEO:
+ case VKD3DSIH_GEU:
case VKD3DSIH_IEQ:
case VKD3DSIH_IGE:
case VKD3DSIH_ILT:
case VKD3DSIH_INE:
- case VKD3DSIH_LT:
- case VKD3DSIH_NE:
+ case VKD3DSIH_LTO:
+ case VKD3DSIH_LTU:
+ case VKD3DSIH_NEO:
+ case VKD3DSIH_NEU:
case VKD3DSIH_UGE:
case VKD3DSIH_ULT:
spirv_compiler_emit_comparison_instruction(compiler, instruction);
@@ -9602,6 +9713,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_DCL:
case VKD3DSIH_DCL_CONSTANT_BUFFER:
case VKD3DSIH_DCL_HS_MAX_TESSFACTOR:
+ case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT:
case VKD3DSIH_DCL_RESOURCE_RAW:
case VKD3DSIH_DCL_RESOURCE_STRUCTURED:
case VKD3DSIH_DCL_SAMPLER:
@@ -9700,6 +9812,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
memset(&shader_desc->patch_constant_signature, 0, sizeof(shader_desc->patch_constant_signature));
compiler->use_vocp = parser->shader_desc.use_vocp;
+ compiler->input_control_point_count = shader_desc->input_control_point_count;
+ compiler->output_control_point_count = shader_desc->output_control_point_count;
+
if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL)
spirv_compiler_emit_shader_signature_outputs(compiler);
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
index fbc04f61fe9..d0d2ea82bc0 100644
--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c
+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c
@@ -146,6 +146,9 @@ STATIC_ASSERT(SM4_MAX_SRC_COUNT <= SPIRV_MAX_SRC_COUNT);
#define VKD3D_SM4_SWIZZLE_SHIFT 4
#define VKD3D_SM4_SWIZZLE_MASK (0xffu << VKD3D_SM4_SWIZZLE_SHIFT)
+#define VKD3D_SM4_SCALAR_DIM_SHIFT 4
+#define VKD3D_SM4_SCALAR_DIM_MASK (0x3u << VKD3D_SM4_SCALAR_DIM_SHIFT)
+
#define VKD3D_SM4_VERSION_MAJOR(version) (((version) >> 4) & 0xf)
#define VKD3D_SM4_VERSION_MINOR(version) (((version) >> 0) & 0xf)
@@ -513,7 +516,8 @@ enum vkd3d_sm4_swizzle_type
VKD3D_SM4_SWIZZLE_VEC4 = 0x1,
VKD3D_SM4_SWIZZLE_SCALAR = 0x2,
- VKD3D_SM4_SWIZZLE_INVALID = ~0u,
+ VKD3D_SM4_SWIZZLE_DEFAULT = ~0u - 1,
+ VKD3D_SM4_SWIZZLE_INVALID = ~0u,
};
enum vkd3d_sm4_dimension
@@ -655,16 +659,18 @@ static const enum vkd3d_primitive_type output_primitive_type_table[] =
/* VKD3D_SM4_OUTPUT_PT_TRIANGLESTRIP */ VKD3D_PT_TRIANGLESTRIP,
};
-static const enum vkd3d_primitive_type input_primitive_type_table[] =
+static const struct
{
- /* UNKNOWN */ VKD3D_PT_UNDEFINED,
- /* VKD3D_SM4_INPUT_PT_POINT */ VKD3D_PT_POINTLIST,
- /* VKD3D_SM4_INPUT_PT_LINE */ VKD3D_PT_LINELIST,
- /* VKD3D_SM4_INPUT_PT_TRIANGLE */ VKD3D_PT_TRIANGLELIST,
- /* UNKNOWN */ VKD3D_PT_UNDEFINED,
- /* UNKNOWN */ VKD3D_PT_UNDEFINED,
- /* VKD3D_SM4_INPUT_PT_LINEADJ */ VKD3D_PT_LINELIST_ADJ,
- /* VKD3D_SM4_INPUT_PT_TRIANGLEADJ */ VKD3D_PT_TRIANGLELIST_ADJ,
+ unsigned int control_point_count;
+ enum vkd3d_primitive_type vkd3d_type;
+}
+input_primitive_type_table[] =
+{
+ [VKD3D_SM4_INPUT_PT_POINT] = {1, VKD3D_PT_POINTLIST},
+ [VKD3D_SM4_INPUT_PT_LINE] = {2, VKD3D_PT_LINELIST},
+ [VKD3D_SM4_INPUT_PT_TRIANGLE] = {3, VKD3D_PT_TRIANGLELIST},
+ [VKD3D_SM4_INPUT_PT_LINEADJ] = {4, VKD3D_PT_LINELIST_ADJ},
+ [VKD3D_SM4_INPUT_PT_TRIANGLEADJ] = {6, VKD3D_PT_TRIANGLELIST_ADJ},
};
static const enum vkd3d_shader_resource_type resource_type_table[] =
@@ -1033,6 +1039,7 @@ static void shader_sm4_read_dcl_input_primitive(struct vkd3d_shader_instruction
{
ins->declaration.primitive_type.type = VKD3D_PT_PATCH;
ins->declaration.primitive_type.patch_vertex_count = primitive_type - VKD3D_SM5_INPUT_PT_PATCH1 + 1;
+ priv->p.shader_desc.input_control_point_count = ins->declaration.primitive_type.patch_vertex_count;
}
else if (primitive_type >= ARRAY_SIZE(input_primitive_type_table))
{
@@ -1040,7 +1047,8 @@ static void shader_sm4_read_dcl_input_primitive(struct vkd3d_shader_instruction
}
else
{
- ins->declaration.primitive_type.type = input_primitive_type_table[primitive_type];
+ ins->declaration.primitive_type.type = input_primitive_type_table[primitive_type].vkd3d_type;
+ priv->p.shader_desc.input_control_point_count = input_primitive_type_table[primitive_type].control_point_count;
}
if (ins->declaration.primitive_type.type == VKD3D_PT_UNDEFINED)
@@ -1150,6 +1158,11 @@ static void shader_sm5_read_control_point_count(struct vkd3d_shader_instruction
{
ins->declaration.count = (opcode_token & VKD3D_SM5_CONTROL_POINT_COUNT_MASK)
>> VKD3D_SM5_CONTROL_POINT_COUNT_SHIFT;
+
+ if (opcode == VKD3D_SM5_OP_DCL_INPUT_CONTROL_POINT_COUNT)
+ priv->p.shader_desc.input_control_point_count = ins->declaration.count;
+ else
+ priv->p.shader_desc.output_control_point_count = ins->declaration.count;
}
static void shader_sm5_read_dcl_tessellator_domain(struct vkd3d_shader_instruction *ins, uint32_t opcode,
@@ -1332,12 +1345,12 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup)
{VKD3D_SM4_OP_ENDIF, VKD3DSIH_ENDIF, "", ""},
{VKD3D_SM4_OP_ENDLOOP, VKD3DSIH_ENDLOOP, "", ""},
{VKD3D_SM4_OP_ENDSWITCH, VKD3DSIH_ENDSWITCH, "", ""},
- {VKD3D_SM4_OP_EQ, VKD3DSIH_EQ, "u", "ff"},
+ {VKD3D_SM4_OP_EQ, VKD3DSIH_EQO, "u", "ff"},
{VKD3D_SM4_OP_EXP, VKD3DSIH_EXP, "f", "f"},
{VKD3D_SM4_OP_FRC, VKD3DSIH_FRC, "f", "f"},
{VKD3D_SM4_OP_FTOI, VKD3DSIH_FTOI, "i", "f"},
{VKD3D_SM4_OP_FTOU, VKD3DSIH_FTOU, "u", "f"},
- {VKD3D_SM4_OP_GE, VKD3DSIH_GE, "u", "ff"},
+ {VKD3D_SM4_OP_GE, VKD3DSIH_GEO, "u", "ff"},
{VKD3D_SM4_OP_IADD, VKD3DSIH_IADD, "i", "ii"},
{VKD3D_SM4_OP_IF, VKD3DSIH_IF, "", "u",
shader_sm4_read_conditional_op},
@@ -1358,7 +1371,7 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup)
{VKD3D_SM4_OP_LD2DMS, VKD3DSIH_LD2DMS, "u", "iRi"},
{VKD3D_SM4_OP_LOG, VKD3DSIH_LOG, "f", "f"},
{VKD3D_SM4_OP_LOOP, VKD3DSIH_LOOP, "", ""},
- {VKD3D_SM4_OP_LT, VKD3DSIH_LT, "u", "ff"},
+ {VKD3D_SM4_OP_LT, VKD3DSIH_LTO, "u", "ff"},
{VKD3D_SM4_OP_MAD, VKD3DSIH_MAD, "f", "fff"},
{VKD3D_SM4_OP_MIN, VKD3DSIH_MIN, "f", "ff"},
{VKD3D_SM4_OP_MAX, VKD3DSIH_MAX, "f", "ff"},
@@ -1367,7 +1380,7 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup)
{VKD3D_SM4_OP_MOV, VKD3DSIH_MOV, "f", "f"},
{VKD3D_SM4_OP_MOVC, VKD3DSIH_MOVC, "f", "uff"},
{VKD3D_SM4_OP_MUL, VKD3DSIH_MUL, "f", "ff"},
- {VKD3D_SM4_OP_NE, VKD3DSIH_NE, "u", "ff"},
+ {VKD3D_SM4_OP_NE, VKD3DSIH_NEU, "u", "ff"},
{VKD3D_SM4_OP_NOP, VKD3DSIH_NOP, "", ""},
{VKD3D_SM4_OP_NOT, VKD3DSIH_NOT, "u", "u"},
{VKD3D_SM4_OP_OR, VKD3DSIH_OR, "u", "uu"},
@@ -1538,8 +1551,8 @@ static void init_sm4_lookup_tables(struct vkd3d_sm4_lookup_tables *lookup)
{VKD3D_SM5_OP_DMAX, VKD3DSIH_DMAX, "d", "dd"},
{VKD3D_SM5_OP_DMIN, VKD3DSIH_DMIN, "d", "dd"},
{VKD3D_SM5_OP_DMUL, VKD3DSIH_DMUL, "d", "dd"},
- {VKD3D_SM5_OP_DEQ, VKD3DSIH_DEQ, "u", "dd"},
- {VKD3D_SM5_OP_DGE, VKD3DSIH_DGE, "u", "dd"},
+ {VKD3D_SM5_OP_DEQ, VKD3DSIH_DEQO, "u", "dd"},
+ {VKD3D_SM5_OP_DGE, VKD3DSIH_DGEO, "u", "dd"},
{VKD3D_SM5_OP_DLT, VKD3DSIH_DLT, "u", "dd"},
{VKD3D_SM5_OP_DNE, VKD3DSIH_DNE, "u", "dd"},
{VKD3D_SM5_OP_DMOV, VKD3DSIH_DMOV, "d", "d"},
@@ -3631,10 +3644,70 @@ struct sm4_instruction
uint32_t idx[3];
unsigned int idx_count;
+
+ struct vkd3d_shader_src_param idx_srcs[7];
+ unsigned int idx_src_count;
};
+static void sm4_register_from_node(struct vkd3d_shader_register *reg, uint32_t *writemask,
+ const struct hlsl_ir_node *instr)
+{
+ assert(instr->reg.allocated);
+ reg->type = VKD3DSPR_TEMP;
+ reg->dimension = VSIR_DIMENSION_VEC4;
+ reg->idx[0].offset = instr->reg.id;
+ reg->idx_count = 1;
+ *writemask = instr->reg.writemask;
+}
+
+static void sm4_numeric_register_from_deref(struct hlsl_ctx *ctx, struct vkd3d_shader_register *reg,
+ enum vkd3d_shader_register_type type, uint32_t *writemask, const struct hlsl_deref *deref,
+ struct sm4_instruction *sm4_instr)
+{
+ const struct hlsl_ir_var *var = deref->var;
+ unsigned int offset_const_deref;
+
+ reg->type = type;
+ reg->idx[0].offset = var->regs[HLSL_REGSET_NUMERIC].id;
+ reg->dimension = VSIR_DIMENSION_VEC4;
+
+ assert(var->regs[HLSL_REGSET_NUMERIC].allocated);
+
+ if (!var->indexable)
+ {
+ offset_const_deref = hlsl_offset_from_deref_safe(ctx, deref);
+ reg->idx[0].offset += offset_const_deref / 4;
+ reg->idx_count = 1;
+ }
+ else
+ {
+ offset_const_deref = deref->const_offset;
+ reg->idx[1].offset = offset_const_deref / 4;
+ reg->idx_count = 2;
+
+ if (deref->rel_offset.node)
+ {
+ struct vkd3d_shader_src_param *idx_src;
+ unsigned int idx_writemask;
+
+ assert(sm4_instr->idx_src_count < ARRAY_SIZE(sm4_instr->idx_srcs));
+ idx_src = &sm4_instr->idx_srcs[sm4_instr->idx_src_count++];
+ memset(idx_src, 0, sizeof(*idx_src));
+
+ reg->idx[1].rel_addr = idx_src;
+ sm4_register_from_node(&idx_src->reg, &idx_writemask, deref->rel_offset.node);
+ assert(idx_writemask != 0);
+ idx_src->swizzle = swizzle_from_sm4(hlsl_swizzle_from_writemask(idx_writemask));
+ }
+ }
+
+ *writemask = 0xf & (0xf << (offset_const_deref % 4));
+ if (var->regs[HLSL_REGSET_NUMERIC].writemask)
+ *writemask = hlsl_combine_writemasks(var->regs[HLSL_REGSET_NUMERIC].writemask, *writemask);
+}
+
static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct vkd3d_shader_register *reg,
- uint32_t *writemask, const struct hlsl_deref *deref)
+ uint32_t *writemask, const struct hlsl_deref *deref, struct sm4_instruction *sm4_instr)
{
const struct hlsl_type *data_type = hlsl_deref_get_type(ctx, deref);
const struct hlsl_ir_var *var = deref->var;
@@ -3749,24 +3822,19 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct vkd3d_shader_re
}
else
{
- struct hlsl_reg hlsl_reg = hlsl_reg_from_deref(ctx, deref);
+ enum vkd3d_shader_register_type type = deref->var->indexable ? VKD3DSPR_IDXTEMP : VKD3DSPR_TEMP;
- assert(hlsl_reg.allocated);
- reg->type = deref->var->indexable ? VKD3DSPR_IDXTEMP : VKD3DSPR_TEMP;
- reg->dimension = VSIR_DIMENSION_VEC4;
- reg->idx[0].offset = hlsl_reg.id;
- reg->idx_count = 1;
- *writemask = hlsl_reg.writemask;
+ sm4_numeric_register_from_deref(ctx, reg, type, writemask, deref, sm4_instr);
}
}
static void sm4_src_from_deref(const struct tpf_writer *tpf, struct vkd3d_shader_src_param *src,
- const struct hlsl_deref *deref, unsigned int map_writemask)
+ const struct hlsl_deref *deref, unsigned int map_writemask, struct sm4_instruction *sm4_instr)
{
unsigned int hlsl_swizzle;
uint32_t writemask;
- sm4_register_from_deref(tpf->ctx, &src->reg, &writemask, deref);
+ sm4_register_from_deref(tpf->ctx, &src->reg, &writemask, deref, sm4_instr);
if (vkd3d_sm4_get_default_swizzle_type(&tpf->lookup, src->reg.type) == VKD3D_SM4_SWIZZLE_VEC4)
{
hlsl_swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), map_writemask);
@@ -3774,17 +3842,6 @@ static void sm4_src_from_deref(const struct tpf_writer *tpf, struct vkd3d_shader
}
}
-static void sm4_register_from_node(struct vkd3d_shader_register *reg, uint32_t *writemask,
- const struct hlsl_ir_node *instr)
-{
- assert(instr->reg.allocated);
- reg->type = VKD3DSPR_TEMP;
- reg->dimension = VSIR_DIMENSION_VEC4;
- reg->idx[0].offset = instr->reg.id;
- reg->idx_count = 1;
- *writemask = instr->reg.writemask;
-}
-
static void sm4_dst_from_node(struct vkd3d_shader_dst_param *dst, const struct hlsl_ir_node *instr)
{
sm4_register_from_node(&dst->reg, &dst->write_mask, instr);
@@ -3837,75 +3894,130 @@ static void sm4_src_from_node(const struct tpf_writer *tpf, struct vkd3d_shader_
}
}
-static void sm4_write_dst_register(const struct tpf_writer *tpf, const struct vkd3d_shader_dst_param *dst)
+static unsigned int sm4_get_index_addressing_from_reg(const struct vkd3d_shader_register *reg,
+ unsigned int i)
+{
+ if (reg->idx[i].rel_addr)
+ {
+ if (reg->idx[i].offset == 0)
+ return VKD3D_SM4_ADDRESSING_RELATIVE;
+ else
+ return VKD3D_SM4_ADDRESSING_RELATIVE | VKD3D_SM4_ADDRESSING_OFFSET;
+ }
+
+ return 0;
+}
+
+static uint32_t sm4_encode_register(const struct tpf_writer *tpf, const struct vkd3d_shader_register *reg,
+ enum vkd3d_sm4_swizzle_type sm4_swizzle_type, uint32_t sm4_swizzle)
{
const struct vkd3d_sm4_register_type_info *register_type_info;
- struct vkd3d_bytecode_buffer *buffer = tpf->buffer;
- uint32_t sm4_reg_type, reg_dim;
+ uint32_t sm4_reg_type, sm4_reg_dim;
uint32_t token = 0;
- unsigned int j;
- register_type_info = get_info_from_vkd3d_register_type(&tpf->lookup, dst->reg.type);
+ register_type_info = get_info_from_vkd3d_register_type(&tpf->lookup, reg->type);
if (!register_type_info)
{
- FIXME("Unhandled vkd3d-shader register type %#x.\n", dst->reg.type);
+ FIXME("Unhandled vkd3d-shader register type %#x.\n", reg->type);
sm4_reg_type = VKD3D_SM4_RT_TEMP;
+ if (sm4_swizzle_type == VKD3D_SM4_SWIZZLE_DEFAULT)
+ sm4_swizzle_type = VKD3D_SM4_SWIZZLE_VEC4;
}
else
{
sm4_reg_type = register_type_info->sm4_type;
+ if (sm4_swizzle_type == VKD3D_SM4_SWIZZLE_DEFAULT)
+ sm4_swizzle_type = register_type_info->default_src_swizzle_type;
}
-
- reg_dim = sm4_dimension_from_vsir_dimension(dst->reg.dimension);
+ sm4_reg_dim = sm4_dimension_from_vsir_dimension(reg->dimension);
token |= sm4_reg_type << VKD3D_SM4_REGISTER_TYPE_SHIFT;
- token |= dst->reg.idx_count << VKD3D_SM4_REGISTER_ORDER_SHIFT;
- token |= reg_dim << VKD3D_SM4_DIMENSION_SHIFT;
- if (reg_dim == VKD3D_SM4_DIMENSION_VEC4)
- token |= dst->write_mask << VKD3D_SM4_WRITEMASK_SHIFT;
- put_u32(buffer, token);
+ token |= reg->idx_count << VKD3D_SM4_REGISTER_ORDER_SHIFT;
+ token |= sm4_reg_dim << VKD3D_SM4_DIMENSION_SHIFT;
+ if (reg->idx_count > 0)
+ token |= sm4_get_index_addressing_from_reg(reg, 0) << VKD3D_SM4_ADDRESSING_SHIFT0;
+ if (reg->idx_count > 1)
+ token |= sm4_get_index_addressing_from_reg(reg, 1) << VKD3D_SM4_ADDRESSING_SHIFT1;
+ if (reg->idx_count > 2)
+ token |= sm4_get_index_addressing_from_reg(reg, 2) << VKD3D_SM4_ADDRESSING_SHIFT2;
- for (j = 0; j < dst->reg.idx_count; ++j)
+ if (sm4_reg_dim == VKD3D_SM4_DIMENSION_VEC4)
{
- put_u32(buffer, dst->reg.idx[j].offset);
- assert(!dst->reg.idx[j].rel_addr);
+ token |= (uint32_t)sm4_swizzle_type << VKD3D_SM4_SWIZZLE_TYPE_SHIFT;
+
+ switch (sm4_swizzle_type)
+ {
+ case VKD3D_SM4_SWIZZLE_NONE:
+ assert(sm4_swizzle || register_is_constant(reg));
+ token |= (sm4_swizzle << VKD3D_SM4_WRITEMASK_SHIFT) & VKD3D_SM4_WRITEMASK_MASK;
+ break;
+
+ case VKD3D_SM4_SWIZZLE_VEC4:
+ token |= (sm4_swizzle << VKD3D_SM4_SWIZZLE_SHIFT) & VKD3D_SM4_SWIZZLE_MASK;
+ break;
+
+ case VKD3D_SM4_SWIZZLE_SCALAR:
+ token |= (sm4_swizzle << VKD3D_SM4_SCALAR_DIM_SHIFT) & VKD3D_SM4_SCALAR_DIM_MASK;
+ break;
+
+ default:
+ vkd3d_unreachable();
+ }
}
+
+ return token;
}
-static void sm4_write_src_register(const struct tpf_writer *tpf, const struct vkd3d_shader_src_param *src)
+static void sm4_write_register_index(const struct tpf_writer *tpf, const struct vkd3d_shader_register *reg,
+ unsigned int j)
{
- const struct vkd3d_sm4_register_type_info *register_type_info;
+ unsigned int addressing = sm4_get_index_addressing_from_reg(reg, j);
struct vkd3d_bytecode_buffer *buffer = tpf->buffer;
- uint32_t sm4_reg_type, reg_dim;
- uint32_t token = 0, mod_token = 0;
- unsigned int j;
+ unsigned int k;
- register_type_info = get_info_from_vkd3d_register_type(&tpf->lookup, src->reg.type);
- if (!register_type_info)
+ if (addressing & VKD3D_SM4_ADDRESSING_RELATIVE)
{
- FIXME("Unhandled vkd3d-shader register type %#x.\n", src->reg.type);
- sm4_reg_type = VKD3D_SM4_RT_TEMP;
+ const struct vkd3d_shader_src_param *idx_src = reg->idx[j].rel_addr;
+ uint32_t idx_src_token;
+
+ assert(idx_src);
+ assert(!idx_src->modifiers);
+ assert(idx_src->reg.type != VKD3DSPR_IMMCONST);
+ idx_src_token = sm4_encode_register(tpf, &idx_src->reg, VKD3D_SM4_SWIZZLE_SCALAR, idx_src->swizzle);
+
+ put_u32(buffer, idx_src_token);
+ for (k = 0; k < idx_src->reg.idx_count; ++k)
+ {
+ put_u32(buffer, idx_src->reg.idx[k].offset);
+ assert(!idx_src->reg.idx[k].rel_addr);
+ }
}
else
{
- sm4_reg_type = register_type_info->sm4_type;
+ put_u32(tpf->buffer, reg->idx[j].offset);
}
+}
- reg_dim = sm4_dimension_from_vsir_dimension(src->reg.dimension);
+static void sm4_write_dst_register(const struct tpf_writer *tpf, const struct vkd3d_shader_dst_param *dst)
+{
+ struct vkd3d_bytecode_buffer *buffer = tpf->buffer;
+ uint32_t token = 0;
+ unsigned int j;
- token |= sm4_reg_type << VKD3D_SM4_REGISTER_TYPE_SHIFT;
- token |= src->reg.idx_count << VKD3D_SM4_REGISTER_ORDER_SHIFT;
- token |= reg_dim << VKD3D_SM4_DIMENSION_SHIFT;
- if (reg_dim == VKD3D_SM4_DIMENSION_VEC4)
- {
- uint32_t swizzle_type = (uint32_t)register_type_info->default_src_swizzle_type;
+ token = sm4_encode_register(tpf, &dst->reg, VKD3D_SM4_SWIZZLE_NONE, dst->write_mask);
+ put_u32(buffer, token);
- token |= swizzle_type << VKD3D_SM4_SWIZZLE_TYPE_SHIFT;
- if (swizzle_type == VKD3D_SM4_SWIZZLE_SCALAR)
- token |= (swizzle_to_sm4(src->swizzle) & 0x3) << VKD3D_SM4_SWIZZLE_SHIFT;
- else
- token |= swizzle_to_sm4(src->swizzle) << VKD3D_SM4_SWIZZLE_SHIFT;
- }
+ for (j = 0; j < dst->reg.idx_count; ++j)
+ sm4_write_register_index(tpf, &dst->reg, j);
+}
+
+static void sm4_write_src_register(const struct tpf_writer *tpf, const struct vkd3d_shader_src_param *src)
+{
+ struct vkd3d_bytecode_buffer *buffer = tpf->buffer;
+ uint32_t token = 0, mod_token = 0;
+ unsigned int j;
+
+ token = sm4_encode_register(tpf, &src->reg, VKD3D_SM4_SWIZZLE_DEFAULT, swizzle_to_sm4(src->swizzle));
switch (src->modifiers)
{
@@ -3946,15 +4058,12 @@ static void sm4_write_src_register(const struct tpf_writer *tpf, const struct vk
}
for (j = 0; j < src->reg.idx_count; ++j)
- {
- put_u32(buffer, src->reg.idx[j].offset);
- assert(!src->reg.idx[j].rel_addr);
- }
+ sm4_write_register_index(tpf, &src->reg, j);
if (src->reg.type == VKD3DSPR_IMMCONST)
{
put_u32(buffer, src->reg.u.immconst_uint[0]);
- if (reg_dim == VKD3D_SM4_DIMENSION_VEC4)
+ if (src->reg.dimension == VSIR_DIMENSION_VEC4)
{
put_u32(buffer, src->reg.u.immconst_uint[1]);
put_u32(buffer, src->reg.u.immconst_uint[2]);
@@ -4476,7 +4585,7 @@ static void write_sm4_ld(const struct tpf_writer *tpf, const struct hlsl_ir_node
sm4_src_from_node(tpf, &instr.srcs[0], coords, coords_writemask);
- sm4_src_from_deref(tpf, &instr.srcs[1], resource, instr.dsts[0].write_mask);
+ sm4_src_from_deref(tpf, &instr.srcs[1], resource, instr.dsts[0].write_mask, &instr);
instr.src_count = 2;
@@ -4563,8 +4672,8 @@ static void write_sm4_sample(const struct tpf_writer *tpf, const struct hlsl_ir_
instr.dst_count = 1;
sm4_src_from_node(tpf, &instr.srcs[0], coords, VKD3DSP_WRITEMASK_ALL);
- sm4_src_from_deref(tpf, &instr.srcs[1], resource, instr.dsts[0].write_mask);
- sm4_src_from_deref(tpf, &instr.srcs[2], sampler, VKD3DSP_WRITEMASK_ALL);
+ sm4_src_from_deref(tpf, &instr.srcs[1], resource, instr.dsts[0].write_mask, &instr);
+ sm4_src_from_deref(tpf, &instr.srcs[2], sampler, VKD3DSP_WRITEMASK_ALL, &instr);
instr.src_count = 3;
if (load->load_type == HLSL_RESOURCE_SAMPLE_LOD
@@ -4605,7 +4714,7 @@ static void write_sm4_sampleinfo(const struct tpf_writer *tpf, const struct hlsl
sm4_dst_from_node(&instr.dsts[0], dst);
instr.dst_count = 1;
- sm4_src_from_deref(tpf, &instr.srcs[0], resource, instr.dsts[0].write_mask);
+ sm4_src_from_deref(tpf, &instr.srcs[0], resource, instr.dsts[0].write_mask, &instr);
instr.src_count = 1;
write_sm4_instruction(tpf, &instr);
@@ -4628,7 +4737,7 @@ static void write_sm4_resinfo(const struct tpf_writer *tpf, const struct hlsl_ir
instr.dst_count = 1;
sm4_src_from_node(tpf, &instr.srcs[0], load->lod.node, VKD3DSP_WRITEMASK_ALL);
- sm4_src_from_deref(tpf, &instr.srcs[1], resource, instr.dsts[0].write_mask);
+ sm4_src_from_deref(tpf, &instr.srcs[1], resource, instr.dsts[0].write_mask, &instr);
instr.src_count = 2;
write_sm4_instruction(tpf, &instr);
@@ -4776,7 +4885,7 @@ static void write_sm4_store_uav_typed(const struct tpf_writer *tpf, const struct
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM5_OP_STORE_UAV_TYPED;
- sm4_register_from_deref(tpf->ctx, &instr.dsts[0].reg, &instr.dsts[0].write_mask, dst);
+ sm4_register_from_deref(tpf->ctx, &instr.dsts[0].reg, &instr.dsts[0].write_mask, dst, &instr);
instr.dst_count = 1;
sm4_src_from_node(tpf, &instr.srcs[0], coords, VKD3DSP_WRITEMASK_ALL);
@@ -4822,6 +4931,11 @@ static void write_sm4_expr(const struct tpf_writer *tpf, const struct hlsl_ir_ex
write_sm4_cast(tpf, expr);
break;
+ case HLSL_OP1_CEIL:
+ assert(type_is_float(dst_type));
+ write_sm4_unary_op(tpf, VKD3D_SM4_OP_ROUND_PI, &expr->node, arg1, 0);
+ break;
+
case HLSL_OP1_COS:
assert(type_is_float(dst_type));
write_sm4_unary_op_with_two_destinations(tpf, VKD3D_SM4_OP_SINCOS, &expr->node, 1, arg1);
@@ -5322,7 +5436,7 @@ static void write_sm4_load(const struct tpf_writer *tpf, const struct hlsl_ir_lo
instr.opcode = VKD3D_SM4_OP_MOVC;
- sm4_src_from_deref(tpf, &instr.srcs[0], &load->src, instr.dsts[0].write_mask);
+ sm4_src_from_deref(tpf, &instr.srcs[0], &load->src, instr.dsts[0].write_mask, &instr);
memset(&value, 0xff, sizeof(value));
sm4_src_from_constant_value(&instr.srcs[1], &value, type->dimx, instr.dsts[0].write_mask);
@@ -5334,7 +5448,7 @@ static void write_sm4_load(const struct tpf_writer *tpf, const struct hlsl_ir_lo
{
instr.opcode = VKD3D_SM4_OP_MOV;
- sm4_src_from_deref(tpf, &instr.srcs[0], &load->src, instr.dsts[0].write_mask);
+ sm4_src_from_deref(tpf, &instr.srcs[0], &load->src, instr.dsts[0].write_mask, &instr);
instr.src_count = 1;
}
@@ -5387,10 +5501,10 @@ static void write_sm4_gather(const struct tpf_writer *tpf, const struct hlsl_ir_
}
}
- sm4_src_from_deref(tpf, &instr.srcs[instr.src_count++], resource, instr.dsts[0].write_mask);
+ sm4_src_from_deref(tpf, &instr.srcs[instr.src_count++], resource, instr.dsts[0].write_mask, &instr);
src = &instr.srcs[instr.src_count++];
- sm4_src_from_deref(tpf, src, sampler, VKD3DSP_WRITEMASK_ALL);
+ sm4_src_from_deref(tpf, src, sampler, VKD3DSP_WRITEMASK_ALL, &instr);
src->reg.dimension = VSIR_DIMENSION_VEC4;
src->swizzle = swizzle;
@@ -5460,6 +5574,9 @@ static void write_sm4_resource_load(const struct tpf_writer *tpf, const struct h
case HLSL_RESOURCE_RESINFO:
write_sm4_resinfo(tpf, load);
break;
+
+ case HLSL_RESOURCE_SAMPLE_PROJ:
+ vkd3d_unreachable();
}
}
@@ -5491,7 +5608,7 @@ static void write_sm4_store(const struct tpf_writer *tpf, const struct hlsl_ir_s
memset(&instr, 0, sizeof(instr));
instr.opcode = VKD3D_SM4_OP_MOV;
- sm4_register_from_deref(tpf->ctx, &instr.dsts[0].reg, &writemask, &store->lhs);
+ sm4_register_from_deref(tpf->ctx, &instr.dsts[0].reg, &writemask, &store->lhs, &instr);
instr.dsts[0].write_mask = hlsl_combine_writemasks(writemask, store->writemask);
instr.dst_count = 1;
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
index ab7300115dc..e5d590637f8 100644
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -93,6 +93,8 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED = 2003,
VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED = 2004,
VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY = 2005,
+ VKD3D_SHADER_ERROR_SPV_INVALID_TYPE = 2006,
+ VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER = 2007,
VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300,
@@ -210,6 +212,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS = 9013,
VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS = 9014,
VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX = 9015,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING = 9016,
};
enum vkd3d_shader_opcode
@@ -291,9 +294,9 @@ enum vkd3d_shader_opcode
VKD3DSIH_DEFAULT,
VKD3DSIH_DEFB,
VKD3DSIH_DEFI,
- VKD3DSIH_DEQ,
+ VKD3DSIH_DEQO,
VKD3DSIH_DFMA,
- VKD3DSIH_DGE,
+ VKD3DSIH_DGEO,
VKD3DSIH_DISCARD,
VKD3DSIH_DIV,
VKD3DSIH_DLT,
@@ -325,7 +328,8 @@ enum vkd3d_shader_opcode
VKD3DSIH_ENDLOOP,
VKD3DSIH_ENDREP,
VKD3DSIH_ENDSWITCH,
- VKD3DSIH_EQ,
+ VKD3DSIH_EQO,
+ VKD3DSIH_EQU,
VKD3DSIH_EVAL_CENTROID,
VKD3DSIH_EVAL_SAMPLE_INDEX,
VKD3DSIH_EXP,
@@ -349,7 +353,8 @@ enum vkd3d_shader_opcode
VKD3DSIH_GATHER4_PO_C_S,
VKD3DSIH_GATHER4_PO_S,
VKD3DSIH_GATHER4_S,
- VKD3DSIH_GE,
+ VKD3DSIH_GEO,
+ VKD3DSIH_GEU,
VKD3DSIH_HS_CONTROL_POINT_PHASE,
VKD3DSIH_HS_DECLS,
VKD3DSIH_HS_FORK_PHASE,
@@ -384,6 +389,7 @@ enum vkd3d_shader_opcode
VKD3DSIH_ISHR,
VKD3DSIH_ITOD,
VKD3DSIH_ITOF,
+ VKD3DSIH_ITOI,
VKD3DSIH_LABEL,
VKD3DSIH_LD,
VKD3DSIH_LD2DMS,
@@ -401,7 +407,8 @@ enum vkd3d_shader_opcode
VKD3DSIH_LOGP,
VKD3DSIH_LOOP,
VKD3DSIH_LRP,
- VKD3DSIH_LT,
+ VKD3DSIH_LTO,
+ VKD3DSIH_LTU,
VKD3DSIH_M3x2,
VKD3DSIH_M3x3,
VKD3DSIH_M3x4,
@@ -415,7 +422,8 @@ enum vkd3d_shader_opcode
VKD3DSIH_MOVC,
VKD3DSIH_MSAD,
VKD3DSIH_MUL,
- VKD3DSIH_NE,
+ VKD3DSIH_NEO,
+ VKD3DSIH_NEU,
VKD3DSIH_NOP,
VKD3DSIH_NOT,
VKD3DSIH_NRM,
@@ -491,6 +499,7 @@ enum vkd3d_shader_opcode
VKD3DSIH_USHR,
VKD3DSIH_UTOD,
VKD3DSIH_UTOF,
+ VKD3DSIH_UTOU,
VKD3DSIH_XOR,
VKD3DSIH_INVALID,
@@ -941,6 +950,12 @@ struct shader_signature
unsigned int element_count;
};
+static inline bool vsir_sysval_semantic_is_tess_factor(enum vkd3d_shader_sysval_semantic sysval_semantic)
+{
+ return sysval_semantic >= VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE
+ && sysval_semantic <= VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN;
+}
+
struct signature_element *vsir_signature_find_element_for_reg(const struct shader_signature *signature,
unsigned int reg_idx, unsigned int write_mask);
void shader_signature_cleanup(struct shader_signature *signature);
@@ -954,6 +969,8 @@ struct vkd3d_shader_desc
struct shader_signature output_signature;
struct shader_signature patch_constant_signature;
+ unsigned int input_control_point_count, output_control_point_count;
+
uint32_t temp_count;
unsigned int ssa_count;
@@ -1120,21 +1137,6 @@ static inline bool vkd3d_shader_instruction_has_texel_offset(const struct vkd3d_
return ins->texel_offset.u || ins->texel_offset.v || ins->texel_offset.w;
}
-static inline bool vkd3d_shader_register_is_input(const struct vkd3d_shader_register *reg)
-{
- return reg->type == VKD3DSPR_INPUT || reg->type == VKD3DSPR_INCONTROLPOINT;
-}
-
-static inline bool vkd3d_shader_register_is_output(const struct vkd3d_shader_register *reg)
-{
- return reg->type == VKD3DSPR_OUTPUT || reg->type == VKD3DSPR_COLOROUT;
-}
-
-static inline bool vkd3d_shader_register_is_patch_constant(const struct vkd3d_shader_register *reg)
-{
- return reg->type == VKD3DSPR_PATCHCONST;
-}
-
static inline bool register_is_constant(const struct vkd3d_shader_register *reg)
{
return (reg->type == VKD3DSPR_IMMCONST || reg->type == VKD3DSPR_IMMCONST64);
@@ -1413,6 +1415,8 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty
return VKD3D_SHADER_COMPONENT_INT;
case VKD3D_DATA_DOUBLE:
return VKD3D_SHADER_COMPONENT_DOUBLE;
+ case VKD3D_DATA_BOOL:
+ return VKD3D_SHADER_COMPONENT_BOOL;
default:
FIXME("Unhandled data type %#x.\n", data_type);
/* fall-through */
diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c
index 2d7051f3a3b..e4f2bad5f8b 100644
--- a/libs/vkd3d/libs/vkd3d/device.c
+++ b/libs/vkd3d/libs/vkd3d/device.c
@@ -2930,7 +2930,14 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device5
if (image_features & VK_FORMAT_FEATURE_BLIT_SRC_BIT)
data->Support1 |= D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE;
if (image_features & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)
+ {
data->Support1 |= D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW;
+ if (device->vk_info.uav_read_without_format)
+ data->Support2 |= D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD;
+ /* We effectively require shaderStorageImageWriteWithoutFormat,
+ * so we can just report UAV_TYPED_STORE unconditionally. */
+ data->Support2 |= D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE;
+ }
if (image_features & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)
data->Support2 |= D3D12_FORMAT_SUPPORT2_UAV_ATOMIC_ADD
@@ -3632,7 +3639,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource(ID3D12Devi
return hr;
}
- return return_interface(&object->ID3D12Resource_iface, &IID_ID3D12Resource, iid, resource);
+ return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource);
}
static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap(ID3D12Device5 *iface,
@@ -3675,7 +3682,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePlacedResource(ID3D12Device5
desc, initial_state, optimized_clear_value, &object)))
return hr;
- return return_interface(&object->ID3D12Resource_iface, &IID_ID3D12Resource, iid, resource);
+ return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource);
}
static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Device5 *iface,
@@ -3693,7 +3700,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateReservedResource(ID3D12Devic
desc, initial_state, optimized_clear_value, &object)))
return hr;
- return return_interface(&object->ID3D12Resource_iface, &IID_ID3D12Resource, iid, resource);
+ return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource);
}
static HRESULT STDMETHODCALLTYPE d3d12_device_CreateSharedHandle(ID3D12Device5 *iface,
@@ -4028,7 +4035,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreateCommittedResource1(ID3D12Dev
return hr;
}
- return return_interface(&object->ID3D12Resource_iface, &IID_ID3D12Resource, iid, resource);
+ return return_interface(&object->ID3D12Resource1_iface, &IID_ID3D12Resource1, iid, resource);
}
static HRESULT STDMETHODCALLTYPE d3d12_device_CreateHeap1(ID3D12Device5 *iface,
diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c
index 8898c247abf..abbdfbe2015 100644
--- a/libs/vkd3d/libs/vkd3d/resource.c
+++ b/libs/vkd3d/libs/vkd3d/resource.c
@@ -1258,12 +1258,13 @@ static bool d3d12_resource_init_tiles(struct d3d12_resource *resource, struct d3
}
/* ID3D12Resource */
-static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource1 *iface,
REFIID riid, void **object)
{
TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
- if (IsEqualGUID(riid, &IID_ID3D12Resource)
+ if (IsEqualGUID(riid, &IID_ID3D12Resource1)
+ || IsEqualGUID(riid, &IID_ID3D12Resource)
|| IsEqualGUID(riid, &IID_ID3D12Pageable)
|| IsEqualGUID(riid, &IID_ID3D12DeviceChild)
|| IsEqualGUID(riid, &IID_ID3D12Object)
@@ -1280,9 +1281,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource *i
return E_NOINTERFACE;
}
-static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource *iface)
+static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource1 *iface)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
ULONG refcount = InterlockedIncrement(&resource->refcount);
TRACE("%p increasing refcount to %u.\n", resource, refcount);
@@ -1298,9 +1299,9 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource *iface)
return refcount;
}
-static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource *iface)
+static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource1 *iface)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
ULONG refcount = InterlockedDecrement(&resource->refcount);
TRACE("%p decreasing refcount to %u.\n", resource, refcount);
@@ -1317,39 +1318,39 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource *iface)
return refcount;
}
-static HRESULT STDMETHODCALLTYPE d3d12_resource_GetPrivateData(ID3D12Resource *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_resource_GetPrivateData(ID3D12Resource1 *iface,
REFGUID guid, UINT *data_size, void *data)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
return vkd3d_get_private_data(&resource->private_store, guid, data_size, data);
}
-static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateData(ID3D12Resource *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateData(ID3D12Resource1 *iface,
REFGUID guid, UINT data_size, const void *data)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
return vkd3d_set_private_data(&resource->private_store, guid, data_size, data);
}
-static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateDataInterface(ID3D12Resource *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_resource_SetPrivateDataInterface(ID3D12Resource1 *iface,
REFGUID guid, const IUnknown *data)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
return vkd3d_set_private_data_interface(&resource->private_store, guid, data);
}
-static HRESULT STDMETHODCALLTYPE d3d12_resource_SetName(ID3D12Resource *iface, const WCHAR *name)
+static HRESULT STDMETHODCALLTYPE d3d12_resource_SetName(ID3D12Resource1 *iface, const WCHAR *name)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
HRESULT hr;
TRACE("iface %p, name %s.\n", iface, debugstr_w(name, resource->device->wchar_size));
@@ -1368,9 +1369,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_SetName(ID3D12Resource *iface, c
VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, name);
}
-static HRESULT STDMETHODCALLTYPE d3d12_resource_GetDevice(ID3D12Resource *iface, REFIID iid, void **device)
+static HRESULT STDMETHODCALLTYPE d3d12_resource_GetDevice(ID3D12Resource1 *iface, REFIID iid, void **device)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
TRACE("iface %p, iid %s, device %p.\n", iface, debugstr_guid(iid), device);
@@ -1421,10 +1422,10 @@ static void d3d12_resource_flush(struct d3d12_resource *resource, uint64_t offse
ERR("Failed to flush memory, vr %d.\n", vr);
}
-static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource *iface, UINT sub_resource,
+static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource1 *iface, UINT sub_resource,
const D3D12_RANGE *read_range, void **data)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
unsigned int sub_resource_count;
TRACE("iface %p, sub_resource %u, read_range %p, data %p.\n",
@@ -1470,10 +1471,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_Map(ID3D12Resource *iface, UINT
return S_OK;
}
-static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource *iface, UINT sub_resource,
+static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource1 *iface, UINT sub_resource,
const D3D12_RANGE *written_range)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
unsigned int sub_resource_count;
TRACE("iface %p, sub_resource %u, written_range %p.\n",
@@ -1492,10 +1493,10 @@ static void STDMETHODCALLTYPE d3d12_resource_Unmap(ID3D12Resource *iface, UINT s
d3d12_resource_flush(resource, written_range->Begin, written_range->End - written_range->Begin);
}
-static D3D12_RESOURCE_DESC * STDMETHODCALLTYPE d3d12_resource_GetDesc(ID3D12Resource *iface,
+static D3D12_RESOURCE_DESC * STDMETHODCALLTYPE d3d12_resource_GetDesc(ID3D12Resource1 *iface,
D3D12_RESOURCE_DESC *resource_desc)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
TRACE("iface %p, resource_desc %p.\n", iface, resource_desc);
@@ -1503,20 +1504,20 @@ static D3D12_RESOURCE_DESC * STDMETHODCALLTYPE d3d12_resource_GetDesc(ID3D12Reso
return resource_desc;
}
-static D3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE d3d12_resource_GetGPUVirtualAddress(ID3D12Resource *iface)
+static D3D12_GPU_VIRTUAL_ADDRESS STDMETHODCALLTYPE d3d12_resource_GetGPUVirtualAddress(ID3D12Resource1 *iface)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
TRACE("iface %p.\n", iface);
return resource->gpu_address;
}
-static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resource *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resource1 *iface,
UINT dst_sub_resource, const D3D12_BOX *dst_box, const void *src_data,
UINT src_row_pitch, UINT src_slice_pitch)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
const struct vkd3d_vk_device_procs *vk_procs;
VkImageSubresource vk_sub_resource;
const struct vkd3d_format *format;
@@ -1597,11 +1598,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_WriteToSubresource(ID3D12Resourc
return S_OK;
}
-static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resource *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resource1 *iface,
void *dst_data, UINT dst_row_pitch, UINT dst_slice_pitch,
UINT src_sub_resource, const D3D12_BOX *src_box)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
const struct vkd3d_vk_device_procs *vk_procs;
VkImageSubresource vk_sub_resource;
const struct vkd3d_format *format;
@@ -1682,10 +1683,10 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resour
return S_OK;
}
-static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource *iface,
+static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource1 *iface,
D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS *flags)
{
- struct d3d12_resource *resource = impl_from_ID3D12Resource(iface);
+ struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface);
struct d3d12_heap *heap;
TRACE("iface %p, heap_properties %p, flags %p.\n",
@@ -1719,7 +1720,15 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_GetHeapProperties(ID3D12Resource
return S_OK;
}
-static const struct ID3D12ResourceVtbl d3d12_resource_vtbl =
+static HRESULT STDMETHODCALLTYPE d3d12_resource_GetProtectedResourceSession(ID3D12Resource1 *iface,
+ REFIID iid, void **session)
+{
+ FIXME("iface %p, iid %s, session %p stub!\n", iface, debugstr_guid(iid), session);
+
+ return E_NOTIMPL;
+}
+
+static const struct ID3D12Resource1Vtbl d3d12_resource_vtbl =
{
/* IUnknown methods */
d3d12_resource_QueryInterface,
@@ -1740,13 +1749,15 @@ static const struct ID3D12ResourceVtbl d3d12_resource_vtbl =
d3d12_resource_WriteToSubresource,
d3d12_resource_ReadFromSubresource,
d3d12_resource_GetHeapProperties,
+ /* ID3D12Resource1 methods */
+ d3d12_resource_GetProtectedResourceSession,
};
struct d3d12_resource *unsafe_impl_from_ID3D12Resource(ID3D12Resource *iface)
{
if (!iface)
return NULL;
- assert(iface->lpVtbl == &d3d12_resource_vtbl);
+ assert(iface->lpVtbl == (ID3D12ResourceVtbl *)&d3d12_resource_vtbl);
return impl_from_ID3D12Resource(iface);
}
@@ -1944,7 +1955,7 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12
{
HRESULT hr;
- resource->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl;
+ resource->ID3D12Resource1_iface.lpVtbl = &d3d12_resource_vtbl;
resource->refcount = 1;
resource->internal_refcount = 1;
@@ -2097,7 +2108,7 @@ HRESULT d3d12_committed_resource_create(struct d3d12_device *device,
if (FAILED(hr = vkd3d_allocate_resource_memory(device, object, heap_properties, heap_flags)))
{
- d3d12_resource_Release(&object->ID3D12Resource_iface);
+ d3d12_resource_Release(&object->ID3D12Resource1_iface);
return hr;
}
@@ -2190,7 +2201,7 @@ HRESULT d3d12_placed_resource_create(struct d3d12_device *device, struct d3d12_h
if (FAILED(hr = vkd3d_bind_heap_memory(device, object, heap, heap_offset)))
{
- d3d12_resource_Release(&object->ID3D12Resource_iface);
+ d3d12_resource_Release(&object->ID3D12Resource1_iface);
return hr;
}
@@ -2214,7 +2225,7 @@ HRESULT d3d12_reserved_resource_create(struct d3d12_device *device,
if (!d3d12_resource_init_tiles(object, device))
{
- d3d12_resource_Release(&object->ID3D12Resource_iface);
+ d3d12_resource_Release(&object->ID3D12Resource1_iface);
return E_OUTOFMEMORY;
}
@@ -2249,7 +2260,7 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device,
memset(object, 0, sizeof(*object));
- object->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl;
+ object->ID3D12Resource1_iface.lpVtbl = &d3d12_resource_vtbl;
object->refcount = 1;
object->internal_refcount = 1;
object->desc = create_info->desc;
@@ -2273,7 +2284,7 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device,
TRACE("Created resource %p.\n", object);
- *resource = &object->ID3D12Resource_iface;
+ *resource = (ID3D12Resource *)&object->ID3D12Resource1_iface;
return S_OK;
}
diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
index 2e9845dfa6d..969ea8c4461 100644
--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
@@ -718,7 +718,7 @@ struct d3d12_resource_tile_info
/* ID3D12Resource */
struct d3d12_resource
{
- ID3D12Resource ID3D12Resource_iface;
+ ID3D12Resource1 ID3D12Resource1_iface;
LONG refcount;
LONG internal_refcount;
@@ -750,7 +750,12 @@ struct d3d12_resource
static inline struct d3d12_resource *impl_from_ID3D12Resource(ID3D12Resource *iface)
{
- return CONTAINING_RECORD(iface, struct d3d12_resource, ID3D12Resource_iface);
+ return CONTAINING_RECORD(iface, struct d3d12_resource, ID3D12Resource1_iface);
+}
+
+static inline struct d3d12_resource *impl_from_ID3D12Resource1(ID3D12Resource1 *iface)
+{
+ return CONTAINING_RECORD(iface, struct d3d12_resource, ID3D12Resource1_iface);
}
static inline bool d3d12_resource_is_buffer(const struct d3d12_resource *resource)
--
2.42.0