NvGpuVmmCache.cs 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. using ChocolArm64.Memory;
  2. using System;
  3. namespace Ryujinx.Graphics.Memory
  4. {
  5. class NvGpuVmmCache
  6. {
  7. private ValueRangeSet<int> CachedRanges;
  8. public NvGpuVmmCache()
  9. {
  10. CachedRanges = new ValueRangeSet<int>();
  11. }
  12. public bool IsRegionModified(AMemory Memory, NvGpuBufferType BufferType, long PA, long Size)
  13. {
  14. (bool[] Modified, long ModifiedCount) = Memory.IsRegionModified(PA, Size);
  15. //Remove all modified ranges.
  16. int Index = 0;
  17. long Position = PA & ~NvGpuVmm.PageMask;
  18. while (ModifiedCount > 0)
  19. {
  20. if (Modified[Index++])
  21. {
  22. CachedRanges.Remove(new ValueRange<int>(Position, Position + NvGpuVmm.PageSize));
  23. ModifiedCount--;
  24. }
  25. Position += NvGpuVmm.PageSize;
  26. }
  27. //Mask has the bit set for the current resource type.
  28. //If the region is not yet present on the list, then a new ValueRange
  29. //is directly added with the current resource type as the only bit set.
  30. //Otherwise, it just sets the bit for this new resource type on the current mask.
  31. int Mask = 1 << (int)BufferType;
  32. ValueRange<int> NewCached = new ValueRange<int>(PA, PA + Size);
  33. ValueRange<int>[] Ranges = CachedRanges.GetAllIntersections(NewCached);
  34. long LastEnd = NewCached.Start;
  35. long Coverage = 0;
  36. for (Index = 0; Index < Ranges.Length; Index++)
  37. {
  38. ValueRange<int> Current = Ranges[Index];
  39. long RgStart = Math.Max(Current.Start, NewCached.Start);
  40. long RgEnd = Math.Min(Current.End, NewCached.End);
  41. if ((Current.Value & Mask) == 0)
  42. {
  43. CachedRanges.Add(new ValueRange<int>(RgStart, RgEnd, Current.Value | Mask));
  44. }
  45. else
  46. {
  47. Coverage += RgEnd - RgStart;
  48. }
  49. if (RgStart > LastEnd)
  50. {
  51. CachedRanges.Add(new ValueRange<int>(LastEnd, RgStart, Mask));
  52. }
  53. LastEnd = RgEnd;
  54. }
  55. if (LastEnd < NewCached.End)
  56. {
  57. CachedRanges.Add(new ValueRange<int>(LastEnd, NewCached.End, Mask));
  58. }
  59. return Coverage != Size;
  60. }
  61. }
  62. }