NvGpuVmmCache.cs 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. using ARMeilleure.Memory;
  2. using System.Collections.Concurrent;
  3. namespace Ryujinx.Graphics.Memory
  4. {
  5. class NvGpuVmmCache
  6. {
  7. private const int PageBits = MemoryManager.PageBits;
  8. private const long PageSize = MemoryManager.PageSize;
  9. private const long PageMask = MemoryManager.PageMask;
  10. private ConcurrentDictionary<long, int>[] _cachedPages;
  11. private MemoryManager _memory;
  12. public NvGpuVmmCache(MemoryManager memory)
  13. {
  14. _memory = memory;
  15. _cachedPages = new ConcurrentDictionary<long, int>[1 << 20];
  16. }
  17. public bool IsRegionModified(long position, long size, NvGpuBufferType bufferType)
  18. {
  19. long va = position;
  20. long pa = _memory.GetPhysicalAddress(va);
  21. long endAddr = (va + size + PageMask) & ~PageMask;
  22. long addrTruncated = va & ~PageMask;
  23. bool modified = _memory.IsRegionModified(addrTruncated, endAddr - addrTruncated);
  24. int newBuffMask = 1 << (int)bufferType;
  25. long cachedPagesCount = 0;
  26. while (va < endAddr)
  27. {
  28. long page = _memory.GetPhysicalAddress(va) >> PageBits;
  29. ConcurrentDictionary<long, int> dictionary = _cachedPages[page];
  30. if (dictionary == null)
  31. {
  32. dictionary = new ConcurrentDictionary<long, int>();
  33. _cachedPages[page] = dictionary;
  34. }
  35. else if (modified)
  36. {
  37. _cachedPages[page].Clear();
  38. }
  39. if (dictionary.TryGetValue(pa, out int currBuffMask))
  40. {
  41. if ((currBuffMask & newBuffMask) != 0)
  42. {
  43. cachedPagesCount++;
  44. }
  45. else
  46. {
  47. dictionary[pa] |= newBuffMask;
  48. }
  49. }
  50. else
  51. {
  52. dictionary[pa] = newBuffMask;
  53. }
  54. va += PageSize;
  55. }
  56. return cachedPagesCount != (endAddr - addrTruncated) >> PageBits;
  57. }
  58. }
  59. }