diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d8938bbd..1e3134a2a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -353,16 +353,18 @@ set(DEV_TOOLS src/core/devtools/layer.cpp src/core/devtools/gcn/gcn_shader_regs.cpp src/core/devtools/widget/cmd_list.cpp src/core/devtools/widget/cmd_list.h + src/core/devtools/widget/common.h src/core/devtools/widget/frame_dump.cpp src/core/devtools/widget/frame_dump.h src/core/devtools/widget/frame_graph.cpp src/core/devtools/widget/frame_graph.h src/core/devtools/widget/imgui_memory_editor.h + src/core/devtools/widget/reg_popup.cpp + src/core/devtools/widget/reg_popup.h src/core/devtools/widget/reg_view.cpp src/core/devtools/widget/reg_view.h src/core/devtools/widget/text_editor.cpp src/core/devtools/widget/text_editor.h - src/core/devtools/widget/types.h ) set(COMMON src/common/logging/backend.cpp diff --git a/src/core/debug_state.cpp b/src/core/debug_state.cpp index cc5d988df..28653fde0 100644 --- a/src/core/debug_state.cpp +++ b/src/core/debug_state.cpp @@ -1,11 +1,13 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include + #include "common/assert.h" #include "common/native_clock.h" #include "common/singleton.h" #include "debug_state.h" -#include "devtools/widget/types.h" +#include "devtools/widget/common.h" #include "libraries/kernel/time_management.h" #include "libraries/system/msgdialog.h" #include "video_core/amdgpu/pm4_cmds.h" diff --git a/src/core/devtools/layer.cpp b/src/core/devtools/layer.cpp index c5e2fe7f9..17ef43bbc 100644 --- a/src/core/devtools/layer.cpp +++ b/src/core/devtools/layer.cpp @@ -105,9 +105,15 @@ void L::DrawAdvanced() { DebugState.should_show_frame_dump = false; std::unique_lock lock{DebugState.frame_dump_list_mutex}; while (!DebugState.frame_dump_list.empty()) { - auto frame_dump = std::move(DebugState.frame_dump_list.back()); - DebugState.frame_dump_list.pop_back(); + const auto& frame_dump = DebugState.frame_dump_list.back(); frame_viewers.emplace_back(frame_dump); + DebugState.frame_dump_list.pop_back(); + } + static bool first_time = true; + if (first_time) { + first_time = false; + DebugState.ShowDebugMessage("Tip: You can shift+click any\n" + "popup to open a new window"); } } diff --git a/src/core/devtools/widget/cmd_list.cpp b/src/core/devtools/widget/cmd_list.cpp index e3eb5533a..482b270d6 100644 --- a/src/core/devtools/widget/cmd_list.cpp +++ b/src/core/devtools/widget/cmd_list.cpp @@ -63,6 +63,21 @@ static HdrType GetNext(HdrType this_pm4, uint32_t n) { return curr_pm4; } +static bool IsDrawCall(AmdGpu::PM4ItOpcode opcode) { + using AmdGpu::PM4ItOpcode; + switch (opcode) { + case PM4ItOpcode::DispatchDirect: + case PM4ItOpcode::DispatchIndirect: + case PM4ItOpcode::DrawIndex2: + case PM4ItOpcode::DrawIndexAuto: + case PM4ItOpcode::DrawIndexOffset2: + case PM4ItOpcode::DrawIndexIndirect: + return true; + default: + return false; + } +} + void ParsePolygonControl(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); @@ -888,7 +903,7 @@ void CmdListViewer::OnSetBase(AmdGpu::PM4Type3Header const* header, u32 const* b Separator(); BeginGroup(); - auto const* pkt = reinterpret_cast(header); + // auto const* pkt = reinterpret_cast(header); Text("BASE_INDEX: %08X", body[0]); Text("ADDRESS0 : %08X", body[1]); Text("ADDRESS1 : %08X", body[2]); @@ -1077,9 +1092,10 @@ void CmdListViewer::OnDispatch(AmdGpu::PM4Type3Header const* header, u32 const* EndGroup(); } -CmdListViewer::CmdListViewer(const FrameDumpViewer* parent, const std::vector& cmd_list, - uintptr_t base_addr, std::string name) - : parent(parent), base_addr(base_addr), name(std::move(name)) { +CmdListViewer::CmdListViewer(DebugStateType::FrameDump* _frame_dump, + const std::vector& cmd_list, uintptr_t _base_addr, + std::string _name) + : frame_dump(_frame_dump), base_addr(_base_addr), name(std::move(_name)) { using namespace AmdGpu; cmdb_addr = (uintptr_t)cmd_list.data(); @@ -1131,11 +1147,7 @@ CmdListViewer::CmdListViewer(const FrameDumpViewer* parent, const std::vectoropen) { + it = extra_batch_view.erase(it); + continue; + } + it->Draw(); + ++it; + } + + if (cmdb_view.Open) { + MemoryEditor::Sizes s; + cmdb_view.CalcSizes(s, cmdb_size, cmdb_addr); + SetNextWindowSize({s.WindowWidth, s.WindowWidth * 0.6f}, ImGuiCond_FirstUseEver); + SetNextWindowSizeConstraints({0.0f}, {s.WindowWidth, FLT_MAX}); + if (Begin(cmdb_view_name.c_str(), &cmdb_view.Open, + ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings)) { + cmdb_view.DrawContents((void*)cmdb_addr, cmdb_size, base_addr); + if (cmdb_view.ContentsWidthChanged) { + cmdb_view.CalcSizes(s, cmdb_size, cmdb_addr); + SetWindowSize({s.WindowWidth, s.WindowWidth * 0.6f}); + } + } + End(); + } + PushID(name.c_str()); if (BeginChild("cmd_queue", {})) { @@ -1213,10 +1253,17 @@ void CmdListViewer::Draw() { } u32 batch_id = ~0u; - s32 current_highlight_batch = -1; + u32 current_highlight_batch = ~0u; + int id = 0; + PushID(0); for (const auto& event : events) { - auto processed_size = 0ull; + PopID(); + PushID(id++); + + if (std::holds_alternative(event)) { + batch_id = std::get(event).id; + } if (show_markers) { if (std::holds_alternative(event)) { @@ -1243,11 +1290,6 @@ void CmdListViewer::Draw() { } } - if (std::holds_alternative(event)) { - batch_id = std::get(event).id; - continue; - } - if (!std::holds_alternative(event)) { continue; } @@ -1274,15 +1316,35 @@ void CmdListViewer::Draw() { PushStyleColor(ImGuiCol_Text, ImVec4{1.0f, 0.7f, 0.7f, 1.0f}); } - if (!group_batches || CollapsingHeader(batch_hdr)) { + const auto open_batch_view = [&, this] { + if (frame_dump->regs.contains(batch.command_addr)) { + auto data = frame_dump->regs.at(batch.command_addr); + if (GetIO().KeyShift) { + auto& pop = extra_batch_view.emplace_back(); + pop.SetData(data, batch_id); + pop.open = true; + } else { + batch_view.SetData(data, batch_id); + batch_view.open = true; + } + } + }; + + bool show_batch_content = true; + + if (group_batches) { + show_batch_content = + CollapsingHeader(batch_hdr, ImGuiTreeNodeFlags_AllowOverlap); + SameLine(GetContentRegionAvail().x - 40.0f); + if (Button("->", {40.0f, 0.0f})) { + open_batch_view(); + } + } + + if (show_batch_content) { + auto processed_size = 0ull; auto bb = ctx.LastItemData.Rect; if (group_batches) { - if (IsItemToggledOpen()) { - if (parent->frame_dump.regs.contains(batch.command_addr)) { - batch_view.SetData(parent->frame_dump.regs.at(batch.command_addr)); - batch_view.open = true; - } - } Indent(); } auto const batch_sz = batch.end_addr - batch.start_addr; @@ -1300,9 +1362,23 @@ void CmdListViewer::Draw() { cmdb_addr + batch.start_addr + processed_size, Gcn::GetOpCodeName((u32)op)); - if (TreeNode(header_name)) { - const bool just_opened = IsItemToggledOpen(); - if (just_opened) { + bool open_pm4 = TreeNode(header_name); + if (!group_batches) { + if (IsDrawCall(op)) { + SameLine(GetContentRegionAvail().x - 40.0f); + if (Button("->", {40.0f, 0.0f})) { + open_batch_view(); + } + } + if (IsItemHovered() && ctx.IO.KeyShift) { + if (BeginTooltip()) { + Text("Batch %d", batch_id); + EndTooltip(); + } + } + } + if (open_pm4) { + if (IsItemToggledOpen()) { // Editor cmdb_view.GotoAddrAndHighlight( reinterpret_cast(pm4_hdr) - cmdb_addr, @@ -1383,6 +1459,7 @@ void CmdListViewer::Draw() { Separator(); } } + PopID(); highlight_batch = current_highlight_batch; @@ -1391,34 +1468,6 @@ void CmdListViewer::Draw() { } EndChild(); PopID(); - - if (cmdb_view.Open) { - MemoryEditor::Sizes s; - cmdb_view.CalcSizes(s, cmdb_size, cmdb_addr); - SetNextWindowSize({s.WindowWidth, s.WindowWidth * 0.6f}, ImGuiCond_FirstUseEver); - SetNextWindowSizeConstraints({0.0f}, {s.WindowWidth, FLT_MAX}); - if (Begin(cmdb_view_name.c_str(), &cmdb_view.Open, - ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings)) { - cmdb_view.DrawContents((void*)cmdb_addr, cmdb_size, base_addr); - if (cmdb_view.ContentsWidthChanged) { - cmdb_view.CalcSizes(s, cmdb_size, cmdb_addr); - SetWindowSize({s.WindowWidth, s.WindowWidth * 0.6f}); - } - } - End(); - } - - if (batch_view.open) { - batch_view.Draw(); - } - for (auto it = extra_batch_view.begin(); it != extra_batch_view.end(); ++it) { - if (!it->open) { - it = extra_batch_view.erase(it); - continue; - } - it->Draw(); - ++it; - } } } // namespace Core::Devtools::Widget \ No newline at end of file diff --git a/src/core/devtools/widget/cmd_list.h b/src/core/devtools/widget/cmd_list.h index 5519537c8..971c8fffe 100644 --- a/src/core/devtools/widget/cmd_list.h +++ b/src/core/devtools/widget/cmd_list.h @@ -5,13 +5,14 @@ #pragma once +#include #include #include +#include "common.h" #include "common/types.h" #include "imgui_memory_editor.h" #include "reg_view.h" -#include "types.h" namespace AmdGpu { union PM4Type3Header; @@ -36,7 +37,7 @@ void ParseZInfo(u32 value, bool begin_table = true); class CmdListViewer { - const FrameDumpViewer* parent; + DebugStateType::FrameDump* frame_dump; uintptr_t base_addr; std::string name; @@ -49,22 +50,22 @@ class CmdListViewer { int batch_bp{-1}; int vqid{255}; - s32 highlight_batch{-1}; + u32 highlight_batch{~0u}; RegView batch_view; std::vector extra_batch_view; - void OnNop(AmdGpu::PM4Type3Header const* header, u32 const* body); - void OnSetBase(AmdGpu::PM4Type3Header const* header, u32 const* body); - void OnSetContextReg(AmdGpu::PM4Type3Header const* header, u32 const* body); - void OnSetShReg(AmdGpu::PM4Type3Header const* header, u32 const* body); - void OnDispatch(AmdGpu::PM4Type3Header const* header, u32 const* body); + static void OnNop(AmdGpu::PM4Type3Header const* header, u32 const* body); + static void OnSetBase(AmdGpu::PM4Type3Header const* header, u32 const* body); + static void OnSetContextReg(AmdGpu::PM4Type3Header const* header, u32 const* body); + static void OnSetShReg(AmdGpu::PM4Type3Header const* header, u32 const* body); + static void OnDispatch(AmdGpu::PM4Type3Header const* header, u32 const* body); public: static void LoadConfig(const char* line); static void SerializeConfig(ImGuiTextBuffer* buf); - explicit CmdListViewer(const FrameDumpViewer* parent, const std::vector& cmd_list, + explicit CmdListViewer(DebugStateType::FrameDump* frame_dump, const std::vector& cmd_list, uintptr_t base_addr = 0, std::string name = ""); void Draw(); diff --git a/src/core/devtools/widget/common.h b/src/core/devtools/widget/common.h new file mode 100644 index 000000000..467fc7b52 --- /dev/null +++ b/src/core/devtools/widget/common.h @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "common/types.h" +#include "video_core/amdgpu/pm4_opcodes.h" + +namespace Core::Devtools::Widget { + +/* + * Generic PM4 header + */ +union PM4Header { + struct { + u32 reserved : 16; + u32 count : 14; + u32 type : 2; // PM4_TYPE + }; + u32 u32All; +}; + +struct PushMarker { + std::string name{}; +}; + +struct PopMarker {}; + +struct BatchBegin { + u32 id; +}; + +struct BatchInfo { + u32 id; + std::string marker{}; + size_t start_addr; + size_t end_addr; + size_t command_addr; + AmdGpu::PM4ItOpcode type; + bool bypass{false}; +}; + +using GPUEvent = std::variant; + +template +void DrawRow(const char* text, const char* fmt, Args... args) { + ImGui::TableNextColumn(); + ImGui::TextUnformatted(text); + ImGui::TableNextColumn(); + char buf[128]; + snprintf(buf, sizeof(buf), fmt, args...); + ImGui::TextUnformatted(buf); +} + +template +void DrawMultipleRow(const char* text, const char* fmt, V arg, Extra&&... extra_args) { + DrawRow(text, fmt, arg); + if constexpr (sizeof...(extra_args) > 0) { + DrawMultipleRow(std::forward(extra_args)...); + } +} + +template +static void DoTooltip(const char* str_id, Args&&... args) { + if (ImGui::BeginTooltip()) { + if (ImGui::BeginTable(str_id, 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + DrawMultipleRow(std::forward(args)...); + ImGui::EndTable(); + } + ImGui::EndTooltip(); + } +} + +} // namespace Core::Devtools::Widget \ No newline at end of file diff --git a/src/core/devtools/widget/frame_dump.cpp b/src/core/devtools/widget/frame_dump.cpp index b0326086c..29b5cb8ee 100644 --- a/src/core/devtools/widget/frame_dump.cpp +++ b/src/core/devtools/widget/frame_dump.cpp @@ -36,7 +36,8 @@ static std::array small_int_to_str(const s32 i) { namespace Core::Devtools::Widget { -FrameDumpViewer::FrameDumpViewer(FrameDump _frame_dump) : frame_dump(std::move(_frame_dump)) { +FrameDumpViewer::FrameDumpViewer(const FrameDump& _frame_dump) + : frame_dump(std::make_shared(_frame_dump)) { static int unique_id = 0; id = unique_id++; @@ -44,15 +45,14 @@ FrameDumpViewer::FrameDumpViewer(FrameDump _frame_dump) : frame_dump(std::move(_ selected_submit_num = 0; selected_queue_num2 = 0; - cmd_list_viewer.reserve(frame_dump.queues.size()); - for (const auto& cmd : frame_dump.queues) { + cmd_list_viewer.reserve(frame_dump->queues.size()); + for (const auto& cmd : frame_dump->queues) { const auto fname = fmt::format("{}_{}_{:02}_{:02}", id, magic_enum::enum_name(selected_queue_type), selected_submit_num, selected_queue_num2); - cmd_list_viewer.emplace_back(this, cmd.data, cmd.base_addr, fname); - if (cmd.type == QueueType::dcb && cmd.submit_num == selected_submit_num && - cmd.num2 == selected_queue_num2) { - selected_cmd = cmd_list_viewer.size() - 1; + cmd_list_viewer.emplace_back(frame_dump.get(), cmd.data, cmd.base_addr, fname); + if (cmd.type == QueueType::dcb && cmd.submit_num == 0 && cmd.num2 == 0) { + selected_cmd = static_cast(cmd_list_viewer.size() - 1); } } } @@ -96,7 +96,7 @@ void FrameDumpViewer::Draw() { magic_enum::enum_name(selected_queue_type), selected_submit_num, selected_queue_num2); Common::FS::IOFile file(fname, Common::FS::FileAccessMode::Write); - auto& data = frame_dump.queues[selected_cmd].data; + const auto& data = frame_dump->queues[selected_cmd].data; if (file.IsOpen()) { DebugState.ShowDebugMessage(fmt::format("Dumping cmd as {}", fname)); file.Write(data); @@ -112,7 +112,7 @@ void FrameDumpViewer::Draw() { if (BeginCombo("##select_submit_num", small_int_to_str(selected_submit_num).data(), ImGuiComboFlags_WidthFitPreview)) { std::array available_submits{}; - for (const auto& cmd : frame_dump.queues) { + for (const auto& cmd : frame_dump->queues) { if (cmd.type == selected_queue_type) { available_submits[cmd.submit_num] = true; } @@ -137,7 +137,7 @@ void FrameDumpViewer::Draw() { if (BeginCombo("##select_queue_num2", small_int_to_str(selected_queue_num2).data(), ImGuiComboFlags_WidthFitPreview)) { std::array available_queues{}; - for (const auto& cmd : frame_dump.queues) { + for (const auto& cmd : frame_dump->queues) { if (cmd.type == selected_queue_type && cmd.submit_num == selected_submit_num) { available_queues[cmd.num2] = true; } @@ -152,12 +152,12 @@ void FrameDumpViewer::Draw() { } } if (selected) { - const auto it = std::ranges::find_if(frame_dump.queues, [&](const auto& cmd) { + const auto it = std::ranges::find_if(frame_dump->queues, [&](const auto& cmd) { return cmd.type == selected_queue_type && cmd.submit_num == selected_submit_num && cmd.num2 == selected_queue_num2; }); - if (it != frame_dump.queues.end()) { - selected_cmd = std::distance(frame_dump.queues.begin(), it); + if (it != frame_dump->queues.end()) { + selected_cmd = static_cast(std::distance(frame_dump->queues.begin(), it)); } } EndCombo(); diff --git a/src/core/devtools/widget/frame_dump.h b/src/core/devtools/widget/frame_dump.h index 4da33b77d..2b3ff2411 100644 --- a/src/core/devtools/widget/frame_dump.h +++ b/src/core/devtools/widget/frame_dump.h @@ -8,7 +8,6 @@ #include "cmd_list.h" #include "core/debug_state.h" -#include "imgui_memory_editor.h" namespace Core::Devtools::Widget { @@ -17,7 +16,7 @@ class CmdListViewer; class FrameDumpViewer { friend class CmdListViewer; - DebugStateType::FrameDump frame_dump; + std::shared_ptr frame_dump; int id; std::vector cmd_list_viewer; @@ -30,7 +29,7 @@ class FrameDumpViewer { public: bool is_open = true; - explicit FrameDumpViewer(DebugStateType::FrameDump frame_dump); + explicit FrameDumpViewer(const DebugStateType::FrameDump& frame_dump); ~FrameDumpViewer(); diff --git a/src/core/devtools/widget/reg_popup.cpp b/src/core/devtools/widget/reg_popup.cpp new file mode 100644 index 000000000..cebffe6be --- /dev/null +++ b/src/core/devtools/widget/reg_popup.cpp @@ -0,0 +1,107 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "reg_popup.h" + +#include +#include +#include + +#include "cmd_list.h" +#include "common.h" + +using namespace ImGui; +using magic_enum::enum_name; + +namespace Core::Devtools::Widget { + +void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) { + if (BeginTable("COLOR_BUFFER", 2, ImGuiTableFlags_Borders)) { + TableNextRow(); + + // clang-format off + + DrawMultipleRow( + "BASE_ADDR", "%X", buffer.base_address, + "PITCH.TILE_MAX", "%X", buffer.pitch.tile_max, + "PITCH.FMASK_TILE_MAX", "%X", buffer.pitch.fmask_tile_max, + "SLICE.TILE_MAX", "%X", buffer.slice.tile_max, + "VIEW.SLICE_START", "%X", buffer.view.slice_start, + "VIEW.SLICE_MAX", "%X", buffer.view.slice_max + ); + + TableNextRow(); + TableNextColumn(); + if (TreeNode("Color0Info")) { + TableNextRow(); + TableNextColumn(); + ParseColor0Info(buffer.info.u32all, false); + TreePop(); + } + + TableNextRow(); + TableNextColumn(); + if (TreeNode("Color0Attrib")) { + TableNextRow(); + TableNextColumn(); + ParseColor0Attrib(buffer.attrib.u32all, false); + TreePop(); + } + + TableNextRow(); + DrawMultipleRow( + "CMASK_BASE_EXT", "%X", buffer.cmask_base_address, + "FMASK_BASE_EXT", "%X", buffer.fmask_base_address, + "FMASK_SLICE.TILE_MAX", "%X", buffer.fmask_slice.tile_max, + "CLEAR_WORD0", "%X", buffer.clear_word0, + "CLEAR_WORD1", "%X", buffer.clear_word1 + ); + + DrawMultipleRow( + "Pitch()", "%X", buffer.Pitch(), + "Height()", "%X", buffer.Height(), + "Address()", "%X", buffer.Address(), + "CmaskAddress", "%X", buffer.CmaskAddress(), + "FmaskAddress", "%X", buffer.FmaskAddress(), + "NumSamples()", "%X", buffer.NumSamples(), + "NumSlices()", "%X", buffer.NumSlices(), + "GetColorSliceSize()", "%X", buffer.GetColorSliceSize() + ); + + auto tiling_mode = buffer.GetTilingMode(); + auto num_format = buffer.NumFormat(); + DrawRow("GetTilingMode()", "%X (%s)", tiling_mode, enum_name(tiling_mode).data()); + DrawRow("IsTiled()", "%X", buffer.IsTiled()); + DrawRow("NumFormat()", "%X (%s)", num_format, enum_name(num_format).data()); + + // clang-format on + + EndTable(); + } +} + +RegPopup::RegPopup() { + static int unique_id = 0; + id = unique_id++; +} + +void RegPopup::SetData(AmdGpu::Liverpool::ColorBuffer color_buffer, u32 batch_id, u32 cb_id) { + this->data = color_buffer; + this->title = fmt::format("Batch #{} CB #{}", batch_id, cb_id); +} + +void RegPopup::Draw() { + + char name[128]; + snprintf(name, sizeof(name), "%s###reg_popup_%d", title.c_str(), id); + + SetNextWindowSize({250.0f, 300.0f}, ImGuiCond_FirstUseEver); + if (Begin(name, &open, ImGuiWindowFlags_NoSavedSettings)) { + if (const auto* buffer = std::get_if(&data)) { + DrawColorBuffer(*buffer); + } + } + End(); +} + +} // namespace Core::Devtools::Widget diff --git a/src/core/devtools/widget/reg_popup.h b/src/core/devtools/widget/reg_popup.h new file mode 100644 index 000000000..a93d990fa --- /dev/null +++ b/src/core/devtools/widget/reg_popup.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "common/types.h" +#include "video_core/renderer_vulkan/liverpool_to_vk.h" + +namespace Core::Devtools::Widget { + +class RegPopup { + int id; + + std::variant data; + std::string title{}; + + void DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer); + +public: + bool open = false; + + RegPopup(); + + void SetData(AmdGpu::Liverpool::ColorBuffer color_buffer, u32 batch_id, u32 cb_id); + + void Draw(); +}; + +} // namespace Core::Devtools::Widget diff --git a/src/core/devtools/widget/reg_view.cpp b/src/core/devtools/widget/reg_view.cpp index 4a62fb35c..235a38ec2 100644 --- a/src/core/devtools/widget/reg_view.cpp +++ b/src/core/devtools/widget/reg_view.cpp @@ -8,7 +8,7 @@ #include #include -#include "cmd_list.h" +#include "common.h" #include "common/io_file.h" #include "core/devtools/options.h" #include "imgui_internal.h" @@ -19,41 +19,9 @@ #define pclose _pclose #endif -#include - using namespace ImGui; using magic_enum::enum_name; -template -void DrawRow(const char* text, const char* fmt, Args... args) { - TableNextColumn(); - TextUnformatted(text); - TableNextColumn(); - char buf[128]; - snprintf(buf, sizeof(buf), fmt, args...); - TextUnformatted(buf); -} - -template -void DrawMultipleRow(const char* text, const char* fmt, V arg, Extra&&... extra_args) { - DrawRow(text, fmt, arg); - if constexpr (sizeof...(extra_args) > 0) { - DrawMultipleRow(std::forward(extra_args)...); - } -} - -// Must end with EndTable -template -static void DoTooltip(const char* str_id, Args&&... args) { - if (BeginTooltip()) { - if (BeginTable(str_id, 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { - DrawMultipleRow(std::forward(args)...); - EndTable(); - } - EndTooltip(); - } -} - static std::optional exec_cli(const char* cli) { std::array buffer{}; std::string output; @@ -132,9 +100,9 @@ void RegView::DrawRegs() { if (BeginTable("REGS", 2, ImGuiTableFlags_Borders)) { - auto& scissor = regs.screen_scissor; - DrawRow("Scissor", "(%d, %d, %d, %d)", scissor.top_left_x, scissor.top_left_y, - scissor.bottom_right_x, scissor.bottom_right_y); + 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); auto cc_mode = regs.color_control.mode.Value(); DrawRow("Color control", "%X (%s)", cc_mode, enum_name(cc_mode).data()); @@ -147,77 +115,40 @@ void RegView::DrawRegs() { const auto& buffer = regs.color_buffers[cb]; - bool open = opened_cb[cb]; + const auto open_new_popup = [&] { + auto& pop = extra_reg_popup.emplace_back(); + pop.SetData(buffer, batch_id, cb); + pop.open = true; + }; + + Text("Color buffer %d", cb); + TableNextColumn(); if (!buffer || !regs.color_target_mask.GetMask(cb)) { - Text("Color buffer %d", cb); - TableNextColumn(); TextUnformatted("N/A"); + } else if (last_selected_cb == cb && default_reg_popup.open) { + if (SmallButton("x")) { + if (GetIO().KeyShift) { + open_new_popup(); + } else { + default_reg_popup.open = false; + } + } } else { - SetNextItemOpen(open); - bool keep_open = TreeNode("cb", "Color buffer %d", cb); - open = opened_cb[cb] = keep_open; - } - - if (open) { - TableNextRow(); - - // clang-format off - - DrawMultipleRow( - "BASE_ADDR", "%X", buffer.base_address, - "PITCH.TILE_MAX", "%X", buffer.pitch.tile_max, - "PITCH.FMASK_TILE_MAX", "%X", buffer.pitch.fmask_tile_max, - "SLICE.TILE_MAX", "%X", buffer.slice.tile_max, - "VIEW.SLICE_START", "%X", buffer.view.slice_start, - "VIEW.SLICE_MAX", "%X", buffer.view.slice_max - ); - - TableNextRow(); - TableNextColumn(); - if (TreeNode("Color0Info")) { - TableNextRow(); - TableNextColumn(); - ParseColor0Info(buffer.info.u32all, false); - TreePop(); + if (SmallButton("->")) { + if (GetIO().KeyShift) { + open_new_popup(); + } else { + last_selected_cb = cb; + default_reg_popup.SetData(buffer, batch_id, cb); + if (!default_reg_popup.open) { + default_reg_popup.open = true; + auto popup_pos = + GetCurrentContext()->LastItemData.Rect.Max + ImVec2(5.0f, 0.0f); + SetNextWindowPos(popup_pos, ImGuiCond_Always); + default_reg_popup.Draw(); + } + } } - - TableNextRow(); - TableNextColumn(); - if (TreeNode("Color0Attrib")) { - TableNextRow(); - TableNextColumn(); - ParseColor0Attrib(buffer.attrib.u32all, false); - TreePop(); - } - - DrawMultipleRow( - "CMASK_BASE_EXT", "%X", buffer.cmask_base_address, - "FMASK_BASE_EXT", "%X", buffer.fmask_base_address, - "FMASK_SLICE.TILE_MAX", "%X", buffer.fmask_slice.tile_max, - "CLEAR_WORD0", "%X", buffer.clear_word0, - "CLEAR_WORD1", "%X", buffer.clear_word1 - ); - - DrawMultipleRow( - "Pitch()", "%X", buffer.Pitch(), - "Height()", "%X", buffer.Height(), - "Address()", "%X", buffer.Address(), - "CmaskAddress", "%X", buffer.CmaskAddress(), - "FmaskAddress", "%X", buffer.FmaskAddress(), - "NumSamples()", "%X", buffer.NumSamples(), - "NumSlices()", "%X", buffer.NumSlices(), - "GetColorSliceSize()", "%X", buffer.GetColorSliceSize() - ); - - auto tiling_mode = buffer.GetTilingMode(); - auto num_format = buffer.NumFormat(); - DrawRow("GetTilingMode()", "%X (%s)", tiling_mode, enum_name(tiling_mode).data()); - DrawRow("IsTiled()", "%X", buffer.IsTiled()); - DrawRow("NumFormat()", "%X (%s)", num_format, enum_name(num_format).data()); - - // clang-format on - - TreePop(); } PopID(); @@ -262,18 +193,20 @@ RegView::RegView() { DockBuilderFinish(root_dock_id); } -void RegView::SetData(DebugStateType::RegDump data) { +void RegView::SetData(DebugStateType::RegDump data, u32 batch_id) { this->data = std::move(data); + this->batch_id = batch_id; // clear cache selected_shader = -1; - opened_cb.fill(false); shader_decomp.clear(); + default_reg_popup.open = false; + extra_reg_popup.clear(); } void RegView::Draw() { char name[128]; - snprintf(name, sizeof(name), "BatchView###reg_dump_%d", id); + snprintf(name, sizeof(name), "BatchView %u###reg_dump_%d", batch_id, id); if (Begin(name, &open, ImGuiWindowFlags_MenuBar)) { const char* names[] = {"vs", "ps", "gs", "es", "hs", "ls"}; @@ -346,6 +279,18 @@ void RegView::Draw() { } End(); } + + if (default_reg_popup.open) { + default_reg_popup.Draw(); + } + for (auto it = extra_reg_popup.begin(); it != extra_reg_popup.end();) { + if (!it->open) { + it = extra_reg_popup.erase(it); + continue; + } + it->Draw(); + ++it; + } } } // namespace Core::Devtools::Widget \ No newline at end of file diff --git a/src/core/devtools/widget/reg_view.h b/src/core/devtools/widget/reg_view.h index 289b67ec7..67ab1e04f 100644 --- a/src/core/devtools/widget/reg_view.h +++ b/src/core/devtools/widget/reg_view.h @@ -4,6 +4,7 @@ #pragma once #include "core/debug_state.h" #include "imgui_memory_editor.h" +#include "reg_popup.h" #include "text_editor.h" namespace Core::Devtools::Widget { @@ -16,13 +17,15 @@ struct ShaderCache { class RegView { int id; - bool first_render = true; DebugStateType::RegDump data; + u32 batch_id{~0u}; std::unordered_map shader_decomp; int selected_shader{-1}; - std::array opened_cb{}; + RegPopup default_reg_popup; + int last_selected_cb{-1}; + std::vector extra_reg_popup; bool show_registers{true}; bool show_user_data{true}; @@ -39,7 +42,7 @@ public: RegView(); - void SetData(DebugStateType::RegDump data); + void SetData(DebugStateType::RegDump data, u32 batch_id); void Draw(); }; diff --git a/src/core/devtools/widget/types.h b/src/core/devtools/widget/types.h deleted file mode 100644 index c1dbf84a9..000000000 --- a/src/core/devtools/widget/types.h +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -#include "common/types.h" -#include "video_core/amdgpu/pm4_opcodes.h" - -namespace Core::Devtools::Widget { - -/* - * Generic PM4 header - */ -union PM4Header { - struct { - u32 reserved : 16; - u32 count : 14; - u32 type : 2; // PM4_TYPE - }; - u32 u32All; -}; - -struct PushMarker { - std::string name{}; -}; - -struct PopMarker {}; - -struct BatchBegin { - u32 id; -}; - -struct BatchInfo { - u32 id; - std::string marker{}; - size_t start_addr; - size_t end_addr; - size_t command_addr; - AmdGpu::PM4ItOpcode type; - bool bypass{false}; -}; - -using GPUEvent = std::variant; - -} // namespace Core::Devtools::Widget \ No newline at end of file diff --git a/src/imgui/renderer/imgui_core.cpp b/src/imgui/renderer/imgui_core.cpp index 75538c1d0..311e86a3c 100644 --- a/src/imgui/renderer/imgui_core.cpp +++ b/src/imgui/renderer/imgui_core.cpp @@ -80,8 +80,6 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w imgui_font_proggyvector_regular_compressed_size, 16.0f); - GetCurrentContext()->DebugLogFlags |= ImGuiDebugLogFlags_EventDocking; - StyleColorsDark(); ::Core::Devtools::Layer::SetupSettings();