diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 8a602c9f22..74d1e319ed 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1078,7 +1078,7 @@ void FramebufferManagerCommon::ShiftDepthForOffsetRendering(VirtualFramebuffer * if (w <= 0) { return; } - Draw::Framebuffer *temp = GetTempFBO(TempFBO::DEPTH_SHIFT, vfb->renderWidth, vfb->renderHeight); + Draw::Framebuffer *temp = GetTempFBO(TempFBO::DEPTH_SHIFT, vfb->renderWidth, vfb->renderHeight, vfb->fbo->MultiSampleLevel()); if (!temp) { return; } @@ -1984,6 +1984,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, } bool creating = old.bufferWidth == 0; + vfb->multisampled = ShouldMultisample(vfb); if (creating) { INFO_LOG(Log::FrameBuf, "Creating %s FBO at %08x/%08x stride=%d %dx%d (force=%d)", GeBufferFormatToString(vfb->fb_format), vfb->fb_address, vfb->z_address, vfb->fb_stride, vfb->bufferWidth, vfb->bufferHeight, (int)force); } else { @@ -2016,7 +2017,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, gpuStats.perFrame.numFBOsCreated++; - vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), msaaLevel_, true, tag }); + vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), vfb->multisampled ? msaaLevel_ : 0, true, tag }); if (Memory::IsVRAMAddress(vfb->fb_address) && vfb->fb_stride != 0) { NotifyMemInfo(MemBlockFlags::ALLOC, vfb->fb_address, vfb->BufferByteSize(RASTER_COLOR), tag, len); } @@ -3165,6 +3166,12 @@ static const char *TempFBOReasonToString(TempFBO reason) { return ""; } +// Only full size framebuffers get MSAA. Smaller ones are mostly effects (blur, bloom), and MSAA changes those +// (Syphon Filter: Logan's Shadow grows a glow around lit floor panels). +bool FramebufferManagerCommon::ShouldMultisample(const VirtualFramebuffer *vfb) const { + return vfb->bufferWidth >= 480 && vfb->bufferHeight >= 272; +} + Draw::Framebuffer *FramebufferManagerCommon::CopyColorSample0(VirtualFramebuffer *vfb) { if (!vfb->fbo || vfb->fbo->MultiSampleLevel() == 0) { return nullptr; @@ -3186,8 +3193,11 @@ Draw::Framebuffer *FramebufferManagerCommon::CopyColorSample0(VirtualFramebuffer return copy; } -Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u16 h) { - u64 key = ((u64)reason << 48) | ((u32)w << 16) | h; +Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u16 h, int msaaLevel) { + if (reason != TempFBO::DEPTH_SHIFT) { + msaaLevel = 0; + } + u64 key = ((u64)msaaLevel << 56) | ((u64)reason << 48) | ((u32)w << 16) | h; auto it = tempFBOs_.find(key); if (it != tempFBOs_.end()) { it->second.last_frame_used = gpuStats.totals.numFlips; @@ -3195,8 +3205,6 @@ Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u } bool z_stencil = reason == TempFBO::STENCIL || reason == TempFBO::DEPTH_SHIFT; - // The depth shift copies to and from a framebuffer, which needs the same samples. - const int msaaLevel = reason == TempFBO::DEPTH_SHIFT ? msaaLevel_ : 0; char name[128]; snprintf(name, sizeof(name), "tempfbo_%s_%dx%d", TempFBOReasonToString(reason), w / renderScaleFactor_, h / renderScaleFactor_); diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index fbc9a4656a..95e2bb1e0d 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -111,6 +111,8 @@ struct VirtualFramebuffer { // The scale factor at which we are rendering (to achieve higher resolution). u8 renderScaleFactor; + // Whether it gets MSAA, if it's on. + bool multisampled; u16 usageFlags; @@ -470,7 +472,8 @@ public: virtual void DeviceLost(); virtual void DeviceRestore(Draw::DrawContext *draw); - Draw::Framebuffer *GetTempFBO(TempFBO reason, u16 w, u16 h); + // msaaLevel is only used for DEPTH_SHIFT, which needs the samples of the framebuffer it shifts. + Draw::Framebuffer *GetTempFBO(TempFBO reason, u16 w, u16 h, int msaaLevel = 0); // A single-sampled copy of the first sample of each pixel of a multisampled framebuffer, or null if it isn't // multisampled or the backend can't. For reading colors as values, which averaging the samples would corrupt. Draw::Framebuffer *CopyColorSample0(VirtualFramebuffer *vfb); @@ -551,6 +554,7 @@ protected: void CopyToDepthFromOverlappingFramebuffers(VirtualFramebuffer *dest); bool UpdateRenderSize(int msaaLevel); + bool ShouldMultisample(const VirtualFramebuffer *vfb) const; void FlushBeforeCopy(); virtual void DecimateFBOs(); // keeping it virtual to let D3D do a little extra