private Pipeline CreateGraphicsPipeline() { var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo(PrimitiveTopology.PointList); var vertexInputState = new PipelineVertexInputStateCreateInfo( new[] { new VertexInputBindingDescription(0, Interop.SizeOf <VertexParticle>(), VertexInputRate.Vertex) }, new[] { new VertexInputAttributeDescription(0, 0, Format.R32G32SFloat, 0), new VertexInputAttributeDescription(1, 0, Format.R32G32SFloat, 8), new VertexInputAttributeDescription(2, 0, Format.R32G32B32SFloat, 16) }); var rasterizationState = new PipelineRasterizationStateCreateInfo { PolygonMode = PolygonMode.Fill, CullMode = CullModes.None, FrontFace = FrontFace.CounterClockwise, LineWidth = 1.0f }; // Additive blending. var blendAttachmentState = new PipelineColorBlendAttachmentState { BlendEnable = true, ColorWriteMask = ColorComponents.All, ColorBlendOp = BlendOp.Add, SrcColorBlendFactor = BlendFactor.One, DstColorBlendFactor = BlendFactor.One, AlphaBlendOp = BlendOp.Add, SrcAlphaBlendFactor = BlendFactor.SrcAlpha, DstAlphaBlendFactor = BlendFactor.DstAlpha }; var colorBlendState = new PipelineColorBlendStateCreateInfo(new[] { blendAttachmentState }); var depthStencilState = new PipelineDepthStencilStateCreateInfo(); var viewportState = new PipelineViewportStateCreateInfo( new Viewport(0, 0, Host.Width, Host.Height), new Rect2D(0, 0, Host.Width, Host.Height)); var multisampleState = new PipelineMultisampleStateCreateInfo { RasterizationSamples = SampleCounts.Count1 }; var pipelineShaderStages = new[] { new PipelineShaderStageCreateInfo(ShaderStages.Vertex, Content.Load <ShaderModule>("shader.vert.spv"), "main"), new PipelineShaderStageCreateInfo(ShaderStages.Fragment, Content.Load <ShaderModule>("shader.frag.spv"), "main"), }; var pipelineCreateInfo = new GraphicsPipelineCreateInfo(_graphicsPipelineLayout, _renderPass, 0, pipelineShaderStages, inputAssemblyState, vertexInputState, rasterizationState, viewportState: viewportState, multisampleState: multisampleState, depthStencilState: depthStencilState, colorBlendState: colorBlendState); return(Context.Device.CreateGraphicsPipeline(pipelineCreateInfo)); }
private Pipeline CreateGraphicsPipeline() { ShaderModule vertexShader = Content.Load <ShaderModule>("Shader.vert.spv"); ShaderModule fragmentShader = Content.Load <ShaderModule>("Shader.frag.spv"); var shaderStageCreateInfos = new[] { new PipelineShaderStageCreateInfo(ShaderStages.Vertex, vertexShader, "main"), new PipelineShaderStageCreateInfo(ShaderStages.Fragment, fragmentShader, "main") }; var vertexInputStateCreateInfo = new PipelineVertexInputStateCreateInfo(); var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo(PrimitiveTopology.TriangleList); var viewportStateCreateInfo = new PipelineViewportStateCreateInfo( new Viewport(0, 0, Host.Width, Host.Height), new Rect2D(0, 0, Host.Width, Host.Height)); var rasterizationStateCreateInfo = new PipelineRasterizationStateCreateInfo { PolygonMode = PolygonMode.Fill, CullMode = CullModes.Back, FrontFace = FrontFace.CounterClockwise, LineWidth = 1.0f }; var multisampleStateCreateInfo = new PipelineMultisampleStateCreateInfo { RasterizationSamples = SampleCounts.Count1, MinSampleShading = 1.0f }; var colorBlendAttachmentState = new PipelineColorBlendAttachmentState { SrcColorBlendFactor = BlendFactor.One, DstColorBlendFactor = BlendFactor.Zero, ColorBlendOp = BlendOp.Add, SrcAlphaBlendFactor = BlendFactor.One, DstAlphaBlendFactor = BlendFactor.Zero, AlphaBlendOp = BlendOp.Add, ColorWriteMask = ColorComponents.All }; var colorBlendStateCreateInfo = new PipelineColorBlendStateCreateInfo( new[] { colorBlendAttachmentState }); var pipelineCreateInfo = new GraphicsPipelineCreateInfo( _pipelineLayout, _renderPass, 0, shaderStageCreateInfos, inputAssemblyStateCreateInfo, vertexInputStateCreateInfo, rasterizationStateCreateInfo, viewportState: viewportStateCreateInfo, multisampleState: multisampleStateCreateInfo, colorBlendState: colorBlendStateCreateInfo); return(Context.Device.CreateGraphicsPipeline(pipelineCreateInfo)); }
private unsafe Pipeline(PipelineSettings settings, VulkanRenderer renderer) { _renderer = renderer; Device device = _renderer.Params.Device; AllocationCallbacks *allocator = (AllocationCallbacks *)_renderer.Params.AllocationCallbacks.ToPointer(); Vk vk = _renderer.Vk; PipelineShaderStageCreateInfo *shaderStages = stackalloc PipelineShaderStageCreateInfo[2] { _renderer.Shader.VertexShaderStage, _renderer.Shader.FragmentShaderStage }; PipelineVertexInputStateCreateInfo vertexInputState = VertexInputState(_bindingDescription, _attributeDescriptions); PipelineInputAssemblyStateCreateInfo inputAssemblyState = InputAssemblyState(settings); PipelineRasterizationStateCreateInfo rasterizationState = RasterizationState(settings); PipelineMultisampleStateCreateInfo multisampleState = MultisampleState(); PipelineColorBlendAttachmentState colourBlendAttachmentState = ColorBlendAttachmentState(settings); PipelineColorBlendStateCreateInfo colourBlendState = ColourBlendState(colourBlendAttachmentState); PipelineViewportStateCreateInfo viewportState = ViewportState(); PipelineDynamicStateCreateInfo dynamicState = DynamicStates(DynamicState.Viewport, DynamicState.Scissor); PipelineDepthStencilStateCreateInfo depthStencilState = DepthStencilState(settings); GraphicsPipelineCreateInfo pipelineCreateInfo = new() { SType = StructureType.GraphicsPipelineCreateInfo, StageCount = 2, PStages = shaderStages, PVertexInputState = &vertexInputState, PInputAssemblyState = &inputAssemblyState, PRasterizationState = &rasterizationState, PMultisampleState = &multisampleState, PColorBlendState = &colourBlendState, PViewportState = &viewportState, PDynamicState = &dynamicState, PDepthStencilState = &depthStencilState, PTessellationState = null, Layout = _renderer.Shader.PipelineLayout, RenderPass = _renderer.Params.RenderPass, Subpass = _renderer.Params.SubpassIndex, BasePipelineIndex = -1, BasePipelineHandle = default }; _renderer.AssertVulkan(vk.CreateGraphicsPipelines(device, default, 1, pipelineCreateInfo, allocator, out _handle));
private unsafe void Recreate() { errorDuringCreate = false; if (Description.RootSignature == null) { return; } PipelineShaderStageCreateInfo[] stages; // try to recover from a rare failure? bool retry = false; // it appears pipeline creation is just not thread safe :( lock (PipeLock) { Xenko.Shaders.Compiler.EffectCompilerCache.CompileSynchronization.Wait(); CreateRenderPass(Description); CreatePipelineLayout(Description); // Create shader stages Dictionary <int, string> inputAttributeNames; 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 = true, }; // TODO VULKAN: Tessellation and multisampling var multisampleState = new PipelineMultisampleStateCreateInfo { StructureType = StructureType.PipelineMultisampleStateCreateInfo, RasterizationSamples = SampleCountFlags.Sample1 }; //var tessellationState = new PipelineTessellationStateCreateInfo(); var rasterizationState = CreateRasterizationState(Description.RasterizerState); var depthStencilState = CreateDepthStencilState(Description); var description = Description.BlendState; var renderTargetCount = Description.Output.RenderTargetCount; 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, Layout = NativeLayout, 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), RenderPass = NativeRenderPass, Subpass = 0, }; try { lock (GraphicsDevice.QueueLock) { NativePipeline = GraphicsDevice.NativeDevice.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo); } } catch (AccessViolationException ae) { // this happens extremely rarely and might be recoverable by reattempting the recreate retry = true; } 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); } if (retry) { Recreate(); } }
private void CreatePipeline() { var dynamicStates = new [] { DynamicState.Viewport, DynamicState.Scissor }; var entryPointName = System.Text.Encoding.UTF8.GetBytes("main\0"); fixed (byte* entryPointNamePointer = &entryPointName[0]) fixed (DynamicState* dynamicStatesPointer = &dynamicStates[0]) fixed (VertexInputAttributeDescription* vertexAttibutesPointer = &vertexAttributes[0]) fixed (VertexInputBindingDescription* vertexBindingsPointer = &vertexBindings[0]) { var dynamicState = new PipelineDynamicStateCreateInfo { StructureType = StructureType.PipelineDynamicStateCreateInfo, DynamicStateCount = (uint)dynamicStates.Length, DynamicStates = new IntPtr(dynamicStatesPointer) }; var viewportState = new PipelineViewportStateCreateInfo { StructureType = StructureType.PipelineViewportStateCreateInfo, ScissorCount = 1, ViewportCount = 1, }; var vertexInputState = new PipelineVertexInputStateCreateInfo { StructureType = StructureType.PipelineVertexInputStateCreateInfo, VertexAttributeDescriptionCount = (uint)vertexAttributes.Length, VertexAttributeDescriptions = new IntPtr(vertexAttibutesPointer), VertexBindingDescriptionCount = (uint)vertexBindings.Length, VertexBindingDescriptions = new IntPtr(vertexBindingsPointer), }; var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { StructureType = StructureType.PipelineInputAssemblyStateCreateInfo, Topology = PrimitiveTopology.TriangleList }; var rasterizerState = new PipelineRasterizationStateCreateInfo { StructureType = StructureType.PipelineRasterizationStateCreateInfo, PolygonMode = PolygonMode.Fill, CullMode = CullModeFlags.None, FrontFace = FrontFace.Clockwise, LineWidth = 1.0f, }; var colorBlendAttachment = new PipelineColorBlendAttachmentState { ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A }; var blendState = new PipelineColorBlendStateCreateInfo { StructureType = StructureType.PipelineColorBlendStateCreateInfo, AttachmentCount = 1, Attachments = new IntPtr(&colorBlendAttachment) }; var depthStencilState = new PipelineDepthStencilStateCreateInfo { StructureType = StructureType.PipelineDepthStencilStateCreateInfo, DepthTestEnable = false, DepthWriteEnable = true, DepthCompareOperation = CompareOperation.LessOrEqual, Back = new StencilOperationState { CompareOperation = CompareOperation.Always }, Front = new StencilOperationState { CompareOperation = CompareOperation.Always } }; var multisampleState = new PipelineMultisampleStateCreateInfo { StructureType = StructureType.PipelineMultisampleStateCreateInfo, RasterizationSamples = SampleCountFlags.Sample1, }; var shaderStages = new[] { new PipelineShaderStageCreateInfo { StructureType = StructureType.PipelineShaderStageCreateInfo, Name = new IntPtr(entryPointNamePointer), Stage = ShaderStageFlags.Vertex, Module = CreateVertexShader() }, new PipelineShaderStageCreateInfo { StructureType = StructureType.PipelineShaderStageCreateInfo, Name = new IntPtr(entryPointNamePointer), Stage = ShaderStageFlags.Fragment, Module = CreateFragmentShader() } }; fixed (PipelineShaderStageCreateInfo* shaderStagesPointer = &shaderStages[0]) { var createInfo = new GraphicsPipelineCreateInfo { StructureType = StructureType.GraphicsPipelineCreateInfo, Layout = pipelineLayout, DynamicState = new IntPtr(&dynamicState), ViewportState = new IntPtr(&viewportState), VertexInputState = new IntPtr(&vertexInputState), InputAssemblyState = new IntPtr(&inputAssemblyState), RasterizationState = new IntPtr(&rasterizerState), ColorBlendState = new IntPtr(&blendState), DepthStencilState = new IntPtr(&depthStencilState), MultisampleState = new IntPtr(&multisampleState), StageCount = (uint)shaderStages.Length, Stages = new IntPtr(shaderStagesPointer), RenderPass = renderPass }; pipeline = device.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo); } foreach (var shaderStage in shaderStages) { device.DestroyShaderModule(shaderStage.Module); } } }
private void CreatePipeline() { var dynamicStates = new [] { DynamicState.Viewport, DynamicState.Scissor }; var entryPointName = System.Text.Encoding.UTF8.GetBytes("main\0"); fixed(byte *entryPointNamePointer = &entryPointName[0]) fixed(DynamicState * dynamicStatesPointer = &dynamicStates[0]) fixed(VertexInputAttributeDescription * vertexAttibutesPointer = &vertexAttributes[0]) fixed(VertexInputBindingDescription * vertexBindingsPointer = &vertexBindings[0]) { var dynamicState = new PipelineDynamicStateCreateInfo { StructureType = StructureType.PipelineDynamicStateCreateInfo, DynamicStateCount = (uint)dynamicStates.Length, DynamicStates = new IntPtr(dynamicStatesPointer) }; var viewportState = new PipelineViewportStateCreateInfo { StructureType = StructureType.PipelineViewportStateCreateInfo, ScissorCount = 1, ViewportCount = 1, }; var vertexInputState = new PipelineVertexInputStateCreateInfo { StructureType = StructureType.PipelineVertexInputStateCreateInfo, VertexAttributeDescriptionCount = (uint)vertexAttributes.Length, VertexAttributeDescriptions = new IntPtr(vertexAttibutesPointer), VertexBindingDescriptionCount = (uint)vertexBindings.Length, VertexBindingDescriptions = new IntPtr(vertexBindingsPointer), }; var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { StructureType = StructureType.PipelineInputAssemblyStateCreateInfo, Topology = PrimitiveTopology.TriangleList }; var rasterizerState = new PipelineRasterizationStateCreateInfo { StructureType = StructureType.PipelineRasterizationStateCreateInfo, PolygonMode = PolygonMode.Fill, CullMode = CullModeFlags.None, FrontFace = FrontFace.Clockwise, LineWidth = 1.0f, }; var colorBlendAttachment = new PipelineColorBlendAttachmentState { ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A }; var blendState = new PipelineColorBlendStateCreateInfo { StructureType = StructureType.PipelineColorBlendStateCreateInfo, AttachmentCount = 1, Attachments = new IntPtr(&colorBlendAttachment) }; var depthStencilState = new PipelineDepthStencilStateCreateInfo { StructureType = StructureType.PipelineDepthStencilStateCreateInfo, DepthTestEnable = false, DepthWriteEnable = true, DepthCompareOperation = CompareOperation.LessOrEqual, Back = new StencilOperationState { CompareOperation = CompareOperation.Always }, Front = new StencilOperationState { CompareOperation = CompareOperation.Always } }; var multisampleState = new PipelineMultisampleStateCreateInfo { StructureType = StructureType.PipelineMultisampleStateCreateInfo, RasterizationSamples = SampleCountFlags.Sample1, }; var shaderStages = new[] { new PipelineShaderStageCreateInfo { StructureType = StructureType.PipelineShaderStageCreateInfo, Name = new IntPtr(entryPointNamePointer), Stage = ShaderStageFlags.Vertex, Module = CreateVertexShader() }, new PipelineShaderStageCreateInfo { StructureType = StructureType.PipelineShaderStageCreateInfo, Name = new IntPtr(entryPointNamePointer), Stage = ShaderStageFlags.Fragment, Module = CreateFragmentShader() } }; fixed(PipelineShaderStageCreateInfo *shaderStagesPointer = &shaderStages[0]) { var createInfo = new GraphicsPipelineCreateInfo { StructureType = StructureType.GraphicsPipelineCreateInfo, Layout = pipelineLayout, DynamicState = new IntPtr(&dynamicState), ViewportState = new IntPtr(&viewportState), VertexInputState = new IntPtr(&vertexInputState), InputAssemblyState = new IntPtr(&inputAssemblyState), RasterizationState = new IntPtr(&rasterizerState), ColorBlendState = new IntPtr(&blendState), DepthStencilState = new IntPtr(&depthStencilState), MultisampleState = new IntPtr(&multisampleState), StageCount = (uint)shaderStages.Length, Stages = new IntPtr(shaderStagesPointer), RenderPass = renderPass }; pipeline = device.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo); } foreach (var shaderStage in shaderStages) { device.DestroyShaderModule(shaderStage.Module); } } }
protected virtual void CreateGraphicsPipeline() { var shaderStages = CreateShaderStages(); var vertexInputInfo = GetVertexInputInfo(); var inputAssembly = new PipelineInputAssemblyStateCreateInfo { Topology = PrimitiveTopology.TriangleList, PrimitiveRestartEnable = false }; var viewport = new Viewport { X = 0f, Y = 0f, Width = extent.Width, Height = extent.Height, MinDepth = 0f, MaxDepth = 1f }; var scissor = new Rect2D { Offset = new Offset2D { X = 0, Y = 0 }, Extent = extent }; 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.CounterClockwise, DepthBiasEnable = false, DepthBiasConstantFactor = 0f, DepthBiasClamp = 0f, DepthBiasSlopeFactor = 0f }; var msaa = new PipelineMultisampleStateCreateInfo { SampleShadingEnable = false, RasterizationSamples = SampleCountFlags.Count1, MinSampleShading = 1f, AlphaToCoverageEnable = false, AlphaToOneEnable = false }; var colorBlendAttachment = new PipelineColorBlendAttachmentState { ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A, BlendEnable = false, SrcColorBlendFactor = BlendFactor.One, DstColorBlendFactor = BlendFactor.Zero, ColorBlendOp = BlendOp.Add, SrcAlphaBlendFactor = BlendFactor.One, DstAlphaBlendFactor = BlendFactor.Zero, AlphaBlendOp = BlendOp.Add }; var colorBlending = new PipelineColorBlendStateCreateInfo { LogicOpEnable = false, LogicOp = LogicOp.Copy, AttachmentCount = 1, Attachments = new PipelineColorBlendAttachmentState[] { colorBlendAttachment }, }; var layoutInfo = GetPipelineLayoutInfo(); pipelineLayout = device.CreatePipelineLayout(layoutInfo); var pipelineCreateInfo = new GraphicsPipelineCreateInfo { StageCount = (shaderStages == null ? 0 : (uint)shaderStages.Length), Stages = shaderStages, VertexInputState = vertexInputInfo, InputAssemblyState = inputAssembly, ViewportState = viewportState, RasterizationState = rasterizer, MultisampleState = msaa, ColorBlendState = colorBlending, Layout = pipelineLayout, RenderPass = renderPass, Subpass = 0, BasePipelineHandle = null, BasePipelineIndex = -1 }; graphicsPipeline = device.CreateGraphicsPipelines(null, new GraphicsPipelineCreateInfo[] { pipelineCreateInfo })[0]; if (shaderStages == null) { return; } foreach (var stage in shaderStages) { device.DestroyShaderModule(stage.Module); } }
public void CreateGraphicsPipeline() { var attachment = new AttachmentDescription { Samples = SampleCounts.Count1, Format = Format.B8G8R8A8UNorm, InitialLayout = ImageLayout.Undefined, FinalLayout = ImageLayout.PresentSrcKhr, LoadOp = AttachmentLoadOp.Clear, StoreOp = AttachmentStoreOp.Store, StencilLoadOp = AttachmentLoadOp.DontCare, StencilStoreOp = AttachmentStoreOp.DontCare }; var subpass = new SubpassDescription(new[] { new AttachmentReference(0, ImageLayout.ColorAttachmentOptimal) }); var createInfo = new RenderPassCreateInfo(new[] { subpass }, new[] { attachment }); using (PipelineCache cache = Device.CreatePipelineCache()) using (RenderPass renderPass = Device.CreateRenderPass(createInfo)) using (PipelineLayout layout = Device.CreatePipelineLayout()) using (ShaderModule vertexShader = Device.CreateShaderModule(new ShaderModuleCreateInfo(ReadAllBytes("Shader.vert.spv")))) using (ShaderModule fragmentShader = Device.CreateShaderModule(new ShaderModuleCreateInfo(ReadAllBytes("Shader.frag.spv")))) { var shaderStageCreateInfos = new[] { new PipelineShaderStageCreateInfo(ShaderStages.Vertex, vertexShader, "main"), new PipelineShaderStageCreateInfo(ShaderStages.Fragment, fragmentShader, "main") }; var vertexInputStateCreateInfo = new PipelineVertexInputStateCreateInfo(); var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo(PrimitiveTopology.TriangleList); var viewportStateCreateInfo = new PipelineViewportStateCreateInfo( new Viewport(0, 0, 32, 32), new Rect2D(0, 0, 32, 32)); var rasterizationStateCreateInfo = new PipelineRasterizationStateCreateInfo { PolygonMode = PolygonMode.Fill, CullMode = CullModes.Back, FrontFace = FrontFace.CounterClockwise, LineWidth = 1.0f }; var tessellationStateCreateInfo = new PipelineTessellationStateCreateInfo(4); var multisampleStateCreateInfo = new PipelineMultisampleStateCreateInfo { RasterizationSamples = SampleCounts.Count1, MinSampleShading = 1.0f }; var colorBlendAttachmentState = new PipelineColorBlendAttachmentState { SrcColorBlendFactor = BlendFactor.One, DstColorBlendFactor = BlendFactor.Zero, ColorBlendOp = BlendOp.Add, SrcAlphaBlendFactor = BlendFactor.One, DstAlphaBlendFactor = BlendFactor.Zero, AlphaBlendOp = BlendOp.Add, ColorWriteMask = ColorComponents.All }; var depthStencilStateCreateInfo = new PipelineDepthStencilStateCreateInfo(); var colorBlendStateCreateInfo = new PipelineColorBlendStateCreateInfo( new[] { colorBlendAttachmentState }); var dynamicStateCreateInfo = new PipelineDynamicStateCreateInfo(DynamicState.LineWidth); var pipelineCreateInfo = new GraphicsPipelineCreateInfo( layout, renderPass, 0, shaderStageCreateInfos, inputAssemblyStateCreateInfo, vertexInputStateCreateInfo, rasterizationStateCreateInfo, tessellationStateCreateInfo, viewportStateCreateInfo, multisampleStateCreateInfo, depthStencilStateCreateInfo, colorBlendStateCreateInfo, dynamicStateCreateInfo); using (Device.CreateGraphicsPipelines(new[] { pipelineCreateInfo })[0]) { } using (Device.CreateGraphicsPipelines(new[] { pipelineCreateInfo }, cache)[0]) { } using (Device.CreateGraphicsPipelines(new[] { pipelineCreateInfo }, allocator: CustomAllocator)[0]) { } using (Device.CreateGraphicsPipelines(new[] { pipelineCreateInfo }, cache, CustomAllocator)[0]) { } using (Device.CreateGraphicsPipeline(pipelineCreateInfo)) { } using (Device.CreateGraphicsPipeline(pipelineCreateInfo, allocator: CustomAllocator)) { } using (Device.CreateGraphicsPipeline(pipelineCreateInfo, cache)) { } using (Device.CreateGraphicsPipeline(pipelineCreateInfo, cache, CustomAllocator)) { } } }
public static Pipeline CreateGraphicsPipeline(Graphics g, PipelineLayout pl, RenderPass rp, string[] shaderNames, bool depthTest, bool depthWrite, bool instancing, Type instanceInfoType, BlendMode blendMode, PrimitiveType primType, PrimitiveRenderMode pmode, PrimitiveCullMode cmode, float lineWidth, Vector2 viewportPos, Vector2 viewportSize) { if (instancing && instanceInfoType == null) { throw new NullReferenceException("Instance info type cannot be null"); } var shaderStageCreateInfos = new PipelineShaderStageCreateInfo[shaderNames.Length]; for (var i = 0; i < shaderNames.Length; i++) { var shader = g.Context.Content.Get <ShaderModule>(shaderNames[i]); var shaderName = Path.GetFileNameWithoutExtension(shaderNames[i]); switch (Path.GetExtension(shaderName)) { case ".vert": shaderStageCreateInfos[i] = new PipelineShaderStageCreateInfo(ShaderStages.Vertex, shader, "main"); break; case ".frag": shaderStageCreateInfos[i] = new PipelineShaderStageCreateInfo(ShaderStages.Fragment, shader, "main"); break; default: throw new NotImplementedException($"Unreognized shader type for file \"{shaderNames[i]}\""); } } var fields = typeof(Vertex).GetFields(); var offset = 0; var loci = 0; List <VertexInputAttributeDescription> vertexAttributes = new List <VertexInputAttributeDescription>(fields.Length); for (var i = 0; i < fields.Length; i++) { var ftype = fields[i].FieldType; if (ftype == typeof(Vector3) || ftype == typeof(Angle)) { vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32SFloat, offset)); offset += 12; loci++; } else if (ftype == typeof(Vector2)) { vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32SFloat, offset)); offset += 8; loci++; } else if (ftype == typeof(Color4)) { vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32A32SFloat, offset)); offset += 16; loci++; } else if (ftype == typeof(float)) { vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32SFloat, offset)); offset += 4; loci++; } else if (ftype == typeof(Matrix4)) { vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32A32SFloat, offset)); loci++; offset += 16; vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32A32SFloat, offset)); loci++; offset += 16; vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32A32SFloat, offset)); loci++; offset += 16; vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32A32SFloat, offset)); loci++; offset += 16; } else { throw new Exception("Field " + fields[i] + " of vertex struct is an illegal type"); } } var vertexFieldsLength = fields.Length; if (instancing) { fields = instanceInfoType.GetFields(); offset = 0; for (var i = 0; i < fields.Length; i++) { var ftype = fields[i].FieldType; if (ftype == typeof(Vector3) || ftype == typeof(Angle)) { vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32SFloat, offset)); loci++; offset += 12; } else if (ftype == typeof(Vector2)) { vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32SFloat, offset)); loci++; offset += 8; } else if (ftype == typeof(Color4)) { vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32A32SFloat, offset)); loci++; offset += 16; } else if (ftype == typeof(float)) { vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32SFloat, offset)); loci++; offset += 4; } else if (ftype == typeof(Matrix4)) { vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32A32SFloat, offset)); loci++; offset += 16; vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32A32SFloat, offset)); loci++; offset += 16; vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32A32SFloat, offset)); loci++; offset += 16; vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32A32SFloat, offset)); loci++; offset += 16; } else { throw new Exception("Field " + fields[i] + " of instance info struct is an illegal type"); } } } var vertexInputStateCreateInfo = new PipelineVertexInputStateCreateInfo( (instancing ? new[] { new VertexInputBindingDescription(0, Interop.SizeOf <Vertex>(), VertexInputRate.Vertex), new VertexInputBindingDescription(1, System.Runtime.InteropServices.Marshal.SizeOf(instanceInfoType), VertexInputRate.Instance) } : new[] { new VertexInputBindingDescription(0, Interop.SizeOf <Vertex>(), VertexInputRate.Vertex) }), vertexAttributes.ToArray() ); var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo((PrimitiveTopology)primType); var viewportStateCreateInfo = new PipelineViewportStateCreateInfo( new Viewport(viewportPos.X + viewportSize.X, viewportPos.Y + viewportSize.Y, -viewportSize.X, -viewportSize.Y), new Rect2D((int)viewportPos.X, (int)viewportPos.Y, (int)viewportSize.X, (int)viewportSize.Y)); var rasterizationStateCreateInfo = new PipelineRasterizationStateCreateInfo { PolygonMode = (PolygonMode)pmode, CullMode = (CullModes)cmode, FrontFace = FrontFace.Clockwise, LineWidth = lineWidth }; var multisampleStateCreateInfo = new PipelineMultisampleStateCreateInfo { RasterizationSamples = g.Samples >= 48 ? SampleCounts.Count64 : g.Samples >= 24 ? SampleCounts.Count32 : g.Samples >= 12 ? SampleCounts.Count16 : g.Samples >= 6 ? SampleCounts.Count8 : g.Samples >= 3 ? SampleCounts.Count4 : g.Samples == 2 ? SampleCounts.Count2 : SampleCounts.Count1, MinSampleShading = 1.0f }; var depthStencilCreateInfo = new PipelineDepthStencilStateCreateInfo { DepthTestEnable = depthTest, DepthWriteEnable = depthWrite, DepthCompareOp = CompareOp.LessOrEqual, Back = new StencilOpState { FailOp = StencilOp.Keep, PassOp = StencilOp.Keep, CompareOp = CompareOp.Always }, Front = new StencilOpState { FailOp = StencilOp.Keep, PassOp = StencilOp.Keep, CompareOp = CompareOp.Always } }; var colorBlendAttachmentState = new PipelineColorBlendAttachmentState { SrcColorBlendFactor = BlendMode.GetBlendFactor(blendMode.SrcColorFactor), DstColorBlendFactor = BlendMode.GetBlendFactor(blendMode.DstColorFactor), ColorBlendOp = BlendMode.GetBlendOp(blendMode.ColorOp), SrcAlphaBlendFactor = BlendMode.GetBlendFactor(blendMode.SrcAlphaFactor), DstAlphaBlendFactor = BlendMode.GetBlendFactor(blendMode.DstAlphaFactor), AlphaBlendOp = BlendMode.GetBlendOp(blendMode.AlphaOp), ColorWriteMask = BlendMode.GetColorWriteMask(blendMode.Mask), BlendEnable = true }; var colorBlendStateCreateInfo = new PipelineColorBlendStateCreateInfo( new[] { colorBlendAttachmentState }); var pipelineCreateInfo = new GraphicsPipelineCreateInfo( pl, rp, 0, shaderStageCreateInfos, inputAssemblyStateCreateInfo, vertexInputStateCreateInfo, rasterizationStateCreateInfo, viewportState: viewportStateCreateInfo, multisampleState: multisampleStateCreateInfo, depthStencilState: depthStencilCreateInfo, colorBlendState: colorBlendStateCreateInfo//, //dynamicState: new PipelineDynamicStateCreateInfo(DynamicState.Viewport) ); return(g.Context.Device.CreateGraphicsPipeline(pipelineCreateInfo)); }
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]; }
internal static Pipeline CreatePipeline( Device logicalDevice, RenderPass renderpass, PipelineLayout layout, ShaderModule vertModule, ShaderModule fragModule, SpecializationContainer specializationContainer, bool depthClamp, bool depthBias, ReadOnlySpan <DeviceTexture> targets, IInternalRenderObject renderObject) { if (logicalDevice == null) { throw new ArgumentNullException(nameof(logicalDevice)); } if (renderpass == null) { throw new ArgumentNullException(nameof(renderpass)); } var shaderStages = new [] { new PipelineShaderStageCreateInfo( stage: ShaderStages.Vertex, module: vertModule, name: "main", specializationInfo: specializationContainer?.GetInfo()), new PipelineShaderStageCreateInfo( stage: ShaderStages.Fragment, module: fragModule, name: "main", specializationInfo: specializationContainer?.GetInfo()) }; var depthTest = new PipelineDepthStencilStateCreateInfo { DepthTestEnable = true, DepthWriteEnable = true, DepthCompareOp = CompareOp.LessOrEqual, DepthBoundsTestEnable = false, StencilTestEnable = false }; var rasterizer = new PipelineRasterizationStateCreateInfo( depthClampEnable: depthClamp, rasterizerDiscardEnable: false, polygonMode: PolygonMode.Fill, cullMode: CullModes.Back, frontFace: renderObject.GetFrontFace(), depthBiasEnable: depthBias, depthBiasConstantFactor: .1f, depthBiasSlopeFactor: 1.75f, lineWidth: 1f ); //Gather all the color targets and setup a blend-state for them ResizeArray <PipelineColorBlendAttachmentState> blendAttachments = new ResizeArray <PipelineColorBlendAttachmentState>(); for (int i = 0; i < targets.Length; i++) { if (!targets[i].DepthTexture) { blendAttachments.Add(new PipelineColorBlendAttachmentState( colorWriteMask: ColorComponents.All, blendEnable: false)); } } var blending = new PipelineColorBlendStateCreateInfo( attachments: blendAttachments.ToArray(), logicOpEnable: false ); var multisampleState = new PipelineMultisampleStateCreateInfo( rasterizationSamples: SampleCounts.Count1, sampleShadingEnable: false ); //Pass the viewport and scissor-rect as dynamic so we are not tied to swapchain size //the advantage is this is that we don't need to recreate the pipeline on swapchain //resize var dynamicState = new PipelineDynamicStateCreateInfo( DynamicState.Viewport, DynamicState.Scissor ); return(logicalDevice.CreateGraphicsPipeline(new GraphicsPipelineCreateInfo( layout: layout, renderPass: renderpass, subpass: 0, stages: shaderStages, inputAssemblyState: renderObject.GetInputAssemblyStateInfo(), vertexInputState: renderObject.GetVertexInputState(), rasterizationState: rasterizer, tessellationState: null, //Pass empty viewport and scissor-rect as we set them dynamically viewportState: new PipelineViewportStateCreateInfo(new Viewport(), new Rect2D()), multisampleState: multisampleState, depthStencilState: depthTest, colorBlendState: blending, dynamicState: dynamicState, flags: PipelineCreateFlags.None ))); }
private Pipeline CreateGraphicsPipeline() { using var pName = SilkMarshal.StringToMemory("main"); var shaderStages = stackalloc PipelineShaderStageCreateInfo[2] { new PipelineShaderStageCreateInfo { SType = StructureType.PipelineShaderStageCreateInfo, Stage = ShaderStageFlags.ShaderStageVertexBit, Module = this.VertexShader, PName = (byte *)pName }, new PipelineShaderStageCreateInfo { SType = StructureType.PipelineShaderStageCreateInfo, Stage = ShaderStageFlags.ShaderStageFragmentBit, Module = this.FragmentShader, PName = (byte *)pName } }; var dynamicStates = stackalloc DynamicState[2] { DynamicState.Viewport, DynamicState.Scissor }; PipelineDynamicStateCreateInfo dynamicState = new PipelineDynamicStateCreateInfo { SType = StructureType.PipelineDynamicStateCreateInfo, DynamicStateCount = 2, PDynamicStates = dynamicStates }; var vertexBindings = stackalloc VertexInputBindingDescription[2] { new VertexInputBindingDescription(0, (uint)sizeof(PositionColorVertex), VertexInputRate.Vertex), new VertexInputBindingDescription(1, (uint)sizeof(InstanceData), VertexInputRate.Instance) }; var vertexAttributes = stackalloc VertexInputAttributeDescription[3] { new VertexInputAttributeDescription(0, 0, Format.R32G32B32Sfloat, 0), new VertexInputAttributeDescription(1, 0, Format.R32G32B32Sfloat, (uint)sizeof(System.Numerics.Vector3)), new VertexInputAttributeDescription(2, 1, Format.R32G32B32Sfloat, 0) }; var vertexInputInfo = new PipelineVertexInputStateCreateInfo { SType = StructureType.PipelineVertexInputStateCreateInfo, VertexBindingDescriptionCount = 2, PVertexBindingDescriptions = vertexBindings, VertexAttributeDescriptionCount = 3, PVertexAttributeDescriptions = vertexAttributes }; var inputAssembly = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, Topology = PrimitiveTopology.TriangleList, PrimitiveRestartEnable = false }; //Marked as dynamic state, will be specified in the command buffer var viewportState = new PipelineViewportStateCreateInfo { SType = StructureType.PipelineViewportStateCreateInfo, ViewportCount = 1, ScissorCount = 1, }; var rasterizer = new PipelineRasterizationStateCreateInfo { SType = StructureType.PipelineRasterizationStateCreateInfo, DepthClampEnable = Vk.False, RasterizerDiscardEnable = Vk.False, PolygonMode = PolygonMode.Fill, LineWidth = 1.0f, CullMode = CullModeFlags.CullModeNone, FrontFace = FrontFace.Clockwise, DepthBiasEnable = Vk.False }; var multisampling = new PipelineMultisampleStateCreateInfo { SType = StructureType.PipelineMultisampleStateCreateInfo, SampleShadingEnable = false, RasterizationSamples = SampleCountFlags.SampleCount1Bit }; var colorBlendAttachment = new PipelineColorBlendAttachmentState { ColorWriteMask = ColorComponentFlags.ColorComponentRBit | ColorComponentFlags.ColorComponentGBit | ColorComponentFlags.ColorComponentBBit | ColorComponentFlags.ColorComponentABit, BlendEnable = Vk.False }; var colorBlending = new PipelineColorBlendStateCreateInfo { SType = StructureType.PipelineColorBlendStateCreateInfo, LogicOpEnable = Vk.False, LogicOp = LogicOp.Copy, AttachmentCount = 1, PAttachments = &colorBlendAttachment }; colorBlending.BlendConstants[0] = 0.0f; colorBlending.BlendConstants[1] = 0.0f; colorBlending.BlendConstants[2] = 0.0f; colorBlending.BlendConstants[3] = 0.0f; var depthState = new PipelineDepthStencilStateCreateInfo { SType = StructureType.PipelineDepthStencilStateCreateInfo, DepthTestEnable = true, DepthWriteEnable = true, DepthCompareOp = CompareOp.LessOrEqual, DepthBoundsTestEnable = false, MinDepthBounds = 0, MaxDepthBounds = 0, StencilTestEnable = false, Back = { FailOp = StencilOp.Keep, PassOp = StencilOp.Keep, CompareOp = CompareOp.Always, CompareMask = 0, Reference = 0, DepthFailOp = StencilOp.Keep, WriteMask = 0 } }; depthState.Front = depthState.Back; var pipelineInfo = new GraphicsPipelineCreateInfo { SType = StructureType.GraphicsPipelineCreateInfo, StageCount = 2, PStages = shaderStages, PDynamicState = &dynamicState, PDepthStencilState = &depthState, PVertexInputState = &vertexInputInfo, PInputAssemblyState = &inputAssembly, PViewportState = &viewportState, PRasterizationState = &rasterizer, PMultisampleState = &multisampling, PColorBlendState = &colorBlending, Layout = this.GraphicsPipelineLayout, RenderPass = RenderPass, Subpass = 0, BasePipelineHandle = default }; Pipeline pipeline; var res = VkApi.CreateGraphicsPipelines(Device, default, 1, &pipelineInfo, null, &pipeline);
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 Pipeline CreatePipelineFromData(EngineRenderer.RenderPass aPass, PipelineVertexInputStateCreateInfo myState, PipelineLayout myLayout, List <PipelineShaderStageCreateInfo> myStages) { var scissor = new Rect2D { Extent = VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent }; var viewportCreateInfo = new PipelineViewportStateCreateInfo { Viewports = new Viewport[] { VulkanRenderer.Viewport }, Scissors = new Rect2D[] { scissor } }; var multisampleCreateInfo = new PipelineMultisampleStateCreateInfo { RasterizationSamples = SampleCountFlags.Count1 }; 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 = CullModeFlags.None, FrontFace = FrontFace.Clockwise, //Todo: flip? LineWidth = 1.0f }; var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo { Topology = PrimitiveTopology.TriangleList }; var pipelineCreateInfo = new GraphicsPipelineCreateInfo { Layout = myLayout, ViewportState = viewportCreateInfo, Stages = myStages.ToArray(), MultisampleState = multisampleCreateInfo, ColorBlendState = colorBlendStateCreatInfo, RasterizationState = rasterizationStateCreateInfo, InputAssemblyState = inputAssemblyStateCreateInfo, VertexInputState = myState,// myBuilder.GetDefaultStateCreateInfo(), RenderPass = aPass, DepthStencilState = new PipelineDepthStencilStateCreateInfo() { } }; Debug.Assert(pipelineCreateInfo.Stages[0].Module.m == myStages[0].Module.m); var Result = VulkanRenderer.SelectedLogicalDevice.CreateGraphicsPipelines(myPipelineCache, new GraphicsPipelineCreateInfo[] { pipelineCreateInfo }); pipelineCreateInfo.Dispose(); inputAssemblyStateCreateInfo.Dispose(); rasterizationStateCreateInfo.Dispose(); colorBlendStateCreatInfo.Dispose(); Debug.Assert(Result.Length == 1); return(Result[0]); }
//[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); } }
private unsafe void Recreate() { if (Description.RootSignature == null) { return; } CreateRenderPass(Description); CreatePipelineLayout(Description); // 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); var 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 = CreateRasterizationState(Description.RasterizerState); var depthStencilState = CreateDepthStencilState(Description); var description = Description.BlendState; var renderTargetCount = Description.Output.RenderTargetCount; 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(DynamicState *dynamicStatesPointer = &dynamicStates[0]) { var vertexInputState = new PipelineVertexInputStateCreateInfo { StructureType = StructureType.PipelineVertexInputStateCreateInfo, VertexAttributeDescriptionCount = (uint)inputAttributeCount, VertexAttributeDescriptions = inputAttributes.Length > 0 ? new IntPtr(Interop.Fixed(inputAttributes)) : IntPtr.Zero, VertexBindingDescriptionCount = (uint)inputBindingCount, VertexBindingDescriptions = inputBindings.Length > 0 ? new IntPtr(Interop.Fixed(inputBindings)) : IntPtr.Zero, }; var colorBlendState = new PipelineColorBlendStateCreateInfo { StructureType = StructureType.PipelineColorBlendStateCreateInfo, AttachmentCount = (uint)renderTargetCount, Attachments = colorBlendAttachments.Length > 0 ? new IntPtr(Interop.Fixed(colorBlendAttachments)) : IntPtr.Zero, }; var dynamicState = new PipelineDynamicStateCreateInfo { StructureType = StructureType.PipelineDynamicStateCreateInfo, DynamicStateCount = (uint)dynamicStates.Length, DynamicStates = new IntPtr(dynamicStatesPointer) }; var createInfo = new GraphicsPipelineCreateInfo { StructureType = StructureType.GraphicsPipelineCreateInfo, Layout = NativeLayout, StageCount = (uint)stages.Length, Stages = stages.Length > 0 ? new IntPtr(Interop.Fixed(stages)) : IntPtr.Zero, //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), RenderPass = NativeRenderPass, Subpass = 0, }; NativePipeline = GraphicsDevice.NativeDevice.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo); } // Cleanup shader modules foreach (var stage in stages) { GraphicsDevice.NativeDevice.DestroyShaderModule(stage.Module); } }
void CreatePipeline() { ShaderModule vertex_shader_module = CreateShaderModule("assets/shader03.vert.spv"); ShaderModule fragment_shader_module = CreateShaderModule("assets/shader03.frag.spv"); var shader_stage_create_infos = stackalloc PipelineShaderStageCreateInfo[2]; // Vertex shader shader_stage_create_infos[0] = new PipelineShaderStageCreateInfo { sType = StructureType.PipelineShaderStageCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkPipelineShaderStageCreateFlagBits flags stage = ShaderStageFlagBits.VertexBit, // VkShaderStageFlagBits stage module = vertex_shader_module, // VkShaderModule module pName = (byte *)Marshal.StringToHGlobalAnsi("main"), // const char *pName pSpecializationInfo = (SpecializationInfo *)0 // const VkSpecializationInfo *pSpecializationInfo }; // Fragment shader shader_stage_create_infos[1] = new PipelineShaderStageCreateInfo { sType = StructureType.PipelineShaderStageCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkPipelineShaderStageCreateFlagBits flags stage = ShaderStageFlagBits.FragmentBit, // VkShaderStageFlagBits stage module = fragment_shader_module, // VkShaderModule module pName = (byte *)Marshal.StringToHGlobalAnsi("main"), // const char *pName pSpecializationInfo = (SpecializationInfo *)0 // const VkSpecializationInfo *pSpecializationInfo }; var vertex_input_state_create_info = new PipelineVertexInputStateCreateInfo { sType = StructureType.PipelineVertexInputStateCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkPipelineVertexInputStateCreateFlagBits flags; vertexBindingDescriptionCount = 0, // uint32_t vertexBindingDescriptionCount pVertexBindingDescriptions = (VertexInputBindingDescription *)0, // const VkVertexInputBindingDescription *pVertexBindingDescriptions vertexAttributeDescriptionCount = 0, // uint32_t vertexAttributeDescriptionCount pVertexAttributeDescriptions = (VertexInputAttributeDescription *)0 // const VkVertexInputAttributeDescription *pVertexAttributeDescriptions }; var input_assembly_state_create_info = new PipelineInputAssemblyStateCreateInfo { sType = StructureType.PipelineInputAssemblyStateCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkPipelineInputAssemblyStateCreateFlagBits flags topology = PrimitiveTopology.TriangleList, // VkPrimitiveTopology topology primitiveRestartEnable = false // VkBool32 primitiveRestartEnable }; Viewport viewport = new Viewport { x = 0.0f, // float x y = 0.0f, // float y width = 300.0f, // float width height = 300.0f, // float height minDepth = 0.0f, // float minDepth maxDepth = 1.0f // float maxDepth }; Rect2D scissor = new Rect2D { offset = new Offset2D { // VkOffset2D offset x = 0, // int32_t x y = 0 // int32_t y }, extent = new Extent2D { // VkExtent2D extent width = 300, // int32_t width height = 300 // int32_t height } }; var viewport_state_create_info = new PipelineViewportStateCreateInfo { sType = StructureType.PipelineViewportStateCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkPipelineViewportStateCreateFlagBits flags viewportCount = 1, // uint32_t viewportCount pViewports = &viewport, // const VkViewport *pViewports scissorCount = 1, // uint32_t scissorCount pScissors = &scissor // const VkRect2D *pScissors }; var rasterization_state_create_info = new PipelineRasterizationStateCreateInfo { sType = StructureType.PipelineRasterizationStateCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkPipelineRasterizationStateCreateFlagBits flags depthClampEnable = false, // VkBool32 depthClampEnable rasterizerDiscardEnable = false, // VkBool32 rasterizerDiscardEnable polygonMode = PolygonMode.Fill, // VkPolygonMode polygonMode cullMode = CullModeFlagBits.BackBit, // VkCullModeFlagBits cullMode frontFace = FrontFace.CounterClockwise, // VkFrontFace frontFace depthBiasEnable = false, // VkBool32 depthBiasEnable depthBiasConstantFactor = 0.0f, // float depthBiasConstantFactor depthBiasClamp = 0.0f, // float depthBiasClamp depthBiasSlopeFactor = 0.0f, // float depthBiasSlopeFactor lineWidth = 1.0f // float lineWidth }; var multisample_state_create_info = new PipelineMultisampleStateCreateInfo { sType = StructureType.PipelineMultisampleStateCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkPipelineMultisampleStateCreateFlagBits flags rasterizationSamples = SampleCountFlagBits._1Bit, // VkSampleCountFlagBits rasterizationSamples sampleShadingEnable = false, // VkBool32 sampleShadingEnable minSampleShading = 1.0f, // float minSampleShading pSampleMask = (uint *)0, // const VkSampleMask *pSampleMask alphaToCoverageEnable = false, // VkBool32 alphaToCoverageEnable alphaToOneEnable = false // VkBool32 alphaToOneEnable }; var color_blend_attachment_state = new PipelineColorBlendAttachmentState { blendEnable = false, // VkBool32 blendEnable sourceColorBlendFactor = BlendFactor.One, // VkBlendFactor srcColorBlendFactor destinationColorBlendFactor = BlendFactor.Zero, // VkBlendFactor dstColorBlendFactor colorBlendOperation = BlendOperation.Add, // VkBlendOp colorBlendOp sourceAlphaBlendFactor = BlendFactor.One, // VkBlendFactor srcAlphaBlendFactor destinationAlphaBlendFactor = BlendFactor.Zero, // VkBlendFactor dstAlphaBlendFactor alphaBlendOperation = BlendOperation.Add, // VkBlendOp alphaBlendOp colorWriteMask = ColorComponentFlagBits.RBit | ColorComponentFlagBits.GBit // VkColorComponentFlagBits colorWriteMask | ColorComponentFlagBits.BBit | ColorComponentFlagBits.ABit }; var color_blend_state_create_info = new PipelineColorBlendStateCreateInfo { sType = StructureType.PipelineColorBlendStateCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkPipelineColorBlendStateCreateFlagBits flags logicOperationEnable = false, // VkBool32 logicOpEnable logicOperation = LogicOperation.Copy, // VkLogicOp logicOp attachmentCount = 1, // uint32_t attachmentCount pAttachments = &color_blend_attachment_state, // const VkPipelineColorBlendAttachmentState *pAttachments }; //blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4] color_blend_state_create_info.blendConstants[0] = 0; color_blend_state_create_info.blendConstants[1] = 0; color_blend_state_create_info.blendConstants[2] = 0; color_blend_state_create_info.blendConstants[3] = 0; var pipeline_layout = CreatePipelineLayout(); var pipeline_create_info = new GraphicsPipelineCreateInfo { sType = StructureType.GraphicsPipelineCreateInfo, // VkStructureType sType pNext = IntPtr.Zero, // const void *pNext flags = 0, // VkPipelineCreateFlagBits flags stageCount = 2, // uint32_t stageCount pStages = shader_stage_create_infos, // const VkPipelineShaderStageCreateInfo *pStages pVertexInputState = &vertex_input_state_create_info, // const VkPipelineVertexInputStateCreateInfo *pVertexInputState; pInputAssemblyState = &input_assembly_state_create_info, // const VkPipelineInputAssemblyStateCreateInfo *pInputAssemblyState pTessellationState = (PipelineTessellationStateCreateInfo *)0, // const VkPipelineTessellationStateCreateInfo *pTessellationState pViewportState = &viewport_state_create_info, // const VkPipelineViewportStateCreateInfo *pViewportState pRasterizationState = &rasterization_state_create_info, // const VkPipelineRasterizationStateCreateInfo *pRasterizationState pMultisampleState = &multisample_state_create_info, // const VkPipelineMultisampleStateCreateInfo *pMultisampleState pDepthStencilState = (PipelineDepthStencilStateCreateInfo *)0, // const VkPipelineDepthStencilStateCreateInfo *pDepthStencilState pColorBlendState = &color_blend_state_create_info, // const VkPipelineColorBlendStateCreateInfo *pColorBlendState pDynamicState = (PipelineDynamicStateCreateInfo *)0, // const VkPipelineDynamicStateCreateInfo *pDynamicState layout = pipeline_layout, // VkPipelineLayout layout renderPass = Vulkan.RenderPass, // VkRenderPass renderPass subpass = 0, // uint32_t subpass basePipelineHandle = default(Pipeline), // VkPipeline basePipelineHandle basePipelineIndex = -1 // int32_t basePipelineIndex }; vk.CreateGraphicsPipelines(GetDevice, default(PipelineCache), 1, &pipeline_create_info, (AllocationCallbacks *)0, out Vulkan.GraphicsPipeline).CheckError(); Marshal.FreeHGlobal((IntPtr)shader_stage_create_infos[0].pName); Marshal.FreeHGlobal((IntPtr)shader_stage_create_infos[1].pName); }
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 })); }
private Pipeline CreateGraphicsPipeline() { // Create shader modules. Shader modules are one of the objects required to create the // graphics pipeline. But after the pipeline is created, we don't need these shader // modules anymore, so we dispose them. ShaderModule vertexShader = Content.Load <ShaderModule>("Shader.vert.spv"); ShaderModule fragmentShader = Content.Load <ShaderModule>("Shader.frag.spv"); var shaderStageCreateInfos = new[] { new PipelineShaderStageCreateInfo(ShaderStages.Vertex, vertexShader, "main"), new PipelineShaderStageCreateInfo(ShaderStages.Fragment, fragmentShader, "main") }; var vertexInputStateCreateInfo = new PipelineVertexInputStateCreateInfo( new[] { new VertexInputBindingDescription(0, Interop.SizeOf <Vertex>(), VertexInputRate.Vertex) }, new[] { new VertexInputAttributeDescription(0, 0, Format.R32G32B32SFloat, 0), // Position. new VertexInputAttributeDescription(1, 0, Format.R32G32B32SFloat, 12), // Normal. new VertexInputAttributeDescription(2, 0, Format.R32G32SFloat, 24) // TexCoord. } ); var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo(PrimitiveTopology.TriangleList); var viewportStateCreateInfo = new PipelineViewportStateCreateInfo( new Viewport(0, 0, Host.Width, Host.Height), new Rect2D(0, 0, Host.Width, Host.Height)); var rasterizationStateCreateInfo = new PipelineRasterizationStateCreateInfo { PolygonMode = PolygonMode.Fill, CullMode = CullModes.Back, FrontFace = FrontFace.CounterClockwise, LineWidth = 1.0f }; var multisampleStateCreateInfo = new PipelineMultisampleStateCreateInfo { RasterizationSamples = SampleCounts.Count1, MinSampleShading = 1.0f }; var depthStencilCreateInfo = new PipelineDepthStencilStateCreateInfo { DepthTestEnable = true, DepthWriteEnable = true, DepthCompareOp = CompareOp.LessOrEqual, Back = new StencilOpState { FailOp = StencilOp.Keep, PassOp = StencilOp.Keep, CompareOp = CompareOp.Always }, Front = new StencilOpState { FailOp = StencilOp.Keep, PassOp = StencilOp.Keep, CompareOp = CompareOp.Always } }; var colorBlendAttachmentState = new PipelineColorBlendAttachmentState { SrcColorBlendFactor = BlendFactor.One, DstColorBlendFactor = BlendFactor.Zero, ColorBlendOp = BlendOp.Add, SrcAlphaBlendFactor = BlendFactor.One, DstAlphaBlendFactor = BlendFactor.Zero, AlphaBlendOp = BlendOp.Add, ColorWriteMask = ColorComponents.All }; var colorBlendStateCreateInfo = new PipelineColorBlendStateCreateInfo( new[] { colorBlendAttachmentState }); var pipelineCreateInfo = new GraphicsPipelineCreateInfo( _pipelineLayout, _renderPass, 0, shaderStageCreateInfos, inputAssemblyStateCreateInfo, vertexInputStateCreateInfo, rasterizationStateCreateInfo, viewportState: viewportStateCreateInfo, multisampleState: multisampleStateCreateInfo, depthStencilState: depthStencilCreateInfo, colorBlendState: colorBlendStateCreateInfo); return(Context.Device.CreateGraphicsPipeline(pipelineCreateInfo)); }
private unsafe void Recreate() { if (Description.RootSignature == null) return; CreateRenderPass(Description); CreatePipelineLayout(Description); // Create shader stages Dictionary<int, string> inputAttributeNames; var 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 = true, }; // TODO VULKAN: Tessellation and multisampling var multisampleState = new PipelineMultisampleStateCreateInfo { StructureType = StructureType.PipelineMultisampleStateCreateInfo, RasterizationSamples = SampleCountFlags.Sample1 }; var tessellationState = new PipelineTessellationStateCreateInfo(); var rasterizationState = CreateRasterizationState(Description.RasterizerState); var depthStencilState = CreateDepthStencilState(Description); var description = Description.BlendState; var renderTargetCount = Description.Output.RenderTargetCount; 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 (DynamicState* dynamicStatesPointer = &dynamicStates[0]) { var vertexInputState = new PipelineVertexInputStateCreateInfo { StructureType = StructureType.PipelineVertexInputStateCreateInfo, VertexAttributeDescriptionCount = (uint)inputAttributeCount, VertexAttributeDescriptions = inputAttributes.Length > 0 ? new IntPtr(Interop.Fixed(inputAttributes)) : IntPtr.Zero, VertexBindingDescriptionCount = (uint)inputBindingCount, VertexBindingDescriptions = inputBindings.Length > 0 ? new IntPtr(Interop.Fixed(inputBindings)) : IntPtr.Zero, }; var colorBlendState = new PipelineColorBlendStateCreateInfo { StructureType = StructureType.PipelineColorBlendStateCreateInfo, AttachmentCount = (uint)renderTargetCount, Attachments = colorBlendAttachments.Length > 0 ? new IntPtr(Interop.Fixed(colorBlendAttachments)) : IntPtr.Zero, }; var dynamicState = new PipelineDynamicStateCreateInfo { StructureType = StructureType.PipelineDynamicStateCreateInfo, DynamicStateCount = (uint)dynamicStates.Length, DynamicStates = new IntPtr(dynamicStatesPointer) }; var createInfo = new GraphicsPipelineCreateInfo { StructureType = StructureType.GraphicsPipelineCreateInfo, Layout = NativeLayout, StageCount = (uint)stages.Length, Stages = stages.Length > 0 ? new IntPtr(Interop.Fixed(stages)) : IntPtr.Zero, //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), RenderPass = NativeRenderPass, Subpass = 0, }; NativePipeline = GraphicsDevice.NativeDevice.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo); } // Cleanup shader modules foreach (var stage in stages) { GraphicsDevice.NativeDevice.DestroyShaderModule(stage.Module); } }