wine-staging/patches/vkd3d-latest/0001-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch
2024-01-24 12:28:57 +11:00

4527 lines
208 KiB
Diff

From 0e56d61705e984093a7e54d0ec788e99545011df 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 3bafee344d8d50172d8da18512ba070c6826b18d.
---
libs/vkd3d/include/private/vkd3d_common.h | 4 +-
libs/vkd3d/include/vkd3d_shader.h | 20 +
libs/vkd3d/libs/vkd3d-common/blob.c | 1 +
libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 135 ++--
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 16 +-
libs/vkd3d/libs/vkd3d-shader/dxbc.c | 4 -
libs/vkd3d/libs/vkd3d-shader/dxil.c | 699 +++++++++++++++---
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 20 +-
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 12 +-
libs/vkd3d/libs/vkd3d-shader/ir.c | 29 +-
libs/vkd3d/libs/vkd3d-shader/spirv.c | 669 ++++++++++-------
libs/vkd3d/libs/vkd3d-shader/tpf.c | 82 +-
.../libs/vkd3d-shader/vkd3d_shader_main.c | 86 ++-
.../libs/vkd3d-shader/vkd3d_shader_private.h | 54 +-
libs/vkd3d/libs/vkd3d/command.c | 4 +
libs/vkd3d/libs/vkd3d/device.c | 114 ++-
libs/vkd3d/libs/vkd3d/resource.c | 19 +-
libs/vkd3d/libs/vkd3d/state.c | 27 +-
libs/vkd3d/libs/vkd3d/utils.c | 2 +
libs/vkd3d/libs/vkd3d/vkd3d_private.h | 23 +-
20 files changed, 1475 insertions(+), 545 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/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h
index 290f9085d2d..b1a1fff6451 100644
--- a/libs/vkd3d/include/vkd3d_shader.h
+++ b/libs/vkd3d/include/vkd3d_shader.h
@@ -196,6 +196,14 @@ enum vkd3d_shader_compile_option_fragment_coordinate_origin
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN),
};
+/** Advertises feature availability. \since 1.11 */
+enum vkd3d_shader_compile_option_feature_flags
+{
+ VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64 = 0x00000001,
+
+ VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLAGS),
+};
+
enum vkd3d_shader_compile_option_name
{
/**
@@ -253,6 +261,16 @@ enum vkd3d_shader_compile_option_name
* \since 1.10
*/
VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN = 0x00000009,
+ /**
+ * This option specifies the shader features available in the target
+ * environment. These are not extensions, i.e. they are always supported
+ * by the driver, but may not be supported by the available hardware.
+ *
+ * \a value is a member of enum vkd3d_shader_compile_option_feature_flags.
+ *
+ * \since 1.11
+ */
+ VKD3D_SHADER_COMPILE_OPTION_FEATURE = 0x0000000a,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME),
};
@@ -1551,6 +1569,8 @@ enum vkd3d_shader_component_type
VKD3D_SHADER_COMPONENT_BOOL = 0x4,
/** 64-bit IEEE floating-point. */
VKD3D_SHADER_COMPONENT_DOUBLE = 0x5,
+ /** 64-bit unsigned integer. \since 1.11 */
+ VKD3D_SHADER_COMPONENT_UINT64 = 0x6,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPONENT_TYPE),
};
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/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
index 82d1d71d9d3..0589bc42174 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
@@ -364,6 +364,7 @@ struct vkd3d_d3d_asm_compiler
struct vkd3d_string_buffer buffer;
struct vkd3d_shader_version shader_version;
struct vkd3d_d3d_asm_colours colours;
+ enum vsir_asm_dialect dialect;
};
static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...)
@@ -606,7 +607,7 @@ static void shader_dump_resource_type(struct vkd3d_d3d_asm_compiler *compiler, e
vkd3d_string_buffer_printf(&compiler->buffer, "unknown");
}
-static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type)
+static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_data_type type)
{
static const char *const data_type_names[] =
{
@@ -623,19 +624,31 @@ static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, const
[VKD3D_DATA_DOUBLE ] = "double",
[VKD3D_DATA_CONTINUED] = "<continued>",
[VKD3D_DATA_UNUSED ] = "<unused>",
+ [VKD3D_DATA_UINT8 ] = "uint8",
+ [VKD3D_DATA_UINT64 ] = "uint64",
+ [VKD3D_DATA_BOOL ] = "bool",
};
+
const char *name;
+
+ if (type < ARRAY_SIZE(data_type_names))
+ name = data_type_names[type];
+ else
+ name = "<unknown>";
+
+ vkd3d_string_buffer_printf(&compiler->buffer, "%s", name);
+}
+
+static void shader_dump_resource_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type)
+{
int i;
vkd3d_string_buffer_printf(&compiler->buffer, "(");
for (i = 0; i < 4; i++)
{
- if (type[i] < ARRAY_SIZE(data_type_names))
- name = data_type_names[type[i]];
- else
- name = "unknown";
- vkd3d_string_buffer_printf(&compiler->buffer, "%s%s", i == 0 ? "" : ",", name);
+ vkd3d_string_buffer_printf(&compiler->buffer, "%s", i == 0 ? "" : ",");
+ shader_dump_data_type(compiler, type[i]);
}
vkd3d_string_buffer_printf(&compiler->buffer, ")");
@@ -682,7 +695,7 @@ static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler,
if (semantic->resource.reg.reg.type == VKD3DSPR_UAV)
shader_dump_uav_flags(compiler, flags);
shader_addline(buffer, " ");
- shader_dump_data_type(compiler, semantic->resource_data_type);
+ shader_dump_resource_data_type(compiler, semantic->resource_data_type);
}
else
{
@@ -1096,15 +1109,15 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const
switch (reg->data_type)
{
case VKD3D_DATA_FLOAT:
- shader_print_float_literal(compiler, "", reg->u.immconst_float[0], "");
+ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], "");
break;
case VKD3D_DATA_INT:
- shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], "");
+ shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], "");
break;
case VKD3D_DATA_RESOURCE:
case VKD3D_DATA_SAMPLER:
case VKD3D_DATA_UINT:
- shader_print_uint_literal(compiler, "", reg->u.immconst_uint[0], "");
+ shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], "");
break;
default:
shader_addline(buffer, "<unhandled data type %#x>", reg->data_type);
@@ -1116,24 +1129,24 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const
switch (reg->data_type)
{
case VKD3D_DATA_FLOAT:
- shader_print_float_literal(compiler, "", reg->u.immconst_float[0], "");
- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[1], "");
- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[2], "");
- shader_print_float_literal(compiler, ", ", reg->u.immconst_float[3], "");
+ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], "");
+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[1], "");
+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[2], "");
+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[3], "");
break;
case VKD3D_DATA_INT:
- shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], "");
- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[1], "");
- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[2], "");
- shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[3], "");
+ shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], "");
+ shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[1], "");
+ shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[2], "");
+ shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[3], "");
break;
case VKD3D_DATA_RESOURCE:
case VKD3D_DATA_SAMPLER:
case VKD3D_DATA_UINT:
- shader_print_uint_literal(compiler, "", reg->u.immconst_uint[0], "");
- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[1], "");
- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[2], "");
- shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[3], "");
+ shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], "");
+ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[1], "");
+ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[2], "");
+ shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[3], "");
break;
default:
shader_addline(buffer, "<unhandled data type %#x>", reg->data_type);
@@ -1155,9 +1168,9 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const
{
if (reg->data_type == VKD3D_DATA_DOUBLE)
{
- shader_print_double_literal(compiler, "", reg->u.immconst_double[0], "");
+ shader_print_double_literal(compiler, "", reg->u.immconst_f64[0], "");
if (reg->dimension == VSIR_DIMENSION_VEC4)
- shader_print_double_literal(compiler, ", ", reg->u.immconst_double[1], "");
+ shader_print_double_literal(compiler, ", ", reg->u.immconst_f64[1], "");
}
else
{
@@ -1265,6 +1278,32 @@ static void shader_print_non_uniform(struct vkd3d_d3d_asm_compiler *compiler, co
compiler->colours.modifier, compiler->colours.reset);
}
+static void shader_dump_reg_type(struct vkd3d_d3d_asm_compiler *compiler,
+ const struct vkd3d_shader_register *reg)
+{
+ static const char *dimensions[] =
+ {
+ [VSIR_DIMENSION_NONE] = "",
+ [VSIR_DIMENSION_SCALAR] = "s:",
+ [VSIR_DIMENSION_VEC4] = "v4:",
+ };
+
+ struct vkd3d_string_buffer *buffer = &compiler->buffer;
+ const char *dimension;
+
+ if (compiler->dialect != VSIR_ASM_VSIR)
+ return;
+
+ if (reg->dimension < ARRAY_SIZE(dimensions))
+ dimension = dimensions[reg->dimension];
+ else
+ dimension = "??";
+
+ shader_addline(buffer, " <%s", dimension);
+ shader_dump_data_type(compiler, reg->data_type);
+ shader_addline(buffer, ">");
+}
+
static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler,
const struct vkd3d_shader_dst_param *param, bool is_declaration)
{
@@ -1278,7 +1317,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler,
static const char write_mask_chars[] = "xyzw";
if (param->reg.data_type == VKD3D_DATA_DOUBLE)
- write_mask = vkd3d_write_mask_32_from_64(write_mask);
+ write_mask = vsir_write_mask_32_from_64(write_mask);
shader_addline(buffer, ".%s", compiler->colours.write_mask);
if (write_mask & VKD3DSP_WRITEMASK_0)
@@ -1294,6 +1333,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler,
shader_print_precision(compiler, &param->reg);
shader_print_non_uniform(compiler, &param->reg);
+ shader_dump_reg_type(compiler, &param->reg);
}
static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler,
@@ -1341,10 +1381,10 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler,
if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_IMMCONST64
&& param->reg.dimension == VSIR_DIMENSION_VEC4)
{
- unsigned int swizzle_x = vkd3d_swizzle_get_component(swizzle, 0);
- unsigned int swizzle_y = vkd3d_swizzle_get_component(swizzle, 1);
- unsigned int swizzle_z = vkd3d_swizzle_get_component(swizzle, 2);
- unsigned int swizzle_w = vkd3d_swizzle_get_component(swizzle, 3);
+ unsigned int swizzle_x = vsir_swizzle_get_component(swizzle, 0);
+ unsigned int swizzle_y = vsir_swizzle_get_component(swizzle, 1);
+ unsigned int swizzle_z = vsir_swizzle_get_component(swizzle, 2);
+ unsigned int swizzle_w = vsir_swizzle_get_component(swizzle, 3);
static const char swizzle_chars[] = "xyzw";
@@ -1367,6 +1407,7 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler,
shader_print_precision(compiler, &param->reg);
shader_print_non_uniform(compiler, &param->reg);
+ shader_dump_reg_type(compiler, &param->reg);
}
static void shader_dump_ins_modifiers(struct vkd3d_d3d_asm_compiler *compiler,
@@ -1577,6 +1618,12 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile
shader_addline(buffer, "p");
break;
+ case VKD3DSIH_ISHL:
+ case VKD3DSIH_ISHR:
+ case VKD3DSIH_USHR:
+ if (ins->flags & VKD3DSI_SHIFT_UNMASKED)
+ shader_addline(buffer, "_unmasked");
+ /* fall through */
default:
shader_dump_precise_flags(compiler, ins->flags);
break;
@@ -1835,25 +1882,25 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler,
vkd3d_string_buffer_printf(buffer, " %sc%u%s", compiler->colours.reg,
shader_get_float_offset(ins->dst[0].reg.type, ins->dst[0].reg.idx[0].offset),
compiler->colours.reset);
- shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_float[0], "");
- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[1], "");
- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[2], "");
- shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[3], "");
+ shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_f32[0], "");
+ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[1], "");
+ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[2], "");
+ shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[3], "");
break;
case VKD3DSIH_DEFI:
vkd3d_string_buffer_printf(buffer, " %si%u%s", compiler->colours.reg,
ins->dst[0].reg.idx[0].offset, compiler->colours.reset);
- shader_print_int_literal(compiler, " = ", ins->src[0].reg.u.immconst_uint[0], "");
- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[1], "");
- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[2], "");
- shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[3], "");
+ shader_print_int_literal(compiler, " = ", ins->src[0].reg.u.immconst_u32[0], "");
+ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[1], "");
+ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[2], "");
+ shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[3], "");
break;
case VKD3DSIH_DEFB:
vkd3d_string_buffer_printf(buffer, " %sb%u%s", compiler->colours.reg,
ins->dst[0].reg.idx[0].offset, compiler->colours.reset);
- shader_print_bool_literal(compiler, " = ", ins->src[0].reg.u.immconst_uint[0], "");
+ shader_print_bool_literal(compiler, " = ", ins->src[0].reg.u.immconst_u32[0], "");
break;
default:
@@ -1883,7 +1930,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler,
|| ins->resource_data_type[1] != VKD3D_DATA_FLOAT
|| ins->resource_data_type[2] != VKD3D_DATA_FLOAT
|| ins->resource_data_type[3] != VKD3D_DATA_FLOAT)
- shader_dump_data_type(compiler, ins->resource_data_type);
+ shader_dump_resource_data_type(compiler, ins->resource_data_type);
for (i = 0; i < ins->dst_count; ++i)
{
@@ -1906,10 +1953,13 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler,
enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions,
const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info,
- struct vkd3d_shader_code *out)
+ struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect)
{
enum vkd3d_shader_compile_option_formatting_flags formatting;
- struct vkd3d_d3d_asm_compiler compiler;
+ struct vkd3d_d3d_asm_compiler compiler =
+ {
+ .dialect = dialect,
+ };
enum vkd3d_result result = VKD3D_OK;
struct vkd3d_string_buffer *buffer;
unsigned int indent, i, j;
@@ -2002,6 +2052,7 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instructio
{
case VKD3DSIH_ELSE:
case VKD3DSIH_IF:
+ case VKD3DSIH_IFC:
case VKD3DSIH_LOOP:
case VKD3DSIH_SWITCH:
++indent;
@@ -2034,7 +2085,7 @@ void vkd3d_shader_trace(const struct vkd3d_shader_instruction_array *instruction
const char *p, *q, *end;
struct vkd3d_shader_code code;
- if (vkd3d_dxbc_binary_to_text(instructions, shader_version, NULL, &code) != VKD3D_OK)
+ if (vkd3d_dxbc_binary_to_text(instructions, shader_version, NULL, &code, VSIR_ASM_VSIR) != VKD3D_OK)
return;
end = (const char *)code.code + code.size;
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
index 3d139416b61..ca6e3b72de9 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
@@ -987,7 +987,7 @@ static void shader_sm1_read_immconst(struct vkd3d_shader_sm1_parser *sm1, const
src_param->reg.idx[2].rel_addr = NULL;
src_param->reg.idx_count = 0;
src_param->reg.dimension = dimension;
- memcpy(src_param->reg.u.immconst_uint, *ptr, count * sizeof(uint32_t));
+ memcpy(src_param->reg.u.immconst_u32, *ptr, count * sizeof(uint32_t));
src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE;
src_param->modifiers = 0;
@@ -1063,12 +1063,12 @@ static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1,
}
}
-static unsigned int mask_from_swizzle(unsigned int swizzle)
+static unsigned int mask_from_swizzle(uint32_t swizzle)
{
- return (1u << vkd3d_swizzle_get_component(swizzle, 0))
- | (1u << vkd3d_swizzle_get_component(swizzle, 1))
- | (1u << vkd3d_swizzle_get_component(swizzle, 2))
- | (1u << vkd3d_swizzle_get_component(swizzle, 3));
+ return (1u << vsir_swizzle_get_component(swizzle, 0))
+ | (1u << vsir_swizzle_get_component(swizzle, 1))
+ | (1u << vsir_swizzle_get_component(swizzle, 2))
+ | (1u << vsir_swizzle_get_component(swizzle, 3));
}
static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, struct vkd3d_shader_instruction *ins)
@@ -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/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c
index 7834c1e1615..63deaaad29a 100644
--- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c
+++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c
@@ -431,10 +431,6 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s
case TAG_OSG5:
if (e[i].sysval_semantic == VKD3D_SHADER_SV_NONE)
e[i].sysval_semantic = map_fragment_output_sysval(e[i].semantic_name);
- /* Fall through. */
- case TAG_PCSG:
- case TAG_PSG1:
- e[i].used_mask = e[i].mask & ~e[i].used_mask;
break;
}
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
index beb9ae574dc..2424b176068 100644
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
@@ -29,6 +29,9 @@ static const uint64_t MAX_ALIGNMENT_EXPONENT = 29;
static const uint64_t GLOBALVAR_FLAG_IS_CONSTANT = 1;
static const uint64_t GLOBALVAR_FLAG_EXPLICIT_TYPE = 2;
static const unsigned int GLOBALVAR_ADDRESS_SPACE_SHIFT = 2;
+static const uint64_t ALLOCA_FLAG_IN_ALLOCA = 0x20;
+static const uint64_t ALLOCA_FLAG_EXPLICIT_TYPE = 0x40;
+static const uint64_t ALLOCA_ALIGNMENT_MASK = ALLOCA_FLAG_IN_ALLOCA - 1;
static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4;
static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64};
@@ -296,8 +299,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 +462,7 @@ struct dxil_record
{
unsigned int code;
unsigned int operand_count;
+ const struct dxil_record *attachment;
uint64_t operands[];
};
@@ -581,6 +605,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 +821,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 +1038,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)
@@ -1210,7 +1237,7 @@ static size_t dxil_block_compute_module_decl_count(const struct dxil_block *bloc
size_t i, count;
for (i = 0, count = 0; i < block->record_count; ++i)
- count += block->records[i]->code == MODULE_CODE_FUNCTION;
+ count += block->records[i]->code == MODULE_CODE_FUNCTION || block->records[i]->code == MODULE_CODE_GLOBALVAR;
return count;
}
@@ -1572,6 +1599,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 +1619,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;
@@ -1844,12 +1886,12 @@ static unsigned int register_get_uint_value(const struct vkd3d_shader_register *
if (reg->type == VKD3DSPR_IMMCONST64)
{
- if (reg->u.immconst_uint64[0] > UINT_MAX)
+ if (reg->u.immconst_u64[0] > UINT_MAX)
FIXME("Truncating 64-bit value.\n");
- return reg->u.immconst_uint64[0];
+ return reg->u.immconst_u64[0];
}
- return reg->u.immconst_uint[0];
+ return reg->u.immconst_u32[0];
}
static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *reg)
@@ -1860,7 +1902,7 @@ static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *re
if (reg->dimension == VSIR_DIMENSION_VEC4)
WARN("Returning vec4.x.\n");
- return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_uint64[0] : reg->u.immconst_uint[0];
+ return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_u64[0] : reg->u.immconst_u32[0];
}
static inline bool sm6_value_is_function_dcl(const struct sm6_value *value)
@@ -2412,7 +2454,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 +2475,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 +2557,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;
@@ -2532,9 +2577,9 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const
value = decode_rotated_signed_value(record->operands[0]);
if (type->u.width <= 32)
- dst->u.reg.u.immconst_uint[0] = value & ((1ull << type->u.width) - 1);
+ dst->u.reg.u.immconst_u32[0] = value & ((1ull << type->u.width) - 1);
else
- dst->u.reg.u.immconst_uint64[0] = value;
+ dst->u.reg.u.immconst_u64[0] = value;
break;
@@ -2551,9 +2596,9 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const
if (type->u.width == 16)
FIXME("Half float type is not supported yet.\n");
else if (type->u.width == 32)
- dst->u.reg.u.immconst_float[0] = bitcast_uint64_to_float(record->operands[0]);
+ dst->u.reg.u.immconst_f32[0] = bitcast_uint64_to_float(record->operands[0]);
else if (type->u.width == 64)
- dst->u.reg.u.immconst_double[0] = bitcast_uint64_to_double(record->operands[0]);
+ dst->u.reg.u.immconst_f64[0] = bitcast_uint64_to_double(record->operands[0]);
else
vkd3d_unreachable();
@@ -2588,6 +2633,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,13 +2678,28 @@ static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_pa
return ins;
}
-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)
+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_INDEXABLE_TEMP);
+ 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 vkd3d_shader_instruction *ins,
+ struct sm6_value *dst)
+{
+ enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type);
+
+ if (ins)
+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_DCL_INDEXABLE_TEMP);
+ else
+ ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_INDEXABLE_TEMP);
ins->declaration.indexable_temp.register_idx = sm6->indexable_temp_count++;
ins->declaration.indexable_temp.register_size = count;
ins->declaration.indexable_temp.alignment = alignment;
@@ -2762,7 +2829,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, NULL, dst);
}
else if (address_space == ADDRESS_SPACE_GROUPSHARED)
{
@@ -2790,31 +2860,37 @@ static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_init
assert(index);
--index;
- if (!(value = sm6_parser_get_value_safe(sm6, index)) || !sm6_value_is_icb(value))
+ if (!(value = sm6_parser_get_value_safe(sm6, index)) || (!sm6_value_is_icb(value) && !sm6_value_is_undef(value)))
{
WARN("Invalid initialiser index %zu.\n", index);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
"Global variable initialiser value index %zu is invalid.", index);
return NULL;
}
- else
+ else if (sm6_value_is_icb(value))
{
return value->u.icb;
}
+ /* In VSIR, initialisation with undefined values of objects is implied, not explicit. */
+ return NULL;
}
static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6)
{
+ size_t i, count, base_value_idx = sm6->value_count;
const struct dxil_block *block = &sm6->root_block;
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;
+ for (i = 0, count = 0; i < block->record_count; ++i)
+ count += block->records[i]->code == MODULE_CODE_GLOBALVAR;
+ sm6_parser_require_space(sm6, count);
+
for (i = 0; i < block->record_count; ++i)
{
sm6->p.location.column = i;
@@ -2868,6 +2944,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;
@@ -2908,45 +2999,6 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade
}
}
-static void sm6_parser_emit_signature(struct sm6_parser *sm6, const struct shader_signature *s,
- enum vkd3d_shader_opcode handler_idx, enum vkd3d_shader_opcode siv_handler_idx,
- struct vkd3d_shader_dst_param *params)
-{
- struct vkd3d_shader_instruction *ins;
- struct vkd3d_shader_dst_param *param;
- const struct signature_element *e;
- unsigned int i;
-
- for (i = 0; i < s->element_count; ++i)
- {
- e = &s->elements[i];
-
- /* Do not check e->used_mask because in some cases it is zero for used elements.
- * TODO: scan ahead for used I/O elements. */
-
- if (e->sysval_semantic != VKD3D_SHADER_SV_NONE && e->sysval_semantic != VKD3D_SHADER_SV_TARGET)
- {
- ins = sm6_parser_add_instruction(sm6, siv_handler_idx);
- param = &ins->declaration.register_semantic.reg;
- ins->declaration.register_semantic.sysval_semantic = vkd3d_siv_from_sysval(e->sysval_semantic);
- }
- else
- {
- ins = sm6_parser_add_instruction(sm6, handler_idx);
- param = &ins->declaration.dst;
- }
-
- ins->flags = e->interpolation_mode;
- *param = params[i];
-
- if (e->register_count > 1)
- {
- param->reg.idx[0].rel_addr = NULL;
- param->reg.idx[0].offset = e->register_count;
- }
- }
-}
-
static void sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature)
{
sm6_parser_init_signature(sm6, output_signature, VKD3DSPR_OUTPUT, sm6->output_params);
@@ -2957,19 +3009,6 @@ static void sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct
sm6_parser_init_signature(sm6, input_signature, VKD3DSPR_INPUT, sm6->input_params);
}
-static void sm6_parser_emit_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature)
-{
- sm6_parser_emit_signature(sm6, output_signature, VKD3DSIH_DCL_OUTPUT, VKD3DSIH_DCL_OUTPUT_SIV, sm6->output_params);
-}
-
-static void sm6_parser_emit_input_signature(struct sm6_parser *sm6, const struct shader_signature *input_signature)
-{
- sm6_parser_emit_signature(sm6, input_signature,
- (sm6->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3DSIH_DCL_INPUT_PS : VKD3DSIH_DCL_INPUT,
- (sm6->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3DSIH_DCL_INPUT_PS_SIV : VKD3DSIH_DCL_INPUT_SIV,
- sm6->input_params);
-}
-
static const struct sm6_value *sm6_parser_next_function_definition(struct sm6_parser *sm6)
{
size_t i, count = sm6->function_count;
@@ -2992,6 +3031,81 @@ static struct sm6_block *sm6_block_create()
return block;
}
+static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_record *record,
+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst)
+{
+ const struct sm6_type *type[2], *elem_type;
+ const struct sm6_value *size;
+ unsigned int i, alignment;
+ uint64_t packed_operands;
+
+ if (!dxil_record_validate_operand_count(record, 4, 4, sm6))
+ return;
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (!(type[i] = sm6_parser_get_type(sm6, record->operands[i])))
+ return;
+ }
+
+ packed_operands = record->operands[3];
+ if (packed_operands & ALLOCA_FLAG_IN_ALLOCA)
+ WARN("Ignoring in_alloca flag.\n");
+ if (!(packed_operands & ALLOCA_FLAG_EXPLICIT_TYPE))
+ {
+ FIXME("Unhandled implicit type.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Implicit result type for ALLOCA instructions is not supported.");
+ return;
+ }
+ packed_operands &= ~(ALLOCA_FLAG_IN_ALLOCA | ALLOCA_FLAG_EXPLICIT_TYPE);
+
+ if (!sm6_type_is_array(type[0]) || !sm6_type_is_numeric(elem_type = type[0]->u.array.elem_type))
+ {
+ WARN("Type is not a numeric array.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Result type of an ALLOCA instruction is not a numeric array.");
+ return;
+ }
+ /* The second type operand is the type of the allocation size operand, in case it is a
+ * forward reference. We only support a constant size, so no forward ref support is needed. */
+ if (!sm6_type_is_integer(type[1]))
+ {
+ WARN("Size operand type is not scalar integer.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "The type of the allocation size operand of an ALLOCA instruction is not scalar integer.");
+ return;
+ }
+
+ if (!(dst->type = sm6_type_get_pointer_to_type(type[0], ADDRESS_SPACE_DEFAULT, sm6)))
+ {
+ WARN("Failed to get pointer type for type class %u.\n", type[0]->class);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE,
+ "Module does not define a pointer type for an ALLOCA instruction.");
+ return;
+ }
+
+ if (!(size = sm6_parser_get_value_safe(sm6, record->operands[2])))
+ return;
+ /* A size of 1 means one instance of type[0], i.e. one array. */
+ if (sm6_value_get_constant_uint(size) != 1)
+ {
+ FIXME("Allocation size is not 1.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "ALLOCA instruction allocation sizes other than 1 are not supported.");
+ return;
+ }
+
+ if (!bitcode_parse_alignment(packed_operands & ALLOCA_ALIGNMENT_MASK, &alignment))
+ WARN("Invalid alignment %"PRIu64".\n", packed_operands);
+ packed_operands &= ~ALLOCA_ALIGNMENT_MASK;
+
+ if (packed_operands)
+ WARN("Ignoring flags %#"PRIx64".\n", packed_operands);
+
+ sm6_parser_declare_indexable_temp(sm6, elem_type, type[0]->u.array.count, alignment, 0, ins, dst);
+}
+
static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_type *type_a,
const struct sm6_type *type_b, struct sm6_parser *sm6)
{
@@ -3092,8 +3206,10 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco
unsigned int i = 0;
a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i);
+ if (!a)
+ return;
b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i);
- if (!a || !b)
+ if (!b)
return;
if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6))
@@ -3167,10 +3283,77 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco
}
else
{
+ if (handler_idx == VKD3DSIH_ISHL || handler_idx == VKD3DSIH_ISHR || handler_idx == VKD3DSIH_USHR)
+ {
+ /* DXC emits AND instructions where necessary to mask shift counts. Shift binops
+ * do not imply masking the shift as the TPF equivalents do. */
+ ins->flags |= VKD3DSI_SHIFT_UNMASKED;
+ }
instruction_dst_param_init_ssa_scalar(ins, sm6);
}
}
+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 +3527,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 +3538,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 +3596,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 +3617,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 +3636,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 +3928,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;
}
@@ -3775,8 +4006,10 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor
}
a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i);
+ if (!a)
+ return;
b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i);
- if (!a || !b)
+ if (!b)
return;
if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6))
@@ -4065,6 +4298,57 @@ static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record
ins->handler_idx = VKD3DSIH_NOP;
}
+static void sm6_parser_emit_store(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;
+ struct vkd3d_shader_dst_param *dst_param;
+ const struct sm6_type *pointee_type;
+ const struct sm6_value *ptr, *src;
+ unsigned int i = 0, alignment;
+ uint64_t alignment_code;
+
+ if (!(ptr = sm6_parser_get_value_by_ref(sm6, record, NULL, &i))
+ || !sm6_value_validate_is_register(ptr, sm6)
+ || !sm6_value_validate_is_pointer(ptr, sm6))
+ {
+ return;
+ }
+
+ pointee_type = ptr->type->u.pointer.type;
+ if (!(src = sm6_parser_get_value_by_ref(sm6, record, pointee_type, &i)))
+ return;
+ if (!sm6_value_validate_is_numeric(src, sm6))
+ return;
+
+ if (pointee_type != src->type)
+ {
+ WARN("Type mismatch.\n");
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH,
+ "Type mismatch in pointer store arguments.");
+ }
+
+ if (!dxil_record_validate_operand_count(record, i + 2, i + 2, sm6))
+ return;
+
+ alignment_code = record->operands[i++];
+ if (!bitcode_parse_alignment(alignment_code, &alignment))
+ WARN("Invalid alignment %"PRIu64".\n", alignment_code);
+
+ if (record->operands[i])
+ WARN("Ignoring volatile modifier.\n");
+
+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV);
+
+ src_param = instruction_src_params_alloc(ins, 1, sm6);
+ src_param_init_from_value(&src_param[0], src);
+
+ dst_param = instruction_dst_params_alloc(ins, 1, sm6);
+ dst_param_init(dst_param);
+ dst_param->reg = ptr->u.reg;
+ dst_param->reg.alignment = alignment;
+}
+
static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_record *record,
struct vkd3d_shader_instruction *ins, struct sm6_value *dst)
{
@@ -4153,6 +4437,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)
{
@@ -4240,6 +4726,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const
record = block->records[i];
switch (record->code)
{
+ case FUNC_CODE_INST_ALLOCA:
+ sm6_parser_emit_alloca(sm6, record, ins, dst);
+ break;
case FUNC_CODE_INST_BINOP:
sm6_parser_emit_binop(sm6, record, ins, dst);
break;
@@ -4266,6 +4755,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const
is_terminator = true;
ret_found = true;
break;
+ case FUNC_CODE_INST_STORE:
+ sm6_parser_emit_store(sm6, record, ins, dst);
+ break;
case FUNC_CODE_INST_VSELECT:
sm6_parser_emit_vselect(sm6, record, ins, dst);
break;
@@ -4278,6 +4770,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 +4826,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:
@@ -4645,7 +5142,7 @@ static const enum vkd3d_shader_sysval_semantic sysval_semantic_table[] =
{
[SEMANTIC_KIND_ARBITRARY] = VKD3D_SHADER_SV_NONE,
[SEMANTIC_KIND_POSITION] = VKD3D_SHADER_SV_POSITION,
- [SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_NONE,
+ [SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_TARGET,
};
static enum vkd3d_shader_sysval_semantic sysval_semantic_from_dxil_semantic_kind(enum dxil_semantic_kind kind)
@@ -5538,7 +6035,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
if ((magic = sm6->start[0]) != BITCODE_MAGIC)
{
WARN("Unknown magic number 0x%08x.\n", magic);
- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER,
+ vkd3d_shader_warning(message_context, &location, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER,
"DXIL bitcode chunk magic number 0x%08x is not the expected 0x%08x.", magic, BITCODE_MAGIC);
}
@@ -5547,7 +6044,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
if ((version.type = version_token >> 16) >= VKD3D_SHADER_TYPE_COUNT)
{
FIXME("Unknown shader type %#x.\n", version.type);
- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE,
+ vkd3d_shader_warning(message_context, &location, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE,
"Unknown shader type %#x.", version.type);
}
@@ -5573,10 +6070,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
if ((ret = dxil_block_init(block, NULL, sm6)) < 0)
{
if (ret == VKD3D_ERROR_OUT_OF_MEMORY)
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory parsing DXIL bitcode chunk.");
else if (ret == VKD3D_ERROR_INVALID_SHADER)
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_BITCODE,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_BITCODE,
"DXIL bitcode chunk has invalid bitcode.");
else
vkd3d_unreachable();
@@ -5606,10 +6103,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
if ((ret = sm6_parser_type_table_init(sm6)) < 0)
{
if (ret == VKD3D_ERROR_OUT_OF_MEMORY)
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory parsing DXIL type table.");
else if (ret == VKD3D_ERROR_INVALID_SHADER)
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_TYPE_TABLE,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_TYPE_TABLE,
"DXIL type table is invalid.");
else
vkd3d_unreachable();
@@ -5619,10 +6116,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
if ((ret = sm6_parser_symtab_init(sm6)) < 0)
{
if (ret == VKD3D_ERROR_OUT_OF_MEMORY)
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory parsing DXIL value symbol table.");
else if (ret == VKD3D_ERROR_INVALID_SHADER)
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_VALUE_SYMTAB,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_VALUE_SYMTAB,
"DXIL value symbol table is invalid.");
else
vkd3d_unreachable();
@@ -5633,7 +6130,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
|| !(sm6->input_params = shader_parser_get_dst_params(&sm6->p, input_signature->element_count)))
{
ERR("Failed to allocate input/output parameters.\n");
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory allocating input/output parameters.");
return VKD3D_ERROR_OUT_OF_MEMORY;
}
@@ -5642,7 +6139,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
if (!(sm6->functions = vkd3d_calloc(function_count, sizeof(*sm6->functions))))
{
ERR("Failed to allocate function array.\n");
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory allocating DXIL function array.");
return VKD3D_ERROR_OUT_OF_MEMORY;
}
@@ -5650,14 +6147,14 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
if (sm6_parser_compute_max_value_count(sm6, &sm6->root_block, 0) == SIZE_MAX)
{
WARN("Value array count overflowed.\n");
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE,
"Overflow occurred in the DXIL module value count.");
return VKD3D_ERROR_INVALID_SHADER;
}
if (!(sm6->values = vkd3d_calloc(sm6->value_capacity, sizeof(*sm6->values))))
{
ERR("Failed to allocate value array.\n");
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory allocating DXIL value array.");
return VKD3D_ERROR_OUT_OF_MEMORY;
}
@@ -5684,7 +6181,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
if (j == ARRAY_SIZE(sm6->metadata_tables))
{
FIXME("Too many metadata tables.\n");
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA,
"A metadata table count greater than %zu is unsupported.", ARRAY_SIZE(sm6->metadata_tables));
return VKD3D_ERROR_INVALID_SHADER;
}
@@ -5702,22 +6199,20 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
if ((ret = sm6_parser_module_init(sm6, &sm6->root_block, 0)) < 0)
{
if (ret == VKD3D_ERROR_OUT_OF_MEMORY)
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory parsing DXIL module.");
else if (ret == VKD3D_ERROR_INVALID_SHADER)
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE,
"DXIL module is invalid.");
return ret;
}
if (!sm6_parser_require_space(sm6, output_signature->element_count + input_signature->element_count))
{
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory emitting shader signature declarations.");
return VKD3D_ERROR_OUT_OF_MEMORY;
}
- sm6_parser_emit_output_signature(sm6, output_signature);
- sm6_parser_emit_input_signature(sm6, input_signature);
sm6->p.shader_desc.ssa_count = sm6->ssa_next_id;
@@ -5732,7 +6227,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
assert(sm6->function_count == 1);
if (!sm6_block_emit_instructions(fn->blocks[0], sm6))
{
- vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory emitting shader instructions.");
return VKD3D_ERROR_OUT_OF_MEMORY;
}
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, &params, &instr->loc)))
+ if (!(resource_load = hlsl_new_resource_load(ctx, &params, &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..d38b3c39712 100644
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
@@ -63,7 +63,7 @@ static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_i
if (shader_register_is_phase_instance_id(reg))
{
vsir_register_init(reg, VKD3DSPR_IMMCONST, reg->data_type, 0);
- reg->u.immconst_uint[0] = instance_id;
+ reg->u.immconst_u32[0] = instance_id;
continue;
}
shader_register_eliminate_phase_addressing(reg, instance_id);
@@ -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:
@@ -590,19 +593,19 @@ struct signature_element *vsir_signature_find_element_for_reg(const struct shade
}
static unsigned int range_map_get_register_count(uint8_t range_map[][VKD3D_VEC4_SIZE],
- unsigned int register_idx, unsigned int write_mask)
+ unsigned int register_idx, uint32_t write_mask)
{
- return range_map[register_idx][vkd3d_write_mask_get_component_idx(write_mask)];
+ return range_map[register_idx][vsir_write_mask_get_component_idx(write_mask)];
}
static void range_map_set_register_range(uint8_t range_map[][VKD3D_VEC4_SIZE], unsigned int register_idx,
- unsigned int register_count, unsigned int write_mask, bool is_dcl_indexrange)
+ unsigned int register_count, uint32_t write_mask, bool is_dcl_indexrange)
{
unsigned int i, j, r, c, component_idx, component_count;
assert(write_mask <= VKD3DSP_WRITEMASK_ALL);
- component_idx = vkd3d_write_mask_get_component_idx(write_mask);
- component_count = vkd3d_write_mask_component_count(write_mask);
+ component_idx = vsir_write_mask_get_component_idx(write_mask);
+ component_count = vsir_write_mask_component_count(write_mask);
assert(register_idx < MAX_REG_OUTPUT && MAX_REG_OUTPUT - register_idx >= register_count);
@@ -896,7 +899,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par
element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask);
e = &signature->elements[element_idx];
- dst_param->write_mask >>= vkd3d_write_mask_get_component_idx(e->mask);
+ dst_param->write_mask >>= vsir_write_mask_get_component_idx(e->mask);
if (is_io_dcl)
{
/* Validated in the TPF reader. */
@@ -999,7 +1002,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par
id_idx = reg->idx_count - 1;
reg_idx = reg->idx[id_idx].offset;
- write_mask = VKD3DSP_WRITEMASK_0 << vkd3d_swizzle_get_component(src_param->swizzle, 0);
+ write_mask = VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(src_param->swizzle, 0);
element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask);
e = &signature->elements[element_idx];
@@ -1008,10 +1011,10 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par
reg->idx[id_idx].offset = element_idx;
reg->idx_count = id_idx + 1;
- if ((component_idx = vkd3d_write_mask_get_component_idx(e->mask)))
+ if ((component_idx = vsir_write_mask_get_component_idx(e->mask)))
{
for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
- if (vkd3d_swizzle_get_component(src_param->swizzle, i))
+ if (vsir_swizzle_get_component(src_param->swizzle, i))
src_param->swizzle -= component_idx << VKD3D_SHADER_SWIZZLE_SHIFT(i);
}
}
@@ -1215,7 +1218,7 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par
param->reg.idx_count = 0;
param->reg.dimension = VSIR_DIMENSION_VEC4;
for (j = 0; j < 4; ++j)
- param->reg.u.immconst_uint[j] = normaliser->defs[i].value[j];
+ param->reg.u.immconst_u32[j] = normaliser->defs[i].value[j];
return;
}
}
@@ -1251,7 +1254,7 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d
get_flat_constant_register_type((struct vkd3d_shader_register *)&ins->dst[0].reg, &def->set, &def->index);
for (j = 0; j < 4; ++j)
- def->value[j] = ins->src[0].reg.u.immconst_uint[j];
+ def->value[j] = ins->src[0].reg.u.immconst_u32[j];
vkd3d_shader_instruction_make_nop(ins);
}
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
index c8a43adbe03..387784f2358 100644
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
@@ -133,7 +133,7 @@ static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv,
}
}
-static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv,
+static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv,
enum vkd3d_shader_spirv_environment environment)
{
spv_diagnostic diagnostic = NULL;
@@ -145,12 +145,13 @@ static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv,
if ((ret = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t),
&diagnostic)))
{
- FIXME("Failed to validate SPIR-V binary, ret %d.\n", ret);
- FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error));
+ vkd3d_string_buffer_printf(buffer, "%s", diagnostic->error);
}
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
+
+ return !ret;
}
#else
@@ -163,8 +164,11 @@ static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_co
}
static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv,
enum vkd3d_shader_spirv_environment environment) {}
-static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv,
- enum vkd3d_shader_spirv_environment environment) {}
+static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv,
+ enum vkd3d_shader_spirv_environment environment)
+{
+ return true;
+}
#endif /* HAVE_SPIRV_TOOLS */
@@ -1194,6 +1198,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)
{
@@ -1783,6 +1797,8 @@ static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder,
break;
case VKD3D_SHADER_COMPONENT_DOUBLE:
return vkd3d_spirv_get_op_type_float(builder, 64);
+ case VKD3D_SHADER_COMPONENT_UINT64:
+ return vkd3d_spirv_get_op_type_int(builder, 64, 0);
default:
FIXME("Unhandled component type %#x.\n", component_type);
return 0;
@@ -1816,6 +1832,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_UINT64:
+ return vkd3d_spirv_get_op_type_int(builder, 64, 0);
case VKD3D_DATA_BOOL:
return vkd3d_spirv_get_op_type_bool(builder);
default:
@@ -2152,6 +2170,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:
@@ -2159,6 +2178,15 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol,
}
}
+static void vkd3d_symbol_make_io(struct vkd3d_symbol *symbol,
+ enum vkd3d_shader_register_type type, unsigned int index)
+{
+ symbol->type = VKD3D_SYMBOL_REGISTER;
+ memset(&symbol->key, 0, sizeof(symbol->key));
+ symbol->key.reg.type = type;
+ symbol->key.reg.idx = index;
+}
+
static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol,
uint32_t val_id, SpvStorageClass storage_class,
enum vkd3d_shader_component_type component_type, DWORD write_mask)
@@ -2376,12 +2404,15 @@ struct spirv_compiler
struct vkd3d_shader_spec_constant *spec_constants;
size_t spec_constants_size;
enum vkd3d_shader_compile_option_formatting_flags formatting;
+ enum vkd3d_shader_compile_option_feature_flags features;
bool write_tess_geom_point_size;
struct vkd3d_string_buffer_cache string_buffers;
struct ssa_register_info *ssa_register_info;
unsigned int ssa_register_count;
+
+ uint64_t config_flags;
};
static bool is_in_default_phase(const struct spirv_compiler *compiler)
@@ -2437,7 +2468,8 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler)
static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *shader_version,
struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info,
const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info,
- struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location)
+ struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location,
+ uint64_t config_flags)
{
const struct shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature;
const struct shader_signature *output_signature = &shader_desc->output_signature;
@@ -2454,6 +2486,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve
memset(compiler, 0, sizeof(*compiler));
compiler->message_context = message_context;
compiler->location = *location;
+ compiler->config_flags = config_flags;
if ((target_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO)))
{
@@ -2533,6 +2566,10 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve
WARN("Ignoring unrecognised value %#x for option %#x.\n", option->value, option->name);
break;
+ case VKD3D_SHADER_COMPILE_OPTION_FEATURE:
+ compiler->features = option->value;
+ break;
+
default:
WARN("Ignoring unrecognised option %#x with value %#x.\n", option->name, option->value);
break;
@@ -2955,7 +2992,7 @@ static uint32_t spirv_compiler_get_constant64(struct spirv_compiler *compiler,
assert(0 < component_count && component_count <= VKD3D_DVEC2_SIZE);
type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
- if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE)
+ if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE && component_type != VKD3D_SHADER_COMPONENT_UINT64)
{
FIXME("Unhandled component_type %#x.\n", component_type);
return vkd3d_spirv_get_op_undef(builder, type_id);
@@ -3015,14 +3052,21 @@ static uint32_t spirv_compiler_get_constant_double_vector(struct spirv_compiler
component_count, (const uint64_t *)values);
}
+static uint32_t spirv_compiler_get_constant_uint64_vector(struct spirv_compiler *compiler,
+ uint64_t value, unsigned int component_count)
+{
+ const uint64_t values[] = {value, value};
+ return spirv_compiler_get_constant64(compiler, VKD3D_SHADER_COMPONENT_UINT64, component_count, values);
+}
+
static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compiler,
- const struct vkd3d_shader_register *reg, DWORD write_mask)
+ const struct vkd3d_shader_register *reg, uint32_t write_mask)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
return vkd3d_spirv_get_type_id(builder,
vkd3d_component_type_from_data_type(reg->data_type),
- vkd3d_write_mask_component_count(write_mask));
+ vsir_write_mask_component_count(write_mask));
}
static uint32_t spirv_compiler_get_type_id_for_dst(struct spirv_compiler *compiler,
@@ -3498,7 +3542,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, &reg->idx[0]);
+ indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, &reg->idx[reg->idx_count - 1]);
}
else if (reg->type == VKD3DSPR_IDXTEMP)
{
@@ -3530,7 +3574,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp
if (index_count)
{
- component_count = vkd3d_write_mask_component_count(register_info->write_mask);
+ component_count = vsir_write_mask_component_count(register_info->write_mask);
type_id = vkd3d_spirv_get_type_id(builder, register_info->component_type, component_count);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, register_info->storage_class, type_id);
register_info->id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id,
@@ -3562,24 +3606,24 @@ static bool vkd3d_swizzle_is_equal(unsigned int dst_write_mask,
return vkd3d_compact_swizzle(VKD3D_SHADER_NO_SWIZZLE, dst_write_mask) == vkd3d_compact_swizzle(swizzle, write_mask);
}
-static bool vkd3d_swizzle_is_scalar(unsigned int swizzle)
+static bool vkd3d_swizzle_is_scalar(uint32_t swizzle)
{
- unsigned int component_idx = vkd3d_swizzle_get_component(swizzle, 0);
- return vkd3d_swizzle_get_component(swizzle, 1) == component_idx
- && vkd3d_swizzle_get_component(swizzle, 2) == component_idx
- && vkd3d_swizzle_get_component(swizzle, 3) == component_idx;
+ unsigned int component_idx = vsir_swizzle_get_component(swizzle, 0);
+ return vsir_swizzle_get_component(swizzle, 1) == component_idx
+ && vsir_swizzle_get_component(swizzle, 2) == component_idx
+ && vsir_swizzle_get_component(swizzle, 3) == component_idx;
}
static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler,
- uint32_t val_id, unsigned int val_write_mask, enum vkd3d_shader_component_type component_type,
- unsigned int swizzle, unsigned int write_mask)
+ uint32_t val_id, uint32_t val_write_mask, enum vkd3d_shader_component_type component_type,
+ uint32_t swizzle, uint32_t write_mask)
{
unsigned int i, component_idx, component_count, val_component_count;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id, components[VKD3D_VEC4_SIZE];
- component_count = vkd3d_write_mask_component_count(write_mask);
- val_component_count = vkd3d_write_mask_component_count(val_write_mask);
+ component_count = vsir_write_mask_component_count(write_mask);
+ val_component_count = vsir_write_mask_component_count(val_write_mask);
if (component_count == val_component_count
&& (component_count == 1 || vkd3d_swizzle_is_equal(val_write_mask, swizzle, write_mask)))
@@ -3589,9 +3633,9 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler,
if (component_count == 1)
{
- component_idx = vkd3d_write_mask_get_component_idx(write_mask);
- component_idx = vkd3d_swizzle_get_component(swizzle, component_idx);
- component_idx -= vkd3d_write_mask_get_component_idx(val_write_mask);
+ component_idx = vsir_write_mask_get_component_idx(write_mask);
+ component_idx = vsir_swizzle_get_component(swizzle, component_idx);
+ component_idx -= vsir_write_mask_get_component_idx(val_write_mask);
return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx);
}
@@ -3601,7 +3645,7 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler,
{
if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
{
- assert(VKD3DSP_WRITEMASK_0 << vkd3d_swizzle_get_component(swizzle, i) == val_write_mask);
+ assert(VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(swizzle, i) == val_write_mask);
components[component_idx++] = val_id;
}
}
@@ -3611,14 +3655,14 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler,
for (i = 0, component_idx = 0; i < VKD3D_VEC4_SIZE; ++i)
{
if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
- components[component_idx++] = vkd3d_swizzle_get_component(swizzle, i);
+ components[component_idx++] = vsir_swizzle_get_component(swizzle, i);
}
return vkd3d_spirv_build_op_vector_shuffle(builder,
type_id, val_id, val_id, components, component_count);
}
static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compiler,
- uint32_t vector1_id, uint32_t vector2_id, unsigned int swizzle, unsigned int write_mask,
+ uint32_t vector1_id, uint32_t vector2_id, uint32_t swizzle, uint32_t write_mask,
enum vkd3d_shader_component_type component_type, unsigned int component_count)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
@@ -3631,9 +3675,9 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil
for (i = 0; i < component_count; ++i)
{
if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
- components[i] = vkd3d_swizzle_get_component(swizzle, i);
+ components[i] = vsir_swizzle_get_component(swizzle, i);
else
- components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(swizzle, i);
+ components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(swizzle, i);
}
type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
@@ -3642,9 +3686,9 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil
}
static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler,
- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask)
+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask)
{
- unsigned int component_count = vkd3d_write_mask_component_count(write_mask);
+ unsigned int component_count = vsir_write_mask_component_count(write_mask);
uint32_t values[VKD3D_VEC4_SIZE] = {0};
unsigned int i, j;
@@ -3653,14 +3697,14 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile
if (reg->dimension == VSIR_DIMENSION_SCALAR)
{
for (i = 0; i < component_count; ++i)
- values[i] = *reg->u.immconst_uint;
+ values[i] = *reg->u.immconst_u32;
}
else
{
for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i)
{
if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
- values[j++] = reg->u.immconst_uint[vkd3d_swizzle_get_component(swizzle, i)];
+ values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)];
}
}
@@ -3669,9 +3713,9 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile
}
static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compiler,
- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask)
+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask)
{
- unsigned int component_count = vkd3d_write_mask_component_count(write_mask);
+ unsigned int component_count = vsir_write_mask_component_count(write_mask);
uint64_t values[VKD3D_DVEC2_SIZE] = {0};
unsigned int i, j;
@@ -3680,14 +3724,14 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi
if (reg->dimension == VSIR_DIMENSION_SCALAR)
{
for (i = 0; i < component_count; ++i)
- values[i] = *reg->u.immconst_uint64;
+ values[i] = *reg->u.immconst_u64;
}
else
{
for (i = 0, j = 0; i < VKD3D_DVEC2_SIZE; ++i)
{
if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
- values[j++] = reg->u.immconst_uint64[vkd3d_swizzle_get_component64(swizzle, i)];
+ values[j++] = reg->u.immconst_u64[vsir_swizzle_get_component64(swizzle, i)];
}
}
@@ -3696,9 +3740,9 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi
}
static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler,
- const struct vkd3d_shader_register *reg, DWORD write_mask)
+ const struct vkd3d_shader_register *reg, uint32_t write_mask)
{
- unsigned int component_count = vkd3d_write_mask_component_count(write_mask);
+ unsigned int component_count = vsir_write_mask_component_count(write_mask);
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id;
@@ -3709,28 +3753,28 @@ static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler,
}
static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler,
- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask,
+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask,
const struct vkd3d_shader_register_info *reg_info)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id, ptr_type_id, index, reg_id, val_id;
unsigned int component_idx, reg_component_count;
enum vkd3d_shader_component_type component_type;
- unsigned int skipped_component_mask;
+ uint32_t skipped_component_mask;
assert(!register_is_constant_or_undef(reg));
- assert(vkd3d_write_mask_component_count(write_mask) == 1);
+ assert(vsir_write_mask_component_count(write_mask) == 1);
- component_idx = vkd3d_write_mask_get_component_idx(write_mask);
- component_idx = vkd3d_swizzle_get_component(swizzle, component_idx);
+ component_idx = vsir_write_mask_get_component_idx(write_mask);
+ component_idx = vsir_swizzle_get_component(swizzle, component_idx);
skipped_component_mask = ~reg_info->write_mask & ((VKD3DSP_WRITEMASK_0 << component_idx) - 1);
if (skipped_component_mask)
- component_idx -= vkd3d_write_mask_component_count(skipped_component_mask);
+ component_idx -= vsir_write_mask_component_count(skipped_component_mask);
component_type = vkd3d_component_type_from_data_type(reg->data_type);
- reg_component_count = vkd3d_write_mask_component_count(reg_info->write_mask);
+ reg_component_count = vsir_write_mask_component_count(reg_info->write_mask);
- if (component_idx >= vkd3d_write_mask_component_count(reg_info->write_mask))
+ if (component_idx >= vsir_write_mask_component_count(reg_info->write_mask))
{
ERR("Invalid component_idx %u for register %#x, %u (write_mask %#x).\n",
component_idx, reg->type, reg->idx[0].offset, reg_info->write_mask);
@@ -3756,6 +3800,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)
{
@@ -3775,7 +3882,7 @@ static void spirv_compiler_set_ssa_register_info(const struct spirv_compiler *co
static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler,
const struct vkd3d_shader_register *reg, enum vkd3d_shader_component_type component_type,
- unsigned int swizzle)
+ uint32_t swizzle)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
enum vkd3d_shader_component_type reg_component_type;
@@ -3801,19 +3908,19 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler
}
type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
- component_idx = vkd3d_swizzle_get_component(swizzle, 0);
+ component_idx = vsir_swizzle_get_component(swizzle, 0);
return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx);
}
static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler,
- const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask)
+ const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
enum vkd3d_shader_component_type component_type;
struct vkd3d_shader_register_info reg_info;
unsigned int component_count;
- unsigned int write_mask32;
uint32_t type_id, val_id;
+ uint32_t write_mask32;
if (reg->type == VKD3DSPR_IMMCONST)
return spirv_compiler_emit_load_constant(compiler, reg, swizzle, write_mask);
@@ -3822,7 +3929,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler,
else if (reg->type == VKD3DSPR_UNDEF)
return spirv_compiler_emit_load_undef(compiler, reg, write_mask);
- component_count = vkd3d_write_mask_component_count(write_mask);
+ component_count = vsir_write_mask_component_count(write_mask);
component_type = vkd3d_component_type_from_data_type(reg->data_type);
if (reg->type == VKD3DSPR_SSA)
@@ -3836,21 +3943,21 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler,
assert(reg_info.component_type != VKD3D_SHADER_COMPONENT_DOUBLE);
spirv_compiler_emit_dereference_register(compiler, reg, &reg_info);
- write_mask32 = (reg->data_type == VKD3D_DATA_DOUBLE) ? vkd3d_write_mask_32_from_64(write_mask) : write_mask;
+ write_mask32 = data_type_is_64_bit(reg->data_type) ? vsir_write_mask_32_from_64(write_mask) : write_mask;
/* Intermediate value (no storage class). */
if (reg_info.storage_class == SpvStorageClassMax)
{
val_id = reg_info.id;
}
- else if (vkd3d_write_mask_component_count(write_mask32) == 1)
+ else if (vsir_write_mask_component_count(write_mask32) == 1)
{
return spirv_compiler_emit_load_scalar(compiler, reg, swizzle, write_mask, &reg_info);
}
else
{
type_id = vkd3d_spirv_get_type_id(builder,
- reg_info.component_type, vkd3d_write_mask_component_count(reg_info.write_mask));
+ reg_info.component_type, vsir_write_mask_component_count(reg_info.write_mask));
val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_info.id, SpvMemoryAccessMaskNone);
}
@@ -3904,7 +4011,7 @@ static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler,
type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask);
if (reg->data_type == VKD3D_DATA_FLOAT || reg->data_type == VKD3D_DATA_DOUBLE)
return vkd3d_spirv_build_op_fnegate(builder, type_id, val_id);
- else if (reg->data_type == VKD3D_DATA_INT || reg->data_type == VKD3D_DATA_UINT)
+ else if (data_type_is_integer(reg->data_type))
return vkd3d_spirv_build_op_snegate(builder, type_id, val_id);
FIXME("Unhandled data type %#x.\n", reg->data_type);
@@ -3953,19 +4060,19 @@ static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *co
}
static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler,
- uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type,
- SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id)
+ uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type,
+ SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id, ptr_type_id, index;
unsigned int component_idx;
- if (vkd3d_write_mask_component_count(dst_write_mask) > 1)
+ if (vsir_write_mask_component_count(dst_write_mask) > 1)
{
type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id);
- component_idx = vkd3d_write_mask_get_component_idx(write_mask);
- component_idx -= vkd3d_write_mask_get_component_idx(dst_write_mask);
+ component_idx = vsir_write_mask_get_component_idx(write_mask);
+ component_idx -= vsir_write_mask_get_component_idx(dst_write_mask);
index = spirv_compiler_get_constant_uint(compiler, component_idx);
dst_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, dst_id, index);
}
@@ -3974,8 +4081,8 @@ static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler,
}
static void spirv_compiler_emit_store(struct spirv_compiler *compiler,
- uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type,
- SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id)
+ uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type,
+ SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
unsigned int component_count, dst_component_count;
@@ -3985,14 +4092,14 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler,
assert(write_mask);
- component_count = vkd3d_write_mask_component_count(write_mask);
- dst_component_count = vkd3d_write_mask_component_count(dst_write_mask);
+ component_count = vsir_write_mask_component_count(write_mask);
+ dst_component_count = vsir_write_mask_component_count(dst_write_mask);
if (dst_component_count == 1 && component_count != 1)
{
type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
val_id = vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id,
- vkd3d_write_mask_get_component_idx(dst_write_mask));
+ vsir_write_mask_get_component_idx(dst_write_mask));
write_mask &= dst_write_mask;
component_count = 1;
}
@@ -4029,12 +4136,12 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler,
}
static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler,
- const struct vkd3d_shader_register *reg, unsigned int write_mask, uint32_t val_id)
+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
enum vkd3d_shader_component_type component_type;
struct vkd3d_shader_register_info reg_info;
- unsigned int src_write_mask = write_mask;
+ uint32_t src_write_mask = write_mask;
uint32_t type_id;
assert(!register_is_constant_or_undef(reg));
@@ -4052,10 +4159,10 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler,
component_type = vkd3d_component_type_from_data_type(reg->data_type);
if (component_type != reg_info.component_type)
{
- if (reg->data_type == VKD3D_DATA_DOUBLE)
- src_write_mask = vkd3d_write_mask_32_from_64(write_mask);
+ if (data_type_is_64_bit(reg->data_type))
+ src_write_mask = vsir_write_mask_32_from_64(write_mask);
type_id = vkd3d_spirv_get_type_id(builder, reg_info.component_type,
- vkd3d_write_mask_component_count(src_write_mask));
+ vsir_write_mask_component_count(src_write_mask));
val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id);
component_type = reg_info.component_type;
}
@@ -4065,9 +4172,9 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler,
}
static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler,
- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id)
+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id)
{
- unsigned int component_count = vkd3d_write_mask_component_count(write_mask);
+ unsigned int component_count = vsir_write_mask_component_count(write_mask);
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id, zero_id, one_id;
@@ -4118,7 +4225,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp
const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_component_type component_type,
uint32_t *component_ids)
{
- unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ unsigned int component_count = vsir_write_mask_component_count(dst->write_mask);
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id, val_id;
@@ -4137,16 +4244,16 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp
static void spirv_compiler_emit_store_dst_scalar(struct spirv_compiler *compiler,
const struct vkd3d_shader_dst_param *dst, uint32_t val_id,
- enum vkd3d_shader_component_type component_type, DWORD swizzle)
+ enum vkd3d_shader_component_type component_type, uint32_t swizzle)
{
- unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ unsigned int component_count = vsir_write_mask_component_count(dst->write_mask);
uint32_t component_ids[VKD3D_VEC4_SIZE];
unsigned int component_idx, i;
- component_idx = vkd3d_write_mask_get_component_idx(dst->write_mask);
+ component_idx = vsir_write_mask_get_component_idx(dst->write_mask);
for (i = 0; i < component_count; ++i)
{
- if (vkd3d_swizzle_get_component(swizzle, component_idx + i))
+ if (vsir_swizzle_get_component(swizzle, component_idx + i))
ERR("Invalid swizzle %#x for scalar value, write mask %#x.\n", swizzle, dst->write_mask);
component_ids[i] = val_id;
@@ -4191,14 +4298,18 @@ static void spirv_compiler_decorate_builtin(struct spirv_compiler *compiler,
}
static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler *compiler,
- uint32_t id, enum vkd3d_shader_interpolation_mode mode)
+ enum vkd3d_shader_component_type component_type, uint32_t id, enum vkd3d_shader_interpolation_mode mode)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
switch (mode)
{
case VKD3DSIM_NONE:
- break;
+ /* VUID-StandaloneSpirv-Flat-04744: integer or double types must be
+ * decorated 'Flat' for fragment shaders. */
+ if (compiler->shader_type != VKD3D_SHADER_TYPE_PIXEL || component_type == VKD3D_SHADER_COMPONENT_FLOAT)
+ break;
+ /* fall through */
case VKD3DSIM_CONSTANT:
vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationFlat, NULL, 0);
break;
@@ -4226,7 +4337,8 @@ static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler
}
static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler,
- enum vkd3d_shader_conditional_op condition, unsigned int component_count, uint32_t val_id)
+ enum vkd3d_shader_conditional_op condition, enum vkd3d_data_type data_type,
+ unsigned int component_count, uint32_t val_id)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id;
@@ -4237,7 +4349,9 @@ static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler,
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count);
op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual;
return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, val_id,
- spirv_compiler_get_constant_uint_vector(compiler, 0, component_count));
+ data_type == VKD3D_DATA_UINT64
+ ? spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count)
+ : spirv_compiler_get_constant_uint_vector(compiler, 0, component_count));
}
static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler,
@@ -4252,6 +4366,19 @@ static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler,
return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id);
}
+static uint32_t spirv_compiler_emit_bool_to_int64(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_uint64_vector(compiler, signedness ? UINT64_MAX : 1,
+ component_count);
+ false_id = spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count);
+ type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT64, 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)
{
@@ -4422,9 +4549,9 @@ vkd3d_register_builtins[] =
};
static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *compiler,
- const struct vkd3d_shader_register *reg)
+ enum vkd3d_shader_register_type type)
{
- switch (reg->type)
+ switch (type)
{
case VKD3DSPR_DEPTHOUTGE:
spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeDepthGreater, NULL, 0);
@@ -4437,9 +4564,9 @@ static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *c
VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT))
{
FIXME("The target environment does not support stencil export.\n");
- spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED,
- "Cannot export stencil reference value for register id %u. "
- "The target environment does not support stencil export.", reg->idx[0].offset);
+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE,
+ "Cannot export stencil reference value. "
+ "The target environment does not support stencil export.");
}
vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityStencilExportEXT);
spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeStencilRefReplacingEXT, NULL, 0);
@@ -4674,17 +4801,16 @@ static unsigned int shader_signature_next_location(const struct shader_signature
}
static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
- const struct vkd3d_shader_dst_param *dst)
+ enum vkd3d_shader_register_type reg_type, unsigned int element_idx)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
- const struct vkd3d_shader_register *reg = &dst->reg;
unsigned int component_idx, input_component_count;
const struct signature_element *signature_element;
const struct shader_signature *shader_signature;
enum vkd3d_shader_component_type component_type;
const struct vkd3d_spirv_builtin *builtin;
enum vkd3d_shader_sysval_semantic sysval;
- unsigned int write_mask, reg_write_mask;
+ uint32_t write_mask, reg_write_mask;
struct vkd3d_symbol *symbol = NULL;
uint32_t val_id, input_id, var_id;
uint32_t type_id, float_type_id;
@@ -4693,26 +4819,21 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
struct rb_entry *entry = NULL;
bool use_private_var = false;
unsigned int array_sizes[2];
- unsigned int element_idx;
-
- assert(!reg->idx_count || !reg->idx[0].rel_addr);
- assert(reg->idx_count < 2 || !reg->idx[1].rel_addr);
- shader_signature = reg->type == VKD3DSPR_PATCHCONST
+ shader_signature = reg_type == VKD3DSPR_PATCHCONST
? &compiler->patch_constant_signature : &compiler->input_signature;
- element_idx = reg->idx[reg->idx_count - 1].offset;
signature_element = &shader_signature->elements[element_idx];
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)
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN && reg_type != VKD3DSPR_PATCHCONST)
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[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)
&& (!vsir_sysval_semantic_is_clip_cull(signature_element->sysval_semantic) || array_sizes[0]))
@@ -4731,8 +4852,8 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
else
{
component_type = signature_element->component_type;
- input_component_count = vkd3d_write_mask_component_count(signature_element->mask);
- component_idx = vkd3d_write_mask_get_component_idx(signature_element->mask);
+ input_component_count = vsir_write_mask_component_count(signature_element->mask);
+ component_idx = vsir_write_mask_get_component_idx(signature_element->mask);
}
if (needs_private_io_variable(builtin))
@@ -4742,13 +4863,13 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
}
else
{
- component_idx = vkd3d_write_mask_get_component_idx(write_mask);
+ component_idx = vsir_write_mask_get_component_idx(write_mask);
reg_write_mask = write_mask >> component_idx;
}
storage_class = SpvStorageClassInput;
- vkd3d_symbol_make_register(&reg_symbol, reg);
+ vkd3d_symbol_make_io(&reg_symbol, reg_type, element_idx);
if ((entry = rb_get(&compiler->symbol_table, &reg_symbol)))
{
@@ -4756,7 +4877,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
* duplicate declarations are: a single register split into multiple declarations having
* different components, which should have been merged, and declarations in one phase
* being repeated in another (i.e. vcp/vocp), which should have been deleted. */
- if (reg->type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler))
+ if (reg_type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler))
FIXME("Duplicate input definition found.\n");
symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry);
return symbol->id;
@@ -4765,7 +4886,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
if (builtin)
{
input_id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, storage_class, array_sizes, 2);
- if (reg->type == VKD3DSPR_PATCHCONST)
+ if (reg_type == VKD3DSPR_PATCHCONST)
vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0);
}
else
@@ -4775,7 +4896,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
input_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream,
storage_class, component_type, input_component_count, array_sizes, 2);
vkd3d_spirv_add_iface_variable(builder, input_id);
- if (reg->type == VKD3DSPR_PATCHCONST)
+ if (reg_type == VKD3DSPR_PATCHCONST)
{
vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0);
location += shader_signature_next_location(&compiler->input_signature);
@@ -4784,7 +4905,8 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
if (component_idx)
vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationComponent, component_idx);
- spirv_compiler_emit_interpolation_decorations(compiler, input_id, signature_element->interpolation_mode);
+ spirv_compiler_emit_interpolation_decorations(compiler, component_type, input_id,
+ signature_element->interpolation_mode);
}
var_id = input_id;
@@ -4802,12 +4924,14 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
assert(!builtin || !builtin->spirv_array_size || use_private_var || array_sizes[0] || array_sizes[1]);
spirv_compiler_put_symbol(compiler, &reg_symbol);
- spirv_compiler_emit_register_debug_name(builder, var_id, reg);
+ vkd3d_spirv_build_op_name(builder, var_id, reg_type == VKD3DSPR_PATCHCONST ? "vpc%u" : "v%u", element_idx);
if (use_private_var)
{
- struct vkd3d_shader_register dst_reg = *reg;
- dst_reg.data_type = VKD3D_DATA_FLOAT;
+ struct vkd3d_shader_register dst_reg;
+
+ vsir_register_init(&dst_reg, reg_type, VKD3D_DATA_FLOAT, 1);
+ dst_reg.idx[0].offset = element_idx;
type_id = vkd3d_spirv_get_type_id(builder, component_type, input_component_count);
@@ -4824,9 +4948,9 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
val_id = spirv_compiler_emit_swizzle(compiler, val_id,
vkd3d_write_mask_from_component_count(input_component_count),
- VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, dst->write_mask >> component_idx);
+ VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, signature_element->mask >> component_idx);
- spirv_compiler_emit_store_reg(compiler, &dst_reg, dst->write_mask, val_id);
+ spirv_compiler_emit_store_reg(compiler, &dst_reg, signature_element->mask, val_id);
}
return input_id;
@@ -4896,7 +5020,7 @@ static void calculate_clip_or_cull_distance_mask(const struct signature_element
return;
}
- write_mask = e->mask >> vkd3d_write_mask_get_component_idx(e->mask);
+ write_mask = e->mask >> vsir_write_mask_get_component_idx(e->mask);
*mask |= (write_mask & VKD3DSP_WRITEMASK_ALL) << (VKD3D_VEC4_SIZE * e->semantic_index);
}
@@ -4995,7 +5119,7 @@ static void spirv_compiler_emit_output_register(struct spirv_compiler *compiler,
SpvStorageClassOutput, builtin->component_type, write_mask);
reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size;
spirv_compiler_put_symbol(compiler, &reg_symbol);
- spirv_compiler_emit_register_execution_mode(compiler, reg);
+ spirv_compiler_emit_register_execution_mode(compiler, reg->type);
spirv_compiler_emit_register_debug_name(builder, output_id, reg);
}
@@ -5024,46 +5148,44 @@ static uint32_t spirv_compiler_emit_shader_phase_builtin_variable(struct spirv_c
return id;
}
-static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const struct vkd3d_shader_dst_param *dst)
+static void spirv_compiler_emit_output(struct spirv_compiler *compiler,
+ enum vkd3d_shader_register_type reg_type, unsigned int element_idx)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
- const struct vkd3d_shader_register *reg = &dst->reg;
unsigned int component_idx, output_component_count;
const struct signature_element *signature_element;
enum vkd3d_shader_component_type component_type;
const struct shader_signature *shader_signature;
const struct vkd3d_spirv_builtin *builtin;
enum vkd3d_shader_sysval_semantic sysval;
- unsigned int write_mask, reg_write_mask;
+ uint32_t write_mask, reg_write_mask;
bool use_private_variable = false;
struct vkd3d_symbol reg_symbol;
SpvStorageClass storage_class;
unsigned int array_sizes[2];
- unsigned int element_idx;
bool is_patch_constant;
uint32_t id, var_id;
- is_patch_constant = is_in_fork_or_join_phase(compiler);
+ is_patch_constant = (reg_type == VKD3DSPR_PATCHCONST);
shader_signature = is_patch_constant ? &compiler->patch_constant_signature : &compiler->output_signature;
- element_idx = reg->idx[reg->idx_count - 1].offset;
signature_element = &shader_signature->elements[element_idx];
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_SHADER_SV_NONE;
- array_sizes[0] = (reg->type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count);
+ 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);
+ builtin = vkd3d_get_spirv_builtin(compiler, reg_type, sysval);
write_mask = signature_element->mask;
- component_idx = vkd3d_write_mask_get_component_idx(write_mask);
- output_component_count = vkd3d_write_mask_component_count(write_mask);
+ component_idx = vsir_write_mask_get_component_idx(write_mask);
+ output_component_count = vsir_write_mask_component_count(write_mask);
if (builtin)
{
component_type = builtin->component_type;
@@ -5077,15 +5199,18 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st
storage_class = SpvStorageClassOutput;
- if (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE
- || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask)
- || needs_private_io_variable(builtin))
+ if (needs_private_io_variable(builtin))
+ use_private_variable = true;
+
+ if (!is_patch_constant
+ && (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE
+ || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask)))
{
use_private_variable = true;
}
reg_write_mask = write_mask >> component_idx;
- vkd3d_symbol_make_register(&reg_symbol, reg);
+ vkd3d_symbol_make_io(&reg_symbol, reg_type, element_idx);
if (rb_get(&compiler->symbol_table, &reg_symbol))
{
@@ -5094,7 +5219,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st
return;
}
- if (compiler->output_info[element_idx].id)
+ if (!is_patch_constant && compiler->output_info[element_idx].id)
{
id = compiler->output_info[element_idx].id;
}
@@ -5105,7 +5230,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st
else
id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, storage_class, array_sizes, 2);
- spirv_compiler_emit_register_execution_mode(compiler, &dst->reg);
+ spirv_compiler_emit_register_execution_mode(compiler, reg_type);
}
else if (signature_element->target_location == SIGNATURE_TARGET_LOCATION_UNUSED)
{
@@ -5146,8 +5271,11 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st
spirv_compiler_decorate_xfb_output(compiler, id, output_component_count, signature_element);
- compiler->output_info[element_idx].id = id;
- compiler->output_info[element_idx].component_type = component_type;
+ if (!is_patch_constant)
+ {
+ compiler->output_info[element_idx].id = id;
+ compiler->output_info[element_idx].component_type = component_type;
+ }
var_id = id;
if (use_private_variable)
@@ -5165,8 +5293,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st
spirv_compiler_put_symbol(compiler, &reg_symbol);
- if (!is_patch_constant)
- spirv_compiler_emit_register_debug_name(builder, var_id, reg);
+ vkd3d_spirv_build_op_name(builder, var_id, reg_type == VKD3DSPR_PATCHCONST ? "vpc%u" : "o%u", element_idx);
if (use_private_variable)
{
@@ -5198,9 +5325,9 @@ static uint32_t spirv_compiler_get_output_array_index(struct spirv_compiler *com
static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compiler,
const struct shader_signature *signature, const struct signature_element *output,
const struct vkd3d_shader_output_info *output_info,
- uint32_t output_index_id, uint32_t val_id, unsigned int write_mask)
+ uint32_t output_index_id, uint32_t val_id, uint32_t write_mask)
{
- unsigned int dst_write_mask, use_mask, uninit_mask, swizzle, mask;
+ uint32_t dst_write_mask, use_mask, uninit_mask, swizzle, mask;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id, zero_id, ptr_type_id, chain_id, object_id;
const struct signature_element *element;
@@ -5222,7 +5349,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi
use_mask |= element->used_mask;
}
}
- index = vkd3d_write_mask_get_component_idx(output->mask);
+ index = vsir_write_mask_get_component_idx(output->mask);
dst_write_mask >>= index;
use_mask >>= index;
write_mask &= dst_write_mask;
@@ -5246,7 +5373,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi
output_info->component_type, VKD3D_VEC4_SIZE, 0);
val_id = spirv_compiler_emit_vector_shuffle(compiler,
zero_id, val_id, swizzle, uninit_mask, output_info->component_type,
- vkd3d_write_mask_component_count(write_mask));
+ vsir_write_mask_component_count(write_mask));
}
else
{
@@ -5258,7 +5385,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi
if (output_index_id)
{
type_id = vkd3d_spirv_get_type_id(builder,
- output_info->component_type, vkd3d_write_mask_component_count(dst_write_mask));
+ output_info->component_type, vsir_write_mask_component_count(dst_write_mask));
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id);
output_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, output_id, output_index_id);
}
@@ -5444,6 +5571,21 @@ static void spirv_compiler_emit_dcl_global_flags(struct spirv_compiler *compiler
flags &= ~(VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS | VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS);
}
+ if (flags & VKD3DSGF_ENABLE_INT64)
+ {
+ if (compiler->features & VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64)
+ {
+ vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityInt64);
+ }
+ else
+ {
+ WARN("Unsupported 64-bit integer ops.\n");
+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE,
+ "The target environment does not support 64-bit integers.");
+ }
+ flags &= ~VKD3DSGF_ENABLE_INT64;
+ }
+
if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS))
FIXME("Unhandled global flags %#"PRIx64".\n", (uint64_t)flags);
else
@@ -5493,39 +5635,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(&reg, 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, &reg);
vkd3d_spirv_end_function_stream_insertion(builder);
vkd3d_symbol_make_register(&reg_symbol, &reg);
- vkd3d_symbol_set_register_info(&reg_symbol, id,
- SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL);
+ vkd3d_symbol_set_register_info(&reg_symbol, id, storage_class,
+ component_type, vkd3d_write_mask_from_component_count(temp->component_count));
spirv_compiler_put_symbol(compiler, &reg_symbol);
}
@@ -5743,34 +5886,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(&reg, 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(&reg, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 2);
+ reg.idx[0].offset = icb->register_idx;
vkd3d_symbol_make_register(&reg_symbol, &reg);
vkd3d_symbol_set_register_info(&reg_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, &reg_symbol);
}
@@ -6147,37 +6280,22 @@ static void spirv_compiler_emit_dcl_input(struct spirv_compiler *compiler,
{
const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst;
- /* 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 if (dst->reg.type != VKD3DSPR_OUTPOINTID)
+ /* INPUT and PATCHCONST are handled in spirv_compiler_emit_io_declarations().
+ * OUTPOINTID is handled in spirv_compiler_emit_hull_shader_builtins(). */
+ if (dst->reg.type != VKD3DSPR_INPUT && dst->reg.type != VKD3DSPR_PATCHCONST
+ && dst->reg.type != VKD3DSPR_OUTPOINTID)
spirv_compiler_emit_input_register(compiler, dst);
}
-static void spirv_compiler_emit_dcl_input_sysval(struct spirv_compiler *compiler,
- const struct vkd3d_shader_instruction *instruction)
-{
- spirv_compiler_emit_input(compiler, &instruction->declaration.register_semantic.reg);
-}
-
static void spirv_compiler_emit_dcl_output(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst;
- 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
+ if (dst->reg.type != VKD3DSPR_OUTPUT && dst->reg.type != VKD3DSPR_PATCHCONST)
spirv_compiler_emit_output_register(compiler, dst);
}
-static void spirv_compiler_emit_dcl_output_siv(struct spirv_compiler *compiler,
- const struct vkd3d_shader_instruction *instruction)
-{
- spirv_compiler_emit_output(compiler, &instruction->declaration.register_semantic.reg);
-}
-
static void spirv_compiler_emit_dcl_stream(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
@@ -6377,7 +6495,6 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile
static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler)
{
- const struct shader_signature *signature = &compiler->output_signature;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
if (is_in_control_point_phase(compiler) && compiler->emit_default_control_point_phase)
@@ -6395,7 +6512,6 @@ static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler)
/* Fork and join phases share output registers (patch constants).
* 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_write_mask, 0, sizeof(compiler->private_output_variable_write_mask));
}
@@ -6438,15 +6554,12 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile
{
const struct shader_signature *output_signature = &compiler->output_signature;
const struct shader_signature *input_signature = &compiler->input_signature;
+ uint32_t type_id, output_ptr_type_id, input_id, dst_id, invocation_id;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
enum vkd3d_shader_component_type component_type;
struct vkd3d_shader_src_param invocation;
struct vkd3d_shader_register input_reg;
- uint32_t type_id, output_ptr_type_id;
- uint32_t input_id, output_id, dst_id;
unsigned int component_count;
- unsigned int array_sizes[2];
- uint32_t invocation_id;
unsigned int i;
invocation_id = spirv_compiler_emit_load_invocation_id(compiler);
@@ -6466,6 +6579,8 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile
{
const struct signature_element *output = &output_signature->elements[i];
const struct signature_element *input = &input_signature->elements[i];
+ struct vkd3d_shader_register_info output_reg_info;
+ struct vkd3d_shader_register output_reg;
assert(input->mask == output->mask);
assert(input->component_type == output->component_type);
@@ -6473,22 +6588,16 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile
input_reg.idx[1].offset = i;
input_id = spirv_compiler_get_register_id(compiler, &input_reg);
+ vsir_register_init(&output_reg, VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1);
+ output_reg.idx[0].offset = i;
+ spirv_compiler_get_register_info(compiler, &output_reg, &output_reg_info);
+
component_type = output->component_type;
- component_count = vkd3d_write_mask_component_count(output->mask);
+ component_count = vsir_write_mask_component_count(output->mask);
type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count);
- if ((array_sizes[0] = (input->register_count > 1) ? input->register_count : 0))
- type_id = vkd3d_spirv_get_op_type_array(builder, type_id, spirv_compiler_get_constant_uint(compiler,
- array_sizes[0]));
-
- array_sizes[1] = compiler->output_control_point_count;
- output_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, SpvStorageClassOutput,
- component_type, component_count, array_sizes, 2);
- vkd3d_spirv_add_iface_variable(builder, output_id);
- vkd3d_spirv_build_op_decorate1(builder, output_id, SpvDecorationLocation, output->register_index);
- vkd3d_spirv_build_op_name(builder, output_id, "vocp%u", output->register_index);
-
output_ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id);
- dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_id, invocation_id);
+
+ dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_reg_info.id, invocation_id);
vkd3d_spirv_build_op_copy_memory(builder, dst_id, input_id, SpvMemoryAccessMaskNone);
}
@@ -6593,12 +6702,14 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru
{VKD3DSIH_ISHR, SpvOpShiftRightArithmetic},
{VKD3DSIH_ITOD, SpvOpConvertSToF},
{VKD3DSIH_ITOF, SpvOpConvertSToF},
+ {VKD3DSIH_ITOI, SpvOpSConvert},
{VKD3DSIH_MUL, SpvOpFMul},
{VKD3DSIH_NOT, SpvOpNot},
{VKD3DSIH_OR, SpvOpBitwiseOr},
{VKD3DSIH_USHR, SpvOpShiftRightLogical},
{VKD3DSIH_UTOD, SpvOpConvertUToF},
{VKD3DSIH_UTOF, SpvOpConvertUToF},
+ {VKD3DSIH_UTOU, SpvOpUConvert},
{VKD3DSIH_XOR, SpvOpBitwiseXor},
};
unsigned int i;
@@ -6650,6 +6761,10 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler,
{
val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI);
}
+ else if (dst->reg.data_type == VKD3D_DATA_UINT64)
+ {
+ val_id = spirv_compiler_emit_bool_to_int64(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI);
+ }
else
{
WARN("Unhandled data type %u.\n", dst->reg.data_type);
@@ -6715,11 +6830,11 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil
* Microsoft fxc will compile immediate constants larger than 5 bits.
* Fixing up the constants would be more elegant, but the simplest way is
* to let this handle constants too. */
- if (instruction->handler_idx == VKD3DSIH_ISHL || instruction->handler_idx == VKD3DSIH_ISHR
- || instruction->handler_idx == VKD3DSIH_USHR)
+ if (!(instruction->flags & VKD3DSI_SHIFT_UNMASKED) && (instruction->handler_idx == VKD3DSIH_ISHL
+ || instruction->handler_idx == VKD3DSIH_ISHR || instruction->handler_idx == VKD3DSIH_USHR))
{
uint32_t mask_id = spirv_compiler_get_constant_vector(compiler,
- VKD3D_SHADER_COMPONENT_UINT, vkd3d_write_mask_component_count(dst->write_mask), 0x1f);
+ VKD3D_SHADER_COMPONENT_UINT, vsir_write_mask_component_count(dst->write_mask), 0x1f);
src_ids[1] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[1], mask_id);
}
@@ -6849,7 +6964,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler,
return;
}
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
if (component_count != 1 && component_count != VKD3D_VEC4_SIZE
&& dst_reg_info.write_mask == VKD3DSP_WRITEMASK_ALL)
{
@@ -6863,7 +6978,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler,
for (i = 0; i < ARRAY_SIZE(components); ++i)
{
if (dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))
- components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(src->swizzle, i);
+ components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(src->swizzle, i);
else
components[i] = i;
}
@@ -6877,6 +6992,11 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler,
general_implementation:
val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
+ if (dst->reg.data_type != src->reg.data_type)
+ {
+ val_id = vkd3d_spirv_build_op_bitcast(builder, vkd3d_spirv_get_type_id_for_data_type(builder,
+ dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)), val_id);
+ }
spirv_compiler_emit_store_dst(compiler, dst, val_id);
}
@@ -6893,12 +7013,12 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler,
src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask);
src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask);
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
type_id = spirv_compiler_get_type_id_for_dst(compiler, dst);
if (src[0].reg.data_type != VKD3D_DATA_BOOL)
condition_id = spirv_compiler_emit_int_to_bool(compiler,
- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id);
+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id);
val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id);
spirv_compiler_emit_store_dst(compiler, dst, val_id);
@@ -6919,11 +7039,11 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler,
src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask);
src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask);
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count);
condition_id = spirv_compiler_emit_int_to_bool(compiler,
- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id);
+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id);
val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src2_id, src1_id);
spirv_compiler_emit_store_dst(compiler, &dst[0], val_id);
@@ -6942,7 +7062,7 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler,
unsigned int component_count, i;
DWORD write_mask;
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
component_type = vkd3d_component_type_from_data_type(dst->reg.data_type);
if (instruction->handler_idx == VKD3DSIH_DP4)
@@ -6980,7 +7100,7 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler,
uint32_t type_id, src_id, val_id, div_id;
unsigned int component_count;
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
type_id = spirv_compiler_get_type_id_for_dst(compiler, dst);
src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
@@ -7060,7 +7180,7 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler,
uint32_t type_id, val_id, src_ids[3];
unsigned int i, component_count;
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, component_count);
for (i = 0; i < ARRAY_SIZE(src_ids); ++i)
@@ -7087,16 +7207,18 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler,
if (dst[0].reg.type != VKD3DSPR_NULL)
{
- component_count = vkd3d_write_mask_component_count(dst[0].write_mask);
+ component_count = vsir_write_mask_component_count(dst[0].write_mask);
type_id = spirv_compiler_get_type_id_for_dst(compiler, &dst[0]);
src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst[0].write_mask);
src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst[0].write_mask);
condition_id = spirv_compiler_emit_int_to_bool(compiler,
- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id);
- uint_max_id = spirv_compiler_get_constant_uint_vector(compiler,
- 0xffffffff, component_count);
+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src1_id);
+ if (dst[0].reg.data_type == VKD3D_DATA_UINT64)
+ uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count);
+ else
+ uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count);
val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, div_op, type_id, src0_id, src1_id);
/* The SPIR-V spec says: "The resulting value is undefined if Operand 2 is 0." */
@@ -7109,16 +7231,18 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler,
{
if (!component_count || dst[0].write_mask != dst[1].write_mask)
{
- component_count = vkd3d_write_mask_component_count(dst[1].write_mask);
+ component_count = vsir_write_mask_component_count(dst[1].write_mask);
type_id = spirv_compiler_get_type_id_for_dst(compiler, &dst[1]);
src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst[1].write_mask);
src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst[1].write_mask);
condition_id = spirv_compiler_emit_int_to_bool(compiler,
- VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id);
- uint_max_id = spirv_compiler_get_constant_uint_vector(compiler,
- 0xffffffff, component_count);
+ VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src1_id);
+ if (dst[1].reg.data_type == VKD3D_DATA_UINT64)
+ uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count);
+ else
+ uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count);
}
val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, mod_op, type_id, src0_id, src1_id);
@@ -7147,7 +7271,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler,
* as a signed integer, but Direct3D expects the result to saturate,
* and for NaN to yield zero. */
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask);
dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst);
src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
@@ -7200,7 +7324,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler,
* as an unsigned integer, but Direct3D expects the result to saturate,
* and for NaN to yield zero. */
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask);
dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst);
src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask);
@@ -7387,7 +7511,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co
return;
}
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask);
src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask);
@@ -7409,7 +7533,7 @@ static uint32_t spirv_compiler_emit_conditional_branch(struct spirv_compiler *co
uint32_t condition_id, merge_block_id;
condition_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0);
- condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, 1, condition_id);
+ condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, src->reg.data_type, 1, condition_id);
merge_block_id = vkd3d_spirv_alloc_id(builder);
@@ -7542,7 +7666,7 @@ static int spirv_compiler_emit_control_flow_instruction(struct spirv_compiler *c
return VKD3D_ERROR_OUT_OF_MEMORY;
val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0);
- condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, 1, val_id);
+ condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, src->reg.data_type, 1, val_id);
true_label = vkd3d_spirv_alloc_id(builder);
merge_block_id = vkd3d_spirv_alloc_id(builder);
@@ -7705,7 +7829,7 @@ static int spirv_compiler_emit_control_flow_instruction(struct spirv_compiler *c
"The swizzle for a switch case value is not scalar.");
}
assert(src->reg.type == VKD3DSPR_IMMCONST);
- value = *src->reg.u.immconst_uint;
+ value = *src->reg.u.immconst_u32;
if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size,
2 * (cf_info->u.switch_.case_block_count + 1), sizeof(*cf_info->u.switch_.case_blocks)))
@@ -8325,7 +8449,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler,
}
else
{
- component_idx = vkd3d_swizzle_get_component(sampler->swizzle, 0);
+ component_idx = vsir_swizzle_get_component(sampler->swizzle, 0);
/* Nvidia driver requires signed integer type. */
component_id = spirv_compiler_get_constant(compiler,
VKD3D_SHADER_COMPONENT_INT, 1, &component_idx);
@@ -8403,7 +8527,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler
if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
continue;
- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i);
+ component_idx = vsir_swizzle_get_component(resource->swizzle, i);
coordinate_id = base_coordinate_id;
if (component_idx)
coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
@@ -8435,7 +8559,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler
if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
continue;
- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i);
+ component_idx = vsir_swizzle_get_component(resource->swizzle, i);
coordinate_id = base_coordinate_id;
if (component_idx)
coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
@@ -8479,7 +8603,7 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler,
if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)))
continue;
- component_idx = vkd3d_swizzle_get_component(resource->swizzle, i);
+ component_idx = vsir_swizzle_get_component(resource->swizzle, i);
coordinate_id = base_coordinate_id;
if (component_idx)
coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id,
@@ -8540,7 +8664,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler *
assert(data->reg.data_type == VKD3D_DATA_UINT);
val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask);
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
for (component_idx = 0; component_idx < component_count; ++component_idx)
{
data_id = component_count > 1 ?
@@ -8569,7 +8693,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler *
assert(data->reg.data_type == VKD3D_DATA_UINT);
val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask);
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
for (component_idx = 0; component_idx < component_count; ++component_idx)
{
/* Mesa Vulkan drivers require the texel parameter to be a vector. */
@@ -8613,7 +8737,7 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler,
assert(data->reg.data_type == VKD3D_DATA_UINT);
val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask);
- component_count = vkd3d_write_mask_component_count(dst->write_mask);
+ component_count = vsir_write_mask_component_count(dst->write_mask);
for (component_idx = 0; component_idx < component_count; ++component_idx)
{
data_id = component_count > 1 ?
@@ -9275,7 +9399,7 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler,
}
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT,
- vkd3d_write_mask_component_count(register_info.write_mask));
+ vsir_write_mask_component_count(register_info.write_mask));
instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id, instr_set_id, op, src_ids, src_count);
@@ -9425,18 +9549,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_DCL_INPUT:
spirv_compiler_emit_dcl_input(compiler, instruction);
break;
- case VKD3DSIH_DCL_INPUT_PS_SGV:
- case VKD3DSIH_DCL_INPUT_PS_SIV:
- case VKD3DSIH_DCL_INPUT_SGV:
- case VKD3DSIH_DCL_INPUT_SIV:
- spirv_compiler_emit_dcl_input_sysval(compiler, instruction);
- break;
case VKD3DSIH_DCL_OUTPUT:
spirv_compiler_emit_dcl_output(compiler, instruction);
break;
- case VKD3DSIH_DCL_OUTPUT_SIV:
- spirv_compiler_emit_dcl_output_siv(compiler, instruction);
- break;
case VKD3DSIH_DCL_STREAM:
spirv_compiler_emit_dcl_stream(compiler, instruction);
break;
@@ -9719,6 +9834,11 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_DCL_CONSTANT_BUFFER:
case VKD3DSIH_DCL_HS_MAX_TESSFACTOR:
case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT:
+ case VKD3DSIH_DCL_INPUT_SGV:
+ case VKD3DSIH_DCL_INPUT_SIV:
+ case VKD3DSIH_DCL_INPUT_PS_SGV:
+ case VKD3DSIH_DCL_INPUT_PS_SIV:
+ case VKD3DSIH_DCL_OUTPUT_SIV:
case VKD3DSIH_DCL_RESOURCE_RAW:
case VKD3DSIH_DCL_RESOURCE_STRUCTURED:
case VKD3DSIH_DCL_SAMPLER:
@@ -9740,6 +9860,30 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
return ret;
}
+static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler)
+{
+ for (unsigned int i = 0; i < compiler->input_signature.element_count; ++i)
+ spirv_compiler_emit_input(compiler, VKD3DSPR_INPUT, i);
+
+ for (unsigned int i = 0; i < compiler->output_signature.element_count; ++i)
+ {
+ /* PS outputs other than TARGET have dedicated registers and therefore
+ * go through spirv_compiler_emit_dcl_output() for now. */
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL
+ && compiler->output_signature.elements[i].sysval_semantic != VKD3D_SHADER_SV_TARGET)
+ continue;
+ spirv_compiler_emit_output(compiler, VKD3DSPR_OUTPUT, i);
+ }
+
+ for (unsigned int i = 0; i < compiler->patch_constant_signature.element_count; ++i)
+ {
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL)
+ spirv_compiler_emit_output(compiler, VKD3DSPR_PATCHCONST, i);
+ else
+ spirv_compiler_emit_input(compiler, VKD3DSPR_PATCHCONST, i);
+ }
+}
+
static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *compiler)
{
unsigned int i;
@@ -9826,6 +9970,8 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL)
spirv_compiler_emit_shader_signature_outputs(compiler);
+ spirv_compiler_emit_io_declarations(compiler);
+
for (i = 0; i < instructions.count && result >= 0; ++i)
{
compiler->location.line = i + 1;
@@ -9874,11 +10020,28 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
if (!vkd3d_spirv_compile_module(builder, spirv, spirv_compiler_get_entry_point_name(compiler)))
return VKD3D_ERROR;
- if (TRACE_ON())
+ if (TRACE_ON() || parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)
{
enum vkd3d_shader_spirv_environment environment = spirv_compiler_get_target_environment(compiler);
- vkd3d_spirv_dump(spirv, environment);
- vkd3d_spirv_validate(spirv, environment);
+ struct vkd3d_string_buffer buffer;
+
+ if (TRACE_ON())
+ vkd3d_spirv_dump(spirv, environment);
+
+ vkd3d_string_buffer_init(&buffer);
+ if (!vkd3d_spirv_validate(&buffer, spirv, environment))
+ {
+ FIXME("Failed to validate SPIR-V binary.\n");
+ vkd3d_shader_trace_text(buffer.buffer, buffer.content_size);
+
+ if (compiler->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)
+ {
+ spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER,
+ "Execution generated an invalid shader, failing compilation:\n%s",
+ buffer.buffer);
+ }
+ }
+ vkd3d_string_buffer_cleanup(&buffer);
}
if (compiler->failed)
@@ -9905,7 +10068,7 @@ int spirv_compile(struct vkd3d_shader_parser *parser,
int ret;
if (!(spirv_compiler = spirv_compiler_create(&parser->shader_version, &parser->shader_desc,
- compile_info, scan_descriptor_info, message_context, &parser->location)))
+ compile_info, scan_descriptor_info, message_context, &parser->location, parser->config_flags)))
{
ERR("Failed to create SPIR-V compiler.\n");
return VKD3D_ERROR;
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
index 80f8ab98c08..f859e758d8e 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;
@@ -918,10 +920,11 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
{
struct vkd3d_shader_index_range *index_range = &ins->declaration.index_range;
- unsigned int i, register_idx, register_count, write_mask;
+ unsigned int i, register_idx, register_count;
enum vkd3d_shader_register_type type;
struct sm4_index_range_array *ranges;
unsigned int *io_masks;
+ uint32_t write_mask;
shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE,
&index_range->dst);
@@ -931,7 +934,7 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins
register_count = index_range->register_count;
write_mask = index_range->dst.write_mask;
- if (vkd3d_write_mask_component_count(write_mask) != 1)
+ if (vsir_write_mask_component_count(write_mask) != 1)
{
WARN("Unhandled write mask %#x.\n", write_mask);
vkd3d_shader_parser_warning(&priv->p, VKD3D_SHADER_WARNING_TPF_UNHANDLED_INDEX_RANGE_MASK,
@@ -1900,19 +1903,19 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui
if (register_type == VKD3D_SM4_RT_IMMCONST || register_type == VKD3D_SM4_RT_IMMCONST64)
{
- unsigned int dword_count;
+ unsigned int u32_count;
switch (param->dimension)
{
case VSIR_DIMENSION_SCALAR:
- dword_count = 1 + (register_type == VKD3D_SM4_RT_IMMCONST64);
- if (end - *ptr < dword_count)
+ u32_count = 1 + (register_type == VKD3D_SM4_RT_IMMCONST64);
+ if (end - *ptr < u32_count)
{
WARN("Invalid ptr %p, end %p.\n", *ptr, end);
return false;
}
- memcpy(param->u.immconst_uint, *ptr, dword_count * sizeof(DWORD));
- *ptr += dword_count;
+ memcpy(param->u.immconst_u32, *ptr, u32_count * sizeof(uint32_t));
+ *ptr += u32_count;
break;
case VSIR_DIMENSION_VEC4:
@@ -1921,7 +1924,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui
WARN("Invalid ptr %p, end %p.\n", *ptr, end);
return false;
}
- memcpy(param->u.immconst_uint, *ptr, VKD3D_VEC4_SIZE * sizeof(DWORD));
+ memcpy(param->u.immconst_u32, *ptr, VKD3D_VEC4_SIZE * sizeof(uint32_t));
*ptr += 4;
break;
@@ -1930,6 +1933,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
@@ -1970,10 +1982,10 @@ static uint32_t swizzle_from_sm4(uint32_t s)
static uint32_t swizzle_to_sm4(uint32_t s)
{
uint32_t ret = 0;
- ret |= ((vkd3d_swizzle_get_component(s, 0)) & 0x3);
- ret |= ((vkd3d_swizzle_get_component(s, 1)) & 0x3) << 2;
- ret |= ((vkd3d_swizzle_get_component(s, 2)) & 0x3) << 4;
- ret |= ((vkd3d_swizzle_get_component(s, 3)) & 0x3) << 6;
+ ret |= ((vsir_swizzle_get_component(s, 0)) & 0x3);
+ ret |= ((vsir_swizzle_get_component(s, 1)) & 0x3) << 2;
+ ret |= ((vsir_swizzle_get_component(s, 2)) & 0x3) << 4;
+ ret |= ((vsir_swizzle_get_component(s, 3)) & 0x3) << 6;
return ret;
}
@@ -2002,12 +2014,12 @@ static bool register_is_control_point_input(const struct vkd3d_shader_register *
|| priv->p.shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY));
}
-static unsigned int mask_from_swizzle(unsigned int swizzle)
+static uint32_t mask_from_swizzle(uint32_t swizzle)
{
- return (1u << vkd3d_swizzle_get_component(swizzle, 0))
- | (1u << vkd3d_swizzle_get_component(swizzle, 1))
- | (1u << vkd3d_swizzle_get_component(swizzle, 2))
- | (1u << vkd3d_swizzle_get_component(swizzle, 3));
+ return (1u << vsir_swizzle_get_component(swizzle, 0))
+ | (1u << vsir_swizzle_get_component(swizzle, 1))
+ | (1u << vsir_swizzle_get_component(swizzle, 2))
+ | (1u << vsir_swizzle_get_component(swizzle, 3));
}
static bool shader_sm4_validate_input_output_register(struct vkd3d_shader_sm4_parser *priv,
@@ -2219,7 +2231,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons
}
if (data_type == VKD3D_DATA_DOUBLE)
- dst_param->write_mask = vkd3d_write_mask_64_from_32(dst_param->write_mask);
+ dst_param->write_mask = vsir_write_mask_64_from_32(dst_param->write_mask);
/* Some scalar registers are declared with no write mask in shader bytecode. */
if (!dst_param->write_mask && shader_sm4_is_scalar_register(&dst_param->reg))
dst_param->write_mask = VKD3DSP_WRITEMASK_0;
@@ -2533,6 +2545,16 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t
return true;
}
+static void uninvert_used_masks(struct shader_signature *signature)
+{
+ for (unsigned int i = 0; i < signature->element_count; ++i)
+ {
+ struct signature_element *e = &signature->elements[i];
+
+ e->used_mask = e->mask & ~e->used_mask;
+ }
+}
+
static bool shader_sm4_parser_validate_signature(struct vkd3d_shader_sm4_parser *sm4,
const struct shader_signature *signature, unsigned int *masks, const char *name)
{
@@ -2628,6 +2650,12 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
return VKD3D_ERROR_INVALID_ARGUMENT;
}
+ /* DXBC stores used masks inverted for output signatures, for some reason.
+ * We return them un-inverted. */
+ uninvert_used_masks(&shader_desc->output_signature);
+ if (sm4->p.shader_version.type == VKD3D_SHADER_TYPE_HULL)
+ uninvert_used_masks(&shader_desc->patch_constant_signature);
+
if (!shader_sm4_parser_validate_signature(sm4, &shader_desc->input_signature,
sm4->input_register_masks, "Input")
|| !shader_sm4_parser_validate_signature(sm4, &shader_desc->output_signature,
@@ -3842,7 +3870,7 @@ static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src,
if (width == 1)
{
src->reg.dimension = VSIR_DIMENSION_SCALAR;
- src->reg.u.immconst_uint[0] = value->u[0].u;
+ src->reg.u.immconst_u32[0] = value->u[0].u;
}
else
{
@@ -3852,9 +3880,9 @@ static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src,
for (i = 0; i < 4; ++i)
{
if ((map_writemask & (1u << i)) && (j < width))
- src->reg.u.immconst_uint[i] = value->u[j++].u;
+ src->reg.u.immconst_u32[i] = value->u[j++].u;
else
- src->reg.u.immconst_uint[i] = 0;
+ src->reg.u.immconst_u32[i] = 0;
}
}
}
@@ -4049,12 +4077,12 @@ static void sm4_write_src_register(const struct tpf_writer *tpf, const struct vk
if (src->reg.type == VKD3DSPR_IMMCONST)
{
- put_u32(buffer, src->reg.u.immconst_uint[0]);
+ put_u32(buffer, src->reg.u.immconst_u32[0]);
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]);
- put_u32(buffer, src->reg.u.immconst_uint[3]);
+ put_u32(buffer, src->reg.u.immconst_u32[1]);
+ put_u32(buffer, src->reg.u.immconst_u32[2]);
+ put_u32(buffer, src->reg.u.immconst_u32[3]);
}
}
}
@@ -4589,7 +4617,7 @@ static void write_sm4_ld(const struct tpf_writer *tpf, const struct hlsl_ir_node
memset(&instr.srcs[2], 0, sizeof(instr.srcs[2]));
reg->type = VKD3DSPR_IMMCONST;
reg->dimension = VSIR_DIMENSION_SCALAR;
- reg->u.immconst_uint[0] = index->value.u[0].u;
+ reg->u.immconst_u32[0] = index->value.u[0].u;
}
else if (tpf->ctx->profile->major_version == 4 && tpf->ctx->profile->minor_version == 0)
{
@@ -4750,7 +4778,7 @@ static void write_sm4_cast_from_bool(const struct tpf_writer *tpf, const struct
sm4_src_from_node(tpf, &instr.srcs[0], arg, instr.dsts[0].write_mask);
instr.srcs[1].reg.type = VKD3DSPR_IMMCONST;
instr.srcs[1].reg.dimension = VSIR_DIMENSION_SCALAR;
- instr.srcs[1].reg.u.immconst_uint[0] = mask;
+ instr.srcs[1].reg.u.immconst_u32[0] = mask;
instr.src_count = 2;
write_sm4_instruction(tpf, &instr);
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
index 8fd8945151f..8fd98d2a551 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')
@@ -305,6 +307,16 @@ void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const s
vkd3d_string_buffer_printf(&context->messages, "\n");
}
+void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location,
+ enum vkd3d_shader_error error, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vkd3d_shader_vwarning(context, location, error, format, args);
+ va_end(args);
+}
+
void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location,
enum vkd3d_shader_error error, const char *format, va_list args)
{
@@ -888,6 +900,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 +940,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 +954,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)
@@ -1074,6 +1083,9 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte
vkd3d_shader_scan_sampler_declaration(context, instruction);
break;
case VKD3DSIH_DCL:
+ if (instruction->declaration.semantic.resource_type == VKD3D_SHADER_RESOURCE_NONE)
+ break;
+
if (instruction->declaration.semantic.resource.reg.reg.type == VKD3DSPR_COMBINED_SAMPLER)
{
vkd3d_shader_scan_combined_sampler_declaration(context, &instruction->declaration.semantic);
@@ -1541,16 +1553,15 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
scan_info = *compile_info;
- if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0)
- return ret;
-
switch (compile_info->target_type)
{
case VKD3D_SHADER_TARGET_D3D_ASM:
- ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out);
+ ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out, VSIR_ASM_D3D);
break;
case VKD3D_SHADER_TARGET_GLSL:
+ if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0)
+ return ret;
if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->shader_version,
message_context, &parser->location)))
{
@@ -1561,19 +1572,22 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
ret = vkd3d_glsl_generator_generate(glsl_generator, parser, out);
vkd3d_glsl_generator_destroy(glsl_generator);
+ vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
break;
case VKD3D_SHADER_TARGET_SPIRV_BINARY:
case VKD3D_SHADER_TARGET_SPIRV_TEXT:
+ if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0)
+ return ret;
ret = spirv_compile(parser, &scan_descriptor_info, compile_info, out, message_context);
+ vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
break;
default:
/* Validation should prevent us from reaching this. */
- assert(0);
+ vkd3d_unreachable();
}
- vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info);
return ret;
}
@@ -1622,14 +1636,10 @@ static int compile_d3d_bytecode(const struct vkd3d_shader_compile_info *compile_
return ret;
}
- if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM)
- {
- ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out);
- vkd3d_shader_parser_destroy(parser);
- return ret;
- }
+ ret = vkd3d_shader_parser_compile(parser, compile_info, out, message_context);
- return VKD3D_ERROR;
+ vkd3d_shader_parser_destroy(parser);
+ return ret;
}
static int compile_dxbc_dxil(const struct vkd3d_shader_compile_info *compile_info,
@@ -1907,6 +1917,10 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types(
static const enum vkd3d_shader_target_type d3dbc_types[] =
{
+ VKD3D_SHADER_TARGET_SPIRV_BINARY,
+#ifdef HAVE_SPIRV_TOOLS
+ VKD3D_SHADER_TARGET_SPIRV_TEXT,
+#endif
VKD3D_SHADER_TARGET_D3D_ASM,
};
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
index a93fa7160f7..47b245bd7ee 100644
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -91,11 +91,12 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001,
VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING = 2002,
VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED = 2003,
- VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED = 2004,
+ VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE = 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_ERROR_SPV_NOT_IMPLEMENTED = 2008,
+ VKD3D_SHADER_ERROR_SPV_INVALID_SHADER = 2009,
VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300,
@@ -196,6 +197,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,
@@ -618,6 +620,11 @@ static inline bool data_type_is_bool(enum vkd3d_data_type data_type)
return data_type == VKD3D_DATA_BOOL;
}
+static inline bool data_type_is_64_bit(enum vkd3d_data_type data_type)
+{
+ return data_type == VKD3D_DATA_DOUBLE || data_type == VKD3D_DATA_UINT64;
+}
+
enum vsir_dimension
{
VSIR_DIMENSION_NONE,
@@ -740,6 +747,7 @@ enum vkd3d_tessellator_domain
#define VKD3DSI_RESINFO_UINT 0x2
#define VKD3DSI_SAMPLE_INFO_UINT 0x1
#define VKD3DSI_SAMPLER_COMPARISON_MODE 0x1
+#define VKD3DSI_SHIFT_UNMASKED 0x1
#define VKD3DSI_PRECISE_X 0x100
#define VKD3DSI_PRECISE_Y 0x200
@@ -793,10 +801,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[];
};
@@ -831,10 +841,10 @@ struct vkd3d_shader_register
unsigned int alignment;
union
{
- DWORD immconst_uint[VKD3D_VEC4_SIZE];
- float immconst_float[VKD3D_VEC4_SIZE];
- uint64_t immconst_uint64[VKD3D_DVEC2_SIZE];
- double immconst_double[VKD3D_DVEC2_SIZE];
+ uint32_t immconst_u32[VKD3D_VEC4_SIZE];
+ float immconst_f32[VKD3D_VEC4_SIZE];
+ uint64_t immconst_u64[VKD3D_DVEC2_SIZE];
+ double immconst_f64[VKD3D_DVEC2_SIZE];
unsigned fp_body_idx;
} u;
};
@@ -1311,9 +1321,15 @@ struct vkd3d_string_buffer_cache
size_t count, max_count, capacity;
};
+enum vsir_asm_dialect
+{
+ VSIR_ASM_VSIR,
+ VSIR_ASM_D3D,
+};
+
enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions,
const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info,
- struct vkd3d_shader_code *out);
+ struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect);
void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer);
struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list);
void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer);
@@ -1382,6 +1398,8 @@ void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const str
enum vkd3d_shader_error error, const char *format, va_list args);
void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location,
enum vkd3d_shader_log_level level, const char *format, va_list args);
+void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location,
+ enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(4, 5);
void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location,
enum vkd3d_shader_error error, const char *format, va_list args);
@@ -1444,6 +1462,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_UINT64:
+ return VKD3D_SHADER_COMPONENT_UINT64;
case VKD3D_DATA_BOOL:
return VKD3D_SHADER_COMPONENT_BOOL;
default:
@@ -1505,7 +1525,7 @@ static inline enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum
return vkd3d_siv_from_sysval_indexed(sysval, 0);
}
-static inline unsigned int vkd3d_write_mask_get_component_idx(DWORD write_mask)
+static inline unsigned int vsir_write_mask_get_component_idx(uint32_t write_mask)
{
unsigned int i;
@@ -1520,7 +1540,7 @@ static inline unsigned int vkd3d_write_mask_get_component_idx(DWORD write_mask)
return 0;
}
-static inline unsigned int vkd3d_write_mask_component_count(DWORD write_mask)
+static inline unsigned int vsir_write_mask_component_count(uint32_t write_mask)
{
unsigned int count = vkd3d_popcount(write_mask & VKD3DSP_WRITEMASK_ALL);
assert(1 <= count && count <= VKD3D_VEC4_SIZE);
@@ -1533,32 +1553,30 @@ static inline unsigned int vkd3d_write_mask_from_component_count(unsigned int co
return (VKD3DSP_WRITEMASK_0 << component_count) - 1;
}
-static inline unsigned int vkd3d_write_mask_64_from_32(DWORD write_mask32)
+static inline uint32_t vsir_write_mask_64_from_32(uint32_t write_mask32)
{
- unsigned int write_mask64 = write_mask32 | (write_mask32 >> 1);
+ uint32_t write_mask64 = write_mask32 | (write_mask32 >> 1);
return (write_mask64 & VKD3DSP_WRITEMASK_0) | ((write_mask64 & VKD3DSP_WRITEMASK_2) >> 1);
}
-static inline unsigned int vkd3d_write_mask_32_from_64(unsigned int write_mask64)
+static inline uint32_t vsir_write_mask_32_from_64(uint32_t write_mask64)
{
- unsigned int write_mask32 = (write_mask64 | (write_mask64 << 1))
+ uint32_t write_mask32 = (write_mask64 | (write_mask64 << 1))
& (VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_2);
return write_mask32 | (write_mask32 << 1);
}
-static inline unsigned int vkd3d_swizzle_get_component(DWORD swizzle,
- unsigned int idx)
+static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx)
{
return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK;
}
-static inline unsigned int vkd3d_swizzle_get_component64(DWORD swizzle,
- unsigned int idx)
+static inline unsigned int vsir_swizzle_get_component64(uint32_t swizzle, unsigned int idx)
{
return ((swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx * 2)) & VKD3D_SHADER_SWIZZLE_MASK) / 2u;
}
-static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned int write_mask)
+static inline unsigned int vkd3d_compact_swizzle(uint32_t swizzle, uint32_t write_mask)
{
unsigned int i, compacted_swizzle = 0;
@@ -1567,7 +1585,7 @@ static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned
if (write_mask & (VKD3DSP_WRITEMASK_0 << i))
{
compacted_swizzle <<= VKD3D_SHADER_SWIZZLE_SHIFT(1);
- compacted_swizzle |= vkd3d_swizzle_get_component(swizzle, i);
+ compacted_swizzle |= vsir_swizzle_get_component(swizzle, i);
}
}
diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c
index 15c8317b191..549f6a45ffb 100644
--- a/libs/vkd3d/libs/vkd3d/command.c
+++ b/libs/vkd3d/libs/vkd3d/command.c
@@ -2644,6 +2644,8 @@ static bool d3d12_command_list_update_compute_pipeline(struct d3d12_command_list
{
const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs;
+ vkd3d_cond_signal(&list->device->worker_cond);
+
if (list->current_pipeline != VK_NULL_HANDLE)
return true;
@@ -2665,6 +2667,8 @@ static bool d3d12_command_list_update_graphics_pipeline(struct d3d12_command_lis
VkRenderPass vk_render_pass;
VkPipeline vk_pipeline;
+ vkd3d_cond_signal(&list->device->worker_cond);
+
if (list->current_pipeline != VK_NULL_HANDLE)
return true;
diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c
index 5c801ca4676..69a46e9188a 100644
--- a/libs/vkd3d/libs/vkd3d/device.c
+++ b/libs/vkd3d/libs/vkd3d/device.c
@@ -2056,7 +2056,7 @@ static HRESULT d3d12_device_init_pipeline_cache(struct d3d12_device *device)
VkPipelineCacheCreateInfo cache_info;
VkResult vr;
- vkd3d_mutex_init(&device->mutex);
+ vkd3d_mutex_init(&device->pipeline_cache_mutex);
cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
cache_info.pNext = NULL;
@@ -2080,7 +2080,7 @@ static void d3d12_device_destroy_pipeline_cache(struct d3d12_device *device)
if (device->vk_pipeline_cache)
VK_CALL(vkDestroyPipelineCache(device->vk_device, device->vk_pipeline_cache, NULL));
- vkd3d_mutex_destroy(&device->mutex);
+ vkd3d_mutex_destroy(&device->pipeline_cache_mutex);
}
#define VKD3D_VA_FALLBACK_BASE 0x8000000000000000ull
@@ -2495,6 +2495,28 @@ static ULONG STDMETHODCALLTYPE d3d12_device_AddRef(ID3D12Device5 *iface)
return refcount;
}
+static HRESULT device_worker_stop(struct d3d12_device *device)
+{
+ HRESULT hr;
+
+ TRACE("device %p.\n", device);
+
+ vkd3d_mutex_lock(&device->worker_mutex);
+
+ device->worker_should_exit = true;
+ vkd3d_cond_signal(&device->worker_cond);
+
+ vkd3d_mutex_unlock(&device->worker_mutex);
+
+ if (FAILED(hr = vkd3d_join_thread(device->vkd3d_instance, &device->worker_thread)))
+ return hr;
+
+ vkd3d_mutex_destroy(&device->worker_mutex);
+ vkd3d_cond_destroy(&device->worker_cond);
+
+ return S_OK;
+}
+
static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface)
{
struct d3d12_device *device = impl_from_ID3D12Device5(iface);
@@ -2520,6 +2542,9 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface)
d3d12_device_destroy_vkd3d_queues(device);
vkd3d_desc_object_cache_cleanup(&device->view_desc_cache);
vkd3d_desc_object_cache_cleanup(&device->cbuffer_desc_cache);
+ if (device->use_vk_heaps)
+ device_worker_stop(device);
+ vkd3d_free(device->heaps);
VK_CALL(vkDestroyDevice(device->vk_device, NULL));
if (device->parent)
IUnknown_Release(device->parent);
@@ -4251,6 +4276,40 @@ struct d3d12_device *unsafe_impl_from_ID3D12Device5(ID3D12Device5 *iface)
return impl_from_ID3D12Device5(iface);
}
+static void *device_worker_main(void *arg)
+{
+ struct d3d12_descriptor_heap *heap;
+ struct d3d12_device *device = arg;
+ size_t i;
+
+ vkd3d_set_thread_name("device_worker");
+
+ vkd3d_mutex_lock(&device->worker_mutex);
+
+ while (!device->worker_should_exit)
+ {
+ for (i = 0; i < device->heap_count; ++i)
+ {
+ /* Descriptor updates are not written to Vulkan descriptor sets until a command list
+ * is submitted to a queue, while the client is free to write d3d12 descriptors earlier,
+ * from any thread. This causes a delay right before command list execution, so
+ * handling these updates in a worker thread can speed up execution significantly. */
+ heap = device->heaps[i];
+ if (heap->dirty_list_head == UINT_MAX)
+ continue;
+ vkd3d_mutex_lock(&heap->vk_sets_mutex);
+ d3d12_desc_flush_vk_heap_updates_locked(heap, device);
+ vkd3d_mutex_unlock(&heap->vk_sets_mutex);
+ }
+
+ vkd3d_cond_wait(&device->worker_cond, &device->worker_mutex);
+ }
+
+ vkd3d_mutex_unlock(&device->worker_mutex);
+
+ return NULL;
+}
+
static HRESULT d3d12_device_init(struct d3d12_device *device,
struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info)
{
@@ -4270,6 +4329,14 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
device->vk_device = VK_NULL_HANDLE;
+ device->heaps = NULL;
+ device->heap_capacity = 0;
+ device->heap_count = 0;
+ memset(&device->worker_thread, 0, sizeof(device->worker_thread));
+ device->worker_should_exit = false;
+ vkd3d_mutex_init(&device->worker_mutex);
+ vkd3d_cond_init(&device->worker_cond);
+
if (FAILED(hr = vkd3d_create_vk_device(device, create_info)))
goto out_free_instance;
@@ -4291,6 +4358,13 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
if (FAILED(hr = vkd3d_vk_descriptor_heap_layouts_init(device)))
goto out_cleanup_uav_clear_state;
+ if (device->use_vk_heaps && FAILED(hr = vkd3d_create_thread(device->vkd3d_instance,
+ device_worker_main, device, &device->worker_thread)))
+ {
+ WARN("Failed to create worker thread, hr %#x.\n", hr);
+ goto out_cleanup_descriptor_heap_layouts;
+ }
+
vkd3d_render_pass_cache_init(&device->render_pass_cache);
vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator);
vkd3d_time_domains_init(device);
@@ -4308,6 +4382,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
return S_OK;
+out_cleanup_descriptor_heap_layouts:
+ vkd3d_vk_descriptor_heap_layouts_cleanup(device);
out_cleanup_uav_clear_state:
vkd3d_uav_clear_state_cleanup(&device->uav_clear_state, device);
out_destroy_null_resources:
@@ -4361,6 +4437,40 @@ void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason,
device->removed_reason = reason;
}
+HRESULT d3d12_device_add_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap)
+{
+ vkd3d_mutex_lock(&device->worker_mutex);
+
+ if (!vkd3d_array_reserve((void **)&device->heaps, &device->heap_capacity, device->heap_count + 1,
+ sizeof(*device->heaps)))
+ {
+ vkd3d_mutex_unlock(&device->worker_mutex);
+ return E_OUTOFMEMORY;
+ }
+ device->heaps[device->heap_count++] = heap;
+
+ vkd3d_mutex_unlock(&device->worker_mutex);
+
+ return S_OK;
+}
+
+void d3d12_device_remove_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap)
+{
+ size_t i;
+
+ vkd3d_mutex_lock(&device->worker_mutex);
+
+ for (i = 0; i < device->heap_count; ++i)
+ {
+ if (device->heaps[i] == heap)
+ {
+ device->heaps[i] = device->heaps[--device->heap_count];
+ break;
+ }
+ }
+
+ vkd3d_mutex_unlock(&device->worker_mutex);
+}
#ifdef _WIN32
struct thread_data
diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c
index abbdfbe2015..609c67102a6 100644
--- a/libs/vkd3d/libs/vkd3d/resource.c
+++ b/libs/vkd3d/libs/vkd3d/resource.c
@@ -2632,20 +2632,18 @@ void d3d12_desc_flush_vk_heap_updates_locked(struct d3d12_descriptor_heap *descr
for (; i != UINT_MAX; i = next)
{
src = &descriptors[i];
- next = (int)src->next >> 1;
+ next = vkd3d_atomic_exchange(&src->next, 0);
+ next = (int)next >> 1;
+ /* A race exists here between updating src->next and getting the current object. The best
+ * we can do is get the object last, which may result in a harmless rewrite later. */
u.object = d3d12_desc_get_object_ref(src, device);
if (!u.object)
- {
- vkd3d_atomic_exchange(&src->next, 0);
continue;
- }
writes.held_refs[writes.held_ref_count++] = u.object;
d3d12_desc_write_vk_heap(descriptor_heap, i, &writes, u.object, device);
-
- vkd3d_atomic_exchange(&src->next, 0);
}
/* Avoid thunk calls wherever possible. */
@@ -3997,6 +3995,9 @@ static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHea
{
struct d3d12_desc *descriptors = (struct d3d12_desc *)heap->descriptors;
+ if (heap->use_vk_heaps)
+ d3d12_device_remove_descriptor_heap(device, heap);
+
for (i = 0; i < heap->desc.NumDescriptors; ++i)
{
d3d12_desc_destroy(&descriptors[i], device);
@@ -4320,6 +4321,12 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device,
dst[i].next = 0;
}
object->dirty_list_head = UINT_MAX;
+
+ if (object->use_vk_heaps && FAILED(hr = d3d12_device_add_descriptor_heap(device, object)))
+ {
+ vkd3d_free(object);
+ return hr;
+ }
}
else
{
diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c
index fc3187f4bea..1457ddf9c7f 100644
--- a/libs/vkd3d/libs/vkd3d/state.c
+++ b/libs/vkd3d/libs/vkd3d/state.c
@@ -515,7 +515,7 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat
assert(p->ShaderVisibility <= D3D12_SHADER_VISIBILITY_PIXEL);
push_constants[p->ShaderVisibility].stageFlags = use_vk_heaps ? VK_SHADER_STAGE_ALL
: stage_flags_from_visibility(p->ShaderVisibility);
- push_constants[p->ShaderVisibility].size += p->u.Constants.Num32BitValues * sizeof(uint32_t);
+ push_constants[p->ShaderVisibility].size += align(p->u.Constants.Num32BitValues, 4) * sizeof(uint32_t);
}
if (push_constants[D3D12_SHADER_VISIBILITY_ALL].size)
{
@@ -564,7 +564,7 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat
idx = push_constant_count == 1 ? 0 : p->ShaderVisibility;
offset = push_constants_offset[idx];
- push_constants_offset[idx] += p->u.Constants.Num32BitValues * sizeof(uint32_t);
+ push_constants_offset[idx] += align(p->u.Constants.Num32BitValues, 4) * sizeof(uint32_t);
root_signature->parameters[i].parameter_type = p->ParameterType;
root_constant->stage_flags = push_constant_count == 1
@@ -1691,7 +1691,7 @@ HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache,
HRESULT hr = S_OK;
unsigned int i;
- vkd3d_mutex_lock(&device->mutex);
+ vkd3d_mutex_lock(&device->pipeline_cache_mutex);
for (i = 0; i < cache->render_pass_count; ++i)
{
@@ -1708,7 +1708,7 @@ HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache,
if (!found)
hr = vkd3d_render_pass_cache_create_pass_locked(cache, device, key, vk_render_pass);
- vkd3d_mutex_unlock(&device->mutex);
+ vkd3d_mutex_unlock(&device->pipeline_cache_mutex);
return hr;
}
@@ -2129,6 +2129,16 @@ static inline unsigned int typed_uav_compile_option(const struct d3d12_device *d
: VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV_READ_FORMAT_R32;
}
+static unsigned int feature_flags_compile_option(const struct d3d12_device *device)
+{
+ unsigned int flags = 0;
+
+ if (device->feature_options1.Int64ShaderOps)
+ flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64;
+
+ return flags;
+}
+
static HRESULT create_shader_stage(struct d3d12_device *device,
struct VkPipelineShaderStageCreateInfo *stage_desc, enum VkShaderStageFlagBits stage,
const D3D12_SHADER_BYTECODE *code, const struct vkd3d_shader_interface_info *shader_interface)
@@ -2145,6 +2155,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device,
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_10},
{VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV, typed_uav_compile_option(device)},
{VKD3D_SHADER_COMPILE_OPTION_WRITE_TESS_GEOM_POINT_SIZE, 0},
+ {VKD3D_SHADER_COMPILE_OPTION_FEATURE, feature_flags_compile_option(device)},
};
stage_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
@@ -3615,7 +3626,7 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12
*vk_render_pass = VK_NULL_HANDLE;
- vkd3d_mutex_lock(&device->mutex);
+ vkd3d_mutex_lock(&device->pipeline_cache_mutex);
LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry)
{
@@ -3627,7 +3638,7 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12
}
}
- vkd3d_mutex_unlock(&device->mutex);
+ vkd3d_mutex_unlock(&device->pipeline_cache_mutex);
return vk_pipeline;
}
@@ -3646,7 +3657,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta
compiled_pipeline->vk_pipeline = vk_pipeline;
compiled_pipeline->vk_render_pass = vk_render_pass;
- vkd3d_mutex_lock(&device->mutex);
+ vkd3d_mutex_lock(&device->pipeline_cache_mutex);
LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry)
{
@@ -3661,7 +3672,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta
if (compiled_pipeline)
list_add_tail(&graphics->compiled_pipelines, &compiled_pipeline->entry);
- vkd3d_mutex_unlock(&device->mutex);
+ vkd3d_mutex_unlock(&device->pipeline_cache_mutex);
return compiled_pipeline;
}
diff --git a/libs/vkd3d/libs/vkd3d/utils.c b/libs/vkd3d/libs/vkd3d/utils.c
index 9b28068be51..5ebe1b63e99 100644
--- a/libs/vkd3d/libs/vkd3d/utils.c
+++ b/libs/vkd3d/libs/vkd3d/utils.c
@@ -539,6 +539,7 @@ bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level)
{
static const D3D_FEATURE_LEVEL valid_feature_levels[] =
{
+ D3D_FEATURE_LEVEL_12_2,
D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_11_1,
@@ -548,6 +549,7 @@ bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level)
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1,
+ D3D_FEATURE_LEVEL_1_0_CORE,
};
unsigned int i;
diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
index f06f564d6ea..bd7e7290d9e 100644
--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
@@ -1757,9 +1757,23 @@ struct d3d12_device
struct vkd3d_gpu_va_allocator gpu_va_allocator;
- struct vkd3d_mutex mutex;
struct vkd3d_desc_object_cache view_desc_cache;
struct vkd3d_desc_object_cache cbuffer_desc_cache;
+
+ VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT];
+ unsigned int vk_pool_count;
+ struct vkd3d_vk_descriptor_heap_layout vk_descriptor_heap_layouts[VKD3D_SET_INDEX_COUNT];
+ bool use_vk_heaps;
+
+ struct d3d12_descriptor_heap **heaps;
+ size_t heap_capacity;
+ size_t heap_count;
+ union vkd3d_thread_handle worker_thread;
+ struct vkd3d_mutex worker_mutex;
+ struct vkd3d_cond worker_cond;
+ bool worker_should_exit;
+
+ struct vkd3d_mutex pipeline_cache_mutex;
struct vkd3d_render_pass_cache render_pass_cache;
VkPipelineCache vk_pipeline_cache;
@@ -1799,11 +1813,6 @@ struct d3d12_device
const struct vkd3d_format_compatibility_list *format_compatibility_lists;
struct vkd3d_null_resources null_resources;
struct vkd3d_uav_clear_state uav_clear_state;
-
- VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT];
- unsigned int vk_pool_count;
- struct vkd3d_vk_descriptor_heap_layout vk_descriptor_heap_layouts[VKD3D_SET_INDEX_COUNT];
- bool use_vk_heaps;
};
HRESULT d3d12_device_create(struct vkd3d_instance *instance,
@@ -1813,6 +1822,8 @@ bool d3d12_device_is_uma(struct d3d12_device *device, bool *coherent);
void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason,
const char *message, ...) VKD3D_PRINTF_FUNC(3, 4);
struct d3d12_device *unsafe_impl_from_ID3D12Device5(ID3D12Device5 *iface);
+HRESULT d3d12_device_add_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap);
+void d3d12_device_remove_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap);
static inline HRESULT d3d12_device_query_interface(struct d3d12_device *device, REFIID iid, void **object)
{
--
2.43.0