From 0e8aeaea3a70c47c922ae566f0ae9b82d61a87c1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 14 Feb 2017 12:42:35 +0100 Subject: [PATCH] D3D11: Implement basic framebuffer readback. Also make debug interfaces more consistent. --- GPU/Common/DepalettizeShaderCommon.cpp | 2 + GPU/Common/FramebufferCommon.cpp | 1 + GPU/Common/FramebufferCommon.h | 6 ++ GPU/D3D11/FramebufferManagerD3D11.cpp | 128 ++++++++++--------------- GPU/D3D11/FramebufferManagerD3D11.h | 10 +- GPU/D3D11/GPU_D3D11.cpp | 12 --- GPU/D3D11/GPU_D3D11.h | 3 - GPU/Directx9/FramebufferDX9.cpp | 26 +---- GPU/Directx9/FramebufferDX9.h | 6 +- GPU/Directx9/GPU_DX9.cpp | 12 --- GPU/Directx9/GPU_DX9.h | 3 - GPU/GLES/FramebufferManagerGLES.h | 6 +- GPU/GLES/GPU_GLES.cpp | 24 ----- GPU/GLES/GPU_GLES.h | 3 - GPU/GPUCommon.cpp | 24 +++++ GPU/GPUCommon.h | 4 + GPU/Software/SoftGpu.cpp | 3 +- GPU/Vulkan/FramebufferVulkan.cpp | 2 +- GPU/Vulkan/FramebufferVulkan.h | 6 +- ext/native/thin3d/thin3d.h | 1 + ext/native/thin3d/thin3d_d3d11.cpp | 13 ++- 21 files changed, 118 insertions(+), 177 deletions(-) diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index f4f6f93642..29f68ce078 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -26,6 +26,8 @@ #define WRITE p+=sprintf +// TODO: Add a compute shader path. Complete waste of time to set up a graphics state. + // Uses integer instructions available since OpenGL 3.0. Suitable for ES 3.0 as well. void GenerateDepalShader300(char *buffer, GEBufferFormat pixelFormat, ShaderLanguage language) { char *p = buffer; diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index a20d11828a..448637b03e 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -1325,6 +1325,7 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst } } +// 1:1 pixel sides buffers, we resize buffers to these before we read them back. VirtualFramebuffer *FramebufferManagerCommon::FindDownloadTempBuffer(VirtualFramebuffer *vfb) { // For now we'll keep these on the same struct as the ones that can get displayed // (and blatantly copy work already done above while at it). diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 205120f31f..faafae74aa 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -152,6 +152,7 @@ namespace Draw { class DrawContext; } +struct GPUDebugBuffer; class TextureCacheCommon; class ShaderManagerCommon; @@ -264,6 +265,11 @@ public: Draw::Framebuffer *GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth = Draw::FBO_8888); + // Debug features + 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; + protected: virtual void SetViewport2D(int x, int y, int w, int h) = 0; void CalculatePostShaderUniforms(int bufferWidth, int bufferHeight, int renderWidth, int renderHeight, PostShaderUniforms *uniforms); diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index fba6d212b1..64fa1dd505 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -105,6 +105,18 @@ FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) vb.Usage = D3D11_USAGE_DYNAMIC; vb.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; device_->CreateBuffer(&vb, nullptr, &quadBuffer_); + + D3D11_TEXTURE2D_DESC packDesc{}; + packDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + packDesc.BindFlags = 0; + packDesc.Width = 512; // 512x512 is the maximum size of a framebuffer on the PSP. + packDesc.Height = 512; + 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, &packTexture_); } FramebufferManagerD3D11::~FramebufferManagerD3D11() { @@ -635,7 +647,7 @@ void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 dstStride, u32 srcStride, u32 wid return; } else { for (u32 y = 0; y < height; ++y) { - ConvertBGRA8888ToRGBA8888(dst32, src32, width); + memcpy(dst32, src32, width * 4); src32 += srcStride; dst32 += dstStride; } @@ -646,21 +658,21 @@ void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 dstStride, u32 srcStride, u32 wid switch (format) { case GE_FORMAT_565: // BGR 565 for (u32 y = 0; y < height; ++y) { - ConvertBGRA8888ToRGB565(dst16, src32, width); + ConvertRGBA8888ToRGB565(dst16, src32, width); src32 += srcStride; dst16 += dstStride; } break; case GE_FORMAT_5551: // ABGR 1555 for (u32 y = 0; y < height; ++y) { - ConvertBGRA8888ToRGBA5551(dst16, src32, width); + ConvertRGBA8888ToRGBA5551(dst16, src32, width); src32 += srcStride; dst16 += dstStride; } break; case GE_FORMAT_4444: // ABGR 4444 for (u32 y = 0; y < height; ++y) { - ConvertBGRA8888ToRGBA4444(dst16, src32, width); + ConvertRGBA8888ToRGBA4444(dst16, src32, width); src32 += srcStride; dst16 += dstStride; } @@ -673,6 +685,9 @@ void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 dstStride, u32 srcStride, u32 wid } } +// This function takes an already correctly-sized framebuffer and packs it into RAM. +// Does not need to account for scaling. +// Color conversion is currently done on CPU but should be done on GPU. void FramebufferManagerD3D11::PackFramebufferD3D11_(VirtualFramebuffer *vfb, int x, int y, int w, int h) { if (!vfb->fbo) { ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferD3D11_: vfb->fbo == 0"); @@ -686,85 +701,38 @@ void FramebufferManagerD3D11::PackFramebufferD3D11_(VirtualFramebuffer *vfb, int // We always need to convert from the framebuffer native format. // Right now that's always 8888. DEBUG_LOG(HLE, "Reading framebuffer to mem, fb_address = %08x", fb_address); + ID3D11Texture2D *colorTex = (ID3D11Texture2D *)draw_->GetFramebufferAPITexture(vfb->fbo, Draw::FB_COLOR_BIT, 0); - /* - LPDIRECT3DSURFACE9 renderTarget = (LPDIRECT3DSURFACE9)draw_->GetFramebufferAPITexture(vfb->fbo, Draw::FB_COLOR_BIT | Draw::FB_SURFACE_BIT, 0); - D3DSURFACE_DESC desc; - renderTarget->GetDesc(&desc); + D3D11_BOX srcBox{ 0, 0, 0, vfb->width, vfb->height, 1 }; + context_->CopySubresourceRegion(packTexture_, 0, 0, 0, 0, colorTex, 0, &srcBox); - LPDIRECT3DSURFACE9 offscreen = GetOffscreenSurface(renderTarget, vfb); - if (offscreen) { - HRESULT hr = pD3Ddevice->GetRenderTargetData(renderTarget, offscreen); - if (SUCCEEDED(hr)) { - D3DLOCKED_RECT locked; - u32 widthFactor = vfb->renderWidth / vfb->bufferWidth; - u32 heightFactor = vfb->renderHeight / vfb->bufferHeight; - RECT rect = { (LONG)(x * widthFactor), (LONG)(y * heightFactor), (LONG)((x + w) * widthFactor), (LONG)((y + h) * heightFactor) }; - hr = offscreen->LockRect(&locked, &rect, D3DLOCK_READONLY); - if (SUCCEEDED(hr)) { - // TODO: Handle the other formats? We don't currently create them, I think. - const int dstByteOffset = (y * vfb->fb_stride + x) * dstBpp; - // Pixel size always 4 here because we always request BGRA8888. - ConvertFromRGBA8888(Memory::GetPointer(fb_address + dstByteOffset), (u8 *)locked.pBits, vfb->fb_stride, locked.Pitch / 4, w, h, vfb->format); - offscreen->UnlockRect(); - } else { - ERROR_LOG_REPORT(G3D, "Unable to lock rect from %08x: %d,%d %dx%d of %dx%d", fb_address, rect.left, rect.top, rect.right, rect.bottom, vfb->renderWidth, vfb->renderHeight); - } - } else { - ERROR_LOG_REPORT(G3D, "Unable to download render target data from %08x", fb_address); - } + // Ideally, we'd round robin between two packTexture_, and simply use the other one. Though if the game + // does a once-off copy, that won't work at all. + + // BIG GPU STALL + D3D11_MAPPED_SUBRESOURCE map; + HRESULT result = context_->Map(packTexture_, 0, D3D11_MAP_READ, 0, &map); + if (FAILED(result)) { + return; } - */ + + // TODO: Handle the other formats? We don't currently create them, I think. + const int srcByteOffset = y * map.RowPitch + x * 4; + const int dstByteOffset = (y * vfb->fb_stride + x) * dstBpp; + // Pixel size always 4 here because we always request BGRA8888. + ConvertFromRGBA8888(Memory::GetPointer(fb_address + dstByteOffset), (u8 *)map.pData, vfb->fb_stride, map.RowPitch/4, w, h, vfb->format); + context_->Unmap(packTexture_, 0); } +// 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; } - // We always read the depth buffer in 24_8 format. const u32 z_address = (0x04000000) | vfb->z_address; - - /* - DEBUG_LOG(SCEGE, "Reading depthbuffer to mem at %08x for vfb=%08x", z_address, vfb->fb_address); - - LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)draw_->GetFramebufferAPITexture(vfb->fbo, Draw::FB_DEPTH_BIT, 0); - if (tex) { - D3DSURFACE_DESC desc; - D3DLOCKED_RECT locked; - tex->GetLevelDesc(0, &desc); - RECT rect = { 0, 0, (LONG)desc.Width, (LONG)desc.Height }; - HRESULT hr = tex->LockRect(0, &locked, &rect, D3DLOCK_READONLY); - - if (SUCCEEDED(hr)) { - const int dstByteOffset = y * vfb->fb_stride * sizeof(s16); - const u32 *packed = (const u32 *)locked.pBits; - u16 *depth = (u16 *)Memory::GetPointer(z_address); - - // TODO: Optimize. - for (int yp = 0; yp < h; ++yp) { - for (int xp = 0; xp < w; ++xp) { - const int offset = (yp + y) & vfb->z_stride + x + xp; - - float scaled = FromScaledDepth((packed[offset] & 0x00FFFFFF) * (1.0f / 16777215.0f)); - if (scaled <= 0.0f) { - depth[offset] = 0; - } else if (scaled >= 65535.0f) { - depth[offset] = 65535; - } else { - depth[offset] = (int)scaled; - } - } - } - - tex->UnlockRect(0); - } else { - ERROR_LOG_REPORT(G3D, "Unable to lock rect from depth %08x: %d,%d %dx%d of %dx%d", vfb->fb_address, rect.left, rect.top, rect.right, rect.bottom, vfb->renderWidth, vfb->renderHeight); - } - } else { - ERROR_LOG_REPORT(G3D, "Unable to download render target depth from %08x", vfb->fb_address); - }*/ + // TODO } void FramebufferManagerD3D11::EndFrame() { @@ -868,18 +836,18 @@ void FramebufferManagerD3D11::Resized() { resized_ = true; } -bool FramebufferManagerD3D11::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { +bool FramebufferManagerD3D11::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) { + return false; +} + +bool FramebufferManagerD3D11::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) { + return false; +} + +bool FramebufferManagerD3D11::GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) { return false; } bool FramebufferManagerD3D11::GetOutputFramebuffer(GPUDebugBuffer &buffer) { return false; } - -bool FramebufferManagerD3D11::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - return false; -} - -bool FramebufferManagerD3D11::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - return false; -} \ No newline at end of file diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index bb91fd4165..6ea83585cf 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -69,9 +69,9 @@ public: virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes); - bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); - bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); + 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); virtual void RebindFramebuffer() override; @@ -136,6 +136,8 @@ private: ShaderManagerD3D11 *shaderManagerD3D11_; DrawEngineD3D11 *drawEngine_; + ID3D11Texture2D *packTexture_; + // Used by post-processing shader std::vector extraFBOs_; @@ -145,4 +147,4 @@ private: AsyncPBO *pixelBufObj_; //this isn't that large u8 currentPBO_; #endif -}; \ No newline at end of file +}; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 1fc5bc9b44..46b54f6088 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -981,18 +981,6 @@ void GPU_D3D11::DoState(PointerWrap &p) { } } -bool GPU_D3D11::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { - return framebufferManagerD3D11_->GetCurrentFramebuffer(buffer, type, maxRes); -} - -bool GPU_D3D11::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - return framebufferManagerD3D11_->GetCurrentDepthbuffer(buffer); -} - -bool GPU_D3D11::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - return framebufferManagerD3D11_->GetCurrentStencilbuffer(buffer); -} - bool GPU_D3D11::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { if (!gstate.isTextureMapEnabled()) { return false; diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index a618462a57..115d118793 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -64,9 +64,6 @@ public: } std::vector GetFramebufferList() override; - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes = -1) override; - bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; - bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; bool GetCurrentClut(GPUDebugBuffer &buffer) override; bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 4a2e13be47..f1934ab891 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -632,7 +632,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float void FramebufferManagerDX9::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) { if (!dst->fbo || !src->fbo || !useBufferedRendering_) { - // This can happen if they recently switched from non-buffered. + // This can happen if we recently switched from non-buffered. draw_->BindBackbufferAsRenderTarget(); return; } @@ -939,11 +939,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float resized_ = true; } - bool FramebufferManagerDX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { - u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : displayFramebufPtr_; - int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : displayStride_; - GEBufferFormat fb_format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : displayFormat_; - + bool FramebufferManagerDX9::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat fb_format, GPUDebugBuffer &buffer, int maxRes) { VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { vfb = GetVFBAt(fb_address); @@ -1026,13 +1022,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float return success; } - bool FramebufferManagerDX9::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - u32 fb_address = gstate.getFrameBufRawAddress(); - int fb_stride = gstate.FrameBufStride(); - - u32 z_address = gstate.getDepthBufRawAddress(); - int z_stride = gstate.DepthBufStride(); - + bool FramebufferManagerDX9::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) { VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { vfb = GetVFBAt(fb_address); @@ -1070,13 +1060,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float return success; } - bool FramebufferManagerDX9::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - u32 fb_address = gstate.getFrameBufRawAddress(); - int fb_stride = gstate.FrameBufStride(); - - u32 z_address = gstate.getDepthBufRawAddress(); - int z_stride = gstate.DepthBufStride(); - + bool FramebufferManagerDX9::GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) { VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { vfb = GetVFBAt(fb_address); @@ -1084,7 +1068,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float if (!vfb) { // If there's no vfb and we're drawing there, must be memory? - buffer = GPUDebugBuffer(Memory::GetPointer(z_address | 0x04000000), z_stride, 512, GPU_DBG_FORMAT_16BIT); + buffer = GPUDebugBuffer(Memory::GetPointer(vfb->z_address | 0x04000000), vfb->z_stride, 512, GPU_DBG_FORMAT_16BIT); return true; } diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index e86e0632b9..35da6ac32a 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -71,9 +71,9 @@ public: virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes); - bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); - bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); + 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); virtual void RebindFramebuffer() override; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 230ac35b42..62c920c397 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -976,18 +976,6 @@ void GPU_DX9::DoState(PointerWrap &p) { } } -bool GPU_DX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { - return framebufferManagerDX9_->GetCurrentFramebuffer(buffer, type, maxRes); -} - -bool GPU_DX9::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - return framebufferManagerDX9_->GetCurrentDepthbuffer(buffer); -} - -bool GPU_DX9::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - return framebufferManagerDX9_->GetCurrentStencilbuffer(buffer); -} - bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { if (!gstate.isTextureMapEnabled()) { return false; diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index e5f97a5389..a09831d598 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -65,9 +65,6 @@ public: } std::vector GetFramebufferList() override; - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes = -1) override; - bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; - bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; bool GetCurrentClut(GPUDebugBuffer &buffer) override; bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index b98ccd52ed..7675738a5e 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -87,9 +87,9 @@ public: bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; - 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); - bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer); + 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); virtual void RebindFramebuffer() override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index f4d5ae585d..28d7192d16 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -1230,30 +1230,6 @@ void GPU_GLES::DoState(PointerWrap &p) { } } -bool GPU_GLES::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { - u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManagerGL_->DisplayFramebufAddr(); - int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManagerGL_->DisplayFramebufStride(); - GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : framebufferManagerGL_->DisplayFramebufFormat(); - return framebufferManagerGL_->GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes); -} - -bool GPU_GLES::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - u32 fb_address = gstate.getFrameBufRawAddress(); - int fb_stride = gstate.FrameBufStride(); - - u32 z_address = gstate.getDepthBufRawAddress(); - int z_stride = gstate.DepthBufStride(); - - return framebufferManagerGL_->GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer); -} - -bool GPU_GLES::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - u32 fb_address = gstate.getFrameBufRawAddress(); - int fb_stride = gstate.FrameBufStride(); - - return framebufferManagerGL_->GetStencilbuffer(fb_address, fb_stride, buffer); -} - bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { if (!gstate.isTextureMapEnabled()) { return false; diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index a90d1c6469..31132ba586 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -67,9 +67,6 @@ public: } std::vector GetFramebufferList() override; - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) override; - bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; - bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override; bool GetCurrentClut(GPUDebugBuffer &buffer) override; bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index efdb4646f5..d75f0d70cf 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2116,3 +2116,27 @@ bool GPUCommon::PerformStencilUpload(u32 dest, int size) { void GPUCommon::PerformStencilUploadInternal(u32 dest, int size) { framebufferManager_->NotifyStencilUpload(dest, size); } + +bool GPUCommon::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { + u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManager_->DisplayFramebufAddr(); + int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManager_->DisplayFramebufStride(); + GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : framebufferManager_->DisplayFramebufFormat(); + return framebufferManager_->GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes); +} + +bool GPUCommon::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { + u32 fb_address = gstate.getFrameBufRawAddress(); + int fb_stride = gstate.FrameBufStride(); + + u32 z_address = gstate.getDepthBufRawAddress(); + int z_stride = gstate.DepthBufStride(); + + return framebufferManager_->GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer); +} + +bool GPUCommon::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { + u32 fb_address = gstate.getFrameBufRawAddress(); + int fb_stride = gstate.FrameBufStride(); + + return framebufferManager_->GetStencilbuffer(fb_address, fb_stride, buffer); +} diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 3016434030..ca8bc4dec8 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -162,6 +162,10 @@ public: // From GPUDebugInterface. bool GetCurrentDisplayList(DisplayList &list) override; + bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) override; + bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; + bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; + std::vector ActiveDisplayLists() override; void ResetListPC(int listID, u32 pc) override; void ResetListStall(int listID, u32 stall) override; diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index e4dae6d0c6..776873afc0 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -838,8 +838,7 @@ bool SoftGPU::FramebufferDirty() { return true; } -bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) -{ +bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { int x1 = gstate.getRegionX1(); int y1 = gstate.getRegionY1(); int x2 = gstate.getRegionX2() + 1; diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index b1fcff2d1c..c969553650 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -1166,7 +1166,7 @@ void FramebufferManagerVulkan::Resized() { resized_ = true; } -bool FramebufferManagerVulkan::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer) { +bool FramebufferManagerVulkan::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxStride) { // TODO: Doing this synchronously will require stalling the pipeline. Maybe better // to do it callback-style? /* diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index b674bec25d..16b6f43630 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -100,9 +100,9 @@ public: bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; - bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer); - bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer); - bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer); + 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); virtual void RebindFramebuffer() override; diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 15f04676d8..05e07547ac 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -328,6 +328,7 @@ enum FBChannel { // Implementation specific FB_SURFACE_BIT = 32, // Used in conjunction with the others in D3D9 to get surfaces through get_api_texture + FB_VIEW_BIT = 64, // Used in conjunction with the others in D3D11 to get shader resource views through get_api_texture }; enum FBBlitFilter { diff --git a/ext/native/thin3d/thin3d_d3d11.cpp b/ext/native/thin3d/thin3d_d3d11.cpp index e2a51dccd3..7047b9ecfa 100644 --- a/ext/native/thin3d/thin3d_d3d11.cpp +++ b/ext/native/thin3d/thin3d_d3d11.cpp @@ -1060,7 +1060,7 @@ Framebuffer *D3D11DrawContext::CreateFramebuffer(const FramebufferDesc &desc) { descColor.Height = desc.height; descColor.MipLevels = 1; descColor.ArraySize = 1; - descColor.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + descColor.Format = DXGI_FORMAT_R8G8B8A8_UNORM; descColor.SampleDesc.Count = 1; descColor.SampleDesc.Quality = 0; descColor.Usage = D3D11_USAGE_DEFAULT; @@ -1213,8 +1213,15 @@ void D3D11DrawContext::BindBackbufferAsRenderTarget() { } uintptr_t D3D11DrawContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) { - // D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo; - return 0; + 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; + default: + return 0; + } } void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {