diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-45679a966c73669bdb7fa371569dcc34a44.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-45679a966c73669bdb7fa371569dcc34a44.patch index d9502ad3..6cc7434e 100644 --- a/patches/vkd3d-latest/0001-Updated-vkd3d-to-45679a966c73669bdb7fa371569dcc34a44.patch +++ b/patches/vkd3d-latest/0001-Updated-vkd3d-to-45679a966c73669bdb7fa371569dcc34a44.patch @@ -1,4 +1,4 @@ -From b68e960703095111f31a57b291a710a7be409745 Mon Sep 17 00:00:00 2001 +From adfeedd876396c6bb597e9591c9d0e33d9098aee Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 8 Dec 2023 13:21:19 +1100 Subject: [PATCH] Updated vkd3d to 45679a966c73669bdb7fa371569dcc34a448d8d4. diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-1015cc952e42828d79a68cfa0e659cac537.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-1015cc952e42828d79a68cfa0e659cac537.patch index 365aa946..96e80c8b 100644 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-1015cc952e42828d79a68cfa0e659cac537.patch +++ b/patches/vkd3d-latest/0002-Updated-vkd3d-to-1015cc952e42828d79a68cfa0e659cac537.patch @@ -1,4 +1,4 @@ -From 81c388b185d602d9c66222118abe9dcbd3742a47 Mon Sep 17 00:00:00 2001 +From 08186f2b1b469ddaf890b51d25563f246172bb8b Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Wed, 13 Dec 2023 09:32:05 +1100 Subject: [PATCH] Updated vkd3d to 1015cc952e42828d79a68cfa0e659cac53772676. diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-21491d1bbb168da8aeaa7bdde6e5f182b22.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-21491d1bbb168da8aeaa7bdde6e5f182b22.patch index b82e33fe..70b101b5 100644 --- a/patches/vkd3d-latest/0003-Updated-vkd3d-to-21491d1bbb168da8aeaa7bdde6e5f182b22.patch +++ b/patches/vkd3d-latest/0003-Updated-vkd3d-to-21491d1bbb168da8aeaa7bdde6e5f182b22.patch @@ -1,4 +1,4 @@ -From b2905d22ada20f34d244cac51b1e95f74f3fa85a Mon Sep 17 00:00:00 2001 +From 9a75872b0928bec06328a77b087b07eb32c20f52 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 14 Dec 2023 10:07:09 +1100 Subject: [PATCH] Updated vkd3d to 21491d1bbb168da8aeaa7bdde6e5f182b2205558. diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-f96a791807701a4583e6c613c2f5bd47c00.patch b/patches/vkd3d-latest/0004-Updated-vkd3d-to-f96a791807701a4583e6c613c2f5bd47c00.patch index a0ce1355..2136b44a 100644 --- a/patches/vkd3d-latest/0004-Updated-vkd3d-to-f96a791807701a4583e6c613c2f5bd47c00.patch +++ b/patches/vkd3d-latest/0004-Updated-vkd3d-to-f96a791807701a4583e6c613c2f5bd47c00.patch @@ -1,4 +1,4 @@ -From 688a47c5490ad3b2459b4823ed8ce98fb3b2ddd6 Mon Sep 17 00:00:00 2001 +From aa331ed696532453589a4be7a098626756853e78 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Sat, 16 Dec 2023 09:37:22 +1100 Subject: [PATCH] Updated vkd3d to f96a791807701a4583e6c613c2f5bd47c00ea767. diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-78343dcf87d3a911264c6c9a87a9146c43c.patch b/patches/vkd3d-latest/0005-Updated-vkd3d-to-78343dcf87d3a911264c6c9a87a9146c43c.patch index 4a1cdfbc..94ef4571 100644 --- a/patches/vkd3d-latest/0005-Updated-vkd3d-to-78343dcf87d3a911264c6c9a87a9146c43c.patch +++ b/patches/vkd3d-latest/0005-Updated-vkd3d-to-78343dcf87d3a911264c6c9a87a9146c43c.patch @@ -1,4 +1,4 @@ -From 21b8243f4b07d2ad878fcb9b80580f0e908ca573 Mon Sep 17 00:00:00 2001 +From d4515b0522bca59c215a0d9171ec82cfb9105aae Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Wed, 3 Jan 2024 19:06:40 +1100 Subject: [PATCH] Updated vkd3d to 78343dcf87d3a911264c6c9a87a9146c43c859c3. diff --git a/patches/vkd3d-latest/0005-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch b/patches/vkd3d-latest/0006-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch similarity index 99% rename from patches/vkd3d-latest/0005-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch rename to patches/vkd3d-latest/0006-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch index 0052d2b6..32fbf97f 100644 --- a/patches/vkd3d-latest/0005-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch +++ b/patches/vkd3d-latest/0006-Updated-vkd3d-to-3bafee344d8d50172d8da18512ba070c682.patch @@ -1,4 +1,4 @@ -From 9452917e69ef1a89831a13b7c0d847d1b2cea7df Mon Sep 17 00:00:00 2001 +From b039b38e401b3e9e182c2fb20e7ef7cf8648bd2e Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 4 Jan 2024 12:22:17 +1100 Subject: [PATCH] Updated vkd3d to 3bafee344d8d50172d8da18512ba070c6826b18d. diff --git a/patches/vkd3d-latest/0006-include-Add-more-D3D_FEATURE_LEVEL_-defines.patch b/patches/vkd3d-latest/0007-include-Add-more-D3D_FEATURE_LEVEL_-defines.patch similarity index 93% rename from patches/vkd3d-latest/0006-include-Add-more-D3D_FEATURE_LEVEL_-defines.patch rename to patches/vkd3d-latest/0007-include-Add-more-D3D_FEATURE_LEVEL_-defines.patch index 56899911..293b79f3 100644 --- a/patches/vkd3d-latest/0006-include-Add-more-D3D_FEATURE_LEVEL_-defines.patch +++ b/patches/vkd3d-latest/0007-include-Add-more-D3D_FEATURE_LEVEL_-defines.patch @@ -1,4 +1,4 @@ -From 5afe7a3efe397c0d59ee64df5060257f0fadf0b9 Mon Sep 17 00:00:00 2001 +From 0c8d2be596270def5721fe0ae2d11732e63f6b3b Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 4 Jan 2024 12:27:13 +1100 Subject: [PATCH] include: Add more D3D_FEATURE_LEVEL_ defines diff --git a/patches/vkd3d-latest/0007-Updated-vkd3d-to-50cebc72780dada0822a1d081f3247f7d1d.patch b/patches/vkd3d-latest/0008-Updated-vkd3d-to-50cebc72780dada0822a1d081f3247f7d1d.patch similarity index 99% rename from patches/vkd3d-latest/0007-Updated-vkd3d-to-50cebc72780dada0822a1d081f3247f7d1d.patch rename to patches/vkd3d-latest/0008-Updated-vkd3d-to-50cebc72780dada0822a1d081f3247f7d1d.patch index 46bcaae1..d3c12abf 100644 --- a/patches/vkd3d-latest/0007-Updated-vkd3d-to-50cebc72780dada0822a1d081f3247f7d1d.patch +++ b/patches/vkd3d-latest/0008-Updated-vkd3d-to-50cebc72780dada0822a1d081f3247f7d1d.patch @@ -1,4 +1,4 @@ -From 7fb898ef917d76fc44c94a90abb2aa747b8693ef Mon Sep 17 00:00:00 2001 +From a725516a5c0da2fe2a145f231a99359ecf942627 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 5 Jan 2024 11:03:00 +1100 Subject: [PATCH] Updated vkd3d to 50cebc72780dada0822a1d081f3247f7d1dbc728. diff --git a/patches/vkd3d-latest/0008-Updated-vkd3d-to-bb64bfff6334c847d06d219840882ec7576.patch b/patches/vkd3d-latest/0009-Updated-vkd3d-to-bb64bfff6334c847d06d219840882ec7576.patch similarity index 99% rename from patches/vkd3d-latest/0008-Updated-vkd3d-to-bb64bfff6334c847d06d219840882ec7576.patch rename to patches/vkd3d-latest/0009-Updated-vkd3d-to-bb64bfff6334c847d06d219840882ec7576.patch index bd03007d..2a88f800 100644 --- a/patches/vkd3d-latest/0008-Updated-vkd3d-to-bb64bfff6334c847d06d219840882ec7576.patch +++ b/patches/vkd3d-latest/0009-Updated-vkd3d-to-bb64bfff6334c847d06d219840882ec7576.patch @@ -1,4 +1,4 @@ -From 85e4bc576b58a0b88844554c8713a1a998ba7cca Mon Sep 17 00:00:00 2001 +From 6ccc482e5f14536495247b88d67743b818a45044 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Wed, 10 Jan 2024 07:40:09 +1100 Subject: [PATCH] Updated vkd3d to bb64bfff6334c847d06d219840882ec75766b330. diff --git a/patches/vkd3d-latest/0010-Updated-vkd3d-to-3e2ace8d33a203bf0c8d6a7bf140ef9a9a0.patch b/patches/vkd3d-latest/0010-Updated-vkd3d-to-3e2ace8d33a203bf0c8d6a7bf140ef9a9a0.patch new file mode 100644 index 00000000..1f7e94d9 --- /dev/null +++ b/patches/vkd3d-latest/0010-Updated-vkd3d-to-3e2ace8d33a203bf0c8d6a7bf140ef9a9a0.patch @@ -0,0 +1,1460 @@ +From 6a3728b4a23434276c39df90387800b72386cd3c Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Sat, 13 Jan 2024 11:46:16 +1100 +Subject: [PATCH] Updated vkd3d to 3e2ace8d33a203bf0c8d6a7bf140ef9a9a08352d. + +--- + libs/vkd3d/Makefile.in | 1 + + libs/vkd3d/include/private/vkd3d_common.h | 1 + + libs/vkd3d/include/vkd3d_shader.h | 7 + + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 60 ++++++- + libs/vkd3d/libs/vkd3d-shader/dxbc.c | 34 ++-- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 12 +- + libs/vkd3d/libs/vkd3d-shader/fx.c | 158 ++++++++++++++++++ + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 77 +++++++-- + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 13 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.l | 1 + + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 81 ++++++++- + libs/vkd3d/libs/vkd3d-shader/ir.c | 8 +- + libs/vkd3d/libs/vkd3d-shader/spirv.c | 40 ++--- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 11 +- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 36 +++- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 6 +- + libs/vkd3d/libs/vkd3d/command.c | 3 +- + libs/vkd3d/libs/vkd3d/device.c | 42 ++++- + libs/vkd3d/libs/vkd3d/resource.c | 22 ++- + libs/vkd3d/libs/vkd3d/state.c | 23 ++- + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 3 +- + 21 files changed, 548 insertions(+), 91 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..54fe1ca5017 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') +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/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 c744dfcedf0..869a709d63f 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; + } + +diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c +new file mode 100644 +index 00000000000..6c4c1203d48 +--- /dev/null ++++ b/libs/vkd3d/libs/vkd3d-shader/fx.c +@@ -0,0 +1,158 @@ ++/* ++ * 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 fx_write_context ++{ ++ struct vkd3d_bytecode_buffer unstructured; ++ struct vkd3d_bytecode_buffer structured; ++ ++ uint32_t technique_count; ++ int status; ++}; ++ ++static uint32_t fx_put_raw_string(struct fx_write_context *fx, const char *string) ++{ ++ /* NULLs are emitted as empty strings using the same 4 bytes at the start of the section. */ ++ return string ? put_string(&fx->unstructured, string) : 0; ++} ++ ++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; ++ ++ name_offset = fx_put_raw_string(fx, var->name); ++ put_u32(buffer, name_offset); ++ put_u32(buffer, 0); /* Pass count. */ ++ put_u32(buffer, 0); /* Annotation count. */ ++ ++ /* TODO: passes */ ++} ++ ++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 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; ++ ++ memset(&fx, 0, sizeof(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.status; ++} ++ ++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) ++ { ++ hlsl_fixme(ctx, &ctx->location, "Writing fx_5_0 binaries is not implemented."); ++ return VKD3D_ERROR_NOT_IMPLEMENTED; ++ } ++ else ++ { ++ vkd3d_unreachable(); ++ } ++} +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +index a41967876a2..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 (decl->name) + { +- if (!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) ++ 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,6 +918,11 @@ 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; + } +@@ -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; + } +@@ -3351,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) +@@ -3461,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, +@@ -3596,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); +@@ -3608,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; +@@ -3632,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 b56dea10f4c..8bc98b99e8a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +@@ -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; + +@@ -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. +@@ -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 +@@ -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); +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 26f9357419b..7424e63a478 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -1096,6 +1096,55 @@ 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, 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; ++ ++ 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}; +@@ -4888,6 +4937,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 +@@ -5094,7 +5144,8 @@ hlsl_prog: + destroy_block($2); + } + | hlsl_prog preproc_directive +- | hlsl_prog technique ++ | hlsl_prog global_technique ++ | hlsl_prog effect_group + | hlsl_prog ';' + + technique_name: +@@ -5110,7 +5161,8 @@ pass_list: + technique9: + KW_TECHNIQUE technique_name '{' pass_list '}' + { +- hlsl_fixme(ctx, &@$, "Unsupported \'technique\' declaration."); ++ if (!add_technique(ctx, $2, "technique", &@1)) ++ YYABORT; + } + + technique10: +@@ -5120,7 +5172,8 @@ technique10: + 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, "technique10", &@1)) ++ YYABORT; + } + + technique11: +@@ -5130,14 +5183,32 @@ technique11: + 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, "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 + { +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index bac4269198b..9fd60fa76a4 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; + } + } +@@ -1116,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; + } + } +@@ -1310,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); + } + } + +diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c +index 987197887de..a9e02d0a98e 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/spirv.c ++++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c +@@ -2198,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; +@@ -3370,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) +@@ -3997,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; +@@ -4011,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; +@@ -4027,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) +@@ -4050,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; + +@@ -4059,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; + +@@ -7068,7 +7068,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); +@@ -7370,7 +7370,7 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp + 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; +@@ -7427,8 +7427,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); +@@ -7460,8 +7460,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); +@@ -8226,7 +8226,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; +@@ -8300,7 +8300,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]; +@@ -8416,7 +8416,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 +@@ -8476,13 +8476,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) + { +@@ -8791,7 +8791,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); +@@ -8834,7 +8834,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); +@@ -9000,7 +9000,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; +diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c +index 2cc56663efe..43b3525bb7b 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"); +@@ -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, +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 224d27f4e1b..cc156f88074 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -1126,8 +1126,8 @@ struct vkd3d_shader_instruction + 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; +@@ -1357,7 +1357,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) + { +diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c +index 013b5d0751f..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, +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 f4ce1ccaffa..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; +@@ -4220,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; + } + } +@@ -4248,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/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 +