PipelineLayoutFactory.cs 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using Ryujinx.Graphics.GAL;
  2. using Silk.NET.Vulkan;
  3. using System.Collections.ObjectModel;
  4. namespace Ryujinx.Graphics.Vulkan
  5. {
  6. static class PipelineLayoutFactory
  7. {
  8. public static unsafe (DescriptorSetLayout[], PipelineLayout) Create(
  9. VulkanRenderer gd,
  10. Device device,
  11. ReadOnlyCollection<ResourceDescriptorCollection> setDescriptors,
  12. bool usePushDescriptors)
  13. {
  14. DescriptorSetLayout[] layouts = new DescriptorSetLayout[setDescriptors.Count];
  15. bool isMoltenVk = gd.IsMoltenVk;
  16. for (int setIndex = 0; setIndex < setDescriptors.Count; setIndex++)
  17. {
  18. ResourceDescriptorCollection rdc = setDescriptors[setIndex];
  19. ResourceStages activeStages = ResourceStages.None;
  20. if (isMoltenVk)
  21. {
  22. for (int descIndex = 0; descIndex < rdc.Descriptors.Count; descIndex++)
  23. {
  24. activeStages |= rdc.Descriptors[descIndex].Stages;
  25. }
  26. }
  27. DescriptorSetLayoutBinding[] layoutBindings = new DescriptorSetLayoutBinding[rdc.Descriptors.Count];
  28. for (int descIndex = 0; descIndex < rdc.Descriptors.Count; descIndex++)
  29. {
  30. ResourceDescriptor descriptor = rdc.Descriptors[descIndex];
  31. ResourceStages stages = descriptor.Stages;
  32. if (descriptor.Type == ResourceType.StorageBuffer && isMoltenVk)
  33. {
  34. // There's a bug on MoltenVK where using the same buffer across different stages
  35. // causes invalid resource errors, allow the binding on all active stages as workaround.
  36. stages = activeStages;
  37. }
  38. layoutBindings[descIndex] = new DescriptorSetLayoutBinding
  39. {
  40. Binding = (uint)descriptor.Binding,
  41. DescriptorType = descriptor.Type.Convert(),
  42. DescriptorCount = (uint)descriptor.Count,
  43. StageFlags = stages.Convert(),
  44. };
  45. }
  46. fixed (DescriptorSetLayoutBinding* pLayoutBindings = layoutBindings)
  47. {
  48. var descriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo
  49. {
  50. SType = StructureType.DescriptorSetLayoutCreateInfo,
  51. PBindings = pLayoutBindings,
  52. BindingCount = (uint)layoutBindings.Length,
  53. Flags = usePushDescriptors && setIndex == 0 ? DescriptorSetLayoutCreateFlags.PushDescriptorBitKhr : DescriptorSetLayoutCreateFlags.None,
  54. };
  55. gd.Api.CreateDescriptorSetLayout(device, descriptorSetLayoutCreateInfo, null, out layouts[setIndex]).ThrowOnError();
  56. }
  57. }
  58. PipelineLayout layout;
  59. fixed (DescriptorSetLayout* pLayouts = layouts)
  60. {
  61. var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo
  62. {
  63. SType = StructureType.PipelineLayoutCreateInfo,
  64. PSetLayouts = pLayouts,
  65. SetLayoutCount = (uint)layouts.Length,
  66. };
  67. gd.Api.CreatePipelineLayout(device, &pipelineLayoutCreateInfo, null, out layout).ThrowOnError();
  68. }
  69. return (layouts, layout);
  70. }
  71. }
  72. }