Pool.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. using Ryujinx.Cpu.Tracking;
  2. using Ryujinx.Graphics.Gpu.Memory;
  3. using System;
  4. namespace Ryujinx.Graphics.Gpu.Image
  5. {
  6. /// <summary>
  7. /// Represents a pool of GPU resources, such as samplers or textures.
  8. /// </summary>
  9. /// <typeparam name="T1">Type of the GPU resource</typeparam>
  10. /// <typeparam name="T2">Type of the descriptor</typeparam>
  11. abstract class Pool<T1, T2> : IDisposable where T2 : unmanaged
  12. {
  13. protected const int DescriptorSize = 0x20;
  14. protected GpuContext Context;
  15. protected PhysicalMemory PhysicalMemory;
  16. protected T1[] Items;
  17. protected T2[] DescriptorCache;
  18. /// <summary>
  19. /// The maximum ID value of resources on the pool (inclusive).
  20. /// </summary>
  21. /// <remarks>
  22. /// The maximum amount of resources on the pool is equal to this value plus one.
  23. /// </remarks>
  24. public int MaximumId { get; }
  25. /// <summary>
  26. /// The address of the pool in guest memory.
  27. /// </summary>
  28. public ulong Address { get; }
  29. /// <summary>
  30. /// The size of the pool in bytes.
  31. /// </summary>
  32. public ulong Size { get; }
  33. private readonly CpuMultiRegionHandle _memoryTracking;
  34. private readonly Action<ulong, ulong> _modifiedDelegate;
  35. /// <summary>
  36. /// Creates a new instance of the GPU resource pool.
  37. /// </summary>
  38. /// <param name="context">GPU context that the pool belongs to</param>
  39. /// <param name="physicalMemory">Physical memory where the resource descriptors are mapped</param>
  40. /// <param name="address">Address of the pool in physical memory</param>
  41. /// <param name="maximumId">Maximum index of an item on the pool (inclusive)</param>
  42. public Pool(GpuContext context, PhysicalMemory physicalMemory, ulong address, int maximumId)
  43. {
  44. Context = context;
  45. PhysicalMemory = physicalMemory;
  46. MaximumId = maximumId;
  47. int count = maximumId + 1;
  48. ulong size = (ulong)(uint)count * DescriptorSize;
  49. Items = new T1[count];
  50. DescriptorCache = new T2[count];
  51. Address = address;
  52. Size = size;
  53. _memoryTracking = physicalMemory.BeginGranularTracking(address, size);
  54. _modifiedDelegate = RegionModified;
  55. }
  56. /// <summary>
  57. /// Gets the descriptor for a given ID.
  58. /// </summary>
  59. /// <param name="id">ID of the descriptor. This is effectively a zero-based index</param>
  60. /// <returns>The descriptor</returns>
  61. public T2 GetDescriptor(int id)
  62. {
  63. return PhysicalMemory.Read<T2>(Address + (ulong)id * DescriptorSize);
  64. }
  65. /// <summary>
  66. /// Gets the GPU resource with the given ID.
  67. /// </summary>
  68. /// <param name="id">ID of the resource. This is effectively a zero-based index</param>
  69. /// <returns>The GPU resource with the given ID</returns>
  70. public abstract T1 Get(int id);
  71. /// <summary>
  72. /// Synchronizes host memory with guest memory.
  73. /// This causes invalidation of pool entries,
  74. /// if a modification of entries by the CPU is detected.
  75. /// </summary>
  76. public void SynchronizeMemory()
  77. {
  78. _memoryTracking.QueryModified(_modifiedDelegate);
  79. }
  80. /// <summary>
  81. /// Indicate that a region of the pool was modified, and must be loaded from memory.
  82. /// </summary>
  83. /// <param name="mAddress">Start address of the modified region</param>
  84. /// <param name="mSize">Size of the modified region</param>
  85. private void RegionModified(ulong mAddress, ulong mSize)
  86. {
  87. if (mAddress < Address)
  88. {
  89. mAddress = Address;
  90. }
  91. ulong maxSize = Address + Size - mAddress;
  92. if (mSize > maxSize)
  93. {
  94. mSize = maxSize;
  95. }
  96. InvalidateRangeImpl(mAddress, mSize);
  97. }
  98. protected abstract void InvalidateRangeImpl(ulong address, ulong size);
  99. protected abstract void Delete(T1 item);
  100. /// <summary>
  101. /// Performs the disposal of all resources stored on the pool.
  102. /// It's an error to try using the pool after disposal.
  103. /// </summary>
  104. public virtual void Dispose()
  105. {
  106. if (Items != null)
  107. {
  108. for (int index = 0; index < Items.Length; index++)
  109. {
  110. Delete(Items[index]);
  111. }
  112. Items = null;
  113. }
  114. _memoryTracking.Dispose();
  115. }
  116. }
  117. }