From c7798715a55a401ab2887d82b5d5329f7086d7b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 17 Sep 2019 14:45:40 +0200 Subject: [PATCH] Fix issue preventing video to work correctly in Digimon. Fixes #12186 (due to BlockTransferAllowCreateFB not updating the framebuffer range speedhack). --- GPU/Common/FramebufferCommon.cpp | 22 ++++++++++++++-------- GPU/Common/FramebufferCommon.h | 4 ++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 6c900531e7..337bdd9646 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -187,7 +187,7 @@ VirtualFramebuffer *FramebufferManagerCommon::GetVFBAt(u32 addr) { return match; } -u32 FramebufferManagerCommon::FramebufferByteSize(const VirtualFramebuffer *vfb) const { +u32 FramebufferManagerCommon::ColorBufferByteSize(const VirtualFramebuffer *vfb) const { return vfb->fb_stride * vfb->height * (vfb->format == GE_FORMAT_8888 ? 4 : 2); } @@ -209,6 +209,7 @@ void FramebufferManagerCommon::SetNumExtraFBOs(int num) { } // Heuristics to figure out the size of FBO to create. +// TODO: Possibly differentiate on whether through mode is used (since in through mode, viewport is meaningless?) void FramebufferManagerCommon::EstimateDrawingSize(u32 fb_address, GEBufferFormat fb_format, int viewport_width, int viewport_height, int region_width, int region_height, int scissor_width, int scissor_height, int fb_stride, int &drawing_width, int &drawing_height) { static const int MAX_FRAMEBUF_HEIGHT = 512; @@ -440,8 +441,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame vfb->usageFlags = FB_USAGE_RENDERTARGET; SetColorUpdated(vfb, skipDrawReason); - u32 byteSize = FramebufferByteSize(vfb); - // FB heuristics always produce an address in VRAM (this is during rendering) so we don't need to poke in the 0x04000000 flag here. + u32 byteSize = ColorBufferByteSize(vfb); if (Memory::IsVRAMAddress(params.fb_address) && params.fb_address + byteSize > framebufRangeEnd_) { framebufRangeEnd_ = params.fb_address + byteSize; } @@ -857,13 +857,13 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { VirtualFramebuffer *vfb = GetVFBAt(displayFramebufPtr_); if (!vfb) { // Let's search for a framebuf within this range. Note that we also look for - // "framebuffers" sitting in RAM so we only take off the kernel and uncached bits of the address - // when comparing. + // "framebuffers" sitting in RAM (created from block transfer or similar) so we only take off the kernel + // and uncached bits of the address when comparing. const u32 addr = displayFramebufPtr_ & 0x3FFFFFFF; for (size_t i = 0; i < vfbs_.size(); ++i) { VirtualFramebuffer *v = vfbs_[i]; const u32 v_addr = v->fb_address & 0x3FFFFFFF; - const u32 v_size = FramebufferByteSize(v); + const u32 v_size = ColorBufferByteSize(v); if (addr >= v_addr && addr < v_addr + v_size) { const u32 dstBpp = v->format == GE_FORMAT_8888 ? 4 : 2; const u32 v_offsetX = ((addr - v_addr) / dstBpp) % v->fb_stride; @@ -1184,7 +1184,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, // We only remove the kernel and uncached bits when comparing. const u32 vfb_address = vfb->fb_address & 0x3FFFFFFF; - const u32 vfb_size = FramebufferByteSize(vfb); + const u32 vfb_size = ColorBufferByteSize(vfb); const u32 vfb_bpp = vfb->format == GE_FORMAT_8888 ? 4 : 2; const u32 vfb_byteStride = vfb->fb_stride * vfb_bpp; const int vfb_byteWidth = vfb->width * vfb_bpp; @@ -1290,7 +1290,7 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst for (size_t i = 0; i < vfbs_.size(); ++i) { VirtualFramebuffer *vfb = vfbs_[i]; const u32 vfb_address = vfb->fb_address & 0x3FFFFFFF; - const u32 vfb_size = FramebufferByteSize(vfb); + const u32 vfb_size = ColorBufferByteSize(vfb); const u32 vfb_bpp = vfb->format == GE_FORMAT_8888 ? 4 : 2; const u32 vfb_byteStride = vfb->fb_stride * vfb_bpp; const u32 vfb_byteWidth = vfb->width * vfb_bpp; @@ -1406,6 +1406,12 @@ VirtualFramebuffer *FramebufferManagerCommon::CreateRAMFramebuffer(uint32_t fbAd textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED); vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, (Draw::FBColorDepth)vfb->colorDepth }); vfbs_.push_back(vfb); + + size_t byteSize = ColorBufferByteSize(vfb); + if (fbAddress + byteSize > framebufRangeEnd_) { + framebufRangeEnd_ = fbAddress + byteSize; + } + return vfb; } diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index ce5e0c8aef..5fbcb05571 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -68,7 +68,7 @@ struct VirtualFramebuffer { bool firstFrameSaved; u32 fb_address; - u32 z_address; + u32 z_address; // If 0, it's a "RAM" framebuffer. int fb_stride; int z_stride; @@ -327,7 +327,7 @@ protected: void CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags); void EstimateDrawingSize(u32 fb_address, GEBufferFormat fb_format, int viewport_width, int viewport_height, int region_width, int region_height, int scissor_width, int scissor_height, int fb_stride, int &drawing_width, int &drawing_height); - u32 FramebufferByteSize(const VirtualFramebuffer *vfb) const; + u32 ColorBufferByteSize(const VirtualFramebuffer *vfb) const; void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb); void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged);