mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
1166 lines
49 KiB
Diff
1166 lines
49 KiB
Diff
From adfeedd876396c6bb597e9591c9d0e33d9098aee Mon Sep 17 00:00:00 2001
|
|
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
|
Date: Fri, 8 Dec 2023 13:21:19 +1100
|
|
Subject: [PATCH] Updated vkd3d to 45679a966c73669bdb7fa371569dcc34a448d8d4.
|
|
|
|
---
|
|
libs/vkd3d/include/private/vkd3d_common.h | 4 +-
|
|
libs/vkd3d/libs/vkd3d-common/blob.c | 1 +
|
|
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 4 +-
|
|
libs/vkd3d/libs/vkd3d-shader/dxil.c | 423 +++++++++++++++++-
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 20 +-
|
|
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 12 +-
|
|
libs/vkd3d/libs/vkd3d-shader/ir.c | 5 +-
|
|
libs/vkd3d/libs/vkd3d-shader/spirv.c | 127 ++++--
|
|
libs/vkd3d/libs/vkd3d-shader/tpf.c | 11 +
|
|
.../libs/vkd3d-shader/vkd3d_shader_main.c | 45 +-
|
|
.../libs/vkd3d-shader/vkd3d_shader_private.h | 3 +
|
|
11 files changed, 564 insertions(+), 91 deletions(-)
|
|
|
|
diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h
|
|
index 34fde1a2aa0..e9bff2fbba3 100644
|
|
--- a/libs/vkd3d/include/private/vkd3d_common.h
|
|
+++ b/libs/vkd3d/include/private/vkd3d_common.h
|
|
@@ -80,7 +80,7 @@ static inline size_t align(size_t addr, size_t alignment)
|
|
# ifdef __MINGW_PRINTF_FORMAT
|
|
# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, args)))
|
|
# else
|
|
-# define VKD3D_PRINTF_FUNC(fmt, args) /* __attribute__((format(printf, fmt, args))) */
|
|
+# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args)))
|
|
# endif
|
|
# define VKD3D_UNUSED __attribute__((unused))
|
|
# define VKD3D_UNREACHABLE __builtin_unreachable()
|
|
@@ -107,7 +107,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v)
|
|
{
|
|
#ifdef _MSC_VER
|
|
return __popcnt(v);
|
|
-#elif defined(__MINGW32__)
|
|
+#elif defined(HAVE_BUILTIN_POPCOUNT)
|
|
return __builtin_popcount(v);
|
|
#else
|
|
v -= (v >> 1) & 0x55555555;
|
|
diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c
|
|
index 71ab9a2c51e..fa2812619ac 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-common/blob.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-common/blob.c
|
|
@@ -17,6 +17,7 @@
|
|
*/
|
|
|
|
#define COBJMACROS
|
|
+
|
|
#define CONST_VTABLE
|
|
#include "vkd3d.h"
|
|
#include "vkd3d_blob.h"
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
index 3d139416b61..c78ffebac69 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
|
@@ -2253,7 +2253,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
|
|
{
|
|
struct hlsl_reg *reg = &jump->condition.node->reg;
|
|
|
|
- struct sm1_instruction instr =
|
|
+ struct sm1_instruction sm1_instr =
|
|
{
|
|
.opcode = D3DSIO_TEXKILL,
|
|
|
|
@@ -2263,7 +2263,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
|
|
.has_dst = 1,
|
|
};
|
|
|
|
- write_sm1_instruction(ctx, buffer, &instr);
|
|
+ write_sm1_instruction(ctx, buffer, &sm1_instr);
|
|
break;
|
|
}
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
index beb9ae574dc..a1065c8bc45 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
|
@@ -296,8 +296,28 @@ enum dx_intrinsic_opcode
|
|
{
|
|
DX_LOAD_INPUT = 4,
|
|
DX_STORE_OUTPUT = 5,
|
|
+ DX_EXP = 21,
|
|
+ DX_FRC = 22,
|
|
+ DX_LOG = 23,
|
|
+ DX_SQRT = 24,
|
|
+ DX_RSQRT = 25,
|
|
+ DX_ROUND_NE = 26,
|
|
+ DX_ROUND_NI = 27,
|
|
+ DX_ROUND_PI = 28,
|
|
+ DX_ROUND_Z = 29,
|
|
+ DX_BFREV = 30,
|
|
+ DX_COUNT_BITS = 31,
|
|
+ DX_FIRST_BIT_LO = 32,
|
|
+ DX_FIRST_BIT_HI = 33,
|
|
+ DX_FIRST_BIT_SHI = 34,
|
|
DX_CREATE_HANDLE = 57,
|
|
DX_CBUFFER_LOAD_LEGACY = 59,
|
|
+ DX_DERIV_COARSEX = 83,
|
|
+ DX_DERIV_COARSEY = 84,
|
|
+ DX_DERIV_FINEX = 85,
|
|
+ DX_DERIV_FINEY = 86,
|
|
+ DX_LEGACY_F32TOF16 = 130,
|
|
+ DX_LEGACY_F16TOF32 = 131,
|
|
};
|
|
|
|
enum dxil_cast_code
|
|
@@ -439,6 +459,7 @@ struct dxil_record
|
|
{
|
|
unsigned int code;
|
|
unsigned int operand_count;
|
|
+ const struct dxil_record *attachment;
|
|
uint64_t operands[];
|
|
};
|
|
|
|
@@ -581,6 +602,7 @@ struct sm6_parser
|
|
size_t descriptor_count;
|
|
|
|
unsigned int indexable_temp_count;
|
|
+ unsigned int icb_count;
|
|
|
|
struct sm6_value *values;
|
|
size_t value_count;
|
|
@@ -796,6 +818,7 @@ static enum vkd3d_result sm6_parser_read_unabbrev_record(struct sm6_parser *sm6)
|
|
|
|
record->code = code;
|
|
record->operand_count = count;
|
|
+ record->attachment = NULL;
|
|
|
|
for (i = 0; i < count; ++i)
|
|
record->operands[i] = sm6_parser_read_vbr(sm6, 6);
|
|
@@ -1012,6 +1035,7 @@ static enum vkd3d_result sm6_parser_read_abbrev_record(struct sm6_parser *sm6, u
|
|
if (!abbrev->operands[i + 1].read_operand(sm6, abbrev->operands[i + 1].context, &record->operands[i]))
|
|
goto fail;
|
|
record->operand_count = count;
|
|
+ record->attachment = NULL;
|
|
|
|
/* An array can occur only as the last operand. */
|
|
if (abbrev->is_array)
|
|
@@ -1572,6 +1596,11 @@ static bool sm6_type_is_bool_i16_i32_i64(const struct sm6_type *type)
|
|
return type->class == TYPE_CLASS_INTEGER && (type->u.width == 1 || type->u.width >= 16);
|
|
}
|
|
|
|
+static bool sm6_type_is_i16_i32_i64(const struct sm6_type *type)
|
|
+{
|
|
+ return type->class == TYPE_CLASS_INTEGER && type->u.width >= 16;
|
|
+}
|
|
+
|
|
static bool sm6_type_is_bool(const struct sm6_type *type)
|
|
{
|
|
return type->class == TYPE_CLASS_INTEGER && type->u.width == 1;
|
|
@@ -1587,6 +1616,16 @@ static inline bool sm6_type_is_i32(const struct sm6_type *type)
|
|
return type->class == TYPE_CLASS_INTEGER && type->u.width == 32;
|
|
}
|
|
|
|
+static bool sm6_type_is_float(const struct sm6_type *type)
|
|
+{
|
|
+ return type->class == TYPE_CLASS_FLOAT && type->u.width == 32;
|
|
+}
|
|
+
|
|
+static bool sm6_type_is_f16_f32(const struct sm6_type *type)
|
|
+{
|
|
+ return type->class == TYPE_CLASS_FLOAT && (type->u.width == 16 || type->u.width == 32);
|
|
+}
|
|
+
|
|
static inline bool sm6_type_is_floating_point(const struct sm6_type *type)
|
|
{
|
|
return type->class == TYPE_CLASS_FLOAT;
|
|
@@ -2412,7 +2451,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co
|
|
return VKD3D_ERROR_INVALID_SHADER;
|
|
}
|
|
size = max(size, sizeof(icb->data[0]));
|
|
- count = type->u.array.count * size / sizeof(icb->data[0]);
|
|
+ count = operands ? type->u.array.count * size / sizeof(icb->data[0]) : 0;
|
|
|
|
if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[count]))))
|
|
{
|
|
@@ -2433,9 +2472,14 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co
|
|
dst->value_type = VALUE_TYPE_ICB;
|
|
dst->u.icb = icb;
|
|
|
|
+ icb->register_idx = sm6->icb_count++;
|
|
icb->data_type = vkd3d_data_type_from_sm6_type(elem_type);
|
|
icb->element_count = type->u.array.count;
|
|
icb->component_count = 1;
|
|
+ icb->is_null = !operands;
|
|
+
|
|
+ if (!operands)
|
|
+ return VKD3D_OK;
|
|
|
|
count = type->u.array.count;
|
|
if (size > sizeof(icb->data[0]))
|
|
@@ -2510,12 +2554,10 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const
|
|
switch (record->code)
|
|
{
|
|
case CST_CODE_NULL:
|
|
- if (sm6_type_is_array(type))
|
|
+ if (sm6_type_is_array(type)
|
|
+ && (ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0)
|
|
{
|
|
- FIXME("Constant null arrays are not supported.\n");
|
|
- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
|
|
- "Constant null arrays are not supported.");
|
|
- return VKD3D_ERROR_INVALID_SHADER;
|
|
+ return ret;
|
|
}
|
|
/* For non-aggregates, register constant data is already zero-filled. */
|
|
break;
|
|
@@ -2588,6 +2630,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const
|
|
break;
|
|
}
|
|
|
|
+ if (record->attachment)
|
|
+ {
|
|
+ WARN("Ignoring metadata attachment.\n");
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "Ignoring a metadata attachment for a constant.");
|
|
+ }
|
|
+
|
|
++sm6->value_count;
|
|
}
|
|
|
|
@@ -2626,6 +2675,18 @@ static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_pa
|
|
return ins;
|
|
}
|
|
|
|
+static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type *elem_type, unsigned int count,
|
|
+ unsigned int alignment, unsigned int init, struct sm6_value *dst)
|
|
+{
|
|
+ enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type);
|
|
+ struct vkd3d_shader_instruction *ins;
|
|
+
|
|
+ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER);
|
|
+ /* The icb value index will be resolved later so forward references can be handled. */
|
|
+ ins->declaration.icb = (void *)(intptr_t)init;
|
|
+ register_init_with_id(&dst->u.reg, VKD3DSPR_IMMCONSTBUFFER, data_type, init);
|
|
+}
|
|
+
|
|
static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type,
|
|
unsigned int count, unsigned int alignment, unsigned int init, struct sm6_value *dst)
|
|
{
|
|
@@ -2762,7 +2823,10 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_
|
|
|
|
if (address_space == ADDRESS_SPACE_DEFAULT)
|
|
{
|
|
- sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst);
|
|
+ if (is_constant)
|
|
+ sm6_parser_declare_icb(sm6, scalar_type, count, alignment, init, dst);
|
|
+ else
|
|
+ sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst);
|
|
}
|
|
else if (address_space == ADDRESS_SPACE_GROUPSHARED)
|
|
{
|
|
@@ -2806,11 +2870,11 @@ static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_init
|
|
static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6)
|
|
{
|
|
const struct dxil_block *block = &sm6->root_block;
|
|
+ size_t i, base_value_idx = sm6->value_count;
|
|
struct vkd3d_shader_instruction *ins;
|
|
const struct dxil_record *record;
|
|
enum vkd3d_result ret;
|
|
uint64_t version;
|
|
- size_t i;
|
|
|
|
sm6->p.location.line = block->id;
|
|
sm6->p.location.column = 0;
|
|
@@ -2868,6 +2932,21 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6)
|
|
ins->declaration.indexable_temp.initialiser = resolve_forward_initialiser(
|
|
(uintptr_t)ins->declaration.indexable_temp.initialiser, sm6);
|
|
}
|
|
+ else if (ins->handler_idx == VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER)
|
|
+ {
|
|
+ ins->declaration.icb = resolve_forward_initialiser((uintptr_t)ins->declaration.icb, sm6);
|
|
+ }
|
|
+ }
|
|
+ for (i = base_value_idx; i < sm6->value_count; ++i)
|
|
+ {
|
|
+ const struct vkd3d_shader_immediate_constant_buffer *icb;
|
|
+ struct sm6_value *value = &sm6->values[i];
|
|
+
|
|
+ if (!sm6_value_is_register(value) || value->u.reg.type != VKD3DSPR_IMMCONSTBUFFER)
|
|
+ continue;
|
|
+
|
|
+ if ((icb = resolve_forward_initialiser(value->u.reg.idx[0].offset, sm6)))
|
|
+ value->u.reg.idx[0].offset = icb->register_idx;
|
|
}
|
|
|
|
return VKD3D_OK;
|
|
@@ -3171,6 +3250,67 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco
|
|
}
|
|
}
|
|
|
|
+static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op)
|
|
+{
|
|
+ switch (op)
|
|
+ {
|
|
+ case DX_EXP:
|
|
+ return VKD3DSIH_EXP;
|
|
+ case DX_FRC:
|
|
+ return VKD3DSIH_FRC;
|
|
+ case DX_LOG:
|
|
+ return VKD3DSIH_LOG;
|
|
+ case DX_SQRT:
|
|
+ return VKD3DSIH_SQRT;
|
|
+ case DX_RSQRT:
|
|
+ return VKD3DSIH_RSQ;
|
|
+ case DX_ROUND_NE:
|
|
+ return VKD3DSIH_ROUND_NE;
|
|
+ case DX_ROUND_NI:
|
|
+ return VKD3DSIH_ROUND_NI;
|
|
+ case DX_ROUND_PI:
|
|
+ return VKD3DSIH_ROUND_PI;
|
|
+ case DX_ROUND_Z:
|
|
+ return VKD3DSIH_ROUND_Z;
|
|
+ case DX_BFREV:
|
|
+ return VKD3DSIH_BFREV;
|
|
+ case DX_COUNT_BITS:
|
|
+ return VKD3DSIH_COUNTBITS;
|
|
+ case DX_FIRST_BIT_LO:
|
|
+ return VKD3DSIH_FIRSTBIT_LO;
|
|
+ case DX_FIRST_BIT_HI:
|
|
+ return VKD3DSIH_FIRSTBIT_HI;
|
|
+ case DX_FIRST_BIT_SHI:
|
|
+ return VKD3DSIH_FIRSTBIT_SHI;
|
|
+ case DX_DERIV_COARSEX:
|
|
+ return VKD3DSIH_DSX_COARSE;
|
|
+ case DX_DERIV_COARSEY:
|
|
+ return VKD3DSIH_DSY_COARSE;
|
|
+ case DX_DERIV_FINEX:
|
|
+ return VKD3DSIH_DSX_FINE;
|
|
+ case DX_DERIV_FINEY:
|
|
+ return VKD3DSIH_DSY_FINE;
|
|
+ case DX_LEGACY_F32TOF16:
|
|
+ return VKD3DSIH_F32TOF16;
|
|
+ case DX_LEGACY_F16TOF32:
|
|
+ return VKD3DSIH_F16TOF32;
|
|
+ default:
|
|
+ vkd3d_unreachable();
|
|
+ }
|
|
+}
|
|
+
|
|
+static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, struct sm6_block *code_block,
|
|
+ enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins)
|
|
+{
|
|
+ struct vkd3d_shader_src_param *src_param;
|
|
+
|
|
+ vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op));
|
|
+ src_param = instruction_src_params_alloc(ins, 1, sm6);
|
|
+ src_param_init_from_value(src_param, operands[0]);
|
|
+
|
|
+ instruction_dst_param_init_ssa_scalar(ins, sm6);
|
|
+}
|
|
+
|
|
static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, struct sm6_block *code_block,
|
|
enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins)
|
|
{
|
|
@@ -3344,7 +3484,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, struct sm6_b
|
|
|
|
struct sm6_dx_opcode_info
|
|
{
|
|
- const char ret_type;
|
|
+ const char *ret_type;
|
|
const char *operand_info;
|
|
void (*handler)(struct sm6_parser *, struct sm6_block *, enum dx_intrinsic_opcode,
|
|
const struct sm6_value **, struct vkd3d_shader_instruction *);
|
|
@@ -3355,16 +3495,40 @@ struct sm6_dx_opcode_info
|
|
b -> constant int1
|
|
c -> constant int8/16/32
|
|
i -> int32
|
|
+ m -> int16/32/64
|
|
+ f -> float
|
|
+ e -> half/float
|
|
+ g -> half/float/double
|
|
H -> handle
|
|
v -> void
|
|
o -> overloaded
|
|
*/
|
|
static const struct sm6_dx_opcode_info sm6_dx_op_table[] =
|
|
{
|
|
- [DX_CBUFFER_LOAD_LEGACY ] = {'o', "Hi", sm6_parser_emit_dx_cbuffer_load},
|
|
- [DX_CREATE_HANDLE ] = {'H', "ccib", sm6_parser_emit_dx_create_handle},
|
|
- [DX_LOAD_INPUT ] = {'o', "ii8i", sm6_parser_emit_dx_load_input},
|
|
- [DX_STORE_OUTPUT ] = {'v', "ii8o", sm6_parser_emit_dx_store_output},
|
|
+ [DX_BFREV ] = {"m0", "m", sm6_parser_emit_dx_unary},
|
|
+ [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load},
|
|
+ [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary},
|
|
+ [DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle},
|
|
+ [DX_DERIV_COARSEX ] = {"e0", "e", sm6_parser_emit_dx_unary},
|
|
+ [DX_DERIV_COARSEY ] = {"e0", "e", sm6_parser_emit_dx_unary},
|
|
+ [DX_DERIV_FINEX ] = {"e0", "e", sm6_parser_emit_dx_unary},
|
|
+ [DX_DERIV_FINEY ] = {"e0", "e", sm6_parser_emit_dx_unary},
|
|
+ [DX_EXP ] = {"g0", "g", sm6_parser_emit_dx_unary},
|
|
+ [DX_FIRST_BIT_HI ] = {"i", "m", sm6_parser_emit_dx_unary},
|
|
+ [DX_FIRST_BIT_LO ] = {"i", "m", sm6_parser_emit_dx_unary},
|
|
+ [DX_FIRST_BIT_SHI ] = {"i", "m", sm6_parser_emit_dx_unary},
|
|
+ [DX_FRC ] = {"g0", "g", sm6_parser_emit_dx_unary},
|
|
+ [DX_LEGACY_F16TOF32 ] = {"f", "i", sm6_parser_emit_dx_unary},
|
|
+ [DX_LEGACY_F32TOF16 ] = {"i", "f", sm6_parser_emit_dx_unary},
|
|
+ [DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input},
|
|
+ [DX_LOG ] = {"g0", "g", sm6_parser_emit_dx_unary},
|
|
+ [DX_ROUND_NE ] = {"g0", "g", sm6_parser_emit_dx_unary},
|
|
+ [DX_ROUND_NI ] = {"g0", "g", sm6_parser_emit_dx_unary},
|
|
+ [DX_ROUND_PI ] = {"g0", "g", sm6_parser_emit_dx_unary},
|
|
+ [DX_ROUND_Z ] = {"g0", "g", sm6_parser_emit_dx_unary},
|
|
+ [DX_RSQRT ] = {"g0", "g", sm6_parser_emit_dx_unary},
|
|
+ [DX_SQRT ] = {"g0", "g", sm6_parser_emit_dx_unary},
|
|
+ [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output},
|
|
};
|
|
|
|
static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type,
|
|
@@ -3389,6 +3553,14 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc
|
|
&& type->u.width <= 32;
|
|
case 'i':
|
|
return sm6_type_is_i32(type);
|
|
+ case 'm':
|
|
+ return sm6_type_is_i16_i32_i64(type);
|
|
+ case 'f':
|
|
+ return sm6_type_is_float(type);
|
|
+ case 'e':
|
|
+ return sm6_type_is_f16_f32(type);
|
|
+ case 'g':
|
|
+ return sm6_type_is_floating_point(type);
|
|
case 'H':
|
|
return (is_return || sm6_value_is_handle(value)) && type == sm6->handle_type;
|
|
case 'v':
|
|
@@ -3402,6 +3574,17 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc
|
|
}
|
|
}
|
|
|
|
+static bool operand_types_match(struct sm6_value *dst, const struct sm6_value **operands, unsigned int operand_count,
|
|
+ char index_char)
|
|
+{
|
|
+ unsigned int i = index_char - '0';
|
|
+
|
|
+ assert(i < 10);
|
|
+ if (i >= operand_count)
|
|
+ return false;
|
|
+ return dst->type == operands[i]->type;
|
|
+}
|
|
+
|
|
static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const char *name,
|
|
const struct sm6_value **operands, unsigned int operand_count, struct sm6_value *dst)
|
|
{
|
|
@@ -3410,7 +3593,9 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_
|
|
|
|
info = &sm6_dx_op_table[op];
|
|
|
|
- if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type, true))
|
|
+ assert(info->ret_type[0]);
|
|
+ if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type[0], true)
|
|
+ || (info->ret_type[1] && !operand_types_match(dst, operands, operand_count, info->ret_type[1])))
|
|
{
|
|
WARN("Failed to validate return type for dx intrinsic id %u, '%s'.\n", op, name);
|
|
/* Return type validation failure is not so critical. We only need to set
|
|
@@ -3700,6 +3885,9 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor
|
|
if (handler_idx == VKD3DSIH_NOP)
|
|
{
|
|
dst->u.reg = value->u.reg;
|
|
+ /* Set the result type for casts from 16-bit min precision. */
|
|
+ if (type->u.width != 16)
|
|
+ dst->u.reg.data_type = vkd3d_data_type_from_sm6_type(type);
|
|
return;
|
|
}
|
|
|
|
@@ -4153,6 +4341,208 @@ static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6,
|
|
return true;
|
|
}
|
|
|
|
+static void sm6_parser_metadata_attachment_block_init(struct sm6_parser *sm6, const struct dxil_block *target_block,
|
|
+ const struct dxil_block *block)
|
|
+{
|
|
+ struct dxil_record *target_record;
|
|
+ const struct dxil_record *record;
|
|
+ unsigned int i;
|
|
+ uint64_t index;
|
|
+
|
|
+ for (i = 0; i < block->record_count; ++i)
|
|
+ {
|
|
+ record = block->records[i];
|
|
+ if (record->code != METADATA_ATTACHMENT)
|
|
+ {
|
|
+ WARN("Ignoring record with code %u.\n", record->code);
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "Ignoring a metadata attachment record with code %u.", record->code);
|
|
+ continue;
|
|
+ }
|
|
+ if (!(record->operand_count & 1))
|
|
+ {
|
|
+ WARN("Ignoring function attachment.\n");
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "Ignoring a metadata function attachment.");
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ index = record->operands[0];
|
|
+ if (!target_block->record_count || index >= target_block->record_count - 1)
|
|
+ {
|
|
+ WARN("Invalid record index %"PRIu64".\n", index);
|
|
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
|
|
+ "Invalid record index %"PRIu64" for a metadata attachment.", index);
|
|
+ continue;
|
|
+ }
|
|
+ /* 'index' is an instruction index, but records[0] is DECLAREBLOCKS, not an instruction. */
|
|
+ target_record = target_block->records[index + 1];
|
|
+ if (target_record->attachment)
|
|
+ {
|
|
+ WARN("Overwriting record attachment.\n");
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "The target record for a metadata attachment already has an attachment.");
|
|
+ }
|
|
+ target_record->attachment = record;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void sm6_parser_metadata_attachments_init(struct sm6_parser *sm6, const struct dxil_block *block)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < block->child_block_count; ++i)
|
|
+ {
|
|
+ if (block->child_blocks[i]->id == METADATA_ATTACHMENT_BLOCK)
|
|
+ sm6_parser_metadata_attachment_block_init(sm6, block, block->child_blocks[i]);
|
|
+ }
|
|
+}
|
|
+
|
|
+static const struct sm6_metadata_value *sm6_parser_find_metadata_kind(const struct sm6_parser *sm6, uint64_t id)
|
|
+{
|
|
+ unsigned int i, j;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i)
|
|
+ {
|
|
+ for (j = 0; j < sm6->metadata_tables[i].count; ++j)
|
|
+ {
|
|
+ if (sm6->metadata_tables[i].values[j].type == VKD3D_METADATA_KIND
|
|
+ && sm6->metadata_tables[i].values[j].u.kind.id == id)
|
|
+ return &sm6->metadata_tables[i].values[j];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static const struct sm6_metadata_value *sm6_parser_metadata_get_value(const struct sm6_parser *sm6, uint64_t index)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i)
|
|
+ {
|
|
+ if (sm6->metadata_tables[i].count > index)
|
|
+ break;
|
|
+ index -= sm6->metadata_tables[i].count;
|
|
+ }
|
|
+
|
|
+ return (index < sm6->metadata_tables[i].count) ? &sm6->metadata_tables[i].values[index] : NULL;
|
|
+}
|
|
+
|
|
+static bool metadata_node_get_unary_uint(const struct sm6_metadata_node *node, unsigned int *operand,
|
|
+ struct sm6_parser *sm6)
|
|
+{
|
|
+ if (node->operand_count != 1)
|
|
+ {
|
|
+ FIXME("Ignoring node with %u operands.\n", node->operand_count);
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "Ignoring metadata attachment node with %u operands; expected unary.", node->operand_count);
|
|
+ return false;
|
|
+ }
|
|
+ if (!sm6_metadata_value_is_value(node->operands[0])
|
|
+ || !sm6_metadata_get_uint_value(sm6, node->operands[0], operand))
|
|
+ {
|
|
+ WARN("Failed to get operand value.\n");
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "Failed to get a metadata attachment operand value; ignoring the attachment.");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static void metadata_attachment_record_apply(const struct dxil_record *record, enum bitcode_function_code func_code,
|
|
+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst, struct sm6_parser *sm6)
|
|
+{
|
|
+ static const char *ignored_names[] =
|
|
+ {
|
|
+ "alias.scope",
|
|
+ "dx.controlflow.hints",
|
|
+ "llvm.loop",
|
|
+ "noalias",
|
|
+ "tbaa",
|
|
+ "range",
|
|
+ };
|
|
+ const struct sm6_metadata_node *node;
|
|
+ const struct sm6_metadata_value *m;
|
|
+ unsigned int i, j, operand;
|
|
+ bool ignored = false;
|
|
+ const char *name;
|
|
+
|
|
+ if (record->attachment)
|
|
+ {
|
|
+ WARN("Ignoring nested metadata attachment.\n");
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "Ignoring a nested metadata attachment.");
|
|
+ }
|
|
+
|
|
+ assert(record->operand_count & 1);
|
|
+ for (i = 1; i < record->operand_count; i += 2)
|
|
+ {
|
|
+ if (!(m = sm6_parser_find_metadata_kind(sm6, record->operands[i])))
|
|
+ {
|
|
+ WARN("Failed to find metadata kind %"PRIx64".\n", record->operands[i]);
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "Failed to find metadata kind %"PRIx64" for an attachment.", record->operands[i]);
|
|
+ continue;
|
|
+ }
|
|
+ name = m->u.kind.name;
|
|
+
|
|
+ m = sm6_parser_metadata_get_value(sm6, record->operands[i + 1]);
|
|
+ if (!m || !sm6_metadata_value_is_node(m))
|
|
+ {
|
|
+ WARN("Failed to retrieve metadata attachment node.\n");
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "Failed to retrieve a metadata attachment node.");
|
|
+ continue;
|
|
+ }
|
|
+ node = m->u.node;
|
|
+
|
|
+ if (!strcmp(name, "dx.precise"))
|
|
+ {
|
|
+ if (!sm6_value_is_register(dst))
|
|
+ {
|
|
+ WARN("Precise value is not a register.\n");
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "A value marked as precise is not a register.");
|
|
+ }
|
|
+ else if (metadata_node_get_unary_uint(node, &operand, sm6) && operand)
|
|
+ {
|
|
+ ins->flags |= sm6_type_is_scalar(dst->type) ? VKD3DSI_PRECISE_X : VKD3DSI_PRECISE_XYZW;
|
|
+ }
|
|
+ }
|
|
+ else if (!strcmp(name, "dx.nonuniform"))
|
|
+ {
|
|
+ if (!sm6_value_is_register(dst))
|
|
+ {
|
|
+ WARN("Non-uniform value is not a register.\n");
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "A value marked as non-uniform is not a register.");
|
|
+ }
|
|
+ else if (metadata_node_get_unary_uint(node, &operand, sm6))
|
|
+ {
|
|
+ dst->u.reg.non_uniform = !!operand;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ for (j = 0; j < ARRAY_SIZE(ignored_names); ++j)
|
|
+ if (!strcmp(name, ignored_names[j]))
|
|
+ break;
|
|
+ if (j == ARRAY_SIZE(ignored_names))
|
|
+ {
|
|
+ WARN("Ignoring metadata attachment '%s'.\n", name);
|
|
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT,
|
|
+ "Ignoring a metadata attachment named '%s'.", name);
|
|
+ }
|
|
+ ignored = true;
|
|
+ }
|
|
+
|
|
+ if (func_code != FUNC_CODE_INST_CALL && !ignored)
|
|
+ WARN("Metadata attachment target is not a function call.\n");
|
|
+ }
|
|
+}
|
|
+
|
|
static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block,
|
|
struct sm6_function *function)
|
|
{
|
|
@@ -4278,6 +4668,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const
|
|
return VKD3D_ERROR;
|
|
assert(ins->handler_idx != VKD3DSIH_INVALID);
|
|
|
|
+ if (record->attachment)
|
|
+ metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6);
|
|
+
|
|
if (is_terminator)
|
|
{
|
|
++block_idx;
|
|
@@ -4331,6 +4724,8 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st
|
|
sm6->p.location.line = block->id;
|
|
sm6->p.location.column = 0;
|
|
|
|
+ sm6_parser_metadata_attachments_init(sm6, block);
|
|
+
|
|
switch (block->id)
|
|
{
|
|
case CONSTANTS_BLOCK:
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
index 0dde4c18587..ed053f16312 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
|
@@ -487,27 +487,27 @@ static void resolve_loop_continue(struct hlsl_ctx *ctx, struct hlsl_block *block
|
|
else if (instr->type == HLSL_IR_JUMP)
|
|
{
|
|
struct hlsl_ir_jump *jump = hlsl_ir_jump(instr);
|
|
- struct hlsl_block block;
|
|
+ struct hlsl_block cond_block;
|
|
|
|
if (jump->type != HLSL_IR_JUMP_UNRESOLVED_CONTINUE)
|
|
continue;
|
|
|
|
if (type == LOOP_DO_WHILE)
|
|
{
|
|
- if (!hlsl_clone_block(ctx, &block, cond))
|
|
+ if (!hlsl_clone_block(ctx, &cond_block, cond))
|
|
return;
|
|
- if (!append_conditional_break(ctx, &block))
|
|
+ if (!append_conditional_break(ctx, &cond_block))
|
|
{
|
|
- hlsl_block_cleanup(&block);
|
|
+ hlsl_block_cleanup(&cond_block);
|
|
return;
|
|
}
|
|
- list_move_before(&instr->entry, &block.instrs);
|
|
+ list_move_before(&instr->entry, &cond_block.instrs);
|
|
}
|
|
else if (type == LOOP_FOR)
|
|
{
|
|
- if (!hlsl_clone_block(ctx, &block, iter))
|
|
+ if (!hlsl_clone_block(ctx, &cond_block, iter))
|
|
return;
|
|
- list_move_before(&instr->entry, &block.instrs);
|
|
+ list_move_before(&instr->entry, &cond_block.instrs);
|
|
}
|
|
jump->type = HLSL_IR_JUMP_CONTINUE;
|
|
}
|
|
@@ -3553,7 +3553,7 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *
|
|
{
|
|
struct hlsl_resource_load_params load_params = { 0 };
|
|
const struct hlsl_type *sampler_type;
|
|
- struct hlsl_ir_node *coords, *load;
|
|
+ struct hlsl_ir_node *coords, *sample;
|
|
|
|
if (params->args_count != 2 && params->args_count != 4)
|
|
{
|
|
@@ -3688,9 +3688,9 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *
|
|
load_params.format = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4);
|
|
load_params.sampling_dim = dim;
|
|
|
|
- if (!(load = hlsl_new_resource_load(ctx, &load_params, loc)))
|
|
+ if (!(sample = hlsl_new_resource_load(ctx, &load_params, loc)))
|
|
return false;
|
|
- hlsl_block_add_instr(params->instrs, load);
|
|
+ hlsl_block_add_instr(params->instrs, sample);
|
|
return true;
|
|
}
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
index 4a622185741..88cbef61d5f 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
|
@@ -1090,7 +1090,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
|
|
unsigned int dim_count = hlsl_sampler_dim_count(val->data_type->sampler_dim);
|
|
struct hlsl_ir_node *coords = index->idx.node;
|
|
struct hlsl_resource_load_params params = {0};
|
|
- struct hlsl_ir_node *load;
|
|
+ struct hlsl_ir_node *resource_load;
|
|
|
|
assert(coords->data_type->class == HLSL_CLASS_VECTOR);
|
|
assert(coords->data_type->base_type == HLSL_TYPE_UINT);
|
|
@@ -1104,9 +1104,9 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
|
|
params.coords = coords;
|
|
params.format = val->data_type->e.resource_format;
|
|
|
|
- if (!(load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc)))
|
|
+ if (!(resource_load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc)))
|
|
return false;
|
|
- hlsl_block_add_instr(block, load);
|
|
+ hlsl_block_add_instr(block, resource_load);
|
|
return true;
|
|
}
|
|
|
|
@@ -2301,7 +2301,6 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in
|
|
struct hlsl_ir_switch_case *c, *def = NULL;
|
|
bool missing_terminal_break = false;
|
|
struct hlsl_ir_node *node;
|
|
- struct hlsl_ir_jump *jump;
|
|
struct hlsl_ir_switch *s;
|
|
|
|
if (instr->type != HLSL_IR_SWITCH)
|
|
@@ -2320,10 +2319,7 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in
|
|
{
|
|
node = LIST_ENTRY(list_tail(&c->body.instrs), struct hlsl_ir_node, entry);
|
|
if (node->type == HLSL_IR_JUMP)
|
|
- {
|
|
- jump = hlsl_ir_jump(node);
|
|
- terminal_break = jump->type == HLSL_IR_JUMP_BREAK;
|
|
- }
|
|
+ terminal_break = (hlsl_ir_jump(node)->type == HLSL_IR_JUMP_BREAK);
|
|
}
|
|
|
|
missing_terminal_break |= !terminal_break;
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
index 710811c6761..a35ef862096 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
|
@@ -463,6 +463,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i
|
|
struct vkd3d_shader_instruction_array *instructions;
|
|
struct control_point_normaliser normaliser;
|
|
unsigned int input_control_point_count;
|
|
+ struct vkd3d_shader_location location;
|
|
struct vkd3d_shader_instruction *ins;
|
|
enum vkd3d_result ret;
|
|
unsigned int i, j;
|
|
@@ -513,8 +514,10 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i
|
|
return VKD3D_OK;
|
|
case VKD3DSIH_HS_FORK_PHASE:
|
|
case VKD3DSIH_HS_JOIN_PHASE:
|
|
+ /* ins may be relocated if the instruction array expands. */
|
|
+ location = ins->location;
|
|
ret = control_point_normaliser_emit_hs_input(&normaliser, input_signature,
|
|
- input_control_point_count, i, &ins->location);
|
|
+ input_control_point_count, i, &location);
|
|
*src_instructions = normaliser.instructions;
|
|
return ret;
|
|
default:
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
index c8a43adbe03..a22c59577ac 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
|
@@ -1194,6 +1194,16 @@ static uint32_t vkd3d_spirv_get_op_constant64(struct vkd3d_spirv_builder *builde
|
|
(const uint32_t *)&value, 2, vkd3d_spirv_build_op_constant64);
|
|
}
|
|
|
|
+static uint32_t vkd3d_spirv_build_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type)
|
|
+{
|
|
+ return vkd3d_spirv_build_op_tr(builder, &builder->global_stream, SpvOpConstantNull, result_type);
|
|
+}
|
|
+
|
|
+static uint32_t vkd3d_spirv_get_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type)
|
|
+{
|
|
+ return vkd3d_spirv_build_once1(builder, SpvOpConstantNull, result_type, vkd3d_spirv_build_op_constant_null);
|
|
+}
|
|
+
|
|
static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_builder *builder,
|
|
uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count)
|
|
{
|
|
@@ -2152,6 +2162,7 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol,
|
|
break;
|
|
|
|
case VKD3DSPR_IMMCONSTBUFFER:
|
|
+ symbol->key.reg.idx = reg->idx_count > 1 ? reg->idx[0].offset : 0;
|
|
break;
|
|
|
|
default:
|
|
@@ -3498,7 +3509,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp
|
|
}
|
|
else if (reg->type == VKD3DSPR_IMMCONSTBUFFER)
|
|
{
|
|
- indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[0]);
|
|
+ indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[reg->idx_count - 1]);
|
|
}
|
|
else if (reg->type == VKD3DSPR_IDXTEMP)
|
|
{
|
|
@@ -3756,6 +3767,69 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler,
|
|
return val_id;
|
|
}
|
|
|
|
+static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compiler,
|
|
+ const struct vkd3d_shader_immediate_constant_buffer *icb, uint32_t *type_id_out)
|
|
+{
|
|
+ uint32_t *elements, elem_type_id, length_id, type_id, const_id;
|
|
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
|
+ enum vkd3d_shader_component_type component_type;
|
|
+ unsigned int i, element_count, component_count;
|
|
+
|
|
+ element_count = icb->element_count;
|
|
+
|
|
+ component_type = vkd3d_component_type_from_data_type(icb->data_type);
|
|
+ component_count = icb->component_count;
|
|
+ elem_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, icb->data_type, component_count);
|
|
+ length_id = spirv_compiler_get_constant_uint(compiler, element_count);
|
|
+ type_id = vkd3d_spirv_get_op_type_array(builder, elem_type_id, length_id);
|
|
+
|
|
+ if (type_id_out)
|
|
+ *type_id_out = type_id;
|
|
+
|
|
+ if (icb->is_null)
|
|
+ {
|
|
+ /* All values are null. Workgroup memory initialisers require OpConstantNull. */
|
|
+ return vkd3d_spirv_get_op_constant_null(builder, type_id);
|
|
+ }
|
|
+
|
|
+ if (!(elements = vkd3d_calloc(element_count, sizeof(*elements))))
|
|
+ {
|
|
+ ERR("Failed to allocate %u elements.", element_count);
|
|
+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY,
|
|
+ "Failed to allocate %u constant array elements.", element_count);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ switch (icb->data_type)
|
|
+ {
|
|
+ case VKD3D_DATA_FLOAT:
|
|
+ case VKD3D_DATA_INT:
|
|
+ case VKD3D_DATA_UINT:
|
|
+ for (i = 0; i < element_count; ++i)
|
|
+ elements[i] = spirv_compiler_get_constant(compiler, component_type, component_count,
|
|
+ &icb->data[component_count * i]);
|
|
+ break;
|
|
+ case VKD3D_DATA_DOUBLE:
|
|
+ case VKD3D_DATA_UINT64:
|
|
+ {
|
|
+ uint64_t *data = (uint64_t *)icb->data;
|
|
+ for (i = 0; i < element_count; ++i)
|
|
+ elements[i] = spirv_compiler_get_constant64(compiler, component_type, component_count,
|
|
+ &data[component_count * i]);
|
|
+ break;
|
|
+ }
|
|
+ default:
|
|
+ FIXME("Unhandled data type %u.\n", icb->data_type);
|
|
+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE,
|
|
+ "Immediate constant buffer data type %u is unhandled.", icb->data_type);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, element_count);
|
|
+ vkd3d_free(elements);
|
|
+ return const_id;
|
|
+}
|
|
+
|
|
static const struct ssa_register_info *spirv_compiler_get_ssa_register_info(const struct spirv_compiler *compiler,
|
|
const struct vkd3d_shader_register *reg)
|
|
{
|
|
@@ -5493,39 +5567,40 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil
|
|
{
|
|
const struct vkd3d_shader_indexable_temp *temp = &instruction->declaration.indexable_temp;
|
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
|
+ uint32_t id, type_id, length_id, ptr_type_id, init_id = 0;
|
|
+ enum vkd3d_shader_component_type component_type;
|
|
struct vkd3d_shader_register reg;
|
|
struct vkd3d_symbol reg_symbol;
|
|
+ SpvStorageClass storage_class;
|
|
size_t function_location;
|
|
- uint32_t id;
|
|
|
|
- if (temp->component_count != 4)
|
|
- FIXME("Unhandled component count %u.\n", temp->component_count);
|
|
+ storage_class = SpvStorageClassFunction;
|
|
|
|
vsir_register_init(®, VKD3DSPR_IDXTEMP, VKD3D_DATA_FLOAT, 1);
|
|
reg.idx[0].offset = temp->register_idx;
|
|
|
|
if (temp->alignment)
|
|
WARN("Ignoring alignment %u.\n", temp->alignment);
|
|
- if (temp->initialiser)
|
|
- {
|
|
- FIXME("Initialisers are not supported.\n");
|
|
- spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED,
|
|
- "Initialisers for indexable temps are not supported.");
|
|
- }
|
|
|
|
function_location = spirv_compiler_get_current_function_location(compiler);
|
|
vkd3d_spirv_begin_function_stream_insertion(builder, function_location);
|
|
|
|
- id = spirv_compiler_emit_array_variable(compiler, &builder->function_stream,
|
|
- SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &temp->register_size, 1);
|
|
+ component_type = vkd3d_component_type_from_data_type(temp->data_type);
|
|
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, temp->component_count);
|
|
+ length_id = spirv_compiler_get_constant_uint(compiler, temp->register_size);
|
|
+ type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id);
|
|
+ ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
|
|
+ if (temp->initialiser)
|
|
+ init_id = spirv_compiler_emit_constant_array(compiler, temp->initialiser, NULL);
|
|
+ id = vkd3d_spirv_build_op_variable(builder, &builder->function_stream, ptr_type_id, storage_class, init_id);
|
|
|
|
spirv_compiler_emit_register_debug_name(builder, id, ®);
|
|
|
|
vkd3d_spirv_end_function_stream_insertion(builder);
|
|
|
|
vkd3d_symbol_make_register(®_symbol, ®);
|
|
- vkd3d_symbol_set_register_info(®_symbol, id,
|
|
- SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL);
|
|
+ vkd3d_symbol_set_register_info(®_symbol, id, storage_class,
|
|
+ component_type, vkd3d_write_mask_from_component_count(temp->component_count));
|
|
spirv_compiler_put_symbol(compiler, ®_symbol);
|
|
}
|
|
|
|
@@ -5743,34 +5818,24 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi
|
|
const struct vkd3d_shader_instruction *instruction)
|
|
{
|
|
const struct vkd3d_shader_immediate_constant_buffer *icb = instruction->declaration.icb;
|
|
- uint32_t *elements, length_id, type_id, const_id, ptr_type_id, icb_id;
|
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
|
+ uint32_t type_id, const_id, ptr_type_id, icb_id;
|
|
struct vkd3d_shader_register reg;
|
|
struct vkd3d_symbol reg_symbol;
|
|
- unsigned int i;
|
|
|
|
- assert(icb->data_type == VKD3D_DATA_FLOAT);
|
|
- assert(icb->component_count == VKD3D_VEC4_SIZE);
|
|
-
|
|
- if (!(elements = vkd3d_calloc(icb->element_count, sizeof(*elements))))
|
|
- return;
|
|
- for (i = 0; i < icb->element_count; ++i)
|
|
- elements[i] = spirv_compiler_get_constant(compiler,
|
|
- VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &icb->data[4 * i]);
|
|
- type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
|
|
- length_id = spirv_compiler_get_constant_uint(compiler, icb->element_count);
|
|
- type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id);
|
|
- const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, icb->element_count);
|
|
+ const_id = spirv_compiler_emit_constant_array(compiler, icb, &type_id);
|
|
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id);
|
|
icb_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
|
|
ptr_type_id, SpvStorageClassPrivate, const_id);
|
|
vkd3d_spirv_build_op_name(builder, icb_id, "icb");
|
|
- vkd3d_free(elements);
|
|
|
|
- vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 0);
|
|
+ /* Set an index count of 2 so vkd3d_symbol_make_register() uses idx[0] as a buffer id. */
|
|
+ vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 2);
|
|
+ reg.idx[0].offset = icb->register_idx;
|
|
vkd3d_symbol_make_register(®_symbol, ®);
|
|
vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate,
|
|
- VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL);
|
|
+ vkd3d_component_type_from_data_type(icb->data_type),
|
|
+ vkd3d_write_mask_from_component_count(icb->component_count));
|
|
spirv_compiler_put_symbol(compiler, ®_symbol);
|
|
}
|
|
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
index 80f8ab98c08..163cd90ee13 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
|
@@ -792,9 +792,11 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui
|
|
ins->handler_idx = VKD3DSIH_INVALID;
|
|
return;
|
|
}
|
|
+ icb->register_idx = 0;
|
|
icb->data_type = VKD3D_DATA_FLOAT;
|
|
icb->component_count = VKD3D_VEC4_SIZE;
|
|
icb->element_count = icb_size / VKD3D_VEC4_SIZE;
|
|
+ icb->is_null = false;
|
|
memcpy(icb->data, tokens, sizeof(*tokens) * icb_size);
|
|
shader_instruction_array_add_icb(&priv->p.instructions, icb);
|
|
ins->declaration.icb = icb;
|
|
@@ -1930,6 +1932,15 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui
|
|
break;
|
|
}
|
|
}
|
|
+ else if (register_type == VKD3D_SM4_RT_IMMCONSTBUFFER)
|
|
+ {
|
|
+ if (param->idx_count != 1)
|
|
+ {
|
|
+ WARN("Unexpected idx count %u.\n", param->idx_count);
|
|
+ vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_INDEX_COUNT,
|
|
+ "Invalid index count %u for immediate const buffer register; expected count 1.", param->idx_count);
|
|
+ }
|
|
+ }
|
|
else if (!shader_is_sm_5_1(priv) && vsir_register_is_descriptor(param))
|
|
{
|
|
/* SM5.1 places a symbol identifier in idx[0] and moves
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
index 8fd8945151f..d4a9d391477 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
|
@@ -23,6 +23,8 @@
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
+/* VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG"); */
|
|
+
|
|
static inline int char_to_int(char c)
|
|
{
|
|
if ('0' <= c && c <= '9')
|
|
@@ -888,6 +890,21 @@ static void vkd3d_shader_scan_combined_sampler_declaration(
|
|
&semantic->resource.range, semantic->resource_type, VKD3D_SHADER_RESOURCE_DATA_FLOAT);
|
|
}
|
|
|
|
+static const struct vkd3d_shader_descriptor_info1 *find_descriptor(
|
|
+ const struct vkd3d_shader_scan_descriptor_info1 *info,
|
|
+ enum vkd3d_shader_descriptor_type type, unsigned int register_id)
|
|
+{
|
|
+ for (unsigned int i = 0; i < info->descriptor_count; ++i)
|
|
+ {
|
|
+ const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i];
|
|
+
|
|
+ if (d->type == type && d->register_id == register_id)
|
|
+ return d;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_context *context,
|
|
const struct vkd3d_shader_register *resource, const struct vkd3d_shader_register *sampler)
|
|
{
|
|
@@ -913,7 +930,6 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co
|
|
|
|
if (vkd3d_shader_ver_ge(context->version, 5, 1))
|
|
{
|
|
- const struct vkd3d_shader_scan_descriptor_info1 *info = context->scan_descriptor_info;
|
|
const struct vkd3d_shader_descriptor_info1 *d;
|
|
bool dynamic_resource, dynamic_sampler;
|
|
|
|
@@ -928,30 +944,13 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co
|
|
if (dynamic_resource || dynamic_sampler)
|
|
return;
|
|
|
|
- for (i = 0; i < info->descriptor_count; ++i)
|
|
- {
|
|
- d = &info->descriptors[i];
|
|
- if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SRV)
|
|
- continue;
|
|
- if (d->register_id != resource->idx[0].offset)
|
|
- continue;
|
|
+ if ((d = find_descriptor(context->scan_descriptor_info,
|
|
+ VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource->idx[0].offset)))
|
|
resource_space = d->register_space;
|
|
- break;
|
|
- }
|
|
|
|
- if (sampler)
|
|
- {
|
|
- for (i = 0; i < info->descriptor_count; ++i)
|
|
- {
|
|
- d = &info->descriptors[i];
|
|
- if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER)
|
|
- continue;
|
|
- if (d->register_id != sampler->idx[0].offset)
|
|
- continue;
|
|
- sampler_space = d->register_space;
|
|
- break;
|
|
- }
|
|
- }
|
|
+ if (sampler && (d = find_descriptor(context->scan_descriptor_info,
|
|
+ VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler->idx[0].offset)))
|
|
+ sampler_space = d->register_space;
|
|
}
|
|
|
|
for (i = 0; i < info->combined_sampler_count; ++i)
|
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
index a93fa7160f7..4944b8a1c53 100644
|
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
|
@@ -196,6 +196,7 @@ enum vkd3d_shader_error
|
|
VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH = 8306,
|
|
VKD3D_SHADER_WARNING_DXIL_INVALID_MASK = 8307,
|
|
VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308,
|
|
+ VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT = 8309,
|
|
|
|
VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000,
|
|
VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001,
|
|
@@ -793,10 +794,12 @@ struct vkd3d_shader_version
|
|
|
|
struct vkd3d_shader_immediate_constant_buffer
|
|
{
|
|
+ unsigned int register_idx;
|
|
enum vkd3d_data_type data_type;
|
|
/* total count is element_count * component_count */
|
|
unsigned int element_count;
|
|
unsigned int component_count;
|
|
+ bool is_null;
|
|
uint32_t data[];
|
|
};
|
|
|
|
--
|
|
2.43.0
|
|
|