Ge Debugger: Add a framebuffer listing, along with some plumbing

This commit is contained in:
Henrik Rydgård 2024-11-21 14:12:17 +01:00
parent 21ffc37ebd
commit d068f79f78
15 changed files with 143 additions and 31 deletions

View File

@ -457,6 +457,8 @@ public:
int MultiSampleLevel() const { return multiSampleLevel_; }
virtual void UpdateTag(const char *tag) {}
virtual const char *Tag() { return "(no name)"; }
protected:
int width_ = -1, height_ = -1, layers_ = 1, multiSampleLevel_ = 0;
};

View File

@ -19,6 +19,8 @@
#include <sstream>
#include <cmath>
#include "ext/imgui/imgui.h"
#include "Common/GPU/thin3d.h"
#include "Common/GPU/OpenGL/GLFeatures.h"
#include "Common/Data/Collections/TinySet.h"
@ -3661,3 +3663,44 @@ static void ApplyKillzoneFramebufferSplit(FramebufferHeuristicParams *params, in
*drawing_width = 480;
}
}
void FramebufferManagerCommon::DrawImGuiDebug(int &selected) const {
ImGui::BeginTable("framebuffers", 4);
ImGui::TableSetupColumn("Tag");
ImGui::TableSetupColumn("Color Addr");
ImGui::TableSetupColumn("Depth Addr");
ImGui::TableSetupColumn("Size");
ImGui::TableHeadersRow();
ImGui::TableSetColumnIndex(0);
for (int i = 0; i < (int)vfbs_.size(); i++) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
auto &vfb = vfbs_[i];
const char *tag = vfb->fbo ? vfb->fbo->Tag() : "(no tag)";
ImGui::PushID(i);
if (ImGui::Selectable(tag, selected == i, ImGuiSelectableFlags_AllowDoubleClick | ImGuiSelectableFlags_SpanAllColumns)) {
selected = i;
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
selected = i;
ImGui::OpenPopup("framebufferPopup");
}
ImGui::TableNextColumn();
ImGui::Text("%08x", vfb->fb_address);
ImGui::TableNextColumn();
ImGui::Text("%08x", vfb->z_address);
ImGui::TableNextColumn();
ImGui::Text("%dx%d", vfb->width, vfb->height);
if (ImGui::BeginPopup("framebufferPopup")) {
ImGui::Text("Framebuffer: %s", tag);
ImGui::EndPopup();
}
ImGui::PopID();
}
ImGui::EndTable();
}

View File

@ -488,6 +488,8 @@ public:
bool PresentedThisFrame() const;
void DrawImGuiDebug(int &selected) const;
protected:
virtual void ReadbackFramebuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode);
// Used for when a shader is required, such as GLES.

View File

