[GPU] performance: negative interval filter

This commit is contained in:
ParantezTech 2026-09-28 04:37:46 +03:00
parent 4799a1f82f
commit b4c065a0b0
3 changed files with 37 additions and 2 deletions

View File

@ -363,7 +363,7 @@ public sealed partial class GuestImageCache
bool IGuestImageStore.MarkCpuWrite(ulong address, ulong size)
{
GpuMemoryAccessProfile.CountImageCpuWrite();
if (!IsValidRange(address, size))
if (!IsValidRange(address, size) || !_pageOwners.MayHaveOwners(address, size))
{
return false;
}

View File

@ -107,6 +107,7 @@ public sealed class ImagePageOwnerTable
public const ulong AddressSpaceSize = 1UL << AddressSpaceBits;
private readonly PageOwnerList?[]?[] _firstLevel = new PageOwnerList?[]?[1 << FirstLevelBits];
private readonly long[] _everOwnedPages = new long[PageCount / 64];
public int AllocatedBucketCount { get; private set; }
@ -129,7 +130,28 @@ public sealed class ImagePageOwnerTable
AllocatedBucketCount++;
}
return bucket[page & (BucketEntries - 1)] ??= new PageOwnerList();
var owners = bucket[page & (BucketEntries - 1)] ??= new PageOwnerList();
Interlocked.Or(ref _everOwnedPages[page / 64], 1L << (int)(page % 64));
return owners;
}
// Bits are never cleared: a false result can safely bypass the image-cache lock.
public bool MayHaveOwners(ulong address, ulong size)
{
if (!TryGetPageRange(address, size, out var first, out var lastExclusive))
{
return false;
}
for (var page = first; page < lastExclusive; page++)
{
if ((Volatile.Read(ref _everOwnedPages[page / 64]) & (1L << (int)(page % 64))) != 0)
{
return true;
}
}
return false;
}
// The half-open page interval of a non-empty byte range inside the address space.

View File

@ -11,6 +11,19 @@ namespace SharpEmu.Libs.Tests.Gpu.Images;
[Collection(SchedulingStateCollection.Name)]
public sealed class ImagePageOwnerTableTests
{
[Fact]
public void OwnerSummaryRejectsOnlyPagesThatNeverHadAnOwner()
{
var table = new ImagePageOwnerTable();
var page = ImagePageOwnerTable.BucketEntries;
var address = (ulong)page << ImagePageOwnerTable.PageBits;
Assert.False(table.MayHaveOwners(address, 4));
table.GetOrCreate((ulong)page).Add(Owner(1));
Assert.True(table.MayHaveOwners(address, 4));
Assert.True(table.MayHaveOwners(address - 4, 8));
Assert.False(table.MayHaveOwners(address - 4, 4));
}
private static ResourceSlotIdentifier Owner(uint index) => new(index, 1);
[Fact]