Devtools - Inspect regs/User data/Shader disassembly (#1358)

* devtools: pm4 - show markers

* SaveDataDialogLib: fix compile with mingw

* devtools: pm4 - show program state

* devtools: pm4 - show program disassembly

* devtools: pm4 - show frame regs

* devtools: pm4 - show color buffer info as popup

add ux improvements for open new windows with shift+click
better window titles

* imgui: skip all textures to avoid hanging with crash diagnostic enabled

not sure why this happens :c

* devtools: pm4 - show reg depth buffer
This commit is contained in:
Vinicius Rangel 2024-10-13 09:02:22 -03:00 committed by GitHub
parent 8776eba8c8
commit cf2e617f08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 4215 additions and 287 deletions

View file

@ -10,6 +10,7 @@
#include "imgui/imgui_std.h"
#include "imgui_internal.h"
#include "layer.h"
#include "options.h"
#include "widget/frame_dump.h"
#include "widget/frame_graph.h"
@ -18,10 +19,9 @@ using namespace Core::Devtools;
using L = Core::Devtools::Layer;
static bool show_simple_fps = false;
static float fps_scale = 1.0f;
static bool show_advanced_debug = false;
static int dump_frame_count = 1;
static Widget::FrameGraph frame_graph;
@ -29,12 +29,16 @@ static std::vector<Widget::FrameDumpViewer> frame_viewers;
static float debug_popup_timing = 3.0f;
static bool just_opened_options = false;
void L::DrawMenuBar() {
const auto& ctx = *GImGui;
const auto& io = ctx.IO;
auto isSystemPaused = DebugState.IsGuestThreadsPaused();
bool open_popup_options = false;
if (BeginMainMenuBar()) {
if (BeginMenu("Options")) {
if (MenuItemEx("Emulator Paused", nullptr, nullptr, isSystemPaused)) {
@ -55,6 +59,7 @@ void L::DrawMenuBar() {
}
ImGui::EndMenu();
}
open_popup_options = MenuItem("Options");
ImGui::EndMenu();
}
EndMainMenuBar();
@ -74,6 +79,11 @@ void L::DrawMenuBar() {
}
}
}
if (open_popup_options) {
OpenPopup("GPU Tools Options");
just_opened_options = true;
}
}
void L::DrawAdvanced() {
@ -91,13 +101,19 @@ void L::DrawAdvanced() {
->AddText({10.0f, io.DisplaySize.y - 40.0f}, IM_COL32_WHITE, "Emulator paused");
}
if (DebugState.should_show_frame_dump) {
if (DebugState.should_show_frame_dump && DebugState.waiting_reg_dumps.empty()) {
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");
}
}
@ -133,6 +149,30 @@ void L::DrawAdvanced() {
debug_popup_timing = 3.0f;
}
}
bool close_popup_options = true;
if (BeginPopupModal("GPU Tools Options", &close_popup_options,
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings)) {
static char disassembly_cli[512];
if (just_opened_options) {
just_opened_options = false;
auto s = Options.disassembly_cli.copy(disassembly_cli, sizeof(disassembly_cli) - 1);
disassembly_cli[s] = '\0';
}
InputText("Shader disassembler: ", disassembly_cli, sizeof(disassembly_cli));
if (IsItemHovered()) {
SetTooltip(R"(Command to disassemble shaders. Example "dis.exe" --raw "{src}")");
}
if (Button("Save")) {
Options.disassembly_cli = disassembly_cli;
SaveIniSettingsToDisk(io.IniFilename);
CloseCurrentPopup();
}
EndPopup();
}
}
void L::DrawSimple() {
@ -140,26 +180,54 @@ void L::DrawSimple() {
Text("Frame time: %.3f ms (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
}
static void LoadSettings(const char* line) {
int i;
float f;
if (sscanf(line, "fps_scale=%f", &f) == 1) {
fps_scale = f;
return;
}
if (sscanf(line, "show_advanced_debug=%d", &i) == 1) {
show_advanced_debug = i != 0;
return;
}
if (sscanf(line, "show_frame_graph=%d", &i) == 1) {
frame_graph.is_open = i != 0;
return;
}
if (sscanf(line, "dump_frame_count=%d", &i) == 1) {
dump_frame_count = i;
return;
}
}
void L::SetupSettings() {
frame_graph.is_open = true;
using SettingLoader = void (*)(const char*);
ImGuiSettingsHandler handler{};
handler.TypeName = "DevtoolsLayer";
handler.TypeHash = ImHashStr(handler.TypeName);
handler.ReadOpenFn = [](ImGuiContext*, ImGuiSettingsHandler*, const char* name) {
return std::string_view("Data") == name ? (void*)1 : nullptr;
if (std::string_view("Data") == name) {
static_assert(std::is_same_v<decltype(&LoadSettings), SettingLoader>);
return (void*)&LoadSettings;
}
if (std::string_view("CmdList") == name) {
static_assert(
std::is_same_v<decltype(&Widget::CmdListViewer::LoadConfig), SettingLoader>);
return (void*)&Widget::CmdListViewer::LoadConfig;
}
if (std::string_view("Options") == name) {
static_assert(std::is_same_v<decltype(&LoadOptionsConfig), SettingLoader>);
return (void*)&LoadOptionsConfig;
}
return (void*)nullptr;
};
handler.ReadLineFn = [](ImGuiContext*, ImGuiSettingsHandler*, void*, const char* line) {
int v;
float f;
if (sscanf(line, "fps_scale=%f", &f) == 1) {
fps_scale = f;
} else if (sscanf(line, "show_advanced_debug=%d", &v) == 1) {
show_advanced_debug = v != 0;
} else if (sscanf(line, "show_frame_graph=%d", &v) == 1) {
frame_graph.is_open = v != 0;
} else if (sscanf(line, "dump_frame_count=%d", &v) == 1) {
dump_frame_count = v;
handler.ReadLineFn = [](ImGuiContext*, ImGuiSettingsHandler*, void* handle, const char* line) {
if (handle != nullptr) {
reinterpret_cast<SettingLoader>(handle)(line);
}
};
handler.WriteAllFn = [](ImGuiContext*, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) {
@ -169,12 +237,19 @@ void L::SetupSettings() {
buf->appendf("show_frame_graph=%d\n", frame_graph.is_open);
buf->appendf("dump_frame_count=%d\n", dump_frame_count);
buf->append("\n");
buf->appendf("[%s][CmdList]\n", handler->TypeName);
Widget::CmdListViewer::SerializeConfig(buf);
buf->append("\n");
buf->appendf("[%s][Options]\n", handler->TypeName);
SerializeOptionsConfig(buf);
buf->append("\n");
};
AddSettingsHandler(&handler);
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);
}