Pool.cs 3.5 KB

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