Example #1
0
        void preparePipelines()
        {
            var inputAssemblyState = new VkPipelineInputAssemblyStateCreateInfo();

            inputAssemblyState.sType    = PipelineInputAssemblyStateCreateInfo;
            inputAssemblyState.topology = VkPrimitiveTopology.TriangleList;
            inputAssemblyState.flags    = 0;
            inputAssemblyState.primitiveRestartEnable = false;

            var rasterizationState = new VkPipelineRasterizationStateCreateInfo();

            rasterizationState.sType       = PipelineRasterizationStateCreateInfo;
            rasterizationState.polygonMode = VkPolygonMode.Fill;
            rasterizationState.cullMode    = VkCullModeFlagBits.Back;
            rasterizationState.frontFace   = VkFrontFace.Clockwise;
            rasterizationState.flags       = 0;

            var blendAttachmentState = new VkPipelineColorBlendAttachmentState();

            blendAttachmentState.colorWriteMask = (VkColorComponentFlagBits)0xf;
            blendAttachmentState.blendEnable    = false;

            var colorBlendState = new VkPipelineColorBlendStateCreateInfo();

            colorBlendState.sType       = PipelineColorBlendStateCreateInfo;
            colorBlendState.attachments = blendAttachmentState;

            var depthStencilState = new VkPipelineDepthStencilStateCreateInfo();

            depthStencilState.sType            = PipelineDepthStencilStateCreateInfo;
            depthStencilState.depthTestEnable  = true;
            depthStencilState.depthWriteEnable = true;
            depthStencilState.depthCompareOp   = VkCompareOp.LessOrEqual;

            var viewportState = new VkPipelineViewportStateCreateInfo();

            viewportState.sType           = PipelineViewportStateCreateInfo;
            viewportState.viewports.count = 1;
            viewportState.scissors.count  = 1;
            viewportState.flags           = 0;

            var multisampleState = new VkPipelineMultisampleStateCreateInfo();

            multisampleState.sType = PipelineMultisampleStateCreateInfo;
            multisampleState.rasterizationSamples = VkSampleCountFlagBits._1;
            multisampleState.flags = 0;

            var dynamicStateEnables = new VkDynamicState[2];

            dynamicStateEnables[0] = VkDynamicState.Viewport;
            dynamicStateEnables[1] = VkDynamicState.Scissor;
            VkPipelineDynamicStateCreateInfo dynamicState = new VkPipelineDynamicStateCreateInfo();

            dynamicState.sType         = PipelineDynamicStateCreateInfo;
            dynamicState.dynamicStates = dynamicStateEnables;
            dynamicState.flags         = 0;

            // Solid rendering pipeline
            // Load shaders
            var shaderStages = new VkPipelineShaderStageCreateInfo[2];

            shaderStages[0] = loadShader(getAssetPath() + "shaders/mesh/mesh.vert.spv", VkShaderStageFlagBits.Vertex);
            shaderStages[1] = loadShader(getAssetPath() + "shaders/mesh/mesh.frag.spv", VkShaderStageFlagBits.Fragment);

            var info = new VkGraphicsPipelineCreateInfo();

            info.sType      = GraphicsPipelineCreateInfo;
            info.layout     = pipelineLayout;
            info.renderPass = renderPass;
            info.flags      = 0;

            var via = vInputStateInfo;

            info.pVertexInputState   = via;
            info.pInputAssemblyState = &inputAssemblyState;
            info.pRasterizationState = &rasterizationState;
            info.pColorBlendState    = &colorBlendState;
            info.pMultisampleState   = &multisampleState;
            info.pViewportState      = &viewportState;
            info.pDepthStencilState  = &depthStencilState;
            info.pDynamicState       = &dynamicState;
            info.stages = shaderStages;
            {
                VkPipeline pipeline;
                vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, null, &pipeline);
                this.pipelines_solid = pipeline;
            }

            // Wire frame rendering pipeline
            if (DeviceFeatures.fillModeNonSolid == true)
            {
                rasterizationState.polygonMode = VkPolygonMode.Line;
                rasterizationState.lineWidth   = 1.0f;
                VkPipeline pipeline;
                vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, null, &pipeline);
                this.pipelines_wireframe = pipeline;
            }
        }
