From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 14 ++++++++++ libs/vkd3d-shader/ir.c | 33 +++++++++++++++++++++--- libs/vkd3d-shader/spirv.c | 33 +++++++++++++++++++----- libs/vkd3d-shader/vkd3d_shader_private.h | 2 ++ 4 files changed, 71 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index c744dfced..3b667833e 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -4868,6 +4868,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; @@ -6216,6 +6228,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))) { @@ -6226,6 +6239,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, diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index cddfd0525..6eb25ef69 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -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; @@ -1574,6 +1574,7 @@ struct cf_flattener const char **block_names; size_t block_name_capacity; size_t block_name_count; + bool after_declarations_section;
unsigned int branch_id; unsigned int loop_id; @@ -1785,18 +1786,28 @@ 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; + /* Indexable temps must be emitted after the initial label. All other declarations + * are emitted earlier to make the trace output appear more logical. */ + return (VKD3DSIH_DCL <= handler_idx && handler_idx <= VKD3DSIH_DCL_VERTICES_OUT + && handler_idx != VKD3DSIH_DCL_INDEXABLE_TEMP) || handler_idx == VKD3DSIH_HS_DECLS; +} + static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flattener *flattener) { struct vkd3d_shader_parser *parser = flattener->parser; struct vkd3d_shader_instruction_array *instructions; struct vkd3d_shader_instruction *dst_ins; - bool main_block_open; + bool main_block_open, is_hull_shader; 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;
- 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 +1819,25 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte
flattener->location = instruction->location;
+ if (!is_hull_shader && !flattener->after_declarations_section && !vsir_instruction_is_dcl(instruction)) + { + flattener->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; + cf_flattener_emit_label(flattener, cf_flattener_alloc_block_id(flattener)); + break; + case VKD3DSIH_LABEL: vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, "Aborting due to not yet implemented feature: Label instruction."); diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 40f6584f9..2501c325c 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1862,8 +1862,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) @@ -2306,6 +2304,7 @@ struct spirv_compiler const struct vkd3d_shader_spirv_target_info *spirv_target_info;
bool after_declarations_section; + bool io_declared; struct shader_signature input_signature; struct shader_signature output_signature; struct shader_signature patch_constant_signature; @@ -2370,6 +2369,7 @@ 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_io_declarations(struct spirv_compiler *compiler);
static const char *spirv_compiler_get_entry_point_name(const struct spirv_compiler *compiler) { @@ -6482,15 +6482,14 @@ 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; @@ -6606,6 +6605,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);
@@ -7568,6 +7568,27 @@ 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]); + + /* 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. + * TODO: emit fixups in the IR? */ + if (!compiler->io_declared) + { + spirv_compiler_emit_io_declarations(compiler); + compiler->io_declared = true; + } }
static void spirv_compiler_emit_merge(struct spirv_compiler *compiler, @@ -9672,8 +9693,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; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 81c5a0ca7..b42090472 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -884,6 +884,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;