From 90c1abd17c4f00af62b9eda122caaf6d2cd5365e Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Tue, 19 Mar 2024 12:20:44 +1100 Subject: [PATCH] Updated vkd3d to 164608a007db3e682fe34b46e9acee4921677a73. --- libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 219 +++++++-------- libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 8 +- libs/vkd3d/libs/vkd3d-shader/dxil.c | 121 ++++++++- libs/vkd3d/libs/vkd3d-shader/fx.c | 199 ++++++++++++-- libs/vkd3d/libs/vkd3d-shader/glsl.c | 9 + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 2 + libs/vkd3d/libs/vkd3d-shader/ir.c | 356 ++++++++++++++++--------- libs/vkd3d/libs/vkd3d-shader/spirv.c | 2 +- 8 files changed, 655 insertions(+), 261 deletions(-) diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c index fcbb321edd1..0623a129eae 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -514,79 +514,88 @@ static void shader_dump_uav_flags(struct vkd3d_d3d_asm_compiler *compiler, uint3 vkd3d_string_buffer_printf(&compiler->buffer, "_unknown_flags(%#x)", uav_flags); } -static void shader_dump_tessellator_domain(struct vkd3d_d3d_asm_compiler *compiler, - enum vkd3d_tessellator_domain domain) +static void shader_print_tessellator_domain(struct vkd3d_d3d_asm_compiler *compiler, + const char *prefix, enum vkd3d_tessellator_domain d, const char *suffix) { struct vkd3d_string_buffer *buffer = &compiler->buffer; + const char *domain; - shader_addline(buffer, "domain_"); - switch (domain) + switch (d) { case VKD3D_TESSELLATOR_DOMAIN_LINE: - shader_addline(buffer, "isoline"); + domain = "domain_isoline"; break; case VKD3D_TESSELLATOR_DOMAIN_TRIANGLE: - shader_addline(buffer, "tri"); + domain = "domain_tri"; break; case VKD3D_TESSELLATOR_DOMAIN_QUAD: - shader_addline(buffer, "quad"); + domain = "domain_quad"; break; default: - shader_addline(buffer, "unknown_tessellator_domain(%#x)", domain); - break; + vkd3d_string_buffer_printf(buffer, "%s%s%s%s", + prefix, compiler->colours.error, d, compiler->colours.reset, suffix); + return; } + + vkd3d_string_buffer_printf(buffer, "%s%s%s", prefix, domain, suffix); } -static void shader_dump_tessellator_output_primitive(struct vkd3d_d3d_asm_compiler *compiler, - enum vkd3d_shader_tessellator_output_primitive output_primitive) +static void shader_print_tessellator_output_primitive(struct vkd3d_d3d_asm_compiler *compiler, + const char *prefix, enum vkd3d_shader_tessellator_output_primitive p, const char *suffix) { struct vkd3d_string_buffer *buffer = &compiler->buffer; + const char *primitive; - shader_addline(buffer, "output_"); - switch (output_primitive) + switch (p) { case VKD3D_SHADER_TESSELLATOR_OUTPUT_POINT: - shader_addline(buffer, "point"); + primitive = "output_point"; break; case VKD3D_SHADER_TESSELLATOR_OUTPUT_LINE: - shader_addline(buffer, "line"); + primitive = "output_line"; break; case VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CW: - shader_addline(buffer, "triangle_cw"); + primitive = "output_triangle_cw"; break; case VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW: - shader_addline(buffer, "triangle_ccw"); + primitive = "output_triangle_ccw"; break; default: - shader_addline(buffer, "unknown_tessellator_output_primitive(%#x)", output_primitive); - break; + vkd3d_string_buffer_printf(buffer, "%s%s%s%s", + prefix, compiler->colours.error, p, compiler->colours.reset, suffix); + return; } + + vkd3d_string_buffer_printf(buffer, "%s%s%s", prefix, primitive, suffix); } -static void shader_dump_tessellator_partitioning(struct vkd3d_d3d_asm_compiler *compiler, - enum vkd3d_shader_tessellator_partitioning partitioning) +static void shader_print_tessellator_partitioning(struct vkd3d_d3d_asm_compiler *compiler, + const char *prefix, enum vkd3d_shader_tessellator_partitioning p, const char *suffix) { struct vkd3d_string_buffer *buffer = &compiler->buffer; + const char *partitioning; - shader_addline(buffer, "partitioning_"); - switch (partitioning) + switch (p) { case VKD3D_SHADER_TESSELLATOR_PARTITIONING_INTEGER: - shader_addline(buffer, "integer"); + partitioning = "partitioning_integer"; break; case VKD3D_SHADER_TESSELLATOR_PARTITIONING_POW2: - shader_addline(buffer, "pow2"); + partitioning = "partitioning_pow2"; break; case VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD: - shader_addline(buffer, "fractional_odd"); + partitioning = "partitioning_fractional_odd"; break; case VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN: - shader_addline(buffer, "fractional_even"); + partitioning = "partitioning_fractional_even"; break; default: - shader_addline(buffer, "unknown_tessellator_partitioning(%#x)", partitioning); - break; + vkd3d_string_buffer_printf(buffer, "%s%s%s%s", + prefix, compiler->colours.error, p, compiler->colours.reset, suffix); + return; } + + vkd3d_string_buffer_printf(buffer, "%s%s%s", prefix, partitioning, suffix); } static void shader_dump_shader_input_sysval_semantic(struct vkd3d_d3d_asm_compiler *compiler, @@ -798,8 +807,8 @@ static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler, } } -static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, - const struct vkd3d_shader_src_param *param); +static void shader_print_src_param(struct vkd3d_d3d_asm_compiler *compiler, + const char *prefix, const struct vkd3d_shader_src_param *param, const char *suffix); static void shader_print_float_literal(struct vkd3d_d3d_asm_compiler *compiler, const char *prefix, float f, const char *suffix) @@ -896,13 +905,9 @@ static void shader_print_untyped_literal(struct vkd3d_d3d_asm_compiler *compiler static void shader_print_subscript(struct vkd3d_d3d_asm_compiler *compiler, unsigned int offset, const struct vkd3d_shader_src_param *rel_addr) { - vkd3d_string_buffer_printf(&compiler->buffer, "["); if (rel_addr) - { - shader_dump_src_param(compiler, rel_addr); - vkd3d_string_buffer_printf(&compiler->buffer, " + "); - } - shader_print_uint_literal(compiler, "", offset, "]"); + shader_print_src_param(compiler, "[", rel_addr, " + "); + shader_print_uint_literal(compiler, rel_addr ? "" : "[", offset, "]"); } static void shader_print_subscript_range(struct vkd3d_d3d_asm_compiler *compiler, @@ -1378,6 +1383,9 @@ static void shader_dump_reg_type(struct vkd3d_d3d_asm_compiler *compiler, if (!(compiler->flags & VSIR_ASM_FLAG_DUMP_TYPES)) return; + if (reg->data_type == VKD3D_DATA_UNUSED) + return; + if (reg->dimension < ARRAY_SIZE(dimensions)) dimension = dimensions[reg->dimension]; else @@ -1414,11 +1422,12 @@ static void shader_print_write_mask(struct vkd3d_d3d_asm_compiler *compiler, compiler->colours.write_mask, buffer, compiler->colours.reset, suffix); } -static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, - const struct vkd3d_shader_dst_param *param, bool is_declaration) +static void shader_print_dst_param(struct vkd3d_d3d_asm_compiler *compiler, + const char *prefix, const struct vkd3d_shader_dst_param *param, bool is_declaration, const char *suffix) { uint32_t write_mask = param->write_mask; + vkd3d_string_buffer_printf(&compiler->buffer, "%s", prefix); shader_dump_register(compiler, ¶m->reg, is_declaration); if (write_mask && param->reg.dimension == VSIR_DIMENSION_VEC4) @@ -1432,48 +1441,65 @@ 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); + vkd3d_string_buffer_printf(&compiler->buffer, "%s", suffix); } -static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, - const struct vkd3d_shader_src_param *param) +static void shader_print_src_param(struct vkd3d_d3d_asm_compiler *compiler, + const char *prefix, const struct vkd3d_shader_src_param *param, const char *suffix) { enum vkd3d_shader_src_modifier src_modifier = param->modifiers; struct vkd3d_string_buffer *buffer = &compiler->buffer; uint32_t swizzle = param->swizzle; + const char *modifier = ""; if (src_modifier == VKD3DSPSM_NEG || src_modifier == VKD3DSPSM_BIASNEG || src_modifier == VKD3DSPSM_SIGNNEG || src_modifier == VKD3DSPSM_X2NEG || src_modifier == VKD3DSPSM_ABSNEG) - shader_addline(buffer, "-"); + modifier = "-"; else if (src_modifier == VKD3DSPSM_COMP) - shader_addline(buffer, "1-"); + modifier = "1-"; else if (src_modifier == VKD3DSPSM_NOT) - shader_addline(buffer, "!"); + modifier = "!"; + vkd3d_string_buffer_printf(buffer, "%s%s", prefix, modifier); if (src_modifier == VKD3DSPSM_ABS || src_modifier == VKD3DSPSM_ABSNEG) - shader_addline(buffer, "|"); + vkd3d_string_buffer_printf(buffer, "|"); shader_dump_register(compiler, ¶m->reg, false); switch (src_modifier) { - case VKD3DSPSM_NONE: break; - case VKD3DSPSM_NEG: break; - case VKD3DSPSM_NOT: break; - case VKD3DSPSM_BIAS: shader_addline(buffer, "_bias"); break; - case VKD3DSPSM_BIASNEG: shader_addline(buffer, "_bias"); break; - case VKD3DSPSM_SIGN: shader_addline(buffer, "_bx2"); break; - case VKD3DSPSM_SIGNNEG: shader_addline(buffer, "_bx2"); break; - case VKD3DSPSM_COMP: break; - case VKD3DSPSM_X2: shader_addline(buffer, "_x2"); break; - case VKD3DSPSM_X2NEG: shader_addline(buffer, "_x2"); break; - case VKD3DSPSM_DZ: shader_addline(buffer, "_dz"); break; - case VKD3DSPSM_DW: shader_addline(buffer, "_dw"); break; + case VKD3DSPSM_NONE: + case VKD3DSPSM_NEG: + case VKD3DSPSM_COMP: + case VKD3DSPSM_ABS: case VKD3DSPSM_ABSNEG: - case VKD3DSPSM_ABS: /* handled later */ break; - default: shader_addline(buffer, "_unknown_modifier(%#x)", src_modifier); + case VKD3DSPSM_NOT: + break; + case VKD3DSPSM_BIAS: + case VKD3DSPSM_BIASNEG: + vkd3d_string_buffer_printf(buffer, "_bias"); + break; + case VKD3DSPSM_SIGN: + case VKD3DSPSM_SIGNNEG: + vkd3d_string_buffer_printf(buffer, "_bx2"); + break; + case VKD3DSPSM_X2: + case VKD3DSPSM_X2NEG: + vkd3d_string_buffer_printf(buffer, "_x2"); + break; + case VKD3DSPSM_DZ: + vkd3d_string_buffer_printf(buffer, "_dz"); + break; + case VKD3DSPSM_DW: + vkd3d_string_buffer_printf(buffer, "_dw"); + break; + default: + vkd3d_string_buffer_printf(buffer, "_%s%s", + compiler->colours.error, src_modifier, compiler->colours.reset); + break; } if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_IMMCONST64 @@ -1491,26 +1517,22 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, swizzle_z = vsir_swizzle_get_component(swizzle, 2); swizzle_w = vsir_swizzle_get_component(swizzle, 3); - if (swizzle_x == swizzle_y - && swizzle_x == swizzle_z - && swizzle_x == swizzle_w) - { - shader_addline(buffer, ".%s%c%s", compiler->colours.swizzle, + if (swizzle_x == swizzle_y && swizzle_x == swizzle_z && swizzle_x == swizzle_w) + vkd3d_string_buffer_printf(buffer, ".%s%c%s", compiler->colours.swizzle, swizzle_chars[swizzle_x], compiler->colours.reset); - } else - { - shader_addline(buffer, ".%s%c%c%c%c%s", compiler->colours.swizzle, + vkd3d_string_buffer_printf(buffer, ".%s%c%c%c%c%s", compiler->colours.swizzle, swizzle_chars[swizzle_x], swizzle_chars[swizzle_y], swizzle_chars[swizzle_z], swizzle_chars[swizzle_w], compiler->colours.reset); - } } + if (src_modifier == VKD3DSPSM_ABS || src_modifier == VKD3DSPSM_ABSNEG) - shader_addline(buffer, "|"); + vkd3d_string_buffer_printf(buffer, "|"); shader_print_precision(compiler, ¶m->reg); shader_print_non_uniform(compiler, ¶m->reg); shader_dump_reg_type(compiler, ¶m->reg); + vkd3d_string_buffer_printf(buffer, "%s", suffix); } static void shader_dump_ins_modifiers(struct vkd3d_d3d_asm_compiler *compiler, @@ -1784,11 +1806,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, compiler->current = ins; if (ins->predicate) - { - vkd3d_string_buffer_printf(buffer, "("); - shader_dump_src_param(compiler, ins->predicate); - vkd3d_string_buffer_printf(buffer, ") "); - } + shader_print_src_param(compiler, "(", ins->predicate, ") "); /* PixWin marks instructions with the coissue flag with a '+' */ if (ins->coissue) @@ -1842,8 +1860,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, break; case VKD3DSIH_DCL_INDEX_RANGE: - vkd3d_string_buffer_printf(buffer, " "); - shader_dump_dst_param(compiler, &ins->declaration.index_range.dst, true); + shader_print_dst_param(compiler, " ", &ins->declaration.index_range.dst, true, ""); shader_print_uint_literal(compiler, " ", ins->declaration.index_range.register_count, ""); break; @@ -1861,16 +1878,14 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, case VKD3DSIH_DCL_INPUT_PS: vkd3d_string_buffer_printf(buffer, " "); shader_dump_interpolation_mode(compiler, ins->flags); - shader_addline(buffer, " "); - shader_dump_dst_param(compiler, &ins->declaration.dst, true); + shader_print_dst_param(compiler, " ", &ins->declaration.dst, true, ""); break; case VKD3DSIH_DCL_INPUT_PS_SGV: case VKD3DSIH_DCL_INPUT_SGV: case VKD3DSIH_DCL_INPUT_SIV: case VKD3DSIH_DCL_OUTPUT_SIV: - vkd3d_string_buffer_printf(buffer, " "); - shader_dump_dst_param(compiler, &ins->declaration.register_semantic.reg, true); + shader_print_dst_param(compiler, " ", &ins->declaration.register_semantic.reg, true, ""); shader_addline(buffer, ", "); shader_dump_shader_input_sysval_semantic(compiler, ins->declaration.register_semantic.sysval_semantic); break; @@ -1878,16 +1893,14 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, case VKD3DSIH_DCL_INPUT_PS_SIV: vkd3d_string_buffer_printf(buffer, " "); shader_dump_interpolation_mode(compiler, ins->flags); - shader_addline(buffer, " "); - shader_dump_dst_param(compiler, &ins->declaration.register_semantic.reg, true); + shader_print_dst_param(compiler, " ", &ins->declaration.register_semantic.reg, true, ""); shader_addline(buffer, ", "); shader_dump_shader_input_sysval_semantic(compiler, ins->declaration.register_semantic.sysval_semantic); break; case VKD3DSIH_DCL_INPUT: case VKD3DSIH_DCL_OUTPUT: - vkd3d_string_buffer_printf(buffer, " "); - shader_dump_dst_param(compiler, &ins->declaration.dst, true); + shader_print_dst_param(compiler, " ", &ins->declaration.dst, true, ""); break; case VKD3DSIH_DCL_INPUT_PRIMITIVE: @@ -1904,14 +1917,12 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, break; case VKD3DSIH_DCL_RESOURCE_RAW: - vkd3d_string_buffer_printf(buffer, " "); - shader_dump_dst_param(compiler, &ins->declaration.raw_resource.resource.reg, true); + shader_print_dst_param(compiler, " ", &ins->declaration.raw_resource.resource.reg, true, ""); shader_dump_register_space(compiler, ins->declaration.raw_resource.resource.range.space); break; case VKD3DSIH_DCL_RESOURCE_STRUCTURED: - vkd3d_string_buffer_printf(buffer, " "); - shader_dump_dst_param(compiler, &ins->declaration.structured_resource.resource.reg, true); + shader_print_dst_param(compiler, " ", &ins->declaration.structured_resource.resource.reg, true, ""); shader_print_uint_literal(compiler, ", ", ins->declaration.structured_resource.byte_stride, ""); shader_dump_register_space(compiler, ins->declaration.structured_resource.resource.range.space); break; @@ -1935,29 +1946,24 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, break; case VKD3DSIH_DCL_TESSELLATOR_DOMAIN: - vkd3d_string_buffer_printf(buffer, " "); - shader_dump_tessellator_domain(compiler, ins->declaration.tessellator_domain); + shader_print_tessellator_domain(compiler, " ", ins->declaration.tessellator_domain, ""); break; case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE: - vkd3d_string_buffer_printf(buffer, " "); - shader_dump_tessellator_output_primitive(compiler, ins->declaration.tessellator_output_primitive); + shader_print_tessellator_output_primitive(compiler, " ", ins->declaration.tessellator_output_primitive, ""); break; case VKD3DSIH_DCL_TESSELLATOR_PARTITIONING: - vkd3d_string_buffer_printf(buffer, " "); - shader_dump_tessellator_partitioning(compiler, ins->declaration.tessellator_partitioning); + shader_print_tessellator_partitioning(compiler, " ", ins->declaration.tessellator_partitioning, ""); break; case VKD3DSIH_DCL_TGSM_RAW: - vkd3d_string_buffer_printf(buffer, " "); - shader_dump_dst_param(compiler, &ins->declaration.tgsm_raw.reg, true); + shader_print_dst_param(compiler, " ", &ins->declaration.tgsm_raw.reg, true, ""); shader_print_uint_literal(compiler, ", ", ins->declaration.tgsm_raw.byte_count, ""); break; case VKD3DSIH_DCL_TGSM_STRUCTURED: - vkd3d_string_buffer_printf(buffer, " "); - shader_dump_dst_param(compiler, &ins->declaration.tgsm_structured.reg, true); + shader_print_dst_param(compiler, " ", &ins->declaration.tgsm_structured.reg, true, ""); shader_print_uint_literal(compiler, ", ", ins->declaration.tgsm_structured.byte_stride, ""); shader_print_uint_literal(compiler, ", ", ins->declaration.tgsm_structured.structure_count, ""); break; @@ -1970,15 +1976,13 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, case VKD3DSIH_DCL_UAV_RAW: shader_dump_uav_flags(compiler, ins->flags); - shader_addline(buffer, " "); - shader_dump_dst_param(compiler, &ins->declaration.raw_resource.resource.reg, true); + shader_print_dst_param(compiler, " ", &ins->declaration.raw_resource.resource.reg, true, ""); shader_dump_register_space(compiler, ins->declaration.raw_resource.resource.range.space); break; case VKD3DSIH_DCL_UAV_STRUCTURED: shader_dump_uav_flags(compiler, ins->flags); - shader_addline(buffer, " "); - shader_dump_dst_param(compiler, &ins->declaration.structured_resource.resource.reg, true); + shader_print_dst_param(compiler, " ", &ins->declaration.structured_resource.resource.reg, true, ""); shader_print_uint_literal(compiler, ", ", ins->declaration.structured_resource.byte_stride, ""); shader_dump_register_space(compiler, ins->declaration.structured_resource.resource.range.space); break; @@ -2040,15 +2044,13 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, for (i = 0; i < ins->dst_count; ++i) { shader_dump_ins_modifiers(compiler, &ins->dst[i]); - shader_addline(buffer, !i ? " " : ", "); - shader_dump_dst_param(compiler, &ins->dst[i], false); + shader_print_dst_param(compiler, !i ? " " : ", ", &ins->dst[i], false, ""); } /* Other source tokens */ for (i = ins->dst_count; i < (ins->dst_count + ins->src_count); ++i) { - shader_addline(buffer, !i ? " " : ", "); - shader_dump_src_param(compiler, &ins->src[i - ins->dst_count]); + shader_print_src_param(compiler, !i ? " " : ", ", &ins->src[i - ins->dst_count], ""); } break; } @@ -2321,6 +2323,10 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, --indent; break; + case VKD3DSIH_LABEL: + indent = 0; + break; + default: break; } @@ -2339,6 +2345,7 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, case VKD3DSIH_IFC: case VKD3DSIH_LOOP: case VKD3DSIH_SWITCH: + case VKD3DSIH_LABEL: ++indent; break; diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c index 9f153a1da04..3b935b07d61 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -1494,12 +1494,12 @@ static uint32_t sm1_version(enum vkd3d_shader_type type, unsigned int major, uns return D3DPS_VERSION(major, minor); } -static D3DXPARAMETER_CLASS sm1_class(const struct hlsl_type *type) +D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) { switch (type->class) { case HLSL_CLASS_ARRAY: - return sm1_class(type->e.array.type); + return hlsl_sm1_class(type->e.array.type); case HLSL_CLASS_MATRIX: assert(type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK); if (type->modifiers & HLSL_MODIFIER_COLUMN_MAJOR) @@ -1520,7 +1520,7 @@ static D3DXPARAMETER_CLASS sm1_class(const struct hlsl_type *type) } } -static D3DXPARAMETER_TYPE sm1_base_type(const struct hlsl_type *type) +D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type) { switch (type->base_type) { @@ -1615,7 +1615,7 @@ static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, struct hlsl_typ } } - type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(sm1_class(type), sm1_base_type(array_type))); + type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(hlsl_sm1_class(type), hlsl_sm1_base_type(array_type))); put_u32(buffer, vkd3d_make_u32(type->dimy, type->dimx)); put_u32(buffer, vkd3d_make_u32(array_size, field_count)); put_u32(buffer, fields_offset); diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index 86671c07d70..7f9a74fa737 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -342,6 +342,8 @@ enum dx_intrinsic_opcode { DX_LOAD_INPUT = 4, DX_STORE_OUTPUT = 5, + DX_FABS = 6, + DX_SATURATE = 7, DX_ISNAN = 8, DX_ISINF = 9, DX_ISFINITE = 10, @@ -374,6 +376,10 @@ enum dx_intrinsic_opcode DX_IMIN = 38, DX_UMAX = 39, DX_UMIN = 40, + DX_FMAD = 46, + DX_FMA = 47, + DX_IMAD = 48, + DX_UMAD = 49, DX_IBFE = 51, DX_UBFE = 52, DX_CREATE_HANDLE = 57, @@ -388,6 +394,7 @@ enum dx_intrinsic_opcode DX_TEXTURE_STORE = 67, DX_BUFFER_LOAD = 68, DX_BUFFER_STORE = 69, + DX_BUFFER_UPDATE_COUNTER = 70, DX_GET_DIMENSIONS = 72, DX_TEXTURE_GATHER = 73, DX_TEXTURE_GATHER_CMP = 74, @@ -2374,14 +2381,18 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, } } -static void instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) +static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instruction *ins, struct sm6_parser *sm6) { - struct vkd3d_shader_dst_param *param = instruction_dst_params_alloc(ins, 1, sm6); struct sm6_value *dst = sm6_parser_get_current_value(sm6); + struct vkd3d_shader_dst_param *param; + + if (!(param = instruction_dst_params_alloc(ins, 1, sm6))) + return false; dst_param_init_ssa_scalar(param, dst->type, dst, sm6); param->write_mask = VKD3DSP_WRITEMASK_0; dst->u.reg = param->reg; + return true; } static void instruction_dst_param_init_ssa_vector(struct vkd3d_shader_instruction *ins, @@ -4134,6 +4145,43 @@ static void sm6_parser_emit_dx_barrier(struct sm6_parser *sm6, enum dx_intrinsic } } +static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_params; + const struct sm6_value *resource; + unsigned int i; + int8_t inc; + + resource = operands[0]; + if (!sm6_value_validate_is_handle(resource, sm6)) + return; + + if (!sm6_value_is_constant(operands[1])) + { + FIXME("Unsupported dynamic update operand.\n"); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "A dynamic update value for a UAV counter operation is not supported."); + return; + } + i = sm6_value_get_constant_uint(operands[1]); + if (i != 1 && i != 255) + { + WARN("Unexpected update value %#x.\n", i); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Update value %#x for a UAV counter operation is not supported.", i); + } + inc = i; + + vsir_instruction_init(ins, &sm6->p.location, (inc < 0) ? VKD3DSIH_IMM_ATOMIC_CONSUME : VKD3DSIH_IMM_ATOMIC_ALLOC); + if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) + return; + src_param_init_vector_from_reg(&src_params[0], &resource->u.handle.reg); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -4225,6 +4273,53 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int ins->handler_idx = VKD3DSIH_NOP; } +static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_param; + + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; + src_param_init_from_value(src_param, operands[0]); + src_param->modifiers = VKD3DSPSM_ABS; + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + +static enum vkd3d_shader_opcode sm6_dx_map_ma_op(enum dx_intrinsic_opcode op, const struct sm6_type *type) +{ + switch (op) + { + case DX_FMA: + return VKD3DSIH_DFMA; + case DX_FMAD: + return VKD3DSIH_MAD; + case DX_IMAD: + case DX_UMAD: + return VKD3DSIH_IMAD; + default: + vkd3d_unreachable(); + } +} + +static void sm6_parser_emit_dx_ma(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_params; + unsigned int i; + + vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_ma_op(op, operands[0]->type)); + if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) + return; + for (i = 0; i < 3; ++i) + src_param_init_from_value(&src_params[i], operands[i]); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -4681,6 +4776,21 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ instruction_dst_param_init_ssa_vector(ins, component_count, sm6); } +static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_param; + + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; + src_param_init_from_value(src_param, operands[0]); + + if (instruction_dst_param_init_ssa_scalar(ins, sm6)) + ins->dst->modifiers = VKD3DSPDM_SATURATE; +} + static void sm6_parser_emit_dx_sincos(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -4967,6 +5077,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_BFREV ] = {"m", "R", sm6_parser_emit_dx_unary}, [DX_BUFFER_LOAD ] = {"o", "Hii", sm6_parser_emit_dx_buffer_load}, [DX_BUFFER_STORE ] = {"v", "Hiiooooc", sm6_parser_emit_dx_buffer_store}, + [DX_BUFFER_UPDATE_COUNTER ] = {"i", "H8", sm6_parser_emit_dx_buffer_update_counter}, [DX_CBUFFER_LOAD_LEGACY ] = {"o", "Hi", sm6_parser_emit_dx_cbuffer_load}, [DX_COS ] = {"g", "R", sm6_parser_emit_dx_sincos}, [DX_COUNT_BITS ] = {"i", "m", sm6_parser_emit_dx_unary}, @@ -4976,9 +5087,12 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_DERIV_FINEX ] = {"e", "R", sm6_parser_emit_dx_unary}, [DX_DERIV_FINEY ] = {"e", "R", sm6_parser_emit_dx_unary}, [DX_EXP ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_FABS ] = {"g", "R", sm6_parser_emit_dx_fabs}, [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_FMA ] = {"g", "RRR", sm6_parser_emit_dx_ma}, + [DX_FMAD ] = {"g", "RRR", sm6_parser_emit_dx_ma}, [DX_FMAX ] = {"g", "RR", sm6_parser_emit_dx_binary}, [DX_FMIN ] = {"g", "RR", sm6_parser_emit_dx_binary}, [DX_FRC ] = {"g", "R", sm6_parser_emit_dx_unary}, @@ -4987,6 +5101,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_HCOS ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_HSIN ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_HTAN ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_IMAD ] = {"m", "RRR", sm6_parser_emit_dx_ma}, [DX_IMAX ] = {"m", "RR", sm6_parser_emit_dx_binary}, [DX_IMIN ] = {"m", "RR", sm6_parser_emit_dx_binary}, [DX_ISFINITE ] = {"1", "g", sm6_parser_emit_dx_unary}, @@ -5009,6 +5124,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_SAMPLE_C_LZ ] = {"o", "HHffffiiif", sm6_parser_emit_dx_sample}, [DX_SAMPLE_GRAD ] = {"o", "HHffffiiifffffff", sm6_parser_emit_dx_sample}, [DX_SAMPLE_LOD ] = {"o", "HHffffiiif", sm6_parser_emit_dx_sample}, + [DX_SATURATE ] = {"g", "R", sm6_parser_emit_dx_saturate}, [DX_SIN ] = {"g", "R", sm6_parser_emit_dx_sincos}, [DX_SPLIT_DOUBLE ] = {"S", "d", sm6_parser_emit_dx_split_double}, [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, @@ -5019,6 +5135,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_TEXTURE_LOAD ] = {"o", "HiiiiCCC", sm6_parser_emit_dx_texture_load}, [DX_TEXTURE_STORE ] = {"v", "Hiiiooooc", sm6_parser_emit_dx_texture_store}, [DX_UBFE ] = {"m", "iiR", sm6_parser_emit_dx_tertiary}, + [DX_UMAD ] = {"m", "RRR", sm6_parser_emit_dx_ma}, [DX_UMAX ] = {"m", "RR", sm6_parser_emit_dx_binary}, [DX_UMIN ] = {"m", "RR", sm6_parser_emit_dx_binary}, }; diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c index fdf132e9ed4..f2be00da33a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d/libs/vkd3d-shader/fx.c @@ -61,7 +61,6 @@ struct fx_write_context; struct fx_write_context_ops { uint32_t (*write_string)(const char *string, struct fx_write_context *fx); - uint32_t (*write_type)(const struct hlsl_type *type, struct fx_write_context *fx); void (*write_technique)(struct hlsl_ir_var *var, struct fx_write_context *fx); void (*write_pass)(struct hlsl_ir_var *var, struct fx_write_context *fx); bool are_child_effects_supported; @@ -87,6 +86,7 @@ struct fx_write_context uint32_t object_variable_count; uint32_t shared_object_count; uint32_t shader_variable_count; + uint32_t parameter_count; int status; bool child_effect; @@ -102,6 +102,11 @@ static void set_status(struct fx_write_context *fx, int status) fx->status = status; } +static bool has_annotations(const struct hlsl_ir_var *var) +{ + return var->annotations && !list_empty(&var->annotations->vars); +} + static uint32_t write_string(const char *string, struct fx_write_context *fx) { return fx->ops->write_string(string, fx); @@ -112,12 +117,16 @@ static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) fx->ops->write_pass(var, fx); } +static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx); + static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context *fx) { struct type_entry *type_entry; unsigned int elements_count; const char *name; + assert(fx->ctx->profile->major_version >= 4); + if (type->class == HLSL_CLASS_ARRAY) { name = hlsl_get_multiarray_element_type(type)->name; @@ -143,7 +152,7 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context if (!(type_entry = hlsl_alloc(fx->ctx, sizeof(*type_entry)))) return 0; - type_entry->offset = fx->ops->write_type(type, fx); + type_entry->offset = write_fx_4_type(type, fx); type_entry->name = name; type_entry->elements_count = elements_count; @@ -156,6 +165,7 @@ static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_co struct fx_write_context *fx) { unsigned int version = ctx->profile->major_version; + struct hlsl_block block; memset(fx, 0, sizeof(*fx)); @@ -181,6 +191,11 @@ static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_co list_init(&fx->types); fx->child_effect = fx->ops->are_child_effects_supported && ctx->child_effect; + + hlsl_block_init(&block); + hlsl_prepend_global_uniform_copy(fx->ctx, &block); + hlsl_block_cleanup(&block); + hlsl_calculate_buffer_offsets(fx->ctx); } static int fx_write_context_cleanup(struct fx_write_context *fx) @@ -302,7 +317,7 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, value |= numeric_type_class[type->class]; break; default: - hlsl_fixme(ctx, &ctx->location, "Not implemented for type class %u.\n", type->class); + hlsl_fixme(ctx, &ctx->location, "Not implemented for type class %u.", type->class); return 0; } @@ -315,7 +330,7 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, value |= (numeric_base_type[type->base_type] << NUMERIC_BASE_TYPE_SHIFT); break; default: - hlsl_fixme(ctx, &ctx->location, "Not implemented for base type %u.\n", type->base_type); + hlsl_fixme(ctx, &ctx->location, "Not implemented for base type %u.", type->base_type); return 0; } @@ -416,7 +431,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co put_u32_unaligned(buffer, variable_type[type->class]); break; default: - hlsl_fixme(ctx, &ctx->location, "Writing type class %u is not implemented.\n", type->class); + hlsl_fixme(ctx, &ctx->location, "Writing type class %u is not implemented.", type->class); return 0; } @@ -498,7 +513,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co put_u32_unaligned(buffer, uav_type[type->sampler_dim]); break; default: - hlsl_fixme(ctx, &ctx->location, "Object type %u is not supported.\n", type->base_type); + hlsl_fixme(ctx, &ctx->location, "Object type %u is not supported.", type->base_type); return 0; } } @@ -604,6 +619,73 @@ static uint32_t write_fx_2_string(const char *string, struct fx_write_context *f return offset; } +static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic, + struct fx_write_context *fx) +{ + struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; + uint32_t semantic_offset, offset, elements_count = 0, name_offset; + struct hlsl_ctx *ctx = fx->ctx; + size_t i; + + /* Resolve arrays to element type and number of elements. */ + if (type->class == HLSL_CLASS_ARRAY) + { + elements_count = hlsl_get_multiarray_size(type); + type = hlsl_get_multiarray_element_type(type); + } + + name_offset = write_string(name, fx); + semantic_offset = write_string(semantic->name, fx); + + switch (type->base_type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_BOOL: + case HLSL_TYPE_INT: + case HLSL_TYPE_VOID: + break; + default: + hlsl_fixme(ctx, &ctx->location, "Writing parameter type %u is not implemented.", + type->base_type); + return 0; + }; + + offset = put_u32(buffer, hlsl_sm1_base_type(type)); + put_u32(buffer, hlsl_sm1_class(type)); + put_u32(buffer, name_offset); + put_u32(buffer, semantic_offset); + put_u32(buffer, elements_count); + + switch (type->class) + { + case HLSL_CLASS_VECTOR: + put_u32(buffer, type->dimx); + put_u32(buffer, type->dimy); + break; + case HLSL_CLASS_SCALAR: + case HLSL_CLASS_MATRIX: + put_u32(buffer, type->dimy); + put_u32(buffer, type->dimx); + break; + case HLSL_CLASS_STRUCT: + put_u32(buffer, type->e.record.field_count); + break; + default: + ; + } + + if (type->class == HLSL_CLASS_STRUCT) + { + for (i = 0; i < type->e.record.field_count; ++i) + { + const struct hlsl_struct_field *field = &type->e.record.fields[i]; + write_fx_2_parameter(field->type, field->name, &field->semantic, fx); + } + } + + return offset; +} + static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) { struct vkd3d_bytecode_buffer *buffer = &fx->structured; @@ -626,6 +708,88 @@ static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_contex set_u32(buffer, count_offset, count); } +static uint32_t get_fx_2_type_size(const struct hlsl_type *type) +{ + uint32_t size = 0, elements_count; + size_t i; + + if (type->class == HLSL_CLASS_ARRAY) + { + elements_count = hlsl_get_multiarray_size(type); + type = hlsl_get_multiarray_element_type(type); + return get_fx_2_type_size(type) * elements_count; + } + else if (type->class == HLSL_CLASS_STRUCT) + { + for (i = 0; i < type->e.record.field_count; ++i) + { + const struct hlsl_struct_field *field = &type->e.record.fields[i]; + size += get_fx_2_type_size(field->type); + } + + return size; + } + + return type->dimx * type->dimy * sizeof(float); +} + +static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct fx_write_context *fx) +{ + struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; + const struct hlsl_type *type = var->data_type; + uint32_t i, offset, size, elements_count = 1; + + size = get_fx_2_type_size(type); + + if (type->class == HLSL_CLASS_ARRAY) + { + elements_count = hlsl_get_multiarray_size(type); + type = hlsl_get_multiarray_element_type(type); + } + + if (type->class == HLSL_CLASS_OBJECT) + { + /* Objects are given sequential ids. */ + offset = put_u32(buffer, fx->object_variable_count++); + for (i = 1; i < elements_count; ++i) + put_u32(buffer, fx->object_variable_count++); + } + else + { + /* FIXME: write actual initial value */ + offset = put_u32(buffer, 0); + + for (i = 1; i < size / sizeof(uint32_t); ++i) + put_u32(buffer, 0); + } + + return offset; +} + +static void write_fx_2_parameters(struct fx_write_context *fx) +{ + struct vkd3d_bytecode_buffer *buffer = &fx->structured; + uint32_t desc_offset, value_offset; + struct hlsl_ctx *ctx = fx->ctx; + struct hlsl_ir_var *var; + + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, fx); + value_offset = write_fx_2_initial_value(var, fx); + + put_u32(buffer, desc_offset); /* Parameter description */ + put_u32(buffer, value_offset); /* Value */ + put_u32(buffer, 0); /* Flags */ + + put_u32(buffer, 0); /* Annotations count */ + if (has_annotations(var)) + hlsl_fixme(ctx, &ctx->location, "Writing annotations for parameters is not implemented."); + + ++fx->parameter_count; + } +} + static const struct fx_write_context_ops fx_2_ops = { .write_string = write_fx_2_string, @@ -635,9 +799,9 @@ static const struct fx_write_context_ops fx_2_ops = static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) { + uint32_t offset, size, technique_count, parameter_count; struct vkd3d_bytecode_buffer buffer = { 0 }; struct vkd3d_bytecode_buffer *structured; - uint32_t offset, size, technique_count; struct fx_write_context fx; fx_write_context_init(ctx, &fx_2_ops, &fx); @@ -649,12 +813,13 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&buffer, 0xfeff0901); /* Version. */ offset = put_u32(&buffer, 0); - put_u32(structured, 0); /* Parameter count */ + parameter_count = put_u32(structured, 0); /* Parameter count */ technique_count = put_u32(structured, 0); put_u32(structured, 0); /* Unknown */ put_u32(structured, 0); /* Object count */ - /* TODO: parameters */ + write_fx_2_parameters(&fx); + set_u32(structured, parameter_count, fx.parameter_count); write_techniques(ctx->globals, &fx); set_u32(structured, technique_count, fx.technique_count); @@ -692,7 +857,6 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) static const struct fx_write_context_ops fx_4_ops = { .write_string = write_fx_4_string, - .write_type = write_fx_4_type, .write_technique = write_fx_4_technique, .write_pass = write_fx_4_pass, .are_child_effects_supported = true, @@ -707,6 +871,7 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write { HAS_EXPLICIT_BIND_POINT = 0x4, }; + struct hlsl_ctx *ctx = fx->ctx; /* Explicit bind point. */ if (var->reg_reservation.reg_type) @@ -725,7 +890,8 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write put_u32(buffer, flags); /* Flags */ put_u32(buffer, 0); /* Annotations count */ - /* FIXME: write annotations */ + if (has_annotations(var)) + hlsl_fixme(ctx, &ctx->location, "Writing annotations for numeric variables is not implemented."); } static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_context *fx) @@ -771,12 +937,13 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_ ++fx->shader_variable_count; break; default: - hlsl_fixme(ctx, &ctx->location, "Writing initializer for object type %u is not implemented.\n", + hlsl_fixme(ctx, &ctx->location, "Writing initializer for object type %u is not implemented.", type->base_type); } put_u32(buffer, 0); /* Annotations count */ - /* FIXME: write annotations */ + if (has_annotations(var)) + hlsl_fixme(ctx, &ctx->location, "Writing annotations for object variables is not implemented."); ++fx->object_variable_count; } @@ -834,12 +1001,6 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx static void write_buffers(struct fx_write_context *fx) { struct hlsl_buffer *buffer; - struct hlsl_block block; - - hlsl_block_init(&block); - hlsl_prepend_global_uniform_copy(fx->ctx, &block); - hlsl_block_init(&block); - hlsl_calculate_buffer_offsets(fx->ctx); LIST_FOR_EACH_ENTRY(buffer, &fx->ctx->buffers, struct hlsl_buffer, entry) { diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c index 23ea89c47be..3977852a48d 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -24,6 +24,7 @@ struct vkd3d_glsl_generator struct vkd3d_string_buffer buffer; struct vkd3d_shader_location location; struct vkd3d_shader_message_context *message_context; + unsigned int indent; bool failed; }; @@ -39,8 +40,14 @@ static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error( generator->failed = true; } +static void shader_glsl_print_indent(struct vkd3d_string_buffer *buffer, unsigned int indent) +{ + vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, ""); +} + static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) { + shader_glsl_print_indent(&gen->buffer, gen->indent); vkd3d_string_buffer_printf(&gen->buffer, "/* */\n", ins->handler_idx); vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, "Internal compiler error: Unhandled instruction %#x.", ins->handler_idx); @@ -57,6 +64,7 @@ static void shader_glsl_ret(struct vkd3d_glsl_generator *generator, */ if (version->major >= 4) { + shader_glsl_print_indent(&generator->buffer, generator->indent); vkd3d_string_buffer_printf(&generator->buffer, "return;\n"); } } @@ -92,6 +100,7 @@ static int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator, vkd3d_string_buffer_printf(&generator->buffer, "#version 440\n\n"); vkd3d_string_buffer_printf(&generator->buffer, "void main()\n{\n"); + ++generator->indent; for (i = 0; i < instructions->count; ++i) { vkd3d_glsl_handle_instruction(generator, &instructions->elements[i]); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h index 5ced5edc766..561782efbf8 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -1363,6 +1363,8 @@ bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), struct hlsl_block *block, void *context); +D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type); +D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type); bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, bool output, D3DSHADER_PARAM_REGISTER_TYPE *type, unsigned int *reg); bool hlsl_sm1_usage_from_semantic(const struct hlsl_semantic *semantic, D3DDECLUSAGE *usage, uint32_t *usage_idx); diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index 55d1216460f..ec32faae8da 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -456,7 +456,7 @@ void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id) { - vsir_src_param_init(param, VKD3DSPR_LABEL, VKD3D_DATA_UINT, 1); + vsir_src_param_init(param, VKD3DSPR_LABEL, VKD3D_DATA_UNUSED, 1); param->reg.dimension = VSIR_DIMENSION_NONE; param->reg.idx[0].offset = label_id; } @@ -467,12 +467,24 @@ static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned src->reg.idx[0].offset = idx; } +static void src_param_init_temp_bool(struct vkd3d_shader_src_param *src, unsigned int idx) +{ + vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_BOOL, 1); + src->reg.idx[0].offset = idx; +} + static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) { vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_BOOL, 1); dst->reg.idx[0].offset = idx; } +static void dst_param_init_temp_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) +{ + vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_BOOL, 1); + dst->reg.idx[0].offset = idx; +} + static void dst_param_init_temp_uint(struct vkd3d_shader_dst_param *dst, unsigned int idx) { vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); @@ -2913,132 +2925,6 @@ fail: return VKD3D_ERROR_OUT_OF_MEMORY; } -static enum vkd3d_result vsir_program_structurise(struct vsir_program *program) -{ - const unsigned int block_temp_idx = program->temp_count; - struct vkd3d_shader_instruction *instructions = NULL; - const struct vkd3d_shader_location no_loc = {0}; - size_t ins_capacity = 0, ins_count = 0, i; - bool first_label_found = false; - - if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count)) - goto fail; - - for (i = 0; i < program->instructions.count; ++i) - { - struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - - switch (ins->handler_idx) - { - case VKD3DSIH_PHI: - case VKD3DSIH_SWITCH_MONOLITHIC: - vkd3d_unreachable(); - - case VKD3DSIH_LABEL: - if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 4)) - goto fail; - - if (!first_label_found) - { - first_label_found = true; - - if (!vsir_instruction_init_with_params(program, - &instructions[ins_count], &no_loc, VKD3DSIH_MOV, 1, 1)) - goto fail; - dst_param_init_temp_uint(&instructions[ins_count].dst[0], block_temp_idx); - src_param_init_const_uint(&instructions[ins_count].src[0], label_from_src_param(&ins->src[0])); - ins_count++; - - if (!vsir_instruction_init_with_params(program, - &instructions[ins_count], &no_loc, VKD3DSIH_LOOP, 0, 0)) - goto fail; - ins_count++; - - if (!vsir_instruction_init_with_params(program, - &instructions[ins_count], &no_loc, VKD3DSIH_SWITCH, 0, 1)) - goto fail; - src_param_init_temp_uint(&instructions[ins_count].src[0], block_temp_idx); - ins_count++; - } - - if (!vsir_instruction_init_with_params(program, - &instructions[ins_count], &no_loc, VKD3DSIH_CASE, 0, 1)) - goto fail; - src_param_init_const_uint(&instructions[ins_count].src[0], label_from_src_param(&ins->src[0])); - ins_count++; - break; - - case VKD3DSIH_BRANCH: - if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 2)) - goto fail; - - if (vsir_register_is_label(&ins->src[0].reg)) - { - if (!vsir_instruction_init_with_params(program, - &instructions[ins_count], &no_loc, VKD3DSIH_MOV, 1, 1)) - goto fail; - dst_param_init_temp_uint(&instructions[ins_count].dst[0], block_temp_idx); - src_param_init_const_uint(&instructions[ins_count].src[0], label_from_src_param(&ins->src[0])); - ins_count++; - } - else - { - if (!vsir_instruction_init_with_params(program, - &instructions[ins_count], &no_loc, VKD3DSIH_MOVC, 1, 3)) - goto fail; - dst_param_init_temp_uint(&instructions[ins_count].dst[0], block_temp_idx); - instructions[ins_count].src[0] = ins->src[0]; - src_param_init_const_uint(&instructions[ins_count].src[1], label_from_src_param(&ins->src[1])); - src_param_init_const_uint(&instructions[ins_count].src[2], label_from_src_param(&ins->src[2])); - ins_count++; - } - - if (!vsir_instruction_init_with_params(program, - &instructions[ins_count], &no_loc, VKD3DSIH_BREAK, 0, 0)) - goto fail; - ins_count++; - break; - - case VKD3DSIH_RET: - default: - if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) - goto fail; - - instructions[ins_count++] = *ins; - break; - } - } - - assert(first_label_found); - - if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 3)) - goto fail; - - if (!vsir_instruction_init_with_params(program, &instructions[ins_count], &no_loc, VKD3DSIH_ENDSWITCH, 0, 0)) - goto fail; - ins_count++; - - if (!vsir_instruction_init_with_params(program, &instructions[ins_count], &no_loc, VKD3DSIH_ENDLOOP, 0, 0)) - goto fail; - ins_count++; - - if (!vsir_instruction_init_with_params(program, &instructions[ins_count], &no_loc, VKD3DSIH_RET, 0, 0)) - goto fail; - ins_count++; - - vkd3d_free(program->instructions.elements); - program->instructions.elements = instructions; - program->instructions.capacity = ins_capacity; - program->instructions.count = ins_count; - program->temp_count += 1; - - return VKD3D_OK; - -fail: - vkd3d_free(instructions); - return VKD3D_ERROR_OUT_OF_MEMORY; -} - struct vsir_block_list { struct vsir_block **blocks; @@ -3283,6 +3169,11 @@ struct vsir_cfg size_t loop_interval_count, loop_interval_capacity; struct vsir_cfg_structure_list structured_program; + + struct vkd3d_shader_instruction *instructions; + size_t ins_capacity, ins_count; + unsigned int jump_target_temp_idx; + unsigned int temp_count; }; static void vsir_cfg_cleanup(struct vsir_cfg *cfg) @@ -4295,6 +4186,213 @@ fail: return VKD3D_ERROR_OUT_OF_MEMORY; } +static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, + struct vsir_cfg_structure_list *list, unsigned int loop_idx) +{ + const struct vkd3d_shader_location no_loc = {0}; + enum vkd3d_result ret; + size_t i; + + for (i = 0; i < list->count; ++i) + { + struct vsir_cfg_structure *structure = &list->structures[i]; + + switch (structure->type) + { + case STRUCTURE_TYPE_BLOCK: + { + struct vsir_block *block = structure->u.block; + + if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->ins_count + (block->end - block->begin))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + memcpy(&cfg->instructions[cfg->ins_count], block->begin, (char *)block->end - (char *)block->begin); + + cfg->ins_count += block->end - block->begin; + break; + } + + case STRUCTURE_TYPE_LOOP: + { + if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->ins_count + 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + vsir_instruction_init(&cfg->instructions[cfg->ins_count++], &no_loc, VKD3DSIH_LOOP); + + if ((ret = vsir_cfg_structure_list_emit(cfg, &structure->u.loop.body, structure->u.loop.idx)) < 0) + return ret; + + if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->ins_count + 5)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + vsir_instruction_init(&cfg->instructions[cfg->ins_count++], &no_loc, VKD3DSIH_ENDLOOP); + + /* Add a trampoline to implement multilevel jumping depending on the stored + * jump_target value. */ + if (loop_idx != UINT_MAX) + { + /* If the multilevel jump is a `continue' and the target is the loop we're inside + * right now, then we can finally do the `continue'. */ + const unsigned int outer_continue_target = loop_idx << 1 | 1; + /* If the multilevel jump is a `continue' to any other target, or if it is a `break' + * and the target is not the loop we just finished emitting, then it means that + * we have to reach an outer loop, so we keep breaking. */ + const unsigned int inner_break_target = structure->u.loop.idx << 1; + + if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + &no_loc, VKD3DSIH_IEQ, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + dst_param_init_temp_bool(&cfg->instructions[cfg->ins_count].dst[0], cfg->temp_count); + src_param_init_temp_uint(&cfg->instructions[cfg->ins_count].src[0], cfg->jump_target_temp_idx); + src_param_init_const_uint(&cfg->instructions[cfg->ins_count].src[1], outer_continue_target); + + ++cfg->ins_count; + + if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + &no_loc, VKD3DSIH_CONTINUEP, 0, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + src_param_init_temp_bool(&cfg->instructions[cfg->ins_count].src[0], cfg->temp_count); + + ++cfg->ins_count; + ++cfg->temp_count; + + if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + &no_loc, VKD3DSIH_IEQ, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + dst_param_init_temp_bool(&cfg->instructions[cfg->ins_count].dst[0], cfg->temp_count); + src_param_init_temp_uint(&cfg->instructions[cfg->ins_count].src[0], cfg->jump_target_temp_idx); + src_param_init_const_uint(&cfg->instructions[cfg->ins_count].src[1], inner_break_target); + + ++cfg->ins_count; + + if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + &no_loc, VKD3DSIH_BREAKP, 0, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + cfg->instructions[cfg->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; + + src_param_init_temp_bool(&cfg->instructions[cfg->ins_count].src[0], cfg->temp_count); + + ++cfg->ins_count; + ++cfg->temp_count; + } + + break; + } + + case STRUCTURE_TYPE_JUMP: + { + /* Encode the jump target as the loop index plus a bit to remember whether + * we're breaking or continueing. */ + unsigned int jump_target = structure->u.jump.target << 1; + enum vkd3d_shader_opcode opcode; + + switch (structure->u.jump.type) + { + case JUMP_CONTINUE: + /* If we're continueing the loop we're directly inside, then we can emit a + * `continue'. Otherwise we first have to break all the loops between here + * and the loop to continue, recording our intention to continue + * in the lowest bit of jump_target. */ + if (structure->u.jump.target == loop_idx) + { + opcode = structure->u.jump.condition ? VKD3DSIH_CONTINUEP : VKD3DSIH_CONTINUE; + break; + } + jump_target |= 1; + /* fall through */ + + case JUMP_BREAK: + opcode = structure->u.jump.condition ? VKD3DSIH_BREAKP : VKD3DSIH_BREAK; + break; + + case JUMP_RET: + assert(!structure->u.jump.condition); + opcode = VKD3DSIH_RET; + break; + + default: + vkd3d_unreachable(); + } + + if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->ins_count + 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + if (opcode == VKD3DSIH_BREAK || opcode == VKD3DSIH_BREAKP) + { + if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + &no_loc, VKD3DSIH_MOV, 1, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + dst_param_init_temp_uint(&cfg->instructions[cfg->ins_count].dst[0], cfg->jump_target_temp_idx); + src_param_init_const_uint(&cfg->instructions[cfg->ins_count].src[0], jump_target); + + ++cfg->ins_count; + } + + if (!vsir_instruction_init_with_params(cfg->program, &cfg->instructions[cfg->ins_count], + &no_loc, opcode, 0, !!structure->u.jump.condition)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + if (structure->u.jump.invert_condition) + cfg->instructions[cfg->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; + + if (structure->u.jump.condition) + cfg->instructions[cfg->ins_count].src[0] = *structure->u.jump.condition; + + ++cfg->ins_count; + break; + } + + default: + vkd3d_unreachable(); + } + } + + return VKD3D_OK; +} + +static enum vkd3d_result vsir_cfg_emit_structured_program(struct vsir_cfg *cfg) +{ + enum vkd3d_result ret; + size_t i; + + cfg->jump_target_temp_idx = cfg->program->temp_count; + cfg->temp_count = cfg->program->temp_count + 1; + + if (!reserve_instructions(&cfg->instructions, &cfg->ins_capacity, cfg->program->instructions.count)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + /* Copy declarations until the first block. */ + for (i = 0; i < cfg->program->instructions.count; ++i) + { + struct vkd3d_shader_instruction *ins = &cfg->program->instructions.elements[i]; + + if (ins->handler_idx == VKD3DSIH_LABEL) + break; + + cfg->instructions[cfg->ins_count++] = *ins; + } + + if ((ret = vsir_cfg_structure_list_emit(cfg, &cfg->structured_program, UINT_MAX)) < 0) + goto fail; + + vkd3d_free(cfg->program->instructions.elements); + cfg->program->instructions.elements = cfg->instructions; + cfg->program->instructions.capacity = cfg->ins_capacity; + cfg->program->instructions.count = cfg->ins_count; + cfg->program->temp_count = cfg->temp_count; + + return VKD3D_OK; + +fail: + vkd3d_free(cfg->instructions); + + return ret; +} + enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info) { @@ -4346,7 +4444,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, return result; } - if ((result = vsir_program_structurise(program)) < 0) + if ((result = vsir_cfg_emit_structured_program(&cfg)) < 0) { vsir_cfg_cleanup(&cfg); return result; @@ -4609,7 +4707,7 @@ static void vsir_validate_register(struct validation_context *ctx, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, "Invalid precision %#x for a LABEL register.", reg->precision); - if (reg->data_type != VKD3D_DATA_UINT) + if (reg->data_type != VKD3D_DATA_UNUSED) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid data type %#x for a LABEL register.", reg->data_type); diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index b4f34c42124..f830bbdaa6d 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -7480,7 +7480,7 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, unsigned int i, component_count; component_count = vsir_write_mask_component_count(dst->write_mask); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_INT, component_count); + type_id = vkd3d_spirv_get_type_id_for_data_type(builder, dst->reg.data_type, component_count); for (i = 0; i < ARRAY_SIZE(src_ids); ++i) src_ids[i] = spirv_compiler_emit_load_src(compiler, &src[i], dst->write_mask); -- 2.43.0