Example #1
0
        private void CreateGraphicsPipeline()
        {
            byte[] vertShaderCode = File.ReadAllBytes("Shaders/vert.spv");
            byte[] fragShaderCode = File.ReadAllBytes("Shaders/frag.spv");

            VkShaderModule vertShaderModule = this.CreateShaderModule(vertShaderCode);
            VkShaderModule fragShaderModule = this.CreateShaderModule(fragShaderCode);

            VkPipelineShaderStageCreateInfo vertShaderStageInfo = new VkPipelineShaderStageCreateInfo()
            {
                sType  = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                stage  = VkShaderStageFlags.VK_SHADER_STAGE_VERTEX_BIT,
                module = vertShaderModule,
                pName  = "main".ToPointer(),
            };

            VkPipelineShaderStageCreateInfo fragShaderStageInfo = new VkPipelineShaderStageCreateInfo()
            {
                sType  = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                stage  = VkShaderStageFlags.VK_SHADER_STAGE_FRAGMENT_BIT,
                module = fragShaderModule,
                pName  = "main".ToPointer(),
            };

            VkPipelineShaderStageCreateInfo *shaderStages = stackalloc VkPipelineShaderStageCreateInfo[] { vertShaderStageInfo, fragShaderStageInfo };

            // Vertex Input
            VkPipelineVertexInputStateCreateInfo vertexInputInfo = new VkPipelineVertexInputStateCreateInfo()
            {
                sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
                vertexBindingDescriptionCount   = 0,
                pVertexBindingDescriptions      = null, // Optional
                vertexAttributeDescriptionCount = 0,
                pVertexAttributeDescriptions    = null, // Optional
            };

            // Input assembly
            VkPipelineInputAssemblyStateCreateInfo inputAssembly = new VkPipelineInputAssemblyStateCreateInfo()
            {
                sType    = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
                topology = VkPrimitiveTopology.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
                primitiveRestartEnable = false,
            };

            // Viewports and scissors
            VkViewport viewport = new VkViewport()
            {
                x        = 0.0f,
                y        = 0.0f,
                width    = (float)swapChainExtent.width,
                height   = (float)swapChainExtent.height,
                minDepth = 0.0f,
                maxDepth = 1.0f,
            };

            VkRect2D scissor = new VkRect2D()
            {
                offset = new VkOffset2D(0, 0),
                extent = swapChainExtent,
            };

            VkPipelineViewportStateCreateInfo viewportState = new VkPipelineViewportStateCreateInfo()
            {
                sType         = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
                viewportCount = 1,
                pViewports    = &viewport,
                scissorCount  = 1,
                pScissors     = &scissor,
            };

            // Rasterizer
            VkPipelineRasterizationStateCreateInfo rasterizer = new VkPipelineRasterizationStateCreateInfo()
            {
                sType                   = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
                depthClampEnable        = false,
                rasterizerDiscardEnable = false,
                polygonMode             = VkPolygonMode.VK_POLYGON_MODE_FILL,
                lineWidth               = 1.0f,
                cullMode                = VkCullModeFlags.VK_CULL_MODE_BACK_BIT,
                frontFace               = VkFrontFace.VK_FRONT_FACE_CLOCKWISE,
                depthBiasEnable         = false,
                depthBiasConstantFactor = 0.0f, // Optional
                depthBiasClamp          = 0.0f, // Optional
                depthBiasSlopeFactor    = 0.0f, // Optional
            };

            VkPipelineMultisampleStateCreateInfo multisampling = new VkPipelineMultisampleStateCreateInfo()
            {
                sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
                sampleShadingEnable   = false,
                rasterizationSamples  = VkSampleCountFlags.VK_SAMPLE_COUNT_1_BIT,
                minSampleShading      = 1.0f,  // Optional
                pSampleMask           = null,  // Optional
                alphaToCoverageEnable = false, // Optional
                alphaToOneEnable      = false, // Optional
            };

            // Depth and Stencil testing
            //VkPipelineDepthStencilStateCreateInfo

            // Color blending
            VkPipelineColorBlendAttachmentState colorBlendAttachment = new VkPipelineColorBlendAttachmentState()
            {
                colorWriteMask = VkColorComponentFlags.VK_COLOR_COMPONENT_R_BIT |
                                 VkColorComponentFlags.VK_COLOR_COMPONENT_G_BIT |
                                 VkColorComponentFlags.VK_COLOR_COMPONENT_B_BIT |
                                 VkColorComponentFlags.VK_COLOR_COMPONENT_A_BIT,
                blendEnable         = false,
                srcColorBlendFactor = VkBlendFactor.VK_BLEND_FACTOR_ONE,  // Optional
                dstColorBlendFactor = VkBlendFactor.VK_BLEND_FACTOR_ZERO, // Optional
                colorBlendOp        = VkBlendOp.VK_BLEND_OP_ADD,          // Optional
                srcAlphaBlendFactor = VkBlendFactor.VK_BLEND_FACTOR_ONE,  // Optional
                dstAlphaBlendFactor = VkBlendFactor.VK_BLEND_FACTOR_ZERO, // Optional
                alphaBlendOp        = VkBlendOp.VK_BLEND_OP_ADD,          // Optional
            };

            VkPipelineColorBlendStateCreateInfo colorBlending = new VkPipelineColorBlendStateCreateInfo()
            {
                sType            = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
                logicOpEnable    = false,
                logicOp          = VkLogicOp.VK_LOGIC_OP_COPY, // Optional
                attachmentCount  = 1,
                pAttachments     = &colorBlendAttachment,
                blendConstants_0 = 0.0f, // Optional
                blendConstants_1 = 0.0f, // Optional
                blendConstants_2 = 0.0f, // Optional
                blendConstants_3 = 0.0f, // Optional
            };

            VkPipelineLayoutCreateInfo pipelineLayoutInfo = new VkPipelineLayoutCreateInfo()
            {
                sType                  = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
                setLayoutCount         = 0,    // Optional
                pSetLayouts            = null, // Optional
                pushConstantRangeCount = 0,    // Optional
                pPushConstantRanges    = null, // Optional
            };

            fixed(VkPipelineLayout *pipelineLayoutPtr = &pipelineLayout)
            {
                Helpers.CheckErrors(VulkanNative.vkCreatePipelineLayout(device, &pipelineLayoutInfo, null, pipelineLayoutPtr));
            }

            VkGraphicsPipelineCreateInfo pipelineInfo = new VkGraphicsPipelineCreateInfo()
            {
                sType               = VkStructureType.VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
                stageCount          = 2,
                pStages             = shaderStages,
                pVertexInputState   = &vertexInputInfo,
                pInputAssemblyState = &inputAssembly,
                pViewportState      = &viewportState,
                pRasterizationState = &rasterizer,
                pMultisampleState   = &multisampling,
                pDepthStencilState  = null, // Optional
                pColorBlendState    = &colorBlending,
                pDynamicState       = null, // Optional
                layout              = this.pipelineLayout,
                renderPass          = this.renderPass,
                subpass             = 0,
                basePipelineHandle  = 0,  // Optional
                basePipelineIndex   = -1, // Optional
            };

            fixed(VkPipeline *graphicsPipelinePtr = &this.graphicsPipeline)
            {
                Helpers.CheckErrors(VulkanNative.vkCreateGraphicsPipelines(this.device, 0, 1, &pipelineInfo, null, graphicsPipelinePtr));
            }

            VulkanNative.vkDestroyShaderModule(device, fragShaderModule, null);
            VulkanNative.vkDestroyShaderModule(device, vertShaderModule, null);
        }
