mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
3189 lines
134 KiB
Diff
3189 lines
134 KiB
Diff
|
From 14870dfefe8b625927240a107b7b841d8e0060f5 Mon Sep 17 00:00:00 2001
|
||
|
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||
|
Date: Fri, 5 Jan 2024 11:03:00 +1100
|
||
|
Subject: [PATCH] Updated vkd3d to 68b898fcb6b4ab2a9660f35edf3554465ab0efbe.
|
||
|
|
||
|
---
|
||
|
libs/vkd3d/Makefile.in | 1 +
|
||
|
libs/vkd3d/include/private/vkd3d_common.h | 5 +-
|
||
|
libs/vkd3d/include/vkd3d_shader.h | 7 +
|
||
|
libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 60 ++-
|
||
|
libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 35 +-
|
||
|
libs/vkd3d/libs/vkd3d-shader/dxbc.c | 34 +-
|
||
|
libs/vkd3d/libs/vkd3d-shader/dxil.c | 15 +-
|
||
|
libs/vkd3d/libs/vkd3d-shader/fx.c | 377 ++++++++++++++++++
|
||
|
libs/vkd3d/libs/vkd3d-shader/hlsl.c | 99 ++++-
|
||
|
libs/vkd3d/libs/vkd3d-shader/hlsl.h | 35 +-
|
||
|
libs/vkd3d/libs/vkd3d-shader/hlsl.l | 1 +
|
||
|
libs/vkd3d/libs/vkd3d-shader/hlsl.y | 142 +++++--
|
||
|
libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 61 ++-
|
||
|
libs/vkd3d/libs/vkd3d-shader/ir.c | 311 +++++++++++++--
|
||
|
libs/vkd3d/libs/vkd3d-shader/spirv.c | 69 ++--
|
||
|
libs/vkd3d/libs/vkd3d-shader/tpf.c | 39 +-
|
||
|
.../libs/vkd3d-shader/vkd3d_shader_main.c | 36 +-
|
||
|
.../libs/vkd3d-shader/vkd3d_shader_private.h | 20 +-
|
||
|
libs/vkd3d/libs/vkd3d/command.c | 6 +-
|
||
|
libs/vkd3d/libs/vkd3d/device.c | 42 +-
|
||
|
libs/vkd3d/libs/vkd3d/resource.c | 96 ++++-
|
||
|
libs/vkd3d/libs/vkd3d/state.c | 23 +-
|
||
|
libs/vkd3d/libs/vkd3d/utils.c | 12 +-
|
||
|
libs/vkd3d/libs/vkd3d/vkd3d_private.h | 3 +-
|
||
|
24 files changed, 1289 insertions(+), 240 deletions(-)
|
||
|
create mode 100644 libs/vkd3d/libs/vkd3d-shader/fx.c
|
||
|
|
||
|
diff --git a/libs/vkd3d/Makefile.in b/libs/vkd3d/Makefile.in
|
||
|
index dbc10594f62..448e9a0e61d 100644
|
||
|
--- a/libs/vkd3d/Makefile.in
|
||
|
+++ b/libs/vkd3d/Makefile.in
|
||
|
@@ -17,6 +17,7 @@ SOURCES = \
|
||
|
libs/vkd3d-shader/d3dbc.c \
|
||
|
libs/vkd3d-shader/dxbc.c \
|
||
|
libs/vkd3d-shader/dxil.c \
|
||
|
+ libs/vkd3d-shader/fx.c \
|
||
|
libs/vkd3d-shader/glsl.c \
|
||
|
libs/vkd3d-shader/hlsl.c \
|
||
|
libs/vkd3d-shader/hlsl.l \
|
||
|
diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h
|
||
|
index e9bff2fbba3..4c97fa06e32 100644
|
||
|
--- a/libs/vkd3d/include/private/vkd3d_common.h
|
||
|
+++ b/libs/vkd3d/include/private/vkd3d_common.h
|
||
|
@@ -52,6 +52,7 @@
|
||
|
#define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9')
|
||
|
#define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C')
|
||
|
#define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L')
|
||
|
+#define TAG_FX10 VKD3D_MAKE_TAG('F', 'X', '1', '0')
|
||
|
#define TAG_ISG1 VKD3D_MAKE_TAG('I', 'S', 'G', '1')
|
||
|
#define TAG_ISGN VKD3D_MAKE_TAG('I', 'S', 'G', 'N')
|
||
|
#define TAG_OSG1 VKD3D_MAKE_TAG('O', 'S', 'G', '1')
|
||
|
@@ -276,10 +277,6 @@ static inline LONG64 InterlockedIncrement64(LONG64 volatile *x)
|
||
|
{
|
||
|
return __sync_add_and_fetch(x, 1);
|
||
|
}
|
||
|
-static inline LONG InterlockedAdd(LONG volatile *x, LONG val)
|
||
|
-{
|
||
|
- return __sync_add_and_fetch(x, val);
|
||
|
-}
|
||
|
# else
|
||
|
# error "InterlockedIncrement() not implemented for this platform"
|
||
|
# endif /* HAVE_SYNC_ADD_AND_FETCH */
|
||
|
diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h
|
||
|
index b1a1fff6451..a9c9ccc4a52 100644
|
||
|
--- a/libs/vkd3d/include/vkd3d_shader.h
|
||
|
+++ b/libs/vkd3d/include/vkd3d_shader.h
|
||
|
@@ -785,6 +785,11 @@ enum vkd3d_shader_target_type
|
||
|
* An 'OpenGL Shading Language' shader. \since 1.3
|
||
|
*/
|
||
|
VKD3D_SHADER_TARGET_GLSL,
|
||
|
+ /**
|
||
|
+ * Binary format used by Direct3D 9/10.x/11 effects profiles.
|
||
|
+ * Output is a raw FX section without container. \since 1.11
|
||
|
+ */
|
||
|
+ VKD3D_SHADER_TARGET_FX,
|
||
|
|
||
|
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TARGET_TYPE),
|
||
|
};
|
||
|
@@ -1270,6 +1275,8 @@ enum vkd3d_shader_descriptor_range_flags
|
||
|
VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE = 0x2,
|
||
|
VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
|
||
|
VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8,
|
||
|
+ /** \since 1.11 */
|
||
|
+ VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS = 0x10000,
|
||
|
|
||
|
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_DESCRIPTOR_RANGE_FLAGS),
|
||
|
};
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
|
||
|
index 0589bc42174..4829956cecf 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c
|
||
|
@@ -365,6 +365,7 @@ struct vkd3d_d3d_asm_compiler
|
||
|
struct vkd3d_shader_version shader_version;
|
||
|
struct vkd3d_d3d_asm_colours colours;
|
||
|
enum vsir_asm_dialect dialect;
|
||
|
+ const struct vkd3d_shader_instruction *current;
|
||
|
};
|
||
|
|
||
|
static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...)
|
||
|
@@ -841,6 +842,27 @@ static void shader_print_bool_literal(struct vkd3d_d3d_asm_compiler *compiler,
|
||
|
compiler->colours.literal, b ? "true" : "false", compiler->colours.reset, suffix);
|
||
|
}
|
||
|
|
||
|
+static void shader_print_untyped_literal(struct vkd3d_d3d_asm_compiler *compiler,
|
||
|
+ const char *prefix, uint32_t u, const char *suffix)
|
||
|
+{
|
||
|
+ union
|
||
|
+ {
|
||
|
+ uint32_t u;
|
||
|
+ float f;
|
||
|
+ } value;
|
||
|
+ unsigned int exponent = (u >> 23) & 0xff;
|
||
|
+
|
||
|
+ value.u = u;
|
||
|
+
|
||
|
+ if (exponent != 0 && exponent != 0xff)
|
||
|
+ return shader_print_float_literal(compiler, prefix, value.f, suffix);
|
||
|
+
|
||
|
+ if (u <= 10000)
|
||
|
+ return shader_print_uint_literal(compiler, prefix, value.u, suffix);
|
||
|
+
|
||
|
+ return shader_print_hex_literal(compiler, prefix, value.u, suffix);
|
||
|
+}
|
||
|
+
|
||
|
static void shader_print_subscript(struct vkd3d_d3d_asm_compiler *compiler,
|
||
|
unsigned int offset, const struct vkd3d_shader_src_param *rel_addr)
|
||
|
{
|
||
|
@@ -1102,6 +1124,19 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const
|
||
|
|
||
|
if (reg->type == VKD3DSPR_IMMCONST)
|
||
|
{
|
||
|
+ bool untyped = false;
|
||
|
+
|
||
|
+ switch (compiler->current->handler_idx)
|
||
|
+ {
|
||
|
+ case VKD3DSIH_MOV:
|
||
|
+ case VKD3DSIH_MOVC:
|
||
|
+ untyped = true;
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
shader_addline(buffer, "%s(", compiler->colours.reset);
|
||
|
switch (reg->dimension)
|
||
|
{
|
||
|
@@ -1109,7 +1144,10 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const
|
||
|
switch (reg->data_type)
|
||
|
{
|
||
|
case VKD3D_DATA_FLOAT:
|
||
|
- shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], "");
|
||
|
+ if (untyped)
|
||
|
+ shader_print_untyped_literal(compiler, "", reg->u.immconst_u32[0], "");
|
||
|
+ else
|
||
|
+ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], "");
|
||
|
break;
|
||
|
case VKD3D_DATA_INT:
|
||
|
shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], "");
|
||
|
@@ -1129,10 +1167,20 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const
|
||
|
switch (reg->data_type)
|
||
|
{
|
||
|
case VKD3D_DATA_FLOAT:
|
||
|
- shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], "");
|
||
|
- shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[1], "");
|
||
|
- shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[2], "");
|
||
|
- shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[3], "");
|
||
|
+ if (untyped)
|
||
|
+ {
|
||
|
+ shader_print_untyped_literal(compiler, "", reg->u.immconst_u32[0], "");
|
||
|
+ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[1], "");
|
||
|
+ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[2], "");
|
||
|
+ shader_print_untyped_literal(compiler, ", ", reg->u.immconst_u32[3], "");
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], "");
|
||
|
+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[1], "");
|
||
|
+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[2], "");
|
||
|
+ shader_print_float_literal(compiler, ", ", reg->u.immconst_f32[3], "");
|
||
|
+ }
|
||
|
break;
|
||
|
case VKD3D_DATA_INT:
|
||
|
shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], "");
|
||
|
@@ -1678,6 +1726,8 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler,
|
||
|
struct vkd3d_string_buffer *buffer = &compiler->buffer;
|
||
|
unsigned int i;
|
||
|
|
||
|
+ compiler->current = ins;
|
||
|
+
|
||
|
if (ins->predicate)
|
||
|
{
|
||
|
vkd3d_string_buffer_printf(buffer, "(");
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
||
|
index ca6e3b72de9..aa0dd8f4b0d 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c
|
||
|
@@ -482,9 +482,23 @@ static void shader_sm1_parse_dst_param(uint32_t param, const struct vkd3d_shader
|
||
|
dst->reg.dimension = VSIR_DIMENSION_SCALAR;
|
||
|
else
|
||
|
dst->reg.dimension = VSIR_DIMENSION_VEC4;
|
||
|
- dst->write_mask = (param & VKD3D_SM1_WRITEMASK_MASK) >> VKD3D_SM1_WRITEMASK_SHIFT;
|
||
|
dst->modifiers = (param & VKD3D_SM1_DST_MODIFIER_MASK) >> VKD3D_SM1_DST_MODIFIER_SHIFT;
|
||
|
dst->shift = (param & VKD3D_SM1_DSTSHIFT_MASK) >> VKD3D_SM1_DSTSHIFT_SHIFT;
|
||
|
+
|
||
|
+ switch (dst->reg.dimension)
|
||
|
+ {
|
||
|
+ case VSIR_DIMENSION_SCALAR:
|
||
|
+ dst->write_mask = VKD3DSP_WRITEMASK_0;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case VSIR_DIMENSION_VEC4:
|
||
|
+ dst->write_mask = (param & VKD3D_SM1_WRITEMASK_MASK) >> VKD3D_SM1_WRITEMASK_SHIFT;
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ dst->write_mask = 0;
|
||
|
+ break;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
static struct signature_element *find_signature_element(const struct shader_signature *signature,
|
||
|
@@ -518,8 +532,6 @@ static struct signature_element *find_signature_element_by_register_index(
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
-#define SM1_COLOR_REGISTER_OFFSET 8
|
||
|
-
|
||
|
static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool output,
|
||
|
const char *name, unsigned int index, enum vkd3d_shader_sysval_semantic sysval,
|
||
|
unsigned int register_index, bool is_dcl, unsigned int mask)
|
||
|
@@ -647,15 +659,15 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *
|
||
|
{
|
||
|
case 0:
|
||
|
return add_signature_element(sm1, true, "POSITION", 0,
|
||
|
- VKD3D_SHADER_SV_POSITION, register_index, is_dcl, mask);
|
||
|
+ VKD3D_SHADER_SV_POSITION, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, mask);
|
||
|
|
||
|
case 1:
|
||
|
return add_signature_element(sm1, true, "FOG", 0,
|
||
|
- VKD3D_SHADER_SV_NONE, register_index, is_dcl, 0x1);
|
||
|
+ VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1);
|
||
|
|
||
|
case 2:
|
||
|
return add_signature_element(sm1, true, "PSIZE", 0,
|
||
|
- VKD3D_SHADER_SV_NONE, register_index, is_dcl, 0x1);
|
||
|
+ VKD3D_SHADER_SV_NONE, SM1_RASTOUT_REGISTER_OFFSET + register_index, is_dcl, 0x1);
|
||
|
|
||
|
default:
|
||
|
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX,
|
||
|
@@ -1348,18 +1360,21 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi
|
||
|
sm1->p.shader_desc.flat_constant_count[i].external = get_external_constant_count(sm1, i);
|
||
|
|
||
|
if (!sm1->p.failed)
|
||
|
- vsir_validate(&sm1->p);
|
||
|
+ ret = vsir_validate(&sm1->p);
|
||
|
+
|
||
|
+ if (sm1->p.failed && ret >= 0)
|
||
|
+ ret = VKD3D_ERROR_INVALID_SHADER;
|
||
|
|
||
|
- if (sm1->p.failed)
|
||
|
+ if (ret < 0)
|
||
|
{
|
||
|
WARN("Failed to parse shader.\n");
|
||
|
shader_sm1_destroy(&sm1->p);
|
||
|
- return VKD3D_ERROR_INVALID_SHADER;
|
||
|
+ return ret;
|
||
|
}
|
||
|
|
||
|
*parser = &sm1->p;
|
||
|
|
||
|
- return VKD3D_OK;
|
||
|
+ return ret;
|
||
|
}
|
||
|
|
||
|
bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic,
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c
|
||
|
index 63deaaad29a..37ebc73c099 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c
|
||
|
@@ -130,13 +130,13 @@ static void skip_dword_unknown(const char **ptr, unsigned int count)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
-static const char *shader_get_string(const char *data, size_t data_size, DWORD offset)
|
||
|
+static const char *shader_get_string(const char *data, size_t data_size, size_t offset)
|
||
|
{
|
||
|
size_t len, max_len;
|
||
|
|
||
|
if (offset >= data_size)
|
||
|
{
|
||
|
- WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size);
|
||
|
+ WARN("Invalid offset %#zx (data size %#zx).\n", offset, data_size);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
@@ -230,7 +230,7 @@ static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_
|
||
|
chunk_offset = read_u32(&ptr);
|
||
|
TRACE("chunk %u at offset %#x\n", i, chunk_offset);
|
||
|
|
||
|
- if (chunk_offset >= data_size || !require_space(chunk_offset, 2, sizeof(DWORD), data_size))
|
||
|
+ if (chunk_offset >= data_size || !require_space(chunk_offset, 2, sizeof(uint32_t), data_size))
|
||
|
{
|
||
|
WARN("Invalid chunk offset %#x (data size %zu).\n", chunk_offset, data_size);
|
||
|
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET,
|
||
|
@@ -399,7 +399,8 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s
|
||
|
|
||
|
for (i = 0; i < count; ++i)
|
||
|
{
|
||
|
- uint32_t name_offset, mask;
|
||
|
+ size_t name_offset;
|
||
|
+ uint32_t mask;
|
||
|
|
||
|
e[i].sort_index = i;
|
||
|
|
||
|
@@ -411,7 +412,7 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s
|
||
|
name_offset = read_u32(&ptr);
|
||
|
if (!(e[i].semantic_name = shader_get_string(data, section->data.size, name_offset)))
|
||
|
{
|
||
|
- WARN("Invalid name offset %#x (data size %#zx).\n", name_offset, section->data.size);
|
||
|
+ WARN("Invalid name offset %#zx (data size %#zx).\n", name_offset, section->data.size);
|
||
|
vkd3d_free(e);
|
||
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
}
|
||
|
@@ -592,7 +593,7 @@ static int shader_parse_descriptor_ranges(struct root_signature_parser_context *
|
||
|
const char *ptr;
|
||
|
unsigned int i;
|
||
|
|
||
|
- if (!require_space(offset, 5 * count, sizeof(DWORD), context->data_size))
|
||
|
+ if (!require_space(offset, 5 * count, sizeof(uint32_t), context->data_size))
|
||
|
{
|
||
|
WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count);
|
||
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
@@ -623,7 +624,8 @@ static void shader_validate_descriptor_range1(const struct vkd3d_shader_descript
|
||
|
| VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE
|
||
|
| VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE
|
||
|
| VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE
|
||
|
- | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC);
|
||
|
+ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DATA_STATIC
|
||
|
+ | VKD3D_SHADER_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS);
|
||
|
|
||
|
if (unknown_flags)
|
||
|
FIXME("Unknown descriptor range flags %#x.\n", unknown_flags);
|
||
|
@@ -670,7 +672,7 @@ static int shader_parse_descriptor_table(struct root_signature_parser_context *c
|
||
|
unsigned int count;
|
||
|
const char *ptr;
|
||
|
|
||
|
- if (!require_space(offset, 2, sizeof(DWORD), context->data_size))
|
||
|
+ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size))
|
||
|
{
|
||
|
WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset);
|
||
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
@@ -697,7 +699,7 @@ static int shader_parse_descriptor_table1(struct root_signature_parser_context *
|
||
|
unsigned int count;
|
||
|
const char *ptr;
|
||
|
|
||
|
- if (!require_space(offset, 2, sizeof(DWORD), context->data_size))
|
||
|
+ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size))
|
||
|
{
|
||
|
WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset);
|
||
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
@@ -722,7 +724,7 @@ static int shader_parse_root_constants(struct root_signature_parser_context *con
|
||
|
{
|
||
|
const char *ptr;
|
||
|
|
||
|
- if (!require_space(offset, 3, sizeof(DWORD), context->data_size))
|
||
|
+ if (!require_space(offset, 3, sizeof(uint32_t), context->data_size))
|
||
|
{
|
||
|
WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset);
|
||
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
@@ -744,7 +746,7 @@ static int shader_parse_root_descriptor(struct root_signature_parser_context *co
|
||
|
{
|
||
|
const char *ptr;
|
||
|
|
||
|
- if (!require_space(offset, 2, sizeof(DWORD), context->data_size))
|
||
|
+ if (!require_space(offset, 2, sizeof(uint32_t), context->data_size))
|
||
|
{
|
||
|
WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset);
|
||
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
@@ -776,7 +778,7 @@ static int shader_parse_root_descriptor1(struct root_signature_parser_context *c
|
||
|
{
|
||
|
const char *ptr;
|
||
|
|
||
|
- if (!require_space(offset, 3, sizeof(DWORD), context->data_size))
|
||
|
+ if (!require_space(offset, 3, sizeof(uint32_t), context->data_size))
|
||
|
{
|
||
|
WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset);
|
||
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
@@ -802,7 +804,7 @@ static int shader_parse_root_parameters(struct root_signature_parser_context *co
|
||
|
unsigned int i;
|
||
|
int ret;
|
||
|
|
||
|
- if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size))
|
||
|
+ if (!require_space(offset, 3 * count, sizeof(uint32_t), context->data_size))
|
||
|
{
|
||
|
WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count);
|
||
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
@@ -844,13 +846,13 @@ static int shader_parse_root_parameters(struct root_signature_parser_context *co
|
||
|
}
|
||
|
|
||
|
static int shader_parse_root_parameters1(struct root_signature_parser_context *context,
|
||
|
- uint32_t offset, DWORD count, struct vkd3d_shader_root_parameter1 *parameters)
|
||
|
+ uint32_t offset, unsigned int count, struct vkd3d_shader_root_parameter1 *parameters)
|
||
|
{
|
||
|
const char *ptr;
|
||
|
unsigned int i;
|
||
|
int ret;
|
||
|
|
||
|
- if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size))
|
||
|
+ if (!require_space(offset, 3 * count, sizeof(uint32_t), context->data_size))
|
||
|
{
|
||
|
WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count);
|
||
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
@@ -897,7 +899,7 @@ static int shader_parse_static_samplers(struct root_signature_parser_context *co
|
||
|
const char *ptr;
|
||
|
unsigned int i;
|
||
|
|
||
|
- if (!require_space(offset, 13 * count, sizeof(DWORD), context->data_size))
|
||
|
+ if (!require_space(offset, 13 * count, sizeof(uint32_t), context->data_size))
|
||
|
{
|
||
|
WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count);
|
||
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
||
|
index 2424b176068..b39ec204bff 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c
|
||
|
@@ -2331,8 +2331,8 @@ static const struct sm6_value *sm6_parser_get_value_by_ref(struct sm6_parser *sm
|
||
|
|
||
|
static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxil_record *record)
|
||
|
{
|
||
|
+ const struct sm6_type *type, *ret_type;
|
||
|
const unsigned int max_count = 15;
|
||
|
- const struct sm6_type *ret_type;
|
||
|
struct sm6_value *fn;
|
||
|
unsigned int i, j;
|
||
|
|
||
|
@@ -2347,18 +2347,18 @@ static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxi
|
||
|
fn->u.function.name = "";
|
||
|
}
|
||
|
|
||
|
- if (!(fn->type = sm6_parser_get_type(sm6, record->operands[0])))
|
||
|
+ if (!(type = sm6_parser_get_type(sm6, record->operands[0])))
|
||
|
return false;
|
||
|
- if (!sm6_type_is_function(fn->type))
|
||
|
+ if (!sm6_type_is_function(type))
|
||
|
{
|
||
|
WARN("Type is not a function.\n");
|
||
|
return false;
|
||
|
}
|
||
|
- ret_type = fn->type->u.function->ret_type;
|
||
|
+ ret_type = type->u.function->ret_type;
|
||
|
|
||
|
- if (!(fn->type = sm6_type_get_pointer_to_type(fn->type, ADDRESS_SPACE_DEFAULT, sm6)))
|
||
|
+ if (!(fn->type = sm6_type_get_pointer_to_type(type, ADDRESS_SPACE_DEFAULT, sm6)))
|
||
|
{
|
||
|
- WARN("Failed to get pointer type for type %u.\n", fn->type->class);
|
||
|
+ WARN("Failed to get pointer type for type %u.\n", type->class);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
@@ -3432,6 +3432,7 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, struct sm6_
|
||
|
/* 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->dimension = VSIR_DIMENSION_VEC4;
|
||
|
reg->idx[0].offset = id;
|
||
|
register_index_address_init(®->idx[1], operands[2], sm6);
|
||
|
reg->non_uniform = !!sm6_value_get_constant_uint(operands[3]);
|
||
|
@@ -6281,7 +6282,7 @@ int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compi
|
||
|
vkd3d_free(byte_code);
|
||
|
|
||
|
if (!sm6->p.failed && ret >= 0)
|
||
|
- vsir_validate(&sm6->p);
|
||
|
+ ret = vsir_validate(&sm6->p);
|
||
|
|
||
|
if (sm6->p.failed && ret >= 0)
|
||
|
ret = VKD3D_ERROR_INVALID_SHADER;
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c
|
||
|
new file mode 100644
|
||
|
index 00000000000..17b9627b6bd
|
||
|
--- /dev/null
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/fx.c
|
||
|
@@ -0,0 +1,377 @@
|
||
|
+/*
|
||
|
+ * FX (Direct3D 9/10/11 effect) support
|
||
|
+ *
|
||
|
+ * Copyright 2023 Nikolay Sivov 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
|
||
|
+ */
|
||
|
+
|
||
|
+#include "hlsl.h"
|
||
|
+
|
||
|
+struct string_entry
|
||
|
+{
|
||
|
+ struct rb_entry entry;
|
||
|
+ /* String points to original data, should not be freed. */
|
||
|
+ const char *string;
|
||
|
+ uint32_t offset;
|
||
|
+};
|
||
|
+
|
||
|
+static int string_storage_compare(const void *key, const struct rb_entry *entry)
|
||
|
+{
|
||
|
+ struct string_entry *string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry);
|
||
|
+ const char *string = key;
|
||
|
+
|
||
|
+ return strcmp(string, string_entry->string);
|
||
|
+}
|
||
|
+
|
||
|
+static void string_storage_destroy(struct rb_entry *entry, void *context)
|
||
|
+{
|
||
|
+ struct string_entry *string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry);
|
||
|
+
|
||
|
+ vkd3d_free(string_entry);
|
||
|
+}
|
||
|
+
|
||
|
+struct fx_write_context
|
||
|
+{
|
||
|
+ struct hlsl_ctx *ctx;
|
||
|
+
|
||
|
+ struct vkd3d_bytecode_buffer unstructured;
|
||
|
+ struct vkd3d_bytecode_buffer structured;
|
||
|
+
|
||
|
+ struct rb_tree strings;
|
||
|
+
|
||
|
+ unsigned int min_technique_version;
|
||
|
+ unsigned int max_technique_version;
|
||
|
+
|
||
|
+ uint32_t technique_count;
|
||
|
+ uint32_t group_count;
|
||
|
+ int status;
|
||
|
+};
|
||
|
+
|
||
|
+static void fx_write_context_init(struct hlsl_ctx *ctx, struct fx_write_context *fx)
|
||
|
+{
|
||
|
+ unsigned int version = ctx->profile->major_version;
|
||
|
+
|
||
|
+ memset(fx, 0, sizeof(*fx));
|
||
|
+
|
||
|
+ fx->ctx = ctx;
|
||
|
+ if (version == 2)
|
||
|
+ {
|
||
|
+ fx->min_technique_version = 9;
|
||
|
+ fx->max_technique_version = 9;
|
||
|
+ }
|
||
|
+ else if (version == 4)
|
||
|
+ {
|
||
|
+ fx->min_technique_version = 10;
|
||
|
+ fx->max_technique_version = 10;
|
||
|
+ }
|
||
|
+ else if (version == 5)
|
||
|
+ {
|
||
|
+ fx->min_technique_version = 10;
|
||
|
+ fx->max_technique_version = 11;
|
||
|
+ }
|
||
|
+
|
||
|
+ rb_init(&fx->strings, string_storage_compare);
|
||
|
+}
|
||
|
+
|
||
|
+static int fx_write_context_cleanup(struct fx_write_context *fx)
|
||
|
+{
|
||
|
+ int status = fx->status;
|
||
|
+ rb_destroy(&fx->strings, string_storage_destroy, NULL);
|
||
|
+
|
||
|
+ return status;
|
||
|
+}
|
||
|
+
|
||
|
+static bool technique_matches_version(const struct hlsl_ir_var *var, const struct fx_write_context *fx)
|
||
|
+{
|
||
|
+ const struct hlsl_type *type = var->data_type;
|
||
|
+
|
||
|
+ if (type->base_type != HLSL_TYPE_TECHNIQUE)
|
||
|
+ return false;
|
||
|
+
|
||
|
+ return type->e.version >= fx->min_technique_version && type->e.version <= fx->max_technique_version;
|
||
|
+}
|
||
|
+
|
||
|
+static uint32_t fx_put_raw_string(struct fx_write_context *fx, const char *string)
|
||
|
+{
|
||
|
+ struct string_entry *string_entry;
|
||
|
+ struct rb_entry *entry;
|
||
|
+
|
||
|
+ /* NULLs are emitted as empty strings using the same 4 bytes at the start of the section. */
|
||
|
+ if (!string)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ if ((entry = rb_get(&fx->strings, string)))
|
||
|
+ {
|
||
|
+ string_entry = RB_ENTRY_VALUE(entry, struct string_entry, entry);
|
||
|
+ return string_entry->offset;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!(string_entry = hlsl_alloc(fx->ctx, sizeof(*string_entry))))
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ string_entry->offset = put_string(&fx->unstructured, string);
|
||
|
+ string_entry->string = string;
|
||
|
+
|
||
|
+ rb_put(&fx->strings, string, &string_entry->entry);
|
||
|
+
|
||
|
+ return string_entry->offset;
|
||
|
+}
|
||
|
+
|
||
|
+static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
||
|
+{
|
||
|
+ struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
||
|
+ uint32_t name_offset;
|
||
|
+
|
||
|
+ name_offset = fx_put_raw_string(fx, var->name);
|
||
|
+ put_u32(buffer, name_offset);
|
||
|
+ put_u32(buffer, 0); /* Annotation count. */
|
||
|
+ put_u32(buffer, 0); /* Assignment count. */
|
||
|
+}
|
||
|
+
|
||
|
+static void write_technique(struct hlsl_ir_var *var, struct fx_write_context *fx)
|
||
|
+{
|
||
|
+ struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
||
|
+ uint32_t name_offset, count = 0;
|
||
|
+ struct hlsl_ir_var *pass;
|
||
|
+ uint32_t count_offset;
|
||
|
+
|
||
|
+ name_offset = fx_put_raw_string(fx, var->name);
|
||
|
+ put_u32(buffer, name_offset);
|
||
|
+ count_offset = put_u32(buffer, 0);
|
||
|
+ put_u32(buffer, 0); /* Annotation count. */
|
||
|
+
|
||
|
+ LIST_FOR_EACH_ENTRY(pass, &var->scope->vars, struct hlsl_ir_var, scope_entry)
|
||
|
+ {
|
||
|
+ write_pass(pass, fx);
|
||
|
+ ++count;
|
||
|
+ }
|
||
|
+
|
||
|
+ set_u32(buffer, count_offset, count);
|
||
|
+}
|
||
|
+
|
||
|
+static void set_status(struct fx_write_context *fx, int status)
|
||
|
+{
|
||
|
+ if (fx->status < 0)
|
||
|
+ return;
|
||
|
+ if (status < 0)
|
||
|
+ fx->status = status;
|
||
|
+}
|
||
|
+
|
||
|
+static void write_techniques(struct hlsl_scope *scope, struct fx_write_context *fx)
|
||
|
+{
|
||
|
+ struct hlsl_ir_var *var;
|
||
|
+
|
||
|
+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
||
|
+ {
|
||
|
+ const struct hlsl_type *type = var->data_type;
|
||
|
+
|
||
|
+ if (type->base_type == HLSL_TYPE_TECHNIQUE && type->e.version == 10)
|
||
|
+ {
|
||
|
+ write_technique(var, fx);
|
||
|
+ ++fx->technique_count;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ set_status(fx, fx->unstructured.status);
|
||
|
+ set_status(fx, fx->structured.status);
|
||
|
+}
|
||
|
+
|
||
|
+static void write_group(struct hlsl_scope *scope, const char *name, struct fx_write_context *fx)
|
||
|
+{
|
||
|
+ struct vkd3d_bytecode_buffer *buffer = &fx->structured;
|
||
|
+ uint32_t name_offset = fx_put_raw_string(fx, name);
|
||
|
+ uint32_t count_offset, count;
|
||
|
+
|
||
|
+ put_u32(buffer, name_offset);
|
||
|
+ count_offset = put_u32(buffer, 0); /* Technique count */
|
||
|
+ put_u32(buffer, 0); /* Annotation count */
|
||
|
+
|
||
|
+ count = fx->technique_count;
|
||
|
+ write_techniques(scope, fx);
|
||
|
+ set_u32(buffer, count_offset, fx->technique_count - count);
|
||
|
+
|
||
|
+ ++fx->group_count;
|
||
|
+}
|
||
|
+
|
||
|
+static void write_groups(struct hlsl_scope *scope, struct fx_write_context *fx)
|
||
|
+{
|
||
|
+ bool needs_default_group = false;
|
||
|
+ struct hlsl_ir_var *var;
|
||
|
+
|
||
|
+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
||
|
+ {
|
||
|
+ if (technique_matches_version(var, fx))
|
||
|
+ {
|
||
|
+ needs_default_group = true;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (needs_default_group)
|
||
|
+ write_group(scope, NULL, fx);
|
||
|
+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
||
|
+ {
|
||
|
+ const struct hlsl_type *type = var->data_type;
|
||
|
+
|
||
|
+ if (type->base_type == HLSL_TYPE_EFFECT_GROUP)
|
||
|
+ write_group(var->scope, var->name, fx);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
||
|
+{
|
||
|
+ struct vkd3d_bytecode_buffer buffer = { 0 };
|
||
|
+ struct fx_write_context fx;
|
||
|
+ uint32_t size_offset, size;
|
||
|
+
|
||
|
+ fx_write_context_init(ctx, &fx);
|
||
|
+
|
||
|
+ put_u32(&fx.unstructured, 0); /* Empty string placeholder. */
|
||
|
+
|
||
|
+ /* TODO: buffers */
|
||
|
+ /* TODO: objects */
|
||
|
+ /* TODO: shared buffers */
|
||
|
+ /* TODO: shared objects */
|
||
|
+
|
||
|
+ write_techniques(ctx->globals, &fx);
|
||
|
+
|
||
|
+ put_u32(&buffer, ctx->profile->minor_version == 0 ? 0xfeff1001 : 0xfeff1011); /* Version. */
|
||
|
+ put_u32(&buffer, 0); /* Buffer count. */
|
||
|
+ put_u32(&buffer, 0); /* Variable count. */
|
||
|
+ put_u32(&buffer, 0); /* Object count. */
|
||
|
+ put_u32(&buffer, 0); /* Pool buffer count. */
|
||
|
+ put_u32(&buffer, 0); /* Pool variable count. */
|
||
|
+ put_u32(&buffer, 0); /* Pool object count. */
|
||
|
+ put_u32(&buffer, fx.technique_count);
|
||
|
+ size_offset = put_u32(&buffer, 0); /* Unstructured size. */
|
||
|
+ put_u32(&buffer, 0); /* String count. */
|
||
|
+ put_u32(&buffer, 0); /* Texture object count. */
|
||
|
+ put_u32(&buffer, 0); /* Depth stencil state count. */
|
||
|
+ put_u32(&buffer, 0); /* Blend state count. */
|
||
|
+ put_u32(&buffer, 0); /* Rasterizer state count. */
|
||
|
+ put_u32(&buffer, 0); /* Sampler state count. */
|
||
|
+ put_u32(&buffer, 0); /* Rendertarget view count. */
|
||
|
+ put_u32(&buffer, 0); /* Depth stencil view count. */
|
||
|
+ put_u32(&buffer, 0); /* Shader count. */
|
||
|
+ put_u32(&buffer, 0); /* Inline shader count. */
|
||
|
+
|
||
|
+ size = align(fx.unstructured.size, 4);
|
||
|
+ set_u32(&buffer, size_offset, size);
|
||
|
+
|
||
|
+ bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size);
|
||
|
+ bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size);
|
||
|
+
|
||
|
+ vkd3d_free(fx.unstructured.data);
|
||
|
+ vkd3d_free(fx.structured.data);
|
||
|
+
|
||
|
+ set_status(&fx, buffer.status);
|
||
|
+
|
||
|
+ if (!fx.status)
|
||
|
+ {
|
||
|
+ out->code = buffer.data;
|
||
|
+ out->size = buffer.size;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (fx.status < 0)
|
||
|
+ ctx->result = fx.status;
|
||
|
+
|
||
|
+ return fx_write_context_cleanup(&fx);
|
||
|
+}
|
||
|
+
|
||
|
+static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
||
|
+{
|
||
|
+ struct vkd3d_bytecode_buffer buffer = { 0 };
|
||
|
+ struct fx_write_context fx;
|
||
|
+ uint32_t size_offset, size;
|
||
|
+
|
||
|
+ fx_write_context_init(ctx, &fx);
|
||
|
+
|
||
|
+ put_u32(&fx.unstructured, 0); /* Empty string placeholder. */
|
||
|
+
|
||
|
+ /* TODO: buffers */
|
||
|
+ /* TODO: objects */
|
||
|
+ /* TODO: interface variables */
|
||
|
+
|
||
|
+ write_groups(ctx->globals, &fx);
|
||
|
+
|
||
|
+ put_u32(&buffer, 0xfeff2001); /* Version. */
|
||
|
+ put_u32(&buffer, 0); /* Buffer count. */
|
||
|
+ put_u32(&buffer, 0); /* Variable count. */
|
||
|
+ put_u32(&buffer, 0); /* Object count. */
|
||
|
+ put_u32(&buffer, 0); /* Pool buffer count. */
|
||
|
+ put_u32(&buffer, 0); /* Pool variable count. */
|
||
|
+ put_u32(&buffer, 0); /* Pool object count. */
|
||
|
+ put_u32(&buffer, fx.technique_count);
|
||
|
+ size_offset = put_u32(&buffer, 0); /* Unstructured size. */
|
||
|
+ put_u32(&buffer, 0); /* String count. */
|
||
|
+ put_u32(&buffer, 0); /* Texture object count. */
|
||
|
+ put_u32(&buffer, 0); /* Depth stencil state count. */
|
||
|
+ put_u32(&buffer, 0); /* Blend state count. */
|
||
|
+ put_u32(&buffer, 0); /* Rasterizer state count. */
|
||
|
+ put_u32(&buffer, 0); /* Sampler state count. */
|
||
|
+ put_u32(&buffer, 0); /* Rendertarget view count. */
|
||
|
+ put_u32(&buffer, 0); /* Depth stencil view count. */
|
||
|
+ put_u32(&buffer, 0); /* Shader count. */
|
||
|
+ put_u32(&buffer, 0); /* Inline shader count. */
|
||
|
+ put_u32(&buffer, fx.group_count); /* Group count. */
|
||
|
+ put_u32(&buffer, 0); /* UAV count. */
|
||
|
+ put_u32(&buffer, 0); /* Interface variables count. */
|
||
|
+ put_u32(&buffer, 0); /* Interface variable element count. */
|
||
|
+ put_u32(&buffer, 0); /* Class instance elements count. */
|
||
|
+
|
||
|
+ size = align(fx.unstructured.size, 4);
|
||
|
+ set_u32(&buffer, size_offset, size);
|
||
|
+
|
||
|
+ bytecode_put_bytes(&buffer, fx.unstructured.data, fx.unstructured.size);
|
||
|
+ bytecode_put_bytes(&buffer, fx.structured.data, fx.structured.size);
|
||
|
+
|
||
|
+ vkd3d_free(fx.unstructured.data);
|
||
|
+ vkd3d_free(fx.structured.data);
|
||
|
+
|
||
|
+ set_status(&fx, buffer.status);
|
||
|
+
|
||
|
+ if (!fx.status)
|
||
|
+ {
|
||
|
+ out->code = buffer.data;
|
||
|
+ out->size = buffer.size;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (fx.status < 0)
|
||
|
+ ctx->result = fx.status;
|
||
|
+
|
||
|
+ return fx_write_context_cleanup(&fx);
|
||
|
+}
|
||
|
+
|
||
|
+int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out)
|
||
|
+{
|
||
|
+ if (ctx->profile->major_version == 2)
|
||
|
+ {
|
||
|
+ hlsl_fixme(ctx, &ctx->location, "Writing fx_2_0 binaries is not implemented.");
|
||
|
+ return VKD3D_ERROR_NOT_IMPLEMENTED;
|
||
|
+ }
|
||
|
+ else if (ctx->profile->major_version == 4)
|
||
|
+ {
|
||
|
+ return hlsl_fx_4_write(ctx, out);
|
||
|
+ }
|
||
|
+ else if (ctx->profile->major_version == 5)
|
||
|
+ {
|
||
|
+ return hlsl_fx_5_write(ctx, out);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ vkd3d_unreachable();
|
||
|
+ }
|
||
|
+}
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
||
|
index da3bbda1bc3..1e247445119 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c
|
||
|
@@ -98,19 +98,22 @@ bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var
|
||
|
struct hlsl_scope *scope = ctx->cur_scope;
|
||
|
struct hlsl_ir_var *var;
|
||
|
|
||
|
- LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
||
|
- {
|
||
|
- if (!strcmp(decl->name, var->name))
|
||
|
- return false;
|
||
|
- }
|
||
|
- if (local_var && scope->upper->upper == ctx->globals)
|
||
|
+ if (decl->name)
|
||
|
{
|
||
|
- /* Check whether the variable redefines a function parameter. */
|
||
|
- LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry)
|
||
|
+ LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
||
|
{
|
||
|
- if (!strcmp(decl->name, var->name))
|
||
|
+ if (var->name && !strcmp(decl->name, var->name))
|
||
|
return false;
|
||
|
}
|
||
|
+ if (local_var && scope->upper->upper == ctx->globals)
|
||
|
+ {
|
||
|
+ /* Check whether the variable redefines a function parameter. */
|
||
|
+ LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry)
|
||
|
+ {
|
||
|
+ if (var->name && !strcmp(decl->name, var->name))
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
list_add_tail(&scope->vars, &decl->scope_entry);
|
||
|
@@ -123,7 +126,7 @@ struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name)
|
||
|
|
||
|
LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry)
|
||
|
{
|
||
|
- if (!strcmp(name, var->name))
|
||
|
+ if (var->name && !strcmp(name, var->name))
|
||
|
return var;
|
||
|
}
|
||
|
if (!scope->upper)
|
||
|
@@ -915,12 +918,17 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2
|
||
|
if (t1->class == HLSL_CLASS_ARRAY)
|
||
|
return t1->e.array.elements_count == t2->e.array.elements_count
|
||
|
&& hlsl_types_are_equal(t1->e.array.type, t2->e.array.type);
|
||
|
+ if (t1->class == HLSL_CLASS_OBJECT)
|
||
|
+ {
|
||
|
+ if (t1->base_type == HLSL_TYPE_TECHNIQUE && t1->e.version != t2->e.version)
|
||
|
+ return false;
|
||
|
+ }
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old,
|
||
|
- unsigned int default_majority, unsigned int modifiers)
|
||
|
+ unsigned int default_majority, uint32_t modifiers)
|
||
|
{
|
||
|
struct hlsl_type *type;
|
||
|
|
||
|
@@ -993,6 +1001,13 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old,
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
+ case HLSL_CLASS_OBJECT:
|
||
|
+ {
|
||
|
+ if (type->base_type == HLSL_TYPE_TECHNIQUE)
|
||
|
+ type->e.version = old->e.version;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
@@ -1030,7 +1045,7 @@ struct hlsl_ir_node *hlsl_new_copy(struct hlsl_ctx *ctx, struct hlsl_ir_node *no
|
||
|
}
|
||
|
|
||
|
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 vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, uint32_t modifiers,
|
||
|
const struct hlsl_reg_reservation *reg_reservation)
|
||
|
{
|
||
|
struct hlsl_ir_var *var;
|
||
|
@@ -1505,7 +1520,7 @@ struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct
|
||
|
return &store->node;
|
||
|
}
|
||
|
|
||
|
-struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components,
|
||
|
+struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int components,
|
||
|
struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc)
|
||
|
{
|
||
|
struct hlsl_ir_swizzle *swizzle;
|
||
|
@@ -2246,7 +2261,7 @@ const char *debug_hlsl_type(struct hlsl_ctx *ctx, const struct hlsl_type *type)
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
-struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, unsigned int modifiers)
|
||
|
+struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, uint32_t modifiers)
|
||
|
{
|
||
|
struct vkd3d_string_buffer *string;
|
||
|
|
||
|
@@ -2432,7 +2447,7 @@ const char *debug_hlsl_writemask(unsigned int writemask)
|
||
|
return vkd3d_dbg_sprintf(".%s", string);
|
||
|
}
|
||
|
|
||
|
-const char *debug_hlsl_swizzle(unsigned int swizzle, unsigned int size)
|
||
|
+const char *debug_hlsl_swizzle(uint32_t swizzle, unsigned int size)
|
||
|
{
|
||
|
static const char components[] = {'x', 'y', 'z', 'w'};
|
||
|
char string[5];
|
||
|
@@ -3147,9 +3162,10 @@ void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function
|
||
|
rb_put(&ctx->functions, func->name, &func->entry);
|
||
|
}
|
||
|
|
||
|
-unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask)
|
||
|
+uint32_t hlsl_map_swizzle(uint32_t swizzle, unsigned int writemask)
|
||
|
{
|
||
|
- unsigned int i, ret = 0;
|
||
|
+ uint32_t ret = 0;
|
||
|
+ unsigned int i;
|
||
|
|
||
|
/* Leave replicate swizzles alone; some instructions need them. */
|
||
|
if (swizzle == HLSL_SWIZZLE(X, X, X, X)
|
||
|
@@ -3169,7 +3185,7 @@ unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask)
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
-unsigned int hlsl_swizzle_from_writemask(unsigned int writemask)
|
||
|
+uint32_t hlsl_swizzle_from_writemask(unsigned int writemask)
|
||
|
{
|
||
|
static const unsigned int swizzles[16] =
|
||
|
{
|
||
|
@@ -3210,9 +3226,10 @@ unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second)
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
-unsigned int hlsl_combine_swizzles(unsigned int first, unsigned int second, unsigned int dim)
|
||
|
+uint32_t hlsl_combine_swizzles(uint32_t first, uint32_t second, unsigned int dim)
|
||
|
{
|
||
|
- unsigned int ret = 0, i;
|
||
|
+ uint32_t ret = 0;
|
||
|
+ unsigned int i;
|
||
|
for (i = 0; i < dim; ++i)
|
||
|
{
|
||
|
unsigned int s = hlsl_swizzle_get_component(second, i);
|
||
|
@@ -3349,12 +3366,25 @@ static void declare_predefined_types(struct hlsl_ctx *ctx)
|
||
|
{"float", HLSL_CLASS_SCALAR, HLSL_TYPE_FLOAT, 1, 1},
|
||
|
{"vector", HLSL_CLASS_VECTOR, HLSL_TYPE_FLOAT, 4, 1},
|
||
|
{"matrix", HLSL_CLASS_MATRIX, HLSL_TYPE_FLOAT, 4, 4},
|
||
|
+ {"fxgroup", HLSL_CLASS_OBJECT, HLSL_TYPE_EFFECT_GROUP, 1, 1},
|
||
|
{"STRING", HLSL_CLASS_OBJECT, HLSL_TYPE_STRING, 1, 1},
|
||
|
{"TEXTURE", HLSL_CLASS_OBJECT, HLSL_TYPE_TEXTURE, 1, 1},
|
||
|
{"PIXELSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_PIXELSHADER, 1, 1},
|
||
|
{"VERTEXSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_VERTEXSHADER, 1, 1},
|
||
|
};
|
||
|
|
||
|
+ static const struct
|
||
|
+ {
|
||
|
+ char *name;
|
||
|
+ unsigned int version;
|
||
|
+ }
|
||
|
+ technique_types[] =
|
||
|
+ {
|
||
|
+ {"technique", 9},
|
||
|
+ {"technique10", 10},
|
||
|
+ {"technique11", 11},
|
||
|
+ };
|
||
|
+
|
||
|
for (bt = 0; bt <= HLSL_TYPE_LAST_SCALAR; ++bt)
|
||
|
{
|
||
|
for (y = 1; y <= 4; ++y)
|
||
|
@@ -3459,6 +3489,13 @@ static void declare_predefined_types(struct hlsl_ctx *ctx)
|
||
|
effect_types[i].base_type, effect_types[i].dimx, effect_types[i].dimy);
|
||
|
hlsl_scope_add_type(ctx->globals, type);
|
||
|
}
|
||
|
+
|
||
|
+ for (i = 0; i < ARRAY_SIZE(technique_types); ++i)
|
||
|
+ {
|
||
|
+ type = hlsl_new_type(ctx, technique_types[i].name, HLSL_CLASS_OBJECT, HLSL_TYPE_TECHNIQUE, 1, 1);
|
||
|
+ type->e.version = technique_types[i].version;
|
||
|
+ hlsl_scope_add_type(ctx->globals, type);
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info,
|
||
|
@@ -3594,7 +3631,13 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d
|
||
|
return VKD3D_ERROR_NOT_IMPLEMENTED;
|
||
|
}
|
||
|
|
||
|
- if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3)
|
||
|
+ if (compile_info->target_type != VKD3D_SHADER_TARGET_FX && profile->type == VKD3D_SHADER_TYPE_EFFECT)
|
||
|
+ {
|
||
|
+ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE,
|
||
|
+ "The '%s' target profile is only compatible with the 'fx' target type.", profile->name);
|
||
|
+ return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
+ }
|
||
|
+ else 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,
|
||
|
"The '%s' target profile is incompatible with the 'd3dbc' target type.", profile->name);
|
||
|
@@ -3606,6 +3649,12 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d
|
||
|
"The '%s' target profile is incompatible with the 'dxbc-tpf' target type.", profile->name);
|
||
|
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
}
|
||
|
+ else if (compile_info->target_type == VKD3D_SHADER_TARGET_FX && profile->type != VKD3D_SHADER_TYPE_EFFECT)
|
||
|
+ {
|
||
|
+ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE,
|
||
|
+ "The '%s' target profile is incompatible with the 'fx' target type.", profile->name);
|
||
|
+ return VKD3D_ERROR_INVALID_ARGUMENT;
|
||
|
+ }
|
||
|
|
||
|
if (!hlsl_ctx_init(&ctx, compile_info, profile, message_context))
|
||
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
||
|
@@ -3630,6 +3679,14 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d
|
||
|
return VKD3D_ERROR_NOT_IMPLEMENTED;
|
||
|
}
|
||
|
|
||
|
+ if (ctx.profile->type == VKD3D_SHADER_TYPE_EFFECT)
|
||
|
+ {
|
||
|
+ ret = hlsl_emit_effect_binary(&ctx, out);
|
||
|
+
|
||
|
+ hlsl_ctx_cleanup(&ctx);
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
+
|
||
|
if ((func = hlsl_get_function(&ctx, entry_point)))
|
||
|
{
|
||
|
LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry)
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
||
|
index ca75a1936f1..8bc98b99e8a 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h
|
||
|
@@ -65,7 +65,7 @@
|
||
|
#define HLSL_SWIZZLE_MASK (0x3u)
|
||
|
#define HLSL_SWIZZLE_SHIFT(idx) (2u * (idx))
|
||
|
|
||
|
-static inline unsigned int hlsl_swizzle_get_component(unsigned int swizzle, unsigned int idx)
|
||
|
+static inline unsigned int hlsl_swizzle_get_component(uint32_t swizzle, unsigned int idx)
|
||
|
{
|
||
|
return (swizzle >> HLSL_SWIZZLE_SHIFT(idx)) & HLSL_SWIZZLE_MASK;
|
||
|
}
|
||
|
@@ -95,6 +95,8 @@ enum hlsl_base_type
|
||
|
HLSL_TYPE_UAV,
|
||
|
HLSL_TYPE_PIXELSHADER,
|
||
|
HLSL_TYPE_VERTEXSHADER,
|
||
|
+ HLSL_TYPE_TECHNIQUE,
|
||
|
+ HLSL_TYPE_EFFECT_GROUP,
|
||
|
HLSL_TYPE_STRING,
|
||
|
HLSL_TYPE_VOID,
|
||
|
};
|
||
|
@@ -138,8 +140,10 @@ struct hlsl_type
|
||
|
struct rb_entry scope_entry;
|
||
|
|
||
|
enum hlsl_type_class class;
|
||
|
- /* If type is <= HLSL_CLASS_LAST_NUMERIC, then base_type is <= HLSL_TYPE_LAST_SCALAR.
|
||
|
- * If type is HLSL_CLASS_OBJECT, then base_type is > HLSL_TYPE_LAST_SCALAR.
|
||
|
+ /* If class is <= HLSL_CLASS_LAST_NUMERIC, then base_type is <= HLSL_TYPE_LAST_SCALAR.
|
||
|
+ * If class is HLSL_CLASS_OBJECT, then base_type is > HLSL_TYPE_LAST_SCALAR.
|
||
|
+ * If class is HLSL_CLASS_OBJECT and base_type is HLSL_TYPE_TECHNIQUE, additional version
|
||
|
+ * field is used to distinguish between technique types.
|
||
|
* Otherwise, base_type is not used. */
|
||
|
enum hlsl_base_type base_type;
|
||
|
|
||
|
@@ -155,7 +159,7 @@ struct hlsl_type
|
||
|
/* Bitfield for storing type modifiers, subset of HLSL_TYPE_MODIFIERS_MASK.
|
||
|
* Modifiers that don't fall inside this mask are to be stored in the variable in
|
||
|
* hlsl_ir_var.modifiers, or in the struct field in hlsl_ir_field.modifiers. */
|
||
|
- unsigned int modifiers;
|
||
|
+ uint32_t modifiers;
|
||
|
/* Size of the type values on each dimension. For non-numeric types, they are set for the
|
||
|
* convenience of the sm1/sm4 backends.
|
||
|
* If type is HLSL_CLASS_SCALAR, then both dimx = 1 and dimy = 1.
|
||
|
@@ -191,6 +195,8 @@ struct hlsl_type
|
||
|
/* Format of the data contained within the type if the base_type is HLSL_TYPE_TEXTURE or
|
||
|
* HLSL_TYPE_UAV. */
|
||
|
struct hlsl_type *resource_format;
|
||
|
+ /* Additional field to distinguish object types. Currently used only for technique types. */
|
||
|
+ unsigned int version;
|
||
|
} e;
|
||
|
|
||
|
/* Number of numeric register components used by one value of this type, for each regset.
|
||
|
@@ -234,7 +240,7 @@ struct hlsl_struct_field
|
||
|
/* Bitfield for storing modifiers that are not in HLSL_TYPE_MODIFIERS_MASK (these are stored in
|
||
|
* type->modifiers instead) and that also are specific to the field and not the whole variable.
|
||
|
* In particular, interpolation modifiers. */
|
||
|
- unsigned int storage_modifiers;
|
||
|
+ uint32_t storage_modifiers;
|
||
|
/* Offset of the field within the type it belongs to, in register components, for each regset. */
|
||
|
unsigned int reg_offset[HLSL_REGSET_LAST + 1];
|
||
|
|
||
|
@@ -392,7 +398,7 @@ struct hlsl_ir_var
|
||
|
/* Buffer where the variable's value is stored, in case it is uniform. */
|
||
|
struct hlsl_buffer *buffer;
|
||
|
/* Bitfield for storage modifiers (type modifiers are stored in data_type->modifiers). */
|
||
|
- unsigned int storage_modifiers;
|
||
|
+ uint32_t storage_modifiers;
|
||
|
/* Optional reservations of registers and/or offsets for variables within constant buffers. */
|
||
|
struct hlsl_reg_reservation reg_reservation;
|
||
|
|
||
|
@@ -400,6 +406,8 @@ struct hlsl_ir_var
|
||
|
struct list scope_entry;
|
||
|
/* Item entry in hlsl_ctx.extern_vars, if the variable is extern. */
|
||
|
struct list extern_entry;
|
||
|
+ /* Scope that variable itself defines, used to provide a container for techniques and passes. */
|
||
|
+ struct hlsl_scope *scope;
|
||
|
|
||
|
/* Indexes of the IR instructions where the variable is first written and last read (liveness
|
||
|
* range). The IR instructions are numerated starting from 2, because 0 means unused, and 1
|
||
|
@@ -622,7 +630,7 @@ struct hlsl_ir_swizzle
|
||
|
{
|
||
|
struct hlsl_ir_node node;
|
||
|
struct hlsl_src val;
|
||
|
- DWORD swizzle;
|
||
|
+ uint32_t swizzle;
|
||
|
};
|
||
|
|
||
|
struct hlsl_ir_index
|
||
|
@@ -1160,6 +1168,7 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl
|
||
|
|
||
|
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);
|
||
|
+int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out);
|
||
|
|
||
|
bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *chain);
|
||
|
bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struct hlsl_deref *other);
|
||
|
@@ -1250,7 +1259,7 @@ struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct
|
||
|
struct hlsl_ir_node *coords, struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc);
|
||
|
struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name,
|
||
|
struct hlsl_struct_field *fields, size_t field_count);
|
||
|
-struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned int components,
|
||
|
+struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int components,
|
||
|
struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc);
|
||
|
struct hlsl_ir_var *hlsl_new_synthetic_var(struct hlsl_ctx *ctx, const char *template,
|
||
|
struct hlsl_type *type, const struct vkd3d_shader_location *loc);
|
||
|
@@ -1264,7 +1273,7 @@ struct hlsl_ir_node *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n
|
||
|
struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg,
|
||
|
const struct vkd3d_shader_location *loc);
|
||
|
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 vkd3d_shader_location *loc, const struct hlsl_semantic *semantic, uint32_t 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);
|
||
|
@@ -1286,7 +1295,7 @@ void hlsl_pop_scope(struct hlsl_ctx *ctx);
|
||
|
bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type);
|
||
|
|
||
|
struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old,
|
||
|
- unsigned int default_majority, unsigned int modifiers);
|
||
|
+ unsigned int default_majority, uint32_t modifiers);
|
||
|
unsigned int hlsl_type_component_count(const struct hlsl_type *type);
|
||
|
unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type, enum hlsl_regset regset);
|
||
|
struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type,
|
||
|
@@ -1304,10 +1313,10 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2
|
||
|
const struct hlsl_type *hlsl_get_multiarray_element_type(const struct hlsl_type *type);
|
||
|
unsigned int hlsl_get_multiarray_size(const struct hlsl_type *type);
|
||
|
|
||
|
-unsigned int hlsl_combine_swizzles(unsigned int first, unsigned int second, unsigned int dim);
|
||
|
+uint32_t hlsl_combine_swizzles(uint32_t first, uint32_t second, unsigned int dim);
|
||
|
unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second);
|
||
|
-unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask);
|
||
|
-unsigned int hlsl_swizzle_from_writemask(unsigned int writemask);
|
||
|
+uint32_t hlsl_map_swizzle(uint32_t swizzle, unsigned int writemask);
|
||
|
+uint32_t hlsl_swizzle_from_writemask(unsigned int writemask);
|
||
|
|
||
|
struct hlsl_type *hlsl_deref_get_type(struct hlsl_ctx *ctx, const struct hlsl_deref *deref);
|
||
|
enum hlsl_regset hlsl_deref_get_regset(struct hlsl_ctx *ctx, const struct hlsl_deref *deref);
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l
|
||
|
index fe838750747..6cef0e02eff 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l
|
||
|
@@ -89,6 +89,7 @@ else {return KW_ELSE; }
|
||
|
extern {return KW_EXTERN; }
|
||
|
false {return KW_FALSE; }
|
||
|
for {return KW_FOR; }
|
||
|
+fxgroup {return KW_FXGROUP; }
|
||
|
GeometryShader {return KW_GEOMETRYSHADER; }
|
||
|
groupshared {return KW_GROUPSHARED; }
|
||
|
if {return KW_IF; }
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
||
|
index ed053f16312..b11cbde26f1 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y
|
||
|
@@ -40,7 +40,7 @@ struct parse_parameter
|
||
|
const char *name;
|
||
|
struct hlsl_semantic semantic;
|
||
|
struct hlsl_reg_reservation reg_reservation;
|
||
|
- unsigned int modifiers;
|
||
|
+ uint32_t modifiers;
|
||
|
};
|
||
|
|
||
|
struct parse_colon_attribute
|
||
|
@@ -75,7 +75,7 @@ struct parse_variable_def
|
||
|
struct parse_initializer initializer;
|
||
|
|
||
|
struct hlsl_type *basic_type;
|
||
|
- unsigned int modifiers;
|
||
|
+ uint32_t modifiers;
|
||
|
struct vkd3d_shader_location modifiers_loc;
|
||
|
};
|
||
|
|
||
|
@@ -405,7 +405,7 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct
|
||
|
return add_cast(ctx, block, node, dst_type, loc);
|
||
|
}
|
||
|
|
||
|
-static DWORD add_modifiers(struct hlsl_ctx *ctx, DWORD modifiers, DWORD mod,
|
||
|
+static uint32_t add_modifiers(struct hlsl_ctx *ctx, uint32_t modifiers, uint32_t mod,
|
||
|
const struct vkd3d_shader_location *loc)
|
||
|
{
|
||
|
if (modifiers & mod)
|
||
|
@@ -868,7 +868,7 @@ static const struct hlsl_struct_field *get_struct_field(const struct hlsl_struct
|
||
|
}
|
||
|
|
||
|
static struct hlsl_type *apply_type_modifiers(struct hlsl_ctx *ctx, struct hlsl_type *type,
|
||
|
- unsigned int *modifiers, bool force_majority, const struct vkd3d_shader_location *loc)
|
||
|
+ uint32_t *modifiers, bool force_majority, const struct vkd3d_shader_location *loc)
|
||
|
{
|
||
|
unsigned int default_majority = 0;
|
||
|
struct hlsl_type *new_type;
|
||
|
@@ -926,7 +926,7 @@ static bool shader_profile_version_lt(const struct hlsl_ctx *ctx, unsigned int m
|
||
|
}
|
||
|
|
||
|
static bool gen_struct_fields(struct hlsl_ctx *ctx, struct parse_fields *fields,
|
||
|
- struct hlsl_type *type, unsigned int modifiers, struct list *defs)
|
||
|
+ struct hlsl_type *type, uint32_t modifiers, struct list *defs)
|
||
|
{
|
||
|
struct parse_variable_def *v, *v_next;
|
||
|
size_t i = 0;
|
||
|
@@ -1019,7 +1019,7 @@ static bool add_typedef(struct hlsl_ctx *ctx, struct hlsl_type *const orig_type,
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
- unsigned int var_modifiers = 0;
|
||
|
+ uint32_t var_modifiers = 0;
|
||
|
|
||
|
if (!(type = apply_type_modifiers(ctx, orig_type, &var_modifiers, true, &v->loc)))
|
||
|
{
|
||
|
@@ -1096,6 +1096,56 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
+static bool add_technique(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope,
|
||
|
+ const char *typename, const struct vkd3d_shader_location *loc)
|
||
|
+{
|
||
|
+ struct hlsl_ir_var *var;
|
||
|
+ struct hlsl_type *type;
|
||
|
+
|
||
|
+ type = hlsl_get_type(ctx->globals, typename, false, false);
|
||
|
+ if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL)))
|
||
|
+ return false;
|
||
|
+ var->scope = scope;
|
||
|
+
|
||
|
+ if (!hlsl_add_var(ctx, var, false))
|
||
|
+ {
|
||
|
+ struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name);
|
||
|
+
|
||
|
+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
|
||
|
+ "Identifier \"%s\" was already declared in this scope.", var->name);
|
||
|
+ hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name);
|
||
|
+ hlsl_free_var(var);
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
+static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope,
|
||
|
+ const struct vkd3d_shader_location *loc)
|
||
|
+{
|
||
|
+ struct hlsl_ir_var *var;
|
||
|
+ struct hlsl_type *type;
|
||
|
+
|
||
|
+ type = hlsl_get_type(ctx->globals, "fxgroup", false, false);
|
||
|
+ if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL)))
|
||
|
+ return false;
|
||
|
+ var->scope = scope;
|
||
|
+
|
||
|
+ if (!hlsl_add_var(ctx, var, false))
|
||
|
+ {
|
||
|
+ struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name);
|
||
|
+
|
||
|
+ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
|
||
|
+ "Identifier \"%s\" was already declared in this scope.", var->name);
|
||
|
+ hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name);
|
||
|
+ hlsl_free_var(var);
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ return true;
|
||
|
+}
|
||
|
+
|
||
|
static struct hlsl_reg_reservation parse_reg_reservation(const char *reg_string)
|
||
|
{
|
||
|
struct hlsl_reg_reservation reservation = {0};
|
||
|
@@ -1717,7 +1767,7 @@ static enum hlsl_ir_expr_op op_from_assignment(enum parse_assign_op op)
|
||
|
return ops[op];
|
||
|
}
|
||
|
|
||
|
-static bool invert_swizzle(unsigned int *swizzle, unsigned int *writemask, unsigned int *ret_width)
|
||
|
+static bool invert_swizzle(uint32_t *swizzle, unsigned int *writemask, unsigned int *ret_width)
|
||
|
{
|
||
|
unsigned int i, j, bit = 0, inverted = 0, width, new_writemask = 0, new_swizzle = 0;
|
||
|
|
||
|
@@ -1791,8 +1841,9 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo
|
||
|
else if (lhs->type == HLSL_IR_SWIZZLE)
|
||
|
{
|
||
|
struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(lhs);
|
||
|
- unsigned int width, s = swizzle->swizzle;
|
||
|
struct hlsl_ir_node *new_swizzle;
|
||
|
+ uint32_t s = swizzle->swizzle;
|
||
|
+ unsigned int width;
|
||
|
|
||
|
if (lhs->data_type->class == HLSL_CLASS_MATRIX)
|
||
|
hlsl_fixme(ctx, &lhs->loc, "Matrix assignment with a writemask.");
|
||
|
@@ -4844,7 +4895,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls
|
||
|
FLOAT floatval;
|
||
|
bool boolval;
|
||
|
char *name;
|
||
|
- DWORD modifiers;
|
||
|
+ uint32_t modifiers;
|
||
|
struct hlsl_ir_node *instr;
|
||
|
struct hlsl_block *block;
|
||
|
struct list *list;
|
||
|
@@ -4887,6 +4938,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls
|
||
|
%token KW_EXTERN
|
||
|
%token KW_FALSE
|
||
|
%token KW_FOR
|
||
|
+%token KW_FXGROUP
|
||
|
%token KW_GEOMETRYSHADER
|
||
|
%token KW_GROUPSHARED
|
||
|
%token KW_IF
|
||
|
@@ -5051,7 +5103,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls
|
||
|
|
||
|
%type <name> any_identifier
|
||
|
%type <name> var_identifier
|
||
|
-%type <name> technique_name
|
||
|
+%type <name> name_opt
|
||
|
|
||
|
%type <parameter> parameter
|
||
|
|
||
|
@@ -5093,50 +5145,88 @@ hlsl_prog:
|
||
|
destroy_block($2);
|
||
|
}
|
||
|
| hlsl_prog preproc_directive
|
||
|
- | hlsl_prog technique
|
||
|
+ | hlsl_prog global_technique
|
||
|
+ | hlsl_prog effect_group
|
||
|
| hlsl_prog ';'
|
||
|
|
||
|
-technique_name:
|
||
|
+name_opt:
|
||
|
%empty
|
||
|
{
|
||
|
$$ = NULL;
|
||
|
}
|
||
|
| any_identifier
|
||
|
|
||
|
+pass:
|
||
|
+ KW_PASS name_opt '{' '}'
|
||
|
+
|
||
|
pass_list:
|
||
|
- %empty
|
||
|
+ pass
|
||
|
+ | pass_list pass
|
||
|
+
|
||
|
+passes:
|
||
|
+ scope_start
|
||
|
+ | scope_start pass_list
|
||
|
|
||
|
technique9:
|
||
|
- KW_TECHNIQUE technique_name '{' pass_list '}'
|
||
|
+ KW_TECHNIQUE name_opt '{' passes '}'
|
||
|
{
|
||
|
- hlsl_fixme(ctx, &@$, "Unsupported \'technique\' declaration.");
|
||
|
+ struct hlsl_scope *scope = ctx->cur_scope;
|
||
|
+ hlsl_pop_scope(ctx);
|
||
|
+
|
||
|
+ if (!add_technique(ctx, $2, scope, "technique", &@1))
|
||
|
+ YYABORT;
|
||
|
}
|
||
|
|
||
|
technique10:
|
||
|
- KW_TECHNIQUE10 technique_name '{' pass_list '}'
|
||
|
+ KW_TECHNIQUE10 name_opt '{' passes '}'
|
||
|
{
|
||
|
+ struct hlsl_scope *scope = ctx->cur_scope;
|
||
|
+ hlsl_pop_scope(ctx);
|
||
|
+
|
||
|
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.");
|
||
|
+ if (!add_technique(ctx, $2, scope, "technique10", &@1))
|
||
|
+ YYABORT;
|
||
|
}
|
||
|
|
||
|
technique11:
|
||
|
- KW_TECHNIQUE11 technique_name '{' pass_list '}'
|
||
|
+ KW_TECHNIQUE11 name_opt '{' passes '}'
|
||
|
{
|
||
|
+ struct hlsl_scope *scope = ctx->cur_scope;
|
||
|
+ hlsl_pop_scope(ctx);
|
||
|
+
|
||
|
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.");
|
||
|
+ if (!add_technique(ctx, $2, scope, "technique11", &@1))
|
||
|
+ YYABORT;
|
||
|
}
|
||
|
|
||
|
-technique:
|
||
|
+global_technique:
|
||
|
technique9
|
||
|
| technique10
|
||
|
| technique11
|
||
|
|
||
|
+group_technique:
|
||
|
+ technique10
|
||
|
+ | technique11
|
||
|
+
|
||
|
+group_techniques:
|
||
|
+ group_technique
|
||
|
+ | group_techniques group_technique
|
||
|
+
|
||
|
+effect_group:
|
||
|
+ KW_FXGROUP any_identifier '{' scope_start group_techniques '}'
|
||
|
+ {
|
||
|
+ struct hlsl_scope *scope = ctx->cur_scope;
|
||
|
+ hlsl_pop_scope(ctx);
|
||
|
+ if (!(add_effect_group(ctx, $2, scope, &@2)))
|
||
|
+ YYABORT;
|
||
|
+ }
|
||
|
+
|
||
|
buffer_declaration:
|
||
|
buffer_type any_identifier colon_attribute
|
||
|
{
|
||
|
@@ -5282,7 +5372,7 @@ field:
|
||
|
var_modifiers field_type variables_def ';'
|
||
|
{
|
||
|
struct hlsl_type *type;
|
||
|
- unsigned int modifiers = $1;
|
||
|
+ uint32_t modifiers = $1;
|
||
|
|
||
|
if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1)))
|
||
|
YYABORT;
|
||
|
@@ -5435,7 +5525,7 @@ func_prototype_no_attrs:
|
||
|
/* var_modifiers is necessary to avoid shift/reduce conflicts. */
|
||
|
var_modifiers type var_identifier '(' parameters ')' colon_attribute
|
||
|
{
|
||
|
- unsigned int modifiers = $1;
|
||
|
+ uint32_t modifiers = $1;
|
||
|
struct hlsl_ir_var *var;
|
||
|
struct hlsl_type *type;
|
||
|
|
||
|
@@ -5709,7 +5799,7 @@ param_list:
|
||
|
parameter:
|
||
|
var_modifiers type_no_void any_identifier arrays colon_attribute
|
||
|
{
|
||
|
- unsigned int modifiers = $1;
|
||
|
+ uint32_t modifiers = $1;
|
||
|
struct hlsl_type *type;
|
||
|
unsigned int i;
|
||
|
|
||
|
@@ -6023,7 +6113,7 @@ typedef:
|
||
|
KW_TYPEDEF var_modifiers typedef_type type_specs ';'
|
||
|
{
|
||
|
struct parse_variable_def *v, *v_next;
|
||
|
- unsigned int modifiers = $2;
|
||
|
+ uint32_t modifiers = $2;
|
||
|
struct hlsl_type *type;
|
||
|
|
||
|
if (!(type = apply_type_modifiers(ctx, $3, &modifiers, false, &@2)))
|
||
|
@@ -6160,7 +6250,7 @@ variable_def:
|
||
|
variable_def_typed:
|
||
|
var_modifiers struct_spec variable_def
|
||
|
{
|
||
|
- unsigned int modifiers = $1;
|
||
|
+ uint32_t modifiers = $1;
|
||
|
struct hlsl_type *type;
|
||
|
|
||
|
if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1)))
|
||
|
@@ -6175,7 +6265,7 @@ variable_def_typed:
|
||
|
}
|
||
|
| var_modifiers type variable_def
|
||
|
{
|
||
|
- unsigned int modifiers = $1;
|
||
|
+ uint32_t modifiers = $1;
|
||
|
struct hlsl_type *type;
|
||
|
|
||
|
if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1)))
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
||
|
index 88cbef61d5f..d37bef15cce 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c
|
||
|
@@ -32,6 +32,11 @@ static struct hlsl_ir_node *new_offset_from_path_index(struct hlsl_ctx *ctx, str
|
||
|
switch (type->class)
|
||
|
{
|
||
|
case HLSL_CLASS_VECTOR:
|
||
|
+ if (idx->type != HLSL_IR_CONSTANT)
|
||
|
+ {
|
||
|
+ hlsl_fixme(ctx, &idx->loc, "Non-constant vector addressing.");
|
||
|
+ break;
|
||
|
+ }
|
||
|
*offset_component += hlsl_ir_constant(idx)->value.u[0].u;
|
||
|
break;
|
||
|
|
||
|
@@ -263,7 +268,7 @@ static bool types_are_semantic_equivalent(struct hlsl_ctx *ctx, const struct hls
|
||
|
}
|
||
|
|
||
|
static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *var,
|
||
|
- struct hlsl_type *type, unsigned int modifiers, struct hlsl_semantic *semantic,
|
||
|
+ struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic,
|
||
|
uint32_t index, bool output, const struct vkd3d_shader_location *loc)
|
||
|
{
|
||
|
struct hlsl_semantic new_semantic;
|
||
|
@@ -331,7 +336,7 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir
|
||
|
}
|
||
|
|
||
|
static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *lhs,
|
||
|
- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index)
|
||
|
+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index)
|
||
|
{
|
||
|
struct hlsl_type *type = lhs->node.data_type, *vector_type_src, *vector_type_dst;
|
||
|
struct vkd3d_shader_location *loc = &lhs->node.loc;
|
||
|
@@ -395,7 +400,7 @@ static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, s
|
||
|
}
|
||
|
|
||
|
static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *lhs,
|
||
|
- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index)
|
||
|
+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index)
|
||
|
{
|
||
|
struct vkd3d_shader_location *loc = &lhs->node.loc;
|
||
|
struct hlsl_type *type = lhs->node.data_type;
|
||
|
@@ -411,7 +416,7 @@ static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *
|
||
|
|
||
|
for (i = 0; i < hlsl_type_element_count(type); ++i)
|
||
|
{
|
||
|
- unsigned int element_modifiers = modifiers;
|
||
|
+ uint32_t element_modifiers = modifiers;
|
||
|
|
||
|
if (type->class == HLSL_CLASS_ARRAY)
|
||
|
{
|
||
|
@@ -473,7 +478,7 @@ static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_block *bloc
|
||
|
}
|
||
|
|
||
|
static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *rhs,
|
||
|
- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index)
|
||
|
+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index)
|
||
|
{
|
||
|
struct hlsl_type *type = rhs->node.data_type, *vector_type;
|
||
|
struct vkd3d_shader_location *loc = &rhs->node.loc;
|
||
|
@@ -529,7 +534,7 @@ static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, s
|
||
|
}
|
||
|
|
||
|
static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_load *rhs,
|
||
|
- unsigned int modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index)
|
||
|
+ uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index)
|
||
|
{
|
||
|
struct vkd3d_shader_location *loc = &rhs->node.loc;
|
||
|
struct hlsl_type *type = rhs->node.data_type;
|
||
|
@@ -1519,7 +1524,7 @@ static void copy_propagation_set_value(struct hlsl_ctx *ctx, struct copy_propaga
|
||
|
|
||
|
static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx,
|
||
|
const struct copy_propagation_state *state, const struct hlsl_ir_load *load,
|
||
|
- unsigned int swizzle, struct hlsl_ir_node *instr)
|
||
|
+ uint32_t swizzle, struct hlsl_ir_node *instr)
|
||
|
{
|
||
|
const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type);
|
||
|
const struct hlsl_deref *deref = &load->src;
|
||
|
@@ -1527,7 +1532,7 @@ static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx,
|
||
|
struct hlsl_ir_node *new_instr = NULL;
|
||
|
unsigned int time = load->node.index;
|
||
|
unsigned int start, count, i;
|
||
|
- unsigned int ret_swizzle = 0;
|
||
|
+ uint32_t ret_swizzle = 0;
|
||
|
|
||
|
if (!hlsl_component_index_range_from_deref(ctx, deref, &start, &count))
|
||
|
return false;
|
||
|
@@ -1573,7 +1578,7 @@ static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx,
|
||
|
|
||
|
static bool copy_propagation_replace_with_constant_vector(struct hlsl_ctx *ctx,
|
||
|
const struct copy_propagation_state *state, const struct hlsl_ir_load *load,
|
||
|
- unsigned int swizzle, struct hlsl_ir_node *instr)
|
||
|
+ uint32_t swizzle, struct hlsl_ir_node *instr)
|
||
|
{
|
||
|
const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type);
|
||
|
const struct hlsl_deref *deref = &load->src;
|
||
|
@@ -2239,7 +2244,7 @@ static bool fold_swizzle_chains(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr
|
||
|
if (next_instr->type == HLSL_IR_SWIZZLE)
|
||
|
{
|
||
|
struct hlsl_ir_node *new_swizzle;
|
||
|
- unsigned int combined_swizzle;
|
||
|
+ uint32_t combined_swizzle;
|
||
|
|
||
|
combined_swizzle = hlsl_combine_swizzles(hlsl_ir_swizzle(next_instr)->swizzle,
|
||
|
swizzle->swizzle, instr->data_type->dimx);
|
||
|
@@ -2478,6 +2483,38 @@ static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
+static bool validate_nonconstant_vector_store_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
|
||
|
+{
|
||
|
+ struct hlsl_ir_node *idx;
|
||
|
+ struct hlsl_deref *deref;
|
||
|
+ struct hlsl_type *type;
|
||
|
+ unsigned int i;
|
||
|
+
|
||
|
+ if (instr->type != HLSL_IR_STORE)
|
||
|
+ return false;
|
||
|
+
|
||
|
+ deref = &hlsl_ir_store(instr)->lhs;
|
||
|
+ assert(deref->var);
|
||
|
+
|
||
|
+ if (deref->path_len == 0)
|
||
|
+ return false;
|
||
|
+
|
||
|
+ type = deref->var->data_type;
|
||
|
+ for (i = 0; i < deref->path_len - 1; ++i)
|
||
|
+ type = hlsl_get_element_type_from_path_index(ctx, type, deref->path[i].node);
|
||
|
+
|
||
|
+ idx = deref->path[deref->path_len - 1].node;
|
||
|
+
|
||
|
+ if (type->class == HLSL_CLASS_VECTOR && idx->type != HLSL_IR_CONSTANT)
|
||
|
+ {
|
||
|
+ /* We should turn this into an hlsl_error after we implement unrolling, because if we get
|
||
|
+ * here after that, it means that the HLSL is invalid. */
|
||
|
+ hlsl_fixme(ctx, &instr->loc, "Non-constant vector addressing on store. Unrolling may be missing.");
|
||
|
+ }
|
||
|
+
|
||
|
+ return false;
|
||
|
+}
|
||
|
+
|
||
|
/* Lower combined samples and sampler variables to synthesized separated textures and samplers.
|
||
|
* That is, translate SM1-style samples in the source to SM4-style samples in the bytecode. */
|
||
|
static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
|
||
|
@@ -3145,7 +3182,7 @@ static bool lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru
|
||
|
|
||
|
for (i = 0; i < dimx; ++i)
|
||
|
{
|
||
|
- unsigned int s = hlsl_swizzle_from_writemask(1 << i);
|
||
|
+ uint32_t s = hlsl_swizzle_from_writemask(1 << i);
|
||
|
|
||
|
if (!(comps[i] = hlsl_new_swizzle(ctx, s, 1, mult, &instr->loc)))
|
||
|
return false;
|
||
|
@@ -4969,6 +5006,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
|
||
|
lower_ir(ctx, lower_abs, body);
|
||
|
}
|
||
|
|
||
|
+ lower_ir(ctx, validate_nonconstant_vector_store_derefs, body);
|
||
|
+
|
||
|
/* 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));
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
||
|
index d38b3c39712..28c7d158452 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/ir.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c
|
||
|
@@ -492,7 +492,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i
|
||
|
if (shader_instruction_is_dcl(ins))
|
||
|
break;
|
||
|
for (j = 0; j < ins->dst_count; ++j)
|
||
|
- shader_dst_param_normalise_outpointid((struct vkd3d_shader_dst_param *)&ins->dst[j], &normaliser);
|
||
|
+ shader_dst_param_normalise_outpointid(&ins->dst[j], &normaliser);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
@@ -533,6 +533,7 @@ struct io_normaliser
|
||
|
{
|
||
|
struct vkd3d_shader_instruction_array instructions;
|
||
|
enum vkd3d_shader_type shader_type;
|
||
|
+ uint8_t major;
|
||
|
struct shader_signature *input_signature;
|
||
|
struct shader_signature *output_signature;
|
||
|
struct shader_signature *patch_constant_signature;
|
||
|
@@ -867,34 +868,65 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par
|
||
|
const struct shader_signature *signature;
|
||
|
const struct signature_element *e;
|
||
|
|
||
|
- if ((reg->type == VKD3DSPR_OUTPUT && io_normaliser_is_in_fork_or_join_phase(normaliser))
|
||
|
- || reg->type == VKD3DSPR_PATCHCONST)
|
||
|
- {
|
||
|
- signature = normaliser->patch_constant_signature;
|
||
|
- /* Convert patch constant outputs to the patch constant register type to avoid the need
|
||
|
- * to convert compiler symbols when accessed as inputs in a later stage. */
|
||
|
- reg->type = VKD3DSPR_PATCHCONST;
|
||
|
- dcl_params = normaliser->pc_dcl_params;
|
||
|
- }
|
||
|
- else if (reg->type == VKD3DSPR_OUTPUT || dst_param->reg.type == VKD3DSPR_COLOROUT)
|
||
|
- {
|
||
|
- signature = normaliser->output_signature;
|
||
|
- reg->type = VKD3DSPR_OUTPUT;
|
||
|
- dcl_params = normaliser->output_dcl_params;
|
||
|
- }
|
||
|
- else if (dst_param->reg.type == VKD3DSPR_INCONTROLPOINT || dst_param->reg.type == VKD3DSPR_INPUT)
|
||
|
- {
|
||
|
- signature = normaliser->input_signature;
|
||
|
- reg->type = VKD3DSPR_INPUT;
|
||
|
- dcl_params = normaliser->input_dcl_params;
|
||
|
- }
|
||
|
- else
|
||
|
+ switch (reg->type)
|
||
|
{
|
||
|
- return true;
|
||
|
+ case VKD3DSPR_OUTPUT:
|
||
|
+ reg_idx = reg->idx[reg->idx_count - 1].offset;
|
||
|
+ if (io_normaliser_is_in_fork_or_join_phase(normaliser))
|
||
|
+ {
|
||
|
+ signature = normaliser->patch_constant_signature;
|
||
|
+ /* Convert patch constant outputs to the patch constant register type to avoid the need
|
||
|
+ * to convert compiler symbols when accessed as inputs in a later stage. */
|
||
|
+ reg->type = VKD3DSPR_PATCHCONST;
|
||
|
+ dcl_params = normaliser->pc_dcl_params;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ signature = normaliser->output_signature;
|
||
|
+ dcl_params = normaliser->output_dcl_params;
|
||
|
+ }
|
||
|
+ break;
|
||
|
+
|
||
|
+ case VKD3DSPR_PATCHCONST:
|
||
|
+ reg_idx = reg->idx[reg->idx_count - 1].offset;
|
||
|
+ signature = normaliser->patch_constant_signature;
|
||
|
+ dcl_params = normaliser->pc_dcl_params;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case VKD3DSPR_COLOROUT:
|
||
|
+ reg_idx = reg->idx[0].offset;
|
||
|
+ signature = normaliser->output_signature;
|
||
|
+ reg->type = VKD3DSPR_OUTPUT;
|
||
|
+ dcl_params = normaliser->output_dcl_params;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case VKD3DSPR_INCONTROLPOINT:
|
||
|
+ case VKD3DSPR_INPUT:
|
||
|
+ reg_idx = reg->idx[reg->idx_count - 1].offset;
|
||
|
+ signature = normaliser->input_signature;
|
||
|
+ reg->type = VKD3DSPR_INPUT;
|
||
|
+ dcl_params = normaliser->input_dcl_params;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case VKD3DSPR_ATTROUT:
|
||
|
+ reg_idx = SM1_COLOR_REGISTER_OFFSET + reg->idx[0].offset;
|
||
|
+ signature = normaliser->output_signature;
|
||
|
+ reg->type = VKD3DSPR_OUTPUT;
|
||
|
+ dcl_params = normaliser->output_dcl_params;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case VKD3DSPR_RASTOUT:
|
||
|
+ reg_idx = SM1_RASTOUT_REGISTER_OFFSET + reg->idx[0].offset;
|
||
|
+ signature = normaliser->output_signature;
|
||
|
+ reg->type = VKD3DSPR_OUTPUT;
|
||
|
+ dcl_params = normaliser->output_dcl_params;
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ return true;
|
||
|
}
|
||
|
|
||
|
id_idx = reg->idx_count - 1;
|
||
|
- reg_idx = reg->idx[id_idx].offset;
|
||
|
write_mask = dst_param->write_mask;
|
||
|
element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask);
|
||
|
e = &signature->elements[element_idx];
|
||
|
@@ -982,26 +1014,42 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par
|
||
|
switch (reg->type)
|
||
|
{
|
||
|
case VKD3DSPR_PATCHCONST:
|
||
|
+ reg_idx = reg->idx[reg->idx_count - 1].offset;
|
||
|
signature = normaliser->patch_constant_signature;
|
||
|
break;
|
||
|
+
|
||
|
case VKD3DSPR_INCONTROLPOINT:
|
||
|
reg->type = VKD3DSPR_INPUT;
|
||
|
/* fall through */
|
||
|
case VKD3DSPR_INPUT:
|
||
|
+ if (normaliser->major < 3 && normaliser->shader_type == VKD3D_SHADER_TYPE_PIXEL)
|
||
|
+ reg_idx = SM1_COLOR_REGISTER_OFFSET + reg->idx[0].offset;
|
||
|
+ else
|
||
|
+ reg_idx = reg->idx[reg->idx_count - 1].offset;
|
||
|
signature = normaliser->input_signature;
|
||
|
break;
|
||
|
+
|
||
|
case VKD3DSPR_OUTCONTROLPOINT:
|
||
|
reg->type = VKD3DSPR_OUTPUT;
|
||
|
/* fall through */
|
||
|
case VKD3DSPR_OUTPUT:
|
||
|
+ reg_idx = reg->idx[reg->idx_count - 1].offset;
|
||
|
signature = normaliser->output_signature;
|
||
|
break;
|
||
|
+
|
||
|
+ case VKD3DSPR_TEXTURE:
|
||
|
+ if (normaliser->shader_type != VKD3D_SHADER_TYPE_PIXEL)
|
||
|
+ return;
|
||
|
+ reg->type = VKD3DSPR_INPUT;
|
||
|
+ reg_idx = reg->idx[0].offset;
|
||
|
+ signature = normaliser->input_signature;
|
||
|
+ break;
|
||
|
+
|
||
|
default:
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
id_idx = reg->idx_count - 1;
|
||
|
- reg_idx = reg->idx[id_idx].offset;
|
||
|
write_mask = VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(src_param->swizzle, 0);
|
||
|
element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask);
|
||
|
|
||
|
@@ -1068,9 +1116,9 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi
|
||
|
if (shader_instruction_is_dcl(ins))
|
||
|
break;
|
||
|
for (i = 0; i < ins->dst_count; ++i)
|
||
|
- shader_dst_param_io_normalise((struct vkd3d_shader_dst_param *)&ins->dst[i], false, normaliser);
|
||
|
+ shader_dst_param_io_normalise(&ins->dst[i], false, normaliser);
|
||
|
for (i = 0; i < ins->src_count; ++i)
|
||
|
- shader_src_param_io_normalise((struct vkd3d_shader_src_param *)&ins->src[i], normaliser);
|
||
|
+ shader_src_param_io_normalise(&ins->src[i], normaliser);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
@@ -1084,6 +1132,7 @@ static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parse
|
||
|
|
||
|
normaliser.phase = VKD3DSIH_INVALID;
|
||
|
normaliser.shader_type = parser->shader_version.type;
|
||
|
+ normaliser.major = parser->shader_version.major;
|
||
|
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;
|
||
|
@@ -1261,7 +1310,7 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d
|
||
|
else
|
||
|
{
|
||
|
for (j = 0; j < ins->src_count; ++j)
|
||
|
- shader_register_normalise_flat_constants((struct vkd3d_shader_src_param *)&ins->src[j], &normaliser);
|
||
|
+ shader_register_normalise_flat_constants(&ins->src[j], &normaliser);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -1462,7 +1511,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
|
||
|
vkd3d_shader_trace(instructions, &parser->shader_version);
|
||
|
|
||
|
if (result >= 0 && !parser->failed)
|
||
|
- vsir_validate(parser);
|
||
|
+ result = vsir_validate(parser);
|
||
|
|
||
|
if (result >= 0 && parser->failed)
|
||
|
result = VKD3D_ERROR_INVALID_SHADER;
|
||
|
@@ -1474,10 +1523,26 @@ struct validation_context
|
||
|
{
|
||
|
struct vkd3d_shader_parser *parser;
|
||
|
size_t instruction_idx;
|
||
|
+ bool invalid_instruction_idx;
|
||
|
bool dcl_temps_found;
|
||
|
unsigned int temp_count;
|
||
|
enum vkd3d_shader_opcode phase;
|
||
|
|
||
|
+ struct validation_context_temp_data
|
||
|
+ {
|
||
|
+ enum vsir_dimension dimension;
|
||
|
+ size_t first_seen;
|
||
|
+ } *temps;
|
||
|
+
|
||
|
+ struct validation_context_ssa_data
|
||
|
+ {
|
||
|
+ enum vsir_dimension dimension;
|
||
|
+ size_t first_seen;
|
||
|
+ uint32_t write_mask;
|
||
|
+ uint32_t read_mask;
|
||
|
+ size_t first_assigned;
|
||
|
+ } *ssas;
|
||
|
+
|
||
|
enum vkd3d_shader_opcode *blocks;
|
||
|
size_t depth;
|
||
|
size_t blocks_capacity;
|
||
|
@@ -1495,8 +1560,16 @@ static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *c
|
||
|
vkd3d_string_buffer_vprintf(&buf, format, args);
|
||
|
va_end(args);
|
||
|
|
||
|
- vkd3d_shader_parser_error(ctx->parser, error, "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer);
|
||
|
- ERR("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer);
|
||
|
+ if (ctx->invalid_instruction_idx)
|
||
|
+ {
|
||
|
+ vkd3d_shader_parser_error(ctx->parser, error, "%s", buf.buffer);
|
||
|
+ ERR("VSIR validation error: %s\n", buf.buffer);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ vkd3d_shader_parser_error(ctx->parser, error, "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer);
|
||
|
+ ERR("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer);
|
||
|
+ }
|
||
|
|
||
|
vkd3d_string_buffer_cleanup(&buf);
|
||
|
}
|
||
|
@@ -1543,17 +1616,101 @@ static void vsir_validate_register(struct validation_context *ctx,
|
||
|
switch (reg->type)
|
||
|
{
|
||
|
case VKD3DSPR_TEMP:
|
||
|
+ {
|
||
|
+ struct validation_context_temp_data *data;
|
||
|
+
|
||
|
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);
|
||
|
+ break;
|
||
|
+ }
|
||
|
|
||
|
- if (reg->idx_count >= 1 && reg->idx[0].rel_addr)
|
||
|
+ if (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 >= temp_count)
|
||
|
+ if (reg->idx[0].offset >= temp_count)
|
||
|
+ {
|
||
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "TEMP register index %u exceeds the maximum count %u.",
|
||
|
reg->idx[0].offset, temp_count);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* parser->shader_desc.temp_count might be smaller then
|
||
|
+ * temp_count if the parser made a mistake; we still don't
|
||
|
+ * want to overflow the array. */
|
||
|
+ if (reg->idx[0].offset >= ctx->parser->shader_desc.temp_count)
|
||
|
+ break;
|
||
|
+ data = &ctx->temps[reg->idx[0].offset];
|
||
|
+
|
||
|
+ if (reg->dimension == VSIR_DIMENSION_NONE)
|
||
|
+ {
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension NONE for a TEMP register.");
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* TEMP registers can be scalar or vec4, provided that
|
||
|
+ * each individual register always appears with the same
|
||
|
+ * dimension. */
|
||
|
+ if (data->dimension == VSIR_DIMENSION_NONE)
|
||
|
+ {
|
||
|
+ data->dimension = reg->dimension;
|
||
|
+ data->first_seen = ctx->instruction_idx;
|
||
|
+ }
|
||
|
+ else if (data->dimension != reg->dimension)
|
||
|
+ {
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a TEMP register: "
|
||
|
+ "it has already been seen with dimension %#x at instruction %zu.",
|
||
|
+ reg->dimension, data->dimension, data->first_seen);
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ case VKD3DSPR_SSA:
|
||
|
+ {
|
||
|
+ struct validation_context_ssa_data *data;
|
||
|
+
|
||
|
+ if (reg->idx_count != 1)
|
||
|
+ {
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a SSA register.",
|
||
|
+ reg->idx_count);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (reg->idx[0].rel_addr)
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Non-NULL relative address for a SSA register.");
|
||
|
+
|
||
|
+ if (reg->idx[0].offset >= ctx->parser->shader_desc.ssa_count)
|
||
|
+ {
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "SSA register index %u exceeds the maximum count %u.",
|
||
|
+ reg->idx[0].offset, ctx->parser->shader_desc.ssa_count);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ data = &ctx->ssas[reg->idx[0].offset];
|
||
|
+
|
||
|
+ if (reg->dimension == VSIR_DIMENSION_NONE)
|
||
|
+ {
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension NONE for a SSA register.");
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* SSA registers can be scalar or vec4, provided that each
|
||
|
+ * individual register always appears with the same
|
||
|
+ * dimension. */
|
||
|
+ if (data->dimension == VSIR_DIMENSION_NONE)
|
||
|
+ {
|
||
|
+ data->dimension = reg->dimension;
|
||
|
+ data->first_seen = ctx->instruction_idx;
|
||
|
+ }
|
||
|
+ else if (data->dimension != reg->dimension)
|
||
|
+ {
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a SSA register: "
|
||
|
+ "it has already been seen with dimension %#x at instruction %zu.",
|
||
|
+ reg->dimension, data->dimension, data->first_seen);
|
||
|
+ }
|
||
|
break;
|
||
|
+ }
|
||
|
|
||
|
case VKD3DSPR_NULL:
|
||
|
if (reg->idx_count != 0)
|
||
|
@@ -1587,6 +1744,26 @@ static void vsir_validate_dst_param(struct validation_context *ctx,
|
||
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Destination has invalid write mask %#x.",
|
||
|
dst->write_mask);
|
||
|
|
||
|
+ switch (dst->reg.dimension)
|
||
|
+ {
|
||
|
+ case VSIR_DIMENSION_SCALAR:
|
||
|
+ if (dst->write_mask != VKD3DSP_WRITEMASK_0)
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Scalar destination has invalid write mask %#x.",
|
||
|
+ dst->write_mask);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case VSIR_DIMENSION_VEC4:
|
||
|
+ if (dst->write_mask == 0)
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Vec4 destination has empty write mask.");
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ if (dst->write_mask != 0)
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Destination of dimension %u has invalid write mask %#x.",
|
||
|
+ dst->reg.dimension, dst->write_mask);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
if (dst->modifiers & ~VKD3DSPDM_MASK)
|
||
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Destination has invalid modifiers %#x.",
|
||
|
dst->modifiers);
|
||
|
@@ -1606,6 +1783,23 @@ static void vsir_validate_dst_param(struct validation_context *ctx,
|
||
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT, "Destination has invalid shift %#x.",
|
||
|
dst->shift);
|
||
|
}
|
||
|
+
|
||
|
+ if (dst->reg.type == VKD3DSPR_SSA && dst->reg.idx[0].offset < ctx->parser->shader_desc.ssa_count)
|
||
|
+ {
|
||
|
+ struct validation_context_ssa_data *data = &ctx->ssas[dst->reg.idx[0].offset];
|
||
|
+
|
||
|
+ if (data->write_mask == 0)
|
||
|
+ {
|
||
|
+ data->write_mask = dst->write_mask;
|
||
|
+ data->first_assigned = ctx->instruction_idx;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE,
|
||
|
+ "SSA register is already assigned at instruction %zu.",
|
||
|
+ data->first_assigned);
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
static void vsir_validate_src_param(struct validation_context *ctx,
|
||
|
@@ -1617,9 +1811,22 @@ static void vsir_validate_src_param(struct validation_context *ctx,
|
||
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source has invalid swizzle %#x.",
|
||
|
src->swizzle);
|
||
|
|
||
|
+ if (src->reg.dimension != VSIR_DIMENSION_VEC4 && src->swizzle != 0)
|
||
|
+ validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source of dimension %u has invalid swizzle %#x.",
|
||
|
+ src->reg.dimension, src->swizzle);
|
||
|
+
|
||
|
if (src->modifiers >= VKD3DSPSM_COUNT)
|
||
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.",
|
||
|
src->modifiers);
|
||
|
+
|
||
|
+ if (src->reg.type == VKD3DSPR_SSA && src->reg.idx[0].offset < ctx->parser->shader_desc.ssa_count)
|
||
|
+ {
|
||
|
+ struct validation_context_ssa_data *data = &ctx->ssas[src->reg.idx[0].offset];
|
||
|
+ unsigned int i;
|
||
|
+
|
||
|
+ for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
|
||
|
+ data->read_mask |= (1u << vsir_swizzle_get_component(src->swizzle, i));
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
static void vsir_validate_dst_count(struct validation_context *ctx,
|
||
|
@@ -1791,22 +1998,52 @@ static void vsir_validate_instruction(struct validation_context *ctx)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
-void vsir_validate(struct vkd3d_shader_parser *parser)
|
||
|
+enum vkd3d_result vsir_validate(struct vkd3d_shader_parser *parser)
|
||
|
{
|
||
|
struct validation_context ctx =
|
||
|
{
|
||
|
.parser = parser,
|
||
|
.phase = VKD3DSIH_INVALID,
|
||
|
};
|
||
|
+ unsigned int i;
|
||
|
|
||
|
if (!(parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION))
|
||
|
- return;
|
||
|
+ return VKD3D_OK;
|
||
|
+
|
||
|
+ if (!(ctx.temps = vkd3d_calloc(parser->shader_desc.temp_count, sizeof(*ctx.temps))))
|
||
|
+ goto fail;
|
||
|
+
|
||
|
+ if (!(ctx.ssas = vkd3d_calloc(parser->shader_desc.ssa_count, sizeof(*ctx.ssas))))
|
||
|
+ goto fail;
|
||
|
|
||
|
for (ctx.instruction_idx = 0; ctx.instruction_idx < parser->instructions.count; ++ctx.instruction_idx)
|
||
|
vsir_validate_instruction(&ctx);
|
||
|
|
||
|
+ ctx.invalid_instruction_idx = true;
|
||
|
+
|
||
|
if (ctx.depth != 0)
|
||
|
validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "%zu nested blocks were not closed.", ctx.depth);
|
||
|
|
||
|
- free(ctx.blocks);
|
||
|
+ for (i = 0; i < parser->shader_desc.ssa_count; ++i)
|
||
|
+ {
|
||
|
+ struct validation_context_ssa_data *data = &ctx.ssas[i];
|
||
|
+
|
||
|
+ if ((data->write_mask | data->read_mask) != data->write_mask)
|
||
|
+ validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE,
|
||
|
+ "SSA register %u has invalid read mask %#x, which is not a subset of the write mask %#x "
|
||
|
+ "at the point of definition.", i, data->read_mask, data->write_mask);
|
||
|
+ }
|
||
|
+
|
||
|
+ vkd3d_free(ctx.blocks);
|
||
|
+ vkd3d_free(ctx.temps);
|
||
|
+ vkd3d_free(ctx.ssas);
|
||
|
+
|
||
|
+ return VKD3D_OK;
|
||
|
+
|
||
|
+fail:
|
||
|
+ vkd3d_free(ctx.blocks);
|
||
|
+ vkd3d_free(ctx.temps);
|
||
|
+ vkd3d_free(ctx.ssas);
|
||
|
+
|
||
|
+ return VKD3D_ERROR_OUT_OF_MEMORY;
|
||
|
}
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
||
|
index 387784f2358..7743319bed5 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c
|
||
|
@@ -1764,6 +1764,15 @@ static uint32_t vkd3d_spirv_build_op_glsl_std450_max(struct vkd3d_spirv_builder
|
||
|
GLSLstd450NMax, operands, ARRAY_SIZE(operands));
|
||
|
}
|
||
|
|
||
|
+static uint32_t vkd3d_spirv_build_op_glsl_std450_umin(struct vkd3d_spirv_builder *builder,
|
||
|
+ uint32_t result_type, uint32_t x, uint32_t y)
|
||
|
+{
|
||
|
+ uint32_t glsl_std450_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
|
||
|
+ uint32_t operands[] = {x, y};
|
||
|
+ return vkd3d_spirv_build_op_ext_inst(builder, result_type, glsl_std450_id,
|
||
|
+ GLSLstd450UMin, operands, ARRAY_SIZE(operands));
|
||
|
+}
|
||
|
+
|
||
|
static uint32_t vkd3d_spirv_build_op_glsl_std450_nclamp(struct vkd3d_spirv_builder *builder,
|
||
|
uint32_t result_type, uint32_t x, uint32_t min, uint32_t max)
|
||
|
{
|
||
|
@@ -2189,7 +2198,7 @@ static void vkd3d_symbol_make_io(struct vkd3d_symbol *symbol,
|
||
|
|
||
|
static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol,
|
||
|
uint32_t val_id, SpvStorageClass storage_class,
|
||
|
- enum vkd3d_shader_component_type component_type, DWORD write_mask)
|
||
|
+ enum vkd3d_shader_component_type component_type, uint32_t write_mask)
|
||
|
{
|
||
|
symbol->id = val_id;
|
||
|
symbol->descriptor_array = NULL;
|
||
|
@@ -3361,7 +3370,7 @@ static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *comp
|
||
|
}
|
||
|
|
||
|
static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler,
|
||
|
- const struct vkd3d_shader_src_param *src, DWORD write_mask);
|
||
|
+ const struct vkd3d_shader_src_param *src, uint32_t write_mask);
|
||
|
|
||
|
static uint32_t spirv_compiler_emit_register_addressing(struct spirv_compiler *compiler,
|
||
|
const struct vkd3d_shader_register_index *reg_index)
|
||
|
@@ -3600,8 +3609,7 @@ static uint32_t spirv_compiler_get_register_id(struct spirv_compiler *compiler,
|
||
|
SpvStorageClassPrivate, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE);
|
||
|
}
|
||
|
|
||
|
-static bool vkd3d_swizzle_is_equal(unsigned int dst_write_mask,
|
||
|
- unsigned int swizzle, unsigned int write_mask)
|
||
|
+static bool vkd3d_swizzle_is_equal(uint32_t dst_write_mask, uint32_t swizzle, uint32_t write_mask)
|
||
|
{
|
||
|
return vkd3d_compact_swizzle(VKD3D_SHADER_NO_SWIZZLE, dst_write_mask) == vkd3d_compact_swizzle(swizzle, write_mask);
|
||
|
}
|
||
|
@@ -3913,7 +3921,7 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler
|
||
|
}
|
||
|
|
||
|
static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler,
|
||
|
- const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask)
|
||
|
+ const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask)
|
||
|
{
|
||
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
||
|
enum vkd3d_shader_component_type component_type;
|
||
|
@@ -3989,7 +3997,7 @@ static void spirv_compiler_emit_execution_mode1(struct spirv_compiler *compiler,
|
||
|
}
|
||
|
|
||
|
static uint32_t spirv_compiler_emit_abs(struct spirv_compiler *compiler,
|
||
|
- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id)
|
||
|
+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id)
|
||
|
{
|
||
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
||
|
uint32_t type_id;
|
||
|
@@ -4003,7 +4011,7 @@ static uint32_t spirv_compiler_emit_abs(struct spirv_compiler *compiler,
|
||
|
}
|
||
|
|
||
|
static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler,
|
||
|
- const struct vkd3d_shader_register *reg, DWORD write_mask, uint32_t val_id)
|
||
|
+ const struct vkd3d_shader_register *reg, uint32_t write_mask, uint32_t val_id)
|
||
|
{
|
||
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
||
|
uint32_t type_id;
|
||
|
@@ -4019,7 +4027,7 @@ static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler,
|
||
|
}
|
||
|
|
||
|
static uint32_t spirv_compiler_emit_src_modifier(struct spirv_compiler *compiler,
|
||
|
- const struct vkd3d_shader_register *reg, DWORD write_mask,
|
||
|
+ const struct vkd3d_shader_register *reg, uint32_t write_mask,
|
||
|
enum vkd3d_shader_src_modifier modifier, uint32_t val_id)
|
||
|
{
|
||
|
switch (modifier)
|
||
|
@@ -4042,7 +4050,7 @@ static uint32_t spirv_compiler_emit_src_modifier(struct spirv_compiler *compiler
|
||
|
}
|
||
|
|
||
|
static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler,
|
||
|
- const struct vkd3d_shader_src_param *src, DWORD write_mask)
|
||
|
+ const struct vkd3d_shader_src_param *src, uint32_t write_mask)
|
||
|
{
|
||
|
uint32_t val_id;
|
||
|
|
||
|
@@ -4051,7 +4059,7 @@ static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler,
|
||
|
}
|
||
|
|
||
|
static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *compiler,
|
||
|
- const struct vkd3d_shader_src_param *src, DWORD write_mask, enum vkd3d_shader_component_type component_type)
|
||
|
+ const struct vkd3d_shader_src_param *src, uint32_t write_mask, enum vkd3d_shader_component_type component_type)
|
||
|
{
|
||
|
struct vkd3d_shader_src_param src_param = *src;
|
||
|
|
||
|
@@ -4209,7 +4217,7 @@ static void spirv_compiler_emit_store_dst(struct spirv_compiler *compiler,
|
||
|
|
||
|
static void spirv_compiler_emit_store_dst_swizzled(struct spirv_compiler *compiler,
|
||
|
const struct vkd3d_shader_dst_param *dst, uint32_t val_id,
|
||
|
- enum vkd3d_shader_component_type component_type, DWORD swizzle)
|
||
|
+ enum vkd3d_shader_component_type component_type, uint32_t swizzle)
|
||
|
{
|
||
|
struct vkd3d_shader_dst_param typed_dst = *dst;
|
||
|
val_id = spirv_compiler_emit_swizzle(compiler,
|
||
|
@@ -6899,8 +6907,8 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp
|
||
|
const struct vkd3d_shader_src_param *src = instruction->src;
|
||
|
uint32_t src_id[SPIRV_MAX_SRC_COUNT];
|
||
|
uint32_t instr_set_id, type_id, val_id;
|
||
|
+ unsigned int i, component_count;
|
||
|
enum GLSLstd450 glsl_inst;
|
||
|
- unsigned int i;
|
||
|
|
||
|
glsl_inst = spirv_compiler_map_ext_glsl_instruction(instruction);
|
||
|
if (glsl_inst == GLSLstd450Bad)
|
||
|
@@ -6926,8 +6934,9 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp
|
||
|
|| instruction->handler_idx == VKD3DSIH_FIRSTBIT_SHI)
|
||
|
{
|
||
|
/* In D3D bits are numbered from the most significant bit. */
|
||
|
+ component_count = vsir_write_mask_component_count(dst->write_mask);
|
||
|
val_id = vkd3d_spirv_build_op_isub(builder, type_id,
|
||
|
- spirv_compiler_get_constant_uint(compiler, 31), val_id);
|
||
|
+ spirv_compiler_get_constant_uint_vector(compiler, 31, component_count), val_id);
|
||
|
}
|
||
|
|
||
|
spirv_compiler_emit_store_dst(compiler, dst, val_id);
|
||
|
@@ -7060,7 +7069,7 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler,
|
||
|
enum vkd3d_shader_component_type component_type;
|
||
|
uint32_t type_id, val_id, src_ids[2];
|
||
|
unsigned int component_count, i;
|
||
|
- DWORD write_mask;
|
||
|
+ uint32_t write_mask;
|
||
|
|
||
|
component_count = vsir_write_mask_component_count(dst->write_mask);
|
||
|
component_type = vkd3d_component_type_from_data_type(dst->reg.data_type);
|
||
|
@@ -7356,13 +7365,13 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler,
|
||
|
static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *compiler,
|
||
|
const struct vkd3d_shader_instruction *instruction)
|
||
|
{
|
||
|
- uint32_t src_ids[4], constituents[VKD3D_VEC4_SIZE], type_id, mask_id;
|
||
|
+ uint32_t src_ids[4], constituents[VKD3D_VEC4_SIZE], type_id, mask_id, size_id, max_count_id;
|
||
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
||
|
const struct vkd3d_shader_dst_param *dst = instruction->dst;
|
||
|
const struct vkd3d_shader_src_param *src = instruction->src;
|
||
|
enum vkd3d_shader_component_type component_type;
|
||
|
unsigned int i, j, k, src_count;
|
||
|
- DWORD write_mask;
|
||
|
+ uint32_t write_mask;
|
||
|
SpvOp op;
|
||
|
|
||
|
src_count = instruction->src_count;
|
||
|
@@ -7371,6 +7380,7 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp
|
||
|
component_type = vkd3d_component_type_from_data_type(dst->reg.data_type);
|
||
|
type_id = vkd3d_spirv_get_type_id(builder, component_type, 1);
|
||
|
mask_id = spirv_compiler_get_constant_uint(compiler, 0x1f);
|
||
|
+ size_id = spirv_compiler_get_constant_uint(compiler, 0x20);
|
||
|
|
||
|
switch (instruction->handler_idx)
|
||
|
{
|
||
|
@@ -7399,6 +7409,9 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp
|
||
|
{
|
||
|
src_ids[j] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[j], mask_id);
|
||
|
}
|
||
|
+ max_count_id = vkd3d_spirv_build_op_isub(builder, type_id, size_id, src_ids[src_count - 2]);
|
||
|
+ src_ids[src_count - 1] = vkd3d_spirv_build_op_glsl_std450_umin(builder, type_id,
|
||
|
+ src_ids[src_count - 1], max_count_id);
|
||
|
|
||
|
constituents[k++] = vkd3d_spirv_build_op_trv(builder, &builder->function_stream,
|
||
|
op, type_id, src_ids, src_count);
|
||
|
@@ -7415,8 +7428,8 @@ static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler,
|
||
|
const struct vkd3d_shader_dst_param *dst = instruction->dst;
|
||
|
const struct vkd3d_shader_src_param *src = instruction->src;
|
||
|
uint32_t components[VKD3D_VEC4_SIZE];
|
||
|
+ uint32_t write_mask;
|
||
|
unsigned int i, j;
|
||
|
- DWORD write_mask;
|
||
|
|
||
|
instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
|
||
|
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2);
|
||
|
@@ -7448,8 +7461,8 @@ static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler,
|
||
|
const struct vkd3d_shader_dst_param *dst = instruction->dst;
|
||
|
const struct vkd3d_shader_src_param *src = instruction->src;
|
||
|
uint32_t components[VKD3D_VEC4_SIZE];
|
||
|
+ uint32_t write_mask;
|
||
|
unsigned int i, j;
|
||
|
- DWORD write_mask;
|
||
|
|
||
|
instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder);
|
||
|
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, 2);
|
||
|
@@ -8214,7 +8227,7 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler,
|
||
|
unsigned int image_operand_count = 0;
|
||
|
struct vkd3d_shader_image image;
|
||
|
uint32_t image_operands[2];
|
||
|
- DWORD coordinate_mask;
|
||
|
+ uint32_t coordinate_mask;
|
||
|
bool multisample;
|
||
|
|
||
|
multisample = instruction->handler_idx == VKD3DSIH_LD2DMS;
|
||
|
@@ -8288,7 +8301,7 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler,
|
||
|
unsigned int image_operand_count = 0;
|
||
|
struct vkd3d_shader_image image;
|
||
|
uint32_t image_operands[3];
|
||
|
- DWORD coordinate_mask;
|
||
|
+ uint32_t coordinate_mask;
|
||
|
SpvOp op;
|
||
|
|
||
|
resource = &src[1];
|
||
|
@@ -8404,7 +8417,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler,
|
||
|
struct vkd3d_shader_image image;
|
||
|
unsigned int component_idx;
|
||
|
uint32_t image_operands[1];
|
||
|
- DWORD coordinate_mask;
|
||
|
+ uint32_t coordinate_mask;
|
||
|
bool extended_offset;
|
||
|
|
||
|
if (instruction->handler_idx == VKD3DSIH_GATHER4_C
|
||
|
@@ -8464,13 +8477,13 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler,
|
||
|
|
||
|
static uint32_t spirv_compiler_emit_raw_structured_addressing(
|
||
|
struct spirv_compiler *compiler, uint32_t type_id, unsigned int stride,
|
||
|
- const struct vkd3d_shader_src_param *src0, DWORD src0_mask,
|
||
|
- const struct vkd3d_shader_src_param *src1, DWORD src1_mask)
|
||
|
+ const struct vkd3d_shader_src_param *src0, uint32_t src0_mask,
|
||
|
+ const struct vkd3d_shader_src_param *src1, uint32_t src1_mask)
|
||
|
{
|
||
|
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
||
|
const struct vkd3d_shader_src_param *offset;
|
||
|
uint32_t structure_id = 0, offset_id;
|
||
|
- DWORD offset_write_mask;
|
||
|
+ uint32_t offset_write_mask;
|
||
|
|
||
|
if (stride)
|
||
|
{
|
||
|
@@ -8779,7 +8792,7 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler,
|
||
|
const struct vkd3d_shader_src_param *src = instruction->src;
|
||
|
const struct vkd3d_symbol *resource_symbol;
|
||
|
struct vkd3d_shader_image image;
|
||
|
- DWORD coordinate_mask;
|
||
|
+ uint32_t coordinate_mask;
|
||
|
uint32_t indices[2];
|
||
|
|
||
|
resource_symbol = spirv_compiler_find_resource(compiler, &src[1].reg);
|
||
|
@@ -8822,7 +8835,7 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler,
|
||
|
const struct vkd3d_shader_src_param *src = instruction->src;
|
||
|
const struct vkd3d_symbol *resource_symbol;
|
||
|
struct vkd3d_shader_image image;
|
||
|
- DWORD coordinate_mask;
|
||
|
+ uint32_t coordinate_mask;
|
||
|
uint32_t indices[2];
|
||
|
|
||
|
resource_symbol = spirv_compiler_find_resource(compiler, &dst->reg);
|
||
|
@@ -8988,7 +9001,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil
|
||
|
struct vkd3d_shader_register_info reg_info;
|
||
|
struct vkd3d_shader_image image;
|
||
|
unsigned int structure_stride;
|
||
|
- DWORD coordinate_mask;
|
||
|
+ uint32_t coordinate_mask;
|
||
|
uint32_t operands[6];
|
||
|
unsigned int i = 0;
|
||
|
SpvScope scope;
|
||
|
@@ -9420,9 +9433,9 @@ static void spirv_compiler_emit_sync(struct spirv_compiler *compiler,
|
||
|
const struct vkd3d_shader_instruction *instruction)
|
||
|
{
|
||
|
unsigned int memory_semantics = SpvMemorySemanticsAcquireReleaseMask;
|
||
|
- unsigned int flags = instruction->flags;
|
||
|
SpvScope execution_scope = SpvScopeMax;
|
||
|
SpvScope memory_scope = SpvScopeDevice;
|
||
|
+ uint32_t flags = instruction->flags;
|
||
|
|
||
|
if (flags & VKD3DSSF_GROUP_SHARED_MEMORY)
|
||
|
{
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
||
|
index f859e758d8e..1f1944bc0da 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c
|
||
|
@@ -742,8 +742,7 @@ static bool shader_sm4_read_register_space(struct vkd3d_shader_sm4_parser *priv,
|
||
|
static void shader_sm4_read_conditional_op(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)
|
||
|
{
|
||
|
- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT,
|
||
|
- (struct vkd3d_shader_src_param *)&ins->src[0]);
|
||
|
+ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &ins->src[0]);
|
||
|
ins->flags = (opcode_token & VKD3D_SM4_CONDITIONAL_NZ) ?
|
||
|
VKD3D_SHADER_CONDITIONAL_OP_NZ : VKD3D_SHADER_CONDITIONAL_OP_Z;
|
||
|
}
|
||
|
@@ -751,8 +750,7 @@ static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins,
|
||
|
static void shader_sm4_read_case_condition(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)
|
||
|
{
|
||
|
- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT,
|
||
|
- (struct vkd3d_shader_src_param *)&ins->src[0]);
|
||
|
+ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &ins->src[0]);
|
||
|
if (ins->src[0].reg.type != VKD3DSPR_IMMCONST)
|
||
|
{
|
||
|
FIXME("Switch case value is not a 32-bit constant.\n");
|
||
|
@@ -823,7 +821,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, u
|
||
|
const uint32_t *end = &tokens[token_count];
|
||
|
enum vkd3d_sm4_data_type data_type;
|
||
|
enum vkd3d_data_type reg_data_type;
|
||
|
- DWORD components;
|
||
|
+ uint32_t components;
|
||
|
unsigned int i;
|
||
|
|
||
|
resource_type = (opcode_token & VKD3D_SM4_RESOURCE_TYPE_MASK) >> VKD3D_SM4_RESOURCE_TYPE_SHIFT;
|
||
|
@@ -1130,9 +1128,8 @@ static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *in
|
||
|
static void shader_sm5_read_fcall(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_src_param *src_params = (struct vkd3d_shader_src_param *)ins->src;
|
||
|
- src_params[0].reg.u.fp_body_idx = *tokens++;
|
||
|
- shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &src_params[0]);
|
||
|
+ ins->src[0].reg.u.fp_body_idx = *tokens++;
|
||
|
+ shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &ins->src[0]);
|
||
|
}
|
||
|
|
||
|
static void shader_sm5_read_dcl_function_body(struct vkd3d_shader_instruction *ins, uint32_t opcode,
|
||
|
@@ -1762,11 +1759,11 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui
|
||
|
const struct vkd3d_sm4_register_type_info *register_type_info;
|
||
|
enum vkd3d_shader_register_type vsir_register_type;
|
||
|
enum vkd3d_sm4_register_precision precision;
|
||
|
+ uint32_t token, order, extended, addressing;
|
||
|
enum vkd3d_sm4_register_type register_type;
|
||
|
enum vkd3d_sm4_extended_operand_type type;
|
||
|
- enum vkd3d_sm4_register_modifier m;
|
||
|
enum vkd3d_sm4_dimension sm4_dimension;
|
||
|
- uint32_t token, order, extended;
|
||
|
+ enum vkd3d_sm4_register_modifier m;
|
||
|
|
||
|
if (*ptr >= end)
|
||
|
{
|
||
|
@@ -1864,7 +1861,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui
|
||
|
|
||
|
if (order >= 1)
|
||
|
{
|
||
|
- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK0) >> VKD3D_SM4_ADDRESSING_SHIFT0;
|
||
|
+ addressing = (token & VKD3D_SM4_ADDRESSING_MASK0) >> VKD3D_SM4_ADDRESSING_SHIFT0;
|
||
|
if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[0])))
|
||
|
{
|
||
|
ERR("Failed to read register index.\n");
|
||
|
@@ -1874,7 +1871,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui
|
||
|
|
||
|
if (order >= 2)
|
||
|
{
|
||
|
- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK1) >> VKD3D_SM4_ADDRESSING_SHIFT1;
|
||
|
+ addressing = (token & VKD3D_SM4_ADDRESSING_MASK1) >> VKD3D_SM4_ADDRESSING_SHIFT1;
|
||
|
if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[1])))
|
||
|
{
|
||
|
ERR("Failed to read register index.\n");
|
||
|
@@ -1884,7 +1881,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui
|
||
|
|
||
|
if (order >= 3)
|
||
|
{
|
||
|
- DWORD addressing = (token & VKD3D_SM4_ADDRESSING_MASK2) >> VKD3D_SM4_ADDRESSING_SHIFT2;
|
||
|
+ addressing = (token & VKD3D_SM4_ADDRESSING_MASK2) >> VKD3D_SM4_ADDRESSING_SHIFT2;
|
||
|
if (!(shader_sm4_read_reg_idx(priv, ptr, end, addressing, ¶m->idx[2])))
|
||
|
{
|
||
|
ERR("Failed to read register index.\n");
|
||
|
@@ -2078,7 +2075,7 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons
|
||
|
const uint32_t *end, enum vkd3d_data_type data_type, struct vkd3d_shader_src_param *src_param)
|
||
|
{
|
||
|
unsigned int dimension, mask;
|
||
|
- DWORD token;
|
||
|
+ uint32_t token;
|
||
|
|
||
|
if (*ptr >= end)
|
||
|
{
|
||
|
@@ -2165,7 +2162,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons
|
||
|
enum vkd3d_sm4_swizzle_type swizzle_type;
|
||
|
enum vkd3d_shader_src_modifier modifier;
|
||
|
unsigned int dimension, swizzle;
|
||
|
- DWORD token;
|
||
|
+ uint32_t token;
|
||
|
|
||
|
if (*ptr >= end)
|
||
|
{
|
||
|
@@ -2245,7 +2242,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
-static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_shader_instruction *ins)
|
||
|
+static void shader_sm4_read_instruction_modifier(uint32_t modifier, struct vkd3d_shader_instruction *ins)
|
||
|
{
|
||
|
enum vkd3d_sm4_instruction_modifier modifier_type = modifier & VKD3D_SM4_MODIFIER_MASK;
|
||
|
|
||
|
@@ -2253,7 +2250,7 @@ static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_sh
|
||
|
{
|
||
|
case VKD3D_SM4_MODIFIER_AOFFIMMI:
|
||
|
{
|
||
|
- static const DWORD recognized_bits = VKD3D_SM4_INSTRUCTION_MODIFIER
|
||
|
+ static const uint32_t recognized_bits = VKD3D_SM4_INSTRUCTION_MODIFIER
|
||
|
| VKD3D_SM4_MODIFIER_MASK
|
||
|
| VKD3D_SM4_AOFFIMMI_U_MASK
|
||
|
| VKD3D_SM4_AOFFIMMI_V_MASK
|
||
|
@@ -2281,7 +2278,7 @@ static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_sh
|
||
|
|
||
|
case VKD3D_SM5_MODIFIER_DATA_TYPE:
|
||
|
{
|
||
|
- DWORD components = (modifier & VKD3D_SM5_MODIFIER_DATA_TYPE_MASK) >> VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT;
|
||
|
+ uint32_t components = (modifier & VKD3D_SM5_MODIFIER_DATA_TYPE_MASK) >> VKD3D_SM5_MODIFIER_DATA_TYPE_SHIFT;
|
||
|
unsigned int i;
|
||
|
|
||
|
for (i = 0; i < VKD3D_VEC4_SIZE; i++)
|
||
|
@@ -2337,9 +2334,9 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str
|
||
|
struct vkd3d_shader_src_param *src_params;
|
||
|
const uint32_t **ptr = &sm4->ptr;
|
||
|
unsigned int i, len;
|
||
|
- size_t remaining;
|
||
|
const uint32_t *p;
|
||
|
- DWORD precise;
|
||
|
+ uint32_t precise;
|
||
|
+ size_t remaining;
|
||
|
|
||
|
if (*ptr >= sm4->end)
|
||
|
{
|
||
|
@@ -5488,7 +5485,7 @@ static void write_sm4_loop(const struct tpf_writer *tpf, const struct hlsl_ir_lo
|
||
|
|
||
|
static void write_sm4_gather(const struct tpf_writer *tpf, const struct hlsl_ir_node *dst,
|
||
|
const struct hlsl_deref *resource, const struct hlsl_deref *sampler,
|
||
|
- const struct hlsl_ir_node *coords, DWORD swizzle, const struct hlsl_ir_node *texel_offset)
|
||
|
+ const struct hlsl_ir_node *coords, uint32_t swizzle, const struct hlsl_ir_node *texel_offset)
|
||
|
{
|
||
|
struct vkd3d_shader_src_param *src;
|
||
|
struct sm4_instruction instr;
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
||
|
index 8fd98d2a551..61e46f5538e 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c
|
||
|
@@ -383,13 +383,42 @@ size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *byte
|
||
|
return offset;
|
||
|
}
|
||
|
|
||
|
-void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value)
|
||
|
+size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size)
|
||
|
+{
|
||
|
+ size_t offset = bytecode_align(buffer);
|
||
|
+
|
||
|
+ if (buffer->status)
|
||
|
+ return offset;
|
||
|
+
|
||
|
+ if (!vkd3d_array_reserve((void **)&buffer->data, &buffer->capacity, offset + size, 1))
|
||
|
+ {
|
||
|
+ buffer->status = VKD3D_ERROR_OUT_OF_MEMORY;
|
||
|
+ return offset;
|
||
|
+ }
|
||
|
+
|
||
|
+ memset(buffer->data + offset, 0, size);
|
||
|
+ buffer->size = offset + size;
|
||
|
+ return offset;
|
||
|
+}
|
||
|
+
|
||
|
+static void bytecode_set_bytes(struct vkd3d_bytecode_buffer *buffer, size_t offset,
|
||
|
+ const void *value, size_t size)
|
||
|
{
|
||
|
if (buffer->status)
|
||
|
return;
|
||
|
|
||
|
- assert(vkd3d_bound_range(offset, sizeof(value), buffer->size));
|
||
|
- memcpy(buffer->data + offset, &value, sizeof(value));
|
||
|
+ assert(vkd3d_bound_range(offset, size, buffer->size));
|
||
|
+ memcpy(buffer->data + offset, value, size);
|
||
|
+}
|
||
|
+
|
||
|
+void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value)
|
||
|
+{
|
||
|
+ bytecode_set_bytes(buffer, offset, &value, sizeof(value));
|
||
|
+}
|
||
|
+
|
||
|
+void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char *string, size_t length)
|
||
|
+{
|
||
|
+ bytecode_set_bytes(buffer, offset, string, length);
|
||
|
}
|
||
|
|
||
|
static void vkd3d_shader_dump_blob(const char *path, const char *profile,
|
||
|
@@ -1913,6 +1942,7 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types(
|
||
|
{
|
||
|
VKD3D_SHADER_TARGET_D3D_BYTECODE,
|
||
|
VKD3D_SHADER_TARGET_DXBC_TPF,
|
||
|
+ VKD3D_SHADER_TARGET_FX,
|
||
|
};
|
||
|
|
||
|
static const enum vkd3d_shader_target_type d3dbc_types[] =
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
||
|
index 47b245bd7ee..0af7ea0d266 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
||
|
+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h
|
||
|
@@ -216,6 +216,7 @@ enum vkd3d_shader_error
|
||
|
VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS = 9014,
|
||
|
VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX = 9015,
|
||
|
VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING = 9016,
|
||
|
+ VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE = 9017,
|
||
|
|
||
|
VKD3D_SHADER_WARNING_VSIR_DYNAMIC_DESCRIPTOR_ARRAY = 9300,
|
||
|
};
|
||
|
@@ -871,14 +872,14 @@ struct vkd3d_shader_dst_param
|
||
|
{
|
||
|
struct vkd3d_shader_register reg;
|
||
|
uint32_t write_mask;
|
||
|
- DWORD modifiers;
|
||
|
- DWORD shift;
|
||
|
+ uint32_t modifiers;
|
||
|
+ unsigned int shift;
|
||
|
};
|
||
|
|
||
|
struct vkd3d_shader_src_param
|
||
|
{
|
||
|
struct vkd3d_shader_register reg;
|
||
|
- DWORD swizzle;
|
||
|
+ uint32_t swizzle;
|
||
|
enum vkd3d_shader_src_modifier modifiers;
|
||
|
};
|
||
|
|
||
|
@@ -955,6 +956,9 @@ enum vkd3d_shader_input_sysval_semantic
|
||
|
VKD3D_SIV_LINE_DENSITY_TESS_FACTOR = 22,
|
||
|
};
|
||
|
|
||
|
+#define SM1_COLOR_REGISTER_OFFSET 8
|
||
|
+#define SM1_RASTOUT_REGISTER_OFFSET 10
|
||
|
+
|
||
|
#define SIGNATURE_TARGET_LOCATION_UNUSED (~0u)
|
||
|
|
||
|
struct signature_element
|
||
|
@@ -1120,11 +1124,11 @@ struct vkd3d_shader_instruction
|
||
|
{
|
||
|
struct vkd3d_shader_location location;
|
||
|
enum vkd3d_shader_opcode handler_idx;
|
||
|
- DWORD flags;
|
||
|
+ uint32_t flags;
|
||
|
unsigned int dst_count;
|
||
|
unsigned int src_count;
|
||
|
- const struct vkd3d_shader_dst_param *dst;
|
||
|
- const struct vkd3d_shader_src_param *src;
|
||
|
+ struct vkd3d_shader_dst_param *dst;
|
||
|
+ struct vkd3d_shader_src_param *src;
|
||
|
struct vkd3d_shader_texel_offset texel_offset;
|
||
|
enum vkd3d_shader_resource_type resource_type;
|
||
|
unsigned int resource_stride;
|
||
|
@@ -1354,7 +1358,9 @@ struct vkd3d_bytecode_buffer
|
||
|
/* Align to the next 4-byte offset, and return that offset. */
|
||
|
size_t bytecode_align(struct vkd3d_bytecode_buffer *buffer);
|
||
|
size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size);
|
||
|
+size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size);
|
||
|
void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value);
|
||
|
+void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char *string, size_t length);
|
||
|
|
||
|
static inline size_t put_u32(struct vkd3d_bytecode_buffer *buffer, uint32_t value)
|
||
|
{
|
||
|
@@ -1445,7 +1451,7 @@ int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info,
|
||
|
int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d_shader_compile_info *compile_info,
|
||
|
struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context);
|
||
|
|
||
|
-void vsir_validate(struct vkd3d_shader_parser *parser);
|
||
|
+enum vkd3d_result vsir_validate(struct vkd3d_shader_parser *parser);
|
||
|
|
||
|
static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type(
|
||
|
enum vkd3d_data_type data_type)
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c
|
||
|
index 549f6a45ffb..4c39d00de24 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d/command.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d/command.c
|
||
|
@@ -3270,7 +3270,8 @@ static void d3d12_command_list_bind_descriptor_heap(struct d3d12_command_list *l
|
||
|
{
|
||
|
VkDescriptorSet vk_descriptor_set = heap->vk_descriptor_sets[set].vk_set;
|
||
|
|
||
|
- if (!vk_descriptor_set)
|
||
|
+ /* Null vk_set_layout means set 0 uses mutable descriptors, and this set is unused. */
|
||
|
+ if (!vk_descriptor_set || !list->device->vk_descriptor_heap_layouts[set].vk_set_layout)
|
||
|
continue;
|
||
|
|
||
|
VK_CALL(vkCmdBindDescriptorSets(list->vk_command_buffer, bindings->vk_bind_point, rs->vk_pipeline_layout,
|
||
|
@@ -6512,7 +6513,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12Command
|
||
|
if (!(op = d3d12_command_queue_op_array_require_space(&command_queue->op_queue)))
|
||
|
{
|
||
|
ERR("Failed to add op.\n");
|
||
|
- return;
|
||
|
+ goto unlock_mutex;
|
||
|
}
|
||
|
op->opcode = VKD3D_CS_OP_COPY_MAPPINGS;
|
||
|
op->u.copy_mappings.dst_resource = dst_resource_impl;
|
||
|
@@ -6524,6 +6525,7 @@ static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12Command
|
||
|
|
||
|
d3d12_command_queue_submit_locked(command_queue);
|
||
|
|
||
|
+unlock_mutex:
|
||
|
vkd3d_mutex_unlock(&command_queue->op_mutex);
|
||
|
}
|
||
|
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c
|
||
|
index 69a46e9188a..ea243977c22 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d/device.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d/device.c
|
||
|
@@ -94,6 +94,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] =
|
||
|
VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker),
|
||
|
VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable),
|
||
|
VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing),
|
||
|
+ VK_EXTENSION(EXT_MUTABLE_DESCRIPTOR_TYPE, EXT_mutable_descriptor_type),
|
||
|
VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2),
|
||
|
VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation),
|
||
|
VK_EXTENSION(EXT_SHADER_STENCIL_EXPORT, EXT_shader_stencil_export),
|
||
|
@@ -106,13 +107,32 @@ static HRESULT vkd3d_create_vk_descriptor_heap_layout(struct d3d12_device *devic
|
||
|
{
|
||
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||
|
VkDescriptorSetLayoutBindingFlagsCreateInfoEXT flags_info;
|
||
|
+ VkMutableDescriptorTypeCreateInfoEXT mutable_info;
|
||
|
+ VkMutableDescriptorTypeListEXT type_list;
|
||
|
VkDescriptorSetLayoutCreateInfo set_desc;
|
||
|
VkDescriptorBindingFlagsEXT set_flags;
|
||
|
VkDescriptorSetLayoutBinding binding;
|
||
|
VkResult vr;
|
||
|
|
||
|
+ static const VkDescriptorType descriptor_types[] =
|
||
|
+ {
|
||
|
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||
|
+ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
|
||
|
+ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||
|
+ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
|
||
|
+ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||
|
+ };
|
||
|
+
|
||
|
+ if (device->vk_info.EXT_mutable_descriptor_type && index && index != VKD3D_SET_INDEX_UAV_COUNTER
|
||
|
+ && device->vk_descriptor_heap_layouts[index].applicable_heap_type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
|
||
|
+ {
|
||
|
+ device->vk_descriptor_heap_layouts[index].vk_set_layout = VK_NULL_HANDLE;
|
||
|
+ return S_OK;
|
||
|
+ }
|
||
|
+
|
||
|
binding.binding = 0;
|
||
|
- binding.descriptorType = device->vk_descriptor_heap_layouts[index].type;
|
||
|
+ binding.descriptorType = (device->vk_info.EXT_mutable_descriptor_type && !index)
|
||
|
+ ? VK_DESCRIPTOR_TYPE_MUTABLE_EXT : device->vk_descriptor_heap_layouts[index].type;
|
||
|
binding.descriptorCount = device->vk_descriptor_heap_layouts[index].count;
|
||
|
binding.stageFlags = VK_SHADER_STAGE_ALL;
|
||
|
binding.pImmutableSamplers = NULL;
|
||
|
@@ -132,6 +152,17 @@ static HRESULT vkd3d_create_vk_descriptor_heap_layout(struct d3d12_device *devic
|
||
|
flags_info.bindingCount = 1;
|
||
|
flags_info.pBindingFlags = &set_flags;
|
||
|
|
||
|
+ if (binding.descriptorType == VK_DESCRIPTOR_TYPE_MUTABLE_EXT)
|
||
|
+ {
|
||
|
+ type_list.descriptorTypeCount = ARRAY_SIZE(descriptor_types);
|
||
|
+ type_list.pDescriptorTypes = descriptor_types;
|
||
|
+ mutable_info.sType = VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT;
|
||
|
+ mutable_info.pNext = NULL;
|
||
|
+ mutable_info.mutableDescriptorTypeListCount = 1;
|
||
|
+ mutable_info.pMutableDescriptorTypeLists = &type_list;
|
||
|
+ flags_info.pNext = &mutable_info;
|
||
|
+ }
|
||
|
+
|
||
|
if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device->vk_device, &set_desc, NULL,
|
||
|
&device->vk_descriptor_heap_layouts[index].vk_set_layout))) < 0)
|
||
|
{
|
||
|
@@ -763,6 +794,7 @@ struct vkd3d_physical_device_info
|
||
|
VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features;
|
||
|
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features;
|
||
|
VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timeline_semaphore_features;
|
||
|
+ VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT mutable_features;
|
||
|
|
||
|
VkPhysicalDeviceFeatures2 features2;
|
||
|
};
|
||
|
@@ -780,6 +812,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
|
||
|
VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features;
|
||
|
VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features;
|
||
|
VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *timeline_semaphore_features;
|
||
|
+ VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT *mutable_features;
|
||
|
VkPhysicalDeviceDepthClipEnableFeaturesEXT *depth_clip_features;
|
||
|
VkPhysicalDeviceMaintenance3Properties *maintenance3_properties;
|
||
|
VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb_properties;
|
||
|
@@ -800,6 +833,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
|
||
|
vertex_divisor_features = &info->vertex_divisor_features;
|
||
|
vertex_divisor_properties = &info->vertex_divisor_properties;
|
||
|
timeline_semaphore_features = &info->timeline_semaphore_features;
|
||
|
+ mutable_features = &info->mutable_features;
|
||
|
xfb_features = &info->xfb_features;
|
||
|
xfb_properties = &info->xfb_properties;
|
||
|
|
||
|
@@ -823,6 +857,8 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
|
||
|
vk_prepend_struct(&info->features2, vertex_divisor_features);
|
||
|
timeline_semaphore_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR;
|
||
|
vk_prepend_struct(&info->features2, timeline_semaphore_features);
|
||
|
+ mutable_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT;
|
||
|
+ vk_prepend_struct(&info->features2, mutable_features);
|
||
|
|
||
|
if (vulkan_info->KHR_get_physical_device_properties2)
|
||
|
VK_CALL(vkGetPhysicalDeviceFeatures2KHR(physical_device, &info->features2));
|
||
|
@@ -1594,6 +1630,8 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
|
||
|
vulkan_info->EXT_shader_demote_to_helper_invocation = false;
|
||
|
if (!physical_device_info->texel_buffer_alignment_features.texelBufferAlignment)
|
||
|
vulkan_info->EXT_texel_buffer_alignment = false;
|
||
|
+ if (!physical_device_info->mutable_features.mutableDescriptorType)
|
||
|
+ vulkan_info->EXT_mutable_descriptor_type = false;
|
||
|
if (!physical_device_info->timeline_semaphore_features.timelineSemaphore)
|
||
|
vulkan_info->KHR_timeline_semaphore = false;
|
||
|
|
||
|
@@ -4513,7 +4551,7 @@ HRESULT vkd3d_create_thread(struct vkd3d_instance *instance,
|
||
|
thread_data->data = data;
|
||
|
if (!(thread->handle = CreateThread(NULL, 0, call_thread_main, thread_data, 0, NULL)))
|
||
|
{
|
||
|
- ERR("Failed to create thread, error %d.\n", GetLastError());
|
||
|
+ ERR("Failed to create thread, error %lu.\n", GetLastError());
|
||
|
vkd3d_free(thread_data);
|
||
|
hr = E_FAIL;
|
||
|
}
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c
|
||
|
index 609c67102a6..163dd6ce210 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d/resource.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d/resource.c
|
||
|
@@ -2470,12 +2470,14 @@ static void d3d12_desc_write_vk_heap_null_descriptor(struct d3d12_descriptor_hea
|
||
|
{
|
||
|
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
||
|
struct d3d12_descriptor_heap_vk_set *descriptor_set;
|
||
|
- enum vkd3d_vk_descriptor_set_index set;
|
||
|
+ enum vkd3d_vk_descriptor_set_index set, end;
|
||
|
unsigned int i = writes->count;
|
||
|
|
||
|
+ end = device->vk_info.EXT_mutable_descriptor_type ? VKD3D_SET_INDEX_UNIFORM_BUFFER
|
||
|
+ : VKD3D_SET_INDEX_STORAGE_IMAGE;
|
||
|
/* Binding a shader with the wrong null descriptor type works in Windows.
|
||
|
* To support that here we must write one to all applicable Vulkan sets. */
|
||
|
- for (set = VKD3D_SET_INDEX_UNIFORM_BUFFER; set <= VKD3D_SET_INDEX_STORAGE_IMAGE; ++set)
|
||
|
+ for (set = VKD3D_SET_INDEX_UNIFORM_BUFFER; set <= end; ++set)
|
||
|
{
|
||
|
descriptor_set = &descriptor_heap->vk_descriptor_sets[set];
|
||
|
writes->vk_descriptor_writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||
|
@@ -3444,6 +3446,7 @@ static void vkd3d_create_null_uav(struct d3d12_desc *descriptor,
|
||
|
vkd3d_desc.miplevel_count = 1;
|
||
|
vkd3d_desc.layer_idx = 0;
|
||
|
vkd3d_desc.layer_count = 1;
|
||
|
+ vkd3d_desc.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||
|
vkd3d_desc.components.r = VK_COMPONENT_SWIZZLE_R;
|
||
|
vkd3d_desc.components.g = VK_COMPONENT_SWIZZLE_G;
|
||
|
vkd3d_desc.components.b = VK_COMPONENT_SWIZZLE_B;
|
||
|
@@ -3661,11 +3664,27 @@ static VkSamplerAddressMode vk_address_mode_from_d3d12(const struct d3d12_device
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+static VkBorderColor vk_border_colour_from_d3d12(D3D12_STATIC_BORDER_COLOR colour)
|
||
|
+{
|
||
|
+ switch (colour)
|
||
|
+ {
|
||
|
+ case D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK:
|
||
|
+ return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||
|
+ case D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK:
|
||
|
+ return VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
|
||
|
+ case D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE:
|
||
|
+ return VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||
|
+ default:
|
||
|
+ FIXME("Unhandled border colour %#x.\n", colour);
|
||
|
+ return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER filter,
|
||
|
D3D12_TEXTURE_ADDRESS_MODE address_u, D3D12_TEXTURE_ADDRESS_MODE address_v,
|
||
|
D3D12_TEXTURE_ADDRESS_MODE address_w, float mip_lod_bias, unsigned int max_anisotropy,
|
||
|
- D3D12_COMPARISON_FUNC comparison_func, float min_lod, float max_lod,
|
||
|
- VkSampler *vk_sampler)
|
||
|
+ D3D12_COMPARISON_FUNC comparison_func, D3D12_STATIC_BORDER_COLOR border_colour,
|
||
|
+ float min_lod, float max_lod, VkSampler *vk_sampler)
|
||
|
{
|
||
|
const struct vkd3d_vk_device_procs *vk_procs;
|
||
|
struct VkSamplerCreateInfo sampler_desc;
|
||
|
@@ -3695,15 +3714,48 @@ static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER f
|
||
|
sampler_desc.maxLod = max_lod;
|
||
|
sampler_desc.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||
|
sampler_desc.unnormalizedCoordinates = VK_FALSE;
|
||
|
+
|
||
|
+ if (address_u == D3D12_TEXTURE_ADDRESS_MODE_BORDER || address_v == D3D12_TEXTURE_ADDRESS_MODE_BORDER
|
||
|
+ || address_w == D3D12_TEXTURE_ADDRESS_MODE_BORDER)
|
||
|
+ sampler_desc.borderColor = vk_border_colour_from_d3d12(border_colour);
|
||
|
+
|
||
|
if ((vr = VK_CALL(vkCreateSampler(device->vk_device, &sampler_desc, NULL, vk_sampler))) < 0)
|
||
|
WARN("Failed to create Vulkan sampler, vr %d.\n", vr);
|
||
|
|
||
|
return vr;
|
||
|
}
|
||
|
|
||
|
+static D3D12_STATIC_BORDER_COLOR d3d12_static_border_colour(const float *colour)
|
||
|
+{
|
||
|
+ unsigned int i;
|
||
|
+
|
||
|
+ static const struct
|
||
|
+ {
|
||
|
+ float colour[4];
|
||
|
+ D3D12_STATIC_BORDER_COLOR static_colour;
|
||
|
+ }
|
||
|
+ colours[] =
|
||
|
+ {
|
||
|
+ {{0.0f, 0.0f, 0.0f, 0.0f}, D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK},
|
||
|
+ {{0.0f, 0.0f, 0.0f, 1.0f}, D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK},
|
||
|
+ {{1.0f, 1.0f, 1.0f, 1.0f}, D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE},
|
||
|
+ };
|
||
|
+
|
||
|
+ for (i = 0; i < ARRAY_SIZE(colours); ++i)
|
||
|
+ {
|
||
|
+ if (!memcmp(colour, colours[i].colour, sizeof(colours[i].colour)))
|
||
|
+ return colours[i].static_colour;
|
||
|
+ }
|
||
|
+
|
||
|
+ FIXME("Unhandled border colour {%.8e, %.8e, %.8e, %.8e}.\n", colour[0], colour[1], colour[2], colour[3]);
|
||
|
+
|
||
|
+ return D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
|
||
|
+}
|
||
|
+
|
||
|
void d3d12_desc_create_sampler(struct d3d12_desc *sampler,
|
||
|
struct d3d12_device *device, const D3D12_SAMPLER_DESC *desc)
|
||
|
{
|
||
|
+ D3D12_STATIC_BORDER_COLOR static_colour = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
|
||
|
struct vkd3d_view *view;
|
||
|
|
||
|
if (!desc)
|
||
|
@@ -3715,8 +3767,7 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler,
|
||
|
if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER
|
||
|
|| desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER
|
||
|
|| desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER)
|
||
|
- FIXME("Ignoring border color {%.8e, %.8e, %.8e, %.8e}.\n",
|
||
|
- desc->BorderColor[0], desc->BorderColor[1], desc->BorderColor[2], desc->BorderColor[3]);
|
||
|
+ static_colour = d3d12_static_border_colour(desc->BorderColor);
|
||
|
|
||
|
if (!(view = vkd3d_view_create(VKD3D_DESCRIPTOR_MAGIC_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLER,
|
||
|
VKD3D_VIEW_TYPE_SAMPLER, device)))
|
||
|
@@ -3724,9 +3775,9 @@ void d3d12_desc_create_sampler(struct d3d12_desc *sampler,
|
||
|
view->v.u.vk_sampler = VK_NULL_HANDLE;
|
||
|
view->v.format = NULL;
|
||
|
|
||
|
- if (d3d12_create_sampler(device, desc->Filter, desc->AddressU,
|
||
|
- desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy,
|
||
|
- desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, &view->v.u.vk_sampler) < 0)
|
||
|
+ if (d3d12_create_sampler(device, desc->Filter, desc->AddressU, desc->AddressV,
|
||
|
+ desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, desc->ComparisonFunc,
|
||
|
+ static_colour, desc->MinLOD, desc->MaxLOD, &view->v.u.vk_sampler) < 0)
|
||
|
{
|
||
|
vkd3d_view_decref(view, device);
|
||
|
return;
|
||
|
@@ -3740,14 +3791,9 @@ HRESULT vkd3d_create_static_sampler(struct d3d12_device *device,
|
||
|
{
|
||
|
VkResult vr;
|
||
|
|
||
|
- if (desc->AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER
|
||
|
- || desc->AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER
|
||
|
- || desc->AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER)
|
||
|
- FIXME("Ignoring border %#x.\n", desc->BorderColor);
|
||
|
-
|
||
|
- vr = d3d12_create_sampler(device, desc->Filter, desc->AddressU,
|
||
|
- desc->AddressV, desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy,
|
||
|
- desc->ComparisonFunc, desc->MinLOD, desc->MaxLOD, vk_sampler);
|
||
|
+ vr = d3d12_create_sampler(device, desc->Filter, desc->AddressU, desc->AddressV,
|
||
|
+ desc->AddressW, desc->MipLODBias, desc->MaxAnisotropy, desc->ComparisonFunc,
|
||
|
+ desc->BorderColor, desc->MinLOD, desc->MaxLOD, vk_sampler);
|
||
|
return hresult_from_vk_result(vr);
|
||
|
}
|
||
|
|
||
|
@@ -4176,9 +4222,11 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_pool(struct d3d12_descrip
|
||
|
|
||
|
for (set = 0, pool_desc.poolSizeCount = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set)
|
||
|
{
|
||
|
- if (device->vk_descriptor_heap_layouts[set].applicable_heap_type == desc->Type)
|
||
|
+ if (device->vk_descriptor_heap_layouts[set].applicable_heap_type == desc->Type
|
||
|
+ && device->vk_descriptor_heap_layouts[set].vk_set_layout)
|
||
|
{
|
||
|
- pool_sizes[pool_desc.poolSizeCount].type = device->vk_descriptor_heap_layouts[set].type;
|
||
|
+ pool_sizes[pool_desc.poolSizeCount].type = (device->vk_info.EXT_mutable_descriptor_type && !set)
|
||
|
+ ? VK_DESCRIPTOR_TYPE_MUTABLE_EXT : device->vk_descriptor_heap_layouts[set].type;
|
||
|
pool_sizes[pool_desc.poolSizeCount++].descriptorCount = desc->NumDescriptors;
|
||
|
}
|
||
|
}
|
||
|
@@ -4204,6 +4252,16 @@ static HRESULT d3d12_descriptor_heap_create_descriptor_set(struct d3d12_descript
|
||
|
VkDescriptorSetAllocateInfo set_desc;
|
||
|
VkResult vr;
|
||
|
|
||
|
+ if (!device->vk_descriptor_heap_layouts[set].vk_set_layout)
|
||
|
+ {
|
||
|
+ /* Set 0 uses mutable descriptors, and this set is unused. */
|
||
|
+ if (!descriptor_heap->vk_descriptor_sets[0].vk_set)
|
||
|
+ d3d12_descriptor_heap_create_descriptor_set(descriptor_heap, device, 0);
|
||
|
+ descriptor_set->vk_set = descriptor_heap->vk_descriptor_sets[0].vk_set;
|
||
|
+ descriptor_set->vk_type = device->vk_descriptor_heap_layouts[set].type;
|
||
|
+ return S_OK;
|
||
|
+ }
|
||
|
+
|
||
|
set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||
|
set_desc.pNext = &set_size;
|
||
|
set_desc.descriptorPool = descriptor_heap->vk_descriptor_pool;
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c
|
||
|
index 1457ddf9c7f..82782e7d5fc 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d/state.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d/state.c
|
||
|
@@ -848,7 +848,20 @@ static void vkd3d_descriptor_heap_binding_from_descriptor_range(const struct d3d
|
||
|
const struct vkd3d_device_descriptor_limits *descriptor_limits = &root_signature->device->vk_info.descriptor_limits;
|
||
|
unsigned int descriptor_set_size;
|
||
|
|
||
|
- switch (range->type)
|
||
|
+ if (root_signature->device->vk_info.EXT_mutable_descriptor_type)
|
||
|
+ {
|
||
|
+ if (range->type == VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER)
|
||
|
+ {
|
||
|
+ binding->set = VKD3D_SET_INDEX_SAMPLER;
|
||
|
+ descriptor_set_size = descriptor_limits->sampler_max_descriptors;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ binding->set = 0;
|
||
|
+ descriptor_set_size = descriptor_limits->sampled_image_max_descriptors;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ else switch (range->type)
|
||
|
{
|
||
|
case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV:
|
||
|
binding->set = is_buffer ? VKD3D_SET_INDEX_UNIFORM_TEXEL_BUFFER : VKD3D_SET_INDEX_SAMPLED_IMAGE;
|
||
|
@@ -1368,8 +1381,14 @@ static unsigned int d3d12_root_signature_copy_descriptor_set_layouts(const struc
|
||
|
|
||
|
if (device->use_vk_heaps)
|
||
|
{
|
||
|
+ VkDescriptorSetLayout mutable_layout = device->vk_descriptor_heap_layouts[0].vk_set_layout;
|
||
|
+
|
||
|
for (set = 0; set < ARRAY_SIZE(device->vk_descriptor_heap_layouts); ++set)
|
||
|
- vk_set_layouts[i++] = device->vk_descriptor_heap_layouts[set].vk_set_layout;
|
||
|
+ {
|
||
|
+ VkDescriptorSetLayout vk_set_layout = device->vk_descriptor_heap_layouts[set].vk_set_layout;
|
||
|
+ /* All layouts must be valid, so if null, just set it to the mutable one. */
|
||
|
+ vk_set_layouts[i++] = vk_set_layout ? vk_set_layout : mutable_layout;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
return i;
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d/utils.c b/libs/vkd3d/libs/vkd3d/utils.c
|
||
|
index 5ebe1b63e99..751971220e7 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d/utils.c
|
||
|
+++ b/libs/vkd3d/libs/vkd3d/utils.c
|
||
|
@@ -683,7 +683,7 @@ const char *debug_vk_extent_3d(VkExtent3D extent)
|
||
|
|
||
|
const char *debug_vk_queue_flags(VkQueueFlags flags)
|
||
|
{
|
||
|
- char buffer[120];
|
||
|
+ char buffer[159];
|
||
|
|
||
|
buffer[0] = '\0';
|
||
|
#define FLAG_TO_STR(f) if (flags & f) { strcat(buffer, " | "#f); flags &= ~f; }
|
||
|
@@ -691,6 +691,10 @@ const char *debug_vk_queue_flags(VkQueueFlags flags)
|
||
|
FLAG_TO_STR(VK_QUEUE_COMPUTE_BIT)
|
||
|
FLAG_TO_STR(VK_QUEUE_TRANSFER_BIT)
|
||
|
FLAG_TO_STR(VK_QUEUE_SPARSE_BINDING_BIT)
|
||
|
+ FLAG_TO_STR(VK_QUEUE_PROTECTED_BIT)
|
||
|
+#undef FLAG_TO_STR
|
||
|
+#define FLAG_TO_STR(f, n) if (flags & f) { strcat(buffer, " | "#n); flags &= ~f; }
|
||
|
+ FLAG_TO_STR(0x20, VK_QUEUE_VIDEO_DECODE_BIT_KHR)
|
||
|
#undef FLAG_TO_STR
|
||
|
if (flags)
|
||
|
FIXME("Unrecognized flag(s) %#x.\n", flags);
|
||
|
@@ -729,10 +733,8 @@ const char *debug_vk_memory_property_flags(VkMemoryPropertyFlags flags)
|
||
|
FLAG_TO_STR(VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
|
||
|
FLAG_TO_STR(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
|
||
|
FLAG_TO_STR(VK_MEMORY_PROPERTY_PROTECTED_BIT)
|
||
|
-#undef FLAG_TO_STR
|
||
|
-#define FLAG_TO_STR(f, n) if (flags & f) { strcat(buffer, " | "#n); flags &= ~f; }
|
||
|
- FLAG_TO_STR(0x40, VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD)
|
||
|
- FLAG_TO_STR(0x80, VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD)
|
||
|
+ FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD)
|
||
|
+ FLAG_TO_STR(VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD)
|
||
|
#undef FLAG_TO_STR
|
||
|
if (flags)
|
||
|
FIXME("Unrecognized flag(s) %#x.\n", flags);
|
||
|
diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
|
||
|
index bd7e7290d9e..9bf4575d46a 100644
|
||
|
--- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h
|
||
|
+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h
|
||
|
@@ -133,6 +133,7 @@ struct vkd3d_vulkan_info
|
||
|
bool EXT_debug_marker;
|
||
|
bool EXT_depth_clip_enable;
|
||
|
bool EXT_descriptor_indexing;
|
||
|
+ bool EXT_mutable_descriptor_type;
|
||
|
bool EXT_robustness2;
|
||
|
bool EXT_shader_demote_to_helper_invocation;
|
||
|
bool EXT_shader_stencil_export;
|
||
|
@@ -248,7 +249,7 @@ static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond)
|
||
|
static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock)
|
||
|
{
|
||
|
if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE))
|
||
|
- ERR("Could not sleep on the condition variable, error %u.\n", GetLastError());
|
||
|
+ ERR("Could not sleep on the condition variable, error %lu.\n", GetLastError());
|
||
|
}
|
||
|
|
||
|
static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond)
|
||
|
--
|
||
|
2.43.0
|
||
|
|