PipelineLayoutFactory.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. using Ryujinx.Graphics.GAL;
  2. using Silk.NET.Vulkan;
  3. using System.Collections.Generic;
  4. using System.Numerics;
  5. namespace Ryujinx.Graphics.Vulkan
  6. {
  7. static class PipelineLayoutFactory
  8. {
  9. private const ShaderStageFlags SupportBufferStages =
  10. ShaderStageFlags.VertexBit |
  11. ShaderStageFlags.FragmentBit |
  12. ShaderStageFlags.ComputeBit;
  13. public static unsafe DescriptorSetLayout[] Create(VulkanRenderer gd, Device device, uint stages, bool usePd, out PipelineLayout layout)
  14. {
  15. int stagesCount = BitOperations.PopCount(stages);
  16. int uCount = Constants.MaxUniformBuffersPerStage * stagesCount + 1;
  17. int tCount = Constants.MaxTexturesPerStage * 2 * stagesCount;
  18. int iCount = Constants.MaxImagesPerStage * 2 * stagesCount;
  19. DescriptorSetLayoutBinding* uLayoutBindings = stackalloc DescriptorSetLayoutBinding[uCount];
  20. DescriptorSetLayoutBinding* sLayoutBindings = stackalloc DescriptorSetLayoutBinding[stagesCount];
  21. DescriptorSetLayoutBinding* tLayoutBindings = stackalloc DescriptorSetLayoutBinding[tCount];
  22. DescriptorSetLayoutBinding* iLayoutBindings = stackalloc DescriptorSetLayoutBinding[iCount];
  23. uLayoutBindings[0] = new DescriptorSetLayoutBinding
  24. {
  25. Binding = 0,
  26. DescriptorType = DescriptorType.UniformBuffer,
  27. DescriptorCount = 1,
  28. StageFlags = SupportBufferStages
  29. };
  30. int iter = 0;
  31. while (stages != 0)
  32. {
  33. int stage = BitOperations.TrailingZeroCount(stages);
  34. stages &= ~(1u << stage);
  35. var stageFlags = stage switch
  36. {
  37. 1 => ShaderStageFlags.FragmentBit,
  38. 2 => ShaderStageFlags.GeometryBit,
  39. 3 => ShaderStageFlags.TessellationControlBit,
  40. 4 => ShaderStageFlags.TessellationEvaluationBit,
  41. _ => ShaderStageFlags.VertexBit | ShaderStageFlags.ComputeBit
  42. };
  43. void Set(DescriptorSetLayoutBinding* bindings, int maxPerStage, DescriptorType type, int start, int skip)
  44. {
  45. int totalPerStage = maxPerStage * skip;
  46. for (int i = 0; i < maxPerStage; i++)
  47. {
  48. bindings[start + iter * totalPerStage + i] = new DescriptorSetLayoutBinding
  49. {
  50. Binding = (uint)(start + stage * totalPerStage + i),
  51. DescriptorType = type,
  52. DescriptorCount = 1,
  53. StageFlags = stageFlags
  54. };
  55. }
  56. }
  57. void SetStorage(DescriptorSetLayoutBinding* bindings, int maxPerStage, int start = 0)
  58. {
  59. bindings[start + iter] = new DescriptorSetLayoutBinding
  60. {
  61. Binding = (uint)(start + stage * maxPerStage),
  62. DescriptorType = DescriptorType.StorageBuffer,
  63. DescriptorCount = (uint)maxPerStage,
  64. StageFlags = stageFlags
  65. };
  66. }
  67. Set(uLayoutBindings, Constants.MaxUniformBuffersPerStage, DescriptorType.UniformBuffer, 1, 1);
  68. SetStorage(sLayoutBindings, Constants.MaxStorageBuffersPerStage);
  69. Set(tLayoutBindings, Constants.MaxTexturesPerStage, DescriptorType.CombinedImageSampler, 0, 2);
  70. Set(tLayoutBindings, Constants.MaxTexturesPerStage, DescriptorType.UniformTexelBuffer, Constants.MaxTexturesPerStage, 2);
  71. Set(iLayoutBindings, Constants.MaxImagesPerStage, DescriptorType.StorageImage, 0, 2);
  72. Set(iLayoutBindings, Constants.MaxImagesPerStage, DescriptorType.StorageTexelBuffer, Constants.MaxImagesPerStage, 2);
  73. iter++;
  74. }
  75. DescriptorSetLayout[] layouts = new DescriptorSetLayout[PipelineBase.DescriptorSetLayouts];
  76. var uDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  77. {
  78. SType = StructureType.DescriptorSetLayoutCreateInfo,
  79. PBindings = uLayoutBindings,
  80. BindingCount = (uint)uCount,
  81. Flags = usePd ? DescriptorSetLayoutCreateFlags.PushDescriptorBitKhr : 0
  82. };
  83. var sDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  84. {
  85. SType = StructureType.DescriptorSetLayoutCreateInfo,
  86. PBindings = sLayoutBindings,
  87. BindingCount = (uint)stagesCount
  88. };
  89. var tDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  90. {
  91. SType = StructureType.DescriptorSetLayoutCreateInfo,
  92. PBindings = tLayoutBindings,
  93. BindingCount = (uint)tCount
  94. };
  95. var iDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  96. {
  97. SType = StructureType.DescriptorSetLayoutCreateInfo,
  98. PBindings = iLayoutBindings,
  99. BindingCount = (uint)iCount
  100. };
  101. gd.Api.CreateDescriptorSetLayout(device, uDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.UniformSetIndex]).ThrowOnError();
  102. gd.Api.CreateDescriptorSetLayout(device, sDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.StorageSetIndex]).ThrowOnError();
  103. gd.Api.CreateDescriptorSetLayout(device, tDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.TextureSetIndex]).ThrowOnError();
  104. gd.Api.CreateDescriptorSetLayout(device, iDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.ImageSetIndex]).ThrowOnError();
  105. fixed (DescriptorSetLayout* pLayouts = layouts)
  106. {
  107. var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo()
  108. {
  109. SType = StructureType.PipelineLayoutCreateInfo,
  110. PSetLayouts = pLayouts,
  111. SetLayoutCount = PipelineBase.DescriptorSetLayouts
  112. };
  113. gd.Api.CreatePipelineLayout(device, &pipelineLayoutCreateInfo, null, out layout).ThrowOnError();
  114. }
  115. return layouts;
  116. }
  117. public static unsafe DescriptorSetLayout[] CreateMinimal(VulkanRenderer gd, Device device, ShaderSource[] shaders, out PipelineLayout layout)
  118. {
  119. int stagesCount = shaders.Length;
  120. int uCount = 0;
  121. int sCount = 0;
  122. int tCount = 0;
  123. int iCount = 0;
  124. foreach (var shader in shaders)
  125. {
  126. uCount += shader.Bindings.UniformBufferBindings.Count;
  127. sCount += shader.Bindings.StorageBufferBindings.Count;
  128. tCount += shader.Bindings.TextureBindings.Count;
  129. iCount += shader.Bindings.ImageBindings.Count;
  130. }
  131. DescriptorSetLayoutBinding* uLayoutBindings = stackalloc DescriptorSetLayoutBinding[uCount];
  132. DescriptorSetLayoutBinding* sLayoutBindings = stackalloc DescriptorSetLayoutBinding[sCount];
  133. DescriptorSetLayoutBinding* tLayoutBindings = stackalloc DescriptorSetLayoutBinding[tCount];
  134. DescriptorSetLayoutBinding* iLayoutBindings = stackalloc DescriptorSetLayoutBinding[iCount];
  135. int uIndex = 0;
  136. int sIndex = 0;
  137. int tIndex = 0;
  138. int iIndex = 0;
  139. foreach (var shader in shaders)
  140. {
  141. var stageFlags = shader.Stage.Convert();
  142. void Set(DescriptorSetLayoutBinding* bindings, DescriptorType type, ref int start, IEnumerable<int> bds)
  143. {
  144. foreach (var b in bds)
  145. {
  146. bindings[start++] = new DescriptorSetLayoutBinding
  147. {
  148. Binding = (uint)b,
  149. DescriptorType = type,
  150. DescriptorCount = 1,
  151. StageFlags = stageFlags
  152. };
  153. }
  154. }
  155. // TODO: Support buffer textures and images here.
  156. // This is only used for the helper shaders on the backend, and we don't use buffer textures on them
  157. // so far, so it's not really necessary right now.
  158. Set(uLayoutBindings, DescriptorType.UniformBuffer, ref uIndex, shader.Bindings.UniformBufferBindings);
  159. Set(sLayoutBindings, DescriptorType.StorageBuffer, ref sIndex, shader.Bindings.StorageBufferBindings);
  160. Set(tLayoutBindings, DescriptorType.CombinedImageSampler, ref tIndex, shader.Bindings.TextureBindings);
  161. Set(iLayoutBindings, DescriptorType.StorageImage, ref iIndex, shader.Bindings.ImageBindings);
  162. }
  163. DescriptorSetLayout[] layouts = new DescriptorSetLayout[PipelineBase.DescriptorSetLayouts];
  164. var uDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  165. {
  166. SType = StructureType.DescriptorSetLayoutCreateInfo,
  167. PBindings = uLayoutBindings,
  168. BindingCount = (uint)uCount
  169. };
  170. var sDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  171. {
  172. SType = StructureType.DescriptorSetLayoutCreateInfo,
  173. PBindings = sLayoutBindings,
  174. BindingCount = (uint)sCount
  175. };
  176. var tDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  177. {
  178. SType = StructureType.DescriptorSetLayoutCreateInfo,
  179. PBindings = tLayoutBindings,
  180. BindingCount = (uint)tCount
  181. };
  182. var iDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  183. {
  184. SType = StructureType.DescriptorSetLayoutCreateInfo,
  185. PBindings = iLayoutBindings,
  186. BindingCount = (uint)iCount
  187. };
  188. gd.Api.CreateDescriptorSetLayout(device, uDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.UniformSetIndex]).ThrowOnError();
  189. gd.Api.CreateDescriptorSetLayout(device, sDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.StorageSetIndex]).ThrowOnError();
  190. gd.Api.CreateDescriptorSetLayout(device, tDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.TextureSetIndex]).ThrowOnError();
  191. gd.Api.CreateDescriptorSetLayout(device, iDescriptorSetLayoutCreateInfo, null, out layouts[PipelineBase.ImageSetIndex]).ThrowOnError();
  192. fixed (DescriptorSetLayout* pLayouts = layouts)
  193. {
  194. var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo()
  195. {
  196. SType = StructureType.PipelineLayoutCreateInfo,
  197. PSetLayouts = pLayouts,
  198. SetLayoutCount = PipelineBase.DescriptorSetLayouts
  199. };
  200. gd.Api.CreatePipelineLayout(device, &pipelineLayoutCreateInfo, null, out layout).ThrowOnError();
  201. }
  202. return layouts;
  203. }
  204. }
  205. }