public void CreatePipelineLayout() { var createInfo = new PipelineLayoutCreateInfo(); using (Device.CreatePipelineLayout(createInfo)) { } using (Device.CreatePipelineLayout(createInfo, CustomAllocator)) { } }
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); }
private PipelineLayout CreatePipelineLayout(DescriptorSetLayout descriptorSetLayout) { var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo { SetLayouts = new DescriptorSetLayout[] { descriptorSetLayout } }; return(VulkanRenderer.SelectedLogicalDevice.CreatePipelineLayout(pipelineLayoutCreateInfo)); }
void CreateComputePipeline() { /* * We create a compute pipeline here. */ /* * Create a shader module. A shader module basically just encapsulates some shader code. */ // the code in comp.spv was created by running the command: // glslangValidator.exe -V shader.comp byte[] code = ReadFile("shaders/shader.comp.spv"); ShaderModuleCreateInfo createInfo = new ShaderModuleCreateInfo() { Code = code }; computeShaderModule = device.CreateShaderModule(createInfo); /* * Now let us actually create the compute pipeline. * A compute pipeline is very simple compared to a graphics pipeline. * It only consists of a single stage with a compute shader. * So first we specify the compute shader stage, and it's entry point(main). */ PipelineShaderStageCreateInfo shaderStageCreateInfo = new PipelineShaderStageCreateInfo() { Stage = ShaderStages.Compute,// VK_SHADER_STAGE_COMPUTE_BIT; Module = computeShaderModule, Name = "main" }; /* * The pipeline layout allows the pipeline to access descriptor sets. * So we just specify the descriptor set layout we created earlier. */ PipelineLayoutCreateInfo pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo(new[] { descriptorSetLayout }); pipelineLayout = device.CreatePipelineLayout(pipelineLayoutCreateInfo); ComputePipelineCreateInfo pipelineCreateInfo = new ComputePipelineCreateInfo() { Stage = shaderStageCreateInfo, Layout = pipelineLayout }; /* * Now, we finally create the compute pipeline. */ ComputePipelineCreateInfo[] ci = { pipelineCreateInfo }; pipelines = device.CreateComputePipelines(ci); }
PipelineLayout CreatePipelineLayout() { // The pipeline layout represents a sequence of descriptor sets with each having a // specific layout. This sequence of layouts is used to determine the interface between // shader stages and shader resources. Each pipeline is created using a pipeline layout. // We're not using any resources in this example so we dont // need to create any descriptor sets var createInfo = new PipelineLayoutCreateInfo(); return(device.CreatePipelineLayout(createInfo)); }
private void CreateComputePipeline() { var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo(new[] { _descriptorSetLayout }); _pipelineLayout = Device.Logical.CreatePipelineLayout(pipelineLayoutCreateInfo); using (ShaderModule shader = Device.Logical.CreateShaderModule(new ShaderModuleCreateInfo(SpirV))) { var computePipelineCreateInfo = new ComputePipelineCreateInfo( new PipelineShaderStageCreateInfo(ShaderStages.Compute, shader, "main"), _pipelineLayout); _pipeline = Device.Logical.CreateComputePipeline(computePipelineCreateInfo); } }
public unsafe PipelineLayout(Api api, DescriptorSetLayout descriptorSetLayout) { _api = api; var descriptorSetLayouts = descriptorSetLayout.VkDescriptorSetLayout; var pipelineLayoutInfo = new PipelineLayoutCreateInfo(); pipelineLayoutInfo.SType = StructureType.PipelineLayoutCreateInfo; pipelineLayoutInfo.SetLayoutCount = 1; pipelineLayoutInfo.PSetLayouts = (VkDescriptorSetLayout *)Unsafe.AsPointer(ref descriptorSetLayouts); pipelineLayoutInfo.PushConstantRangeCount = 0; pipelineLayoutInfo.PPushConstantRanges = (PushConstantRange *)0; Util.Verify(_api.Vk.CreatePipelineLayout(_api.Device.VkDevice, pipelineLayoutInfo, default, out _vkPipelineLayout), $"{nameof(PipelineLayout)}: Failed to create pipeline layout");
PipelineLayout CreatePipelineLayout() { var layout_create_info = new PipelineLayoutCreateInfo { sType = StructureType.PipelineLayoutCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkPipelineLayoutCreateFlagBits flags setLayoutCount = 0, // uint32_t setLayoutCount pSetLayouts = (DescriptorSetLayout *)0, // const VkDescriptorSetLayout *pSetLayouts pushConstantRangeCount = 0, // uint32_t pushConstantRangeCount pPushConstantRanges = (PushConstantRange *)0 // const VkPushConstantRange *pPushConstantRanges }; PipelineLayout pipeline_layout; vk.CreatePipelineLayout(GetDevice, ref layout_create_info, (AllocationCallbacks *)0, out pipeline_layout).CheckError(); return(pipeline_layout); }
private PipelineLayout CreatePipelineLayout() { PipelineLayoutCreateInfo createInfo = new PipelineLayoutCreateInfo { SType = StructureType.PipelineLayoutCreateInfo }; fixed(DescriptorSetLayout *pLayouts = this.DescriptorSetLayouts) { createInfo.SetLayoutCount = (uint)this.DescriptorSetLayouts.Length; createInfo.PSetLayouts = pLayouts; PipelineLayout pipelineLayout; var res = VkApi.CreatePipelineLayout(this.Device, &createInfo, null, &pipelineLayout); if (res != Result.Success) { throw new VMASharp.VulkanResultException("Failed to create Pipeline Layout!", res); } return(pipelineLayout); } }
protected PipelineLayout CreatePipelineLayout(DescriptorSetLayout descriptorSetLayout) { var createInfo = new PipelineLayoutCreateInfo(new[] { descriptorSetLayout }, null); return(device.CreatePipelineLayout(createInfo)); }
Pipeline[] CreatePipelines() { var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo { SetLayouts = new DescriptorSetLayout [] { descriptorSetLayout } }; pipelineLayout = device.CreatePipelineLayout(pipelineLayoutCreateInfo); var vertexShaderModule = device.CreateShaderModule(LoadResource("XLogo.Shaders.shader.vert.spv")); var fragmentShaderModule = device.CreateShaderModule(LoadResource("XLogo.Shaders.shader.frag.spv")); PipelineShaderStageCreateInfo [] pipelineShaderStages = { new PipelineShaderStageCreateInfo { Stage = ShaderStageFlags.Vertex, Module = vertexShaderModule, Name = "main" }, new PipelineShaderStageCreateInfo { Stage = ShaderStageFlags.Fragment, Module = fragmentShaderModule, Name = "main" } }; var viewport = new Viewport { MinDepth = 0, MaxDepth = 1.0f, Width = surfaceCapabilities.CurrentExtent.Width, Height = surfaceCapabilities.CurrentExtent.Height }; var scissor = new Rect2D { Extent = surfaceCapabilities.CurrentExtent }; var viewportCreateInfo = new PipelineViewportStateCreateInfo { Viewports = new Viewport [] { viewport }, Scissors = new Rect2D [] { scissor } }; var multisampleCreateInfo = new PipelineMultisampleStateCreateInfo { RasterizationSamples = SampleCountFlags.Count1, SampleMask = new uint [] { ~0u } }; var colorBlendAttachmentState = new PipelineColorBlendAttachmentState { ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A }; var colorBlendStateCreatInfo = new PipelineColorBlendStateCreateInfo { LogicOp = LogicOp.Copy, Attachments = new PipelineColorBlendAttachmentState [] { colorBlendAttachmentState } }; var rasterizationStateCreateInfo = new PipelineRasterizationStateCreateInfo { PolygonMode = PolygonMode.Fill, CullMode = (uint)CullModeFlags.None, FrontFace = FrontFace.Clockwise, LineWidth = 1.0f }; var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo { Topology = PrimitiveTopology.TriangleList }; var vertexInputBindingDescription = new VertexInputBindingDescription { Stride = 3 * sizeof(float), InputRate = VertexInputRate.Vertex }; var vertexInputAttributeDescription = new VertexInputAttributeDescription { Format = Format.R32g32b32Sfloat }; var vertexInputStateCreateInfo = new PipelineVertexInputStateCreateInfo { VertexBindingDescriptions = new VertexInputBindingDescription [] { vertexInputBindingDescription }, VertexAttributeDescriptions = new VertexInputAttributeDescription [] { vertexInputAttributeDescription } }; var pipelineCreateInfo = new GraphicsPipelineCreateInfo { Layout = pipelineLayout, ViewportState = viewportCreateInfo, Stages = pipelineShaderStages, MultisampleState = multisampleCreateInfo, ColorBlendState = colorBlendStateCreatInfo, RasterizationState = rasterizationStateCreateInfo, InputAssemblyState = inputAssemblyStateCreateInfo, VertexInputState = vertexInputStateCreateInfo, DynamicState = new PipelineDynamicStateCreateInfo(), RenderPass = renderPass }; return(device.CreateGraphicsPipelines(device.CreatePipelineCache(new PipelineCacheCreateInfo()), new GraphicsPipelineCreateInfo [] { pipelineCreateInfo })); }
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); } }
private PipelineLayout CreatePipelineLayout() { var layoutCreateInfo = new PipelineLayoutCreateInfo(); return(Context.Device.CreatePipelineLayout(layoutCreateInfo)); }
public unsafe PipelineLayout CreatePipelineLayout(ref PipelineLayoutCreateInfo createInfo, AllocationCallbacks* allocator = null) { PipelineLayout pipelineLayout; fixed (PipelineLayoutCreateInfo* __createInfo__ = &createInfo) { vkCreatePipelineLayout(this, __createInfo__, allocator, &pipelineLayout).CheckError(); } return pipelineLayout; }
private unsafe void CreatePipelineLayout(PipelineStateDescription pipelineStateDescription) { // Remap descriptor set indices to those in the shader. This ordering generated by the ShaderCompiler var resourceGroups = pipelineStateDescription.EffectBytecode.Reflection.ResourceBindings.Select(x => x.ResourceGroup ?? "Globals").Distinct().ToList(); ResourceGroupCount = resourceGroups.Count; var layouts = pipelineStateDescription.RootSignature.EffectDescriptorSetReflection.Layouts; // Get binding indices used by the shader var destinationBindings = pipelineStateDescription.EffectBytecode.Stages .SelectMany(x => BinarySerialization.Read <ShaderInputBytecode>(x.Data).ResourceBindings) .GroupBy(x => x.Key, x => x.Value) .ToDictionary(x => x.Key, x => x.First()); var maxBindingIndex = destinationBindings.Max(x => x.Value); var destinationEntries = new DescriptorSetLayoutBuilder.Entry[maxBindingIndex + 1]; DescriptorBindingMapping = new List <DescriptorSetInfo>(); for (int i = 0; i < resourceGroups.Count; i++) { var resourceGroupName = resourceGroups[i] == "Globals" ? pipelineStateDescription.RootSignature.EffectDescriptorSetReflection.DefaultSetSlot : resourceGroups[i]; var layoutIndex = resourceGroups[i] == null ? 0 : layouts.FindIndex(x => x.Name == resourceGroupName); // Check if the resource group is used by the shader if (layoutIndex == -1) { continue; } var sourceEntries = layouts[layoutIndex].Layout.Entries; for (int sourceBinding = 0; sourceBinding < sourceEntries.Count; sourceBinding++) { var sourceEntry = sourceEntries[sourceBinding]; int destinationBinding; if (destinationBindings.TryGetValue(sourceEntry.Key.Name, out destinationBinding)) { destinationEntries[destinationBinding] = sourceEntry; // No need to umpdate immutable samplers if (sourceEntry.Class == EffectParameterClass.Sampler && sourceEntry.ImmutableSampler != null) { continue; } DescriptorBindingMapping.Add(new DescriptorSetInfo { SourceSet = layoutIndex, SourceBinding = sourceBinding, DestinationBinding = destinationBinding, DescriptorType = VulkanConvertExtensions.ConvertDescriptorType(sourceEntry.Class, sourceEntry.Type), ResourceElementIsInteger = sourceEntry.ElementType != EffectParameterType.Float && sourceEntry.ElementType != EffectParameterType.Double, }); } } } // Create default sampler, used by texture and buffer loads destinationEntries[0] = new DescriptorSetLayoutBuilder.Entry { Class = EffectParameterClass.Sampler, Type = EffectParameterType.Sampler, ImmutableSampler = GraphicsDevice.SamplerStates.PointWrap, ArraySize = 1, }; // Create descriptor set layout NativeDescriptorSetLayout = DescriptorSetLayout.CreateNativeDescriptorSetLayout(GraphicsDevice, destinationEntries, out DescriptorTypeCounts); // Create pipeline layout var nativeDescriptorSetLayout = NativeDescriptorSetLayout; var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo { StructureType = StructureType.PipelineLayoutCreateInfo, SetLayoutCount = 1, SetLayouts = new IntPtr(&nativeDescriptorSetLayout) }; NativeLayout = GraphicsDevice.NativeDevice.CreatePipelineLayout(ref pipelineLayoutCreateInfo); }
internal static unsafe extern Result vkCreatePipelineLayout(Device device, PipelineLayoutCreateInfo* createInfo, AllocationCallbacks* allocator, PipelineLayout* pipelineLayout);
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[] 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); }
public static PipelineLayout CreatePipelineLayout(Graphics g, params DescriptorSetLayout[] setLayouts) { var layoutCreateInfo = new PipelineLayoutCreateInfo(setLayouts); return(g.Context.Device.CreatePipelineLayout(layoutCreateInfo)); }
//[HandleProcessCorruptedStateExceptionsAttribute, SecurityCriticalAttribute] private unsafe void Recreate() { errorDuringCreate = false; if (Description.RootSignature == null) { return; } PipelineShaderStageCreateInfo[] stages; // create render pass bool hasDepthStencilAttachment = Description.Output.DepthStencilFormat != PixelFormat.None; var renderTargetCount = Description.Output.RenderTargetCount; var attachmentCount = renderTargetCount; if (hasDepthStencilAttachment) { attachmentCount++; } var attachments = new AttachmentDescription[attachmentCount]; var colorAttachmentReferences = new AttachmentReference[renderTargetCount]; fixed(PixelFormat *renderTargetFormat = &Description.Output.RenderTargetFormat0) fixed(BlendStateRenderTargetDescription * blendDescription = &Description.BlendState.RenderTarget0) { for (int i = 0; i < renderTargetCount; i++) { var currentBlendDesc = Description.BlendState.IndependentBlendEnable ? (blendDescription + i) : blendDescription; attachments[i] = new AttachmentDescription { Format = VulkanConvertExtensions.ConvertPixelFormat(*(renderTargetFormat + i)), Samples = SampleCountFlags.Sample1, LoadOperation = currentBlendDesc->BlendEnable ? AttachmentLoadOperation.Load : AttachmentLoadOperation.DontCare, // TODO VULKAN: Only if any destination blend? StoreOperation = AttachmentStoreOperation.Store, StencilLoadOperation = AttachmentLoadOperation.DontCare, StencilStoreOperation = AttachmentStoreOperation.DontCare, InitialLayout = ImageLayout.ColorAttachmentOptimal, FinalLayout = ImageLayout.ColorAttachmentOptimal, }; colorAttachmentReferences[i] = new AttachmentReference { Attachment = (uint)i, Layout = ImageLayout.ColorAttachmentOptimal, }; } } if (hasDepthStencilAttachment) { attachments[attachmentCount - 1] = new AttachmentDescription { Format = Texture.GetFallbackDepthStencilFormat(GraphicsDevice, VulkanConvertExtensions.ConvertPixelFormat(Description.Output.DepthStencilFormat)), Samples = SampleCountFlags.Sample1, LoadOperation = AttachmentLoadOperation.Load, // TODO VULKAN: Only if depth read enabled? StoreOperation = AttachmentStoreOperation.Store, // TODO VULKAN: Only if depth write enabled? StencilLoadOperation = AttachmentLoadOperation.DontCare, // TODO VULKAN: Handle stencil StencilStoreOperation = AttachmentStoreOperation.DontCare, InitialLayout = ImageLayout.DepthStencilAttachmentOptimal, FinalLayout = ImageLayout.DepthStencilAttachmentOptimal, }; } var depthAttachmentReference = new AttachmentReference { Attachment = (uint)attachments.Length - 1, Layout = ImageLayout.DepthStencilAttachmentOptimal, }; var subpass = new SubpassDescription { PipelineBindPoint = PipelineBindPoint.Graphics, ColorAttachmentCount = (uint)renderTargetCount, ColorAttachments = colorAttachmentReferences.Length > 0 ? new IntPtr(Interop.Fixed(colorAttachmentReferences)) : IntPtr.Zero, DepthStencilAttachment = hasDepthStencilAttachment ? new IntPtr(&depthAttachmentReference) : IntPtr.Zero, }; var renderPassCreateInfo = new RenderPassCreateInfo { StructureType = StructureType.RenderPassCreateInfo, AttachmentCount = (uint)attachmentCount, Attachments = attachments.Length > 0 ? new IntPtr(Interop.Fixed(attachments)) : IntPtr.Zero, SubpassCount = 1, Subpasses = new IntPtr(&subpass) }; // create pipeline layout // Remap descriptor set indices to those in the shader. This ordering generated by the ShaderCompiler var resourceGroups = Description.EffectBytecode.Reflection.ResourceBindings.Select(x => x.ResourceGroup ?? "Globals").Distinct().ToList(); ResourceGroupCount = resourceGroups.Count; var layouts = Description.RootSignature.EffectDescriptorSetReflection.Layouts; // Get binding indices used by the shader var destinationBindings = Description.EffectBytecode.Stages .SelectMany(x => BinarySerialization.Read <ShaderInputBytecode>(x.Data).ResourceBindings) .GroupBy(x => x.Key, x => x.Value) .ToDictionary(x => x.Key, x => x.First()); var maxBindingIndex = destinationBindings.Max(x => x.Value); var destinationEntries = new DescriptorSetLayoutBuilder.Entry[maxBindingIndex + 1]; DescriptorBindingMapping = new List <DescriptorSetInfo>(); for (int i = 0; i < resourceGroups.Count; i++) { var resourceGroupName = resourceGroups[i] == "Globals" ? Description.RootSignature.EffectDescriptorSetReflection.DefaultSetSlot : resourceGroups[i]; var layoutIndex = resourceGroups[i] == null ? 0 : layouts.FindIndex(x => x.Name == resourceGroupName); // Check if the resource group is used by the shader if (layoutIndex == -1) { continue; } var sourceEntries = layouts[layoutIndex].Layout.Entries; for (int sourceBinding = 0; sourceBinding < sourceEntries.Count; sourceBinding++) { var sourceEntry = sourceEntries[sourceBinding]; int destinationBinding; if (destinationBindings.TryGetValue(sourceEntry.Key.Name, out destinationBinding)) { destinationEntries[destinationBinding] = sourceEntry; // No need to umpdate immutable samplers if (sourceEntry.Class == EffectParameterClass.Sampler && sourceEntry.ImmutableSampler != null) { continue; } DescriptorBindingMapping.Add(new DescriptorSetInfo { SourceSet = layoutIndex, SourceBinding = sourceBinding, DestinationBinding = destinationBinding, DescriptorType = VulkanConvertExtensions.ConvertDescriptorType(sourceEntry.Class, sourceEntry.Type) }); } } } // Create default sampler, used by texture and buffer loads destinationEntries[0] = new DescriptorSetLayoutBuilder.Entry { Class = EffectParameterClass.Sampler, Type = EffectParameterType.Sampler, ImmutableSampler = GraphicsDevice.SamplerStates.PointWrap, ArraySize = 1, }; // Create descriptor set layout NativeDescriptorSetLayout = DescriptorSetLayout.CreateNativeDescriptorSetLayout(GraphicsDevice, destinationEntries, out DescriptorTypeCounts); // Create pipeline layout var nativeDescriptorSetLayout = NativeDescriptorSetLayout; var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo { StructureType = StructureType.PipelineLayoutCreateInfo, SetLayoutCount = 1, SetLayouts = new IntPtr(&nativeDescriptorSetLayout) }; // Create shader stages Dictionary <int, string> inputAttributeNames; // Note: important to pin this so that stages[x].Name is valid during this whole function void *defaultEntryPointData = Interop.Fixed(defaultEntryPoint); stages = CreateShaderStages(Description, out inputAttributeNames); var inputAttributes = new VertexInputAttributeDescription[Description.InputElements.Length]; int inputAttributeCount = 0; var inputBindings = new VertexInputBindingDescription[inputAttributes.Length]; int inputBindingCount = 0; for (int inputElementIndex = 0; inputElementIndex < inputAttributes.Length; inputElementIndex++) { var inputElement = Description.InputElements[inputElementIndex]; var slotIndex = inputElement.InputSlot; if (inputElement.InstanceDataStepRate > 1) { throw new NotImplementedException(); } Format format; int size; bool isCompressed; VulkanConvertExtensions.ConvertPixelFormat(inputElement.Format, out format, out size, out isCompressed); var location = inputAttributeNames.FirstOrDefault(x => x.Value == inputElement.SemanticName && inputElement.SemanticIndex == 0 || x.Value == inputElement.SemanticName + inputElement.SemanticIndex); if (location.Value != null) { inputAttributes[inputAttributeCount++] = new VertexInputAttributeDescription { Format = format, Offset = (uint)inputElement.AlignedByteOffset, Binding = (uint)inputElement.InputSlot, Location = (uint)location.Key }; } inputBindings[slotIndex].Binding = (uint)slotIndex; inputBindings[slotIndex].InputRate = inputElement.InputSlotClass == InputClassification.Vertex ? VertexInputRate.Vertex : VertexInputRate.Instance; // TODO VULKAN: This is currently an argument to Draw() overloads. if (inputBindings[slotIndex].Stride < inputElement.AlignedByteOffset + size) { inputBindings[slotIndex].Stride = (uint)(inputElement.AlignedByteOffset + size); } if (inputElement.InputSlot >= inputBindingCount) { inputBindingCount = inputElement.InputSlot + 1; } } var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { StructureType = StructureType.PipelineInputAssemblyStateCreateInfo, Topology = VulkanConvertExtensions.ConvertPrimitiveType(Description.PrimitiveType), PrimitiveRestartEnable = VulkanConvertExtensions.ConvertPrimitiveRestart(Description.PrimitiveType), }; // TODO VULKAN: Tessellation and multisampling var multisampleState = new PipelineMultisampleStateCreateInfo { StructureType = StructureType.PipelineMultisampleStateCreateInfo, RasterizationSamples = SampleCountFlags.Sample1 }; //var tessellationState = new PipelineTessellationStateCreateInfo(); var rasterizationState = new PipelineRasterizationStateCreateInfo { StructureType = StructureType.PipelineRasterizationStateCreateInfo, CullMode = VulkanConvertExtensions.ConvertCullMode(Description.RasterizerState.CullMode), FrontFace = Description.RasterizerState.FrontFaceCounterClockwise ? FrontFace.CounterClockwise : FrontFace.Clockwise, PolygonMode = VulkanConvertExtensions.ConvertFillMode(Description.RasterizerState.FillMode), DepthBiasEnable = true, // TODO VULKAN DepthBiasConstantFactor = Description.RasterizerState.DepthBias, DepthBiasSlopeFactor = Description.RasterizerState.SlopeScaleDepthBias, DepthBiasClamp = Description.RasterizerState.DepthBiasClamp, LineWidth = 1.0f, DepthClampEnable = !Description.RasterizerState.DepthClipEnable, RasterizerDiscardEnable = false, }; var depthStencilState = new PipelineDepthStencilStateCreateInfo { StructureType = StructureType.PipelineDepthStencilStateCreateInfo, DepthTestEnable = Description.DepthStencilState.DepthBufferEnable, StencilTestEnable = Description.DepthStencilState.StencilEnable, DepthWriteEnable = Description.DepthStencilState.DepthBufferWriteEnable, MinDepthBounds = 0.0f, MaxDepthBounds = 1.0f, DepthCompareOperation = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.DepthBufferFunction), Front = new StencilOperationState { CompareOperation = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.FrontFace.StencilFunction), DepthFailOperation = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilDepthBufferFail), FailOperation = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilFail), PassOperation = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilPass), CompareMask = Description.DepthStencilState.StencilMask, WriteMask = Description.DepthStencilState.StencilWriteMask }, Back = new StencilOperationState { CompareOperation = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.BackFace.StencilFunction), DepthFailOperation = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilDepthBufferFail), FailOperation = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilFail), PassOperation = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilPass), CompareMask = Description.DepthStencilState.StencilMask, WriteMask = Description.DepthStencilState.StencilWriteMask } }; var description = Description.BlendState; var colorBlendAttachments = new PipelineColorBlendAttachmentState[renderTargetCount]; var renderTargetBlendState = &description.RenderTarget0; for (int i = 0; i < renderTargetCount; i++) { colorBlendAttachments[i] = new PipelineColorBlendAttachmentState { BlendEnable = renderTargetBlendState->BlendEnable, AlphaBlendOperation = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->AlphaBlendFunction), ColorBlendOperation = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->ColorBlendFunction), DestinationAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaDestinationBlend), DestinationColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorDestinationBlend), SourceAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaSourceBlend), SourceColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorSourceBlend), ColorWriteMask = VulkanConvertExtensions.ConvertColorWriteChannels(renderTargetBlendState->ColorWriteChannels), }; if (description.IndependentBlendEnable) { renderTargetBlendState++; } } var viewportState = new PipelineViewportStateCreateInfo { StructureType = StructureType.PipelineViewportStateCreateInfo, ScissorCount = 1, ViewportCount = 1, }; fixed(void *dynamicStatesPointer = dynamicStates.Length == 0?null : dynamicStates, inputAttributesPointer = inputAttributes.Length == 0?null : inputAttributes, inputBindingsPointer = inputBindings.Length == 0?null : inputBindings, colorBlendAttachmentsPointer = colorBlendAttachments.Length == 0?null : colorBlendAttachments, stagesPointer = stages.Length == 0?null : stages) { var vertexInputState = new PipelineVertexInputStateCreateInfo { StructureType = StructureType.PipelineVertexInputStateCreateInfo, VertexAttributeDescriptionCount = (uint)inputAttributeCount, VertexAttributeDescriptions = (IntPtr)inputAttributesPointer, VertexBindingDescriptionCount = (uint)inputBindingCount, VertexBindingDescriptions = (IntPtr)inputBindingsPointer, }; var colorBlendState = new PipelineColorBlendStateCreateInfo { StructureType = StructureType.PipelineColorBlendStateCreateInfo, AttachmentCount = (uint)renderTargetCount, Attachments = (IntPtr)colorBlendAttachmentsPointer, }; var dynamicState = new PipelineDynamicStateCreateInfo { StructureType = StructureType.PipelineDynamicStateCreateInfo, DynamicStateCount = (uint)dynamicStates.Length, DynamicStates = (IntPtr)dynamicStatesPointer, }; var createInfo = new GraphicsPipelineCreateInfo { StructureType = StructureType.GraphicsPipelineCreateInfo, StageCount = (uint)stages.Length, Stages = (IntPtr)stagesPointer, //TessellationState = new IntPtr(&tessellationState), VertexInputState = new IntPtr(&vertexInputState), InputAssemblyState = new IntPtr(&inputAssemblyState), RasterizationState = new IntPtr(&rasterizationState), MultisampleState = new IntPtr(&multisampleState), DepthStencilState = new IntPtr(&depthStencilState), ColorBlendState = new IntPtr(&colorBlendState), DynamicState = new IntPtr(&dynamicState), ViewportState = new IntPtr(&viewportState), Subpass = 0, }; using (GraphicsDevice.QueueLock.ReadLock()) { NativeRenderPass = GraphicsDevice.NativeDevice.CreateRenderPass(ref renderPassCreateInfo); NativeLayout = GraphicsDevice.NativeDevice.CreatePipelineLayout(ref pipelineLayoutCreateInfo); createInfo.Layout = NativeLayout; createInfo.RenderPass = NativeRenderPass; try { NativePipeline = GraphicsDevice.NativeDevice.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo); } catch (Exception e) { errorDuringCreate = true; NativePipeline = Pipeline.Null; } } } // Cleanup shader modules for (int i = 0; i < stages.Length; i++) { GraphicsDevice.NativeDevice.DestroyShaderModule(stages[i].Module); } }
protected PipelineLayout CreatePipelineLayout() { var createInfo = new PipelineLayoutCreateInfo(); return(device.CreatePipelineLayout(createInfo)); }
public bool Create(string vsName, string fsName, VertexInputBindingDescription [] vbind, VertexInputAttributeDescription [] vatts) { Device dv = mDevices.GetLogicalDevice(); PipelineShaderStageCreateInfo plssciv = new PipelineShaderStageCreateInfo( ShaderStages.Vertex, mShaders[vsName], "main", null); PipelineShaderStageCreateInfo plsscif = new PipelineShaderStageCreateInfo( ShaderStages.Fragment, mShaders[fsName], "main", null); PipelineVertexInputStateCreateInfo plvisci = new PipelineVertexInputStateCreateInfo( vbind, vatts); PipelineInputAssemblyStateCreateInfo pliasci = new PipelineInputAssemblyStateCreateInfo( PrimitiveTopology.TriangleList); Viewport vp = new Viewport(0, 0, 1280, 720, 0f, 1f); Rect2D scissor = new Rect2D(Offset2D.Zero, mDevices.GetChainExtent()); PipelineViewportStateCreateInfo plvpsci = new PipelineViewportStateCreateInfo( new Viewport[1] { vp }, new Rect2D[1] { scissor }); PipelineRasterizationStateCreateInfo plrsci = new PipelineRasterizationStateCreateInfo(); plrsci.LineWidth = 1; PipelineMultisampleStateCreateInfo plmssci = new PipelineMultisampleStateCreateInfo(); plmssci.RasterizationSamples = SampleCounts.Count1; PipelineColorBlendAttachmentState plcbas = new PipelineColorBlendAttachmentState(); plcbas.ColorWriteMask = ColorComponents.All; plcbas.BlendEnable = false; PipelineColorBlendStateCreateInfo plcbsci = new PipelineColorBlendStateCreateInfo(); plcbsci.LogicOpEnable = false; plcbsci.LogicOp = LogicOp.Copy; plcbsci.Attachments = new PipelineColorBlendAttachmentState[1] { plcbas }; plcbsci.BlendConstants = ColorF4.Zero; PipelineLayoutCreateInfo pllci = new PipelineLayoutCreateInfo( mDevices.GetDSLs()); mPipeLayout = dv.CreatePipelineLayout(pllci); AttachmentDescription ad = new AttachmentDescription(); ad.Format = Format.B8G8R8A8UNorm; ad.Samples = SampleCounts.Count1; ad.LoadOp = AttachmentLoadOp.Clear; ad.StoreOp = AttachmentStoreOp.Store; ad.StencilLoadOp = AttachmentLoadOp.DontCare; ad.StencilStoreOp = AttachmentStoreOp.DontCare; ad.InitialLayout = ImageLayout.Undefined; ad.FinalLayout = ImageLayout.PresentSrcKhr; AttachmentReference ar = new AttachmentReference(0, ImageLayout.ColorAttachmentOptimal); SubpassDescription spd = new SubpassDescription(); spd.ColorAttachments = new AttachmentReference[1] { ar }; SubpassDependency spdc = new SubpassDependency(); spdc.SrcSubpass = Constant.SubpassExternal; spdc.DstSubpass = 0; spdc.SrcStageMask = PipelineStages.ColorAttachmentOutput; spdc.SrcAccessMask = 0; spdc.DstStageMask = PipelineStages.ColorAttachmentOutput; spdc.DstAccessMask = Accesses.ColorAttachmentRead | Accesses.ColorAttachmentWrite; RenderPassCreateInfo rpci = new RenderPassCreateInfo( new SubpassDescription[1] { spd }, new AttachmentDescription[1] { ad }, new SubpassDependency[1] { spdc }); mRenderPass = dv.CreateRenderPass(rpci); GraphicsPipelineCreateInfo gplci = new GraphicsPipelineCreateInfo(); gplci.Stages = new PipelineShaderStageCreateInfo[2] { plssciv, plsscif }; gplci.VertexInputState = plvisci; gplci.InputAssemblyState = pliasci; gplci.ViewportState = plvpsci; gplci.RasterizationState = plrsci; gplci.MultisampleState = plmssci; gplci.DepthStencilState = null; gplci.ColorBlendState = plcbsci; gplci.DynamicState = null; gplci.Layout = mPipeLayout; gplci.RenderPass = mRenderPass; gplci.Subpass = 0; gplci.BasePipelineHandle = null; gplci.BasePipelineIndex = -1; mPipe = dv.CreateGraphicsPipeline(gplci); CreateSyncObjects(); return(true); }
private void CreateGraphicsPipeline() { // Shader stages var vertShaderCode = System.IO.File.ReadAllBytes("Shaders/vert.spv"); var fragShaderCode = System.IO.File.ReadAllBytes("Shaders/frag.spv"); var vertShaderModule = vkDevice.CreateShaderModule(vertShaderCode); var fragShaderModule = vkDevice.CreateShaderModule(fragShaderCode); var vertShaderStageInfo = new PipelineShaderStageCreateInfo() { Stage = ShaderStageFlags.Vertex, Module = vertShaderModule, Name = "main", }; var fragShaderStageInfo = new PipelineShaderStageCreateInfo() { Stage = ShaderStageFlags.Fragment, Module = fragShaderModule, Name = "main", }; var shaderStages = new PipelineShaderStageCreateInfo[] { vertShaderStageInfo, fragShaderStageInfo }; // VertexInput var vertexInputInfo = new PipelineVertexInputStateCreateInfo() { VertexBindingDescriptionCount = 0, VertexBindingDescriptions = null, VertexAttributeDescriptionCount = 0, VertexAttributeDescriptions = null, }; var inputAssembly = new PipelineInputAssemblyStateCreateInfo() { Topology = PrimitiveTopology.TriangleList, PrimitiveRestartEnable = false, }; var viewport = new Viewport() { X = 0f, Y = 0f, Width = (float)vkSwapChainExtent.Width, Height = (float)vkSwapChainExtent.Height, MinDepth = 0f, MaxDepth = 1f, }; var scissor = new Rect2D() { Offset = new Offset2D() { X = 0, Y = 0 }, Extent = vkSwapChainExtent, }; var viewportState = new PipelineViewportStateCreateInfo() { ViewportCount = 1, Viewports = new Viewport[] { viewport }, ScissorCount = 1, Scissors = new Rect2D[] { scissor }, }; var rasterizer = new PipelineRasterizationStateCreateInfo() { DepthClampEnable = false, RasterizerDiscardEnable = false, PolygonMode = PolygonMode.Fill, LineWidth = 1f, CullMode = CullModeFlags.Back, FrontFace = FrontFace.Clockwise, DepthBiasEnable = false, DepthBiasConstantFactor = 0f, DepthBiasClamp = 0f, DepthBiasSlopeFactor = 0f, }; var multisampling = new PipelineMultisampleStateCreateInfo() { SampleShadingEnable = false, RasterizationSamples = SampleCountFlags.Count1, MinSampleShading = 1f, SampleMask = null, AlphaToCoverageEnable = false, AlphaToOneEnable = false, }; var colorBlendAttachmend = new PipelineColorBlendAttachmentState() { ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A, BlendEnable = false, }; var colorBlending = new PipelineColorBlendStateCreateInfo() { LogicOpEnable = false, LogicOp = LogicOp.Copy, Attachments = new PipelineColorBlendAttachmentState[] { colorBlendAttachmend }, BlendConstants = new float[] { 0f, 0f, 0f, 0f }, }; var pipelineLayoutInfo = new PipelineLayoutCreateInfo() { SetLayoutCount = 0, PushConstantRangeCount = 0, }; vkPipelineLayout = vkDevice.CreatePipelineLayout(pipelineLayoutInfo); var pipelineInfo = new GraphicsPipelineCreateInfo() { StageCount = 2, Stages = shaderStages, VertexInputState = vertexInputInfo, InputAssemblyState = inputAssembly, ViewportState = viewportState, RasterizationState = rasterizer, MultisampleState = multisampling, DepthStencilState = null, ColorBlendState = colorBlending, DynamicState = null, Layout = vkPipelineLayout, RenderPass = vkRenderPass, Subpass = 0, BasePipelineHandle = null, BasePipelineIndex = -1, }; vkGraphicsPipeline = vkDevice.CreateGraphicsPipelines(null, new GraphicsPipelineCreateInfo[] { pipelineInfo })[0]; }
private unsafe void CreatePipelineLayout(PipelineStateDescription pipelineStateDescription) { // Remap descriptor set indices to those in the shader. This ordering generated by the ShaderCompiler var resourceGroups = pipelineStateDescription.EffectBytecode.Reflection.ResourceBindings.Select(x => x.ResourceGroup ?? "Globals").Distinct().ToList(); ResourceGroupCount = resourceGroups.Count; var layouts = pipelineStateDescription.RootSignature.EffectDescriptorSetReflection.Layouts; // Get binding indices used by the shader var destinationBindings = pipelineStateDescription.EffectBytecode.Stages .SelectMany(x => BinarySerialization.Read<ShaderInputBytecode>(x.Data).ResourceBindings) .GroupBy(x => x.Key, x => x.Value) .ToDictionary(x => x.Key, x => x.First()); var maxBindingIndex = destinationBindings.Max(x => x.Value); var destinationEntries = new DescriptorSetLayoutBuilder.Entry[maxBindingIndex + 1]; DescriptorBindingMapping = new List<DescriptorSetInfo>(); for (int i = 0; i < resourceGroups.Count; i++) { var resourceGroupName = resourceGroups[i] == "Globals" ? pipelineStateDescription.RootSignature.EffectDescriptorSetReflection.DefaultSetSlot : resourceGroups[i]; var layoutIndex = resourceGroups[i] == null ? 0 : layouts.FindIndex(x => x.Name == resourceGroupName); // Check if the resource group is used by the shader if (layoutIndex == -1) continue; var sourceEntries = layouts[layoutIndex].Layout.Entries; for (int sourceBinding = 0; sourceBinding < sourceEntries.Count; sourceBinding++) { var sourceEntry = sourceEntries[sourceBinding]; int destinationBinding; if (destinationBindings.TryGetValue(sourceEntry.Key.Name, out destinationBinding)) { destinationEntries[destinationBinding] = sourceEntry; // No need to umpdate immutable samplers if (sourceEntry.Class == EffectParameterClass.Sampler && sourceEntry.ImmutableSampler != null) { continue; } DescriptorBindingMapping.Add(new DescriptorSetInfo { SourceSet = layoutIndex, SourceBinding = sourceBinding, DestinationBinding = destinationBinding, DescriptorType = VulkanConvertExtensions.ConvertDescriptorType(sourceEntry.Class, sourceEntry.Type) }); } } } // Create default sampler, used by texture and buffer loads destinationEntries[0] = new DescriptorSetLayoutBuilder.Entry { Class = EffectParameterClass.Sampler, Type = EffectParameterType.Sampler, ImmutableSampler = GraphicsDevice.SamplerStates.PointWrap, ArraySize = 1, }; // Create descriptor set layout NativeDescriptorSetLayout = DescriptorSetLayout.CreateNativeDescriptorSetLayout(GraphicsDevice, destinationEntries, out DescriptorTypeCounts); // Create pipeline layout var nativeDescriptorSetLayout = NativeDescriptorSetLayout; var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo { StructureType = StructureType.PipelineLayoutCreateInfo, SetLayoutCount = 1, SetLayouts = new IntPtr(&nativeDescriptorSetLayout) }; NativeLayout = GraphicsDevice.NativeDevice.CreatePipelineLayout(ref pipelineLayoutCreateInfo); }