mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
4911 lines
192 KiB
Diff
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(¶m->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(®->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], ®ister_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, ®_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
|
|
|