From 5d3c2eccd13f412683546a993e75943674c614cd Mon Sep 17 00:00:00 2001 From: Vinicius Rangel Date: Wed, 16 Oct 2024 02:04:28 -0300 Subject: [PATCH] devtools: show compute shader regs --- src/core/debug_state.cpp | 29 ++++--- src/core/debug_state.h | 9 +- src/core/devtools/widget/reg_view.cpp | 119 ++++++++++++++++++++------ src/core/devtools/widget/reg_view.h | 4 +- src/video_core/amdgpu/liverpool.cpp | 8 +- 5 files changed, 130 insertions(+), 39 deletions(-) diff --git a/src/core/debug_state.cpp b/src/core/debug_state.cpp index e449d2daa..adcb0cadb 100644 --- a/src/core/debug_state.cpp +++ b/src/core/debug_state.cpp @@ -143,7 +143,7 @@ void DebugStateImpl::PushQueueDump(QueueDump dump) { } void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr, - const AmdGpu::Liverpool::Regs& regs) { + const AmdGpu::Liverpool::Regs& regs, bool is_compute) { std::scoped_lock lock{frame_dump_list_mutex}; const auto it = waiting_reg_dumps.find(header_addr); if (it == waiting_reg_dumps.end()) { @@ -154,15 +154,24 @@ void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr, waiting_reg_dumps_dbg.erase(waiting_reg_dumps_dbg.find(header_addr)); auto& dump = frame.regs[header_addr - base_addr]; dump.regs = regs; - for (int i = 0; i < RegDump::MaxShaderStages; i++) { - if (regs.stage_enable.IsStageEnabled(i)) { - auto stage = regs.ProgramForStage(i); - if (stage->address_lo != 0) { - auto code = stage->Code(); - dump.stages[i] = ShaderDump{ - .user_data = *stage, - .code = std::vector{code.begin(), code.end()}, - }; + if (is_compute) { + dump.is_compute = true; + const auto& cs = dump.regs.cs_program; + dump.cs_data = ComputerShaderDump{ + .cs_program = cs, + .code = std::vector{cs.Code().begin(), cs.Code().end()}, + }; + } else { + for (int i = 0; i < RegDump::MaxShaderStages; i++) { + if (regs.stage_enable.IsStageEnabled(i)) { + auto stage = regs.ProgramForStage(i); + if (stage->address_lo != 0) { + auto code = stage->Code(); + dump.stages[i] = ShaderDump{ + .user_data = *stage, + .code = std::vector{code.begin(), code.end()}, + }; + } } } } diff --git a/src/core/debug_state.h b/src/core/debug_state.h index 6c43ae28a..cd1c6aa93 100644 --- a/src/core/debug_state.h +++ b/src/core/debug_state.h @@ -54,10 +54,17 @@ struct ShaderDump { std::vector code{}; }; +struct ComputerShaderDump { + Vulkan::Liverpool::ComputeProgram cs_program{}; + std::vector code{}; +}; + struct RegDump { + bool is_compute{false}; static constexpr size_t MaxShaderStages = 5; Vulkan::Liverpool::Regs regs{}; std::array stages{}; + ComputerShaderDump cs_data{}; }; struct FrameDump { @@ -144,7 +151,7 @@ public: void PushQueueDump(QueueDump dump); void PushRegsDump(uintptr_t base_addr, uintptr_t header_addr, - const AmdGpu::Liverpool::Regs& regs); + const AmdGpu::Liverpool::Regs& regs, bool is_compute = false); }; } // namespace DebugStateType diff --git a/src/core/devtools/widget/reg_view.cpp b/src/core/devtools/widget/reg_view.cpp index 6426cc4fb..27892c651 100644 --- a/src/core/devtools/widget/reg_view.cpp +++ b/src/core/devtools/widget/reg_view.cpp @@ -43,7 +43,16 @@ static std::optional exec_cli(const char* cli) { namespace Core::Devtools::Widget { void RegView::ProcessShader(int shader_id) { - auto shader = data.stages[shader_id]; + std::vector shader_code; + Vulkan::Liverpool::UserData user_data; + if (data.is_compute) { + shader_code = data.cs_data.code; + user_data = data.cs_data.cs_program.user_data; + } else { + const auto& s = data.stages[shader_id]; + shader_code = s.code; + user_data = s.user_data.user_data; + } std::string shader_dis; @@ -60,7 +69,7 @@ void RegView::ProcessShader(int shader_id) { } else { cli.replace(pos, src_arg.size(), "\"" + bin_path.string() + "\""); Common::FS::IOFile file(bin_path, Common::FS::FileAccessMode::Write); - file.Write(shader.code); + file.Write(shader_code); file.Close(); auto result = exec_cli(cli.c_str()); @@ -88,7 +97,7 @@ void RegView::ProcessShader(int shader_id) { ShaderCache cache{ .hex_view = hex_view, .dis_view = dis_view, - .user_data = shader.user_data.user_data, + .user_data = user_data, }; shader_decomp.emplace(shader_id, std::move(cache)); } @@ -99,11 +108,48 @@ void RegView::SelectShader(int id) { } } -void RegView::DrawRegs() { +void RegView::DrawComputeRegs() { + const auto& cs = data.cs_data.cs_program; + + if (BeginTable("CREGS", 2, ImGuiTableFlags_Borders)) { + TableNextRow(); + + // clang-format off + DrawValueRowList( + "DISPATCH_INITIATOR", cs.dispatch_initiator, + "DIM_X", cs.dim_x, + "DIM_Y", cs.dim_y, + "DIM_Z", cs.dim_z, + "START_X", cs.start_x, + "START_Y", cs.start_y, + "START_Z", cs.start_z, + "NUM_THREAD_X.FULL", cs.num_thread_x.full, + "NUM_THREAD_X.PARTIAL", cs.num_thread_x.partial, + "NUM_THREAD_Y.FULL", cs.num_thread_y.full, + "NUM_THREAD_Y.PARTIAL", cs.num_thread_y.partial, + "NUM_THREAD_Z.FULL", cs.num_thread_z.full, + "NUM_THREAD_Z.PARTIAL", cs.num_thread_z.partial, + "MAX_WAVE_ID", cs.max_wave_id, + "SETTINGS.NUM_VGPRS", cs.settings.num_vgprs, + "SETTINGS.NUM_SGPRS", cs.settings.num_sgprs, + "SETTINGS.NUM_USER_REGS", cs.settings.num_user_regs, + "SETTINGS.TGID_ENABLE", cs.settings.tgid_enable, + "SETTINGS.LDS_DWORDS", cs.settings.lds_dwords, + "RESOURCE_LIMITS", cs.resource_limits + ); + // clang-format on + + EndTable(); + } +} + +void RegView::DrawGraphicsRegs() { const auto& regs = data.regs; if (BeginTable("REGS", 2, ImGuiTableFlags_Borders)) { + TableNextRow(); + DrawValueRow("Primitive type", regs.primitive_type); auto& s = regs.screen_scissor; DrawRow("Scissor", "(%d, %d, %d, %d)", s.top_left_x, s.top_left_y, s.bottom_right_x, s.bottom_right_y); @@ -165,6 +211,18 @@ void RegView::DrawRegs() { } } + DrawRow("Primitive restart", "%X (IDX: %X)", regs.enable_primitive_restart & 1, + regs.primitive_restart_index); + // clang-format off + DrawValueRowList( + "Polygon mode", regs.polygon_control.PolyMode(), + "Cull mode", regs.polygon_control.CullingMode(), + "Clip Space", regs.clipper_control.clip_space, + "Front face", regs.polygon_control.front_face, + "Num Samples", regs.aa_config.NumSamples() + ); + // clang-format on + EndTable(); } } @@ -210,25 +268,33 @@ void RegView::SetData(DebugStateType::RegDump _data, const std::string& base_tit this->title = fmt::format("{}/Batch {}", base_title, batch_id); // clear cache shader_decomp.clear(); - const auto& regs = data.regs; - if (selected_shader >= 0 && !regs.stage_enable.IsStageEnabled(selected_shader)) { - selected_shader = -1; - } - if (default_reg_popup.open) { + if (data.is_compute) { + selected_shader = -2; + last_selected_cb = -1; default_reg_popup.open = false; - if (last_selected_cb == depth_id) { - const auto& has_depth = - regs.depth_buffer.Address() != 0 && regs.depth_control.depth_enable; - if (has_depth) { - default_reg_popup.SetData(title, regs.depth_buffer, regs.depth_control); - default_reg_popup.open = true; - } - } else if (last_selected_cb >= 0 && last_selected_cb < AmdGpu::Liverpool::NumColorBuffers) { - const auto& buffer = regs.color_buffers[last_selected_cb]; - const bool has_cb = buffer && regs.color_target_mask.GetMask(last_selected_cb); - if (has_cb) { - default_reg_popup.SetData(title, buffer, last_selected_cb); - default_reg_popup.open = true; + ProcessShader(-2); + } else { + const auto& regs = data.regs; + if (selected_shader >= 0 && !regs.stage_enable.IsStageEnabled(selected_shader)) { + selected_shader = -1; + } + if (default_reg_popup.open) { + default_reg_popup.open = false; + if (last_selected_cb == depth_id) { + const auto& has_depth = + regs.depth_buffer.Address() != 0 && regs.depth_control.depth_enable; + if (has_depth) { + default_reg_popup.SetData(title, regs.depth_buffer, regs.depth_control); + default_reg_popup.open = true; + } + } else if (last_selected_cb >= 0 && + last_selected_cb < AmdGpu::Liverpool::NumColorBuffers) { + const auto& buffer = regs.color_buffers[last_selected_cb]; + const bool has_cb = buffer && regs.color_target_mask.GetMask(last_selected_cb); + if (has_cb) { + default_reg_popup.SetData(title, buffer, last_selected_cb); + default_reg_popup.open = true; + } } } } @@ -267,7 +333,8 @@ void RegView::Draw() { EndMenuBar(); } - if (BeginChild("STAGES", {}, + if (!data.is_compute && + BeginChild("STAGES", {}, ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeY)) { for (int i = 0; i < DebugStateType::RegDump::MaxShaderStages; i++) { if (data.regs.stage_enable.IsStageEnabled(i)) { @@ -331,7 +398,11 @@ void RegView::Draw() { if (show_registers) { snprintf(name, sizeof(name), "Regs###reg_dump_%d/regs", id); if (Begin(name, &show_registers)) { - DrawRegs(); + if (data.is_compute) { + DrawComputeRegs(); + } else { + DrawGraphicsRegs(); + } } End(); } diff --git a/src/core/devtools/widget/reg_view.h b/src/core/devtools/widget/reg_view.h index ac7c1a1ae..3ac8ec077 100644 --- a/src/core/devtools/widget/reg_view.h +++ b/src/core/devtools/widget/reg_view.h @@ -37,7 +37,9 @@ class RegView { void SelectShader(int shader_id); - void DrawRegs(); + void DrawComputeRegs(); + + void DrawGraphicsRegs(); public: bool open = false; diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index d4ebeb883..7b4727088 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -446,7 +446,8 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::spandim_z; regs.cs_program.dispatch_initiator = dispatch_direct->dispatch_initiator; if (DebugState.DumpingCurrentReg()) { - DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs); + DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs, + true); } if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) { const auto cmd_address = reinterpret_cast(header); @@ -463,7 +464,8 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header), regs); + DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs, + true); } if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) { const auto cmd_address = reinterpret_cast(header); @@ -645,7 +647,7 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, int vqid) { regs.cs_program.dim_z = dispatch_direct->dim_z; regs.cs_program.dispatch_initiator = dispatch_direct->dispatch_initiator; if (DebugState.DumpingCurrentReg()) { - DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs); + DebugState.PushRegsDump(base_addr, reinterpret_cast(header), regs, true); } if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) { const auto cmd_address = reinterpret_cast(header);