TextureBindingsManager.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. using Ryujinx.Graphics.GAL;
  2. using Ryujinx.Graphics.Gpu.State;
  3. using Ryujinx.Graphics.Shader;
  4. using System;
  5. namespace Ryujinx.Graphics.Gpu.Image
  6. {
  7. class TextureBindingsManager
  8. {
  9. private GpuContext _context;
  10. private bool _isCompute;
  11. private SamplerPool _samplerPool;
  12. private SamplerIndex _samplerIndex;
  13. private ulong _texturePoolAddress;
  14. private int _texturePoolMaximumId;
  15. private TexturePoolCache _texturePoolCache;
  16. private TextureBindingInfo[][] _textureBindings;
  17. private TextureBindingInfo[][] _imageBindings;
  18. private struct TextureStatePerStage
  19. {
  20. public ITexture Texture;
  21. public ISampler Sampler;
  22. }
  23. private TextureStatePerStage[][] _textureState;
  24. private TextureStatePerStage[][] _imageState;
  25. private int _textureBufferIndex;
  26. private bool _rebind;
  27. public TextureBindingsManager(GpuContext context, TexturePoolCache texturePoolCache, bool isCompute)
  28. {
  29. _context = context;
  30. _texturePoolCache = texturePoolCache;
  31. _isCompute = isCompute;
  32. int stages = isCompute ? 1 : Constants.TotalShaderStages;
  33. _textureBindings = new TextureBindingInfo[stages][];
  34. _imageBindings = new TextureBindingInfo[stages][];
  35. _textureState = new TextureStatePerStage[stages][];
  36. _imageState = new TextureStatePerStage[stages][];
  37. }
  38. public void SetTextures(int stage, TextureBindingInfo[] bindings)
  39. {
  40. _textureBindings[stage] = bindings;
  41. _textureState[stage] = new TextureStatePerStage[bindings.Length];
  42. }
  43. public void SetImages(int stage, TextureBindingInfo[] bindings)
  44. {
  45. _imageBindings[stage] = bindings;
  46. _imageState[stage] = new TextureStatePerStage[bindings.Length];
  47. }
  48. public void SetTextureBufferIndex(int index)
  49. {
  50. _textureBufferIndex = index;
  51. }
  52. public void SetSamplerPool(ulong gpuVa, int maximumId, SamplerIndex samplerIndex)
  53. {
  54. ulong address = _context.MemoryManager.Translate(gpuVa);
  55. if (_samplerPool != null)
  56. {
  57. if (_samplerPool.Address == address && _samplerPool.MaximumId >= maximumId)
  58. {
  59. return;
  60. }
  61. _samplerPool.Dispose();
  62. }
  63. _samplerPool = new SamplerPool(_context, address, maximumId);
  64. _samplerIndex = samplerIndex;
  65. }
  66. public void SetTexturePool(ulong gpuVa, int maximumId)
  67. {
  68. ulong address = _context.MemoryManager.Translate(gpuVa);
  69. _texturePoolAddress = address;
  70. _texturePoolMaximumId = maximumId;
  71. }
  72. public void CommitBindings()
  73. {
  74. TexturePool texturePool = _texturePoolCache.FindOrCreate(
  75. _texturePoolAddress,
  76. _texturePoolMaximumId);
  77. if (_isCompute)
  78. {
  79. CommitTextureBindings(texturePool, ShaderStage.Compute, 0);
  80. CommitImageBindings (texturePool, ShaderStage.Compute, 0);
  81. }
  82. else
  83. {
  84. for (ShaderStage stage = ShaderStage.Vertex; stage <= ShaderStage.Fragment; stage++)
  85. {
  86. int stageIndex = (int)stage - 1;
  87. CommitTextureBindings(texturePool, stage, stageIndex);
  88. CommitImageBindings (texturePool, stage, stageIndex);
  89. }
  90. }
  91. _rebind = false;
  92. }
  93. private void CommitTextureBindings(TexturePool pool, ShaderStage stage, int stageIndex)
  94. {
  95. if (_textureBindings[stageIndex] == null)
  96. {
  97. return;
  98. }
  99. for (int index = 0; index < _textureBindings[stageIndex].Length; index++)
  100. {
  101. TextureBindingInfo binding = _textureBindings[stageIndex][index];
  102. int packedId = ReadPackedId(stageIndex, binding.Handle);
  103. int textureId = UnpackTextureId(packedId);
  104. int samplerId;
  105. if (_samplerIndex == SamplerIndex.ViaHeaderIndex)
  106. {
  107. samplerId = textureId;
  108. }
  109. else
  110. {
  111. samplerId = UnpackSamplerId(packedId);
  112. }
  113. Texture texture = pool.Get(textureId);
  114. ITexture hostTexture = texture?.GetTargetTexture(binding.Target);
  115. if (_textureState[stageIndex][index].Texture != hostTexture || _rebind)
  116. {
  117. _textureState[stageIndex][index].Texture = hostTexture;
  118. _context.Renderer.Pipeline.BindTexture(index, stage, hostTexture);
  119. }
  120. Sampler sampler = _samplerPool.Get(samplerId);
  121. ISampler hostSampler = sampler?.HostSampler;
  122. if (_textureState[stageIndex][index].Sampler != hostSampler || _rebind)
  123. {
  124. _textureState[stageIndex][index].Sampler = hostSampler;
  125. _context.Renderer.Pipeline.BindSampler(index, stage, hostSampler);
  126. }
  127. }
  128. }
  129. private void CommitImageBindings(TexturePool pool, ShaderStage stage, int stageIndex)
  130. {
  131. if (_imageBindings[stageIndex] == null)
  132. {
  133. return;
  134. }
  135. for (int index = 0; index < _imageBindings[stageIndex].Length; index++)
  136. {
  137. TextureBindingInfo binding = _imageBindings[stageIndex][index];
  138. int packedId = ReadPackedId(stageIndex, binding.Handle);
  139. int textureId = UnpackTextureId(packedId);
  140. Texture texture = pool.Get(textureId);
  141. ITexture hostTexture = texture?.GetTargetTexture(binding.Target);
  142. if (_imageState[stageIndex][index].Texture != hostTexture || _rebind)
  143. {
  144. _imageState[stageIndex][index].Texture = hostTexture;
  145. _context.Renderer.Pipeline.BindImage(index, stage, hostTexture);
  146. }
  147. }
  148. }
  149. private int ReadPackedId(int stage, int wordOffset)
  150. {
  151. ulong address;
  152. var bufferManager = _context.Methods.BufferManager;
  153. if (_isCompute)
  154. {
  155. address = bufferManager.GetComputeUniformBufferAddress(_textureBufferIndex);
  156. }
  157. else
  158. {
  159. address = bufferManager.GetGraphicsUniformBufferAddress(stage, _textureBufferIndex);
  160. }
  161. address += (uint)wordOffset * 4;
  162. return BitConverter.ToInt32(_context.PhysicalMemory.Read(address, 4));
  163. }
  164. private static int UnpackTextureId(int packedId)
  165. {
  166. return (packedId >> 0) & 0xfffff;
  167. }
  168. private static int UnpackSamplerId(int packedId)
  169. {
  170. return (packedId >> 20) & 0xfff;
  171. }
  172. public void InvalidatePoolRange(ulong address, ulong size)
  173. {
  174. _samplerPool?.InvalidateRange(address, size);
  175. _texturePoolCache.InvalidateRange(address, size);
  176. }
  177. public void Rebind()
  178. {
  179. _rebind = true;
  180. }
  181. }
  182. }