Example #2
0
        void preparePipelines()
        {
            var inputAssemblyState = VkPipelineInputAssemblyStateCreateInfo.Alloc();

            inputAssemblyState[0].topology = VkPrimitiveTopology.TriangleList;
            inputAssemblyState[0].primitiveRestartEnable = false;

            var rasterizationState = VkPipelineRasterizationStateCreateInfo.Alloc();

            rasterizationState[0].polygonMode      = VkPolygonMode.Fill;
            rasterizationState[0].cullMode         = VkCullModeFlagBits.None;
            rasterizationState[0].frontFace        = VkFrontFace.CounterClockwise;
            rasterizationState[0].depthClampEnable = false;
            rasterizationState[0].lineWidth        = 1.0f;

            var blendAttachmentState = VkPipelineColorBlendAttachmentState.Alloc();

            blendAttachmentState[0].colorWriteMask = (VkColorComponentFlagBits)0xf;
            blendAttachmentState[0].blendEnable    = false;

            var colorBlendState = VkPipelineColorBlendStateCreateInfo.Alloc();

            colorBlendState[0].attachments.count   = 1;
            colorBlendState[0].attachments.pointer = blendAttachmentState;

            var depthStencilState = VkPipelineDepthStencilStateCreateInfo.Alloc();

            depthStencilState[0].depthTestEnable  = true;
            depthStencilState[0].depthWriteEnable = true;
            depthStencilState[0].depthCompareOp   = VkCompareOp.LessOrEqual;
            depthStencilState[0].front            = depthStencilState[0].back;
            depthStencilState[0].back.compareOp   = VkCompareOp.Always;

            var viewportState = VkPipelineViewportStateCreateInfo.Alloc();

            viewportState[0].viewports.count = 1;
            viewportState[0].scissors.count  = 1;

            var multisampleState = VkPipelineMultisampleStateCreateInfo.Alloc();

            multisampleState[0].rasterizationSamples = VkSampleCountFlagBits._1;

            var dynamicStateEnables = new VkDynamicState[] {
                VkDynamicState.Viewport,
                VkDynamicState.Scissor
            };
            var dynamicState = VkPipelineDynamicStateCreateInfo.Alloc();

            dynamicState[0].dynamicStates = dynamicStateEnables;

            // Load shaders
            var shaderStages = VkPipelineShaderStageCreateInfo.Alloc(2);

            shaderStages[0] = loadShader(getAssetPath() + "shaders/texture/texture.vert.spv", VkShaderStageFlagBits.Vertex);
            shaderStages[1] = loadShader(getAssetPath() + "shaders/texture/texture.frag.spv", VkShaderStageFlagBits.Fragment);

            var pipelineCreateInfo = VkGraphicsPipelineCreateInfo.Alloc();

            pipelineCreateInfo[0].layout            = pipelineLayout;
            pipelineCreateInfo[0].renderPass        = renderPass;
            pipelineCreateInfo[0].basePipelineIndex = -1;

            var vertexInputState = vDescription.inputState;

            pipelineCreateInfo[0].pVertexInputState   = vertexInputState;
            pipelineCreateInfo[0].pInputAssemblyState = inputAssemblyState;
            pipelineCreateInfo[0].pRasterizationState = rasterizationState;
            pipelineCreateInfo[0].pColorBlendState    = colorBlendState;
            pipelineCreateInfo[0].pMultisampleState   = multisampleState;
            pipelineCreateInfo[0].pViewportState      = viewportState;
            pipelineCreateInfo[0].pDepthStencilState  = depthStencilState;
            pipelineCreateInfo[0].pDynamicState       = dynamicState;
            pipelineCreateInfo[0].stages.count        = 2;
            pipelineCreateInfo[0].stages.pointer      = shaderStages;
            {
                VkPipeline pipeline;
                vkCreateGraphicsPipelines(device, pipelineCache, 1, pipelineCreateInfo, null, &pipeline);
                this.pipeline = pipeline;
            }
        }