Example #2
0
        private void CreateGraphicsPipeline()
        {
            // Shader stages
            var vertShaderCode = System.IO.File.ReadAllBytes("Shaders/vert.spv");
            var fragShaderCode = System.IO.File.ReadAllBytes("Shaders/frag.spv");

            var vertShaderModule = CreateShaderModule(vertShaderCode);
            var fragShaderModule = CreateShaderModule(fragShaderCode);

            string name      = "main";
            int    byteCount = System.Text.Encoding.UTF8.GetByteCount(name);
            byte * utf8Ptr   = stackalloc byte[byteCount];

            fixed(char *namePtr = name)
            {
                System.Text.Encoding.UTF8.GetBytes(namePtr, name.Length, utf8Ptr, byteCount);
            }

            var vertShaderStageInfo = new VkPipelineShaderStageCreateInfo()
            {
                sType  = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                stage  = VkShaderStageFlagBits.VK_SHADER_STAGE_VERTEX_BIT,
                module = vertShaderModule,
                pName  = utf8Ptr,
            };

            var fragShaderStageInfo = new VkPipelineShaderStageCreateInfo()
            {
                sType  = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                stage  = VkShaderStageFlagBits.VK_SHADER_STAGE_FRAGMENT_BIT,
                module = fragShaderModule,
                pName  = utf8Ptr,
            };

            var shaderStages = stackalloc VkPipelineShaderStageCreateInfo[] { vertShaderStageInfo, fragShaderStageInfo };

            // VertexInput
            var vertexInputInfo = new VkPipelineVertexInputStateCreateInfo()
            {
                sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
                vertexBindingDescriptionCount   = 0,
                pVertexBindingDescriptions      = null,
                vertexAttributeDescriptionCount = 0,
                pVertexAttributeDescriptions    = null,
            };

            var inputAssembly = new VkPipelineInputAssemblyStateCreateInfo()
            {
                sType    = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
                topology = VkPrimitiveTopology.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
                primitiveRestartEnable = false,
            };

            var viewport = new VkViewport()
            {
                x        = 0f,
                y        = 0f,
                width    = (float)vkSwapChainExtent.width,
                height   = (float)vkSwapChainExtent.height,
                minDepth = 0f,
                maxDepth = 1f,
            };

            var scissor = new VkRect2D()
            {
                offset = new VkOffset2D()
                {
                    x = 0, y = 0
                },
                extent = vkSwapChainExtent,
            };

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

            var rasterizer = new VkPipelineRasterizationStateCreateInfo()
            {
                sType                   = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
                depthClampEnable        = false,
                rasterizerDiscardEnable = false,
                polygonMode             = VkPolygonMode.VK_POLYGON_MODE_FILL,
                lineWidth               = 1f,
                cullMode                = VkCullModeFlagBits.VK_CULL_MODE_BACK_BIT,
                frontFace               = VkFrontFace.VK_FRONT_FACE_CLOCKWISE,
                depthBiasEnable         = false,
                depthBiasConstantFactor = 0f,
                depthBiasClamp          = 0f,
                depthBiasSlopeFactor    = 0f,
            };

            var multisampling = new VkPipelineMultisampleStateCreateInfo()
            {
                sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
                sampleShadingEnable   = false,
                rasterizationSamples  = VkSampleCountFlagBits.VK_SAMPLE_COUNT_1_BIT,
                minSampleShading      = 1f,
                pSampleMask           = null,
                alphaToCoverageEnable = false,
                alphaToOneEnable      = false,
            };

            var colorBlendAttachment = new VkPipelineColorBlendAttachmentState()
            {
                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,
                blendEnable    = false,
            };


            var colorBlending = new VkPipelineColorBlendStateCreateInfo()
            {
                sType            = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
                logicOpEnable    = false,
                logicOp          = VkLogicOp.VK_LOGIC_OP_COPY,
                pAttachments     = &colorBlendAttachment,
                attachmentCount  = 1,
                blendConstants_0 = 0f,
                blendConstants_1 = 0f,
                blendConstants_2 = 0f,
                blendConstants_3 = 0f,
            };

            var pipelineLayoutInfo = new VkPipelineLayoutCreateInfo()
            {
                sType                  = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
                setLayoutCount         = 0,
                pushConstantRangeCount = 0,
            };

            VkPipelineLayout newPipelineLayout;
            var result = VulkanNative.vkCreatePipelineLayout(vkDevice, &pipelineLayoutInfo, null, &newPipelineLayout);

            vkPipelineLayout = newPipelineLayout;
            Helpers.CheckErrors(result);

            var pipelineInfo = new VkGraphicsPipelineCreateInfo()
            {
                sType               = VkStructureType.VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
                stageCount          = 2,
                pStages             = shaderStages,
                pVertexInputState   = &vertexInputInfo,
                pInputAssemblyState = &inputAssembly,
                pViewportState      = &viewportState,
                pRasterizationState = &rasterizer,
                pMultisampleState   = &multisampling,
                pDepthStencilState  = null,
                pColorBlendState    = &colorBlending,
                pDynamicState       = null,
                layout              = vkPipelineLayout,
                renderPass          = vkRenderPass,
                subpass             = 0,
                basePipelineHandle  = 0,
                basePipelineIndex   = -1,
            };

            VkPipeline newPipeline;

            result             = VulkanNative.vkCreateGraphicsPipelines(vkDevice, 0, 1, &pipelineInfo, null, &newPipeline);
            vkGraphicsPipeline = newPipeline;
            Helpers.CheckErrors(result);

            VulkanNative.vkDestroyShaderModule(vkDevice, vertShaderModule, null);
            VulkanNative.vkDestroyShaderModule(vkDevice, fragShaderModule, null);
        }
Example #3
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;
        }