From 18e422dfe4de22b9ac865821b27f0a98fcd03c23 Mon Sep 17 00:00:00 2001 From: Giovanni Mascellani Date: Sun, 17 Nov 2024 23:27:49 +0100 Subject: [PATCH] vkd3d-shader/ir: Encode I/O declarations in vsir_program. Most I/O registers are already described by the shader signatures. The registers that are not do not have any property other then being used by the program or not, so they can be collectively described with a bitmap. --- libs/vkd3d-shader/d3d_asm.c | 28 ++++++ libs/vkd3d-shader/glsl.c | 3 - libs/vkd3d-shader/ir.c | 120 +++++++++++++++++++++++ libs/vkd3d-shader/msl.c | 2 - libs/vkd3d-shader/spirv.c | 57 +++-------- libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 6 files changed, 163 insertions(+), 48 deletions(-) diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 7c5444f6..f008770a 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -2547,6 +2547,33 @@ static void trace_signature(const struct shader_signature *signature, const char vkd3d_string_buffer_cleanup(&buffer); } +static void trace_io_declarations(const struct vsir_program *program) +{ + struct vkd3d_string_buffer buffer; + bool empty = true; + unsigned int i; + + vkd3d_string_buffer_init(&buffer); + + vkd3d_string_buffer_printf(&buffer, "Input/output declarations:"); + + for (i = 0; i < sizeof(program->io_dcls) * CHAR_BIT; ++i) + { + if (bitmap_is_set(program->io_dcls, i)) + { + empty = false; + vkd3d_string_buffer_printf(&buffer, " %u", i); + } + } + + if (empty) + vkd3d_string_buffer_printf(&buffer, " empty"); + + 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; @@ -2556,6 +2583,7 @@ void vsir_program_trace(const struct vsir_program *program) trace_signature(&program->input_signature, "Input"); trace_signature(&program->output_signature, "Output"); trace_signature(&program->patch_constant_signature, "Patch-constant"); + trace_io_declarations(program); if (d3d_asm_compile(program, NULL, &code, flags) != VKD3D_OK) return; diff --git a/libs/vkd3d-shader/glsl.c b/libs/vkd3d-shader/glsl.c index 0df0e30f..ad834613 100644 --- a/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d-shader/glsl.c @@ -1507,12 +1507,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, 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_SGV: case VKD3DSIH_DCL_INPUT_PS_SIV: case VKD3DSIH_DCL_INPUT_SGV: - case VKD3DSIH_DCL_OUTPUT: case VKD3DSIH_DCL_OUTPUT_SIV: case VKD3DSIH_NOP: break; diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 53b26dac..8a8fe6a7 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -7143,6 +7143,89 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro return VKD3D_OK; } +static enum vkd3d_result vsir_program_remove_io_decls(struct vsir_program *program, + struct vsir_transformation_context *ctx) +{ + enum vkd3d_result ret = VKD3D_OK; + size_t i; + + for (i = 0; i < program->instructions.count; ++i) + { + struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; + + if (ins->opcode == VKD3DSIH_DCL_INPUT || ins->opcode == VKD3DSIH_DCL_INPUT_PS) + { + switch (ins->declaration.dst.reg.type) + { + case VKD3DSPR_INPUT: + case VKD3DSPR_OUTPUT: + case VKD3DSPR_PATCHCONST: + case VKD3DSPR_INCONTROLPOINT: + case VKD3DSPR_OUTCONTROLPOINT: + break; + + case VKD3DSPR_PRIMID: + case VKD3DSPR_FORKINSTID: + case VKD3DSPR_JOININSTID: + case VKD3DSPR_THREADID: + case VKD3DSPR_THREADGROUPID: + case VKD3DSPR_LOCALTHREADID: + case VKD3DSPR_LOCALTHREADINDEX: + case VKD3DSPR_COVERAGE: + case VKD3DSPR_TESSCOORD: + case VKD3DSPR_OUTPOINTID: + case VKD3DSPR_GSINSTID: + case VKD3DSPR_WAVELANECOUNT: + case VKD3DSPR_WAVELANEINDEX: + bitmap_set(program->io_dcls, ins->declaration.dst.reg.type); + break; + + default: + vkd3d_shader_error(ctx->message_context, &ins->location, + VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, + "Internal compiler error: invalid register type %#x for input declaration.", + ins->declaration.dst.reg.type); + ret = VKD3D_ERROR; + break; + } + + vkd3d_shader_instruction_make_nop(ins); + } + else if (ins->opcode == VKD3DSIH_DCL_OUTPUT) + { + switch (ins->declaration.dst.reg.type) + { + case VKD3DSPR_INPUT: + case VKD3DSPR_OUTPUT: + case VKD3DSPR_PATCHCONST: + case VKD3DSPR_INCONTROLPOINT: + case VKD3DSPR_OUTCONTROLPOINT: + break; + + case VKD3DSPR_DEPTHOUT: + case VKD3DSPR_SAMPLEMASK: + case VKD3DSPR_DEPTHOUTGE: + case VKD3DSPR_DEPTHOUTLE: + case VKD3DSPR_OUTSTENCILREF: + bitmap_set(program->io_dcls, ins->declaration.dst.reg.type); + break; + + default: + vkd3d_shader_error(ctx->message_context, &ins->location, + VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, + "Internal compiler error: invalid register type %#x for output declaration.", + ins->declaration.dst.reg.type); + ret = VKD3D_ERROR; + break; + } + + vkd3d_shader_instruction_make_nop(ins); + } + } + + return ret; +} + struct validation_context { struct vkd3d_shader_message_context *message_context; @@ -9139,6 +9222,41 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c vsir_validate_signature(&ctx, &program->output_signature, SIGNATURE_TYPE_OUTPUT); vsir_validate_signature(&ctx, &program->patch_constant_signature, SIGNATURE_TYPE_PATCH_CONSTANT); + for (i = 0; i < sizeof(program->io_dcls) * CHAR_BIT; ++i) + { + if (!bitmap_is_set(program->io_dcls, i)) + continue; + + switch (i) + { + /* Input registers */ + case VKD3DSPR_PRIMID: + case VKD3DSPR_FORKINSTID: + case VKD3DSPR_JOININSTID: + case VKD3DSPR_THREADID: + case VKD3DSPR_THREADGROUPID: + case VKD3DSPR_LOCALTHREADID: + case VKD3DSPR_LOCALTHREADINDEX: + case VKD3DSPR_COVERAGE: + case VKD3DSPR_TESSCOORD: + case VKD3DSPR_OUTPOINTID: + case VKD3DSPR_GSINSTID: + case VKD3DSPR_WAVELANECOUNT: + case VKD3DSPR_WAVELANEINDEX: + /* Output registers */ + case VKD3DSPR_DEPTHOUT: + case VKD3DSPR_SAMPLEMASK: + case VKD3DSPR_DEPTHOUTGE: + case VKD3DSPR_DEPTHOUTLE: + case VKD3DSPR_OUTSTENCILREF: + break; + + default: + validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "Invalid input/output declaration %u.", i); + } + } + if (!(ctx.temps = vkd3d_calloc(ctx.program->temp_count, sizeof(*ctx.temps)))) goto fail; @@ -9290,6 +9408,8 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t vsir_transform(&ctx, vsir_program_insert_fragment_fog); vsir_transform(&ctx, vsir_program_insert_vertex_fog); + vsir_transform(&ctx, vsir_program_remove_io_decls); + if (TRACE_ON()) vsir_program_trace(program); diff --git a/libs/vkd3d-shader/msl.c b/libs/vkd3d-shader/msl.c index 9a3c3ed8..76eaef47 100644 --- a/libs/vkd3d-shader/msl.c +++ b/libs/vkd3d-shader/msl.c @@ -513,8 +513,6 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d case VKD3DSIH_AND: msl_binop(gen, ins, "&"); break; - case VKD3DSIH_DCL_INPUT: - case VKD3DSIH_DCL_OUTPUT: case VKD3DSIH_DCL_OUTPUT_SIV: case VKD3DSIH_NOP: break; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 2765997c..cac76e69 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -5801,16 +5801,6 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler * compiler->epilogue_function_id = 0; } -static void spirv_compiler_emit_hull_shader_builtins(struct spirv_compiler *compiler) -{ - struct vkd3d_shader_dst_param dst; - - memset(&dst, 0, sizeof(dst)); - vsir_register_init(&dst.reg, VKD3DSPR_OUTPOINTID, VKD3D_DATA_FLOAT, 0); - dst.write_mask = VKD3DSP_WRITEMASK_0; - spirv_compiler_emit_io_register(compiler, &dst); -} - static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *compiler) { const struct vkd3d_shader_transform_feedback_info *xfb_info = compiler->xfb_info; @@ -5823,7 +5813,6 @@ static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *comp break; case VKD3D_SHADER_TYPE_HULL: vkd3d_spirv_set_execution_model(builder, SpvExecutionModelTessellationControl); - spirv_compiler_emit_hull_shader_builtins(compiler); break; case VKD3D_SHADER_TYPE_DOMAIN: vkd3d_spirv_set_execution_model(builder, SpvExecutionModelTessellationEvaluation); @@ -6643,27 +6632,6 @@ static void spirv_compiler_emit_dcl_tgsm_structured(struct spirv_compiler *compi tgsm_structured->structure_count * stride, stride, tgsm_structured->zero_init); } -static void spirv_compiler_emit_dcl_input(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) -{ - const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst; - - /* INPUT and PATCHCONST are handled in spirv_compiler_emit_io_declarations(). - * OUTPOINTID is handled in spirv_compiler_emit_hull_shader_builtins(). */ - if (dst->reg.type != VKD3DSPR_INPUT && dst->reg.type != VKD3DSPR_PATCHCONST - && dst->reg.type != VKD3DSPR_OUTPOINTID) - spirv_compiler_emit_io_register(compiler, dst); -} - -static void spirv_compiler_emit_dcl_output(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) -{ - const struct vkd3d_shader_dst_param *dst = &instruction->declaration.dst; - - if (dst->reg.type != VKD3DSPR_OUTPUT && dst->reg.type != VKD3DSPR_PATCHCONST) - spirv_compiler_emit_io_register(compiler, dst); -} - static void spirv_compiler_emit_dcl_stream(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { @@ -10089,13 +10057,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_DCL_TGSM_STRUCTURED: spirv_compiler_emit_dcl_tgsm_structured(compiler, instruction); break; - case VKD3DSIH_DCL_INPUT_PS: - case VKD3DSIH_DCL_INPUT: - spirv_compiler_emit_dcl_input(compiler, instruction); - break; - case VKD3DSIH_DCL_OUTPUT: - spirv_compiler_emit_dcl_output(compiler, instruction); - break; case VKD3DSIH_DCL_STREAM: spirv_compiler_emit_dcl_stream(compiler, instruction); break; @@ -10458,6 +10419,8 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) { + struct vkd3d_shader_dst_param dst; + for (unsigned int i = 0; i < compiler->input_signature.element_count; ++i) spirv_compiler_emit_input(compiler, VKD3DSPR_INPUT, i); @@ -10481,8 +10444,6 @@ static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) if (compiler->program->has_point_size) { - struct vkd3d_shader_dst_param dst; - vsir_dst_param_init(&dst, VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); dst.reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; spirv_compiler_emit_io_register(compiler, &dst); @@ -10490,11 +10451,21 @@ static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) if (compiler->program->has_point_coord) { - struct vkd3d_shader_dst_param dst; - vsir_dst_param_init(&dst, VKD3DSPR_POINT_COORD, VKD3D_DATA_FLOAT, 0); spirv_compiler_emit_io_register(compiler, &dst); } + + for (unsigned int i = 0; i < sizeof(compiler->program->io_dcls) * CHAR_BIT; ++i) + { + /* For hull shaders we internally generate references to OUTPOINTID, + * so that must always be enabled. */ + if (bitmap_is_set(compiler->program->io_dcls, i) + || (compiler->program->shader_version.type == VKD3D_SHADER_TYPE_HULL && i == VKD3DSPR_OUTPOINTID)) + { + vsir_dst_param_init(&dst, i, VKD3D_DATA_FLOAT, 0); + spirv_compiler_emit_io_register(compiler, &dst); + } + } } static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *compiler) diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 4c9795e4..09e0e66c 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1433,6 +1433,7 @@ struct vsir_program enum vsir_control_flow_type cf_type; enum vsir_normalisation_level normalisation_level; enum vkd3d_tessellator_domain tess_domain; + uint32_t io_dcls[VKD3D_BITMAP_SIZE(VKD3DSPR_COUNT)]; const char **block_names; size_t block_name_count;