From c3c5450b8f6186cea12dd76b0c80202d358d67ad Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 23 Sep 2022 21:18:39 -0700 Subject: [PATCH 1/2] GE Debugger: Fix small tex/clut recopying. If it's less than 256 bytes, we can't mark the entire VRAM area copied. This still helps frame dumps avoid excessively slow VRAM recopying situations, but fixes issues like missing trees in #12738. --- GPU/Debugger/Playback.cpp | 4 +--- GPU/Debugger/Record.cpp | 11 ++++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/GPU/Debugger/Playback.cpp b/GPU/Debugger/Playback.cpp index c47eba66b37e..ff35966ef9bc 100644 --- a/GPU/Debugger/Playback.cpp +++ b/GPU/Debugger/Playback.cpp @@ -489,11 +489,9 @@ void DumpExecute::Clut(u32 ptr, u32 sz) { // This is always run when we have the actual address set. if (execClutAddr != 0) { const bool isTarget = (execClutFlags & 1) != 0; - const bool unchangedVRAM = (execClutFlags & 2) != 0; - // TODO: Could use drawnVRAM flag, but it can be wrong. // Could potentially always skip if !isTarget, but playing it safe for offset texture behavior. - if (Memory::IsValidRange(execClutAddr, sz) && !unchangedVRAM && (!isTarget || !g_Config.bSoftwareRendering)) { + if (Memory::IsValidRange(execClutAddr, sz) && (!isTarget || !g_Config.bSoftwareRendering)) { // Intentionally don't trigger an upload here. Memory::MemcpyUnchecked(execClutAddr, pushbuf_.data() + ptr, sz); } diff --git a/GPU/Debugger/Record.cpp b/GPU/Debugger/Record.cpp index 248ba1e48c08..cc73992c1be3 100644 --- a/GPU/Debugger/Record.cpp +++ b/GPU/Debugger/Record.cpp @@ -326,14 +326,19 @@ static u32 GetTargetFlags(u32 addr, u32 sizeInRAM) { bool isDirtyVRAM = false; bool isDrawnVRAM = false; uint32_t start = (addr >> DIRTY_VRAM_SHIFT) & DIRTY_VRAM_MASK; - for (uint32_t i = 0; i < (sizeInRAM + DIRTY_VRAM_ROUND) >> DIRTY_VRAM_SHIFT; ++i) { + uint32_t blocks = (sizeInRAM + DIRTY_VRAM_ROUND) >> DIRTY_VRAM_SHIFT; + bool startEven = (addr & DIRTY_VRAM_ROUND) == 0; + bool endEven = ((addr + sizeInRAM) & DIRTY_VRAM_ROUND) == 0; + for (uint32_t i = 0; i < blocks; ++i) { DirtyVRAMFlag flag = dirtyVRAM[start + i]; isDirtyVRAM = isDirtyVRAM || flag != DirtyVRAMFlag::CLEAN; isDrawnVRAM = isDrawnVRAM || flag == DirtyVRAMFlag::DRAWN; // Mark the VRAM clean now that it's been copied to VRAM. - if (flag == DirtyVRAMFlag::DIRTY) - dirtyVRAM[start + i] = DirtyVRAMFlag::CLEAN; + if (flag == DirtyVRAMFlag::DIRTY) { + if ((i > 0 || startEven) && (i < blocks || endEven)) + dirtyVRAM[start + i] = DirtyVRAMFlag::CLEAN; + } } // The isTarget flag is mostly used for replay of dumps on a PSP. From 7ff54349687ba449a7cda9cc2ded3778783717a8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 23 Sep 2022 21:20:14 -0700 Subject: [PATCH 2/2] GE Debugger: Tag frame dump replay VRAM writes. Just for debugging, it's helpful especially paired with softgpu tagging. --- GPU/Debugger/Playback.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GPU/Debugger/Playback.cpp b/GPU/Debugger/Playback.cpp index ff35966ef9bc..da55c9238df6 100644 --- a/GPU/Debugger/Playback.cpp +++ b/GPU/Debugger/Playback.cpp @@ -28,6 +28,7 @@ #include "Core/Config.h" #include "Core/Core.h" #include "Core/CoreTiming.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/ELF/ParamSFO.h" #include "Core/FileSystems/MetaFileSystem.h" #include "Core/HLE/sceDisplay.h" @@ -494,6 +495,7 @@ void DumpExecute::Clut(u32 ptr, u32 sz) { if (Memory::IsValidRange(execClutAddr, sz) && (!isTarget || !g_Config.bSoftwareRendering)) { // Intentionally don't trigger an upload here. Memory::MemcpyUnchecked(execClutAddr, pushbuf_.data() + ptr, sz); + NotifyMemInfo(MemBlockFlags::WRITE, execClutAddr, sz, "ReplayClut"); } execClutAddr = 0; @@ -548,6 +550,7 @@ void DumpExecute::Memcpy(u32 ptr, u32 sz) { if (Memory::IsVRAMAddress(execMemcpyDest)) { SyncStall(); Memory::MemcpyUnchecked(execMemcpyDest, pushbuf_.data() + ptr, sz); + NotifyMemInfo(MemBlockFlags::WRITE, execMemcpyDest, sz, "ReplayMemcpy"); gpu->PerformMemoryUpload(execMemcpyDest, sz); } } @@ -598,6 +601,7 @@ void DumpExecute::Framebuf(int level, u32 ptr, u32 sz) { if (Memory::IsValidRange(framebuf->addr, pspSize) && !unchangedVRAM && (!isTarget || !g_Config.bSoftwareRendering)) { // Intentionally don't trigger an upload here. Memory::MemcpyUnchecked(framebuf->addr, pushbuf_.data() + ptr + headerSize, pspSize); + NotifyMemInfo(MemBlockFlags::WRITE, framebuf->addr, pspSize, "ReplayTex"); } }