From a0d84d45cc110e582dba98ff6f7f9911ade65e5b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 7 Oct 2013 00:38:46 -0700 Subject: [PATCH 1/6] Flip the texture preview when it's a framebuffer. --- GPU/GLES/GLES_GPU.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index 07f4369084..4c87a126aa 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -1562,7 +1562,7 @@ bool GLES_GPU::GetCurrentTexture(GPUDebugBuffer &buffer) { glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); - buffer.Allocate(w, h, GE_FORMAT_8888, false); + buffer.Allocate(w, h, GE_FORMAT_8888, gstate_c.flipTexture); glPixelStorei(GL_PACK_ALIGNMENT, 4); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.GetData()); From 31171cc04441b93b2947f5106496ffa6b9c19cb3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 7 Oct 2013 00:50:15 -0700 Subject: [PATCH 2/6] Grab the stencil buffer in softgpu debugging. --- GPU/Common/GPUDebugInterface.h | 4 +++- GPU/Software/SoftGpu.cpp | 32 +++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h index 68e03debd2..5daef9ef29 100644 --- a/GPU/Common/GPUDebugInterface.h +++ b/GPU/Common/GPUDebugInterface.h @@ -112,7 +112,9 @@ struct GPUDebugBuffer { u32 pixelSize = 2; if (fmt == GPU_DBG_FORMAT_8888 || fmt == GPU_DBG_FORMAT_FLOAT) { pixelSize = 4; - }; + } else if (fmt == GPU_DBG_FORMAT_8BIT) { + pixelSize = 1; + } data_ = new u8[pixelSize * stride * height]; } diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 4fcec22ec8..2c3388a552 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -759,15 +759,41 @@ bool SoftGPU::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { // We don't know the height, so just use 512, which should be the max (hopefully?) // TODO: Could check clipping and such, though...? - // TODO: Is the value 16-bit? It seems to be. buffer = GPUDebugBuffer(depthbuf.data, gstate.DepthBufStride(), 512, GPU_DBG_FORMAT_16BIT); return true; } bool SoftGPU::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - // TODO: Just need the alpha value from the framebuffer... - return false; + buffer.Allocate(gstate.DepthBufStride(), 512, GPU_DBG_FORMAT_8BIT); + + for (int y = 0; y < 512; ++y) { + u8 *row = buffer.GetData() + gstate.DepthBufStride() * y; + switch (gstate.FrameBufFormat()) { + case GE_FORMAT_565: + memset(row, 0, gstate.DepthBufStride()); + break; + case GE_FORMAT_5551: + for (int x = 0; x < gstate.DepthBufStride(); ++x) { + row[x] = (fb.Get16(x, y, gstate.FrameBufStride()) & 0x8000) != 0 ? 0xFF : 0; + } + break; + case GE_FORMAT_4444: + for (int x = 0; x < gstate.DepthBufStride(); ++x) { + row[x] = Convert4To8(fb.Get16(x, y, gstate.FrameBufStride()) >> 12); + } + break; + case GE_FORMAT_8888: + for (int x = 0; x < gstate.DepthBufStride(); ++x) { + row[x] = fb.Get32(x, y, gstate.FrameBufStride()) >> 24; + } + break; + case GE_FORMAT_INVALID: + ERROR_LOG(HLE, "Impossible framebuffer format."); + break; + } + } + return true; } bool SoftGPU::GetCurrentTexture(GPUDebugBuffer &buffer) From b9453f82ca97792bb0107600309dbe936c313268 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 7 Oct 2013 01:00:43 -0700 Subject: [PATCH 3/6] Use the full alpha bits for stencil in softgpu. It works to increment and set the stencil, so it can't be high bits only. --- GPU/Software/Rasterizer.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index 5d3d6d4b44..fc06734a85 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -319,22 +319,33 @@ static inline u8 GetPixelStencil(int x, int y) if (gstate.FrameBufFormat() == GE_FORMAT_565) { // TODO: Should we return 0xFF instead here? return 0; - } else if (gstate.FrameBufFormat() != GE_FORMAT_8888) { + } else if (gstate.FrameBufFormat() == GE_FORMAT_5551) { return ((fb.Get16(x, y, gstate.FrameBufStride()) & 0x8000) != 0) ? 0xFF : 0; + } else if (gstate.FrameBufFormat() != GE_FORMAT_4444) { + return fb.Get16(x, y, gstate.FrameBufStride()) >> 12; } else { - // TODO: Not the whole value? - return ((fb.Get32(x, y, gstate.FrameBufStride()) & 0x80000000) != 0) ? 0xFF : 0; + return fb.Get32(x, y, gstate.FrameBufStride()) >> 24; } } static inline void SetPixelStencil(int x, int y, u8 value) { + // TODO: This seems like it maybe respects the alpha mask (at least in some scenarios?) + if (gstate.FrameBufFormat() == GE_FORMAT_565) { // Do nothing - } else if (gstate.FrameBufFormat() != GE_FORMAT_8888) { - fb.Set16(x, y, gstate.FrameBufStride(), (fb.Get16(x, y, gstate.FrameBufStride()) & ~0x8000) | ((value&0x80)<<8)); + } else if (gstate.FrameBufFormat() == GE_FORMAT_5551) { + u16 pixel = fb.Get16(x, y, gstate.FrameBufStride()) & ~0x8000; + pixel |= value != 0 ? 0x8000 : 0; + fb.Set16(x, y, gstate.FrameBufStride(), pixel); + } else if (gstate.FrameBufFormat() != GE_FORMAT_4444) { + u16 pixel = fb.Get16(x, y, gstate.FrameBufStride()) & ~0xF000; + pixel |= (u16)value << 12; + fb.Set16(x, y, gstate.FrameBufStride(), pixel); } else { - fb.Set32(x, y, gstate.FrameBufStride(), (fb.Get32(x, y, gstate.FrameBufStride()) & ~0x80000000) | ((value&0x80)<<24)); + u32 pixel = fb.Get32(x, y, gstate.FrameBufStride()) & ~0xFF000000; + pixel |= (u32)value << 24; + fb.Set32(x, y, gstate.FrameBufStride(), pixel); } } From 5c2d418d95beddb9f5e9c2abc15bcc4fa9a1cf0e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 7 Oct 2013 01:02:58 -0700 Subject: [PATCH 4/6] Read softgpu stencil using existing funcs. Slower but at least it's the same. --- GPU/Software/Rasterizer.cpp | 14 ++++++++++++++ GPU/Software/Rasterizer.h | 4 ++++ GPU/Software/SoftGpu.cpp | 35 ++++++----------------------------- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index fc06734a85..c79231f014 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -959,4 +959,18 @@ void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& } } +bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) +{ + buffer.Allocate(gstate.DepthBufStride(), 512, GPU_DBG_FORMAT_8BIT); + + u8 *row = buffer.GetData(); + for (int y = 0; y < 512; ++y) { + for (int x = 0; x < gstate.DepthBufStride(); ++x) { + row[x] = GetPixelStencil(x, y); + } + row += gstate.DepthBufStride(); + } + return true; +} + } // namespace diff --git a/GPU/Software/Rasterizer.h b/GPU/Software/Rasterizer.h index e49767e187..7f06222fc7 100644 --- a/GPU/Software/Rasterizer.h +++ b/GPU/Software/Rasterizer.h @@ -19,9 +19,13 @@ #include "TransformUnit.h" // for DrawingCoords +struct GPUDebugBuffer; + namespace Rasterizer { // Draws a triangle if its vertices are specified in counter-clockwise order void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& v2); +bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); + } diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 2c3388a552..9e02ca7c3c 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -28,6 +28,7 @@ #include "GPU/Software/SoftGpu.h" #include "GPU/Software/TransformUnit.h" #include "GPU/Software/Colors.h" +#include "GPU/Software/Rasterizer.h" static GLuint temp_texture = 0; @@ -765,40 +766,15 @@ bool SoftGPU::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) bool SoftGPU::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - buffer.Allocate(gstate.DepthBufStride(), 512, GPU_DBG_FORMAT_8BIT); - - for (int y = 0; y < 512; ++y) { - u8 *row = buffer.GetData() + gstate.DepthBufStride() * y; - switch (gstate.FrameBufFormat()) { - case GE_FORMAT_565: - memset(row, 0, gstate.DepthBufStride()); - break; - case GE_FORMAT_5551: - for (int x = 0; x < gstate.DepthBufStride(); ++x) { - row[x] = (fb.Get16(x, y, gstate.FrameBufStride()) & 0x8000) != 0 ? 0xFF : 0; - } - break; - case GE_FORMAT_4444: - for (int x = 0; x < gstate.DepthBufStride(); ++x) { - row[x] = Convert4To8(fb.Get16(x, y, gstate.FrameBufStride()) >> 12); - } - break; - case GE_FORMAT_8888: - for (int x = 0; x < gstate.DepthBufStride(); ++x) { - row[x] = fb.Get32(x, y, gstate.FrameBufStride()) >> 24; - } - break; - case GE_FORMAT_INVALID: - ERROR_LOG(HLE, "Impossible framebuffer format."); - break; - } - } - return true; + return Rasterizer::GetCurrentStencilbuffer(buffer); } bool SoftGPU::GetCurrentTexture(GPUDebugBuffer &buffer) { static const int level = 0; + + WARN_LOG(G3D, "Software texture preview currently very broken."); + u32 bufw = GetTextureBufw(level, gstate.getTextureAddress(level), gstate.getTextureFormat()); switch (gstate.getTextureFormat()) { @@ -806,6 +782,7 @@ bool SoftGPU::GetCurrentTexture(GPUDebugBuffer &buffer) case GE_TFMT_5551: case GE_TFMT_4444: case GE_TFMT_8888: + // TODO: Swizzling, of course. buffer = GPUDebugBuffer(Memory::GetPointer(gstate.getTextureAddress(level)), bufw, gstate.getTextureHeight(level), gstate.getTextureFormat()); return true; From b9811c7c9798a1619a6cd04554cb95115e859ece Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 7 Oct 2013 01:26:48 -0700 Subject: [PATCH 5/6] Use the slow way to get the softgpu texture. So that it actually shows what the softgpu is using. --- GPU/Software/Rasterizer.cpp | 21 +++++++++++++++++++++ GPU/Software/Rasterizer.h | 1 + GPU/Software/SoftGpu.cpp | 20 +------------------- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index c79231f014..2da595f3bf 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -973,4 +973,25 @@ bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) return true; } +bool GetCurrentTexture(GPUDebugBuffer &buffer) +{ + int w = gstate.getTextureWidth(0); + int h = gstate.getTextureHeight(0); + buffer.Allocate(w, h, GE_FORMAT_8888, false); + + GETextureFormat texfmt = gstate.getTextureFormat(); + u32 texaddr = gstate.getTextureAddress(0); + int texbufwidthbits = GetTextureBufw(0, texaddr, texfmt) * 8; + u8 *texptr = Memory::GetPointer(texaddr); + + u32 *row = (u32 *)buffer.GetData(); + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + row[x] = SampleNearest(0, x, y, texptr, texbufwidthbits); + } + row += w; + } + return true; +} + } // namespace diff --git a/GPU/Software/Rasterizer.h b/GPU/Software/Rasterizer.h index 7f06222fc7..ace598c4e5 100644 --- a/GPU/Software/Rasterizer.h +++ b/GPU/Software/Rasterizer.h @@ -27,5 +27,6 @@ namespace Rasterizer { void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData& v2); bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); +bool GetCurrentTexture(GPUDebugBuffer &buffer); } diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 9e02ca7c3c..16d629afb0 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -771,23 +771,5 @@ bool SoftGPU::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) bool SoftGPU::GetCurrentTexture(GPUDebugBuffer &buffer) { - static const int level = 0; - - WARN_LOG(G3D, "Software texture preview currently very broken."); - - u32 bufw = GetTextureBufw(level, gstate.getTextureAddress(level), gstate.getTextureFormat()); - switch (gstate.getTextureFormat()) - { - case GE_TFMT_5650: - case GE_TFMT_5551: - case GE_TFMT_4444: - case GE_TFMT_8888: - // TODO: Swizzling, of course. - buffer = GPUDebugBuffer(Memory::GetPointer(gstate.getTextureAddress(level)), bufw, gstate.getTextureHeight(level), gstate.getTextureFormat()); - return true; - - default: - // TODO: Support these... - return false; - } + return Rasterizer::GetCurrentTexture(buffer); } From 5e54847aaf3ecc38dd0ab43b51335cdf67734d33 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 7 Oct 2013 01:43:40 -0700 Subject: [PATCH 6/6] Wait better with broken win32 cond vars. --- Windows/GEDebugger/GEDebugger.cpp | 33 +++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index 72d269f6a8..556f733b80 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -37,6 +37,7 @@ enum PauseAction { PAUSE_CONTINUE, + PAUSE_BREAK, PAUSE_GETFRAMEBUF, PAUSE_GETDEPTHBUF, PAUSE_GETSTENCILBUF, @@ -52,6 +53,7 @@ static condition_variable pauseWait; static PauseAction pauseAction = PAUSE_CONTINUE; static recursive_mutex actionLock; static condition_variable actionWait; +static bool actionComplete; static recursive_mutex breaksLock; static std::vector breakCmds; @@ -110,15 +112,18 @@ bool CGEDebugger::IsOpOrTextureBreakPoint(u32 op) { return IsOpBreakPoint(op) || IsTextureBreakPoint(op); } -static void SetPauseAction(PauseAction act) { +static void SetPauseAction(PauseAction act, bool waitComplete = true) { { lock_guard guard(pauseLock); actionLock.lock(); pauseAction = act; } + actionComplete = false; pauseWait.notify_one(); - actionWait.wait(actionLock); + while (waitComplete && !actionComplete) { + actionWait.wait(actionLock); + } actionLock.unlock(); } @@ -130,6 +135,9 @@ static void RunPauseAction() { // Don't notify, just go back, woke up by accident. return; + case PAUSE_BREAK: + break; + case PAUSE_GETFRAMEBUF: bufferResult = gpuDebug->GetCurrentFramebuffer(bufferFrame); break; @@ -154,15 +162,15 @@ static void RunPauseAction() { ERROR_LOG(HLE, "Unsupported pause action, forgot to add it to the switch."); } + actionComplete = true; actionWait.notify_one(); - pauseAction = PAUSE_CONTINUE; + pauseAction = PAUSE_BREAK; } static void ForceUnpause() { - lock_guard guard(pauseLock); - lock_guard actionGuard(actionLock); - pauseAction = PAUSE_CONTINUE; - pauseWait.notify_one(); + SetPauseAction(PAUSE_CONTINUE, false); + actionComplete = true; + actionWait.notify_one(); } CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent) @@ -408,7 +416,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { attached = true; SetupPreviews(); - pauseWait.notify_one(); + SetPauseAction(PAUSE_CONTINUE, false); breakNextOp = false; breakNextDraw = true; break; @@ -424,9 +432,9 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, L""); // TODO: detach? Should probably have separate UI, or just on activate? + SetPauseAction(PAUSE_CONTINUE, false); breakNextOp = false; breakNextDraw = false; - pauseWait.notify_one(); break; } break; @@ -452,7 +460,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { attached = true; SetupPreviews(); - pauseWait.notify_one(); + SetPauseAction(PAUSE_CONTINUE, false); breakNextOp = true; breakNextDraw = false; break; @@ -503,6 +511,11 @@ static void PauseWithMessage(UINT msg, WPARAM wParam = NULL, LPARAM lParam = NUL PostMessage(geDebuggerWindow->GetDlgHandle(), msg, wParam, lParam); + // Just to be sure. + if (pauseAction == PAUSE_CONTINUE) { + pauseAction = PAUSE_BREAK; + } + do { RunPauseAction(); pauseWait.wait(pauseLock);