FramebufferParams.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. using Ryujinx.Graphics.GAL;
  2. using Silk.NET.Vulkan;
  3. using System;
  4. using System.Linq;
  5. using VkFormat = Silk.NET.Vulkan.Format;
  6. namespace Ryujinx.Graphics.Vulkan
  7. {
  8. class FramebufferParams
  9. {
  10. private readonly Device _device;
  11. private readonly Auto<DisposableImageView>[] _attachments;
  12. private readonly TextureView[] _colors;
  13. private readonly TextureView _depthStencil;
  14. private readonly TextureView[] _colorsCanonical;
  15. private readonly TextureView _baseAttachment;
  16. private readonly uint _validColorAttachments;
  17. public uint Width { get; }
  18. public uint Height { get; }
  19. public uint Layers { get; }
  20. public uint[] AttachmentSamples { get; }
  21. public VkFormat[] AttachmentFormats { get; }
  22. public int[] AttachmentIndices { get; }
  23. public uint AttachmentIntegerFormatMask { get; }
  24. public bool LogicOpsAllowed { get; }
  25. public int AttachmentsCount { get; }
  26. public int MaxColorAttachmentIndex => AttachmentIndices.Length > 0 ? AttachmentIndices[^1] : -1;
  27. public bool HasDepthStencil { get; }
  28. public int ColorAttachmentsCount => AttachmentsCount - (HasDepthStencil ? 1 : 0);
  29. public FramebufferParams(Device device, TextureView view, uint width, uint height)
  30. {
  31. var format = view.Info.Format;
  32. bool isDepthStencil = format.IsDepthOrStencil();
  33. _device = device;
  34. _attachments = new[] { view.GetImageViewForAttachment() };
  35. _validColorAttachments = isDepthStencil ? 0u : 1u;
  36. _baseAttachment = view;
  37. if (isDepthStencil)
  38. {
  39. _depthStencil = view;
  40. }
  41. else
  42. {
  43. _colors = new TextureView[] { view };
  44. _colorsCanonical = _colors;
  45. }
  46. Width = width;
  47. Height = height;
  48. Layers = 1;
  49. AttachmentSamples = new[] { (uint)view.Info.Samples };
  50. AttachmentFormats = new[] { view.VkFormat };
  51. AttachmentIndices = isDepthStencil ? Array.Empty<int>() : new[] { 0 };
  52. AttachmentIntegerFormatMask = format.IsInteger() ? 1u : 0u;
  53. LogicOpsAllowed = !format.IsFloatOrSrgb();
  54. AttachmentsCount = 1;
  55. HasDepthStencil = isDepthStencil;
  56. }
  57. public FramebufferParams(Device device, ITexture[] colors, ITexture depthStencil)
  58. {
  59. _device = device;
  60. int colorsCount = colors.Count(IsValidTextureView);
  61. int count = colorsCount + (IsValidTextureView(depthStencil) ? 1 : 0);
  62. _attachments = new Auto<DisposableImageView>[count];
  63. _colors = new TextureView[colorsCount];
  64. _colorsCanonical = colors.Select(color => color is TextureView view && view.Valid ? view : null).ToArray();
  65. AttachmentSamples = new uint[count];
  66. AttachmentFormats = new VkFormat[count];
  67. AttachmentIndices = new int[colorsCount];
  68. uint width = uint.MaxValue;
  69. uint height = uint.MaxValue;
  70. uint layers = uint.MaxValue;
  71. int index = 0;
  72. int bindIndex = 0;
  73. uint attachmentIntegerFormatMask = 0;
  74. bool allFormatsFloatOrSrgb = colorsCount != 0;
  75. foreach (ITexture color in colors)
  76. {
  77. if (IsValidTextureView(color))
  78. {
  79. var texture = (TextureView)color;
  80. _attachments[index] = texture.GetImageViewForAttachment();
  81. _colors[index] = texture;
  82. _validColorAttachments |= 1u << bindIndex;
  83. _baseAttachment = texture;
  84. AttachmentSamples[index] = (uint)texture.Info.Samples;
  85. AttachmentFormats[index] = texture.VkFormat;
  86. AttachmentIndices[index] = bindIndex;
  87. var format = texture.Info.Format;
  88. if (format.IsInteger())
  89. {
  90. attachmentIntegerFormatMask |= 1u << bindIndex;
  91. }
  92. allFormatsFloatOrSrgb &= format.IsFloatOrSrgb();
  93. width = Math.Min(width, (uint)texture.Width);
  94. height = Math.Min(height, (uint)texture.Height);
  95. layers = Math.Min(layers, (uint)texture.Layers);
  96. if (++index >= colorsCount)
  97. {
  98. break;
  99. }
  100. }
  101. bindIndex++;
  102. }
  103. AttachmentIntegerFormatMask = attachmentIntegerFormatMask;
  104. LogicOpsAllowed = !allFormatsFloatOrSrgb;
  105. if (depthStencil is TextureView dsTexture && dsTexture.Valid)
  106. {
  107. _attachments[count - 1] = dsTexture.GetImageViewForAttachment();
  108. _depthStencil = dsTexture;
  109. _baseAttachment ??= dsTexture;
  110. AttachmentSamples[count - 1] = (uint)dsTexture.Info.Samples;
  111. AttachmentFormats[count - 1] = dsTexture.VkFormat;
  112. width = Math.Min(width, (uint)dsTexture.Width);
  113. height = Math.Min(height, (uint)dsTexture.Height);
  114. layers = Math.Min(layers, (uint)dsTexture.Layers);
  115. HasDepthStencil = true;
  116. }
  117. if (count == 0)
  118. {
  119. width = height = layers = 1;
  120. }
  121. Width = width;
  122. Height = height;
  123. Layers = layers;
  124. AttachmentsCount = count;
  125. }
  126. public Auto<DisposableImageView> GetAttachment(int index)
  127. {
  128. if ((uint)index >= _attachments.Length)
  129. {
  130. return null;
  131. }
  132. return _attachments[index];
  133. }
  134. public Auto<DisposableImageView> GetDepthStencilAttachment()
  135. {
  136. if (!HasDepthStencil)
  137. {
  138. return null;
  139. }
  140. return _attachments[AttachmentsCount - 1];
  141. }
  142. public ComponentType GetAttachmentComponentType(int index)
  143. {
  144. if (_colors != null && (uint)index < _colors.Length)
  145. {
  146. var format = _colors[index].Info.Format;
  147. if (format.IsSint())
  148. {
  149. return ComponentType.SignedInteger;
  150. }
  151. if (format.IsUint())
  152. {
  153. return ComponentType.UnsignedInteger;
  154. }
  155. }
  156. return ComponentType.Float;
  157. }
  158. public ImageAspectFlags GetDepthStencilAspectFlags()
  159. {
  160. if (_depthStencil == null)
  161. {
  162. return ImageAspectFlags.None;
  163. }
  164. return _depthStencil.Info.Format.ConvertAspectFlags();
  165. }
  166. public bool IsValidColorAttachment(int bindIndex)
  167. {
  168. return (uint)bindIndex < Constants.MaxRenderTargets && (_validColorAttachments & (1u << bindIndex)) != 0;
  169. }
  170. private static bool IsValidTextureView(ITexture texture)
  171. {
  172. return texture is TextureView view && view.Valid;
  173. }
  174. public ClearRect GetClearRect(Rectangle<int> scissor, int layer, int layerCount)
  175. {
  176. int x = scissor.X;
  177. int y = scissor.Y;
  178. int width = Math.Min((int)Width - scissor.X, scissor.Width);
  179. int height = Math.Min((int)Height - scissor.Y, scissor.Height);
  180. return new ClearRect(new Rect2D(new Offset2D(x, y), new Extent2D((uint)width, (uint)height)), (uint)layer, (uint)layerCount);
  181. }
  182. public unsafe Auto<DisposableFramebuffer> Create(Vk api, CommandBufferScoped cbs, Auto<DisposableRenderPass> renderPass)
  183. {
  184. ImageView* attachments = stackalloc ImageView[_attachments.Length];
  185. for (int i = 0; i < _attachments.Length; i++)
  186. {
  187. attachments[i] = _attachments[i].Get(cbs).Value;
  188. }
  189. var framebufferCreateInfo = new FramebufferCreateInfo
  190. {
  191. SType = StructureType.FramebufferCreateInfo,
  192. RenderPass = renderPass.Get(cbs).Value,
  193. AttachmentCount = (uint)_attachments.Length,
  194. PAttachments = attachments,
  195. Width = Width,
  196. Height = Height,
  197. Layers = Layers,
  198. };
  199. api.CreateFramebuffer(_device, in framebufferCreateInfo, null, out var framebuffer).ThrowOnError();
  200. return new Auto<DisposableFramebuffer>(new DisposableFramebuffer(api, _device, framebuffer), null, _attachments);
  201. }
  202. public TextureView[] GetAttachmentViews()
  203. {
  204. var result = new TextureView[_attachments.Length];
  205. _colors?.CopyTo(result, 0);
  206. if (_depthStencil != null)
  207. {
  208. result[^1] = _depthStencil;
  209. }
  210. return result;
  211. }
  212. public RenderPassCacheKey GetRenderPassCacheKey()
  213. {
  214. return new RenderPassCacheKey(_depthStencil, _colorsCanonical);
  215. }
  216. public void InsertLoadOpBarriers(VulkanRenderer gd, CommandBufferScoped cbs)
  217. {
  218. if (_colors != null)
  219. {
  220. foreach (var color in _colors)
  221. {
  222. // If Clear or DontCare were used, this would need to be write bit.
  223. color.Storage?.QueueLoadOpBarrier(cbs, false);
  224. }
  225. }
  226. _depthStencil?.Storage?.QueueLoadOpBarrier(cbs, true);
  227. gd.Barriers.Flush(cbs, false, null, null);
  228. }
  229. public void AddStoreOpUsage()
  230. {
  231. if (_colors != null)
  232. {
  233. foreach (var color in _colors)
  234. {
  235. color.Storage?.AddStoreOpUsage(false);
  236. }
  237. }
  238. _depthStencil?.Storage?.AddStoreOpUsage(true);
  239. }
  240. public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
  241. VulkanRenderer gd,
  242. Device device,
  243. CommandBufferScoped cbs)
  244. {
  245. return _baseAttachment.GetPassAndFramebuffer(gd, device, cbs, this);
  246. }
  247. public TextureView GetColorView(int index)
  248. {
  249. return _colorsCanonical[index];
  250. }
  251. public TextureView GetDepthStencilView()
  252. {
  253. return _depthStencil;
  254. }
  255. }
  256. }