From cc155ec460b672bb82a414d1e44e5d18e9ebbe25 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 15 Jan 2022 23:24:58 -0800 Subject: [PATCH] softgpu: Avoid texture/CLUT flush unless overlap. Only need to flush here if there's some overlap in the target. --- GPU/Software/BinManager.cpp | 2 +- GPU/Software/BinManager.h | 2 +- GPU/Software/SoftGpu.cpp | 19 +++++++++++-------- GPU/Software/TransformUnit.cpp | 20 +++++++++++++++++++- GPU/Software/TransformUnit.h | 3 ++- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/GPU/Software/BinManager.cpp b/GPU/Software/BinManager.cpp index e56f2553e2..cdb07f8bc9 100644 --- a/GPU/Software/BinManager.cpp +++ b/GPU/Software/BinManager.cpp @@ -174,7 +174,7 @@ void BinManager::UpdateState() { } } -void BinManager::UpdateClut(void *src) { +void BinManager::UpdateClut(const void *src) { if (cluts_.Full()) Flush(); clutIndex_ = (int)cluts_.Push(BinClut()); diff --git a/GPU/Software/BinManager.h b/GPU/Software/BinManager.h index 138531bb81..eff0c4e6c9 100644 --- a/GPU/Software/BinManager.h +++ b/GPU/Software/BinManager.h @@ -153,7 +153,7 @@ public: ~BinManager(); void UpdateState(); - void UpdateClut(void *src); + void UpdateClut(const void *src); const Rasterizer::RasterizerState &State() { return states_[stateIndex_]; diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 2e21e9dc07..44401d8ba7 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -548,6 +548,10 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_SCISSOR1: case GE_CMD_SCISSOR2: + for (int i = 0; i < 8; ++i) { + // TODO: Narrow down the risk range, for now assuming 512x512 max texture. + drawEngine_->transformUnit.FlushIfOverlap(gstate.getTextureAddress(i), 4 * 512 * 512); + } break; case GE_CMD_MINZ: @@ -576,8 +580,8 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_TEXADDR5: case GE_CMD_TEXADDR6: case GE_CMD_TEXADDR7: - // TODO: Try not flushing here, unless overlap with framebuf/depthbuf? - drawEngine_->transformUnit.Flush(); + // TODO: Narrow down the risk range, for now assuming 512x512 max texture. + drawEngine_->transformUnit.FlushIfOverlap(gstate.getTextureAddress(cmd - GE_CMD_TEXADDR0), 4 * 512 * 512); break; case GE_CMD_TEXBUFWIDTH0: @@ -588,8 +592,8 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_TEXBUFWIDTH5: case GE_CMD_TEXBUFWIDTH6: case GE_CMD_TEXBUFWIDTH7: - // TODO: Try not flushing here, unless overlap with framebuf/depthbuf? - drawEngine_->transformUnit.Flush(); + // TODO: Narrow down the risk range, for now assuming 512x512 max texture. + drawEngine_->transformUnit.FlushIfOverlap(gstate.getTextureAddress(cmd - GE_CMD_TEXBUFWIDTH0), 4 * 512 * 512); break; case GE_CMD_CLUTADDR: @@ -598,13 +602,12 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_LOADCLUT: { - // Might be copying drawing into the CLUT, so flush. - // TODO: It seems worth copying the CLUT to state... - drawEngine_->transformUnit.Flush(); - u32 clutAddr = gstate.getClutAddress(); u32 clutTotalBytes = gstate.getClutLoadBytes(); + // Might be copying drawing into the CLUT, so flush. + drawEngine_->transformUnit.FlushIfOverlap(clutAddr, clutTotalBytes); + if (Memory::IsValidAddress(clutAddr)) { u32 validSize = Memory::ValidSize(clutAddr, clutTotalBytes); Memory::MemcpyUnchecked(clut, clutAddr, validSize); diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 5d2a9a527a..c628a3c853 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -613,7 +613,25 @@ void TransformUnit::Flush() { GPUDebug::NotifyDraw(); } -void TransformUnit::NotifyClutUpdate(void *src) { +void TransformUnit::FlushIfOverlap(uint32_t addr, uint32_t sz) { + if (!Memory::IsVRAMAddress(addr)) + return; + addr &= 0x0FFFFFFF; + + uint32_t targetHeight = gstate.getScissorY2() + 1; + uint32_t target = gstate.getFrameBufAddress() & 0x0FFFFFFF; + uint32_t targetStride = gstate.FrameBufStride() * (gstate.FrameBufFormat() == GE_FORMAT_8888 ? 4 : 2); + uint32_t ztarget = gstate.getDepthBufAddress() & 0x0FFFFFFF; + uint32_t ztargetStride = gstate.DepthBufStride() * 2; + + // TODO: Skip if the texture is between width and stride? + if (addr < target + targetHeight * targetStride && addr + sz >= target) + Flush(); + else if (addr < ztarget + targetHeight * ztargetStride && addr + sz >= ztarget) + Flush(); +} + +void TransformUnit::NotifyClutUpdate(const void *src) { binner_->UpdateClut(src); } diff --git a/GPU/Software/TransformUnit.h b/GPU/Software/TransformUnit.h index 8f8fcd72b2..fe8f757d9a 100644 --- a/GPU/Software/TransformUnit.h +++ b/GPU/Software/TransformUnit.h @@ -120,7 +120,8 @@ public: bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices); void Flush(); - void NotifyClutUpdate(void *src); + void FlushIfOverlap(uint32_t addr, uint32_t sz); + void NotifyClutUpdate(const void *src); private: VertexData ReadVertex(VertexReader &vreader, bool &outside_range_flag);