From 2c8e78408bd02c9dcfe6366bf681ecde4a7e1c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 6 Dec 2024 09:18:28 +0100 Subject: [PATCH] Add basic vertex data viewer (with the same flaws as the old one) --- GPU/Common/DrawEngineCommon.cpp | 3 + GPU/Common/GPUDebugInterface.h | 2 +- GPU/Debugger/State.h | 2 +- GPU/GPUCommon.cpp | 14 ++++- GPU/GPUCommon.h | 2 +- UI/ImDebugger/ImGe.cpp | 90 +++++++++++++++++++++++++++++- Windows/GEDebugger/TabVertices.cpp | 13 +---- 7 files changed, 107 insertions(+), 19 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 4b9659c45a..7ef2a88041 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -691,6 +691,9 @@ bool DrawEngineCommon::GetCurrentSimpleVertices(int count, std::vector ActiveDisplayLists() = 0; virtual void ResetListPC(int listID, u32 pc) = 0; virtual void ResetListStall(int listID, u32 stall) = 0; diff --git a/GPU/Debugger/State.h b/GPU/Debugger/State.h index 7b9b396ea7..005a23c984 100644 --- a/GPU/Debugger/State.h +++ b/GPU/Debugger/State.h @@ -59,11 +59,11 @@ enum VertexListCols { VERTEXLIST_COL_NX, VERTEXLIST_COL_NY, VERTEXLIST_COL_NZ, + VERTEXLIST_COL_COUNT, }; class GPUDebugInterface; - struct TabStateRow { std::string_view title; uint8_t cmd; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 0b045fdbfa..2005ba08fa 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1581,13 +1581,21 @@ bool GPUCommon::GetCurrentDisplayList(DisplayList &list) { return true; } -bool GPUCommon::GetCurrentCommand(u32 *cmd) { +int GPUCommon::GetCurrentPrimCount() { DisplayList list; if (GetCurrentDisplayList(list)) { - *cmd = Memory::Read_U32(list.pc); + u32 cmd = Memory::Read_U32(list.pc); + if ((cmd >> 24) == GE_CMD_PRIM || (cmd >> 24) == GE_CMD_BOUNDINGBOX) { + return cmd & 0xFFFF; + } else if ((cmd >> 24) == GE_CMD_BEZIER || (cmd >> 24) == GE_CMD_SPLINE) { + u32 u = (cmd & 0x00FF) >> 0; + u32 v = (cmd & 0xFF00) >> 8; + return u * v; + } return true; } else { - return false; + // Current prim value. + return gstate.cmdmem[GE_CMD_PRIM] & 0xFFFF; } } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index c36f20c6af..316d2e9eeb 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -328,7 +328,7 @@ public: // From GPUDebugInterface. bool GetCurrentDisplayList(DisplayList &list) override; bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) override; - bool GetCurrentCommand(u32 *cmd) override; + int GetCurrentPrimCount() override; FramebufferManagerCommon *GetFramebufferManagerCommon() override { return nullptr; } diff --git a/UI/ImDebugger/ImGe.cpp b/UI/ImDebugger/ImGe.cpp index cc0e339890..32adfa374b 100644 --- a/UI/ImDebugger/ImGe.cpp +++ b/UI/ImDebugger/ImGe.cpp @@ -5,6 +5,7 @@ #include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/FramebufferManagerCommon.h" #include "GPU/Common/TextureCacheCommon.h" +#include "GPU/Common/VertexDecoderCommon.h" #include "Core/HLE/sceDisplay.h" #include "Core/HW/Display.h" @@ -96,7 +97,6 @@ void DrawGeStateWindow(ImConfig &cfg, GPUDebugInterface *gpuDebug) { ImGui::End(); return; } - if (ImGui::BeginTabBar("GeRegs", ImGuiTabBarFlags_None)) { auto buildStateTab = [&](const char *tabName, const TabStateRow *rows, size_t numRows) { if (ImGui::BeginTabItem(tabName)) { @@ -135,6 +135,94 @@ void DrawGeStateWindow(ImConfig &cfg, GPUDebugInterface *gpuDebug) { buildStateTab("Texture", g_stateTextureRows, g_stateTextureRowsSize); buildStateTab("Settings", g_stateSettingsRows, g_stateSettingsRowsSize); + // Do a vertex tab (maybe later a separate window) + if (ImGui::BeginTabItem("Vertices")) { + const ImGuiTableFlags tableFlags = + ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_ScrollY; + if (ImGui::BeginTabBar("vertexmode", ImGuiTabBarFlags_None)) { + auto state = gpuDebug->GetGState(); + char fmtTemp[256]; + FormatStateRow(gpuDebug, fmtTemp, sizeof(fmtTemp), CMD_FMT_VERTEXTYPE, state.vertType, true, false, false); + ImGui::TextUnformatted(fmtTemp); + // Let's see if it's fast enough to just do all this each frame. + int rowCount_ = gpuDebug->GetCurrentPrimCount(); + std::vector vertices; + std::vector indices; + if (!gpuDebug->GetCurrentSimpleVertices(rowCount_, vertices, indices)) { + rowCount_ = 0; + } + VertexDecoderOptions options{}; + // TODO: Maybe an option? + options.applySkinInDecode = true; + + auto buildVertexTable = [&](bool raw) { + // Ignore indices for now. + if (ImGui::BeginTable("rawverts", VERTEXLIST_COL_COUNT + 1, tableFlags)) { + static VertexDecoder decoder; + decoder.SetVertexType(state.vertType, options); + + static const char *colNames[] = { + "Index", + "X", + "Y", + "Z", + "U", + "V", + "Color", + "NX", + "NY", + "NZ", + }; + for (int i = 0; i < ARRAY_SIZE(colNames); i++) { + ImGui::TableSetupColumn(colNames[i], ImGuiTableColumnFlags_WidthFixed, 0.0f, i); + } + ImGui::TableSetupScrollFreeze(0, 1); // Make header row always visible + ImGui::TableHeadersRow(); + + ImGuiListClipper clipper; + _dbg_assert_(rowCount_ >= 0); + clipper.Begin(rowCount_); + while (clipper.Step()) { + for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { + int index = indices.empty() ? i : indices[i]; + ImGui::PushID(i); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("%d", index); + for (int column = 0; column < VERTEXLIST_COL_COUNT; column++) { + ImGui::TableNextColumn(); + char temp[36]; + if (raw) { + FormatVertColRaw(&decoder, temp, sizeof(temp), index, column); + } else { + FormatVertCol(temp, sizeof(temp), vertices[index], column); + } + ImGui::TextUnformatted(temp); + } + ImGui::PopID(); + } + } + clipper.End(); + + ImGui::EndTable(); + } + }; + + if (ImGui::BeginTabItem("Raw")) { + buildVertexTable(true); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Transformed")) { + buildVertexTable(false); + ImGui::EndTabItem(); + } + // TODO: Let's not include columns for which we have no data. + ImGui::EndTabBar(); + } + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); } ImGui::End(); diff --git a/Windows/GEDebugger/TabVertices.cpp b/Windows/GEDebugger/TabVertices.cpp index b693752059..5d18b1d9d3 100644 --- a/Windows/GEDebugger/TabVertices.cpp +++ b/Windows/GEDebugger/TabVertices.cpp @@ -168,19 +168,8 @@ int CtrlVertexList::GetRowCount() { // TODO: Maybe there are smarter ways? Also, is this the best place to recalc? auto state = gpuDebug->GetGState(); - rowCount_ = state.prim & 0xFFFF; - // Override if we're on a prim command. - u32 cmd; - if (gpuDebug->GetCurrentCommand(&cmd)) { - if ((cmd >> 24) == GE_CMD_PRIM || (cmd >> 24) == GE_CMD_BOUNDINGBOX) { - rowCount_ = cmd & 0xFFFF; - } else if ((cmd >> 24) == GE_CMD_BEZIER || (cmd >> 24) == GE_CMD_SPLINE) { - u32 u = (cmd & 0x00FF) >> 0; - u32 v = (cmd & 0xFF00) >> 8; - rowCount_ = u * v; - } - } + int rowCount_ = gpuDebug->GetCurrentPrimCount(); if (!gpuDebug->GetCurrentSimpleVertices(rowCount_, vertices, indices)) { rowCount_ = 0; }