Example #3
0
        public FGraphicsPipeline(VkDevice device, VkPhysicalDevice physicalDevice, VkPipelineCache pipelineCache, VkRenderPass renderPass,
                                 string shaderPath, uint swapchainImageCount, FTexture textureArray)
        {
            this.device = device;
            this.swapchainImageCount = swapchainImageCount;
            this.renderPass          = renderPass;

            desclayout     = CreateDescriptorLayout(device, 1);
            descriptorPool = CreateDescriptorPool(device, swapchainImageCount, 7);
            descriptorSets = AllocateDescriptorSets(device, desclayout, descriptorPool,
                                                    swapchainImageCount);

            sampler = CreateSampler(device, textureArray.MipLevels);
            for (int i = 0; i < swapchainImageCount; i++)
            {
                VkDescriptorImageInfo imageInfo = new VkDescriptorImageInfo();
                imageInfo.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
                imageInfo.imageView   = textureArray.imageView;
                imageInfo.sampler     = sampler;

                VkWriteDescriptorSet[] writes = new VkWriteDescriptorSet[1];
                writes[0].dstSet          = descriptorSets[i];
                writes[0].dstBinding      = 0;
                writes[0].dstArrayElement = 0;
                writes[0].descriptorType  = VkDescriptorType.CombinedImageSampler;
                writes[0].descriptorCount = 1;
                writes[0].pImageInfo      = &imageInfo;

                fixed(VkWriteDescriptorSet *ptr = writes)
                vkUpdateDescriptorSets(device, (uint)writes.Length, ptr, 0, null);
            }

            uniformdata = CreateUniformBuffer(device, physicalDevice, 1);

            VkShaderModule vs = LoadShader(device, $"{shaderPath}.vert.spv");
            VkShaderModule fs = LoadShader(device, $"{shaderPath}.frag.spv");


            VkGraphicsPipelineCreateInfo pCreateInfo = VkGraphicsPipelineCreateInfo.New();

            pCreateInfo.flags = VkPipelineCreateFlags.DisableOptimization;

            VkPipelineShaderStageCreateInfo[] shaderStages = new VkPipelineShaderStageCreateInfo[2];
            shaderStages[0]        = VkPipelineShaderStageCreateInfo.New();
            shaderStages[0].stage  = VkShaderStageFlags.Vertex;
            shaderStages[0].module = vs;

            byte[] vsFuncName = Encoding.UTF8.GetBytes("main" + char.MinValue);

            fixed(byte *ptr = &(vsFuncName[0]))
            shaderStages[0].pName = ptr;

            shaderStages[1]        = VkPipelineShaderStageCreateInfo.New();
            shaderStages[1].stage  = VkShaderStageFlags.Fragment;
            shaderStages[1].module = fs;
            byte[] fsFuncName = Encoding.UTF8.GetBytes("main" + char.MinValue);

            fixed(byte *ptr = &(fsFuncName[0]))
            shaderStages[1].pName = ptr;

            fixed(VkPipelineShaderStageCreateInfo *ptr = shaderStages)
            pCreateInfo.pStages = ptr;

            pCreateInfo.stageCount = 2;

            VkVertexInputBindingDescription[] bindings = new VkVertexInputBindingDescription[4];
            bindings[0]           = new VkVertexInputBindingDescription();
            bindings[0].binding   = 0;
            bindings[0].stride    = (uint)sizeof(VoxelRenderer.VoxelVertex);
            bindings[0].inputRate = VkVertexInputRate.Vertex;

            bindings[1]           = new VkVertexInputBindingDescription();
            bindings[1].binding   = 1;
            bindings[1].stride    = (uint)sizeof(VoxelRenderer.VoxelVertex);
            bindings[1].inputRate = VkVertexInputRate.Vertex;

            bindings[2]           = new VkVertexInputBindingDescription();
            bindings[2].binding   = 2;
            bindings[2].stride    = (uint)sizeof(VoxelRenderer.VoxelVertex);
            bindings[2].inputRate = VkVertexInputRate.Vertex;

            bindings[3]           = new VkVertexInputBindingDescription();
            bindings[3].binding   = 3;
            bindings[3].stride    = (uint)sizeof(VoxelRenderer.VoxelVertex);
            bindings[3].inputRate = VkVertexInputRate.Vertex;

            VkVertexInputAttributeDescription[] attribs = new VkVertexInputAttributeDescription[4];
            attribs[0].binding  = 0;
            attribs[0].location = 0;
            attribs[0].format   = VkFormat.R32g32b32Sfloat;
            attribs[0].offset   = 0;

            attribs[1].binding  = 1;
            attribs[1].location = 1;
            attribs[1].format   = VkFormat.R32g32b32Sfloat;
            attribs[1].offset   = 0;

            attribs[2].binding  = 2;
            attribs[2].location = 2;
            attribs[2].format   = VkFormat.R32g32b32Sfloat;
            attribs[2].offset   = 0;

            attribs[3].binding  = 3;
            attribs[3].location = 3;
            attribs[3].format   = VkFormat.R32Uint;
            attribs[3].offset   = 0;

            VkPipelineVertexInputStateCreateInfo vertexInput = VkPipelineVertexInputStateCreateInfo.New();

            fixed(VkVertexInputBindingDescription *ptr = bindings)
            vertexInput.pVertexBindingDescriptions = ptr;

            vertexInput.vertexBindingDescriptionCount = (uint)bindings.Length;

            fixed(VkVertexInputAttributeDescription *ptr = attribs)
            vertexInput.pVertexAttributeDescriptions = ptr;

            vertexInput.vertexAttributeDescriptionCount = (uint)attribs.Length;
            pCreateInfo.pVertexInputState = &vertexInput;

            VkPipelineInputAssemblyStateCreateInfo inputAssembly = VkPipelineInputAssemblyStateCreateInfo.New();

            inputAssembly.topology          = VkPrimitiveTopology.TriangleList;
            pCreateInfo.pInputAssemblyState = &inputAssembly;

            VkPipelineViewportStateCreateInfo viewportState = VkPipelineViewportStateCreateInfo.New();

            viewportState.viewportCount = 1;
            viewportState.scissorCount  = 1;
            pCreateInfo.pViewportState  = &viewportState;

            VkPipelineRasterizationStateCreateInfo rasterizationState = VkPipelineRasterizationStateCreateInfo.New();

            rasterizationState.lineWidth    = 1;
            rasterizationState.frontFace    = VkFrontFace.Clockwise;
            rasterizationState.cullMode     = VkCullModeFlags.Back;
            rasterizationState.polygonMode  = VkPolygonMode.Fill;//TODO add line debug render
            pCreateInfo.pRasterizationState = &rasterizationState;

            VkPipelineMultisampleStateCreateInfo multisampleState = VkPipelineMultisampleStateCreateInfo.New();

            multisampleState.rasterizationSamples = VkSampleCountFlags.Count1;
            pCreateInfo.pMultisampleState         = &multisampleState;

            VkPipelineDepthStencilStateCreateInfo depthState = VkPipelineDepthStencilStateCreateInfo.New();

            depthState.depthTestEnable     = VkBool32.True;
            depthState.depthWriteEnable    = VkBool32.True;
            depthState.depthCompareOp      = VkCompareOp.Less;
            pCreateInfo.pDepthStencilState = &depthState;

            VkPipelineColorBlendAttachmentState colourAttachment = new VkPipelineColorBlendAttachmentState();

            colourAttachment.colorWriteMask = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A;

            VkPipelineColorBlendStateCreateInfo colourState = VkPipelineColorBlendStateCreateInfo.New();

            colourState.pAttachments     = &colourAttachment;
            colourState.attachmentCount  = 1;
            pCreateInfo.pColorBlendState = &colourState;

            VkDynamicState[] dynamicStates = new VkDynamicState[2];
            dynamicStates[0] = VkDynamicState.Viewport;
            dynamicStates[1] = VkDynamicState.Scissor;

            VkPipelineDynamicStateCreateInfo dynamicState = VkPipelineDynamicStateCreateInfo.New();

            dynamicState.dynamicStateCount = (uint)dynamicStates.Length;

            fixed(VkDynamicState *ptr = &(dynamicStates[0]))
            dynamicState.pDynamicStates = ptr;

            pCreateInfo.pDynamicState = &dynamicState;

            this.pipelineLayout    = CreatePipelineLayout(device, desclayout);
            pCreateInfo.layout     = this.pipelineLayout;
            pCreateInfo.renderPass = renderPass;
            pCreateInfo.subpass    = 0;


            VkPipeline pipeline = VkPipeline.Null;

            Assert(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pCreateInfo, null, &pipeline));
            this.pipeline = pipeline;
        }
        void preparePipelines()
        {
            var inputAssemblyState = VkPipelineInputAssemblyStateCreateInfo.Alloc();

            inputAssemblyState->topology = VkPrimitiveTopology.TriangleList;
            inputAssemblyState->primitiveRestartEnable = false;

            var rasterizationState = VkPipelineRasterizationStateCreateInfo.Alloc();

            rasterizationState->polygonMode = VkPolygonMode.Fill;
            rasterizationState->cullMode    = VkCullModeFlagBits.None;
            rasterizationState->frontFace   = VkFrontFace.CounterClockwise;
            rasterizationState->lineWidth   = 1.0f;

            var blendAttachmentState = VkPipelineColorBlendAttachmentState.Alloc();

            blendAttachmentState->colorWriteMask = (VkColorComponentFlagBits)0xf;
            blendAttachmentState->blendEnable    = false;

            var colorBlendState = VkPipelineColorBlendStateCreateInfo.Alloc();

            colorBlendState->attachments.count   = 1;
            colorBlendState->attachments.pointer = blendAttachmentState;

            var depthStencilState = VkPipelineDepthStencilStateCreateInfo.Alloc();

            depthStencilState->depthTestEnable  = true;
            depthStencilState->depthWriteEnable = true;
            depthStencilState->depthCompareOp   = VkCompareOp.LessOrEqual;
            depthStencilState->front            = depthStencilState->back;
            depthStencilState->back.compareOp   = VkCompareOp.Always;

            var viewportState = VkPipelineViewportStateCreateInfo.Alloc();

            viewportState[0].viewports.count = 1;
            viewportState[0].scissors.count  = 1;

            var multisampleState = VkPipelineMultisampleStateCreateInfo.Alloc();

            multisampleState->rasterizationSamples = VkSampleCountFlagBits._1;

            var dynamicStateEnables = new VkDynamicState[] { VkDynamicState.Viewport, VkDynamicState.Scissor };
            var dynamicState        = VkPipelineDynamicStateCreateInfo.Alloc();

            dynamicState[0].dynamicStates = dynamicStateEnables;

            var shaderStages = VkPipelineShaderStageCreateInfo.Alloc(2);

            var pipelineCreateInfo = VkGraphicsPipelineCreateInfo.Alloc();

            pipelineCreateInfo->layout              = pipelineLayoutRadialBlur;
            pipelineCreateInfo->renderPass          = renderPass;
            pipelineCreateInfo->basePipelineIndex   = -1;
            pipelineCreateInfo->pInputAssemblyState = inputAssemblyState;
            pipelineCreateInfo->pRasterizationState = rasterizationState;
            pipelineCreateInfo->pColorBlendState    = colorBlendState;
            pipelineCreateInfo->pMultisampleState   = multisampleState;
            pipelineCreateInfo->pViewportState      = viewportState;
            pipelineCreateInfo->pDepthStencilState  = depthStencilState;
            pipelineCreateInfo->pDynamicState       = dynamicState;
            pipelineCreateInfo->stages.count        = 2;
            pipelineCreateInfo->stages.pointer      = shaderStages;

            // Radial blur pipeline
            shaderStages[0] = loadShader(getAssetPath() + "shaders/radialblur/radialblur.vert.spv", VkShaderStageFlagBits.Vertex);
            shaderStages[1] = loadShader(getAssetPath() + "shaders/radialblur/radialblur.frag.spv", VkShaderStageFlagBits.Fragment);
            // Empty vertex input state
            var emptyInputState = VkPipelineVertexInputStateCreateInfo.Alloc();

            pipelineCreateInfo->pVertexInputState = emptyInputState;
            pipelineCreateInfo->layout            = pipelineLayoutRadialBlur;
            // Additive blending
            blendAttachmentState->colorWriteMask      = (VkColorComponentFlagBits)0xF;
            blendAttachmentState->blendEnable         = true;
            blendAttachmentState->colorBlendOp        = VkBlendOp.Add;
            blendAttachmentState->srcColorBlendFactor = VkBlendFactor.One;
            blendAttachmentState->dstColorBlendFactor = VkBlendFactor.One;
            blendAttachmentState->alphaBlendOp        = VkBlendOp.Add;
            blendAttachmentState->srcAlphaBlendFactor = VkBlendFactor.SrcAlpha;
            blendAttachmentState->dstAlphaBlendFactor = VkBlendFactor.DstAlpha;
            {
                VkPipeline pipeline;
                vkCreateGraphicsPipelines(device, pipelineCache, 1, pipelineCreateInfo, null, &pipeline);
                this.pipelineRadialBlur = pipeline;
            }

            // No blending (for debug display)
            blendAttachmentState->blendEnable = false;
            {
                VkPipeline pipeline;
                vkCreateGraphicsPipelines(device, pipelineCache, 1, pipelineCreateInfo, null, &pipeline);
                this.pipelineOffscreenDisplay = pipeline;
            }

            // Phong pass
            pipelineCreateInfo->layout            = pipelineLayoutScene;
            shaderStages[0]                       = loadShader(getAssetPath() + "shaders/radialblur/phongpass.vert.spv", VkShaderStageFlagBits.Vertex);
            shaderStages[1]                       = loadShader(getAssetPath() + "shaders/radialblur/phongpass.frag.spv", VkShaderStageFlagBits.Fragment);
            pipelineCreateInfo->pVertexInputState = inputInfo;
            blendAttachmentState->blendEnable     = false;
            depthStencilState->depthWriteEnable   = true;
            {
                VkPipeline pipeline;
                vkCreateGraphicsPipelines(device, pipelineCache, 1, pipelineCreateInfo, null, &pipeline);
                this.pipelinePhongPass = pipeline;
            }

            // Color only pass (offscreen blur base)
            shaderStages[0] = loadShader(getAssetPath() + "shaders/radialblur/colorpass.vert.spv", VkShaderStageFlagBits.Vertex);
            shaderStages[1] = loadShader(getAssetPath() + "shaders/radialblur/colorpass.frag.spv", VkShaderStageFlagBits.Fragment);
            pipelineCreateInfo->renderPass = offscreenPass.renderPass;
            {
                VkPipeline pipeline;
                vkCreateGraphicsPipelines(device, pipelineCache, 1, pipelineCreateInfo, null, &pipeline);
                this.pipelineColorPass = pipeline;
            }
        }
        void preparePipelines()
        {
            var inputAssemblyState = new VkPipelineInputAssemblyStateCreateInfo();

            inputAssemblyState.sType    = PipelineInputAssemblyStateCreateInfo;
            inputAssemblyState.topology = VkPrimitiveTopology.TriangleList;
            inputAssemblyState.primitiveRestartEnable = false;

            var rasterizationState = new VkPipelineRasterizationStateCreateInfo();

            rasterizationState.sType       = PipelineRasterizationStateCreateInfo;
            rasterizationState.polygonMode = VkPolygonMode.Fill;
            rasterizationState.cullMode    = VkCullModeFlagBits.None;
            rasterizationState.frontFace   = VkFrontFace.CounterClockwise;

            var blendAttachmentState = new VkPipelineColorBlendAttachmentState(
                (VkColorComponentFlagBits)0xf, false);

            var colorBlendState = new VkPipelineColorBlendStateCreateInfo();

            colorBlendState.sType       = PipelineColorBlendStateCreateInfo;
            colorBlendState.attachments = blendAttachmentState;

            var depthStencilState = new VkPipelineDepthStencilStateCreateInfo();

            depthStencilState.sType            = PipelineDepthStencilStateCreateInfo;
            depthStencilState.depthTestEnable  = true;
            depthStencilState.depthWriteEnable = true;
            depthStencilState.depthCompareOp   = VkCompareOp.LessOrEqual;

            var viewportState = new VkPipelineViewportStateCreateInfo();

            viewportState.sType           = PipelineViewportStateCreateInfo;
            viewportState.viewports.count = 1;
            viewportState.scissors.count  = 1;

            var multisampleState = new VkPipelineMultisampleStateCreateInfo();

            multisampleState.sType = PipelineMultisampleStateCreateInfo;
            multisampleState.rasterizationSamples = VkSampleCountFlagBits._1;

            var dynamicStateEnables = new VkDynamicState[] {
                VkDynamicState.Viewport,
                VkDynamicState.Scissor,
            };

            var dynamicState = new VkPipelineDynamicStateCreateInfo();

            dynamicState.sType         = PipelineDynamicStateCreateInfo;
            dynamicState.dynamicStates = dynamicStateEnables;

            // Load shaders
            var shaderStages = new VkPipelineShaderStageCreateInfo[] {
                loadShader(getAssetPath() + "shaders/dynamicuniformbuffer/base.vert.spv", VkShaderStageFlagBits.Vertex),
                loadShader(getAssetPath() + "shaders/dynamicuniformbuffer/base.frag.spv", VkShaderStageFlagBits.Fragment)
            };

            var info = new VkGraphicsPipelineCreateInfo();

            info.sType               = GraphicsPipelineCreateInfo;
            info.layout              = pipelineLayout;
            info.renderPass          = renderPass;
            info.pVertexInputState   = vertices_inputState;
            info.pInputAssemblyState = &inputAssemblyState;
            info.pRasterizationState = &rasterizationState;
            info.pColorBlendState    = &colorBlendState;
            info.pMultisampleState   = &multisampleState;
            info.pViewportState      = &viewportState;
            info.pDepthStencilState  = &depthStencilState;
            info.pDynamicState       = &dynamicState;
            info.stages              = shaderStages;

            VkPipeline pipeline;

            vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, null, &pipeline);
            this.pipeline = pipeline;
        }