wine-staging/patches/vkd3d-latest/0003-Updated-vkd3d-to-a03e78bf6285d4344f5d7774729b4b64175.patch
2023-11-11 09:57:14 +11:00

4911 lines
192 KiB
Diff

From 288f77dac789c2ac0b2c85d4c57bca7ecc5f2164 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Tue, 7 Nov 2023 12:20:58 +1100
Subject: [PATCH] Updated vkd3d to a03e78bf6285d4344f5d7774729b4b64175422a7.
---
libs/vkd3d/include/vkd3d_d3dcompiler.h | 23 +-
libs/vkd3d/include/vkd3d_d3dcompiler_types.h | 45 ++
libs/vkd3d/include/vkd3d_utils.h | 4 +-
libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 23 +-
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 21 +-
libs/vkd3d/libs/vkd3d-shader/dxil.c | 586 +++++++++++++++++-
libs/vkd3d/libs/vkd3d-shader/hlsl.c | 200 +++++-
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 58 +-
libs/vkd3d/libs/vkd3d-shader/hlsl.l | 34 +-
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 273 +++++++-
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 483 +++++++++++++--
libs/vkd3d/libs/vkd3d-shader/ir.c | 118 +++-
libs/vkd3d/libs/vkd3d-shader/spirv.c | 200 +++---
libs/vkd3d/libs/vkd3d-shader/tpf.c | 114 +++-
.../libs/vkd3d-shader/vkd3d_shader_main.c | 50 +-
.../libs/vkd3d-shader/vkd3d_shader_private.h | 45 +-
libs/vkd3d/libs/vkd3d/state.c | 48 +-
libs/vkd3d/libs/vkd3d/vkd3d_shaders.h | 568 ++++++-----------
18 files changed, 2152 insertions(+), 741 deletions(-)
create mode 100644 libs/vkd3d/include/vkd3d_d3dcompiler_types.h
diff --git a/libs/vkd3d/include/vkd3d_d3dcompiler.h b/libs/vkd3d/include/vkd3d_d3dcompiler.h
index 78d52948310..c78cf25b955 100644
--- a/libs/vkd3d/include/vkd3d_d3dcompiler.h
+++ b/libs/vkd3d/include/vkd3d_d3dcompiler.h
@@ -20,6 +20,8 @@
#define __VKD3D_D3DCOMPILER_H
#ifndef __D3DCOMPILER_H__
+#include <vkd3d_d3dcompiler_types.h>
+
#define D3DCOMPILE_DEBUG 0x00000001
#define D3DCOMPILE_SKIP_VALIDATION 0x00000002
#define D3DCOMPILE_SKIP_OPTIMIZATION 0x00000004
@@ -58,27 +60,6 @@
#define D3DCOMPILE_SECDATA_PRESERVE_TEMPLATE_SLOTS 0x00000002
#define D3DCOMPILE_SECDATA_REQUIRE_TEMPLATE_MATCH 0x00000004
-typedef enum D3D_BLOB_PART
-{
- D3D_BLOB_INPUT_SIGNATURE_BLOB,
- D3D_BLOB_OUTPUT_SIGNATURE_BLOB,
- D3D_BLOB_INPUT_AND_OUTPUT_SIGNATURE_BLOB,
- D3D_BLOB_PATCH_CONSTANT_SIGNATURE_BLOB,
- D3D_BLOB_ALL_SIGNATURE_BLOB,
- D3D_BLOB_DEBUG_INFO,
- D3D_BLOB_LEGACY_SHADER,
- D3D_BLOB_XNA_PREPASS_SHADER,
- D3D_BLOB_XNA_SHADER,
- D3D_BLOB_PDB,
- D3D_BLOB_PRIVATE_DATA,
- D3D_BLOB_ROOT_SIGNATURE,
- D3D_BLOB_DEBUG_NAME,
- D3D_BLOB_TEST_ALTERNATE_SHADER = 0x8000,
- D3D_BLOB_TEST_COMPILE_DETAILS,
- D3D_BLOB_TEST_COMPILE_PERF,
- D3D_BLOB_TEST_COMPILE_REPORT
-} D3D_BLOB_PART;
-
typedef enum D3DCOMPILER_STRIP_FLAGS
{
D3DCOMPILER_STRIP_REFLECTION_DATA = 0x00000001,
diff --git a/libs/vkd3d/include/vkd3d_d3dcompiler_types.h b/libs/vkd3d/include/vkd3d_d3dcompiler_types.h
new file mode 100644
index 00000000000..b3a47cdd912
--- /dev/null
+++ b/libs/vkd3d/include/vkd3d_d3dcompiler_types.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2010 Matteo Bruni for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __VKD3D_D3DCOMPILER_TYPES_H
+#define __VKD3D_D3DCOMPILER_TYPES_H
+#ifndef __D3DCOMPILER_H__
+
+typedef enum D3D_BLOB_PART
+{
+ D3D_BLOB_INPUT_SIGNATURE_BLOB,
+ D3D_BLOB_OUTPUT_SIGNATURE_BLOB,
+ D3D_BLOB_INPUT_AND_OUTPUT_SIGNATURE_BLOB,
+ D3D_BLOB_PATCH_CONSTANT_SIGNATURE_BLOB,
+ D3D_BLOB_ALL_SIGNATURE_BLOB,
+ D3D_BLOB_DEBUG_INFO,
+ D3D_BLOB_LEGACY_SHADER,
+ D3D_BLOB_XNA_PREPASS_SHADER,
+ D3D_BLOB_XNA_SHADER,
+ D3D_BLOB_PDB,
+ D3D_BLOB_PRIVATE_DATA,
+ D3D_BLOB_ROOT_SIGNATURE,
+ D3D_BLOB_DEBUG_NAME,
+ D3D_BLOB_TEST_ALTERNATE_SHADER = 0x8000,
+ D3D_BLOB_TEST_COMPILE_DETAILS,
+ D3D_BLOB_TEST_COMPILE_PERF,
+ D3D_BLOB_TEST_COMPILE_REPORT
+} D3D_BLOB_PART;
+
+#endif /* __D3DCOMPILER_H__ */
+#endif /* __VKD3D_D3DCOMPILER_TYPES_H */
diff --git a/libs/vkd3d/include/vkd3d_utils.h b/libs/vkd3d/include/vkd3d_utils.h
index b5ec7981356..686ddf386e7 100644
--- a/libs/vkd3d/include/vkd3d_utils.h
+++ b/libs/vkd3d/include/vkd3d_utils.h
@@ -20,6 +20,7 @@
#define __VKD3D_UTILS_H
#include <vkd3d.h>
+#include <vkd3d_d3dcompiler_types.h>
#ifndef VKD3D_UTILS_API_VERSION
#define VKD3D_UTILS_API_VERSION VKD3D_API_VERSION_1_0
@@ -51,9 +52,6 @@ extern "C" {
# define VKD3D_UTILS_API VKD3D_IMPORT
#endif
-/** \since 1.10 */
-typedef enum D3D_BLOB_PART D3D_BLOB_PART;
-
/* 1.0 */
VKD3D_UTILS_API HANDLE vkd3d_create_event(void);
VKD3D_UTILS_API HRESULT vkd3d_signal_event(HANDLE event);
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
index 40daa5354d8..5cea0c0c260 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
@@ -152,6 +152,7 @@ static const char * const shader_opcode_names[] =
[VKD3DSIH_FIRSTBIT_LO ] = "firstbit_lo",
[VKD3DSIH_FIRSTBIT_SHI ] = "firstbit_shi",
[VKD3DSIH_FRC ] = "frc",
+ [VKD3DSIH_FREM ] = "frem",
[VKD3DSIH_FTOD ] = "ftod",
[VKD3DSIH_FTOI ] = "ftoi",
[VKD3DSIH_FTOU ] = "ftou",
@@ -170,6 +171,7 @@ static const char * const shader_opcode_names[] =
[VKD3DSIH_HS_JOIN_PHASE ] = "hs_join_phase",
[VKD3DSIH_IADD ] = "iadd",
[VKD3DSIH_IBFE ] = "ibfe",
+ [VKD3DSIH_IDIV ] = "idiv",
[VKD3DSIH_IEQ ] = "ieq",
[VKD3DSIH_IF ] = "if",
[VKD3DSIH_IFC ] = "ifc",
@@ -358,11 +360,6 @@ struct vkd3d_d3d_asm_compiler
struct vkd3d_d3d_asm_colours colours;
};
-static int shader_ver_ge(const struct vkd3d_shader_version *v, int major, int minor)
-{
- return v->major > major || (v->major == major && v->minor >= minor);
-}
-
static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...)
{
va_list args;
@@ -424,7 +421,7 @@ static void shader_dump_global_flags(struct vkd3d_d3d_asm_compiler *compiler,
}
if (global_flags)
- vkd3d_string_buffer_printf(&compiler->buffer, "unknown_flags(%#"PRIx64")", global_flags);
+ vkd3d_string_buffer_printf(&compiler->buffer, "unknown_flags(%#"PRIx64")", (uint64_t)global_flags);
}
static void shader_dump_sync_flags(struct vkd3d_d3d_asm_compiler *compiler, uint32_t sync_flags)
@@ -684,7 +681,7 @@ static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler,
else
{
/* Pixel shaders 3.0 don't have usage semantics. */
- if (!shader_ver_ge(&compiler->shader_version, 3, 0)
+ if (!vkd3d_shader_ver_ge(&compiler->shader_version, 3, 0)
&& compiler->shader_version.type == VKD3D_SHADER_TYPE_PIXEL)
return;
else
@@ -908,7 +905,7 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const
case VKD3DSPR_TEXCRDOUT:
/* Vertex shaders >= 3.0 use general purpose output registers
* (VKD3DSPR_OUTPUT), which can include an address token. */
- if (shader_ver_ge(&compiler->shader_version, 3, 0))
+ if (vkd3d_shader_ver_ge(&compiler->shader_version, 3, 0))
shader_addline(buffer, "o");
else
shader_addline(buffer, "oT");
@@ -1174,7 +1171,7 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const
{
if (offset != ~0u)
{
- bool is_sm_5_1 = shader_ver_ge(&compiler->shader_version, 5, 1);
+ bool is_sm_5_1 = vkd3d_shader_ver_ge(&compiler->shader_version, 5, 1);
if (reg->idx[0].rel_addr || reg->type == VKD3DSPR_IMMCONSTBUFFER
|| reg->type == VKD3DSPR_INCONTROLPOINT || (reg->type == VKD3DSPR_INPUT
@@ -1570,7 +1567,7 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile
break;
case VKD3DSIH_TEX:
- if (shader_ver_ge(&compiler->shader_version, 2, 0) && (ins->flags & VKD3DSI_TEXLD_PROJECT))
+ if (vkd3d_shader_ver_ge(&compiler->shader_version, 2, 0) && (ins->flags & VKD3DSI_TEXLD_PROJECT))
shader_addline(buffer, "p");
break;
@@ -1582,7 +1579,7 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile
static void shader_dump_register_space(struct vkd3d_d3d_asm_compiler *compiler, unsigned int register_space)
{
- if (shader_ver_ge(&compiler->shader_version, 5, 1))
+ if (vkd3d_shader_ver_ge(&compiler->shader_version, 5, 1))
shader_print_uint_literal(compiler, ", space=", register_space, "");
}
@@ -1626,9 +1623,9 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler,
case VKD3DSIH_DCL_CONSTANT_BUFFER:
vkd3d_string_buffer_printf(buffer, " ");
shader_dump_register(compiler, &ins->declaration.cb.src.reg, true);
- if (shader_ver_ge(&compiler->shader_version, 6, 0))
+ if (vkd3d_shader_ver_ge(&compiler->shader_version, 6, 0))
shader_print_subscript(compiler, ins->declaration.cb.size, NULL);
- else if (shader_ver_ge(&compiler->shader_version, 5, 1))
+ else if (vkd3d_shader_ver_ge(&compiler->shader_version, 5, 1))
shader_print_subscript(compiler, ins->declaration.cb.size / VKD3D_VEC4_SIZE / sizeof(float), NULL);
shader_addline(buffer, ", %s",
ins->flags & VKD3DSI_INDEXED_DYNAMIC ? "dynamicIndexed" : "immediateIndexed");
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
index 67fa32710fd..b1e2dc91d94 100644
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
@@ -402,16 +402,6 @@ static uint32_t read_u32(const uint32_t **ptr)
return *(*ptr)++;
}
-static bool shader_ver_ge(const struct vkd3d_shader_version *v, unsigned int major, unsigned int minor)
-{
- return v->major > major || (v->major == major && v->minor >= minor);
-}
-
-static bool shader_ver_le(const struct vkd3d_shader_version *v, unsigned int major, unsigned int minor)
-{
- return v->major < major || (v->major == major && v->minor <= minor);
-}
-
static bool has_relative_address(uint32_t param)
{
enum vkd3d_sm1_address_mode_type address_mode;
@@ -434,8 +424,8 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info(
return NULL;
if (opcode == info->sm1_opcode
- && shader_ver_ge(&sm1->p.shader_version, info->min_version.major, info->min_version.minor)
- && (shader_ver_le(&sm1->p.shader_version, info->max_version.major, info->max_version.minor)
+ && vkd3d_shader_ver_ge(&sm1->p.shader_version, info->min_version.major, info->min_version.minor)
+ && (vkd3d_shader_ver_le(&sm1->p.shader_version, info->max_version.major, info->max_version.minor)
|| !info->max_version.major))
return info;
}
@@ -555,9 +545,9 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp
return false;
element = &signature->elements[signature->element_count++];
+ memset(element, 0, sizeof(*element));
element->semantic_name = name;
element->semantic_index = index;
- element->stream_index = 0;
element->sysval_semantic = sysval;
element->component_type = VKD3D_SHADER_COMPONENT_FLOAT;
element->register_index = register_index;
@@ -565,7 +555,8 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp
element->register_count = 1;
element->mask = mask;
element->used_mask = is_dcl ? 0 : mask;
- element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE;
+ if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output)
+ element->interpolation_mode = VKD3DSIM_LINEAR;
return true;
}
@@ -1262,7 +1253,7 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1,
return VKD3D_ERROR_INVALID_SHADER;
}
- if (!shader_ver_le(&version, 3, 0))
+ if (!vkd3d_shader_ver_le(&version, 3, 0))
{
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_D3DBC_INVALID_VERSION_TOKEN,
"Invalid shader version %u.%u (token 0x%08x).", version.major, version.minor, code[0]);
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
index 19ce2936acb..e0e242cb788 100644
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
@@ -242,10 +242,51 @@ enum dxil_shader_properties_tag
SHADER_PROPERTIES_ENTRY_ROOT_SIG = 12,
};
+enum dxil_binop_code
+{
+ BINOP_ADD = 0,
+ BINOP_SUB = 1,
+ BINOP_MUL = 2,
+ BINOP_UDIV = 3,
+ BINOP_SDIV = 4,
+ BINOP_UREM = 5,
+ BINOP_SREM = 6,
+ BINOP_SHL = 7,
+ BINOP_LSHR = 8,
+ BINOP_ASHR = 9,
+ BINOP_AND = 10,
+ BINOP_OR = 11,
+ BINOP_XOR = 12
+};
+
+enum dxil_fast_fp_flags
+{
+ FP_ALLOW_UNSAFE_ALGEBRA = 0x1,
+ FP_NO_NAN = 0x2,
+ FP_NO_INF = 0x4,
+ FP_NO_SIGNED_ZEROS = 0x8,
+ FP_ALLOW_RECIPROCAL = 0x10,
+};
+
+enum dxil_overflowing_binop_flags
+{
+ /* Operation is known to never overflow. */
+ OB_NO_UNSIGNED_WRAP = 0x1,
+ OB_NO_SIGNED_WRAP = 0x2,
+};
+
+enum dxil_possibly_exact_binop_flags
+{
+ /* "A udiv or sdiv instruction, which can be marked as "exact", indicating that no bits are destroyed." */
+ PEB_EXACT = 0x1,
+};
+
enum dx_intrinsic_opcode
{
DX_LOAD_INPUT = 4,
DX_STORE_OUTPUT = 5,
+ DX_CREATE_HANDLE = 57,
+ DX_CBUFFER_LOAD_LEGACY = 59,
};
struct sm6_pointer_info
@@ -305,6 +346,7 @@ enum sm6_value_type
{
VALUE_TYPE_FUNCTION,
VALUE_TYPE_REG,
+ VALUE_TYPE_HANDLE,
};
struct sm6_function_data
@@ -314,6 +356,12 @@ struct sm6_function_data
unsigned int attribs_id;
};
+struct sm6_handle_data
+{
+ const struct sm6_descriptor_info *d;
+ struct vkd3d_shader_register reg;
+};
+
struct sm6_value
{
const struct sm6_type *type;
@@ -323,6 +371,7 @@ struct sm6_value
{
struct sm6_function_data function;
struct vkd3d_shader_register reg;
+ struct sm6_handle_data handle;
} u;
};
@@ -427,6 +476,13 @@ struct sm6_named_metadata
struct sm6_metadata_value value;
};
+struct sm6_descriptor_info
+{
+ enum vkd3d_shader_descriptor_type type;
+ unsigned int id;
+ struct vkd3d_shader_register_range range;
+};
+
struct sm6_parser
{
const uint32_t *ptr, *start, *end;
@@ -442,6 +498,7 @@ struct sm6_parser
struct sm6_type *types;
size_t type_count;
struct sm6_type *metadata_type;
+ struct sm6_type *handle_type;
struct sm6_symbol *global_symbols;
size_t global_symbol_count;
@@ -458,6 +515,10 @@ struct sm6_parser
struct sm6_named_metadata *named_metadata;
unsigned int named_metadata_count;
+ struct sm6_descriptor_info *descriptors;
+ size_t descriptor_capacity;
+ size_t descriptor_count;
+
struct sm6_value *values;
size_t value_count;
size_t value_capacity;
@@ -1352,7 +1413,7 @@ static enum vkd3d_result sm6_parser_type_table_init(struct sm6_parser *sm6)
case TYPE_CODE_STRUCT_ANON:
case TYPE_CODE_STRUCT_NAMED:
- if (!dxil_record_validate_operand_min_count(record, 2, sm6))
+ if (!dxil_record_validate_operand_min_count(record, 1, sm6))
return VKD3D_ERROR_INVALID_SHADER;
if (record->code == TYPE_CODE_STRUCT_NAMED && !struct_name)
{
@@ -1391,6 +1452,9 @@ static enum vkd3d_result sm6_parser_type_table_init(struct sm6_parser *sm6)
break;
}
+ if (!ascii_strcasecmp(struct_name, "dx.types.Handle"))
+ sm6->handle_type = type;
+
type->u.struc->name = struct_name;
struct_name = NULL;
break;
@@ -1438,6 +1502,16 @@ static inline bool sm6_type_is_integer(const struct sm6_type *type)
return type->class == TYPE_CLASS_INTEGER;
}
+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_bool(const struct sm6_type *type)
+{
+ return type->class == TYPE_CLASS_INTEGER && type->u.width == 1;
+}
+
static inline bool sm6_type_is_i8(const struct sm6_type *type)
{
return type->class == TYPE_CLASS_INTEGER && type->u.width == 8;
@@ -1453,6 +1527,11 @@ static inline bool sm6_type_is_floating_point(const struct sm6_type *type)
return type->class == TYPE_CLASS_FLOAT;
}
+static bool sm6_type_is_scalar(const struct sm6_type *type)
+{
+ return type->class == TYPE_CLASS_INTEGER || type->class == TYPE_CLASS_FLOAT || type->class == TYPE_CLASS_POINTER;
+}
+
static inline bool sm6_type_is_numeric(const struct sm6_type *type)
{
return type->class == TYPE_CLASS_INTEGER || type->class == TYPE_CLASS_FLOAT;
@@ -1463,6 +1542,11 @@ static inline bool sm6_type_is_pointer(const struct sm6_type *type)
return type->class == TYPE_CLASS_POINTER;
}
+static bool sm6_type_is_aggregate(const struct sm6_type *type)
+{
+ return type->class == TYPE_CLASS_STRUCT || type->class == TYPE_CLASS_VECTOR || type->class == TYPE_CLASS_ARRAY;
+}
+
static bool sm6_type_is_numeric_aggregate(const struct sm6_type *type)
{
unsigned int i;
@@ -1533,6 +1617,27 @@ static const struct sm6_type *sm6_type_get_pointer_to_type(const struct sm6_type
return NULL;
}
+/* Call for aggregate types only. */
+static const struct sm6_type *sm6_type_get_element_type_at_index(const struct sm6_type *type, uint64_t elem_idx)
+{
+ switch (type->class)
+ {
+ case TYPE_CLASS_ARRAY:
+ case TYPE_CLASS_VECTOR:
+ if (elem_idx >= type->u.array.count)
+ return NULL;
+ return type->u.array.elem_type;
+
+ case TYPE_CLASS_STRUCT:
+ if (elem_idx >= type->u.struc->elem_count)
+ return NULL;
+ return type->u.struc->elem_types[elem_idx];
+
+ default:
+ vkd3d_unreachable();
+ }
+}
+
/* Never returns null for elem_idx 0. */
static const struct sm6_type *sm6_type_get_scalar_type(const struct sm6_type *type, unsigned int elem_idx)
{
@@ -1557,6 +1662,11 @@ static const struct sm6_type *sm6_type_get_scalar_type(const struct sm6_type *ty
}
}
+static unsigned int sm6_type_max_vector_size(const struct sm6_type *type)
+{
+ return min((VKD3D_VEC4_SIZE * sizeof(uint32_t) * CHAR_BIT) / type->u.width, VKD3D_VEC4_SIZE);
+}
+
static const struct sm6_type *sm6_parser_get_type(struct sm6_parser *sm6, uint64_t type_id)
{
if (type_id >= sm6->type_count)
@@ -1661,7 +1771,7 @@ static const char *sm6_parser_get_global_symbol_name(const struct sm6_parser *sm
static unsigned int register_get_uint_value(const struct vkd3d_shader_register *reg)
{
- if (!register_is_constant(reg) || !data_type_is_integer(reg->data_type))
+ if (!register_is_constant(reg) || (!data_type_is_integer(reg->data_type) && !data_type_is_bool(reg->data_type)))
return UINT_MAX;
if (reg->dimension == VSIR_DIMENSION_VEC4)
@@ -1710,6 +1820,11 @@ static inline bool sm6_value_is_register(const struct sm6_value *value)
return value->value_type == VALUE_TYPE_REG;
}
+static bool sm6_value_is_handle(const struct sm6_value *value)
+{
+ return value->value_type == VALUE_TYPE_HANDLE;
+}
+
static inline bool sm6_value_is_constant(const struct sm6_value *value)
{
return sm6_value_is_register(value) && register_is_constant(&value->u.reg);
@@ -1782,6 +1897,8 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type
{
switch (type->u.width)
{
+ case 1:
+ return VKD3D_DATA_BOOL;
case 8:
return VKD3D_DATA_UINT8;
case 32:
@@ -1811,8 +1928,8 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type
return VKD3D_DATA_UINT;
}
-static void register_init_ssa_scalar(struct vkd3d_shader_register *reg, const struct sm6_type *type,
- struct sm6_parser *sm6)
+static void register_init_ssa_vector(struct vkd3d_shader_register *reg, const struct sm6_type *type,
+ unsigned int component_count, struct sm6_parser *sm6)
{
enum vkd3d_data_type data_type;
unsigned int id;
@@ -1820,6 +1937,13 @@ static void register_init_ssa_scalar(struct vkd3d_shader_register *reg, const st
id = sm6_parser_alloc_ssa_id(sm6);
data_type = vkd3d_data_type_from_sm6_type(sm6_type_get_scalar_type(type, 0));
register_init_with_id(reg, VKD3DSPR_SSA, data_type, id);
+ reg->dimension = component_count > 1 ? VSIR_DIMENSION_VEC4 : VSIR_DIMENSION_SCALAR;
+}
+
+static void register_init_ssa_scalar(struct vkd3d_shader_register *reg, const struct sm6_type *type,
+ struct sm6_parser *sm6)
+{
+ register_init_ssa_vector(reg, type, 1, sm6);
}
static void dst_param_init(struct vkd3d_shader_dst_param *param)
@@ -1836,6 +1960,13 @@ static inline void dst_param_init_scalar(struct vkd3d_shader_dst_param *param, u
param->shift = 0;
}
+static void dst_param_init_vector(struct vkd3d_shader_dst_param *param, unsigned int component_count)
+{
+ param->write_mask = (1u << component_count) - 1;
+ param->modifiers = 0;
+ param->shift = 0;
+}
+
static void dst_param_init_ssa_scalar(struct vkd3d_shader_dst_param *param, const struct sm6_type *type,
struct sm6_parser *sm6)
{
@@ -1861,25 +1992,32 @@ static void src_param_init_from_value(struct vkd3d_shader_src_param *param, cons
param->reg = src->u.reg;
}
-static void register_address_init(struct vkd3d_shader_register *reg, const struct sm6_value *address,
- unsigned int idx, struct sm6_parser *sm6)
+static void src_param_init_vector_from_reg(struct vkd3d_shader_src_param *param,
+ const struct vkd3d_shader_register *reg)
+{
+ param->swizzle = VKD3D_SHADER_NO_SWIZZLE;
+ param->modifiers = VKD3DSPSM_NONE;
+ param->reg = *reg;
+}
+
+static void register_index_address_init(struct vkd3d_shader_register_index *idx, const struct sm6_value *address,
+ struct sm6_parser *sm6)
{
- assert(idx < ARRAY_SIZE(reg->idx));
if (sm6_value_is_constant(address))
{
- reg->idx[idx].offset = sm6_value_get_constant_uint(address);
+ idx->offset = sm6_value_get_constant_uint(address);
}
else if (sm6_value_is_undef(address))
{
- reg->idx[idx].offset = 0;
+ idx->offset = 0;
}
else
{
struct vkd3d_shader_src_param *rel_addr = shader_parser_get_src_params(&sm6->p, 1);
if (rel_addr)
src_param_init_from_value(rel_addr, address);
- reg->idx[idx].offset = 0;
- reg->idx[idx].rel_addr = rel_addr;
+ idx->offset = 0;
+ idx->rel_addr = rel_addr;
}
}
@@ -1893,6 +2031,17 @@ static void instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instructio
dst->u.reg = param->reg;
}
+static void instruction_dst_param_init_ssa_vector(struct vkd3d_shader_instruction *ins,
+ unsigned int component_count, struct sm6_parser *sm6)
+{
+ struct vkd3d_shader_dst_param *param = instruction_dst_params_alloc(ins, 1, sm6);
+ struct sm6_value *dst = sm6_parser_get_current_value(sm6);
+
+ dst_param_init_vector(param, component_count);
+ register_init_ssa_vector(&param->reg, sm6_type_get_scalar_type(dst->type, 0), component_count, sm6);
+ dst->u.reg = param->reg;
+}
+
/* Recurse through the block tree while maintaining a current value count. The current
* count is the sum of the global count plus all declarations within the current function.
* Store into value_capacity the highest count seen. */
@@ -1957,6 +2106,18 @@ static size_t sm6_parser_get_value_index(struct sm6_parser *sm6, uint64_t idx)
return i;
}
+static bool sm6_value_validate_is_handle(const struct sm6_value *value, struct sm6_parser *sm6)
+{
+ if (!sm6_value_is_handle(value))
+ {
+ WARN("Handle parameter of type %u is not a handle.\n", value->value_type);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE,
+ "A handle parameter passed to a DX intrinsic function is not a handle.");
+ return false;
+ }
+ return true;
+}
+
static const struct sm6_value *sm6_parser_get_value_safe(struct sm6_parser *sm6, unsigned int idx)
{
if (idx < sm6->value_count)
@@ -2230,9 +2391,7 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const
dst = sm6_parser_get_current_value(sm6);
dst->type = type;
dst->value_type = VALUE_TYPE_REG;
- dst->u.reg.type = reg_type;
- dst->u.reg.dimension = VSIR_DIMENSION_SCALAR;
- dst->u.reg.data_type = reg_data_type;
+ vsir_register_init(&dst->u.reg, reg_type, reg_data_type, 0);
switch (record->code)
{
@@ -2519,6 +2678,273 @@ static struct sm6_block *sm6_block_create()
return block;
}
+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)
+{
+ bool is_int = sm6_type_is_bool_i16_i32_i64(type_a);
+ bool is_bool = sm6_type_is_bool(type_a);
+ enum vkd3d_shader_opcode op;
+ bool is_valid;
+
+ if (!is_int && !sm6_type_is_floating_point(type_a))
+ {
+ WARN("Argument type %u is not bool, int16/32/64 or floating point.\n", type_a->class);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "An argument to a binary operation is not bool, int16/32/64 or floating point.");
+ return VKD3DSIH_INVALID;
+ }
+ if (type_a != type_b)
+ {
+ WARN("Type mismatch, type %u width %u vs type %u width %u.\n", type_a->class,
+ type_a->u.width, type_b->class, type_b->u.width);
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH,
+ "Type mismatch in binary operation arguments.");
+ }
+
+ switch (code)
+ {
+ case BINOP_ADD:
+ case BINOP_SUB:
+ /* NEG is applied later for subtraction. */
+ op = is_int ? VKD3DSIH_IADD : VKD3DSIH_ADD;
+ is_valid = !is_bool;
+ break;
+ case BINOP_AND:
+ op = VKD3DSIH_AND;
+ is_valid = is_int;
+ break;
+ case BINOP_ASHR:
+ op = VKD3DSIH_ISHR;
+ is_valid = is_int && !is_bool;
+ break;
+ case BINOP_LSHR:
+ op = VKD3DSIH_USHR;
+ is_valid = is_int && !is_bool;
+ break;
+ case BINOP_MUL:
+ op = is_int ? VKD3DSIH_UMUL : VKD3DSIH_MUL;
+ is_valid = !is_bool;
+ break;
+ case BINOP_OR:
+ op = VKD3DSIH_OR;
+ is_valid = is_int;
+ break;
+ case BINOP_SDIV:
+ op = is_int ? VKD3DSIH_IDIV : VKD3DSIH_DIV;
+ is_valid = !is_bool;
+ break;
+ case BINOP_SREM:
+ op = is_int ? VKD3DSIH_IDIV : VKD3DSIH_FREM;
+ is_valid = !is_bool;
+ break;
+ case BINOP_SHL:
+ op = VKD3DSIH_ISHL;
+ is_valid = is_int && !is_bool;
+ break;
+ case BINOP_UDIV:
+ case BINOP_UREM:
+ op = VKD3DSIH_UDIV;
+ is_valid = is_int && !is_bool;
+ break;
+ case BINOP_XOR:
+ op = VKD3DSIH_XOR;
+ is_valid = is_int;
+ break;
+ default:
+ FIXME("Unhandled binary op %#"PRIx64".\n", code);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Binary operation %#"PRIx64" is unhandled.", code);
+ return VKD3DSIH_INVALID;
+ }
+
+ if (!is_valid)
+ {
+ WARN("Invalid operation %u for type %u, width %u.\n", op, type_a->class, type_a->u.width);
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION,
+ "Binary operation %u is invalid on type class %u, width %u.", op, type_a->class, type_a->u.width);
+ }
+
+ return op;
+}
+
+static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_record *record,
+ struct vkd3d_shader_instruction *ins, struct sm6_value *dst)
+{
+ struct vkd3d_shader_src_param *src_params;
+ enum vkd3d_shader_opcode handler_idx;
+ const struct sm6_value *a, *b;
+ unsigned int i = 0;
+ uint64_t code;
+
+ a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i);
+ b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i);
+ if (!a || !b)
+ return;
+
+ if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6))
+ return;
+
+ code = record->operands[i++];
+ if ((handler_idx = map_binary_op(code, a->type, b->type, sm6)) == VKD3DSIH_INVALID)
+ return;
+
+ vsir_instruction_init(ins, &sm6->p.location, handler_idx);
+
+ if (record->operand_count > i && record->operands[i])
+ {
+ uint64_t flags = record->operands[i];
+ bool silence_warning = false;
+
+ switch (handler_idx)
+ {
+ case VKD3DSIH_ADD:
+ case VKD3DSIH_MUL:
+ case VKD3DSIH_DIV:
+ case VKD3DSIH_FREM:
+ if (!(flags & FP_ALLOW_UNSAFE_ALGEBRA))
+ ins->flags |= VKD3DSI_PRECISE_X;
+ flags &= ~FP_ALLOW_UNSAFE_ALGEBRA;
+ /* SPIR-V FPFastMathMode is only available in the Kernel executon model. */
+ silence_warning = !(flags & ~(FP_NO_NAN | FP_NO_INF | FP_NO_SIGNED_ZEROS | FP_ALLOW_RECIPROCAL));
+ break;
+ case VKD3DSIH_IADD:
+ case VKD3DSIH_UMUL:
+ case VKD3DSIH_ISHL:
+ silence_warning = !(flags & ~(OB_NO_UNSIGNED_WRAP | OB_NO_SIGNED_WRAP));
+ break;
+ case VKD3DSIH_ISHR:
+ case VKD3DSIH_USHR:
+ case VKD3DSIH_IDIV:
+ case VKD3DSIH_UDIV:
+ silence_warning = !(flags & ~PEB_EXACT);
+ break;
+ default:
+ break;
+ }
+ /* The above flags are very common and cause warning spam. */
+ if (flags && silence_warning)
+ {
+ TRACE("Ignoring flags %#"PRIx64".\n", flags);
+ }
+ else if (flags)
+ {
+ WARN("Ignoring flags %#"PRIx64".\n", flags);
+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS,
+ "Ignoring flags %#"PRIx64" for a binary operation.", flags);
+ }
+ }
+
+ src_params = instruction_src_params_alloc(ins, 2, sm6);
+ src_param_init_from_value(&src_params[0], a);
+ src_param_init_from_value(&src_params[1], b);
+ if (code == BINOP_SUB)
+ src_params[1].modifiers = VKD3DSPSM_NEG;
+
+ dst->type = a->type;
+
+ if (handler_idx == VKD3DSIH_UMUL || handler_idx == VKD3DSIH_UDIV || handler_idx == VKD3DSIH_IDIV)
+ {
+ struct vkd3d_shader_dst_param *dst_params = instruction_dst_params_alloc(ins, 2, sm6);
+ unsigned int index = code != BINOP_UDIV && code != BINOP_SDIV;
+
+ dst_param_init(&dst_params[0]);
+ dst_param_init(&dst_params[1]);
+ register_init_ssa_scalar(&dst_params[index].reg, a->type, sm6);
+ vsir_register_init(&dst_params[index ^ 1].reg, VKD3DSPR_NULL, VKD3D_DATA_UNUSED, 0);
+ dst->u.reg = dst_params[index].reg;
+ }
+ else
+ {
+ 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)
+{
+ struct sm6_value *dst = sm6_parser_get_current_value(sm6);
+ struct vkd3d_shader_src_param *src_param;
+ const struct sm6_value *buffer;
+ const struct sm6_type *type;
+
+ buffer = operands[0];
+ if (!sm6_value_validate_is_handle(buffer, sm6))
+ return;
+
+ vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV);
+
+ src_param = instruction_src_params_alloc(ins, 1, sm6);
+ src_param_init_vector_from_reg(src_param, &buffer->u.handle.reg);
+ register_index_address_init(&src_param->reg.idx[2], operands[1], sm6);
+ assert(src_param->reg.idx_count == 3);
+
+ type = sm6_type_get_scalar_type(dst->type, 0);
+ assert(type);
+ src_param->reg.data_type = vkd3d_data_type_from_sm6_type(type);
+
+ instruction_dst_param_init_ssa_vector(ins, sm6_type_max_vector_size(type), sm6);
+}
+
+static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_parser *sm6,
+ enum vkd3d_shader_descriptor_type type, unsigned int id, const struct sm6_value *address)
+{
+ const struct sm6_descriptor_info *d;
+ unsigned int register_index;
+ size_t i;
+
+ for (i = 0; i < sm6->descriptor_count; ++i)
+ {
+ d = &sm6->descriptors[i];
+
+ if (d->type != type || d->id != id)
+ continue;
+
+ if (!sm6_value_is_constant(address))
+ return d;
+
+ register_index = sm6_value_get_constant_uint(address);
+ if (register_index >= d->range.first && register_index <= d->range.last)
+ return d;
+ }
+
+ return NULL;
+}
+
+static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, struct sm6_block *code_block,
+ enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins)
+{
+ enum vkd3d_shader_descriptor_type type;
+ const struct sm6_descriptor_info *d;
+ struct vkd3d_shader_register *reg;
+ struct sm6_value *dst;
+ unsigned int id;
+
+ type = sm6_value_get_constant_uint(operands[0]);
+ id = sm6_value_get_constant_uint(operands[1]);
+ if (!(d = sm6_parser_get_descriptor(sm6, type, id, operands[2])))
+ {
+ WARN("Failed to find resource type %#x, id %#x.\n", type, id);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Descriptor for resource type %#x, id %#x was not found.", type, id);
+ return;
+ }
+
+ dst = sm6_parser_get_current_value(sm6);
+ dst->value_type = VALUE_TYPE_HANDLE;
+ dst->u.handle.d = d;
+
+ reg = &dst->u.handle.reg;
+ /* Set idx_count to 3 for use with load instructions.
+ * TODO: set register type from resource type when other types are supported. */
+ vsir_register_init(reg, VKD3DSPR_CONSTBUFFER, VKD3D_DATA_FLOAT, 3);
+ reg->idx[0].offset = id;
+ register_index_address_init(&reg->idx[1], operands[2], sm6);
+ reg->non_uniform = !!sm6_value_get_constant_uint(operands[3]);
+
+ /* NOP is used to flag no instruction emitted. */
+ ins->handler_idx = VKD3DSIH_NOP;
+}
+
static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, struct sm6_block *code_block,
enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins)
{
@@ -2546,7 +2972,7 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, struct sm6_blo
src_param->reg = sm6->input_params[row_index].reg;
src_param_init_scalar(src_param, column_index);
if (e->register_count > 1)
- register_address_init(&src_param->reg, operands[1], 0, sm6);
+ register_index_address_init(&src_param->reg.idx[0], operands[1], sm6);
instruction_dst_param_init_ssa_scalar(ins, sm6);
}
@@ -2598,7 +3024,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, struct sm6_b
dst_param_init_scalar(dst_param, column_index);
dst_param->reg = sm6->output_params[row_index].reg;
if (e->register_count > 1)
- register_address_init(&dst_param->reg, operands[1], 0, sm6);
+ register_index_address_init(&dst_param->reg.idx[0], operands[1], sm6);
if ((src_param = instruction_src_params_alloc(ins, 1, sm6)))
src_param_init_from_value(src_param, value);
@@ -2614,18 +3040,29 @@ struct sm6_dx_opcode_info
/*
8 -> int8
+ b -> constant int1
+ c -> constant int8/16/32
i -> int32
+ 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},
};
-static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_type *type, char info_type)
+static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type,
+ bool is_return)
{
+ const struct sm6_type *type = value->type;
+
+ if (info_type != 'H' && !sm6_value_is_register(value))
+ return false;
+
switch (info_type)
{
case 0:
@@ -2633,8 +3070,15 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc
return false;
case '8':
return sm6_type_is_i8(type);
+ case 'b':
+ return sm6_value_is_constant(value) && sm6_type_is_bool(type);
+ case 'c':
+ return sm6_value_is_constant(value) && sm6_type_is_integer(type) && type->u.width >= 8
+ && type->u.width <= 32;
case 'i':
return sm6_type_is_i32(type);
+ case 'H':
+ return (is_return || sm6_value_is_handle(value)) && type == sm6->handle_type;
case 'v':
return !type;
case 'o':
@@ -2654,7 +3098,7 @@ 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->type, info->ret_type))
+ if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type, true))
{
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
@@ -2664,7 +3108,7 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_
for (i = 0; i < operand_count; ++i)
{
const struct sm6_value *value = operands[i];
- if (!sm6_value_is_register(value) || !sm6_parser_validate_operand_type(sm6, value->type, info->operand_info[i]))
+ if (!sm6_parser_validate_operand_type(sm6, value, info->operand_info[i], false))
{
WARN("Failed to validate operand %u for dx intrinsic id %u, '%s'.\n", i + 1, op, name);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
@@ -2804,6 +3248,64 @@ static void sm6_parser_emit_call(struct sm6_parser *sm6, const struct dxil_recor
fn_value->u.function.name, &operands[1], operand_count - 1, ins, dst);
}
+static void sm6_parser_emit_extractval(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;
+ const struct sm6_type *type;
+ const struct sm6_value *src;
+ unsigned int i = 0;
+ uint64_t elem_idx;
+
+ if (!(src = sm6_parser_get_value_by_ref(sm6, record, NULL, &i)))
+ return;
+
+ if (!dxil_record_validate_operand_min_count(record, i + 1, sm6))
+ return;
+
+ if (record->operand_count > i + 1)
+ {
+ FIXME("Unhandled multiple indices.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Multiple extractval indices are not supported.");
+ return;
+ }
+
+ type = src->type;
+ if (!sm6_type_is_aggregate(type))
+ {
+ WARN("Invalid extraction from non-aggregate.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Source type of an extractval instruction is not an aggregate.");
+ return;
+ }
+
+ elem_idx = record->operands[i];
+ if (!(type = sm6_type_get_element_type_at_index(type, elem_idx)))
+ {
+ WARN("Invalid element index %"PRIu64".\n", elem_idx);
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Element index %"PRIu64" for an extractval instruction is out of bounds.", elem_idx);
+ return;
+ }
+ if (!sm6_type_is_scalar(type))
+ {
+ FIXME("Nested extraction is not supported.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND,
+ "Extraction from nested aggregates is not supported.");
+ return;
+ }
+ dst->type = type;
+
+ ins->handler_idx = VKD3DSIH_MOV;
+
+ src_param = instruction_src_params_alloc(ins, 1, sm6);
+ src_param_init_from_value(src_param, src);
+ src_param->swizzle = vkd3d_shader_create_swizzle(elem_idx, elem_idx, elem_idx, elem_idx);
+
+ instruction_dst_param_init_ssa_scalar(ins, sm6);
+}
+
static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record *record,
struct sm6_block *code_block, struct vkd3d_shader_instruction *ins)
{
@@ -2956,9 +3458,15 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const
record = block->records[i];
switch (record->code)
{
+ case FUNC_CODE_INST_BINOP:
+ sm6_parser_emit_binop(sm6, record, ins, dst);
+ break;
case FUNC_CODE_INST_CALL:
sm6_parser_emit_call(sm6, record, code_block, ins, dst);
break;
+ case FUNC_CODE_INST_EXTRACTVAL:
+ sm6_parser_emit_extractval(sm6, record, ins, dst);
+ break;
case FUNC_CODE_INST_RET:
sm6_parser_emit_ret(sm6, record, code_block, ins);
is_terminator = true;
@@ -3423,8 +3931,7 @@ static bool sm6_parser_resources_load_register_range(struct sm6_parser *sm6,
}
static enum vkd3d_result sm6_parser_resources_load_cbv(struct sm6_parser *sm6,
- const struct sm6_metadata_node *node, const struct vkd3d_shader_register_range *range,
- unsigned int register_id, struct vkd3d_shader_instruction *ins)
+ const struct sm6_metadata_node *node, struct sm6_descriptor_info *d, struct vkd3d_shader_instruction *ins)
{
struct vkd3d_shader_register *reg;
unsigned int buffer_size;
@@ -3459,11 +3966,11 @@ static enum vkd3d_result sm6_parser_resources_load_cbv(struct sm6_parser *sm6,
reg = &ins->declaration.cb.src.reg;
vsir_register_init(reg, VKD3DSPR_CONSTBUFFER, VKD3D_DATA_FLOAT, 3);
- reg->idx[0].offset = register_id;
- reg->idx[1].offset = range->first;
- reg->idx[2].offset = range->last;
+ reg->idx[0].offset = d->id;
+ reg->idx[1].offset = d->range.first;
+ reg->idx[2].offset = d->range.last;
- ins->declaration.cb.range = *range;
+ ins->declaration.cb.range = d->range;
return VKD3D_OK;
}
@@ -3471,12 +3978,12 @@ static enum vkd3d_result sm6_parser_resources_load_cbv(struct sm6_parser *sm6,
static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6,
enum vkd3d_shader_descriptor_type type, const struct sm6_metadata_node *descriptor_node)
{
- struct vkd3d_shader_register_range range;
struct vkd3d_shader_instruction *ins;
const struct sm6_metadata_node *node;
const struct sm6_metadata_value *m;
- unsigned int i, register_id;
+ struct sm6_descriptor_info *d;
enum vkd3d_result ret;
+ unsigned int i;
for (i = 0; i < descriptor_node->operand_count; ++i)
{
@@ -3498,7 +4005,18 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6,
return VKD3D_ERROR_INVALID_SHADER;
}
- if (!sm6_metadata_get_uint_value(sm6, node->operands[0], &register_id))
+ if (!vkd3d_array_reserve((void **)&sm6->descriptors, &sm6->descriptor_capacity,
+ sm6->descriptor_count + 1, sizeof(*sm6->descriptors)))
+ {
+ ERR("Failed to allocate descriptor array.\n");
+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
+ "Out of memory allocating the descriptor array.");
+ return VKD3D_ERROR_OUT_OF_MEMORY;
+ }
+ d = &sm6->descriptors[sm6->descriptor_count];
+ d->type = type;
+
+ if (!sm6_metadata_get_uint_value(sm6, node->operands[0], &d->id))
{
WARN("Failed to load resource id.\n");
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES,
@@ -3506,7 +4024,7 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6,
return VKD3D_ERROR_INVALID_SHADER;
}
- if (!sm6_parser_resources_load_register_range(sm6, node, &range))
+ if (!sm6_parser_resources_load_register_range(sm6, node, &d->range))
{
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES,
"Resource register range is invalid.");
@@ -3522,7 +4040,7 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6,
switch (type)
{
case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV:
- if ((ret = sm6_parser_resources_load_cbv(sm6, node, &range, register_id, ins)) < 0)
+ if ((ret = sm6_parser_resources_load_cbv(sm6, node, d, ins)) < 0)
return ret;
break;
default:
@@ -3532,6 +4050,7 @@ static enum vkd3d_result sm6_parser_descriptor_type_init(struct sm6_parser *sm6,
return VKD3D_ERROR_INVALID_SHADER;
}
+ ++sm6->descriptor_count;
++sm6->p.instructions.count;
}
@@ -3779,10 +4298,12 @@ static enum vkd3d_result sm6_parser_read_signature(struct sm6_parser *sm6, const
return VKD3D_ERROR_INVALID_SHADER;
}
- e->mask = vkd3d_write_mask_from_component_count(column_count) << index;
+ e->mask = vkd3d_write_mask_from_component_count(column_count);
e->used_mask = e->mask;
+ e->mask <<= index;
signature_element_read_additional_element_values(e, element_node, sm6);
+ e->used_mask <<= index;
m = element_node->operands[4];
if (!sm6_metadata_value_is_node(m))
@@ -3857,7 +4378,7 @@ static void sm6_parser_emit_global_flags(struct sm6_parser *sm6, const struct sm
enum vkd3d_shader_global_flags global_flags, mask, rotated_flags;
struct vkd3d_shader_instruction *ins;
- if (!sm6_metadata_get_uint64_value(sm6, m, &global_flags))
+ if (!sm6_metadata_get_uint64_value(sm6, m, (uint64_t*)&global_flags))
{
WARN("Failed to load global flags.\n");
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
@@ -4132,6 +4653,7 @@ static void sm6_parser_destroy(struct vkd3d_shader_parser *parser)
sm6_symtab_cleanup(sm6->global_symbols, sm6->global_symbol_count);
sm6_functions_cleanup(sm6->functions, sm6->function_count);
sm6_parser_metadata_cleanup(sm6);
+ vkd3d_free(sm6->descriptors);
vkd3d_free(sm6->values);
free_shader_desc(&parser->shader_desc);
vkd3d_free(sm6);
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
index 2d383bc2fb5..1d3fd0f7d83 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
@@ -249,14 +249,7 @@ static enum hlsl_regset type_get_regset(const struct hlsl_type *type)
enum hlsl_regset hlsl_deref_get_regset(struct hlsl_ctx *ctx, const struct hlsl_deref *deref)
{
- struct hlsl_type *type;
-
- if (deref->data_type)
- type = deref->data_type;
- else
- type = hlsl_deref_get_type(ctx, deref);
-
- return type_get_regset(type);
+ return type_get_regset(hlsl_deref_get_type(ctx, deref));
}
unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset)
@@ -519,7 +512,9 @@ static bool init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hl
{
deref->var = var;
deref->path_len = path_len;
- deref->offset.node = NULL;
+ deref->rel_offset.node = NULL;
+ deref->const_offset = 0;
+ deref->data_type = NULL;
if (path_len == 0)
{
@@ -546,7 +541,8 @@ bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *d
deref->path = NULL;
deref->path_len = 0;
- deref->offset.node = NULL;
+ deref->rel_offset.node = NULL;
+ deref->const_offset = 0;
assert(chain);
if (chain->type == HLSL_IR_INDEX)
@@ -609,7 +605,7 @@ struct hlsl_type *hlsl_deref_get_type(struct hlsl_ctx *ctx, const struct hlsl_de
assert(deref);
- if (deref->offset.node)
+ if (hlsl_deref_is_lowered(deref))
return deref->data_type;
type = deref->var->data_type;
@@ -763,7 +759,7 @@ struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim
{
struct hlsl_type *type;
- if (!(type = vkd3d_calloc(1, sizeof(*type))))
+ if (!(type = hlsl_alloc(ctx, sizeof(*type))))
return NULL;
type->class = HLSL_CLASS_OBJECT;
type->base_type = HLSL_TYPE_UAV;
@@ -1120,7 +1116,7 @@ bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struc
if (!other)
return true;
- assert(!other->offset.node);
+ assert(!hlsl_deref_is_lowered(other));
if (!init_deref(ctx, deref, other->var, other->path_len))
return false;
@@ -1142,7 +1138,8 @@ void hlsl_cleanup_deref(struct hlsl_deref *deref)
deref->path = NULL;
deref->path_len = 0;
- hlsl_src_remove(&deref->offset);
+ hlsl_src_remove(&deref->rel_offset);
+ deref->const_offset = 0;
}
/* Initializes a simple variable dereference, so that it can be passed to load/store functions. */
@@ -1177,7 +1174,7 @@ struct hlsl_ir_node *hlsl_new_store_index(struct hlsl_ctx *ctx, const struct hls
unsigned int i;
assert(lhs);
- assert(!lhs->offset.node);
+ assert(!hlsl_deref_is_lowered(lhs));
if (!(store = hlsl_alloc(ctx, sizeof(*store))))
return NULL;
@@ -1343,6 +1340,40 @@ struct hlsl_ir_node *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *cond
return &iff->node;
}
+struct hlsl_ir_switch_case *hlsl_new_switch_case(struct hlsl_ctx *ctx, unsigned int value,
+ bool is_default, struct hlsl_block *body, const struct vkd3d_shader_location *loc)
+{
+ struct hlsl_ir_switch_case *c;
+
+ if (!(c = hlsl_alloc(ctx, sizeof(*c))))
+ return NULL;
+
+ c->value = value;
+ c->is_default = is_default;
+ hlsl_block_init(&c->body);
+ if (body)
+ hlsl_block_add_block(&c->body, body);
+ c->loc = *loc;
+
+ return c;
+}
+
+struct hlsl_ir_node *hlsl_new_switch(struct hlsl_ctx *ctx, struct hlsl_ir_node *selector,
+ struct list *cases, const struct vkd3d_shader_location *loc)
+{
+ struct hlsl_ir_switch *s;
+
+ if (!(s = hlsl_alloc(ctx, sizeof(*s))))
+ return NULL;
+ init_node(&s->node, HLSL_IR_SWITCH, NULL, loc);
+ hlsl_src_from_node(&s->selector, selector);
+ list_init(&s->cases);
+ if (cases)
+ list_move_head(&s->cases, cases);
+
+ return &s->node;
+}
+
struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl_deref *deref,
struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc)
{
@@ -1350,7 +1381,7 @@ struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl
struct hlsl_type *type;
unsigned int i;
- assert(!deref->offset.node);
+ assert(!hlsl_deref_is_lowered(deref));
type = hlsl_deref_get_type(ctx, deref);
if (idx)
@@ -1586,7 +1617,7 @@ static bool clone_block(struct hlsl_ctx *ctx, struct hlsl_block *dst_block,
if (!list_empty(&src->uses))
{
- if (!vkd3d_array_reserve((void **)&map->instrs, &map->capacity, map->count + 1, sizeof(*map->instrs)))
+ if (!hlsl_array_reserve(ctx, (void **)&map->instrs, &map->capacity, map->count + 1, sizeof(*map->instrs)))
{
hlsl_block_cleanup(dst_block);
return false;
@@ -1623,7 +1654,7 @@ static bool clone_deref(struct hlsl_ctx *ctx, struct clone_instr_map *map,
{
unsigned int i;
- assert(!src->offset.node);
+ assert(!hlsl_deref_is_lowered(src));
if (!init_deref(ctx, dst, src->var, src->path_len))
return false;
@@ -1805,6 +1836,58 @@ static struct hlsl_ir_node *clone_index(struct hlsl_ctx *ctx, struct clone_instr
return dst;
}
+void hlsl_free_ir_switch_case(struct hlsl_ir_switch_case *c)
+{
+ hlsl_block_cleanup(&c->body);
+ list_remove(&c->entry);
+ vkd3d_free(c);
+}
+
+void hlsl_cleanup_ir_switch_cases(struct list *cases)
+{
+ struct hlsl_ir_switch_case *c, *next;
+
+ LIST_FOR_EACH_ENTRY_SAFE(c, next, cases, struct hlsl_ir_switch_case, entry)
+ {
+ hlsl_free_ir_switch_case(c);
+ }
+}
+
+static struct hlsl_ir_node *clone_switch(struct hlsl_ctx *ctx,
+ struct clone_instr_map *map, struct hlsl_ir_switch *s)
+{
+ struct hlsl_ir_switch_case *c, *d;
+ struct hlsl_ir_node *ret;
+ struct hlsl_block body;
+ struct list cases;
+
+ list_init(&cases);
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ if (!(clone_block(ctx, &body, &c->body, map)))
+ {
+ hlsl_cleanup_ir_switch_cases(&cases);
+ return NULL;
+ }
+
+ d = hlsl_new_switch_case(ctx, c->value, c->is_default, &body, &c->loc);
+ hlsl_block_cleanup(&body);
+ if (!d)
+ {
+ hlsl_cleanup_ir_switch_cases(&cases);
+ return NULL;
+ }
+
+ list_add_tail(&cases, &d->entry);
+ }
+
+ ret = hlsl_new_switch(ctx, map_instr(map, s->selector.node), &cases, &s->node.loc);
+ hlsl_cleanup_ir_switch_cases(&cases);
+
+ return ret;
+}
+
static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx,
struct clone_instr_map *map, const struct hlsl_ir_node *instr)
{
@@ -1843,6 +1926,9 @@ static struct hlsl_ir_node *clone_instr(struct hlsl_ctx *ctx,
case HLSL_IR_STORE:
return clone_store(ctx, map, hlsl_ir_store(instr));
+ case HLSL_IR_SWITCH:
+ return clone_switch(ctx, map, hlsl_ir_switch(instr));
+
case HLSL_IR_SWIZZLE:
return clone_swizzle(ctx, map, hlsl_ir_swizzle(instr));
}
@@ -2261,6 +2347,7 @@ const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type)
[HLSL_IR_RESOURCE_LOAD ] = "HLSL_IR_RESOURCE_LOAD",
[HLSL_IR_RESOURCE_STORE] = "HLSL_IR_RESOURCE_STORE",
[HLSL_IR_STORE ] = "HLSL_IR_STORE",
+ [HLSL_IR_SWITCH ] = "HLSL_IR_SWITCH",
[HLSL_IR_SWIZZLE ] = "HLSL_IR_SWIZZLE",
};
@@ -2327,21 +2414,34 @@ static void dump_deref(struct vkd3d_string_buffer *buffer, const struct hlsl_der
if (deref->var)
{
vkd3d_string_buffer_printf(buffer, "%s", deref->var->name);
- if (deref->path_len)
+ if (!hlsl_deref_is_lowered(deref))
{
- vkd3d_string_buffer_printf(buffer, "[");
- for (i = 0; i < deref->path_len; ++i)
+ if (deref->path_len)
{
vkd3d_string_buffer_printf(buffer, "[");
- dump_src(buffer, &deref->path[i]);
+ for (i = 0; i < deref->path_len; ++i)
+ {
+ vkd3d_string_buffer_printf(buffer, "[");
+ dump_src(buffer, &deref->path[i]);
+ vkd3d_string_buffer_printf(buffer, "]");
+ }
vkd3d_string_buffer_printf(buffer, "]");
}
- vkd3d_string_buffer_printf(buffer, "]");
}
- else if (deref->offset.node)
+ else
{
+ bool show_rel, show_const;
+
+ show_rel = deref->rel_offset.node;
+ show_const = deref->const_offset != 0 || !show_rel;
+
vkd3d_string_buffer_printf(buffer, "[");
- dump_src(buffer, &deref->offset);
+ if (show_rel)
+ dump_src(buffer, &deref->rel_offset);
+ if (show_rel && show_const)
+ vkd3d_string_buffer_printf(buffer, " + ");
+ if (show_const)
+ vkd3d_string_buffer_printf(buffer, "%uc", deref->const_offset);
vkd3d_string_buffer_printf(buffer, "]");
}
}
@@ -2685,6 +2785,32 @@ static void dump_ir_index(struct vkd3d_string_buffer *buffer, const struct hlsl_
vkd3d_string_buffer_printf(buffer, "]");
}
+static void dump_ir_switch(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, const struct hlsl_ir_switch *s)
+{
+ struct hlsl_ir_switch_case *c;
+
+ vkd3d_string_buffer_printf(buffer, "switch (");
+ dump_src(buffer, &s->selector);
+ vkd3d_string_buffer_printf(buffer, ") {\n");
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ if (c->is_default)
+ {
+ vkd3d_string_buffer_printf(buffer, " %10s default: {\n", "");
+ }
+ else
+ {
+ vkd3d_string_buffer_printf(buffer, " %10s case %u : {\n", "", c->value);
+ }
+
+ dump_block(ctx, buffer, &c->body);
+ vkd3d_string_buffer_printf(buffer, " %10s }\n", "");
+ }
+
+ vkd3d_string_buffer_printf(buffer, " %10s }", "");
+}
+
static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, const struct hlsl_ir_node *instr)
{
if (instr->index)
@@ -2740,6 +2866,10 @@ static void dump_instr(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer,
dump_ir_store(buffer, hlsl_ir_store(instr));
break;
+ case HLSL_IR_SWITCH:
+ dump_ir_switch(ctx, buffer, hlsl_ir_switch(instr));
+ break;
+
case HLSL_IR_SWIZZLE:
dump_ir_swizzle(buffer, hlsl_ir_swizzle(instr));
break;
@@ -2881,7 +3011,7 @@ static void free_ir_resource_load(struct hlsl_ir_resource_load *load)
static void free_ir_resource_store(struct hlsl_ir_resource_store *store)
{
- hlsl_src_remove(&store->resource.offset);
+ hlsl_src_remove(&store->resource.rel_offset);
hlsl_src_remove(&store->coords);
hlsl_src_remove(&store->value);
vkd3d_free(store);
@@ -2900,6 +3030,14 @@ static void free_ir_swizzle(struct hlsl_ir_swizzle *swizzle)
vkd3d_free(swizzle);
}
+static void free_ir_switch(struct hlsl_ir_switch *s)
+{
+ hlsl_src_remove(&s->selector);
+ hlsl_cleanup_ir_switch_cases(&s->cases);
+
+ vkd3d_free(s);
+}
+
static void free_ir_index(struct hlsl_ir_index *index)
{
hlsl_src_remove(&index->val);
@@ -2960,6 +3098,10 @@ void hlsl_free_instr(struct hlsl_ir_node *node)
case HLSL_IR_SWIZZLE:
free_ir_swizzle(hlsl_ir_swizzle(node));
break;
+
+ case HLSL_IR_SWITCH:
+ free_ir_switch(hlsl_ir_switch(node));
+ break;
}
}
@@ -3118,7 +3260,7 @@ unsigned int hlsl_combine_swizzles(unsigned int first, unsigned int second, unsi
return ret;
}
-static const struct hlsl_profile_info *get_target_info(const char *target)
+const struct hlsl_profile_info *hlsl_get_target_info(const char *target)
{
unsigned int i;
@@ -3485,14 +3627,12 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d
}
entry_point = hlsl_source_info->entry_point ? hlsl_source_info->entry_point : "main";
- if (!(profile = get_target_info(hlsl_source_info->profile)))
+ if (!(profile = hlsl_get_target_info(hlsl_source_info->profile)))
{
FIXME("Unknown compilation target %s.\n", debugstr_a(hlsl_source_info->profile));
return VKD3D_ERROR_NOT_IMPLEMENTED;
}
- vkd3d_shader_dump_shader(compile_info->source_type, profile->type, &compile_info->source);
-
if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3)
{
vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE,
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
index ea2117e5128..3d8f5aed174 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
@@ -281,6 +281,7 @@ enum hlsl_ir_node_type
HLSL_IR_RESOURCE_STORE,
HLSL_IR_STORE,
HLSL_IR_SWIZZLE,
+ HLSL_IR_SWITCH,
};
/* Common data for every type of IR instruction node. */
@@ -424,6 +425,9 @@ struct hlsl_ir_var
* It may be less than the allocation size, e.g. for texture arrays. */
unsigned int bind_count[HLSL_REGSET_LAST_OBJECT + 1];
+ /* Whether the shader performs dereferences with non-constant offsets in the variable. */
+ bool indexable;
+
uint32_t is_input_semantic : 1;
uint32_t is_output_semantic : 1;
uint32_t is_uniform : 1;
@@ -499,6 +503,22 @@ struct hlsl_ir_loop
unsigned int next_index; /* liveness index of the end of the loop */
};
+struct hlsl_ir_switch_case
+{
+ unsigned int value;
+ bool is_default;
+ struct hlsl_block body;
+ struct list entry;
+ struct vkd3d_shader_location loc;
+};
+
+struct hlsl_ir_switch
+{
+ struct hlsl_ir_node node;
+ struct hlsl_src selector;
+ struct list cases;
+};
+
enum hlsl_ir_expr_op
{
HLSL_OP0_VOID,
@@ -621,17 +641,25 @@ struct hlsl_deref
unsigned int path_len;
struct hlsl_src *path;
- /* Single instruction node of data type uint used to represent the register offset (in register
- * components, within the pertaining regset), from the start of the variable, of the part
- * referenced.
- * The path is lowered to this single offset -- whose value may vary between SM1 and SM4 --
- * before writing the bytecode.
+ /* Before writing the bytecode, deref paths are lowered into an offset (within the pertaining
+ * regset) from the start of the variable, to the part of the variable that is referenced.
+ * This offset is stored using two fields, one for a variable part and other for a constant
+ * part, which are added together:
+ * - rel_offset: An offset given by an instruction node, in whole registers.
+ * - const_offset: A constant number of register components.
* Since the type information cannot longer be retrieved from the offset alone, the type is
- * stored in the data_type field. */
- struct hlsl_src offset;
+ * stored in the data_type field, which remains NULL if the deref hasn't been lowered yet. */
+ struct hlsl_src rel_offset;
+ unsigned int const_offset;
struct hlsl_type *data_type;
};
+/* Whether the path has been lowered to an offset or not. */
+static inline bool hlsl_deref_is_lowered(const struct hlsl_deref *deref)
+{
+ return !!deref->data_type;
+}
+
struct hlsl_ir_load
{
struct hlsl_ir_node node;
@@ -710,6 +738,8 @@ struct hlsl_scope
struct hlsl_scope *upper;
/* The scope was created for the loop statement. */
bool loop;
+ /* The scope was created for the switch statement. */
+ bool _switch;
};
struct hlsl_profile_info
@@ -947,6 +977,12 @@ static inline struct hlsl_ir_index *hlsl_ir_index(const struct hlsl_ir_node *nod
return CONTAINING_RECORD(node, struct hlsl_ir_index, node);
}
+static inline struct hlsl_ir_switch *hlsl_ir_switch(const struct hlsl_ir_node *node)
+{
+ assert(node->type == HLSL_IR_SWITCH);
+ return CONTAINING_RECORD(node, struct hlsl_ir_switch, node);
+}
+
static inline void hlsl_block_init(struct hlsl_block *block)
{
list_init(&block->instrs);
@@ -1120,6 +1156,9 @@ bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struc
void hlsl_cleanup_deref(struct hlsl_deref *deref);
void hlsl_cleanup_semantic(struct hlsl_semantic *semantic);
+void hlsl_cleanup_ir_switch_cases(struct list *cases);
+void hlsl_free_ir_switch_case(struct hlsl_ir_switch_case *c);
+
void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
void hlsl_free_attribute(struct hlsl_attribute *attr);
@@ -1130,6 +1169,7 @@ void hlsl_free_var(struct hlsl_ir_var *decl);
struct hlsl_ir_function *hlsl_get_function(struct hlsl_ctx *ctx, const char *name);
struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const char *name);
+const struct hlsl_profile_info *hlsl_get_target_info(const char *target);
struct hlsl_type *hlsl_get_type(struct hlsl_scope *scope, const char *name, bool recursive, bool case_insensitive);
struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name);
@@ -1213,6 +1253,10 @@ struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr
struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type,
const struct vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, unsigned int modifiers,
const struct hlsl_reg_reservation *reg_reservation);
+struct hlsl_ir_switch_case *hlsl_new_switch_case(struct hlsl_ctx *ctx, unsigned int value, bool is_default,
+ struct hlsl_block *body, const struct vkd3d_shader_location *loc);
+struct hlsl_ir_node *hlsl_new_switch(struct hlsl_ctx *ctx, struct hlsl_ir_node *selector,
+ struct list *cases, const struct vkd3d_shader_location *loc);
void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc,
enum vkd3d_shader_error error, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5);
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l
index b3d4aeee839..0e5f2bb6134 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l
@@ -46,14 +46,13 @@ static void update_location(struct hlsl_ctx *ctx, YYLTYPE *loc);
%x pp pp_line pp_pragma pp_ignore
-RESERVED1 auto|case|catch|char|class|const_cast|default|delete|dynamic_cast|enum
+RESERVED1 auto|catch|char|class|const_cast|delete|dynamic_cast|enum
RESERVED2 explicit|friend|goto|long|mutable|new|operator|private|protected|public
RESERVED3 reinterpret_cast|short|signed|sizeof|static_cast|template|this|throw|try
RESERVED4 typename|union|unsigned|using|virtual
WS [ \t]
NEWLINE (\n)|(\r\n)
-DOUBLESLASHCOMMENT "//"[^\n]*
STRING \"[^\"]*\"
IDENTIFIER [A-Za-z_][A-Za-z0-9_]*
@@ -73,13 +72,16 @@ ANY (.)
BlendState {return KW_BLENDSTATE; }
break {return KW_BREAK; }
Buffer {return KW_BUFFER; }
+case {return KW_CASE; }
cbuffer {return KW_CBUFFER; }
centroid {return KW_CENTROID; }
+column_major {return KW_COLUMN_MAJOR; }
compile {return KW_COMPILE; }
const {return KW_CONST; }
continue {return KW_CONTINUE; }
DepthStencilState {return KW_DEPTHSTENCILSTATE; }
DepthStencilView {return KW_DEPTHSTENCILVIEW; }
+default {return KW_DEFAULT; }
discard {return KW_DISCARD; }
do {return KW_DO; }
double {return KW_DOUBLE; }
@@ -103,9 +105,10 @@ pass {return KW_PASS; }
PixelShader {return KW_PIXELSHADER; }
precise {return KW_PRECISE; }
RasterizerState {return KW_RASTERIZERSTATE; }
+register {return KW_REGISTER; }
RenderTargetView {return KW_RENDERTARGETVIEW; }
return {return KW_RETURN; }
-register {return KW_REGISTER; }
+row_major {return KW_ROW_MAJOR; }
RWBuffer {return KW_RWBUFFER; }
RWStructuredBuffer {return KW_RWSTRUCTUREDBUFFER; }
RWTexture1D {return KW_RWTEXTURE1D; }
@@ -117,10 +120,10 @@ sampler {return KW_SAMPLER; }
sampler1D {return KW_SAMPLER1D; }
sampler2D {return KW_SAMPLER2D; }
sampler3D {return KW_SAMPLER3D; }
-samplerCUBE {return KW_SAMPLERCUBE; }
-sampler_state {return KW_SAMPLER_STATE; }
SamplerComparisonState {return KW_SAMPLERCOMPARISONSTATE;}
+samplerCUBE {return KW_SAMPLERCUBE; }
SamplerState {return KW_SAMPLER; }
+sampler_state {return KW_SAMPLER_STATE; }
shared {return KW_SHARED; }
stateblock {return KW_STATEBLOCK; }
stateblock_state {return KW_STATEBLOCK_STATE; }
@@ -129,21 +132,22 @@ string {return KW_STRING; }
struct {return KW_STRUCT; }
switch {return KW_SWITCH; }
tbuffer {return KW_TBUFFER; }
-technique {return KW_TECHNIQUE; }
+(?i:technique) {return KW_TECHNIQUE; }
technique10 {return KW_TECHNIQUE10; }
+technique11 {return KW_TECHNIQUE11; }
texture {return KW_TEXTURE; }
-texture1D {return KW_TEXTURE1D; }
Texture1D {return KW_TEXTURE1D; }
+texture1D {return KW_TEXTURE1D; }
Texture1DArray {return KW_TEXTURE1DARRAY; }
-texture2D {return KW_TEXTURE2D; }
Texture2D {return KW_TEXTURE2D; }
+texture2D {return KW_TEXTURE2D; }
Texture2DArray {return KW_TEXTURE2DARRAY; }
Texture2DMS {return KW_TEXTURE2DMS; }
Texture2DMSArray {return KW_TEXTURE2DMSARRAY; }
-texture3D {return KW_TEXTURE3D; }
Texture3D {return KW_TEXTURE3D; }
-textureCUBE {return KW_TEXTURECUBE; }
+texture3D {return KW_TEXTURE3D; }
TextureCube {return KW_TEXTURECUBE; }
+textureCUBE {return KW_TEXTURECUBE; }
TextureCubeArray {return KW_TEXTURECUBEARRAY; }
true {return KW_TRUE; }
typedef {return KW_TYPEDEF; }
@@ -163,7 +167,6 @@ while {return KW_WHILE; }
\<\<= {return OP_LEFTSHIFTASSIGN; }
\>\> {return OP_RIGHTSHIFT; }
\>\>= {return OP_RIGHTSHIFTASSIGN; }
-\.\.\. {return OP_ELLIPSIS; }
\<= {return OP_LE; }
\>= {return OP_GE; }
!= {return OP_NE; }
@@ -175,13 +178,6 @@ while {return KW_WHILE; }
&= {return OP_ANDASSIGN; }
\|= {return OP_ORASSIGN; }
^= {return OP_XORASSIGN; }
-## {return OP_UNKNOWN1; }
-#@ {return OP_UNKNOWN2; }
-:: {return OP_UNKNOWN3; }
-\-\> {return OP_UNKNOWN4; }
-
-column_major {return KW_COLUMN_MAJOR; }
-row_major {return KW_ROW_MAJOR; }
{IDENTIFIER} {
struct hlsl_ctx *ctx = yyget_extra(yyscanner);
@@ -220,8 +216,6 @@ row_major {return KW_ROW_MAJOR; }
return C_INTEGER;
}
-{DOUBLESLASHCOMMENT} {}
-
{WS}+ {}
{NEWLINE} {
struct hlsl_ctx *ctx = yyget_extra(yyscanner);
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
index e58574f7560..0e72a539e3f 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
@@ -162,6 +162,12 @@ static void destroy_block(struct hlsl_block *block)
vkd3d_free(block);
}
+static void destroy_switch_cases(struct list *cases)
+{
+ hlsl_cleanup_ir_switch_cases(cases);
+ vkd3d_free(cases);
+}
+
static bool hlsl_types_are_componentwise_compatible(struct hlsl_ctx *ctx, struct hlsl_type *src,
struct hlsl_type *dst)
{
@@ -508,6 +514,28 @@ static void resolve_loop_continue(struct hlsl_ctx *ctx, struct hlsl_block *block
}
}
+static void check_loop_attributes(struct hlsl_ctx *ctx, const struct parse_attribute_list *attributes,
+ const struct vkd3d_shader_location *loc)
+{
+ bool has_unroll = false, has_loop = false, has_fastopt = false;
+ unsigned int i;
+
+ for (i = 0; i < attributes->count; ++i)
+ {
+ const char *name = attributes->attrs[i]->name;
+
+ has_loop |= !strcmp(name, "loop");
+ has_unroll |= !strcmp(name, "unroll");
+ has_fastopt |= !strcmp(name, "fastopt");
+ }
+
+ if (has_unroll && has_loop)
+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Unroll attribute can't be used with 'loop' attribute.");
+
+ if (has_unroll && has_fastopt)
+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Unroll attribute can't be used with 'fastopt' attribute.");
+}
+
static struct hlsl_block *create_loop(struct hlsl_ctx *ctx, enum loop_type type,
const struct parse_attribute_list *attributes, struct hlsl_block *init, struct hlsl_block *cond,
struct hlsl_block *iter, struct hlsl_block *body, const struct vkd3d_shader_location *loc)
@@ -518,6 +546,8 @@ static struct hlsl_block *create_loop(struct hlsl_ctx *ctx, enum loop_type type,
if (attribute_list_has_duplicates(attributes))
hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Found duplicate attribute.");
+ check_loop_attributes(ctx, attributes, loc);
+
/* Ignore unroll(0) attribute, and any invalid attribute. */
for (i = 0; i < attributes->count; ++i)
{
@@ -533,8 +563,11 @@ static struct hlsl_block *create_loop(struct hlsl_ctx *ctx, enum loop_type type,
hlsl_warning(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_IMPLEMENTED, "Loop unrolling is not implemented.");
}
}
- else if (!strcmp(attr->name, "loop")
- || !strcmp(attr->name, "fastopt")
+ else if (!strcmp(attr->name, "loop"))
+ {
+ /* TODO: this attribute will be used to disable unrolling, once it's implememented. */
+ }
+ else if (!strcmp(attr->name, "fastopt")
|| !strcmp(attr->name, "allow_uav_condition"))
{
hlsl_fixme(ctx, loc, "Unhandled attribute '%s'.", attr->name);
@@ -1180,6 +1213,7 @@ static unsigned int evaluate_static_expression_as_uint(struct hlsl_ctx *ctx, str
case HLSL_IR_RESOURCE_LOAD:
case HLSL_IR_RESOURCE_STORE:
case HLSL_IR_STORE:
+ case HLSL_IR_SWITCH:
hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
"Expected literal expression.");
}
@@ -4633,12 +4667,64 @@ static void validate_texture_format_type(struct hlsl_ctx *ctx, struct hlsl_type
}
}
-static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
+static bool check_continue(struct hlsl_ctx *ctx, const struct hlsl_scope *scope, const struct vkd3d_shader_location *loc)
{
+ if (scope->_switch)
+ {
+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
+ "The 'continue' statement is not allowed in 'switch' statements.");
+ return false;
+ }
+
if (scope->loop)
- return scope;
+ return true;
+
+ if (scope->upper)
+ return check_continue(ctx, scope->upper, loc);
+
+ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "The 'continue' statement is only allowed in loops.");
+ return false;
+}
+
+static bool is_break_allowed(const struct hlsl_scope *scope)
+{
+ if (scope->loop || scope->_switch)
+ return true;
+
+ return scope->upper ? is_break_allowed(scope->upper) : false;
+}
+
+static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hlsl_ir_switch_case *check, struct list *cases)
+{
+ struct hlsl_ir_switch_case *c;
+ bool found_duplicate = false;
- return scope->upper ? get_loop_scope(scope->upper) : NULL;
+ LIST_FOR_EACH_ENTRY(c, cases, struct hlsl_ir_switch_case, entry)
+ {
+ if (check->is_default)
+ {
+ if ((found_duplicate = c->is_default))
+ {
+ hlsl_error(ctx, &check->loc, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_SWITCH_CASE,
+ "Found multiple 'default' statements.");
+ hlsl_note(ctx, &c->loc, VKD3D_SHADER_LOG_ERROR, "The 'default' statement was previously found here.");
+ }
+ }
+ else
+ {
+ if (c->is_default) continue;
+ if ((found_duplicate = (c->value == check->value)))
+ {
+ hlsl_error(ctx, &check->loc, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_SWITCH_CASE,
+ "Found duplicate 'case' statement.");
+ hlsl_note(ctx, &c->loc, VKD3D_SHADER_LOG_ERROR, "The same 'case %d' statement was previously found here.",
+ c->value);
+ }
+ }
+
+ if (found_duplicate)
+ break;
+ }
}
}
@@ -4679,17 +4765,20 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
enum hlsl_sampler_dim sampler_dim;
struct hlsl_attribute *attr;
struct parse_attribute_list attr_list;
+ struct hlsl_ir_switch_case *switch_case;
}
%token KW_BLENDSTATE
%token KW_BREAK
%token KW_BUFFER
+%token KW_CASE
%token KW_CBUFFER
%token KW_CENTROID
%token KW_COLUMN_MAJOR
%token KW_COMPILE
%token KW_CONST
%token KW_CONTINUE
+%token KW_DEFAULT
%token KW_DEPTHSTENCILSTATE
%token KW_DEPTHSTENCILVIEW
%token KW_DISCARD
@@ -4743,6 +4832,7 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
%token KW_TBUFFER
%token KW_TECHNIQUE
%token KW_TECHNIQUE10
+%token KW_TECHNIQUE11
%token KW_TEXTURE
%token KW_TEXTURE1D
%token KW_TEXTURE1DARRAY
@@ -4771,7 +4861,6 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
%token OP_LEFTSHIFTASSIGN
%token OP_RIGHTSHIFT
%token OP_RIGHTSHIFTASSIGN
-%token OP_ELLIPSIS
%token OP_LE
%token OP_GE
%token OP_NE
@@ -4783,10 +4872,6 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
%token OP_ANDASSIGN
%token OP_ORASSIGN
%token OP_XORASSIGN
-%token OP_UNKNOWN1
-%token OP_UNKNOWN2
-%token OP_UNKNOWN3
-%token OP_UNKNOWN4
%token <floatval> C_FLOAT
@@ -4796,6 +4881,7 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
%type <list> type_specs
%type <list> variables_def
%type <list> variables_def_typed
+%type <list> switch_cases
%token <name> VAR_IDENTIFIER
%token <name> NEW_IDENTIFIER
@@ -4838,6 +4924,7 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
%type <block> statement
%type <block> statement_list
%type <block> struct_declaration_without_vars
+%type <block> switch_statement
%type <block> unary_expr
%type <boolval> boolean
@@ -4863,6 +4950,7 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
%type <name> any_identifier
%type <name> var_identifier
+%type <name> technique_name
%type <parameter> parameter
@@ -4876,6 +4964,8 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope)
%type <semantic> semantic
+%type <switch_case> switch_case
+
%type <type> field_type
%type <type> named_struct_spec
%type <type> unnamed_struct_spec
@@ -4902,8 +4992,50 @@ hlsl_prog:
destroy_block($2);
}
| hlsl_prog preproc_directive
+ | hlsl_prog technique
| hlsl_prog ';'
+technique_name:
+ %empty
+ {
+ $$ = NULL;
+ }
+ | any_identifier
+
+pass_list:
+ %empty
+
+technique9:
+ KW_TECHNIQUE technique_name '{' pass_list '}'
+ {
+ hlsl_fixme(ctx, &@$, "Unsupported \'technique\' declaration.");
+ }
+
+technique10:
+ KW_TECHNIQUE10 technique_name '{' pass_list '}'
+ {
+ if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2)
+ hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
+ "The 'technique10' keyword is invalid for this profile.");
+
+ hlsl_fixme(ctx, &@$, "Unsupported \'technique10\' declaration.");
+ }
+
+technique11:
+ KW_TECHNIQUE11 technique_name '{' pass_list '}'
+ {
+ if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2)
+ hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
+ "The 'technique11' keyword is invalid for this profile.");
+
+ hlsl_fixme(ctx, &@$, "Unsupported \'technique11\' declaration.");
+ }
+
+technique:
+ technique9
+ | technique10
+ | technique11
+
buffer_declaration:
buffer_type any_identifier colon_attribute
{
@@ -5357,6 +5489,13 @@ loop_scope_start:
ctx->cur_scope->loop = true;
}
+switch_scope_start:
+ %empty
+ {
+ hlsl_push_scope(ctx);
+ ctx->cur_scope->_switch = true;
+ }
+
var_identifier:
VAR_IDENTIFIER
| NEW_IDENTIFIER
@@ -6185,18 +6324,17 @@ statement:
| jump_statement
| selection_statement
| loop_statement
+ | switch_statement
jump_statement:
KW_BREAK ';'
{
struct hlsl_ir_node *jump;
- /* TODO: allow 'break' in the 'switch' statements. */
-
- if (!get_loop_scope(ctx->cur_scope))
+ if (!is_break_allowed(ctx->cur_scope))
{
hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
- "The 'break' statement must be used inside of a loop.");
+ "The 'break' statement must be used inside of a loop or a switch.");
}
if (!($$ = make_empty_block(ctx)))
@@ -6208,13 +6346,8 @@ jump_statement:
| KW_CONTINUE ';'
{
struct hlsl_ir_node *jump;
- struct hlsl_scope *scope;
- if (!(scope = get_loop_scope(ctx->cur_scope)))
- {
- hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
- "The 'continue' statement must be used inside of a loop.");
- }
+ check_continue(ctx, ctx->cur_scope, &@1);
if (!($$ = make_empty_block(ctx)))
YYABORT;
@@ -6333,6 +6466,106 @@ loop_statement:
hlsl_pop_scope(ctx);
}
+switch_statement:
+ attribute_list_optional switch_scope_start KW_SWITCH '(' expr ')' '{' switch_cases '}'
+ {
+ struct hlsl_ir_node *selector = node_from_block($5);
+ struct hlsl_ir_node *s;
+
+ if (!(selector = add_implicit_conversion(ctx, $5, selector, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &@5)))
+ {
+ destroy_switch_cases($8);
+ destroy_block($5);
+ YYABORT;
+ }
+
+ s = hlsl_new_switch(ctx, selector, $8, &@3);
+
+ destroy_switch_cases($8);
+
+ if (!s)
+ {
+ destroy_block($5);
+ YYABORT;
+ }
+
+ $$ = $5;
+ hlsl_block_add_instr($$, s);
+
+ hlsl_pop_scope(ctx);
+ }
+
+switch_case:
+ KW_CASE expr ':' statement_list
+ {
+ struct hlsl_ir_switch_case *c;
+ unsigned int value;
+
+ value = evaluate_static_expression_as_uint(ctx, $2, &@2);
+
+ c = hlsl_new_switch_case(ctx, value, false, $4, &@2);
+
+ destroy_block($2);
+ destroy_block($4);
+
+ if (!c)
+ YYABORT;
+ $$ = c;
+ }
+ | KW_CASE expr ':'
+ {
+ struct hlsl_ir_switch_case *c;
+ unsigned int value;
+
+ value = evaluate_static_expression_as_uint(ctx, $2, &@2);
+
+ c = hlsl_new_switch_case(ctx, value, false, NULL, &@2);
+
+ destroy_block($2);
+
+ if (!c)
+ YYABORT;
+ $$ = c;
+ }
+ | KW_DEFAULT ':' statement_list
+ {
+ struct hlsl_ir_switch_case *c;
+
+ c = hlsl_new_switch_case(ctx, 0, true, $3, &@1);
+
+ destroy_block($3);
+
+ if (!c)
+ YYABORT;
+ $$ = c;
+ }
+ | KW_DEFAULT ':'
+ {
+ struct hlsl_ir_switch_case *c;
+
+ if (!(c = hlsl_new_switch_case(ctx, 0, true, NULL, &@1)))
+ YYABORT;
+ $$ = c;
+ }
+
+switch_cases:
+ switch_case
+ {
+ struct hlsl_ir_switch_case *c = LIST_ENTRY($1, struct hlsl_ir_switch_case, entry);
+ if (!($$ = make_empty_list(ctx)))
+ {
+ hlsl_free_ir_switch_case(c);
+ YYABORT;
+ }
+ list_add_head($$, &$1->entry);
+ }
+ | switch_cases switch_case
+ {
+ $$ = $1;
+ check_duplicated_switch_cases(ctx, $2, $$);
+ list_add_tail($$, &$2->entry);
+ }
+
expr_optional:
%empty
{
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
index 7d17ca8cec6..6eac5d490c3 100644
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
@@ -23,30 +23,21 @@
/* TODO: remove when no longer needed, only used for new_offset_instr_from_deref() */
static struct hlsl_ir_node *new_offset_from_path_index(struct hlsl_ctx *ctx, struct hlsl_block *block,
- struct hlsl_type *type, struct hlsl_ir_node *offset, struct hlsl_ir_node *idx,
- enum hlsl_regset regset, const struct vkd3d_shader_location *loc)
+ struct hlsl_type *type, struct hlsl_ir_node *base_offset, struct hlsl_ir_node *idx,
+ enum hlsl_regset regset, unsigned int *offset_component, const struct vkd3d_shader_location *loc)
{
struct hlsl_ir_node *idx_offset = NULL;
struct hlsl_ir_node *c;
- hlsl_block_init(block);
-
switch (type->class)
{
case HLSL_CLASS_VECTOR:
- idx_offset = idx;
+ *offset_component += hlsl_ir_constant(idx)->value.u[0].u;
break;
case HLSL_CLASS_MATRIX:
{
- if (!(c = hlsl_new_uint_constant(ctx, 4, loc)))
- return NULL;
- hlsl_block_add_instr(block, c);
-
- if (!(idx_offset = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, c, idx)))
- return NULL;
- hlsl_block_add_instr(block, idx_offset);
-
+ idx_offset = idx;
break;
}
@@ -54,6 +45,12 @@ static struct hlsl_ir_node *new_offset_from_path_index(struct hlsl_ctx *ctx, str
{
unsigned int size = hlsl_type_get_array_element_reg_size(type->e.array.type, regset);
+ if (regset == HLSL_REGSET_NUMERIC)
+ {
+ assert(size % 4 == 0);
+ size /= 4;
+ }
+
if (!(c = hlsl_new_uint_constant(ctx, size, loc)))
return NULL;
hlsl_block_add_instr(block, c);
@@ -69,8 +66,16 @@ static struct hlsl_ir_node *new_offset_from_path_index(struct hlsl_ctx *ctx, str
{
unsigned int field_idx = hlsl_ir_constant(idx)->value.u[0].u;
struct hlsl_struct_field *field = &type->e.record.fields[field_idx];
+ unsigned int field_offset = field->reg_offset[regset];
+
+ if (regset == HLSL_REGSET_NUMERIC)
+ {
+ assert(*offset_component == 0);
+ *offset_component = field_offset % 4;
+ field_offset /= 4;
+ }
- if (!(c = hlsl_new_uint_constant(ctx, field->reg_offset[regset], loc)))
+ if (!(c = hlsl_new_uint_constant(ctx, field_offset, loc)))
return NULL;
hlsl_block_add_instr(block, c);
@@ -83,27 +88,33 @@ static struct hlsl_ir_node *new_offset_from_path_index(struct hlsl_ctx *ctx, str
vkd3d_unreachable();
}
- if (offset)
+ if (idx_offset)
{
- if (!(idx_offset = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, offset, idx_offset)))
+ if (!(base_offset = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, base_offset, idx_offset)))
return NULL;
- hlsl_block_add_instr(block, idx_offset);
+ hlsl_block_add_instr(block, base_offset);
}
- return idx_offset;
+ return base_offset;
}
/* TODO: remove when no longer needed, only used for replace_deref_path_with_offset() */
static struct hlsl_ir_node *new_offset_instr_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block,
- const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc)
+ const struct hlsl_deref *deref, unsigned int *offset_component, const struct vkd3d_shader_location *loc)
{
enum hlsl_regset regset = hlsl_deref_get_regset(ctx, deref);
- struct hlsl_ir_node *offset = NULL;
+ struct hlsl_ir_node *offset;
struct hlsl_type *type;
unsigned int i;
+ *offset_component = 0;
+
hlsl_block_init(block);
+ if (!(offset = hlsl_new_uint_constant(ctx, 0, loc)))
+ return NULL;
+ hlsl_block_add_instr(block, offset);
+
assert(deref->var);
type = deref->var->data_type;
@@ -111,9 +122,14 @@ static struct hlsl_ir_node *new_offset_instr_from_deref(struct hlsl_ctx *ctx, st
{
struct hlsl_block idx_block;
+ hlsl_block_init(&idx_block);
+
if (!(offset = new_offset_from_path_index(ctx, &idx_block, type, offset, deref->path[i].node,
- regset, loc)))
+ regset, offset_component, loc)))
+ {
+ hlsl_block_cleanup(&idx_block);
return NULL;
+ }
hlsl_block_add_block(block, &idx_block);
@@ -127,14 +143,13 @@ static struct hlsl_ir_node *new_offset_instr_from_deref(struct hlsl_ctx *ctx, st
static bool replace_deref_path_with_offset(struct hlsl_ctx *ctx, struct hlsl_deref *deref,
struct hlsl_ir_node *instr)
{
- struct hlsl_type *type;
+ unsigned int offset_component;
struct hlsl_ir_node *offset;
struct hlsl_block block;
+ struct hlsl_type *type;
assert(deref->var);
-
- /* register offsets shouldn't be used before this point is reached. */
- assert(!deref->offset.node);
+ assert(!hlsl_deref_is_lowered(deref));
type = hlsl_deref_get_type(ctx, deref);
@@ -148,16 +163,35 @@ static bool replace_deref_path_with_offset(struct hlsl_ctx *ctx, struct hlsl_der
deref->data_type = type;
- if (!(offset = new_offset_instr_from_deref(ctx, &block, deref, &instr->loc)))
+ if (!(offset = new_offset_instr_from_deref(ctx, &block, deref, &offset_component, &instr->loc)))
return false;
list_move_before(&instr->entry, &block.instrs);
hlsl_cleanup_deref(deref);
- hlsl_src_from_node(&deref->offset, offset);
+ hlsl_src_from_node(&deref->rel_offset, offset);
+ deref->const_offset = offset_component;
return true;
}
+static bool clean_constant_deref_offset_srcs(struct hlsl_ctx *ctx, struct hlsl_deref *deref,
+ struct hlsl_ir_node *instr)
+{
+ if (deref->rel_offset.node && deref->rel_offset.node->type == HLSL_IR_CONSTANT)
+ {
+ enum hlsl_regset regset = hlsl_deref_get_regset(ctx, deref);
+
+ if (regset == HLSL_REGSET_NUMERIC)
+ deref->const_offset += 4 * hlsl_ir_constant(deref->rel_offset.node)->value.u[0].u;
+ else
+ deref->const_offset += hlsl_ir_constant(deref->rel_offset.node)->value.u[0].u;
+ hlsl_src_remove(&deref->rel_offset);
+ return true;
+ }
+ return false;
+}
+
+
/* Split uniforms into two variables representing the constant and temp
* registers, and copy the former to the latter, so that writes to uniforms
* work. */
@@ -575,7 +609,19 @@ bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx,
progress |= hlsl_transform_ir(ctx, func, &iff->else_block, context);
}
else if (instr->type == HLSL_IR_LOOP)
+ {
progress |= hlsl_transform_ir(ctx, func, &hlsl_ir_loop(instr)->body, context);
+ }
+ else if (instr->type == HLSL_IR_SWITCH)
+ {
+ struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
+ struct hlsl_ir_switch_case *c;
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ progress |= hlsl_transform_ir(ctx, func, &c->body, context);
+ }
+ }
progress |= func(ctx, instr, context);
}
@@ -835,6 +881,30 @@ static bool lower_return(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fun
}
}
}
+ else if (instr->type == HLSL_IR_SWITCH)
+ {
+ struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
+ struct hlsl_ir_switch_case *c;
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ has_early_return |= lower_return(ctx, func, &c->body, true);
+ }
+
+ if (has_early_return)
+ {
+ if (in_loop)
+ {
+ /* For a 'switch' nested in a loop append a break after the 'switch'. */
+ insert_early_return_break(ctx, func, instr);
+ }
+ else
+ {
+ cf_instr = instr;
+ break;
+ }
+ }
+ }
}
if (return_instr)
@@ -1639,6 +1709,19 @@ static void copy_propagation_invalidate_from_block(struct hlsl_ctx *ctx, struct
break;
}
+ case HLSL_IR_SWITCH:
+ {
+ struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
+ struct hlsl_ir_switch_case *c;
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ copy_propagation_invalidate_from_block(ctx, state, &c->body);
+ }
+
+ break;
+ }
+
default:
break;
}
@@ -1687,6 +1770,28 @@ static bool copy_propagation_process_loop(struct hlsl_ctx *ctx, struct hlsl_ir_l
return progress;
}
+static bool copy_propagation_process_switch(struct hlsl_ctx *ctx, struct hlsl_ir_switch *s,
+ struct copy_propagation_state *state)
+{
+ struct copy_propagation_state inner_state;
+ struct hlsl_ir_switch_case *c;
+ bool progress = false;
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ copy_propagation_state_init(ctx, &inner_state, state);
+ progress |= copy_propagation_transform_block(ctx, &c->body, &inner_state);
+ copy_propagation_state_destroy(&inner_state);
+ }
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ copy_propagation_invalidate_from_block(ctx, state, &c->body);
+ }
+
+ return progress;
+}
+
static bool copy_propagation_transform_block(struct hlsl_ctx *ctx, struct hlsl_block *block,
struct copy_propagation_state *state)
{
@@ -1725,6 +1830,10 @@ static bool copy_propagation_transform_block(struct hlsl_ctx *ctx, struct hlsl_b
progress |= copy_propagation_process_loop(ctx, hlsl_ir_loop(instr), state);
break;
+ case HLSL_IR_SWITCH:
+ progress |= copy_propagation_process_switch(ctx, hlsl_ir_switch(instr), state);
+ break;
+
default:
break;
}
@@ -2094,6 +2203,118 @@ static bool remove_trivial_conditional_branches(struct hlsl_ctx *ctx, struct hls
return true;
}
+static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
+{
+ 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)
+ return false;
+ s = hlsl_ir_switch(instr);
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ bool terminal_break = false;
+
+ if (list_empty(&c->body.instrs))
+ {
+ terminal_break = !!list_next(&s->cases, &c->entry);
+ }
+ else
+ {
+ 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;
+ }
+ }
+
+ missing_terminal_break |= !terminal_break;
+
+ if (!terminal_break)
+ {
+ if (c->is_default)
+ {
+ hlsl_error(ctx, &c->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
+ "The 'default' case block is not terminated with 'break' or 'return'.");
+ }
+ else
+ {
+ hlsl_error(ctx, &c->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
+ "Switch case block '%u' is not terminated with 'break' or 'return'.", c->value);
+ }
+ }
+ }
+
+ if (missing_terminal_break)
+ return true;
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ if (c->is_default)
+ {
+ def = c;
+
+ /* Remove preceding empty cases. */
+ while (list_prev(&s->cases, &def->entry))
+ {
+ c = LIST_ENTRY(list_prev(&s->cases, &def->entry), struct hlsl_ir_switch_case, entry);
+ if (!list_empty(&c->body.instrs))
+ break;
+ hlsl_free_ir_switch_case(c);
+ }
+
+ if (list_empty(&def->body.instrs))
+ {
+ /* Remove following empty cases. */
+ while (list_next(&s->cases, &def->entry))
+ {
+ c = LIST_ENTRY(list_next(&s->cases, &def->entry), struct hlsl_ir_switch_case, entry);
+ if (!list_empty(&c->body.instrs))
+ break;
+ hlsl_free_ir_switch_case(c);
+ }
+
+ /* Merge with the next case. */
+ if (list_next(&s->cases, &def->entry))
+ {
+ c = LIST_ENTRY(list_next(&s->cases, &def->entry), struct hlsl_ir_switch_case, entry);
+ c->is_default = true;
+ hlsl_free_ir_switch_case(def);
+ def = c;
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (def)
+ {
+ list_remove(&def->entry);
+ }
+ else
+ {
+ struct hlsl_ir_node *jump;
+
+ if (!(def = hlsl_new_switch_case(ctx, 0, true, NULL, &s->node.loc)))
+ return true;
+ if (!(jump = hlsl_new_jump(ctx, HLSL_IR_JUMP_BREAK, NULL, &s->node.loc)))
+ {
+ hlsl_free_ir_switch_case(def);
+ return true;
+ }
+ hlsl_block_add_instr(&def->body, jump);
+ }
+ list_add_tail(&s->cases, &def->entry);
+
+ return true;
+}
+
static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
{
struct hlsl_ir_node *idx;
@@ -2929,6 +3150,7 @@ static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
case HLSL_IR_JUMP:
case HLSL_IR_LOOP:
case HLSL_IR_RESOURCE_STORE:
+ case HLSL_IR_SWITCH:
break;
}
@@ -2956,6 +3178,16 @@ static unsigned int index_instructions(struct hlsl_block *block, unsigned int in
index = index_instructions(&hlsl_ir_loop(instr)->body, index);
hlsl_ir_loop(instr)->next_index = index;
}
+ else if (instr->type == HLSL_IR_SWITCH)
+ {
+ struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
+ struct hlsl_ir_switch_case *c;
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ index = index_instructions(&c->body, index);
+ }
+ }
}
return index;
@@ -2978,6 +3210,19 @@ static void dump_function(struct rb_entry *entry, void *context)
rb_for_each_entry(&func->overloads, dump_function_decl, ctx);
}
+static bool mark_indexable_vars(struct hlsl_ctx *ctx, struct hlsl_deref *deref,
+ struct hlsl_ir_node *instr)
+{
+ if (!deref->rel_offset.node)
+ return false;
+
+ assert(deref->var);
+ assert(deref->rel_offset.node->type != HLSL_IR_CONSTANT);
+ deref->var->indexable = true;
+
+ return true;
+}
+
static char get_regset_name(enum hlsl_regset regset)
{
switch (regset)
@@ -3066,8 +3311,8 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop
if (!var->first_write)
var->first_write = loop_first ? min(instr->index, loop_first) : instr->index;
store->rhs.node->last_read = last_read;
- if (store->lhs.offset.node)
- store->lhs.offset.node->last_read = last_read;
+ if (store->lhs.rel_offset.node)
+ store->lhs.rel_offset.node->last_read = last_read;
break;
}
case HLSL_IR_EXPR:
@@ -3094,8 +3339,8 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop
var = load->src.var;
var->last_read = max(var->last_read, last_read);
- if (load->src.offset.node)
- load->src.offset.node->last_read = last_read;
+ if (load->src.rel_offset.node)
+ load->src.rel_offset.node->last_read = last_read;
break;
}
case HLSL_IR_LOOP:
@@ -3112,14 +3357,14 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop
var = load->resource.var;
var->last_read = max(var->last_read, last_read);
- if (load->resource.offset.node)
- load->resource.offset.node->last_read = last_read;
+ if (load->resource.rel_offset.node)
+ load->resource.rel_offset.node->last_read = last_read;
if ((var = load->sampler.var))
{
var->last_read = max(var->last_read, last_read);
- if (load->sampler.offset.node)
- load->sampler.offset.node->last_read = last_read;
+ if (load->sampler.rel_offset.node)
+ load->sampler.rel_offset.node->last_read = last_read;
}
if (load->coords.node)
@@ -3144,8 +3389,8 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop
var = store->resource.var;
var->last_read = max(var->last_read, last_read);
- if (store->resource.offset.node)
- store->resource.offset.node->last_read = last_read;
+ if (store->resource.rel_offset.node)
+ store->resource.rel_offset.node->last_read = last_read;
store->coords.node->last_read = last_read;
store->value.node->last_read = last_read;
break;
@@ -3173,6 +3418,16 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop
jump->condition.node->last_read = last_read;
break;
}
+ case HLSL_IR_SWITCH:
+ {
+ struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
+ struct hlsl_ir_switch_case *c;
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ compute_liveness_recurse(&c->body, loop_first, loop_last);
+ s->selector.node->last_read = last_read;
+ break;
+ }
case HLSL_IR_CONSTANT:
break;
}
@@ -3206,18 +3461,20 @@ static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl
struct register_allocator
{
- size_t count, capacity;
-
- /* Highest register index that has been allocated.
- * Used to declare sm4 temp count. */
- uint32_t max_reg;
-
struct allocation
{
uint32_t reg;
unsigned int writemask;
unsigned int first_write, last_read;
} *allocations;
+ size_t count, capacity;
+
+ /* Indexable temps are allocated separately and always keep their index regardless of their
+ * lifetime. */
+ size_t indexable_count;
+
+ /* Total number of registers allocated so far. Used to declare sm4 temp count. */
+ uint32_t reg_count;
};
static unsigned int get_available_writemask(const struct register_allocator *allocator,
@@ -3260,7 +3517,7 @@ static void record_allocation(struct hlsl_ctx *ctx, struct register_allocator *a
allocation->first_write = first_write;
allocation->last_read = last_read;
- allocator->max_reg = max(allocator->max_reg, reg_idx);
+ allocator->reg_count = max(allocator->reg_count, reg_idx + 1);
}
/* reg_size is the number of register components to be reserved, while component_count is the number
@@ -3464,11 +3721,23 @@ static void allocate_variable_temp_register(struct hlsl_ctx *ctx,
if (!var->regs[HLSL_REGSET_NUMERIC].allocated && var->last_read)
{
- var->regs[HLSL_REGSET_NUMERIC] = allocate_numeric_registers_for_type(ctx, allocator,
- var->first_write, var->last_read, var->data_type);
+ if (var->indexable)
+ {
+ var->regs[HLSL_REGSET_NUMERIC].id = allocator->indexable_count++;
+ var->regs[HLSL_REGSET_NUMERIC].allocation_size = 1;
+ var->regs[HLSL_REGSET_NUMERIC].writemask = 0;
+ var->regs[HLSL_REGSET_NUMERIC].allocated = true;
- TRACE("Allocated %s to %s (liveness %u-%u).\n", var->name, debug_register('r',
- var->regs[HLSL_REGSET_NUMERIC], var->data_type), var->first_write, var->last_read);
+ TRACE("Allocated %s to x%u[].\n", var->name, var->regs[HLSL_REGSET_NUMERIC].id);
+ }
+ else
+ {
+ var->regs[HLSL_REGSET_NUMERIC] = allocate_numeric_registers_for_type(ctx, allocator,
+ var->first_write, var->last_read, var->data_type);
+
+ TRACE("Allocated %s to %s (liveness %u-%u).\n", var->name, debug_register('r',
+ var->regs[HLSL_REGSET_NUMERIC], var->data_type), var->first_write, var->last_read);
+ }
}
}
@@ -3524,6 +3793,18 @@ static void allocate_temp_registers_recurse(struct hlsl_ctx *ctx,
break;
}
+ case HLSL_IR_SWITCH:
+ {
+ struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
+ struct hlsl_ir_switch_case *c;
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ allocate_temp_registers_recurse(ctx, &c->body, allocator);
+ }
+ break;
+ }
+
default:
break;
}
@@ -3633,6 +3914,18 @@ static void allocate_const_registers_recurse(struct hlsl_ctx *ctx,
break;
}
+ case HLSL_IR_SWITCH:
+ {
+ struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
+ struct hlsl_ir_switch_case *c;
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ allocate_const_registers_recurse(ctx, &c->body, allocator);
+ }
+ break;
+ }
+
default:
break;
}
@@ -3691,7 +3984,7 @@ static void allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functio
}
allocate_temp_registers_recurse(ctx, &entry_func->body, &allocator);
- ctx->temp_count = allocator.max_reg + 1;
+ ctx->temp_count = allocator.reg_count;
vkd3d_free(allocator.allocations);
}
@@ -4206,30 +4499,25 @@ bool hlsl_regset_index_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref
bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, unsigned int *offset)
{
- struct hlsl_ir_node *offset_node = deref->offset.node;
- enum hlsl_regset regset;
+ enum hlsl_regset regset = hlsl_deref_get_regset(ctx, deref);
+ struct hlsl_ir_node *offset_node = deref->rel_offset.node;
unsigned int size;
- if (!offset_node)
- {
- *offset = 0;
- return true;
- }
-
- /* We should always have generated a cast to UINT. */
- assert(offset_node->data_type->class == HLSL_CLASS_SCALAR
- && offset_node->data_type->base_type == HLSL_TYPE_UINT);
+ *offset = deref->const_offset;
- if (offset_node->type != HLSL_IR_CONSTANT)
+ if (offset_node)
+ {
+ /* We should always have generated a cast to UINT. */
+ assert(offset_node->data_type->class == HLSL_CLASS_SCALAR
+ && offset_node->data_type->base_type == HLSL_TYPE_UINT);
+ assert(offset_node->type != HLSL_IR_CONSTANT);
return false;
-
- *offset = hlsl_ir_constant(offset_node)->value.u[0].u;
- regset = hlsl_deref_get_regset(ctx, deref);
+ }
size = deref->var->data_type->reg_size[regset];
if (*offset >= size)
{
- hlsl_error(ctx, &deref->offset.node->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS,
+ hlsl_error(ctx, &offset_node->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS,
"Dereference is out of bounds. %u/%u", *offset, size);
return false;
}
@@ -4244,8 +4532,8 @@ unsigned int hlsl_offset_from_deref_safe(struct hlsl_ctx *ctx, const struct hlsl
if (hlsl_offset_from_deref(ctx, deref, &offset))
return offset;
- hlsl_fixme(ctx, &deref->offset.node->loc, "Dereference with non-constant offset of type %s.",
- hlsl_node_type_to_string(deref->offset.node->type));
+ hlsl_fixme(ctx, &deref->rel_offset.node->loc, "Dereference with non-constant offset of type %s.",
+ hlsl_node_type_to_string(deref->rel_offset.node->type));
return 0;
}
@@ -4335,6 +4623,62 @@ static bool type_has_object_components(struct hlsl_type *type)
return false;
}
+static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *body)
+{
+ struct hlsl_ir_node *instr, *next;
+ struct hlsl_block block;
+ struct list *start;
+
+ LIST_FOR_EACH_ENTRY_SAFE(instr, next, &body->instrs, struct hlsl_ir_node, entry)
+ {
+ if (instr->type == HLSL_IR_IF)
+ {
+ struct hlsl_ir_if *iff = hlsl_ir_if(instr);
+
+ remove_unreachable_code(ctx, &iff->then_block);
+ remove_unreachable_code(ctx, &iff->else_block);
+ }
+ else if (instr->type == HLSL_IR_LOOP)
+ {
+ struct hlsl_ir_loop *loop = hlsl_ir_loop(instr);
+
+ remove_unreachable_code(ctx, &loop->body);
+ }
+ else if (instr->type == HLSL_IR_SWITCH)
+ {
+ struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
+ struct hlsl_ir_switch_case *c;
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ remove_unreachable_code(ctx, &c->body);
+ }
+ }
+ }
+
+ /* Remove instructions past unconditional jumps. */
+ LIST_FOR_EACH_ENTRY(instr, &body->instrs, struct hlsl_ir_node, entry)
+ {
+ struct hlsl_ir_jump *jump;
+
+ if (instr->type != HLSL_IR_JUMP)
+ continue;
+
+ jump = hlsl_ir_jump(instr);
+ if (jump->type != HLSL_IR_JUMP_BREAK && jump->type != HLSL_IR_JUMP_CONTINUE)
+ continue;
+
+ if (!(start = list_next(&body->instrs, &instr->entry)))
+ break;
+
+ hlsl_block_init(&block);
+ list_move_slice_tail(&block.instrs, start, list_tail(&body->instrs));
+ hlsl_block_cleanup(&block);
+
+ break;
+ }
+}
+
int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,
enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out)
{
@@ -4452,6 +4796,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
progress |= hlsl_transform_ir(ctx, remove_trivial_conditional_branches, body, NULL);
}
while (progress);
+ remove_unreachable_code(ctx, body);
+ hlsl_transform_ir(ctx, normalize_switch_cases, body, NULL);
lower_ir(ctx, lower_nonconstant_vector_derefs, body);
lower_ir(ctx, lower_casts_to_bool, body);
@@ -4482,6 +4828,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
/* TODO: move forward, remove when no longer needed */
transform_derefs(ctx, replace_deref_path_with_offset, body);
while (hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL));
+ transform_derefs(ctx, clean_constant_deref_offset_srcs, body);
do
compute_liveness(ctx, entry_func);
@@ -4492,6 +4839,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
if (TRACE_ON())
rb_for_each_entry(&ctx->functions, dump_function, ctx);
+ transform_derefs(ctx, mark_indexable_vars, body);
+
calculate_resource_register_counts(ctx);
allocate_register_reservations(ctx);
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
index 511b0e8faf9..758b594b330 100644
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
@@ -550,6 +550,8 @@ struct io_normaliser
uint8_t input_range_map[MAX_REG_OUTPUT][VKD3D_VEC4_SIZE];
uint8_t output_range_map[MAX_REG_OUTPUT][VKD3D_VEC4_SIZE];
uint8_t pc_range_map[MAX_REG_OUTPUT][VKD3D_VEC4_SIZE];
+
+ bool use_vocp;
};
static bool io_normaliser_is_in_fork_or_join_phase(const struct io_normaliser *normaliser)
@@ -581,6 +583,12 @@ static unsigned int shader_signature_find_element_for_reg(const struct shader_si
vkd3d_unreachable();
}
+struct signature_element *vsir_signature_find_element_for_reg(const struct shader_signature *signature,
+ unsigned int reg_idx, unsigned int write_mask)
+{
+ return &signature->elements[shader_signature_find_element_for_reg(signature, reg_idx, write_mask)];
+}
+
static unsigned int range_map_get_register_count(uint8_t range_map[][VKD3D_VEC4_SIZE],
unsigned int register_idx, unsigned int write_mask)
{
@@ -1025,6 +1033,10 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi
if (normaliser->shader_type == VKD3D_SHADER_TYPE_HULL)
{
reg = &ins->declaration.dst.reg;
+
+ if (reg->type == VKD3DSPR_OUTCONTROLPOINT)
+ normaliser->use_vocp = true;
+
/* We don't need to keep OUTCONTROLPOINT or PATCHCONST input declarations since their
* equivalents were declared earlier, but INCONTROLPOINT may be the first occurrence. */
if (reg->type == VKD3DSPR_OUTCONTROLPOINT || reg->type == VKD3DSPR_PATCHCONST)
@@ -1065,24 +1077,22 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi
}
}
-static enum vkd3d_result instruction_array_normalise_io_registers(struct vkd3d_shader_instruction_array *instructions,
- enum vkd3d_shader_type shader_type, struct shader_signature *input_signature,
- struct shader_signature *output_signature, struct shader_signature *patch_constant_signature)
+static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parser *parser)
{
- struct io_normaliser normaliser = {*instructions};
+ struct io_normaliser normaliser = {parser->instructions};
struct vkd3d_shader_instruction *ins;
bool has_control_point_phase;
unsigned int i, j;
normaliser.phase = VKD3DSIH_INVALID;
- normaliser.shader_type = shader_type;
- normaliser.input_signature = input_signature;
- normaliser.output_signature = output_signature;
- normaliser.patch_constant_signature = patch_constant_signature;
+ normaliser.shader_type = parser->shader_version.type;
+ normaliser.input_signature = &parser->shader_desc.input_signature;
+ normaliser.output_signature = &parser->shader_desc.output_signature;
+ normaliser.patch_constant_signature = &parser->shader_desc.patch_constant_signature;
- for (i = 0, has_control_point_phase = false; i < instructions->count; ++i)
+ for (i = 0, has_control_point_phase = false; i < parser->instructions.count; ++i)
{
- ins = &instructions->elements[i];
+ ins = &parser->instructions.elements[i];
switch (ins->handler_idx)
{
@@ -1121,11 +1131,11 @@ static enum vkd3d_result instruction_array_normalise_io_registers(struct vkd3d_s
}
}
- if (!shader_signature_merge(input_signature, normaliser.input_range_map, false)
- || !shader_signature_merge(output_signature, normaliser.output_range_map, false)
- || !shader_signature_merge(patch_constant_signature, normaliser.pc_range_map, true))
+ if (!shader_signature_merge(&parser->shader_desc.input_signature, normaliser.input_range_map, false)
+ || !shader_signature_merge(&parser->shader_desc.output_signature, normaliser.output_range_map, false)
+ || !shader_signature_merge(&parser->shader_desc.patch_constant_signature, normaliser.pc_range_map, true))
{
- *instructions = normaliser.instructions;
+ parser->instructions = normaliser.instructions;
return VKD3D_ERROR_OUT_OF_MEMORY;
}
@@ -1133,7 +1143,8 @@ static enum vkd3d_result instruction_array_normalise_io_registers(struct vkd3d_s
for (i = 0; i < normaliser.instructions.count; ++i)
shader_instruction_normalise_io_params(&normaliser.instructions.elements[i], &normaliser);
- *instructions = normaliser.instructions;
+ parser->instructions = normaliser.instructions;
+ parser->shader_desc.use_vocp = normaliser.use_vocp;
return VKD3D_OK;
}
@@ -1438,9 +1449,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
&parser->shader_desc.input_signature);
}
if (result >= 0)
- result = instruction_array_normalise_io_registers(instructions, parser->shader_version.type,
- &parser->shader_desc.input_signature, &parser->shader_desc.output_signature,
- &parser->shader_desc.patch_constant_signature);
+ result = shader_normalise_io_registers(parser);
if (result >= 0)
result = instruction_array_normalise_flat_constants(parser);
@@ -1467,6 +1476,7 @@ struct validation_context
{
struct vkd3d_shader_parser *parser;
size_t instruction_idx;
+ bool dcl_temps_found;
};
static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *ctx,
@@ -1492,6 +1502,41 @@ static void vsir_validate_register(struct validation_context *ctx,
if (reg->type >= VKD3DSPR_COUNT)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, "Invalid register type %#x.",
reg->type);
+
+ if (reg->precision >= VKD3D_SHADER_REGISTER_PRECISION_COUNT)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, "Invalid register precision %#x.",
+ reg->precision);
+
+ if (reg->data_type >= VKD3D_DATA_COUNT)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid register data type %#x.",
+ reg->data_type);
+
+ if (reg->dimension >= VSIR_DIMENSION_COUNT)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid register dimension %#x.",
+ reg->dimension);
+
+ if (reg->idx_count > ARRAY_SIZE(reg->idx))
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid register index count %u.",
+ reg->idx_count);
+
+ switch (reg->type)
+ {
+ case VKD3DSPR_TEMP:
+ if (reg->idx_count != 1)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a TEMP register.",
+ reg->idx_count);
+
+ if (reg->idx_count >= 1 && reg->idx[0].rel_addr)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Non-NULL relative address for a TEMP register.");
+
+ if (reg->idx_count >= 1 && reg->idx[0].offset >= ctx->parser->shader_desc.temp_count)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "TEMP register index %u exceeds the declared count %u.",
+ reg->idx[0].offset, ctx->parser->shader_desc.temp_count);
+ break;
+
+ default:
+ break;
+ }
}
static void vsir_validate_dst_param(struct validation_context *ctx,
@@ -1538,6 +1583,24 @@ static void vsir_validate_src_param(struct validation_context *ctx,
src->modifiers);
}
+static void vsir_validate_dst_count(struct validation_context *ctx,
+ const struct vkd3d_shader_instruction *instruction, unsigned int count)
+{
+ if (instruction->dst_count != count)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT,
+ "Invalid destination count %u for an instruction of type %#x, expected %u.",
+ instruction->dst_count, instruction->handler_idx, count);
+}
+
+static void vsir_validate_src_count(struct validation_context *ctx,
+ const struct vkd3d_shader_instruction *instruction, unsigned int count)
+{
+ if (instruction->src_count != count)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT,
+ "Invalid source count %u for an instruction of type %#x, expected %u.",
+ instruction->src_count, instruction->handler_idx, count);
+}
+
static void vsir_validate_instruction(struct validation_context *ctx)
{
const struct vkd3d_shader_instruction *instruction = &ctx->parser->instructions.elements[ctx->instruction_idx];
@@ -1556,6 +1619,25 @@ static void vsir_validate_instruction(struct validation_context *ctx)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Invalid instruction handler %#x.",
instruction->handler_idx);
}
+
+ switch (instruction->handler_idx)
+ {
+ case VKD3DSIH_DCL_TEMPS:
+ vsir_validate_dst_count(ctx, instruction, 0);
+ vsir_validate_src_count(ctx, instruction, 0);
+ /* TODO Check that each phase in a hull shader has at most
+ * one occurrence. */
+ if (ctx->dcl_temps_found && ctx->parser->shader_version.type != VKD3D_SHADER_TYPE_HULL)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS, "Duplicate DCL_TEMPS instruction.");
+ ctx->dcl_temps_found = true;
+ if (instruction->declaration.count != ctx->parser->shader_desc.temp_count)
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS, "Invalid DCL_TEMPS count %u, expected %u.",
+ instruction->declaration.count, ctx->parser->shader_desc.temp_count);
+ break;
+
+ default:
+ break;
+ }
}
void vsir_validate(struct vkd3d_shader_parser *parser)
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
index 2dab97ccbb3..a25edb64491 100644
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
@@ -173,7 +173,13 @@ enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d
{
switch (sysval)
{
+ case VKD3D_SHADER_SV_COVERAGE:
+ case VKD3D_SHADER_SV_DEPTH:
+ case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL:
+ case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL:
case VKD3D_SHADER_SV_NONE:
+ case VKD3D_SHADER_SV_STENCIL_REF:
+ case VKD3D_SHADER_SV_TARGET:
return VKD3D_SIV_NONE;
case VKD3D_SHADER_SV_POSITION:
return VKD3D_SIV_POSITION;
@@ -181,6 +187,16 @@ enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d
return VKD3D_SIV_CLIP_DISTANCE;
case VKD3D_SHADER_SV_CULL_DISTANCE:
return VKD3D_SIV_CULL_DISTANCE;
+ case VKD3D_SHADER_SV_INSTANCE_ID:
+ return VKD3D_SIV_INSTANCE_ID;
+ case VKD3D_SHADER_SV_IS_FRONT_FACE:
+ return VKD3D_SIV_IS_FRONT_FACE;
+ case VKD3D_SHADER_SV_PRIMITIVE_ID:
+ return VKD3D_SIV_PRIMITIVE_ID;
+ case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX:
+ return VKD3D_SIV_RENDER_TARGET_ARRAY_INDEX;
+ case VKD3D_SHADER_SV_SAMPLE_INDEX:
+ return VKD3D_SIV_SAMPLE_INDEX;
case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE:
return VKD3D_SIV_QUAD_U0_TESS_FACTOR + index;
case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT:
@@ -193,6 +209,10 @@ enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d
return VKD3D_SIV_LINE_DETAIL_TESS_FACTOR;
case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN:
return VKD3D_SIV_LINE_DENSITY_TESS_FACTOR;
+ case VKD3D_SHADER_SV_VERTEX_ID:
+ return VKD3D_SIV_VERTEX_ID;
+ case VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX:
+ return VKD3D_SIV_VIEWPORT_ARRAY_INDEX;
default:
FIXME("Unhandled sysval %#x, index %u.\n", sysval, index);
return VKD3D_SIV_NONE;
@@ -1411,13 +1431,6 @@ static uint32_t vkd3d_spirv_build_op_udiv(struct vkd3d_spirv_builder *builder,
SpvOpUDiv, result_type, operand0, operand1);
}
-static uint32_t vkd3d_spirv_build_op_umod(struct vkd3d_spirv_builder *builder,
- uint32_t result_type, uint32_t operand0, uint32_t operand1)
-{
- return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream,
- SpvOpUMod, result_type, operand0, operand1);
-}
-
static uint32_t vkd3d_spirv_build_op_isub(struct vkd3d_spirv_builder *builder,
uint32_t result_type, uint32_t operand0, uint32_t operand1)
{
@@ -3523,6 +3536,14 @@ 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)
+{
+ 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;
+}
+
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)
@@ -3725,6 +3746,26 @@ static void spirv_compiler_set_ssa_register_id(const struct spirv_compiler *comp
compiler->ssa_register_ids[i] = val_id;
}
+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)
+{
+ struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+ unsigned int component_idx;
+ uint32_t type_id, val_id;
+
+ val_id = spirv_compiler_get_ssa_register_id(compiler, reg);
+ assert(val_id);
+ assert(vkd3d_swizzle_is_scalar(swizzle));
+
+ if (reg->dimension == VSIR_DIMENSION_SCALAR)
+ return val_id;
+
+ type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
+ component_idx = vkd3d_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)
{
@@ -3746,7 +3787,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler,
component_type = vkd3d_component_type_from_data_type(reg->data_type);
if (reg->type == VKD3DSPR_SSA)
- return spirv_compiler_get_ssa_register_id(compiler, reg);
+ return spirv_compiler_emit_load_ssa_reg(compiler, reg, component_type, swizzle);
if (!spirv_compiler_get_register_info(compiler, reg, &reg_info))
{
@@ -3824,7 +3865,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)
+ else if (reg->data_type == VKD3D_DATA_INT || reg->data_type == VKD3D_DATA_UINT)
return vkd3d_spirv_build_op_snegate(builder, type_id, val_id);
FIXME("Unhandled data type %#x.\n", reg->data_type);
@@ -4592,8 +4633,7 @@ static unsigned int shader_register_get_io_indices(const struct vkd3d_shader_reg
}
static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
- const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_input_sysval_semantic sysval,
- enum vkd3d_shader_interpolation_mode interpolation_mode)
+ const struct vkd3d_shader_dst_param *dst)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_register *reg = &dst->reg;
@@ -4601,18 +4641,18 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
const struct signature_element *signature_element;
const struct shader_signature *shader_signature;
enum vkd3d_shader_component_type component_type;
- uint32_t type_id, ptr_type_id, float_type_id;
+ enum vkd3d_shader_input_sysval_semantic sysval;
const struct vkd3d_spirv_builtin *builtin;
unsigned int 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;
struct vkd3d_symbol reg_symbol;
SpvStorageClass storage_class;
struct rb_entry *entry = NULL;
bool use_private_var = false;
unsigned int array_sizes[2];
unsigned int element_idx;
- uint32_t i, index;
assert(!reg->idx_count || !reg->idx[0].rel_addr);
assert(reg->idx_count < 2 || !reg->idx[1].rel_addr);
@@ -4622,10 +4662,12 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
element_idx = shader_register_get_io_indices(reg, array_sizes);
signature_element = &shader_signature->elements[element_idx];
-
- if ((compiler->shader_type == VKD3D_SHADER_TYPE_HULL || compiler->shader_type == VKD3D_SHADER_TYPE_GEOMETRY)
- && !sysval && signature_element->sysval_semantic)
- sysval = vkd3d_siv_from_sysval(signature_element->sysval_semantic);
+ sysval = vkd3d_siv_from_sysval(signature_element->sysval_semantic);
+ /* The Vulkan spec does not explicitly forbid passing varyings from the
+ * TCS to the TES via builtins. However, Mesa doesn't seem to handle it
+ * well, and we don't actually need them to be in builtins. */
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN && reg->type != VKD3DSPR_PATCHCONST)
+ sysval = VKD3D_SIV_NONE;
builtin = get_spirv_builtin_for_sysval(compiler, sysval);
@@ -4693,7 +4735,7 @@ 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, interpolation_mode);
+ spirv_compiler_emit_interpolation_decorations(compiler, input_id, signature_element->interpolation_mode);
}
var_id = input_id;
@@ -4715,47 +4757,27 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
if (use_private_var)
{
+ struct vkd3d_shader_register dst_reg = *reg;
+ dst_reg.data_type = VKD3D_DATA_FLOAT;
+
type_id = vkd3d_spirv_get_type_id(builder, component_type, input_component_count);
- for (i = 0; i < max(array_sizes[0], 1); ++i)
- {
- struct vkd3d_shader_register dst_reg = *reg;
- dst_reg.data_type = VKD3D_DATA_FLOAT;
- val_id = input_id;
- if (array_sizes[0])
- {
- ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassInput, type_id);
- index = spirv_compiler_get_constant_uint(compiler, i);
- val_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, input_id, index);
- dst_reg.idx[0].offset = i;
- }
- else if (builtin && builtin->spirv_array_size)
- {
- /* The D3D builtin is not an array, but the SPIR-V builtin is,
- * so we'll need to index into the SPIR-V builtin when loading
- * it. This happens when reading TessLevel in domain shaders. */
- ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassInput, type_id);
- index = spirv_compiler_get_constant_uint(compiler, builtin->member_idx);
- val_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, input_id, index);
- dst_reg.idx[0].offset = element_idx + i;
- }
- val_id = vkd3d_spirv_build_op_load(builder, type_id, val_id, SpvMemoryAccessMaskNone);
+ val_id = vkd3d_spirv_build_op_load(builder, type_id, input_id, SpvMemoryAccessMaskNone);
- if (builtin && builtin->fixup_pfn)
- val_id = builtin->fixup_pfn(compiler, val_id);
+ if (builtin && builtin->fixup_pfn)
+ val_id = builtin->fixup_pfn(compiler, val_id);
- if (component_type != VKD3D_SHADER_COMPONENT_FLOAT)
- {
- float_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, input_component_count);
- val_id = vkd3d_spirv_build_op_bitcast(builder, float_type_id, val_id);
- }
+ if (component_type != VKD3D_SHADER_COMPONENT_FLOAT)
+ {
+ float_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, input_component_count);
+ val_id = vkd3d_spirv_build_op_bitcast(builder, float_type_id, val_id);
+ }
- 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);
+ 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);
- spirv_compiler_emit_store_reg(compiler, &dst_reg, dst->write_mask, val_id);
- }
+ spirv_compiler_emit_store_reg(compiler, &dst_reg, dst->write_mask, val_id);
}
return input_id;
@@ -4806,13 +4828,12 @@ static void spirv_compiler_emit_shader_phase_input(struct spirv_compiler *compil
case VKD3DSPR_INPUT:
case VKD3DSPR_INCONTROLPOINT:
case VKD3DSPR_PATCHCONST:
- spirv_compiler_emit_input(compiler, dst, VKD3D_SIV_NONE, VKD3DSIM_NONE);
+ spirv_compiler_emit_input(compiler, dst);
return;
case VKD3DSPR_PRIMID:
spirv_compiler_emit_input_register(compiler, dst);
return;
case VKD3DSPR_OUTPOINTID: /* Emitted in spirv_compiler_emit_initial_declarations(). */
- case VKD3DSPR_OUTCONTROLPOINT: /* See spirv_compiler_leave_shader_phase(). */
return;
default:
FIXME("Unhandled shader phase input register %#x.\n", reg->type);
@@ -4977,8 +4998,7 @@ 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, enum vkd3d_shader_input_sysval_semantic sysval)
+static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const struct vkd3d_shader_dst_param *dst)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_register *reg = &dst->reg;
@@ -4986,6 +5006,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler,
const struct signature_element *signature_element;
enum vkd3d_shader_component_type component_type;
const struct shader_signature *shader_signature;
+ enum vkd3d_shader_input_sysval_semantic sysval;
const struct vkd3d_spirv_builtin *builtin;
unsigned int write_mask, reg_write_mask;
bool use_private_variable = false;
@@ -5002,6 +5023,10 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler,
element_idx = shader_register_get_io_indices(reg, array_sizes);
signature_element = &shader_signature->elements[element_idx];
+ sysval = vkd3d_siv_from_sysval(signature_element->sysval_semantic);
+ /* Don't use builtins for TCS -> TES varyings. See spirv_compiler_emit_input(). */
+ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && !is_patch_constant)
+ sysval = VKD3D_SIV_NONE;
builtin = vkd3d_get_spirv_builtin(compiler, dst->reg.type, sysval);
@@ -5393,9 +5418,9 @@ static void spirv_compiler_emit_dcl_global_flags(struct spirv_compiler *compiler
}
if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS))
- FIXME("Unhandled global flags %#"PRIx64".\n", flags);
+ FIXME("Unhandled global flags %#"PRIx64".\n", (uint64_t)flags);
else
- WARN("Unhandled global flags %#"PRIx64".\n", flags);
+ WARN("Unhandled global flags %#"PRIx64".\n", (uint64_t)flags);
}
static void spirv_compiler_emit_temps(struct spirv_compiler *compiler, uint32_t count)
@@ -6089,33 +6114,15 @@ static void spirv_compiler_emit_dcl_input(struct spirv_compiler *compiler,
if (spirv_compiler_get_current_shader_phase(compiler))
spirv_compiler_emit_shader_phase_input(compiler, dst);
else if (vkd3d_shader_register_is_input(&dst->reg) || dst->reg.type == VKD3DSPR_PATCHCONST)
- spirv_compiler_emit_input(compiler, dst, VKD3D_SIV_NONE, VKD3DSIM_NONE);
+ spirv_compiler_emit_input(compiler, dst);
else
spirv_compiler_emit_input_register(compiler, dst);
-
- if (dst->reg.type == VKD3DSPR_OUTCONTROLPOINT)
- compiler->use_vocp = true;
-}
-
-static void spirv_compiler_emit_dcl_input_ps(struct spirv_compiler *compiler,
- const struct vkd3d_shader_instruction *instruction)
-{
- spirv_compiler_emit_input(compiler, &instruction->declaration.dst, VKD3D_SIV_NONE, instruction->flags);
-}
-
-static void spirv_compiler_emit_dcl_input_ps_sysval(struct spirv_compiler *compiler,
- const struct vkd3d_shader_instruction *instruction)
-{
- const struct vkd3d_shader_register_semantic *semantic = &instruction->declaration.register_semantic;
-
- spirv_compiler_emit_input(compiler, &semantic->reg, semantic->sysval_semantic, instruction->flags);
}
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,
- instruction->declaration.register_semantic.sysval_semantic, VKD3DSIM_NONE);
+ spirv_compiler_emit_input(compiler, &instruction->declaration.register_semantic.reg);
}
static void spirv_compiler_emit_dcl_output(struct spirv_compiler *compiler,
@@ -6125,7 +6132,7 @@ static void spirv_compiler_emit_dcl_output(struct spirv_compiler *compiler,
if (vkd3d_shader_register_is_output(&dst->reg)
|| (is_in_fork_or_join_phase(compiler) && vkd3d_shader_register_is_patch_constant(&dst->reg)))
- spirv_compiler_emit_output(compiler, dst, VKD3D_SIV_NONE);
+ spirv_compiler_emit_output(compiler, dst);
else
spirv_compiler_emit_output_register(compiler, dst);
}
@@ -6133,13 +6140,7 @@ static void spirv_compiler_emit_dcl_output(struct spirv_compiler *compiler,
static void spirv_compiler_emit_dcl_output_siv(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
- enum vkd3d_shader_input_sysval_semantic sysval;
- const struct vkd3d_shader_dst_param *dst;
-
- dst = &instruction->declaration.register_semantic.reg;
- sysval = instruction->declaration.register_semantic.sysval_semantic;
-
- spirv_compiler_emit_output(compiler, dst, sysval);
+ spirv_compiler_emit_output(compiler, &instruction->declaration.register_semantic.reg);
}
static void spirv_compiler_emit_dcl_stream(struct spirv_compiler *compiler,
@@ -6569,6 +6570,7 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru
{VKD3DSIH_DTOF, SpvOpFConvert},
{VKD3DSIH_DTOI, SpvOpConvertFToS},
{VKD3DSIH_DTOU, SpvOpConvertFToU},
+ {VKD3DSIH_FREM, SpvOpFRem},
{VKD3DSIH_FTOD, SpvOpFConvert},
{VKD3DSIH_IADD, SpvOpIAdd},
{VKD3DSIH_INEG, SpvOpSNegate},
@@ -6947,7 +6949,7 @@ static void spirv_compiler_emit_imul(struct spirv_compiler *compiler,
uint32_t type_id, val_id, src0_id, src1_id;
if (dst[0].reg.type != VKD3DSPR_NULL)
- FIXME("Extended multiplies not implemented.\n"); /* SpvOpSMulExtended */
+ FIXME("Extended multiplies not implemented.\n"); /* SpvOpSMulExtended/SpvOpUMulExtended */
if (dst[1].reg.type == VKD3DSPR_NULL)
return;
@@ -6983,7 +6985,7 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler,
spirv_compiler_emit_store_dst(compiler, dst, val_id);
}
-static void spirv_compiler_emit_udiv(struct spirv_compiler *compiler,
+static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
uint32_t type_id, val_id, src0_id, src1_id, condition_id, uint_max_id;
@@ -6991,6 +6993,10 @@ static void spirv_compiler_emit_udiv(struct spirv_compiler *compiler,
const struct vkd3d_shader_dst_param *dst = instruction->dst;
const struct vkd3d_shader_src_param *src = instruction->src;
unsigned int component_count = 0;
+ SpvOp div_op, mod_op;
+
+ div_op = instruction->handler_idx == VKD3DSIH_IDIV ? SpvOpSDiv : SpvOpUDiv;
+ mod_op = instruction->handler_idx == VKD3DSIH_IDIV ? SpvOpSRem : SpvOpUMod;
if (dst[0].reg.type != VKD3DSPR_NULL)
{
@@ -7005,7 +7011,7 @@ static void spirv_compiler_emit_udiv(struct spirv_compiler *compiler,
uint_max_id = spirv_compiler_get_constant_uint_vector(compiler,
0xffffffff, component_count);
- val_id = vkd3d_spirv_build_op_udiv(builder, type_id, src0_id, src1_id);
+ 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." */
val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, val_id, uint_max_id);
@@ -7028,7 +7034,7 @@ static void spirv_compiler_emit_udiv(struct spirv_compiler *compiler,
0xffffffff, component_count);
}
- val_id = vkd3d_spirv_build_op_umod(builder, type_id, src0_id, src1_id);
+ val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, mod_op, type_id, src0_id, src1_id);
/* The SPIR-V spec says: "The resulting value is undefined if Operand 2 is 0." */
val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, val_id, uint_max_id);
@@ -9301,16 +9307,12 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_DCL_TGSM_STRUCTURED:
spirv_compiler_emit_dcl_tgsm_structured(compiler, instruction);
break;
+ case VKD3DSIH_DCL_INPUT_PS:
case VKD3DSIH_DCL_INPUT:
spirv_compiler_emit_dcl_input(compiler, instruction);
break;
- case VKD3DSIH_DCL_INPUT_PS:
- spirv_compiler_emit_dcl_input_ps(compiler, instruction);
- break;
case VKD3DSIH_DCL_INPUT_PS_SGV:
case VKD3DSIH_DCL_INPUT_PS_SIV:
- spirv_compiler_emit_dcl_input_ps_sysval(compiler, instruction);
- break;
case VKD3DSIH_DCL_INPUT_SGV:
case VKD3DSIH_DCL_INPUT_SIV:
spirv_compiler_emit_dcl_input_sysval(compiler, instruction);
@@ -9384,6 +9386,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
case VKD3DSIH_DTOF:
case VKD3DSIH_DTOI:
case VKD3DSIH_DTOU:
+ case VKD3DSIH_FREM:
case VKD3DSIH_FTOD:
case VKD3DSIH_IADD:
case VKD3DSIH_INEG:
@@ -9437,13 +9440,15 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
spirv_compiler_emit_sincos(compiler, instruction);
break;
case VKD3DSIH_IMUL:
+ case VKD3DSIH_UMUL:
spirv_compiler_emit_imul(compiler, instruction);
break;
case VKD3DSIH_IMAD:
spirv_compiler_emit_imad(compiler, instruction);
break;
+ case VKD3DSIH_IDIV:
case VKD3DSIH_UDIV:
- spirv_compiler_emit_udiv(compiler, instruction);
+ spirv_compiler_emit_int_div(compiler, instruction);
break;
case VKD3DSIH_FTOI:
spirv_compiler_emit_ftoi(compiler, instruction);
@@ -9693,6 +9698,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
memset(&shader_desc->input_signature, 0, sizeof(shader_desc->input_signature));
memset(&shader_desc->output_signature, 0, sizeof(shader_desc->output_signature));
memset(&shader_desc->patch_constant_signature, 0, sizeof(shader_desc->patch_constant_signature));
+ compiler->use_vocp = parser->shader_desc.use_vocp;
if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL)
spirv_compiler_emit_shader_signature_outputs(compiler);
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
index 0ea5a682fa4..fbc04f61fe9 100644
--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c
+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c
@@ -549,6 +549,8 @@ static enum vkd3d_sm4_dimension sm4_dimension_from_vsir_dimension(enum vsir_dime
return VKD3D_SM4_DIMENSION_SCALAR;
case VSIR_DIMENSION_VEC4:
return VKD3D_SM4_DIMENSION_VEC4;
+ case VSIR_DIMENSION_COUNT:
+ vkd3d_unreachable();
}
vkd3d_unreachable();
}
@@ -1070,16 +1072,31 @@ static void shader_sm4_read_declaration_register_semantic(struct vkd3d_shader_in
static void shader_sm4_read_dcl_input_ps(struct vkd3d_shader_instruction *ins, uint32_t opcode,
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
{
+ struct vkd3d_shader_dst_param *dst = &ins->declaration.dst;
+
ins->flags = (opcode_token & VKD3D_SM4_INTERPOLATION_MODE_MASK) >> VKD3D_SM4_INTERPOLATION_MODE_SHIFT;
- shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, &ins->declaration.dst);
+ if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, dst))
+ {
+ struct signature_element *e = vsir_signature_find_element_for_reg(
+ &priv->p.shader_desc.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask);
+
+ e->interpolation_mode = ins->flags;
+ }
}
static void shader_sm4_read_dcl_input_ps_siv(struct vkd3d_shader_instruction *ins, uint32_t opcode,
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
{
+ struct vkd3d_shader_dst_param *dst = &ins->declaration.register_semantic.reg;
+
ins->flags = (opcode_token & VKD3D_SM4_INTERPOLATION_MODE_MASK) >> VKD3D_SM4_INTERPOLATION_MODE_SHIFT;
- shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT,
- &ins->declaration.register_semantic.reg);
+ if (shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_FLOAT, dst))
+ {
+ struct signature_element *e = vsir_signature_find_element_for_reg(
+ &priv->p.shader_desc.input_signature, dst->reg.idx[dst->reg.idx_count - 1].offset, dst->write_mask);
+
+ e->interpolation_mode = ins->flags;
+ }
ins->declaration.register_semantic.sysval_semantic = *tokens;
}
@@ -3443,7 +3460,8 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
- if (var->is_uniform && var->buffer == cbuffer)
+ if (var->is_uniform && var->buffer == cbuffer
+ && var->data_type->class != HLSL_CLASS_OBJECT)
++var_count;
}
@@ -3477,7 +3495,8 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
- if (var->is_uniform && var->buffer == cbuffer)
+ if (var->is_uniform && var->buffer == cbuffer
+ && var->data_type->class != HLSL_CLASS_OBJECT)
{
uint32_t flags = 0;
@@ -3504,7 +3523,8 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
j = 0;
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
- if (var->is_uniform && var->buffer == cbuffer)
+ if (var->is_uniform && var->buffer == cbuffer
+ && var->data_type->class != HLSL_CLASS_OBJECT)
{
const unsigned int var_size = (profile->major_version >= 5 ? 10 : 6);
size_t var_offset = vars_start + j * var_size * sizeof(uint32_t);
@@ -3732,7 +3752,7 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct vkd3d_shader_re
struct hlsl_reg hlsl_reg = hlsl_reg_from_deref(ctx, deref);
assert(hlsl_reg.allocated);
- reg->type = VKD3DSPR_TEMP;
+ reg->type = deref->var->indexable ? VKD3DSPR_IDXTEMP : VKD3DSPR_TEMP;
reg->dimension = VSIR_DIMENSION_VEC4;
reg->idx[0].offset = hlsl_reg.id;
reg->idx_count = 1;
@@ -3773,7 +3793,7 @@ static void sm4_dst_from_node(struct vkd3d_shader_dst_param *dst, const struct h
static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src,
const struct hlsl_constant_value *value, unsigned int width, unsigned int map_writemask)
{
- src->swizzle = VKD3D_SHADER_NO_SWIZZLE;
+ src->swizzle = 0;
src->reg.type = VKD3DSPR_IMMCONST;
if (width == 1)
{
@@ -4251,6 +4271,20 @@ static void write_sm4_dcl_temps(const struct tpf_writer *tpf, uint32_t temp_coun
write_sm4_instruction(tpf, &instr);
}
+static void write_sm4_dcl_indexable_temp(const struct tpf_writer *tpf, uint32_t idx,
+ uint32_t size, uint32_t comp_count)
+{
+ struct sm4_instruction instr =
+ {
+ .opcode = VKD3D_SM4_OP_DCL_INDEXABLE_TEMP,
+
+ .idx = {idx, size, comp_count},
+ .idx_count = 3,
+ };
+
+ write_sm4_instruction(tpf, &instr);
+}
+
static void write_sm4_dcl_thread_group(const struct tpf_writer *tpf, const uint32_t thread_count[3])
{
struct sm4_instruction instr =
@@ -5467,6 +5501,46 @@ static void write_sm4_store(const struct tpf_writer *tpf, const struct hlsl_ir_s
write_sm4_instruction(tpf, &instr);
}
+static void write_sm4_switch(const struct tpf_writer *tpf, const struct hlsl_ir_switch *s)
+{
+ const struct hlsl_ir_node *selector = s->selector.node;
+ struct hlsl_ir_switch_case *c;
+ struct sm4_instruction instr;
+
+ memset(&instr, 0, sizeof(instr));
+ instr.opcode = VKD3D_SM4_OP_SWITCH;
+
+ sm4_src_from_node(tpf, &instr.srcs[0], selector, VKD3DSP_WRITEMASK_ALL);
+ instr.src_count = 1;
+
+ write_sm4_instruction(tpf, &instr);
+
+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry)
+ {
+ memset(&instr, 0, sizeof(instr));
+ if (c->is_default)
+ {
+ instr.opcode = VKD3D_SM4_OP_DEFAULT;
+ }
+ else
+ {
+ struct hlsl_constant_value value = { .u[0].u = c->value };
+
+ instr.opcode = VKD3D_SM4_OP_CASE;
+ sm4_src_from_constant_value(&instr.srcs[0], &value, 1, VKD3DSP_WRITEMASK_ALL);
+ instr.src_count = 1;
+ }
+
+ write_sm4_instruction(tpf, &instr);
+ write_sm4_block(tpf, &c->body);
+ }
+
+ memset(&instr, 0, sizeof(instr));
+ instr.opcode = VKD3D_SM4_OP_ENDSWITCH;
+
+ write_sm4_instruction(tpf, &instr);
+}
+
static void write_sm4_swizzle(const struct tpf_writer *tpf, const struct hlsl_ir_swizzle *swizzle)
{
unsigned int hlsl_swizzle;
@@ -5554,6 +5628,10 @@ static void write_sm4_block(const struct tpf_writer *tpf, const struct hlsl_bloc
write_sm4_store(tpf, hlsl_ir_store(instr));
break;
+ case HLSL_IR_SWITCH:
+ write_sm4_switch(tpf, hlsl_ir_switch(instr));
+ break;
+
case HLSL_IR_SWIZZLE:
write_sm4_swizzle(tpf, hlsl_ir_swizzle(instr));
break;
@@ -5572,6 +5650,7 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
struct extern_resource *extern_resources;
unsigned int extern_resources_count, i;
const struct hlsl_buffer *cbuffer;
+ const struct hlsl_scope *scope;
const struct hlsl_ir_var *var;
size_t token_count_position;
struct tpf_writer tpf;
@@ -5626,6 +5705,25 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
if (ctx->temp_count)
write_sm4_dcl_temps(&tpf, ctx->temp_count);
+ LIST_FOR_EACH_ENTRY(scope, &ctx->scopes, struct hlsl_scope, entry)
+ {
+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
+ {
+ if (var->is_uniform || var->is_input_semantic || var->is_output_semantic)
+ continue;
+ if (!var->regs[HLSL_REGSET_NUMERIC].allocated)
+ continue;
+
+ if (var->indexable)
+ {
+ unsigned int id = var->regs[HLSL_REGSET_NUMERIC].id;
+ unsigned int size = align(var->data_type->reg_size[HLSL_REGSET_NUMERIC], 4) / 4;
+
+ write_sm4_dcl_indexable_temp(&tpf, id, size, 4);
+ }
+ }
+ }
+
write_sm4_block(&tpf, &entry_func->body);
write_sm4_ret(&tpf);
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
index 4ce1c9daf90..ce51186e26b 100644
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
@@ -18,6 +18,7 @@
#include "vkd3d_shader_private.h"
#include "vkd3d_version.h"
+#include "hlsl.h"
#include <stdio.h>
#include <math.h>
@@ -381,7 +382,7 @@ void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value
memcpy(buffer->data + offset, &value, sizeof(value));
}
-static void vkd3d_shader_dump_blob(const char *path, const char *prefix,
+static void vkd3d_shader_dump_blob(const char *path, const char *profile,
const char *suffix, const void *data, size_t size)
{
static LONG shader_id = 0;
@@ -391,7 +392,10 @@ static void vkd3d_shader_dump_blob(const char *path, const char *prefix,
id = InterlockedIncrement(&shader_id) - 1;
- snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%s-%u.%s", path, prefix, id, suffix);
+ if (profile)
+ snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%u-%s.%s", path, id, profile, suffix);
+ else
+ snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%u.%s", path, id, suffix);
if ((f = fopen(filename, "wb")))
{
if (fwrite(data, 1, size, f) != size)
@@ -423,9 +427,12 @@ static const char *shader_get_source_type_suffix(enum vkd3d_shader_source_type t
}
}
-void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type,
- enum vkd3d_shader_type shader_type, const struct vkd3d_shader_code *shader)
+void vkd3d_shader_dump_shader(const struct vkd3d_shader_compile_info *compile_info)
{
+ const struct vkd3d_shader_code *shader = &compile_info->source;
+ const struct vkd3d_shader_hlsl_source_info *hlsl_source_info;
+ const struct hlsl_profile_info *profile;
+ const char *profile_name = NULL;
static bool enabled = true;
const char *path;
@@ -438,8 +445,19 @@ void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type,
return;
}
- vkd3d_shader_dump_blob(path, shader_get_type_prefix(shader_type),
- shader_get_source_type_suffix(source_type), shader->code, shader->size);
+ if (compile_info->source_type == VKD3D_SHADER_SOURCE_HLSL)
+ {
+ if (!(hlsl_source_info = vkd3d_find_struct(compile_info->next, HLSL_SOURCE_INFO)))
+ return;
+
+ if (!(profile = hlsl_get_target_info(hlsl_source_info->profile)))
+ return;
+
+ profile_name = profile->name;
+ }
+
+ vkd3d_shader_dump_blob(path, profile_name, shader_get_source_type_suffix(compile_info->source_type),
+ shader->code, shader->size);
}
static void init_scan_signature_info(const struct vkd3d_shader_compile_info *info)
@@ -784,6 +802,9 @@ static struct vkd3d_shader_descriptor_info1 *vkd3d_shader_scan_add_descriptor(st
struct vkd3d_shader_scan_descriptor_info1 *info = context->scan_descriptor_info;
struct vkd3d_shader_descriptor_info1 *d;
+ if (!info)
+ return NULL;
+
if (!vkd3d_array_reserve((void **)&info->descriptors, &context->descriptors_size,
info->descriptor_count + 1, sizeof(*info->descriptors)))
{
@@ -811,9 +832,6 @@ static void vkd3d_shader_scan_constant_buffer_declaration(struct vkd3d_shader_sc
const struct vkd3d_shader_constant_buffer *cb = &instruction->declaration.cb;
struct vkd3d_shader_descriptor_info1 *d;
- if (!context->scan_descriptor_info)
- return;
-
if (!(d = vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV,
&cb->src.reg, &cb->range, VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT)))
return;
@@ -826,9 +844,6 @@ static void vkd3d_shader_scan_sampler_declaration(struct vkd3d_shader_scan_conte
const struct vkd3d_shader_sampler *sampler = &instruction->declaration.sampler;
struct vkd3d_shader_descriptor_info1 *d;
- if (!context->scan_descriptor_info)
- return;
-
if (!(d = vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER,
&sampler->src.reg, &sampler->range, VKD3D_SHADER_RESOURCE_NONE, VKD3D_SHADER_RESOURCE_DATA_UINT)))
return;
@@ -854,9 +869,6 @@ static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_cont
struct vkd3d_shader_descriptor_info1 *d;
enum vkd3d_shader_descriptor_type type;
- if (!context->scan_descriptor_info)
- return;
-
if (resource->reg.reg.type == VKD3DSPR_UAV)
type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV;
else
@@ -1313,6 +1325,8 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
vkd3d_shader_message_context_init(&message_context, compile_info->log_level);
+ vkd3d_shader_dump_shader(compile_info);
+
switch (compile_info->source_type)
{
case VKD3D_SHADER_SOURCE_DXBC_TPF:
@@ -1354,8 +1368,6 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
struct vkd3d_shader_compile_info scan_info;
int ret;
- vkd3d_shader_dump_shader(compile_info->source_type, parser->shader_version.type, &compile_info->source);
-
scan_info = *compile_info;
if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0)
@@ -1439,8 +1451,6 @@ static int compile_d3d_bytecode(const struct vkd3d_shader_compile_info *compile_
return ret;
}
- vkd3d_shader_dump_shader(compile_info->source_type, parser->shader_version.type, &compile_info->source);
-
if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM)
{
ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out);
@@ -1487,6 +1497,8 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
vkd3d_shader_message_context_init(&message_context, compile_info->log_level);
+ vkd3d_shader_dump_shader(compile_info);
+
switch (compile_info->source_type)
{
case VKD3D_SHADER_SOURCE_DXBC_TPF:
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
index c9d2dec8b89..ab7300115dc 100644
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -142,6 +142,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_HLSL_RECURSIVE_CALL = 5025,
VKD3D_SHADER_ERROR_HLSL_INCONSISTENT_SAMPLER = 5026,
VKD3D_SHADER_ERROR_HLSL_NON_FINITE_RESULT = 5027,
+ VKD3D_SHADER_ERROR_HLSL_DUPLICATE_SWITCH_CASE = 5028,
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300,
VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301,
@@ -181,6 +182,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_DXIL_INVALID_SIGNATURE = 8016,
VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES = 8017,
VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES = 8018,
+ VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE = 8019,
VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300,
VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301,
@@ -190,6 +192,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH = 8305,
VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH = 8306,
VKD3D_SHADER_WARNING_DXIL_INVALID_MASK = 8307,
+ VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308,
VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000,
VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001,
@@ -198,6 +201,15 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS = 9004,
VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT = 9005,
VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE = 9006,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION = 9007,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE = 9008,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION = 9009,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT = 9010,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT = 9011,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT = 9012,
+ VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS = 9013,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS = 9014,
+ VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX = 9015,
};
enum vkd3d_shader_opcode
@@ -325,6 +337,7 @@ enum vkd3d_shader_opcode
VKD3DSIH_FIRSTBIT_LO,
VKD3DSIH_FIRSTBIT_SHI,
VKD3DSIH_FRC,
+ VKD3DSIH_FREM,
VKD3DSIH_FTOD,
VKD3DSIH_FTOI,
VKD3DSIH_FTOU,
@@ -343,6 +356,7 @@ enum vkd3d_shader_opcode
VKD3DSIH_HS_JOIN_PHASE,
VKD3DSIH_IADD,
VKD3DSIH_IBFE,
+ VKD3DSIH_IDIV,
VKD3DSIH_IEQ,
VKD3DSIH_IF,
VKD3DSIH_IFC,
@@ -554,6 +568,8 @@ enum vkd3d_shader_register_precision
VKD3D_SHADER_REGISTER_PRECISION_MIN_INT_16,
VKD3D_SHADER_REGISTER_PRECISION_MIN_UINT_16,
+ VKD3D_SHADER_REGISTER_PRECISION_COUNT,
+
VKD3D_SHADER_REGISTER_PRECISION_INVALID = ~0u,
};
@@ -574,6 +590,9 @@ enum vkd3d_data_type
VKD3D_DATA_UNUSED,
VKD3D_DATA_UINT8,
VKD3D_DATA_UINT64,
+ VKD3D_DATA_BOOL,
+
+ VKD3D_DATA_COUNT,
};
static inline bool data_type_is_integer(enum vkd3d_data_type data_type)
@@ -582,11 +601,18 @@ static inline bool data_type_is_integer(enum vkd3d_data_type data_type)
|| data_type == VKD3D_DATA_UINT64;
}
+static inline bool data_type_is_bool(enum vkd3d_data_type data_type)
+{
+ return data_type == VKD3D_DATA_BOOL;
+}
+
enum vsir_dimension
{
VSIR_DIMENSION_NONE,
VSIR_DIMENSION_SCALAR,
VSIR_DIMENSION_VEC4,
+
+ VSIR_DIMENSION_COUNT,
};
enum vkd3d_shader_src_modifier
@@ -915,6 +941,8 @@ struct shader_signature
unsigned int element_count;
};
+struct signature_element *vsir_signature_find_element_for_reg(const struct shader_signature *signature,
+ unsigned int reg_idx, unsigned int write_mask);
void shader_signature_cleanup(struct shader_signature *signature);
struct vkd3d_shader_desc
@@ -933,6 +961,8 @@ struct vkd3d_shader_desc
{
uint32_t used, external;
} flat_constant_count[3];
+
+ bool use_vocp;
};
struct vkd3d_shader_register_semantic
@@ -1072,6 +1102,16 @@ struct vkd3d_shader_instruction
} declaration;
};
+static inline bool vkd3d_shader_ver_ge(const struct vkd3d_shader_version *v, unsigned int major, unsigned int minor)
+{
+ return v->major > major || (v->major == major && v->minor >= minor);
+}
+
+static inline bool vkd3d_shader_ver_le(const struct vkd3d_shader_version *v, unsigned int major, unsigned int minor)
+{
+ return v->major < major || (v->major == major && v->minor <= minor);
+}
+
void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location,
enum vkd3d_shader_opcode handler_idx);
@@ -1082,7 +1122,7 @@ static inline bool vkd3d_shader_instruction_has_texel_offset(const struct vkd3d_
static inline bool vkd3d_shader_register_is_input(const struct vkd3d_shader_register *reg)
{
- return reg->type == VKD3DSPR_INPUT || reg->type == VKD3DSPR_INCONTROLPOINT || reg->type == VKD3DSPR_OUTCONTROLPOINT;
+ return reg->type == VKD3DSPR_INPUT || reg->type == VKD3DSPR_INCONTROLPOINT;
}
static inline bool vkd3d_shader_register_is_output(const struct vkd3d_shader_register *reg)
@@ -1314,8 +1354,7 @@ void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const stru
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);
-void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type,
- enum vkd3d_shader_type shader_type, const struct vkd3d_shader_code *shader);
+void vkd3d_shader_dump_shader(const struct vkd3d_shader_compile_info *compile_info);
void vkd3d_shader_trace_text_(const char *text, size_t size, const char *function);
#define vkd3d_shader_trace_text(text, size) \
vkd3d_shader_trace_text_(text, size, __FUNCTION__)
diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c
index 0b92cffcde3..2545c0f0433 100644
--- a/libs/vkd3d/libs/vkd3d/state.c
+++ b/libs/vkd3d/libs/vkd3d/state.c
@@ -3605,6 +3605,36 @@ VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_sta
return vk_pipeline;
}
+static int compile_hlsl_cs(const struct vkd3d_shader_code *hlsl, struct vkd3d_shader_code *dxbc)
+{
+ struct vkd3d_shader_hlsl_source_info hlsl_info;
+ struct vkd3d_shader_compile_info info;
+
+ static const struct vkd3d_shader_compile_option options[] =
+ {
+ {VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_9},
+ };
+
+ info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO;
+ info.next = &hlsl_info;
+ info.source = *hlsl;
+ info.source_type = VKD3D_SHADER_SOURCE_HLSL;
+ info.target_type = VKD3D_SHADER_TARGET_DXBC_TPF;
+ info.options = options;
+ info.option_count = ARRAY_SIZE(options);
+ info.log_level = VKD3D_SHADER_LOG_NONE;
+ info.source_name = NULL;
+
+ hlsl_info.type = VKD3D_SHADER_STRUCTURE_TYPE_HLSL_SOURCE_INFO;
+ hlsl_info.next = NULL;
+ hlsl_info.entry_point = "main";
+ hlsl_info.secondary_code.code = NULL;
+ hlsl_info.secondary_code.size = 0;
+ hlsl_info.profile = "cs_5_0";
+
+ return vkd3d_shader_compile(&info, dxbc, NULL);
+}
+
static void vkd3d_uav_clear_pipelines_cleanup(struct vkd3d_uav_clear_pipelines *pipelines,
struct d3d12_device *device)
{
@@ -3658,7 +3688,7 @@ HRESULT vkd3d_uav_clear_state_init(struct vkd3d_uav_clear_state *state, struct d
{
VkPipeline *pipeline;
VkPipelineLayout *pipeline_layout;
- D3D12_SHADER_BYTECODE code;
+ struct vkd3d_shader_code code;
}
pipelines[] =
{
@@ -3748,13 +3778,25 @@ HRESULT vkd3d_uav_clear_state_init(struct vkd3d_uav_clear_state *state, struct d
for (i = 0; i < ARRAY_SIZE(pipelines); ++i)
{
+ struct vkd3d_shader_code dxbc;
+ int ret;
+
+ if ((ret = compile_hlsl_cs(&pipelines[i].code, &dxbc)))
+ {
+ ERR("Failed to compile HLSL compute shader %u, ret %d.\n", i, ret);
+ hr = hresult_from_vk_result(ret);
+ goto fail;
+ }
+
if (pipelines[i].pipeline_layout == &state->vk_pipeline_layout_buffer)
binding.flags = VKD3D_SHADER_BINDING_FLAG_BUFFER;
else
binding.flags = VKD3D_SHADER_BINDING_FLAG_IMAGE;
- if (FAILED(hr = vkd3d_create_compute_pipeline(device, &pipelines[i].code, &shader_interface,
- *pipelines[i].pipeline_layout, pipelines[i].pipeline)))
+ hr = vkd3d_create_compute_pipeline(device, &(D3D12_SHADER_BYTECODE){dxbc.code, dxbc.size},
+ &shader_interface, *pipelines[i].pipeline_layout, pipelines[i].pipeline);
+ vkd3d_shader_free_shader_code(&dxbc);
+ if (FAILED(hr))
{
ERR("Failed to create compute pipeline %u, hr %#x.\n", i, hr);
goto fail;
diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_shaders.h b/libs/vkd3d/libs/vkd3d/vkd3d_shaders.h
index b2a90cdbf3c..3fefe0da849 100644
--- a/libs/vkd3d/libs/vkd3d/vkd3d_shaders.h
+++ b/libs/vkd3d/libs/vkd3d/vkd3d_shaders.h
@@ -19,370 +19,208 @@
#ifndef __VKD3D_SHADERS_H
#define __VKD3D_SHADERS_H
-static const uint32_t cs_uav_clear_buffer_float_code[] =
-{
-#if 0
- RWBuffer<float4> dst;
-
- struct
- {
- float4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(128, 1, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (thread_id.x < u_info.dst_extent.x)
- dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0xe114ba61, 0xff6a0d0b, 0x7b25c8f4, 0xfcf7cf22, 0x00000001, 0x0000010c, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400089c, 0x0011e000, 0x00000000, 0x00005555,
- 0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000080, 0x00000001, 0x00000001,
- 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
- 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
- 0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
- 0x00000000, 0x01000015, 0x0100003e,
-};
-
-static const uint32_t cs_uav_clear_buffer_uint_code[] =
-{
-#if 0
- RWBuffer<uint4> dst;
-
- struct
- {
- uint4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(128, 1, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (thread_id.x < u_info.dst_extent.x)
- dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0x3afd0cfd, 0x5145c166, 0x5b9f76b8, 0xa73775cd, 0x00000001, 0x0000010c, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400089c, 0x0011e000, 0x00000000, 0x00004444,
- 0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000080, 0x00000001, 0x00000001,
- 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
- 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
- 0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
- 0x00000000, 0x01000015, 0x0100003e,
-};
-
-static const uint32_t cs_uav_clear_1d_array_float_code[] =
-{
-#if 0
- RWTexture1DArray<float4> dst;
-
- struct
- {
- float4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(64, 1, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (thread_id.x < u_info.dst_extent.x)
- dst[int2(u_info.dst_offset.x + thread_id.x, thread_id.y)] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0x3d73bc2d, 0x2b635f3d, 0x6bf98e92, 0xbe0aa5d9, 0x00000001, 0x0000011c, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000c8, 0x00050050, 0x00000032, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400389c, 0x0011e000, 0x00000000, 0x00005555,
- 0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
- 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
- 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
- 0x00000001, 0x04000036, 0x001000e2, 0x00000000, 0x00020556, 0x080000a4, 0x0011e0f2, 0x00000000,
- 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
-};
-
-static const uint32_t cs_uav_clear_1d_array_uint_code[] =
-{
-#if 0
- RWTexture1DArray<uint4> dst;
-
- struct
- {
- uint4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(64, 1, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (thread_id.x < u_info.dst_extent.x)
- dst[int2(u_info.dst_offset.x + thread_id.x, thread_id.y)] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0x2f0ca457, 0x72068b34, 0xd9dadc2b, 0xd3178c3e, 0x00000001, 0x0000011c, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000c8, 0x00050050, 0x00000032, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400389c, 0x0011e000, 0x00000000, 0x00004444,
- 0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
- 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
- 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
- 0x00000001, 0x04000036, 0x001000e2, 0x00000000, 0x00020556, 0x080000a4, 0x0011e0f2, 0x00000000,
- 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
-};
-
-static const uint32_t cs_uav_clear_1d_float_code[] =
-{
-#if 0
- RWTexture1D<float4> dst;
-
- struct
- {
- float4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(64, 1, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (thread_id.x < u_info.dst_extent.x)
- dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0x05266503, 0x4b97006f, 0x01a5cc63, 0xe617d0a1, 0x00000001, 0x0000010c, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400109c, 0x0011e000, 0x00000000, 0x00005555,
- 0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
- 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
- 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
- 0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
- 0x00000000, 0x01000015, 0x0100003e,
-};
-
-static const uint32_t cs_uav_clear_1d_uint_code[] =
-{
-#if 0
- RWTexture1D<uint4> dst;
-
- struct
- {
- uint4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(64, 1, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (thread_id.x < u_info.dst_extent.x)
- dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0x19d5c8f2, 0x3ca4ac24, 0x9e258499, 0xf0463fd6, 0x00000001, 0x0000010c, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000b8, 0x00050050, 0x0000002e, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400109c, 0x0011e000, 0x00000000, 0x00004444,
- 0x0200005f, 0x00020012, 0x02000068, 0x00000001, 0x0400009b, 0x00000040, 0x00000001, 0x00000001,
- 0x07000022, 0x00100012, 0x00000000, 0x0002000a, 0x0020802a, 0x00000000, 0x00000001, 0x0304001f,
- 0x0010000a, 0x00000000, 0x0700001e, 0x00100012, 0x00000000, 0x0002000a, 0x0020800a, 0x00000000,
- 0x00000001, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
- 0x00000000, 0x01000015, 0x0100003e,
-};
-
-static const uint32_t cs_uav_clear_2d_array_float_code[] =
-{
-#if 0
- RWTexture2DArray<float4> dst;
-
- struct
- {
- float4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(8, 8, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (all(thread_id.xy < u_info.dst_extent.xy))
- dst[int3(u_info.dst_offset.xy + thread_id.xy, thread_id.z)] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0x924d2d2c, 0xb9166376, 0x99f83871, 0x8ef65025, 0x00000001, 0x00000138, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400409c, 0x0011e000, 0x00000000, 0x00005555,
- 0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
- 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
- 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
- 0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
- 0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
- 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
-};
-
-static const uint32_t cs_uav_clear_2d_array_uint_code[] =
-{
-#if 0
- RWTexture2DArray<uint4> dst;
-
- struct
- {
- uint4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(8, 8, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (all(thread_id.xy < u_info.dst_extent.xy))
- dst[int3(u_info.dst_offset.xy + thread_id.xy, thread_id.z)] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0xa92219d4, 0xa2c5e47d, 0x0d308500, 0xf32197b4, 0x00000001, 0x00000138, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400409c, 0x0011e000, 0x00000000, 0x00004444,
- 0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
- 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
- 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
- 0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
- 0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
- 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
-};
-
-static const uint32_t cs_uav_clear_2d_float_code[] =
-{
-#if 0
- RWTexture2D<float4> dst;
-
- struct
- {
- float4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(8, 8, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (all(thread_id.xy < u_info.dst_extent.xy))
- dst[u_info.dst_offset.xy + thread_id.xy] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0x6e735b3f, 0x7348c4fa, 0xb3634e42, 0x50e2d99b, 0x00000001, 0x00000128, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000d4, 0x00050050, 0x00000035, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400189c, 0x0011e000, 0x00000000, 0x00005555,
- 0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
- 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
- 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
- 0x00000000, 0x0700001e, 0x001000f2, 0x00000000, 0x00020546, 0x00208546, 0x00000000, 0x00000001,
- 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000,
- 0x01000015, 0x0100003e,
-};
-
-static const uint32_t cs_uav_clear_2d_uint_code[] =
-{
-#if 0
- RWTexture2D<uint4> dst;
-
- struct
- {
- uint4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(8, 8, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (all(thread_id.xy < u_info.dst_extent.xy))
- dst[u_info.dst_offset.xy + thread_id.xy] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0xf01db5dd, 0xc7dc5e55, 0xb017c1a8, 0x55abd52d, 0x00000001, 0x00000128, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000d4, 0x00050050, 0x00000035, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400189c, 0x0011e000, 0x00000000, 0x00004444,
- 0x0200005f, 0x00020032, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
- 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
- 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
- 0x00000000, 0x0700001e, 0x001000f2, 0x00000000, 0x00020546, 0x00208546, 0x00000000, 0x00000001,
- 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208e46, 0x00000000, 0x00000000,
- 0x01000015, 0x0100003e,
-};
-
-static const uint32_t cs_uav_clear_3d_float_code[] =
-{
-#if 0
- RWTexture3D<float4> dst;
-
- struct
- {
- float4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(8, 8, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (all(thread_id.xy < u_info.dst_extent.xy))
- dst[int3(u_info.dst_offset.xy, 0) + thread_id.xyz] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0x5d8f36a0, 0x30fa86a5, 0xfec7f2ef, 0xdfd76cbb, 0x00000001, 0x00000138, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400289c, 0x0011e000, 0x00000000, 0x00005555,
- 0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
- 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
- 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
- 0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
- 0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
- 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
-};
-
-static const uint32_t cs_uav_clear_3d_uint_code[] =
-{
-#if 0
- RWTexture3D<uint4> dst;
-
- struct
- {
- uint4 clear_value;
- int2 dst_offset;
- int2 dst_extent;
- } u_info;
-
- [numthreads(8, 8, 1)]
- void main(int3 thread_id : SV_DispatchThreadID)
- {
- if (all(thread_id.xy < u_info.dst_extent.xy))
- dst[int3(u_info.dst_offset.xy, 0) + thread_id.xyz] = u_info.clear_value;
- }
-#endif
- 0x43425844, 0x5b9c95b1, 0xc9bde4e3, 0x9aaff806, 0x24a1d264, 0x00000001, 0x00000138, 0x00000003,
- 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f,
- 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x000000e4, 0x00050050, 0x00000039, 0x0100086a,
- 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0400289c, 0x0011e000, 0x00000000, 0x00004444,
- 0x0200005f, 0x00020072, 0x02000068, 0x00000001, 0x0400009b, 0x00000008, 0x00000008, 0x00000001,
- 0x07000022, 0x00100032, 0x00000000, 0x00020046, 0x00208ae6, 0x00000000, 0x00000001, 0x07000001,
- 0x00100012, 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000000, 0x0304001f, 0x0010000a,
- 0x00000000, 0x0700001e, 0x00100032, 0x00000000, 0x00020046, 0x00208046, 0x00000000, 0x00000001,
- 0x04000036, 0x001000c2, 0x00000000, 0x00020aa6, 0x080000a4, 0x0011e0f2, 0x00000000, 0x00100e46,
- 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x01000015, 0x0100003e,
-};
+static const char cs_uav_clear_buffer_float_code[] =
+ "RWBuffer<float4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " float4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(128, 1, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (thread_id.x < u_info.dst_extent.x)\n"
+ " dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;\n"
+ "}\n";
+
+static const char cs_uav_clear_buffer_uint_code[] =
+ "RWBuffer<uint4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " uint4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(128, 1, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (thread_id.x < u_info.dst_extent.x)\n"
+ " dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;\n"
+ "}\n";
+
+static const char cs_uav_clear_1d_array_float_code[] =
+ "RWTexture1DArray<float4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " float4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(64, 1, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (thread_id.x < u_info.dst_extent.x)\n"
+ " dst[int2(u_info.dst_offset.x + thread_id.x, thread_id.y)] = u_info.clear_value;\n"
+ "}\n";
+
+static const char cs_uav_clear_1d_array_uint_code[] =
+ "RWTexture1DArray<uint4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " uint4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(64, 1, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (thread_id.x < u_info.dst_extent.x)\n"
+ " dst[int2(u_info.dst_offset.x + thread_id.x, thread_id.y)] = u_info.clear_value;\n"
+ "}\n";
+
+static const char cs_uav_clear_1d_float_code[] =
+ "RWTexture1D<float4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " float4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(64, 1, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (thread_id.x < u_info.dst_extent.x)\n"
+ " dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;\n"
+ "}\n";
+
+static const char cs_uav_clear_1d_uint_code[] =
+ "RWTexture1D<uint4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " uint4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(64, 1, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (thread_id.x < u_info.dst_extent.x)\n"
+ " dst[u_info.dst_offset.x + thread_id.x] = u_info.clear_value;\n"
+ "}\n";
+
+static const char cs_uav_clear_2d_array_float_code[] =
+ "RWTexture2DArray<float4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " float4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(8, 8, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (all(thread_id.xy < u_info.dst_extent.xy))\n"
+ " dst[int3(u_info.dst_offset.xy + thread_id.xy, thread_id.z)] = u_info.clear_value;\n"
+ "}\n";
+
+static const char cs_uav_clear_2d_array_uint_code[] =
+ "RWTexture2DArray<uint4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " uint4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(8, 8, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (all(thread_id.xy < u_info.dst_extent.xy))\n"
+ " dst[int3(u_info.dst_offset.xy + thread_id.xy, thread_id.z)] = u_info.clear_value;\n"
+ "}\n";
+
+static const char cs_uav_clear_2d_float_code[] =
+ "RWTexture2D<float4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " float4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(8, 8, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (all(thread_id.xy < u_info.dst_extent.xy))\n"
+ " dst[u_info.dst_offset.xy + thread_id.xy] = u_info.clear_value;\n"
+ "}\n";
+
+static const char cs_uav_clear_2d_uint_code[] =
+ "RWTexture2D<uint4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " uint4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(8, 8, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (all(thread_id.xy < u_info.dst_extent.xy))\n"
+ " dst[u_info.dst_offset.xy + thread_id.xy] = u_info.clear_value;\n"
+ "}\n";
+
+static const char cs_uav_clear_3d_float_code[] =
+ "RWTexture3D<float4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " float4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(8, 8, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (all(thread_id.xy < u_info.dst_extent.xy))\n"
+ " dst[int3(u_info.dst_offset.xy, 0) + thread_id.xyz] = u_info.clear_value;\n"
+ "}\n";
+
+static const char cs_uav_clear_3d_uint_code[] =
+ "RWTexture3D<uint4> dst;\n"
+ "\n"
+ "struct\n"
+ "{\n"
+ " uint4 clear_value;\n"
+ " int2 dst_offset;\n"
+ " int2 dst_extent;\n"
+ "} u_info;\n"
+ "\n"
+ "[numthreads(8, 8, 1)]\n"
+ "void main(int3 thread_id : SV_DispatchThreadID)\n"
+ "{\n"
+ " if (all(thread_id.xy < u_info.dst_extent.xy))\n"
+ " dst[int3(u_info.dst_offset.xy, 0) + thread_id.xyz] = u_info.clear_value;\n"
+ "}\n";
#endif /* __VKD3D_SHADERS_H */
--
2.42.0