NvGpuVmmCache.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using ChocolArm64.Memory;
  2. using System;
  3. namespace Ryujinx.Graphics.Memory
  4. {
  5. class NvGpuVmmCache
  6. {
  7. private struct CachedResource
  8. {
  9. public long Key;
  10. public int Mask;
  11. public CachedResource(long Key, int Mask)
  12. {
  13. this.Key = Key;
  14. this.Mask = Mask;
  15. }
  16. public override int GetHashCode()
  17. {
  18. return (int)(Key * 23 + Mask);
  19. }
  20. public override bool Equals(object obj)
  21. {
  22. return obj is CachedResource Cached && Equals(Cached);
  23. }
  24. public bool Equals(CachedResource other)
  25. {
  26. return Key == other.Key && Mask == other.Mask;
  27. }
  28. }
  29. private ValueRangeSet<CachedResource> CachedRanges;
  30. public NvGpuVmmCache()
  31. {
  32. CachedRanges = new ValueRangeSet<CachedResource>();
  33. }
  34. public bool IsRegionModified(MemoryManager Memory, NvGpuBufferType BufferType, long Start, long Size)
  35. {
  36. (bool[] Modified, long ModifiedCount) = Memory.IsRegionModified(Start, Size);
  37. //Remove all modified ranges.
  38. int Index = 0;
  39. long Position = Start & ~NvGpuVmm.PageMask;
  40. while (ModifiedCount > 0)
  41. {
  42. if (Modified[Index++])
  43. {
  44. CachedRanges.Remove(new ValueRange<CachedResource>(Position, Position + NvGpuVmm.PageSize));
  45. ModifiedCount--;
  46. }
  47. Position += NvGpuVmm.PageSize;
  48. }
  49. //Mask has the bit set for the current resource type.
  50. //If the region is not yet present on the list, then a new ValueRange
  51. //is directly added with the current resource type as the only bit set.
  52. //Otherwise, it just sets the bit for this new resource type on the current mask.
  53. //The physical address of the resource is used as key, those keys are used to keep
  54. //track of resources that are already on the cache. A resource may be inside another
  55. //resource, and in this case we should return true if the "sub-resource" was not
  56. //yet cached.
  57. int Mask = 1 << (int)BufferType;
  58. CachedResource NewCachedValue = new CachedResource(Start, Mask);
  59. ValueRange<CachedResource> NewCached = new ValueRange<CachedResource>(Start, Start + Size);
  60. ValueRange<CachedResource>[] Ranges = CachedRanges.GetAllIntersections(NewCached);
  61. bool IsKeyCached = Ranges.Length > 0 && Ranges[0].Value.Key == Start;
  62. long LastEnd = NewCached.Start;
  63. long Coverage = 0;
  64. for (Index = 0; Index < Ranges.Length; Index++)
  65. {
  66. ValueRange<CachedResource> Current = Ranges[Index];
  67. CachedResource Cached = Current.Value;
  68. long RgStart = Math.Max(Current.Start, NewCached.Start);
  69. long RgEnd = Math.Min(Current.End, NewCached.End);
  70. if ((Cached.Mask & Mask) != 0)
  71. {
  72. Coverage += RgEnd - RgStart;
  73. }
  74. //Highest key value has priority, this prevents larger resources
  75. //for completely invalidating smaller ones on the cache. For example,
  76. //consider that a resource in the range [100, 200) was added, and then
  77. //another one in the range [50, 200). We prevent the new resource from
  78. //completely replacing the old one by spliting it like this:
  79. //New resource key is added at [50, 100), old key is still present at [100, 200).
  80. if (Cached.Key < Start)
  81. {
  82. Cached.Key = Start;
  83. }
  84. Cached.Mask |= Mask;
  85. CachedRanges.Add(new ValueRange<CachedResource>(RgStart, RgEnd, Cached));
  86. if (RgStart > LastEnd)
  87. {
  88. CachedRanges.Add(new ValueRange<CachedResource>(LastEnd, RgStart, NewCachedValue));
  89. }
  90. LastEnd = RgEnd;
  91. }
  92. if (LastEnd < NewCached.End)
  93. {
  94. CachedRanges.Add(new ValueRange<CachedResource>(LastEnd, NewCached.End, NewCachedValue));
  95. }
  96. return !IsKeyCached || Coverage != Size;
  97. }
  98. }
  99. }