[Gpu] Cover the whole tile plan when a buffer reads back an image

TrySynchronizeBufferFromImage sized the copy from the mip layout, but the
tile plan of a fully fitting image can extend past it; Silent Hill hit a
128x128 slice planned at the exact end of the mip chain and the tiler
aborted the process. Grow the copy to the plan's tiled end when the
buffer holds it, otherwise keep the guest bytes.
This commit is contained in:
kuba 2026-10-03 19:37:33 +02:00
parent a17aaca533
commit e65b2e8233
1 changed files with 28 additions and 0 deletions

View File

@ -703,11 +703,39 @@ public sealed unsafe partial class GuestImageCache
}
}
// The mip layout can end before the tile plan does (Silent Hill: a 128x128 slice planned at
// the exact end of the mip chain aborted the process). Cover the whole plan when the buffer
// holds it; otherwise keep the guest bytes instead of copying a partial image.
if (!plan.Depth && plan.Color.Tiled)
{
var tiledEnd = TiledEndOf(plan.Color.Tiles);
if (tiledEnd > copySize)
{
if (tiledEnd > available)
{
return false;
}
copySize = tiledEnd;
}
}
DownloadToBuffer(image, buffer, bufferOffset, copySize, plan);
image.MarkBufferHoldsGpuContents();
return true;
}
private static ulong TiledEndOf(List<TileTransfer> tiles)
{
var end = 0UL;
foreach (var tile in tiles)
{
end = Math.Max(end, tile.TiledOffset + tile.TiledSize);
}
return end;
}
// Publishes a GPU-owned image to guest memory after its tick completes; false when it cannot.
private bool TryDownloadToGuest(ResourceSlotIdentifier imageIdentifier)
{