PipelineLayoutFactory.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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.ShaderStageVertexBit |
  11. ShaderStageFlags.ShaderStageFragmentBit |
  12. ShaderStageFlags.ShaderStageComputeBit;
  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.ShaderStageFragmentBit,
  38. 2 => ShaderStageFlags.ShaderStageGeometryBit,
  39. 3 => ShaderStageFlags.ShaderStageTessellationControlBit,
  40. 4 => ShaderStageFlags.ShaderStageTessellationEvaluationBit,
  41. _ => ShaderStageFlags.ShaderStageVertexBit | ShaderStageFlags.ShaderStageComputeBit
  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[PipelineFull.DescriptorSetLayouts];
  76. var uDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  77. {
  78. SType = StructureType.DescriptorSetLayoutCreateInfo,
  79. PBindings = uLayoutBindings,
  80. BindingCount = (uint)uCount,
  81. Flags = usePd ? DescriptorSetLayoutCreateFlags.DescriptorSetLayoutCreatePushDescriptorBitKhr : 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[PipelineFull.UniformSetIndex]).ThrowOnError();
  102. gd.Api.CreateDescriptorSetLayout(device, sDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.StorageSetIndex]).ThrowOnError();
  103. gd.Api.CreateDescriptorSetLayout(device, tDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.TextureSetIndex]).ThrowOnError();
  104. gd.Api.CreateDescriptorSetLayout(device, iDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.ImageSetIndex]).ThrowOnError();
  105. fixed (DescriptorSetLayout* pLayouts = layouts)
  106. {
  107. var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo()
  108. {
  109. SType = StructureType.PipelineLayoutCreateInfo,
  110. PSetLayouts = pLayouts,
  111. SetLayoutCount = PipelineFull.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 tCount = 0;
  122. int iCount = 0;
  123. foreach (var shader in shaders)
  124. {
  125. uCount += shader.Bindings.UniformBufferBindings.Count;
  126. tCount += shader.Bindings.TextureBindings.Count;
  127. iCount += shader.Bindings.ImageBindings.Count;
  128. }
  129. DescriptorSetLayoutBinding* uLayoutBindings = stackalloc DescriptorSetLayoutBinding[uCount];
  130. DescriptorSetLayoutBinding* sLayoutBindings = stackalloc DescriptorSetLayoutBinding[stagesCount];
  131. DescriptorSetLayoutBinding* tLayoutBindings = stackalloc DescriptorSetLayoutBinding[tCount];
  132. DescriptorSetLayoutBinding* iLayoutBindings = stackalloc DescriptorSetLayoutBinding[iCount];
  133. int uIndex = 0;
  134. int sIndex = 0;
  135. int tIndex = 0;
  136. int iIndex = 0;
  137. foreach (var shader in shaders)
  138. {
  139. var stageFlags = shader.Stage.Convert();
  140. void Set(DescriptorSetLayoutBinding* bindings, DescriptorType type, ref int start, IEnumerable<int> bds)
  141. {
  142. foreach (var b in bds)
  143. {
  144. bindings[start++] = new DescriptorSetLayoutBinding
  145. {
  146. Binding = (uint)b,
  147. DescriptorType = type,
  148. DescriptorCount = 1,
  149. StageFlags = stageFlags
  150. };
  151. }
  152. }
  153. void SetStorage(DescriptorSetLayoutBinding* bindings, ref int start, int count)
  154. {
  155. bindings[start++] = new DescriptorSetLayoutBinding
  156. {
  157. Binding = (uint)start,
  158. DescriptorType = DescriptorType.StorageBuffer,
  159. DescriptorCount = (uint)count,
  160. StageFlags = stageFlags
  161. };
  162. }
  163. // TODO: Support buffer textures and images here.
  164. // This is only used for the helper shaders on the backend, and we don't use buffer textures on them
  165. // so far, so it's not really necessary right now.
  166. Set(uLayoutBindings, DescriptorType.UniformBuffer, ref uIndex, shader.Bindings.UniformBufferBindings);
  167. SetStorage(sLayoutBindings, ref sIndex, shader.Bindings.StorageBufferBindings.Count);
  168. Set(tLayoutBindings, DescriptorType.CombinedImageSampler, ref tIndex, shader.Bindings.TextureBindings);
  169. Set(iLayoutBindings, DescriptorType.StorageImage, ref iIndex, shader.Bindings.ImageBindings);
  170. }
  171. DescriptorSetLayout[] layouts = new DescriptorSetLayout[PipelineFull.DescriptorSetLayouts];
  172. var uDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  173. {
  174. SType = StructureType.DescriptorSetLayoutCreateInfo,
  175. PBindings = uLayoutBindings,
  176. BindingCount = (uint)uCount
  177. };
  178. var sDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  179. {
  180. SType = StructureType.DescriptorSetLayoutCreateInfo,
  181. PBindings = sLayoutBindings,
  182. BindingCount = (uint)stagesCount
  183. };
  184. var tDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  185. {
  186. SType = StructureType.DescriptorSetLayoutCreateInfo,
  187. PBindings = tLayoutBindings,
  188. BindingCount = (uint)tCount
  189. };
  190. var iDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo()
  191. {
  192. SType = StructureType.DescriptorSetLayoutCreateInfo,
  193. PBindings = iLayoutBindings,
  194. BindingCount = (uint)iCount
  195. };
  196. gd.Api.CreateDescriptorSetLayout(device, uDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.UniformSetIndex]).ThrowOnError();
  197. gd.Api.CreateDescriptorSetLayout(device, sDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.StorageSetIndex]).ThrowOnError();
  198. gd.Api.CreateDescriptorSetLayout(device, tDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.TextureSetIndex]).ThrowOnError();
  199. gd.Api.CreateDescriptorSetLayout(device, iDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.ImageSetIndex]).ThrowOnError();
  200. fixed (DescriptorSetLayout* pLayouts = layouts)
  201. {
  202. var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo()
  203. {
  204. SType = StructureType.PipelineLayoutCreateInfo,
  205. PSetLayouts = pLayouts,
  206. SetLayoutCount = PipelineFull.DescriptorSetLayouts
  207. };
  208. gd.Api.CreatePipelineLayout(device, &pipelineLayoutCreateInfo, null, out layout).ThrowOnError();
  209. }
  210. return layouts;
  211. }
  212. }
  213. }