vkd3d-shader/ir: Include an initial label instruction in the first control flow block.

This commit is contained in:
Conor McCarthy 2024-01-12 13:20:32 +10:00 committed by Alexandre Julliard
parent d402804851
commit 559d9d4ee0
Notes: Alexandre Julliard 2024-01-17 22:42:55 +01:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/450
5 changed files with 84 additions and 26 deletions

View File

@ -4869,6 +4869,18 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st
return VKD3D_OK;
}
static void sm6_parser_emit_label(struct sm6_parser *sm6, unsigned int label_id)
{
struct vkd3d_shader_src_param *src_param;
struct vkd3d_shader_instruction *ins;
ins = sm6_parser_add_instruction(sm6, VKD3DSIH_LABEL);
if (!(src_param = instruction_src_params_alloc(ins, 1, sm6)))
return;
vsir_src_param_init_label(src_param, label_id);
}
static bool sm6_parser_allocate_named_metadata(struct sm6_parser *sm6)
{
struct dxil_block *block;
@ -6217,6 +6229,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
}
sm6->p.shader_desc.ssa_count = sm6->ssa_next_id;
sm6->p.shader_desc.block_count = 1;
if (!(fn = sm6_parser_get_function(sm6, sm6->entry_point)))
{
@ -6227,6 +6240,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t
}
assert(sm6->function_count == 1);
sm6_parser_emit_label(sm6, 1);
if (!sm6_block_emit_instructions(fn->blocks[0], sm6))
{
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,

View File

@ -320,7 +320,7 @@ static void vsir_src_param_init(struct vkd3d_shader_src_param *param, enum vkd3d
param->modifiers = VKD3DSPSM_NONE;
}
static void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id)
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);
param->reg.dimension = VSIR_DIMENSION_NONE;
@ -1785,18 +1785,27 @@ static void VKD3D_PRINTF_FUNC(3, 4) cf_flattener_create_block_name(struct cf_fla
flattener->block_names[block_id] = buffer.buffer;
}
static bool vsir_instruction_is_dcl(const struct vkd3d_shader_instruction *instruction)
{
enum vkd3d_shader_opcode handler_idx = instruction->handler_idx;
return (VKD3DSIH_DCL <= handler_idx && handler_idx <= VKD3DSIH_DCL_VERTICES_OUT)
|| handler_idx == VKD3DSIH_HS_DECLS;
}
static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flattener *flattener)
{
bool main_block_open, is_hull_shader, after_declarations_section;
struct vkd3d_shader_parser *parser = flattener->parser;
struct vkd3d_shader_instruction_array *instructions;
struct vkd3d_shader_instruction *dst_ins;
bool main_block_open;
size_t i;
instructions = &parser->instructions;
main_block_open = parser->shader_version.type != VKD3D_SHADER_TYPE_HULL;
is_hull_shader = parser->shader_version.type == VKD3D_SHADER_TYPE_HULL;
main_block_open = !is_hull_shader;
after_declarations_section = is_hull_shader;
if (!cf_flattener_require_space(flattener, instructions->count))
if (!cf_flattener_require_space(flattener, instructions->count + 1))
return VKD3D_ERROR_OUT_OF_MEMORY;
for (i = 0; i < instructions->count; ++i)
@ -1808,11 +1817,29 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte
flattener->location = instruction->location;
/* Declarations should occur before the first code block, which in hull shaders is marked by the first
* phase instruction, and in all other shader types begins with the first label instruction. */
if (!after_declarations_section && !vsir_instruction_is_dcl(instruction)
&& instruction->handler_idx != VKD3DSIH_NOP)
{
after_declarations_section = true;
cf_flattener_emit_label(flattener, cf_flattener_alloc_block_id(flattener));
}
cf_info = flattener->control_flow_depth
? &flattener->control_flow_info[flattener->control_flow_depth - 1] : NULL;
switch (instruction->handler_idx)
{
case VKD3DSIH_HS_CONTROL_POINT_PHASE:
case VKD3DSIH_HS_FORK_PHASE:
case VKD3DSIH_HS_JOIN_PHASE:
if (!cf_flattener_copy_instruction(flattener, instruction))
return VKD3D_ERROR_OUT_OF_MEMORY;
if (instruction->handler_idx != VKD3DSIH_HS_CONTROL_POINT_PHASE || !instruction->flags)
after_declarations_section = false;
break;
case VKD3DSIH_LABEL:
vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
"Aborting due to not yet implemented feature: Label instruction.");

View File

@ -1871,8 +1871,6 @@ static void vkd3d_spirv_builder_begin_main_function(struct vkd3d_spirv_builder *
vkd3d_spirv_build_op_function(builder, void_id,
builder->main_function_id, SpvFunctionControlMaskNone, function_type_id);
vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder));
builder->main_function_location = vkd3d_spirv_stream_current_location(&builder->function_stream);
}
static void vkd3d_spirv_builder_free(struct vkd3d_spirv_builder *builder)
@ -2314,7 +2312,7 @@ struct spirv_compiler
struct vkd3d_push_constant_buffer_binding *push_constants;
const struct vkd3d_shader_spirv_target_info *spirv_target_info;
bool after_declarations_section;
bool prolog_emitted;
struct shader_signature input_signature;
struct shader_signature output_signature;
struct shader_signature patch_constant_signature;
@ -2381,6 +2379,8 @@ static bool is_in_fork_or_join_phase(const struct spirv_compiler *compiler)
static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *compiler);
static size_t spirv_compiler_get_current_function_location(struct spirv_compiler *compiler);
static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler);
static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler);
static const char *spirv_compiler_get_entry_point_name(const struct spirv_compiler *compiler)
{
@ -6498,20 +6498,45 @@ static void spirv_compiler_enter_shader_phase(struct spirv_compiler *compiler,
vkd3d_spirv_build_op_function(builder, void_id, function_id,
SpvFunctionControlMaskNone, function_type_id);
vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder));
compiler->phase = instruction->handler_idx;
spirv_compiler_emit_shader_phase_name(compiler, function_id, NULL);
phase = (instruction->handler_idx == VKD3DSIH_HS_CONTROL_POINT_PHASE)
? &compiler->control_point_phase : &compiler->patch_constant_phase;
phase->function_id = function_id;
phase->function_location = vkd3d_spirv_stream_current_location(&builder->function_stream);
/* The insertion location must be set after the label is emitted. */
phase->function_location = 0;
if (instruction->handler_idx == VKD3DSIH_HS_CONTROL_POINT_PHASE)
compiler->emit_default_control_point_phase = instruction->flags;
}
static void spirv_compiler_initialise_block(struct spirv_compiler *compiler)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
/* Insertion locations must point immediately after the function's initial label. */
if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL)
{
struct vkd3d_shader_phase *phase = (compiler->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE)
? &compiler->control_point_phase : &compiler->patch_constant_phase;
if (!phase->function_location)
phase->function_location = vkd3d_spirv_stream_current_location(&builder->function_stream);
}
else if (!builder->main_function_location)
{
builder->main_function_location = vkd3d_spirv_stream_current_location(&builder->function_stream);
}
/* I/O declarations can result in emission of fixups, which must occur after the initial label. */
if (!compiler->prolog_emitted)
{
spirv_compiler_emit_main_prolog(compiler);
spirv_compiler_emit_io_declarations(compiler);
compiler->prolog_emitted = true;
}
}
static void spirv_compiler_emit_default_control_point_phase(struct spirv_compiler *compiler)
{
const struct shader_signature *output_signature = &compiler->output_signature;
@ -6524,6 +6549,8 @@ static void spirv_compiler_emit_default_control_point_phase(struct spirv_compile
unsigned int component_count;
unsigned int i;
vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder));
spirv_compiler_initialise_block(compiler);
invocation_id = spirv_compiler_emit_load_invocation_id(compiler);
memset(&invocation, 0, sizeof(invocation));
@ -6622,6 +6649,7 @@ static void spirv_compiler_emit_hull_shader_main(struct spirv_compiler *compiler
memset(compiler->descriptor_offset_ids, 0, compiler->offset_info.descriptor_table_count
* sizeof(*compiler->descriptor_offset_ids));
vkd3d_spirv_builder_begin_main_function(builder);
vkd3d_spirv_build_op_label(builder, vkd3d_spirv_alloc_id(builder));
void_id = vkd3d_spirv_get_op_type_void(builder);
@ -7589,6 +7617,8 @@ static void spirv_compiler_emit_label(struct spirv_compiler *compiler,
--block_id;
if (block_id < compiler->block_name_count && compiler->block_names[block_id])
vkd3d_spirv_build_op_name(builder, label_id, compiler->block_names[block_id]);
spirv_compiler_initialise_block(compiler);
}
static void spirv_compiler_emit_merge(struct spirv_compiler *compiler,
@ -9228,23 +9258,11 @@ static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler)
spirv_compiler_emit_point_size(compiler);
}
static bool is_dcl_instruction(enum vkd3d_shader_opcode handler_idx)
{
return (VKD3DSIH_DCL <= handler_idx && handler_idx <= VKD3DSIH_DCL_VERTICES_OUT)
|| handler_idx == VKD3DSIH_HS_DECLS;
}
static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler,
const struct vkd3d_shader_instruction *instruction)
{
int ret = VKD3D_OK;
if (!is_dcl_instruction(instruction->handler_idx) && !compiler->after_declarations_section)
{
compiler->after_declarations_section = true;
spirv_compiler_emit_main_prolog(compiler);
}
switch (instruction->handler_idx)
{
case VKD3DSIH_DCL_GLOBAL_FLAGS:
@ -9692,8 +9710,6 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL)
spirv_compiler_emit_shader_signature_outputs(compiler);
spirv_compiler_emit_io_declarations(compiler);
for (i = 0; i < instructions.count && result >= 0; ++i)
{
compiler->location.line = i + 1;

View File

@ -1117,8 +1117,7 @@ static void shader_sm4_read_dcl_indexable_temp(struct vkd3d_shader_instruction *
ins->declaration.indexable_temp.alignment = 0;
ins->declaration.indexable_temp.data_type = VKD3D_DATA_FLOAT;
ins->declaration.indexable_temp.component_count = *tokens;
/* Indexable temp declarations are global, but except for hull shaders the backend currently emits them within a function. */
ins->declaration.indexable_temp.has_function_scope = priv->p.shader_version.type != VKD3D_SHADER_TYPE_HULL;
ins->declaration.indexable_temp.has_function_scope = false;
}
static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *ins, uint32_t opcode,

View File

@ -886,6 +886,8 @@ struct vkd3d_shader_src_param
enum vkd3d_shader_src_modifier modifiers;
};
void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id);
struct vkd3d_shader_index_range
{
struct vkd3d_shader_dst_param dst;