Beispiel #1
0
        protected virtual void SetupInstancedVertexDescriptions()
        {
            // Binding description
            vertices_bindingDescriptions.Count = 2;
            vertices_bindingDescriptions[0]    =
                Initializers.vertexInputBindingDescription(
                    Pipeline.VERTEX_DATA_BUFFER_BIND_ID,
                    (uint)sizeof(Vertex),
                    VkVertexInputRate.Vertex);

            vertices_bindingDescriptions[1] =
                Initializers.vertexInputBindingDescription(
                    Pipeline.VERTEX_INSTANCE_BUFFER_BIND_ID,
                    (uint)sizeof(ObjectToWorld),
                    VkVertexInputRate.Instance);

            // Attribute descriptions
            // Describes memory layout and shader positions
            vertices_attributeDescriptions.Count = 10;
            // Location 0 : Position
            vertices_attributeDescriptions[0] =
                Initializers.vertexInputAttributeDescription(
                    Pipeline.VERTEX_DATA_BUFFER_BIND_ID,
                    0,
                    VkFormat.R32g32b32Sfloat,
                    0);
            // Location 1 : Normal
            vertices_attributeDescriptions[1] =
                Initializers.vertexInputAttributeDescription(
                    Pipeline.VERTEX_DATA_BUFFER_BIND_ID,
                    1,
                    VkFormat.R32g32b32Sfloat,
                    12);
            // Location 2 : Texture coordinates
            vertices_attributeDescriptions[2] =
                Initializers.vertexInputAttributeDescription(
                    Pipeline.VERTEX_DATA_BUFFER_BIND_ID,
                    2,
                    VkFormat.R32g32Sfloat,
                    24);
            // Location 3 : Color
            //vertices_attributeDescriptions[3] =
            //    Initializers.vertexInputAttributeDescription(
            //     Pipeline.VERTEX_DATA_BUFFER_BIND_ID,
            //        3,
            //        VkFormat.R32g32b32Sfloat,
            //        32);



            //Location 3-9 Instance model matrix and normal matrix
            vertices_attributeDescriptions[3] =
                Initializers.vertexInputAttributeDescription(
                    Pipeline.VERTEX_INSTANCE_BUFFER_BIND_ID,
                    3,
                    VkFormat.R32g32b32a32Sfloat,
                    0);
            vertices_attributeDescriptions[4] =
                Initializers.vertexInputAttributeDescription(
                    Pipeline.VERTEX_INSTANCE_BUFFER_BIND_ID,
                    4,
                    VkFormat.R32g32b32a32Sfloat,
                    16);
            vertices_attributeDescriptions[5] =
                Initializers.vertexInputAttributeDescription(
                    Pipeline.VERTEX_INSTANCE_BUFFER_BIND_ID,
                    5,
                    VkFormat.R32g32b32a32Sfloat,
                    32);
            vertices_attributeDescriptions[6] =
                Initializers.vertexInputAttributeDescription(
                    Pipeline.VERTEX_INSTANCE_BUFFER_BIND_ID,
                    6,
                    VkFormat.R32g32b32a32Sfloat,
                    48);
            vertices_attributeDescriptions[7] =
                Initializers.vertexInputAttributeDescription(
                    Pipeline.VERTEX_INSTANCE_BUFFER_BIND_ID,
                    7,
                    VkFormat.R32g32b32Sfloat,
                    64);
            vertices_attributeDescriptions[8] =
                Initializers.vertexInputAttributeDescription(
                    Pipeline.VERTEX_INSTANCE_BUFFER_BIND_ID,
                    8,
                    VkFormat.R32g32b32Sfloat,
                    76);
            vertices_attributeDescriptions[9] =
                Initializers.vertexInputAttributeDescription(
                    Pipeline.VERTEX_INSTANCE_BUFFER_BIND_ID,
                    9,
                    VkFormat.R32g32b32Sfloat,
                    88);


            vertices_inputState = Initializers.pipelineVertexInputStateCreateInfo();
            vertices_inputState.vertexBindingDescriptionCount   = (vertices_bindingDescriptions.Count);
            vertices_inputState.pVertexBindingDescriptions      = (VkVertexInputBindingDescription *)vertices_bindingDescriptions.Data;
            vertices_inputState.vertexAttributeDescriptionCount = (vertices_attributeDescriptions.Count);
            vertices_inputState.pVertexAttributeDescriptions    = (VkVertexInputAttributeDescription *)vertices_attributeDescriptions.Data;
        }
