From e7eca477b0659aa41550ef83a03da47e791bc2f4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 8 Feb 2014 20:42:23 -0800 Subject: [PATCH] Add a tab to show vertex values to the GE debugger. Should be pretty useful, especially for depth issues. --- GPU/Common/GPUDebugInterface.h | 1 + GPU/GLES/TransformPipeline.cpp | 28 ++- GPU/Software/TransformUnit.cpp | 28 ++- Windows/GEDebugger/GEDebugger.cpp | 6 + Windows/GEDebugger/GEDebugger.h | 2 + Windows/GEDebugger/TabVertices.cpp | 270 +++++++++++++++++++++++++++++ Windows/GEDebugger/TabVertices.h | 71 ++++++++ Windows/PPSSPP.vcxproj | 2 + Windows/PPSSPP.vcxproj.filters | 6 + Windows/ppsspp.rc | 10 ++ Windows/resource.h | 9 +- 11 files changed, 422 insertions(+), 11 deletions(-) create mode 100644 Windows/GEDebugger/TabVertices.cpp create mode 100644 Windows/GEDebugger/TabVertices.h diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h index fec1972bff..5c9ef9cd66 100644 --- a/GPU/Common/GPUDebugInterface.h +++ b/GPU/Common/GPUDebugInterface.h @@ -183,6 +183,7 @@ struct GPUDebugVertex { float x; float y; float z; + u8 c[4]; }; class GPUDebugInterface { diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 7c3e04a35f..bf9b0d2c81 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -909,22 +909,42 @@ bool TransformDrawEngine::GetCurrentSimpleVertices(int count, std::vectorAddTabDialog(settings, L"Settings"); + vertices = new TabVertices(_hInstance, m_hDlg); + tabs->AddTabDialog(vertices, L"Vertices"); + lists = new TabDisplayLists(_hInstance, m_hDlg); tabs->AddTabDialog(lists, L"Lists"); @@ -121,6 +125,7 @@ CGEDebugger::~CGEDebugger() { delete lighting; delete textureState; delete settings; + delete vertices; delete lists; delete tabs; delete fbTabs; @@ -227,6 +232,7 @@ void CGEDebugger::UpdatePreviews() { lighting->Update(); textureState->Update(); settings->Update(); + vertices->Update(); lists->Update(); } diff --git a/Windows/GEDebugger/GEDebugger.h b/Windows/GEDebugger/GEDebugger.h index 6e968609e6..015248e34f 100644 --- a/Windows/GEDebugger/GEDebugger.h +++ b/Windows/GEDebugger/GEDebugger.h @@ -49,6 +49,7 @@ class TabStateFlags; class TabStateLighting; class TabStateTexture; class TabStateSettings; +class TabVertices; class CGEDebugger : public Dialog { public: @@ -75,6 +76,7 @@ private: TabStateLighting *lighting; TabStateTexture *textureState; TabStateSettings *settings; + TabVertices *vertices; SimpleGLWindow *frameWindow; SimpleGLWindow *texWindow; TabControl *tabs; diff --git a/Windows/GEDebugger/TabVertices.cpp b/Windows/GEDebugger/TabVertices.cpp new file mode 100644 index 0000000000..0b1479dd22 --- /dev/null +++ b/Windows/GEDebugger/TabVertices.cpp @@ -0,0 +1,270 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "base/basictypes.h" +#include "Windows/resource.h" +#include "Windows/GEDebugger/GEDebugger.h" +#include "Windows/GEDebugger/TabVertices.h" +#include "GPU/GLES/VertexDecoder.h" +#include "GPU/GPUState.h" +#include "GPU/GeDisasm.h" +#include "GPU/Common/GPUDebugInterface.h" + +static const GenericListViewColumn vertexListCols[] = { + { L"X", 0.17f }, + { L"Y", 0.17f }, + { L"Z", 0.17f }, + { L"U", 0.16f }, + { L"V", 0.16f }, + { L"Color", 0.17f }, + // TODO: Normal, weight, morph? +}; + +enum VertexListCols { + VERTEXLIST_COL_X, + VERTEXLIST_COL_Y, + VERTEXLIST_COL_Z, + VERTEXLIST_COL_U, + VERTEXLIST_COL_V, + VERTEXLIST_COL_COLOR, +}; + +CtrlVertexList::CtrlVertexList(HWND hwnd) + : GenericListControl(hwnd, vertexListCols, ARRAY_SIZE(vertexListCols)), raw_(false) { + decoder = new VertexDecoder(); + Update(); +} + +CtrlVertexList::~CtrlVertexList() { + delete decoder; +} + +void CtrlVertexList::GetColumnText(wchar_t *dest, int row, int col) { + if (row < 0 || row >= rowCount_ ) { + wcscpy(dest, L"Invalid"); + return; + } + + if (!indices.empty()) { + if (row >= indices.size()) { + swprintf(dest, L"Invalid indice %d", row); + return; + } + row = indices[row]; + } + + if (raw_) { + FormatVertColRaw(dest, row, col); + } else { + if (row >= vertices.size()) { + swprintf(dest, L"Invalid vertex %d", row); + return; + } + + FormatVertCol(dest, vertices[row], col); + } +} + +void CtrlVertexList::FormatVertCol(wchar_t *dest, const GPUDebugVertex &vert, int col) { + switch (col) { + case VERTEXLIST_COL_X: + swprintf(dest, L"%f", vert.x); + break; + case VERTEXLIST_COL_Y: + swprintf(dest, L"%f", vert.y); + break; + case VERTEXLIST_COL_Z: + swprintf(dest, L"%f", vert.z); + break; + case VERTEXLIST_COL_U: + swprintf(dest, L"%f", vert.u); + break; + case VERTEXLIST_COL_V: + swprintf(dest, L"%f", vert.v); + break; + case VERTEXLIST_COL_COLOR: + swprintf(dest, L"%02x%02x%02x%02x", vert.c[0], vert.c[1], vert.c[2], vert.c[3]); + break; + + default: + wcscpy(dest, L"Invalid"); + break; + } +} + +void CtrlVertexList::FormatVertColRaw(wchar_t *dest, int row, int col) { + // We could use the vertex decoder and reader, but those already do some minor adjustments. + // There's only a few values - let's just go after them directly. + const u8 *vert = Memory::GetPointer(gpuDebug->GetVertexAddress()) + row * decoder->size; + const u8 *pos = vert + decoder->posoff; + const u8 *tc = vert + decoder->tcoff; + const u8 *color = vert + decoder->coloff; + + switch (col) { + case VERTEXLIST_COL_X: + FormatVertColRawType(dest, pos, decoder->pos, 0); + break; + case VERTEXLIST_COL_Y: + FormatVertColRawType(dest, pos, decoder->pos, 1); + break; + case VERTEXLIST_COL_Z: + FormatVertColRawType(dest, pos, decoder->pos, 2); + break; + case VERTEXLIST_COL_U: + FormatVertColRawType(dest, tc, decoder->tc, 0); + break; + case VERTEXLIST_COL_V: + FormatVertColRawType(dest, tc, decoder->tc, 1); + break; + case VERTEXLIST_COL_COLOR: + FormatVertColRawColor(dest, color, decoder->col); + break; + + default: + wcscpy(dest, L"Invalid"); + break; + } +} + +void CtrlVertexList::FormatVertColRawType(wchar_t *dest, const void *data, int type, int offset) { + switch (type) { + case 0: + wcscpy(dest, L"-"); + break; + + case 1: // 8-bit + swprintf(dest, L"%02x", ((const u8 *)data)[offset]); + break; + + case 2: // 16-bit + swprintf(dest, L"%04x", ((const u16_le *)data)[offset]); + break; + + case 3: // float + swprintf(dest, L"%f", ((const float *)data)[offset]); + break; + + default: + wcscpy(dest, L"Invalid"); + break; + } +} + +void CtrlVertexList::FormatVertColRawColor(wchar_t *dest, const void *data, int type) { + switch (type) { + case GE_VTYPE_COL_NONE >> GE_VTYPE_COL_SHIFT: + wcscpy(dest, L"-"); + break; + + case GE_VTYPE_COL_565 >> GE_VTYPE_COL_SHIFT: + case GE_VTYPE_COL_5551 >> GE_VTYPE_COL_SHIFT: + case GE_VTYPE_COL_4444 >> GE_VTYPE_COL_SHIFT: + swprintf(dest, L"%04x", *(const u16_le *)data); + break; + + case GE_VTYPE_COL_8888 >> GE_VTYPE_COL_SHIFT: + swprintf(dest, L"%08x", *(const u32_le *)data); + break; + + default: + wcscpy(dest, L"Invalid"); + break; + } +} + +int CtrlVertexList::GetRowCount() { + if (!gpuDebug || !Memory::IsValidAddress(gpuDebug->GetVertexAddress())) { + rowCount_ = 0; + return rowCount_; + } + + // 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. + DisplayList list; + if (gpuDebug->GetCurrentDisplayList(list)) { + u32 cmd = Memory::Read_U32(list.pc); + if ((cmd >> 24) == GE_CMD_PRIM) { + rowCount_ = cmd & 0xFFFF; + } + } + + if (!gpuDebug->GetCurrentSimpleVertices(rowCount_, vertices, indices)) { + rowCount_ = 0; + } + decoder->SetVertexType(state.vertType); + return rowCount_; +} + +TabVertices::TabVertices(HINSTANCE _hInstance, HWND _hParent) + : Dialog((LPCSTR)IDD_GEDBG_TAB_VERTICES, _hInstance, _hParent) { + values = new CtrlVertexList(GetDlgItem(m_hDlg, IDC_GEDBG_VERTICES)); +} + +TabVertices::~TabVertices() { + delete values; +} + +void TabVertices::UpdateSize(WORD width, WORD height) { + struct Position { + int x,y; + int w,h; + }; + + Position position; + static const int borderMargin = 5; + static const int checkboxSpace = 22; + + position.x = borderMargin; + position.y = borderMargin + checkboxSpace; + position.w = width - 2 * borderMargin; + position.h = height - 2 * borderMargin - checkboxSpace; + + HWND handle = GetDlgItem(m_hDlg, IDC_GEDBG_VERTICES); + MoveWindow(handle, position.x, position.y, position.w, position.h, TRUE); +} + +BOOL TabVertices::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_INITDIALOG: + return TRUE; + + case WM_SIZE: + UpdateSize(LOWORD(lParam), HIWORD(lParam)); + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDC_GEDBG_RAWVERTS) { + values->SetRaw(IsDlgButtonChecked(m_hDlg, IDC_GEDBG_RAWVERTS) == BST_CHECKED); + values->Update(); + } + return TRUE; + + case WM_NOTIFY: + switch (wParam) + { + case IDC_GEDBG_VERTICES: + values->HandleNotify(lParam); + break; + } + break; + } + + return FALSE; +} \ No newline at end of file diff --git a/Windows/GEDebugger/TabVertices.h b/Windows/GEDebugger/TabVertices.h new file mode 100644 index 0000000000..bfe19e8c13 --- /dev/null +++ b/Windows/GEDebugger/TabVertices.h @@ -0,0 +1,71 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include +#include "GPU/Common/GPUDebugInterface.h" +#include "Windows/W32Util/DialogManager.h" +#include "Windows/W32Util/Misc.h" + +class VertexDecoder; + +class CtrlVertexList: public GenericListControl { +public: + CtrlVertexList(HWND hwnd); + ~CtrlVertexList(); + + void SetRaw(bool raw) { + raw_ = raw; + Update(); + } + +protected: + virtual bool WindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& returnValue) { return false; }; + virtual void GetColumnText(wchar_t *dest, int row, int col); + virtual int GetRowCount(); + +private: + void FormatVertCol(wchar_t *dest, const GPUDebugVertex &vert, int col); + void FormatVertColRaw(wchar_t *dest, int row, int col); + void FormatVertColRawType(wchar_t *dest, const void *data, int type, int offset); + void FormatVertColRawColor(wchar_t *dest, const void *data, int type); + + std::vector vertices; + std::vector indices; + int rowCount_; + bool raw_; + VertexDecoder *decoder; +}; + +class TabVertices : public Dialog { +public: + TabVertices(HINSTANCE _hInstance, HWND _hParent); + ~TabVertices(); + + virtual void Update() { + values->Update(); + } + +protected: + BOOL DlgProc(UINT message, WPARAM wParam, LPARAM lParam); + +private: + void UpdateSize(WORD width, WORD height); + + CtrlVertexList *values; +}; \ No newline at end of file diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index a69552c61a..e501733af7 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -294,6 +294,7 @@ + @@ -346,6 +347,7 @@ + diff --git a/Windows/PPSSPP.vcxproj.filters b/Windows/PPSSPP.vcxproj.filters index 45b5d191c8..92331e214d 100644 --- a/Windows/PPSSPP.vcxproj.filters +++ b/Windows/PPSSPP.vcxproj.filters @@ -143,6 +143,9 @@ Windows\Input + + Windows\GE Debugger + @@ -260,6 +263,9 @@ Windows\Input + + Windows\GE Debugger + diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index dc5756f8bb..02b78c84a0 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -207,6 +207,16 @@ BEGIN CONTROL "",IDC_GEDBG_LISTS_SELECTEDLIST,"CtrlDisplayListView",WS_BORDER,225,7,84,89 END +IDD_GEDBG_TAB_VERTICES DIALOGEX 0, 0, 316, 183 +STYLE DS_SETFONT | WS_CHILD | DS_CONTROL +CAPTION "Dialog" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + AUTOCHECKBOX "Before transform (raw)", IDC_GEDBG_RAWVERTS, 5, 5, 100, 10 + CONTROL "",IDC_GEDBG_VERTICES,"SysListView32",LVS_ALIGNLEFT | LVS_SHOWSELALWAYS | LVS_REPORT | WS_BORDER | WS_TABSTOP,7,22,217,86 +END + + #include "aboutbox.rc" IDD_MEMORY DIALOGEX 0, 0, 566, 287 diff --git a/Windows/resource.h b/Windows/resource.h index fbf7219045..b5be2dd979 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -79,6 +79,7 @@ #define IDD_TABDISPLAYLISTS 251 #define IDD_GEDBG_TAB_VALUES 252 #define IDD_DUMPMEMORY 253 +#define IDD_GEDBG_TAB_VERTICES 254 #define IDC_STOPGO 1001 #define IDC_ADDRESS 1002 @@ -156,6 +157,8 @@ #define IDC_GEDBG_FRAMEBUFADDR 1191 #define IDC_GEDBG_TEXADDR 1192 #define IDC_GEDBG_FBTABS 1193 +#define IDC_GEDBG_VERTICES 1194 +#define IDC_GEDBG_RAWVERTS 1195 #define ID_SHADERS_BASE 5000 @@ -312,9 +315,9 @@ // Next default values for new objects #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 254 -#define _APS_NEXT_COMMAND_VALUE 40144 -#define _APS_NEXT_CONTROL_VALUE 1193 +#define _APS_NEXT_RESOURCE_VALUE 255 +#define _APS_NEXT_COMMAND_VALUE 40148 +#define _APS_NEXT_CONTROL_VALUE 1196 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif