From 0806cca6d0c3d59da09a8b7a429165261710a047 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 13 Jun 2025 07:50:21 +1000 Subject: [PATCH] Updated vkd3d to a8ca1f95c50561a16de5769646dcda0c045b7a46. --- libs/vkd3d/include/private/vkd3d_common.h | 1 + libs/vkd3d/include/private/vkd3d_version.h | 2 +- libs/vkd3d/libs/vkd3d-shader/dxil.c | 117 +++++++- libs/vkd3d/libs/vkd3d-shader/fx.c | 328 +++++++++++++++------ libs/vkd3d/libs/vkd3d-shader/ir.c | 40 +-- libs/vkd3d/libs/vkd3d-shader/msl.c | 28 +- libs/vkd3d/libs/vkd3d-shader/spirv.c | 92 +----- 7 files changed, 397 insertions(+), 211 deletions(-) diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h index 93c8a0bec7c..0501e6a06c2 100644 --- a/libs/vkd3d/include/private/vkd3d_common.h +++ b/libs/vkd3d/include/private/vkd3d_common.h @@ -66,6 +66,7 @@ #define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9') #define TAG_CLI4 VKD3D_MAKE_TAG('C', 'L', 'I', '4') +#define TAG_CLIT VKD3D_MAKE_TAG('C', 'L', 'I', 'T') #define TAG_CTAB VKD3D_MAKE_TAG('C', 'T', 'A', 'B') #define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C') #define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L') diff --git a/libs/vkd3d/include/private/vkd3d_version.h b/libs/vkd3d/include/private/vkd3d_version.h index ae34ff97e25..687751d6a5f 100644 --- a/libs/vkd3d/include/private/vkd3d_version.h +++ b/libs/vkd3d/include/private/vkd3d_version.h @@ -1 +1 @@ -#define VKD3D_VCS_ID " (git 379b297d)" +#define VKD3D_VCS_ID " (git a8ca1f95)" diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index 1cbef387260..53578ce7141 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -2499,6 +2499,79 @@ static enum vkd3d_data_type vkd3d_data_type_from_sm6_type(const struct sm6_type return VKD3D_DATA_UINT; } +/* Based on the implementation in the OpenGL Mathematics library. */ +static uint32_t half_to_float(uint16_t value) +{ + uint32_t s = (value & 0x8000u) << 16; + uint32_t e = (value >> 10) & 0x1fu; + uint32_t m = value & 0x3ffu; + + if (!e) + { + if (!m) + { + /* Plus or minus zero */ + return s; + } + else + { + /* Denormalized number -- renormalize it */ + while (!(m & 0x400u)) + { + m <<= 1; + --e; + } + + ++e; + m &= ~0x400u; + } + } + else if (e == 31u) + { + /* Positive or negative infinity for zero 'm'. + * Nan for non-zero 'm' -- preserve sign and significand bits */ + return s | 0x7f800000u | (m << 13); + } + + /* Normalized number */ + e += 127u - 15u; + m <<= 13; + + /* Assemble s, e and m. */ + return s | (e << 23) | m; +} + +static void register_convert_to_minimum_precision(struct vkd3d_shader_register *reg) +{ + unsigned int i; + + switch (reg->data_type) + { + case VKD3D_DATA_HALF: + reg->data_type = VKD3D_DATA_FLOAT; + reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_FLOAT_16; + if (reg->type == VKD3DSPR_IMMCONST) + { + for (i = 0; i < VSIR_DIMENSION_VEC4; ++i) + reg->u.immconst_u32[i] = half_to_float(reg->u.immconst_u32[i]); + } + break; + + case VKD3D_DATA_UINT16: + reg->data_type = VKD3D_DATA_UINT; + reg->precision = VKD3D_SHADER_REGISTER_PRECISION_MIN_UINT_16; + if (reg->type == VKD3DSPR_IMMCONST) + { + for (i = 0; i < VSIR_DIMENSION_VEC4; ++i) + reg->u.immconst_u32[i] = (int16_t)reg->u.immconst_u32[i]; + } + break; + + default: + break; + } +} + static void register_index_address_init(struct vkd3d_shader_register_index *idx, const struct sm6_value *address, struct sm6_parser *sm6); @@ -2516,6 +2589,7 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str case VALUE_TYPE_SSA: register_init_with_id(reg, VKD3DSPR_SSA, data_type, value->u.ssa.id); reg->dimension = sm6_type_is_scalar(value->type) ? VSIR_DIMENSION_SCALAR : VSIR_DIMENSION_VEC4; + register_convert_to_minimum_precision(reg); break; case VALUE_TYPE_ICB: @@ -2523,6 +2597,7 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str reg->idx[0].offset = value->u.icb.id; register_index_address_init(®->idx[1], value->u.icb.index.index, sm6); reg->idx[1].is_in_bounds = value->u.icb.index.is_in_bounds; + register_convert_to_minimum_precision(reg); break; case VALUE_TYPE_IDXTEMP: @@ -2530,6 +2605,7 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str reg->idx[0].offset = value->u.idxtemp.id; register_index_address_init(®->idx[1], value->u.idxtemp.index.index, sm6); reg->idx[1].is_in_bounds = value->u.idxtemp.index.is_in_bounds; + register_convert_to_minimum_precision(reg); break; case VALUE_TYPE_GROUPSHAREDMEM: @@ -2543,6 +2619,7 @@ static void sm6_register_from_value(struct vkd3d_shader_register *reg, const str vsir_register_init(reg, scalar_type->u.width == 64 ? VKD3DSPR_IMMCONST64 : VKD3DSPR_IMMCONST, data_type, 0); reg->u = value->u.constant.immconst; + register_convert_to_minimum_precision(reg); break; case VALUE_TYPE_UNDEFINED: @@ -3105,6 +3182,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co struct vkd3d_shader_immediate_constant_buffer *icb; const struct sm6_type *elem_type; unsigned int i, size, count; + uint64_t *data64; elem_type = type->u.array.elem_type; /* Multidimensional arrays are emitted in flattened form. */ @@ -3156,16 +3234,37 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co return VKD3D_OK; count = type->u.array.count; - if (size > sizeof(icb->data[0])) - { - uint64_t *data = (uint64_t *)icb->data; - for (i = 0; i < count; ++i) - data[i] = operands[i]; - } - else + switch (icb->data_type) { - for (i = 0; i < count; ++i) - icb->data[i] = operands[i]; + case VKD3D_DATA_HALF: + for (i = 0; i < count; ++i) + icb->data[i] = half_to_float(operands[i]); + icb->data_type = VKD3D_DATA_FLOAT; + break; + + case VKD3D_DATA_UINT16: + for (i = 0; i < count; ++i) + icb->data[i] = (int16_t)operands[i]; + icb->data_type = VKD3D_DATA_UINT; + break; + + case VKD3D_DATA_FLOAT: + case VKD3D_DATA_UINT: + for (i = 0; i < count; ++i) + icb->data[i] = operands[i]; + break; + + case VKD3D_DATA_DOUBLE: + case VKD3D_DATA_UINT64: + data64 = (uint64_t *)icb->data; + for (i = 0; i < count; ++i) + data64[i] = operands[i]; + break; + + default: + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid array of type %u.", icb->data_type); + return VKD3D_ERROR_INVALID_SHADER; } return VKD3D_OK; diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c index 9efaa0bc1fa..f7b2e3d7d13 100644 --- a/libs/vkd3d/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d/libs/vkd3d-shader/fx.c @@ -54,6 +54,19 @@ enum state_property_component_type FX_COMPONENT_TYPE_COUNT, }; +enum fxlvm_constants +{ + FX_FXLC_COMP_COUNT_MASK = 0xffff, + FX_FXLC_OPCODE_MASK = 0x7ff, + FX_FXLC_OPCODE_SHIFT = 20, + FX_FXLC_IS_SCALAR_MASK = 0x80000000, + + FX_FXLC_REG_LITERAL = 1, + FX_FXLC_REG_CB = 2, + FX_FXLC_REG_OUTPUT = 4, + FX_FXLC_REG_TEMP = 7, +}; + struct rhs_named_value { const char *name; @@ -1079,17 +1092,6 @@ enum fx_4_type_constants FX_4_ASSIGNMENT_VALUE_EXPRESSION = 0x6, FX_4_ASSIGNMENT_INLINE_SHADER = 0x7, FX_5_ASSIGNMENT_INLINE_SHADER = 0x8, - - /* FXLVM constants */ - FX_4_FXLC_COMP_COUNT_MASK = 0xffff, - FX_4_FXLC_OPCODE_MASK = 0x7ff, - FX_4_FXLC_OPCODE_SHIFT = 20, - FX_4_FXLC_IS_SCALAR_MASK = 0x80000000, - - FX_4_FXLC_REG_LITERAL = 1, - FX_4_FXLC_REG_CB = 2, - FX_4_FXLC_REG_OUTPUT = 4, - FX_4_FXLC_REG_TEMP = 7, }; static const uint32_t fx_4_numeric_base_types[] = @@ -4268,6 +4270,8 @@ static void fx_dump_blob(struct fx_parser *parser, const void *blob, uint32_t si } } +static void fx_2_parse_fxlvm_expression(struct fx_parser *parser, const uint32_t *blob, uint32_t size); + static void fx_parse_fx_2_array_selector(struct fx_parser *parser) { uint32_t size, blob_size = 0; @@ -4295,7 +4299,7 @@ static void fx_parse_fx_2_array_selector(struct fx_parser *parser) { parse_fx_print_indent(parser); vkd3d_string_buffer_printf(&parser->buffer, "selector blob size %u\n", blob_size); - fx_dump_blob(parser, blob, blob_size); + fx_2_parse_fxlvm_expression(parser, blob, blob_size); } } @@ -4718,7 +4722,7 @@ static const struct uint32_t opcode; const char *name; } -fx_4_fxlc_opcodes[] = +fxlc_opcodes[] = { { 0x100, "mov" }, { 0x101, "neg" }, @@ -4773,14 +4777,14 @@ fx_4_fxlc_opcodes[] = { 0x70e, "d3ds_dotswiz" }, }; -static const char *fx_4_get_fxlc_opcode_name(uint32_t opcode) +static const char *get_fxlc_opcode_name(uint32_t opcode) { size_t i; - for (i = 0; i < ARRAY_SIZE(fx_4_fxlc_opcodes); ++i) + for (i = 0; i < ARRAY_SIZE(fxlc_opcodes); ++i) { - if (fx_4_fxlc_opcodes[i].opcode == opcode) - return fx_4_fxlc_opcodes[i].name; + if (fxlc_opcodes[i].opcode == opcode) + return fxlc_opcodes[i].name; } return ""; @@ -4804,10 +4808,29 @@ struct fx_4_ctab_entry uint32_t default_value; }; +struct fxlc_arg +{ + uint32_t reg_type; + uint32_t address; + bool indexed; + struct + { + uint32_t reg_type; + uint32_t address; + } index; +}; + struct fxlvm_code { - const float *cli4; - uint32_t cli4_count; + const uint32_t *ptr, *end; + bool failed; + + union + { + const float *_4; + const double *_8; + } cli; + uint32_t cli_count; const struct fx_4_ctab_entry *constants; uint32_t ctab_offset; @@ -4818,7 +4841,45 @@ struct fxlvm_code bool scalar; }; -static void fx_4_parse_print_swizzle(struct fx_parser *parser, const struct fxlvm_code *code, unsigned int addr) +static uint32_t fxlvm_read_u32(struct fxlvm_code *code) +{ + if (code->end == code->ptr) + { + code->failed = true; + return 0; + } + + return *code->ptr++; +} + +static const uint32_t *find_d3dbc_section(const uint32_t *ptr, uint32_t count, uint32_t tag, uint32_t *size) +{ + if (!count) + return NULL; + + /* Skip version tag */ + ptr++; + count--; + + while (count > 2 && (*ptr & 0xffff) == 0xfffe) + { + unsigned int section_size; + + section_size = (*ptr >> 16); + if (!section_size || section_size + 1 > count) + break; + if (*(ptr + 1) == tag) + { + *size = section_size; + return ptr + 2; + } + count -= section_size + 1; + ptr += section_size + 1; + } + return NULL; +} + +static void fx_parse_print_swizzle(struct fx_parser *parser, const struct fxlvm_code *code, unsigned int addr) { unsigned int comp_count = code->scalar ? 1 : code->comp_count; static const char comp[] = "xyzw"; @@ -4827,44 +4888,76 @@ static void fx_4_parse_print_swizzle(struct fx_parser *parser, const struct fxlv vkd3d_string_buffer_printf(&parser->buffer, ".%.*s", comp_count, &comp[addr % 4]); } -static void fx_4_parse_fxlc_constant_argument(struct fx_parser *parser, - const struct fx_4_fxlc_argument *arg, const struct fxlvm_code *code) +static void fx_parse_fxlc_constant_argument(struct fx_parser *parser, + const struct fxlc_arg *arg, const struct fxlvm_code *code) { - uint32_t i, offset, register_index = arg->address / 4; /* Address counts in components. */ + uint32_t register_index = arg->address / 4; /* Address counts in components. */ - for (i = 0; i < code->ctab_count; ++i) + if (code->ctab_count) { - const struct fx_4_ctab_entry *c = &code->constants[i]; + uint32_t i, offset; - if (register_index < c->register_index || register_index - c->register_index >= c->register_count) - continue; + for (i = 0; i < code->ctab_count; ++i) + { + const struct fx_4_ctab_entry *c = &code->constants[i]; - vkd3d_string_buffer_printf(&parser->buffer, "%s", &code->ctab[c->name]); + if (register_index < c->register_index || register_index - c->register_index >= c->register_count) + continue; - /* Register offset within variable */ - offset = arg->address - c->register_index * 4; + vkd3d_string_buffer_printf(&parser->buffer, "%s", &code->ctab[c->name]); - if (offset / 4) - vkd3d_string_buffer_printf(&parser->buffer, "[%u]", offset / 4); - fx_4_parse_print_swizzle(parser, code, offset); - return; + /* Register offset within variable */ + offset = arg->address - c->register_index * 4; + + if (offset / 4) + vkd3d_string_buffer_printf(&parser->buffer, "[%u]", offset / 4); + fx_parse_print_swizzle(parser, code, offset); + return; + } + + vkd3d_string_buffer_printf(&parser->buffer, "(var-not-found)"); + } + else + { + vkd3d_string_buffer_printf(&parser->buffer, "c%u", register_index); + fx_parse_print_swizzle(parser, code, arg->address); + } +} + +static void fx_parse_fxlc_argument(struct fx_parser *parser, struct fxlc_arg *arg, struct fxlvm_code *code) +{ + uint32_t flags; + + memset(arg, 0, sizeof(*arg)); + + flags = fxlvm_read_u32(code); + if (flags) + { + arg->indexed = true; + arg->index.reg_type = fxlvm_read_u32(code); + arg->index.address = fxlvm_read_u32(code); } + arg->reg_type = fxlvm_read_u32(code); + arg->address = fxlvm_read_u32(code); +} - vkd3d_string_buffer_printf(&parser->buffer, "(var-not-found)"); +static void fx_print_fxlc_literal(struct fx_parser *parser, uint32_t address, struct fxlvm_code *code) +{ + if (parser->version.major >= 4) + vkd3d_string_buffer_print_f32(&parser->buffer, code->cli._4[address]); + else + vkd3d_string_buffer_print_f64(&parser->buffer, code->cli._8[address]); } -static void fx_4_parse_fxlc_argument(struct fx_parser *parser, uint32_t offset, const struct fxlvm_code *code) +static void fx_print_fxlc_argument(struct fx_parser *parser, const struct fxlc_arg *arg, struct fxlvm_code *code) { - struct fx_4_fxlc_argument arg; uint32_t count; - fx_parser_read_unstructured(parser, &arg, offset, sizeof(arg)); - - switch (arg.reg_type) + switch (arg->reg_type) { - case FX_4_FXLC_REG_LITERAL: + case FX_FXLC_REG_LITERAL: count = code->scalar ? 1 : code->comp_count; - if (arg.address >= code->cli4_count || count > code->cli4_count - arg.address) + if (arg->address >= code->cli_count || count > code->cli_count - arg->address) { vkd3d_string_buffer_printf(&parser->buffer, "()"); parser->failed = true; @@ -4872,42 +4965,120 @@ static void fx_4_parse_fxlc_argument(struct fx_parser *parser, uint32_t offset, } vkd3d_string_buffer_printf(&parser->buffer, "("); - vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg.address]); + fx_print_fxlc_literal(parser, arg->address, code); for (unsigned int i = 1; i < code->comp_count; ++i) { vkd3d_string_buffer_printf(&parser->buffer, ", "); - vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg.address + (code->scalar ? 0 : i)]); + fx_print_fxlc_literal(parser, arg->address + (code->scalar ? 0 : i), code); } vkd3d_string_buffer_printf(&parser->buffer, ")"); break; - case FX_4_FXLC_REG_CB: - fx_4_parse_fxlc_constant_argument(parser, &arg, code); + case FX_FXLC_REG_CB: + fx_parse_fxlc_constant_argument(parser, arg, code); break; - case FX_4_FXLC_REG_OUTPUT: - case FX_4_FXLC_REG_TEMP: - if (arg.reg_type == FX_4_FXLC_REG_OUTPUT) + case FX_FXLC_REG_OUTPUT: + case FX_FXLC_REG_TEMP: + if (arg->reg_type == FX_FXLC_REG_OUTPUT) vkd3d_string_buffer_printf(&parser->buffer, "expr"); else - vkd3d_string_buffer_printf(&parser->buffer, "r%u", arg.address / 4); - fx_4_parse_print_swizzle(parser, code, arg.address); + vkd3d_string_buffer_printf(&parser->buffer, "r%u", arg->address / 4); + fx_parse_print_swizzle(parser, code, arg->address); break; default: - vkd3d_string_buffer_printf(&parser->buffer, "", arg.reg_type); + vkd3d_string_buffer_printf(&parser->buffer, "", arg->reg_type); + break; + } +} + +static void fx_parse_fxlvm_expression(struct fx_parser *parser, struct fxlvm_code *code) +{ + struct fxlc_arg args[9]; + uint32_t ins_count; + size_t i, j; + + ins_count = fxlvm_read_u32(code); + + parse_fx_start_indent(parser); + + for (i = 0; i < ins_count; ++i) + { + uint32_t instr, opcode, src_count; + + instr = fxlvm_read_u32(code); + src_count = fxlvm_read_u32(code); + + if (src_count >= ARRAY_SIZE(args)) + { + fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, + "Unexpected instruction source count %u.", src_count); break; + } + + /* Sources entries are followed by the destination, first read them all. + Output format is "opcode dst, src[0]...src[n]". */ + for (j = 0; j < src_count; ++j) + fx_parse_fxlc_argument(parser, &args[j], code); + fx_parse_fxlc_argument(parser, &args[src_count], code); + + opcode = (instr >> FX_FXLC_OPCODE_SHIFT) & FX_FXLC_OPCODE_MASK; + code->comp_count = instr & FX_FXLC_COMP_COUNT_MASK; + + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "%s ", get_fxlc_opcode_name(opcode)); + + code->scalar = false; + fx_print_fxlc_argument(parser, &args[src_count], code); + vkd3d_string_buffer_printf(&parser->buffer, ", "); + + for (j = 0; j < src_count; ++j) + { + /* Scalar modifier applies only to the first source. */ + code->scalar = j == 0 && !!(instr & FX_FXLC_IS_SCALAR_MASK); + fx_print_fxlc_argument(parser, &args[j], code); + if (j < src_count - 1) + vkd3d_string_buffer_printf(&parser->buffer, ", "); + } + + vkd3d_string_buffer_printf(&parser->buffer, "\n"); } + + parse_fx_end_indent(parser); +} + +static void fx_2_parse_fxlvm_expression(struct fx_parser *parser, const uint32_t *blob, uint32_t size) +{ + uint32_t count = size / sizeof(uint32_t); + struct fxlvm_code code = { 0 }; + uint32_t section_size; + const uint32_t *data; + + /* Literal constants, using 64-bit floats. */ + if ((data = find_d3dbc_section(blob, count, TAG_CLIT, §ion_size))) + { + code.cli_count = *data++; + code.cli._8 = (const double *)data; + } + + /* CTAB does not contain variable names */ + + /* Code blob */ + code.ptr = find_d3dbc_section(blob, count, TAG_FXLC, &count); + code.end = code.ptr + count; + + fx_parse_fxlvm_expression(parser, &code); } static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offset) { struct vkd3d_shader_dxbc_section_desc *section, fxlc, cli4, ctab; struct vkd3d_shader_dxbc_desc dxbc_desc; + struct fxlvm_code code = { 0 }; struct vkd3d_shader_code dxbc; - uint32_t size, ins_count; - struct fxlvm_code code; - size_t i, j; + uint32_t size; + size_t i; offset = fx_parser_read_unstructured(parser, &size, offset, sizeof(size)); @@ -4943,8 +5114,8 @@ static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offse { uint32_t cli4_offset = offset + (size_t)cli4.data.code - (size_t)dxbc.code; - fx_parser_read_unstructured(parser, &code.cli4_count, cli4_offset, sizeof(code.cli4_count)); - code.cli4 = fx_parser_get_unstructured_ptr(parser, cli4_offset + 4, code.cli4_count * sizeof(float)); + fx_parser_read_unstructured(parser, &code.cli_count, cli4_offset, sizeof(code.cli_count)); + code.cli._4 = fx_parser_get_unstructured_ptr(parser, cli4_offset + 4, code.cli_count * sizeof(float)); } if (ctab.data.code) @@ -4960,47 +5131,10 @@ static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offse ctab_offset + consts_offset, code.ctab_count * sizeof(*code.constants)); } - offset += (size_t)fxlc.data.code - (size_t)dxbc.code; - offset = fx_parser_read_unstructured(parser, &ins_count, offset, sizeof(ins_count)); - - parse_fx_start_indent(parser); - - for (i = 0; i < ins_count; ++i) - { - uint32_t instr, opcode, src_count; - struct fx_4_fxlc_argument arg; - - offset = fx_parser_read_unstructured(parser, &instr, offset, sizeof(instr)); - offset = fx_parser_read_unstructured(parser, &src_count, offset, sizeof(src_count)); + code.ptr = fxlc.data.code; + code.end = (uint32_t *)((uint8_t *)fxlc.data.code + fxlc.data.size); - opcode = (instr >> FX_4_FXLC_OPCODE_SHIFT) & FX_4_FXLC_OPCODE_MASK; - code.comp_count = instr & FX_4_FXLC_COMP_COUNT_MASK; - code.scalar = false; - - parse_fx_print_indent(parser); - vkd3d_string_buffer_printf(&parser->buffer, "%s ", fx_4_get_fxlc_opcode_name(opcode)); - - /* Destination first. */ - fx_4_parse_fxlc_argument(parser, offset + sizeof(arg) * src_count, &code); - - for (j = 0; j < src_count; ++j) - { - vkd3d_string_buffer_printf(&parser->buffer, ", "); - - /* Scalar modifier applies only to first source. */ - code.scalar = j == 0 && !!(instr & FX_4_FXLC_IS_SCALAR_MASK); - fx_4_parse_fxlc_argument(parser, offset, &code); - - offset += sizeof(arg); - } - - /* Destination */ - offset += sizeof(arg); - - vkd3d_string_buffer_printf(&parser->buffer, "\n"); - } - - parse_fx_end_indent(parser); + fx_parse_fxlvm_expression(parser, &code); } static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32_t count, diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index 1925e20c685..0aebfea2add 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -8727,8 +8727,9 @@ static void vsir_validate_dst_count(struct validation_context *ctx, { if (instruction->dst_count != count) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, - "Invalid destination count %u for an instruction of type %#x, expected %u.", - instruction->dst_count, instruction->opcode, count); + "Invalid destination parameter count %u for instruction \"%s\" (%#x); expected %u.", + instruction->dst_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); } static void vsir_validate_src_count(struct validation_context *ctx, @@ -8736,8 +8737,9 @@ static void vsir_validate_src_count(struct validation_context *ctx, { if (instruction->src_count != count) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, - "Invalid source count %u for an instruction of type %#x, expected %u.", - instruction->src_count, instruction->opcode, count); + "Invalid source parameter count %u for instruction \"%s\" (%#x); expected %u.", + instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); } static bool vsir_validate_src_min_count(struct validation_context *ctx, @@ -8746,8 +8748,9 @@ static bool vsir_validate_src_min_count(struct validation_context *ctx, if (instruction->src_count < count) { validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, - "Invalid source count %u for an instruction of type %#x, expected at least %u.", - instruction->src_count, instruction->opcode, count); + "Invalid source parameter count %u for instruction \"%s\" (%#x); expected at least %u.", + instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); return false; } @@ -8760,8 +8763,9 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx, if (instruction->src_count > count) { validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, - "Invalid source count %u for an instruction of type %#x, expected at most %u.", - instruction->src_count, instruction->opcode, count); + "Invalid source parameter count %u for instruction \"%s\" (%#x); expected at most %u.", + instruction->src_count, vsir_opcode_get_name(instruction->opcode, ""), + instruction->opcode, count); return false; } @@ -9249,7 +9253,9 @@ static void vsir_validate_cf_type(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction, enum vsir_control_flow_type expected_type) { if (ctx->program->cf_type != expected_type) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x in %s shader.", + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, + "Invalid instruction \"%s\" (%#x) in %s shader.", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode, name_from_cf_type(ctx->program->cf_type)); } @@ -9268,12 +9274,12 @@ static void vsir_validate_hull_shader_phase(struct validation_context *ctx, { if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, - "Phase instruction %#x is only valid in a hull shader.", - instruction->opcode); + "Phase instruction \"%s\" (%#x) is only valid in a hull shader.", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); if (ctx->depth != 0) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, - "Phase instruction %#x must appear to top level.", - instruction->opcode); + "Phase instruction \"%s\" (%#x) must appear at the top level.", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); ctx->phase = instruction->opcode; ctx->dcl_temps_found = false; } @@ -10038,8 +10044,8 @@ static void vsir_validate_instruction(struct validation_context *ctx) default: if (!vsir_instruction_is_dcl(instruction)) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, - "Instruction %#x appear before any phase instruction in a hull shader.", - instruction->opcode); + "Instruction \"%s\" (%#x) appears before any phase instruction in a hull shader.", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); break; } } @@ -10059,8 +10065,8 @@ static void vsir_validate_instruction(struct validation_context *ctx) default: if (!vsir_instruction_is_dcl(instruction)) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, - "Invalid instruction %#x outside any block.", - instruction->opcode); + "Invalid instruction \"%s\" (%#x) outside any block.", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); break; } } diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c index 47ea6ce1f4b..08519787b0a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/msl.c +++ b/libs/vkd3d/libs/vkd3d-shader/msl.c @@ -612,10 +612,12 @@ static void VKD3D_PRINTF_FUNC(3, 4) msl_print_assignment( static void msl_unhandled(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins) { + const char *name = vsir_opcode_get_name(ins->opcode, ""); + msl_print_indent(gen->buffer, gen->indent); - vkd3d_string_buffer_printf(gen->buffer, "/* */\n", ins->opcode); + vkd3d_string_buffer_printf(gen->buffer, "/* */\n", name, ins->opcode); msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled instruction %#x.", ins->opcode); + "Internal compiler error: Unhandled instruction \"%s\" (%#x).", name, ins->opcode); } static void msl_binop(struct msl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *op) @@ -861,10 +863,11 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct data_type = VKD3D_DATA_FLOAT; } - if (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS - || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBE - || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY - || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY) + if (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBE + || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY + || (ins->opcode != VKD3DSIH_LD2DMS + && (resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMS + || resource_type == VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY))) msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_UNSUPPORTED, "Texel fetches from resource type %#x are not supported.", resource_type); @@ -903,7 +906,10 @@ static void msl_ld(struct msl_generator *gen, const struct vkd3d_shader_instruct if (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) { vkd3d_string_buffer_printf(read, ", "); - msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VKD3D_DATA_UINT); + if (ins->opcode != VKD3DSIH_LD2DMS) + msl_print_src_with_type(read, gen, &ins->src[0], VKD3DSP_WRITEMASK_3, VKD3D_DATA_UINT); + else + msl_print_src_with_type(read, gen, &ins->src[2], VKD3DSP_WRITEMASK_0, VKD3D_DATA_UINT); } vkd3d_string_buffer_printf(read, "))"); msl_print_swizzle(read, ins->src[1].swizzle, ins->dst[0].write_mask); @@ -1096,6 +1102,7 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d break; case VKD3DSIH_ILT: case VKD3DSIH_LTO: + case VKD3DSIH_ULT: msl_relop(gen, ins, "<"); break; case VKD3DSIH_MAD: @@ -1114,11 +1121,15 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d case VKD3DSIH_NEU: msl_relop(gen, ins, "!="); break; + case VKD3DSIH_INEG: + msl_unary_op(gen, ins, "-"); + break; case VKD3DSIH_ITOF: case VKD3DSIH_UTOF: msl_cast(gen, ins, "float"); break; case VKD3DSIH_LD: + case VKD3DSIH_LD2DMS: msl_ld(gen, ins); break; case VKD3DSIH_LOG: @@ -1166,6 +1177,9 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d case VKD3DSIH_SWITCH: msl_switch(gen, ins); break; + case VKD3DSIH_XOR: + msl_binop(gen, ins, "^"); + break; default: msl_unhandled(gen, ins); break; diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index 3e58718afa1..13ebde5cfd5 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -4527,70 +4527,6 @@ static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compil return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); } -/* Based on the implementation in the OpenGL Mathematics library. */ -static uint32_t half_to_float(uint16_t value) -{ - uint32_t s = (value & 0x8000u) << 16; - uint32_t e = (value >> 10) & 0x1fu; - uint32_t m = value & 0x3ffu; - - if (!e) - { - if (!m) - { - /* Plus or minus zero */ - return s; - } - else - { - /* Denormalized number -- renormalize it */ - - while (!(m & 0x400u)) - { - m <<= 1; - --e; - } - - ++e; - m &= ~0x400u; - } - } - else if (e == 31u) - { - /* Positive or negative infinity for zero 'm'. - * Nan for non-zero 'm' -- preserve sign and significand bits */ - return s | 0x7f800000u | (m << 13); - } - - /* Normalized number */ - e += 127u - 15u; - m <<= 13; - - /* Assemble s, e and m. */ - return s | (e << 23) | m; -} - -static uint32_t convert_raw_constant32(enum vkd3d_data_type data_type, unsigned int uint_value) -{ - int16_t i; - - /* TODO: native 16-bit support. */ - if (data_type != VKD3D_DATA_UINT16 && data_type != VKD3D_DATA_HALF) - return uint_value; - - if (data_type == VKD3D_DATA_HALF) - return half_to_float(uint_value); - - /* Values in DXIL have no signedness, so it is ambiguous whether 16-bit constants should or - * should not be sign-extended when 16-bit execution is not supported. The AMD RX 580 Windows - * driver has no 16-bit support, and sign-extends all 16-bit constant ints to 32 bits. These - * results differ from SM 5. The RX 6750 XT supports 16-bit execution, so constants are not - * extended, and results match SM 5. It seems best to replicate the sign-extension, and if - * execution is 16-bit, the values will be truncated. */ - i = uint_value; - return (int32_t)i; -} - static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) { @@ -4603,15 +4539,14 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile if (reg->dimension == VSIR_DIMENSION_SCALAR) { for (i = 0; i < component_count; ++i) - values[i] = convert_raw_constant32(reg->data_type, reg->u.immconst_u32[0]); + values[i] = reg->u.immconst_u32[0]; } else { for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) { if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - values[j++] = convert_raw_constant32(reg->data_type, - reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]); + values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]; } } @@ -4755,13 +4690,6 @@ static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compil switch (icb->data_type) { - case VKD3D_DATA_HALF: - case VKD3D_DATA_UINT16: - /* Scalar only. */ - for (i = 0; i < element_count; ++i) - elements[i] = vkd3d_spirv_get_op_constant(builder, elem_type_id, - convert_raw_constant32(icb->data_type, icb->data[i])); - break; case VKD3D_DATA_FLOAT: case VKD3D_DATA_INT: case VKD3D_DATA_UINT: @@ -9203,7 +9131,9 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, &src[3], VKD3DSP_WRITEMASK_0); break; default: - ERR("Unexpected instruction %#x.\n", instruction->opcode); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, + "Unhandled instruction \"%s\" (%#x).", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); return; } @@ -9884,7 +9814,9 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil op = spirv_compiler_map_atomic_instruction(instruction); if (op == SpvOpMax) { - ERR("Unexpected instruction %#x.\n", instruction->opcode); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, + "Unhandled instruction \"%s\" (%#x).", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); return; } @@ -9963,9 +9895,9 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil if (instruction->flags & VKD3DARF_VOLATILE) { - WARN("Ignoring 'volatile' attribute.\n"); spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_IGNORING_FLAG, - "Ignoring the 'volatile' attribute flag for atomic instruction %#x.", instruction->opcode); + "Ignoring the 'volatile' attribute flag for atomic instruction \"%s\" (%#x).", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); } memory_semantic = (instruction->flags & VKD3DARF_SEQ_CST) @@ -11040,9 +10972,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, /* nothing to do */ break; default: - FIXME("Unhandled instruction %#x.\n", instruction->opcode); spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER, - "Encountered invalid/unhandled instruction handler %#x.", instruction->opcode); + "Unhandled instruction \"%s\" (%#x).", + vsir_opcode_get_name(instruction->opcode, ""), instruction->opcode); break; } -- 2.47.2