Beispiel #2
0
        private void createGraphicsPipeline()
        {
            var vertShaderModule = createShaderModule(typeof(Shader_Vert_02));
            var fragShaderModule = createShaderModule(typeof(Shader_Frag_02));

            VkPipelineShaderStageCreateInfo vertShaderStageInfo = new VkPipelineShaderStageCreateInfo();

            vertShaderStageInfo.sType  = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
            vertShaderStageInfo.stage  = VkShaderStageFlagBits.VK_SHADER_STAGE_VERTEX_BIT;
            vertShaderStageInfo.module = vertShaderModule;
            vertShaderStageInfo.pName  = "main";

            VkPipelineShaderStageCreateInfo fragShaderStageInfo = new VkPipelineShaderStageCreateInfo();

            fragShaderStageInfo.sType  = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
            fragShaderStageInfo.stage  = VkShaderStageFlagBits.VK_SHADER_STAGE_FRAGMENT_BIT;
            fragShaderStageInfo.module = fragShaderModule;
            fragShaderStageInfo.pName  = "main";

            VkPipelineShaderStageCreateInfo[] shaderStages = new VkPipelineShaderStageCreateInfo[2] {
                vertShaderStageInfo, fragShaderStageInfo
            };

            VkPipelineVertexInputStateCreateInfo vertexInputInfo = new VkPipelineVertexInputStateCreateInfo();

            vertexInputInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
            vertexInputInfo.vertexBindingDescriptionCount   = 0;
            vertexInputInfo.vertexAttributeDescriptionCount = 0;

            VkPipelineInputAssemblyStateCreateInfo inputAssembly = new VkPipelineInputAssemblyStateCreateInfo();

            inputAssembly.sType    = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
            inputAssembly.topology = VkPrimitiveTopology.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
            inputAssembly.primitiveRestartEnable = VkBool32.VK_FALSE;

            VkViewport viewport = new VkViewport();

            viewport.x        = 0.0f;
            viewport.y        = 0.0f;
            viewport.width    = (float)swapChainExtent.width;
            viewport.height   = (float)swapChainExtent.height;
            viewport.minDepth = 0.0f;
            viewport.maxDepth = 1.0f;

            VkRect2D scissor = new VkRect2D();

            scissor.offset = new VkOffset2D()
            {
                x = 0, y = 0
            };
            scissor.extent = swapChainExtent;

            VkPipelineViewportStateCreateInfo viewportState = new VkPipelineViewportStateCreateInfo();

            viewportState.sType         = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
            viewportState.viewportCount = 1;
            viewportState.pViewports    = new VkViewport[] { viewport };
            viewportState.scissorCount  = 1;
            viewportState.pSicssors     = new VkRect2D[] { scissor };

            VkPipelineRasterizationStateCreateInfo rasterizer = new VkPipelineRasterizationStateCreateInfo();

            rasterizer.sType                   = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
            rasterizer.depthClampEnable        = VkBool32.VK_FALSE;
            rasterizer.rasterizerDiscardEnable = VkBool32.VK_FALSE;
            rasterizer.polygonMode             = VkPolygonMode.VK_POLYGON_MODE_FILL;
            rasterizer.lineWidth               = 1.0f;
            rasterizer.cullMode                = VkCullModeFlagBits.VK_CULL_MODE_BACK_BIT;
            rasterizer.frontFace               = VkFrontFace.VK_FRONT_FACE_CLOCKWISE;
            rasterizer.depthBiasEnable         = VkBool32.VK_FALSE;

            VkPipelineMultisampleStateCreateInfo multisampling = new VkPipelineMultisampleStateCreateInfo();

            multisampling.sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
            multisampling.sampleShadingEnable  = VkBool32.VK_FALSE;
            multisampling.rasterizationSamples = VkSampleCountFlagBits.VK_SAMPLE_COUNT_1_BIT;

            VkPipelineColorBlendAttachmentState colorBlendAttachment = new VkPipelineColorBlendAttachmentState();

            colorBlendAttachment.colorWriteMask = VkColorComponentFlagBits.VK_COLOR_COMPONENT_R_BIT | VkColorComponentFlagBits.VK_COLOR_COMPONENT_G_BIT | VkColorComponentFlagBits.VK_COLOR_COMPONENT_B_BIT | VkColorComponentFlagBits.VK_COLOR_COMPONENT_A_BIT;
            colorBlendAttachment.blendEnable    = VkBool32.VK_FALSE;

            VkPipelineColorBlendStateCreateInfo colorBlending = VkPipelineColorBlendStateCreateInfo.Create();

            colorBlending.sType             = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
            colorBlending.logicOpEnable     = VkBool32.VK_FALSE;
            colorBlending.logicOp           = VkLogicOp.VK_LOGIC_OP_COPY;
            colorBlending.attachmentCount   = 1;
            colorBlending.pAttachments      = new VkPipelineColorBlendAttachmentState[] { colorBlendAttachment };
            colorBlending.blendConstants[0] = 0.0f;
            colorBlending.blendConstants[1] = 0.0f;
            colorBlending.blendConstants[2] = 0.0f;
            colorBlending.blendConstants[3] = 0.0f;

            VkPipelineLayoutCreateInfo pipelineLayoutInfo = new VkPipelineLayoutCreateInfo();

            pipelineLayoutInfo.sType                  = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
            pipelineLayoutInfo.setLayoutCount         = 0;
            pipelineLayoutInfo.pushConstantRangeCount = 0;

            VkResult result = Vulkan.vkCreatePipelineLayout(device, pipelineLayoutInfo, null, out pipelineLayout);

            if (result != VkResult.VK_SUCCESS)
            {
                throw Program.Throw("failed to create pipeline layout!");
            }

            VkGraphicsPipelineCreateInfo pipelineInfo = new VkGraphicsPipelineCreateInfo();

            pipelineInfo.sType               = VkStructureType.VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
            pipelineInfo.stageCount          = shaderStages.Length;
            pipelineInfo.pStages             = shaderStages;
            pipelineInfo.pVertexInputState   = vertexInputInfo;
            pipelineInfo.pInputAssemblyState = inputAssembly;
            pipelineInfo.pViewportState      = viewportState;
            pipelineInfo.pRasterizationState = rasterizer;
            pipelineInfo.pMultisampleState   = multisampling;
            pipelineInfo.pColorBlendState    = colorBlending;
            pipelineInfo.layout              = pipelineLayout;
            pipelineInfo.renderPass          = renderPass;
            pipelineInfo.subpass             = 0;
            pipelineInfo.basePipelineHandle  = null;

            VkPipeline[] pipelineResult = new VkPipeline[1];
            result = Vulkan.vkCreateGraphicsPipelines(device, null, 1, new VkGraphicsPipelineCreateInfo[] { pipelineInfo }, null, pipelineResult);
            if (result != VkResult.VK_SUCCESS)
            {
                throw Program.Throw("failed to create graphics pipeline!", result);
            }

            graphicsPipeline = pipelineResult[0];

            Vulkan.vkDestroyShaderModule(device, fragShaderModule, null);
            Vulkan.vkDestroyShaderModule(device, vertShaderModule, null);
        }
