diff --git a/src/core/devtools/layer.cpp b/src/core/devtools/layer.cpp index c7874ac2d..c5e2fe7f9 100644 --- a/src/core/devtools/layer.cpp +++ b/src/core/devtools/layer.cpp @@ -242,7 +242,8 @@ void L::SetupSettings() { const ImGuiID dock_id = ImHashStr("FrameDumpDock"); DockBuilderAddNode(dock_id, 0); - DockBuilderSetNodePos(dock_id, ImVec2{50.0, 50.0}); + DockBuilderSetNodePos(dock_id, ImVec2{450.0, 150.0}); + DockBuilderSetNodeSize(dock_id, ImVec2{400.0, 500.0}); DockBuilderFinish(dock_id); } diff --git a/src/core/devtools/widget/cmd_list.cpp b/src/core/devtools/widget/cmd_list.cpp index 3a3deadbf..e3eb5533a 100644 --- a/src/core/devtools/widget/cmd_list.cpp +++ b/src/core/devtools/widget/cmd_list.cpp @@ -32,8 +32,8 @@ const char* GetOpCodeName(u32 op); namespace Core::Devtools::Widget { -static bool group_batches = false; -static bool show_markers = true; +static bool group_batches = true; +static bool show_markers = false; void CmdListViewer::LoadConfig(const char* line) { int i; @@ -63,10 +63,11 @@ static HdrType GetNext(HdrType this_pm4, uint32_t n) { return curr_pm4; } -static void ParsePolygonControl(u32 value) { +void ParsePolygonControl(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); - if (BeginTable("PA_SU_SC_MODE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (!begin_table || + BeginTable("PA_SU_SC_MODE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { TableNextRow(); TableSetColumnIndex(0); Text("CULL_FRONT"); @@ -146,14 +147,17 @@ static void ParsePolygonControl(u32 value) { TableSetColumnIndex(1); Text("%X", reg.multi_prim_ib_ena.Value()); - EndTable(); + if (begin_table) { + EndTable(); + } } } -static void ParseAaConfig(u32 value) { +void ParseAaConfig(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); - if (BeginTable("PA_SC_AA_CONFIG", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (!begin_table || + BeginTable("PA_SC_AA_CONFIG", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { TableNextRow(); TableSetColumnIndex(0); Text("MSAA_NUM_SAMPLES"); @@ -184,14 +188,17 @@ static void ParseAaConfig(u32 value) { TableSetColumnIndex(1); Text("%X", reg.detail_to_exposed_mode.Value()); - EndTable(); + if (begin_table) { + EndTable(); + } } } -static void ParseViewportControl(u32 value) { +void ParseViewportControl(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); - if (BeginTable("PA_CL_VTE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (!begin_table || + BeginTable("PA_CL_VTE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { TableNextRow(); TableSetColumnIndex(0); Text("VPORT_X_SCALE_ENA"); @@ -252,14 +259,17 @@ static void ParseViewportControl(u32 value) { TableSetColumnIndex(1); Text("%X", reg.perfcounter_ref.Value()); - EndTable(); + if (begin_table) { + EndTable(); + } } } -static void ParseColorControl(u32 value) { +void ParseColorControl(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); - if (BeginTable("CB_COLOR_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (!begin_table || + BeginTable("CB_COLOR_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { TableNextRow(); TableSetColumnIndex(0); Text("DISABLE_DUAL_QUAD__VI"); @@ -284,14 +294,17 @@ static void ParseColorControl(u32 value) { TableSetColumnIndex(1); Text("%X", reg.rop3.Value()); - EndTable(); + if (begin_table) { + EndTable(); + } } } -static void ParseColor0Info(u32 value) { +void ParseColor0Info(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); - if (BeginTable("CB_COLOR_INFO", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (!begin_table || + BeginTable("CB_COLOR_INFO", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { TableNextRow(); TableSetColumnIndex(0); Text("ENDIAN"); @@ -400,14 +413,17 @@ static void ParseColor0Info(u32 value) { TableSetColumnIndex(1); Text("%X", reg.cmask_addr_type.Value()); - EndTable(); + if (begin_table) { + EndTable(); + } } } -static void ParseColor0Attrib(u32 value) { +void ParseColor0Attrib(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); - if (BeginTable("CB_COLOR_ATTRIB", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (!begin_table || + BeginTable("CB_COLOR_ATTRIB", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { TableNextRow(); TableSetColumnIndex(0); Text("TILE_MODE_INDEX"); @@ -444,14 +460,17 @@ static void ParseColor0Attrib(u32 value) { TableSetColumnIndex(1); Text("%X", reg.force_dst_alpha_1.Value()); - EndTable(); + if (begin_table) { + EndTable(); + } } } -static void ParseBlendControl(u32 value) { +void ParseBlendControl(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); - if (BeginTable("CB_BLEND_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (!begin_table || + BeginTable("CB_BLEND_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { TableNextRow(); TableSetColumnIndex(0); Text("COLOR_SRCBLEND"); @@ -510,14 +529,17 @@ static void ParseBlendControl(u32 value) { TableSetColumnIndex(1); Text("%X", reg.disable_rop3.Value()); - EndTable(); + if (begin_table) { + EndTable(); + } } } -static void ParseDepthRenderControl(u32 value) { +void ParseDepthRenderControl(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); - if (BeginTable("DB_RENDER_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (!begin_table || + BeginTable("DB_RENDER_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { TableNextRow(); TableSetColumnIndex(0); Text("DEPTH_CLEAR_ENABLE"); @@ -578,14 +600,17 @@ static void ParseDepthRenderControl(u32 value) { TableSetColumnIndex(1); Text("%X", reg.decompress_enable.Value()); - EndTable(); + if (begin_table) { + EndTable(); + } } } -static void ParseDepthControl(u32 value) { +void ParseDepthControl(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); - if (BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (!begin_table || + BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { TableNextRow(); TableSetColumnIndex(0); Text("STENCIL_ENABLE"); @@ -648,14 +673,17 @@ static void ParseDepthControl(u32 value) { TableSetColumnIndex(1); Text("%X", reg.disable_color_writes_on_depth_pass.Value()); - EndTable(); + if (begin_table) { + EndTable(); + } } } -static void ParseEqaa(u32 value) { +void ParseEqaa(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); - if (BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (!begin_table || + BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { TableNextRow(); TableSetColumnIndex(0); Text("MAX_ANCHOR_SAMPLES"); @@ -728,14 +756,17 @@ static void ParseEqaa(u32 value) { TableSetColumnIndex(1); Text("%X", reg.enable_postz_overrasterization.Value()); - EndTable(); + if (begin_table) { + EndTable(); + } } } -static void ParseZInfo(u32 value) { +void ParseZInfo(u32 value, bool begin_table) { auto const reg = reinterpret_cast(value); - if (BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + if (!begin_table || + BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { TableNextRow(); TableSetColumnIndex(0); Text("FORMAT"); @@ -796,7 +827,9 @@ static void ParseZInfo(u32 value) { TableSetColumnIndex(1); Text("%X", reg.zrange_precision.Value()); - EndTable(); + if (begin_table) { + EndTable(); + } } } diff --git a/src/core/devtools/widget/cmd_list.h b/src/core/devtools/widget/cmd_list.h index 8eb463120..5519537c8 100644 --- a/src/core/devtools/widget/cmd_list.h +++ b/src/core/devtools/widget/cmd_list.h @@ -22,6 +22,18 @@ namespace Core::Devtools::Widget { class FrameDumpViewer; +void ParsePolygonControl(u32 value, bool begin_table = true); +void ParseAaConfig(u32 value, bool begin_table = true); +void ParseViewportControl(u32 value, bool begin_table = true); +void ParseColorControl(u32 value, bool begin_table = true); +void ParseColor0Info(u32 value, bool begin_table = true); +void ParseColor0Attrib(u32 value, bool begin_table = true); +void ParseBlendControl(u32 value, bool begin_table = true); +void ParseDepthRenderControl(u32 value, bool begin_table = true); +void ParseDepthControl(u32 value, bool begin_table = true); +void ParseEqaa(u32 value, bool begin_table = true); +void ParseZInfo(u32 value, bool begin_table = true); + class CmdListViewer { const FrameDumpViewer* parent; diff --git a/src/core/devtools/widget/frame_dump.cpp b/src/core/devtools/widget/frame_dump.cpp index 4e6476dfa..b0326086c 100644 --- a/src/core/devtools/widget/frame_dump.cpp +++ b/src/core/devtools/widget/frame_dump.cpp @@ -66,11 +66,11 @@ void FrameDumpViewer::Draw() { char name[32]; snprintf(name, sizeof(name), "Frame #%d dump", id); - static ImGuiID dock_id = ImHashStr("FrameDumpDock"); - SetNextWindowDockID(dock_id, ImGuiCond_Appearing); if (Begin(name, &is_open, ImGuiWindowFlags_NoSavedSettings)) { if (IsWindowAppearing()) { auto window = GetCurrentWindow(); + static ImGuiID dock_id = ImHashStr("FrameDumpDock"); + SetWindowDock(window, dock_id, ImGuiCond_Once | ImGuiCond_FirstUseEver); SetWindowSize(window, ImVec2{470.0f, 600.0f}); } BeginGroup(); diff --git a/src/core/devtools/widget/reg_view.cpp b/src/core/devtools/widget/reg_view.cpp index fe3df1028..4a62fb35c 100644 --- a/src/core/devtools/widget/reg_view.cpp +++ b/src/core/devtools/widget/reg_view.cpp @@ -5,8 +5,10 @@ #include #include #include +#include #include +#include "cmd_list.h" #include "common/io_file.h" #include "core/devtools/options.h" #include "imgui_internal.h" @@ -17,7 +19,40 @@ #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{}; @@ -85,31 +120,142 @@ void RegView::ProcessShader(int shader_id) { }; shader_decomp.emplace(shader_id, std::move(cache)); } +void RegView::SelectShader(int id) { + selected_shader = id; + if (!shader_decomp.contains(id)) { + ProcessShader(id); + } +} + +void RegView::DrawRegs() { + const auto& regs = data.regs; + + 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 cc_mode = regs.color_control.mode.Value(); + DrawRow("Color control", "%X (%s)", cc_mode, enum_name(cc_mode).data()); + + for (int cb = 0; cb < AmdGpu::Liverpool::NumColorBuffers; ++cb) { + PushID(cb); + + TableNextRow(); + TableNextColumn(); + + const auto& buffer = regs.color_buffers[cb]; + + bool open = opened_cb[cb]; + if (!buffer || !regs.color_target_mask.GetMask(cb)) { + Text("Color buffer %d", cb); + TableNextColumn(); + TextUnformatted("N/A"); + } 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(); + } + + 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(); + } + + EndTable(); + } +} RegView::RegView() { static int unique_id = 0; id = unique_id++; - char name[64]; + char name[128]; snprintf(name, sizeof(name), "BatchView###reg_dump_%d", id); + SetNextWindowPos({400.0f, 200.0f}); + SetNextWindowSize({450.0f, 500.0f}); + ImGuiID root_dock_id; Begin(name); - SetWindowPos({400.0f, 200.0f}); - - char dock_name[64]; - snprintf(dock_name, sizeof(dock_name), "BatchView###reg_dump_%d/dock_space", id); - auto root_dock_id = ImHashStr(dock_name); - DockSpace(root_dock_id, {}, ImGuiDockNodeFlags_AutoHideTabBar); - + { + char dock_name[64]; + snprintf(dock_name, sizeof(dock_name), "BatchView###reg_dump_%d/dock_space", id); + root_dock_id = ImHashStr(dock_name); + DockSpace(root_dock_id); + } End(); ImGuiID up1, down1; - auto center = DockBuilderAddNode(root_dock_id); - DockBuilderSplitNode(center, ImGuiDir_Up, 0.2f, &up1, &down1); + DockBuilderRemoveNodeChildNodes(root_dock_id); + DockBuilderSplitNode(root_dock_id, ImGuiDir_Up, 0.2f, &up1, &down1); snprintf(name, sizeof(name), "User data###reg_dump_%d/user_data", id); DockBuilderDockWindow(name, up1); + snprintf(name, sizeof(name), "Regs###reg_dump_%d/regs", id); + DockBuilderDockWindow(name, down1); + snprintf(name, sizeof(name), "Disassembly###reg_dump_%d/disassembly", id); DockBuilderDockWindow(name, down1); @@ -120,12 +266,13 @@ void RegView::SetData(DebugStateType::RegDump data) { this->data = std::move(data); // clear cache selected_shader = -1; + opened_cb.fill(false); shader_decomp.clear(); } void RegView::Draw() { - char name[64]; + char name[128]; snprintf(name, sizeof(name), "BatchView###reg_dump_%d", id); if (Begin(name, &open, ImGuiWindowFlags_MenuBar)) { const char* names[] = {"vs", "ps", "gs", "es", "hs", "ls"}; @@ -136,50 +283,69 @@ void RegView::Draw() { if (data.regs.stage_enable.IsStageEnabled(i)) { bool selected = selected_shader == i; if (Selectable(names[i], &selected)) { - selected_shader = i; + SelectShader(i); } } } ImGui::EndMenu(); } if (BeginMenu("Windows")) { + Checkbox("Registers", &show_registers); Checkbox("User data", &show_user_data); Checkbox("Disassembly", &show_disassembly); ImGui::EndMenu(); } EndMenuBar(); } - if (selected_shader == -1) { - Text("Select a stage"); - End(); - return; - } char dock_name[64]; snprintf(dock_name, sizeof(dock_name), "BatchView###reg_dump_%d/dock_space", id); auto root_dock_id = ImHashStr(dock_name); - DockSpace(root_dock_id, {}, ImGuiDockNodeFlags_AutoHideTabBar); + DockSpace(root_dock_id); } End(); - auto shader_cache = shader_decomp.find(selected_shader); - if (shader_cache == shader_decomp.end()) { - ProcessShader(selected_shader); - return; - } - auto& shader = shader_cache->second; + auto get_shader = [&]() -> ShaderCache* { + auto shader_cache = shader_decomp.find(selected_shader); + if (shader_cache == shader_decomp.end()) { + return nullptr; + } + return &shader_cache->second; + }; - snprintf(name, sizeof(name), "User data###reg_dump_%d/user_data", id); - if (Begin(name, &show_user_data)) { - shader.hex_view.DrawContents(shader.user_data.data(), shader.user_data.size()); + if (show_user_data) { + snprintf(name, sizeof(name), "User data###reg_dump_%d/user_data", id); + if (Begin(name, &show_user_data)) { + auto shader = get_shader(); + if (!shader) { + Text("Select a stage"); + } else { + shader->hex_view.DrawContents(shader->user_data.data(), shader->user_data.size()); + } + } + End(); } - End(); - snprintf(name, sizeof(name), "Disassembly###reg_dump_%d/disassembly", id); - if (Begin(name, &show_disassembly)) { - shader.dis_view.Render("Disassembly", GetContentRegionAvail()); + if (show_disassembly) { + snprintf(name, sizeof(name), "Disassembly###reg_dump_%d/disassembly", id); + if (Begin(name, &show_disassembly)) { + auto shader = get_shader(); + if (!shader) { + Text("Select a stage"); + } else { + shader->dis_view.Render("Disassembly", GetContentRegionAvail()); + } + } + End(); + } + + if (show_registers) { + snprintf(name, sizeof(name), "Regs###reg_dump_%d/regs", id); + if (Begin(name, &show_registers)) { + DrawRegs(); + } + End(); } - End(); } } // 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 5ebf13f6b..289b67ec7 100644 --- a/src/core/devtools/widget/reg_view.h +++ b/src/core/devtools/widget/reg_view.h @@ -16,16 +16,24 @@ struct ShaderCache { class RegView { int id; + bool first_render = true; DebugStateType::RegDump data; std::unordered_map shader_decomp; int selected_shader{-1}; + std::array opened_cb{}; + + bool show_registers{true}; bool show_user_data{true}; bool show_disassembly{true}; void ProcessShader(int shader_id); + void SelectShader(int shader_id); + + void DrawRegs(); + public: bool open = false; diff --git a/src/imgui/renderer/imgui_core.cpp b/src/imgui/renderer/imgui_core.cpp index 311e86a3c..75538c1d0 100644 --- a/src/imgui/renderer/imgui_core.cpp +++ b/src/imgui/renderer/imgui_core.cpp @@ -80,6 +80,8 @@ 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(); diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 8d92fe3c6..a4cf79334 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -772,6 +772,8 @@ struct Liverpool { BitField<27, 1, u32> fmask_compress_1frag_only; BitField<28, 1, u32> dcc_enable; BitField<29, 1, u32> cmask_addr_type; + + u32 u32all; } info; union Color0Attrib { BitField<0, 5, TilingMode> tile_mode_index; @@ -780,6 +782,8 @@ struct Liverpool { BitField<12, 3, u32> num_samples_log2; BitField<15, 2, u32> num_fragments_log2; BitField<17, 1, u32> force_dst_alpha_1; + + u32 u32all; } attrib; INSERT_PADDING_WORDS(1); u32 cmask_base_address;