GpuResourceManager.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. using Ryujinx.Graphics.Gal;
  2. using Ryujinx.Graphics.Memory;
  3. using Ryujinx.Graphics.Texture;
  4. using System.Collections.Generic;
  5. namespace Ryujinx.Graphics
  6. {
  7. public class GpuResourceManager
  8. {
  9. private enum ImageType
  10. {
  11. None,
  12. Texture,
  13. TextureArrayLayer,
  14. ColorBuffer,
  15. ZetaBuffer
  16. }
  17. private NvGpu _gpu;
  18. private HashSet<long>[] _uploadedKeys;
  19. private Dictionary<long, ImageType> _imageTypes;
  20. private Dictionary<long, int> _mirroredTextures;
  21. public GpuResourceManager(NvGpu gpu)
  22. {
  23. _gpu = gpu;
  24. _uploadedKeys = new HashSet<long>[(int)NvGpuBufferType.Count];
  25. for (int index = 0; index < _uploadedKeys.Length; index++)
  26. {
  27. _uploadedKeys[index] = new HashSet<long>();
  28. }
  29. _imageTypes = new Dictionary<long, ImageType>();
  30. _mirroredTextures = new Dictionary<long, int>();
  31. }
  32. public void SendColorBuffer(NvGpuVmm vmm, long position, int attachment, GalImage newImage)
  33. {
  34. long size = (uint)ImageUtils.GetSize(newImage);
  35. _imageTypes[position] = ImageType.ColorBuffer;
  36. if (!TryReuse(vmm, position, newImage))
  37. {
  38. _gpu.Renderer.Texture.Create(position, (int)size, newImage);
  39. }
  40. _gpu.Renderer.RenderTarget.BindColor(position, attachment);
  41. }
  42. public void SendZetaBuffer(NvGpuVmm vmm, long position, GalImage newImage)
  43. {
  44. long size = (uint)ImageUtils.GetSize(newImage);
  45. _imageTypes[position] = ImageType.ZetaBuffer;
  46. if (!TryReuse(vmm, position, newImage))
  47. {
  48. _gpu.Renderer.Texture.Create(position, (int)size, newImage);
  49. }
  50. _gpu.Renderer.RenderTarget.BindZeta(position);
  51. }
  52. public void SendTexture(NvGpuVmm vmm, long position, GalImage newImage)
  53. {
  54. PrepareSendTexture(vmm, position, newImage);
  55. _imageTypes[position] = ImageType.Texture;
  56. }
  57. public bool TryGetTextureLayer(long position, out int layerIndex)
  58. {
  59. if (_mirroredTextures.TryGetValue(position, out layerIndex))
  60. {
  61. ImageType type = _imageTypes[position];
  62. // FIXME(thog): I'm actually unsure if we should deny all other image type, gpu testing needs to be done here.
  63. if (type != ImageType.Texture && type != ImageType.TextureArrayLayer)
  64. {
  65. layerIndex = -1;
  66. return false;
  67. }
  68. return true;
  69. }
  70. layerIndex = -1;
  71. return false;
  72. }
  73. public void SetTextureArrayLayer(long position, int layerIndex)
  74. {
  75. _imageTypes[position] = ImageType.TextureArrayLayer;
  76. _mirroredTextures[position] = layerIndex;
  77. }
  78. private void PrepareSendTexture(NvGpuVmm vmm, long position, GalImage newImage)
  79. {
  80. long size = ImageUtils.GetSize(newImage);
  81. bool skipCheck = false;
  82. if (_imageTypes.TryGetValue(position, out ImageType oldType))
  83. {
  84. if (oldType == ImageType.ColorBuffer || oldType == ImageType.ZetaBuffer)
  85. {
  86. // Avoid data destruction
  87. MemoryRegionModified(vmm, position, size, NvGpuBufferType.Texture);
  88. skipCheck = true;
  89. }
  90. }
  91. if (skipCheck || !MemoryRegionModified(vmm, position, size, NvGpuBufferType.Texture))
  92. {
  93. if (TryReuse(vmm, position, newImage))
  94. {
  95. return;
  96. }
  97. }
  98. byte[] data = ImageUtils.ReadTexture(vmm, newImage, position);
  99. _gpu.Renderer.Texture.Create(position, data, newImage);
  100. }
  101. private bool TryReuse(NvGpuVmm vmm, long position, GalImage newImage)
  102. {
  103. if (_gpu.Renderer.Texture.TryGetImage(position, out GalImage cachedImage) && cachedImage.TextureTarget == newImage.TextureTarget && cachedImage.SizeMatches(newImage))
  104. {
  105. _gpu.Renderer.RenderTarget.Reinterpret(position, newImage);
  106. return true;
  107. }
  108. return false;
  109. }
  110. public bool MemoryRegionModified(NvGpuVmm vmm, long position, long size, NvGpuBufferType type)
  111. {
  112. HashSet<long> uploaded = _uploadedKeys[(int)type];
  113. if (!uploaded.Add(position))
  114. {
  115. return false;
  116. }
  117. return vmm.IsRegionModified(position, size, type);
  118. }
  119. public void ClearPbCache()
  120. {
  121. for (int index = 0; index < _uploadedKeys.Length; index++)
  122. {
  123. _uploadedKeys[index].Clear();
  124. }
  125. }
  126. public void ClearPbCache(NvGpuBufferType type)
  127. {
  128. _uploadedKeys[(int)type].Clear();
  129. }
  130. }
  131. }