Beispiel #3
0
        public static VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo()
        {
            VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = VkPipelineVertexInputStateCreateInfo.New();

            return(pipelineVertexInputStateCreateInfo);
        }
        private VkPipeline 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.
            VkShaderModule vertexShader   = Content.LoadShader("Shader.vert.spv");
            VkShaderModule fragmentShader = Content.LoadShader("Shader.frag.spv");
            VkPipelineShaderStageCreateInfo *shaderStageCreateInfos = stackalloc VkPipelineShaderStageCreateInfo[2]
            {
                new VkPipelineShaderStageCreateInfo
                {
                    sType  = VkStructureType.PipelineShaderStageCreateInfo,
                    pNext  = null,
                    stage  = VkShaderStageFlags.Vertex,
                    module = vertexShader,
                    pName  = Interop.String.ToPointer("main")
                },
                new VkPipelineShaderStageCreateInfo
                {
                    sType  = VkStructureType.PipelineShaderStageCreateInfo,
                    pNext  = null,
                    stage  = VkShaderStageFlags.Fragment,
                    module = fragmentShader,
                    pName  = Interop.String.ToPointer("main")
                }
            };

            VkVertexInputBindingDescription vertexInputBindingDescription = new VkVertexInputBindingDescription
            {
                binding   = 0,
                stride    = (uint)Unsafe.SizeOf <Vertex>(),
                inputRate = VkVertexInputRate.Vertex
            };
            VkVertexInputAttributeDescription *vertexInputAttributeDescription = stackalloc VkVertexInputAttributeDescription[3]
            {
                new VkVertexInputAttributeDescription
                {
                    location = 0,
                    binding  = 0,
                    format   = VkFormat.R32G32B32A32SFloat,
                    offset   = 0
                },  // Position.
                new VkVertexInputAttributeDescription
                {
                    location = 1,
                    binding  = 0,
                    format   = VkFormat.R32G32B32SFloat,
                    offset   = 12
                }, // Normal.
                new VkVertexInputAttributeDescription
                {
                    location = 2,
                    binding  = 0,
                    format   = VkFormat.R32G32SFloat,
                    offset   = 24
                }// TexCoord.
            };
            var vertexInputStateCreateInfo = new VkPipelineVertexInputStateCreateInfo
            {
                sType = VkStructureType.PipelineVertexInputStateCreateInfo,
                pNext = null,
                vertexBindingDescriptionCount   = 1,
                pVertexBindingDescriptions      = &vertexInputBindingDescription,
                vertexAttributeDescriptionCount = 3,
                pVertexAttributeDescriptions    = vertexInputAttributeDescription
            };
            var inputAssemblyStateCreateInfo = new VkPipelineInputAssemblyStateCreateInfo
            {
                sType    = VkStructureType.PipelineInputAssemblyStateCreateInfo,
                pNext    = null,
                topology = VkPrimitiveTopology.TriangleList
            };

            Viewport  viewport = new Viewport(0, 0, Host.Width, Host.Height);
            Rectangle scissor  = new Rectangle(0, 0, Host.Width, Host.Height);

            var viewportStateCreateInfo = new VkPipelineViewportStateCreateInfo
            {
                sType         = VkStructureType.PipelineViewportStateCreateInfo,
                pNext         = null,
                viewportCount = 1,
                pViewports    = &viewport,
                scissorCount  = 1,
                pScissors     = &scissor
            };
            var rasterizationStateCreateInfo = new VkPipelineRasterizationStateCreateInfo
            {
                sType       = VkStructureType.PipelineRasterizationStateCreateInfo,
                polygonMode = VkPolygonMode.Fill,
                cullMode    = VkCullModeFlags.Back,
                frontFace   = VkFrontFace.CounterClockwise,
                lineWidth   = 1.0f
            };
            var multisampleStateCreateInfo = new VkPipelineMultisampleStateCreateInfo
            {
                sType = VkStructureType.PipelineMultisampleStateCreateInfo,
                rasterizationSamples = VkSampleCountFlags.Count1,
                minSampleShading     = 1.0f
            };
            var depthStencilStateCreateInfo = new VkPipelineDepthStencilStateCreateInfo
            {
                sType            = VkStructureType.PipelineDepthStencilStateCreateInfo,
                depthTestEnable  = true,
                depthWriteEnable = true,
                depthCompareOp   = VkCompareOp.LessOrEqual,
                back             = new VkStencilOpState
                {
                    failOp    = VkStencilOp.Keep,
                    passOp    = VkStencilOp.Keep,
                    compareOp = VkCompareOp.Always
                },
                front = new VkStencilOpState
                {
                    failOp    = VkStencilOp.Keep,
                    passOp    = VkStencilOp.Keep,
                    compareOp = VkCompareOp.Always
                }
            };
            var colorBlendAttachmentState = new VkPipelineColorBlendAttachmentState
            {
                srcColorBlendFactor = VkBlendFactor.One,
                dstColorBlendFactor = VkBlendFactor.Zero,
                colorBlendOp        = VkBlendOp.Add,
                srcAlphaBlendFactor = VkBlendFactor.One,
                dstAlphaBlendFactor = VkBlendFactor.Zero,
                alphaBlendOp        = VkBlendOp.Add,
                colorWriteMask      = VkColorComponentFlags.All
            };
            var colorBlendStateCreateInfo = new VkPipelineColorBlendStateCreateInfo
            {
                sType           = VkStructureType.PipelineColorBlendStateCreateInfo,
                pNext           = null,
                attachmentCount = 1,
                pAttachments    = &colorBlendAttachmentState
            };

            var pipelineCreateInfo = new VkGraphicsPipelineCreateInfo
            {
                sType               = VkStructureType.GraphicsPipelineCreateInfo,
                pNext               = null,
                layout              = _pipelineLayout,
                renderPass          = _renderPass,
                subpass             = (uint)0,
                stageCount          = 2,
                pStages             = shaderStageCreateInfos,
                pInputAssemblyState = &inputAssemblyStateCreateInfo,
                pVertexInputState   = &vertexInputStateCreateInfo,
                pRasterizationState = &rasterizationStateCreateInfo,
                pMultisampleState   = &multisampleStateCreateInfo,
                pColorBlendState    = &colorBlendStateCreateInfo,
                pDepthStencilState  = &depthStencilStateCreateInfo,
                pViewportState      = &viewportStateCreateInfo
            };


            VkPipeline pipeline;
            VkResult   result = vkCreateGraphicsPipelines(Context.Device, VkPipelineCache.Null, 1, &pipelineCreateInfo, null, &pipeline);

            result.CheckResult();

            return(pipeline);
        }
    }
}
Beispiel #5
0
        public VkPipeline(VkGraphicsDevice gd, ref GraphicsPipelineDescription description)
            : base(ref description)
        {
            _gd = gd;
            IsComputePipeline = false;

            VkGraphicsPipelineCreateInfo pipelineCI = VkGraphicsPipelineCreateInfo.New();

            // Blend State
            VkPipelineColorBlendStateCreateInfo blendStateCI = VkPipelineColorBlendStateCreateInfo.New();
            int attachmentsCount = description.BlendState.AttachmentStates.Length;
            VkPipelineColorBlendAttachmentState *attachmentsPtr
                = stackalloc VkPipelineColorBlendAttachmentState[attachmentsCount];

            for (int i = 0; i < attachmentsCount; i++)
            {
                BlendAttachmentDescription          vdDesc          = description.BlendState.AttachmentStates[i];
                VkPipelineColorBlendAttachmentState attachmentState = new VkPipelineColorBlendAttachmentState();
                attachmentState.srcColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceColorFactor);
                attachmentState.dstColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationColorFactor);
                attachmentState.colorBlendOp        = VkFormats.VdToVkBlendOp(vdDesc.ColorFunction);
                attachmentState.srcAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceAlphaFactor);
                attachmentState.dstAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationAlphaFactor);
                attachmentState.alphaBlendOp        = VkFormats.VdToVkBlendOp(vdDesc.AlphaFunction);
                attachmentState.blendEnable         = vdDesc.BlendEnabled;
                attachmentState.colorWriteMask      = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A;
                attachmentsPtr[i] = attachmentState;
            }

            blendStateCI.attachmentCount = (uint)attachmentsCount;
            blendStateCI.pAttachments    = attachmentsPtr;
            RgbaFloat blendFactor = description.BlendState.BlendFactor;

            blendStateCI.blendConstants_0 = blendFactor.R;
            blendStateCI.blendConstants_1 = blendFactor.G;
            blendStateCI.blendConstants_2 = blendFactor.B;
            blendStateCI.blendConstants_3 = blendFactor.A;

            pipelineCI.pColorBlendState = &blendStateCI;

            // Rasterizer State
            RasterizerStateDescription             rsDesc = description.RasterizerState;
            VkPipelineRasterizationStateCreateInfo rsCI   = VkPipelineRasterizationStateCreateInfo.New();

            rsCI.cullMode         = VkFormats.VdToVkCullMode(rsDesc.CullMode);
            rsCI.polygonMode      = VkFormats.VdToVkPolygonMode(rsDesc.FillMode);
            rsCI.depthClampEnable = !rsDesc.DepthClipEnabled;
            rsCI.frontFace        = rsDesc.FrontFace == FrontFace.Clockwise ? VkFrontFace.Clockwise : VkFrontFace.CounterClockwise;
            rsCI.lineWidth        = 1f;

            pipelineCI.pRasterizationState = &rsCI;

            ScissorTestEnabled = rsDesc.ScissorTestEnabled;

            // Dynamic State
            VkPipelineDynamicStateCreateInfo dynamicStateCI = VkPipelineDynamicStateCreateInfo.New();
            VkDynamicState *dynamicStates = stackalloc VkDynamicState[2];

            dynamicStates[0] = VkDynamicState.Viewport;
            dynamicStates[1] = VkDynamicState.Scissor;
            dynamicStateCI.dynamicStateCount = 2;
            dynamicStateCI.pDynamicStates    = dynamicStates;

            pipelineCI.pDynamicState = &dynamicStateCI;

            // Depth Stencil State
            DepthStencilStateDescription          vdDssDesc = description.DepthStencilState;
            VkPipelineDepthStencilStateCreateInfo dssCI     = VkPipelineDepthStencilStateCreateInfo.New();

            dssCI.depthWriteEnable  = vdDssDesc.DepthWriteEnabled;
            dssCI.depthTestEnable   = vdDssDesc.DepthTestEnabled;
            dssCI.depthCompareOp    = VkFormats.VdToVkCompareOp(vdDssDesc.DepthComparison);
            dssCI.stencilTestEnable = vdDssDesc.StencilTestEnabled;

            dssCI.front.failOp      = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.Fail);
            dssCI.front.passOp      = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.Pass);
            dssCI.front.depthFailOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.DepthFail);
            dssCI.front.compareMask = vdDssDesc.StencilReadMask;
            dssCI.front.writeMask   = vdDssDesc.StencilWriteMask;
            dssCI.front.reference   = vdDssDesc.StencilReference;

            dssCI.back.failOp      = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.Fail);
            dssCI.back.passOp      = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.Pass);
            dssCI.back.depthFailOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.DepthFail);
            dssCI.back.compareMask = vdDssDesc.StencilReadMask;
            dssCI.back.writeMask   = vdDssDesc.StencilWriteMask;
            dssCI.back.reference   = vdDssDesc.StencilReference;

            pipelineCI.pDepthStencilState = &dssCI;

            // Multisample
            VkPipelineMultisampleStateCreateInfo multisampleCI = VkPipelineMultisampleStateCreateInfo.New();
            VkSampleCountFlags vkSampleCount = VkFormats.VdToVkSampleCount(description.Outputs.SampleCount);

            multisampleCI.rasterizationSamples = vkSampleCount;

            pipelineCI.pMultisampleState = &multisampleCI;

            // Input Assembly
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyCI = VkPipelineInputAssemblyStateCreateInfo.New();

            inputAssemblyCI.topology = VkFormats.VdToVkPrimitiveTopology(description.PrimitiveTopology);

            pipelineCI.pInputAssemblyState = &inputAssemblyCI;

            // Vertex Input State
            VkPipelineVertexInputStateCreateInfo vertexInputCI = VkPipelineVertexInputStateCreateInfo.New();

            VertexLayoutDescription[] inputDescriptions = description.ShaderSet.VertexLayouts;
            uint bindingCount   = (uint)inputDescriptions.Length;
            uint attributeCount = 0;

            for (int i = 0; i < inputDescriptions.Length; i++)
            {
                attributeCount += (uint)inputDescriptions[i].Elements.Length;
            }
            VkVertexInputBindingDescription *  bindingDescs   = stackalloc VkVertexInputBindingDescription[(int)bindingCount];
            VkVertexInputAttributeDescription *attributeDescs = stackalloc VkVertexInputAttributeDescription[(int)attributeCount];

            int targetIndex    = 0;
            int targetLocation = 0;

            for (int binding = 0; binding < inputDescriptions.Length; binding++)
            {
                VertexLayoutDescription inputDesc = inputDescriptions[binding];
                bindingDescs[binding] = new VkVertexInputBindingDescription()
                {
                    binding   = (uint)binding,
                    inputRate = (inputDesc.InstanceStepRate != 0) ? VkVertexInputRate.Instance : VkVertexInputRate.Vertex,
                    stride    = inputDesc.Stride
                };

                uint currentOffset = 0;
                for (int location = 0; location < inputDesc.Elements.Length; location++)
                {
                    VertexElementDescription inputElement = inputDesc.Elements[location];

                    attributeDescs[targetIndex] = new VkVertexInputAttributeDescription()
                    {
                        format   = VkFormats.VdToVkVertexElementFormat(inputElement.Format),
                        binding  = (uint)binding,
                        location = (uint)(targetLocation + location),
                        offset   = currentOffset
                    };

                    targetIndex   += 1;
                    currentOffset += FormatHelpers.GetSizeInBytes(inputElement.Format);
                }

                targetLocation += inputDesc.Elements.Length;
            }

            vertexInputCI.vertexBindingDescriptionCount   = bindingCount;
            vertexInputCI.pVertexBindingDescriptions      = bindingDescs;
            vertexInputCI.vertexAttributeDescriptionCount = attributeCount;
            vertexInputCI.pVertexAttributeDescriptions    = attributeDescs;

            pipelineCI.pVertexInputState = &vertexInputCI;

            // Shader Stage
            Shader[] shaders = description.ShaderSet.Shaders;
            StackList <VkPipelineShaderStageCreateInfo> stages = new StackList <VkPipelineShaderStageCreateInfo>();

            foreach (Shader shader in shaders)
            {
                VkShader vkShader = Util.AssertSubtype <Shader, VkShader>(shader);
                VkPipelineShaderStageCreateInfo stageCI = VkPipelineShaderStageCreateInfo.New();
                stageCI.module = vkShader.ShaderModule;
                stageCI.stage  = VkFormats.VdToVkShaderStages(shader.Stage);
                stageCI.pName  = CommonStrings.main; // Meh
                stages.Add(stageCI);
            }

            pipelineCI.stageCount = stages.Count;
            pipelineCI.pStages    = (VkPipelineShaderStageCreateInfo *)stages.Data;

            // ViewportState
            VkPipelineViewportStateCreateInfo viewportStateCI = VkPipelineViewportStateCreateInfo.New();

            viewportStateCI.viewportCount = 1;
            viewportStateCI.scissorCount  = 1;

            pipelineCI.pViewportState = &viewportStateCI;

            // Pipeline Layout
            ResourceLayout[]           resourceLayouts  = description.ResourceLayouts;
            VkPipelineLayoutCreateInfo pipelineLayoutCI = VkPipelineLayoutCreateInfo.New();

            pipelineLayoutCI.setLayoutCount = (uint)resourceLayouts.Length;
            VkDescriptorSetLayout *dsls = stackalloc VkDescriptorSetLayout[resourceLayouts.Length];

            for (int i = 0; i < resourceLayouts.Length; i++)
            {
                dsls[i] = Util.AssertSubtype <ResourceLayout, VkResourceLayout>(resourceLayouts[i]).DescriptorSetLayout;
            }
            pipelineLayoutCI.pSetLayouts = dsls;

            vkCreatePipelineLayout(_gd.Device, ref pipelineLayoutCI, null, out _pipelineLayout);
            pipelineCI.layout = _pipelineLayout;

            // Create fake RenderPass for compatibility.

            VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New();
            OutputDescription      outputDesc   = description.Outputs;
            StackList <VkAttachmentDescription, Size512Bytes> attachments = new StackList <VkAttachmentDescription, Size512Bytes>();

            // TODO: A huge portion of this next part is duplicated in VkFramebuffer.cs.

            StackList <VkAttachmentDescription> colorAttachmentDescs = new StackList <VkAttachmentDescription>();
            StackList <VkAttachmentReference>   colorAttachmentRefs  = new StackList <VkAttachmentReference>();

            for (uint i = 0; i < outputDesc.ColorAttachments.Length; i++)
            {
                colorAttachmentDescs[i].format         = VkFormats.VdToVkPixelFormat(outputDesc.ColorAttachments[i].Format);
                colorAttachmentDescs[i].samples        = vkSampleCount;
                colorAttachmentDescs[i].loadOp         = VkAttachmentLoadOp.DontCare;
                colorAttachmentDescs[i].storeOp        = VkAttachmentStoreOp.Store;
                colorAttachmentDescs[i].stencilLoadOp  = VkAttachmentLoadOp.DontCare;
                colorAttachmentDescs[i].stencilStoreOp = VkAttachmentStoreOp.DontCare;
                colorAttachmentDescs[i].initialLayout  = VkImageLayout.Undefined;
                colorAttachmentDescs[i].finalLayout    = VkImageLayout.ShaderReadOnlyOptimal;
                attachments.Add(colorAttachmentDescs[i]);

                colorAttachmentRefs[i].attachment = i;
                colorAttachmentRefs[i].layout     = VkImageLayout.ColorAttachmentOptimal;
            }

            VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription();
            VkAttachmentReference   depthAttachmentRef  = new VkAttachmentReference();

            if (outputDesc.DepthAttachment != null)
            {
                PixelFormat depthFormat = outputDesc.DepthAttachment.Value.Format;
                bool        hasStencil  = FormatHelpers.IsStencilFormat(depthFormat);
                depthAttachmentDesc.format         = VkFormats.VdToVkPixelFormat(outputDesc.DepthAttachment.Value.Format, toDepthFormat: true);
                depthAttachmentDesc.samples        = vkSampleCount;
                depthAttachmentDesc.loadOp         = VkAttachmentLoadOp.DontCare;
                depthAttachmentDesc.storeOp        = VkAttachmentStoreOp.Store;
                depthAttachmentDesc.stencilLoadOp  = VkAttachmentLoadOp.DontCare;
                depthAttachmentDesc.stencilStoreOp = hasStencil ? VkAttachmentStoreOp.Store : VkAttachmentStoreOp.DontCare;
                depthAttachmentDesc.initialLayout  = VkImageLayout.Undefined;
                depthAttachmentDesc.finalLayout    = VkImageLayout.DepthStencilAttachmentOptimal;

                depthAttachmentRef.attachment = (uint)outputDesc.ColorAttachments.Length;
                depthAttachmentRef.layout     = VkImageLayout.DepthStencilAttachmentOptimal;
            }

            VkSubpassDescription subpass = new VkSubpassDescription();

            subpass.pipelineBindPoint    = VkPipelineBindPoint.Graphics;
            subpass.colorAttachmentCount = (uint)outputDesc.ColorAttachments.Length;
            subpass.pColorAttachments    = (VkAttachmentReference *)colorAttachmentRefs.Data;
            for (int i = 0; i < colorAttachmentDescs.Count; i++)
            {
                attachments.Add(colorAttachmentDescs[i]);
            }

            if (outputDesc.DepthAttachment != null)
            {
                subpass.pDepthStencilAttachment = &depthAttachmentRef;
                attachments.Add(depthAttachmentDesc);
            }

            VkSubpassDependency subpassDependency = new VkSubpassDependency();

            subpassDependency.srcSubpass    = SubpassExternal;
            subpassDependency.srcStageMask  = VkPipelineStageFlags.ColorAttachmentOutput;
            subpassDependency.dstStageMask  = VkPipelineStageFlags.ColorAttachmentOutput;
            subpassDependency.dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite;
            if (outputDesc.DepthAttachment != null)
            {
                subpassDependency.dstAccessMask |= VkAccessFlags.DepthStencilAttachmentRead | VkAccessFlags.DepthStencilAttachmentWrite;
            }

            renderPassCI.attachmentCount = attachments.Count;
            renderPassCI.pAttachments    = (VkAttachmentDescription *)attachments.Data;
            renderPassCI.subpassCount    = 1;
            renderPassCI.pSubpasses      = &subpass;
            renderPassCI.dependencyCount = 1;
            renderPassCI.pDependencies   = &subpassDependency;

            VkResult creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPass);

            CheckResult(creationResult);

            pipelineCI.renderPass = _renderPass;

            VkResult result = vkCreateGraphicsPipelines(_gd.Device, VkPipelineCache.Null, 1, ref pipelineCI, null, out _devicePipeline);

            CheckResult(result);

            ResourceSetCount = (uint)description.ResourceLayouts.Length;
        }
