diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index faafae74aa..a5c5324b73 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -269,6 +269,7 @@ public: virtual bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) = 0; virtual bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) = 0; virtual bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) = 0; + virtual bool GetOutputFramebuffer(GPUDebugBuffer &buffer) = 0; protected: virtual void SetViewport2D(int x, int y, int w, int h) = 0; diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 64fa1dd505..a1d4fb301a 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -120,6 +120,7 @@ FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) } FramebufferManagerD3D11::~FramebufferManagerD3D11() { + packTexture_->Release(); // Drawing cleanup if (quadVertexShader_) quadVertexShader_->Release(); @@ -836,8 +837,71 @@ void FramebufferManagerD3D11::Resized() { resized_ = true; } +// Lots of this code could be shared (like the downsampling). bool FramebufferManagerD3D11::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) { - return false; + 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 | 0x04000000), fb_stride, 512, format); + return true; + } + + int w = vfb->renderWidth, h = vfb->renderHeight; + Draw::Framebuffer *fboForRead = nullptr; + if (vfb->fbo) { + if (maxRes > 0 && vfb->renderWidth > vfb->width * maxRes) { + w = vfb->width * maxRes; + h = vfb->height * maxRes; + + Draw::Framebuffer *tempFBO = GetTempFBO(w, h); + VirtualFramebuffer tempVfb = *vfb; + tempVfb.fbo = tempFBO; + tempVfb.bufferWidth = vfb->width; + tempVfb.bufferHeight = vfb->height; + tempVfb.renderWidth = w; + tempVfb.renderHeight = h; + BlitFramebuffer(&tempVfb, 0, 0, vfb, 0, 0, vfb->width, vfb->height, 0); + + fboForRead = tempFBO; + } else { + fboForRead = vfb->fbo; + } + } + + buffer.Allocate(w, h, GE_FORMAT_8888, !useBufferedRendering_, true); + + ID3D11Texture2D *packTex; + D3D11_TEXTURE2D_DESC packDesc{}; + packDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + packDesc.BindFlags = 0; + packDesc.Width = w; + packDesc.Height = h; + packDesc.ArraySize = 1; + packDesc.MipLevels = 1; + packDesc.Usage = D3D11_USAGE_STAGING; + packDesc.SampleDesc.Count = 1; + packDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + device_->CreateTexture2D(&packDesc, nullptr, &packTex); + + ID3D11Texture2D *nativeTex = (ID3D11Texture2D *)draw_->GetFramebufferAPITexture(fboForRead, Draw::FB_COLOR_BIT, 0); + context_->CopyResource(packTex, nativeTex); + + D3D11_MAPPED_SUBRESOURCE map; + context_->Map(packTex, 0, D3D11_MAP_READ, 0, &map); + + for (int y = 0; y < h; y++) { + uint8_t *dest = (uint8_t *)buffer.GetData() + y * w * 4; + const uint8_t *src = ((const uint8_t *)map.pData) + map.RowPitch * y; + memcpy(dest, src, 4 * w); + } + + context_->Unmap(packTex, 0); + packTex->Release(); + return true; } bool FramebufferManagerD3D11::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) { diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index 6ea83585cf..5cf4afe8a3 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -72,7 +72,7 @@ public: 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; - bool GetOutputFramebuffer(GPUDebugBuffer &buffer); + bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; virtual void RebindFramebuffer() override; @@ -136,6 +136,8 @@ private: ShaderManagerD3D11 *shaderManagerD3D11_; DrawEngineD3D11 *drawEngine_; + // 1:1 Readback texture, 512x512 fixed + // For larger debug readbacks, we create/destroy textures on the fly. ID3D11Texture2D *packTexture_; // Used by post-processing shader diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 46b54f6088..2a54d64d32 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -995,10 +995,6 @@ bool GPU_D3D11::GetCurrentClut(GPUDebugBuffer &buffer) { return textureCacheD3D11_->GetCurrentClutBuffer(buffer); } -bool GPU_D3D11::GetOutputFramebuffer(GPUDebugBuffer &buffer) { - return framebufferManagerD3D11_->GetOutputFramebuffer(buffer); -} - bool GPU_D3D11::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { return drawEngine_.GetCurrentSimpleVertices(count, vertices, indices); } diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 115d118793..f78d78113a 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -66,7 +66,6 @@ public: bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; bool GetCurrentClut(GPUDebugBuffer &buffer) override; - bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) override; typedef void (GPU_D3D11::*CmdFunc)(u32 op, u32 diff); diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index 35da6ac32a..80a560b361 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -74,7 +74,7 @@ public: bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes); 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; - bool GetOutputFramebuffer(GPUDebugBuffer &buffer); + bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; virtual void RebindFramebuffer() override; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 62c920c397..d839a0671c 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -1069,10 +1069,6 @@ bool GPU_DX9::GetCurrentClut(GPUDebugBuffer &buffer) { return textureCacheDX9_->GetCurrentClutBuffer(buffer); } -bool GPU_DX9::GetOutputFramebuffer(GPUDebugBuffer &buffer) { - return framebufferManagerDX9_->GetOutputFramebuffer(buffer); -} - bool GPU_DX9::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { return drawEngine_.GetCurrentSimpleVertices(count, vertices, indices); } diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index a09831d598..bc79df79db 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -67,7 +67,6 @@ public: bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; bool GetCurrentClut(GPUDebugBuffer &buffer) override; - bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) override; typedef void (GPU_DX9::*CmdFunc)(u32 op, u32 diff); diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 7675738a5e..260141d234 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -90,7 +90,7 @@ public: 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; - bool GetOutputFramebuffer(GPUDebugBuffer &buffer); + bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; virtual void RebindFramebuffer() override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 28d7192d16..fc3454ec7d 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -1271,10 +1271,6 @@ bool GPU_GLES::GetCurrentClut(GPUDebugBuffer &buffer) { return textureCacheGL_->GetCurrentClutBuffer(buffer); } -bool GPU_GLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) { - return framebufferManagerGL_->GetOutputFramebuffer(buffer); -} - bool GPU_GLES::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { return drawEngine_.GetCurrentSimpleVertices(count, vertices, indices); } diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 31132ba586..debbd688d8 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -69,7 +69,6 @@ public: bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; bool GetCurrentClut(GPUDebugBuffer &buffer) override; - bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) override; bool DescribeCodePtr(const u8 *ptr, std::string &name) override; diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index 16b6f43630..b424adccb9 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -103,7 +103,7 @@ public: 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; - static bool GetOutputFramebuffer(GPUDebugBuffer &buffer); + bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; virtual void RebindFramebuffer() override;