-- v4: vkd3d-shader/spirv: Emit line numbers if debugging info is not stripped. vkd3d-compiler: Add a command line option for instruction numbering. vkd3d-shader/d3d-asm: Enable instruction numbering for trace output.
From: Conor McCarthy cmccarthy@codeweavers.com
--- include/vkd3d_shader.h | 1 + libs/vkd3d-shader/d3d_asm.c | 6 ++++++ 2 files changed, 7 insertions(+)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 2f4478a79..b4a68df53 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -147,6 +147,7 @@ enum vkd3d_shader_compile_option_formatting_flags VKD3D_SHADER_COMPILE_OPTION_FORMATTING_OFFSETS = 0x00000004, VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER = 0x00000008, VKD3D_SHADER_COMPILE_OPTION_FORMATTING_RAW_IDS = 0x00000010, + VKD3D_SHADER_COMPILE_OPTION_FORMATTING_NUMBERS = 0x00000020,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_FORMATTING_FLAGS), }; diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index dd96b7fa5..bfe6ef1c7 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -2097,6 +2097,9 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, buffer = &compiler.buffer; vkd3d_string_buffer_init(buffer);
+ if (formatting & VKD3D_SHADER_COMPILE_OPTION_FORMATTING_NUMBERS) + vkd3d_string_buffer_printf(buffer, " "); + compiler.shader_version = *shader_version; shader_version = &compiler.shader_version; vkd3d_string_buffer_printf(buffer, "%s%s_%u_%u%s\n", compiler.colours.version, @@ -2108,6 +2111,9 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, { struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
+ if (formatting & VKD3D_SHADER_COMPILE_OPTION_FORMATTING_NUMBERS) + vkd3d_string_buffer_printf(buffer, "%4u: ", i + 1); + switch (ins->handler_idx) { case VKD3DSIH_ELSE:
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/d3d_asm.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index bfe6ef1c7..f4c91438a 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -2074,6 +2074,8 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program,
formatting = VKD3D_SHADER_COMPILE_OPTION_FORMATTING_INDENT | VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER; + if (dialect == VSIR_ASM_VSIR) + formatting |= VKD3D_SHADER_COMPILE_OPTION_FORMATTING_NUMBERS; if (compile_info) { for (i = 0; i < compile_info->option_count; ++i)
From: Conor McCarthy cmccarthy@codeweavers.com
--- programs/vkd3d-compiler/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/programs/vkd3d-compiler/main.c b/programs/vkd3d-compiler/main.c index 4aa368b04..6c4a62884 100644 --- a/programs/vkd3d-compiler/main.c +++ b/programs/vkd3d-compiler/main.c @@ -191,8 +191,9 @@ static void print_usage(const char *program_name) " --formatting=<flags> Specify the formatting options for text output.\n" " <flags> is a comma separated list of formatting flags,\n" " optionally prefixed by '+' or '-'. Valid flags are\n" - " 'colour', 'indent', 'offsets', 'header', and 'raw-ids'.\n" - " The 'indent' and 'header' flags are enabled by default.\n" + " 'colour', 'indent', 'offsets', 'header', 'raw-ids' and\n" + " 'numbers'. The 'indent' and 'header' flags are enabled\n" + " by default.\n" " --fragment-coordinate-origin=<origin>\n" " Specify the origin of fragment coordinates for SPIR-V\n" " targets. Valid values are 'upper-left' (default) and\n" @@ -305,6 +306,7 @@ static bool parse_formatting(uint32_t *formatting, bool *colour, char *arg) {"offsets", VKD3D_SHADER_COMPILE_OPTION_FORMATTING_OFFSETS}, {"header", VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER}, {"raw-ids", VKD3D_SHADER_COMPILE_OPTION_FORMATTING_RAW_IDS}, + {"numbers", VKD3D_SHADER_COMPILE_OPTION_FORMATTING_NUMBERS}, }; char *tok;
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/ir.c | 7 ------- libs/vkd3d-shader/spirv.c | 13 +++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 7 +++++++ 3 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 56e8d974d..78b724648 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -39,13 +39,6 @@ static inline bool shader_register_is_phase_instance_id(const struct vkd3d_shade return reg->type == VKD3DSPR_FORKINSTID || reg->type == VKD3DSPR_JOININSTID; }
-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 void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *ins) { struct vkd3d_shader_location location = ins->location; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 298ad31d9..2e05a8d13 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -362,6 +362,7 @@ struct vkd3d_spirv_builder uint32_t invocation_count; SpvExecutionModel execution_model;
+ uint32_t file_string_id; uint32_t current_id; uint32_t main_function_id; struct rb_tree declarations; @@ -930,6 +931,11 @@ static void vkd3d_spirv_build_op_name(struct vkd3d_spirv_builder *builder, vkd3d_spirv_build_string(stream, name, name_size); }
+static void vkd3d_spirv_build_op_line(struct vkd3d_spirv_builder *builder, uint32_t line_number) +{ + vkd3d_spirv_build_op3(&builder->function_stream, SpvOpLine, builder->file_string_id, line_number, 0); +} + static void vkd3d_spirv_build_op_member_name(struct vkd3d_spirv_builder *builder, uint32_t type_id, uint32_t member, const char *fmt, ...) { @@ -1877,6 +1883,10 @@ static void vkd3d_spirv_builder_init(struct vkd3d_spirv_builder *builder, const
rb_init(&builder->declarations, vkd3d_spirv_declaration_compare);
+ /* OpString must appear before other declarations such as names. The source name is + * not particularly useful here, if one is available at all, so emit an empty string. */ + builder->file_string_id = vkd3d_spirv_build_op_r1(builder, &builder->debug_stream, SpvOpString, 0); + builder->main_function_id = vkd3d_spirv_alloc_id(builder); vkd3d_spirv_build_op_name(builder, builder->main_function_id, "%s", entry_point); } @@ -9448,6 +9458,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, { int ret = VKD3D_OK;
+ if (!compiler->strip_debug && !vsir_instruction_is_dcl(instruction) && instruction->handler_idx != VKD3DSIH_NOP) + vkd3d_spirv_build_op_line(&compiler->spirv_builder, compiler->location.line); + switch (instruction->handler_idx) { case VKD3DSIH_DCL_GLOBAL_FLAGS: diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index e5f706e95..85263fa49 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1189,6 +1189,13 @@ static inline bool vkd3d_shader_instruction_has_texel_offset(const struct vkd3d_ return ins->texel_offset.u || ins->texel_offset.v || ins->texel_offset.w; }
+static inline 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 inline bool register_is_constant(const struct vkd3d_shader_register *reg) { return (reg->type == VKD3DSPR_IMMCONST || reg->type == VKD3DSPR_IMMCONST64);
Another issue is vkd3d-compiler disassembles only the source TPF, not normalised VSIR, but the SPIR-V disassembly contains VSIR line numbers. To resolve that we would need an option to emit disassembled VSIR.
Another issue is vkd3d-compiler disassembles only the source TPF, not normalised VSIR, but the SPIR-V disassembly contains VSIR line numbers.
I see we indeed set "compiler->location.line" to the current instruction index in spirv_compiler_generate_spirv(), I guess because that code was simply never updated. We should probably use "instruction->location.line" in the call to vkd3d_spirv_build_op_line() in any case, regardless of whether "compiler->location" is accurate or not.
To be useful for debugging we need the SPIR-V line number to match the TPF and VSIR line numbers, which is the case if we use `instruction->location.line` for both the disassembler and `OpLine`, but then the disassembly does not match FXC's output, if that matters much.
Setting this as draft because emitting reasonable line numbers from DXIL needs work. The need to set the record number while parsing clashes with the need to emit instructions with consistent line numbers. Different parsing stages can emit instructions, so this becomes complex. Instructions should probably be emitted using a separate location declared in the sm6 parser.