diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index ac8cd42e35..72bbb9f632 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -1872,7 +1872,15 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB } } - buffer.Allocate(w, h, GE_FORMAT_8888, !useBufferedRendering_, true); + if (!useBufferedRendering_) { + // Safety check. + w = std::min(w, PSP_CoreParameter().pixelWidth); + h = std::min(h, PSP_CoreParameter().pixelHeight); + } + + // TODO: Maybe should handle flipY inside CopyFramebufferToMemorySync somehow? + bool flipY = (g_Config.iGPUBackend == GPU_BACKEND_OPENGL && !useBufferedRendering_) ? true : false; + buffer.Allocate(w, h, GE_FORMAT_8888, flipY, true); bool retval = draw_->CopyFramebufferToMemorySync(bound, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w); // We may have blitted to a temp FBO. RebindFramebuffer(); @@ -1891,16 +1899,21 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 return true; } - if (!vfb->fbo) { - return false; + int w = vfb->renderWidth; + int h = vfb->renderHeight; + if (!useBufferedRendering_) { + // Safety check. + w = std::min(w, PSP_CoreParameter().pixelWidth); + h = std::min(h, PSP_CoreParameter().pixelHeight); } + bool flipY = (g_Config.iGPUBackend == GPU_BACKEND_OPENGL && !useBufferedRendering_) ? true : 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_); + buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT_DIV_256, flipY); } else { - buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_FLOAT, !useBufferedRendering_); + buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT, flipY); } - draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, vfb->renderWidth, vfb->renderHeight, Draw::DataFormat::D32F, buffer.GetData(), vfb->renderWidth); + draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w); return true; } @@ -1917,13 +1930,22 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G return true; } -#ifndef USING_GLES2 - buffer.Allocate(vfb->renderWidth, vfb->renderHeight, GPU_DBG_FORMAT_8BIT, !useBufferedRendering_); - draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_STENCIL_BIT, 0, 0, vfb->renderWidth, vfb->renderHeight, Draw::DataFormat::S8, buffer.GetData(), vfb->renderWidth); - return true; -#else - return false; -#endif + int w = vfb->renderWidth; + int h = vfb->renderHeight; + if (!useBufferedRendering_) { + // Safety check. + w = std::min(w, PSP_CoreParameter().pixelWidth); + h = std::min(h, PSP_CoreParameter().pixelHeight); + } + + bool flipY = (g_Config.iGPUBackend == GPU_BACKEND_OPENGL && !useBufferedRendering_) ? true : false; + buffer.Allocate(w, h, GPU_DBG_FORMAT_8BIT, flipY); + if (draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_STENCIL_BIT, 0, 0, w,h, Draw::DataFormat::S8, buffer.GetData(), w)) { + return true; + } else { + buffer.Free(); + return false; + } } bool FramebufferManagerCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) { diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index c14705bdc9..81f67a244d 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -391,7 +391,7 @@ void FramebufferManagerVulkan::RebindFramebuffer() { bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, bool skipZero) { // In Vulkan we should be able to simply copy the stencil data directly to a stencil buffer without - // messing about with bitplane textures and the like. + // messing about with bitplane textures and the like. Or actually, maybe not... return false; } diff --git a/ext/native/thin3d/thin3d_d3d11.cpp b/ext/native/thin3d/thin3d_d3d11.cpp index ecd7752cc8..45db38b91a 100644 --- a/ext/native/thin3d/thin3d_d3d11.cpp +++ b/ext/native/thin3d/thin3d_d3d11.cpp @@ -1385,7 +1385,10 @@ bool D3D11DrawContext::CopyFramebufferToMemorySync(Framebuffer *src, int channel break; case FB_DEPTH_BIT: case FB_STENCIL_BIT: - assert(fb); + if (!fb) { + // Not supported. + return false; + } packDesc.Format = fb->depthStencilFormat; break; default: @@ -1393,6 +1396,14 @@ bool D3D11DrawContext::CopyFramebufferToMemorySync(Framebuffer *src, int channel } device_->CreateTexture2D(&packDesc, nullptr, &packTex); } else { + switch (channelBits) { + case FB_DEPTH_BIT: + case FB_STENCIL_BIT: + if (!fb) + return false; + default: + break; + } packTex = packTexture_; } @@ -1404,7 +1415,7 @@ bool D3D11DrawContext::CopyFramebufferToMemorySync(Framebuffer *src, int channel case FB_DEPTH_BIT: case FB_STENCIL_BIT: // For depth/stencil buffers, we can't reliably copy subrectangles, so just copy the whole resource. - assert(fb); // We haven't got a texture for the backbuffer depth. Could make one but I don't think we need one. + assert(fb); // Can't copy depth/stencil from backbuffer. Shouldn't happen thanks to checks above. context_->CopyResource(packTex, fb->depthStencilTex); break; default: