diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h index 1b7fd4cff0..6f53fa75d0 100644 --- a/GPU/Common/GPUDebugInterface.h +++ b/GPU/Common/GPUDebugInterface.h @@ -30,11 +30,28 @@ struct GPUDebugOp { std::string desc; }; +enum GPUDebugBufferFormat { + // These match GEBufferFormat. + GPU_DBG_FORMAT_565 = 0, + GPU_DBG_FORMAT_5551 = 1, + GPU_DBG_FORMAT_4444 = 2, + GPU_DBG_FORMAT_8888 = 3, + GPU_DBG_FORMAT_INVALID = 0xFF, + + // These don't, they're for depth buffers. + GPU_DBG_FORMAT_FLOAT = 0x10, + GPU_DBG_FORMAT_16BIT = 0x11, +}; + struct GPUDebugBuffer { GPUDebugBuffer() : alloc_(false), data_(NULL) { } GPUDebugBuffer(void *data, u32 stride, u32 height, GEBufferFormat fmt) + : alloc_(false), data_((u8 *)data), stride_(stride), height_(height), fmt_(GPUDebugBufferFormat(fmt)), flipped_(false) { + } + + GPUDebugBuffer(void *data, u32 stride, u32 height, GPUDebugBufferFormat fmt) : alloc_(false), data_((u8 *)data), stride_(stride), height_(height), fmt_(fmt), flipped_(false) { } @@ -70,6 +87,10 @@ struct GPUDebugBuffer { } void Allocate(u32 stride, u32 height, GEBufferFormat fmt, bool flipped = false) { + Allocate(stride, height, GPUDebugBufferFormat(fmt), flipped); + } + + void Allocate(u32 stride, u32 height, GPUDebugBufferFormat fmt, bool flipped = false) { if (alloc_ && stride_ == stride && height_ == height && fmt_ == fmt) { // Already allocated the right size. flipped_ = flipped; @@ -84,7 +105,7 @@ struct GPUDebugBuffer { flipped_ = flipped; u32 pixelSize = 2; - if (fmt == GE_FORMAT_8888) { + if (fmt == GPU_DBG_FORMAT_8888 || fmt == GPU_DBG_FORMAT_FLOAT) { pixelSize = 4; }; @@ -114,7 +135,7 @@ struct GPUDebugBuffer { return flipped_; } - GEBufferFormat GetFormat() const { + GPUDebugBufferFormat GetFormat() const { return fmt_; } @@ -124,7 +145,7 @@ private: u32 height_; u32 stride_; bool flipped_; - GEBufferFormat fmt_; + GPUDebugBufferFormat fmt_; }; class GPUDebugInterface { @@ -153,6 +174,16 @@ public: return false; } + // Similar to GetCurrentFramebuffer(). + virtual bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { + return false; + } + + // Similar to GetCurrentFramebuffer(). + virtual bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { + return false; + } + // Similar to GetCurrentFramebuffer(). virtual bool GetCurrentTexture(GPUDebugBuffer &buffer) { return false; diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index d75e642713..33b2449eea 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -1342,8 +1342,7 @@ void FramebufferManager::Resized() { resized_ = true; } -bool FramebufferManager::GetCurrentFramebuffer(GPUDebugBuffer &buffer) -{ +bool FramebufferManager::GetCurrentFramebuffer(GPUDebugBuffer &buffer) { u32 fb_address = (gstate.fbptr & 0xFFFFFF) | ((gstate.fbwidth & 0xFF0000) << 8); int fb_stride = gstate.fbwidth & 0x3C0; @@ -1366,3 +1365,62 @@ bool FramebufferManager::GetCurrentFramebuffer(GPUDebugBuffer &buffer) return true; } + +bool FramebufferManager::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { + u32 fb_address = (gstate.fbptr & 0xFFFFFF) | ((gstate.fbwidth & 0xFF0000) << 8); + int fb_stride = gstate.fbwidth & 0x3C0; + + u32 z_address = (gstate.zbptr & 0xFFFFFF) | ((gstate.zbwidth & 0xFF0000) << 8); + int z_stride = gstate.zbwidth & 0x3C0; + + VirtualFramebuffer *vfb = currentRenderVfb_; + if (!vfb) { + vfb = GetVFBAt(fb_address); + } + + if (!vfb) { + // If there's no vfb and we're drawing there, must be memory? + buffer = GPUDebugBuffer(Memory::GetPointer(z_address), z_stride, 512, GPU_DBG_FORMAT_16BIT); + return true; + } + +#ifndef USING_GLES2 + buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_FLOAT, true); + + fbo_bind_for_read(vfb->fbo); + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_DEPTH_COMPONENT, GL_FLOAT, buffer.GetData()); + + return true; +#else + return false; +#endif +} + +bool FramebufferManager::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { + u32 fb_address = (gstate.fbptr & 0xFFFFFF) | ((gstate.fbwidth & 0xFF0000) << 8); + int fb_stride = gstate.fbwidth & 0x3C0; + + VirtualFramebuffer *vfb = currentRenderVfb_; + if (!vfb) { + vfb = GetVFBAt(fb_address); + } + + if (!vfb) { + // If there's no vfb and we're drawing there, must be memory? + buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, GPU_DBG_FORMAT_8888); + return true; + } + +#ifndef USING_GLES2 + buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_16BIT, true); + + fbo_bind_for_read(vfb->fbo); + glPixelStorei(GL_PACK_ALIGNMENT, 2); + glReadPixels(0, 0, vfb->renderWidth, vfb->renderHeight, GL_STENCIL_INDEX, GL_UNSIGNED_SHORT, buffer.GetData()); + + return true; +#else + return false; +#endif +} diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index a268769099..0f1a479f2c 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -171,6 +171,8 @@ public: void DestroyFramebuf(VirtualFramebuffer *vfb); bool GetCurrentFramebuffer(GPUDebugBuffer &buffer); + bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); + bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); private: void CompileDraw2DProgram(); diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index a6547523db..c81764c4cc 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -1519,6 +1519,14 @@ bool GLES_GPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer) { return framebufferManager_.GetCurrentFramebuffer(buffer); } +bool GLES_GPU::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { + return framebufferManager_.GetCurrentDepthbuffer(buffer); +} + +bool GLES_GPU::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { + return framebufferManager_.GetCurrentStencilbuffer(buffer); +} + bool GLES_GPU::GetCurrentTexture(GPUDebugBuffer &buffer) { if (!gstate.isTextureMapEnabled()) { return false; diff --git a/GPU/GLES/GLES_GPU.h b/GPU/GLES/GLES_GPU.h index a3280b3013..dc4bd38299 100644 --- a/GPU/GLES/GLES_GPU.h +++ b/GPU/GLES/GLES_GPU.h @@ -67,6 +67,8 @@ public: std::vector GetFramebufferList(); bool GetCurrentFramebuffer(GPUDebugBuffer &buffer); + bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); + bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); bool GetCurrentTexture(GPUDebugBuffer &buffer); protected: diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index cf1110eb26..f3d452f91a 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -78,6 +78,14 @@ public: // TODO return false; } + virtual bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { + // TODO + return false; + } + virtual bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { + // TODO + return false; + } protected: virtual void FastRunLoop(DisplayList &list);