Pool.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. using Ryujinx.Graphics.Gpu.Memory;
  2. using System;
  3. namespace Ryujinx.Graphics.Gpu.Image
  4. {
  5. /// <summary>
  6. /// Represents a pool of GPU resources, such as samplers or textures.
  7. /// </summary>
  8. /// <typeparam name="T">Type of the GPU resource</typeparam>
  9. abstract class Pool<T> : IDisposable
  10. {
  11. protected const int DescriptorSize = 0x20;
  12. protected GpuContext Context;
  13. protected T[] Items;
  14. /// <summary>
  15. /// The maximum ID value of resources on the pool (inclusive).
  16. /// </summary>
  17. /// <remarks>
  18. /// The maximum amount of resources on the pool is equal to this value plus one.
  19. /// </remarks>
  20. public int MaximumId { get; }
  21. /// <summary>
  22. /// The address of the pool in guest memory.
  23. /// </summary>
  24. public ulong Address { get; }
  25. /// <summary>
  26. /// The size of the pool in bytes.
  27. /// </summary>
  28. public ulong Size { get; }
  29. private readonly (ulong, ulong)[] _modifiedRanges;
  30. public Pool(GpuContext context, ulong address, int maximumId)
  31. {
  32. Context = context;
  33. MaximumId = maximumId;
  34. int count = maximumId + 1;
  35. ulong size = (ulong)(uint)count * DescriptorSize;;
  36. Items = new T[count];
  37. Address = address;
  38. Size = size;
  39. _modifiedRanges = new (ulong, ulong)[size / PhysicalMemory.PageSize];
  40. }
  41. /// <summary>
  42. /// Gets the GPU resource with the given ID.
  43. /// </summary>
  44. /// <param name="id">ID of the resource. This is effectively a zero-based index</param>
  45. /// <returns>The GPU resource with the given ID</returns>
  46. public abstract T Get(int id);
  47. /// <summary>
  48. /// Synchronizes host memory with guest memory.
  49. /// This causes invalidation of pool entries,
  50. /// if a modification of entries by the CPU is detected.
  51. /// </summary>
  52. public void SynchronizeMemory()
  53. {
  54. int count = Context.PhysicalMemory.QueryModified(Address, Size, ResourceName.TexturePool, _modifiedRanges);
  55. for (int index = 0; index < count; index++)
  56. {
  57. (ulong mAddress, ulong mSize) = _modifiedRanges[index];
  58. if (mAddress < Address)
  59. {
  60. mAddress = Address;
  61. }
  62. ulong maxSize = Address + Size - mAddress;
  63. if (mSize > maxSize)
  64. {
  65. mSize = maxSize;
  66. }
  67. InvalidateRangeImpl(mAddress, mSize);
  68. }
  69. }
  70. private void InvalidateRangeInternal(ulong offset, int size)
  71. {
  72. InvalidateRangeImpl(Address + offset, (ulong)size);
  73. }
  74. /// <summary>
  75. /// Invalidates a range of memory of the GPU resource pool.
  76. /// Entries that falls inside the speicified range will be invalidated,
  77. /// causing all the data to be reloaded from guest memory.
  78. /// </summary>
  79. /// <param name="address">The start address of the range to invalidate</param>
  80. /// <param name="size">The size of the range to invalidate</param>
  81. public void InvalidateRange(ulong address, ulong size)
  82. {
  83. ulong endAddress = address + size;
  84. ulong texturePoolEndAddress = Address + Size;
  85. // If the range being invalidated is not overlapping the texture pool range,
  86. // then we don't have anything to do, exit early.
  87. if (address >= texturePoolEndAddress || endAddress <= Address)
  88. {
  89. return;
  90. }
  91. if (address < Address)
  92. {
  93. address = Address;
  94. }
  95. if (endAddress > texturePoolEndAddress)
  96. {
  97. endAddress = texturePoolEndAddress;
  98. }
  99. size = endAddress - address;
  100. InvalidateRangeImpl(address, size);
  101. }
  102. protected abstract void InvalidateRangeImpl(ulong address, ulong size);
  103. protected abstract void Delete(T item);
  104. /// <summary>
  105. /// Performs the disposal of all resources stored on the pool.
  106. /// It's an error to try using the pool after disposal.
  107. /// </summary>
  108. public void Dispose()
  109. {
  110. if (Items != null)
  111. {
  112. for (int index = 0; index < Items.Length; index++)
  113. {
  114. Delete(Items[index]);
  115. }
  116. Items = null;
  117. }
  118. }
  119. }
  120. }