diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 6a0abae94c..1a273ad3d3 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -908,12 +908,83 @@ bool FramebufferManagerD3D11::GetFramebuffer(u32 fb_address, int fb_stride, GEBu return true; } +bool FramebufferManagerD3D11::GetDepthStencilBuffer(VirtualFramebuffer *vfb, GPUDebugBuffer &buffer, bool stencil) { + int w = vfb->renderWidth, h = vfb->renderHeight; + Draw::Framebuffer *fboForRead = nullptr; + fboForRead = vfb->fbo; + + buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT, !useBufferedRendering_); + + 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)draw_->GetFramebufferAPITexture(fboForRead, Draw::FB_DEPTH_BIT | Draw::FB_FORMAT_BIT, 0); + device_->CreateTexture2D(&packDesc, nullptr, &packTex); + + ID3D11Texture2D *nativeTex = (ID3D11Texture2D *)draw_->GetFramebufferAPITexture(fboForRead, Draw::FB_DEPTH_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++) { + float *dest = (float *)(buffer.GetData() + y * w * 4); + const uint32_t *src = (const uint32_t *)((const uint8_t *)map.pData + map.RowPitch * y); + for (int x = 0; x < w; x++) { + if (stencil) { + dest[x] = (src[x] >> 24) / (256.f); + } else { + dest[x] = (src[x] & 0xFFFFFF) / (256.f * 256.f * 256.f); + } + } + } + + 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) { - 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(z_address | 0x04000000), z_stride, 512, GPU_DBG_FORMAT_16BIT); + return true; + } + + if (!vfb->fbo) { + return false; + } + + return GetDepthStencilBuffer(vfb, buffer, false); } bool FramebufferManagerD3D11::GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) { - return false; + VirtualFramebuffer *vfb = currentRenderVfb_; + if (!vfb) { + vfb = GetVFBAt(fb_address); + } + + if (!vfb) { + return false; + } + + if (!vfb->fbo) { + return false; + } + + return GetDepthStencilBuffer(vfb, buffer, true); } bool FramebufferManagerD3D11::GetOutputFramebuffer(GPUDebugBuffer &buffer) { diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index 469bad59cb..fb46b0a0d3 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -103,6 +103,7 @@ private: Draw::Framebuffer *dest, float destX1, float destY1, float destX2, float destY2, Draw::Framebuffer *src, float srcX1, float srcY1, float srcX2, float srcY2, bool linearFilter); + bool GetDepthStencilBuffer(VirtualFramebuffer *vfb, GPUDebugBuffer &buffer, bool stencil); ID3D11Device *device_; ID3D11DeviceContext *context_; diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 11bfbf712d..1b910e93ea 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -1366,6 +1366,10 @@ bool FramebufferManagerGLES::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z return true; } + if (!vfb->fbo) { + return false; + } + if (gstate_c.Supports(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_FLOAT_DIV_256, !useBufferedRendering_); } else { diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index c75722dcae..e81593d5ef 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -334,7 +334,8 @@ 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 + FB_VIEW_BIT = 64, // Used in conjunction with the others in D3D11 to get shader resource views through get_api_texture + FB_FORMAT_BIT = 128, // Actually retrieves the native format instead. D3D11 only. }; enum FBBlitFilter { diff --git a/ext/native/thin3d/thin3d_d3d11.cpp b/ext/native/thin3d/thin3d_d3d11.cpp index 5189183db3..f44961f9ce 100644 --- a/ext/native/thin3d/thin3d_d3d11.cpp +++ b/ext/native/thin3d/thin3d_d3d11.cpp @@ -1064,9 +1064,11 @@ public: ID3D11Texture2D *colorTex = nullptr; ID3D11RenderTargetView *colorRTView = nullptr; ID3D11ShaderResourceView *colorSRView = nullptr; + DXGI_FORMAT colorFormat = DXGI_FORMAT_UNKNOWN; ID3D11Texture2D *depthStencilTex = nullptr; ID3D11DepthStencilView *depthStencilRTView = nullptr; + DXGI_FORMAT depthStencilFormat = DXGI_FORMAT_UNKNOWN; }; Framebuffer *D3D11DrawContext::CreateFramebuffer(const FramebufferDesc &desc) { @@ -1074,14 +1076,14 @@ Framebuffer *D3D11DrawContext::CreateFramebuffer(const FramebufferDesc &desc) { D3D11Framebuffer *fb = new D3D11Framebuffer(); fb->width = desc.width; fb->height = desc.height; - if (desc.numColorAttachments) { + fb->colorFormat = DXGI_FORMAT_R8G8B8A8_UNORM; D3D11_TEXTURE2D_DESC descColor{}; descColor.Width = desc.width; descColor.Height = desc.height; descColor.MipLevels = 1; descColor.ArraySize = 1; - descColor.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + descColor.Format = fb->colorFormat; descColor.SampleDesc.Count = 1; descColor.SampleDesc.Quality = 0; descColor.Usage = D3D11_USAGE_DEFAULT; @@ -1106,12 +1108,13 @@ Framebuffer *D3D11DrawContext::CreateFramebuffer(const FramebufferDesc &desc) { } if (desc.z_stencil) { + fb->depthStencilFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; D3D11_TEXTURE2D_DESC descDepth{}; descDepth.Width = desc.width; descDepth.Height = desc.height; descDepth.MipLevels = 1; descDepth.ArraySize = 1; - descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + descDepth.Format = fb->depthStencilFormat; descDepth.SampleDesc.Count = 1; descDepth.SampleDesc.Quality = 0; descDepth.Usage = D3D11_USAGE_DEFAULT; @@ -1240,6 +1243,9 @@ uintptr_t D3D11DrawContext::GetFramebufferAPITexture(Framebuffer *fbo, int chann 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; }