Beispiel #6
0
        public Pipeline Build()
        {
            var stages         = _stages.ToArray();
            var vertexBindings = new VkVertexInputBindingDescription[_vertexBindingDescriptions.Count];
            {
                var i = 0;
                foreach (var kv in _vertexBindingDescriptions)
                {
                    vertexBindings[i++] = kv.Value;
                }
            }
            var attributeBindings = new VkVertexInputAttributeDescription[_vertexAttributeDescriptions.Count];
            {
                var i = 0;
                foreach (var kv in _vertexAttributeDescriptions)
                {
                    attributeBindings[i++] = kv.Value;
                }
            }
            var blendStates = new VkPipelineColorBlendAttachmentState[_blendAttachmentStates.Count];

            foreach (var kv in _blendAttachmentStates)
            {
                blendStates[kv.Key] = kv.Value;
            }
            var viewports     = _viewports.ToArray();
            var scissors      = _viewportScissors.ToArray();
            var dynamicStates = _dynamicStates.ToArray();


            try
            {
                unsafe
                {
                    fixed(VkViewport *viewportPtr = viewports)
                    fixed(VkRect2D * scissorPtr       = scissors)
                    fixed(VkDynamicState * dynamicPtr = dynamicStates)
                    fixed(VkPipelineColorBlendAttachmentState * blendPtr   = blendStates)
                    fixed(VkVertexInputBindingDescription * vertexPtr      = vertexBindings)
                    fixed(VkVertexInputAttributeDescription * attributePtr = attributeBindings)
                    fixed(VkPipelineShaderStageCreateInfo * stagePtr       = stages)
                    {
                        if (_basePipeline != null)
                        {
                            _flags |= VkPipelineCreateFlag.Derivative;
                        }
                        else
                        {
                            _flags &= ~VkPipelineCreateFlag.Derivative;
                        }

                        var vertexInputState = new VkPipelineVertexInputStateCreateInfo()
                        {
                            SType = VkStructureType.PipelineVertexInputStateCreateInfo,
                            PNext = IntPtr.Zero,
                            Flags = 0,
                            VertexBindingDescriptionCount   = (uint)vertexBindings.Length,
                            PVertexBindingDescriptions      = vertexPtr,
                            VertexAttributeDescriptionCount = (uint)attributeBindings.Length,
                            PVertexAttributeDescriptions    = attributePtr
                        };

                        var assemblyState = _asmInfo;
                        var tessState     = _tessInfo;

                        var viewportState = new VkPipelineViewportStateCreateInfo()
                        {
                            SType         = VkStructureType.PipelineViewportStateCreateInfo,
                            PNext         = IntPtr.Zero,
                            Flags         = 0,
                            ViewportCount = (uint)viewports.Length,
                            PViewports    = viewportPtr,
                            ScissorCount  = (uint)scissors.Length,
                            PScissors     = scissorPtr
                        };

                        var rasterState       = _rasterInfo;
                        var multisampleState  = _multisampleInfo;
                        var depthStencilState = _depthStencilInfo;
                        var colorBlendState   = _colorBlendInfo;

                        colorBlendState.AttachmentCount = (uint)blendStates.Length;
                        colorBlendState.PAttachments    = blendPtr;

                        var dynamicState = new VkPipelineDynamicStateCreateInfo()
                        {
                            SType             = VkStructureType.PipelineDynamicStateCreateInfo,
                            PNext             = IntPtr.Zero,
                            Flags             = 0,
                            DynamicStateCount = (uint)dynamicStates.Length,
                            PDynamicStates    = dynamicPtr
                        };

                        var info = new VkGraphicsPipelineCreateInfo()
                        {
                            SType               = VkStructureType.GraphicsPipelineCreateInfo,
                            PNext               = IntPtr.Zero,
                            Flags               = _flags,
                            StageCount          = (uint)stages.Length,
                            PStages             = stagePtr,
                            PVertexInputState   = &vertexInputState,
                            PInputAssemblyState = &assemblyState,
                            PTessellationState  = &tessState,
                            PViewportState      = &viewportState,
                            PRasterizationState = &rasterState,
                            PMultisampleState   = &multisampleState,
                            PDepthStencilState  = &depthStencilState,
                            PColorBlendState    = &colorBlendState,
                            PDynamicState       =
                                dynamicStates.Length > 0 ? &dynamicState : (VkPipelineDynamicStateCreateInfo *)0,
                            Layout             = _pipelineLayout.Handle,
                            RenderPass         = _pass.Handle,
                            Subpass            = _subpassId,
                            BasePipelineHandle = _basePipeline?.Handle ?? VkPipeline.Null,
                            BasePipelineIndex  = _basePipelineIndex
                        };

                        VkPipeline result = VkPipeline.Null;

                        VkException.Check(VkDevice.vkCreateGraphicsPipelines(_pass.Device.Handle, VkPipelineCache.Null,
                                                                             1,
                                                                             &info, _pass.Instance.AllocationCallbacks, &result));
                        Debug.Assert(result != VkPipeline.Null);
                        return(new Pipeline(_pass.Device, VkPipelineBindPoint.Graphics, _pipelineLayout, result));
                    }
                }
            }
            finally
            {
                foreach (var pin in _pins)
                {
                    pin.Free();
                }
                foreach (var strPin in _strPins)
                {
                    Marshal.FreeHGlobal(strPin);
                }
            }
        }