@ -25,6 +25,8 @@
#include "GPU/GPU.h"
#include "GPU/GPUInterface.h"
class FramebufferManagerCommon;
struct GPUDebugOp {
u32 pc;
u8 cmd;
@ -218,6 +220,9 @@ public:
virtual uint32_t SetAddrTranslation(uint32_t value) = 0;
virtual uint32_t GetAddrTranslation() = 0;
// TODO: Make a proper debug interface instead of accessing directly?
virtual FramebufferManagerCommon *GetFramebufferManagerCommon() = 0;
virtual bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) {
return false;

View File

@ -181,6 +181,10 @@ public:
bool GetCurrentDisplayList(DisplayList &list) override;
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) override;
FramebufferManagerCommon *GetFramebufferManagerCommon() override {
return nullptr;
}
std::vector<std::string> DebugGetShaderIDs(DebugShaderType shader) override { return std::vector<std::string>(); };
std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override {
return "N/A";

View File

@ -28,6 +28,10 @@ public:
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override;
bool GetCurrentClut(GPUDebugBuffer &buffer) override;
FramebufferManagerCommon *GetFramebufferManagerCommon() override {
return framebufferManager_;
}
// Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend.
std::vector<std::string> DebugGetShaderIDs(DebugShaderType shader) override;
std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override;

View File

@ -1656,7 +1656,7 @@ void EmuScreen::renderImDebugger() {
ImGui_ImplThin3d_NewFrame(draw, ui_draw2d.GetDrawMatrix());
ImGui::NewFrame();
imDebugger_->Frame(currentDebugMIPS);
imDebugger_->Frame(currentDebugMIPS, gpuDebug);
ImGui::Render();
ImGui_ImplThin3d_RenderDrawData(ImGui::GetDrawData(), draw);

View File

@ -26,7 +26,11 @@
// Callstack window
#include "Core/MIPS/MIPSStackWalk.h"
// GPU things
#include "GPU/Common/GPUDebugInterface.h"
#include "UI/ImDebugger/ImDebugger.h"
#include "UI/ImDebugger/ImGe.h"
void DrawRegisterView(MIPSDebugInterface *mipsDebug, bool *open) {
if (!ImGui::Begin("Registers", open)) {
@ -332,7 +336,7 @@ void DrawHLEModules(ImConfig &config) {
ImGui::End();
}
void ImDebugger::Frame(MIPSDebugInterface *mipsDebug) {
void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebug) {
// Snapshot the coreState to avoid inconsistency.
const CoreState coreState = ::coreState;
@ -370,14 +374,23 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug) {
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Window")) {
ImGui::Checkbox("Dear ImGUI Demo", &cfg_.demoOpen);
if (ImGui::BeginMenu("CPU")) {
ImGui::Checkbox("CPU debugger", &cfg_.disasmOpen);
ImGui::Checkbox("Registers", &cfg_.regsOpen);
ImGui::Checkbox("Callstacks", &cfg_.callstackOpen);
ImGui::Checkbox("HLE Modules", &cfg_.modulesOpen);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("OS HLE")) {
ImGui::Checkbox("HLE Threads", &cfg_.threadsOpen);
ImGui::Checkbox("HLE Modules", &cfg_.modulesOpen);
ImGui::Checkbox("sceAtrac", &cfg_.atracOpen);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Ge (GPU)")) {
ImGui::Checkbox("Framebuffers", &cfg_.framebuffersOpen);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Tools")) {
ImGui::Checkbox("Struct viewer", &cfg_.structViewerOpen);
ImGui::EndMenu();
}
@ -385,6 +398,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug) {
if (ImGui::MenuItem("Close Debugger")) {
g_Config.bShowImDebugger = false;
}
ImGui::Checkbox("Dear ImGUI Demo", &cfg_.demoOpen);
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
@ -422,6 +436,10 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug) {
DrawHLEModules(cfg_);
}
if (cfg_.framebuffersOpen) {
DrawFramebuffersWindow(cfg_, gpuDebug->GetFramebufferManagerCommon());
}
if (cfg_.structViewerOpen) {
structViewer_.Draw(mipsDebug, &cfg_.structViewerOpen);
}

View File

@ -15,6 +15,7 @@
#include "UI/ImDebugger/ImDisasmView.h"
#include "UI/ImDebugger/ImStructViewer.h"
#include "UI/ImDebugger/ImGe.h"
// This is the main state container of the whole Dear ImGUI-based in-game cross-platform debugger.
//
@ -22,7 +23,7 @@
// * If windows/objects need state, prefix the class name with Im and just store straight in parent struct
class MIPSDebugInterface;
class GPUDebugInterface;
// Corresponds to the CDisasm dialog
class ImDisasmWindow {
@ -59,6 +60,7 @@ struct ImConfig {
bool hleModulesOpen = false;
bool atracOpen = true;
bool structViewerOpen = false;
bool framebuffersOpen = false;
// HLE explorer settings
// bool filterByUsed = true;
@ -66,10 +68,11 @@ struct ImConfig {
// Various selections
int selectedModule = 0;
int selectedThread = 0;
int selectedFramebuffer = -1;
};
struct ImDebugger {
void Frame(MIPSDebugInterface *mipsDebug);
void Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebug);
ImDisasmWindow disasm_;
ImLuaConsole luaConsole_;

View File

@ -2,6 +2,7 @@
#include "ext/imgui/imgui_internal.h"
#include "Common/StringUtils.h"
#include "Common/Log.h"
#include "Core/Core.h"
#include "Core/Debugger/DebugInterface.h"
#include "Core/Debugger/DisassemblyManager.h"
@ -417,11 +418,11 @@ void ImDisasmView::Draw(ImDrawList *drawList) {
line.params += line.info.conditionMet ? " ; true" : " ; false";
}
drawArguments(drawList, rect, line, pixelPositions_.argumentsStart, rowY1 + 2, textColor, currentArguments);
drawArguments(drawList, rect, line, pixelPositions_.argumentsStart, rowY1 + 2.f, textColor, currentArguments);
// The actual opcode.
// Should be bold!
drawList->AddText(ImVec2(rect.left + pixelPositions_.opcodeStart, rect.top + rowY1 + 2), textColor, line.name.c_str());
drawList->AddText(ImVec2(rect.left + pixelPositions_.opcodeStart, rect.top + rowY1 + 2.f), textColor, line.name.c_str());
address += line.totalSize;
}
@ -707,7 +708,7 @@ void ImDisasmView::toggleBreakpoint(bool toggleEnabled) {
}
}
void ImDisasmView::onMouseDown(int x, int y, int button) {
void ImDisasmView::onMouseDown(float x, float y, int button) {
u32 newAddress = yToAddress(y);
bool extend = ImGui::IsKeyDown(ImGuiKey_LeftShift);
if (button == 1) {
@ -722,6 +723,20 @@ void ImDisasmView::onMouseDown(int x, int y, int button) {
setCurAddress(newAddress, extend);
}
void ImDisasmView::onMouseMove(float x, float y, int button) {
if ((button & 1) != 0) {
setCurAddress(yToAddress(y), ImGui::IsKeyDown(ImGuiKey_LeftShift));
}
}
void ImDisasmView::onMouseUp(float x, float y, int button) {
if (button == 1) {
if (ImGui::IsKeyDown(ImGuiKey_LeftShift)) {
setCurAddress(yToAddress(y), true);
}
}
}
void ImDisasmView::CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructionsMode mode) {
_assert_msg_((startAddr & 3) == 0, "readMemory() can't handle unaligned reads");
@ -758,14 +773,6 @@ void ImDisasmView::NopInstructions(u32 selectRangeStart, u32 selectRangeEnd) {
}
}
void ImDisasmView::onMouseUp(int x, int y, int button) {
if (button == 1) {
if (ImGui::IsKeyDown(ImGuiKey_LeftShift)) {
setCurAddress(yToAddress(y), true);
}
}
}
void ImDisasmView::PopupMenu() {
if (ImGui::BeginPopup("context")) {
ImGui::Text("Address: %08x", curAddress_);
@ -891,12 +898,6 @@ void ImDisasmView::PopupMenu() {
}
}
void ImDisasmView::onMouseMove(int x, int y, int button) {
if ((button & 1) != 0) {
setCurAddress(yToAddress(y), ImGui::IsKeyDown(ImGuiKey_LeftShift));
}
}
void ImDisasmView::updateStatusBarText() {
auto memLock = Memory::Lock();
if (!PSP_IsInited())
@ -997,8 +998,8 @@ void ImDisasmView::updateStatusBarText() {
}
}
u32 ImDisasmView::yToAddress(int y) {
int line = y / rowHeight_;
u32 ImDisasmView::yToAddress(float y) {
int line = (int)(y / rowHeight_);
return manager.getNthNextAddress(windowStart_, line);
}

View File

@ -7,7 +7,6 @@
#include "ext/imgui/imgui.h"
#include "Common/CommonTypes.h"
#include "Common/Log.h"
#include "Core/Debugger/DisassemblyManager.h"
#include "Core/Debugger/DebugInterface.h"
@ -31,16 +30,16 @@ public:
void onChar(int c);
void onKeyDown(ImGuiKey key);
void onMouseDown(int x, int y, int button);
void onMouseUp(int x, int y, int button);
void onMouseMove(int x, int y, int button);
void onMouseDown(float x, float y, int button);
void onMouseUp(float x, float y, int button);
void onMouseMove(float x, float y, int button);
void scrollAddressIntoView();
bool curAddressIsVisible();
void ScanVisibleFunctions();
void clearFunctions() { manager.clear(); };
void getOpcodeText(u32 address, char* dest, int bufsize);
u32 yToAddress(int y);
u32 yToAddress(float y);
void setDebugger(DebugInterface *deb) {
if (debugger != deb) {

14
UI/ImDebugger/ImGe.cpp Normal file
View File

@ -0,0 +1,14 @@
#include "UI/ImDebugger/ImGe.h"
#include "UI/ImDebugger/ImDebugger.h"
#include "GPU/Common/FramebufferManagerCommon.h"
void DrawFramebuffersWindow(ImConfig &cfg, FramebufferManagerCommon *framebufferManager) {
if (!ImGui::Begin("Framebuffers", &cfg.framebuffersOpen)) {
ImGui::End();
return;
}
framebufferManager->DrawImGuiDebug(cfg.selectedFramebuffer);
ImGui::End();
}

9
UI/ImDebugger/ImGe.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
// GE-related windows of the ImDebugger
struct ImConfig;
class FramebufferManagerCommon;
void DrawFramebuffersWindow(ImConfig &cfg, FramebufferManagerCommon *framebufferManager);

View File

@ -53,6 +53,7 @@
<ClCompile Include="GPUDriverTestScreen.cpp" />
<ClCompile Include="ImDebugger\ImDebugger.cpp" />
<ClCompile Include="ImDebugger\ImDisasmView.cpp" />
<ClCompile Include="ImDebugger\ImGe.cpp" />
<ClCompile Include="ImDebugger\ImStructViewer.cpp" />
<ClCompile Include="JitCompareScreen.cpp" />
<ClCompile Include="JoystickHistoryView.cpp" />
@ -96,6 +97,7 @@
<ClInclude Include="GPUDriverTestScreen.h" />
<ClInclude Include="ImDebugger\ImDebugger.h" />
<ClInclude Include="ImDebugger\ImDisasmView.h" />
<ClInclude Include="ImDebugger\ImGe.h" />
<ClInclude Include="ImDebugger\ImStructViewer.h" />
<ClInclude Include="JitCompareScreen.h" />
<ClInclude Include="JoystickHistoryView.h" />

View File

@ -107,6 +107,9 @@
<ClCompile Include="ImDebugger\ImStructViewer.cpp">
<Filter>ImDebugger</Filter>
</ClCompile>
<ClCompile Include="ImDebugger\ImGe.cpp">
<Filter>ImDebugger</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GameInfoCache.h" />
@ -214,6 +217,9 @@
<ClInclude Include="ImDebugger\ImStructViewer.h">
<Filter>ImDebugger</Filter>
</ClInclude>
<ClInclude Include="ImDebugger\ImGe.h">
<Filter>ImDebugger</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Screens">