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