TexturePool.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. using Ryujinx.Graphics.GAL;
  2. using Ryujinx.Graphics.GAL.Texture;
  3. using Ryujinx.Graphics.Gpu.Memory;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Runtime.InteropServices;
  7. namespace Ryujinx.Graphics.Gpu.Image
  8. {
  9. class TexturePool : Pool<Texture>
  10. {
  11. private TextureManager _textureManager;
  12. public LinkedListNode<TexturePool> CacheNode { get; set; }
  13. private struct TextureContainer
  14. {
  15. public Texture Texture0 { get; set; }
  16. public Texture Texture1 { get; set; }
  17. }
  18. public TexturePool(
  19. GpuContext context,
  20. TextureManager textureManager,
  21. ulong address,
  22. int maximumId) : base(context, address, maximumId)
  23. {
  24. _textureManager = textureManager;
  25. }
  26. public override Texture Get(int id)
  27. {
  28. if ((uint)id >= Items.Length)
  29. {
  30. return null;
  31. }
  32. SynchronizeMemory();
  33. Texture texture = Items[id];
  34. if (texture == null)
  35. {
  36. ulong address = Address + (ulong)(uint)id * DescriptorSize;
  37. Span<byte> data = Context.PhysicalMemory.Read(address, DescriptorSize);
  38. TextureDescriptor descriptor = MemoryMarshal.Cast<byte, TextureDescriptor>(data)[0];
  39. TextureInfo info = GetInfo(descriptor);
  40. // Bad address. We can't add a texture with a invalid address
  41. // to the cache.
  42. if (info.Address == MemoryManager.BadAddress)
  43. {
  44. return null;
  45. }
  46. texture = _textureManager.FindOrCreateTexture(info, TextureSearchFlags.Sampler);
  47. texture.IncrementReferenceCount();
  48. Items[id] = texture;
  49. }
  50. else
  51. {
  52. // Memory is automatically synchronized on texture creation.
  53. texture.SynchronizeMemory();
  54. }
  55. return texture;
  56. }
  57. protected override void InvalidateRangeImpl(ulong address, ulong size)
  58. {
  59. ulong endAddress = address + size;
  60. for (; address < endAddress; address += DescriptorSize)
  61. {
  62. int id = (int)((address - Address) / DescriptorSize);
  63. Texture texture = Items[id];
  64. if (texture != null)
  65. {
  66. Span<byte> data = Context.PhysicalMemory.Read(address, DescriptorSize);
  67. TextureDescriptor descriptor = MemoryMarshal.Cast<byte, TextureDescriptor>(data)[0];
  68. // If the descriptors are the same, the texture is the same,
  69. // we don't need to remove as it was not modified. Just continue.
  70. if (texture.IsPerfectMatch(GetInfo(descriptor), TextureSearchFlags.Strict))
  71. {
  72. continue;
  73. }
  74. texture.DecrementReferenceCount();
  75. Items[id] = null;
  76. }
  77. }
  78. }
  79. private TextureInfo GetInfo(TextureDescriptor descriptor)
  80. {
  81. ulong address = Context.MemoryManager.Translate(descriptor.UnpackAddress());
  82. int width = descriptor.UnpackWidth();
  83. int height = descriptor.UnpackHeight();
  84. int depthOrLayers = descriptor.UnpackDepth();
  85. int levels = descriptor.UnpackLevels();
  86. TextureMsaaMode msaaMode = descriptor.UnpackTextureMsaaMode();
  87. int samplesInX = msaaMode.SamplesInX();
  88. int samplesInY = msaaMode.SamplesInY();
  89. int stride = descriptor.UnpackStride();
  90. TextureDescriptorType descriptorType = descriptor.UnpackTextureDescriptorType();
  91. bool isLinear = descriptorType == TextureDescriptorType.Linear;
  92. Target target = descriptor.UnpackTextureTarget().Convert((samplesInX | samplesInY) != 1);
  93. uint format = descriptor.UnpackFormat();
  94. bool srgb = descriptor.UnpackSrgb();
  95. if (!FormatTable.TryGetTextureFormat(format, srgb, out FormatInfo formatInfo))
  96. {
  97. // TODO: Warning.
  98. formatInfo = FormatInfo.Default;
  99. }
  100. int gobBlocksInY = descriptor.UnpackGobBlocksInY();
  101. int gobBlocksInZ = descriptor.UnpackGobBlocksInZ();
  102. int gobBlocksInTileX = descriptor.UnpackGobBlocksInTileX();
  103. SwizzleComponent swizzleR = descriptor.UnpackSwizzleR().Convert();
  104. SwizzleComponent swizzleG = descriptor.UnpackSwizzleG().Convert();
  105. SwizzleComponent swizzleB = descriptor.UnpackSwizzleB().Convert();
  106. SwizzleComponent swizzleA = descriptor.UnpackSwizzleA().Convert();
  107. DepthStencilMode depthStencilMode = GetDepthStencilMode(
  108. formatInfo.Format,
  109. swizzleR,
  110. swizzleG,
  111. swizzleB,
  112. swizzleA);
  113. return new TextureInfo(
  114. address,
  115. width,
  116. height,
  117. depthOrLayers,
  118. levels,
  119. samplesInX,
  120. samplesInY,
  121. stride,
  122. isLinear,
  123. gobBlocksInY,
  124. gobBlocksInZ,
  125. gobBlocksInTileX,
  126. target,
  127. formatInfo,
  128. depthStencilMode,
  129. swizzleR,
  130. swizzleG,
  131. swizzleB,
  132. swizzleA);
  133. }
  134. private static DepthStencilMode GetDepthStencilMode(Format format, params SwizzleComponent[] components)
  135. {
  136. // R = Depth, G = Stencil.
  137. // On 24-bits depth formats, this is inverted (Stencil is R etc).
  138. // NVN setup:
  139. // For depth, A is set to 1.0f, the other components are set to Depth.
  140. // For stencil, all components are set to Stencil.
  141. SwizzleComponent component = components[0];
  142. for (int index = 1; index < 4 && !IsRG(component); index++)
  143. {
  144. component = components[index];
  145. }
  146. if (!IsRG(component))
  147. {
  148. return DepthStencilMode.Depth;
  149. }
  150. if (format == Format.D24X8Unorm || format == Format.D24UnormS8Uint)
  151. {
  152. return component == SwizzleComponent.Red
  153. ? DepthStencilMode.Stencil
  154. : DepthStencilMode.Depth;
  155. }
  156. else
  157. {
  158. return component == SwizzleComponent.Red
  159. ? DepthStencilMode.Depth
  160. : DepthStencilMode.Stencil;
  161. }
  162. }
  163. private static bool IsRG(SwizzleComponent component)
  164. {
  165. return component == SwizzleComponent.Red ||
  166. component == SwizzleComponent.Green;
  167. }
  168. protected override void Delete(Texture item)
  169. {
  170. item?.DecrementReferenceCount();
  171. }
  172. }
  173. }