Beispiel #7
0
        void CreateGraphicsPipeline()
        {
            var vert = CreateShaderModule(File.ReadAllBytes("vert.spv"));
            var frag = CreateShaderModule(File.ReadAllBytes("frag.spv"));

            var vertInfo = new VkPipelineShaderStageCreateInfo();

            vertInfo.stage  = VkShaderStageFlags.VertexBit;
            vertInfo.module = vert;
            vertInfo.name   = "main";

            var fragInfo = new VkPipelineShaderStageCreateInfo();

            fragInfo.stage  = VkShaderStageFlags.FragmentBit;
            fragInfo.module = frag;
            fragInfo.name   = "main";

            var shaderStages = new List <VkPipelineShaderStageCreateInfo> {
                vertInfo, fragInfo
            };

            var vertexInputInfo = new VkPipelineVertexInputStateCreateInfo();

            vertexInputInfo.vertexBindingDescriptions = new List <VkVertexInputBindingDescription> {
                Vertex.GetBindingDescription()
            };
            vertexInputInfo.vertexAttributeDescriptions = Vertex.GetAttributeDescriptions();

            var inputAssembly = new VkPipelineInputAssemblyStateCreateInfo();

            inputAssembly.topology = VkPrimitiveTopology.TriangleList;

            var viewport = new VkViewport();

            viewport.width    = swapchainExtent.width;
            viewport.height   = swapchainExtent.height;
            viewport.minDepth = 0f;
            viewport.maxDepth = 1f;

            var scissor = new VkRect2D();

            scissor.extent = swapchainExtent;

            var viewportState = new VkPipelineViewportStateCreateInfo();

            viewportState.viewports = new List <VkViewport> {
                viewport
            };
            viewportState.scissors = new List <VkRect2D> {
                scissor
            };

            var rasterizer = new VkPipelineRasterizationStateCreateInfo();

            rasterizer.polygonMode = VkPolygonMode.Fill;
            rasterizer.lineWidth   = 1f;
            rasterizer.cullMode    = VkCullModeFlags.BackBit;
            rasterizer.frontFace   = VkFrontFace.CounterClockwise;

            var multisampling = new VkPipelineMultisampleStateCreateInfo();

            multisampling.rasterizationSamples = VkSampleCountFlags._1_Bit;
            multisampling.minSampleShading     = 1f;

            var colorBlendAttachment = new VkPipelineColorBlendAttachmentState();

            colorBlendAttachment.colorWriteMask = VkColorComponentFlags.RBit
                                                  | VkColorComponentFlags.GBit
                                                  | VkColorComponentFlags.BBit
                                                  | VkColorComponentFlags.ABit;
            colorBlendAttachment.srcColorBlendFactor = VkBlendFactor.One;
            colorBlendAttachment.dstColorBlendFactor = VkBlendFactor.Zero;
            colorBlendAttachment.colorBlendOp        = VkBlendOp.Add;
            colorBlendAttachment.srcAlphaBlendFactor = VkBlendFactor.One;
            colorBlendAttachment.dstAlphaBlendFactor = VkBlendFactor.Zero;
            colorBlendAttachment.alphaBlendOp        = VkBlendOp.Add;

            var colorBlending = new VkPipelineColorBlendStateCreateInfo();

            colorBlending.logicOp     = VkLogicOp.Copy;
            colorBlending.attachments = new List <VkPipelineColorBlendAttachmentState> {
                colorBlendAttachment
            };

            var pipelineLayoutInfo = new VkPipelineLayoutCreateInfo();

            pipelineLayoutInfo.setLayouts = new List <VkDescriptorSetLayout> {
                descriptorSetLayout
            };

            pipelineLayout?.Dispose();

            pipelineLayout = new VkPipelineLayout(device, pipelineLayoutInfo);

            var info = new VkGraphicsPipelineCreateInfo();

            info.stages             = shaderStages;
            info.vertexInputState   = vertexInputInfo;
            info.inputAssemblyState = inputAssembly;
            info.viewportState      = viewportState;
            info.rasterizationState = rasterizer;
            info.multisampleState   = multisampling;
            info.colorBlendState    = colorBlending;
            info.layout             = pipelineLayout;
            info.renderPass         = renderPass;
            info.subpass            = 0;
            info.basePipelineHandle = null;
            info.basePipelineIndex  = -1;

            pipeline?.Dispose();

            pipeline = new VkGraphicsPipeline(device, info, null);

            vert.Dispose();
            frag.Dispose();
        }
