From 71470ee302ed26329231d806f2ff18f187f714bc Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 8 Dec 2023 13:21:19 +1100 Subject: [PATCH] Updated vkd3d to 3bafee344d8d50172d8da18512ba070c6826b18d. --- libs/vkd3d/include/private/vkd3d_common.h | 4 +- libs/vkd3d/include/vkd3d_shader.h | 20 + libs/vkd3d/libs/vkd3d-common/blob.c | 1 + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 135 ++-- libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 16 +- libs/vkd3d/libs/vkd3d-shader/dxbc.c | 4 - libs/vkd3d/libs/vkd3d-shader/dxil.c | 699 +++++++++++++++--- libs/vkd3d/libs/vkd3d-shader/hlsl.y | 20 +- libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 12 +- libs/vkd3d/libs/vkd3d-shader/ir.c | 29 +- libs/vkd3d/libs/vkd3d-shader/spirv.c | 669 ++++++++++------- libs/vkd3d/libs/vkd3d-shader/tpf.c | 82 +- .../libs/vkd3d-shader/vkd3d_shader_main.c | 86 ++- .../libs/vkd3d-shader/vkd3d_shader_private.h | 54 +- libs/vkd3d/libs/vkd3d/command.c | 4 + libs/vkd3d/libs/vkd3d/device.c | 114 ++- libs/vkd3d/libs/vkd3d/resource.c | 19 +- libs/vkd3d/libs/vkd3d/state.c | 27 +- libs/vkd3d/libs/vkd3d/utils.c | 2 + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 23 +- 20 files changed, 1475 insertions(+), 545 deletions(-) diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h index 34fde1a2aa0..e9bff2fbba3 100644 --- a/libs/vkd3d/include/private/vkd3d_common.h +++ b/libs/vkd3d/include/private/vkd3d_common.h @@ -80,7 +80,7 @@ static inline size_t align(size_t addr, size_t alignment) # ifdef __MINGW_PRINTF_FORMAT # define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, args))) # else -# define VKD3D_PRINTF_FUNC(fmt, args) /* __attribute__((format(printf, fmt, args))) */ +# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args))) # endif # define VKD3D_UNUSED __attribute__((unused)) # define VKD3D_UNREACHABLE __builtin_unreachable() @@ -107,7 +107,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v) { #ifdef _MSC_VER return __popcnt(v); -#elif defined(__MINGW32__) +#elif defined(HAVE_BUILTIN_POPCOUNT) return __builtin_popcount(v); #else v -= (v >> 1) & 0x55555555; diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h index 290f9085d2d..b1a1fff6451 100644 --- a/libs/vkd3d/include/vkd3d_shader.h +++ b/libs/vkd3d/include/vkd3d_shader.h @@ -196,6 +196,14 @@ enum vkd3d_shader_compile_option_fragment_coordinate_origin VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN), }; +/** Advertises feature availability. \since 1.11 */ +enum vkd3d_shader_compile_option_feature_flags +{ + VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64 = 0x00000001, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FEATURE_FLAGS), +}; + enum vkd3d_shader_compile_option_name { /** @@ -253,6 +261,16 @@ enum vkd3d_shader_compile_option_name * \since 1.10 */ VKD3D_SHADER_COMPILE_OPTION_FRAGMENT_COORDINATE_ORIGIN = 0x00000009, + /** + * This option specifies the shader features available in the target + * environment. These are not extensions, i.e. they are always supported + * by the driver, but may not be supported by the available hardware. + * + * \a value is a member of enum vkd3d_shader_compile_option_feature_flags. + * + * \since 1.11 + */ + VKD3D_SHADER_COMPILE_OPTION_FEATURE = 0x0000000a, VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME), }; @@ -1551,6 +1569,8 @@ enum vkd3d_shader_component_type VKD3D_SHADER_COMPONENT_BOOL = 0x4, /** 64-bit IEEE floating-point. */ VKD3D_SHADER_COMPONENT_DOUBLE = 0x5, + /** 64-bit unsigned integer. \since 1.11 */ + VKD3D_SHADER_COMPONENT_UINT64 = 0x6, VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPONENT_TYPE), }; diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c index 71ab9a2c51e..fa2812619ac 100644 --- a/libs/vkd3d/libs/vkd3d-common/blob.c +++ b/libs/vkd3d/libs/vkd3d-common/blob.c @@ -17,6 +17,7 @@ */ #define COBJMACROS + #define CONST_VTABLE #include "vkd3d.h" #include "vkd3d_blob.h" diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c index 82d1d71d9d3..0589bc42174 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -364,6 +364,7 @@ struct vkd3d_d3d_asm_compiler struct vkd3d_string_buffer buffer; struct vkd3d_shader_version shader_version; struct vkd3d_d3d_asm_colours colours; + enum vsir_asm_dialect dialect; }; static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...) @@ -606,7 +607,7 @@ static void shader_dump_resource_type(struct vkd3d_d3d_asm_compiler *compiler, e vkd3d_string_buffer_printf(&compiler->buffer, "unknown"); } -static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type) +static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_data_type type) { static const char *const data_type_names[] = { @@ -623,19 +624,31 @@ static void shader_dump_data_type(struct vkd3d_d3d_asm_compiler *compiler, const [VKD3D_DATA_DOUBLE ] = "double", [VKD3D_DATA_CONTINUED] = "", [VKD3D_DATA_UNUSED ] = "", + [VKD3D_DATA_UINT8 ] = "uint8", + [VKD3D_DATA_UINT64 ] = "uint64", + [VKD3D_DATA_BOOL ] = "bool", }; + const char *name; + + if (type < ARRAY_SIZE(data_type_names)) + name = data_type_names[type]; + else + name = ""; + + vkd3d_string_buffer_printf(&compiler->buffer, "%s", name); +} + +static void shader_dump_resource_data_type(struct vkd3d_d3d_asm_compiler *compiler, const enum vkd3d_data_type *type) +{ int i; vkd3d_string_buffer_printf(&compiler->buffer, "("); for (i = 0; i < 4; i++) { - if (type[i] < ARRAY_SIZE(data_type_names)) - name = data_type_names[type[i]]; - else - name = "unknown"; - vkd3d_string_buffer_printf(&compiler->buffer, "%s%s", i == 0 ? "" : ",", name); + vkd3d_string_buffer_printf(&compiler->buffer, "%s", i == 0 ? "" : ","); + shader_dump_data_type(compiler, type[i]); } vkd3d_string_buffer_printf(&compiler->buffer, ")"); @@ -682,7 +695,7 @@ static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler, if (semantic->resource.reg.reg.type == VKD3DSPR_UAV) shader_dump_uav_flags(compiler, flags); shader_addline(buffer, " "); - shader_dump_data_type(compiler, semantic->resource_data_type); + shader_dump_resource_data_type(compiler, semantic->resource_data_type); } else { @@ -1096,15 +1109,15 @@ 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_float[0], ""); + shader_print_float_literal(compiler, "", reg->u.immconst_f32[0], ""); break; case VKD3D_DATA_INT: - shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], ""); + shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); break; case VKD3D_DATA_RESOURCE: case VKD3D_DATA_SAMPLER: case VKD3D_DATA_UINT: - shader_print_uint_literal(compiler, "", reg->u.immconst_uint[0], ""); + shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); break; default: shader_addline(buffer, "", reg->data_type); @@ -1116,24 +1129,24 @@ 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_float[0], ""); - shader_print_float_literal(compiler, ", ", reg->u.immconst_float[1], ""); - shader_print_float_literal(compiler, ", ", reg->u.immconst_float[2], ""); - shader_print_float_literal(compiler, ", ", reg->u.immconst_float[3], ""); + 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_uint[0], ""); - shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[1], ""); - shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[2], ""); - shader_print_int_literal(compiler, ", ", reg->u.immconst_uint[3], ""); + shader_print_int_literal(compiler, "", reg->u.immconst_u32[0], ""); + shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[1], ""); + shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[2], ""); + shader_print_int_literal(compiler, ", ", reg->u.immconst_u32[3], ""); break; case VKD3D_DATA_RESOURCE: case VKD3D_DATA_SAMPLER: case VKD3D_DATA_UINT: - shader_print_uint_literal(compiler, "", reg->u.immconst_uint[0], ""); - shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[1], ""); - shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[2], ""); - shader_print_uint_literal(compiler, ", ", reg->u.immconst_uint[3], ""); + shader_print_uint_literal(compiler, "", reg->u.immconst_u32[0], ""); + shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[1], ""); + shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[2], ""); + shader_print_uint_literal(compiler, ", ", reg->u.immconst_u32[3], ""); break; default: shader_addline(buffer, "", reg->data_type); @@ -1155,9 +1168,9 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const { if (reg->data_type == VKD3D_DATA_DOUBLE) { - shader_print_double_literal(compiler, "", reg->u.immconst_double[0], ""); + shader_print_double_literal(compiler, "", reg->u.immconst_f64[0], ""); if (reg->dimension == VSIR_DIMENSION_VEC4) - shader_print_double_literal(compiler, ", ", reg->u.immconst_double[1], ""); + shader_print_double_literal(compiler, ", ", reg->u.immconst_f64[1], ""); } else { @@ -1265,6 +1278,32 @@ static void shader_print_non_uniform(struct vkd3d_d3d_asm_compiler *compiler, co compiler->colours.modifier, compiler->colours.reset); } +static void shader_dump_reg_type(struct vkd3d_d3d_asm_compiler *compiler, + const struct vkd3d_shader_register *reg) +{ + static const char *dimensions[] = + { + [VSIR_DIMENSION_NONE] = "", + [VSIR_DIMENSION_SCALAR] = "s:", + [VSIR_DIMENSION_VEC4] = "v4:", + }; + + struct vkd3d_string_buffer *buffer = &compiler->buffer; + const char *dimension; + + if (compiler->dialect != VSIR_ASM_VSIR) + return; + + if (reg->dimension < ARRAY_SIZE(dimensions)) + dimension = dimensions[reg->dimension]; + else + dimension = "??"; + + shader_addline(buffer, " <%s", dimension); + shader_dump_data_type(compiler, reg->data_type); + shader_addline(buffer, ">"); +} + static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, const struct vkd3d_shader_dst_param *param, bool is_declaration) { @@ -1278,7 +1317,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, static const char write_mask_chars[] = "xyzw"; if (param->reg.data_type == VKD3D_DATA_DOUBLE) - write_mask = vkd3d_write_mask_32_from_64(write_mask); + write_mask = vsir_write_mask_32_from_64(write_mask); shader_addline(buffer, ".%s", compiler->colours.write_mask); if (write_mask & VKD3DSP_WRITEMASK_0) @@ -1294,6 +1333,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, shader_print_precision(compiler, ¶m->reg); shader_print_non_uniform(compiler, ¶m->reg); + shader_dump_reg_type(compiler, ¶m->reg); } static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, @@ -1341,10 +1381,10 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_IMMCONST64 && param->reg.dimension == VSIR_DIMENSION_VEC4) { - unsigned int swizzle_x = vkd3d_swizzle_get_component(swizzle, 0); - unsigned int swizzle_y = vkd3d_swizzle_get_component(swizzle, 1); - unsigned int swizzle_z = vkd3d_swizzle_get_component(swizzle, 2); - unsigned int swizzle_w = vkd3d_swizzle_get_component(swizzle, 3); + unsigned int swizzle_x = vsir_swizzle_get_component(swizzle, 0); + unsigned int swizzle_y = vsir_swizzle_get_component(swizzle, 1); + unsigned int swizzle_z = vsir_swizzle_get_component(swizzle, 2); + unsigned int swizzle_w = vsir_swizzle_get_component(swizzle, 3); static const char swizzle_chars[] = "xyzw"; @@ -1367,6 +1407,7 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, shader_print_precision(compiler, ¶m->reg); shader_print_non_uniform(compiler, ¶m->reg); + shader_dump_reg_type(compiler, ¶m->reg); } static void shader_dump_ins_modifiers(struct vkd3d_d3d_asm_compiler *compiler, @@ -1577,6 +1618,12 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile shader_addline(buffer, "p"); break; + case VKD3DSIH_ISHL: + case VKD3DSIH_ISHR: + case VKD3DSIH_USHR: + if (ins->flags & VKD3DSI_SHIFT_UNMASKED) + shader_addline(buffer, "_unmasked"); + /* fall through */ default: shader_dump_precise_flags(compiler, ins->flags); break; @@ -1835,25 +1882,25 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, vkd3d_string_buffer_printf(buffer, " %sc%u%s", compiler->colours.reg, shader_get_float_offset(ins->dst[0].reg.type, ins->dst[0].reg.idx[0].offset), compiler->colours.reset); - shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_float[0], ""); - shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[1], ""); - shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[2], ""); - shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_float[3], ""); + shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_f32[0], ""); + shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[1], ""); + shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[2], ""); + shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[3], ""); break; case VKD3DSIH_DEFI: vkd3d_string_buffer_printf(buffer, " %si%u%s", compiler->colours.reg, ins->dst[0].reg.idx[0].offset, compiler->colours.reset); - shader_print_int_literal(compiler, " = ", ins->src[0].reg.u.immconst_uint[0], ""); - shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[1], ""); - shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[2], ""); - shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_uint[3], ""); + shader_print_int_literal(compiler, " = ", ins->src[0].reg.u.immconst_u32[0], ""); + shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[1], ""); + shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[2], ""); + shader_print_int_literal(compiler, ", ", ins->src[0].reg.u.immconst_u32[3], ""); break; case VKD3DSIH_DEFB: vkd3d_string_buffer_printf(buffer, " %sb%u%s", compiler->colours.reg, ins->dst[0].reg.idx[0].offset, compiler->colours.reset); - shader_print_bool_literal(compiler, " = ", ins->src[0].reg.u.immconst_uint[0], ""); + shader_print_bool_literal(compiler, " = ", ins->src[0].reg.u.immconst_u32[0], ""); break; default: @@ -1883,7 +1930,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, || ins->resource_data_type[1] != VKD3D_DATA_FLOAT || ins->resource_data_type[2] != VKD3D_DATA_FLOAT || ins->resource_data_type[3] != VKD3D_DATA_FLOAT) - shader_dump_data_type(compiler, ins->resource_data_type); + shader_dump_resource_data_type(compiler, ins->resource_data_type); for (i = 0; i < ins->dst_count; ++i) { @@ -1906,10 +1953,13 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions, const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_code *out) + struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect) { enum vkd3d_shader_compile_option_formatting_flags formatting; - struct vkd3d_d3d_asm_compiler compiler; + struct vkd3d_d3d_asm_compiler compiler = + { + .dialect = dialect, + }; enum vkd3d_result result = VKD3D_OK; struct vkd3d_string_buffer *buffer; unsigned int indent, i, j; @@ -2002,6 +2052,7 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instructio { case VKD3DSIH_ELSE: case VKD3DSIH_IF: + case VKD3DSIH_IFC: case VKD3DSIH_LOOP: case VKD3DSIH_SWITCH: ++indent; @@ -2034,7 +2085,7 @@ void vkd3d_shader_trace(const struct vkd3d_shader_instruction_array *instruction const char *p, *q, *end; struct vkd3d_shader_code code; - if (vkd3d_dxbc_binary_to_text(instructions, shader_version, NULL, &code) != VKD3D_OK) + if (vkd3d_dxbc_binary_to_text(instructions, shader_version, NULL, &code, VSIR_ASM_VSIR) != VKD3D_OK) return; end = (const char *)code.code + code.size; diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c index 3d139416b61..ca6e3b72de9 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -987,7 +987,7 @@ static void shader_sm1_read_immconst(struct vkd3d_shader_sm1_parser *sm1, const src_param->reg.idx[2].rel_addr = NULL; src_param->reg.idx_count = 0; src_param->reg.dimension = dimension; - memcpy(src_param->reg.u.immconst_uint, *ptr, count * sizeof(uint32_t)); + memcpy(src_param->reg.u.immconst_u32, *ptr, count * sizeof(uint32_t)); src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE; src_param->modifiers = 0; @@ -1063,12 +1063,12 @@ static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1, } } -static unsigned int mask_from_swizzle(unsigned int swizzle) +static unsigned int mask_from_swizzle(uint32_t swizzle) { - return (1u << vkd3d_swizzle_get_component(swizzle, 0)) - | (1u << vkd3d_swizzle_get_component(swizzle, 1)) - | (1u << vkd3d_swizzle_get_component(swizzle, 2)) - | (1u << vkd3d_swizzle_get_component(swizzle, 3)); + return (1u << vsir_swizzle_get_component(swizzle, 0)) + | (1u << vsir_swizzle_get_component(swizzle, 1)) + | (1u << vsir_swizzle_get_component(swizzle, 2)) + | (1u << vsir_swizzle_get_component(swizzle, 3)); } static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, struct vkd3d_shader_instruction *ins) @@ -2253,7 +2253,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b { struct hlsl_reg *reg = &jump->condition.node->reg; - struct sm1_instruction instr = + struct sm1_instruction sm1_instr = { .opcode = D3DSIO_TEXKILL, @@ -2263,7 +2263,7 @@ static void write_sm1_jump(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b .has_dst = 1, }; - write_sm1_instruction(ctx, buffer, &instr); + write_sm1_instruction(ctx, buffer, &sm1_instr); break; } diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c index 7834c1e1615..63deaaad29a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c @@ -431,10 +431,6 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s case TAG_OSG5: if (e[i].sysval_semantic == VKD3D_SHADER_SV_NONE) e[i].sysval_semantic = map_fragment_output_sysval(e[i].semantic_name); - /* Fall through. */ - case TAG_PCSG: - case TAG_PSG1: - e[i].used_mask = e[i].mask & ~e[i].used_mask; break; } diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index beb9ae574dc..2424b176068 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -29,6 +29,9 @@ static const uint64_t MAX_ALIGNMENT_EXPONENT = 29; static const uint64_t GLOBALVAR_FLAG_IS_CONSTANT = 1; static const uint64_t GLOBALVAR_FLAG_EXPLICIT_TYPE = 2; static const unsigned int GLOBALVAR_ADDRESS_SPACE_SHIFT = 2; +static const uint64_t ALLOCA_FLAG_IN_ALLOCA = 0x20; +static const uint64_t ALLOCA_FLAG_EXPLICIT_TYPE = 0x40; +static const uint64_t ALLOCA_ALIGNMENT_MASK = ALLOCA_FLAG_IN_ALLOCA - 1; static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4; static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64}; @@ -296,8 +299,28 @@ enum dx_intrinsic_opcode { DX_LOAD_INPUT = 4, DX_STORE_OUTPUT = 5, + DX_EXP = 21, + DX_FRC = 22, + DX_LOG = 23, + DX_SQRT = 24, + DX_RSQRT = 25, + DX_ROUND_NE = 26, + DX_ROUND_NI = 27, + DX_ROUND_PI = 28, + DX_ROUND_Z = 29, + DX_BFREV = 30, + DX_COUNT_BITS = 31, + DX_FIRST_BIT_LO = 32, + DX_FIRST_BIT_HI = 33, + DX_FIRST_BIT_SHI = 34, DX_CREATE_HANDLE = 57, DX_CBUFFER_LOAD_LEGACY = 59, + DX_DERIV_COARSEX = 83, + DX_DERIV_COARSEY = 84, + DX_DERIV_FINEX = 85, + DX_DERIV_FINEY = 86, + DX_LEGACY_F32TOF16 = 130, + DX_LEGACY_F16TOF32 = 131, }; enum dxil_cast_code @@ -439,6 +462,7 @@ struct dxil_record { unsigned int code; unsigned int operand_count; + const struct dxil_record *attachment; uint64_t operands[]; }; @@ -581,6 +605,7 @@ struct sm6_parser size_t descriptor_count; unsigned int indexable_temp_count; + unsigned int icb_count; struct sm6_value *values; size_t value_count; @@ -796,6 +821,7 @@ static enum vkd3d_result sm6_parser_read_unabbrev_record(struct sm6_parser *sm6) record->code = code; record->operand_count = count; + record->attachment = NULL; for (i = 0; i < count; ++i) record->operands[i] = sm6_parser_read_vbr(sm6, 6); @@ -1012,6 +1038,7 @@ static enum vkd3d_result sm6_parser_read_abbrev_record(struct sm6_parser *sm6, u if (!abbrev->operands[i + 1].read_operand(sm6, abbrev->operands[i + 1].context, &record->operands[i])) goto fail; record->operand_count = count; + record->attachment = NULL; /* An array can occur only as the last operand. */ if (abbrev->is_array) @@ -1210,7 +1237,7 @@ static size_t dxil_block_compute_module_decl_count(const struct dxil_block *bloc size_t i, count; for (i = 0, count = 0; i < block->record_count; ++i) - count += block->records[i]->code == MODULE_CODE_FUNCTION; + count += block->records[i]->code == MODULE_CODE_FUNCTION || block->records[i]->code == MODULE_CODE_GLOBALVAR; return count; } @@ -1572,6 +1599,11 @@ static bool sm6_type_is_bool_i16_i32_i64(const struct sm6_type *type) return type->class == TYPE_CLASS_INTEGER && (type->u.width == 1 || type->u.width >= 16); } +static bool sm6_type_is_i16_i32_i64(const struct sm6_type *type) +{ + return type->class == TYPE_CLASS_INTEGER && type->u.width >= 16; +} + static bool sm6_type_is_bool(const struct sm6_type *type) { return type->class == TYPE_CLASS_INTEGER && type->u.width == 1; @@ -1587,6 +1619,16 @@ static inline bool sm6_type_is_i32(const struct sm6_type *type) return type->class == TYPE_CLASS_INTEGER && type->u.width == 32; } +static bool sm6_type_is_float(const struct sm6_type *type) +{ + return type->class == TYPE_CLASS_FLOAT && type->u.width == 32; +} + +static bool sm6_type_is_f16_f32(const struct sm6_type *type) +{ + return type->class == TYPE_CLASS_FLOAT && (type->u.width == 16 || type->u.width == 32); +} + static inline bool sm6_type_is_floating_point(const struct sm6_type *type) { return type->class == TYPE_CLASS_FLOAT; @@ -1844,12 +1886,12 @@ static unsigned int register_get_uint_value(const struct vkd3d_shader_register * if (reg->type == VKD3DSPR_IMMCONST64) { - if (reg->u.immconst_uint64[0] > UINT_MAX) + if (reg->u.immconst_u64[0] > UINT_MAX) FIXME("Truncating 64-bit value.\n"); - return reg->u.immconst_uint64[0]; + return reg->u.immconst_u64[0]; } - return reg->u.immconst_uint[0]; + return reg->u.immconst_u32[0]; } static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *reg) @@ -1860,7 +1902,7 @@ static uint64_t register_get_uint64_value(const struct vkd3d_shader_register *re if (reg->dimension == VSIR_DIMENSION_VEC4) WARN("Returning vec4.x.\n"); - return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_uint64[0] : reg->u.immconst_uint[0]; + return (reg->type == VKD3DSPR_IMMCONST64) ? reg->u.immconst_u64[0] : reg->u.immconst_u32[0]; } static inline bool sm6_value_is_function_dcl(const struct sm6_value *value) @@ -2412,7 +2454,7 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co return VKD3D_ERROR_INVALID_SHADER; } size = max(size, sizeof(icb->data[0])); - count = type->u.array.count * size / sizeof(icb->data[0]); + count = operands ? type->u.array.count * size / sizeof(icb->data[0]) : 0; if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[count])))) { @@ -2433,9 +2475,14 @@ static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, co dst->value_type = VALUE_TYPE_ICB; dst->u.icb = icb; + icb->register_idx = sm6->icb_count++; icb->data_type = vkd3d_data_type_from_sm6_type(elem_type); icb->element_count = type->u.array.count; icb->component_count = 1; + icb->is_null = !operands; + + if (!operands) + return VKD3D_OK; count = type->u.array.count; if (size > sizeof(icb->data[0])) @@ -2510,12 +2557,10 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const switch (record->code) { case CST_CODE_NULL: - if (sm6_type_is_array(type)) + if (sm6_type_is_array(type) + && (ret = value_allocate_constant_array(dst, type, NULL, sm6)) < 0) { - FIXME("Constant null arrays are not supported.\n"); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Constant null arrays are not supported."); - return VKD3D_ERROR_INVALID_SHADER; + return ret; } /* For non-aggregates, register constant data is already zero-filled. */ break; @@ -2532,9 +2577,9 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const value = decode_rotated_signed_value(record->operands[0]); if (type->u.width <= 32) - dst->u.reg.u.immconst_uint[0] = value & ((1ull << type->u.width) - 1); + dst->u.reg.u.immconst_u32[0] = value & ((1ull << type->u.width) - 1); else - dst->u.reg.u.immconst_uint64[0] = value; + dst->u.reg.u.immconst_u64[0] = value; break; @@ -2551,9 +2596,9 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const if (type->u.width == 16) FIXME("Half float type is not supported yet.\n"); else if (type->u.width == 32) - dst->u.reg.u.immconst_float[0] = bitcast_uint64_to_float(record->operands[0]); + dst->u.reg.u.immconst_f32[0] = bitcast_uint64_to_float(record->operands[0]); else if (type->u.width == 64) - dst->u.reg.u.immconst_double[0] = bitcast_uint64_to_double(record->operands[0]); + dst->u.reg.u.immconst_f64[0] = bitcast_uint64_to_double(record->operands[0]); else vkd3d_unreachable(); @@ -2588,6 +2633,13 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const break; } + if (record->attachment) + { + WARN("Ignoring metadata attachment.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring a metadata attachment for a constant."); + } + ++sm6->value_count; } @@ -2626,13 +2678,28 @@ static struct vkd3d_shader_instruction *sm6_parser_add_instruction(struct sm6_pa return ins; } -static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, - unsigned int count, unsigned int alignment, unsigned int init, struct sm6_value *dst) +static void sm6_parser_declare_icb(struct sm6_parser *sm6, const struct sm6_type *elem_type, unsigned int count, + unsigned int alignment, unsigned int init, struct sm6_value *dst) { enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); struct vkd3d_shader_instruction *ins; - ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_INDEXABLE_TEMP); + ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER); + /* The icb value index will be resolved later so forward references can be handled. */ + ins->declaration.icb = (void *)(intptr_t)init; + register_init_with_id(&dst->u.reg, VKD3DSPR_IMMCONSTBUFFER, data_type, init); +} + +static void sm6_parser_declare_indexable_temp(struct sm6_parser *sm6, const struct sm6_type *elem_type, + unsigned int count, unsigned int alignment, unsigned int init, struct vkd3d_shader_instruction *ins, + struct sm6_value *dst) +{ + enum vkd3d_data_type data_type = vkd3d_data_type_from_sm6_type(elem_type); + + if (ins) + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_DCL_INDEXABLE_TEMP); + else + ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_INDEXABLE_TEMP); ins->declaration.indexable_temp.register_idx = sm6->indexable_temp_count++; ins->declaration.indexable_temp.register_size = count; ins->declaration.indexable_temp.alignment = alignment; @@ -2762,7 +2829,10 @@ static bool sm6_parser_declare_global(struct sm6_parser *sm6, const struct dxil_ if (address_space == ADDRESS_SPACE_DEFAULT) { - sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, dst); + if (is_constant) + sm6_parser_declare_icb(sm6, scalar_type, count, alignment, init, dst); + else + sm6_parser_declare_indexable_temp(sm6, scalar_type, count, alignment, init, NULL, dst); } else if (address_space == ADDRESS_SPACE_GROUPSHARED) { @@ -2790,31 +2860,37 @@ static const struct vkd3d_shader_immediate_constant_buffer *resolve_forward_init assert(index); --index; - if (!(value = sm6_parser_get_value_safe(sm6, index)) || !sm6_value_is_icb(value)) + if (!(value = sm6_parser_get_value_safe(sm6, index)) || (!sm6_value_is_icb(value) && !sm6_value_is_undef(value))) { WARN("Invalid initialiser index %zu.\n", index); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, "Global variable initialiser value index %zu is invalid.", index); return NULL; } - else + else if (sm6_value_is_icb(value)) { return value->u.icb; } + /* In VSIR, initialisation with undefined values of objects is implied, not explicit. */ + return NULL; } static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) { + size_t i, count, base_value_idx = sm6->value_count; const struct dxil_block *block = &sm6->root_block; struct vkd3d_shader_instruction *ins; const struct dxil_record *record; enum vkd3d_result ret; uint64_t version; - size_t i; sm6->p.location.line = block->id; sm6->p.location.column = 0; + for (i = 0, count = 0; i < block->record_count; ++i) + count += block->records[i]->code == MODULE_CODE_GLOBALVAR; + sm6_parser_require_space(sm6, count); + for (i = 0; i < block->record_count; ++i) { sm6->p.location.column = i; @@ -2868,6 +2944,21 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) ins->declaration.indexable_temp.initialiser = resolve_forward_initialiser( (uintptr_t)ins->declaration.indexable_temp.initialiser, sm6); } + else if (ins->handler_idx == VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER) + { + ins->declaration.icb = resolve_forward_initialiser((uintptr_t)ins->declaration.icb, sm6); + } + } + for (i = base_value_idx; i < sm6->value_count; ++i) + { + const struct vkd3d_shader_immediate_constant_buffer *icb; + struct sm6_value *value = &sm6->values[i]; + + if (!sm6_value_is_register(value) || value->u.reg.type != VKD3DSPR_IMMCONSTBUFFER) + continue; + + if ((icb = resolve_forward_initialiser(value->u.reg.idx[0].offset, sm6))) + value->u.reg.idx[0].offset = icb->register_idx; } return VKD3D_OK; @@ -2908,45 +2999,6 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade } } -static void sm6_parser_emit_signature(struct sm6_parser *sm6, const struct shader_signature *s, - enum vkd3d_shader_opcode handler_idx, enum vkd3d_shader_opcode siv_handler_idx, - struct vkd3d_shader_dst_param *params) -{ - struct vkd3d_shader_instruction *ins; - struct vkd3d_shader_dst_param *param; - const struct signature_element *e; - unsigned int i; - - for (i = 0; i < s->element_count; ++i) - { - e = &s->elements[i]; - - /* Do not check e->used_mask because in some cases it is zero for used elements. - * TODO: scan ahead for used I/O elements. */ - - if (e->sysval_semantic != VKD3D_SHADER_SV_NONE && e->sysval_semantic != VKD3D_SHADER_SV_TARGET) - { - ins = sm6_parser_add_instruction(sm6, siv_handler_idx); - param = &ins->declaration.register_semantic.reg; - ins->declaration.register_semantic.sysval_semantic = vkd3d_siv_from_sysval(e->sysval_semantic); - } - else - { - ins = sm6_parser_add_instruction(sm6, handler_idx); - param = &ins->declaration.dst; - } - - ins->flags = e->interpolation_mode; - *param = params[i]; - - if (e->register_count > 1) - { - param->reg.idx[0].rel_addr = NULL; - param->reg.idx[0].offset = e->register_count; - } - } -} - static void sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) { sm6_parser_init_signature(sm6, output_signature, VKD3DSPR_OUTPUT, sm6->output_params); @@ -2957,19 +3009,6 @@ static void sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct sm6_parser_init_signature(sm6, input_signature, VKD3DSPR_INPUT, sm6->input_params); } -static void sm6_parser_emit_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) -{ - sm6_parser_emit_signature(sm6, output_signature, VKD3DSIH_DCL_OUTPUT, VKD3DSIH_DCL_OUTPUT_SIV, sm6->output_params); -} - -static void sm6_parser_emit_input_signature(struct sm6_parser *sm6, const struct shader_signature *input_signature) -{ - sm6_parser_emit_signature(sm6, input_signature, - (sm6->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3DSIH_DCL_INPUT_PS : VKD3DSIH_DCL_INPUT, - (sm6->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL) ? VKD3DSIH_DCL_INPUT_PS_SIV : VKD3DSIH_DCL_INPUT_SIV, - sm6->input_params); -} - static const struct sm6_value *sm6_parser_next_function_definition(struct sm6_parser *sm6) { size_t i, count = sm6->function_count; @@ -2992,6 +3031,81 @@ static struct sm6_block *sm6_block_create() return block; } +static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_record *record, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst) +{ + const struct sm6_type *type[2], *elem_type; + const struct sm6_value *size; + unsigned int i, alignment; + uint64_t packed_operands; + + if (!dxil_record_validate_operand_count(record, 4, 4, sm6)) + return; + + for (i = 0; i < 2; ++i) + { + if (!(type[i] = sm6_parser_get_type(sm6, record->operands[i]))) + return; + } + + packed_operands = record->operands[3]; + if (packed_operands & ALLOCA_FLAG_IN_ALLOCA) + WARN("Ignoring in_alloca flag.\n"); + if (!(packed_operands & ALLOCA_FLAG_EXPLICIT_TYPE)) + { + FIXME("Unhandled implicit type.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Implicit result type for ALLOCA instructions is not supported."); + return; + } + packed_operands &= ~(ALLOCA_FLAG_IN_ALLOCA | ALLOCA_FLAG_EXPLICIT_TYPE); + + if (!sm6_type_is_array(type[0]) || !sm6_type_is_numeric(elem_type = type[0]->u.array.elem_type)) + { + WARN("Type is not a numeric array.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Result type of an ALLOCA instruction is not a numeric array."); + return; + } + /* The second type operand is the type of the allocation size operand, in case it is a + * forward reference. We only support a constant size, so no forward ref support is needed. */ + if (!sm6_type_is_integer(type[1])) + { + WARN("Size operand type is not scalar integer.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "The type of the allocation size operand of an ALLOCA instruction is not scalar integer."); + return; + } + + if (!(dst->type = sm6_type_get_pointer_to_type(type[0], ADDRESS_SPACE_DEFAULT, sm6))) + { + WARN("Failed to get pointer type for type class %u.\n", type[0]->class); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + "Module does not define a pointer type for an ALLOCA instruction."); + return; + } + + if (!(size = sm6_parser_get_value_safe(sm6, record->operands[2]))) + return; + /* A size of 1 means one instance of type[0], i.e. one array. */ + if (sm6_value_get_constant_uint(size) != 1) + { + FIXME("Allocation size is not 1.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "ALLOCA instruction allocation sizes other than 1 are not supported."); + return; + } + + if (!bitcode_parse_alignment(packed_operands & ALLOCA_ALIGNMENT_MASK, &alignment)) + WARN("Invalid alignment %"PRIu64".\n", packed_operands); + packed_operands &= ~ALLOCA_ALIGNMENT_MASK; + + if (packed_operands) + WARN("Ignoring flags %#"PRIx64".\n", packed_operands); + + sm6_parser_declare_indexable_temp(sm6, elem_type, type[0]->u.array.count, alignment, 0, ins, dst); +} + static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_type *type_a, const struct sm6_type *type_b, struct sm6_parser *sm6) { @@ -3092,8 +3206,10 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco unsigned int i = 0; a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i); + if (!a) + return; b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i); - if (!a || !b) + if (!b) return; if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6)) @@ -3167,10 +3283,77 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco } else { + if (handler_idx == VKD3DSIH_ISHL || handler_idx == VKD3DSIH_ISHR || handler_idx == VKD3DSIH_USHR) + { + /* DXC emits AND instructions where necessary to mask shift counts. Shift binops + * do not imply masking the shift as the TPF equivalents do. */ + ins->flags |= VKD3DSI_SHIFT_UNMASKED; + } instruction_dst_param_init_ssa_scalar(ins, sm6); } } +static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) +{ + switch (op) + { + case DX_EXP: + return VKD3DSIH_EXP; + case DX_FRC: + return VKD3DSIH_FRC; + case DX_LOG: + return VKD3DSIH_LOG; + case DX_SQRT: + return VKD3DSIH_SQRT; + case DX_RSQRT: + return VKD3DSIH_RSQ; + case DX_ROUND_NE: + return VKD3DSIH_ROUND_NE; + case DX_ROUND_NI: + return VKD3DSIH_ROUND_NI; + case DX_ROUND_PI: + return VKD3DSIH_ROUND_PI; + case DX_ROUND_Z: + return VKD3DSIH_ROUND_Z; + case DX_BFREV: + return VKD3DSIH_BFREV; + case DX_COUNT_BITS: + return VKD3DSIH_COUNTBITS; + case DX_FIRST_BIT_LO: + return VKD3DSIH_FIRSTBIT_LO; + case DX_FIRST_BIT_HI: + return VKD3DSIH_FIRSTBIT_HI; + case DX_FIRST_BIT_SHI: + return VKD3DSIH_FIRSTBIT_SHI; + case DX_DERIV_COARSEX: + return VKD3DSIH_DSX_COARSE; + case DX_DERIV_COARSEY: + return VKD3DSIH_DSY_COARSE; + case DX_DERIV_FINEX: + return VKD3DSIH_DSX_FINE; + case DX_DERIV_FINEY: + return VKD3DSIH_DSY_FINE; + case DX_LEGACY_F32TOF16: + return VKD3DSIH_F32TOF16; + case DX_LEGACY_F16TOF32: + return VKD3DSIH_F16TOF32; + default: + vkd3d_unreachable(); + } +} + +static void sm6_parser_emit_dx_unary(struct sm6_parser *sm6, struct sm6_block *code_block, + enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) +{ + struct vkd3d_shader_src_param *src_param; + + vsir_instruction_init(ins, &sm6->p.location, map_dx_unary_op(op)); + src_param = instruction_src_params_alloc(ins, 1, sm6); + src_param_init_from_value(src_param, operands[0]); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, struct sm6_block *code_block, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct vkd3d_shader_instruction *ins) { @@ -3344,7 +3527,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, struct sm6_b struct sm6_dx_opcode_info { - const char ret_type; + const char *ret_type; const char *operand_info; void (*handler)(struct sm6_parser *, struct sm6_block *, enum dx_intrinsic_opcode, const struct sm6_value **, struct vkd3d_shader_instruction *); @@ -3355,16 +3538,40 @@ struct sm6_dx_opcode_info b -> constant int1 c -> constant int8/16/32 i -> int32 + m -> int16/32/64 + f -> float + e -> half/float + g -> half/float/double H -> handle v -> void o -> overloaded */ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = { - [DX_CBUFFER_LOAD_LEGACY ] = {'o', "Hi", sm6_parser_emit_dx_cbuffer_load}, - [DX_CREATE_HANDLE ] = {'H', "ccib", sm6_parser_emit_dx_create_handle}, - [DX_LOAD_INPUT ] = {'o', "ii8i", sm6_parser_emit_dx_load_input}, - [DX_STORE_OUTPUT ] = {'v', "ii8o", sm6_parser_emit_dx_store_output}, + [DX_BFREV ] = {"m0", "m", sm6_parser_emit_dx_unary}, + [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, + [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, + [DX_CREATE_HANDLE ] = {"H", "ccib", sm6_parser_emit_dx_create_handle}, + [DX_DERIV_COARSEX ] = {"e0", "e", sm6_parser_emit_dx_unary}, + [DX_DERIV_COARSEY ] = {"e0", "e", sm6_parser_emit_dx_unary}, + [DX_DERIV_FINEX ] = {"e0", "e", sm6_parser_emit_dx_unary}, + [DX_DERIV_FINEY ] = {"e0", "e", sm6_parser_emit_dx_unary}, + [DX_EXP ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_FIRST_BIT_HI ] = {"i", "m", sm6_parser_emit_dx_unary}, + [DX_FIRST_BIT_LO ] = {"i", "m", sm6_parser_emit_dx_unary}, + [DX_FIRST_BIT_SHI ] = {"i", "m", sm6_parser_emit_dx_unary}, + [DX_FRC ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_LEGACY_F16TOF32 ] = {"f", "i", sm6_parser_emit_dx_unary}, + [DX_LEGACY_F32TOF16 ] = {"i", "f", sm6_parser_emit_dx_unary}, + [DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input}, + [DX_LOG ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_ROUND_NE ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_ROUND_NI ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_ROUND_PI ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_ROUND_Z ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_RSQRT ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_SQRT ] = {"g0", "g", sm6_parser_emit_dx_unary}, + [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, }; static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struct sm6_value *value, char info_type, @@ -3389,6 +3596,14 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc && type->u.width <= 32; case 'i': return sm6_type_is_i32(type); + case 'm': + return sm6_type_is_i16_i32_i64(type); + case 'f': + return sm6_type_is_float(type); + case 'e': + return sm6_type_is_f16_f32(type); + case 'g': + return sm6_type_is_floating_point(type); case 'H': return (is_return || sm6_value_is_handle(value)) && type == sm6->handle_type; case 'v': @@ -3402,6 +3617,17 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc } } +static bool operand_types_match(struct sm6_value *dst, const struct sm6_value **operands, unsigned int operand_count, + char index_char) +{ + unsigned int i = index_char - '0'; + + assert(i < 10); + if (i >= operand_count) + return false; + return dst->type == operands[i]->type; +} + static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const char *name, const struct sm6_value **operands, unsigned int operand_count, struct sm6_value *dst) { @@ -3410,7 +3636,9 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ info = &sm6_dx_op_table[op]; - if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type, true)) + assert(info->ret_type[0]); + if (!sm6_parser_validate_operand_type(sm6, dst, info->ret_type[0], true) + || (info->ret_type[1] && !operand_types_match(dst, operands, operand_count, info->ret_type[1]))) { WARN("Failed to validate return type for dx intrinsic id %u, '%s'.\n", op, name); /* Return type validation failure is not so critical. We only need to set @@ -3700,6 +3928,9 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor if (handler_idx == VKD3DSIH_NOP) { dst->u.reg = value->u.reg; + /* Set the result type for casts from 16-bit min precision. */ + if (type->u.width != 16) + dst->u.reg.data_type = vkd3d_data_type_from_sm6_type(type); return; } @@ -3775,8 +4006,10 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor } a = sm6_parser_get_value_by_ref(sm6, record, NULL, &i); + if (!a) + return; b = sm6_parser_get_value_by_ref(sm6, record, a->type, &i); - if (!a || !b) + if (!b) return; if (!dxil_record_validate_operand_count(record, i + 1, i + 2, sm6)) @@ -4065,6 +4298,57 @@ static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record ins->handler_idx = VKD3DSIH_NOP; } +static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_record *record, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst) +{ + struct vkd3d_shader_src_param *src_param; + struct vkd3d_shader_dst_param *dst_param; + const struct sm6_type *pointee_type; + const struct sm6_value *ptr, *src; + unsigned int i = 0, alignment; + uint64_t alignment_code; + + if (!(ptr = sm6_parser_get_value_by_ref(sm6, record, NULL, &i)) + || !sm6_value_validate_is_register(ptr, sm6) + || !sm6_value_validate_is_pointer(ptr, sm6)) + { + return; + } + + pointee_type = ptr->type->u.pointer.type; + if (!(src = sm6_parser_get_value_by_ref(sm6, record, pointee_type, &i))) + return; + if (!sm6_value_validate_is_numeric(src, sm6)) + return; + + if (pointee_type != src->type) + { + WARN("Type mismatch.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "Type mismatch in pointer store arguments."); + } + + if (!dxil_record_validate_operand_count(record, i + 2, i + 2, sm6)) + return; + + alignment_code = record->operands[i++]; + if (!bitcode_parse_alignment(alignment_code, &alignment)) + WARN("Invalid alignment %"PRIu64".\n", alignment_code); + + if (record->operands[i]) + WARN("Ignoring volatile modifier.\n"); + + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); + + src_param = instruction_src_params_alloc(ins, 1, sm6); + src_param_init_from_value(&src_param[0], src); + + dst_param = instruction_dst_params_alloc(ins, 1, sm6); + dst_param_init(dst_param); + dst_param->reg = ptr->u.reg; + dst_param->reg.alignment = alignment; +} + static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_record *record, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { @@ -4153,6 +4437,208 @@ static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6, return true; } +static void sm6_parser_metadata_attachment_block_init(struct sm6_parser *sm6, const struct dxil_block *target_block, + const struct dxil_block *block) +{ + struct dxil_record *target_record; + const struct dxil_record *record; + unsigned int i; + uint64_t index; + + for (i = 0; i < block->record_count; ++i) + { + record = block->records[i]; + if (record->code != METADATA_ATTACHMENT) + { + WARN("Ignoring record with code %u.\n", record->code); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring a metadata attachment record with code %u.", record->code); + continue; + } + if (!(record->operand_count & 1)) + { + WARN("Ignoring function attachment.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring a metadata function attachment."); + continue; + } + + index = record->operands[0]; + if (!target_block->record_count || index >= target_block->record_count - 1) + { + WARN("Invalid record index %"PRIu64".\n", index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid record index %"PRIu64" for a metadata attachment.", index); + continue; + } + /* 'index' is an instruction index, but records[0] is DECLAREBLOCKS, not an instruction. */ + target_record = target_block->records[index + 1]; + if (target_record->attachment) + { + WARN("Overwriting record attachment.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "The target record for a metadata attachment already has an attachment."); + } + target_record->attachment = record; + } +} + +static void sm6_parser_metadata_attachments_init(struct sm6_parser *sm6, const struct dxil_block *block) +{ + unsigned int i; + + for (i = 0; i < block->child_block_count; ++i) + { + if (block->child_blocks[i]->id == METADATA_ATTACHMENT_BLOCK) + sm6_parser_metadata_attachment_block_init(sm6, block, block->child_blocks[i]); + } +} + +static const struct sm6_metadata_value *sm6_parser_find_metadata_kind(const struct sm6_parser *sm6, uint64_t id) +{ + unsigned int i, j; + + for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) + { + for (j = 0; j < sm6->metadata_tables[i].count; ++j) + { + if (sm6->metadata_tables[i].values[j].type == VKD3D_METADATA_KIND + && sm6->metadata_tables[i].values[j].u.kind.id == id) + return &sm6->metadata_tables[i].values[j]; + } + } + + return NULL; +} + +static const struct sm6_metadata_value *sm6_parser_metadata_get_value(const struct sm6_parser *sm6, uint64_t index) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(sm6->metadata_tables); ++i) + { + if (sm6->metadata_tables[i].count > index) + break; + index -= sm6->metadata_tables[i].count; + } + + return (index < sm6->metadata_tables[i].count) ? &sm6->metadata_tables[i].values[index] : NULL; +} + +static bool metadata_node_get_unary_uint(const struct sm6_metadata_node *node, unsigned int *operand, + struct sm6_parser *sm6) +{ + if (node->operand_count != 1) + { + FIXME("Ignoring node with %u operands.\n", node->operand_count); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring metadata attachment node with %u operands; expected unary.", node->operand_count); + return false; + } + if (!sm6_metadata_value_is_value(node->operands[0]) + || !sm6_metadata_get_uint_value(sm6, node->operands[0], operand)) + { + WARN("Failed to get operand value.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Failed to get a metadata attachment operand value; ignoring the attachment."); + return false; + } + + return true; +} + +static void metadata_attachment_record_apply(const struct dxil_record *record, enum bitcode_function_code func_code, + struct vkd3d_shader_instruction *ins, struct sm6_value *dst, struct sm6_parser *sm6) +{ + static const char *ignored_names[] = + { + "alias.scope", + "dx.controlflow.hints", + "llvm.loop", + "noalias", + "tbaa", + "range", + }; + const struct sm6_metadata_node *node; + const struct sm6_metadata_value *m; + unsigned int i, j, operand; + bool ignored = false; + const char *name; + + if (record->attachment) + { + WARN("Ignoring nested metadata attachment.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring a nested metadata attachment."); + } + + assert(record->operand_count & 1); + for (i = 1; i < record->operand_count; i += 2) + { + if (!(m = sm6_parser_find_metadata_kind(sm6, record->operands[i]))) + { + WARN("Failed to find metadata kind %"PRIx64".\n", record->operands[i]); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Failed to find metadata kind %"PRIx64" for an attachment.", record->operands[i]); + continue; + } + name = m->u.kind.name; + + m = sm6_parser_metadata_get_value(sm6, record->operands[i + 1]); + if (!m || !sm6_metadata_value_is_node(m)) + { + WARN("Failed to retrieve metadata attachment node.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Failed to retrieve a metadata attachment node."); + continue; + } + node = m->u.node; + + if (!strcmp(name, "dx.precise")) + { + if (!sm6_value_is_register(dst)) + { + WARN("Precise value is not a register.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "A value marked as precise is not a register."); + } + else if (metadata_node_get_unary_uint(node, &operand, sm6) && operand) + { + ins->flags |= sm6_type_is_scalar(dst->type) ? VKD3DSI_PRECISE_X : VKD3DSI_PRECISE_XYZW; + } + } + else if (!strcmp(name, "dx.nonuniform")) + { + if (!sm6_value_is_register(dst)) + { + WARN("Non-uniform value is not a register.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "A value marked as non-uniform is not a register."); + } + else if (metadata_node_get_unary_uint(node, &operand, sm6)) + { + dst->u.reg.non_uniform = !!operand; + } + } + else + { + for (j = 0; j < ARRAY_SIZE(ignored_names); ++j) + if (!strcmp(name, ignored_names[j])) + break; + if (j == ARRAY_SIZE(ignored_names)) + { + WARN("Ignoring metadata attachment '%s'.\n", name); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT, + "Ignoring a metadata attachment named '%s'.", name); + } + ignored = true; + } + + if (func_code != FUNC_CODE_INST_CALL && !ignored) + WARN("Metadata attachment target is not a function call.\n"); + } +} + static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, struct sm6_function *function) { @@ -4240,6 +4726,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const record = block->records[i]; switch (record->code) { + case FUNC_CODE_INST_ALLOCA: + sm6_parser_emit_alloca(sm6, record, ins, dst); + break; case FUNC_CODE_INST_BINOP: sm6_parser_emit_binop(sm6, record, ins, dst); break; @@ -4266,6 +4755,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const is_terminator = true; ret_found = true; break; + case FUNC_CODE_INST_STORE: + sm6_parser_emit_store(sm6, record, ins, dst); + break; case FUNC_CODE_INST_VSELECT: sm6_parser_emit_vselect(sm6, record, ins, dst); break; @@ -4278,6 +4770,9 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const return VKD3D_ERROR; assert(ins->handler_idx != VKD3DSIH_INVALID); + if (record->attachment) + metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); + if (is_terminator) { ++block_idx; @@ -4331,6 +4826,8 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st sm6->p.location.line = block->id; sm6->p.location.column = 0; + sm6_parser_metadata_attachments_init(sm6, block); + switch (block->id) { case CONSTANTS_BLOCK: @@ -4645,7 +5142,7 @@ static const enum vkd3d_shader_sysval_semantic sysval_semantic_table[] = { [SEMANTIC_KIND_ARBITRARY] = VKD3D_SHADER_SV_NONE, [SEMANTIC_KIND_POSITION] = VKD3D_SHADER_SV_POSITION, - [SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_NONE, + [SEMANTIC_KIND_TARGET] = VKD3D_SHADER_SV_TARGET, }; static enum vkd3d_shader_sysval_semantic sysval_semantic_from_dxil_semantic_kind(enum dxil_semantic_kind kind) @@ -5538,7 +6035,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t if ((magic = sm6->start[0]) != BITCODE_MAGIC) { WARN("Unknown magic number 0x%08x.\n", magic); - vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER, + vkd3d_shader_warning(message_context, &location, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER, "DXIL bitcode chunk magic number 0x%08x is not the expected 0x%08x.", magic, BITCODE_MAGIC); } @@ -5547,7 +6044,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t if ((version.type = version_token >> 16) >= VKD3D_SHADER_TYPE_COUNT) { FIXME("Unknown shader type %#x.\n", version.type); - vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE, + vkd3d_shader_warning(message_context, &location, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE, "Unknown shader type %#x.", version.type); } @@ -5573,10 +6070,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t if ((ret = dxil_block_init(block, NULL, sm6)) < 0) { if (ret == VKD3D_ERROR_OUT_OF_MEMORY) - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Out of memory parsing DXIL bitcode chunk."); else if (ret == VKD3D_ERROR_INVALID_SHADER) - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_BITCODE, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_BITCODE, "DXIL bitcode chunk has invalid bitcode."); else vkd3d_unreachable(); @@ -5606,10 +6103,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t if ((ret = sm6_parser_type_table_init(sm6)) < 0) { if (ret == VKD3D_ERROR_OUT_OF_MEMORY) - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Out of memory parsing DXIL type table."); else if (ret == VKD3D_ERROR_INVALID_SHADER) - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_TYPE_TABLE, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_TYPE_TABLE, "DXIL type table is invalid."); else vkd3d_unreachable(); @@ -5619,10 +6116,10 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t if ((ret = sm6_parser_symtab_init(sm6)) < 0) { if (ret == VKD3D_ERROR_OUT_OF_MEMORY) - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Out of memory parsing DXIL value symbol table."); else if (ret == VKD3D_ERROR_INVALID_SHADER) - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_VALUE_SYMTAB, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_VALUE_SYMTAB, "DXIL value symbol table is invalid."); else vkd3d_unreachable(); @@ -5633,7 +6130,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t || !(sm6->input_params = shader_parser_get_dst_params(&sm6->p, input_signature->element_count))) { ERR("Failed to allocate input/output parameters.\n"); - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Out of memory allocating input/output parameters."); return VKD3D_ERROR_OUT_OF_MEMORY; } @@ -5642,7 +6139,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t if (!(sm6->functions = vkd3d_calloc(function_count, sizeof(*sm6->functions)))) { ERR("Failed to allocate function array.\n"); - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Out of memory allocating DXIL function array."); return VKD3D_ERROR_OUT_OF_MEMORY; } @@ -5650,14 +6147,14 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t if (sm6_parser_compute_max_value_count(sm6, &sm6->root_block, 0) == SIZE_MAX) { WARN("Value array count overflowed.\n"); - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, "Overflow occurred in the DXIL module value count."); return VKD3D_ERROR_INVALID_SHADER; } if (!(sm6->values = vkd3d_calloc(sm6->value_capacity, sizeof(*sm6->values)))) { ERR("Failed to allocate value array.\n"); - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Out of memory allocating DXIL value array."); return VKD3D_ERROR_OUT_OF_MEMORY; } @@ -5684,7 +6181,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t if (j == ARRAY_SIZE(sm6->metadata_tables)) { FIXME("Too many metadata tables.\n"); - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA, "A metadata table count greater than %zu is unsupported.", ARRAY_SIZE(sm6->metadata_tables)); return VKD3D_ERROR_INVALID_SHADER; } @@ -5702,22 +6199,20 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t if ((ret = sm6_parser_module_init(sm6, &sm6->root_block, 0)) < 0) { if (ret == VKD3D_ERROR_OUT_OF_MEMORY) - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Out of memory parsing DXIL module."); else if (ret == VKD3D_ERROR_INVALID_SHADER) - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, "DXIL module is invalid."); return ret; } if (!sm6_parser_require_space(sm6, output_signature->element_count + input_signature->element_count)) { - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Out of memory emitting shader signature declarations."); return VKD3D_ERROR_OUT_OF_MEMORY; } - sm6_parser_emit_output_signature(sm6, output_signature); - sm6_parser_emit_input_signature(sm6, input_signature); sm6->p.shader_desc.ssa_count = sm6->ssa_next_id; @@ -5732,7 +6227,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t assert(sm6->function_count == 1); if (!sm6_block_emit_instructions(fn->blocks[0], sm6)) { - vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Out of memory emitting shader instructions."); return VKD3D_ERROR_OUT_OF_MEMORY; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index 0dde4c18587..ed053f16312 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -487,27 +487,27 @@ static void resolve_loop_continue(struct hlsl_ctx *ctx, struct hlsl_block *block else if (instr->type == HLSL_IR_JUMP) { struct hlsl_ir_jump *jump = hlsl_ir_jump(instr); - struct hlsl_block block; + struct hlsl_block cond_block; if (jump->type != HLSL_IR_JUMP_UNRESOLVED_CONTINUE) continue; if (type == LOOP_DO_WHILE) { - if (!hlsl_clone_block(ctx, &block, cond)) + if (!hlsl_clone_block(ctx, &cond_block, cond)) return; - if (!append_conditional_break(ctx, &block)) + if (!append_conditional_break(ctx, &cond_block)) { - hlsl_block_cleanup(&block); + hlsl_block_cleanup(&cond_block); return; } - list_move_before(&instr->entry, &block.instrs); + list_move_before(&instr->entry, &cond_block.instrs); } else if (type == LOOP_FOR) { - if (!hlsl_clone_block(ctx, &block, iter)) + if (!hlsl_clone_block(ctx, &cond_block, iter)) return; - list_move_before(&instr->entry, &block.instrs); + list_move_before(&instr->entry, &cond_block.instrs); } jump->type = HLSL_IR_JUMP_CONTINUE; } @@ -3553,7 +3553,7 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * { struct hlsl_resource_load_params load_params = { 0 }; const struct hlsl_type *sampler_type; - struct hlsl_ir_node *coords, *load; + struct hlsl_ir_node *coords, *sample; if (params->args_count != 2 && params->args_count != 4) { @@ -3688,9 +3688,9 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * load_params.format = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4); load_params.sampling_dim = dim; - if (!(load = hlsl_new_resource_load(ctx, &load_params, loc))) + if (!(sample = hlsl_new_resource_load(ctx, &load_params, loc))) return false; - hlsl_block_add_instr(params->instrs, load); + hlsl_block_add_instr(params->instrs, sample); return true; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index 4a622185741..88cbef61d5f 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -1090,7 +1090,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, unsigned int dim_count = hlsl_sampler_dim_count(val->data_type->sampler_dim); struct hlsl_ir_node *coords = index->idx.node; struct hlsl_resource_load_params params = {0}; - struct hlsl_ir_node *load; + struct hlsl_ir_node *resource_load; assert(coords->data_type->class == HLSL_CLASS_VECTOR); assert(coords->data_type->base_type == HLSL_TYPE_UINT); @@ -1104,9 +1104,9 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, params.coords = coords; params.format = val->data_type->e.resource_format; - if (!(load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) + if (!(resource_load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) return false; - hlsl_block_add_instr(block, load); + hlsl_block_add_instr(block, resource_load); return true; } @@ -2301,7 +2301,6 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in struct hlsl_ir_switch_case *c, *def = NULL; bool missing_terminal_break = false; struct hlsl_ir_node *node; - struct hlsl_ir_jump *jump; struct hlsl_ir_switch *s; if (instr->type != HLSL_IR_SWITCH) @@ -2320,10 +2319,7 @@ static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *in { node = LIST_ENTRY(list_tail(&c->body.instrs), struct hlsl_ir_node, entry); if (node->type == HLSL_IR_JUMP) - { - jump = hlsl_ir_jump(node); - terminal_break = jump->type == HLSL_IR_JUMP_BREAK; - } + terminal_break = (hlsl_ir_jump(node)->type == HLSL_IR_JUMP_BREAK); } missing_terminal_break |= !terminal_break; diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index 710811c6761..d38b3c39712 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -63,7 +63,7 @@ static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_i if (shader_register_is_phase_instance_id(reg)) { vsir_register_init(reg, VKD3DSPR_IMMCONST, reg->data_type, 0); - reg->u.immconst_uint[0] = instance_id; + reg->u.immconst_u32[0] = instance_id; continue; } shader_register_eliminate_phase_addressing(reg, instance_id); @@ -463,6 +463,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i struct vkd3d_shader_instruction_array *instructions; struct control_point_normaliser normaliser; unsigned int input_control_point_count; + struct vkd3d_shader_location location; struct vkd3d_shader_instruction *ins; enum vkd3d_result ret; unsigned int i, j; @@ -513,8 +514,10 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i return VKD3D_OK; case VKD3DSIH_HS_FORK_PHASE: case VKD3DSIH_HS_JOIN_PHASE: + /* ins may be relocated if the instruction array expands. */ + location = ins->location; ret = control_point_normaliser_emit_hs_input(&normaliser, input_signature, - input_control_point_count, i, &ins->location); + input_control_point_count, i, &location); *src_instructions = normaliser.instructions; return ret; default: @@ -590,19 +593,19 @@ struct signature_element *vsir_signature_find_element_for_reg(const struct shade } static unsigned int range_map_get_register_count(uint8_t range_map[][VKD3D_VEC4_SIZE], - unsigned int register_idx, unsigned int write_mask) + unsigned int register_idx, uint32_t write_mask) { - return range_map[register_idx][vkd3d_write_mask_get_component_idx(write_mask)]; + return range_map[register_idx][vsir_write_mask_get_component_idx(write_mask)]; } static void range_map_set_register_range(uint8_t range_map[][VKD3D_VEC4_SIZE], unsigned int register_idx, - unsigned int register_count, unsigned int write_mask, bool is_dcl_indexrange) + unsigned int register_count, uint32_t write_mask, bool is_dcl_indexrange) { unsigned int i, j, r, c, component_idx, component_count; assert(write_mask <= VKD3DSP_WRITEMASK_ALL); - component_idx = vkd3d_write_mask_get_component_idx(write_mask); - component_count = vkd3d_write_mask_component_count(write_mask); + component_idx = vsir_write_mask_get_component_idx(write_mask); + component_count = vsir_write_mask_component_count(write_mask); assert(register_idx < MAX_REG_OUTPUT && MAX_REG_OUTPUT - register_idx >= register_count); @@ -896,7 +899,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par element_idx = shader_signature_find_element_for_reg(signature, reg_idx, write_mask); e = &signature->elements[element_idx]; - dst_param->write_mask >>= vkd3d_write_mask_get_component_idx(e->mask); + dst_param->write_mask >>= vsir_write_mask_get_component_idx(e->mask); if (is_io_dcl) { /* Validated in the TPF reader. */ @@ -999,7 +1002,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par id_idx = reg->idx_count - 1; reg_idx = reg->idx[id_idx].offset; - write_mask = VKD3DSP_WRITEMASK_0 << vkd3d_swizzle_get_component(src_param->swizzle, 0); + 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); e = &signature->elements[element_idx]; @@ -1008,10 +1011,10 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par reg->idx[id_idx].offset = element_idx; reg->idx_count = id_idx + 1; - if ((component_idx = vkd3d_write_mask_get_component_idx(e->mask))) + if ((component_idx = vsir_write_mask_get_component_idx(e->mask))) { for (i = 0; i < VKD3D_VEC4_SIZE; ++i) - if (vkd3d_swizzle_get_component(src_param->swizzle, i)) + if (vsir_swizzle_get_component(src_param->swizzle, i)) src_param->swizzle -= component_idx << VKD3D_SHADER_SWIZZLE_SHIFT(i); } } @@ -1215,7 +1218,7 @@ static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_par param->reg.idx_count = 0; param->reg.dimension = VSIR_DIMENSION_VEC4; for (j = 0; j < 4; ++j) - param->reg.u.immconst_uint[j] = normaliser->defs[i].value[j]; + param->reg.u.immconst_u32[j] = normaliser->defs[i].value[j]; return; } } @@ -1251,7 +1254,7 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d get_flat_constant_register_type((struct vkd3d_shader_register *)&ins->dst[0].reg, &def->set, &def->index); for (j = 0; j < 4; ++j) - def->value[j] = ins->src[0].reg.u.immconst_uint[j]; + def->value[j] = ins->src[0].reg.u.immconst_u32[j]; vkd3d_shader_instruction_make_nop(ins); } diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index c8a43adbe03..387784f2358 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -133,7 +133,7 @@ static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, } } -static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, +static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv, enum vkd3d_shader_spirv_environment environment) { spv_diagnostic diagnostic = NULL; @@ -145,12 +145,13 @@ static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, if ((ret = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t), &diagnostic))) { - FIXME("Failed to validate SPIR-V binary, ret %d.\n", ret); - FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error)); + vkd3d_string_buffer_printf(buffer, "%s", diagnostic->error); } spvDiagnosticDestroy(diagnostic); spvContextDestroy(context); + + return !ret; } #else @@ -163,8 +164,11 @@ static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_co } static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, enum vkd3d_shader_spirv_environment environment) {} -static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, - enum vkd3d_shader_spirv_environment environment) {} +static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struct vkd3d_shader_code *spirv, + enum vkd3d_shader_spirv_environment environment) +{ + return true; +} #endif /* HAVE_SPIRV_TOOLS */ @@ -1194,6 +1198,16 @@ static uint32_t vkd3d_spirv_get_op_constant64(struct vkd3d_spirv_builder *builde (const uint32_t *)&value, 2, vkd3d_spirv_build_op_constant64); } +static uint32_t vkd3d_spirv_build_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) +{ + return vkd3d_spirv_build_op_tr(builder, &builder->global_stream, SpvOpConstantNull, result_type); +} + +static uint32_t vkd3d_spirv_get_op_constant_null(struct vkd3d_spirv_builder *builder, uint32_t result_type) +{ + return vkd3d_spirv_build_once1(builder, SpvOpConstantNull, result_type, vkd3d_spirv_build_op_constant_null); +} + static uint32_t vkd3d_spirv_build_op_constant_composite(struct vkd3d_spirv_builder *builder, uint32_t result_type, const uint32_t *constituents, unsigned int constituent_count) { @@ -1783,6 +1797,8 @@ static uint32_t vkd3d_spirv_get_type_id(struct vkd3d_spirv_builder *builder, break; case VKD3D_SHADER_COMPONENT_DOUBLE: return vkd3d_spirv_get_op_type_float(builder, 64); + case VKD3D_SHADER_COMPONENT_UINT64: + return vkd3d_spirv_get_op_type_int(builder, 64, 0); default: FIXME("Unhandled component type %#x.\n", component_type); return 0; @@ -1816,6 +1832,8 @@ static uint32_t vkd3d_spirv_get_type_id_for_data_type(struct vkd3d_spirv_builder break; case VKD3D_DATA_DOUBLE: return vkd3d_spirv_get_op_type_float(builder, 64); + case VKD3D_DATA_UINT64: + return vkd3d_spirv_get_op_type_int(builder, 64, 0); case VKD3D_DATA_BOOL: return vkd3d_spirv_get_op_type_bool(builder); default: @@ -2152,6 +2170,7 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol, break; case VKD3DSPR_IMMCONSTBUFFER: + symbol->key.reg.idx = reg->idx_count > 1 ? reg->idx[0].offset : 0; break; default: @@ -2159,6 +2178,15 @@ static void vkd3d_symbol_make_register(struct vkd3d_symbol *symbol, } } +static void vkd3d_symbol_make_io(struct vkd3d_symbol *symbol, + enum vkd3d_shader_register_type type, unsigned int index) +{ + symbol->type = VKD3D_SYMBOL_REGISTER; + memset(&symbol->key, 0, sizeof(symbol->key)); + symbol->key.reg.type = type; + symbol->key.reg.idx = index; +} + 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) @@ -2376,12 +2404,15 @@ struct spirv_compiler struct vkd3d_shader_spec_constant *spec_constants; size_t spec_constants_size; enum vkd3d_shader_compile_option_formatting_flags formatting; + enum vkd3d_shader_compile_option_feature_flags features; bool write_tess_geom_point_size; struct vkd3d_string_buffer_cache string_buffers; struct ssa_register_info *ssa_register_info; unsigned int ssa_register_count; + + uint64_t config_flags; }; static bool is_in_default_phase(const struct spirv_compiler *compiler) @@ -2437,7 +2468,8 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler) static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *shader_version, struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info, - struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location) + struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location, + uint64_t config_flags) { const struct shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature; const struct shader_signature *output_signature = &shader_desc->output_signature; @@ -2454,6 +2486,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve memset(compiler, 0, sizeof(*compiler)); compiler->message_context = message_context; compiler->location = *location; + compiler->config_flags = config_flags; if ((target_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO))) { @@ -2533,6 +2566,10 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve WARN("Ignoring unrecognised value %#x for option %#x.\n", option->value, option->name); break; + case VKD3D_SHADER_COMPILE_OPTION_FEATURE: + compiler->features = option->value; + break; + default: WARN("Ignoring unrecognised option %#x with value %#x.\n", option->name, option->value); break; @@ -2955,7 +2992,7 @@ static uint32_t spirv_compiler_get_constant64(struct spirv_compiler *compiler, assert(0 < component_count && component_count <= VKD3D_DVEC2_SIZE); type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); - if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE) + if (component_type != VKD3D_SHADER_COMPONENT_DOUBLE && component_type != VKD3D_SHADER_COMPONENT_UINT64) { FIXME("Unhandled component_type %#x.\n", component_type); return vkd3d_spirv_get_op_undef(builder, type_id); @@ -3015,14 +3052,21 @@ static uint32_t spirv_compiler_get_constant_double_vector(struct spirv_compiler component_count, (const uint64_t *)values); } +static uint32_t spirv_compiler_get_constant_uint64_vector(struct spirv_compiler *compiler, + uint64_t value, unsigned int component_count) +{ + const uint64_t values[] = {value, value}; + return spirv_compiler_get_constant64(compiler, VKD3D_SHADER_COMPONENT_UINT64, component_count, values); +} + static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, DWORD write_mask) + const struct vkd3d_shader_register *reg, uint32_t write_mask) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; return vkd3d_spirv_get_type_id(builder, vkd3d_component_type_from_data_type(reg->data_type), - vkd3d_write_mask_component_count(write_mask)); + vsir_write_mask_component_count(write_mask)); } static uint32_t spirv_compiler_get_type_id_for_dst(struct spirv_compiler *compiler, @@ -3498,7 +3542,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp } else if (reg->type == VKD3DSPR_IMMCONSTBUFFER) { - indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[0]); + indexes[index_count++] = spirv_compiler_emit_register_addressing(compiler, ®->idx[reg->idx_count - 1]); } else if (reg->type == VKD3DSPR_IDXTEMP) { @@ -3530,7 +3574,7 @@ static void spirv_compiler_emit_dereference_register(struct spirv_compiler *comp if (index_count) { - component_count = vkd3d_write_mask_component_count(register_info->write_mask); + component_count = vsir_write_mask_component_count(register_info->write_mask); type_id = vkd3d_spirv_get_type_id(builder, register_info->component_type, component_count); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, register_info->storage_class, type_id); register_info->id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, @@ -3562,24 +3606,24 @@ static bool vkd3d_swizzle_is_equal(unsigned int dst_write_mask, return vkd3d_compact_swizzle(VKD3D_SHADER_NO_SWIZZLE, dst_write_mask) == vkd3d_compact_swizzle(swizzle, write_mask); } -static bool vkd3d_swizzle_is_scalar(unsigned int swizzle) +static bool vkd3d_swizzle_is_scalar(uint32_t swizzle) { - unsigned int component_idx = vkd3d_swizzle_get_component(swizzle, 0); - return vkd3d_swizzle_get_component(swizzle, 1) == component_idx - && vkd3d_swizzle_get_component(swizzle, 2) == component_idx - && vkd3d_swizzle_get_component(swizzle, 3) == component_idx; + unsigned int component_idx = vsir_swizzle_get_component(swizzle, 0); + return vsir_swizzle_get_component(swizzle, 1) == component_idx + && vsir_swizzle_get_component(swizzle, 2) == component_idx + && vsir_swizzle_get_component(swizzle, 3) == component_idx; } static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, - uint32_t val_id, unsigned int val_write_mask, enum vkd3d_shader_component_type component_type, - unsigned int swizzle, unsigned int write_mask) + uint32_t val_id, uint32_t val_write_mask, enum vkd3d_shader_component_type component_type, + uint32_t swizzle, uint32_t write_mask) { unsigned int i, component_idx, component_count, val_component_count; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id, components[VKD3D_VEC4_SIZE]; - component_count = vkd3d_write_mask_component_count(write_mask); - val_component_count = vkd3d_write_mask_component_count(val_write_mask); + component_count = vsir_write_mask_component_count(write_mask); + val_component_count = vsir_write_mask_component_count(val_write_mask); if (component_count == val_component_count && (component_count == 1 || vkd3d_swizzle_is_equal(val_write_mask, swizzle, write_mask))) @@ -3589,9 +3633,9 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, if (component_count == 1) { - component_idx = vkd3d_write_mask_get_component_idx(write_mask); - component_idx = vkd3d_swizzle_get_component(swizzle, component_idx); - component_idx -= vkd3d_write_mask_get_component_idx(val_write_mask); + component_idx = vsir_write_mask_get_component_idx(write_mask); + component_idx = vsir_swizzle_get_component(swizzle, component_idx); + component_idx -= vsir_write_mask_get_component_idx(val_write_mask); return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx); } @@ -3601,7 +3645,7 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, { if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) { - assert(VKD3DSP_WRITEMASK_0 << vkd3d_swizzle_get_component(swizzle, i) == val_write_mask); + assert(VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(swizzle, i) == val_write_mask); components[component_idx++] = val_id; } } @@ -3611,14 +3655,14 @@ static uint32_t spirv_compiler_emit_swizzle(struct spirv_compiler *compiler, for (i = 0, component_idx = 0; i < VKD3D_VEC4_SIZE; ++i) { if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - components[component_idx++] = vkd3d_swizzle_get_component(swizzle, i); + components[component_idx++] = vsir_swizzle_get_component(swizzle, i); } return vkd3d_spirv_build_op_vector_shuffle(builder, type_id, val_id, val_id, components, component_count); } static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compiler, - uint32_t vector1_id, uint32_t vector2_id, unsigned int swizzle, unsigned int write_mask, + uint32_t vector1_id, uint32_t vector2_id, uint32_t swizzle, uint32_t write_mask, enum vkd3d_shader_component_type component_type, unsigned int component_count) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -3631,9 +3675,9 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil for (i = 0; i < component_count; ++i) { if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - components[i] = vkd3d_swizzle_get_component(swizzle, i); + components[i] = vsir_swizzle_get_component(swizzle, i); else - components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(swizzle, i); + components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(swizzle, i); } type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); @@ -3642,9 +3686,9 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil } static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) + const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) { - unsigned int component_count = vkd3d_write_mask_component_count(write_mask); + unsigned int component_count = vsir_write_mask_component_count(write_mask); uint32_t values[VKD3D_VEC4_SIZE] = {0}; unsigned int i, j; @@ -3653,14 +3697,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] = *reg->u.immconst_uint; + values[i] = *reg->u.immconst_u32; } else { for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) { if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - values[j++] = reg->u.immconst_uint[vkd3d_swizzle_get_component(swizzle, i)]; + values[j++] = reg->u.immconst_u32[vsir_swizzle_get_component(swizzle, i)]; } } @@ -3669,9 +3713,9 @@ static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compile } static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) + const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) { - unsigned int component_count = vkd3d_write_mask_component_count(write_mask); + unsigned int component_count = vsir_write_mask_component_count(write_mask); uint64_t values[VKD3D_DVEC2_SIZE] = {0}; unsigned int i, j; @@ -3680,14 +3724,14 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi if (reg->dimension == VSIR_DIMENSION_SCALAR) { for (i = 0; i < component_count; ++i) - values[i] = *reg->u.immconst_uint64; + values[i] = *reg->u.immconst_u64; } else { for (i = 0, j = 0; i < VKD3D_DVEC2_SIZE; ++i) { if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - values[j++] = reg->u.immconst_uint64[vkd3d_swizzle_get_component64(swizzle, i)]; + values[j++] = reg->u.immconst_u64[vsir_swizzle_get_component64(swizzle, i)]; } } @@ -3696,9 +3740,9 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi } static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, DWORD write_mask) + const struct vkd3d_shader_register *reg, uint32_t write_mask) { - unsigned int component_count = vkd3d_write_mask_component_count(write_mask); + unsigned int component_count = vsir_write_mask_component_count(write_mask); struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id; @@ -3709,28 +3753,28 @@ static uint32_t spirv_compiler_emit_load_undef(struct spirv_compiler *compiler, } static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask, + const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask, const struct vkd3d_shader_register_info *reg_info) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id, ptr_type_id, index, reg_id, val_id; unsigned int component_idx, reg_component_count; enum vkd3d_shader_component_type component_type; - unsigned int skipped_component_mask; + uint32_t skipped_component_mask; assert(!register_is_constant_or_undef(reg)); - assert(vkd3d_write_mask_component_count(write_mask) == 1); + assert(vsir_write_mask_component_count(write_mask) == 1); - component_idx = vkd3d_write_mask_get_component_idx(write_mask); - component_idx = vkd3d_swizzle_get_component(swizzle, component_idx); + component_idx = vsir_write_mask_get_component_idx(write_mask); + component_idx = vsir_swizzle_get_component(swizzle, component_idx); skipped_component_mask = ~reg_info->write_mask & ((VKD3DSP_WRITEMASK_0 << component_idx) - 1); if (skipped_component_mask) - component_idx -= vkd3d_write_mask_component_count(skipped_component_mask); + component_idx -= vsir_write_mask_component_count(skipped_component_mask); component_type = vkd3d_component_type_from_data_type(reg->data_type); - reg_component_count = vkd3d_write_mask_component_count(reg_info->write_mask); + reg_component_count = vsir_write_mask_component_count(reg_info->write_mask); - if (component_idx >= vkd3d_write_mask_component_count(reg_info->write_mask)) + if (component_idx >= vsir_write_mask_component_count(reg_info->write_mask)) { ERR("Invalid component_idx %u for register %#x, %u (write_mask %#x).\n", component_idx, reg->type, reg->idx[0].offset, reg_info->write_mask); @@ -3756,6 +3800,69 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler, return val_id; } +static uint32_t spirv_compiler_emit_constant_array(struct spirv_compiler *compiler, + const struct vkd3d_shader_immediate_constant_buffer *icb, uint32_t *type_id_out) +{ + uint32_t *elements, elem_type_id, length_id, type_id, const_id; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + enum vkd3d_shader_component_type component_type; + unsigned int i, element_count, component_count; + + element_count = icb->element_count; + + component_type = vkd3d_component_type_from_data_type(icb->data_type); + component_count = icb->component_count; + elem_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, icb->data_type, component_count); + length_id = spirv_compiler_get_constant_uint(compiler, element_count); + type_id = vkd3d_spirv_get_op_type_array(builder, elem_type_id, length_id); + + if (type_id_out) + *type_id_out = type_id; + + if (icb->is_null) + { + /* All values are null. Workgroup memory initialisers require OpConstantNull. */ + return vkd3d_spirv_get_op_constant_null(builder, type_id); + } + + if (!(elements = vkd3d_calloc(element_count, sizeof(*elements)))) + { + ERR("Failed to allocate %u elements.", element_count); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY, + "Failed to allocate %u constant array elements.", element_count); + return 0; + } + + switch (icb->data_type) + { + case VKD3D_DATA_FLOAT: + case VKD3D_DATA_INT: + case VKD3D_DATA_UINT: + for (i = 0; i < element_count; ++i) + elements[i] = spirv_compiler_get_constant(compiler, component_type, component_count, + &icb->data[component_count * i]); + break; + case VKD3D_DATA_DOUBLE: + case VKD3D_DATA_UINT64: + { + uint64_t *data = (uint64_t *)icb->data; + for (i = 0; i < element_count; ++i) + elements[i] = spirv_compiler_get_constant64(compiler, component_type, component_count, + &data[component_count * i]); + break; + } + default: + FIXME("Unhandled data type %u.\n", icb->data_type); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE, + "Immediate constant buffer data type %u is unhandled.", icb->data_type); + break; + } + + const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, element_count); + vkd3d_free(elements); + return const_id; +} + static const struct ssa_register_info *spirv_compiler_get_ssa_register_info(const struct spirv_compiler *compiler, const struct vkd3d_shader_register *reg) { @@ -3775,7 +3882,7 @@ static void spirv_compiler_set_ssa_register_info(const struct spirv_compiler *co static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler, const struct vkd3d_shader_register *reg, enum vkd3d_shader_component_type component_type, - unsigned int swizzle) + uint32_t swizzle) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; enum vkd3d_shader_component_type reg_component_type; @@ -3801,19 +3908,19 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler } type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); - component_idx = vkd3d_swizzle_get_component(swizzle, 0); + component_idx = vsir_swizzle_get_component(swizzle, 0); return vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, component_idx); } static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, DWORD swizzle, DWORD write_mask) + const struct vkd3d_shader_register *reg, DWORD swizzle, uint32_t write_mask) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; enum vkd3d_shader_component_type component_type; struct vkd3d_shader_register_info reg_info; unsigned int component_count; - unsigned int write_mask32; uint32_t type_id, val_id; + uint32_t write_mask32; if (reg->type == VKD3DSPR_IMMCONST) return spirv_compiler_emit_load_constant(compiler, reg, swizzle, write_mask); @@ -3822,7 +3929,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, else if (reg->type == VKD3DSPR_UNDEF) return spirv_compiler_emit_load_undef(compiler, reg, write_mask); - component_count = vkd3d_write_mask_component_count(write_mask); + component_count = vsir_write_mask_component_count(write_mask); component_type = vkd3d_component_type_from_data_type(reg->data_type); if (reg->type == VKD3DSPR_SSA) @@ -3836,21 +3943,21 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, assert(reg_info.component_type != VKD3D_SHADER_COMPONENT_DOUBLE); spirv_compiler_emit_dereference_register(compiler, reg, ®_info); - write_mask32 = (reg->data_type == VKD3D_DATA_DOUBLE) ? vkd3d_write_mask_32_from_64(write_mask) : write_mask; + write_mask32 = data_type_is_64_bit(reg->data_type) ? vsir_write_mask_32_from_64(write_mask) : write_mask; /* Intermediate value (no storage class). */ if (reg_info.storage_class == SpvStorageClassMax) { val_id = reg_info.id; } - else if (vkd3d_write_mask_component_count(write_mask32) == 1) + else if (vsir_write_mask_component_count(write_mask32) == 1) { return spirv_compiler_emit_load_scalar(compiler, reg, swizzle, write_mask, ®_info); } else { type_id = vkd3d_spirv_get_type_id(builder, - reg_info.component_type, vkd3d_write_mask_component_count(reg_info.write_mask)); + reg_info.component_type, vsir_write_mask_component_count(reg_info.write_mask)); val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_info.id, SpvMemoryAccessMaskNone); } @@ -3904,7 +4011,7 @@ static uint32_t spirv_compiler_emit_neg(struct spirv_compiler *compiler, type_id = spirv_compiler_get_type_id_for_reg(compiler, reg, write_mask); if (reg->data_type == VKD3D_DATA_FLOAT || reg->data_type == VKD3D_DATA_DOUBLE) return vkd3d_spirv_build_op_fnegate(builder, type_id, val_id); - else if (reg->data_type == VKD3D_DATA_INT || reg->data_type == VKD3D_DATA_UINT) + else if (data_type_is_integer(reg->data_type)) return vkd3d_spirv_build_op_snegate(builder, type_id, val_id); FIXME("Unhandled data type %#x.\n", reg->data_type); @@ -3953,19 +4060,19 @@ static uint32_t spirv_compiler_emit_load_src_with_type(struct spirv_compiler *co } static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, - uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type, - SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id) + uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type, + SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id, ptr_type_id, index; unsigned int component_idx; - if (vkd3d_write_mask_component_count(dst_write_mask) > 1) + if (vsir_write_mask_component_count(dst_write_mask) > 1) { type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); - component_idx = vkd3d_write_mask_get_component_idx(write_mask); - component_idx -= vkd3d_write_mask_get_component_idx(dst_write_mask); + component_idx = vsir_write_mask_get_component_idx(write_mask); + component_idx -= vsir_write_mask_get_component_idx(dst_write_mask); index = spirv_compiler_get_constant_uint(compiler, component_idx); dst_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, dst_id, index); } @@ -3974,8 +4081,8 @@ static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, } static void spirv_compiler_emit_store(struct spirv_compiler *compiler, - uint32_t dst_id, unsigned int dst_write_mask, enum vkd3d_shader_component_type component_type, - SpvStorageClass storage_class, unsigned int write_mask, uint32_t val_id) + uint32_t dst_id, uint32_t dst_write_mask, enum vkd3d_shader_component_type component_type, + SpvStorageClass storage_class, uint32_t write_mask, uint32_t val_id) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; unsigned int component_count, dst_component_count; @@ -3985,14 +4092,14 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, assert(write_mask); - component_count = vkd3d_write_mask_component_count(write_mask); - dst_component_count = vkd3d_write_mask_component_count(dst_write_mask); + component_count = vsir_write_mask_component_count(write_mask); + dst_component_count = vsir_write_mask_component_count(dst_write_mask); if (dst_component_count == 1 && component_count != 1) { type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); val_id = vkd3d_spirv_build_op_composite_extract1(builder, type_id, val_id, - vkd3d_write_mask_get_component_idx(dst_write_mask)); + vsir_write_mask_get_component_idx(dst_write_mask)); write_mask &= dst_write_mask; component_count = 1; } @@ -4029,12 +4136,12 @@ static void spirv_compiler_emit_store(struct spirv_compiler *compiler, } static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg, unsigned int 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; enum vkd3d_shader_component_type component_type; struct vkd3d_shader_register_info reg_info; - unsigned int src_write_mask = write_mask; + uint32_t src_write_mask = write_mask; uint32_t type_id; assert(!register_is_constant_or_undef(reg)); @@ -4052,10 +4159,10 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, component_type = vkd3d_component_type_from_data_type(reg->data_type); if (component_type != reg_info.component_type) { - if (reg->data_type == VKD3D_DATA_DOUBLE) - src_write_mask = vkd3d_write_mask_32_from_64(write_mask); + if (data_type_is_64_bit(reg->data_type)) + src_write_mask = vsir_write_mask_32_from_64(write_mask); type_id = vkd3d_spirv_get_type_id(builder, reg_info.component_type, - vkd3d_write_mask_component_count(src_write_mask)); + vsir_write_mask_component_count(src_write_mask)); val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); component_type = reg_info.component_type; } @@ -4065,9 +4172,9 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, } static uint32_t spirv_compiler_emit_sat(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) { - unsigned int component_count = vkd3d_write_mask_component_count(write_mask); + unsigned int component_count = vsir_write_mask_component_count(write_mask); struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id, zero_id, one_id; @@ -4118,7 +4225,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_component_type component_type, uint32_t *component_ids) { - unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask); + unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id, val_id; @@ -4137,16 +4244,16 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp static void spirv_compiler_emit_store_dst_scalar(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) { - unsigned int component_count = vkd3d_write_mask_component_count(dst->write_mask); + unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); uint32_t component_ids[VKD3D_VEC4_SIZE]; unsigned int component_idx, i; - component_idx = vkd3d_write_mask_get_component_idx(dst->write_mask); + component_idx = vsir_write_mask_get_component_idx(dst->write_mask); for (i = 0; i < component_count; ++i) { - if (vkd3d_swizzle_get_component(swizzle, component_idx + i)) + if (vsir_swizzle_get_component(swizzle, component_idx + i)) ERR("Invalid swizzle %#x for scalar value, write mask %#x.\n", swizzle, dst->write_mask); component_ids[i] = val_id; @@ -4191,14 +4298,18 @@ static void spirv_compiler_decorate_builtin(struct spirv_compiler *compiler, } static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler *compiler, - uint32_t id, enum vkd3d_shader_interpolation_mode mode) + enum vkd3d_shader_component_type component_type, uint32_t id, enum vkd3d_shader_interpolation_mode mode) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; switch (mode) { case VKD3DSIM_NONE: - break; + /* VUID-StandaloneSpirv-Flat-04744: integer or double types must be + * decorated 'Flat' for fragment shaders. */ + if (compiler->shader_type != VKD3D_SHADER_TYPE_PIXEL || component_type == VKD3D_SHADER_COMPONENT_FLOAT) + break; + /* fall through */ case VKD3DSIM_CONSTANT: vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationFlat, NULL, 0); break; @@ -4226,7 +4337,8 @@ static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler } static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, - enum vkd3d_shader_conditional_op condition, unsigned int component_count, uint32_t val_id) + enum vkd3d_shader_conditional_op condition, enum vkd3d_data_type data_type, + unsigned int component_count, uint32_t val_id) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id; @@ -4237,7 +4349,9 @@ static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual; return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, val_id, - spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); + data_type == VKD3D_DATA_UINT64 + ? spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count) + : spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); } static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, @@ -4252,6 +4366,19 @@ static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); } +static uint32_t spirv_compiler_emit_bool_to_int64(struct spirv_compiler *compiler, + unsigned int component_count, uint32_t val_id, bool signedness) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, true_id, false_id; + + true_id = spirv_compiler_get_constant_uint64_vector(compiler, signedness ? UINT64_MAX : 1, + component_count); + false_id = spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count); + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT64, component_count); + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); +} + static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compiler, unsigned int component_count, uint32_t val_id, bool signedness) { @@ -4422,9 +4549,9 @@ vkd3d_register_builtins[] = }; static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *compiler, - const struct vkd3d_shader_register *reg) + enum vkd3d_shader_register_type type) { - switch (reg->type) + switch (type) { case VKD3DSPR_DEPTHOUTGE: spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeDepthGreater, NULL, 0); @@ -4437,9 +4564,9 @@ static void spirv_compiler_emit_register_execution_mode(struct spirv_compiler *c VKD3D_SHADER_SPIRV_EXTENSION_EXT_STENCIL_EXPORT)) { FIXME("The target environment does not support stencil export.\n"); - spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED, - "Cannot export stencil reference value for register id %u. " - "The target environment does not support stencil export.", reg->idx[0].offset); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, + "Cannot export stencil reference value. " + "The target environment does not support stencil export."); } vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityStencilExportEXT); spirv_compiler_emit_execution_mode(compiler, SpvExecutionModeStencilRefReplacingEXT, NULL, 0); @@ -4674,17 +4801,16 @@ static unsigned int shader_signature_next_location(const struct shader_signature } static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst) + enum vkd3d_shader_register_type reg_type, unsigned int element_idx) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_register *reg = &dst->reg; unsigned int component_idx, input_component_count; const struct signature_element *signature_element; const struct shader_signature *shader_signature; enum vkd3d_shader_component_type component_type; const struct vkd3d_spirv_builtin *builtin; enum vkd3d_shader_sysval_semantic sysval; - unsigned int write_mask, reg_write_mask; + uint32_t write_mask, reg_write_mask; struct vkd3d_symbol *symbol = NULL; uint32_t val_id, input_id, var_id; uint32_t type_id, float_type_id; @@ -4693,26 +4819,21 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, struct rb_entry *entry = NULL; bool use_private_var = false; unsigned int array_sizes[2]; - unsigned int element_idx; - - assert(!reg->idx_count || !reg->idx[0].rel_addr); - assert(reg->idx_count < 2 || !reg->idx[1].rel_addr); - shader_signature = reg->type == VKD3DSPR_PATCHCONST + shader_signature = reg_type == VKD3DSPR_PATCHCONST ? &compiler->patch_constant_signature : &compiler->input_signature; - element_idx = reg->idx[reg->idx_count - 1].offset; signature_element = &shader_signature->elements[element_idx]; sysval = signature_element->sysval_semantic; /* The Vulkan spec does not explicitly forbid passing varyings from the * TCS to the TES via builtins. However, Mesa doesn't seem to handle it * well, and we don't actually need them to be in builtins. */ - if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN && reg->type != VKD3DSPR_PATCHCONST) + if (compiler->shader_type == VKD3D_SHADER_TYPE_DOMAIN && reg_type != VKD3DSPR_PATCHCONST) sysval = VKD3D_SHADER_SV_NONE; builtin = get_spirv_builtin_for_sysval(compiler, sysval); - array_sizes[0] = (reg->type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); + array_sizes[0] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); array_sizes[1] = signature_element->register_count; if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic) && (!vsir_sysval_semantic_is_clip_cull(signature_element->sysval_semantic) || array_sizes[0])) @@ -4731,8 +4852,8 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, else { component_type = signature_element->component_type; - input_component_count = vkd3d_write_mask_component_count(signature_element->mask); - component_idx = vkd3d_write_mask_get_component_idx(signature_element->mask); + input_component_count = vsir_write_mask_component_count(signature_element->mask); + component_idx = vsir_write_mask_get_component_idx(signature_element->mask); } if (needs_private_io_variable(builtin)) @@ -4742,13 +4863,13 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, } else { - component_idx = vkd3d_write_mask_get_component_idx(write_mask); + component_idx = vsir_write_mask_get_component_idx(write_mask); reg_write_mask = write_mask >> component_idx; } storage_class = SpvStorageClassInput; - vkd3d_symbol_make_register(®_symbol, reg); + vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); if ((entry = rb_get(&compiler->symbol_table, ®_symbol))) { @@ -4756,7 +4877,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, * duplicate declarations are: a single register split into multiple declarations having * different components, which should have been merged, and declarations in one phase * being repeated in another (i.e. vcp/vocp), which should have been deleted. */ - if (reg->type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler)) + if (reg_type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler)) FIXME("Duplicate input definition found.\n"); symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); return symbol->id; @@ -4765,7 +4886,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, if (builtin) { input_id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, storage_class, array_sizes, 2); - if (reg->type == VKD3DSPR_PATCHCONST) + if (reg_type == VKD3DSPR_PATCHCONST) vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0); } else @@ -4775,7 +4896,7 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, input_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, storage_class, component_type, input_component_count, array_sizes, 2); vkd3d_spirv_add_iface_variable(builder, input_id); - if (reg->type == VKD3DSPR_PATCHCONST) + if (reg_type == VKD3DSPR_PATCHCONST) { vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0); location += shader_signature_next_location(&compiler->input_signature); @@ -4784,7 +4905,8 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, if (component_idx) vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationComponent, component_idx); - spirv_compiler_emit_interpolation_decorations(compiler, input_id, signature_element->interpolation_mode); + spirv_compiler_emit_interpolation_decorations(compiler, component_type, input_id, + signature_element->interpolation_mode); } var_id = input_id; @@ -4802,12 +4924,14 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, assert(!builtin || !builtin->spirv_array_size || use_private_var || array_sizes[0] || array_sizes[1]); spirv_compiler_put_symbol(compiler, ®_symbol); - spirv_compiler_emit_register_debug_name(builder, var_id, reg); + vkd3d_spirv_build_op_name(builder, var_id, reg_type == VKD3DSPR_PATCHCONST ? "vpc%u" : "v%u", element_idx); if (use_private_var) { - struct vkd3d_shader_register dst_reg = *reg; - dst_reg.data_type = VKD3D_DATA_FLOAT; + struct vkd3d_shader_register dst_reg; + + vsir_register_init(&dst_reg, reg_type, VKD3D_DATA_FLOAT, 1); + dst_reg.idx[0].offset = element_idx; type_id = vkd3d_spirv_get_type_id(builder, component_type, input_component_count); @@ -4824,9 +4948,9 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, val_id = spirv_compiler_emit_swizzle(compiler, val_id, vkd3d_write_mask_from_component_count(input_component_count), - VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, dst->write_mask >> component_idx); + VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, signature_element->mask >> component_idx); - spirv_compiler_emit_store_reg(compiler, &dst_reg, dst->write_mask, val_id); + spirv_compiler_emit_store_reg(compiler, &dst_reg, signature_element->mask, val_id); } return input_id; @@ -4896,7 +5020,7 @@ static void calculate_clip_or_cull_distance_mask(const struct signature_element return; } - write_mask = e->mask >> vkd3d_write_mask_get_component_idx(e->mask); + write_mask = e->mask >> vsir_write_mask_get_component_idx(e->mask); *mask |= (write_mask & VKD3DSP_WRITEMASK_ALL) << (VKD3D_VEC4_SIZE * e->semantic_index); } @@ -4995,7 +5119,7 @@ static void spirv_compiler_emit_output_register(struct spirv_compiler *compiler, SpvStorageClassOutput, builtin->component_type, write_mask); reg_symbol.info.reg.is_aggregate = builtin->spirv_array_size; spirv_compiler_put_symbol(compiler, ®_symbol); - spirv_compiler_emit_register_execution_mode(compiler, reg); + spirv_compiler_emit_register_execution_mode(compiler, reg->type); spirv_compiler_emit_register_debug_name(builder, output_id, reg); } @@ -5024,46 +5148,44 @@ static uint32_t spirv_compiler_emit_shader_phase_builtin_variable(struct spirv_c return id; } -static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const struct vkd3d_shader_dst_param *dst) +static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + enum vkd3d_shader_register_type reg_type, unsigned int element_idx) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - const struct vkd3d_shader_register *reg = &dst->reg; unsigned int component_idx, output_component_count; const struct signature_element *signature_element; enum vkd3d_shader_component_type component_type; const struct shader_signature *shader_signature; const struct vkd3d_spirv_builtin *builtin; enum vkd3d_shader_sysval_semantic sysval; - unsigned int write_mask, reg_write_mask; + uint32_t write_mask, reg_write_mask; bool use_private_variable = false; struct vkd3d_symbol reg_symbol; SpvStorageClass storage_class; unsigned int array_sizes[2]; - unsigned int element_idx; bool is_patch_constant; uint32_t id, var_id; - is_patch_constant = is_in_fork_or_join_phase(compiler); + is_patch_constant = (reg_type == VKD3DSPR_PATCHCONST); shader_signature = is_patch_constant ? &compiler->patch_constant_signature : &compiler->output_signature; - element_idx = reg->idx[reg->idx_count - 1].offset; signature_element = &shader_signature->elements[element_idx]; sysval = signature_element->sysval_semantic; /* Don't use builtins for TCS -> TES varyings. See spirv_compiler_emit_input(). */ if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && !is_patch_constant) sysval = VKD3D_SHADER_SV_NONE; - array_sizes[0] = (reg->type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); + array_sizes[0] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); array_sizes[1] = signature_element->register_count; if (array_sizes[1] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic)) array_sizes[1] = 0; - builtin = vkd3d_get_spirv_builtin(compiler, dst->reg.type, sysval); + builtin = vkd3d_get_spirv_builtin(compiler, reg_type, sysval); write_mask = signature_element->mask; - component_idx = vkd3d_write_mask_get_component_idx(write_mask); - output_component_count = vkd3d_write_mask_component_count(write_mask); + component_idx = vsir_write_mask_get_component_idx(write_mask); + output_component_count = vsir_write_mask_component_count(write_mask); if (builtin) { component_type = builtin->component_type; @@ -5077,15 +5199,18 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st storage_class = SpvStorageClassOutput; - if (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE - || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask) - || needs_private_io_variable(builtin)) + if (needs_private_io_variable(builtin)) + use_private_variable = true; + + if (!is_patch_constant + && (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE + || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask))) { use_private_variable = true; } reg_write_mask = write_mask >> component_idx; - vkd3d_symbol_make_register(®_symbol, reg); + vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); if (rb_get(&compiler->symbol_table, ®_symbol)) { @@ -5094,7 +5219,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st return; } - if (compiler->output_info[element_idx].id) + if (!is_patch_constant && compiler->output_info[element_idx].id) { id = compiler->output_info[element_idx].id; } @@ -5105,7 +5230,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st else id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, storage_class, array_sizes, 2); - spirv_compiler_emit_register_execution_mode(compiler, &dst->reg); + spirv_compiler_emit_register_execution_mode(compiler, reg_type); } else if (signature_element->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) { @@ -5146,8 +5271,11 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st spirv_compiler_decorate_xfb_output(compiler, id, output_component_count, signature_element); - compiler->output_info[element_idx].id = id; - compiler->output_info[element_idx].component_type = component_type; + if (!is_patch_constant) + { + compiler->output_info[element_idx].id = id; + compiler->output_info[element_idx].component_type = component_type; + } var_id = id; if (use_private_variable) @@ -5165,8 +5293,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const st spirv_compiler_put_symbol(compiler, ®_symbol); - if (!is_patch_constant) - spirv_compiler_emit_register_debug_name(builder, var_id, reg); + vkd3d_spirv_build_op_name(builder, var_id, reg_type == VKD3DSPR_PATCHCONST ? "vpc%u" : "o%u", element_idx); if (use_private_variable) { @@ -5198,9 +5325,9 @@ static uint32_t spirv_compiler_get_output_array_index(struct spirv_compiler *com static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compiler, const struct shader_signature *signature, const struct signature_element *output, const struct vkd3d_shader_output_info *output_info, - uint32_t output_index_id, uint32_t val_id, unsigned int write_mask) + uint32_t output_index_id, uint32_t val_id, uint32_t write_mask) { - unsigned int dst_write_mask, use_mask, uninit_mask, swizzle, mask; + uint32_t dst_write_mask, use_mask, uninit_mask, swizzle, mask; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id, zero_id, ptr_type_id, chain_id, object_id; const struct signature_element *element; @@ -5222,7 +5349,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi use_mask |= element->used_mask; } } - index = vkd3d_write_mask_get_component_idx(output->mask); + index = vsir_write_mask_get_component_idx(output->mask); dst_write_mask >>= index; use_mask >>= index; write_mask &= dst_write_mask; @@ -5246,7 +5373,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi output_info->component_type, VKD3D_VEC4_SIZE, 0); val_id = spirv_compiler_emit_vector_shuffle(compiler, zero_id, val_id, swizzle, uninit_mask, output_info->component_type, - vkd3d_write_mask_component_count(write_mask)); + vsir_write_mask_component_count(write_mask)); } else { @@ -5258,7 +5385,7 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi if (output_index_id) { type_id = vkd3d_spirv_get_type_id(builder, - output_info->component_type, vkd3d_write_mask_component_count(dst_write_mask)); + output_info->component_type, vsir_write_mask_component_count(dst_write_mask)); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); output_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, output_id, output_index_id); } @@ -5444,6 +5571,21 @@ static void spirv_compiler_emit_dcl_global_flags(struct spirv_compiler *compiler flags &= ~(VKD3DSGF_ENABLE_DOUBLE_PRECISION_FLOAT_OPS | VKD3DSGF_ENABLE_11_1_DOUBLE_EXTENSIONS); } + if (flags & VKD3DSGF_ENABLE_INT64) + { + if (compiler->features & VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64) + { + vkd3d_spirv_enable_capability(&compiler->spirv_builder, SpvCapabilityInt64); + } + else + { + WARN("Unsupported 64-bit integer ops.\n"); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE, + "The target environment does not support 64-bit integers."); + } + flags &= ~VKD3DSGF_ENABLE_INT64; + } + if (flags & ~(VKD3DSGF_REFACTORING_ALLOWED | VKD3DSGF_ENABLE_RAW_AND_STRUCTURED_BUFFERS)) FIXME("Unhandled global flags %#"PRIx64".\n", (uint64_t)flags); else @@ -5493,39 +5635,40 @@ static void spirv_compiler_emit_dcl_indexable_temp(struct spirv_compiler *compil { const struct vkd3d_shader_indexable_temp *temp = &instruction->declaration.indexable_temp; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t id, type_id, length_id, ptr_type_id, init_id = 0; + enum vkd3d_shader_component_type component_type; struct vkd3d_shader_register reg; struct vkd3d_symbol reg_symbol; + SpvStorageClass storage_class; size_t function_location; - uint32_t id; - if (temp->component_count != 4) - FIXME("Unhandled component count %u.\n", temp->component_count); + storage_class = SpvStorageClassFunction; vsir_register_init(®, VKD3DSPR_IDXTEMP, VKD3D_DATA_FLOAT, 1); reg.idx[0].offset = temp->register_idx; if (temp->alignment) WARN("Ignoring alignment %u.\n", temp->alignment); - if (temp->initialiser) - { - FIXME("Initialisers are not supported.\n"); - spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, - "Initialisers for indexable temps are not supported."); - } function_location = spirv_compiler_get_current_function_location(compiler); vkd3d_spirv_begin_function_stream_insertion(builder, function_location); - id = spirv_compiler_emit_array_variable(compiler, &builder->function_stream, - SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &temp->register_size, 1); + component_type = vkd3d_component_type_from_data_type(temp->data_type); + type_id = vkd3d_spirv_get_type_id(builder, component_type, temp->component_count); + length_id = spirv_compiler_get_constant_uint(compiler, temp->register_size); + type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); + if (temp->initialiser) + init_id = spirv_compiler_emit_constant_array(compiler, temp->initialiser, NULL); + id = vkd3d_spirv_build_op_variable(builder, &builder->function_stream, ptr_type_id, storage_class, init_id); spirv_compiler_emit_register_debug_name(builder, id, ®); vkd3d_spirv_end_function_stream_insertion(builder); vkd3d_symbol_make_register(®_symbol, ®); - vkd3d_symbol_set_register_info(®_symbol, id, - SpvStorageClassFunction, VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); + vkd3d_symbol_set_register_info(®_symbol, id, storage_class, + component_type, vkd3d_write_mask_from_component_count(temp->component_count)); spirv_compiler_put_symbol(compiler, ®_symbol); } @@ -5743,34 +5886,24 @@ static void spirv_compiler_emit_dcl_immediate_constant_buffer(struct spirv_compi const struct vkd3d_shader_instruction *instruction) { const struct vkd3d_shader_immediate_constant_buffer *icb = instruction->declaration.icb; - uint32_t *elements, length_id, type_id, const_id, ptr_type_id, icb_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, const_id, ptr_type_id, icb_id; struct vkd3d_shader_register reg; struct vkd3d_symbol reg_symbol; - unsigned int i; - assert(icb->data_type == VKD3D_DATA_FLOAT); - assert(icb->component_count == VKD3D_VEC4_SIZE); - - if (!(elements = vkd3d_calloc(icb->element_count, sizeof(*elements)))) - return; - for (i = 0; i < icb->element_count; ++i) - elements[i] = spirv_compiler_get_constant(compiler, - VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE, &icb->data[4 * i]); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_VEC4_SIZE); - length_id = spirv_compiler_get_constant_uint(compiler, icb->element_count); - type_id = vkd3d_spirv_get_op_type_array(builder, type_id, length_id); - const_id = vkd3d_spirv_build_op_constant_composite(builder, type_id, elements, icb->element_count); + const_id = spirv_compiler_emit_constant_array(compiler, icb, &type_id); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassPrivate, type_id); icb_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, ptr_type_id, SpvStorageClassPrivate, const_id); vkd3d_spirv_build_op_name(builder, icb_id, "icb"); - vkd3d_free(elements); - vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 0); + /* Set an index count of 2 so vkd3d_symbol_make_register() uses idx[0] as a buffer id. */ + vsir_register_init(®, VKD3DSPR_IMMCONSTBUFFER, VKD3D_DATA_FLOAT, 2); + reg.idx[0].offset = icb->register_idx; vkd3d_symbol_make_register(®_symbol, ®); vkd3d_symbol_set_register_info(®_symbol, icb_id, SpvStorageClassPrivate, - VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); + vkd3d_component_type_from_data_type(icb->data_type), + vkd3d_write_mask_from_component_count(icb->component_count)); spirv_compiler_put_symbol(compiler, ®_symbol); } @@ -6147,37 +6280,22 @@ static void spirv_compiler_emit_dcl_input(struct spirv_compiler *compiler, { const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst; - /* OUTPOINTID is handled in spirv_compiler_emit_hull_shader_builtins(). */ - if (dst->reg.type == VKD3DSPR_INPUT || dst->reg.type == VKD3DSPR_PATCHCONST) - spirv_compiler_emit_input(compiler, dst); - else if (dst->reg.type != VKD3DSPR_OUTPOINTID) + /* INPUT and PATCHCONST are handled in spirv_compiler_emit_io_declarations(). + * OUTPOINTID is handled in spirv_compiler_emit_hull_shader_builtins(). */ + if (dst->reg.type != VKD3DSPR_INPUT && dst->reg.type != VKD3DSPR_PATCHCONST + && dst->reg.type != VKD3DSPR_OUTPOINTID) spirv_compiler_emit_input_register(compiler, dst); } -static void spirv_compiler_emit_dcl_input_sysval(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) -{ - spirv_compiler_emit_input(compiler, &instruction->declaration.register_semantic.reg); -} - static void spirv_compiler_emit_dcl_output(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst; - if (dst->reg.type == VKD3DSPR_OUTPUT - || (is_in_fork_or_join_phase(compiler) && dst->reg.type == VKD3DSPR_PATCHCONST)) - spirv_compiler_emit_output(compiler, dst); - else + if (dst->reg.type != VKD3DSPR_OUTPUT && dst->reg.type != VKD3DSPR_PATCHCONST) spirv_compiler_emit_output_register(compiler, dst); } -static void spirv_compiler_emit_dcl_output_siv(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) -{ - spirv_compiler_emit_output(compiler, &instruction->declaration.register_semantic.reg); -} - static void spirv_compiler_emit_dcl_stream(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { @@ -6377,7 +6495,6 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler) { - const struct shader_signature *signature = &compiler->output_signature; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; if (is_in_control_point_phase(compiler) && compiler->emit_default_control_point_phase) @@ -6395,7 +6512,6 @@ static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler) /* Fork and join phases share output registers (patch constants). * Control point phase has separate output registers. */ - memset(compiler->output_info, 0, signature->element_count * sizeof(*compiler->output_info)); memset(compiler->private_output_variable, 0, sizeof(compiler->private_output_variable)); memset(compiler->private_output_variable_write_mask, 0, sizeof(compiler->private_output_variable_write_mask)); } @@ -6438,15 +6554,12 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile { const struct shader_signature *output_signature = &compiler->output_signature; const struct shader_signature *input_signature = &compiler->input_signature; + uint32_t type_id, output_ptr_type_id, input_id, dst_id, invocation_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; enum vkd3d_shader_component_type component_type; struct vkd3d_shader_src_param invocation; struct vkd3d_shader_register input_reg; - uint32_t type_id, output_ptr_type_id; - uint32_t input_id, output_id, dst_id; unsigned int component_count; - unsigned int array_sizes[2]; - uint32_t invocation_id; unsigned int i; invocation_id = spirv_compiler_emit_load_invocation_id(compiler); @@ -6466,6 +6579,8 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile { const struct signature_element *output = &output_signature->elements[i]; const struct signature_element *input = &input_signature->elements[i]; + struct vkd3d_shader_register_info output_reg_info; + struct vkd3d_shader_register output_reg; assert(input->mask == output->mask); assert(input->component_type == output->component_type); @@ -6473,22 +6588,16 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile input_reg.idx[1].offset = i; input_id = spirv_compiler_get_register_id(compiler, &input_reg); + vsir_register_init(&output_reg, VKD3DSPR_OUTPUT, VKD3D_DATA_FLOAT, 1); + output_reg.idx[0].offset = i; + spirv_compiler_get_register_info(compiler, &output_reg, &output_reg_info); + component_type = output->component_type; - component_count = vkd3d_write_mask_component_count(output->mask); + component_count = vsir_write_mask_component_count(output->mask); type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); - if ((array_sizes[0] = (input->register_count > 1) ? input->register_count : 0)) - type_id = vkd3d_spirv_get_op_type_array(builder, type_id, spirv_compiler_get_constant_uint(compiler, - array_sizes[0])); - - array_sizes[1] = compiler->output_control_point_count; - output_id = spirv_compiler_emit_array_variable(compiler, &builder->global_stream, SpvStorageClassOutput, - component_type, component_count, array_sizes, 2); - vkd3d_spirv_add_iface_variable(builder, output_id); - vkd3d_spirv_build_op_decorate1(builder, output_id, SpvDecorationLocation, output->register_index); - vkd3d_spirv_build_op_name(builder, output_id, "vocp%u", output->register_index); - output_ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); - dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_id, invocation_id); + + dst_id = vkd3d_spirv_build_op_access_chain1(builder, output_ptr_type_id, output_reg_info.id, invocation_id); vkd3d_spirv_build_op_copy_memory(builder, dst_id, input_id, SpvMemoryAccessMaskNone); } @@ -6593,12 +6702,14 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru {VKD3DSIH_ISHR, SpvOpShiftRightArithmetic}, {VKD3DSIH_ITOD, SpvOpConvertSToF}, {VKD3DSIH_ITOF, SpvOpConvertSToF}, + {VKD3DSIH_ITOI, SpvOpSConvert}, {VKD3DSIH_MUL, SpvOpFMul}, {VKD3DSIH_NOT, SpvOpNot}, {VKD3DSIH_OR, SpvOpBitwiseOr}, {VKD3DSIH_USHR, SpvOpShiftRightLogical}, {VKD3DSIH_UTOD, SpvOpConvertUToF}, {VKD3DSIH_UTOF, SpvOpConvertUToF}, + {VKD3DSIH_UTOU, SpvOpUConvert}, {VKD3DSIH_XOR, SpvOpBitwiseXor}, }; unsigned int i; @@ -6650,6 +6761,10 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, { val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); } + else if (dst->reg.data_type == VKD3D_DATA_UINT64) + { + val_id = spirv_compiler_emit_bool_to_int64(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); + } else { WARN("Unhandled data type %u.\n", dst->reg.data_type); @@ -6715,11 +6830,11 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil * Microsoft fxc will compile immediate constants larger than 5 bits. * Fixing up the constants would be more elegant, but the simplest way is * to let this handle constants too. */ - if (instruction->handler_idx == VKD3DSIH_ISHL || instruction->handler_idx == VKD3DSIH_ISHR - || instruction->handler_idx == VKD3DSIH_USHR) + if (!(instruction->flags & VKD3DSI_SHIFT_UNMASKED) && (instruction->handler_idx == VKD3DSIH_ISHL + || instruction->handler_idx == VKD3DSIH_ISHR || instruction->handler_idx == VKD3DSIH_USHR)) { uint32_t mask_id = spirv_compiler_get_constant_vector(compiler, - VKD3D_SHADER_COMPONENT_UINT, vkd3d_write_mask_component_count(dst->write_mask), 0x1f); + VKD3D_SHADER_COMPONENT_UINT, vsir_write_mask_component_count(dst->write_mask), 0x1f); src_ids[1] = vkd3d_spirv_build_op_and(builder, type_id, src_ids[1], mask_id); } @@ -6849,7 +6964,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, return; } - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); if (component_count != 1 && component_count != VKD3D_VEC4_SIZE && dst_reg_info.write_mask == VKD3DSP_WRITEMASK_ALL) { @@ -6863,7 +6978,7 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, for (i = 0; i < ARRAY_SIZE(components); ++i) { if (dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)) - components[i] = VKD3D_VEC4_SIZE + vkd3d_swizzle_get_component(src->swizzle, i); + components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(src->swizzle, i); else components[i] = i; } @@ -6877,6 +6992,11 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, general_implementation: val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); + if (dst->reg.data_type != src->reg.data_type) + { + val_id = vkd3d_spirv_build_op_bitcast(builder, vkd3d_spirv_get_type_id_for_data_type(builder, + dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)), val_id); + } spirv_compiler_emit_store_dst(compiler, dst, val_id); } @@ -6893,12 +7013,12 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask); - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); if (src[0].reg.data_type != VKD3D_DATA_BOOL) condition_id = spirv_compiler_emit_int_to_bool(compiler, - VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id); + VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src1_id, src2_id); spirv_compiler_emit_store_dst(compiler, dst, val_id); @@ -6919,11 +7039,11 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler, src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); src2_id = spirv_compiler_emit_load_src(compiler, &src[2], dst->write_mask); - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); condition_id = spirv_compiler_emit_int_to_bool(compiler, - VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, condition_id); + VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, component_count, condition_id); val_id = vkd3d_spirv_build_op_select(builder, type_id, condition_id, src2_id, src1_id); spirv_compiler_emit_store_dst(compiler, &dst[0], val_id); @@ -6942,7 +7062,7 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, unsigned int component_count, i; DWORD write_mask; - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); if (instruction->handler_idx == VKD3DSIH_DP4) @@ -6980,7 +7100,7 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler, uint32_t type_id, src_id, val_id, div_id; unsigned int component_count; - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); @@ -7060,7 +7180,7 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, uint32_t type_id, val_id, src_ids[3]; unsigned int i, component_count; - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, component_count); for (i = 0; i < ARRAY_SIZE(src_ids); ++i) @@ -7087,16 +7207,18 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, if (dst[0].reg.type != VKD3DSPR_NULL) { - component_count = vkd3d_write_mask_component_count(dst[0].write_mask); + component_count = vsir_write_mask_component_count(dst[0].write_mask); type_id = spirv_compiler_get_type_id_for_dst(compiler, &dst[0]); src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst[0].write_mask); src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst[0].write_mask); condition_id = spirv_compiler_emit_int_to_bool(compiler, - VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id); - uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, - 0xffffffff, component_count); + VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src1_id); + if (dst[0].reg.data_type == VKD3D_DATA_UINT64) + uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count); + else + uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count); val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, div_op, type_id, src0_id, src1_id); /* The SPIR-V spec says: "The resulting value is undefined if Operand 2 is 0." */ @@ -7109,16 +7231,18 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, { if (!component_count || dst[0].write_mask != dst[1].write_mask) { - component_count = vkd3d_write_mask_component_count(dst[1].write_mask); + component_count = vsir_write_mask_component_count(dst[1].write_mask); type_id = spirv_compiler_get_type_id_for_dst(compiler, &dst[1]); src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst[1].write_mask); src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst[1].write_mask); condition_id = spirv_compiler_emit_int_to_bool(compiler, - VKD3D_SHADER_CONDITIONAL_OP_NZ, component_count, src1_id); - uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, - 0xffffffff, component_count); + VKD3D_SHADER_CONDITIONAL_OP_NZ, src[1].reg.data_type, component_count, src1_id); + if (dst[1].reg.data_type == VKD3D_DATA_UINT64) + uint_max_id = spirv_compiler_get_constant_uint64_vector(compiler, UINT64_MAX, component_count); + else + uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, 0xffffffff, component_count); } val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, mod_op, type_id, src0_id, src1_id); @@ -7147,7 +7271,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, * as a signed integer, but Direct3D expects the result to saturate, * and for NaN to yield zero. */ - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask); dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); @@ -7200,7 +7324,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, * as an unsigned integer, but Direct3D expects the result to saturate, * and for NaN to yield zero. */ - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask); dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); @@ -7387,7 +7511,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co return; } - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); src0_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); src1_id = spirv_compiler_emit_load_src(compiler, &src[1], dst->write_mask); @@ -7409,7 +7533,7 @@ static uint32_t spirv_compiler_emit_conditional_branch(struct spirv_compiler *co uint32_t condition_id, merge_block_id; condition_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); - condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, 1, condition_id); + condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, src->reg.data_type, 1, condition_id); merge_block_id = vkd3d_spirv_alloc_id(builder); @@ -7542,7 +7666,7 @@ static int spirv_compiler_emit_control_flow_instruction(struct spirv_compiler *c return VKD3D_ERROR_OUT_OF_MEMORY; val_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); - condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, 1, val_id); + condition_id = spirv_compiler_emit_int_to_bool(compiler, instruction->flags, src->reg.data_type, 1, val_id); true_label = vkd3d_spirv_alloc_id(builder); merge_block_id = vkd3d_spirv_alloc_id(builder); @@ -7705,7 +7829,7 @@ static int spirv_compiler_emit_control_flow_instruction(struct spirv_compiler *c "The swizzle for a switch case value is not scalar."); } assert(src->reg.type == VKD3DSPR_IMMCONST); - value = *src->reg.u.immconst_uint; + value = *src->reg.u.immconst_u32; if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.case_blocks, &cf_info->u.switch_.case_blocks_size, 2 * (cf_info->u.switch_.case_block_count + 1), sizeof(*cf_info->u.switch_.case_blocks))) @@ -8325,7 +8449,7 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, } else { - component_idx = vkd3d_swizzle_get_component(sampler->swizzle, 0); + component_idx = vsir_swizzle_get_component(sampler->swizzle, 0); /* Nvidia driver requires signed integer type. */ component_id = spirv_compiler_get_constant(compiler, VKD3D_SHADER_COMPONENT_INT, 1, &component_idx); @@ -8403,7 +8527,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) continue; - component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); + component_idx = vsir_swizzle_get_component(resource->swizzle, i); coordinate_id = base_coordinate_id; if (component_idx) coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, @@ -8435,7 +8559,7 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) continue; - component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); + component_idx = vsir_swizzle_get_component(resource->swizzle, i); coordinate_id = base_coordinate_id; if (component_idx) coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, @@ -8479,7 +8603,7 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, if (!(dst->write_mask & (VKD3DSP_WRITEMASK_0 << i))) continue; - component_idx = vkd3d_swizzle_get_component(resource->swizzle, i); + component_idx = vsir_swizzle_get_component(resource->swizzle, i); coordinate_id = base_coordinate_id; if (component_idx) coordinate_id = vkd3d_spirv_build_op_iadd(builder, type_id, @@ -8540,7 +8664,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * assert(data->reg.data_type == VKD3D_DATA_UINT); val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); for (component_idx = 0; component_idx < component_count; ++component_idx) { data_id = component_count > 1 ? @@ -8569,7 +8693,7 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * assert(data->reg.data_type == VKD3D_DATA_UINT); val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); for (component_idx = 0; component_idx < component_count; ++component_idx) { /* Mesa Vulkan drivers require the texel parameter to be a vector. */ @@ -8613,7 +8737,7 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, assert(data->reg.data_type == VKD3D_DATA_UINT); val_id = spirv_compiler_emit_load_src(compiler, data, dst->write_mask); - component_count = vkd3d_write_mask_component_count(dst->write_mask); + component_count = vsir_write_mask_component_count(dst->write_mask); for (component_idx = 0; component_idx < component_count; ++component_idx) { data_id = component_count > 1 ? @@ -9275,7 +9399,7 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, } type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, - vkd3d_write_mask_component_count(register_info.write_mask)); + vsir_write_mask_component_count(register_info.write_mask)); instr_set_id = vkd3d_spirv_get_glsl_std450_instr_set(builder); val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id, instr_set_id, op, src_ids, src_count); @@ -9425,18 +9549,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_DCL_INPUT: spirv_compiler_emit_dcl_input(compiler, instruction); break; - case VKD3DSIH_DCL_INPUT_PS_SGV: - case VKD3DSIH_DCL_INPUT_PS_SIV: - case VKD3DSIH_DCL_INPUT_SGV: - case VKD3DSIH_DCL_INPUT_SIV: - spirv_compiler_emit_dcl_input_sysval(compiler, instruction); - break; case VKD3DSIH_DCL_OUTPUT: spirv_compiler_emit_dcl_output(compiler, instruction); break; - case VKD3DSIH_DCL_OUTPUT_SIV: - spirv_compiler_emit_dcl_output_siv(compiler, instruction); - break; case VKD3DSIH_DCL_STREAM: spirv_compiler_emit_dcl_stream(compiler, instruction); break; @@ -9719,6 +9834,11 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_DCL_CONSTANT_BUFFER: case VKD3DSIH_DCL_HS_MAX_TESSFACTOR: case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT: + case VKD3DSIH_DCL_INPUT_SGV: + case VKD3DSIH_DCL_INPUT_SIV: + case VKD3DSIH_DCL_INPUT_PS_SGV: + case VKD3DSIH_DCL_INPUT_PS_SIV: + case VKD3DSIH_DCL_OUTPUT_SIV: case VKD3DSIH_DCL_RESOURCE_RAW: case VKD3DSIH_DCL_RESOURCE_STRUCTURED: case VKD3DSIH_DCL_SAMPLER: @@ -9740,6 +9860,30 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, return ret; } +static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) +{ + for (unsigned int i = 0; i < compiler->input_signature.element_count; ++i) + spirv_compiler_emit_input(compiler, VKD3DSPR_INPUT, i); + + for (unsigned int i = 0; i < compiler->output_signature.element_count; ++i) + { + /* PS outputs other than TARGET have dedicated registers and therefore + * go through spirv_compiler_emit_dcl_output() for now. */ + if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL + && compiler->output_signature.elements[i].sysval_semantic != VKD3D_SHADER_SV_TARGET) + continue; + spirv_compiler_emit_output(compiler, VKD3DSPR_OUTPUT, i); + } + + for (unsigned int i = 0; i < compiler->patch_constant_signature.element_count; ++i) + { + if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL) + spirv_compiler_emit_output(compiler, VKD3DSPR_PATCHCONST, i); + else + spirv_compiler_emit_input(compiler, VKD3DSPR_PATCHCONST, i); + } +} + static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *compiler) { unsigned int i; @@ -9826,6 +9970,8 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) spirv_compiler_emit_shader_signature_outputs(compiler); + spirv_compiler_emit_io_declarations(compiler); + for (i = 0; i < instructions.count && result >= 0; ++i) { compiler->location.line = i + 1; @@ -9874,11 +10020,28 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, if (!vkd3d_spirv_compile_module(builder, spirv, spirv_compiler_get_entry_point_name(compiler))) return VKD3D_ERROR; - if (TRACE_ON()) + if (TRACE_ON() || parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION) { enum vkd3d_shader_spirv_environment environment = spirv_compiler_get_target_environment(compiler); - vkd3d_spirv_dump(spirv, environment); - vkd3d_spirv_validate(spirv, environment); + struct vkd3d_string_buffer buffer; + + if (TRACE_ON()) + vkd3d_spirv_dump(spirv, environment); + + vkd3d_string_buffer_init(&buffer); + if (!vkd3d_spirv_validate(&buffer, spirv, environment)) + { + FIXME("Failed to validate SPIR-V binary.\n"); + vkd3d_shader_trace_text(buffer.buffer, buffer.content_size); + + if (compiler->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION) + { + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER, + "Execution generated an invalid shader, failing compilation:\n%s", + buffer.buffer); + } + } + vkd3d_string_buffer_cleanup(&buffer); } if (compiler->failed) @@ -9905,7 +10068,7 @@ int spirv_compile(struct vkd3d_shader_parser *parser, int ret; if (!(spirv_compiler = spirv_compiler_create(&parser->shader_version, &parser->shader_desc, - compile_info, scan_descriptor_info, message_context, &parser->location))) + compile_info, scan_descriptor_info, message_context, &parser->location, parser->config_flags))) { ERR("Failed to create SPIR-V compiler.\n"); return VKD3D_ERROR; diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c index 80f8ab98c08..f859e758d8e 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -792,9 +792,11 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui ins->handler_idx = VKD3DSIH_INVALID; return; } + icb->register_idx = 0; icb->data_type = VKD3D_DATA_FLOAT; icb->component_count = VKD3D_VEC4_SIZE; icb->element_count = icb_size / VKD3D_VEC4_SIZE; + icb->is_null = false; memcpy(icb->data, tokens, sizeof(*tokens) * icb_size); shader_instruction_array_add_icb(&priv->p.instructions, icb); ins->declaration.icb = icb; @@ -918,10 +920,11 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) { struct vkd3d_shader_index_range *index_range = &ins->declaration.index_range; - unsigned int i, register_idx, register_count, write_mask; + unsigned int i, register_idx, register_count; enum vkd3d_shader_register_type type; struct sm4_index_range_array *ranges; unsigned int *io_masks; + uint32_t write_mask; shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &index_range->dst); @@ -931,7 +934,7 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins register_count = index_range->register_count; write_mask = index_range->dst.write_mask; - if (vkd3d_write_mask_component_count(write_mask) != 1) + if (vsir_write_mask_component_count(write_mask) != 1) { WARN("Unhandled write mask %#x.\n", write_mask); vkd3d_shader_parser_warning(&priv->p, VKD3D_SHADER_WARNING_TPF_UNHANDLED_INDEX_RANGE_MASK, @@ -1900,19 +1903,19 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui if (register_type == VKD3D_SM4_RT_IMMCONST || register_type == VKD3D_SM4_RT_IMMCONST64) { - unsigned int dword_count; + unsigned int u32_count; switch (param->dimension) { case VSIR_DIMENSION_SCALAR: - dword_count = 1 + (register_type == VKD3D_SM4_RT_IMMCONST64); - if (end - *ptr < dword_count) + u32_count = 1 + (register_type == VKD3D_SM4_RT_IMMCONST64); + if (end - *ptr < u32_count) { WARN("Invalid ptr %p, end %p.\n", *ptr, end); return false; } - memcpy(param->u.immconst_uint, *ptr, dword_count * sizeof(DWORD)); - *ptr += dword_count; + memcpy(param->u.immconst_u32, *ptr, u32_count * sizeof(uint32_t)); + *ptr += u32_count; break; case VSIR_DIMENSION_VEC4: @@ -1921,7 +1924,7 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui WARN("Invalid ptr %p, end %p.\n", *ptr, end); return false; } - memcpy(param->u.immconst_uint, *ptr, VKD3D_VEC4_SIZE * sizeof(DWORD)); + memcpy(param->u.immconst_u32, *ptr, VKD3D_VEC4_SIZE * sizeof(uint32_t)); *ptr += 4; break; @@ -1930,6 +1933,15 @@ static bool shader_sm4_read_param(struct vkd3d_shader_sm4_parser *priv, const ui break; } } + else if (register_type == VKD3D_SM4_RT_IMMCONSTBUFFER) + { + if (param->idx_count != 1) + { + WARN("Unexpected idx count %u.\n", param->idx_count); + vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_INDEX_COUNT, + "Invalid index count %u for immediate const buffer register; expected count 1.", param->idx_count); + } + } else if (!shader_is_sm_5_1(priv) && vsir_register_is_descriptor(param)) { /* SM5.1 places a symbol identifier in idx[0] and moves @@ -1970,10 +1982,10 @@ static uint32_t swizzle_from_sm4(uint32_t s) static uint32_t swizzle_to_sm4(uint32_t s) { uint32_t ret = 0; - ret |= ((vkd3d_swizzle_get_component(s, 0)) & 0x3); - ret |= ((vkd3d_swizzle_get_component(s, 1)) & 0x3) << 2; - ret |= ((vkd3d_swizzle_get_component(s, 2)) & 0x3) << 4; - ret |= ((vkd3d_swizzle_get_component(s, 3)) & 0x3) << 6; + ret |= ((vsir_swizzle_get_component(s, 0)) & 0x3); + ret |= ((vsir_swizzle_get_component(s, 1)) & 0x3) << 2; + ret |= ((vsir_swizzle_get_component(s, 2)) & 0x3) << 4; + ret |= ((vsir_swizzle_get_component(s, 3)) & 0x3) << 6; return ret; } @@ -2002,12 +2014,12 @@ static bool register_is_control_point_input(const struct vkd3d_shader_register * || priv->p.shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY)); } -static unsigned int mask_from_swizzle(unsigned int swizzle) +static uint32_t mask_from_swizzle(uint32_t swizzle) { - return (1u << vkd3d_swizzle_get_component(swizzle, 0)) - | (1u << vkd3d_swizzle_get_component(swizzle, 1)) - | (1u << vkd3d_swizzle_get_component(swizzle, 2)) - | (1u << vkd3d_swizzle_get_component(swizzle, 3)); + return (1u << vsir_swizzle_get_component(swizzle, 0)) + | (1u << vsir_swizzle_get_component(swizzle, 1)) + | (1u << vsir_swizzle_get_component(swizzle, 2)) + | (1u << vsir_swizzle_get_component(swizzle, 3)); } static bool shader_sm4_validate_input_output_register(struct vkd3d_shader_sm4_parser *priv, @@ -2219,7 +2231,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons } if (data_type == VKD3D_DATA_DOUBLE) - dst_param->write_mask = vkd3d_write_mask_64_from_32(dst_param->write_mask); + dst_param->write_mask = vsir_write_mask_64_from_32(dst_param->write_mask); /* Some scalar registers are declared with no write mask in shader bytecode. */ if (!dst_param->write_mask && shader_sm4_is_scalar_register(&dst_param->reg)) dst_param->write_mask = VKD3DSP_WRITEMASK_0; @@ -2533,6 +2545,16 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t return true; } +static void uninvert_used_masks(struct shader_signature *signature) +{ + for (unsigned int i = 0; i < signature->element_count; ++i) + { + struct signature_element *e = &signature->elements[i]; + + e->used_mask = e->mask & ~e->used_mask; + } +} + static bool shader_sm4_parser_validate_signature(struct vkd3d_shader_sm4_parser *sm4, const struct shader_signature *signature, unsigned int *masks, const char *name) { @@ -2628,6 +2650,12 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi return VKD3D_ERROR_INVALID_ARGUMENT; } + /* DXBC stores used masks inverted for output signatures, for some reason. + * We return them un-inverted. */ + uninvert_used_masks(&shader_desc->output_signature); + if (sm4->p.shader_version.type == VKD3D_SHADER_TYPE_HULL) + uninvert_used_masks(&shader_desc->patch_constant_signature); + if (!shader_sm4_parser_validate_signature(sm4, &shader_desc->input_signature, sm4->input_register_masks, "Input") || !shader_sm4_parser_validate_signature(sm4, &shader_desc->output_signature, @@ -3842,7 +3870,7 @@ static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src, if (width == 1) { src->reg.dimension = VSIR_DIMENSION_SCALAR; - src->reg.u.immconst_uint[0] = value->u[0].u; + src->reg.u.immconst_u32[0] = value->u[0].u; } else { @@ -3852,9 +3880,9 @@ static void sm4_src_from_constant_value(struct vkd3d_shader_src_param *src, for (i = 0; i < 4; ++i) { if ((map_writemask & (1u << i)) && (j < width)) - src->reg.u.immconst_uint[i] = value->u[j++].u; + src->reg.u.immconst_u32[i] = value->u[j++].u; else - src->reg.u.immconst_uint[i] = 0; + src->reg.u.immconst_u32[i] = 0; } } } @@ -4049,12 +4077,12 @@ static void sm4_write_src_register(const struct tpf_writer *tpf, const struct vk if (src->reg.type == VKD3DSPR_IMMCONST) { - put_u32(buffer, src->reg.u.immconst_uint[0]); + put_u32(buffer, src->reg.u.immconst_u32[0]); if (src->reg.dimension == VSIR_DIMENSION_VEC4) { - put_u32(buffer, src->reg.u.immconst_uint[1]); - put_u32(buffer, src->reg.u.immconst_uint[2]); - put_u32(buffer, src->reg.u.immconst_uint[3]); + put_u32(buffer, src->reg.u.immconst_u32[1]); + put_u32(buffer, src->reg.u.immconst_u32[2]); + put_u32(buffer, src->reg.u.immconst_u32[3]); } } } @@ -4589,7 +4617,7 @@ static void write_sm4_ld(const struct tpf_writer *tpf, const struct hlsl_ir_node memset(&instr.srcs[2], 0, sizeof(instr.srcs[2])); reg->type = VKD3DSPR_IMMCONST; reg->dimension = VSIR_DIMENSION_SCALAR; - reg->u.immconst_uint[0] = index->value.u[0].u; + reg->u.immconst_u32[0] = index->value.u[0].u; } else if (tpf->ctx->profile->major_version == 4 && tpf->ctx->profile->minor_version == 0) { @@ -4750,7 +4778,7 @@ static void write_sm4_cast_from_bool(const struct tpf_writer *tpf, const struct sm4_src_from_node(tpf, &instr.srcs[0], arg, instr.dsts[0].write_mask); instr.srcs[1].reg.type = VKD3DSPR_IMMCONST; instr.srcs[1].reg.dimension = VSIR_DIMENSION_SCALAR; - instr.srcs[1].reg.u.immconst_uint[0] = mask; + instr.srcs[1].reg.u.immconst_u32[0] = mask; instr.src_count = 2; write_sm4_instruction(tpf, &instr); diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c index 8fd8945151f..8fd98d2a551 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c @@ -23,6 +23,8 @@ #include #include +/* VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG"); */ + static inline int char_to_int(char c) { if ('0' <= c && c <= '9') @@ -305,6 +307,16 @@ void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const s vkd3d_string_buffer_printf(&context->messages, "\n"); } +void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, + enum vkd3d_shader_error error, const char *format, ...) +{ + va_list args; + + va_start(args, format); + vkd3d_shader_vwarning(context, location, error, format, args); + va_end(args); +} + void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, enum vkd3d_shader_error error, const char *format, va_list args) { @@ -888,6 +900,21 @@ static void vkd3d_shader_scan_combined_sampler_declaration( &semantic->resource.range, semantic->resource_type, VKD3D_SHADER_RESOURCE_DATA_FLOAT); } +static const struct vkd3d_shader_descriptor_info1 *find_descriptor( + const struct vkd3d_shader_scan_descriptor_info1 *info, + enum vkd3d_shader_descriptor_type type, unsigned int register_id) +{ + for (unsigned int i = 0; i < info->descriptor_count; ++i) + { + const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i]; + + if (d->type == type && d->register_id == register_id) + return d; + } + + return NULL; +} + static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_context *context, const struct vkd3d_shader_register *resource, const struct vkd3d_shader_register *sampler) { @@ -913,7 +940,6 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co if (vkd3d_shader_ver_ge(context->version, 5, 1)) { - const struct vkd3d_shader_scan_descriptor_info1 *info = context->scan_descriptor_info; const struct vkd3d_shader_descriptor_info1 *d; bool dynamic_resource, dynamic_sampler; @@ -928,30 +954,13 @@ static void vkd3d_shader_scan_combined_sampler_usage(struct vkd3d_shader_scan_co if (dynamic_resource || dynamic_sampler) return; - for (i = 0; i < info->descriptor_count; ++i) - { - d = &info->descriptors[i]; - if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SRV) - continue; - if (d->register_id != resource->idx[0].offset) - continue; + if ((d = find_descriptor(context->scan_descriptor_info, + VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource->idx[0].offset))) resource_space = d->register_space; - break; - } - if (sampler) - { - for (i = 0; i < info->descriptor_count; ++i) - { - d = &info->descriptors[i]; - if (d->type != VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER) - continue; - if (d->register_id != sampler->idx[0].offset) - continue; - sampler_space = d->register_space; - break; - } - } + if (sampler && (d = find_descriptor(context->scan_descriptor_info, + VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler->idx[0].offset))) + sampler_space = d->register_space; } for (i = 0; i < info->combined_sampler_count; ++i) @@ -1074,6 +1083,9 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte vkd3d_shader_scan_sampler_declaration(context, instruction); break; case VKD3DSIH_DCL: + if (instruction->declaration.semantic.resource_type == VKD3D_SHADER_RESOURCE_NONE) + break; + if (instruction->declaration.semantic.resource.reg.reg.type == VKD3DSPR_COMBINED_SAMPLER) { vkd3d_shader_scan_combined_sampler_declaration(context, &instruction->declaration.semantic); @@ -1541,16 +1553,15 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, scan_info = *compile_info; - if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) - return ret; - switch (compile_info->target_type) { case VKD3D_SHADER_TARGET_D3D_ASM: - ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out); + ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out, VSIR_ASM_D3D); break; case VKD3D_SHADER_TARGET_GLSL: + if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) + return ret; if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->shader_version, message_context, &parser->location))) { @@ -1561,19 +1572,22 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, ret = vkd3d_glsl_generator_generate(glsl_generator, parser, out); vkd3d_glsl_generator_destroy(glsl_generator); + vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); break; case VKD3D_SHADER_TARGET_SPIRV_BINARY: case VKD3D_SHADER_TARGET_SPIRV_TEXT: + if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) + return ret; ret = spirv_compile(parser, &scan_descriptor_info, compile_info, out, message_context); + vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); break; default: /* Validation should prevent us from reaching this. */ - assert(0); + vkd3d_unreachable(); } - vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); return ret; } @@ -1622,14 +1636,10 @@ static int compile_d3d_bytecode(const struct vkd3d_shader_compile_info *compile_ return ret; } - if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM) - { - ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out); - vkd3d_shader_parser_destroy(parser); - return ret; - } + ret = vkd3d_shader_parser_compile(parser, compile_info, out, message_context); - return VKD3D_ERROR; + vkd3d_shader_parser_destroy(parser); + return ret; } static int compile_dxbc_dxil(const struct vkd3d_shader_compile_info *compile_info, @@ -1907,6 +1917,10 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( static const enum vkd3d_shader_target_type d3dbc_types[] = { + VKD3D_SHADER_TARGET_SPIRV_BINARY, +#ifdef HAVE_SPIRV_TOOLS + VKD3D_SHADER_TARGET_SPIRV_TEXT, +#endif VKD3D_SHADER_TARGET_D3D_ASM, }; diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index a93fa7160f7..47b245bd7ee 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -91,11 +91,12 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001, VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING = 2002, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED = 2003, - VKD3D_SHADER_ERROR_SPV_STENCIL_EXPORT_UNSUPPORTED = 2004, + VKD3D_SHADER_ERROR_SPV_UNSUPPORTED_FEATURE = 2004, VKD3D_SHADER_ERROR_SPV_OUT_OF_MEMORY = 2005, VKD3D_SHADER_ERROR_SPV_INVALID_TYPE = 2006, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER = 2007, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED = 2008, + VKD3D_SHADER_ERROR_SPV_INVALID_SHADER = 2009, VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300, @@ -196,6 +197,7 @@ enum vkd3d_shader_error VKD3D_SHADER_WARNING_DXIL_ENTRY_POINT_MISMATCH = 8306, VKD3D_SHADER_WARNING_DXIL_INVALID_MASK = 8307, VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308, + VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT = 8309, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001, @@ -618,6 +620,11 @@ static inline bool data_type_is_bool(enum vkd3d_data_type data_type) return data_type == VKD3D_DATA_BOOL; } +static inline bool data_type_is_64_bit(enum vkd3d_data_type data_type) +{ + return data_type == VKD3D_DATA_DOUBLE || data_type == VKD3D_DATA_UINT64; +} + enum vsir_dimension { VSIR_DIMENSION_NONE, @@ -740,6 +747,7 @@ enum vkd3d_tessellator_domain #define VKD3DSI_RESINFO_UINT 0x2 #define VKD3DSI_SAMPLE_INFO_UINT 0x1 #define VKD3DSI_SAMPLER_COMPARISON_MODE 0x1 +#define VKD3DSI_SHIFT_UNMASKED 0x1 #define VKD3DSI_PRECISE_X 0x100 #define VKD3DSI_PRECISE_Y 0x200 @@ -793,10 +801,12 @@ struct vkd3d_shader_version struct vkd3d_shader_immediate_constant_buffer { + unsigned int register_idx; enum vkd3d_data_type data_type; /* total count is element_count * component_count */ unsigned int element_count; unsigned int component_count; + bool is_null; uint32_t data[]; }; @@ -831,10 +841,10 @@ struct vkd3d_shader_register unsigned int alignment; union { - DWORD immconst_uint[VKD3D_VEC4_SIZE]; - float immconst_float[VKD3D_VEC4_SIZE]; - uint64_t immconst_uint64[VKD3D_DVEC2_SIZE]; - double immconst_double[VKD3D_DVEC2_SIZE]; + uint32_t immconst_u32[VKD3D_VEC4_SIZE]; + float immconst_f32[VKD3D_VEC4_SIZE]; + uint64_t immconst_u64[VKD3D_DVEC2_SIZE]; + double immconst_f64[VKD3D_DVEC2_SIZE]; unsigned fp_body_idx; } u; }; @@ -1311,9 +1321,15 @@ struct vkd3d_string_buffer_cache size_t count, max_count, capacity; }; +enum vsir_asm_dialect +{ + VSIR_ASM_VSIR, + VSIR_ASM_D3D, +}; + enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions, const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_code *out); + struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect); void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer); struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list); void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer); @@ -1382,6 +1398,8 @@ void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, const str enum vkd3d_shader_error error, const char *format, va_list args); void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, enum vkd3d_shader_log_level level, const char *format, va_list args); +void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, + enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(4, 5); void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, enum vkd3d_shader_error error, const char *format, va_list args); @@ -1444,6 +1462,8 @@ static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_ty return VKD3D_SHADER_COMPONENT_INT; case VKD3D_DATA_DOUBLE: return VKD3D_SHADER_COMPONENT_DOUBLE; + case VKD3D_DATA_UINT64: + return VKD3D_SHADER_COMPONENT_UINT64; case VKD3D_DATA_BOOL: return VKD3D_SHADER_COMPONENT_BOOL; default: @@ -1505,7 +1525,7 @@ static inline enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum return vkd3d_siv_from_sysval_indexed(sysval, 0); } -static inline unsigned int vkd3d_write_mask_get_component_idx(DWORD write_mask) +static inline unsigned int vsir_write_mask_get_component_idx(uint32_t write_mask) { unsigned int i; @@ -1520,7 +1540,7 @@ static inline unsigned int vkd3d_write_mask_get_component_idx(DWORD write_mask) return 0; } -static inline unsigned int vkd3d_write_mask_component_count(DWORD write_mask) +static inline unsigned int vsir_write_mask_component_count(uint32_t write_mask) { unsigned int count = vkd3d_popcount(write_mask & VKD3DSP_WRITEMASK_ALL); assert(1 <= count && count <= VKD3D_VEC4_SIZE); @@ -1533,32 +1553,30 @@ static inline unsigned int vkd3d_write_mask_from_component_count(unsigned int co return (VKD3DSP_WRITEMASK_0 << component_count) - 1; } -static inline unsigned int vkd3d_write_mask_64_from_32(DWORD write_mask32) +static inline uint32_t vsir_write_mask_64_from_32(uint32_t write_mask32) { - unsigned int write_mask64 = write_mask32 | (write_mask32 >> 1); + uint32_t write_mask64 = write_mask32 | (write_mask32 >> 1); return (write_mask64 & VKD3DSP_WRITEMASK_0) | ((write_mask64 & VKD3DSP_WRITEMASK_2) >> 1); } -static inline unsigned int vkd3d_write_mask_32_from_64(unsigned int write_mask64) +static inline uint32_t vsir_write_mask_32_from_64(uint32_t write_mask64) { - unsigned int write_mask32 = (write_mask64 | (write_mask64 << 1)) + uint32_t write_mask32 = (write_mask64 | (write_mask64 << 1)) & (VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_2); return write_mask32 | (write_mask32 << 1); } -static inline unsigned int vkd3d_swizzle_get_component(DWORD swizzle, - unsigned int idx) +static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx) { return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK; } -static inline unsigned int vkd3d_swizzle_get_component64(DWORD swizzle, - unsigned int idx) +static inline unsigned int vsir_swizzle_get_component64(uint32_t swizzle, unsigned int idx) { return ((swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx * 2)) & VKD3D_SHADER_SWIZZLE_MASK) / 2u; } -static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned int write_mask) +static inline unsigned int vkd3d_compact_swizzle(uint32_t swizzle, uint32_t write_mask) { unsigned int i, compacted_swizzle = 0; @@ -1567,7 +1585,7 @@ static inline unsigned int vkd3d_compact_swizzle(unsigned int swizzle, unsigned if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) { compacted_swizzle <<= VKD3D_SHADER_SWIZZLE_SHIFT(1); - compacted_swizzle |= vkd3d_swizzle_get_component(swizzle, i); + compacted_swizzle |= vsir_swizzle_get_component(swizzle, i); } } diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c index 15c8317b191..549f6a45ffb 100644 --- a/libs/vkd3d/libs/vkd3d/command.c +++ b/libs/vkd3d/libs/vkd3d/command.c @@ -2644,6 +2644,8 @@ static bool d3d12_command_list_update_compute_pipeline(struct d3d12_command_list { const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; + vkd3d_cond_signal(&list->device->worker_cond); + if (list->current_pipeline != VK_NULL_HANDLE) return true; @@ -2665,6 +2667,8 @@ static bool d3d12_command_list_update_graphics_pipeline(struct d3d12_command_lis VkRenderPass vk_render_pass; VkPipeline vk_pipeline; + vkd3d_cond_signal(&list->device->worker_cond); + if (list->current_pipeline != VK_NULL_HANDLE) return true; diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c index 5c801ca4676..69a46e9188a 100644 --- a/libs/vkd3d/libs/vkd3d/device.c +++ b/libs/vkd3d/libs/vkd3d/device.c @@ -2056,7 +2056,7 @@ static HRESULT d3d12_device_init_pipeline_cache(struct d3d12_device *device) VkPipelineCacheCreateInfo cache_info; VkResult vr; - vkd3d_mutex_init(&device->mutex); + vkd3d_mutex_init(&device->pipeline_cache_mutex); cache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; cache_info.pNext = NULL; @@ -2080,7 +2080,7 @@ static void d3d12_device_destroy_pipeline_cache(struct d3d12_device *device) if (device->vk_pipeline_cache) VK_CALL(vkDestroyPipelineCache(device->vk_device, device->vk_pipeline_cache, NULL)); - vkd3d_mutex_destroy(&device->mutex); + vkd3d_mutex_destroy(&device->pipeline_cache_mutex); } #define VKD3D_VA_FALLBACK_BASE 0x8000000000000000ull @@ -2495,6 +2495,28 @@ static ULONG STDMETHODCALLTYPE d3d12_device_AddRef(ID3D12Device5 *iface) return refcount; } +static HRESULT device_worker_stop(struct d3d12_device *device) +{ + HRESULT hr; + + TRACE("device %p.\n", device); + + vkd3d_mutex_lock(&device->worker_mutex); + + device->worker_should_exit = true; + vkd3d_cond_signal(&device->worker_cond); + + vkd3d_mutex_unlock(&device->worker_mutex); + + if (FAILED(hr = vkd3d_join_thread(device->vkd3d_instance, &device->worker_thread))) + return hr; + + vkd3d_mutex_destroy(&device->worker_mutex); + vkd3d_cond_destroy(&device->worker_cond); + + return S_OK; +} + static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface) { struct d3d12_device *device = impl_from_ID3D12Device5(iface); @@ -2520,6 +2542,9 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface) d3d12_device_destroy_vkd3d_queues(device); vkd3d_desc_object_cache_cleanup(&device->view_desc_cache); vkd3d_desc_object_cache_cleanup(&device->cbuffer_desc_cache); + if (device->use_vk_heaps) + device_worker_stop(device); + vkd3d_free(device->heaps); VK_CALL(vkDestroyDevice(device->vk_device, NULL)); if (device->parent) IUnknown_Release(device->parent); @@ -4251,6 +4276,40 @@ struct d3d12_device *unsafe_impl_from_ID3D12Device5(ID3D12Device5 *iface) return impl_from_ID3D12Device5(iface); } +static void *device_worker_main(void *arg) +{ + struct d3d12_descriptor_heap *heap; + struct d3d12_device *device = arg; + size_t i; + + vkd3d_set_thread_name("device_worker"); + + vkd3d_mutex_lock(&device->worker_mutex); + + while (!device->worker_should_exit) + { + for (i = 0; i < device->heap_count; ++i) + { + /* Descriptor updates are not written to Vulkan descriptor sets until a command list + * is submitted to a queue, while the client is free to write d3d12 descriptors earlier, + * from any thread. This causes a delay right before command list execution, so + * handling these updates in a worker thread can speed up execution significantly. */ + heap = device->heaps[i]; + if (heap->dirty_list_head == UINT_MAX) + continue; + vkd3d_mutex_lock(&heap->vk_sets_mutex); + d3d12_desc_flush_vk_heap_updates_locked(heap, device); + vkd3d_mutex_unlock(&heap->vk_sets_mutex); + } + + vkd3d_cond_wait(&device->worker_cond, &device->worker_mutex); + } + + vkd3d_mutex_unlock(&device->worker_mutex); + + return NULL; +} + static HRESULT d3d12_device_init(struct d3d12_device *device, struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info) { @@ -4270,6 +4329,14 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, device->vk_device = VK_NULL_HANDLE; + device->heaps = NULL; + device->heap_capacity = 0; + device->heap_count = 0; + memset(&device->worker_thread, 0, sizeof(device->worker_thread)); + device->worker_should_exit = false; + vkd3d_mutex_init(&device->worker_mutex); + vkd3d_cond_init(&device->worker_cond); + if (FAILED(hr = vkd3d_create_vk_device(device, create_info))) goto out_free_instance; @@ -4291,6 +4358,13 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, if (FAILED(hr = vkd3d_vk_descriptor_heap_layouts_init(device))) goto out_cleanup_uav_clear_state; + if (device->use_vk_heaps && FAILED(hr = vkd3d_create_thread(device->vkd3d_instance, + device_worker_main, device, &device->worker_thread))) + { + WARN("Failed to create worker thread, hr %#x.\n", hr); + goto out_cleanup_descriptor_heap_layouts; + } + vkd3d_render_pass_cache_init(&device->render_pass_cache); vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator); vkd3d_time_domains_init(device); @@ -4308,6 +4382,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, return S_OK; +out_cleanup_descriptor_heap_layouts: + vkd3d_vk_descriptor_heap_layouts_cleanup(device); out_cleanup_uav_clear_state: vkd3d_uav_clear_state_cleanup(&device->uav_clear_state, device); out_destroy_null_resources: @@ -4361,6 +4437,40 @@ void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, device->removed_reason = reason; } +HRESULT d3d12_device_add_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap) +{ + vkd3d_mutex_lock(&device->worker_mutex); + + if (!vkd3d_array_reserve((void **)&device->heaps, &device->heap_capacity, device->heap_count + 1, + sizeof(*device->heaps))) + { + vkd3d_mutex_unlock(&device->worker_mutex); + return E_OUTOFMEMORY; + } + device->heaps[device->heap_count++] = heap; + + vkd3d_mutex_unlock(&device->worker_mutex); + + return S_OK; +} + +void d3d12_device_remove_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap) +{ + size_t i; + + vkd3d_mutex_lock(&device->worker_mutex); + + for (i = 0; i < device->heap_count; ++i) + { + if (device->heaps[i] == heap) + { + device->heaps[i] = device->heaps[--device->heap_count]; + break; + } + } + + vkd3d_mutex_unlock(&device->worker_mutex); +} #ifdef _WIN32 struct thread_data diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c index abbdfbe2015..609c67102a6 100644 --- a/libs/vkd3d/libs/vkd3d/resource.c +++ b/libs/vkd3d/libs/vkd3d/resource.c @@ -2632,20 +2632,18 @@ void d3d12_desc_flush_vk_heap_updates_locked(struct d3d12_descriptor_heap *descr for (; i != UINT_MAX; i = next) { src = &descriptors[i]; - next = (int)src->next >> 1; + next = vkd3d_atomic_exchange(&src->next, 0); + next = (int)next >> 1; + /* A race exists here between updating src->next and getting the current object. The best + * we can do is get the object last, which may result in a harmless rewrite later. */ u.object = d3d12_desc_get_object_ref(src, device); if (!u.object) - { - vkd3d_atomic_exchange(&src->next, 0); continue; - } writes.held_refs[writes.held_ref_count++] = u.object; d3d12_desc_write_vk_heap(descriptor_heap, i, &writes, u.object, device); - - vkd3d_atomic_exchange(&src->next, 0); } /* Avoid thunk calls wherever possible. */ @@ -3997,6 +3995,9 @@ static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHea { struct d3d12_desc *descriptors = (struct d3d12_desc *)heap->descriptors; + if (heap->use_vk_heaps) + d3d12_device_remove_descriptor_heap(device, heap); + for (i = 0; i < heap->desc.NumDescriptors; ++i) { d3d12_desc_destroy(&descriptors[i], device); @@ -4320,6 +4321,12 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device, dst[i].next = 0; } object->dirty_list_head = UINT_MAX; + + if (object->use_vk_heaps && FAILED(hr = d3d12_device_add_descriptor_heap(device, object))) + { + vkd3d_free(object); + return hr; + } } else { diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c index fc3187f4bea..1457ddf9c7f 100644 --- a/libs/vkd3d/libs/vkd3d/state.c +++ b/libs/vkd3d/libs/vkd3d/state.c @@ -515,7 +515,7 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat assert(p->ShaderVisibility <= D3D12_SHADER_VISIBILITY_PIXEL); push_constants[p->ShaderVisibility].stageFlags = use_vk_heaps ? VK_SHADER_STAGE_ALL : stage_flags_from_visibility(p->ShaderVisibility); - push_constants[p->ShaderVisibility].size += p->u.Constants.Num32BitValues * sizeof(uint32_t); + push_constants[p->ShaderVisibility].size += align(p->u.Constants.Num32BitValues, 4) * sizeof(uint32_t); } if (push_constants[D3D12_SHADER_VISIBILITY_ALL].size) { @@ -564,7 +564,7 @@ static HRESULT d3d12_root_signature_init_push_constants(struct d3d12_root_signat idx = push_constant_count == 1 ? 0 : p->ShaderVisibility; offset = push_constants_offset[idx]; - push_constants_offset[idx] += p->u.Constants.Num32BitValues * sizeof(uint32_t); + push_constants_offset[idx] += align(p->u.Constants.Num32BitValues, 4) * sizeof(uint32_t); root_signature->parameters[i].parameter_type = p->ParameterType; root_constant->stage_flags = push_constant_count == 1 @@ -1691,7 +1691,7 @@ HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache, HRESULT hr = S_OK; unsigned int i; - vkd3d_mutex_lock(&device->mutex); + vkd3d_mutex_lock(&device->pipeline_cache_mutex); for (i = 0; i < cache->render_pass_count; ++i) { @@ -1708,7 +1708,7 @@ HRESULT vkd3d_render_pass_cache_find(struct vkd3d_render_pass_cache *cache, if (!found) hr = vkd3d_render_pass_cache_create_pass_locked(cache, device, key, vk_render_pass); - vkd3d_mutex_unlock(&device->mutex); + vkd3d_mutex_unlock(&device->pipeline_cache_mutex); return hr; } @@ -2129,6 +2129,16 @@ static inline unsigned int typed_uav_compile_option(const struct d3d12_device *d : VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV_READ_FORMAT_R32; } +static unsigned int feature_flags_compile_option(const struct d3d12_device *device) +{ + unsigned int flags = 0; + + if (device->feature_options1.Int64ShaderOps) + flags |= VKD3D_SHADER_COMPILE_OPTION_FEATURE_INT64; + + return flags; +} + static HRESULT create_shader_stage(struct d3d12_device *device, struct VkPipelineShaderStageCreateInfo *stage_desc, enum VkShaderStageFlagBits stage, const D3D12_SHADER_BYTECODE *code, const struct vkd3d_shader_interface_info *shader_interface) @@ -2145,6 +2155,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device, {VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_10}, {VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV, typed_uav_compile_option(device)}, {VKD3D_SHADER_COMPILE_OPTION_WRITE_TESS_GEOM_POINT_SIZE, 0}, + {VKD3D_SHADER_COMPILE_OPTION_FEATURE, feature_flags_compile_option(device)}, }; stage_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; @@ -3615,7 +3626,7 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12 *vk_render_pass = VK_NULL_HANDLE; - vkd3d_mutex_lock(&device->mutex); + vkd3d_mutex_lock(&device->pipeline_cache_mutex); LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry) { @@ -3627,7 +3638,7 @@ static VkPipeline d3d12_pipeline_state_find_compiled_pipeline(const struct d3d12 } } - vkd3d_mutex_unlock(&device->mutex); + vkd3d_mutex_unlock(&device->pipeline_cache_mutex); return vk_pipeline; } @@ -3646,7 +3657,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta compiled_pipeline->vk_pipeline = vk_pipeline; compiled_pipeline->vk_render_pass = vk_render_pass; - vkd3d_mutex_lock(&device->mutex); + vkd3d_mutex_lock(&device->pipeline_cache_mutex); LIST_FOR_EACH_ENTRY(current, &graphics->compiled_pipelines, struct vkd3d_compiled_pipeline, entry) { @@ -3661,7 +3672,7 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta if (compiled_pipeline) list_add_tail(&graphics->compiled_pipelines, &compiled_pipeline->entry); - vkd3d_mutex_unlock(&device->mutex); + vkd3d_mutex_unlock(&device->pipeline_cache_mutex); return compiled_pipeline; } diff --git a/libs/vkd3d/libs/vkd3d/utils.c b/libs/vkd3d/libs/vkd3d/utils.c index 9b28068be51..5ebe1b63e99 100644 --- a/libs/vkd3d/libs/vkd3d/utils.c +++ b/libs/vkd3d/libs/vkd3d/utils.c @@ -539,6 +539,7 @@ bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) { static const D3D_FEATURE_LEVEL valid_feature_levels[] = { + D3D_FEATURE_LEVEL_12_2, D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_11_1, @@ -548,6 +549,7 @@ bool is_valid_feature_level(D3D_FEATURE_LEVEL feature_level) D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1, + D3D_FEATURE_LEVEL_1_0_CORE, }; unsigned int i; diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h index f06f564d6ea..bd7e7290d9e 100644 --- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h @@ -1757,9 +1757,23 @@ struct d3d12_device struct vkd3d_gpu_va_allocator gpu_va_allocator; - struct vkd3d_mutex mutex; struct vkd3d_desc_object_cache view_desc_cache; struct vkd3d_desc_object_cache cbuffer_desc_cache; + + VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT]; + unsigned int vk_pool_count; + struct vkd3d_vk_descriptor_heap_layout vk_descriptor_heap_layouts[VKD3D_SET_INDEX_COUNT]; + bool use_vk_heaps; + + struct d3d12_descriptor_heap **heaps; + size_t heap_capacity; + size_t heap_count; + union vkd3d_thread_handle worker_thread; + struct vkd3d_mutex worker_mutex; + struct vkd3d_cond worker_cond; + bool worker_should_exit; + + struct vkd3d_mutex pipeline_cache_mutex; struct vkd3d_render_pass_cache render_pass_cache; VkPipelineCache vk_pipeline_cache; @@ -1799,11 +1813,6 @@ struct d3d12_device const struct vkd3d_format_compatibility_list *format_compatibility_lists; struct vkd3d_null_resources null_resources; struct vkd3d_uav_clear_state uav_clear_state; - - VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT]; - unsigned int vk_pool_count; - struct vkd3d_vk_descriptor_heap_layout vk_descriptor_heap_layouts[VKD3D_SET_INDEX_COUNT]; - bool use_vk_heaps; }; HRESULT d3d12_device_create(struct vkd3d_instance *instance, @@ -1813,6 +1822,8 @@ bool d3d12_device_is_uma(struct d3d12_device *device, bool *coherent); void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, const char *message, ...) VKD3D_PRINTF_FUNC(3, 4); struct d3d12_device *unsafe_impl_from_ID3D12Device5(ID3D12Device5 *iface); +HRESULT d3d12_device_add_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap); +void d3d12_device_remove_descriptor_heap(struct d3d12_device *device, struct d3d12_descriptor_heap *heap); static inline HRESULT d3d12_device_query_interface(struct d3d12_device *device, REFIID iid, void **object) { -- 2.43.0