wine-staging/patches/vkd3d-latest/0002-Updated-vkd3d-to-68b898fcb6b4ab2a9660f35edf3554465ab.patch

3189 lines
134 KiB
Diff
Raw Normal View History

2024-01-23 17:28:57 -08:00
From 9190b1dd7de2cb8c8be10168cab2bfd48339fc90 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(&reg->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, &param->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, &param->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, &param->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