private void CreateDescriptors() { int bindingCount = Inputs.Count + 1; // + 1 output. // Setup bindings. var bindings = new DescriptorSetLayoutBinding[bindingCount]; for (int i = 0; i < Inputs.Count; i++) { bindings[i] = Inputs[i].GetDescriptorSetLayoutBinding(i); } bindings[Inputs.Count] = Output.GetDescriptorSetLayoutBinding(Inputs.Count); _descriptorSetLayout = Device.Logical.CreateDescriptorSetLayout(new DescriptorSetLayoutCreateInfo(bindings)); var descriptorPoolCreateInfo = new DescriptorPoolCreateInfo( 1, new[] { new DescriptorPoolSize(DescriptorType.StorageBuffer, bindingCount) }); _descriptorPool = Device.Logical.CreateDescriptorPool(descriptorPoolCreateInfo); _descriptorSet = _descriptorPool.AllocateSets(new DescriptorSetAllocateInfo(1, _descriptorSetLayout))[0]; // Setup write descriptors. var writeDescriptorSets = new WriteDescriptorSet[bindingCount]; for (int i = 0; i < Inputs.Count; i++) { writeDescriptorSets[i] = Inputs[i].GetWriteDescriptorSet(_descriptorSet, i); } writeDescriptorSets[Inputs.Count] = Output.GetWriteDescriptorSet(_descriptorSet, Inputs.Count); _descriptorPool.UpdateSets(writeDescriptorSets); }
void CreateDescriptorSetLayout() { /* * Here we specify a descriptor set layout. This allows us to bind our descriptors to * resources in the shader. */ /* * Here we specify a binding of type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER to the binding point * 0. This binds to * layout(std140, binding = 0) buffer buf * in the compute shader. */ DescriptorSetLayoutBinding descriptorSetLayoutBinding = new DescriptorSetLayoutBinding() { Binding = 0, // binding = 0 DescriptorType = DescriptorType.StorageBuffer, // VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; DescriptorCount = 1, StageFlags = ShaderStages.Compute // VK_SHADER_STAGE_COMPUTE_BIT; }; DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo(); // descriptorSetLayoutCreateInfo.bindingCount = 1; // only a single binding in this descriptor set layout. DescriptorSetLayoutBinding[] temp = { descriptorSetLayoutBinding }; descriptorSetLayoutCreateInfo.Bindings = temp; // Create the descriptor set layout. descriptorSetLayout = device.CreateDescriptorSetLayout(descriptorSetLayoutCreateInfo); }
private DescriptorSetLayout[] CreateDescriptorSetLayouts() { DescriptorSetLayoutBinding binding = new DescriptorSetLayoutBinding { Binding = 0, DescriptorType = DescriptorType.UniformBuffer, DescriptorCount = 1, StageFlags = ShaderStageFlags.ShaderStageVertexBit }; DescriptorSetLayoutCreateInfo createInfo = new DescriptorSetLayoutCreateInfo { SType = StructureType.DescriptorSetLayoutCreateInfo, BindingCount = 1, PBindings = &binding }; DescriptorSetLayout layout; var res = VkApi.CreateDescriptorSetLayout(this.Device, &createInfo, null, &layout); if (res != Result.Success) { throw new VMASharp.VulkanResultException("Failed to create Descriptor Set Layout!", res); } return(new[] { layout }); }
protected override void CreateDescriptorSetLayout() { var uboLayoutBinding = new DescriptorSetLayoutBinding { Binding = 0, DescriptorType = DescriptorType.UniformBuffer, DescriptorCount = 1, ImmutableSamplers = null, StageFlags = ShaderStageFlags.Vertex }; var samplerLayoutBinding = new DescriptorSetLayoutBinding { Binding = 1, DescriptorCount = 1, DescriptorType = DescriptorType.CombinedImageSampler, ImmutableSamplers = null, StageFlags = ShaderStageFlags.Fragment }; var bindings = new[] { uboLayoutBinding, samplerLayoutBinding }; var layoutInfo = new DescriptorSetLayoutCreateInfo { BindingCount = (uint)bindings.Length, Bindings = bindings, }; descriptorSetLayout = device.CreateDescriptorSetLayout(layoutInfo); }
protected override unsafe DescriptorSetLayout[] CreateDescriptorSetLayouts(VulkanGraphicsDevice gd, Device device, out PipelineLayout layout) { DescriptorSetLayoutBinding uLayoutBindings = new DescriptorSetLayoutBinding { Binding = 0, DescriptorType = DescriptorType.UniformBuffer, DescriptorCount = 1, StageFlags = ShaderStageFlags.ShaderStageVertexBit }; DescriptorSetLayoutBinding tLayoutBindings = new DescriptorSetLayoutBinding { Binding = 0, DescriptorType = DescriptorType.CombinedImageSampler, DescriptorCount = 1, StageFlags = ShaderStageFlags.ShaderStageFragmentBit }; DescriptorSetLayout[] layouts = new DescriptorSetLayout[3]; var uDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = &uLayoutBindings, BindingCount = 1 }; var sDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, BindingCount = 0 }; var tDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = &tLayoutBindings, BindingCount = 1 }; gd.Api.CreateDescriptorSetLayout(device, uDescriptorSetLayoutCreateInfo, null, out layouts[0]).ThrowOnError(); gd.Api.CreateDescriptorSetLayout(device, sDescriptorSetLayoutCreateInfo, null, out layouts[1]).ThrowOnError(); gd.Api.CreateDescriptorSetLayout(device, tDescriptorSetLayoutCreateInfo, null, out layouts[2]).ThrowOnError(); fixed(DescriptorSetLayout *pLayouts = layouts) { var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo() { SType = StructureType.PipelineLayoutCreateInfo, PSetLayouts = pLayouts, SetLayoutCount = 3 }; gd.Api.CreatePipelineLayout(device, &pipelineLayoutCreateInfo, null, out layout).ThrowOnError(); } return(layouts); }
internal static unsafe SharpVulkan.DescriptorSetLayout CreateNativeDescriptorSetLayout(GraphicsDevice device, IList <DescriptorSetLayoutBuilder.Entry> entries, out uint[] typeCounts) { var bindings = new DescriptorSetLayoutBinding[entries.Count]; var immutableSamplers = new Sampler[entries.Count]; int usedBindingCount = 0; typeCounts = new uint[DescriptorTypeCount]; fixed(Sampler *immutableSamplersPointer = &immutableSamplers[0]) { for (int i = 0; i < entries.Count; i++) { var entry = entries[i]; // TODO VULKAN: Special case for unused bindings in PipelineState. Handle more nicely. if (entry.ArraySize == 0) { continue; } bindings[usedBindingCount] = new DescriptorSetLayoutBinding { DescriptorType = VulkanConvertExtensions.ConvertDescriptorType(entry.Class, entry.Type), StageFlags = ShaderStageFlags.All, // TODO VULKAN: Filter? Binding = (uint)i, DescriptorCount = (uint)entry.ArraySize }; if (entry.ImmutableSampler != null) { // TODO VULKAN: Handle immutable samplers for DescriptorCount > 1 if (entry.ArraySize > 1) { throw new NotImplementedException(); } // Remember this, so we can choose the right DescriptorType in DescriptorSet.SetShaderResourceView immutableSamplers[i] = entry.ImmutableSampler.NativeSampler; //bindings[i].DescriptorType = DescriptorType.CombinedImageSampler; bindings[usedBindingCount].ImmutableSamplers = new IntPtr(immutableSamplersPointer + i); } typeCounts[(int)bindings[usedBindingCount].DescriptorType] += bindings[usedBindingCount].DescriptorCount; usedBindingCount++; } var createInfo = new DescriptorSetLayoutCreateInfo { StructureType = StructureType.DescriptorSetLayoutCreateInfo, BindingCount = (uint)usedBindingCount, Bindings = usedBindingCount > 0 ? new IntPtr(Interop.Fixed(bindings)) : IntPtr.Zero }; return(device.NativeDevice.CreateDescriptorSetLayout(ref createInfo)); } }
internal static unsafe SharpVulkan.DescriptorSetLayout CreateNativeDescriptorSetLayout(GraphicsDevice device, IList<DescriptorSetLayoutBuilder.Entry> entries, out uint[] typeCounts) { var bindings = new DescriptorSetLayoutBinding[entries.Count]; var immutableSamplers = new Sampler[entries.Count]; int usedBindingCount = 0; typeCounts = new uint[DescriptorTypeCount]; fixed (Sampler* immutableSamplersPointer = &immutableSamplers[0]) { for (int i = 0; i < entries.Count; i++) { var entry = entries[i]; // TODO VULKAN: Special case for unused bindings in PipelineState. Handle more nicely. if (entry.ArraySize == 0) continue; bindings[usedBindingCount] = new DescriptorSetLayoutBinding { DescriptorType = VulkanConvertExtensions.ConvertDescriptorType(entry.Class, entry.Type), StageFlags = ShaderStageFlags.All, // TODO VULKAN: Filter? Binding = (uint)i, DescriptorCount = (uint)entry.ArraySize }; if (entry.ImmutableSampler != null) { // TODO VULKAN: Handle immutable samplers for DescriptorCount > 1 if (entry.ArraySize > 1) { throw new NotImplementedException(); } // Remember this, so we can choose the right DescriptorType in DescriptorSet.SetShaderResourceView immutableSamplers[i] = entry.ImmutableSampler.NativeSampler; //bindings[i].DescriptorType = DescriptorType.CombinedImageSampler; bindings[usedBindingCount].ImmutableSamplers = new IntPtr(immutableSamplersPointer + i); } typeCounts[(int)bindings[usedBindingCount].DescriptorType] += bindings[usedBindingCount].DescriptorCount; usedBindingCount++; } var createInfo = new DescriptorSetLayoutCreateInfo { StructureType = StructureType.DescriptorSetLayoutCreateInfo, BindingCount = (uint)usedBindingCount, Bindings = usedBindingCount > 0 ? new IntPtr(Interop.Fixed(bindings)) : IntPtr.Zero }; return device.NativeDevice.CreateDescriptorSetLayout(ref createInfo); } }
DescriptorSetLayout CreateDescriptorSetLayout() { var layoutBinding = new DescriptorSetLayoutBinding { DescriptorType = DescriptorType.UniformBuffer, DescriptorCount = 1, StageFlags = ShaderStageFlags.Vertex }; var descriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo { Bindings = new DescriptorSetLayoutBinding [] { layoutBinding } }; return(device.CreateDescriptorSetLayout(descriptorSetLayoutCreateInfo)); }
private void CreateDescriptorSetLayout() { var uboLayoutBinding = new DescriptorSetLayoutBinding() { Binding = 0, DescriptorType = DescriptorType.UniformBuffer, DescriptorCount = 1, StageFlags = ShaderStageFlags.Vertex, }; var layoutInfo = new DescriptorSetLayoutCreateInfo() { BindingCount = 1, Bindings = new DescriptorSetLayoutBinding[] { uboLayoutBinding }, }; vkDescriptorSetLayout = vkDevice.CreateDescriptorSetLayout(layoutInfo); }
private static DescriptorSetLayout CreateLayout( Device logicalDevice, ReadOnlySpan <IShaderInput> inputs) { var bindings = new DescriptorSetLayoutBinding[inputs.Length]; for (int i = 0; i < bindings.Length; i++) { bindings[i] = new DescriptorSetLayoutBinding( binding: i, descriptorType: inputs[i].DescriptorType, descriptorCount: 1, //NOTE: At the moment all resources are bound in both the vertex and the fragment //shader, this is the most user friendly setup. Need to do some profiling to //see if this is hurting the performance stageFlags: ShaderStages.Vertex | ShaderStages.Fragment); } return(logicalDevice.CreateDescriptorSetLayout(new DescriptorSetLayoutCreateInfo( bindings))); }
public DescriptorSetLayout GetDescriptorSetLayout() { List <DescriptorSetLayoutBinding> myBindings = new List <DescriptorSetLayoutBinding>(); foreach (var A in myBindingNumberToItems) { var Item = new DescriptorSetLayoutBinding(); Item.DescriptorType = (DescriptorType)A.Value.myType; Item.StageFlags = A.Value.ShaderStage; Item.DescriptorCount = A.Value.DescriptorCount; Item.Binding = A.Value.Binding; myBindings.Add(Item); } var descriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo { Bindings = myBindings.ToArray() }; return(new DescriptorSetLayout(VulkanRenderer.SelectedLogicalDevice, descriptorSetLayoutCreateInfo)); }
public void CreateDescriptorLayout() { DescriptorSetLayoutBinding dslb = new DescriptorSetLayoutBinding(); dslb.Binding = 0; dslb.DescriptorType = DescriptorType.UniformBuffer; dslb.DescriptorCount = 1; dslb.StageFlags = ShaderStages.Vertex; DescriptorSetLayoutCreateInfo dslci = new DescriptorSetLayoutCreateInfo(); dslci.Bindings = new DescriptorSetLayoutBinding[] { dslb }; mDSLs = new DescriptorSetLayout[mChainImageViews.Length]; for (int i = 0; i < mChainImageViews.Length; i++) { mDSLs[i] = mLogical.CreateDescriptorSetLayout(dslci); } }
public static DescriptorSetLayout CreateDescriptorSetLayout(Graphics g, DescriptorItem[] items) { var bindings = new DescriptorSetLayoutBinding[items.Length]; for (var i = 0; i < items.Length; i++) { var item = items[i]; bindings[i] = new DescriptorSetLayoutBinding( i, item.Type == DescriptorItem.DescriptorType.UniformBuffer ? DescriptorType.UniformBuffer : item.Type == DescriptorItem.DescriptorType.CombinedImageSampler ? DescriptorType.CombinedImageSampler : DescriptorType.UniformBuffer, item.Count, item.Shader == DescriptorItem.ShaderType.Vertex ? ShaderStages.Vertex : item.Shader == DescriptorItem.ShaderType.Fragment ? ShaderStages.Fragment : ShaderStages.All ); } return(g.Context.Device.CreateDescriptorSetLayout(new DescriptorSetLayoutCreateInfo(bindings))); }
public DescriptorSetLayout(Device selectedDevice) { AllocationCallbacks pAllocator = null; this.selectedDevice = selectedDevice; var layoutBinding = new DescriptorSetLayoutBinding { DescriptorType = DescriptorType.UniformBuffer, DescriptorCount = 1, StageFlags = ShaderStageFlags.Vertex }; var descriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo { Bindings = new DescriptorSetLayoutBinding[] { layoutBinding } }; Result result; //DescriptorSetLayout pSetLayout; unsafe { //pSetLayout = new DescriptorSetLayout(); fixed(UInt64 *ptrpSetLayout = &this.m) { result = Interop.NativeMethods.vkCreateDescriptorSetLayout(selectedDevice.Handle, descriptorSetLayoutCreateInfo != null ? descriptorSetLayoutCreateInfo.m : (Interop.DescriptorSetLayoutCreateInfo *) default(IntPtr), pAllocator != null ? pAllocator.m : null, ptrpSetLayout); } if (result != Result.Success) { throw new ResultException(result); } } }
private unsafe void CreatePipelineLayout() { var binding = new DescriptorSetLayoutBinding { Binding = 0, DescriptorCount = 1, DescriptorType = DescriptorType.UniformBuffer, StageFlags = ShaderStageFlags.Vertex }; var descriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo { StructureType = StructureType.DescriptorSetLayoutCreateInfo, BindingCount = 1, Bindings = new IntPtr(&binding) }; descriptorSetLayout = device.CreateDescriptorSetLayout(ref descriptorSetLayoutCreateInfo); var localDescriptorSetLayout = descriptorSetLayout; var createInfo = new PipelineLayoutCreateInfo { StructureType = StructureType.PipelineLayoutCreateInfo, SetLayoutCount = 1, SetLayouts = new IntPtr(&localDescriptorSetLayout) }; pipelineLayout = device.CreatePipelineLayout(ref createInfo); var poolSize = new DescriptorPoolSize { DescriptorCount = 2, Type = DescriptorType.UniformBuffer }; var descriptorPoolCreateinfo = new DescriptorPoolCreateInfo { StructureType = StructureType.DescriptorPoolCreateInfo, PoolSizeCount = 1, PoolSizes = new IntPtr(&poolSize), MaxSets = 2 }; descriptorPool = device.CreateDescriptorPool(ref descriptorPoolCreateinfo); var bufferCreateInfo = new BufferCreateInfo { StructureType = StructureType.BufferCreateInfo, Usage = BufferUsageFlags.UniformBuffer, Size = 64, }; uniformBuffer = device.CreateBuffer(ref bufferCreateInfo); MemoryRequirements memoryRequirements; device.GetBufferMemoryRequirements(uniformBuffer, out memoryRequirements); var memory = AllocateMemory(MemoryPropertyFlags.HostVisible | MemoryPropertyFlags.HostCoherent, memoryRequirements); device.BindBufferMemory(uniformBuffer, memory, 0); var mappedMemory = device.MapMemory(memory, 0, 64, MemoryMapFlags.None); var data = new[] { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; Utilities.Write(mappedMemory, data, 0, data.Length); device.UnmapMemory(memory); }
public static unsafe DescriptorSetLayout[] Create(VulkanGraphicsDevice gd, Device device, uint stages, out PipelineLayout layout) { int stagesCount = BitOperations.PopCount(stages); int uCount = Constants.MaxUniformBuffersPerStage * stagesCount + 1; int tCount = Constants.MaxTexturesPerStage * stagesCount; int iCount = Constants.MaxImagesPerStage * stagesCount; int bTCount = tCount; int bICount = iCount; DescriptorSetLayoutBinding *uLayoutBindings = stackalloc DescriptorSetLayoutBinding[uCount]; DescriptorSetLayoutBinding *sLayoutBindings = stackalloc DescriptorSetLayoutBinding[stagesCount]; DescriptorSetLayoutBinding *tLayoutBindings = stackalloc DescriptorSetLayoutBinding[tCount]; DescriptorSetLayoutBinding *iLayoutBindings = stackalloc DescriptorSetLayoutBinding[iCount]; DescriptorSetLayoutBinding *bTLayoutBindings = stackalloc DescriptorSetLayoutBinding[bTCount]; DescriptorSetLayoutBinding *bILayoutBindings = stackalloc DescriptorSetLayoutBinding[bICount]; uLayoutBindings[0] = new DescriptorSetLayoutBinding { Binding = 0, DescriptorType = DescriptorType.UniformBuffer, DescriptorCount = 1, StageFlags = ShaderStageFlags.ShaderStageFragmentBit | ShaderStageFlags.ShaderStageComputeBit }; int iter = 0; while (stages != 0) { int stage = BitOperations.TrailingZeroCount(stages); stages &= ~(1u << stage); var stageFlags = stage switch { 1 => ShaderStageFlags.ShaderStageFragmentBit, 2 => ShaderStageFlags.ShaderStageGeometryBit, 3 => ShaderStageFlags.ShaderStageTessellationControlBit, 4 => ShaderStageFlags.ShaderStageTessellationEvaluationBit, _ => ShaderStageFlags.ShaderStageVertexBit | ShaderStageFlags.ShaderStageComputeBit }; void Set(DescriptorSetLayoutBinding *bindings, int maxPerStage, DescriptorType type, int start = 0) { for (int i = 0; i < maxPerStage; i++) { bindings[start + iter * maxPerStage + i] = new DescriptorSetLayoutBinding { Binding = (uint)(start + stage * maxPerStage + i), DescriptorType = type, DescriptorCount = 1, StageFlags = stageFlags }; } } void SetStorage(DescriptorSetLayoutBinding *bindings, int maxPerStage, int start = 0) { bindings[start + iter] = new DescriptorSetLayoutBinding { Binding = (uint)(start + stage * maxPerStage), DescriptorType = DescriptorType.StorageBuffer, DescriptorCount = (uint)maxPerStage, StageFlags = stageFlags }; } Set(uLayoutBindings, Constants.MaxUniformBuffersPerStage, DescriptorType.UniformBuffer, 1); SetStorage(sLayoutBindings, Constants.MaxStorageBuffersPerStage); Set(tLayoutBindings, Constants.MaxTexturesPerStage, DescriptorType.CombinedImageSampler); Set(iLayoutBindings, Constants.MaxImagesPerStage, DescriptorType.StorageImage); Set(bTLayoutBindings, Constants.MaxTexturesPerStage, DescriptorType.UniformTexelBuffer); Set(bILayoutBindings, Constants.MaxImagesPerStage, DescriptorType.StorageTexelBuffer); iter++; } DescriptorSetLayout[] layouts = new DescriptorSetLayout[PipelineFull.DescriptorSetLayouts]; var uDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = uLayoutBindings, BindingCount = (uint)uCount }; var sDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = sLayoutBindings, BindingCount = (uint)stagesCount }; var tDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = tLayoutBindings, BindingCount = (uint)tCount }; var iDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = iLayoutBindings, BindingCount = (uint)iCount }; var bTDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = bTLayoutBindings, BindingCount = (uint)bTCount }; var bIDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = bILayoutBindings, BindingCount = (uint)bICount }; gd.Api.CreateDescriptorSetLayout(device, uDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.UniformSetIndex]).ThrowOnError(); gd.Api.CreateDescriptorSetLayout(device, sDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.StorageSetIndex]).ThrowOnError(); gd.Api.CreateDescriptorSetLayout(device, tDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.TextureSetIndex]).ThrowOnError(); gd.Api.CreateDescriptorSetLayout(device, iDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.ImageSetIndex]).ThrowOnError(); gd.Api.CreateDescriptorSetLayout(device, bTDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.BufferTextureSetIndex]).ThrowOnError(); gd.Api.CreateDescriptorSetLayout(device, bIDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.BufferImageSetIndex]).ThrowOnError(); fixed(DescriptorSetLayout *pLayouts = layouts) { var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo() { SType = StructureType.PipelineLayoutCreateInfo, PSetLayouts = pLayouts, SetLayoutCount = PipelineFull.DescriptorSetLayouts }; gd.Api.CreatePipelineLayout(device, &pipelineLayoutCreateInfo, null, out layout).ThrowOnError(); } return(layouts); } }
public static unsafe DescriptorSetLayout[] CreateMinimal(VulkanRenderer gd, Device device, ShaderSource[] shaders, out PipelineLayout layout) { int stagesCount = shaders.Length; int uCount = 0; int tCount = 0; int iCount = 0; foreach (var shader in shaders) { uCount += shader.Bindings.UniformBufferBindings.Count; tCount += shader.Bindings.TextureBindings.Count; iCount += shader.Bindings.ImageBindings.Count; } DescriptorSetLayoutBinding *uLayoutBindings = stackalloc DescriptorSetLayoutBinding[uCount]; DescriptorSetLayoutBinding *sLayoutBindings = stackalloc DescriptorSetLayoutBinding[stagesCount]; DescriptorSetLayoutBinding *tLayoutBindings = stackalloc DescriptorSetLayoutBinding[tCount]; DescriptorSetLayoutBinding *iLayoutBindings = stackalloc DescriptorSetLayoutBinding[iCount]; int uIndex = 0; int sIndex = 0; int tIndex = 0; int iIndex = 0; foreach (var shader in shaders) { var stageFlags = shader.Stage.Convert(); void Set(DescriptorSetLayoutBinding *bindings, DescriptorType type, ref int start, IEnumerable <int> bds) { foreach (var b in bds) { bindings[start++] = new DescriptorSetLayoutBinding { Binding = (uint)b, DescriptorType = type, DescriptorCount = 1, StageFlags = stageFlags }; } } void SetStorage(DescriptorSetLayoutBinding *bindings, ref int start, int count) { bindings[start++] = new DescriptorSetLayoutBinding { Binding = (uint)start, DescriptorType = DescriptorType.StorageBuffer, DescriptorCount = (uint)count, StageFlags = stageFlags }; } // TODO: Support buffer textures and images here. // This is only used for the helper shaders on the backend, and we don't use buffer textures on them // so far, so it's not really necessary right now. Set(uLayoutBindings, DescriptorType.UniformBuffer, ref uIndex, shader.Bindings.UniformBufferBindings); SetStorage(sLayoutBindings, ref sIndex, shader.Bindings.StorageBufferBindings.Count); Set(tLayoutBindings, DescriptorType.CombinedImageSampler, ref tIndex, shader.Bindings.TextureBindings); Set(iLayoutBindings, DescriptorType.StorageImage, ref iIndex, shader.Bindings.ImageBindings); } DescriptorSetLayout[] layouts = new DescriptorSetLayout[PipelineFull.DescriptorSetLayouts]; var uDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = uLayoutBindings, BindingCount = (uint)uCount }; var sDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = sLayoutBindings, BindingCount = (uint)stagesCount }; var tDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = tLayoutBindings, BindingCount = (uint)tCount }; var iDescriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo() { SType = StructureType.DescriptorSetLayoutCreateInfo, PBindings = iLayoutBindings, BindingCount = (uint)iCount }; gd.Api.CreateDescriptorSetLayout(device, uDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.UniformSetIndex]).ThrowOnError(); gd.Api.CreateDescriptorSetLayout(device, sDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.StorageSetIndex]).ThrowOnError(); gd.Api.CreateDescriptorSetLayout(device, tDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.TextureSetIndex]).ThrowOnError(); gd.Api.CreateDescriptorSetLayout(device, iDescriptorSetLayoutCreateInfo, null, out layouts[PipelineFull.ImageSetIndex]).ThrowOnError(); fixed(DescriptorSetLayout *pLayouts = layouts) { var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo() { SType = StructureType.PipelineLayoutCreateInfo, PSetLayouts = pLayouts, SetLayoutCount = PipelineFull.DescriptorSetLayouts }; gd.Api.CreatePipelineLayout(device, &pipelineLayoutCreateInfo, null, out layout).ThrowOnError(); } return(layouts); }