Ignore extreme Y offsets when matching framebuffers.

Fixes #15828
This commit is contained in:
Henrik Rydgård
2026-02-12 11:03:46 +01:00
parent 03a55cb395
commit 8ceffa08cb
4 changed files with 24 additions and 8 deletions
+5 -3
View File
@@ -508,6 +508,9 @@ public:
return displayLayoutConfigCopy_;
}
// For the debugger.
inline int PeekBindSeqCount() const { return fbBindSeqCount_; }
protected:
virtual void ReadbackFramebuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode);
// Used for when a shader is required, such as GLES.
@@ -565,9 +568,8 @@ protected:
dstBuffer->reallyDirtyAfterDisplay = true;
}
inline int GetBindSeqCount() {
return fbBindSeqCount_++;
}
// For use when binding.
inline int GetBindSeqCount() { return fbBindSeqCount_++; }
static SkipGPUReadbackMode GetSkipGPUReadbackMode();
+7 -3
View File
@@ -1090,6 +1090,10 @@ bool TextureCacheCommon::MatchFramebuffer(
matchInfo->xOffset = entry.bufw == 0 ? 0 : -(-texelOffset % (int)entry.bufw);
}
if (matchInfo->yOffset >= 512) {
// Reject unreasonably large y offsets. 512 is the largest texture size.
return false;
}
if (matchInfo->yOffset > 0 && matchInfo->yOffset + minSubareaHeight >= framebuffer->height) {
// Can't be inside the framebuffer.
return false;
@@ -1121,14 +1125,14 @@ bool TextureCacheCommon::MatchFramebuffer(
// Check for CLUT. The framebuffer is always RGB, but it can be interpreted as a CLUT texture.
// 3rd Birthday (and a bunch of other games) render to a 16 bit clut texture.
if (matchingClutFormat) {
if (!noOffset) {
WARN_LOG_ONCE(subareaClut, Log::G3D, "Matching framebuffer (%s) using %s with offset at %08x +%dx%d", RasterChannelToString(channel), GeTextureFormatToString(entry.format), fb_address, matchInfo->xOffset, matchInfo->yOffset);
}
if (channel == RasterChannel::RASTER_DEPTH && framebuffer->last_frame_depth_updated < 0) {
// Reject depth textures that have not been rendered to. See #15828
// We're right before the final check here, so we can bail.
return false;
} else {
if (!noOffset) {
WARN_LOG_ONCE(subareaClut, Log::G3D, "Matching framebuffer (%s) using %s with offset at %08x +%dx%d", RasterChannelToString(channel), GeTextureFormatToString(entry.format), fb_address, matchInfo->xOffset, matchInfo->yOffset);
}
return true;
}
} else if (IsClutFormat((GETextureFormat)(entry.format)) || IsDXTFormat((GETextureFormat)(entry.format))) {
-1
View File
@@ -17,7 +17,6 @@
#include <algorithm>
#include "Common/GPU/Vulkan/VulkanLoader.h"
#include "Common/GPU/Vulkan/VulkanRenderManager.h"
#include "GPU/GPUState.h"
+12 -1
View File
@@ -33,11 +33,16 @@ void DrawFramebuffersWindow(ImConfig &cfg, FramebufferManagerCommon *framebuffer
return;
}
ImGui::BeginTable("framebuffers", 4);
ImGui::Text("Cur frame: %d seq: %d", gpuStats.numFlips, framebufferManager->PeekBindSeqCount());
ImGui::BeginTable("framebuffers", 7);
ImGui::TableSetupColumn("Tag", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Color Addr", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Depth Addr", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("BindSeq", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("LastRender", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("LastUse", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableHeadersRow();
@@ -69,6 +74,12 @@ void DrawFramebuffersWindow(ImConfig &cfg, FramebufferManagerCommon *framebuffer
ImGui::Text("Framebuffer: %s", tag);
ImGui::EndPopup();
}
ImGui::TableNextColumn();
ImGui::Text("%d/%d", vfb->colorBindSeq, vfb->depthBindSeq);
ImGui::TableNextColumn();
ImGui::Text("%d/%d", vfb->last_frame_render, vfb->last_frame_depth_updated);
ImGui::TableNextColumn();
ImGui::Text("%d/%d", vfb->last_frame_used, vfb->last_frame_depth_render);
ImGui::PopID();
}
ImGui::EndTable();