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.
This commit is contained in:
Giovanni Mascellani 2024-11-17 23:27:49 +01:00 committed by Henri Verbeet
parent a92b602b33
commit 18e422dfe4
Notes: Henri Verbeet 2024-12-03 14:56:21 +01:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1288
6 changed files with 163 additions and 48 deletions

View File

@ -2547,6 +2547,33 @@ static void trace_signature(const struct shader_signature *signature, const char
vkd3d_string_buffer_cleanup(&buffer); 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) void vsir_program_trace(const struct vsir_program *program)
{ {
const unsigned int flags = VSIR_ASM_FLAG_DUMP_TYPES | VSIR_ASM_FLAG_DUMP_ALL_INDICES; 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->input_signature, "Input");
trace_signature(&program->output_signature, "Output"); trace_signature(&program->output_signature, "Output");
trace_signature(&program->patch_constant_signature, "Patch-constant"); trace_signature(&program->patch_constant_signature, "Patch-constant");
trace_io_declarations(program);
if (d3d_asm_compile(program, NULL, &code, flags) != VKD3D_OK) if (d3d_asm_compile(program, NULL, &code, flags) != VKD3D_OK)
return; return;

View File

@ -1507,12 +1507,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen,
case VKD3DSIH_DCL_INDEXABLE_TEMP: case VKD3DSIH_DCL_INDEXABLE_TEMP:
shader_glsl_dcl_indexable_temp(gen, ins); shader_glsl_dcl_indexable_temp(gen, ins);
break; break;
case VKD3DSIH_DCL_INPUT:
case VKD3DSIH_DCL_INPUT_PS:
case VKD3DSIH_DCL_INPUT_PS_SGV: case VKD3DSIH_DCL_INPUT_PS_SGV:
case VKD3DSIH_DCL_INPUT_PS_SIV: case VKD3DSIH_DCL_INPUT_PS_SIV:
case VKD3DSIH_DCL_INPUT_SGV: case VKD3DSIH_DCL_INPUT_SGV:
case VKD3DSIH_DCL_OUTPUT:
case VKD3DSIH_DCL_OUTPUT_SIV: case VKD3DSIH_DCL_OUTPUT_SIV:
case VKD3DSIH_NOP: case VKD3DSIH_NOP:
break; break;

View File

@ -7143,6 +7143,89 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro
return VKD3D_OK; 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 validation_context
{ {
struct vkd3d_shader_message_context *message_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->output_signature, SIGNATURE_TYPE_OUTPUT);
vsir_validate_signature(&ctx, &program->patch_constant_signature, SIGNATURE_TYPE_PATCH_CONSTANT); 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)))) if (!(ctx.temps = vkd3d_calloc(ctx.program->temp_count, sizeof(*ctx.temps))))
goto fail; 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_fragment_fog);
vsir_transform(&ctx, vsir_program_insert_vertex_fog); vsir_transform(&ctx, vsir_program_insert_vertex_fog);
vsir_transform(&ctx, vsir_program_remove_io_decls);
if (TRACE_ON()) if (TRACE_ON())
vsir_program_trace(program); vsir_program_trace(program);

View File

@ -513,8 +513,6 @@ static void msl_handle_instruction(struct msl_generator *gen, const struct vkd3d
case VKD3DSIH_AND: case VKD3DSIH_AND:
msl_binop(gen, ins, "&"); msl_binop(gen, ins, "&");
break; break;
case VKD3DSIH_DCL_INPUT:
case VKD3DSIH_DCL_OUTPUT:
case VKD3DSIH_DCL_OUTPUT_SIV: case VKD3DSIH_DCL_OUTPUT_SIV:
case VKD3DSIH_NOP: case VKD3DSIH_NOP:
break; break;

View File

@ -5801,16 +5801,6 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler *
compiler->epilogue_function_id = 0; 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) static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *compiler)
{ {
const struct vkd3d_shader_transform_feedback_info *xfb_info = compiler->xfb_info; 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; break;
case VKD3D_SHADER_TYPE_HULL: case VKD3D_SHADER_TYPE_HULL:
vkd3d_spirv_set_execution_model(builder, SpvExecutionModelTessellationControl); vkd3d_spirv_set_execution_model(builder, SpvExecutionModelTessellationControl);
spirv_compiler_emit_hull_shader_builtins(compiler);
break; break;
case VKD3D_SHADER_TYPE_DOMAIN: case VKD3D_SHADER_TYPE_DOMAIN:
vkd3d_spirv_set_execution_model(builder, SpvExecutionModelTessellationEvaluation); 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); 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, static void spirv_compiler_emit_dcl_stream(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction) 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: case VKD3DSIH_DCL_TGSM_STRUCTURED:
spirv_compiler_emit_dcl_tgsm_structured(compiler, instruction); spirv_compiler_emit_dcl_tgsm_structured(compiler, instruction);
break; 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: case VKD3DSIH_DCL_STREAM:
spirv_compiler_emit_dcl_stream(compiler, instruction); spirv_compiler_emit_dcl_stream(compiler, instruction);
break; 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) 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) for (unsigned int i = 0; i < compiler->input_signature.element_count; ++i)
spirv_compiler_emit_input(compiler, VKD3DSPR_INPUT, 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) if (compiler->program->has_point_size)
{ {
struct vkd3d_shader_dst_param dst;
vsir_dst_param_init(&dst, VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1); vsir_dst_param_init(&dst, VKD3DSPR_RASTOUT, VKD3D_DATA_FLOAT, 1);
dst.reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; dst.reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE;
spirv_compiler_emit_io_register(compiler, &dst); 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) if (compiler->program->has_point_coord)
{ {
struct vkd3d_shader_dst_param dst;
vsir_dst_param_init(&dst, VKD3DSPR_POINT_COORD, VKD3D_DATA_FLOAT, 0); vsir_dst_param_init(&dst, VKD3DSPR_POINT_COORD, VKD3D_DATA_FLOAT, 0);
spirv_compiler_emit_io_register(compiler, &dst); 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) static void spirv_compiler_emit_descriptor_declarations(struct spirv_compiler *compiler)

View File

@ -1433,6 +1433,7 @@ struct vsir_program
enum vsir_control_flow_type cf_type; enum vsir_control_flow_type cf_type;
enum vsir_normalisation_level normalisation_level; enum vsir_normalisation_level normalisation_level;
enum vkd3d_tessellator_domain tess_domain; enum vkd3d_tessellator_domain tess_domain;
uint32_t io_dcls[VKD3D_BITMAP_SIZE(VKD3DSPR_COUNT)];
const char **block_names; const char **block_names;
size_t block_name_count; size_t block_name_count;