From 9c3e00aa08f58a2191e1bd8838c93db14cd80d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 11 Aug 2022 22:45:40 +0200 Subject: [PATCH 01/41] Add a second set of tabs to the Windows GE debugger. Also reorder stuff. --- Windows/GEDebugger/GEDebugger.cpp | 45 ++++++++++++++++++++++----- Windows/GEDebugger/GEDebugger.h | 8 +++-- Windows/GEDebugger/TabState.cpp | 51 ++++++++++++++++--------------- Windows/ppsspp.rc | 3 +- Windows/resource.h | 4 ++- 5 files changed, 75 insertions(+), 36 deletions(-) diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 2a7c32713f..16aa373b68 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -146,8 +146,10 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) MapWindowPoints(HWND_DESKTOP,m_hDlg,(LPPOINT)&frameRect,2); MoveWindow(frameWnd,frameRect.left,frameRect.top,512,272,TRUE); - tabs = new TabControl(GetDlgItem(m_hDlg,IDC_GEDBG_MAINTAB)); - HWND wnd = tabs->AddTabWindow(L"CtrlDisplayListView",L"Display List"); + tabs = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_MAINTAB)); + tabsRight_ = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_RIGHTTAB)); + + HWND wnd = tabs->AddTabWindow(L"CtrlDisplayListView", L"Display List"); displayList = CtrlDisplayListView::getFrom(wnd); fbTabs = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_FBTABS)); @@ -162,7 +164,7 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) tabs->AddTabDialog(flags, L"Flags"); lighting = new TabStateLighting(_hInstance, m_hDlg); - tabs->AddTabDialog(lighting, L"Lighting"); + tabs->AddTabDialog(lighting, L"Light"); textureState = new TabStateTexture(_hInstance, m_hDlg); tabs->AddTabDialog(textureState, L"Texture"); @@ -171,7 +173,7 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) tabs->AddTabDialog(settings, L"Settings"); vertices = new TabVertices(_hInstance, m_hDlg); - tabs->AddTabDialog(vertices, L"Vertices"); + tabs->AddTabDialog(vertices, L"Verts"); matrices = new TabMatrices(_hInstance, m_hDlg); tabs->AddTabDialog(matrices, L"Matrices"); @@ -184,6 +186,18 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) tabs->ShowTab(0, true); + + lightingRight_ = new TabStateLighting(_hInstance, m_hDlg); + tabsRight_->AddTabDialog(lightingRight_, L"Light"); + + textureStateRight_ = new TabStateTexture(_hInstance, m_hDlg); + tabsRight_->AddTabDialog(textureStateRight_, L"Texture"); + + settingsRight_ = new TabStateSettings(_hInstance, m_hDlg); + tabsRight_->AddTabDialog(settingsRight_, L"Settings"); + + tabsRight_->ShowTab(0, true); + // set window position int x = g_Config.iGEWindowX == -1 ? windowRect.left : g_Config.iGEWindowX; int y = g_Config.iGEWindowY == -1 ? windowRect.top : g_Config.iGEWindowY; @@ -200,13 +214,17 @@ CGEDebugger::~CGEDebugger() { CleanupPrimPreview(); delete flags; delete lighting; + delete lightingRight_; delete textureState; + delete textureStateRight_; delete settings; + delete settingsRight_; delete vertices; delete matrices; delete lists; delete watch; delete tabs; + delete tabsRight_; delete fbTabs; } @@ -364,8 +382,11 @@ void CGEDebugger::UpdatePreviews() { flags->Update(); lighting->Update(); + lightingRight_->Update(); textureState->Update(); + textureStateRight_->Update(); settings->Update(); + settingsRight_->Update(); vertices->Update(); matrices->Update(); lists->Update(); @@ -696,16 +717,23 @@ void CGEDebugger::UpdateTextureLevel(int level) { } void CGEDebugger::UpdateSize(WORD width, WORD height) { - // only resize the tab for now + // only resize the tabs for now HWND tabControl = GetDlgItem(m_hDlg, IDC_GEDBG_MAINTAB); + HWND tabControlRight = GetDlgItem(m_hDlg, IDC_GEDBG_RIGHTTAB); RECT tabRect; GetWindowRect(tabControl,&tabRect); MapWindowPoints(HWND_DESKTOP,m_hDlg,(LPPOINT)&tabRect,2); - tabRect.right = tabRect.left + (width-tabRect.left*2); // assume same gap on both sides + tabRect.right = tabRect.left + (width / 2-tabRect.left*2); // assume same gap on both sides tabRect.bottom = tabRect.top + (height-tabRect.top-tabRect.left); // assume same gap on bottom too - MoveWindow(tabControl,tabRect.left,tabRect.top,tabRect.right-tabRect.left,tabRect.bottom-tabRect.top,TRUE); + + RECT tabRectRight = tabRect; + tabRectRight.left += tabRect.right; + tabRectRight.right += tabRect.right; + + MoveWindow(tabControl, tabRect.left, tabRect.top, tabRect.right - tabRect.left, tabRect.bottom - tabRect.top, TRUE); + MoveWindow(tabControlRight, tabRectRight.left, tabRectRight.top, tabRectRight.right - tabRectRight.left, tabRectRight.bottom - tabRectRight.top, TRUE); } void CGEDebugger::SavePosition() { @@ -777,6 +805,9 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { lists->Update(); } break; + case IDC_GEDBG_RIGHTTAB: + tabsRight_->HandleNotify(lParam); + break; case IDC_GEDBG_FBTABS: fbTabs->HandleNotify(lParam); if (GPUDebug::IsActive() && gpuDebug != nullptr) { diff --git a/Windows/GEDebugger/GEDebugger.h b/Windows/GEDebugger/GEDebugger.h index ebf9a2c0d7..7dabf9c63c 100644 --- a/Windows/GEDebugger/GEDebugger.h +++ b/Windows/GEDebugger/GEDebugger.h @@ -81,8 +81,8 @@ private: void PrimaryPreviewHover(int x, int y); void SecondPreviewHover(int x, int y); void PreviewExport(const GPUDebugBuffer *buffer); - void DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); - void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); + static void DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); + static void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); void UpdateMenus(); u32 TexturePreviewFlags(const GPUgstate &state); @@ -93,12 +93,16 @@ private: TabStateLighting *lighting = nullptr; TabStateTexture *textureState = nullptr; TabStateSettings *settings = nullptr; + TabStateLighting *lightingRight_ = nullptr; + TabStateTexture *textureStateRight_ = nullptr; + TabStateSettings *settingsRight_ = nullptr; TabVertices *vertices = nullptr; TabMatrices *matrices = nullptr; SimpleGLWindow *primaryWindow = nullptr; SimpleGLWindow *secondWindow = nullptr; TabStateWatch *watch = nullptr; TabControl *tabs = nullptr; + TabControl *tabsRight_ = nullptr; TabControl *fbTabs = nullptr; int textureLevel_ = 0; bool showClut_ = false; diff --git a/Windows/GEDebugger/TabState.cpp b/Windows/GEDebugger/TabState.cpp index 486e6030b4..9d6735aabd 100644 --- a/Windows/GEDebugger/TabState.cpp +++ b/Windows/GEDebugger/TabState.cpp @@ -177,23 +177,25 @@ static const TabStateRow stateLightingRows[] = { }; static const TabStateRow stateTextureRows[] = { + { L"Texture L0 addr", GE_CMD_TEXADDR0, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH0 }, + { L"Texture L0 size", GE_CMD_TEXSIZE0, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE }, + { L"Tex format", GE_CMD_TEXFORMAT, CMD_FMT_TEXFMT, GE_CMD_TEXTUREMAPENABLE }, + { L"Tex CLUT", GE_CMD_CLUTADDR, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_CLUTADDRUPPER }, + { L"Tex CLUT format", GE_CMD_CLUTFORMAT, CMD_FMT_CLUTFMT, GE_CMD_TEXTUREMAPENABLE }, + { L"Tex U scale", GE_CMD_TEXSCALEU, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE }, { L"Tex V scale", GE_CMD_TEXSCALEV, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE }, { L"Tex U offset", GE_CMD_TEXOFFSETU, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE }, { L"Tex V offset", GE_CMD_TEXOFFSETV, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE }, { L"Tex mapping mode", GE_CMD_TEXMAPMODE, CMD_FMT_TEXMAPMODE, GE_CMD_TEXTUREMAPENABLE }, { L"Tex shade srcs", GE_CMD_TEXSHADELS, CMD_FMT_TEXSHADELS, GE_CMD_TEXTUREMAPENABLE }, + { L"Tex func", GE_CMD_TEXFUNC, CMD_FMT_TEXFUNC, GE_CMD_TEXTUREMAPENABLE }, + { L"Tex env color", GE_CMD_TEXENVCOLOR, CMD_FMT_HEX, GE_CMD_TEXTUREMAPENABLE }, { L"Tex mode", GE_CMD_TEXMODE, CMD_FMT_TEXMODE, GE_CMD_TEXTUREMAPENABLE }, - { L"Tex format", GE_CMD_TEXFORMAT, CMD_FMT_TEXFMT, GE_CMD_TEXTUREMAPENABLE }, { L"Tex filtering", GE_CMD_TEXFILTER, CMD_FMT_TEXFILTER, GE_CMD_TEXTUREMAPENABLE }, { L"Tex wrapping", GE_CMD_TEXWRAP, CMD_FMT_TEXWRAP, GE_CMD_TEXTUREMAPENABLE }, { L"Tex level/bias", GE_CMD_TEXLEVEL, CMD_FMT_TEXLEVEL, GE_CMD_TEXTUREMAPENABLE }, { L"Tex lod slope", GE_CMD_TEXLODSLOPE, CMD_FMT_FLOAT24, GE_CMD_TEXTUREMAPENABLE }, - { L"Tex func", GE_CMD_TEXFUNC, CMD_FMT_TEXFUNC, GE_CMD_TEXTUREMAPENABLE }, - { L"Tex env color", GE_CMD_TEXENVCOLOR, CMD_FMT_HEX, GE_CMD_TEXTUREMAPENABLE }, - { L"CLUT", GE_CMD_CLUTADDR, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_CLUTADDRUPPER }, - { L"CLUT format", GE_CMD_CLUTFORMAT, CMD_FMT_CLUTFMT, GE_CMD_TEXTUREMAPENABLE }, - { L"Texture L0 addr", GE_CMD_TEXADDR0, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH0 }, { L"Texture L1 addr", GE_CMD_TEXADDR1, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH1 }, { L"Texture L2 addr", GE_CMD_TEXADDR2, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH2 }, { L"Texture L3 addr", GE_CMD_TEXADDR3, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH3 }, @@ -201,7 +203,6 @@ static const TabStateRow stateTextureRows[] = { { L"Texture L5 addr", GE_CMD_TEXADDR5, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH5 }, { L"Texture L6 addr", GE_CMD_TEXADDR6, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH6 }, { L"Texture L7 addr", GE_CMD_TEXADDR7, CMD_FMT_PTRWIDTH, GE_CMD_TEXTUREMAPENABLE, GE_CMD_TEXBUFWIDTH7 }, - { L"Texture L0 size", GE_CMD_TEXSIZE0, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE }, { L"Texture L1 size", GE_CMD_TEXSIZE1, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE }, { L"Texture L2 size", GE_CMD_TEXSIZE2, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE }, { L"Texture L3 size", GE_CMD_TEXSIZE3, CMD_FMT_TEXSIZE, GE_CMD_TEXTUREMAPENABLE }, @@ -212,27 +213,34 @@ static const TabStateRow stateTextureRows[] = { }; static const TabStateRow stateSettingsRows[] = { - { L"Clear mode", GE_CMD_CLEARMODE, CMD_FMT_CLEARMODE }, { L"Framebuffer", GE_CMD_FRAMEBUFPTR, CMD_FMT_PTRWIDTH, 0, GE_CMD_FRAMEBUFWIDTH }, { L"Framebuffer format", GE_CMD_FRAMEBUFPIXFORMAT, CMD_FMT_TEXFMT }, { L"Depthbuffer", GE_CMD_ZBUFPTR, CMD_FMT_PTRWIDTH, 0, GE_CMD_ZBUFWIDTH }, + { L"Viewport Scale", GE_CMD_VIEWPORTXSCALE, CMD_FMT_XYZ, 0, GE_CMD_VIEWPORTYSCALE, GE_CMD_VIEWPORTZSCALE }, + { L"Viewport Offset", GE_CMD_VIEWPORTXCENTER, CMD_FMT_XYZ, 0, GE_CMD_VIEWPORTYCENTER, GE_CMD_VIEWPORTZCENTER }, + { L"Scissor", GE_CMD_SCISSOR1, CMD_FMT_XYXY, 0, GE_CMD_SCISSOR2 }, + { L"Region", GE_CMD_REGION1, CMD_FMT_XYXY, 0, GE_CMD_REGION2 }, + { L"Color test", GE_CMD_COLORTEST, CMD_FMT_COLORTEST, GE_CMD_COLORTESTENABLE, GE_CMD_COLORREF, GE_CMD_COLORTESTMASK }, + { L"Alpha test", GE_CMD_ALPHATEST, CMD_FMT_ALPHATEST, GE_CMD_ALPHATESTENABLE }, + { L"Clear mode", GE_CMD_CLEARMODE, CMD_FMT_CLEARMODE }, + { L"Stencil test", GE_CMD_STENCILTEST, CMD_FMT_STENCILTEST, GE_CMD_STENCILTESTENABLE }, + { L"Stencil test op", GE_CMD_STENCILOP, CMD_FMT_STENCILOP, GE_CMD_STENCILTESTENABLE }, + { L"Depth test", GE_CMD_ZTEST, CMD_FMT_ZTEST, GE_CMD_ZTESTENABLE }, + { L"RGB mask", GE_CMD_MASKRGB, CMD_FMT_HEX }, + { L"Stencil/alpha mask", GE_CMD_MASKALPHA, CMD_FMT_HEX }, + { L"Transfer src", GE_CMD_TRANSFERSRC, CMD_FMT_PTRWIDTH, 0, GE_CMD_TRANSFERSRCW }, + { L"Transfer src pos", GE_CMD_TRANSFERSRCPOS, CMD_FMT_XY }, + { L"Transfer dst", GE_CMD_TRANSFERDST, CMD_FMT_PTRWIDTH, 0, GE_CMD_TRANSFERDSTW }, + { L"Transfer dst pos", GE_CMD_TRANSFERDSTPOS, CMD_FMT_XY }, + { L"Transfer size", GE_CMD_TRANSFERSIZE, CMD_FMT_XY }, { L"Vertex type", GE_CMD_VERTEXTYPE, CMD_FMT_VERTEXTYPE }, { L"Offset addr", GE_CMD_OFFSETADDR, CMD_FMT_OFFSETADDR }, { L"Vertex addr", GE_CMD_VADDR, CMD_FMT_VADDR }, { L"Index addr", GE_CMD_IADDR, CMD_FMT_IADDR }, - { L"Region", GE_CMD_REGION1, CMD_FMT_XYXY, 0, GE_CMD_REGION2 }, - { L"Scissor", GE_CMD_SCISSOR1, CMD_FMT_XYXY, 0, GE_CMD_SCISSOR2 }, { L"Min Z", GE_CMD_MINZ, CMD_FMT_HEX }, { L"Max Z", GE_CMD_MAXZ, CMD_FMT_HEX }, - { L"Viewport Scale", GE_CMD_VIEWPORTXSCALE, CMD_FMT_XYZ, 0, GE_CMD_VIEWPORTYSCALE, GE_CMD_VIEWPORTZSCALE }, - { L"Viewport Offset", GE_CMD_VIEWPORTXCENTER, CMD_FMT_XYZ, 0, GE_CMD_VIEWPORTYCENTER, GE_CMD_VIEWPORTZCENTER }, { L"Offset", GE_CMD_OFFSETX, CMD_FMT_F16_XY, 0, GE_CMD_OFFSETY }, { L"Cull mode", GE_CMD_CULL, CMD_FMT_CULL, GE_CMD_CULLFACEENABLE }, - { L"Color test", GE_CMD_COLORTEST, CMD_FMT_COLORTEST, GE_CMD_COLORTESTENABLE, GE_CMD_COLORREF, GE_CMD_COLORTESTMASK }, - { L"Alpha test", GE_CMD_ALPHATEST, CMD_FMT_ALPHATEST, GE_CMD_ALPHATESTENABLE }, - { L"Stencil test", GE_CMD_STENCILTEST, CMD_FMT_STENCILTEST, GE_CMD_STENCILTESTENABLE }, - { L"Stencil test op", GE_CMD_STENCILOP, CMD_FMT_STENCILOP, GE_CMD_STENCILTESTENABLE }, - { L"Depth test", GE_CMD_ZTEST, CMD_FMT_ZTEST, GE_CMD_ZTESTENABLE }, { L"Alpha blend mode", GE_CMD_BLENDMODE, CMD_FMT_BLENDMODE, GE_CMD_ALPHABLENDENABLE }, { L"Blend color A", GE_CMD_BLENDFIXEDA, CMD_FMT_HEX, GE_CMD_ALPHABLENDENABLE }, { L"Blend color B", GE_CMD_BLENDFIXEDB, CMD_FMT_HEX, GE_CMD_ALPHABLENDENABLE }, @@ -240,8 +248,6 @@ static const TabStateRow stateSettingsRows[] = { { L"Fog 1", GE_CMD_FOG1, CMD_FMT_FLOAT24, GE_CMD_FOGENABLE }, { L"Fog 2", GE_CMD_FOG2, CMD_FMT_FLOAT24, GE_CMD_FOGENABLE }, { L"Fog color", GE_CMD_FOGCOLOR, CMD_FMT_HEX, GE_CMD_FOGENABLE }, - { L"RGB mask", GE_CMD_MASKRGB, CMD_FMT_HEX }, - { L"Stencil/alpha mask", GE_CMD_MASKALPHA, CMD_FMT_HEX }, { L"Morph Weight 0", GE_CMD_MORPHWEIGHT0, CMD_FMT_FLOAT24 }, { L"Morph Weight 1", GE_CMD_MORPHWEIGHT1, CMD_FMT_FLOAT24 }, { L"Morph Weight 2", GE_CMD_MORPHWEIGHT2, CMD_FMT_FLOAT24 }, @@ -259,11 +265,6 @@ static const TabStateRow stateSettingsRows[] = { { L"Dither 1", GE_CMD_DITH1, CMD_FMT_HEX, GE_CMD_DITHERENABLE }, { L"Dither 2", GE_CMD_DITH2, CMD_FMT_HEX, GE_CMD_DITHERENABLE }, { L"Dither 3", GE_CMD_DITH3, CMD_FMT_HEX, GE_CMD_DITHERENABLE }, - { L"Transfer src", GE_CMD_TRANSFERSRC, CMD_FMT_PTRWIDTH, 0, GE_CMD_TRANSFERSRCW }, - { L"Transfer src pos", GE_CMD_TRANSFERSRCPOS, CMD_FMT_XY }, - { L"Transfer dst", GE_CMD_TRANSFERDST, CMD_FMT_PTRWIDTH, 0, GE_CMD_TRANSFERDSTW }, - { L"Transfer dst pos", GE_CMD_TRANSFERDSTPOS, CMD_FMT_XY }, - { L"Transfer size", GE_CMD_TRANSFERSIZE, CMD_FMT_XY }, }; // TODO: Commands not present in the above lists (some because they don't have meaningful values...): @@ -1013,7 +1014,7 @@ void CtrlStateValues::OnRightClick(int row, int column, const POINT &point) { } bool CtrlStateValues::OnRowPrePaint(int row, LPNMLVCUSTOMDRAW msg) { - if (RowValuesChanged(row)) { + if (gpuDebug && RowValuesChanged(row)) { msg->clrText = RGB(255, 0, 0); return true; } diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index b306c1a7f5..cbfb3727b4 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -212,7 +212,8 @@ BEGIN PUSHBUTTON "&Resume",IDC_GEDBG_RESUME,444,2,44,14 CONTROL "",IDC_GEDBG_TEX,"SimpleGLWindow",WS_CHILD | WS_VISIBLE,10,20,128,128 CONTROL "",IDC_GEDBG_FRAME,"SimpleGLWindow",WS_CHILD | WS_VISIBLE,148,20,256,136 - CONTROL "",IDC_GEDBG_MAINTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,10,216,480,180 + CONTROL "",IDC_GEDBG_MAINTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,10,216,280,180 + CONTROL "",IDC_GEDBG_RIGHTTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,210,216,280,180 EDITTEXT IDC_GEDBG_FRAMEBUFADDR,148,192,200,12,ES_READONLY | NOT WS_BORDER EDITTEXT IDC_GEDBG_TEXADDR,10,152,128,12,ES_READONLY | NOT WS_BORDER CONTROL "Force opaque",IDC_GEDBG_FORCEOPAQUE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,164,60,12 diff --git a/Windows/resource.h b/Windows/resource.h index 29879fdc57..2b30032234 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -264,7 +264,6 @@ #define ID_OPTIONS_BUFLINEARFILTER 40152 #define ID_OPTIONS_BUFNEARESTFILTER 40153 #define ID_OPTIONS_DIRECT3D9 40154 -#define ID_OPTIONS_DIRECT3D11 40169 #define ID_OPTIONS_OPENGL 40155 #define ID_EMULATION_ROTATION_H 40156 #define ID_EMULATION_ROTATION_V 40157 @@ -326,6 +325,9 @@ #define IDC_GEDBG_FLUSHAUTO 40213 #define IDI_BREAKPOINT_SMALL 40214 #define IDC_GEDBG_SETPRIMFILTER 40215 +#define IDC_GEDBG_RIGHTTAB 40216 +#define ID_OPTIONS_DIRECT3D11 40217 + // Dummy option to let the buffered rendering hotkey cycle through all the options. #define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500 From 8cb7d9cd9f3ab406e7c6bfab31e9b219860467ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 12 Aug 2022 21:33:02 +0200 Subject: [PATCH 02/41] Pause the debugger on TRANSFERSTART (treat that as a prim) --- GPU/Debugger/Debugger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Debugger/Debugger.cpp b/GPU/Debugger/Debugger.cpp index 04fb647f1d..28dc194b74 100644 --- a/GPU/Debugger/Debugger.cpp +++ b/GPU/Debugger/Debugger.cpp @@ -111,7 +111,7 @@ bool NotifyCommand(u32 pc) { } bool process = true; - if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE) { + if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE || cmd == GE_CMD_TRANSFERSTART) { primsThisFrame++; if (!restrictPrimRanges.empty()) { From 5993864d8f628eb587027f2872bba74692c4b7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 14 Aug 2022 11:15:07 +0200 Subject: [PATCH 03/41] Add plain Create method to CtrlDisplayListView --- Windows/GEDebugger/CtrlDisplayListView.cpp | 12 ++++++++++++ Windows/GEDebugger/CtrlDisplayListView.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/Windows/GEDebugger/CtrlDisplayListView.cpp b/Windows/GEDebugger/CtrlDisplayListView.cpp index 296851c630..4a0e9095a3 100644 --- a/Windows/GEDebugger/CtrlDisplayListView.cpp +++ b/Windows/GEDebugger/CtrlDisplayListView.cpp @@ -3,6 +3,7 @@ #include "Common/System/Display.h" #include "Windows/GEDebugger/CtrlDisplayListView.h" #include "Windows/GEDebugger/GEDebugger.h" +#include "Windows/MainWindow.h" #include "Windows/InputBox.h" #include "Windows/W32Util/ContextMenu.h" #include "Windows/main.h" @@ -70,6 +71,17 @@ CtrlDisplayListView *CtrlDisplayListView::getFrom(HWND hwnd) return (CtrlDisplayListView*) GetWindowLongPtr(hwnd, GWLP_USERDATA); } +CtrlDisplayListView *CtrlDisplayListView::Create(HWND parentWnd) { + DWORD style = WS_CHILD; + RECT tabRect{ 0, 0, 100, 100 }; + + HWND hWnd = CreateWindowEx(0, windowClass, L"", style, + tabRect.left, tabRect.top, tabRect.right - tabRect.left, tabRect.bottom - tabRect.top, + parentWnd, 0, MainWindow::GetHInstance(), 0); + + return new CtrlDisplayListView(hWnd); +} + LRESULT CALLBACK CtrlDisplayListView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { CtrlDisplayListView *win = CtrlDisplayListView::getFrom(hwnd); diff --git a/Windows/GEDebugger/CtrlDisplayListView.h b/Windows/GEDebugger/CtrlDisplayListView.h index fe605f799e..4112b91f93 100644 --- a/Windows/GEDebugger/CtrlDisplayListView.h +++ b/Windows/GEDebugger/CtrlDisplayListView.h @@ -36,6 +36,8 @@ public: static void registerClass(); static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); static CtrlDisplayListView * getFrom(HWND wnd); + + CtrlDisplayListView *Create(HWND parentWnd); HWND GetHWND() { return wnd; From 60b2b1db5f193ecbcf8107f4b52a6b02ec16ff86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 14 Aug 2022 11:26:51 +0200 Subject: [PATCH 04/41] Move the display list view to its own column on the right --- Windows/GEDebugger/CtrlDisplayListView.cpp | 4 ++-- Windows/GEDebugger/CtrlDisplayListView.h | 2 +- Windows/GEDebugger/GEDebugger.cpp | 14 +++++++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Windows/GEDebugger/CtrlDisplayListView.cpp b/Windows/GEDebugger/CtrlDisplayListView.cpp index 4a0e9095a3..188884a292 100644 --- a/Windows/GEDebugger/CtrlDisplayListView.cpp +++ b/Windows/GEDebugger/CtrlDisplayListView.cpp @@ -72,10 +72,10 @@ CtrlDisplayListView *CtrlDisplayListView::getFrom(HWND hwnd) } CtrlDisplayListView *CtrlDisplayListView::Create(HWND parentWnd) { - DWORD style = WS_CHILD; + DWORD style = WS_CHILD | WS_VISIBLE | WS_BORDER; RECT tabRect{ 0, 0, 100, 100 }; - HWND hWnd = CreateWindowEx(0, windowClass, L"", style, + HWND hWnd = CreateWindowEx(0, windowClass, L"Display List", style, tabRect.left, tabRect.top, tabRect.right - tabRect.left, tabRect.bottom - tabRect.top, parentWnd, 0, MainWindow::GetHInstance(), 0); diff --git a/Windows/GEDebugger/CtrlDisplayListView.h b/Windows/GEDebugger/CtrlDisplayListView.h index 4112b91f93..73d96b2c12 100644 --- a/Windows/GEDebugger/CtrlDisplayListView.h +++ b/Windows/GEDebugger/CtrlDisplayListView.h @@ -37,7 +37,7 @@ public: static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); static CtrlDisplayListView * getFrom(HWND wnd); - CtrlDisplayListView *Create(HWND parentWnd); + static CtrlDisplayListView *Create(HWND parentWnd); HWND GetHWND() { return wnd; diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 16aa373b68..18ccc1823f 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -141,7 +141,6 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) // up both the size and the aspect ratio RECT frameRect; HWND frameWnd = GetDlgItem(m_hDlg,IDC_GEDBG_FRAME); - GetWindowRect(frameWnd,&frameRect); MapWindowPoints(HWND_DESKTOP,m_hDlg,(LPPOINT)&frameRect,2); MoveWindow(frameWnd,frameRect.left,frameRect.top,512,272,TRUE); @@ -149,8 +148,8 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) tabs = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_MAINTAB)); tabsRight_ = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_RIGHTTAB)); - HWND wnd = tabs->AddTabWindow(L"CtrlDisplayListView", L"Display List"); - displayList = CtrlDisplayListView::getFrom(wnd); + // HWND wnd = tabs->AddTabWindow(L"CtrlDisplayListView", L"Display List"); + displayList = CtrlDisplayListView::Create(m_hDlg); fbTabs = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_FBTABS)); fbTabs->SetMinTabWidth(50); @@ -731,9 +730,18 @@ void CGEDebugger::UpdateSize(WORD width, WORD height) { RECT tabRectRight = tabRect; tabRectRight.left += tabRect.right; tabRectRight.right += tabRect.right; + + RECT frameRect; + HWND frameWnd = GetDlgItem(m_hDlg, IDC_GEDBG_FRAME); + GetWindowRect(frameWnd, &frameRect); + RECT listRect = { frameRect.right + 10, 40, tabRectRight.right, tabRect.top }; + MoveWindow(tabControl, tabRect.left, tabRect.top, tabRect.right - tabRect.left, tabRect.bottom - tabRect.top, TRUE); MoveWindow(tabControlRight, tabRectRight.left, tabRectRight.top, tabRectRight.right - tabRectRight.left, tabRectRight.bottom - tabRectRight.top, TRUE); + if (displayList) { + MoveWindow(displayList->GetHWND(), listRect.left, listRect.top, listRect.right - listRect.left, listRect.bottom - listRect.top, TRUE); + } } void CGEDebugger::SavePosition() { From 2a0f23665f95b081d36e286d33026f574ceb02ec Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Aug 2022 09:12:57 -0700 Subject: [PATCH 05/41] GE Debugger: Track tabs per panel. --- Windows/GEDebugger/GEDebugger.cpp | 195 +++++++++++++++++++----------- Windows/GEDebugger/GEDebugger.h | 46 +++++-- Windows/GEDebugger/TabState.h | 2 +- Windows/W32Util/DialogManager.h | 4 +- Windows/W32Util/TabControl.cpp | 15 +++ Windows/W32Util/TabControl.h | 5 + Windows/ppsspp.rc | 3 +- Windows/resource.h | 3 +- 8 files changed, 182 insertions(+), 91 deletions(-) diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 18ccc1823f..bec47dee0a 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -59,6 +59,53 @@ enum PrimaryDisplayType { PRIMARY_STENCILBUF, }; +static void *AddDisplayListTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, HINSTANCE inst, HWND parent) { + HWND wnd = tabs->AddTabWindow(L"CtrlDisplayListView", tab->name); + return CtrlDisplayListView::getFrom(wnd); +} + +static void RemoveDisplayListTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr) { + CtrlDisplayListView *view = (CtrlDisplayListView *)ptr; + DestroyWindow(view->GetHWND()); +} + +static void UpdateDisplayListTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr) { + CtrlDisplayListView *view = (CtrlDisplayListView *)ptr; + DisplayList list; + if (gpuDebug != nullptr && gpuDebug->GetCurrentDisplayList(list)) { + view->setDisplayList(list); + } +} + +template +static void *AddStateTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, HINSTANCE inst, HWND parent) { + T *w = new T(inst, parent); + tabs->AddTabDialog(w, tab->name); + return w; +} + +static void RemoveStateTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr) { + Dialog *view = (Dialog *)ptr; + delete view; +} + +static void UpdateStateTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr) { + Dialog *view = (Dialog *)ptr; + view->Update(); +} + +static const std::vector defaultTabs = { + { L"Display List", GETabPosition::LEFT, GETabType::LIST_DISASM, {}, &AddDisplayListTab, &RemoveDisplayListTab, &UpdateDisplayListTab }, + { L"Flags", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Light", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Texture", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Settings", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Verts", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Matrices", GETabPosition::LEFT, GETabType::STATE, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Lists", GETabPosition::LEFT, GETabType::LISTS, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, + { L"Watch", GETabPosition::LEFT, GETabType::WATCH, {}, &AddStateTab, &RemoveStateTab, &UpdateStateTab }, +}; + StepCountDlg::StepCountDlg(HINSTANCE _hInstance, HWND _hParent) : Dialog((LPCSTR)IDD_GEDBG_STEPCOUNT, _hInstance, _hParent) { DialogManager::AddDlg(this); @@ -147,9 +194,7 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) tabs = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_MAINTAB)); tabsRight_ = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_RIGHTTAB)); - - // HWND wnd = tabs->AddTabWindow(L"CtrlDisplayListView", L"Display List"); - displayList = CtrlDisplayListView::Create(m_hDlg); + tabsTR_ = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_TOPRIGHTTAB)); fbTabs = new TabControl(GetDlgItem(m_hDlg, IDC_GEDBG_FBTABS)); fbTabs->SetMinTabWidth(50); @@ -159,43 +204,17 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) fbTabs->AddTab(NULL, L"Stencil"); fbTabs->ShowTab(0, true); - flags = new TabStateFlags(_hInstance, m_hDlg); - tabs->AddTabDialog(flags, L"Flags"); + tabStates_ = defaultTabs; + for (GEDebuggerTab &tabState : tabStates_) { + AddTab(&tabState, tabState.pos); + } - lighting = new TabStateLighting(_hInstance, m_hDlg); - tabs->AddTabDialog(lighting, L"Light"); - - textureState = new TabStateTexture(_hInstance, m_hDlg); - tabs->AddTabDialog(textureState, L"Texture"); - - settings = new TabStateSettings(_hInstance, m_hDlg); - tabs->AddTabDialog(settings, L"Settings"); - - vertices = new TabVertices(_hInstance, m_hDlg); - tabs->AddTabDialog(vertices, L"Verts"); - - matrices = new TabMatrices(_hInstance, m_hDlg); - tabs->AddTabDialog(matrices, L"Matrices"); - - lists = new TabDisplayLists(_hInstance, m_hDlg); - tabs->AddTabDialog(lists, L"Lists"); - - watch = new TabStateWatch(_hInstance, m_hDlg); - tabs->AddTabDialog(watch, L"Watch"); - - tabs->ShowTab(0, true); - - - lightingRight_ = new TabStateLighting(_hInstance, m_hDlg); - tabsRight_->AddTabDialog(lightingRight_, L"Light"); - - textureStateRight_ = new TabStateTexture(_hInstance, m_hDlg); - tabsRight_->AddTabDialog(textureStateRight_, L"Texture"); - - settingsRight_ = new TabStateSettings(_hInstance, m_hDlg); - tabsRight_->AddTabDialog(settingsRight_, L"Settings"); - - tabsRight_->ShowTab(0, true); + if (tabs->Count() > 0) + tabs->ShowTab(0, true); + if (tabsRight_->Count() > 0) + tabsRight_->ShowTab(0, true); + if (tabsTR_->Count() > 0) + tabsTR_->ShowTab(0, true); // set window position int x = g_Config.iGEWindowX == -1 ? windowRect.left : g_Config.iGEWindowX; @@ -211,19 +230,14 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) CGEDebugger::~CGEDebugger() { CleanupPrimPreview(); - delete flags; - delete lighting; - delete lightingRight_; - delete textureState; - delete textureStateRight_; - delete settings; - delete settingsRight_; - delete vertices; - delete matrices; - delete lists; - delete watch; + + for (GEDebuggerTab &tabState : tabStates_) { + RemoveTab(&tabState, GETabPosition::ALL); + } + delete tabs; delete tabsRight_; + delete tabsTR_; delete fbTabs; } @@ -370,29 +384,56 @@ void CGEDebugger::UpdatePreviews() { UpdatePrimPreview(primOp, 3); } - DisplayList list; - if (gpuDebug != nullptr && gpuDebug->GetCurrentDisplayList(list)) { - displayList->setDisplayList(list); - } - wchar_t primCounter[1024]{}; swprintf(primCounter, ARRAY_SIZE(primCounter), L"%d/%d", PrimsThisFrame(), PrimsLastFrame()); SetDlgItemText(m_hDlg, IDC_GEDBG_PRIMCOUNTER, primCounter); - flags->Update(); - lighting->Update(); - lightingRight_->Update(); - textureState->Update(); - textureStateRight_->Update(); - settings->Update(); - settingsRight_->Update(); - vertices->Update(); - matrices->Update(); - lists->Update(); - watch->Update(); + for (GEDebuggerTab &tabState : tabStates_) { + UpdateTab(&tabState); + } + updating_ = false; } +void CGEDebugger::UpdateTab(GEDebuggerTab *tab) { + auto doUpdate = [&](GETabPosition pos, TabControl *t, int index) { + if (tab->pos & pos) + tab->update(tab, t, pos, tab->state[index].ptr); + }; + + doUpdate(GETabPosition::LEFT, tabs, 0); + doUpdate(GETabPosition::RIGHT, tabsRight_, 1); + doUpdate(GETabPosition::TOPRIGHT, tabsTR_, 2); +} + +void CGEDebugger::AddTab(GEDebuggerTab *tab, GETabPosition mask) { + auto doAdd = [&](GETabPosition pos, TabControl *t, int index) { + // On init, we still have nullptr, but already have pos, so we use that. + if ((mask & pos) && tab->state[index].ptr == nullptr) { + tab->state[index].ptr = tab->add(tab, t, pos, m_hInstance, m_hDlg); + tab->pos |= pos; + } + }; + + doAdd(GETabPosition::LEFT, tabs, 0); + doAdd(GETabPosition::RIGHT, tabsRight_, 1); + doAdd(GETabPosition::TOPRIGHT, tabsTR_, 2); +} + +void CGEDebugger::RemoveTab(GEDebuggerTab *tab, GETabPosition mask) { + auto doRemove = [&](GETabPosition pos, TabControl *t, int index) { + if ((tab->pos & pos) && (mask & pos)) { + _assert_(tab->state[index].ptr != nullptr); + tab->remove(tab, t, pos, tab->state[index].ptr); + tab->pos = GETabPosition((int)tab->pos & ~(int)pos); + } + }; + + doRemove(GETabPosition::LEFT, tabs, 0); + doRemove(GETabPosition::RIGHT, tabsRight_, 1); + doRemove(GETabPosition::TOPRIGHT, tabsTR_, 2); +} + u32 CGEDebugger::TexturePreviewFlags(const GPUgstate &state) { if (state.isTextureAlphaUsed() && !forceOpaque_) { return SimpleGLWindow::ALPHA_BLEND | SimpleGLWindow::RESIZE_BEST_CENTER; @@ -719,6 +760,7 @@ void CGEDebugger::UpdateSize(WORD width, WORD height) { // only resize the tabs for now HWND tabControl = GetDlgItem(m_hDlg, IDC_GEDBG_MAINTAB); HWND tabControlRight = GetDlgItem(m_hDlg, IDC_GEDBG_RIGHTTAB); + HWND tabControlTR = GetDlgItem(m_hDlg, IDC_GEDBG_TOPRIGHTTAB); RECT tabRect; GetWindowRect(tabControl,&tabRect); @@ -734,14 +776,13 @@ void CGEDebugger::UpdateSize(WORD width, WORD height) { RECT frameRect; HWND frameWnd = GetDlgItem(m_hDlg, IDC_GEDBG_FRAME); GetWindowRect(frameWnd, &frameRect); + MapWindowPoints(HWND_DESKTOP, m_hDlg, (LPPOINT)&frameRect, 2); - RECT listRect = { frameRect.right + 10, 40, tabRectRight.right, tabRect.top }; + RECT trRect = { frameRect.right + 10, frameRect.top, tabRectRight.right, tabRectRight.top }; MoveWindow(tabControl, tabRect.left, tabRect.top, tabRect.right - tabRect.left, tabRect.bottom - tabRect.top, TRUE); MoveWindow(tabControlRight, tabRectRight.left, tabRectRight.top, tabRectRight.right - tabRectRight.left, tabRectRight.bottom - tabRectRight.top, TRUE); - if (displayList) { - MoveWindow(displayList->GetHWND(), listRect.left, listRect.top, listRect.right - listRect.left, listRect.bottom - listRect.top, TRUE); - } + MoveWindow(tabControlTR, trRect.left, trRect.top, trRect.right - trRect.left, trRect.bottom - trRect.top, TRUE); } void CGEDebugger::SavePosition() { @@ -810,12 +851,18 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { case IDC_GEDBG_MAINTAB: tabs->HandleNotify(lParam); if (gpuDebug != nullptr) { - lists->Update(); + for (GEDebuggerTab &tabState : tabStates_) { + if (tabState.type == GETabType::LISTS) + UpdateTab(&tabState); + } } break; case IDC_GEDBG_RIGHTTAB: tabsRight_->HandleNotify(lParam); break; + case IDC_GEDBG_TOPRIGHTTAB: + tabsTR_->HandleNotify(lParam); + break; case IDC_GEDBG_FBTABS: fbTabs->HandleNotify(lParam); if (GPUDebug::IsActive() && gpuDebug != nullptr) { @@ -996,8 +1043,10 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { case WM_GEDBG_UPDATE_WATCH: // Just a notification to update. - if (watch) - watch->Update(); + for (GEDebuggerTab &tabState : tabStates_) { + if (tabState.type == GETabType::WATCH) + UpdateTab(&tabState); + } break; } diff --git a/Windows/GEDebugger/GEDebugger.h b/Windows/GEDebugger/GEDebugger.h index 7dabf9c63c..0e716f1adc 100644 --- a/Windows/GEDebugger/GEDebugger.h +++ b/Windows/GEDebugger/GEDebugger.h @@ -44,6 +44,35 @@ class TabMatrices; class TabStateWatch; struct GPUgstate; +enum class GETabPosition { + LEFT = 1, + RIGHT = 2, + TOPRIGHT = 4, + ALL = 7, +}; +ENUM_CLASS_BITOPS(GETabPosition); + +enum class GETabType { + LIST_DISASM, + LISTS, + STATE, + WATCH, +}; + +struct GEDebuggerTab { + const wchar_t *name; + GETabPosition pos; + GETabType type; + union { + Dialog *dlg; + CtrlDisplayListView *displayList; + void *ptr; + } state[3]; + void *(*add)(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, HINSTANCE inst, HWND parent); + void (*remove)(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr); + void (*update)(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr); +}; + class StepCountDlg : public Dialog { public: StepCountDlg(HINSTANCE _hInstance, HWND _hParent); @@ -84,25 +113,18 @@ private: static void DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); static void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]); void UpdateMenus(); + void UpdateTab(GEDebuggerTab *tab); + void AddTab(GEDebuggerTab *tab, GETabPosition mask); + void RemoveTab(GEDebuggerTab *tab, GETabPosition mask); u32 TexturePreviewFlags(const GPUgstate &state); - CtrlDisplayListView *displayList = nullptr; - TabDisplayLists *lists = nullptr; - TabStateFlags *flags = nullptr; - TabStateLighting *lighting = nullptr; - TabStateTexture *textureState = nullptr; - TabStateSettings *settings = nullptr; - TabStateLighting *lightingRight_ = nullptr; - TabStateTexture *textureStateRight_ = nullptr; - TabStateSettings *settingsRight_ = nullptr; - TabVertices *vertices = nullptr; - TabMatrices *matrices = nullptr; SimpleGLWindow *primaryWindow = nullptr; SimpleGLWindow *secondWindow = nullptr; - TabStateWatch *watch = nullptr; + std::vector tabStates_; TabControl *tabs = nullptr; TabControl *tabsRight_ = nullptr; + TabControl *tabsTR_ = nullptr; TabControl *fbTabs = nullptr; int textureLevel_ = 0; bool showClut_ = false; diff --git a/Windows/GEDebugger/TabState.h b/Windows/GEDebugger/TabState.h index c60c849028..dbc1558fa0 100644 --- a/Windows/GEDebugger/TabState.h +++ b/Windows/GEDebugger/TabState.h @@ -57,7 +57,7 @@ public: TabStateValues(const TabStateRow *rows, int rowCount, LPCSTR dialogID, HINSTANCE _hInstance, HWND _hParent); ~TabStateValues(); - virtual void Update() { + void Update() override { values->Update(); } diff --git a/Windows/W32Util/DialogManager.h b/Windows/W32Util/DialogManager.h index fc943b3ddd..55497223ac 100644 --- a/Windows/W32Util/DialogManager.h +++ b/Windows/W32Util/DialogManager.h @@ -18,6 +18,7 @@ protected: virtual void Create(); void Destroy(); + HINSTANCE m_hInstance; HWND m_hParent; HWND m_hDlg; LPCSTR m_hResource; @@ -26,9 +27,6 @@ protected: virtual BOOL DlgProc(UINT message, WPARAM wParam, LPARAM lParam) = 0; static INT_PTR CALLBACK DlgProcStatic(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); - -private: - HINSTANCE m_hInstance; }; diff --git a/Windows/W32Util/TabControl.cpp b/Windows/W32Util/TabControl.cpp index 2d315213df..8721a9637c 100644 --- a/Windows/W32Util/TabControl.cpp +++ b/Windows/W32Util/TabControl.cpp @@ -93,6 +93,21 @@ void TabControl::AddTab(HWND handle, const wchar_t* title) ShowTab(index); } +HWND TabControl::RemoveTab(int index) { + int prevIndex = CurrentTabIndex(); + if (currentTab >= index) + --currentTab; + + HWND prevHandle = tabs[index].pageHandle; + TabCtrl_DeleteItem(hwnd, index); + tabs.erase(tabs.begin() + index); + + if (prevIndex == index) + ShowTab(currentTab, true); + + return prevHandle; +} + int TabControl::AppendPageToControl(const wchar_t *title) { TCITEM tcItem; diff --git a/Windows/W32Util/TabControl.h b/Windows/W32Util/TabControl.h index 7eb2360dcf..c8212af004 100644 --- a/Windows/W32Util/TabControl.h +++ b/Windows/W32Util/TabControl.h @@ -14,6 +14,7 @@ public: HWND AddTabWindow(const wchar_t* className, const wchar_t* title, DWORD style = 0); void AddTabDialog(Dialog* dialog, const wchar_t* title); void AddTab(HWND hwnd, const wchar_t* title); + HWND RemoveTab(int index); void ShowTab(int index, bool setControlIndex = true); void ShowTab(HWND pageHandle); void NextTab(bool cycle); @@ -30,6 +31,10 @@ public: bool GetShowTabTitles() { return showTabTitles; } void SetMinTabWidth(int w); + int Count() { + return (int)tabs.size(); + } + private: static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); void OnResize(); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index cbfb3727b4..80a6295986 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -196,7 +196,7 @@ BEGIN CONTROL "",IDC_DEBUG_BOTTOMTABS,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,1,338,513,93 END -IDD_GEDEBUGGER DIALOGEX 0, 0, 500, 400 +IDD_GEDEBUGGER DIALOGEX 0, 0, 490, 400 STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME EXSTYLE WS_EX_ACCEPTFILES | WS_EX_TOOLWINDOW CAPTION "GE" @@ -212,6 +212,7 @@ BEGIN PUSHBUTTON "&Resume",IDC_GEDBG_RESUME,444,2,44,14 CONTROL "",IDC_GEDBG_TEX,"SimpleGLWindow",WS_CHILD | WS_VISIBLE,10,20,128,128 CONTROL "",IDC_GEDBG_FRAME,"SimpleGLWindow",WS_CHILD | WS_VISIBLE,148,20,256,136 + CONTROL "",IDC_GEDBG_TOPRIGHTTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,500,20,280,136 CONTROL "",IDC_GEDBG_MAINTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,10,216,280,180 CONTROL "",IDC_GEDBG_RIGHTTAB,"SysTabControl32",TCS_TABS | TCS_FOCUSNEVER,210,216,280,180 EDITTEXT IDC_GEDBG_FRAMEBUFADDR,148,192,200,12,ES_READONLY | NOT WS_BORDER diff --git a/Windows/resource.h b/Windows/resource.h index 2b30032234..7cbe5bf9df 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -327,6 +327,7 @@ #define IDC_GEDBG_SETPRIMFILTER 40215 #define IDC_GEDBG_RIGHTTAB 40216 #define ID_OPTIONS_DIRECT3D11 40217 +#define IDC_GEDBG_TOPRIGHTTAB 40218 // Dummy option to let the buffered rendering hotkey cycle through all the options. @@ -340,7 +341,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 256 -#define _APS_NEXT_COMMAND_VALUE 40216 +#define _APS_NEXT_COMMAND_VALUE 40219 #define _APS_NEXT_CONTROL_VALUE 1202 #define _APS_NEXT_SYMED_VALUE 101 #endif From 5958943e236753d5e1116e09bc17f65bc77c21fa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Aug 2022 09:32:35 -0700 Subject: [PATCH 06/41] GE Debugger: Show/hide tabs if empty. --- Windows/GEDebugger/GEDebugger.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index bec47dee0a..a1ae45d671 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -766,12 +766,22 @@ void CGEDebugger::UpdateSize(WORD width, WORD height) { GetWindowRect(tabControl,&tabRect); MapWindowPoints(HWND_DESKTOP,m_hDlg,(LPPOINT)&tabRect,2); - tabRect.right = tabRect.left + (width / 2-tabRect.left*2); // assume same gap on both sides - tabRect.bottom = tabRect.top + (height-tabRect.top-tabRect.left); // assume same gap on bottom too + // Assume the same gap (tabRect.left) on all sides. + if (tabsTR_ && tabsTR_->Count() == 0) { + tabRect.right = tabRect.left + (width - tabRect.left * 2); + } else { + tabRect.right = tabRect.left + (width / 2 - tabRect.left * 2); + } + tabRect.bottom = tabRect.top + (height - tabRect.top - tabRect.left); RECT tabRectRight = tabRect; - tabRectRight.left += tabRect.right; - tabRectRight.right += tabRect.right; + if (tabs && tabsTR_ && tabs->Count() == 0 && tabsTR_->Count() != 0) { + tabRect.right = tabRect.left; + tabRect.bottom = tabRect.top; + } else { + tabRectRight.left += tabRect.right; + tabRectRight.right += tabRect.right; + } RECT frameRect; HWND frameWnd = GetDlgItem(m_hDlg, IDC_GEDBG_FRAME); @@ -779,6 +789,10 @@ void CGEDebugger::UpdateSize(WORD width, WORD height) { MapWindowPoints(HWND_DESKTOP, m_hDlg, (LPPOINT)&frameRect, 2); RECT trRect = { frameRect.right + 10, frameRect.top, tabRectRight.right, tabRectRight.top }; + if (tabsTR_ && tabsTR_->Count() == 0) { + trRect.right = trRect.left; + trRect.bottom = trRect.top; + } MoveWindow(tabControl, tabRect.left, tabRect.top, tabRect.right - tabRect.left, tabRect.bottom - tabRect.top, TRUE); MoveWindow(tabControlRight, tabRectRight.left, tabRectRight.top, tabRectRight.right - tabRectRight.left, tabRectRight.bottom - tabRectRight.top, TRUE); From 49679c6a50944dab11dc5c0f137fcbb8423b6d41 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Aug 2022 10:16:16 -0700 Subject: [PATCH 07/41] GE Debugger: Add context menu to control tabs. Crurent non-functional, but shows up for the correct tab. --- Windows/GEDebugger/GEDebugger.cpp | 116 ++++++++++++++++++++++++++---- Windows/GEDebugger/GEDebugger.h | 13 ++-- Windows/W32Util/ContextMenu.h | 1 + Windows/W32Util/TabControl.cpp | 8 +++ Windows/W32Util/TabControl.h | 1 + Windows/ppsspp.rc | 6 ++ Windows/resource.h | 5 +- 7 files changed, 132 insertions(+), 18 deletions(-) diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index a1ae45d671..9c30abb1d1 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -59,6 +59,13 @@ enum PrimaryDisplayType { PRIMARY_STENCILBUF, }; +enum class GEPanelIndex { + LEFT, + RIGHT, + TOPRIGHT, + COUNT, +}; + static void *AddDisplayListTab(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, HINSTANCE inst, HWND parent) { HWND wnd = tabs->AddTabWindow(L"CtrlDisplayListView", tab->name); return CtrlDisplayListView::getFrom(wnd); @@ -396,42 +403,64 @@ void CGEDebugger::UpdatePreviews() { } void CGEDebugger::UpdateTab(GEDebuggerTab *tab) { - auto doUpdate = [&](GETabPosition pos, TabControl *t, int index) { + auto doUpdate = [&](GETabPosition pos, TabControl *t, GEPanelIndex index) { if (tab->pos & pos) - tab->update(tab, t, pos, tab->state[index].ptr); + tab->update(tab, t, pos, tab->state[(int)index].ptr); }; - doUpdate(GETabPosition::LEFT, tabs, 0); - doUpdate(GETabPosition::RIGHT, tabsRight_, 1); - doUpdate(GETabPosition::TOPRIGHT, tabsTR_, 2); + doUpdate(GETabPosition::LEFT, tabs, GEPanelIndex::LEFT); + doUpdate(GETabPosition::RIGHT, tabsRight_, GEPanelIndex::RIGHT); + doUpdate(GETabPosition::TOPRIGHT, tabsTR_, GEPanelIndex::TOPRIGHT); } void CGEDebugger::AddTab(GEDebuggerTab *tab, GETabPosition mask) { - auto doAdd = [&](GETabPosition pos, TabControl *t, int index) { + auto doAdd = [&](GETabPosition pos, TabControl *t, GEPanelIndex pindex) { + int index = (int)pindex; // On init, we still have nullptr, but already have pos, so we use that. if ((mask & pos) && tab->state[index].ptr == nullptr) { + tab->state[index].index = t->Count(); tab->state[index].ptr = tab->add(tab, t, pos, m_hInstance, m_hDlg); tab->pos |= pos; } }; - doAdd(GETabPosition::LEFT, tabs, 0); - doAdd(GETabPosition::RIGHT, tabsRight_, 1); - doAdd(GETabPosition::TOPRIGHT, tabsTR_, 2); + doAdd(GETabPosition::LEFT, tabs, GEPanelIndex::LEFT); + doAdd(GETabPosition::RIGHT, tabsRight_, GEPanelIndex::RIGHT); + doAdd(GETabPosition::TOPRIGHT, tabsTR_, GEPanelIndex::TOPRIGHT); } void CGEDebugger::RemoveTab(GEDebuggerTab *tab, GETabPosition mask) { - auto doRemove = [&](GETabPosition pos, TabControl *t, int index) { + auto doRemove = [&](GETabPosition pos, TabControl *t, GEPanelIndex pindex) { + int index = (int)pindex; if ((tab->pos & pos) && (mask & pos)) { _assert_(tab->state[index].ptr != nullptr); tab->remove(tab, t, pos, tab->state[index].ptr); tab->pos = GETabPosition((int)tab->pos & ~(int)pos); + tab->state[index].index = -1; } }; - doRemove(GETabPosition::LEFT, tabs, 0); - doRemove(GETabPosition::RIGHT, tabsRight_, 1); - doRemove(GETabPosition::TOPRIGHT, tabsTR_, 2); + doRemove(GETabPosition::LEFT, tabs, GEPanelIndex::LEFT); + doRemove(GETabPosition::RIGHT, tabsRight_, GEPanelIndex::RIGHT); + doRemove(GETabPosition::TOPRIGHT, tabsTR_, GEPanelIndex::TOPRIGHT); +} + +int CGEDebugger::HasTabIndex(GEDebuggerTab *tab, GETabPosition pos) { + int stateIndex = 0; + switch (pos) { + case GETabPosition::LEFT: stateIndex = (int)GEPanelIndex::LEFT; break; + case GETabPosition::RIGHT: stateIndex = (int)GEPanelIndex::RIGHT; break; + case GETabPosition::TOPRIGHT: stateIndex = (int)GEPanelIndex::TOPRIGHT; break; + default: _assert_msg_(false, "Invalid GE tab position"); break; + } + + if (tab->pos & pos) { + auto &state = tab->state[stateIndex]; + if (state.ptr == nullptr) + return -1; + return state.index; + } + return -1; } u32 CGEDebugger::TexturePreviewFlags(const GPUgstate &state) { @@ -870,12 +899,15 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { UpdateTab(&tabState); } } + CheckTabMessage(tabs, GETabPosition::LEFT, lParam); break; case IDC_GEDBG_RIGHTTAB: tabsRight_->HandleNotify(lParam); + CheckTabMessage(tabsRight_, GETabPosition::RIGHT, lParam); break; case IDC_GEDBG_TOPRIGHTTAB: tabsTR_->HandleNotify(lParam); + CheckTabMessage(tabsTR_, GETabPosition::TOPRIGHT, lParam); break; case IDC_GEDBG_FBTABS: fbTabs->HandleNotify(lParam); @@ -1067,6 +1099,64 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { return FALSE; } +void CGEDebugger::CheckTabMessage(TabControl *t, GETabPosition pos, LPARAM lParam) { + NMHDR *msg = (LPNMHDR)lParam; + if (msg->code != NM_RCLICK) + return; + + POINT cursorPos; + GetCursorPos(&cursorPos); + int tabIndex = t->HitTest(cursorPos); + if (tabIndex == -1) + return; + + // Find the tabState that was clicked on. + GEDebuggerTab *tab = nullptr; + for (GEDebuggerTab &tabState : tabStates_) { + int foundIndex = HasTabIndex(&tabState, pos); + if (foundIndex == tabIndex) { + tab = &tabState; + break; + } + } + // Shouldn't normally happen... maybe we added some other type of tab. + if (!tab) + return; + + int currentPanels = 0; + for (int i = 0; i < (int)GEPanelIndex::COUNT; ++i) { + if (tab && tab->state[i].index != -1 && tab->state[i].ptr) + currentPanels++; + } + + HMENU subMenu = GetContextMenu(ContextMenuID::GEDBG_TABS); + static const int itemIDs[] = { ID_GEDBG_SHOWONLEFT, ID_GEDBG_SHOWONRIGHT, ID_GEDBG_SHOWONTOPRIGHT }; + for (int i = 0; i < (int)GEPanelIndex::COUNT; ++i) { + bool active = tab && tab->state[i].index != -1 && tab->state[i].ptr; + bool disabled = active && currentPanels == 1; + CheckMenuItem(subMenu, itemIDs[i], active ? MF_CHECKED : MF_UNCHECKED); + EnableMenuItem(subMenu, itemIDs[i], disabled ? MF_GRAYED : MF_ENABLED); + } + + switch (TriggerContextMenu(ContextMenuID::GEDBG_TABS, m_hDlg, ContextPoint::FromCursor())) { + case ID_GEDBG_SHOWONLEFT: + // TODO + break; + + case ID_GEDBG_SHOWONRIGHT: + // TODO + break; + + case ID_GEDBG_SHOWONTOPRIGHT: + // TODO + break; + + default: + // Cancel, that's fine. + break; + } +} + void CGEDebugger::UpdateMenus() { CheckMenuItem(GetMenu(m_hDlg), IDC_GEDBG_FLUSHAUTO, MF_BYCOMMAND | (autoFlush_ ? MF_CHECKED : MF_UNCHECKED)); } diff --git a/Windows/GEDebugger/GEDebugger.h b/Windows/GEDebugger/GEDebugger.h index 0e716f1adc..c7d70dc3ee 100644 --- a/Windows/GEDebugger/GEDebugger.h +++ b/Windows/GEDebugger/GEDebugger.h @@ -63,10 +63,13 @@ struct GEDebuggerTab { const wchar_t *name; GETabPosition pos; GETabType type; - union { - Dialog *dlg; - CtrlDisplayListView *displayList; - void *ptr; + struct { + union { + Dialog *dlg; + CtrlDisplayListView *displayList; + void *ptr; + }; + int index = -1; } state[3]; void *(*add)(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, HINSTANCE inst, HWND parent); void (*remove)(GEDebuggerTab *tab, TabControl *tabs, GETabPosition pos, void *ptr); @@ -116,6 +119,8 @@ private: void UpdateTab(GEDebuggerTab *tab); void AddTab(GEDebuggerTab *tab, GETabPosition mask); void RemoveTab(GEDebuggerTab *tab, GETabPosition mask); + int HasTabIndex(GEDebuggerTab *tab, GETabPosition pos); + void CheckTabMessage(TabControl *t, GETabPosition pos, LPARAM lParam); u32 TexturePreviewFlags(const GPUgstate &state); diff --git a/Windows/W32Util/ContextMenu.h b/Windows/W32Util/ContextMenu.h index f8fbe46488..9e52e2aa47 100644 --- a/Windows/W32Util/ContextMenu.h +++ b/Windows/W32Util/ContextMenu.h @@ -31,6 +31,7 @@ enum class ContextMenuID { GEDBG_STATE = 7, GEDBG_PREVIEW = 8, GEDBG_MATRIX = 9, + GEDBG_TABS = 10, }; struct ContextPoint { diff --git a/Windows/W32Util/TabControl.cpp b/Windows/W32Util/TabControl.cpp index 8721a9637c..75c819ec04 100644 --- a/Windows/W32Util/TabControl.cpp +++ b/Windows/W32Util/TabControl.cpp @@ -272,6 +272,14 @@ void TabControl::HandleNotify(LPARAM lParam) } } +int TabControl::HitTest(const POINT &screenPos) { + TCHITTESTINFO hitTest{}; + hitTest.pt = screenPos; + ScreenToClient(hwnd, &hitTest.pt); + + return TabCtrl_HitTest(hwnd, &hitTest); +} + void TabControl::OnResize() { RECT tabRect; diff --git a/Windows/W32Util/TabControl.h b/Windows/W32Util/TabControl.h index c8212af004..3d4b26f93e 100644 --- a/Windows/W32Util/TabControl.h +++ b/Windows/W32Util/TabControl.h @@ -11,6 +11,7 @@ class TabControl public: TabControl(HWND handle, bool noDisplayArea = false); void HandleNotify(LPARAM lParam); + int HitTest(const POINT &screenPos); HWND AddTabWindow(const wchar_t* className, const wchar_t* title, DWORD style = 0); void AddTabDialog(Dialog* dialog, const wchar_t* title); void AddTab(HWND hwnd, const wchar_t* title); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 80a6295986..e2f38fd8e6 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -792,6 +792,12 @@ BEGIN MENUITEM SEPARATOR MENUITEM "Toggle Breakpoint", ID_DISASM_TOGGLEBREAKPOINT END + POPUP "getaboptions" + BEGIN + MENUITEM "Show in &Left Pane" ID_GEDBG_SHOWONLEFT + MENUITEM "Show in &Right Pane" ID_GEDBG_SHOWONRIGHT + MENUITEM "Show in &Top Right Pane" ID_GEDBG_SHOWONTOPRIGHT + END END #endif // English (United States) resources diff --git a/Windows/resource.h b/Windows/resource.h index 7cbe5bf9df..eacb42760b 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -328,6 +328,9 @@ #define IDC_GEDBG_RIGHTTAB 40216 #define ID_OPTIONS_DIRECT3D11 40217 #define IDC_GEDBG_TOPRIGHTTAB 40218 +#define ID_GEDBG_SHOWONLEFT 40219 +#define ID_GEDBG_SHOWONRIGHT 40220 +#define ID_GEDBG_SHOWONTOPRIGHT 40221 // Dummy option to let the buffered rendering hotkey cycle through all the options. @@ -341,7 +344,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 256 -#define _APS_NEXT_COMMAND_VALUE 40219 +#define _APS_NEXT_COMMAND_VALUE 40222 #define _APS_NEXT_CONTROL_VALUE 1202 #define _APS_NEXT_SYMED_VALUE 101 #endif From 6272f3e1d6f5f247aff3cd5830a501882cc24d1e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Aug 2022 10:57:31 -0700 Subject: [PATCH 08/41] GE Debugger: Actually allow swapping tabs. --- Windows/GEDebugger/CtrlDisplayListView.cpp | 11 ------- Windows/GEDebugger/CtrlDisplayListView.h | 2 -- Windows/GEDebugger/GEDebugger.cpp | 37 +++++++++++++++++----- Windows/W32Util/Misc.cpp | 3 ++ Windows/W32Util/TabControl.cpp | 14 +++++--- 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/Windows/GEDebugger/CtrlDisplayListView.cpp b/Windows/GEDebugger/CtrlDisplayListView.cpp index 188884a292..c9dd0c9d65 100644 --- a/Windows/GEDebugger/CtrlDisplayListView.cpp +++ b/Windows/GEDebugger/CtrlDisplayListView.cpp @@ -71,17 +71,6 @@ CtrlDisplayListView *CtrlDisplayListView::getFrom(HWND hwnd) return (CtrlDisplayListView*) GetWindowLongPtr(hwnd, GWLP_USERDATA); } -CtrlDisplayListView *CtrlDisplayListView::Create(HWND parentWnd) { - DWORD style = WS_CHILD | WS_VISIBLE | WS_BORDER; - RECT tabRect{ 0, 0, 100, 100 }; - - HWND hWnd = CreateWindowEx(0, windowClass, L"Display List", style, - tabRect.left, tabRect.top, tabRect.right - tabRect.left, tabRect.bottom - tabRect.top, - parentWnd, 0, MainWindow::GetHInstance(), 0); - - return new CtrlDisplayListView(hWnd); -} - LRESULT CALLBACK CtrlDisplayListView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { CtrlDisplayListView *win = CtrlDisplayListView::getFrom(hwnd); diff --git a/Windows/GEDebugger/CtrlDisplayListView.h b/Windows/GEDebugger/CtrlDisplayListView.h index 73d96b2c12..fe605f799e 100644 --- a/Windows/GEDebugger/CtrlDisplayListView.h +++ b/Windows/GEDebugger/CtrlDisplayListView.h @@ -36,8 +36,6 @@ public: static void registerClass(); static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); static CtrlDisplayListView * getFrom(HWND wnd); - - static CtrlDisplayListView *Create(HWND parentWnd); HWND GetHWND() { return wnd; diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 9c30abb1d1..52c41edf0f 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -421,6 +421,7 @@ void CGEDebugger::AddTab(GEDebuggerTab *tab, GETabPosition mask) { tab->state[index].index = t->Count(); tab->state[index].ptr = tab->add(tab, t, pos, m_hInstance, m_hDlg); tab->pos |= pos; + t->ShowTab(tab->state[index].index, true); } }; @@ -433,10 +434,18 @@ void CGEDebugger::RemoveTab(GEDebuggerTab *tab, GETabPosition mask) { auto doRemove = [&](GETabPosition pos, TabControl *t, GEPanelIndex pindex) { int index = (int)pindex; if ((tab->pos & pos) && (mask & pos)) { - _assert_(tab->state[index].ptr != nullptr); - tab->remove(tab, t, pos, tab->state[index].ptr); + auto &state = tab->state[index]; + _assert_(state.ptr != nullptr); + t->RemoveTab(state.index); + for (auto &tabState : tabStates_) { + if (tabState.state[index].index > state.index) + --tabState.state[index].index; + } + + tab->remove(tab, t, pos, state.ptr); tab->pos = GETabPosition((int)tab->pos & ~(int)pos); - tab->state[index].index = -1; + state.ptr = nullptr; + state.index = -1; } }; @@ -1125,30 +1134,42 @@ void CGEDebugger::CheckTabMessage(TabControl *t, GETabPosition pos, LPARAM lPara int currentPanels = 0; for (int i = 0; i < (int)GEPanelIndex::COUNT; ++i) { - if (tab && tab->state[i].index != -1 && tab->state[i].ptr) + if (tab->state[i].index != -1 && tab->state[i].ptr) currentPanels++; } HMENU subMenu = GetContextMenu(ContextMenuID::GEDBG_TABS); static const int itemIDs[] = { ID_GEDBG_SHOWONLEFT, ID_GEDBG_SHOWONRIGHT, ID_GEDBG_SHOWONTOPRIGHT }; for (int i = 0; i < (int)GEPanelIndex::COUNT; ++i) { - bool active = tab && tab->state[i].index != -1 && tab->state[i].ptr; + bool active = tab->state[i].index != -1 && tab->state[i].ptr; bool disabled = active && currentPanels == 1; CheckMenuItem(subMenu, itemIDs[i], active ? MF_CHECKED : MF_UNCHECKED); EnableMenuItem(subMenu, itemIDs[i], disabled ? MF_GRAYED : MF_ENABLED); } + auto toggleState = [&](GEPanelIndex i, GETabPosition pos) { + auto &state = tab->state[(int)i]; + if (state.index != -1 && state.ptr) + RemoveTab(tab, pos); + else + AddTab(tab, pos); + + RECT rc; + GetClientRect(m_hDlg, &rc); + UpdateSize(rc.right - rc.left, rc.bottom - rc.top); + }; + switch (TriggerContextMenu(ContextMenuID::GEDBG_TABS, m_hDlg, ContextPoint::FromCursor())) { case ID_GEDBG_SHOWONLEFT: - // TODO + toggleState(GEPanelIndex::LEFT, GETabPosition::LEFT); break; case ID_GEDBG_SHOWONRIGHT: - // TODO + toggleState(GEPanelIndex::RIGHT, GETabPosition::RIGHT); break; case ID_GEDBG_SHOWONTOPRIGHT: - // TODO + toggleState(GEPanelIndex::TOPRIGHT, GETabPosition::TOPRIGHT); break; default: diff --git a/Windows/W32Util/Misc.cpp b/Windows/W32Util/Misc.cpp index 37bdfd475e..657a0193d2 100644 --- a/Windows/W32Util/Misc.cpp +++ b/Windows/W32Util/Misc.cpp @@ -204,6 +204,7 @@ GenericListControl::GenericListControl(HWND hwnd, const GenericListViewDef& def) } GenericListControl::~GenericListControl() { + SetWindowLongPtr(handle, GWLP_USERDATA, (LONG_PTR)nullptr); // Don't destroy the image list, it's done automatically by the list view. } @@ -376,6 +377,8 @@ void GenericListControl::ResizeColumns() LRESULT CALLBACK GenericListControl::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { GenericListControl* list = (GenericListControl*) GetWindowLongPtr(hwnd,GWLP_USERDATA); + if (!list) + return FALSE; LRESULT returnValue; if (list->valid && list->WindowMessage(msg,wParam,lParam,returnValue) == true) diff --git a/Windows/W32Util/TabControl.cpp b/Windows/W32Util/TabControl.cpp index 75c819ec04..d4556725b6 100644 --- a/Windows/W32Util/TabControl.cpp +++ b/Windows/W32Util/TabControl.cpp @@ -99,11 +99,17 @@ HWND TabControl::RemoveTab(int index) { --currentTab; HWND prevHandle = tabs[index].pageHandle; - TabCtrl_DeleteItem(hwnd, index); - tabs.erase(tabs.begin() + index); + if (tabs.size() == 1) { + TabCtrl_DeleteAllItems(hwnd); + tabs.clear(); + currentTab = 0; + } else { + TabCtrl_DeleteItem(hwnd, index); + tabs.erase(tabs.begin() + index); - if (prevIndex == index) - ShowTab(currentTab, true); + if (prevIndex == index) + ShowTab(currentTab, true); + } return prevHandle; } From 8390867019d7ba1ac979dbae82981d4b6911d9ef Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Aug 2022 11:07:53 -0700 Subject: [PATCH 09/41] GE Debugger: Correct tab updating for right panel. --- Windows/GEDebugger/GEDebugger.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 52c41edf0f..b28ee32ccb 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -422,6 +422,8 @@ void CGEDebugger::AddTab(GEDebuggerTab *tab, GETabPosition mask) { tab->state[index].ptr = tab->add(tab, t, pos, m_hInstance, m_hDlg); tab->pos |= pos; t->ShowTab(tab->state[index].index, true); + if (gpuDebug) + tab->update(tab, t, pos, tab->state[index].ptr); } }; @@ -805,7 +807,7 @@ void CGEDebugger::UpdateSize(WORD width, WORD height) { MapWindowPoints(HWND_DESKTOP,m_hDlg,(LPPOINT)&tabRect,2); // Assume the same gap (tabRect.left) on all sides. - if (tabsTR_ && tabsTR_->Count() == 0) { + if (tabsRight_ && tabsRight_->Count() == 0) { tabRect.right = tabRect.left + (width - tabRect.left * 2); } else { tabRect.right = tabRect.left + (width / 2 - tabRect.left * 2); @@ -813,12 +815,12 @@ void CGEDebugger::UpdateSize(WORD width, WORD height) { tabRect.bottom = tabRect.top + (height - tabRect.top - tabRect.left); RECT tabRectRight = tabRect; - if (tabs && tabsTR_ && tabs->Count() == 0 && tabsTR_->Count() != 0) { + if (tabs && tabsRight_ && tabs->Count() == 0 && tabsRight_->Count() != 0) { tabRect.right = tabRect.left; tabRect.bottom = tabRect.top; } else { tabRectRight.left += tabRect.right; - tabRectRight.right += tabRect.right; + tabRectRight.right += tabRect.right + tabRect.left; } RECT frameRect; From 2a4443b85e917b24791c306001fece6a139f79bb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Aug 2022 11:26:37 -0700 Subject: [PATCH 10/41] GE Debugger: Cleanup duplicate dlist redraws. It's still not redrawing properly on resize, but it tries to... --- Windows/GEDebugger/CtrlDisplayListView.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Windows/GEDebugger/CtrlDisplayListView.cpp b/Windows/GEDebugger/CtrlDisplayListView.cpp index c9dd0c9d65..6b521c4996 100644 --- a/Windows/GEDebugger/CtrlDisplayListView.cpp +++ b/Windows/GEDebugger/CtrlDisplayListView.cpp @@ -150,8 +150,7 @@ void CtrlDisplayListView::redraw() GetClientRect(wnd, &rect); visibleRows = rect.bottom/rowHeight; - InvalidateRect(wnd, NULL, FALSE); - UpdateWindow(wnd); + RedrawWindow(wnd, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_INTERNALPAINT | RDW_ALLCHILDREN); } From 6fad5463d034402653f009b6498c939b7df5b0f9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Aug 2022 11:42:04 -0700 Subject: [PATCH 11/41] GE Debugger: Save tab configuration. --- Core/Config.cpp | 3 +++ Core/Config.h | 3 +++ Windows/GEDebugger/GEDebugger.cpp | 42 +++++++++++++++++++++++++------ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 91264ca5b4..4c5d312bf2 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1167,6 +1167,9 @@ static ConfigSetting debuggerSettings[] = { ConfigSetting("GEWindowY", &g_Config.iGEWindowY, -1), ConfigSetting("GEWindowW", &g_Config.iGEWindowW, -1), ConfigSetting("GEWindowH", &g_Config.iGEWindowH, -1), + ConfigSetting("GEWindowTabsBL", &g_Config.uGETabsLeft, (uint32_t)0), + ConfigSetting("GEWindowTabsBR", &g_Config.uGETabsRight, (uint32_t)0), + ConfigSetting("GEWindowTabsTR", &g_Config.uGETabsTopRight, (uint32_t)0), ConfigSetting("ConsoleWindowX", &g_Config.iConsoleWindowX, -1), ConfigSetting("ConsoleWindowY", &g_Config.iConsoleWindowY, -1), ConfigSetting("FontWidth", &g_Config.iFontWidth, 8), diff --git a/Core/Config.h b/Core/Config.h index e682234ba3..7a35ff0d09 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -462,6 +462,9 @@ public: int iGEWindowY; int iGEWindowW; int iGEWindowH; + uint32_t uGETabsLeft; + uint32_t uGETabsRight; + uint32_t uGETabsTopRight; int iConsoleWindowX; int iConsoleWindowY; int iFontWidth; diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index b28ee32ccb..1546019124 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -212,6 +212,27 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) fbTabs->ShowTab(0, true); tabStates_ = defaultTabs; + // Restore settings, if any set. + _assert_msg_(defaultTabs.size() <= 32, "Cannot have more than 32 tabs"); + if ((g_Config.uGETabsLeft | g_Config.uGETabsRight | g_Config.uGETabsTopRight) != 0) { + for (int i = 0; i < (int)tabStates_.size(); ++i) { + int mask = 1 << i; + tabStates_[i].pos = (GETabPosition)0; + if (g_Config.uGETabsLeft & mask) + tabStates_[i].pos |= GETabPosition::LEFT; + if (g_Config.uGETabsRight & mask) + tabStates_[i].pos |= GETabPosition::RIGHT; + if (g_Config.uGETabsTopRight & mask) + tabStates_[i].pos |= GETabPosition::TOPRIGHT; + // If this is a new tab, add it to left. + if (tabStates_[i].pos == (GETabPosition)0) { + tabStates_[i].pos |= GETabPosition::LEFT; + g_Config.uGETabsLeft |= 1 << i; + } + } + } else { + g_Config.uGETabsLeft = (1 << tabStates_.size()) - 1; + } for (GEDebuggerTab &tabState : tabStates_) { AddTab(&tabState, tabState.pos); } @@ -1123,10 +1144,13 @@ void CGEDebugger::CheckTabMessage(TabControl *t, GETabPosition pos, LPARAM lPara // Find the tabState that was clicked on. GEDebuggerTab *tab = nullptr; - for (GEDebuggerTab &tabState : tabStates_) { + int tabStateIndex = 0; + for (int i = 0; i < (int)tabStates_.size(); ++i) { + GEDebuggerTab &tabState = tabStates_[i]; int foundIndex = HasTabIndex(&tabState, pos); if (foundIndex == tabIndex) { tab = &tabState; + tabStateIndex = i; break; } } @@ -1149,12 +1173,16 @@ void CGEDebugger::CheckTabMessage(TabControl *t, GETabPosition pos, LPARAM lPara EnableMenuItem(subMenu, itemIDs[i], disabled ? MF_GRAYED : MF_ENABLED); } - auto toggleState = [&](GEPanelIndex i, GETabPosition pos) { + auto toggleState = [&](GEPanelIndex i, GETabPosition pos, uint32_t &configured) { auto &state = tab->state[(int)i]; - if (state.index != -1 && state.ptr) + bool removing = state.index != -1 && state.ptr; + if (removing) { RemoveTab(tab, pos); - else + configured &= ~(1 << tabStateIndex); + } else { AddTab(tab, pos); + configured |= 1 << tabStateIndex; + } RECT rc; GetClientRect(m_hDlg, &rc); @@ -1163,15 +1191,15 @@ void CGEDebugger::CheckTabMessage(TabControl *t, GETabPosition pos, LPARAM lPara switch (TriggerContextMenu(ContextMenuID::GEDBG_TABS, m_hDlg, ContextPoint::FromCursor())) { case ID_GEDBG_SHOWONLEFT: - toggleState(GEPanelIndex::LEFT, GETabPosition::LEFT); + toggleState(GEPanelIndex::LEFT, GETabPosition::LEFT, g_Config.uGETabsLeft); break; case ID_GEDBG_SHOWONRIGHT: - toggleState(GEPanelIndex::RIGHT, GETabPosition::RIGHT); + toggleState(GEPanelIndex::RIGHT, GETabPosition::RIGHT, g_Config.uGETabsRight); break; case ID_GEDBG_SHOWONTOPRIGHT: - toggleState(GEPanelIndex::TOPRIGHT, GETabPosition::TOPRIGHT); + toggleState(GEPanelIndex::TOPRIGHT, GETabPosition::TOPRIGHT, g_Config.uGETabsTopRight); break; default: From 0b22c9840450193a215498f7d9a9bd092bb3a248 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Aug 2022 13:19:52 -0700 Subject: [PATCH 12/41] GPU: Skip fb create upload when clearing. This doesn't verify it's a full screen clear, but on a new framebuffer that's very very common. --- GPU/Common/FramebufferManagerCommon.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 68920e2a12..036c67c22b 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -469,7 +469,8 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame vfbs_.push_back(vfb); currentRenderVfb_ = vfb; - if (useBufferedRendering_ && !g_Config.bDisableSlowFramebufEffects) { + // Assume that if we're clearing right when switching to a new framebuffer, we don't need to upload. + if (useBufferedRendering_ && !g_Config.bDisableSlowFramebufEffects && params.isDrawing) { gpu->PerformMemoryUpload(params.fb_address, byteSize); // Alpha was already done by PerformMemoryUpload. PerformStencilUpload(params.fb_address, byteSize, StencilUpload::STENCIL_IS_ZERO | StencilUpload::IGNORE_ALPHA); From 132686513d546816cef6e62005241f84cce2dc22 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Aug 2022 16:14:23 -0700 Subject: [PATCH 13/41] GE Debugger: Correct base accounting in playback. On a jump, was forgetting the base value which caused corruption. --- GPU/Debugger/Playback.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/GPU/Debugger/Playback.cpp b/GPU/Debugger/Playback.cpp index 8fa93e7d7c..aa34ce3ccf 100644 --- a/GPU/Debugger/Playback.cpp +++ b/GPU/Debugger/Playback.cpp @@ -367,6 +367,7 @@ bool DumpExecute::SubmitCmds(const void *p, u32 sz) { Memory::Write_U32((GE_CMD_JUMP << 24) | (execListBuf & 0x00FFFFFF), execListPos + 4); execListPos = execListBuf; + lastBase_ = execListBuf & 0xFF000000; // Don't continue until we've stalled. SyncStall(); @@ -450,9 +451,9 @@ void DumpExecute::Vertices(u32 ptr, u32 sz) { return; } - if (lastBase_ != (psp & 0x0FF000000)) { + if (lastBase_ != (psp & 0xFF000000)) { execListQueue.push_back((GE_CMD_BASE << 24) | ((psp >> 8) & 0x00FF0000)); - lastBase_ = psp & 0x0FF000000; + lastBase_ = psp & 0xFF000000; } execListQueue.push_back((GE_CMD_VADDR << 24) | (psp & 0x00FFFFFF)); } @@ -464,9 +465,9 @@ void DumpExecute::Indices(u32 ptr, u32 sz) { return; } - if (lastBase_ != (psp & 0x0FF000000)) { + if (lastBase_ != (psp & 0xFF000000)) { execListQueue.push_back((GE_CMD_BASE << 24) | ((psp >> 8) & 0x00FF0000)); - lastBase_ = psp & 0x0FF000000; + lastBase_ = psp & 0xFF000000; } execListQueue.push_back((GE_CMD_IADDR << 24) | (psp & 0x00FFFFFF)); } From daaf448d2231f643b02ffe504bcfae29bacac0b9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Aug 2022 16:17:04 -0700 Subject: [PATCH 14/41] GE Debugger: Fix crash on 0 count prim. --- GPU/Common/DrawEngineCommon.cpp | 2 +- GPU/Software/TransformUnit.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 0755988029..34e0f7ff90 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -266,7 +266,7 @@ bool DrawEngineCommon::GetCurrentSimpleVertices(int count, std::vector 0 && (gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { const u8 *inds = Memory::GetPointer(gstate_c.indexAddr); const u16_le *inds16 = (const u16_le *)inds; From 6060706fc8cafa24ef81db97e38a9ede97e2410c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 14 Aug 2022 22:13:39 -0700 Subject: [PATCH 15/41] GPU: Avoid using depth buffers for blending. For now, until it's implemented. --- GPU/Common/FramebufferManagerCommon.cpp | 5 ++++- GPU/Common/FramebufferManagerCommon.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 68920e2a12..bfa097d936 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -238,6 +238,9 @@ void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GPU } params->isDrawing = !gstate.isModeClear() || !gstate.isClearModeColorMask() || !gstate.isClearModeAlphaMask(); params->isModeThrough = gstate.isModeThrough(); + const bool alphaBlending = gstate.isAlphaBlendEnabled(); + const bool logicOpBlending = gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_CLEAR && gstate.getLogicOp() != GE_LOGIC_COPY; + params->isBlending = alphaBlending || logicOpBlending; // Viewport-X1 and Y1 are not the upper left corner, but half the width/height. A bit confusing. float vpx = gstate.getViewportXScale(); @@ -321,7 +324,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame vfb->height = drawing_height; } break; - } else if (params.fb_address == v->z_address && params.fmt != GE_FORMAT_8888 && params.fb_stride == v->z_stride) { + } else if (params.fb_address == v->z_address && params.fmt != GE_FORMAT_8888 && params.fb_stride == v->z_stride && !params.isBlending) { // Looks like the game might be intending to use color to write directly to a Z buffer. // This is seen in Kuroyou 2. diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 5277d6a03e..ca995fda06 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -139,6 +139,7 @@ struct FramebufferHeuristicParams { bool isWritingDepth; bool isDrawing; bool isModeThrough; + bool isBlending; int viewportWidth; int viewportHeight; int regionWidth; From 12fa098dab59433521e2c31e5814e92d093663ee Mon Sep 17 00:00:00 2001 From: tunip3 <26260613+tunip3@users.noreply.github.com> Date: Mon, 15 Aug 2022 23:15:12 +0100 Subject: [PATCH 16/41] remove unneeded switch case as un broken cases fall through --- UWP/StorageFolderBrowser.cpp | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/UWP/StorageFolderBrowser.cpp b/UWP/StorageFolderBrowser.cpp index 00f5275dbb..24df2dba98 100644 --- a/UWP/StorageFolderBrowser.cpp +++ b/UWP/StorageFolderBrowser.cpp @@ -66,35 +66,7 @@ void StorageFolderBrowser::threadfunc() { cond_.wait(lock); } if (operationRequested_) { - switch (operation_.type) { - case OpType::LIST_DIRECTORY: { - - /* - Streams::Buffer ^buf = ref new Streams::Buffer(operation_.size); - operationFailed_ = false; - stream_->Seek(operation_.offset); - auto task = create_task(stream_->ReadAsync(buf, operation_.size, Streams::InputStreamOptions::None)); - Streams::IBuffer ^output = nullptr; - try { - task.wait(); - output = task.get(); - } - catch (const std::exception& e) { - operationFailed_ = true; - const char *what = e.what(); - ILOG("%s", what); - } operationRequested_ = false; - std::unique_lock lock(mutexResponse_); - response_.buffer = output; - responseAvailable_ = true; - condResponse_.notify_one(); - break;*/ - } - default: - operationRequested_ = false; - break; - } } } } From 77e41f80736873338a1ae0d5c035a82741b74e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 00:34:38 +0200 Subject: [PATCH 17/41] Revert "Pause the debugger on TRANSFERSTART (treat that as a prim)" This reverts commit 8cb7d9cd9f3ab406e7c6bfab31e9b219860467ed. --- GPU/Debugger/Debugger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Debugger/Debugger.cpp b/GPU/Debugger/Debugger.cpp index 28dc194b74..04fb647f1d 100644 --- a/GPU/Debugger/Debugger.cpp +++ b/GPU/Debugger/Debugger.cpp @@ -111,7 +111,7 @@ bool NotifyCommand(u32 pc) { } bool process = true; - if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE || cmd == GE_CMD_TRANSFERSTART) { + if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE) { primsThisFrame++; if (!restrictPrimRanges.empty()) { From 9f2447c0b4505a083c2e15a260bc8439c43de87b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 10:55:44 +0200 Subject: [PATCH 18/41] Assorted minor cleanup --- GPU/Common/FramebufferManagerCommon.cpp | 4 ++-- GPU/Common/FramebufferManagerCommon.h | 20 ++++++++++---------- GPU/GLES/FramebufferManagerGLES.cpp | 1 - GPU/GLES/FramebufferManagerGLES.h | 2 -- GPU/GPUCommon.cpp | 2 +- GPU/GPUCommon.h | 4 ++-- GPU/GPUInterface.h | 4 ++-- 7 files changed, 17 insertions(+), 20 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 0da6dc00ca..66d497f807 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -114,7 +114,7 @@ void FramebufferManagerCommon::SetDisplayFramebuffer(u32 framebuf, u32 stride, G GPURecord::NotifyDisplay(framebuf, stride, format); } -VirtualFramebuffer *FramebufferManagerCommon::GetVFBAt(u32 addr) { +VirtualFramebuffer *FramebufferManagerCommon::GetVFBAt(u32 addr) const { addr &= 0x3FFFFFFF; VirtualFramebuffer *match = nullptr; for (size_t i = 0; i < vfbs_.size(); ++i) { @@ -2480,7 +2480,7 @@ void FramebufferManagerCommon::RebindFramebuffer(const char *tag) { } } -std::vector FramebufferManagerCommon::GetFramebufferList() { +std::vector FramebufferManagerCommon::GetFramebufferList() const { std::vector list; for (size_t i = 0; i < vfbs_.size(); ++i) { diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index ca995fda06..3809e75f2d 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -249,7 +249,7 @@ public: } } void RebindFramebuffer(const char *tag); - std::vector GetFramebufferList(); + std::vector GetFramebufferList() const; void CopyDisplayToOutput(bool reallyDirty); @@ -276,25 +276,25 @@ public: size_t NumVFBs() const { return vfbs_.size(); } - u32 PrevDisplayFramebufAddr() { + u32 PrevDisplayFramebufAddr() const { return prevDisplayFramebuf_ ? prevDisplayFramebuf_->fb_address : 0; } - u32 DisplayFramebufAddr() { + u32 DisplayFramebufAddr() const { return displayFramebuf_ ? displayFramebuf_->fb_address : 0; } - u32 DisplayFramebufStride() { + u32 DisplayFramebufStride() const { return displayFramebuf_ ? displayStride_ : 0; } - GEBufferFormat DisplayFramebufFormat() { + GEBufferFormat DisplayFramebufFormat() const { return displayFramebuf_ ? displayFormat_ : GE_FORMAT_INVALID; } - bool UseBufferedRendering() { + bool UseBufferedRendering() const { return useBufferedRendering_; } - bool MayIntersectFramebuffer(u32 start) { + bool MayIntersectFramebuffer(u32 start) const { // Clear the cache/kernel bits. start = start & 0x3FFFFFFF; // Most games only have two framebuffers at the start. @@ -308,8 +308,8 @@ public: return currentRenderVfb_; } // TODO: Break out into some form of FBO manager - VirtualFramebuffer *GetVFBAt(u32 addr); - VirtualFramebuffer *GetDisplayVFB() { + VirtualFramebuffer *GetVFBAt(u32 addr) const; + VirtualFramebuffer *GetDisplayVFB() const { return GetVFBAt(displayFramebufPtr_); } @@ -349,7 +349,7 @@ public: virtual bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer); virtual bool GetOutputFramebuffer(GPUDebugBuffer &buffer); - const std::vector &Framebuffers() { + const std::vector &Framebuffers() const { return vfbs_; } void ReinterpretFramebuffer(VirtualFramebuffer *vfb, GEBufferFormat oldFormat, GEBufferFormat newFormat); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index f9e04803a7..48503bdc15 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -36,7 +36,6 @@ #include "GPU/Debugger/Stepping.h" #include "GPU/GLES/FramebufferManagerGLES.h" #include "GPU/GLES/TextureCacheGLES.h" -#include "GPU/GLES/DrawEngineGLES.h" #include "GPU/GLES/ShaderManagerGLES.h" FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render) : diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index b859aefd9c..5e5793ad16 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -61,6 +61,4 @@ private: int u_depthDownloadFactor = -1; int u_depthDownloadShift = -1; int u_depthDownloadTo8 = -1; - - DrawEngineGLES *drawEngineGL_ = nullptr; }; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 2996348b54..a0deb403aa 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2969,7 +2969,7 @@ bool GPUCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) { return framebufferManager_ ? framebufferManager_->GetOutputFramebuffer(buffer) : false; } -std::vector GPUCommon::GetFramebufferList() { +std::vector GPUCommon::GetFramebufferList() const { return framebufferManager_->GetFramebufferList(); } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 9a9db7b062..59298d8e92 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -230,11 +230,11 @@ public: const std::list& GetDisplayLists() override { return dlQueue; } - std::vector GetFramebufferList() override; + std::vector GetFramebufferList() const override; void ClearShaderCache() override {} void CleanupBeforeUI() override {} - s64 GetListTicks(int listid) override { + s64 GetListTicks(int listid) const override { if (listid >= 0 && listid < DisplayListMaxCount) { return dls[listid].waitTicks; } diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 1d2c74021a..832897f598 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -253,8 +253,8 @@ public: virtual void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) = 0; virtual const std::list& GetDisplayLists() = 0; // TODO: Currently Qt only, needs to be cleaned up. - virtual std::vector GetFramebufferList() = 0; - virtual s64 GetListTicks(int listid) = 0; + virtual std::vector GetFramebufferList() const = 0; + virtual s64 GetListTicks(int listid) const = 0; // For debugging. The IDs returned are opaque, do not poke in them or display them in any way. virtual std::vector DebugGetShaderIDs(DebugShaderType type) = 0; From ccdb1f73309dc34676c4bb66961dc91175583b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 11:11:59 +0200 Subject: [PATCH 19/41] Move out the reinterpret stuff to ReinterpretFramebuffer.cpp. Draw2D refactor. --- GPU/Common/Draw2D.cpp | 79 +++++++----- GPU/Common/FramebufferManagerCommon.cpp | 157 ----------------------- GPU/Common/FramebufferManagerCommon.h | 1 + GPU/Common/ReinterpretFramebuffer.cpp | 161 ++++++++++++++++++++++++ 4 files changed, 213 insertions(+), 185 deletions(-) diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index 882da8590f..f3e55c8e92 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -68,24 +68,56 @@ void GenerateDraw2DVS(char *buffer, const ShaderLanguageDesc &lang) { writer.EndVSMain(varyings); } -// verts have positions in clip coordinates. +void FramebufferManagerCommon::Ensure2DResources() { + using namespace Draw; + + const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + + if (!draw2DVs_) { + char *vsCode = new char[4000]; + GenerateDraw2DVS(vsCode, shaderLanguageDesc); + draw2DVs_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "draw2d_vs"); + _assert_(draw2DVs_); + delete[] vsCode; + } + + if (!draw2DSamplerLinear_) { + SamplerStateDesc descLinear{}; + descLinear.magFilter = TextureFilter::LINEAR; + descLinear.minFilter = TextureFilter::LINEAR; + descLinear.mipFilter = TextureFilter::LINEAR; + descLinear.wrapU = TextureAddressMode::CLAMP_TO_EDGE; + descLinear.wrapV = TextureAddressMode::CLAMP_TO_EDGE; + draw2DSamplerLinear_ = draw_->CreateSamplerState(descLinear); + } + + if (!draw2DSamplerNearest_) { + SamplerStateDesc descNearest{}; + descNearest.magFilter = TextureFilter::NEAREST; + descNearest.minFilter = TextureFilter::NEAREST; + descNearest.mipFilter = TextureFilter::NEAREST; + descNearest.wrapU = TextureAddressMode::CLAMP_TO_EDGE; + descNearest.wrapV = TextureAddressMode::CLAMP_TO_EDGE; + draw2DSamplerNearest_ = draw_->CreateSamplerState(descNearest); + } +} + void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, RasterChannel channel) { using namespace Draw; - if (!draw2DPipelineColor_) { - const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + Ensure2DResources(); + const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + + if (!draw2DPipelineColor_) { char *fsCode = new char[4000]; char *fsDepthCode = new char[4000]; - char *vsCode = new char[4000]; GenerateDraw2DFs(fsCode, shaderLanguageDesc); GenerateDraw2DDepthFs(fsDepthCode, shaderLanguageDesc); - GenerateDraw2DVS(vsCode, shaderLanguageDesc); draw2DFs_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "draw2d_fs"); - draw2DVs_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "draw2d_vs"); - _assert_(draw2DFs_ && draw2DVs_); + _assert_(draw2DFs_); if (draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { draw2DFsDepth_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsDepthCode, strlen(fsDepthCode), "draw2d_depth_fs"); @@ -94,7 +126,8 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver draw2DFsDepth_ = nullptr; } - InputLayoutDesc desc = { + // verts have positions in 2D clip coordinates. + static const InputLayoutDesc desc = { { { 16, false }, }, @@ -139,7 +172,6 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver } delete[] fsCode; - delete[] vsCode; rasterNoCull->Release(); blendOff->Release(); @@ -147,29 +179,20 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver noDepthStencil->Release(); depthWriteAlways->Release(); inputLayout->Release(); - - SamplerStateDesc descLinear{}; - descLinear.magFilter = TextureFilter::LINEAR; - descLinear.minFilter = TextureFilter::LINEAR; - descLinear.mipFilter = TextureFilter::LINEAR; - descLinear.wrapU = TextureAddressMode::CLAMP_TO_EDGE; - descLinear.wrapV = TextureAddressMode::CLAMP_TO_EDGE; - draw2DSamplerLinear_= draw_->CreateSamplerState(descLinear); - - SamplerStateDesc descNearest{}; - descLinear.magFilter = TextureFilter::NEAREST; - descLinear.minFilter = TextureFilter::NEAREST; - descLinear.mipFilter = TextureFilter::NEAREST; - descLinear.wrapU = TextureAddressMode::CLAMP_TO_EDGE; - descLinear.wrapV = TextureAddressMode::CLAMP_TO_EDGE; - draw2DSamplerNearest_ = draw_->CreateSamplerState(descNearest); } - if (channel == RASTER_DEPTH && !draw2DPipelineDepth_) { - return; + switch (channel) { + case RASTER_DEPTH: + if (!draw2DPipelineDepth_) { + return; + } + draw_->BindPipeline(draw2DPipelineDepth_); + break; + case RASTER_COLOR: + draw_->BindPipeline(draw2DPipelineColor_); + break; } - draw_->BindPipeline(channel == RASTER_COLOR ? draw2DPipelineColor_ : draw2DPipelineDepth_); if (tex) { draw_->BindTextures(TEX_SLOT_PSP_TEXTURE, 1, &tex); } diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 66d497f807..a755a5aab1 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -689,163 +689,6 @@ void FramebufferManagerCommon::NotifyRenderFramebufferUpdated(VirtualFramebuffer } } -// Can't easily dynamically create these strings, we just pass along the pointer. -static const char *reinterpretStrings[3][3] = { - { - "self_reinterpret_565", - "reinterpret_565_to_5551", - "reinterpret_565_to_4444", - }, - { - "reinterpret_5551_to_565", - "self_reinterpret_5551", - "reinterpret_5551_to_4444", - }, - { - "reinterpret_4444_to_565", - "reinterpret_4444_to_5551", - "self_reinterpret_4444", - }, -}; - -void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, GEBufferFormat oldFormat, GEBufferFormat newFormat) { - if (!useBufferedRendering_ || !vfb->fbo) { - return; - } - - _assert_(newFormat != oldFormat); - // The caller is responsible for updating the format. - _assert_(newFormat == vfb->format); - - ShaderLanguage lang = draw_->GetShaderLanguageDesc().shaderLanguage; - - // Copy image required for now, might get rid of this later. - bool doReinterpret = PSP_CoreParameter().compat.flags().ReinterpretFramebuffers && - (lang == HLSL_D3D11 || lang == GLSL_VULKAN || lang == GLSL_3xx) && - draw_->GetDeviceCaps().framebufferCopySupported; - - if (!doReinterpret) { - // Fake reinterpret - just clear the way we always did on Vulkan. Just clear color and stencil. - if (oldFormat == GE_FORMAT_565) { - // We have to bind here instead of clear, since it can be that no framebuffer is bound. - // The backend can sometimes directly optimize it to a clear. - - // Games that are marked as doing reinterpret just ignore this - better to keep the data than to clear. - // Fixes #13717. - if (!PSP_CoreParameter().compat.flags().ReinterpretFramebuffers && !PSP_CoreParameter().compat.flags().BlueToAlpha) { - draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }, "FakeReinterpret"); - // Need to dirty anything that has command buffer dynamic state, in case we started a new pass above. - // Should find a way to feed that information back, maybe... Or simply correct the issue in the rendermanager. - gstate_c.Dirty(DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE); - - if (currentRenderVfb_ != vfb) { - // In case ReinterpretFramebuffer was called from the texture manager. - draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After FakeReinterpret"); - } - } - } - return; - } - - // We only reinterpret between 16 - bit formats, for now. - if (!IsGeBufferFormat16BitColor(oldFormat) || !IsGeBufferFormat16BitColor(newFormat)) { - // 16->32 and 32->16 will require some more specialized shaders. - return; - } - - char *vsCode = nullptr; - char *fsCode = nullptr; - - if (!reinterpretVS_) { - vsCode = new char[4000]; - const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); - GenerateReinterpretVertexShader(vsCode, shaderLanguageDesc); - reinterpretVS_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "reinterpret_vs"); - _assert_(reinterpretVS_); - } - - if (!reinterpretSampler_) { - Draw::SamplerStateDesc samplerDesc{}; - samplerDesc.magFilter = Draw::TextureFilter::LINEAR; - samplerDesc.minFilter = Draw::TextureFilter::LINEAR; - reinterpretSampler_ = draw_->CreateSamplerState(samplerDesc); - } - - if (!reinterpretVBuf_) { - reinterpretVBuf_ = draw_->CreateBuffer(12 * 3, Draw::BufferUsageFlag::DYNAMIC | Draw::BufferUsageFlag::VERTEXDATA); - } - - // See if we need to create a new pipeline. - - Draw::Pipeline *pipeline = reinterpretFromTo_[(int)oldFormat][(int)newFormat]; - if (!pipeline) { - fsCode = new char[4000]; - const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); - GenerateReinterpretFragmentShader(fsCode, oldFormat, newFormat, shaderLanguageDesc); - Draw::ShaderModule *reinterpretFS = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "reinterpret_fs"); - _assert_(reinterpretFS); - - std::vector shaders; - shaders.push_back(reinterpretVS_); - shaders.push_back(reinterpretFS); - - using namespace Draw; - Draw::PipelineDesc desc{}; - // We use a "fullscreen triangle". - // TODO: clear the stencil buffer. Hard to actually initialize it with the new alpha, though possible - let's see if - // we need it. - DepthStencilState *depth = draw_->CreateDepthStencilState({ false, false, Comparison::LESS }); - BlendState *blendstateOff = draw_->CreateBlendState({ false, 0xF }); - RasterState *rasterNoCull = draw_->CreateRasterState({}); - - // No uniforms for these, only a single texture input. - PipelineDesc pipelineDesc{ Primitive::TRIANGLE_LIST, shaders, nullptr, depth, blendstateOff, rasterNoCull, nullptr }; - pipeline = draw_->CreateGraphicsPipeline(pipelineDesc); - _assert_(pipeline != nullptr); - reinterpretFromTo_[(int)oldFormat][(int)newFormat] = pipeline; - - depth->Release(); - blendstateOff->Release(); - rasterNoCull->Release(); - reinterpretFS->Release(); - } - - // Copy to a temp framebuffer. - Draw::Framebuffer *temp = GetTempFBO(TempFBO::REINTERPRET, vfb->renderWidth, vfb->renderHeight); - - // Ideally on Vulkan this should be using the original framebuffer as an input attachment, allowing it to read from - // itself while writing. - draw_->InvalidateCachedState(); - draw_->CopyFramebufferImage(vfb->fbo, 0, 0, 0, 0, temp, 0, 0, 0, 0, vfb->renderWidth, vfb->renderHeight, 1, Draw::FBChannel::FB_COLOR_BIT, "reinterpret_prep"); - draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, reinterpretStrings[(int)oldFormat][(int)newFormat]); - draw_->BindPipeline(pipeline); - draw_->BindFramebufferAsTexture(temp, 0, Draw::FBChannel::FB_COLOR_BIT, 0); - draw_->BindSamplerStates(0, 1, &reinterpretSampler_); - draw_->SetScissorRect(0, 0, vfb->renderWidth, vfb->renderHeight); - Draw::Viewport vp = Draw::Viewport{ 0.0f, 0.0f, (float)vfb->renderWidth, (float)vfb->renderHeight, 0.0f, 1.0f }; - draw_->SetViewports(1, &vp); - // Vertex buffer not used - vertices generated in shader. - // TODO: Switch to a vertex buffer for GLES2/D3D9 compat. - draw_->BindVertexBuffers(0, 1, &reinterpretVBuf_, nullptr); - draw_->Draw(3, 0); - draw_->InvalidateCachedState(); - - // Unbind. - draw_->BindTexture(0, nullptr); - - shaderManager_->DirtyLastShader(); - textureCache_->ForgetLastTexture(); - - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); - - if (currentRenderVfb_ != vfb) { - // In case ReinterpretFramebuffer was called from the texture manager. - draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After reinterpret"); - } - delete[] vsCode; - delete[] fsCode; -} - void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) { if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) { ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height); diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 3809e75f2d..624d20a3d0 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -361,6 +361,7 @@ protected: void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags); void DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, RasterChannel channel); + void Ensure2DResources(); bool UpdateSize(); diff --git a/GPU/Common/ReinterpretFramebuffer.cpp b/GPU/Common/ReinterpretFramebuffer.cpp index 71b0b24910..691998ed85 100644 --- a/GPU/Common/ReinterpretFramebuffer.cpp +++ b/GPU/Common/ReinterpretFramebuffer.cpp @@ -4,7 +4,10 @@ #include "Common/GPU/ShaderWriter.h" #include "Common/Log.h" #include "Common/GPU/thin3d.h" +#include "Core/System.h" #include "GPU/Common/ReinterpretFramebuffer.h" +#include "GPU/Common/FramebufferManagerCommon.h" +#include "GPU/Common/TextureCacheCommon.h" static const VaryingDef varyings[1] = { { "vec2", "v_texcoord", Draw::SEM_TEXCOORD0, 0, "highp" }, @@ -90,3 +93,161 @@ bool GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lan writer.EndVSMain(varyings); return true; } + + +// Can't easily dynamically create these strings, we just pass along the pointer. +static const char *reinterpretStrings[3][3] = { + { + "self_reinterpret_565", + "reinterpret_565_to_5551", + "reinterpret_565_to_4444", + }, + { + "reinterpret_5551_to_565", + "self_reinterpret_5551", + "reinterpret_5551_to_4444", + }, + { + "reinterpret_4444_to_565", + "reinterpret_4444_to_5551", + "self_reinterpret_4444", + }, +}; + +void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, GEBufferFormat oldFormat, GEBufferFormat newFormat) { + if (!useBufferedRendering_ || !vfb->fbo) { + return; + } + + _assert_(newFormat != oldFormat); + // The caller is responsible for updating the format. + _assert_(newFormat == vfb->format); + + ShaderLanguage lang = draw_->GetShaderLanguageDesc().shaderLanguage; + + // Copy image required for now, might get rid of this later. + bool doReinterpret = PSP_CoreParameter().compat.flags().ReinterpretFramebuffers && + (lang == HLSL_D3D11 || lang == GLSL_VULKAN || lang == GLSL_3xx) && + draw_->GetDeviceCaps().framebufferCopySupported; + + if (!doReinterpret) { + // Fake reinterpret - just clear the way we always did on Vulkan. Just clear color and stencil. + if (oldFormat == GE_FORMAT_565) { + // We have to bind here instead of clear, since it can be that no framebuffer is bound. + // The backend can sometimes directly optimize it to a clear. + + // Games that are marked as doing reinterpret just ignore this - better to keep the data than to clear. + // Fixes #13717. + if (!PSP_CoreParameter().compat.flags().ReinterpretFramebuffers && !PSP_CoreParameter().compat.flags().BlueToAlpha) { + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }, "FakeReinterpret"); + // Need to dirty anything that has command buffer dynamic state, in case we started a new pass above. + // Should find a way to feed that information back, maybe... Or simply correct the issue in the rendermanager. + gstate_c.Dirty(DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE); + + if (currentRenderVfb_ != vfb) { + // In case ReinterpretFramebuffer was called from the texture manager. + draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After FakeReinterpret"); + } + } + } + return; + } + + // We only reinterpret between 16 - bit formats, for now. + if (!IsGeBufferFormat16BitColor(oldFormat) || !IsGeBufferFormat16BitColor(newFormat)) { + // 16->32 and 32->16 will require some more specialized shaders. + return; + } + + char *vsCode = nullptr; + char *fsCode = nullptr; + + if (!reinterpretVS_) { + vsCode = new char[4000]; + const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + GenerateReinterpretVertexShader(vsCode, shaderLanguageDesc); + reinterpretVS_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "reinterpret_vs"); + _assert_(reinterpretVS_); + } + + if (!reinterpretSampler_) { + Draw::SamplerStateDesc samplerDesc{}; + samplerDesc.magFilter = Draw::TextureFilter::LINEAR; + samplerDesc.minFilter = Draw::TextureFilter::LINEAR; + reinterpretSampler_ = draw_->CreateSamplerState(samplerDesc); + } + + if (!reinterpretVBuf_) { + reinterpretVBuf_ = draw_->CreateBuffer(12 * 3, Draw::BufferUsageFlag::DYNAMIC | Draw::BufferUsageFlag::VERTEXDATA); + } + + // See if we need to create a new pipeline. + + Draw::Pipeline *pipeline = reinterpretFromTo_[(int)oldFormat][(int)newFormat]; + if (!pipeline) { + fsCode = new char[4000]; + const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + GenerateReinterpretFragmentShader(fsCode, oldFormat, newFormat, shaderLanguageDesc); + Draw::ShaderModule *reinterpretFS = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "reinterpret_fs"); + _assert_(reinterpretFS); + + std::vector shaders; + shaders.push_back(reinterpretVS_); + shaders.push_back(reinterpretFS); + + using namespace Draw; + Draw::PipelineDesc desc{}; + // We use a "fullscreen triangle". + // TODO: clear the stencil buffer. Hard to actually initialize it with the new alpha, though possible - let's see if + // we need it. + DepthStencilState *depth = draw_->CreateDepthStencilState({ false, false, Comparison::LESS }); + BlendState *blendstateOff = draw_->CreateBlendState({ false, 0xF }); + RasterState *rasterNoCull = draw_->CreateRasterState({}); + + // No uniforms for these, only a single texture input. + PipelineDesc pipelineDesc{ Primitive::TRIANGLE_LIST, shaders, nullptr, depth, blendstateOff, rasterNoCull, nullptr }; + pipeline = draw_->CreateGraphicsPipeline(pipelineDesc); + _assert_(pipeline != nullptr); + reinterpretFromTo_[(int)oldFormat][(int)newFormat] = pipeline; + + depth->Release(); + blendstateOff->Release(); + rasterNoCull->Release(); + reinterpretFS->Release(); + } + + // Copy to a temp framebuffer. + Draw::Framebuffer *temp = GetTempFBO(TempFBO::REINTERPRET, vfb->renderWidth, vfb->renderHeight); + + // Ideally on Vulkan this should be using the original framebuffer as an input attachment, allowing it to read from + // itself while writing. + draw_->InvalidateCachedState(); + draw_->CopyFramebufferImage(vfb->fbo, 0, 0, 0, 0, temp, 0, 0, 0, 0, vfb->renderWidth, vfb->renderHeight, 1, Draw::FBChannel::FB_COLOR_BIT, "reinterpret_prep"); + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, reinterpretStrings[(int)oldFormat][(int)newFormat]); + draw_->BindPipeline(pipeline); + draw_->BindFramebufferAsTexture(temp, 0, Draw::FBChannel::FB_COLOR_BIT, 0); + draw_->BindSamplerStates(0, 1, &reinterpretSampler_); + draw_->SetScissorRect(0, 0, vfb->renderWidth, vfb->renderHeight); + Draw::Viewport vp = Draw::Viewport{ 0.0f, 0.0f, (float)vfb->renderWidth, (float)vfb->renderHeight, 0.0f, 1.0f }; + draw_->SetViewports(1, &vp); + // Vertex buffer not used - vertices generated in shader. + // TODO: Switch to a vertex buffer for GLES2/D3D9 compat. + draw_->BindVertexBuffers(0, 1, &reinterpretVBuf_, nullptr); + draw_->Draw(3, 0); + draw_->InvalidateCachedState(); + + // Unbind. + draw_->BindTexture(0, nullptr); + + shaderManager_->DirtyLastShader(); + textureCache_->ForgetLastTexture(); + + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); + + if (currentRenderVfb_ != vfb) { + // In case ReinterpretFramebuffer was called from the texture manager. + draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After reinterpret"); + } + delete[] vsCode; + delete[] fsCode; +} From 31fe0fc39e5da8551c6509f2860341124a7aa120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 11:23:34 +0200 Subject: [PATCH 20/41] Remove some unnecessary bool returns. --- Common/GPU/ShaderWriter.cpp | 3 ++ Common/GPU/ShaderWriter.h | 2 +- GPU/Common/DepalettizeShaderCommon.cpp | 5 +-- GPU/Common/Draw2D.cpp | 7 ++-- GPU/Common/ReinterpretFramebuffer.cpp | 21 ++++-------- GPU/Common/ReinterpretFramebuffer.h | 4 +-- GPU/Common/StencilCommon.cpp | 1 - unittest/TestShaderGenerators.cpp | 44 +++++++++++++++----------- 8 files changed, 41 insertions(+), 46 deletions(-) diff --git a/Common/GPU/ShaderWriter.cpp b/Common/GPU/ShaderWriter.cpp index d57a855ac7..900e2d1160 100644 --- a/Common/GPU/ShaderWriter.cpp +++ b/Common/GPU/ShaderWriter.cpp @@ -313,6 +313,9 @@ void ShaderWriter::EndVSMain(Slice varyings) { case HLSL_D3D11: case HLSL_D3D9: C(" VS_OUTPUT vs_out;\n"); + if (strlen(lang_.viewportYSign)) { + F(" gl_Position.y *= %s1.0;\n", lang_.viewportYSign); + } C(" vs_out.pos = gl_Position;\n"); for (auto &varying : varyings) { F(" vs_out.%s = %s;\n", varying.name, varying.name); diff --git a/Common/GPU/ShaderWriter.h b/Common/GPU/ShaderWriter.h index 9d16f2bf9a..f07d4159f5 100644 --- a/Common/GPU/ShaderWriter.h +++ b/Common/GPU/ShaderWriter.h @@ -43,7 +43,7 @@ enum FSFlags { class ShaderWriter { public: - ShaderWriter(char *buffer, const ShaderLanguageDesc &lang, ShaderStage stage, const char **gl_extensions, size_t num_gl_extensions) : p_(buffer), lang_(lang), stage_(stage) { + ShaderWriter(char *buffer, const ShaderLanguageDesc &lang, ShaderStage stage, const char **gl_extensions = nullptr, size_t num_gl_extensions = 0) : p_(buffer), lang_(lang), stage_(stage) { Preamble(gl_extensions, num_gl_extensions); } ShaderWriter(const ShaderWriter &) = delete; diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index c35cc0e41f..0ec0b6c66c 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -264,7 +264,7 @@ void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config, c } void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLanguageDesc &lang) { - ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0); + ShaderWriter writer(buffer, lang, ShaderStage::Fragment); writer.DeclareSamplers(samplers); writer.HighPrecisionFloat(); writer.BeginFSMain(Slice::empty(), varyings, FSFLAG_NONE); @@ -289,9 +289,6 @@ void GenerateDepalVs(char *buffer, const ShaderLanguageDesc &lang) { writer.BeginVSMain(vsInputs, Slice::empty(), varyings); writer.C(" v_texcoord = a_texcoord0;\n"); writer.C(" gl_Position = vec4(a_position, 0.0, 1.0);\n"); - if (strlen(lang.viewportYSign)) { - writer.F(" gl_Position.y *= %s1.0;\n", lang.viewportYSign); - } writer.EndVSMain(varyings); } diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index f3e55c8e92..1a89c45fd4 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -40,7 +40,7 @@ static const SamplerDef samplers[1] = { }; void GenerateDraw2DFs(char *buffer, const ShaderLanguageDesc &lang) { - ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0); + ShaderWriter writer(buffer, lang, ShaderStage::Fragment); writer.DeclareSamplers(samplers); writer.BeginFSMain(Slice::empty(), varyings, FSFLAG_NONE); writer.C(" vec4 outColor = ").SampleTexture2D("tex", "v_texcoord.xy").C(";\n"); @@ -48,7 +48,7 @@ void GenerateDraw2DFs(char *buffer, const ShaderLanguageDesc &lang) { } void GenerateDraw2DDepthFs(char *buffer, const ShaderLanguageDesc &lang) { - ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0); + ShaderWriter writer(buffer, lang, ShaderStage::Fragment); writer.DeclareSamplers(samplers); writer.BeginFSMain(Slice::empty(), varyings, FSFLAG_WRITEDEPTH); writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n"); @@ -57,13 +57,12 @@ void GenerateDraw2DDepthFs(char *buffer, const ShaderLanguageDesc &lang) { } void GenerateDraw2DVS(char *buffer, const ShaderLanguageDesc &lang) { - ShaderWriter writer(buffer, lang, ShaderStage::Vertex, nullptr, 0); + ShaderWriter writer(buffer, lang, ShaderStage::Vertex); writer.BeginVSMain(inputs, Slice::empty(), varyings); writer.C(" v_texcoord = a_texcoord0;\n"); // yes, this should be right. Should be 2.0 in the far corners. writer.C(" gl_Position = vec4(a_position, 0.0, 1.0);\n"); - writer.F(" gl_Position.y *= %s1.0;\n", lang.viewportYSign); writer.EndVSMain(varyings); } diff --git a/GPU/Common/ReinterpretFramebuffer.cpp b/GPU/Common/ReinterpretFramebuffer.cpp index 691998ed85..bf77181fa7 100644 --- a/GPU/Common/ReinterpretFramebuffer.cpp +++ b/GPU/Common/ReinterpretFramebuffer.cpp @@ -20,12 +20,10 @@ static const SamplerDef samplers[1] = { // TODO: We could possibly have an option to preserve any extra color precision? But gonna start without it. // Requires full size integer math. It would be possible to make a floating point-only version with lots of // modulo and stuff, might do it one day. -bool GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang) { - if (!lang.bitwiseOps) { - return false; - } +void GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang) { + _assert_(lang.bitwiseOps); - ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0); + ShaderWriter writer(buffer, lang, ShaderStage::Fragment); writer.HighPrecisionFloat(); @@ -72,26 +70,19 @@ bool GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBuff } writer.EndFSMain("outColor", FSFLAG_NONE); - return true; } -bool GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang) { - if (!lang.bitwiseOps) { - return false; - } - ShaderWriter writer(buffer, lang, ShaderStage::Vertex, nullptr, 0); +void GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang) { + _assert_(lang.bitwiseOps); + ShaderWriter writer(buffer, lang, ShaderStage::Vertex); writer.BeginVSMain(Slice::empty(), Slice::empty(), varyings); writer.C(" float x = -1.0 + float((gl_VertexIndex & 1) << 2);\n"); writer.C(" float y = -1.0 + float((gl_VertexIndex & 2) << 1);\n"); writer.C(" v_texcoord = (vec2(x, y) + vec2(1.0, 1.0)) * 0.5;\n"); - if (strlen(lang.viewportYSign)) { - writer.F(" y *= %s1.0;\n", lang.viewportYSign); - } writer.C(" gl_Position = vec4(x, y, 0.0, 1.0);\n"); writer.EndVSMain(varyings); - return true; } diff --git a/GPU/Common/ReinterpretFramebuffer.h b/GPU/Common/ReinterpretFramebuffer.h index e45472a321..5819366887 100644 --- a/GPU/Common/ReinterpretFramebuffer.h +++ b/GPU/Common/ReinterpretFramebuffer.h @@ -4,8 +4,8 @@ #include "GPU/GPUCommon.h" #include "Common/GPU/ShaderWriter.h" -bool GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang); +void GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang); // Just a single one. Can probably be shared with a lot of similar use cases. // Generates the coordinates for a fullscreen triangle. -bool GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang); +void GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang); diff --git a/GPU/Common/StencilCommon.cpp b/GPU/Common/StencilCommon.cpp index 950c84dd35..acac2967ed 100644 --- a/GPU/Common/StencilCommon.cpp +++ b/GPU/Common/StencilCommon.cpp @@ -123,7 +123,6 @@ void GenerateStencilVs(char *buffer, const ShaderLanguageDesc &lang) { writer.C(" v_texcoord = a_position * 2.0;\n"); // yes, this should be right. Should be 2.0 in the far corners. } writer.C(" gl_Position = vec4(v_texcoord * 2.0 - vec2(1.0, 1.0), 0.0, 1.0);\n"); - writer.F(" gl_Position.y *= %s1.0;\n", lang.viewportYSign); writer.EndVSMain(varyings); } diff --git a/unittest/TestShaderGenerators.cpp b/unittest/TestShaderGenerators.cpp index 1a5d6b4164..19b0b0d2e9 100644 --- a/unittest/TestShaderGenerators.cpp +++ b/unittest/TestShaderGenerators.cpp @@ -181,19 +181,23 @@ bool TestReinterpretShaders() { bool failed = false; for (int k = 0; k < ARRAY_SIZE(languages); k++) { + printf("=== %s ===\n\n", ShaderLanguageToString(languages[k])); + ShaderLanguageDesc desc(languages[k]); - if (!GenerateReinterpretVertexShader(buffer, desc)) { - printf("Failed!\n%s\n", buffer); + + // These require bitwise operations. + if (!desc.bitwiseOps) { + continue; + } + + GenerateReinterpretVertexShader(buffer, desc); + std::string errorMessage; + if (!TestCompileShader(buffer, languages[k], ShaderStage::Vertex, &errorMessage)) { + printf("Error compiling fragment shader:\n\n%s\n\n%s\n", LineNumberString(buffer).c_str(), errorMessage.c_str()); failed = true; + return false; } else { - std::string errorMessage; - if (!TestCompileShader(buffer, languages[k], ShaderStage::Vertex, &errorMessage)) { - printf("Error compiling fragment shader:\n\n%s\n\n%s\n", LineNumberString(buffer).c_str(), errorMessage.c_str()); - failed = true; - return false; - } else { - //printf("===\n%s\n===\n", buffer); - } + //printf("===\n%s\n===\n", buffer); } } @@ -201,23 +205,25 @@ bool TestReinterpretShaders() { printf("=== %s ===\n\n", ShaderLanguageToString(languages[k])); ShaderLanguageDesc desc(languages[k]); + + // These require bitwise operations. + if (!desc.bitwiseOps) { + continue; + } + std::string errorMessage; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (i == j) continue; // useless shader! - if (!GenerateReinterpretFragmentShader(buffer, fmts[i], fmts[j], desc)) { - printf("Failed!\n%s\n", buffer); + GenerateReinterpretFragmentShader(buffer, fmts[i], fmts[j], desc); + if (!TestCompileShader(buffer, languages[k], ShaderStage::Fragment, &errorMessage)) { + printf("Error compiling fragment shader %d:\n\n%s\n\n%s\n", (int)j, LineNumberString(buffer).c_str(), errorMessage.c_str()); failed = true; + return false; } else { - if (!TestCompileShader(buffer, languages[k], ShaderStage::Fragment, &errorMessage)) { - printf("Error compiling fragment shader %d:\n\n%s\n\n%s\n", (int)j, LineNumberString(buffer).c_str(), errorMessage.c_str()); - failed = true; - return false; - } else { - printf("===\n%s\n===\n", buffer); - } + printf("===\n%s\n===\n", buffer); } } } From 3a0d43ae1e2a80455cbd527149f0715b3a2515dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 11:47:38 +0200 Subject: [PATCH 21/41] Remove deprecated function (mostly) --- Common/GPU/D3D11/thin3d_d3d11.cpp | 17 ----------------- Common/GPU/Vulkan/thin3d_vulkan.cpp | 20 -------------------- Common/GPU/thin3d.h | 8 ++++---- 3 files changed, 4 insertions(+), 41 deletions(-) diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index 90bec0ecfe..6dd922f1c1 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -100,8 +100,6 @@ public: } void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; - uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) override; - void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override; void InvalidateCachedState() override; @@ -1709,21 +1707,6 @@ uint64_t D3D11DrawContext::GetNativeObject(NativeObject obj, void *srcObject) { } } -uintptr_t D3D11DrawContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) { - D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo; - switch (channelBit) { - case FB_COLOR_BIT: return (uintptr_t)fb->colorTex; - case FB_DEPTH_BIT: return (uintptr_t)fb->depthStencilTex; - case FB_COLOR_BIT | FB_VIEW_BIT: return (uintptr_t)fb->colorRTView; - case FB_DEPTH_BIT | FB_VIEW_BIT: return (uintptr_t)fb->depthStencilRTView; - case FB_COLOR_BIT | FB_FORMAT_BIT: return (uintptr_t)fb->colorFormat; - case FB_DEPTH_BIT | FB_FORMAT_BIT: return (uintptr_t)fb->depthStencilFormat; - case FB_STENCIL_BIT | FB_FORMAT_BIT: return (uintptr_t)fb->depthStencilFormat; - default: - return 0; - } -} - void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) { D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo; if (fb) { diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 3b0f0d10e6..72236d5e74 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -395,8 +395,6 @@ public: } void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; - uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) override; - void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override; void SetScissorRect(int left, int top, int width, int height) override; @@ -1580,24 +1578,6 @@ void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChanne boundImageView_[binding] = renderManager_.BindFramebufferAsTexture(fb->GetFB(), binding, aspect, attachment); } -uintptr_t VKContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) { - if (!fbo) - return 0; - - VKFramebuffer *fb = (VKFramebuffer *)fbo; - VkImageView view = VK_NULL_HANDLE; - switch (channelBit) { - case FB_COLOR_BIT: - view = fb->GetFB()->color.imageView; - break; - case FB_DEPTH_BIT: - case FB_STENCIL_BIT: - view = fb->GetFB()->depth.imageView; - break; - } - return (uintptr_t)view; -} - void VKContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) { VKFramebuffer *fb = (VKFramebuffer *)fbo; if (fb) { diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index cbd5cafef1..7dfa09fc7e 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -605,12 +605,15 @@ public: virtual void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {} // Partial pipeline state, used to create pipelines. (in practice, in d3d11 they'll use the native state objects directly). + // TODO: Possibly ditch these and just put the descs directly in PipelineDesc since only D3D11 benefits. virtual DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) = 0; virtual BlendState *CreateBlendState(const BlendStateDesc &desc) = 0; virtual SamplerState *CreateSamplerState(const SamplerStateDesc &desc) = 0; virtual RasterState *CreateRasterState(const RasterStateDesc &desc) = 0; // virtual ComputePipeline CreateComputePipeline(const ComputePipelineDesc &desc) = 0 virtual InputLayout *CreateInputLayout(const InputLayoutDesc &desc) = 0; + virtual ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const std::string &tag = "thin3d") = 0; + virtual Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc) = 0; // Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them. ShaderModule *GetVshaderPreset(VertexShaderPreset preset) { return vsPresets_[preset]; } @@ -623,9 +626,6 @@ public: // On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. virtual Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) = 0; - virtual ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const std::string &tag = "thin3d") = 0; - virtual Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc) = 0; - // Copies data from the CPU over into the buffer, at a specific offset. This does not change the size of the buffer and cannot write outside it. virtual void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) = 0; @@ -646,7 +646,7 @@ public: // binding must be < MAX_TEXTURE_SLOTS (0, 1 are okay if it's 2). virtual void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) = 0; - // deprecated + // deprecated, only used by D3D9 virtual uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) { return 0; } From a4cf0871161c8476087e1982db0a905592a4879a Mon Sep 17 00:00:00 2001 From: tunip3 <26260613+tunip3@users.noreply.github.com> Date: Tue, 16 Aug 2022 11:03:06 +0100 Subject: [PATCH 22/41] remove storage fileloader and storage folderbrowser --- UWP/PPSSPP_UWPMain.cpp | 9 +- UWP/StorageFileLoader.cpp | 185 ----------------------------------- UWP/StorageFileLoader.h | 90 ----------------- UWP/StorageFolderBrowser.cpp | 72 -------------- UWP/StorageFolderBrowser.h | 70 ------------- UWP/UWP.vcxproj | 6 +- UWP/UWP.vcxproj.filters | 6 +- 7 files changed, 4 insertions(+), 434 deletions(-) delete mode 100644 UWP/StorageFileLoader.cpp delete mode 100644 UWP/StorageFileLoader.h delete mode 100644 UWP/StorageFolderBrowser.cpp delete mode 100644 UWP/StorageFolderBrowser.h diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index ead36b0743..795481e979 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -32,7 +32,6 @@ #include "XAudioSoundStream.h" #include "UWPHost.h" #include "UWPUtil.h" -#include "StorageFileLoader.h" #include "App.h" using namespace UWP; @@ -304,11 +303,6 @@ void PPSSPP_UWPMain::OnSuspend() { // TODO } -void PPSSPP_UWPMain::LoadStorageFile(StorageFile ^file) { - std::unique_ptr factory(new StorageFileLoaderFactory(file, IdentifiedFileType::PSP_ISO)); - RegisterFileLoaderFactory("override://", std::move(factory)); - NativeMessageReceived("boot", "override://file"); -} UWPGraphicsContext::UWPGraphicsContext(std::shared_ptr resources) { std::vector adapterNames; @@ -463,7 +457,8 @@ void System_SendMessage(const char *command, const char *parameter) { create_task(picker->PickSingleFileAsync()).then([](StorageFile ^file){ if (file) { - g_main->LoadStorageFile(file); + std::string path = FromPlatformString(file->Path); + NativeMessageReceived("boot", path.c_str()); } }); } else if (!strcmp(command, "toggle_fullscreen")) { diff --git a/UWP/StorageFileLoader.cpp b/UWP/StorageFileLoader.cpp deleted file mode 100644 index 8e831a8787..0000000000 --- a/UWP/StorageFileLoader.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include "pch.h" -#include "ppltasks.h" - -#include "Common/Log.h" -#include "Common/File/FileUtil.h" -#include "Common/File/Path.h" -#include "Common/File/DirListing.h" -#include "Common/Thread/ThreadUtil.h" -#include "StorageFileLoader.h" -#include "Common/Log.h" -#include "UWPUtil.h" - -using namespace Concurrency; -using namespace Windows::Storage; -using namespace Windows::Storage::Streams; - -// Not sure how necessary this one is. -static std::mutex initMutex; - -StorageFileLoader::StorageFileLoader(Windows::Storage::StorageFile ^file) { - active_ = false; - file_ = file; - path_ = Path(FromPlatformString(file_->Path)); - thread_.reset(new std::thread([this]() { this->threadfunc(); })); - - // Before we proceed, we need to block until the thread has found the size. - // Hacky way: - while (size_ < 0) { - Sleep(10); - } -} - -StorageFileLoader::~StorageFileLoader() { - { - std::unique_lock lock(mutex_); - active_ = false; - operationRequested_ = false; - cond_.notify_one(); - } - thread_->join(); -} - -void StorageFileLoader::threadfunc() { - SetCurrentThreadName("StorageFileLoader"); - - { - std::unique_lock lock(initMutex); - _assert_(!active_); - auto opentask = create_task(file_->OpenReadAsync()).then([this](IRandomAccessStreamWithContentType ^stream) { - stream_ = stream; - active_ = true; - }); - - try { - opentask.wait(); - } catch (const std::exception& e) { - operationFailed_ = true; - // TODO: What do we do? - const char *what = e.what(); - INFO_LOG(SYSTEM, "%s", what); - } catch (Platform::COMException ^e) { - - } - - auto sizetask = create_task(file_->GetBasicPropertiesAsync()).then([this](Windows::Storage::FileProperties::BasicProperties ^props) { - size_ = props->Size; - }); - try { - sizetask.wait(); - } catch (const std::exception& e) { - const char *what = e.what(); - INFO_LOG(SYSTEM, "%s", what); - } catch (Platform::COMException ^e) { - std::string what = FromPlatformString(e->ToString()); - INFO_LOG(SYSTEM, "%s", what.c_str()); - } - } - - std::unique_lock lock(mutex_); - while (active_) { - if (!operationRequested_) { - cond_.wait(lock); - } - if (operationRequested_) { - switch (operation_.type) { - case OpType::READ_AT: { - Streams::Buffer ^buf = ref new Streams::Buffer((unsigned int)operation_.size); - operationFailed_ = false; - stream_->Seek(operation_.offset); - auto task = create_task(stream_->ReadAsync(buf, (unsigned int)operation_.size, Streams::InputStreamOptions::None)); - Streams::IBuffer ^output = nullptr; - try { - task.wait(); - output = task.get(); - } catch (const std::exception& e) { - operationFailed_ = true; - const char *what = e.what(); - INFO_LOG(SYSTEM, "%s", what); - } - std::unique_lock lock(mutexResponse_); - operationRequested_ = false; - response_.buffer = output; - responseAvailable_ = true; - condResponse_.notify_one(); - break; - } - default: - operationRequested_ = false; - break; - } - } - } -} - -bool StorageFileLoader::Exists() { - return file_ != nullptr; -} - -bool StorageFileLoader::ExistsFast() { - return file_ != nullptr; -} - -bool StorageFileLoader::IsDirectory() { - return (file_->Attributes & Windows::Storage::FileAttributes::Directory) != Windows::Storage::FileAttributes::Normal; -} - -s64 StorageFileLoader::FileSize() { - EnsureOpen(); - if (size_ == -1) - __debugbreak(); // crude race condition detection - return size_; -} - -Path StorageFileLoader::GetPath() const { - return path_; -} - -void StorageFileLoader::EnsureOpen() { - while (size_ == -1) - Sleep(50); -} - -size_t StorageFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags) { - // We can't handle multiple of these at a time, so serialize the easy way. - std::unique_lock lock(operationMutex_); - - EnsureOpen(); - - _assert_(!operationRequested_); - _assert_(!responseAvailable_) - - { - std::unique_lock lock(mutex_); - operation_.type = OpType::READ_AT; - operation_.offset = absolutePos; - operation_.size = (int64_t)(bytes * count); - operationRequested_ = true; - cond_.notify_one(); - } - - // OK, now wait for response... - { - std::unique_lock responseLock(mutexResponse_); - while (!responseAvailable_) { - condResponse_.wait(responseLock); - } - // still under mutexResponse_ lock here. - responseAvailable_ = false; - if (operationFailed_) { - return 0; - } - - DataReader ^rd = DataReader::FromBuffer(response_.buffer); - size_t len = response_.buffer->Length; - Platform::Array ^bytearray = ref new Platform::Array((unsigned int)len); - rd->ReadBytes(bytearray); - memcpy(data, bytearray->Data, len); - response_.buffer = nullptr; - return len / bytes; - } -} - -FileLoader *StorageFileLoaderFactory::ConstructFileLoader(const Path &filename) { - return file_ ? new StorageFileLoader(file_) : nullptr; -} diff --git a/UWP/StorageFileLoader.h b/UWP/StorageFileLoader.h deleted file mode 100644 index 316ca4cc34..0000000000 --- a/UWP/StorageFileLoader.h +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once - -#include "pch.h" - -#include -#include -#include -#include -#include - -#include "Common/CommonTypes.h" -#include "Common/File/Path.h" -#include "Core/Loaders.h" - -// This thing is a terrible abomination that wraps asynchronous file access behind a synchronous interface, -// completely defeating MS' design goals for StorageFile. But hey, you gotta do what you gotta do. -// This opens a stream attached to the passed-in file. Multiple of these can be created against one StorageFile. -class StorageFileLoader : public FileLoader { -public: - StorageFileLoader(Windows::Storage::StorageFile ^file); - ~StorageFileLoader(); - - bool Exists() override; - bool ExistsFast() override; - - bool IsDirectory() override; - s64 FileSize() override; - Path GetPath() const override; - - size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override; - -private: - void threadfunc(); - void EnsureOpen(); - - enum class OpType { - NONE, - READ_AT, - }; - - struct Operation { - OpType type; - int64_t offset; - int64_t size; - }; - - struct Response { - Windows::Storage::Streams::IBuffer ^buffer; - }; - - bool active_ = false; - int64_t size_ = -1; - std::unique_ptr thread_; - - Windows::Storage::StorageFile ^file_; - Windows::Storage::Streams::IRandomAccessStreamWithContentType ^stream_; - Path path_; - - std::mutex operationMutex_; - - bool operationRequested_ = false; - Operation operation_{ OpType::NONE, 0, 0 }; - std::condition_variable cond_; - std::mutex mutex_; - - bool operationFailed_ = false; - - bool responseAvailable_ = false; - Response response_; - std::condition_variable condResponse_; - std::mutex mutexResponse_; - - int64_t seekPos_ = 0; -}; - -class StorageFileLoaderFactory : public FileLoaderFactory { -public: - StorageFileLoaderFactory(Windows::Storage::StorageFile ^file, IdentifiedFileType fileType) : file_(file), fileType_(fileType) { } - FileLoader *ConstructFileLoader(const Path &filename) override; - -private: - Windows::Storage::StorageFile ^file_; - IdentifiedFileType fileType_; -}; - -// Similar to StorageFileLoader but for directory browsing. -class StorageDirectoryWrapper { -private: - std::thread thread_; -}; diff --git a/UWP/StorageFolderBrowser.cpp b/UWP/StorageFolderBrowser.cpp deleted file mode 100644 index 24df2dba98..0000000000 --- a/UWP/StorageFolderBrowser.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "pch.h" -#include "ppltasks.h" - -#include "Common/Thread/ThreadUtil.h" - -#include "StorageFolderBrowser.h" -#include "UWPUtil.h" - -using namespace Concurrency; -using namespace Windows::Storage; -using namespace Windows::Storage::Streams; - -static std::mutex initMutex; - -StorageFolderBrowser::StorageFolderBrowser(Windows::Storage::StorageFolder ^folder) : folder_(folder) { - thread_.reset(new std::thread([this]() { this->threadfunc(); })); - - path_ = FromPlatformString(folder->Path); - displayName_ = FromPlatformString(folder->DisplayName); -} - -void StorageFolderBrowser::threadfunc() { - SetCurrentThreadName("StorageFileLoader"); - - initMutex.lock(); - - /* - auto opentask = create_task(folder_->GetItemsAsync()->OpenReadAsync()).then([this](IRandomAccessStreamWithContentType ^stream) { - stream_ = stream; - active_ = true; - }); - - try { - opentask.wait(); - } - catch (const std::exception& e) { - operationFailed_ = true; - // TODO: What do we do? - const char *what = e.what(); - ILOG("%s", what); - } - catch (Platform::COMException ^e) { - - } - - auto sizetask = create_task(file_->GetBasicPropertiesAsync()).then([this](Windows::Storage::FileProperties::BasicProperties ^props) { - size_ = props->Size; - }); - try { - sizetask.wait(); - } - catch (const std::exception& e) { - const char *what = e.what(); - ILOG("%s", what); - } - catch (Platform::COMException ^e) { - std::string what = FromPlatformString(e->ToString()); - ILOG("%s", what.c_str()); - } - */ - initMutex.unlock(); - - std::unique_lock lock(mutex_); - while (active_) { - if (!operationRequested_) { - cond_.wait(lock); - } - if (operationRequested_) { - operationRequested_ = false; - } - } -} diff --git a/UWP/StorageFolderBrowser.h b/UWP/StorageFolderBrowser.h deleted file mode 100644 index b349b4636e..0000000000 --- a/UWP/StorageFolderBrowser.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once -#pragma once - -#include "pch.h" - -#include -#include -#include -#include -#include - -#include "Common/CommonTypes.h" -#include "Core/Loaders.h" - -// This thing is a terrible abomination that wraps asynchronous file access behind a synchronous interface, -// completely defeating MS' design goals for StorageFile. But hey, you gotta do what you gotta do. -// This opens a stream attached to the passed-in file. Multiple of these can be created against one StorageFile. - -class StorageFolderBrowser { -public: - StorageFolderBrowser(Windows::Storage::StorageFolder ^folder); - ~StorageFolderBrowser(); - - std::string GetPath() const { - return path_; - } - - std::string DisplayName() const { - return displayName_; - } - - -private: - void threadfunc(); - - enum class OpType { - NONE, - LIST_DIRECTORY, - CHANGE_FOLDER, - }; - - struct Operation { - OpType type; - }; - - struct Response { - }; - - std::string path_; - std::string displayName_; - - bool active_ = false; - std::unique_ptr thread_; - - Windows::Storage::StorageFolder ^folder_; - - bool operationRequested_ = false; - Operation operation_{ OpType::NONE }; - std::condition_variable cond_; - std::mutex mutex_; - - bool operationFailed_ = false; - - bool responseAvailable_ = false; - Response response_; - std::condition_variable condResponse_; - std::mutex mutexResponse_; - - int64_t seekPos_ = 0; -}; diff --git a/UWP/UWP.vcxproj b/UWP/UWP.vcxproj index 6426e6309b..3b7f8013d4 100644 --- a/UWP/UWP.vcxproj +++ b/UWP/UWP.vcxproj @@ -538,8 +538,6 @@ - - @@ -579,8 +577,6 @@ Create Create - - @@ -1778,4 +1774,4 @@ - + \ No newline at end of file diff --git a/UWP/UWP.vcxproj.filters b/UWP/UWP.vcxproj.filters index 209fd4951f..03611fcc46 100644 --- a/UWP/UWP.vcxproj.filters +++ b/UWP/UWP.vcxproj.filters @@ -61,10 +61,8 @@ - - @@ -74,11 +72,9 @@ - - @@ -381,4 +377,4 @@ Content - + \ No newline at end of file From cbe6a9161a9b684937b1f53f398a8a78c6a1349e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 12:14:10 +0200 Subject: [PATCH 23/41] Remove some unused code in FramebufferManagerD3D11.cpp/h --- GPU/D3D11/FramebufferManagerD3D11.cpp | 60 --------------------------- GPU/D3D11/FramebufferManagerD3D11.h | 9 ---- GPU/D3D11/GPU_D3D11.cpp | 3 -- GPU/Directx9/GPU_DX9.cpp | 1 - 4 files changed, 73 deletions(-) diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 599e5718fa..f05bc499fe 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -20,74 +20,14 @@ #include #include "Common/Common.h" -#include "Common/Data/Convert/ColorConv.h" #include "Common/GPU/thin3d.h" -#include "Core/MemMap.h" -#include "Core/Config.h" -#include "Core/ConfigValues.h" -#include "Core/System.h" -#include "Core/Reporting.h" -#include "GPU/ge_constants.h" -#include "GPU/GPUState.h" -#include "GPU/Debugger/Stepping.h" #include "GPU/Common/FramebufferManagerCommon.h" #include "GPU/Common/PresentationCommon.h" -#include "GPU/Common/TextureDecoder.h" #include "GPU/D3D11/FramebufferManagerD3D11.h" -#include "GPU/D3D11/ShaderManagerD3D11.h" -#include "GPU/D3D11/TextureCacheD3D11.h" -#include "GPU/D3D11/DrawEngineD3D11.h" - -#ifdef _M_SSE -#include -#endif FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) : FramebufferManagerCommon(draw) { - device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE); - context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); - featureLevel_ = (D3D_FEATURE_LEVEL)draw->GetNativeObject(Draw::NativeObject::FEATURE_LEVEL); - presentation_->SetLanguage(HLSL_D3D11); preferredPixelsFormat_ = Draw::DataFormat::B8G8R8A8_UNORM; } - -static void CopyPixelDepthOnly(u32 *dstp, const u32 *srcp, size_t c) { - size_t x = 0; - -#ifdef _M_SSE - size_t sseSize = (c / 4) * 4; - const __m128i srcMask = _mm_set1_epi32(0x00FFFFFF); - const __m128i dstMask = _mm_set1_epi32(0xFF000000); - __m128i *dst = (__m128i *)dstp; - const __m128i *src = (const __m128i *)srcp; - - for (; x < sseSize; x += 4) { - const __m128i bits24 = _mm_and_si128(_mm_load_si128(src), srcMask); - const __m128i bits8 = _mm_and_si128(_mm_load_si128(dst), dstMask); - _mm_store_si128(dst, _mm_or_si128(bits24, bits8)); - dst++; - src++; - } -#endif - - // Copy the remaining pixels that didn't fit in SSE. - for (; x < c; ++x) { - memcpy(dstp + x, srcp + x, 3); - } -} - -// Nobody calls this yet. -void FramebufferManagerD3D11::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) { - if (!vfb->fbo) { - ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0"); - return; - } - - const u32 z_address = vfb->z_address; - // TODO -} - -void FramebufferManagerD3D11::EndFrame() { -} diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index 17ba33ec58..fc280e9de6 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -34,13 +34,4 @@ class ShaderManagerD3D11; class FramebufferManagerD3D11 : public FramebufferManagerCommon { public: FramebufferManagerD3D11(Draw::DrawContext *draw); - - void EndFrame(); - -private: - void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); - - ID3D11Device *device_; - ID3D11DeviceContext *context_; - D3D_FEATURE_LEVEL featureLevel_; }; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 23798640ee..ba41521fde 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -232,7 +232,6 @@ void GPU_D3D11::BeginFrame() { textureCacheD3D11_->StartFrame(); drawEngine_.BeginFrame(); - // fragmentTestCache_.Decimate(); shaderManagerD3D11_->DirtyLastShader(); @@ -255,9 +254,7 @@ void GPU_D3D11::CopyDisplayToOutput(bool reallyDirty) { context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], blendColor, 0xFFFFFFFF); framebufferManagerD3D11_->CopyDisplayToOutput(reallyDirty); - framebufferManagerD3D11_->EndFrame(); - // shaderManager_->EndFrame(); shaderManagerD3D11_->DirtyLastShader(); gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index fe2cf594fd..65da1a0773 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -280,7 +280,6 @@ void GPU_DX9::ReapplyGfxState() { void GPU_DX9::BeginFrame() { textureCacheDX9_->StartFrame(); drawEngine_.BeginFrame(); - // fragmentTestCache_.Decimate(); GPUCommon::BeginFrame(); shaderManagerDX9_->DirtyShader(); From b7dc1379c60c38d897a443db581e10c42fc49297 Mon Sep 17 00:00:00 2001 From: tunip3 <26260613+tunip3@users.noreply.github.com> Date: Tue, 16 Aug 2022 11:34:55 +0100 Subject: [PATCH 24/41] add bin and elf to picker as they now work --- UWP/PPSSPP_UWPMain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 795481e979..e4ed18b8f2 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -451,8 +451,8 @@ void System_SendMessage(const char *command, const char *parameter) { picker->FileTypeFilter->Append(".iso"); // Can't load these this way currently, they require mounting the underlying folder. - // picker->FileTypeFilter->Append(".bin"); - // picker->FileTypeFilter->Append(".elf"); + picker->FileTypeFilter->Append(".bin"); + picker->FileTypeFilter->Append(".elf"); picker->SuggestedStartLocation = Pickers::PickerLocationId::DocumentsLibrary; create_task(picker->PickSingleFileAsync()).then([](StorageFile ^file){ From 1e57a358b8710fd8be5ae92ffa37463b27c0f164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 12:46:13 +0200 Subject: [PATCH 25/41] thin3d: Properly AddRef and Release shader modules from the pipeline in backends that need it --- Common/GPU/D3D9/thin3d_d3d9.cpp | 16 +++++++++++---- Common/GPU/thin3d.cpp | 5 +++++ Common/GPU/thin3d.h | 4 +++- GPU/Common/Draw2D.cpp | 26 ++++++++++++++----------- GPU/Common/FramebufferManagerCommon.cpp | 11 ++++++----- GPU/Common/FramebufferManagerCommon.h | 3 +-- 6 files changed, 42 insertions(+), 23 deletions(-) diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index 7b2fa934b0..845fa45d5f 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -259,17 +259,23 @@ class D3D9Pipeline : public Pipeline { public: D3D9Pipeline() {} ~D3D9Pipeline() { + if (vshader) { + vshader->Release(); + } + if (pshader) { + pshader->Release(); + } } - D3D9ShaderModule *vshader; - D3D9ShaderModule *pshader; + D3D9ShaderModule *vshader = nullptr; + D3D9ShaderModule *pshader = nullptr; - D3DPRIMITIVETYPE prim; + D3DPRIMITIVETYPE prim{}; AutoRef inputLayout; AutoRef depthStencil; AutoRef blend; AutoRef raster; - UniformBufferDesc dynamicUniforms; + UniformBufferDesc dynamicUniforms{}; void Apply(LPDIRECT3DDEVICE9 device, uint8_t stencilRef, uint8_t stencilWriteMask, uint8_t stencilCompareMask); }; @@ -713,9 +719,11 @@ Pipeline *D3D9Context::CreateGraphicsPipeline(const PipelineDesc &desc) { } if (iter->GetStage() == ShaderStage::Fragment) { pipeline->pshader = static_cast(iter); + pipeline->pshader->AddRef(); } else if (iter->GetStage() == ShaderStage::Vertex) { pipeline->vshader = static_cast(iter); + pipeline->vshader->AddRef(); } } pipeline->prim = primToD3D9[(int)desc.prim]; diff --git a/Common/GPU/thin3d.cpp b/Common/GPU/thin3d.cpp index b5a2b89c2c..9dee5898fb 100644 --- a/Common/GPU/thin3d.cpp +++ b/Common/GPU/thin3d.cpp @@ -66,10 +66,15 @@ bool DataFormatIsDepthStencil(DataFormat fmt) { } } +RefCountedObject::~RefCountedObject() { + _dbg_assert_(refcount_ == 0xDEDEDE); +} bool RefCountedObject::Release() { if (refcount_ > 0 && refcount_ < 10000) { if (--refcount_ == 0) { + // Make it very obvious if we try to free this again. + refcount_ = 0xDEDEDE; delete this; return true; } diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index 7dfa09fc7e..264e240fa9 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -341,7 +341,9 @@ public: RefCountedObject() { refcount_ = 1; } - virtual ~RefCountedObject() {} + RefCountedObject(const RefCountedObject &other) = delete; + RefCountedObject& operator=(RefCountedObject const&) = delete; + virtual ~RefCountedObject(); void AddRef() { refcount_++; } bool Release(); diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index 1a89c45fd4..a137379b59 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -110,19 +110,20 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver if (!draw2DPipelineColor_) { char *fsCode = new char[4000]; - char *fsDepthCode = new char[4000]; GenerateDraw2DFs(fsCode, shaderLanguageDesc); - GenerateDraw2DDepthFs(fsDepthCode, shaderLanguageDesc); - draw2DFs_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "draw2d_fs"); + ShaderModule *draw2DFs = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "draw2d_fs"); + delete[] fsCode; - _assert_(draw2DFs_); + _assert_(draw2DFs); + ShaderModule *draw2DFsDepth = nullptr; if (draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { - draw2DFsDepth_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsDepthCode, strlen(fsDepthCode), "draw2d_depth_fs"); - _assert_(draw2DFsDepth_); - } else { - draw2DFsDepth_ = nullptr; + char *fsDepthCode = new char[4000]; + GenerateDraw2DDepthFs(fsDepthCode, shaderLanguageDesc); + draw2DFsDepth = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsDepthCode, strlen(fsDepthCode), "draw2d_depth_fs"); + delete[] fsDepthCode; + _assert_(draw2DFsDepth); } // verts have positions in 2D clip coordinates. @@ -151,7 +152,7 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver PipelineDesc draw2DColorPipelineDesc{ Primitive::TRIANGLE_STRIP, - { draw2DVs_, draw2DFs_ }, + { draw2DVs_, draw2DFs }, inputLayout, noDepthStencil, blendOff, rasterNoCull, nullptr, }; @@ -159,7 +160,7 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver PipelineDesc draw2DDepthPipelineDesc{ Primitive::TRIANGLE_STRIP, - { draw2DVs_, draw2DFsDepth_ }, + { draw2DVs_, draw2DFsDepth }, inputLayout, depthWriteAlways, blendDiscard, rasterNoCull, nullptr, }; @@ -170,7 +171,10 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver draw2DPipelineDepth_ = nullptr; } - delete[] fsCode; + draw2DFs->Release(); + if (draw2DFsDepth) { + draw2DFsDepth->Release(); + } rasterNoCull->Release(); blendOff->Release(); diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index a755a5aab1..b402cff8e0 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2351,6 +2351,9 @@ static void DoRelease(T *&obj) { void FramebufferManagerCommon::DeviceLost() { DestroyAllFBOs(); + + presentation_->DeviceLost(); + for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { DoRelease(reinterpretFromTo_[i][j]); @@ -2363,14 +2366,12 @@ void FramebufferManagerCommon::DeviceLost() { DoRelease(stencilUploadVs_); DoRelease(stencilUploadSampler_); DoRelease(stencilUploadPipeline_); - DoRelease(draw2DPipelineColor_); - DoRelease(draw2DPipelineDepth_); DoRelease(draw2DSamplerNearest_); DoRelease(draw2DSamplerLinear_); DoRelease(draw2DVs_); - DoRelease(draw2DFs_); - DoRelease(draw2DFsDepth_); - presentation_->DeviceLost(); + DoRelease(draw2DPipelineColor_); + DoRelease(draw2DPipelineDepth_); + draw_ = nullptr; } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 624d20a3d0..df35a139b6 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -492,6 +492,5 @@ protected: Draw::SamplerState *draw2DSamplerLinear_ = nullptr; Draw::SamplerState *draw2DSamplerNearest_ = nullptr; Draw::ShaderModule *draw2DVs_ = nullptr; - Draw::ShaderModule *draw2DFs_ = nullptr; - Draw::ShaderModule *draw2DFsDepth_ = nullptr; + // The fragment shaders are "owned" by the pipelines since they're 1:1. }; From 570e0326e72b9ef08a5c852ef6f8ef68a839be65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 12:48:41 +0200 Subject: [PATCH 26/41] Rely on refcounting for stencil upload shader modules --- GPU/Common/FramebufferManagerCommon.cpp | 2 -- GPU/Common/FramebufferManagerCommon.h | 2 -- GPU/Common/StencilCommon.cpp | 11 +++++++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index b402cff8e0..0a5cdd2743 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2362,8 +2362,6 @@ void FramebufferManagerCommon::DeviceLost() { DoRelease(reinterpretVBuf_); DoRelease(reinterpretSampler_); DoRelease(reinterpretVS_); - DoRelease(stencilUploadFs_); - DoRelease(stencilUploadVs_); DoRelease(stencilUploadSampler_); DoRelease(stencilUploadPipeline_); DoRelease(draw2DSamplerNearest_); diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index df35a139b6..f60d6cb679 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -482,8 +482,6 @@ protected: // Common implementation of stencil buffer upload. Also not 100% optimal, but not perforamnce // critical either. Draw::Pipeline *stencilUploadPipeline_ = nullptr; - Draw::ShaderModule *stencilUploadVs_ = nullptr; - Draw::ShaderModule *stencilUploadFs_ = nullptr; Draw::SamplerState *stencilUploadSampler_ = nullptr; // Draw2D pipelines diff --git a/GPU/Common/StencilCommon.cpp b/GPU/Common/StencilCommon.cpp index acac2967ed..5cd0f9d795 100644 --- a/GPU/Common/StencilCommon.cpp +++ b/GPU/Common/StencilCommon.cpp @@ -207,10 +207,10 @@ bool FramebufferManagerCommon::PerformStencilUpload(u32 addr, int size, StencilU GenerateStencilFs(fsCode, shaderLanguageDesc, draw_->GetBugs()); GenerateStencilVs(vsCode, shaderLanguageDesc); - stencilUploadFs_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "stencil_fs"); - stencilUploadVs_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "stencil_vs"); + ShaderModule *stencilUploadFs = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "stencil_fs"); + ShaderModule *stencilUploadVs = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "stencil_vs"); - _assert_(stencilUploadFs_ && stencilUploadVs_); + _assert_(stencilUploadFs && stencilUploadVs); InputLayoutDesc desc = { { @@ -234,7 +234,7 @@ bool FramebufferManagerCommon::PerformStencilUpload(u32 addr, int size, StencilU PipelineDesc stencilWriteDesc{ Primitive::TRIANGLE_LIST, - { stencilUploadVs_, stencilUploadFs_ }, + { stencilUploadVs, stencilUploadFs }, inputLayout, stencilWrite, blendOff, rasterNoCull, &stencilUBDesc, }; stencilUploadPipeline_ = draw_->CreateGraphicsPipeline(stencilWriteDesc); @@ -248,6 +248,9 @@ bool FramebufferManagerCommon::PerformStencilUpload(u32 addr, int size, StencilU stencilWrite->Release(); inputLayout->Release(); + stencilUploadFs->Release(); + stencilUploadVs->Release(); + SamplerStateDesc descNearest{}; stencilUploadSampler_ = draw_->CreateSamplerState(descNearest); } From dbf16cb106195bde6f50b3efdbea5145af5b5224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 12:50:48 +0200 Subject: [PATCH 27/41] Minor cleanup in reinterpret --- GPU/Common/ReinterpretFramebuffer.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/GPU/Common/ReinterpretFramebuffer.cpp b/GPU/Common/ReinterpretFramebuffer.cpp index bf77181fa7..b453a4d3d6 100644 --- a/GPU/Common/ReinterpretFramebuffer.cpp +++ b/GPU/Common/ReinterpretFramebuffer.cpp @@ -150,15 +150,13 @@ void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, G return; } - char *vsCode = nullptr; - char *fsCode = nullptr; - if (!reinterpretVS_) { - vsCode = new char[4000]; + char *vsCode = new char[4000]; const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); GenerateReinterpretVertexShader(vsCode, shaderLanguageDesc); reinterpretVS_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "reinterpret_vs"); _assert_(reinterpretVS_); + delete[] vsCode; } if (!reinterpretSampler_) { @@ -176,11 +174,12 @@ void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, G Draw::Pipeline *pipeline = reinterpretFromTo_[(int)oldFormat][(int)newFormat]; if (!pipeline) { - fsCode = new char[4000]; + char *fsCode = new char[4000]; const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); GenerateReinterpretFragmentShader(fsCode, oldFormat, newFormat, shaderLanguageDesc); Draw::ShaderModule *reinterpretFS = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "reinterpret_fs"); _assert_(reinterpretFS); + delete[] fsCode; std::vector shaders; shaders.push_back(reinterpretVS_); @@ -239,6 +238,4 @@ void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, G // In case ReinterpretFramebuffer was called from the texture manager. draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After reinterpret"); } - delete[] vsCode; - delete[] fsCode; } From 35a1ca064a2152c3414d218d2e60f2a5a9517f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 19:21:50 +0200 Subject: [PATCH 28/41] Refactor 2D pipeline creation --- GPU/Common/Draw2D.cpp | 162 +++++++++++------------- GPU/Common/FramebufferManagerCommon.cpp | 2 +- GPU/Common/FramebufferManagerCommon.h | 8 +- 3 files changed, 80 insertions(+), 92 deletions(-) diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index a137379b59..ccffd4e611 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -39,16 +39,14 @@ static const SamplerDef samplers[1] = { { "tex" }, }; -void GenerateDraw2DFs(char *buffer, const ShaderLanguageDesc &lang) { - ShaderWriter writer(buffer, lang, ShaderStage::Fragment); +void GenerateDraw2DFs(ShaderWriter &writer) { writer.DeclareSamplers(samplers); writer.BeginFSMain(Slice::empty(), varyings, FSFLAG_NONE); writer.C(" vec4 outColor = ").SampleTexture2D("tex", "v_texcoord.xy").C(";\n"); writer.EndFSMain("outColor", FSFLAG_NONE); } -void GenerateDraw2DDepthFs(char *buffer, const ShaderLanguageDesc &lang) { - ShaderWriter writer(buffer, lang, ShaderStage::Fragment); +void GenerateDraw2DDepthFs(ShaderWriter &writer) { writer.DeclareSamplers(samplers); writer.BeginFSMain(Slice::empty(), varyings, FSFLAG_WRITEDEPTH); writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n"); @@ -56,9 +54,7 @@ void GenerateDraw2DDepthFs(char *buffer, const ShaderLanguageDesc &lang) { writer.EndFSMain("outColor", FSFLAG_WRITEDEPTH); } -void GenerateDraw2DVS(char *buffer, const ShaderLanguageDesc &lang) { - ShaderWriter writer(buffer, lang, ShaderStage::Vertex); - +void GenerateDraw2DVS(ShaderWriter &writer) { writer.BeginVSMain(inputs, Slice::empty(), varyings); writer.C(" v_texcoord = a_texcoord0;\n"); // yes, this should be right. Should be 2.0 in the far corners. @@ -74,7 +70,8 @@ void FramebufferManagerCommon::Ensure2DResources() { if (!draw2DVs_) { char *vsCode = new char[4000]; - GenerateDraw2DVS(vsCode, shaderLanguageDesc); + ShaderWriter writer(vsCode, shaderLanguageDesc, ShaderStage::Vertex); + GenerateDraw2DVS(writer); draw2DVs_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "draw2d_vs"); _assert_(draw2DVs_); delete[] vsCode; @@ -101,6 +98,63 @@ void FramebufferManagerCommon::Ensure2DResources() { } } +Draw::Pipeline *FramebufferManagerCommon::Create2DPipeline(void (*generate)(ShaderWriter &)) { + using namespace Draw; + const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + + char *fsCode = new char[4000]; + ShaderWriter writer(fsCode, shaderLanguageDesc, ShaderStage::Fragment); + generate(writer); + + ShaderModule *fs = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "draw2d_fs"); + delete[] fsCode; + + _assert_(fs); + + // verts have positions in 2D clip coordinates. + static const InputLayoutDesc desc = { + { + { 16, false }, + }, + { + { 0, SEM_POSITION, DataFormat::R32G32_FLOAT, 0 }, + { 0, SEM_TEXCOORD0, DataFormat::R32G32_FLOAT, 8 }, + }, + }; + InputLayout *inputLayout = draw_->CreateInputLayout(desc); + + BlendState *blendOff = draw_->CreateBlendState({ false, 0xF }); + BlendState *blendDiscard = draw_->CreateBlendState({ false, 0x0 }); + + DepthStencilState *noDepthStencil = draw_->CreateDepthStencilState(DepthStencilStateDesc{}); + RasterState *rasterNoCull = draw_->CreateRasterState({}); + + DepthStencilStateDesc dsWriteDesc{}; + dsWriteDesc.depthTestEnabled = true; + dsWriteDesc.depthWriteEnabled = true; + dsWriteDesc.depthCompare = Draw::Comparison::ALWAYS; + DepthStencilState *depthWriteAlways = draw_->CreateDepthStencilState(dsWriteDesc); + + PipelineDesc pipelineDesc{ + Primitive::TRIANGLE_STRIP, + { draw2DVs_, fs }, + inputLayout, noDepthStencil, blendOff, rasterNoCull, nullptr, + }; + + Draw::Pipeline *pipeline = draw_->CreateGraphicsPipeline(pipelineDesc); + + fs->Release(); + + rasterNoCull->Release(); + blendOff->Release(); + blendDiscard->Release(); + noDepthStencil->Release(); + depthWriteAlways->Release(); + inputLayout->Release(); + + return pipeline; +} + void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, RasterChannel channel) { using namespace Draw; @@ -108,92 +162,24 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); - if (!draw2DPipelineColor_) { - char *fsCode = new char[4000]; - GenerateDraw2DFs(fsCode, shaderLanguageDesc); - - ShaderModule *draw2DFs = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "draw2d_fs"); - delete[] fsCode; - - _assert_(draw2DFs); - - ShaderModule *draw2DFsDepth = nullptr; - if (draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { - char *fsDepthCode = new char[4000]; - GenerateDraw2DDepthFs(fsDepthCode, shaderLanguageDesc); - draw2DFsDepth = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsDepthCode, strlen(fsDepthCode), "draw2d_depth_fs"); - delete[] fsDepthCode; - _assert_(draw2DFsDepth); - } - - // verts have positions in 2D clip coordinates. - static const InputLayoutDesc desc = { - { - { 16, false }, - }, - { - { 0, SEM_POSITION, DataFormat::R32G32_FLOAT, 0 }, - { 0, SEM_TEXCOORD0, DataFormat::R32G32_FLOAT, 8 }, - }, - }; - InputLayout *inputLayout = draw_->CreateInputLayout(desc); - - BlendState *blendOff = draw_->CreateBlendState({ false, 0xF }); - BlendState *blendDiscard = draw_->CreateBlendState({ false, 0x0 }); - - DepthStencilState *noDepthStencil = draw_->CreateDepthStencilState(DepthStencilStateDesc{}); - RasterState *rasterNoCull = draw_->CreateRasterState({}); - - DepthStencilStateDesc dsWriteDesc{}; - dsWriteDesc.depthTestEnabled = true; - dsWriteDesc.depthWriteEnabled = true; - dsWriteDesc.depthCompare = Draw::Comparison::ALWAYS; - DepthStencilState *depthWriteAlways = draw_->CreateDepthStencilState(dsWriteDesc); - - PipelineDesc draw2DColorPipelineDesc{ - Primitive::TRIANGLE_STRIP, - { draw2DVs_, draw2DFs }, - inputLayout, noDepthStencil, blendOff, rasterNoCull, nullptr, - }; - - draw2DPipelineColor_ = draw_->CreateGraphicsPipeline(draw2DColorPipelineDesc); - - PipelineDesc draw2DDepthPipelineDesc{ - Primitive::TRIANGLE_STRIP, - { draw2DVs_, draw2DFsDepth }, - inputLayout, depthWriteAlways, blendDiscard, rasterNoCull, nullptr, - }; - - if (draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { - draw2DPipelineDepth_ = draw_->CreateGraphicsPipeline(draw2DDepthPipelineDesc); - _assert_(draw2DPipelineDepth_); - } else { - draw2DPipelineDepth_ = nullptr; - } - - draw2DFs->Release(); - if (draw2DFsDepth) { - draw2DFsDepth->Release(); - } - - rasterNoCull->Release(); - blendOff->Release(); - blendDiscard->Release(); - noDepthStencil->Release(); - depthWriteAlways->Release(); - inputLayout->Release(); - } - switch (channel) { + case RASTER_COLOR: + if (!draw2DPipelineColor_) { + draw2DPipelineColor_ = Create2DPipeline(&GenerateDraw2DFs); + } + draw_->BindPipeline(draw2DPipelineColor_); + break; + case RASTER_DEPTH: - if (!draw2DPipelineDepth_) { + if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { + // Can't do it return; } + if (!draw2DPipelineDepth_) { + draw2DPipelineDepth_ = Create2DPipeline(&GenerateDraw2DFs); + } draw_->BindPipeline(draw2DPipelineDepth_); break; - case RASTER_COLOR: - draw_->BindPipeline(draw2DPipelineColor_); - break; } if (tex) { diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 0a5cdd2743..afec95d06d 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -47,7 +47,7 @@ #include "GPU/GPUState.h" FramebufferManagerCommon::FramebufferManagerCommon(Draw::DrawContext *draw) - : draw_(draw), displayFormat_(GE_FORMAT_565) { + : draw_(draw) { presentation_ = new PresentationCommon(draw); } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index f60d6cb679..54884f35bc 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -55,6 +55,7 @@ namespace Draw { } class VulkanFBO; +class ShaderWriter; // We have to track VFBs and depth buffers together, since bits are shared between the color alpha channel // and the stencil buffer on the PSP. @@ -362,6 +363,7 @@ protected: void DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, RasterChannel channel); void Ensure2DResources(); + Draw::Pipeline *Create2DPipeline(void (*generate)(ShaderWriter &)); bool UpdateSize(); @@ -422,7 +424,7 @@ protected: u32 displayFramebufPtr_ = 0; u32 displayStride_ = 0; - GEBufferFormat displayFormat_; + GEBufferFormat displayFormat_ = GE_FORMAT_565; u32 prevDisplayFramebufPtr_ = 0; VirtualFramebuffer *displayFramebuf_ = nullptr; @@ -450,8 +452,8 @@ protected: float renderWidth_ = 0.0f; float renderHeight_ = 0.0f; float renderScaleFactor_ = 1.0f; - int pixelWidth_; - int pixelHeight_; + int pixelWidth_ = 0; + int pixelHeight_ = 0; int bloomHack_ = 0; Draw::DataFormat preferredPixelsFormat_ = Draw::DataFormat::R8G8B8A8_UNORM; From 5b6a14edeb6f9ad14a6d1a796e78c60e5280ba60 Mon Sep 17 00:00:00 2001 From: fp64 <106717720+fp64@users.noreply.github.com> Date: Tue, 16 Aug 2022 18:22:01 -0400 Subject: [PATCH 29/41] Add a newline to "Leaving main" message. Also implement SYSPROP_DISPLAY_XRES/SYSPROP_DISPLAY_YRES for SDL. Also fix couple of warnings. --- Common/Render/TextureAtlas.h | 2 +- Core/HLE/sceAudiocodec.cpp | 5 +++++ SDL/SDLMain.cpp | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Common/Render/TextureAtlas.h b/Common/Render/TextureAtlas.h index 58a2b86c96..aed38e273f 100644 --- a/Common/Render/TextureAtlas.h +++ b/Common/Render/TextureAtlas.h @@ -3,7 +3,7 @@ #include #include -#define ATLAS_MAGIC ('A' + ('T' << 8) + ('L' << 16) | ('A' << 24)) +#define ATLAS_MAGIC ('A' | ('T' << 8) | ('L' << 16) | ('A' << 24)) // Metadata file structure v0: // diff --git a/Core/HLE/sceAudiocodec.cpp b/Core/HLE/sceAudiocodec.cpp index 6d40c6802e..3c9643d897 100644 --- a/Core/HLE/sceAudiocodec.cpp +++ b/Core/HLE/sceAudiocodec.cpp @@ -187,6 +187,9 @@ void __sceAudiocodecDoState(PointerWrap &p){ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunknown-warning-option" #pragma clang diagnostic ignored "-Wsizeof-pointer-div" +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsizeof-pointer-div" #endif DoArray(p, codec_, s >= 2 ? count : (int)ARRAY_SIZE(codec_)); DoArray(p, ctxPtr_, s >= 2 ? count : (int)ARRAY_SIZE(ctxPtr_)); @@ -197,6 +200,8 @@ void __sceAudiocodecDoState(PointerWrap &p){ } #ifdef __clang__ #pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop #endif delete[] codec_; delete[] ctxPtr_; diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index ec612d1182..da966cabae 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -388,6 +388,10 @@ int System_GetPropertyInt(SystemProperty prop) { return KEYBOARD_LAYOUT_QWERTZ; return KEYBOARD_LAYOUT_QWERTY; } + case SYSPROP_DISPLAY_XRES: + return g_DesktopWidth; + case SYSPROP_DISPLAY_YRES: + return g_DesktopHeight; default: return -1; } @@ -1240,7 +1244,7 @@ int main(int argc, char *argv[]) { #endif glslang::FinalizeProcess(); - printf("Leaving main"); + printf("Leaving main\n"); #ifdef HAVE_LIBNX socketExit(); #endif From cdb4124bc1561005d2e2d38f030e9b23f5e42ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 21:38:09 +0200 Subject: [PATCH 30/41] More removing redundant stuff --- GPU/Directx9/FramebufferManagerDX9.cpp | 3 --- GPU/Directx9/FramebufferManagerDX9.h | 4 +--- GPU/Directx9/GPU_DX9.cpp | 2 -- GPU/GLES/DepthBufferGLES.cpp | 28 +++++++++++++------------ GPU/GLES/FramebufferManagerGLES.cpp | 24 ++++++--------------- GPU/GLES/FramebufferManagerGLES.h | 15 ++----------- GPU/GLES/GPU_GLES.cpp | 5 +---- GPU/Vulkan/FramebufferManagerVulkan.cpp | 15 ------------- GPU/Vulkan/FramebufferManagerVulkan.h | 6 ------ GPU/Vulkan/GPU_Vulkan.cpp | 3 +-- 10 files changed, 26 insertions(+), 79 deletions(-) diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp index dab35117dc..084d30a0fe 100644 --- a/GPU/Directx9/FramebufferManagerDX9.cpp +++ b/GPU/Directx9/FramebufferManagerDX9.cpp @@ -223,9 +223,6 @@ namespace DX9 { } } - void FramebufferManagerDX9::EndFrame() { - } - void FramebufferManagerDX9::DecimateFBOs() { FramebufferManagerCommon::DecimateFBOs(); for (auto it = offscreenSurfaces_.begin(); it != offscreenSurfaces_.end(); ) { diff --git a/GPU/Directx9/FramebufferManagerDX9.h b/GPU/Directx9/FramebufferManagerDX9.h index 141f719310..6057519f0a 100644 --- a/GPU/Directx9/FramebufferManagerDX9.h +++ b/GPU/Directx9/FramebufferManagerDX9.h @@ -41,8 +41,6 @@ public: void DestroyAllFBOs() override; - void EndFrame(); - bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) override; bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) override; bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) override; @@ -70,4 +68,4 @@ private: std::unordered_map offscreenSurfaces_; }; -} +} // namespace diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 65da1a0773..66c0d9bc1f 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -299,9 +299,7 @@ void GPU_DX9::CopyDisplayToOutput(bool reallyDirty) { drawEngine_.Flush(); framebufferManagerDX9_->CopyDisplayToOutput(reallyDirty); - framebufferManagerDX9_->EndFrame(); - // shaderManager_->EndFrame(); shaderManagerDX9_->DirtyLastShader(); gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); diff --git a/GPU/GLES/DepthBufferGLES.cpp b/GPU/GLES/DepthBufferGLES.cpp index ef761de10f..6334fbd5ee 100644 --- a/GPU/GLES/DepthBufferGLES.cpp +++ b/GPU/GLES/DepthBufferGLES.cpp @@ -97,6 +97,8 @@ void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int const bool useColorPath = gl_extensions.IsGLES; bool format16Bit = false; + GLRenderManager *render = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + if (useColorPath) { if (!depthDownloadProgram_) { std::string errorString; @@ -104,8 +106,8 @@ void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int vs_code = ApplyGLSLPrelude(depth_vs, GL_VERTEX_SHADER); fs_code = ApplyGLSLPrelude(depth_dl_fs, GL_FRAGMENT_SHADER); std::vector shaders; - shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vs_code, "depth_dl")); - shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code, "depth_dl")); + shaders.push_back(render->CreateShader(GL_VERTEX_SHADER, vs_code, "depth_dl")); + shaders.push_back(render->CreateShader(GL_FRAGMENT_SHADER, fs_code, "depth_dl")); std::vector semantics; semantics.push_back({ 0, "a_position" }); semantics.push_back({ 1, "a_texcoord0" }); @@ -116,9 +118,9 @@ void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int queries.push_back({ &u_depthDownloadTo8, "u_depthTo8" }); std::vector inits; inits.push_back({ &u_depthDownloadTex, 0, TEX_SLOT_PSP_TEXTURE }); - depthDownloadProgram_ = render_->CreateProgram(shaders, semantics, queries, inits, false, false); + depthDownloadProgram_ = render->CreateProgram(shaders, semantics, queries, inits, false, false); for (auto iter : shaders) { - render_->DeleteShader(iter); + render->DeleteShader(iter); } if (!depthDownloadProgram_) { ERROR_LOG_REPORT(G3D, "Failed to compile depthDownloadProgram! This shouldn't happen.\n%s", errorString.c_str()); @@ -128,26 +130,26 @@ void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int shaderManager_->DirtyLastShader(); auto *blitFBO = GetTempFBO(TempFBO::COPY, vfb->renderWidth, vfb->renderHeight); draw_->BindFramebufferAsRenderTarget(blitFBO, { Draw::RPAction::CLEAR, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }, "PackDepthbuffer"); - render_->SetViewport({ 0, 0, (float)vfb->renderWidth, (float)vfb->renderHeight, 0.0f, 1.0f }); + render->SetViewport({ 0, 0, (float)vfb->renderWidth, (float)vfb->renderHeight, 0.0f, 1.0f }); // We must bind the program after starting the render pass, and set the color mask after clearing. - render_->SetScissor({ 0, 0, vfb->renderWidth, vfb->renderHeight }); - render_->SetDepth(false, false, GL_ALWAYS); - render_->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE, GL_FALSE); - render_->BindProgram(depthDownloadProgram_); + render->SetScissor({ 0, 0, vfb->renderWidth, vfb->renderHeight }); + render->SetDepth(false, false, GL_ALWAYS); + render->SetRaster(false, GL_CCW, GL_FRONT, GL_FALSE, GL_FALSE); + render->BindProgram(depthDownloadProgram_); if (!gstate_c.Supports(GPU_SUPPORTS_ACCURATE_DEPTH)) { float factors[] = { 0.0f, 1.0f }; - render_->SetUniformF(&u_depthDownloadFactor, 2, factors); + render->SetUniformF(&u_depthDownloadFactor, 2, factors); } else { const float factor = DepthSliceFactor(); float factors[] = { -0.5f * (factor - 1.0f) * (1.0f / factor), factor }; - render_->SetUniformF(&u_depthDownloadFactor, 2, factors); + render->SetUniformF(&u_depthDownloadFactor, 2, factors); } float shifts[] = { 16777215.0f, 16777215.0f / 256.0f, 16777215.0f / 65536.0f, 16777215.0f / 16777216.0f }; - render_->SetUniformF(&u_depthDownloadShift, 4, shifts); + render->SetUniformF(&u_depthDownloadShift, 4, shifts); float to8[] = { 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f }; - render_->SetUniformF(&u_depthDownloadTo8, 4, to8); + render->SetUniformF(&u_depthDownloadTo8, 4, to8); draw_->BindFramebufferAsTexture(vfb->fbo, TEX_SLOT_PSP_TEXTURE, Draw::FB_DEPTH_BIT, 0); float u1 = 1.0f; diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 48503bdc15..9d1dc8d3dd 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -38,9 +38,8 @@ #include "GPU/GLES/TextureCacheGLES.h" #include "GPU/GLES/ShaderManagerGLES.h" -FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render) : - FramebufferManagerCommon(draw), - render_(render) +FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) : + FramebufferManagerCommon(draw) { needBackBufferYSwap_ = true; presentation_->SetLanguage(draw_->GetShaderLanguageDesc().shaderLanguage); @@ -50,10 +49,6 @@ FramebufferManagerGLES::~FramebufferManagerGLES() { delete[] convBuf_; } -void FramebufferManagerGLES::Init() { - FramebufferManagerCommon::Init(); -} - void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) { _assert_msg_(nvfb->fbo, "Expecting a valid nvfb in UpdateDownloadTempBuffer"); @@ -66,26 +61,19 @@ void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) } } -void FramebufferManagerGLES::EndFrame() { -} - void FramebufferManagerGLES::DeviceLost() { FramebufferManagerCommon::DeviceLost(); if (depthDownloadProgram_) { - render_->DeleteProgram(depthDownloadProgram_); + GLRenderManager *render = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + render->DeleteProgram(depthDownloadProgram_); depthDownloadProgram_ = nullptr; } } -void FramebufferManagerGLES::DeviceRestore(Draw::DrawContext *draw) { - FramebufferManagerCommon::DeviceRestore(draw); - render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); -} - void FramebufferManagerGLES::Resized() { FramebufferManagerCommon::Resized(); - - render_->Resize(PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); + GLRenderManager *render = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); + render->Resize(PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); } bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) { diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 5e5793ad16..eb5354b60e 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -18,30 +18,21 @@ #pragma once #include "Common/GPU/thin3d.h" -// Keeps track of allocated FBOs. -// Also provides facilities for drawing and later converting raw -// pixel data. - #include "GPU/GPUCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" -#include "Common/GPU/OpenGL/GLRenderManager.h" -struct GLSLProgram; class TextureCacheGLES; class DrawEngineGLES; class ShaderManagerGLES; +class GLRProgram; class FramebufferManagerGLES : public FramebufferManagerCommon { public: - FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render); + FramebufferManagerGLES(Draw::DrawContext *draw); ~FramebufferManagerGLES(); - virtual void Init() override; - void EndFrame(); void Resized() override; - void DeviceLost() override; - void DeviceRestore(Draw::DrawContext *draw) override; bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; @@ -51,8 +42,6 @@ protected: private: void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); - GLRenderManager *render_; - u8 *convBuf_ = nullptr; u32 convBufSize_ = 0; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index a18a9cb556..f774e4bebd 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -57,10 +57,8 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) UpdateVsyncInterval(true); CheckGPUFeatures(); - GLRenderManager *render = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); - shaderManagerGL_ = new ShaderManagerGLES(draw); - framebufferManagerGL_ = new FramebufferManagerGLES(draw, render); + framebufferManagerGL_ = new FramebufferManagerGLES(draw); framebufferManager_ = framebufferManagerGL_; textureCacheGL_ = new TextureCacheGLES(draw); textureCache_ = textureCacheGL_; @@ -375,7 +373,6 @@ void GPU_GLES::CopyDisplayToOutput(bool reallyDirty) { shaderManagerGL_->DirtyLastShader(); framebufferManagerGL_->CopyDisplayToOutput(reallyDirty); - framebufferManagerGL_->EndFrame(); } void GPU_GLES::FinishDeferred() { diff --git a/GPU/Vulkan/FramebufferManagerVulkan.cpp b/GPU/Vulkan/FramebufferManagerVulkan.cpp index 1f3f258932..7748f24371 100644 --- a/GPU/Vulkan/FramebufferManagerVulkan.cpp +++ b/GPU/Vulkan/FramebufferManagerVulkan.cpp @@ -79,18 +79,3 @@ void FramebufferManagerVulkan::NotifyClear(bool clearColor, bool clearAlpha, boo SetDepthUpdated(); } } - -void FramebufferManagerVulkan::BeginFrameVulkan() { - BeginFrame(); -} - -void FramebufferManagerVulkan::EndFrame() { -} - -void FramebufferManagerVulkan::DeviceLost() { - FramebufferManagerCommon::DeviceLost(); -} - -void FramebufferManagerVulkan::DeviceRestore(Draw::DrawContext *draw) { - FramebufferManagerCommon::DeviceRestore(draw); -} diff --git a/GPU/Vulkan/FramebufferManagerVulkan.h b/GPU/Vulkan/FramebufferManagerVulkan.h index a303338320..0f5d7c4f53 100644 --- a/GPU/Vulkan/FramebufferManagerVulkan.h +++ b/GPU/Vulkan/FramebufferManagerVulkan.h @@ -36,12 +36,6 @@ public: FramebufferManagerVulkan(Draw::DrawContext *draw); ~FramebufferManagerVulkan(); - void BeginFrameVulkan(); // there's a BeginFrame in the base class, which this calls - void EndFrame(); - - void DeviceLost() override; - void DeviceRestore(Draw::DrawContext *draw) override; - // If within a render pass, this will just issue a regular clear. If beginning a new render pass, // do that. void NotifyClear(bool clearColor, bool clearAlpha, bool clearDepth, uint32_t color, float depth); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index a421e209c3..7d2dc8b5c0 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -317,7 +317,7 @@ void GPU_Vulkan::BeginHostFrame() { frame.push_->Reset(); frame.push_->Begin(vulkan); - framebufferManagerVulkan_->BeginFrameVulkan(); + framebufferManagerVulkan_->BeginFrame(); textureCacheVulkan_->SetPushBuffer(frameData_[curFrame].push_); shaderManagerVulkan_->DirtyShader(); @@ -339,7 +339,6 @@ void GPU_Vulkan::EndHostFrame() { frame.push_->End(); drawEngine_.EndFrame(); - framebufferManagerVulkan_->EndFrame(); textureCacheVulkan_->EndFrame(); draw_->InvalidateCachedState(); From 1f276fcc203b91eaa079712cb80ea39e4d0dc3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 21:42:03 +0200 Subject: [PATCH 31/41] Vulkan: Restore a minor old forgotten optimization --- GPU/Vulkan/DrawEngineVulkan.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index e50e6477ba..7be943ed63 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -531,10 +531,6 @@ void DrawEngineVulkan::DoFlush() { gpuStats.numFlushes++; - // TODO: Needs to be behind a check for changed render pass, at an appropriate time in this function. - // Similar issues as with the lastRenderStepId_ check. Will need a bit of a rethink. - lastPipeline_ = nullptr; - // If have a new render pass, dirty our dynamic state so it gets re-set. // We have to do this again after the last possible place in DoFlush that can cause a renderpass switch // like a shader blend blit or similar. But before we actually set the state! @@ -544,6 +540,7 @@ void DrawEngineVulkan::DoFlush() { gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_BLEND_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); textureCache_->ForgetLastTexture(); lastRenderStepId_ = curRenderStepId; + lastPipeline_ = nullptr; } bool tess = gstate_c.submitType == SubmitType::HW_BEZIER || gstate_c.submitType == SubmitType::HW_SPLINE; From d0cdb360fd44d41924627bc179689edc82fe7635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 21:48:54 +0200 Subject: [PATCH 32/41] Remove the DX9 namespace, for consistency with the other backends --- Common/GPU/D3D9/D3D9StateCache.cpp | 8 +--- Common/GPU/D3D9/D3D9StateCache.h | 58 ++++++++++++-------------- Common/GPU/D3D9/thin3d_d3d9.cpp | 12 +----- GPU/Directx9/DrawEngineDX9.cpp | 12 ++---- GPU/Directx9/DrawEngineDX9.h | 4 -- GPU/Directx9/FramebufferManagerDX9.cpp | 4 +- GPU/Directx9/FramebufferManagerDX9.h | 4 -- GPU/Directx9/GPU_DX9.cpp | 4 -- GPU/Directx9/GPU_DX9.h | 6 --- GPU/Directx9/ShaderManagerDX9.cpp | 4 -- GPU/Directx9/ShaderManagerDX9.h | 4 -- GPU/Directx9/StateMappingDX9.cpp | 4 -- GPU/Directx9/TextureCacheDX9.cpp | 4 -- GPU/Directx9/TextureCacheDX9.h | 4 -- GPU/GPU.cpp | 2 +- Windows/GPU/D3D9Context.cpp | 8 ++-- 16 files changed, 40 insertions(+), 102 deletions(-) diff --git a/Common/GPU/D3D9/D3D9StateCache.cpp b/Common/GPU/D3D9/D3D9StateCache.cpp index 3388dd2486..b069d60296 100644 --- a/Common/GPU/D3D9/D3D9StateCache.cpp +++ b/Common/GPU/D3D9/D3D9StateCache.cpp @@ -2,12 +2,10 @@ #include "Common/GPU/D3D9/D3D9StateCache.h" -namespace DX9 { - DirectXState dxstate; -LPDIRECT3DDEVICE9 pD3Ddevice = nullptr; -LPDIRECT3DDEVICE9EX pD3DdeviceEx = nullptr; +LPDIRECT3DDEVICE9 pD3Ddevice9 = nullptr; +LPDIRECT3DDEVICE9EX pD3DdeviceEx9 = nullptr; int DirectXState::state_count = 0; @@ -62,6 +60,4 @@ void DirectXState::Restore() { texAddressW.restore(); count++; } -} // namespace DX9 - #endif // _MSC_VER diff --git a/Common/GPU/D3D9/D3D9StateCache.h b/Common/GPU/D3D9/D3D9StateCache.h index 09f3286222..ae2dbd0ff4 100644 --- a/Common/GPU/D3D9/D3D9StateCache.h +++ b/Common/GPU/D3D9/D3D9StateCache.h @@ -4,11 +4,9 @@ #include "Common/GPU/D3D9/D3D9ShaderCompiler.h" -namespace DX9 { - // TODO: Get rid of these somehow. -extern LPDIRECT3DDEVICE9 pD3Ddevice; -extern LPDIRECT3DDEVICE9EX pD3DdeviceEx; +extern LPDIRECT3DDEVICE9 pD3Ddevice9; +extern LPDIRECT3DDEVICE9EX pD3DdeviceEx9; class DirectXState { private: @@ -44,7 +42,7 @@ private: return _value; } void restore() { - pD3Ddevice->SetRenderState(cap, _value); + pD3Ddevice9->SetRenderState(cap, _value); } }; @@ -69,7 +67,7 @@ private: p1 = old; } void restore() { - pD3Ddevice->SetRenderState(_state1, p1); + pD3Ddevice9->SetRenderState(_state1, p1); } }; @@ -94,7 +92,7 @@ private: p1 = old; } void restore() { - pD3Ddevice->SetSamplerState(0, _state1, p1); + pD3Ddevice9->SetSamplerState(0, _state1, p1); } }; @@ -123,7 +121,7 @@ private: p1 = old; } void restore() { - pD3Ddevice->SetSamplerState(0, _state1, p1d); + pD3Ddevice9->SetSamplerState(0, _state1, p1d); } }; @@ -141,11 +139,11 @@ private: inline void set(DWORD newp1, DWORD newp2) { if (p1 != newp1) { p1 = newp1; - pD3Ddevice->SetRenderState(_state1, p1); + pD3Ddevice9->SetRenderState(_state1, p1); } if (p2 != newp2) { p2 = newp2; - pD3Ddevice->SetRenderState(_state2, p2); + pD3Ddevice9->SetRenderState(_state2, p2); } } void force(DWORD newp1, DWORD newp2) { @@ -156,8 +154,8 @@ private: p2 = old2; } void restore() { - pD3Ddevice->SetRenderState(_state1, p1); - pD3Ddevice->SetRenderState(_state2, p2); + pD3Ddevice9->SetRenderState(_state1, p1); + pD3Ddevice9->SetRenderState(_state2, p2); } }; @@ -177,15 +175,15 @@ private: inline void set(DWORD newp1, DWORD newp2, DWORD newp3) { if (p1 != newp1) { p1 = newp1; - pD3Ddevice->SetRenderState(_state1, p1); + pD3Ddevice9->SetRenderState(_state1, p1); } if (p2 != newp2) { p2 = newp2; - pD3Ddevice->SetRenderState(_state2, p2); + pD3Ddevice9->SetRenderState(_state2, p2); } if (p3 != newp3) { p3 = newp3; - pD3Ddevice->SetRenderState(_state3, p3); + pD3Ddevice9->SetRenderState(_state3, p3); } } void force(DWORD newp1, DWORD newp2, DWORD newp3) { @@ -198,9 +196,9 @@ private: p3 = old3; } void restore() { - pD3Ddevice->SetRenderState(_state1, p1); - pD3Ddevice->SetRenderState(_state2, p2); - pD3Ddevice->SetRenderState(_state3, p3); + pD3Ddevice9->SetRenderState(_state1, p1); + pD3Ddevice9->SetRenderState(_state2, p2); + pD3Ddevice9->SetRenderState(_state3, p3); } }; @@ -222,19 +220,19 @@ private: inline void set(DWORD newp1, DWORD newp2, DWORD newp3, DWORD newp4) { if (p1 != newp1) { p1 = newp1; - pD3Ddevice->SetRenderState(_state1, p1); + pD3Ddevice9->SetRenderState(_state1, p1); } if (p2 != newp2) { p2 = newp2; - pD3Ddevice->SetRenderState(_state2, p2); + pD3Ddevice9->SetRenderState(_state2, p2); } if (p3 != newp3) { p3 = newp3; - pD3Ddevice->SetRenderState(_state3, p3); + pD3Ddevice9->SetRenderState(_state3, p3); } if (p4 != newp4) { p4 = newp4; - pD3Ddevice->SetRenderState(_state4, p4); + pD3Ddevice9->SetRenderState(_state4, p4); } } void force(DWORD newp1, DWORD newp2, DWORD newp3, DWORD newp4) { @@ -249,10 +247,10 @@ private: p4 = old4; } void restore() { - pD3Ddevice->SetRenderState(_state1, p1); - pD3Ddevice->SetRenderState(_state2, p2); - pD3Ddevice->SetRenderState(_state3, p3); - pD3Ddevice->SetRenderState(_state3, p4); + pD3Ddevice9->SetRenderState(_state1, p1); + pD3Ddevice9->SetRenderState(_state2, p2); + pD3Ddevice9->SetRenderState(_state3, p3); + pD3Ddevice9->SetRenderState(_state3, p4); } }; @@ -284,7 +282,7 @@ private: c = old; } inline void restore() { - pD3Ddevice->SetRenderState(D3DRS_BLENDFACTOR, c); + pD3Ddevice9->SetRenderState(D3DRS_BLENDFACTOR, c); } }; @@ -318,7 +316,7 @@ private: } inline void restore() { - pD3Ddevice->SetViewport(&viewport); + pD3Ddevice9->SetViewport(&viewport); } }; @@ -340,7 +338,7 @@ private: } inline void restore() { - pD3Ddevice->SetScissorRect(&rect); + pD3Ddevice9->SetScissorRect(&rect); } }; @@ -412,5 +410,3 @@ struct GLExtensions { extern GLExtensions gl_extensions; void CheckGLExtensions(); - -}; diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index 845fa45d5f..938789479c 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -152,7 +152,6 @@ public: D3DCMPFUNC stencilCompareOp; void Apply(LPDIRECT3DDEVICE9 device, uint8_t stencilRef, uint8_t stencilWriteMask, uint8_t stencilCompareMask) { - using namespace DX9; dxstate.depthTest.set(depthTestEnabled); if (depthTestEnabled) { dxstate.depthWrite.set(depthWriteEnabled); @@ -174,7 +173,6 @@ public: DWORD cullMode; // D3DCULL_* void Apply(LPDIRECT3DDEVICE9 device) { - using namespace DX9; dxstate.cullMode.set(cullMode); dxstate.scissorTest.enable(); } @@ -188,7 +186,6 @@ public: uint32_t colorMask; void Apply(LPDIRECT3DDEVICE9 device) { - using namespace DX9; dxstate.blend.set(enabled); dxstate.blendFunc.set(srcCol, dstCol, srcAlpha, dstAlpha); dxstate.blendEquation.set(eqCol, eqAlpha); @@ -202,7 +199,6 @@ public: D3DTEXTUREFILTERTYPE magFilt, minFilt, mipFilt; void Apply(LPDIRECT3DDEVICE9 device, int index) { - using namespace DX9; dxstate.texAddressU.set(wrapS); dxstate.texAddressV.set(wrapT); dxstate.texMagFilter.set(magFilt); @@ -689,7 +685,7 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID shaderLanguageDesc_.Init(HLSL_D3D9); - DX9::dxstate.Restore(); + dxstate.Restore(); } D3D9Context::~D3D9Context() { @@ -1037,15 +1033,11 @@ void D3D9Context::Clear(int mask, uint32_t colorval, float depthVal, int stencil } void D3D9Context::SetScissorRect(int left, int top, int width, int height) { - using namespace DX9; - dxstate.scissorRect.set(left, top, left + width, top + height); dxstate.scissorTest.set(true); } void D3D9Context::SetViewports(int count, Viewport *viewports) { - using namespace DX9; - int x = (int)viewports[0].TopLeftX; int y = (int)viewports[0].TopLeftY; int w = (int)viewports[0].Width; @@ -1058,7 +1050,6 @@ void D3D9Context::SetBlendFactor(float color[4]) { uint32_t g = (uint32_t)(color[1] * 255.0f); uint32_t b = (uint32_t)(color[2] * 255.0f); uint32_t a = (uint32_t)(color[3] * 255.0f); - using namespace DX9; dxstate.blendColor.set(color); } @@ -1179,7 +1170,6 @@ D3D9Framebuffer::~D3D9Framebuffer() { } void D3D9Context::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) { - using namespace DX9; if (fbo) { D3D9Framebuffer *fb = (D3D9Framebuffer *)fbo; device_->SetRenderTarget(0, fb->surf); diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index d69c03da21..ffad2bd469 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -42,8 +42,6 @@ #include "GPU/Directx9/ShaderManagerDX9.h" #include "GPU/Directx9/GPU_DX9.h" -namespace DX9 { - static const D3DPRIMITIVETYPE d3d_prim[8] = { // Points, which are expanded to triangles. D3DPT_TRIANGLELIST, @@ -248,7 +246,7 @@ void DrawEngineDX9::MarkUnreliable(VertexArrayInfoDX9 *vai) { } void DrawEngineDX9::ClearTrackedVertexArrays() { - vai_.Iterate([&](uint32_t hash, DX9::VertexArrayInfoDX9 *vai) { + vai_.Iterate([&](uint32_t hash, VertexArrayInfoDX9 *vai) { delete vai; }); vai_.Clear(); @@ -264,7 +262,7 @@ void DrawEngineDX9::DecimateTrackedVertexArrays() { const int threshold = gpuStats.numFlips - VAI_KILL_AGE; const int unreliableThreshold = gpuStats.numFlips - VAI_UNRELIABLE_KILL_AGE; int unreliableLeft = VAI_UNRELIABLE_KILL_MAX; - vai_.Iterate([&](uint32_t hash, DX9::VertexArrayInfoDX9 *vai) { + vai_.Iterate([&](uint32_t hash, VertexArrayInfoDX9 *vai) { bool kill; if (vai->status == VertexArrayInfoDX9::VAI_UNRELIABLE) { // We limit killing unreliable so we don't rehash too often. @@ -524,7 +522,7 @@ rotateVBO: ApplyDrawState(prim); ApplyDrawStateLate(); - DX9::VSShader *vshader = shaderManager_->ApplyShader(true, useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat); + VSShader *vshader = shaderManager_->ApplyShader(true, useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat); IDirect3DVertexDeclaration9 *pHardwareVertexDecl = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType()); if (pHardwareVertexDecl) { @@ -616,7 +614,7 @@ rotateVBO: ApplyDrawStateLate(); - DX9::VSShader *vshader = shaderManager_->ApplyShader(false, false, lastVType_, decOptions_.expandAllWeightsToFloat); + VSShader *vshader = shaderManager_->ApplyShader(false, false, lastVType_, decOptions_.expandAllWeightsToFloat); if (result.action == SW_DRAW_PRIMITIVES) { if (result.setStencil) { @@ -686,5 +684,3 @@ rotateVBO: void TessellationDataTransferDX9::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) { // TODO } - -} // namespace diff --git a/GPU/Directx9/DrawEngineDX9.h b/GPU/Directx9/DrawEngineDX9.h index f0963beb91..616620a412 100644 --- a/GPU/Directx9/DrawEngineDX9.h +++ b/GPU/Directx9/DrawEngineDX9.h @@ -30,8 +30,6 @@ struct DecVtxFormat; struct UVScale; -namespace DX9 { - class VSShader; class ShaderManagerDX9; class TextureCacheDX9; @@ -175,5 +173,3 @@ private: int lastRenderStepId_ = -1; }; - -} // namespace diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp index 084d30a0fe..610940584c 100644 --- a/GPU/Directx9/FramebufferManagerDX9.cpp +++ b/GPU/Directx9/FramebufferManagerDX9.cpp @@ -45,7 +45,7 @@ #include #endif -namespace DX9 { +// TODO: De-indent, the day we move all this readback stuff to GPU/Common FramebufferManagerDX9::FramebufferManagerDX9(Draw::DrawContext *draw) : FramebufferManagerCommon(draw) { @@ -396,5 +396,3 @@ namespace DX9 { return success; } - -} // namespace DX9 diff --git a/GPU/Directx9/FramebufferManagerDX9.h b/GPU/Directx9/FramebufferManagerDX9.h index 6057519f0a..4835ded4d1 100644 --- a/GPU/Directx9/FramebufferManagerDX9.h +++ b/GPU/Directx9/FramebufferManagerDX9.h @@ -28,8 +28,6 @@ #include "GPU/GPUCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" -namespace DX9 { - class TextureCacheDX9; class DrawEngineDX9; class ShaderManagerDX9; @@ -67,5 +65,3 @@ private: std::unordered_map offscreenSurfaces_; }; - -} // namespace diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 66c0d9bc1f..c3f4476fcb 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -49,8 +49,6 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceGe.h" -namespace DX9 { - GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw), drawEngine_(draw) { @@ -393,5 +391,3 @@ std::string GPU_DX9::DebugGetShaderString(std::string id, DebugShaderType type, return shaderManagerDX9_->DebugGetShaderString(id, type, stringType); } } - -} // namespace DX9 diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 7c6100925a..349d2bd0a8 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -26,8 +26,6 @@ #include "GPU/Common/DepalettizeCommon.h" #include "GPU/Common/VertexDecoderCommon.h" -namespace DX9 { - class ShaderManagerDX9; class LinkedShaderDX9; class TextureCacheDX9; @@ -80,7 +78,3 @@ private: DrawEngineDX9 drawEngine_; ShaderManagerDX9 *shaderManagerDX9_; }; - -} // namespace DX9 - -typedef DX9::GPU_DX9 DIRECTX9_GPU; diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 99be9bd2ee..7cae12bb53 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -49,8 +49,6 @@ using namespace Lin; -namespace DX9 { - PSShader::PSShader(LPDIRECT3DDEVICE9 device, FShaderID id, const char *code) : id_(id) { source_ = code; #ifdef SHADERLOG @@ -702,5 +700,3 @@ std::string ShaderManagerDX9::DebugGetShaderString(std::string id, DebugShaderTy return "N/A"; } } - -} // namespace diff --git a/GPU/Directx9/ShaderManagerDX9.h b/GPU/Directx9/ShaderManagerDX9.h index 3c1e42d1fd..04cdf79544 100644 --- a/GPU/Directx9/ShaderManagerDX9.h +++ b/GPU/Directx9/ShaderManagerDX9.h @@ -27,8 +27,6 @@ #include "GPU/Common/ShaderId.h" #include "Common/Math/lin/matrix4x4.h" -namespace DX9 { - class PSShader; class VSShader; @@ -126,5 +124,3 @@ private: typedef std::map VSCache; VSCache vsCache_; }; - -}; diff --git a/GPU/Directx9/StateMappingDX9.cpp b/GPU/Directx9/StateMappingDX9.cpp index 018d3253ed..0de9c1774d 100644 --- a/GPU/Directx9/StateMappingDX9.cpp +++ b/GPU/Directx9/StateMappingDX9.cpp @@ -32,8 +32,6 @@ #include "GPU/Directx9/TextureCacheDX9.h" #include "GPU/Directx9/FramebufferManagerDX9.h" -namespace DX9 { - static const D3DBLEND dxBlendFactorLookup[(size_t)BlendFactor::COUNT] = { D3DBLEND_ZERO, D3DBLEND_ONE, @@ -298,5 +296,3 @@ void DrawEngineDX9::ApplyDrawStateLate() { // At this point, we know if the vertices are full alpha or not. // TODO: Set the nearest/linear here (since we correctly know if alpha/color tests are needed)? } - -} diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 82ec19ceb6..1394183f1b 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -51,8 +51,6 @@ D3DFORMAT ToD3D9Format(Draw::DataFormat fmt) { } } -namespace DX9 { - #define INVALID_TEX (LPDIRECT3DTEXTURE9)(-1) static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { @@ -443,5 +441,3 @@ bool TextureCacheDX9::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) return success; } - -}; diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 925d28982a..47005cbd5c 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -26,8 +26,6 @@ struct VirtualFramebuffer; class DepalShaderCache; -namespace DX9 { - class FramebufferManagerDX9; class ShaderManagerDX9; @@ -78,5 +76,3 @@ private: }; D3DFORMAT getClutDestFormat(GEPaletteFormat format); - -}; diff --git a/GPU/GPU.cpp b/GPU/GPU.cpp index 958b2b08f1..ed6a553c7e 100644 --- a/GPU/GPU.cpp +++ b/GPU/GPU.cpp @@ -83,7 +83,7 @@ bool GPU_Init(GraphicsContext *ctx, Draw::DrawContext *draw) { break; case GPUCORE_DIRECTX9: #if PPSSPP_API(D3D9) - SetGPU(new DIRECTX9_GPU(ctx, draw)); + SetGPU(new GPU_DX9(ctx, draw)); break; #else return false; diff --git a/Windows/GPU/D3D9Context.cpp b/Windows/GPU/D3D9Context.cpp index 9367078a81..7c1f4868e9 100644 --- a/Windows/GPU/D3D9Context.cpp +++ b/Windows/GPU/D3D9Context.cpp @@ -160,8 +160,8 @@ bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { } device_->BeginScene(); - DX9::pD3Ddevice = device_; - DX9::pD3DdeviceEx = deviceEx_; + pD3Ddevice9 = device_; + pD3DdeviceEx9 = deviceEx_; if (deviceEx_ && IsWin7OrHigher()) { // TODO: This makes it slower? @@ -212,8 +212,8 @@ void D3D9Context::Shutdown() { device_->Release(); d3d_->Release(); UnloadD3DCompiler(); - DX9::pD3Ddevice = nullptr; - DX9::pD3DdeviceEx = nullptr; + pD3Ddevice9 = nullptr; + pD3DdeviceEx9 = nullptr; device_ = nullptr; hWnd_ = nullptr; FreeLibrary(hD3D9_); From 2f3cad9964975d4715aefe44004aaa1dc1963f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 21:54:36 +0200 Subject: [PATCH 33/41] After recording a GE dump, open an explorer window pointing at the file --- GPU/Debugger/Record.cpp | 1 + Windows/GEDebugger/GEDebugger.cpp | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/GPU/Debugger/Record.cpp b/GPU/Debugger/Record.cpp index 100e0dd3c4..0a15fb8f43 100644 --- a/GPU/Debugger/Record.cpp +++ b/GPU/Debugger/Record.cpp @@ -29,6 +29,7 @@ #include "Common/Thread/ParallelLoop.h" #include "Common/Log.h" #include "Common/StringUtils.h" +#include "Common/System/System.h" #include "Core/Core.h" #include "Core/ELF/ParamSFO.h" diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 1546019124..60ae3a0b3b 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -21,12 +21,18 @@ #include #include +#include +#include + #include "Common/Data/Convert/ColorConv.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/Data/Text/Parsers.h" #include "Common/StringUtils.h" +#include "Common/System/System.h" + #include "Core/Config.h" #include "Core/Screenshot.h" + #include "Windows/GEDebugger/GEDebugger.h" #include "Windows/GEDebugger/SimpleGLWindow.h" #include "Windows/GEDebugger/CtrlDisplayListView.h" @@ -38,6 +44,7 @@ #include "Windows/InputBox.h" #include "Windows/MainWindow.h" #include "Windows/main.h" + #include "GPU/GPUInterface.h" #include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/GPUStateUtils.h" @@ -46,8 +53,6 @@ #include "GPU/Debugger/Debugger.h" #include "GPU/Debugger/Record.h" #include "GPU/Debugger/Stepping.h" -#include -#include using namespace GPUBreakpoints; using namespace GPUDebug; @@ -1048,6 +1053,10 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { break; case IDC_GEDBG_RECORD: + GPURecord::SetCallback([](const Path &path) { + // Opens a Windows Explorer window with the file. + OpenDirectory(path.c_str()); + }); GPURecord::Activate(); break; From 5785cf40ad91e29bc7b5d247f11153afd02eae0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 22:39:09 +0200 Subject: [PATCH 34/41] Clean up and comment framebuffer struct better, add bind sequence numbers --- GPU/Common/FramebufferManagerCommon.cpp | 30 ++++----- GPU/Common/FramebufferManagerCommon.h | 83 +++++++++++++++++-------- GPU/GLES/DepthBufferGLES.cpp | 2 +- GPU/ge_constants.h | 5 +- 4 files changed, 77 insertions(+), 43 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index afec95d06d..005d63a4fa 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -275,7 +275,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame // As there are no clear "framebuffer width" and "framebuffer height" registers, // we need to infer the size of the current framebuffer somehow. int drawing_width, drawing_height; - EstimateDrawingSize(params.fb_address, params.fmt, params.viewportWidth, params.viewportHeight, params.regionWidth, params.regionHeight, params.scissorWidth, params.scissorHeight, std::max(params.fb_stride, 4), drawing_width, drawing_height); + EstimateDrawingSize(params.fb_address, params.fmt, params.viewportWidth, params.viewportHeight, params.regionWidth, params.regionHeight, params.scissorWidth, params.scissorHeight, std::max(params.fb_stride, (u16)4), drawing_width, drawing_height); gstate_c.SetCurRTOffset(0, 0); bool vfbFormatChanged = false; @@ -530,6 +530,9 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame NotifyRenderFramebufferUpdated(vfb, vfbFormatChanged); } + vfb->colorBindSeq = GetBindSeqCount(); + vfb->depthBindSeq = GetBindSeqCount(); + gstate_c.curRTWidth = vfb->width; gstate_c.curRTHeight = vfb->height; gstate_c.curRTRenderWidth = vfb->renderWidth; @@ -692,8 +695,7 @@ void FramebufferManagerCommon::NotifyRenderFramebufferUpdated(VirtualFramebuffer void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) { if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) { ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height); - vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD) & ~FB_USAGE_DOWNLOAD_CLEAR; - vfb->firstFrameSaved = true; + vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; } else { DownloadFramebufferOnSwitch(prevVfb); } @@ -1026,14 +1028,13 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, GEBu } void FramebufferManagerCommon::DownloadFramebufferOnSwitch(VirtualFramebuffer *vfb) { - if (vfb && vfb->safeWidth > 0 && vfb->safeHeight > 0 && !vfb->firstFrameSaved && !vfb->memoryUpdated) { + if (vfb && vfb->safeWidth > 0 && vfb->safeHeight > 0 && !(vfb->usageFlags & FB_USAGE_FIRST_FRAME_SAVED) && !vfb->memoryUpdated) { // Some games will draw to some memory once, and use it as a render-to-texture later. // To support this, we save the first frame to memory when we have a safe w/h. // Saving each frame would be slow. if (!g_Config.bDisableSlowFramebufEffects && !PSP_CoreParameter().compat.flags().DisableFirstFrameReadback) { ReadFramebufferToMemory(vfb, 0, 0, vfb->safeWidth, vfb->safeHeight); - vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD) & ~FB_USAGE_DOWNLOAD_CLEAR; - vfb->firstFrameSaved = true; + vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; vfb->safeWidth = 0; vfb->safeHeight = 0; } @@ -1198,8 +1199,7 @@ void FramebufferManagerCommon::DecimateFBOs() { if (ShouldDownloadFramebuffer(vfb) && age == 0 && !vfb->memoryUpdated) { ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height); - vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD) & ~FB_USAGE_DOWNLOAD_CLEAR; - vfb->firstFrameSaved = true; + vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; } // Let's also "decimate" the usageFlags. @@ -1286,7 +1286,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, } if (force1x && g_Config.iInternalResolution != 1) { - vfb->renderScaleFactor = 1.0f; + vfb->renderScaleFactor = 1; vfb->renderWidth = vfb->bufferWidth; vfb->renderHeight = vfb->bufferHeight; } else { @@ -1654,7 +1654,7 @@ VirtualFramebuffer *FramebufferManagerCommon::FindDownloadTempBuffer(VirtualFram nvfb->height = vfb->height; nvfb->renderWidth = vfb->bufferWidth; nvfb->renderHeight = vfb->bufferHeight; - nvfb->renderScaleFactor = 1.0f; // For readbacks we resize to the original size, of course. + nvfb->renderScaleFactor = 1; // For readbacks we resize to the original size, of course. nvfb->bufferWidth = vfb->bufferWidth; nvfb->bufferHeight = vfb->bufferHeight; nvfb->format = vfb->format; @@ -2023,7 +2023,7 @@ void FramebufferManagerCommon::ShowScreenResolution() { // * Video file recording(would probably be great if it was async.) // * Screenshots(benefit slightly from async.) // * Save state screenshots(could probably be async but need to manage the stall.) -bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) { +bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxScaleFactor) { VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { vfb = GetVFBAt(fb_address); @@ -2042,9 +2042,9 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB Draw::Framebuffer *bound = nullptr; if (vfb->fbo) { - if (maxRes > 0 && vfb->renderWidth > vfb->width * maxRes) { - w = vfb->width * maxRes; - h = vfb->height * maxRes; + if (maxScaleFactor > 0 && vfb->renderWidth > vfb->width * maxScaleFactor) { + w = vfb->width * maxScaleFactor; + h = vfb->height * maxScaleFactor; Draw::Framebuffer *tempFBO = GetTempFBO(TempFBO::COPY, w, h); VirtualFramebuffer tempVfb = *vfb; @@ -2053,7 +2053,7 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB tempVfb.bufferHeight = vfb->height; tempVfb.renderWidth = w; tempVfb.renderHeight = h; - tempVfb.renderScaleFactor = (float)maxRes; + tempVfb.renderScaleFactor = maxScaleFactor; BlitFramebuffer(&tempVfb, 0, 0, vfb, 0, 0, vfb->width, vfb->height, 0, "Blit_GetFramebuffer"); bound = tempFBO; diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 54884f35bc..a2d395ad42 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -43,6 +43,7 @@ enum { FB_USAGE_DOWNLOAD = 16, FB_USAGE_DOWNLOAD_CLEAR = 32, FB_USAGE_BLUE_TO_ALPHA = 64, + FB_USAGE_FIRST_FRAME_SAVED = 128, }; enum { @@ -63,48 +64,76 @@ class ShaderWriter; // when such a situation is detected. In order to reliably detect this, we separately track depth buffers, // and they know which color buffer they were used with last. struct VirtualFramebuffer { + Draw::Framebuffer *fbo; + u32 fb_address; u32 z_address; // If 0, it's a "RAM" framebuffer. - int fb_stride; - int z_stride; - - GEBufferFormat format; // virtual, in reality they are all RGBA8888 for better quality but we can reinterpret that as necessary + u16 fb_stride; + u16 z_stride; // width/height: The detected size of the current framebuffer, in original PSP pixels. u16 width; u16 height; // bufferWidth/bufferHeight: The pre-scaling size of the buffer itself. May only be bigger than or equal to width/height. - // Actual physical buffer is this size times the render resolution multiplier. + // In original PSP pixels - actual framebuffer is this size times the render resolution multiplier. // The buffer may be used to render a width or height from 0 to these values without being recreated. u16 bufferWidth; u16 bufferHeight; // renderWidth/renderHeight: The scaled size we render at. May be scaled to render at higher resolutions. - // The physical buffer may be larger than renderWidth/renderHeight. + // These are simply bufferWidth/Height * renderScaleFactor and are thus redundant. u16 renderWidth; u16 renderHeight; - float renderScaleFactor; - - u16 usageFlags; - - u16 newWidth; - u16 newHeight; - - int lastFrameNewSize; - - Draw::Framebuffer *fbo; - + // Attempt to keep track of a bounding rectangle of what's been actually drawn. However, right now these are not + // used in a very detailed way (they're only ever 0 or equal to width/height) u16 drawnWidth; u16 drawnHeight; - GEBufferFormat drawnFormat; + + // The dimensions at which we are confident that we can read back this buffer without stomping on irrelevant memory. u16 safeWidth; u16 safeHeight; + // The scale factor at which we are rendering (to achieve higher resolution). + u8 renderScaleFactor; + + // The original PSP format of the framebuffer. + // In reality they are all RGBA8888 for better quality but this is what the PSP thinks it is. This is necessary + // when we need to interpret the bits directly (depal or buffer aliasing). + GEBufferFormat format; + + // The configured buffer format at the time of the latest/current draw. This will change first, then + // if different we'll "reinterpret" the framebuffer to match 'format' as needed. + GEBufferFormat drawnFormat; + + u16 usageFlags; + + // These are used to track state to try to avoid buffer size shifting back and forth. + // Though that shouldn't really happen, should it, since we always grow, don't shrink? + u16 newWidth; + u16 newHeight; + + // The frame number at which this was last resized. + int lastFrameNewSize; + + // Tracking for downloads-to-CLUT. + u16 clutUpdatedBytes; + bool memoryUpdated; + + // TODO: Fold into usageFlags? bool dirtyAfterDisplay; bool reallyDirtyAfterDisplay; // takes frame skipping into account + // Global sequence numbers for the last time these were bound. + // Not based on frames at all. Can be used to determine new-ness of one framebuffer over another, + // can even be within a frame. + int colorBindSeq; + int depthBindSeq; + + // These are mainly used for garbage collection purposes and similar. + // Cannot be used to determine new-ness against a similar other buffer, since they are + // only at frame granularity. int last_frame_used; int last_frame_attached; int last_frame_render; @@ -113,9 +142,6 @@ struct VirtualFramebuffer { int last_frame_failed; int last_frame_depth_updated; int last_frame_depth_render; - u32 clutUpdatedBytes; - bool memoryUpdated; - bool firstFrameSaved; }; struct TrackedDepthBuffer { @@ -132,9 +158,9 @@ struct TrackedDepthBuffer { struct FramebufferHeuristicParams { u32 fb_address; - int fb_stride; u32 z_address; - int z_stride; + u16 fb_stride; + u16 z_stride; GEBufferFormat fmt; bool isClearingDepth; bool isWritingDepth; @@ -412,6 +438,10 @@ protected: dstBuffer->reallyDirtyAfterDisplay = true; } + inline int GetBindSeqCount() { + return fbBindSeqCount_++; + } + PresentationCommon *presentation_ = nullptr; Draw::DrawContext *draw_ = nullptr; @@ -427,6 +457,8 @@ protected: GEBufferFormat displayFormat_ = GE_FORMAT_565; u32 prevDisplayFramebufPtr_ = 0; + int fbBindSeqCount_ = 0; + VirtualFramebuffer *displayFramebuf_ = nullptr; VirtualFramebuffer *prevDisplayFramebuf_ = nullptr; VirtualFramebuffer *prevPrevDisplayFramebuf_ = nullptr; @@ -451,7 +483,8 @@ protected: // Sampled in BeginFrame/UpdateSize for safety. float renderWidth_ = 0.0f; float renderHeight_ = 0.0f; - float renderScaleFactor_ = 1.0f; + + int renderScaleFactor_ = 1; int pixelWidth_ = 0; int pixelHeight_ = 0; int bloomHack_ = 0; @@ -481,7 +514,7 @@ protected: Draw::SamplerState *reinterpretSampler_ = nullptr; Draw::Buffer *reinterpretVBuf_ = nullptr; - // Common implementation of stencil buffer upload. Also not 100% optimal, but not perforamnce + // Common implementation of stencil buffer upload. Also not 100% optimal, but not performance // critical either. Draw::Pipeline *stencilUploadPipeline_ = nullptr; Draw::SamplerState *stencilUploadSampler_ = nullptr; diff --git a/GPU/GLES/DepthBufferGLES.cpp b/GPU/GLES/DepthBufferGLES.cpp index 6334fbd5ee..e5bcc20bf9 100644 --- a/GPU/GLES/DepthBufferGLES.cpp +++ b/GPU/GLES/DepthBufferGLES.cpp @@ -84,7 +84,7 @@ void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int // Pixel size always 4 here because we always request float const u32 bufSize = vfb->z_stride * (h - y) * 4; const u32 z_address = vfb->z_address; - const int packWidth = std::min(vfb->z_stride, std::min(x + w, (int)vfb->width)); + const int packWidth = std::min((int)vfb->z_stride, std::min(x + w, (int)vfb->width)); if (!convBuf_ || convBufSize_ < bufSize) { delete[] convBuf_; diff --git a/GPU/ge_constants.h b/GPU/ge_constants.h index 954934dcab..78363c3879 100644 --- a/GPU/ge_constants.h +++ b/GPU/ge_constants.h @@ -17,6 +17,8 @@ #pragma once +#include + enum GECommand { GE_CMD_NOP = 0, GE_CMD_VADDR = 0x1, @@ -276,8 +278,7 @@ enum GECommand { GE_CMD_NOP_FF = 0xFF, }; -enum GEBufferFormat -{ +enum GEBufferFormat : uint8_t { GE_FORMAT_565 = 0, GE_FORMAT_5551 = 1, GE_FORMAT_4444 = 2, From 19367dd890a95dd3e85c8dd7c97657c922857a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 16 Aug 2022 23:00:16 +0200 Subject: [PATCH 35/41] Comment updates --- GPU/Common/FramebufferManagerCommon.cpp | 2 ++ GPU/Common/FramebufferManagerCommon.h | 4 +++- GPU/Directx9/FramebufferManagerDX9.cpp | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 005d63a4fa..73d55312e5 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -121,6 +121,7 @@ VirtualFramebuffer *FramebufferManagerCommon::GetVFBAt(u32 addr) const { VirtualFramebuffer *v = vfbs_[i]; if (v->fb_address == addr) { // Could check w too but whatever + // NOTE: This gets the OLDEST image at the address - is that good? if (match == nullptr || match->last_frame_render < v->last_frame_render) { match = v; } @@ -2083,6 +2084,7 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) { VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { + // TODO: This is flawed, as it looks for color buffers at the address, not depth. vfb = GetVFBAt(fb_address); } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index a2d395ad42..d473ab6875 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -334,8 +334,10 @@ public: VirtualFramebuffer *GetCurrentRenderVFB() const { return currentRenderVfb_; } - // TODO: Break out into some form of FBO manager + + // This only checks for the color channel. VirtualFramebuffer *GetVFBAt(u32 addr) const; + VirtualFramebuffer *GetDisplayVFB() const { return GetVFBAt(displayFramebufPtr_); } diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp index 610940584c..bba5e670e2 100644 --- a/GPU/Directx9/FramebufferManagerDX9.cpp +++ b/GPU/Directx9/FramebufferManagerDX9.cpp @@ -327,6 +327,7 @@ bool FramebufferManagerDX9::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) { VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { + // TODO: This is flawed, as it looks for color buffers at the address, not depth. vfb = GetVFBAt(fb_address); } From a8b1d1191e0a54c5a7205cd6f89c9f6a440813b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 17 Aug 2022 00:07:05 +0200 Subject: [PATCH 36/41] Oops, remove wrong comments --- GPU/Common/FramebufferManagerCommon.cpp | 1 - GPU/Directx9/FramebufferManagerDX9.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 73d55312e5..9a34758bb6 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2084,7 +2084,6 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) { VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { - // TODO: This is flawed, as it looks for color buffers at the address, not depth. vfb = GetVFBAt(fb_address); } diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp index bba5e670e2..610940584c 100644 --- a/GPU/Directx9/FramebufferManagerDX9.cpp +++ b/GPU/Directx9/FramebufferManagerDX9.cpp @@ -327,7 +327,6 @@ bool FramebufferManagerDX9::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) { VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { - // TODO: This is flawed, as it looks for color buffers at the address, not depth. vfb = GetVFBAt(fb_address); } From 078fc881a772321bb3dec5090ba75606a5047d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 17 Aug 2022 10:15:02 +0200 Subject: [PATCH 37/41] Revise comments according to feedback --- GPU/Common/FramebufferManagerCommon.cpp | 5 ++--- GPU/Common/FramebufferManagerCommon.h | 9 ++++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 9a34758bb6..78440f5441 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -120,9 +120,8 @@ VirtualFramebuffer *FramebufferManagerCommon::GetVFBAt(u32 addr) const { for (size_t i = 0; i < vfbs_.size(); ++i) { VirtualFramebuffer *v = vfbs_[i]; if (v->fb_address == addr) { - // Could check w too but whatever - // NOTE: This gets the OLDEST image at the address - is that good? - if (match == nullptr || match->last_frame_render < v->last_frame_render) { + // Could check w too but whatever (actually, might very well make sense to do so, depending on context). + if (!match || v->last_frame_render > match->last_frame_render) { match = v; } } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index d473ab6875..d69d99d231 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -86,8 +86,8 @@ struct VirtualFramebuffer { u16 renderWidth; u16 renderHeight; - // Attempt to keep track of a bounding rectangle of what's been actually drawn. However, right now these are not - // used in a very detailed way (they're only ever 0 or equal to width/height) + // Attempt to keep track of a bounding rectangle of what's been actually drawn. Coarse, but might be smaller + // than width/height if framebuffer has been enlarged. In PSP pixels. u16 drawnWidth; u16 drawnHeight; @@ -110,7 +110,10 @@ struct VirtualFramebuffer { u16 usageFlags; // These are used to track state to try to avoid buffer size shifting back and forth. - // Though that shouldn't really happen, should it, since we always grow, don't shrink? + // You might think that doesn't happen since we mostly grow framebuffers, but we do resize down, + // if the size has shrunk for a while and the framebuffer is also larger than the stride. + // At this point, the "safe" size is probably a lie, and we have had various issues with readbacks, so this resizes down to avoid them. + // An example would be a game that always uses the address 0x00154000 for temp buffers, and uses it for a full-screen effect for 3 frames, then goes back to using it for character shadows or something much smaller. u16 newWidth; u16 newHeight; From 74f1c94ddb2bcb8bf504da30bd2a10a104559e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 17 Aug 2022 10:34:07 +0200 Subject: [PATCH 38/41] Use sequence numbers instead of a tracking array for depth buffers --- GPU/Common/FramebufferManagerCommon.cpp | 87 ++++++------------------- GPU/Common/FramebufferManagerCommon.h | 16 +---- 2 files changed, 22 insertions(+), 81 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 78440f5441..1855d088ff 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -71,12 +71,6 @@ FramebufferManagerCommon::~FramebufferManagerCommon() { } bvfbs_.clear(); - // Shouldn't be anything left here in theory, but just in case... - for (auto trackedDepth : trackedDepthBuffers_) { - delete trackedDepth; - } - trackedDepthBuffers_.clear(); - delete presentation_; } @@ -375,17 +369,11 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame // Lookup in the depth tracking to find which VFB has the latest version of this Z buffer. // Then bind it in color-to-depth mode. // - // We are going to do this by having a special render mode where we take color and move to + // We do this by having a special render mode where we take color and move to // depth in the fragment shader, and set color writes to off. // - // We'll need a special fragment shader flag to convert color to depth. - - for (auto &depth : this->trackedDepthBuffers_) { - if (depth->z_address == params.fb_address && depth->z_stride == params.fb_stride) { - // Found the matching depth buffer. Use this vfb. - vfb = depth->vfb; - } - } + // We use a special fragment shader flag to convert color to depth. + vfb = GetLatestDepthBufferAt(params.fb_address /* !!! */, params.fb_stride); } gstate_c.SetFramebufferRenderMode(mode); @@ -453,14 +441,13 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame // Looks up by z_address, so if one is found here and not have last pointers equal to this one, // there is another one. - TrackedDepthBuffer *prevDepth = GetOrCreateTrackedDepthBuffer(vfb); + VirtualFramebuffer *prevDepth = GetLatestDepthBufferAt(vfb->z_address, vfb->z_stride); // We might already want to copy depth, in case this is a temp buffer. See #7810. - if (prevDepth->vfb != vfb) { - if (!params.isClearingDepth && prevDepth->vfb) { - BlitFramebufferDepth(prevDepth->vfb, vfb); + if (prevDepth != vfb) { + if (!params.isClearingDepth && prevDepth) { + BlitFramebufferDepth(prevDepth, vfb); } - prevDepth->vfb = vfb; } SetColorUpdated(vfb, skipDrawReason); @@ -558,13 +545,6 @@ void FramebufferManagerCommon::DestroyFramebuf(VirtualFramebuffer *v) { if (prevPrevDisplayFramebuf_ == v) prevPrevDisplayFramebuf_ = nullptr; - // Remove any depth buffer tracking related to this vfb. - for (auto it = trackedDepthBuffers_.begin(); it != trackedDepthBuffers_.end(); it++) { - if ((*it)->vfb == v) { - (*it)->vfb = nullptr; // Mark for deletion in the next Decimate - } - } - delete v; } @@ -626,32 +606,16 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir dst->last_frame_depth_updated = gpuStats.numFlips; } -TrackedDepthBuffer *FramebufferManagerCommon::GetOrCreateTrackedDepthBuffer(VirtualFramebuffer *vfb) { - for (auto tracked : trackedDepthBuffers_) { - // Disable tracking if color of the new vfb is clashing with tracked depth. - if (vfb->fb_address == tracked->z_address) { - tracked->vfb = nullptr; // this is checked for. Cheaper than deleting. - continue; - } - - if (vfb->z_address == tracked->z_address) { - if (vfb->z_stride == tracked->z_stride) { - return tracked; - } else { - // Stride has changed, mark as bad. - tracked->vfb = nullptr; - } +VirtualFramebuffer *FramebufferManagerCommon::GetLatestDepthBufferAt(u32 z_address, u16 z_stride) { + int maxSeq = -1; + VirtualFramebuffer *latestDepth = nullptr; + for (auto vfb : vfbs_) { + if (vfb->z_address == z_address && vfb->z_stride == z_stride && vfb->depthBindSeq > maxSeq) { + maxSeq = vfb->depthBindSeq; + latestDepth = vfb; } } - - TrackedDepthBuffer *tracked = new TrackedDepthBuffer(); - tracked->vfb = vfb; - tracked->z_address = vfb->z_address; - tracked->z_stride = vfb->z_stride; - - trackedDepthBuffers_.push_back(tracked); - - return tracked; + return latestDepth; } void FramebufferManagerCommon::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) { @@ -703,14 +667,14 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe shaderManager_->DirtyLastShader(); // Copy depth between the framebuffers, if the z_address is the same (checked inside.) - TrackedDepthBuffer *prevDepth = GetOrCreateTrackedDepthBuffer(vfb); + VirtualFramebuffer * prevDepth = GetLatestDepthBufferAt(vfb->z_address, vfb->z_stride); // We might already want to copy depth, in case this is a temp buffer. See #7810. - if (prevDepth->vfb != vfb) { - if (!isClearingDepth && prevDepth->vfb) { - BlitFramebufferDepth(prevDepth->vfb, vfb); + if (prevDepth != vfb) { + if (!isClearingDepth && prevDepth) { + BlitFramebufferDepth(prevDepth, vfb); } - prevDepth->vfb = vfb; + prevDepth = vfb; } if (vfb->drawnFormat != vfb->format) { @@ -1234,16 +1198,6 @@ void FramebufferManagerCommon::DecimateFBOs() { bvfbs_.erase(bvfbs_.begin() + i--); } } - - // Also clean up the TrackedDepthBuffer array... - for (auto it = trackedDepthBuffers_.begin(); it != trackedDepthBuffers_.end();) { - if ((*it)->vfb == nullptr) { - delete *it; - it = trackedDepthBuffers_.erase(it); - } else { - it++; - } - } } // Requires width/height to be set already. @@ -2220,6 +2174,7 @@ void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb, // We'll pseudo-blit framebuffers here to get a resized version of vfb. if (gameUsesSequentialCopies_) { // Ignore the x/y/etc., read the entire thing. + // TODO: What game did we need this for? x = 0; y = 0; w = vfb->width; diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index d69d99d231..7952e83827 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -147,18 +147,6 @@ struct VirtualFramebuffer { int last_frame_depth_render; }; -struct TrackedDepthBuffer { - u32 z_address; - int z_stride; - - // Really need to make sure we're killing these TrackedDepthBuffer's off when the VirtualFrameBuffers die. - VirtualFramebuffer *vfb; - - // Could do full tracking of which framebuffers are used with this depth buffer, - // but probably not necessary. - // std::set> seen_fbs; -}; - struct FramebufferHeuristicParams { u32 fb_address; u32 z_address; @@ -300,7 +288,7 @@ public: void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes); void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride); - TrackedDepthBuffer *GetOrCreateTrackedDepthBuffer(VirtualFramebuffer *vfb); + VirtualFramebuffer *GetLatestDepthBufferAt(u32 z_address, u16 z_stride); void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height); @@ -481,8 +469,6 @@ protected: std::vector vfbs_; std::vector bvfbs_; // blitting framebuffers (for download) - std::vector trackedDepthBuffers_; - bool gameUsesSequentialCopies_ = false; // Sampled in BeginFrame/UpdateSize for safety. From f2aecada794a9ae01816634ec12f314a10e08a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 17 Aug 2022 14:02:51 +0200 Subject: [PATCH 39/41] Add Silverfall to [AtracLoopHack]. At least we're gathering a good list of test cases once we have an idea for a real fix... See #14575 --- assets/compat.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assets/compat.ini b/assets/compat.ini index 005b5931e9..8eb89db0d9 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -1263,3 +1263,5 @@ ULES00897 = true ULUS10194 = true ULES00618 = true +# Silver Fall +ULES00808 = true From 3c3708e6e4a1a6be7b37ffd5d5afe1ac17b1338e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 17 Aug 2022 14:04:08 +0200 Subject: [PATCH 40/41] Silverfall: Add the US game ID too --- assets/compat.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/compat.ini b/assets/compat.ini index 8eb89db0d9..c6011605d7 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -1265,3 +1265,4 @@ ULES00618 = true # Silver Fall ULES00808 = true +ULUS10270 = true From 2887671e6f4faf8aa53800c885d0ac58f1609826 Mon Sep 17 00:00:00 2001 From: Lubos Date: Wed, 17 Aug 2022 16:55:19 +0200 Subject: [PATCH 41/41] OpenXR - Refactor display framerate --- Core/HLE/sceDisplay.cpp | 38 +++++++++++++++++++------------------ Core/HLE/sceDisplay.h | 2 ++ android/jni/app-android.cpp | 3 +++ 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index e3a44e54d8..7db5998ff7 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -57,12 +57,6 @@ #include "GPU/Common/PostShader.h" #include "GPU/Debugger/Record.h" -#ifdef OPENXR -#define FRAMELIMIT 72 -#else -#define FRAMELIMIT 60 -#endif - struct FrameBufferState { u32 topaddr; GEBufferFormat fmt; @@ -110,8 +104,10 @@ static int height; static bool wasPaused; static bool flippedThisFrame; +static int framerate = 60; + // 1.001f to compensate for the classic 59.94 NTSC framerate that the PSP seems to have. -static const double timePerVblank = 1.001f / (float)FRAMELIMIT; +static double timePerVblank = 1.001f / (float)framerate; // Don't include this in the state, time increases regardless of state. static double curFrameTime; @@ -133,7 +129,7 @@ const double vblankMs = 0.7315; // These are guesses based on tests. const double vsyncStartMs = 0.5925; const double vsyncEndMs = 0.7265; -const double frameMs = 1001.0 / (double)FRAMELIMIT; +double frameMs = 1001.0 / (double)framerate; enum { PSP_DISPLAY_SETBUF_IMMEDIATE = 0, @@ -164,7 +160,7 @@ static void ScheduleLagSync(int over = 0) { if (lagSyncScheduled) { // Reset over if it became too high, such as after pausing or initial loading. // There's no real sense in it being more than 1/60th of a second. - if (over > 1000000 / FRAMELIMIT) { + if (over > 1000000 / framerate) { over = 0; } CoreTiming::ScheduleEvent(usToCycles(1000 + over), lagSyncEvent, 0); @@ -364,7 +360,7 @@ static int FrameTimingLimit() { return PSP_CoreParameter().analogFpsLimit; if (PSP_CoreParameter().fastForward) return 0; - return FRAMELIMIT; + return framerate; } static bool FrameTimingThrottled() { @@ -395,8 +391,8 @@ static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) { return; float scaledTimestep = timestep; - if (fpsLimit > 0 && fpsLimit != FRAMELIMIT) { - scaledTimestep *= (float)FRAMELIMIT / fpsLimit; + if (fpsLimit > 0 && fpsLimit != framerate) { + scaledTimestep *= (float)framerate / fpsLimit; } if (lastFrameTime == 0.0 || wasPaused) { @@ -470,9 +466,9 @@ static void DoFrameIdleTiming() { float scaledVblank = timePerVblank; int fpsLimit = FrameTimingLimit(); - if (fpsLimit != 0 && fpsLimit != FRAMELIMIT) { + if (fpsLimit != 0 && fpsLimit != framerate) { // 0 is handled in FrameTimingThrottled(). - scaledVblank *= (float)FRAMELIMIT / fpsLimit; + scaledVblank *= (float)framerate / fpsLimit; } // If we have over at least a vblank of spare time, maintain at least 30fps in delay. @@ -592,7 +588,7 @@ void __DisplayFlip(int cyclesLate) { bool forceNoFlip = false; float refreshRate = System_GetPropertyFloat(SYSPROP_DISPLAY_REFRESH_RATE); // Avoid skipping on devices that have 58 or 59 FPS, except when alternate speed is set. - bool refreshRateNeedsSkip = FrameTimingLimit() != FRAMELIMIT && FrameTimingLimit() > refreshRate; + bool refreshRateNeedsSkip = FrameTimingLimit() != framerate && FrameTimingLimit() > refreshRate; // Alternative to frameskip fast-forward, where we draw everything. // Useful if skipping a frame breaks graphics or for checking drawing speed. if (fastForwardSkipFlip && (!FrameTimingThrottled() || refreshRateNeedsSkip)) { @@ -691,9 +687,9 @@ void hleLagSync(u64 userdata, int cyclesLate) { float scale = 1.0f; int fpsLimit = FrameTimingLimit(); - if (fpsLimit != 0 && fpsLimit != FRAMELIMIT) { + if (fpsLimit != 0 && fpsLimit != framerate) { // 0 is handled in FrameTimingThrottled(). - scale = (float)FRAMELIMIT / fpsLimit; + scale = (float)framerate / fpsLimit; } const double goal = lastLagSync + (scale / 1000.0f); @@ -851,7 +847,7 @@ u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync) } // 1001 to account for NTSC timing (59.94 fps.) - u64 expected = msToCycles(1001) / FRAMELIMIT - LEEWAY_CYCLES_PER_FLIP; + u64 expected = msToCycles(1001) / framerate - LEEWAY_CYCLES_PER_FLIP; lastFlipCycles = now; nextFlipCycles = std::max(lastFlipCycles, nextFlipCycles) + expected; } @@ -1083,3 +1079,9 @@ void Register_sceDisplay() { void Register_sceDisplay_driver() { RegisterModule("sceDisplay_driver", ARRAY_SIZE(sceDisplay), sceDisplay); } + +void __DisplaySetFramerate(int value) { + framerate = value; + timePerVblank = 1.001f / (float)framerate; + frameMs = 1001.0 / (double)framerate; +} diff --git a/Core/HLE/sceDisplay.h b/Core/HLE/sceDisplay.h index bb134af815..b68133e8a2 100644 --- a/Core/HLE/sceDisplay.h +++ b/Core/HLE/sceDisplay.h @@ -34,3 +34,5 @@ void __DisplaySetWasPaused(); void Register_sceDisplay_driver(); void __DisplayWaitForVblanks(const char* reason, int vblanks, bool callbacks = false); + +void __DisplaySetFramerate(int value); diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 23c6d56dc5..aaf9d290db 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -94,6 +94,7 @@ struct JNIEnv {}; #include "UI/GameInfoCache.h" #ifdef OPENXR +#include "Core/HLE/sceDisplay.h" #include "VR/VRBase.h" #include "VR/VRInput.h" #include "VR/VRRenderer.h" @@ -818,6 +819,8 @@ retry: java.AppVersion = gitVer.ToInteger(); strcpy(java.AppName, "PPSSPP"); VR_Init(java); + + __DisplaySetFramerate(72); #endif }