mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-19 17:29:06 +02:00
MSAA: Only multisample full size framebuffers
Smaller framebuffers are mostly effects (blur, bloom), and MSAA changes how those come out, like a higher resolution would. Syphon Filter: Logan's Shadow grew a glow around its lit floor panels that the PSP doesn't have. Effects in Call of Duty: Road to Victory and Assassin's Creed: Bloodlines shifted too. A framebuffer that grows to full size gets MSAA from then on. The temporary buffer that shifts depth for offset rendering now takes the samples of the framebuffer it shifts, since they can differ. Over the frame dumps at 2x and 4x, the differences away from edges compared to no MSAA drop by a fifth and 53 dumps get closer. The one that moved away, Silent Hill: Origins' flashlight shadow, now matches the PSP; without MSAA it shows a known replay artifact there. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
2c19007b61
commit
d4cc5d8666
2 files changed
+19
-7
No files matched your search
@@ -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_);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user