Merge pull request #16081 from hrydgard/zbuffer-upload-heuristic

Fix green flashes with Burnout Dominator lens flare
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2022-09-22 11:02:27 +02:00
commit c108db0e71
2 files changed
+27 -18

No files matched your search

+21 -16
View File
@@ -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.
+6 -2
View File
@@ -1208,6 +1208,8 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes) {
clutRenderOffset_ = MAX_CLUT_OFFSET;
const std::vector<VirtualFramebuffer *> &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;