diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index c4655cf02e..af924216dd 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -547,27 +547,24 @@ void FramebufferManagerCommon::SetDepthFrameBuffer(bool isClearingDepth) { return; } + // First time use of this framebuffer's depth buffer. + currentRenderVfb_->usageFlags |= FB_USAGE_RENDER_DEPTH; + // If this first draw call is anything other than a clear, "resolve" the depth buffer, // by copying from any overlapping buffers with fresher content. - if (!isClearingDepth) { + if (!isClearingDepth && useBufferedRendering_) { CopyToDepthFromOverlappingFramebuffers(currentRenderVfb_); - // Special compatibility trick for Burnout Dominator lens flares. Not sure how to best generalize this. See issue #11100 - if (PSP_CoreParameter().compat.flags().UploadDepthForCLUTTextures && (currentRenderVfb_->usageFlags & FB_USAGE_CLUT) != 0) { - // Set the flag, then upload memory contents to depth channel. + // Special compatibility trick for Burnout Dominator lens flares. See issue #11100 + if (PSP_CoreParameter().compat.flags().UploadDepthForCLUTTextures && currentRenderVfb_->z_address > 0x04110000) { // Sanity check the depth buffer pointer. - if (currentRenderVfb_->z_address != 0 && currentRenderVfb_->z_address != currentRenderVfb_->fb_address) { - if (Memory::IsValidRange(currentRenderVfb_->z_address, currentRenderVfb_->width * 2)) { - const u16 *src = (const u16 *)Memory::GetPointerUnchecked(currentRenderVfb_->z_address); - DrawPixels(currentRenderVfb_, 0, 0, (const u8 *)src, GE_FORMAT_DEPTH16, currentRenderVfb_->z_stride, currentRenderVfb_->width, currentRenderVfb_->height, RASTER_DEPTH, "Depth Upload"); - } + if (Memory::IsValidRange(currentRenderVfb_->z_address, currentRenderVfb_->width * 2)) { + const u16 *src = (const u16 *)Memory::GetPointerUnchecked(currentRenderVfb_->z_address); + DrawPixels(currentRenderVfb_, 0, 0, (const u8 *)src, GE_FORMAT_DEPTH16, currentRenderVfb_->z_stride, currentRenderVfb_->width, currentRenderVfb_->height, RASTER_DEPTH, "Depth Upload"); } } } - // First time use of this framebuffer's depth buffer. - currentRenderVfb_->usageFlags |= FB_USAGE_RENDER_DEPTH; - currentRenderVfb_->depthBindSeq = GetBindSeqCount(); } @@ -1540,7 +1537,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, if (creating) { WARN_LOG(FRAMEBUF, "Creating %s FBO at %08x/%d %dx%d (force=%d)", GeBufferFormatToString(vfb->fb_format), vfb->fb_address, vfb->fb_stride, vfb->bufferWidth, vfb->bufferHeight, (int)force); } else { - WARN_LOG(FRAMEBUF, "Resizing %s FBO at %08x/%d from %dx%d to %dx%d (force=%d)", GeBufferFormatToString(vfb->fb_format), vfb->fb_address, vfb->fb_stride, old.bufferWidth, old.bufferHeight, vfb->bufferWidth, vfb->bufferHeight, (int)force); + WARN_LOG(FRAMEBUF, "Resizing %s FBO at %08x/%d from %dx%d to %dx%d (force=%d, skipCopy=%d)", GeBufferFormatToString(vfb->fb_format), vfb->fb_address, vfb->fb_stride, old.bufferWidth, old.bufferHeight, vfb->bufferWidth, vfb->bufferHeight, (int)force, (int)skipCopy); } // During hardware rendering, we always render at full color depth even if the game wouldn't on real hardware. @@ -1578,8 +1575,10 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, if (vfb->fbo) { draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }, "ResizeFramebufFBO"); if (!skipCopy) { - BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min((u16)oldWidth, std::min(vfb->bufferWidth, vfb->width)), std::min((u16)oldHeight, std::min(vfb->height, vfb->bufferHeight)), 0, RASTER_COLOR, "Blit_ResizeFramebufFBO"); - // Depth copying is handled by deferred copies later. + BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min((u16)oldWidth, std::min(vfb->bufferWidth, vfb->width)), std::min((u16)oldHeight, std::min(vfb->height, vfb->bufferHeight)), 0, RASTER_COLOR, "BlitColor_ResizeFramebufFBO"); + } + if (vfb->usageFlags & FB_USAGE_RENDER_DEPTH) { + BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min((u16)oldWidth, std::min(vfb->bufferWidth, vfb->width)), std::min((u16)oldHeight, std::min(vfb->height, vfb->bufferHeight)), 0, RASTER_DEPTH, "BlitDepth_ResizeFramebufFBO"); } } fbosToDelete_.push_back(old.fbo); @@ -2214,8 +2213,9 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS int dstBpp = BufferFormatBytesPerPixel(dstRect.vfb->fb_format); float dstXFactor = (float)bpp / dstBpp; if (dstRect.w_bytes / bpp > dstRect.vfb->width || dstRect.h > dstRect.vfb->height) { - // The buffer isn't big enough, and we have a clear hint of size. Resize. + // The buffer isn't big enough, and we have a clear hint of size. Resize. // This happens in Valkyrie Profile when uploading video at the ending. + // Also happens to the CLUT framebuffer in the Burnout Dominator lens flare effect. See #16075 ResizeFramebufFBO(dstRect.vfb, dstRect.w_bytes / bpp, dstRect.h, false, true); // Make sure we don't flop back and forth. dstRect.vfb->newWidth = std::max(dstRect.w_bytes / bpp, (int)dstRect.vfb->width); @@ -2780,6 +2780,11 @@ void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX return; } + if (channel == RASTER_DEPTH && !draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { + // Can't do anything :( + return; + } + // Perform a little bit of clipping first. // Block transfer coords are unsigned so I don't think we need to clip on the left side.. Although there are // other uses for BlitFramebuffer. diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 3b0f662002..e47f768b35 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1208,6 +1208,8 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes) { clutRenderOffset_ = MAX_CLUT_OFFSET; const std::vector &framebuffers = framebufferManager_->Framebuffers(); + u32 bestClutAddress = 0xFFFFFFFF; + VirtualFramebuffer *chosenFramebuffer = nullptr; for (VirtualFramebuffer *framebuffer : framebuffers) { const u32 fb_address = framebuffer->fb_address & 0x3FFFFFFF; @@ -1234,7 +1236,7 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes) { WARN_LOG_N_TIMES(clutfb, 5, G3D, "Detected LoadCLUT(%d bytes) from framebuffer %08x (%s), byte offset %d", loadBytes, fb_address, GeBufferFormatToString(framebuffer->fb_format), offset); framebuffer->last_frame_clut = gpuStats.numFlips; framebuffer->usageFlags |= FB_USAGE_CLUT; - clutRenderAddress_ = framebuffer->fb_address; + bestClutAddress = framebuffer->fb_address; clutRenderOffset_ = (u32)offset; chosenFramebuffer = framebuffer; if (offset == 0) { @@ -1245,7 +1247,9 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes) { } } - if (chosenFramebuffer) { + if (chosenFramebuffer && chosenFramebuffer->fbo) { + clutRenderAddress_ = bestClutAddress; + if (!dynamicClutTemp_) { Draw::FramebufferDesc desc{}; desc.width = 512;