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 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 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 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); } } }
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)) { } } }
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);
//[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); } }
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)); }