Merge pull request #22479 from hrydgard/record-dirty-blocks

GE dump recording: Track every VRAM block a range touches
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2026-10-09 18:54:23 +02:00
commit 8218e0b210
2 files changed
+33 -8

No files matched your search

+11 -4
View File
@@ -898,6 +898,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
};
GLRect2D scissorRc = { -1, -1, -1, -1 };
// GL_DEPTH_STENCIL_TEXTURE_MODE needs GL 4.3 or GLES 3.1. Without it a depth-stencil texture samples depth,
// and setting the mode is an error (Apple's GL 4.1).
const bool stencilTexturing = gl_extensions.ARB_stencil_texturing || (gl_extensions.IsGLES && gl_extensions.VersionGEThan(3, 1));
CHECK_GL_ERROR_IF_DEBUG();
auto &commands = step.commands;
@@ -1219,15 +1222,19 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->z_stencil_texture.texture);
curTex[slot] = &c.bind_fb_texture.framebuffer->z_stencil_texture;
}
// This should be uncommon, so always set the mode.
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);
// This should be uncommon, so always set the mode (where it exists).
if (stencilTexturing) {
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);
}
} else if (c.bind_fb_texture.aspect == GL_STENCIL_BUFFER_BIT) {
if (curTex[slot] != &c.bind_fb_texture.framebuffer->z_stencil_texture) {
glBindTexture(GL_TEXTURE_2D, c.bind_fb_texture.framebuffer->z_stencil_texture.texture);
curTex[slot] = &c.bind_fb_texture.framebuffer->z_stencil_texture;
}
// This should be uncommon, so always set the mode.
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
// This should be uncommon, so always set the mode (where it exists).
if (stencilTexturing) {
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
}
} else {
curTex[slot] = nullptr;
}
+22 -4
View File
@@ -102,8 +102,25 @@ void Recorder::DirtyAllVRAM(DirtyVRAMFlag flag) {
}
void Recorder::DirtyVRAM(u32 start, u32 sz, DirtyVRAMFlag flag) {
u32 count = (sz + DIRTY_VRAM_ROUND) >> DIRTY_VRAM_SHIFT;
if (sz == 0)
return;
// Every block the range touches, also when it starts partway into one. Only CLEAN (the dump has the data)
// leaves out partly covered blocks at the ends, since the rest of those isn't in the dump.
u32 first = (start >> DIRTY_VRAM_SHIFT) & DIRTY_VRAM_MASK;
u32 count = ((start & DIRTY_VRAM_ROUND) + sz + DIRTY_VRAM_ROUND) >> DIRTY_VRAM_SHIFT;
if (flag == DirtyVRAMFlag::CLEAN) {
if ((start & DIRTY_VRAM_ROUND) != 0) {
first++;
count--;
}
if (count > 0 && ((start + sz) & DIRTY_VRAM_ROUND) != 0)
count--;
// Past the end of VRAM, only what's inside is in the dump.
if (first + count > DIRTY_VRAM_SIZE)
count = first < DIRTY_VRAM_SIZE ? DIRTY_VRAM_SIZE - first : 0;
if (count == 0)
return;
}
if (first + count > DIRTY_VRAM_SIZE) {
DirtyAllVRAM(flag);
return;
@@ -365,7 +382,8 @@ u32 Recorder::GetTargetFlags(u32 addr, u32 sizeInRAM) {
bool isDirtyVRAM = false;
bool isDrawnVRAM = false;
uint32_t start = (addr >> DIRTY_VRAM_SHIFT) & DIRTY_VRAM_MASK;
uint32_t blocks = (sizeInRAM + DIRTY_VRAM_ROUND) >> DIRTY_VRAM_SHIFT;
// Every block the range touches, also when it starts partway into one.
uint32_t blocks = sizeInRAM == 0 ? 0 : ((addr & DIRTY_VRAM_ROUND) + sizeInRAM + DIRTY_VRAM_ROUND) >> DIRTY_VRAM_SHIFT;
if (start + blocks >= DIRTY_VRAM_SIZE)
return 0;
bool startEven = (addr & DIRTY_VRAM_ROUND) == 0;
@@ -376,9 +394,9 @@ u32 Recorder::GetTargetFlags(u32 addr, u32 sizeInRAM) {
isDirtyVRAM = isDirtyVRAM || flag != DirtyVRAMFlag::CLEAN;
isDrawnVRAM = isDrawnVRAM || flag == DirtyVRAMFlag::DRAWN;
// Mark the VRAM clean now that it's been copied to VRAM.
// Mark the VRAM clean now that it's been copied to the dump, except partly covered blocks at the ends.
if (flag == DirtyVRAMFlag::UNKNOWN || flag == DirtyVRAMFlag::DIRTY) {
if ((i > 0 || startEven) && (i < blocks || endEven))
if ((i > 0 || startEven) && (i + 1 < blocks || endEven))
dirtyVRAM[start + i] = DirtyVRAMFlag::CLEAN;
}
}