Beispiel #8
0
        public unsafe GraphicsPipeline(
            Device device,
            RenderPass renderPass,
            List <DescriptorLayout> layouts,
            List <ShaderModule> shaders,
            PipelineInputBuilder pipelineInputBuilder,
            uint subPass            = 0,
            PipelineOptions options = null
            ) : base(device, renderPass, VkPipelineLayout.Null, VkPipeline.Null)
        {
            if (options == null)
            {
                options = PipelineOptions.Default;
            }

            #region Pipeline Layout

            var setLayout = new NativeList <VkDescriptorSetLayout>();
            foreach (var layout in layouts)
            {
                setLayout.Add(layout.Handle);
            }

            var pipelineLayoutInfo = new VkPipelineLayoutCreateInfo
            {
                sType          = VkStructureType.PipelineLayoutCreateInfo,
                setLayoutCount = setLayout.Count,
                pSetLayouts    = (VkDescriptorSetLayout *)setLayout.Data.ToPointer()
            };

            VkPipelineLayout pipelineLayout;
            if (VulkanNative.vkCreatePipelineLayout(
                    device.Handle,
                    &pipelineLayoutInfo,
                    null,
                    &pipelineLayout
                    ) != VkResult.Success)
            {
                throw new Exception("failed to create pipeline layout");
            }
            _layout = pipelineLayout;

            #endregion

            var bindingDescriptions   = pipelineInputBuilder.BindingDescriptions;
            var attributeDescriptions = pipelineInputBuilder.AttributeDescriptions;

            var vertexInputInfo = new VkPipelineVertexInputStateCreateInfo
            {
                sType = VkStructureType.PipelineVertexInputStateCreateInfo,
                vertexBindingDescriptionCount   = bindingDescriptions.Count,
                pVertexBindingDescriptions      = (VkVertexInputBindingDescription *)bindingDescriptions.Data.ToPointer(),
                vertexAttributeDescriptionCount = attributeDescriptions.Count,
                pVertexAttributeDescriptions    = (VkVertexInputAttributeDescription *)attributeDescriptions.Data.ToPointer()
            };

            var inputAssemble = new VkPipelineInputAssemblyStateCreateInfo
            {
                sType    = VkStructureType.PipelineInputAssemblyStateCreateInfo,
                topology = options.Topology,
                primitiveRestartEnable = VkBool32.False
            };

            var viewport = new VkViewport(); //dynamic (ignored)
            var scissor  = new VkRect2D();   //dynamic (ignored)

            var viewportState = new VkPipelineViewportStateCreateInfo
            {
                sType         = VkStructureType.PipelineViewportStateCreateInfo,
                viewportCount = 1,
                pViewports    = &viewport,
                scissorCount  = 1,
                pScissors     = &scissor
            };

            var rasterizer = new VkPipelineRasterizationStateCreateInfo
            {
                sType                   = VkStructureType.PipelineRasterizationStateCreateInfo,
                depthClampEnable        = false,
                rasterizerDiscardEnable = VkBool32.False,
                polygonMode             = options.PolygonMode,
                lineWidth               = 1.0f,
                cullMode                = options.CullMode,
                frontFace               = options.FrontFace,
                depthBiasEnable         = VkBool32.False
            };

            var multisampling = new VkPipelineMultisampleStateCreateInfo
            {
                sType = VkStructureType.PipelineMultisampleStateCreateInfo,
                sampleShadingEnable   = VkBool32.False,
                rasterizationSamples  = VkSampleCountFlags.Count1,
                minSampleShading      = 1.0f,
                pSampleMask           = null,
                alphaToCoverageEnable = VkBool32.False,
                alphaToOneEnable      = VkBool32.False
            };

            bool hasDepthAttachment    = false;
            var  colorBlendAttachments = new NativeList <VkPipelineColorBlendAttachmentState>();
            foreach (var attachment in renderPass.Attachments)
            {
                if ((attachment.ImageUsageFlags & VkImageUsageFlags.DepthStencilAttachment) != 0)
                {
                    hasDepthAttachment = true;
                    continue;
                }

                colorBlendAttachments.Add(new VkPipelineColorBlendAttachmentState
                {
                    colorWriteMask = (
                        VkColorComponentFlags.R |
                        VkColorComponentFlags.G |
                        VkColorComponentFlags.B |
                        VkColorComponentFlags.A
                        ),
                    blendEnable = VkBool32.False,
                });
            }

            var depthStencil = new VkPipelineDepthStencilStateCreateInfo
            {
                sType                 = VkStructureType.PipelineDepthStencilStateCreateInfo,
                depthTestEnable       = VkBool32.True,
                depthWriteEnable      = VkBool32.True,
                depthCompareOp        = VkCompareOp.Less,
                depthBoundsTestEnable = VkBool32.False,
                stencilTestEnable     = VkBool32.False,
            };

            var colorBlending = new VkPipelineColorBlendStateCreateInfo
            {
                sType            = VkStructureType.PipelineColorBlendStateCreateInfo,
                logicOpEnable    = VkBool32.False,
                logicOp          = VkLogicOp.Copy,
                attachmentCount  = colorBlendAttachments.Count,
                pAttachments     = (VkPipelineColorBlendAttachmentState *)colorBlendAttachments.Data.ToPointer(),
                blendConstants_0 = 0.0f,
                blendConstants_1 = 0.0f,
                blendConstants_2 = 0.0f,
                blendConstants_3 = 0.0f
            };

            var dynamicStates = new NativeList <VkDynamicState>();
            dynamicStates.Add(VkDynamicState.Viewport);
            dynamicStates.Add(VkDynamicState.Scissor);
            dynamicStates.Add(VkDynamicState.LineWidth);

            var dynamicStateInfo = new VkPipelineDynamicStateCreateInfo
            {
                sType             = VkStructureType.PipelineDynamicStateCreateInfo,
                dynamicStateCount = dynamicStates.Count,
                pDynamicStates    = (VkDynamicState *)dynamicStates.Data.ToPointer()
            };

            var shaderInfo = new NativeList <VkPipelineShaderStageCreateInfo>();
            foreach (var shader in shaders)
            {
                shaderInfo.Add(new VkPipelineShaderStageCreateInfo
                {
                    sType  = VkStructureType.PipelineShaderStageCreateInfo,
                    module = shader.Handle,
                    stage  = (VkShaderStageFlags)shader.Type,
                    pName  = GraphicsApiConstants.MAIN
                });
            }

            var pipelineInfo = new VkGraphicsPipelineCreateInfo
            {
                sType               = VkStructureType.GraphicsPipelineCreateInfo,
                stageCount          = shaderInfo.Count,
                pStages             = (VkPipelineShaderStageCreateInfo *)shaderInfo.Data.ToPointer(),
                pVertexInputState   = &vertexInputInfo,
                pInputAssemblyState = &inputAssemble,
                pViewportState      = &viewportState,
                pRasterizationState = &rasterizer,
                pMultisampleState   = &multisampling,
                pDepthStencilState  = hasDepthAttachment ? &depthStencil : null,
                pColorBlendState    = &colorBlending,
                pDynamicState       = &dynamicStateInfo,
                layout              = _layout,
                renderPass          = _renderPass.Handle,
                subpass             = subPass,
                basePipelineHandle  = VkPipeline.Null,
                basePipelineIndex   = -1
            };

            VkPipeline pipeline;
            if (VulkanNative.vkCreateGraphicsPipelines(
                    _device.Handle,
                    VkPipelineCache.Null,
                    1,
                    &pipelineInfo,
                    null,
                    &pipeline
                    ) != VkResult.Success)
            {
                throw new Exception("faield to create graphics pipeline");
            }
            _handle = pipeline;
        }