SoftGPU: Fix block transfer and self-render overlap tracking

- The block transfer overlap check passed the stride in pixels where bytes
  are expected, so it only covered part of the rectangle.
- A selfrender/selfdepth flush in UpdateState dropped the current draw's
  pending writes and reads, so later transfers didn't wait for it.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-09-29 10:33:32 -06:00
1 parent 507bb0801b
commit d6f8615d2a
2 files changed
+15 -4

No files matched your search

+13 -2
View File
@@ -246,21 +246,32 @@ void BinManager::UpdateState() {
if (newMaxTasks > MAX_POSSIBLE_TASKS)
newMaxTasks = MAX_POSSIBLE_TASKS;
// We don't want to overlap wrong, so flush any pending.
bool flushed = false;
if (maxTasks_ != newMaxTasks) {
maxTasks_ = newMaxTasks;
Flush("selfrender");
flushed = true;
}
pendingOverlap_ = pendingOverlap_ || selfRender;
// Lastly, we have to check if we're newly writing depth we were texturing before.
// This happens in Call of Duty (depth clear after depth texture), for example.
if (!hadDepth && state.pixelID.depthWrite) {
if (!flushed && !hadDepth && state.pixelID.depthWrite) {
for (size_t i = 0; i < states_.Size(); ++i) {
if (HasTextureWrite(states_.Peek(i))) {
Flush("selfdepth");
flushed = true;
break;
}
}
}
if (flushed) {
// The flush forgot what this draw writes and reads, so record it again.
MarkPendingWrites(state);
MarkPendingReads(state);
ClearDirty(SoftDirty::BINNER_RANGE);
}
pendingOverlap_ = pendingOverlap_ || selfRender;
ClearDirty(SoftDirty::BINNER_OVERLAP);
}
}
+2 -2
View File
@@ -826,8 +826,8 @@ void SoftGPU::Execute_BlockTransferStart(u32 op, u32 diff) {
// Need to flush both source and target, so we overwrite properly.
if (Memory::IsValidRange(src, srcSize) && Memory::IsValidRange(dst, dstSize)) {
drawEngine_->transformUnit.FlushIfOverlap(this, "blockxfer", false, src, srcStride, width * bpp, height);
drawEngine_->transformUnit.FlushIfOverlap(this, "blockxfer", true, dst, dstStride, width * bpp, height);
drawEngine_->transformUnit.FlushIfOverlap(this, "blockxfer", false, src, srcStride * bpp, width * bpp, height);
drawEngine_->transformUnit.FlushIfOverlap(this, "blockxfer", true, dst, dstStride * bpp, width * bpp, height);
} else {
drawEngine_->transformUnit.Flush(this, "blockxfer_wrap");
}