2018-06-08 20:15:56 -04:00
|
|
|
using ChocolArm64.Memory;
|
|
|
|
using System;
|
|
|
|
|
2018-09-08 13:51:50 -04:00
|
|
|
namespace Ryujinx.Graphics.Memory
|
2018-06-08 20:15:56 -04:00
|
|
|
{
|
|
|
|
class NvGpuVmmCache
|
|
|
|
{
|
2018-09-18 00:30:35 -04:00
|
|
|
private ValueRangeSet<int> CachedRanges;
|
2018-06-08 20:15:56 -04:00
|
|
|
|
|
|
|
public NvGpuVmmCache()
|
|
|
|
{
|
2018-09-18 00:30:35 -04:00
|
|
|
CachedRanges = new ValueRangeSet<int>();
|
2018-06-08 20:15:56 -04:00
|
|
|
}
|
|
|
|
|
2018-07-08 15:55:15 -04:00
|
|
|
public bool IsRegionModified(AMemory Memory, NvGpuBufferType BufferType, long PA, long Size)
|
2018-06-08 20:15:56 -04:00
|
|
|
{
|
2018-07-29 00:39:15 -04:00
|
|
|
(bool[] Modified, long ModifiedCount) = Memory.IsRegionModified(PA, Size);
|
2018-07-08 15:55:15 -04:00
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
//Remove all modified ranges.
|
2018-07-08 15:55:15 -04:00
|
|
|
int Index = 0;
|
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
long Position = PA & ~NvGpuVmm.PageMask;
|
2018-06-08 20:15:56 -04:00
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
while (ModifiedCount > 0)
|
|
|
|
{
|
|
|
|
if (Modified[Index++])
|
2018-06-08 20:15:56 -04:00
|
|
|
{
|
2018-09-18 00:30:35 -04:00
|
|
|
CachedRanges.Remove(new ValueRange<int>(Position, Position + NvGpuVmm.PageSize));
|
2018-06-08 20:15:56 -04:00
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
ModifiedCount--;
|
2018-06-08 20:15:56 -04:00
|
|
|
}
|
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
Position += NvGpuVmm.PageSize;
|
2018-06-08 20:15:56 -04:00
|
|
|
}
|
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
//Mask has the bit set for the current resource type.
|
|
|
|
//If the region is not yet present on the list, then a new ValueRange
|
|
|
|
//is directly added with the current resource type as the only bit set.
|
|
|
|
//Otherwise, it just sets the bit for this new resource type on the current mask.
|
|
|
|
int Mask = 1 << (int)BufferType;
|
2018-06-08 20:15:56 -04:00
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
ValueRange<int> NewCached = new ValueRange<int>(PA, PA + Size);
|
2018-07-29 00:39:15 -04:00
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
ValueRange<int>[] Ranges = CachedRanges.GetAllIntersections(NewCached);
|
2018-07-29 00:39:15 -04:00
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
long LastEnd = NewCached.Start;
|
2018-07-29 00:39:15 -04:00
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
long Coverage = 0;
|
2018-07-29 00:39:15 -04:00
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
for (Index = 0; Index < Ranges.Length; Index++)
|
2018-07-29 00:39:15 -04:00
|
|
|
{
|
2018-09-18 00:30:35 -04:00
|
|
|
ValueRange<int> Current = Ranges[Index];
|
2018-07-29 00:39:15 -04:00
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
long RgStart = Math.Max(Current.Start, NewCached.Start);
|
|
|
|
long RgEnd = Math.Min(Current.End, NewCached.End);
|
2018-07-29 00:39:15 -04:00
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
if ((Current.Value & Mask) == 0)
|
2018-07-29 00:39:15 -04:00
|
|
|
{
|
2018-09-18 00:30:35 -04:00
|
|
|
CachedRanges.Add(new ValueRange<int>(RgStart, RgEnd, Current.Value | Mask));
|
2018-07-29 00:39:15 -04:00
|
|
|
}
|
2018-09-18 00:30:35 -04:00
|
|
|
else
|
2018-07-29 00:39:15 -04:00
|
|
|
{
|
2018-09-18 00:30:35 -04:00
|
|
|
Coverage += RgEnd - RgStart;
|
2018-07-29 00:39:15 -04:00
|
|
|
}
|
2018-06-08 20:15:56 -04:00
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
if (RgStart > LastEnd)
|
2018-06-08 20:15:56 -04:00
|
|
|
{
|
2018-09-18 00:30:35 -04:00
|
|
|
CachedRanges.Add(new ValueRange<int>(LastEnd, RgStart, Mask));
|
2018-06-08 20:15:56 -04:00
|
|
|
}
|
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
LastEnd = RgEnd;
|
2018-06-08 20:15:56 -04:00
|
|
|
}
|
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
if (LastEnd < NewCached.End)
|
2018-06-08 20:15:56 -04:00
|
|
|
{
|
2018-09-18 00:30:35 -04:00
|
|
|
CachedRanges.Add(new ValueRange<int>(LastEnd, NewCached.End, Mask));
|
2018-06-08 20:15:56 -04:00
|
|
|
}
|
|
|
|
|
2018-09-18 00:30:35 -04:00
|
|
|
return Coverage != Size;
|
2018-06-08 20:15:56 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|