From 1652829e1c0845b53db7cc789c6ea1043beb4f55 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Wed, 9 Oct 2024 20:40:25 +1100 Subject: [PATCH] Updated vkd3d to cd74461d6dabae4e702de61a90533d811aa0a3fb. --- libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 59 ++- libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 2 +- libs/vkd3d/libs/vkd3d-shader/dxbc.c | 2 - libs/vkd3d/libs/vkd3d-shader/dxil.c | 10 +- libs/vkd3d/libs/vkd3d-shader/glsl.c | 254 ++++++++++--- libs/vkd3d/libs/vkd3d-shader/hlsl.c | 1 - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 103 ++--- libs/vkd3d/libs/vkd3d-shader/ir.c | 9 +- libs/vkd3d/libs/vkd3d-shader/msl.c | 357 +++++++++++++++++- libs/vkd3d/libs/vkd3d-shader/preproc.h | 3 +- libs/vkd3d/libs/vkd3d-shader/preproc.l | 53 +-- libs/vkd3d/libs/vkd3d-shader/preproc.y | 13 - libs/vkd3d/libs/vkd3d-shader/spirv.c | 17 +- libs/vkd3d/libs/vkd3d-shader/tpf.c | 7 +- .../libs/vkd3d-shader/vkd3d_shader_main.c | 2 +- .../libs/vkd3d-shader/vkd3d_shader_private.h | 10 +- 16 files changed, 726 insertions(+), 176 deletions(-) diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c index 9fe4b74486a..38d566d9fe0 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -2268,7 +2268,7 @@ static const char *get_semantic_register_name(enum vkd3d_shader_sysval_semantic } } -static enum vkd3d_result dump_signature(struct vkd3d_d3d_asm_compiler *compiler, +static enum vkd3d_result dump_dxbc_signature(struct vkd3d_d3d_asm_compiler *compiler, const char *name, const char *register_name, const struct shader_signature *signature) { struct vkd3d_string_buffer *buffer = &compiler->buffer; @@ -2335,21 +2335,21 @@ static enum vkd3d_result dump_signature(struct vkd3d_d3d_asm_compiler *compiler, return VKD3D_OK; } -static enum vkd3d_result dump_signatures(struct vkd3d_d3d_asm_compiler *compiler, +static enum vkd3d_result dump_dxbc_signatures(struct vkd3d_d3d_asm_compiler *compiler, const struct vsir_program *program) { enum vkd3d_result ret; - if ((ret = dump_signature(compiler, ".input", + if ((ret = dump_dxbc_signature(compiler, ".input", program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN ? "vicp" : "v", &program->input_signature)) < 0) return ret; - if ((ret = dump_signature(compiler, ".output", "o", + if ((ret = dump_dxbc_signature(compiler, ".output", "o", &program->output_signature)) < 0) return ret; - if ((ret = dump_signature(compiler, ".patch_constant", + if ((ret = dump_dxbc_signature(compiler, ".patch_constant", program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN ? "vpc" : "o", &program->patch_constant_signature)) < 0) return ret; @@ -2437,7 +2437,7 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, * doesn't even have an explicit concept of signature. */ if (formatting & VKD3D_SHADER_COMPILE_OPTION_FORMATTING_IO_SIGNATURES && shader_version->major >= 4) { - if ((result = dump_signatures(&compiler, program)) < 0) + if ((result = dump_dxbc_signatures(&compiler, program)) < 0) { vkd3d_string_buffer_cleanup(buffer); return result; @@ -2499,12 +2499,57 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, return result; } -void vkd3d_shader_trace(const struct vsir_program *program) +/* This is meant exclusively for development use. Therefore, differently from + * dump_dxbc_signature(), it doesn't try particularly hard to make the output + * nice or easily parsable, and it dumps all fields, not just the DXBC ones. + * This format isn't meant to be stable. */ +static void trace_signature(const struct shader_signature *signature, const char *signature_type) +{ + struct vkd3d_string_buffer buffer; + unsigned int i; + + TRACE("%s signature:%s\n", signature_type, signature->element_count == 0 ? " empty" : ""); + + vkd3d_string_buffer_init(&buffer); + + for (i = 0; i < signature->element_count; ++i) + { + const struct signature_element *element = &signature->elements[i]; + + vkd3d_string_buffer_clear(&buffer); + + vkd3d_string_buffer_printf(&buffer, "Element %u: %s %u-%u %s", i, + get_component_type_name(element->component_type), + element->register_index, element->register_index + element->register_count, + element->semantic_name); + if (element->semantic_index != -1) + vkd3d_string_buffer_printf(&buffer, "%u", element->semantic_index); + vkd3d_string_buffer_printf(&buffer, + " mask %#x used_mask %#x sysval %s min_precision %s interpolation %u stream %u", + element->mask, element->used_mask, get_sysval_semantic_name(element->sysval_semantic), + get_minimum_precision_name(element->min_precision), element->interpolation_mode, + element->stream_index); + if (element->target_location != -1) + vkd3d_string_buffer_printf(&buffer, " target %u", element->target_location); + else + vkd3d_string_buffer_printf(&buffer, " unused"); + + TRACE("%s\n", buffer.buffer); + } + + vkd3d_string_buffer_cleanup(&buffer); +} + +void vsir_program_trace(const struct vsir_program *program) { const unsigned int flags = VSIR_ASM_FLAG_DUMP_TYPES | VSIR_ASM_FLAG_DUMP_ALL_INDICES; struct vkd3d_shader_code code; const char *p, *q, *end; + trace_signature(&program->input_signature, "Input"); + trace_signature(&program->output_signature, "Output"); + trace_signature(&program->patch_constant_signature, "Patch-constant"); + if (d3d_asm_compile(program, NULL, &code, flags) != VKD3D_OK) return; diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c index 267cf410cbe..589b800f8c9 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -1390,7 +1390,7 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c WARN("Failed to validate shader after parsing, ret %d.\n", ret); if (TRACE_ON()) - vkd3d_shader_trace(program); + vsir_program_trace(program); vsir_program_cleanup(program); return ret; diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c index 93fc993e0d1..f6ac8e0829e 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c @@ -419,8 +419,6 @@ static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *s const char *name; uint32_t mask; - e[i].sort_index = i; - if (has_stream_index) e[i].stream_index = read_u32(&ptr); else diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index d4296ef4bc5..c66b059325a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -4174,6 +4174,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty const struct sm6_type *type_b, struct sm6_parser *sm6) { bool is_int = sm6_type_is_bool_i16_i32_i64(type_a); + bool is_double = sm6_type_is_double(type_a); bool is_bool = sm6_type_is_bool(type_a); enum vkd3d_shader_opcode op; bool is_valid; @@ -4198,7 +4199,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty case BINOP_ADD: case BINOP_SUB: /* NEG is applied later for subtraction. */ - op = is_int ? VKD3DSIH_IADD : VKD3DSIH_ADD; + op = is_int ? VKD3DSIH_IADD : (is_double ? VKD3DSIH_DADD : VKD3DSIH_ADD); is_valid = !is_bool; break; case BINOP_AND: @@ -4214,7 +4215,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty is_valid = is_int && !is_bool; break; case BINOP_MUL: - op = is_int ? VKD3DSIH_UMUL : VKD3DSIH_MUL; + op = is_int ? VKD3DSIH_UMUL : (is_double ? VKD3DSIH_DMUL : VKD3DSIH_MUL); is_valid = !is_bool; break; case BINOP_OR: @@ -4222,7 +4223,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty is_valid = is_int; break; case BINOP_SDIV: - op = is_int ? VKD3DSIH_IDIV : VKD3DSIH_DIV; + op = is_int ? VKD3DSIH_IDIV : (is_double ? VKD3DSIH_DDIV : VKD3DSIH_DIV); is_valid = !is_bool; break; case BINOP_SREM: @@ -9637,6 +9638,7 @@ static enum vkd3d_result sm6_parser_emit_thread_group(struct sm6_parser *sm6, co ins->declaration.thread_group_size.x = group_sizes[0]; ins->declaration.thread_group_size.y = group_sizes[1]; ins->declaration.thread_group_size.z = group_sizes[2]; + sm6->p.program->thread_group_size = ins->declaration.thread_group_size; return VKD3D_OK; } @@ -10592,7 +10594,7 @@ int dxil_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t co WARN("Failed to validate shader after parsing, ret %d.\n", ret); if (TRACE_ON()) - vkd3d_shader_trace(program); + vsir_program_trace(program); sm6_parser_cleanup(&sm6); vsir_program_cleanup(program); diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c index c2fb58c55e6..4dc95899a11 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -62,6 +62,9 @@ struct vkd3d_glsl_generator const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info; }; +static void shader_glsl_print_subscript(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_src_param *rel_addr, unsigned int offset); + static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error( struct vkd3d_glsl_generator *generator, enum vkd3d_shader_error error, const char *fmt, ...) @@ -263,6 +266,11 @@ static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, gen->prefix, reg->idx[0].offset, reg->idx[2].offset); break; + case VKD3DSPR_IDXTEMP: + vkd3d_string_buffer_printf(buffer, "x%u", reg->idx[0].offset); + shader_glsl_print_subscript(buffer, gen, reg->idx[1].rel_addr, reg->idx[1].offset); + break; + default: vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, "Internal compiler error: Unhandled register type %#x.", reg->type); @@ -438,6 +446,26 @@ static uint32_t glsl_dst_init(struct glsl_dst *glsl_dst, struct vkd3d_glsl_gener return write_mask; } +static void shader_glsl_print_subscript(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_src_param *rel_addr, unsigned int offset) +{ + struct glsl_src r; + + if (!rel_addr) + { + vkd3d_string_buffer_printf(buffer, "[%u]", offset); + return; + } + + glsl_src_init(&r, gen, rel_addr, VKD3DSP_WRITEMASK_0); + vkd3d_string_buffer_printf(buffer, "[%s", r.str->buffer); + if (offset) + vkd3d_string_buffer_printf(buffer, " + %u", offset); + else + vkd3d_string_buffer_printf(buffer, "]"); + glsl_src_cleanup(&r, &gen->string_buffers); +} + static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_glsl_generator *gen, struct glsl_dst *dst, enum vkd3d_data_type data_type, const char *format, va_list args) { @@ -903,19 +931,27 @@ static void shader_glsl_print_sysval_name(struct vkd3d_string_buffer *buffer, st switch (sysval) { case VKD3D_SHADER_SV_POSITION: - if (version->type == VKD3D_SHADER_TYPE_PIXEL || version->type == VKD3D_SHADER_TYPE_COMPUTE) + if (version->type == VKD3D_SHADER_TYPE_COMPUTE) { vkd3d_string_buffer_printf(buffer, "", sysval); vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled system value %#x.", sysval); + "Internal compiler error: Unhandled SV_POSITION in shader type #%x.", version->type); + break; } + if (idx) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled SV_POSITION index %u.", idx); + if (version->type == VKD3D_SHADER_TYPE_PIXEL) + vkd3d_string_buffer_printf(buffer, "gl_FragCoord"); else - { vkd3d_string_buffer_printf(buffer, "gl_Position"); - if (idx) - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled SV_POSITION index %u.", idx); - } + break; + + case VKD3D_SHADER_SV_VERTEX_ID: + if (version->type != VKD3D_SHADER_TYPE_VERTEX) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled SV_VERTEX_ID in shader type #%x.", version->type); + vkd3d_string_buffer_printf(buffer, "intBitsToFloat(ivec4(gl_VertexID, 0, 0, 0))"); break; case VKD3D_SHADER_SV_IS_FRONT_FACE: @@ -972,7 +1008,19 @@ static void shader_glsl_shader_prologue(struct vkd3d_glsl_generator *gen) } else { - vkd3d_string_buffer_printf(buffer, " = shader_in_%u", i); + switch (e->component_type) + { + case VKD3D_SHADER_COMPONENT_UINT: + vkd3d_string_buffer_printf(buffer, " = uintBitsToFloat(shader_in_%u)", i); + break; + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled input component type %#x.", e->component_type); + /* fall through */ + case VKD3D_SHADER_COMPONENT_FLOAT: + vkd3d_string_buffer_printf(buffer, " = shader_in_%u", i); + break; + } } } else @@ -989,6 +1037,7 @@ static void shader_glsl_shader_epilogue(struct vkd3d_glsl_generator *gen) { const struct shader_signature *signature = &gen->program->output_signature; struct vkd3d_string_buffer *buffer = gen->buffer; + enum vkd3d_shader_component_type type; const struct signature_element *e; unsigned int i; @@ -999,11 +1048,13 @@ static void shader_glsl_shader_epilogue(struct vkd3d_glsl_generator *gen) if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) continue; + type = e->component_type; shader_glsl_print_indent(buffer, gen->indent); if (e->sysval_semantic == VKD3D_SHADER_SV_NONE) { if (gen->interstage_output) { + type = VKD3D_SHADER_COMPONENT_FLOAT; vkd3d_string_buffer_printf(buffer, "shader_out.reg_%u", e->target_location); if (e->target_location >= gen->limits.output_count) vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, @@ -1023,7 +1074,19 @@ static void shader_glsl_shader_epilogue(struct vkd3d_glsl_generator *gen) shader_glsl_print_sysval_name(buffer, gen, e->sysval_semantic, e->semantic_index); } shader_glsl_print_write_mask(buffer, e->mask); - vkd3d_string_buffer_printf(buffer, " = %s_out[%u]", gen->prefix, e->register_index); + switch (type) + { + case VKD3D_SHADER_COMPONENT_UINT: + vkd3d_string_buffer_printf(buffer, " = floatBitsToUint(%s_out[%u])", gen->prefix, e->register_index); + break; + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled output component type %#x.", e->component_type); + /* fall through */ + case VKD3D_SHADER_COMPONENT_FLOAT: + vkd3d_string_buffer_printf(buffer, " = %s_out[%u]", gen->prefix, e->register_index); + break; + } shader_glsl_print_write_mask(buffer, e->mask); vkd3d_string_buffer_printf(buffer, ";\n"); } @@ -1041,6 +1104,15 @@ static void shader_glsl_ret(struct vkd3d_glsl_generator *gen, const struct vkd3d } } +static void shader_glsl_dcl_indexable_temp(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, "vec4 x%u[%u];\n", + ins->declaration.indexable_temp.register_idx, + ins->declaration.indexable_temp.register_size); +} + static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) { @@ -1049,14 +1121,19 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, switch (ins->opcode) { case VKD3DSIH_ADD: + case VKD3DSIH_IADD: shader_glsl_binop(gen, ins, "+"); break; case VKD3DSIH_AND: shader_glsl_binop(gen, ins, "&"); break; + case VKD3DSIH_DCL_INDEXABLE_TEMP: + shader_glsl_dcl_indexable_temp(gen, ins); + break; case VKD3DSIH_DCL_INPUT: case VKD3DSIH_DCL_INPUT_PS: case VKD3DSIH_DCL_INPUT_PS_SIV: + case VKD3DSIH_DCL_INPUT_SGV: case VKD3DSIH_DCL_OUTPUT: case VKD3DSIH_DCL_OUTPUT_SIV: case VKD3DSIH_NOP: @@ -1079,6 +1156,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, case VKD3DSIH_ENDIF: shader_glsl_endif(gen); break; + case VKD3DSIH_EQO: case VKD3DSIH_IEQ: shader_glsl_relop(gen, ins, "==", "equal"); break; @@ -1108,26 +1186,30 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, case VKD3DSIH_LTO: shader_glsl_relop(gen, ins, "<", "lessThan"); break; - case VKD3DSIH_IMUL: - shader_glsl_mul_extended(gen, ins); - break; - case VKD3DSIH_ISHL: - shader_glsl_binop(gen, ins, "<<"); - break; - case VKD3DSIH_ISHR: - case VKD3DSIH_USHR: - shader_glsl_binop(gen, ins, ">>"); - break; + case VKD3DSIH_IMAX: case VKD3DSIH_MAX: shader_glsl_intrinsic(gen, ins, "max"); break; case VKD3DSIH_MIN: shader_glsl_intrinsic(gen, ins, "min"); break; + case VKD3DSIH_IMUL: + shader_glsl_mul_extended(gen, ins); + break; case VKD3DSIH_INE: case VKD3DSIH_NEU: shader_glsl_relop(gen, ins, "!=", "notEqual"); break; + case VKD3DSIH_INEG: + shader_glsl_unary_op(gen, ins, "-"); + break; + case VKD3DSIH_ISHL: + shader_glsl_binop(gen, ins, "<<"); + break; + case VKD3DSIH_ISHR: + case VKD3DSIH_USHR: + shader_glsl_binop(gen, ins, ">>"); + break; case VKD3DSIH_ITOF: case VKD3DSIH_UTOF: shader_glsl_cast(gen, ins, "float", "vec"); @@ -1485,15 +1567,62 @@ static void shader_glsl_generate_descriptor_declarations(struct vkd3d_glsl_gener vkd3d_string_buffer_printf(gen->buffer, "\n"); } -static void shader_glsl_generate_interface_block(struct vkd3d_string_buffer *buffer, - const char *type, unsigned int count) +static const struct signature_element *signature_get_element_by_location( + const struct shader_signature *signature, unsigned int location) { + const struct signature_element *e; + unsigned int i; + + for (i = 0; i < signature->element_count; ++i) + { + e = &signature->elements[i]; + + if (e->target_location != location) + continue; + + return e; + } + + return NULL; +} + +static const char *shader_glsl_get_interpolation(struct vkd3d_glsl_generator *gen, + const struct shader_signature *signature, const char *type, unsigned int location) +{ + enum vkd3d_shader_interpolation_mode m; + const struct signature_element *e; + + if ((e = signature_get_element_by_location(signature, location))) + m = e->interpolation_mode; + else + m = VKD3DSIM_NONE; + + switch (m) + { + case VKD3DSIM_NONE: + case VKD3DSIM_LINEAR: + return ""; + case VKD3DSIM_CONSTANT: + return "flat "; + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled interpolation mode %#x for %s location %u.", m, type, location); + return ""; + } +} + +static void shader_glsl_generate_interface_block(struct vkd3d_glsl_generator *gen, + const struct shader_signature *signature, const char *type, unsigned int count) +{ + struct vkd3d_string_buffer *buffer = gen->buffer; + const char *interpolation; unsigned int i; vkd3d_string_buffer_printf(buffer, "%s shader_in_out\n{\n", type); for (i = 0; i < count; ++i) { - vkd3d_string_buffer_printf(buffer, " vec4 reg_%u;\n", i); + interpolation = shader_glsl_get_interpolation(gen, signature, type, i); + vkd3d_string_buffer_printf(buffer, " %svec4 reg_%u;\n", interpolation, i); } vkd3d_string_buffer_printf(buffer, "} shader_%s;\n", type); } @@ -1503,30 +1632,16 @@ static void shader_glsl_generate_input_declarations(struct vkd3d_glsl_generator const struct shader_signature *signature = &gen->program->input_signature; struct vkd3d_string_buffer *buffer = gen->buffer; const struct signature_element *e; - unsigned int i; + unsigned int i, count; if (!gen->interstage_input) { - for (i = 0; i < signature->element_count; ++i) + for (i = 0, count = 0; i < signature->element_count; ++i) { e = &signature->elements[i]; - if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) - continue; - - if (e->sysval_semantic) - { - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled system value %#x.", e->sysval_semantic); - continue; - } - - if (e->component_type != VKD3D_SHADER_COMPONENT_FLOAT) - { - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled component type %#x.", e->component_type); + if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED || e->sysval_semantic) continue; - } if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) { @@ -1542,15 +1657,32 @@ static void shader_glsl_generate_input_declarations(struct vkd3d_glsl_generator continue; } - vkd3d_string_buffer_printf(buffer, - "layout(location = %u) in vec4 shader_in_%u;\n", e->target_location, i); + vkd3d_string_buffer_printf(buffer, "layout(location = %u) in ", e->target_location); + switch (e->component_type) + { + case VKD3D_SHADER_COMPONENT_UINT: + vkd3d_string_buffer_printf(buffer, "uvec4"); + break; + case VKD3D_SHADER_COMPONENT_FLOAT: + vkd3d_string_buffer_printf(buffer, "vec4"); + break; + default: + vkd3d_string_buffer_printf(buffer, "", e->component_type); + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled input component type %#x.", e->component_type); + break; + } + vkd3d_string_buffer_printf(buffer, " shader_in_%u;\n", i); + ++count; } + if (count) + vkd3d_string_buffer_printf(buffer, "\n"); } else if (gen->limits.input_count) { - shader_glsl_generate_interface_block(buffer, "in", gen->limits.input_count); + shader_glsl_generate_interface_block(gen, signature, "in", gen->limits.input_count); + vkd3d_string_buffer_printf(buffer, "\n"); } - vkd3d_string_buffer_printf(buffer, "\n"); } static void shader_glsl_generate_output_declarations(struct vkd3d_glsl_generator *gen) @@ -1558,11 +1690,11 @@ static void shader_glsl_generate_output_declarations(struct vkd3d_glsl_generator const struct shader_signature *signature = &gen->program->output_signature; struct vkd3d_string_buffer *buffer = gen->buffer; const struct signature_element *e; - unsigned int i; + unsigned int i, count; if (!gen->interstage_output) { - for (i = 0; i < signature->element_count; ++i) + for (i = 0, count = 0; i < signature->element_count; ++i) { e = &signature->elements[i]; @@ -1576,13 +1708,6 @@ static void shader_glsl_generate_output_declarations(struct vkd3d_glsl_generator continue; } - if (e->component_type != VKD3D_SHADER_COMPONENT_FLOAT) - { - vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled component type %#x.", e->component_type); - continue; - } - if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) { vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, @@ -1597,15 +1722,32 @@ static void shader_glsl_generate_output_declarations(struct vkd3d_glsl_generator continue; } - vkd3d_string_buffer_printf(buffer, - "layout(location = %u) out vec4 shader_out_%u;\n", e->target_location, i); + vkd3d_string_buffer_printf(buffer, "layout(location = %u) out ", e->target_location); + switch (e->component_type) + { + case VKD3D_SHADER_COMPONENT_UINT: + vkd3d_string_buffer_printf(buffer, "uvec4"); + break; + case VKD3D_SHADER_COMPONENT_FLOAT: + vkd3d_string_buffer_printf(buffer, "vec4"); + break; + default: + vkd3d_string_buffer_printf(buffer, "", e->component_type); + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled output component type %#x.", e->component_type); + break; + } + vkd3d_string_buffer_printf(buffer, " shader_out_%u;\n", i); + ++count; } + if (count) + vkd3d_string_buffer_printf(buffer, "\n"); } else if (gen->limits.output_count) { - shader_glsl_generate_interface_block(buffer, "out", gen->limits.output_count); + shader_glsl_generate_interface_block(gen, signature, "out", gen->limits.output_count); + vkd3d_string_buffer_printf(buffer, "\n"); } - vkd3d_string_buffer_printf(buffer, "\n"); } static void shader_glsl_generate_declarations(struct vkd3d_glsl_generator *gen) diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c index 9ace1930c1b..b44c0296f69 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c @@ -1621,7 +1621,6 @@ struct hlsl_ir_node *hlsl_new_binary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_exp { struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {arg1, arg2}; - VKD3D_ASSERT(hlsl_types_are_equal(arg1->data_type, arg2->data_type)); return hlsl_new_expr(ctx, op, operands, arg1->data_type, &arg1->loc); } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index ef37eb75f03..2230cd5b919 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -461,6 +461,40 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct return add_cast(ctx, block, node, dst_type, loc); } +static bool add_explicit_conversion(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_type *dst_type, const struct parse_array_sizes *arrays, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *instr = node_from_block(block); + struct hlsl_type *src_type = instr->data_type; + unsigned int i; + + for (i = 0; i < arrays->count; ++i) + { + if (arrays->sizes[i] == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Implicit size arrays not allowed in casts."); + dst_type = hlsl_new_array_type(ctx, dst_type, arrays->sizes[i]); + } + + if (instr->data_type->class == HLSL_CLASS_ERROR) + return true; + + if (!explicit_compatible_data_types(ctx, src_type, dst_type)) + { + struct vkd3d_string_buffer *src_string, *dst_string; + + src_string = hlsl_type_to_string(ctx, src_type); + dst_string = hlsl_type_to_string(ctx, dst_type); + if (src_string && dst_string) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Can't cast from %s to %s.", + src_string->buffer, dst_string->buffer); + hlsl_release_string_buffer(ctx, src_string); + hlsl_release_string_buffer(ctx, dst_string); + return false; + } + + return add_cast(ctx, block, instr, dst_type, loc); +} + static uint32_t add_modifiers(struct hlsl_ctx *ctx, uint32_t modifiers, uint32_t mod, const struct vkd3d_shader_location *loc) { @@ -978,6 +1012,12 @@ static bool add_array_access(struct hlsl_ctx *ctx, struct hlsl_block *block, str const struct hlsl_type *expr_type = array->data_type, *index_type = index->data_type; struct hlsl_ir_node *return_index, *cast; + if (array->data_type->class == HLSL_CLASS_ERROR || index->data_type->class == HLSL_CLASS_ERROR) + { + block->value = ctx->error_instr; + return true; + } + if ((expr_type->class == HLSL_CLASS_TEXTURE || expr_type->class == HLSL_CLASS_UAV) && expr_type->sampler_dim != HLSL_SAMPLER_DIM_GENERIC) { @@ -2314,6 +2354,9 @@ static bool add_increment(struct hlsl_ctx *ctx, struct hlsl_block *block, bool d struct hlsl_ir_node *lhs = node_from_block(block); struct hlsl_ir_node *one; + if (lhs->data_type->class == HLSL_CLASS_ERROR) + return true; + if (lhs->data_type->modifiers & HLSL_MODIFIER_CONST) hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_MODIFIES_CONST, "Argument to %s%screment operator is const.", post ? "post" : "pre", decrement ? "de" : "in"); @@ -2366,9 +2409,9 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i { struct hlsl_default_value default_value = {0}; - if (hlsl_is_numeric_type(dst_comp_type)) + if (src->type == HLSL_IR_COMPILE || src->type == HLSL_IR_SAMPLER_STATE) { - if (src->type == HLSL_IR_COMPILE || src->type == HLSL_IR_SAMPLER_STATE) + if (hlsl_is_numeric_type(dst_comp_type)) { /* Default values are discarded if they contain an object * literal expression for a numeric component. */ @@ -2381,17 +2424,17 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i dst->default_values = NULL; } } - else - { - if (!hlsl_clone_block(ctx, &block, instrs)) - return; - default_value = evaluate_static_expression(ctx, &block, dst_comp_type, &src->loc); + } + else + { + if (!hlsl_clone_block(ctx, &block, instrs)) + return; + default_value = evaluate_static_expression(ctx, &block, dst_comp_type, &src->loc); - if (dst->default_values) - dst->default_values[*store_index] = default_value; + if (dst->default_values) + dst->default_values[*store_index] = default_value; - hlsl_block_cleanup(&block); - } + hlsl_block_cleanup(&block); } } else @@ -8770,7 +8813,6 @@ postfix_expr: YYABORT; } vkd3d_free($3); - $$ = $1; } else if (hlsl_is_numeric_type(node->data_type)) { @@ -8784,14 +8826,14 @@ postfix_expr: } hlsl_block_add_instr($1, swizzle); vkd3d_free($3); - $$ = $1; } - else + else if (node->data_type->class != HLSL_CLASS_ERROR) { hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Invalid subscript \"%s\".", $3); vkd3d_free($3); YYABORT; } + $$ = $1; } | postfix_expr '[' expr ']' { @@ -8903,10 +8945,6 @@ unary_expr: /* var_modifiers is necessary to avoid shift/reduce conflicts. */ | '(' var_modifiers type arrays ')' unary_expr { - struct hlsl_type *src_type = node_from_block($6)->data_type; - struct hlsl_type *dst_type; - unsigned int i; - if ($2) { hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, @@ -8914,36 +8952,13 @@ unary_expr: YYABORT; } - dst_type = $3; - for (i = 0; i < $4.count; ++i) - { - if ($4.sizes[i] == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT) - { - hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Implicit size arrays not allowed in casts."); - } - dst_type = hlsl_new_array_type(ctx, dst_type, $4.sizes[i]); - } - - if (!explicit_compatible_data_types(ctx, src_type, dst_type)) - { - struct vkd3d_string_buffer *src_string, *dst_string; - - src_string = hlsl_type_to_string(ctx, src_type); - dst_string = hlsl_type_to_string(ctx, dst_type); - if (src_string && dst_string) - hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Can't cast from %s to %s.", - src_string->buffer, dst_string->buffer); - hlsl_release_string_buffer(ctx, src_string); - hlsl_release_string_buffer(ctx, dst_string); - YYABORT; - } - - if (!add_cast(ctx, $6, node_from_block($6), dst_type, &@3)) + if (!add_explicit_conversion(ctx, $6, $3, &$4, &@3)) { destroy_block($6); + vkd3d_free($4.sizes); YYABORT; } + vkd3d_free($4.sizes); $$ = $6; } diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index 6a74e2eb8de..14cf23e8d1a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -681,6 +681,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr case VKD3DSIH_DCL_CONSTANT_BUFFER: case VKD3DSIH_DCL_SAMPLER: case VKD3DSIH_DCL_TEMPS: + case VKD3DSIH_DCL_THREAD_GROUP: vkd3d_shader_instruction_make_nop(ins); break; @@ -763,7 +764,7 @@ static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_i } for (i = 0; i < ins->dst_count; ++i) - shader_register_eliminate_phase_addressing((struct vkd3d_shader_register *)&ins->dst[i].reg, instance_id); + shader_register_eliminate_phase_addressing(&ins->dst[i].reg, instance_id); } static const struct vkd3d_shader_varying_map *find_varying_map( @@ -1470,6 +1471,9 @@ static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map return false; memcpy(elements, s->elements, element_count * sizeof(*elements)); + for (i = 0; i < element_count; ++i) + elements[i].sort_index = i; + qsort(elements, element_count, sizeof(elements[0]), signature_element_register_compare); for (i = 0, new_count = 0; i < element_count; i = j, elements[new_count++] = *e) @@ -1667,7 +1671,6 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par vkd3d_unreachable(); e = &signature->elements[element_idx]; - dst_param->write_mask >>= vsir_write_mask_get_component_idx(e->mask); if (is_io_dcl) { /* Validated in the TPF reader. */ @@ -7149,7 +7152,7 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t vsir_transform(&ctx, vsir_program_insert_clip_planes); if (TRACE_ON()) - vkd3d_shader_trace(program); + vsir_program_trace(program); return ctx.result; } diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c index 6b41363d60e..bfc013959e7 100644 --- a/libs/vkd3d/libs/vkd3d-shader/msl.c +++ b/libs/vkd3d/libs/vkd3d-shader/msl.c @@ -38,6 +38,7 @@ struct msl_generator struct vkd3d_shader_location location; struct vkd3d_shader_message_context *message_context; unsigned int indent; + const char *prefix; }; static void VKD3D_PRINTF_FUNC(3, 4) msl_compiler_error(struct msl_generator *gen, @@ -50,16 +51,37 @@ static void VKD3D_PRINTF_FUNC(3, 4) msl_compiler_error(struct msl_generator *gen va_end(args); } +static const char *msl_get_prefix(enum vkd3d_shader_type type) +{ + switch (type) + { + case VKD3D_SHADER_TYPE_VERTEX: + return "vs"; + case VKD3D_SHADER_TYPE_HULL: + return "hs"; + case VKD3D_SHADER_TYPE_DOMAIN: + return "ds"; + case VKD3D_SHADER_TYPE_GEOMETRY: + return "gs"; + case VKD3D_SHADER_TYPE_PIXEL: + return "ps"; + case VKD3D_SHADER_TYPE_COMPUTE: + return "cs"; + default: + return NULL; + } +} + static void msl_print_indent(struct vkd3d_string_buffer *buffer, unsigned int indent) { vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, ""); } static void msl_print_register_datatype(struct vkd3d_string_buffer *buffer, - struct msl_generator *gen, const struct vkd3d_shader_register *reg) + struct msl_generator *gen, enum vkd3d_data_type data_type) { vkd3d_string_buffer_printf(buffer, "."); - switch (reg->data_type) + switch (data_type) { case VKD3D_DATA_FLOAT: vkd3d_string_buffer_printf(buffer, "f"); @@ -72,8 +94,8 @@ static void msl_print_register_datatype(struct vkd3d_string_buffer *buffer, break; default: msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, - "Internal compiler error: Unhandled register datatype %#x.", reg->data_type); - vkd3d_string_buffer_printf(buffer, "", reg->data_type); + "Internal compiler error: Unhandled register datatype %#x.", data_type); + vkd3d_string_buffer_printf(buffer, "", data_type); break; } } @@ -85,7 +107,7 @@ static void msl_print_register_name(struct vkd3d_string_buffer *buffer, { case VKD3DSPR_TEMP: vkd3d_string_buffer_printf(buffer, "r[%u]", reg->idx[0].offset); - msl_print_register_datatype(buffer, gen, reg); + msl_print_register_datatype(buffer, gen, reg->data_type); break; default: msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, @@ -244,6 +266,309 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d } } +static void msl_generate_input_struct_declarations(struct msl_generator *gen) +{ + const struct shader_signature *signature = &gen->program->input_signature; + enum vkd3d_shader_type type = gen->program->shader_version.type; + struct vkd3d_string_buffer *buffer = gen->buffer; + const struct signature_element *e; + unsigned int i; + + vkd3d_string_buffer_printf(buffer, "struct vkd3d_%s_in\n{\n", gen->prefix); + + for (i = 0; i < signature->element_count; ++i) + { + e = &signature->elements[i]; + + if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) + continue; + + if (e->sysval_semantic) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled system value %#x.", e->sysval_semantic); + continue; + } + + if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled minimum precision %#x.", e->min_precision); + continue; + } + + if (e->interpolation_mode != VKD3DSIM_NONE) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled interpolation mode %#x.", e->interpolation_mode); + continue; + } + + if(e->register_count > 1) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled register count %u.", e->register_count); + continue; + } + + msl_print_indent(gen->buffer, 1); + + switch(e->component_type) + { + case VKD3D_SHADER_COMPONENT_FLOAT: + vkd3d_string_buffer_printf(buffer, "float4 "); + break; + case VKD3D_SHADER_COMPONENT_INT: + vkd3d_string_buffer_printf(buffer, "int4 "); + break; + case VKD3D_SHADER_COMPONENT_UINT: + vkd3d_string_buffer_printf(buffer, "uint4 "); + break; + default: + vkd3d_string_buffer_printf(buffer, " ", e->component_type); + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled component type %#x.", e->component_type); + break; + } + + vkd3d_string_buffer_printf(buffer, "shader_in_%u ", i); + + switch (type) + { + case VKD3D_SHADER_TYPE_VERTEX: + vkd3d_string_buffer_printf(gen->buffer, "[[attribute(%u)]]", e->target_location); + break; + case VKD3D_SHADER_TYPE_PIXEL: + vkd3d_string_buffer_printf(gen->buffer, "[[user(locn%u)]]", e->target_location); + break; + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled shader type %#x.", type); + break; + } + + vkd3d_string_buffer_printf(buffer, ";\n"); + } + + vkd3d_string_buffer_printf(buffer, "};\n\n"); +} + +static void msl_generate_vertex_output_element_attribute(struct msl_generator *gen, const struct signature_element *e) +{ + switch (e->sysval_semantic) + { + case VKD3D_SHADER_SV_POSITION: + vkd3d_string_buffer_printf(gen->buffer, "[[position]]"); + break; + case VKD3D_SHADER_SV_NONE: + vkd3d_string_buffer_printf(gen->buffer, "[[user(locn%u)]]", e->target_location); + break; + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled vertex shader system value %#x.", e->sysval_semantic); + break; + } +} + +static void msl_generate_pixel_output_element_attribute(struct msl_generator *gen, const struct signature_element *e) +{ + switch (e->sysval_semantic) + { + case VKD3D_SHADER_SV_TARGET: + vkd3d_string_buffer_printf(gen->buffer, "[[color(%u)]]", e->target_location); + break; + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled pixel shader system value %#x.", e->sysval_semantic); + break; + } +} + +static void msl_generate_output_struct_declarations(struct msl_generator *gen) +{ + const struct shader_signature *signature = &gen->program->output_signature; + enum vkd3d_shader_type type = gen->program->shader_version.type; + struct vkd3d_string_buffer *buffer = gen->buffer; + const struct signature_element *e; + unsigned int i; + + vkd3d_string_buffer_printf(buffer, "struct vkd3d_%s_out\n{\n", gen->prefix); + + for (i = 0; i < signature->element_count; ++i) + { + e = &signature->elements[i]; + + if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) + continue; + + if (e->min_precision != VKD3D_SHADER_MINIMUM_PRECISION_NONE) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled minimum precision %#x.", e->min_precision); + continue; + } + + if (e->interpolation_mode != VKD3DSIM_NONE) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled interpolation mode %#x.", e->interpolation_mode); + continue; + } + + if(e->register_count > 1) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled register count %u.", e->register_count); + continue; + } + + msl_print_indent(gen->buffer, 1); + + switch(e->component_type) + { + case VKD3D_SHADER_COMPONENT_FLOAT: + vkd3d_string_buffer_printf(buffer, "float4 "); + break; + case VKD3D_SHADER_COMPONENT_INT: + vkd3d_string_buffer_printf(buffer, "int4 "); + break; + case VKD3D_SHADER_COMPONENT_UINT: + vkd3d_string_buffer_printf(buffer, "uint4 "); + break; + default: + vkd3d_string_buffer_printf(buffer, " ", e->component_type); + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled component type %#x.", e->component_type); + break; + } + + vkd3d_string_buffer_printf(buffer, "shader_out_%u ", i); + + switch (type) + { + case VKD3D_SHADER_TYPE_VERTEX: + msl_generate_vertex_output_element_attribute(gen, e); + break; + case VKD3D_SHADER_TYPE_PIXEL: + msl_generate_pixel_output_element_attribute(gen, e); + break; + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled shader type %#x.", type); + break; + } + + vkd3d_string_buffer_printf(buffer, ";\n"); + } + + vkd3d_string_buffer_printf(buffer, "};\n\n"); +} + +static void msl_generate_entrypoint_prologue(struct msl_generator *gen) +{ + const struct shader_signature *signature = &gen->program->input_signature; + struct vkd3d_string_buffer *buffer = gen->buffer; + const struct signature_element *e; + unsigned int i; + + for (i = 0; i < signature->element_count; ++i) + { + e = &signature->elements[i]; + + if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) + continue; + + vkd3d_string_buffer_printf(buffer, " %s_in[%u]", gen->prefix, e->register_index); + if (e->sysval_semantic == VKD3D_SHADER_SV_NONE) + { + msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = input.shader_in_%u", i); + msl_print_write_mask(buffer, e->mask); + } + else + { + vkd3d_string_buffer_printf(buffer, " = ", e->sysval_semantic); + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled system value %#x input.", e->sysval_semantic); + } + vkd3d_string_buffer_printf(buffer, ";\n"); + } +} + +static void msl_generate_entrypoint_epilogue(struct msl_generator *gen) +{ + const struct shader_signature *signature = &gen->program->output_signature; + struct vkd3d_string_buffer *buffer = gen->buffer; + const struct signature_element *e; + unsigned int i; + + for (i = 0; i < signature->element_count; ++i) + { + e = &signature->elements[i]; + + if (e->target_location == SIGNATURE_TARGET_LOCATION_UNUSED) + continue; + + switch (e->sysval_semantic) + { + case VKD3D_SHADER_SV_NONE: + case VKD3D_SHADER_SV_TARGET: + case VKD3D_SHADER_SV_POSITION: + vkd3d_string_buffer_printf(buffer, " output.shader_out_%u", i); + msl_print_write_mask(buffer, e->mask); + vkd3d_string_buffer_printf(buffer, " = %s_out", gen->prefix); + msl_print_register_datatype(buffer, gen, vkd3d_data_type_from_component_type(e->component_type)); + msl_print_write_mask(buffer, e->mask); + break; + default: + vkd3d_string_buffer_printf(buffer, " ", e->sysval_semantic); + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled system value %#x input.", e->sysval_semantic); + } + vkd3d_string_buffer_printf(buffer, ";\n"); + } +} + +static void msl_generate_entrypoint(struct msl_generator *gen) +{ + enum vkd3d_shader_type type = gen->program->shader_version.type; + + switch (type) + { + case VKD3D_SHADER_TYPE_VERTEX: + vkd3d_string_buffer_printf(gen->buffer, "vertex "); + break; + case VKD3D_SHADER_TYPE_PIXEL: + vkd3d_string_buffer_printf(gen->buffer, "fragment "); + break; + default: + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled shader type %#x.", type); + return; + } + + vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_out shader_entry(\n", gen->prefix); + + /* TODO: descriptor declaration */ + + msl_print_indent(gen->buffer, 1); + vkd3d_string_buffer_printf(gen->buffer, "vkd3d_%s_in input [[stage_in]])\n{\n", gen->prefix); + + /* TODO: declare #maximum_register + 1 */ + vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 %s_in[%u];\n", gen->prefix, 32); + vkd3d_string_buffer_printf(gen->buffer, " vkd3d_vec4 %s_out[%u];\n", gen->prefix, 32); + vkd3d_string_buffer_printf(gen->buffer, " vkd3d_%s_out output;\n", gen->prefix); + + msl_generate_entrypoint_prologue(gen); + + vkd3d_string_buffer_printf(gen->buffer, " %s_main(%s_in, %s_out);\n", gen->prefix, gen->prefix, gen->prefix); + + msl_generate_entrypoint_epilogue(gen); + + vkd3d_string_buffer_printf(gen->buffer, " return output;\n}\n"); +} + static void msl_generator_generate(struct msl_generator *gen) { const struct vkd3d_shader_instruction_array *instructions = &gen->program->instructions; @@ -258,7 +583,13 @@ static void msl_generator_generate(struct msl_generator *gen) vkd3d_string_buffer_printf(gen->buffer, " int4 i;\n"); vkd3d_string_buffer_printf(gen->buffer, " float4 f;\n};\n\n"); - vkd3d_string_buffer_printf(gen->buffer, "void shader_main()\n{\n"); + msl_generate_input_struct_declarations(gen); + msl_generate_output_struct_declarations(gen); + + vkd3d_string_buffer_printf(gen->buffer, + "void %s_main(thread vkd3d_vec4 *v, " + "thread vkd3d_vec4 *o)\n{\n", + gen->prefix); ++gen->indent; @@ -273,7 +604,11 @@ static void msl_generator_generate(struct msl_generator *gen) msl_handle_instruction(gen, &instructions->elements[i]); } - vkd3d_string_buffer_printf(gen->buffer, "}\n"); + --gen->indent; + + vkd3d_string_buffer_printf(gen->buffer, "}\n\n"); + + msl_generate_entrypoint(gen); if (TRACE_ON()) vkd3d_string_buffer_trace(gen->buffer); @@ -288,6 +623,8 @@ static void msl_generator_cleanup(struct msl_generator *gen) static int msl_generator_init(struct msl_generator *gen, struct vsir_program *program, struct vkd3d_shader_message_context *message_context) { + enum vkd3d_shader_type type = program->shader_version.type; + memset(gen, 0, sizeof(*gen)); gen->program = program; vkd3d_string_buffer_cache_init(&gen->string_buffers); @@ -297,6 +634,12 @@ static int msl_generator_init(struct msl_generator *gen, struct vsir_program *pr return VKD3D_ERROR_OUT_OF_MEMORY; } gen->message_context = message_context; + if (!(gen->prefix = msl_get_prefix(type))) + { + msl_compiler_error(gen, VKD3D_SHADER_ERROR_MSL_INTERNAL, + "Internal compiler error: Unhandled shader type %#x.", type); + return VKD3D_ERROR_INVALID_SHADER; + } return VKD3D_OK; } diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.h b/libs/vkd3d/libs/vkd3d-shader/preproc.h index 9806614a35b..a98c8ae3df5 100644 --- a/libs/vkd3d/libs/vkd3d-shader/preproc.h +++ b/libs/vkd3d/libs/vkd3d-shader/preproc.h @@ -60,6 +60,7 @@ struct preproc_expansion { struct preproc_buffer buffer; const struct preproc_text *text; + struct preproc_text *arg_values; /* Back-pointer to the macro, if this expansion a macro body. This is * necessary so that argument tokens can be correctly replaced. */ struct preproc_macro *macro; @@ -72,7 +73,6 @@ struct preproc_macro char **arg_names; size_t arg_count; - struct preproc_text *arg_values; struct preproc_text body; }; @@ -117,6 +117,7 @@ struct preproc_ctx STATE_ARGS, } state; unsigned int paren_depth; + struct preproc_text *arg_values; } text_func, directive_func; int current_directive; diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l index 41c21cca1f5..d167415c356 100644 --- a/libs/vkd3d/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l @@ -30,11 +30,11 @@ #define YY_DECL static int preproc_lexer_lex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) -static struct preproc_macro *preproc_get_top_macro(struct preproc_ctx *ctx) +static struct preproc_expansion *preproc_get_top_expansion(struct preproc_ctx *ctx) { if (!ctx->expansion_count) return NULL; - return ctx->expansion_stack[ctx->expansion_count - 1].macro; + return &ctx->expansion_stack[ctx->expansion_count - 1]; } static void update_location(struct preproc_ctx *ctx); @@ -133,14 +133,14 @@ INT_SUFFIX [uUlL]{0,2} if (!ctx->last_was_newline) { - struct preproc_macro *macro; + struct preproc_expansion *exp; /* Stringification is only done for function-like macro bodies. * Anywhere else, we need to parse it as two separate tokens. * We could use a state for this, but yyless() is easier and cheap. */ - if ((macro = preproc_get_top_macro(ctx)) && macro->arg_count) + if ((exp = preproc_get_top_expansion(ctx)) && exp->macro && exp->macro->arg_count) return T_HASHSTRING; yyless(1); @@ -259,6 +259,12 @@ static void preproc_pop_buffer(struct preproc_ctx *ctx) yy_delete_buffer(exp->buffer.lexer_buffer, ctx->scanner); + if (exp->macro) + { + for (unsigned int i = 0; i < exp->macro->arg_count; ++i) + vkd3d_string_buffer_cleanup(&exp->arg_values[i].text); + free(exp->arg_values); + } --ctx->expansion_count; TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count); } @@ -311,15 +317,15 @@ static int return_token(int token, YYSTYPE *lval, const char *text) static const struct preproc_text *find_arg_expansion(struct preproc_ctx *ctx, const char *s) { - struct preproc_macro *macro; + struct preproc_expansion *exp; unsigned int i; - if ((macro = preproc_get_top_macro(ctx))) + if ((exp = preproc_get_top_expansion(ctx)) && exp->macro) { - for (i = 0; i < macro->arg_count; ++i) + for (i = 0; i < exp->macro->arg_count; ++i) { - if (!strcmp(s, macro->arg_names[i])) - return ¯o->arg_values[i]; + if (!strcmp(s, exp->macro->arg_names[i])) + return &exp->arg_values[i]; } } return NULL; @@ -331,7 +337,7 @@ static void preproc_text_add(struct preproc_text *text, const char *string) } static bool preproc_push_expansion(struct preproc_ctx *ctx, - const struct preproc_text *text, struct preproc_macro *macro) + const struct preproc_text *text, struct preproc_macro *macro, struct preproc_text *arg_values) { struct preproc_expansion *exp; @@ -343,6 +349,7 @@ static bool preproc_push_expansion(struct preproc_ctx *ctx, exp->buffer.lexer_buffer = yy_scan_bytes(text->text.buffer, text->text.content_size, ctx->scanner); exp->buffer.location = text->location; exp->macro = macro; + exp->arg_values = arg_values; TRACE("Expansion stack size is now %zu.\n", ctx->expansion_count); return true; } @@ -543,7 +550,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) if ((expansion = find_arg_expansion(ctx, text))) { - preproc_push_expansion(ctx, expansion, NULL); + preproc_push_expansion(ctx, expansion, NULL, NULL); continue; } @@ -551,7 +558,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) { if (!macro->arg_count) { - preproc_push_expansion(ctx, ¯o->body, macro); + preproc_push_expansion(ctx, ¯o->body, macro, NULL); } else { @@ -617,16 +624,19 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) case STATE_IDENTIFIER: if (token == '(') { - struct preproc_text *first_arg = &func_state->macro->arg_values[0]; - unsigned int i; + struct preproc_text *arg_values; + + if (!(arg_values = calloc(func_state->macro->arg_count, sizeof(*arg_values)))) + return 0; + + for (unsigned int i = 0; i < func_state->macro->arg_count; ++i) + vkd3d_string_buffer_init(&arg_values[i].text); + arg_values[0].location = *lloc; func_state->arg_count = 0; func_state->paren_depth = 1; func_state->state = STATE_ARGS; - for (i = 0; i < func_state->macro->arg_count; ++i) - func_state->macro->arg_values[i].text.content_size = 0; - - first_arg->location = *lloc; + func_state->arg_values = arg_values; } else { @@ -650,7 +660,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) VKD3D_ASSERT(func_state->macro->arg_count); if (func_state->arg_count < func_state->macro->arg_count) - current_arg = &func_state->macro->arg_values[func_state->arg_count]; + current_arg = &func_state->arg_values[func_state->arg_count]; switch (token) { @@ -665,7 +675,7 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) if ((expansion = find_arg_expansion(ctx, text))) { - preproc_push_expansion(ctx, expansion, NULL); + preproc_push_expansion(ctx, expansion, NULL, NULL); continue; } @@ -701,7 +711,8 @@ int yylex(YYSTYPE *lval, YYLTYPE *lloc, yyscan_t scanner) { if (++func_state->arg_count == func_state->macro->arg_count) { - preproc_push_expansion(ctx, &func_state->macro->body, func_state->macro); + preproc_push_expansion(ctx, &func_state->macro->body, + func_state->macro, func_state->arg_values); } else { diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.y b/libs/vkd3d/libs/vkd3d-shader/preproc.y index 366e351e3b5..c6be17bd230 100644 --- a/libs/vkd3d/libs/vkd3d-shader/preproc.y +++ b/libs/vkd3d/libs/vkd3d-shader/preproc.y @@ -91,7 +91,6 @@ bool preproc_add_macro(struct preproc_ctx *ctx, const struct vkd3d_shader_locati size_t arg_count, const struct vkd3d_shader_location *body_loc, struct vkd3d_string_buffer *body) { struct preproc_macro *macro; - unsigned int i; int ret; if ((macro = preproc_find_macro(ctx, name))) @@ -108,14 +107,6 @@ bool preproc_add_macro(struct preproc_ctx *ctx, const struct vkd3d_shader_locati macro->name = name; macro->arg_names = arg_names; macro->arg_count = arg_count; - macro->arg_values = NULL; - if (arg_count && !(macro->arg_values = vkd3d_calloc(arg_count, sizeof(*macro->arg_values)))) - { - vkd3d_free(macro); - return false; - } - for (i = 0; i < arg_count; ++i) - vkd3d_string_buffer_init(¯o->arg_values[i].text); macro->body.text = *body; macro->body.location = *body_loc; ret = rb_put(&ctx->macros, name, ¯o->entry); @@ -129,12 +120,8 @@ void preproc_free_macro(struct preproc_macro *macro) vkd3d_free(macro->name); for (i = 0; i < macro->arg_count; ++i) - { - vkd3d_string_buffer_cleanup(¯o->arg_values[i].text); vkd3d_free(macro->arg_names[i]); - } vkd3d_free(macro->arg_names); - vkd3d_free(macro->arg_values); vkd3d_string_buffer_cleanup(¯o->body.text); vkd3d_free(macro); } diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index 11c054a28f5..cb610c929b6 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -5510,7 +5510,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, const struct shader_signature *shader_signature; const struct vkd3d_spirv_builtin *builtin; enum vkd3d_shader_sysval_semantic sysval; - uint32_t write_mask, reg_write_mask; + uint32_t write_mask; bool use_private_variable = false; struct vkd3d_symbol reg_symbol; SpvStorageClass storage_class; @@ -5561,7 +5561,6 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, use_private_variable = true; } - reg_write_mask = write_mask >> component_idx; vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); if (rb_get(&compiler->symbol_table, ®_symbol)) @@ -5639,7 +5638,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, use_private_variable ? VKD3D_SHADER_COMPONENT_FLOAT : component_type, - use_private_variable ? VKD3DSP_WRITEMASK_ALL : reg_write_mask); + use_private_variable ? VKD3DSP_WRITEMASK_ALL : write_mask); reg_symbol.info.reg.is_aggregate = array_sizes[0] || array_sizes[1]; VKD3D_ASSERT(!builtin || !builtin->spirv_array_size || use_private_variable || array_sizes[0] || array_sizes[1]); @@ -5650,7 +5649,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, if (use_private_variable) { compiler->private_output_variable[element_idx] = var_id; - compiler->private_output_variable_write_mask[element_idx] |= reg_write_mask; + compiler->private_output_variable_write_mask[element_idx] |= write_mask >> component_idx; if (!compiler->epilogue_function_id) compiler->epilogue_function_id = vkd3d_spirv_alloc_id(builder); } @@ -6891,10 +6890,9 @@ static void spirv_compiler_emit_tessellator_partitioning(struct spirv_compiler * spirv_compiler_emit_execution_mode(compiler, mode, NULL, 0); } -static void spirv_compiler_emit_dcl_thread_group(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) +static void spirv_compiler_emit_thread_group_size(struct spirv_compiler *compiler, + const struct vsir_thread_group_size *group_size) { - const struct vkd3d_shader_thread_group_size *group_size = &instruction->declaration.thread_group_size; const uint32_t local_size[] = {group_size->x, group_size->y, group_size->z}; spirv_compiler_emit_execution_mode(compiler, @@ -10228,9 +10226,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, spirv_compiler_emit_tessellator_partitioning(compiler, instruction->declaration.tessellator_partitioning); break; - case VKD3DSIH_DCL_THREAD_GROUP: - spirv_compiler_emit_dcl_thread_group(compiler, instruction); - break; case VKD3DSIH_HS_CONTROL_POINT_PHASE: case VKD3DSIH_HS_FORK_PHASE: case VKD3DSIH_HS_JOIN_PHASE: @@ -10650,6 +10645,8 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct spirv_compiler_emit_temps(compiler, program->temp_count); if (program->ssa_count) spirv_compiler_allocate_ssa_register_ids(compiler, program->ssa_count); + if (compiler->shader_type == VKD3D_SHADER_TYPE_COMPUTE) + spirv_compiler_emit_thread_group_size(compiler, &program->thread_group_size); spirv_compiler_emit_descriptor_declarations(compiler); diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c index 00a525c9ac3..75bdb06fe0e 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -1289,11 +1289,14 @@ static void shader_sm5_read_dcl_hs_max_tessfactor(struct vkd3d_shader_instructio } static void shader_sm5_read_dcl_thread_group(struct vkd3d_shader_instruction *ins, uint32_t opcode, - uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) + uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *sm4) { + struct vsir_program *program = sm4->p.program; + ins->declaration.thread_group_size.x = *tokens++; ins->declaration.thread_group_size.y = *tokens++; ins->declaration.thread_group_size.z = *tokens++; + program->thread_group_size = ins->declaration.thread_group_size; } static void shader_sm5_read_dcl_uav_raw(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token, @@ -2959,7 +2962,7 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con WARN("Failed to validate shader after parsing, ret %d.\n", ret); if (TRACE_ON()) - vkd3d_shader_trace(program); + vsir_program_trace(program); vsir_program_cleanup(program); return ret; diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c index ee8a633431a..9b320106340 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1489,7 +1489,7 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh descriptor_info1, combined_sampler_info, message_context); if (TRACE_ON()) - vkd3d_shader_trace(program); + vsir_program_trace(program); for (i = 0; i < program->instructions.count; ++i) { diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index eab164cc848..1a42f385fc0 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1061,6 +1061,9 @@ enum vkd3d_shader_input_sysval_semantic struct signature_element { + /* sort_index is not a property of the signature element, it is just a + * convenience field used to retain the original order in a signature and + * recover it after having permuted the signature itself. */ unsigned int sort_index; const char *semantic_name; unsigned int semantic_index; @@ -1164,7 +1167,7 @@ struct vkd3d_shader_tgsm_structured bool zero_init; }; -struct vkd3d_shader_thread_group_size +struct vsir_thread_group_size { unsigned int x, y, z; }; @@ -1243,7 +1246,7 @@ struct vkd3d_shader_instruction struct vkd3d_shader_structured_resource structured_resource; struct vkd3d_shader_tgsm_raw tgsm_raw; struct vkd3d_shader_tgsm_structured tgsm_structured; - struct vkd3d_shader_thread_group_size thread_group_size; + struct vsir_thread_group_size thread_group_size; enum vkd3d_tessellator_domain tessellator_domain; enum vkd3d_shader_tessellator_output_primitive tessellator_output_primitive; enum vkd3d_shader_tessellator_partitioning tessellator_partitioning; @@ -1390,6 +1393,7 @@ struct vsir_program bool free_parameters; unsigned int input_control_point_count, output_control_point_count; + struct vsir_thread_group_size thread_group_size; unsigned int flat_constant_count[3]; unsigned int block_count; unsigned int temp_count; @@ -1474,7 +1478,7 @@ struct vkd3d_shader_scan_descriptor_info1 unsigned int descriptor_count; }; -void vkd3d_shader_trace(const struct vsir_program *program); +void vsir_program_trace(const struct vsir_program *program); const char *shader_get_type_prefix(enum vkd3d_shader_type type); -- 2.45.2