Example #1
0
        public static VkPipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(
            uint viewportCount,
            uint scissorCount,
            uint flags = 0)
        {
            VkPipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = VkPipelineViewportStateCreateInfo.New();

            pipelineViewportStateCreateInfo.viewportCount = viewportCount;
            pipelineViewportStateCreateInfo.scissorCount  = scissorCount;
            pipelineViewportStateCreateInfo.flags         = flags;
            return(pipelineViewportStateCreateInfo);
        }
        internal VkPipelineViewportStateCreateInfo GetNative(DisposableList <IDisposable> marshalled)
        {
            var result = new VkPipelineViewportStateCreateInfo();

            result.sType = VkStructureType.PipelineViewportStateCreateInfo;

            var viewportMarshalled = new MarshalledArray <VkViewport>(viewports);

            result.viewportCount = (uint)viewportMarshalled.Count;
            result.pViewports    = viewportMarshalled.Address;

            var scissorMarshalled = new MarshalledArray <VkRect2D>(scissors);

            result.scissorCount = (uint)scissorMarshalled.Count;
            result.pScissors    = scissorMarshalled.Address;

            marshalled.Add(viewportMarshalled);
            marshalled.Add(scissorMarshalled);

            return(result);
        }
Example #3
0
        private VkPipelineViewportStateCreateInfo CreateViewportState()
        {
            VkExtent2D currentExtent = vkctrl.GetCurrentExtent();
            var        viewport      = new VkViewport()
            {
                width    = currentExtent.width,
                height   = currentExtent.height,
                x        = 0,
                y        = 0,
                minDepth = 0.0f,
                maxDepth = 1.0f,
            };
            var scissor = new VkRect2D()
            {
                extent = currentExtent
            };
            var viewportState = new VkPipelineViewportStateCreateInfo();

            viewportState.viewports = new[] { viewport };
            viewportState.scissors  = new[] { scissor };
            return(viewportState);
        }
Example #4
0
        void preparePipelines()
        {
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
                Initializers.pipelineInputAssemblyStateCreateInfo(
                    VkPrimitiveTopology.TriangleList,
                    0,
                    False);

            VkPipelineRasterizationStateCreateInfo rasterizationState =
                Initializers.pipelineRasterizationStateCreateInfo(
                    VkPolygonMode.Fill,
                    VkCullModeFlags.Back,
                    VkFrontFace.Clockwise,
                    0);

            VkPipelineColorBlendAttachmentState blendAttachmentState =
                Initializers.pipelineColorBlendAttachmentState(
                    (VkColorComponentFlags)0xf,
                    False);

            VkPipelineColorBlendStateCreateInfo colorBlendState =
                Initializers.pipelineColorBlendStateCreateInfo(
                    1,
                    &blendAttachmentState);

            VkPipelineDepthStencilStateCreateInfo depthStencilState =
                Initializers.pipelineDepthStencilStateCreateInfo(
                    True,
                    True,
                    VkCompareOp.LessOrEqual);

            VkPipelineViewportStateCreateInfo viewportState =
                Initializers.pipelineViewportStateCreateInfo(1, 1, 0);

            VkPipelineMultisampleStateCreateInfo multisampleState =
                Initializers.pipelineMultisampleStateCreateInfo(VkSampleCountFlags._1);

            FixedArray3 <VkDynamicState> dynamicStateEnables = new FixedArray3 <VkDynamicState>(
                VkDynamicState.Viewport,
                VkDynamicState.Scissor,
                VkDynamicState.LineWidth);
            VkPipelineDynamicStateCreateInfo dynamicState =
                Initializers.pipelineDynamicStateCreateInfo((VkDynamicState *)Unsafe.AsPointer(ref dynamicStateEnables), dynamicStateEnables.Count);

            VkGraphicsPipelineCreateInfo pipelineCreateInfo =
                Initializers.pipelineCreateInfo(pipelineLayout, RenderPass);

            FixedArray2 <VkPipelineShaderStageCreateInfo> shaderStages = new FixedArray2 <VkPipelineShaderStageCreateInfo>();

            shaderStages.First  = loadShader(getAssetPath() + "shaders/pipelines/phong.vert.spv", VkShaderStageFlags.Vertex);
            shaderStages.Second = loadShader(getAssetPath() + "shaders/pipelines/phong.frag.spv", VkShaderStageFlags.Fragment);

            pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
            pipelineCreateInfo.pRasterizationState = &rasterizationState;
            pipelineCreateInfo.pColorBlendState    = &colorBlendState;
            pipelineCreateInfo.pMultisampleState   = &multisampleState;
            pipelineCreateInfo.pViewportState      = &viewportState;
            pipelineCreateInfo.pDepthStencilState  = &depthStencilState;
            pipelineCreateInfo.pDynamicState       = &dynamicState;
            pipelineCreateInfo.stageCount          = shaderStages.Count;
            pipelineCreateInfo.pStages             = (VkPipelineShaderStageCreateInfo *)Unsafe.AsPointer(ref shaderStages);

            // Shared vertex bindings and attributes used by all pipelines

            // Binding description
            VkVertexInputBindingDescription vertexInputBindings
                = Initializers.vertexInputBindingDescription(VERTEX_BUFFER_BIND_ID, vertexLayout.GetStride(), VkVertexInputRate.Vertex);

            // Attribute descriptions
            FixedArray4 <VkVertexInputAttributeDescription> vertexInputAttributes = new FixedArray4 <VkVertexInputAttributeDescription>
            {
                First  = Initializers.vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 0, VkFormat.R32g32b32Sfloat, 0),                  // Location 0: Position
                Second = Initializers.vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 1, VkFormat.R32g32b32Sfloat, sizeof(float) * 3),  // Location 1: Color
                Third  = Initializers.vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 2, VkFormat.R32g32Sfloat, sizeof(float) * 6),     // Location 2 : Texture coordinates
                Fourth = Initializers.vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID, 3, VkFormat.R32g32b32Sfloat, sizeof(float) * 8),  // Location 3 : Normal
            };

            VkPipelineVertexInputStateCreateInfo vertexInputState = VkPipelineVertexInputStateCreateInfo.New();

            vertexInputState.vertexBindingDescriptionCount   = 1;
            vertexInputState.pVertexBindingDescriptions      = &vertexInputBindings;
            vertexInputState.vertexAttributeDescriptionCount = vertexInputAttributes.Count;
            vertexInputState.pVertexAttributeDescriptions    = (VkVertexInputAttributeDescription *)Unsafe.AsPointer(ref vertexInputAttributes);

            pipelineCreateInfo.pVertexInputState = &vertexInputState;

            // Create the graphics pipeline state objects

            // We are using this pipeline as the base for the other pipelines (derivatives)
            // Pipeline derivatives can be used for pipelines that share most of their state
            // Depending on the implementation this may result in better performance for pipeline
            // switchting and faster creation time
            pipelineCreateInfo.flags = VkPipelineCreateFlags.AllowDerivatives;

            // Textured pipeline
            // Phong shading pipeline
            shaderStages.First  = loadShader(getAssetPath() + "shaders/pipelines/phong.vert.spv", VkShaderStageFlags.Vertex);
            shaderStages.Second = loadShader(getAssetPath() + "shaders/pipelines/phong.frag.spv", VkShaderStageFlags.Fragment);
            Util.CheckResult(vkCreateGraphicsPipelines(Device, PipelineCache, 1, ref pipelineCreateInfo, null, out pipelines_phong));

            // All pipelines created after the base pipeline will be derivatives
            pipelineCreateInfo.flags = VkPipelineCreateFlags.Derivative;
            // Base pipeline will be our first created pipeline
            pipelineCreateInfo.basePipelineHandle = pipelines_phong;
            // It's only allowed to either use a handle or index for the base pipeline
            // As we use the handle, we must set the index to -1 (see section 9.5 of the specification)
            pipelineCreateInfo.basePipelineIndex = -1;

            // Toon shading pipeline
            shaderStages.First  = loadShader(getAssetPath() + "shaders/pipelines/toon.vert.spv", VkShaderStageFlags.Vertex);
            shaderStages.Second = loadShader(getAssetPath() + "shaders/pipelines/toon.frag.spv", VkShaderStageFlags.Fragment);
            Util.CheckResult(vkCreateGraphicsPipelines(Device, PipelineCache, 1, ref pipelineCreateInfo, null, out pipelines_toon));

            // Pipeline for wire frame rendering
            // Non solid rendering is not a mandatory Vulkan feature
            if (DeviceFeatures.fillModeNonSolid != 0)
            {
                rasterizationState.polygonMode = VkPolygonMode.Line;
                shaderStages.First             = loadShader(getAssetPath() + "shaders/pipelines/wireframe.vert.spv", VkShaderStageFlags.Vertex);
                shaderStages.Second            = loadShader(getAssetPath() + "shaders/pipelines/wireframe.frag.spv", VkShaderStageFlags.Fragment);
                Util.CheckResult(vkCreateGraphicsPipelines(Device, PipelineCache, 1, ref pipelineCreateInfo, null, out pipelines_wireframe));
            }
        }
Example #5
0
        void preparePipelines()
        {
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
                Initializers.pipelineInputAssemblyStateCreateInfo(
                    VkPrimitiveTopology.TriangleList,
                    0,
                    False);

            VkPipelineRasterizationStateCreateInfo rasterizationState =
                Initializers.pipelineRasterizationStateCreateInfo(
                    VkPolygonMode.Fill,
                    VkCullModeFlags.None,
                    VkFrontFace.CounterClockwise,
                    0);

            VkPipelineColorBlendAttachmentState blendAttachmentState =
                Initializers.pipelineColorBlendAttachmentState(
                    (VkColorComponentFlags)0xf,
                    False);

            VkPipelineColorBlendStateCreateInfo colorBlendState =
                Initializers.pipelineColorBlendStateCreateInfo(
                    1,
                    &blendAttachmentState);

            VkPipelineDepthStencilStateCreateInfo depthStencilState =
                Initializers.pipelineDepthStencilStateCreateInfo(
                    True,
                    True,
                    VkCompareOp.LessOrEqual);

            VkPipelineViewportStateCreateInfo viewportState =
                Initializers.pipelineViewportStateCreateInfo(1, 1, 0);

            VkPipelineMultisampleStateCreateInfo multisampleState =
                Initializers.pipelineMultisampleStateCreateInfo(
                    VkSampleCountFlags.Count1,
                    0);

            FixedArray2 <VkDynamicState> dynamicStateEnables = new FixedArray2 <VkDynamicState>(
                VkDynamicState.Viewport,
                VkDynamicState.Scissor);
            VkPipelineDynamicStateCreateInfo dynamicState =
                Initializers.pipelineDynamicStateCreateInfo(
                    (VkDynamicState *)Unsafe.AsPointer(ref dynamicStateEnables),
                    dynamicStateEnables.Count,
                    0);

            // Load shaders
            FixedArray2 <VkPipelineShaderStageCreateInfo> shaderStages = new FixedArray2 <VkPipelineShaderStageCreateInfo>();

            shaderStages.First  = loadShader(getAssetPath() + "shaders/texture/texture.vert.spv", VkShaderStageFlags.Vertex);
            shaderStages.Second = loadShader(getAssetPath() + "shaders/texture/texture.frag.spv", VkShaderStageFlags.Fragment);

            VkGraphicsPipelineCreateInfo pipelineCreateInfo =
                Initializers.pipelineCreateInfo(
                    pipelineLayout,
                    renderPass,
                    0);

            var vertexInputState = vertices.inputState;

            pipelineCreateInfo.pVertexInputState   = &vertexInputState;
            pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
            pipelineCreateInfo.pRasterizationState = &rasterizationState;
            pipelineCreateInfo.pColorBlendState    = &colorBlendState;
            pipelineCreateInfo.pMultisampleState   = &multisampleState;
            pipelineCreateInfo.pViewportState      = &viewportState;
            pipelineCreateInfo.pDepthStencilState  = &depthStencilState;
            pipelineCreateInfo.pDynamicState       = &dynamicState;
            pipelineCreateInfo.stageCount          = shaderStages.Count;
            pipelineCreateInfo.pStages             = (VkPipelineShaderStageCreateInfo *)Unsafe.AsPointer(ref shaderStages);

            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_solid));
        }
Example #6
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);
        }
        private VkPipeline CreateNewGraphicsPipeline(ref VkPipelineCacheKey cacheKey)
        {
            VkGraphicsPipelineCreateInfo pipelineCI = VkGraphicsPipelineCreateInfo.New();

            // RenderPass
            pipelineCI.renderPass = cacheKey.RenderPass;
            pipelineCI.subpass    = 0;

            pipelineCI.layout = cacheKey.PipelineLayout;

            // DynamicState
            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;

            // ColorBlendState
            VkPipelineColorBlendAttachmentState colorBlendAttachementState = new VkPipelineColorBlendAttachmentState();

            colorBlendAttachementState.colorWriteMask      = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A;
            colorBlendAttachementState.blendEnable         = cacheKey.BlendState.IsBlendEnabled;
            colorBlendAttachementState.srcColorBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.SourceColorBlend);
            colorBlendAttachementState.dstColorBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.DestinationColorBlend);
            colorBlendAttachementState.colorBlendOp        = VkFormats.VeldridToVkBlendOp(cacheKey.BlendState.ColorBlendFunction);
            colorBlendAttachementState.srcAlphaBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.SourceAlphaBlend);
            colorBlendAttachementState.dstAlphaBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.DestinationAlphaBlend);
            colorBlendAttachementState.alphaBlendOp        = VkFormats.VeldridToVkBlendOp(cacheKey.BlendState.AlphaBlendFunction);

            VkPipelineColorBlendStateCreateInfo colorBlendStateCI = VkPipelineColorBlendStateCreateInfo.New();

            if (cacheKey.Framebuffer.ColorTexture != null)
            {
                colorBlendStateCI.attachmentCount  = 1;
                colorBlendStateCI.pAttachments     = &colorBlendAttachementState;
                colorBlendStateCI.blendConstants_0 = cacheKey.BlendState.BlendFactor.R;
                colorBlendStateCI.blendConstants_1 = cacheKey.BlendState.BlendFactor.G;
                colorBlendStateCI.blendConstants_2 = cacheKey.BlendState.BlendFactor.B;
                colorBlendStateCI.blendConstants_3 = cacheKey.BlendState.BlendFactor.A;
                pipelineCI.pColorBlendState        = &colorBlendStateCI;
            }

            // DepthStencilState
            VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = VkPipelineDepthStencilStateCreateInfo.New();

            depthStencilStateCI.depthCompareOp   = VkFormats.VeldridToVkDepthComparison(cacheKey.DepthStencilState.DepthComparison);
            depthStencilStateCI.depthWriteEnable = cacheKey.DepthStencilState.IsDepthWriteEnabled;
            depthStencilStateCI.depthTestEnable  = cacheKey.DepthStencilState.IsDepthEnabled;
            pipelineCI.pDepthStencilState        = &depthStencilStateCI;

            // MultisampleState
            VkPipelineMultisampleStateCreateInfo multisampleStateCI = VkPipelineMultisampleStateCreateInfo.New();

            multisampleStateCI.rasterizationSamples = VkSampleCountFlags.Count1;
            pipelineCI.pMultisampleState            = &multisampleStateCI;

            // RasterizationState
            VkPipelineRasterizationStateCreateInfo rasterizationStateCI = ((VkRasterizerState)cacheKey.RasterizerState).RasterizerStateCreateInfo;

            rasterizationStateCI.lineWidth = 1f;
            pipelineCI.pRasterizationState = &rasterizationStateCI;

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

            viewportStateCI.viewportCount = 1;
            viewportStateCI.scissorCount  = 1;
            pipelineCI.pViewportState     = &viewportStateCI;

            // InputAssemblyState
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = VkPipelineInputAssemblyStateCreateInfo.New();

            inputAssemblyStateCI.topology  = cacheKey.PrimitiveTopology;
            pipelineCI.pInputAssemblyState = &inputAssemblyStateCI;

            // VertexInputState
            VkPipelineVertexInputStateCreateInfo vertexInputStateCI = VkPipelineVertexInputStateCreateInfo.New();

            VertexInputDescription[] inputDescriptions = cacheKey.ShaderSet.InputLayout.InputDescriptions;
            uint bindingCount   = (uint)inputDescriptions.Length;
            uint attributeCount = (uint)inputDescriptions.Sum(desc => desc.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++)
            {
                VertexInputDescription inputDesc = inputDescriptions[binding];
                bindingDescs[targetIndex] = new VkVertexInputBindingDescription()
                {
                    binding   = (uint)binding,
                    inputRate = (inputDesc.Elements[0].StorageClassifier == VertexElementInputClass.PerInstance) ? VkVertexInputRate.Instance : VkVertexInputRate.Vertex,
                    stride    = ((VkVertexBuffer)cacheKey.VertexBindings[binding]).Stride
                };

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

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

                    targetIndex   += 1;
                    currentOffset += inputElement.SizeInBytes;
                }

                targetLocation += inputDesc.Elements.Length;
            }

            vertexInputStateCI.vertexBindingDescriptionCount   = bindingCount;
            vertexInputStateCI.pVertexBindingDescriptions      = bindingDescs;
            vertexInputStateCI.vertexAttributeDescriptionCount = attributeCount;
            vertexInputStateCI.pVertexAttributeDescriptions    = attributeDescs;
            pipelineCI.pVertexInputState = &vertexInputStateCI;

            // ShaderStage
            StackList <VkPipelineShaderStageCreateInfo> shaderStageCIs = new StackList <VkPipelineShaderStageCreateInfo>();

            VkPipelineShaderStageCreateInfo vertexStage = VkPipelineShaderStageCreateInfo.New();

            vertexStage.stage  = VkShaderStageFlags.Vertex;
            vertexStage.module = cacheKey.ShaderSet.VertexShader.ShaderModule;
            vertexStage.pName  = CommonStrings.main;
            shaderStageCIs.Add(vertexStage);

            VkPipelineShaderStageCreateInfo fragmentStage = VkPipelineShaderStageCreateInfo.New();

            fragmentStage.stage  = VkShaderStageFlags.Fragment;
            fragmentStage.module = cacheKey.ShaderSet.FragmentShader.ShaderModule;
            fragmentStage.pName  = CommonStrings.main;
            shaderStageCIs.Add(fragmentStage);

            if (cacheKey.ShaderSet.TessellationControlShader != null)
            {
                VkPipelineShaderStageCreateInfo tcStage = VkPipelineShaderStageCreateInfo.New();
                tcStage.stage  = VkShaderStageFlags.TessellationControl;
                tcStage.module = cacheKey.ShaderSet.TessellationControlShader.ShaderModule;
                tcStage.pName  = CommonStrings.main;
                shaderStageCIs.Add(tcStage);
            }

            if (cacheKey.ShaderSet.TessellationEvaluationShader != null)
            {
                VkPipelineShaderStageCreateInfo teStage = VkPipelineShaderStageCreateInfo.New();
                teStage.stage  = VkShaderStageFlags.TessellationEvaluation;
                teStage.module = cacheKey.ShaderSet.TessellationEvaluationShader.ShaderModule;
                teStage.pName  = CommonStrings.main;
                shaderStageCIs.Add(teStage);
            }

            if (cacheKey.ShaderSet.GeometryShader != null)
            {
                VkPipelineShaderStageCreateInfo geometryStage = VkPipelineShaderStageCreateInfo.New();
                geometryStage.stage  = VkShaderStageFlags.Geometry;
                geometryStage.module = cacheKey.ShaderSet.GeometryShader.ShaderModule;
                geometryStage.pName  = CommonStrings.main;
                shaderStageCIs.Add(geometryStage);
            }

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

            VkResult result = vkCreateGraphicsPipelines(_device, VkPipelineCache.Null, 1, ref pipelineCI, null, out VkPipeline ret);

            CheckResult(result);
            return(ret);
        }
Example #8
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 #9
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;
        }
Example #10
0
        void preparePipelines()
        {
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
                Initializers.pipelineInputAssemblyStateCreateInfo(
                    VkPrimitiveTopology.TriangleList,
                    0,
                    False);

            VkPipelineRasterizationStateCreateInfo rasterizationState =
                Initializers.pipelineRasterizationStateCreateInfo(
                    VkPolygonMode.Fill,
                    VkCullModeFlags.Back,
                    VkFrontFace.CounterClockwise,
                    0);

            VkPipelineColorBlendAttachmentState blendAttachmentState =
                Initializers.pipelineColorBlendAttachmentState(
                    (VkColorComponentFlags)0xf,
                    False);

            VkPipelineColorBlendStateCreateInfo colorBlendState =
                Initializers.pipelineColorBlendStateCreateInfo(
                    1,
                    &blendAttachmentState);

            VkPipelineDepthStencilStateCreateInfo depthStencilState =
                Initializers.pipelineDepthStencilStateCreateInfo(
                    False,
                    False,
                    VkCompareOp.LessOrEqual);

            VkPipelineViewportStateCreateInfo viewportState =
                Initializers.pipelineViewportStateCreateInfo(1, 1, 0);

            VkPipelineMultisampleStateCreateInfo multisampleState =
                Initializers.pipelineMultisampleStateCreateInfo(
                    VkSampleCountFlags.Count1,
                    0);

            FixedArray2<VkDynamicState> dynamicStateEnables = new FixedArray2<VkDynamicState>(
                 VkDynamicState.Viewport,
                 VkDynamicState.Scissor);
            VkPipelineDynamicStateCreateInfo dynamicState =
                Initializers.pipelineDynamicStateCreateInfo(
                    &dynamicStateEnables.First,
                    dynamicStateEnables.Count,
                    0);

            // Skybox pipeline (background cube)
            FixedArray2<VkPipelineShaderStageCreateInfo> shaderStages = new FixedArray2<VkPipelineShaderStageCreateInfo>(
                loadShader(getAssetPath() + "shaders/cubemap/skybox.vert.spv", VkShaderStageFlags.Vertex),
                loadShader(getAssetPath() + "shaders/cubemap/skybox.frag.spv", VkShaderStageFlags.Fragment));

            VkGraphicsPipelineCreateInfo pipelineCreateInfo =
                Initializers.pipelineCreateInfo(
                    pipelineLayout,
                    renderPass,
                    0);

            var inputState = vertices.inputState;
            pipelineCreateInfo.pVertexInputState = &inputState;
            pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
            pipelineCreateInfo.pRasterizationState = &rasterizationState;
            pipelineCreateInfo.pColorBlendState = &colorBlendState;
            pipelineCreateInfo.pMultisampleState = &multisampleState;
            pipelineCreateInfo.pViewportState = &viewportState;
            pipelineCreateInfo.pDepthStencilState = &depthStencilState;
            pipelineCreateInfo.pDynamicState = &dynamicState;
            pipelineCreateInfo.stageCount = shaderStages.Count;
            pipelineCreateInfo.pStages = &shaderStages.First;

            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_skybox));

            // Cube map reflect pipeline
            shaderStages.First = loadShader(getAssetPath() + "shaders/cubemap/reflect.vert.spv", VkShaderStageFlags.Vertex);
            shaderStages.Second = loadShader(getAssetPath() + "shaders/cubemap/reflect.frag.spv", VkShaderStageFlags.Fragment);
            // Enable depth test and write
            depthStencilState.depthWriteEnable = True;
            depthStencilState.depthTestEnable = True;
            // Flip cull mode
            rasterizationState.cullMode = VkCullModeFlags.Front;
            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_reflect));
        }
Example #11
0
        private VkPipeline CreateVulkanPipeline()
        {
            var  pipelineShaderStageCreateInfos      = stackalloc VkPipelineShaderStageCreateInfo[2];
            uint pipelineShaderStageCreateInfosCount = 0;

            try
            {
                VkPipeline vulkanPipeline;

                var device  = Device;
                var surface = device.Surface;

                var vertexInputBindingDescription = new VkVertexInputBindingDescription {
                    inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
                };

                var vertexInputAttributeDescriptions = Array.Empty <VkVertexInputAttributeDescription>();

                var pipelineVertexInputStateCreateInfo = new VkPipelineVertexInputStateCreateInfo {
                    sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
                    vertexBindingDescriptionCount = 1,
                    pVertexBindingDescriptions    = &vertexInputBindingDescription,
                };

                var pipelineInputAssemblyStateCreateInfo = new VkPipelineInputAssemblyStateCreateInfo {
                    sType    = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
                    topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
                };

                var pipelineViewportStateCreateInfo = new VkPipelineViewportStateCreateInfo {
                    sType         = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
                    viewportCount = 1,
                    scissorCount  = 1,
                };

                var pipelineRasterizationStateCreateInfo = new VkPipelineRasterizationStateCreateInfo {
                    sType     = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
                    frontFace = VK_FRONT_FACE_CLOCKWISE,
                    cullMode  = VK_CULL_MODE_BACK_BIT,
                    lineWidth = 1.0f,
                };

                var pipelineMultisampleStateCreateInfo = new VkPipelineMultisampleStateCreateInfo {
                    sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
                    rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
                };

                var pipelineDepthStencilStateCreateInfo = new VkPipelineDepthStencilStateCreateInfo {
                    sType          = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
                    depthCompareOp = VK_COMPARE_OP_ALWAYS,
                    front          = new VkStencilOpState {
                        compareOp = VK_COMPARE_OP_ALWAYS,
                    },
                    back = new VkStencilOpState {
                        compareOp = VK_COMPARE_OP_ALWAYS,
                    },
                };

                var pipelineColorBlendAttachmentState = new VkPipelineColorBlendAttachmentState {
                    colorWriteMask = VK_COLOR_COMPONENT_A_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_R_BIT,
                };

                var pipelineColorBlendStateCreateInfo = new VkPipelineColorBlendStateCreateInfo {
                    sType           = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
                    attachmentCount = 1,
                    pAttachments    = &pipelineColorBlendAttachmentState,
                };

                var dynamicStates = stackalloc VkDynamicState[2] {
                    VK_DYNAMIC_STATE_VIEWPORT,
                    VK_DYNAMIC_STATE_SCISSOR,
                };

                var pipelineDynamicStateCreateInfo = new VkPipelineDynamicStateCreateInfo {
                    sType             = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
                    dynamicStateCount = 2,
                    pDynamicStates    = dynamicStates,
                };

                var pipelineCreateInfo = new VkGraphicsPipelineCreateInfo {
                    sType               = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
                    pViewportState      = &pipelineViewportStateCreateInfo,
                    pRasterizationState = &pipelineRasterizationStateCreateInfo,
                    pMultisampleState   = &pipelineMultisampleStateCreateInfo,
                    pDepthStencilState  = &pipelineDepthStencilStateCreateInfo,
                    pColorBlendState    = &pipelineColorBlendStateCreateInfo,
                    pDynamicState       = &pipelineDynamicStateCreateInfo,
                    layout              = Signature.VulkanPipelineLayout,
                    renderPass          = device.VulkanRenderPass,
                };

                var vertexShader = VertexShader;

                if (vertexShader != null)
                {
                    var shaderIndex = pipelineShaderStageCreateInfosCount++;

                    var entryPointName       = vertexShader.EntryPointName.GetUtf8Span();
                    var entryPointNameLength = (nuint)entryPointName.Length + 1;

                    pipelineShaderStageCreateInfos[shaderIndex] = new VkPipelineShaderStageCreateInfo {
                        sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                        stage  = VK_SHADER_STAGE_VERTEX_BIT,
                        module = vertexShader.VulkanShaderModule,
                        pName  = AllocateArray <sbyte>(entryPointNameLength),
                    };

                    var destination = new Span <sbyte>(pipelineShaderStageCreateInfos[shaderIndex].pName, (int)entryPointNameLength);
                    entryPointName.CopyTo(destination);
                    destination[entryPointName.Length] = 0x00;

                    var inputs       = Signature.Inputs;
                    var inputsLength = inputs.Length;

                    var inputElementsCount = GetInputElementsCount(inputs);
                    var inputElementsIndex = 0;

                    if (inputElementsCount != 0)
                    {
                        vertexInputAttributeDescriptions = new VkVertexInputAttributeDescription[inputElementsCount];

                        for (var inputIndex = 0; inputIndex < inputsLength; inputIndex++)
                        {
                            var input = inputs[inputIndex];

                            var inputElements       = input.Elements;
                            var inputElementsLength = inputElements.Length;

                            uint inputBindingStride = 0;

                            for (var inputElementIndex = 0; inputElementIndex < inputElementsLength; inputElementIndex++)
                            {
                                var inputElement = inputElements[inputElementIndex];

                                vertexInputAttributeDescriptions[inputElementsIndex] = new VkVertexInputAttributeDescription {
                                    location = unchecked ((uint)inputElementIndex),
                                    binding  = unchecked ((uint)inputIndex),
                                    format   = GetInputElementFormat(inputElement.Type),
                                    offset   = inputBindingStride,
                                };

                                inputBindingStride += inputElement.Size;
                                inputElementsIndex++;
                            }

                            vertexInputBindingDescription.stride = inputBindingStride;
                        }
                    }

                    pipelineCreateInfo.pVertexInputState   = &pipelineVertexInputStateCreateInfo;
                    pipelineCreateInfo.pInputAssemblyState = &pipelineInputAssemblyStateCreateInfo;
                }

                var pixelShader = PixelShader;

                if (pixelShader != null)
                {
                    var shaderIndex = pipelineShaderStageCreateInfosCount++;

                    var entryPointName       = pixelShader.EntryPointName.GetUtf8Span();
                    var entryPointNameLength = (nuint)entryPointName.Length + 1;

                    pipelineShaderStageCreateInfos[shaderIndex] = new VkPipelineShaderStageCreateInfo {
                        sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                        stage  = VK_SHADER_STAGE_FRAGMENT_BIT,
                        module = pixelShader.VulkanShaderModule,
                        pName  = AllocateArray <sbyte>(entryPointNameLength),
                    };

                    var destination = new Span <sbyte>(pipelineShaderStageCreateInfos[shaderIndex].pName, (int)entryPointNameLength);
                    entryPointName.CopyTo(destination);
                    destination[entryPointName.Length] = 0x00;
                }

                if (pipelineShaderStageCreateInfosCount != 0)
                {
                    pipelineCreateInfo.stageCount = pipelineShaderStageCreateInfosCount;
                    pipelineCreateInfo.pStages    = pipelineShaderStageCreateInfos;
                }

                fixed(VkVertexInputAttributeDescription *pVertexInputAttributeDescriptions = vertexInputAttributeDescriptions)
                {
                    pipelineVertexInputStateCreateInfo.vertexAttributeDescriptionCount = unchecked ((uint)vertexInputAttributeDescriptions.Length);
                    pipelineVertexInputStateCreateInfo.pVertexAttributeDescriptions    = pVertexInputAttributeDescriptions;

                    ThrowExternalExceptionIfNotSuccess(vkCreateGraphicsPipelines(device.VulkanDevice, pipelineCache: VK_NULL_HANDLE, 1, &pipelineCreateInfo, pAllocator: null, (ulong *)&vulkanPipeline), nameof(vkCreateGraphicsPipelines));
                }

                return(vulkanPipeline);
            }
            finally
            {
                for (uint index = 0; index < pipelineShaderStageCreateInfosCount; index++)
                {
                    var entryPointName = pipelineShaderStageCreateInfos[index].pName;
                    Free(entryPointName);
                }
            }
Example #12
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 #13
0
        void preparePipelines()
        {
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
                Initializers.pipelineInputAssemblyStateCreateInfo(
                    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
                    0,
                    VK_FALSE);

            VkPipelineRasterizationStateCreateInfo rasterizationState =
                Initializers.pipelineRasterizationStateCreateInfo(
                    VK_POLYGON_MODE_FILL,
                    VK_CULL_MODE_NONE,
                    VK_FRONT_FACE_COUNTER_CLOCKWISE,
                    0);

            VkPipelineColorBlendAttachmentState blendAttachmentState =
                Initializers.pipelineColorBlendAttachmentState(
                    0xf,
                    VK_FALSE);

            VkPipelineColorBlendStateCreateInfo colorBlendState =
                Initializers.pipelineColorBlendStateCreateInfo(
                    1,
                    &blendAttachmentState);

            VkPipelineDepthStencilStateCreateInfo depthStencilState =
                Initializers.pipelineDepthStencilStateCreateInfo(
                    VK_TRUE,
                    VK_TRUE,
                    VK_COMPARE_OP_LESS_OR_EQUAL);

            VkPipelineViewportStateCreateInfo viewportState =
                Initializers.pipelineViewportStateCreateInfo(1, 1, 0);

            VkPipelineMultisampleStateCreateInfo multisampleState =
                Initializers.pipelineMultisampleStateCreateInfo(
                    VK_SAMPLE_COUNT_1_BIT,
                    0);

            NativeList <VkDynamicState> dynamicStateEnables = new NativeList <VkDynamicState>
            {
                VK_DYNAMIC_STATE_VIEWPORT,
                VK_DYNAMIC_STATE_SCISSOR
            };
            VkPipelineDynamicStateCreateInfo dynamicState =
                Initializers.pipelineDynamicStateCreateInfo(
                    (VkDynamicState *)dynamicStateEnables.Data,
                    dynamicStateEnables.Count,
                    0);

            FixedArray2 <VkPipelineShaderStageCreateInfo> shaderStages = new FixedArray2 <VkPipelineShaderStageCreateInfo>();

            VkGraphicsPipelineCreateInfo pipelineCreateInfo =
                Initializers.pipelineCreateInfo(
                    pipelineLayouts_radialBlur,
                    renderPass,
                    0);

            pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
            pipelineCreateInfo.pRasterizationState = &rasterizationState;
            pipelineCreateInfo.pColorBlendState    = &colorBlendState;
            pipelineCreateInfo.pMultisampleState   = &multisampleState;
            pipelineCreateInfo.pViewportState      = &viewportState;
            pipelineCreateInfo.pDepthStencilState  = &depthStencilState;
            pipelineCreateInfo.pDynamicState       = &dynamicState;
            pipelineCreateInfo.stageCount          = shaderStages.Count;
            pipelineCreateInfo.pStages             = &shaderStages.First;

            // Radial blur pipeline
            shaderStages.First  = loadShader(getAssetPath() + "shaders/radialblur/radialblur.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
            shaderStages.Second = loadShader(getAssetPath() + "shaders/radialblur/radialblur.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
            // Empty vertex input state
            VkPipelineVertexInputStateCreateInfo emptyInputState = Initializers.pipelineVertexInputStateCreateInfo();

            pipelineCreateInfo.pVertexInputState = &emptyInputState;
            pipelineCreateInfo.layout            = pipelineLayouts_radialBlur;
            // Additive blending
            blendAttachmentState.colorWriteMask      = (VkColorComponentFlags)0xF;
            blendAttachmentState.blendEnable         = VK_TRUE;
            blendAttachmentState.colorBlendOp        = VK_BLEND_OP_ADD;
            blendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
            blendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
            blendAttachmentState.alphaBlendOp        = VK_BLEND_OP_ADD;
            blendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
            blendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA;
            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_radialBlur));

            // No blending (for debug display)
            blendAttachmentState.blendEnable = VK_FALSE;
            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_offscreenDisplay));

            // Phong pass
            pipelineCreateInfo.layout = pipelineLayouts_scene;
            shaderStages.First        = loadShader(getAssetPath() + "shaders/radialblur/phongpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
            shaderStages.Second       = loadShader(getAssetPath() + "shaders/radialblur/phongpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
            var vis = vertices_inputState;

            pipelineCreateInfo.pVertexInputState = &vis;
            blendAttachmentState.blendEnable     = VK_FALSE;
            depthStencilState.depthWriteEnable   = VK_TRUE;
            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_phongPass));

            // Color only pass (offscreen blur base)
            shaderStages.First            = loadShader(getAssetPath() + "shaders/radialblur/colorpass.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
            shaderStages.Second           = loadShader(getAssetPath() + "shaders/radialblur/colorpass.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
            pipelineCreateInfo.renderPass = offscreenPass.renderPass;
            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_colorPass));
        }
Example #14
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 #15
0
        public VkPipeline(VkGraphicsDevice gd, ref PipelineDescription description)
        {
            _gd = gd;

            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        = VkFrontFace.Clockwise;
            rsCI.lineWidth        = 1f;

            pipelineCI.pRasterizationState = &rsCI;

            // 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.ComparisonKind);

            pipelineCI.pDepthStencilState = &dssCI;

            // Multisample
            VkPipelineMultisampleStateCreateInfo multisampleCI = VkPipelineMultisampleStateCreateInfo.New();

            multisampleCI.rasterizationSamples = VkSampleCountFlags.Count1;

            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[targetIndex] = new VkVertexInputBindingDescription()
                {
                    binding   = (uint)binding,
                    inputRate = (inputDesc.Elements[0].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
            ShaderStageDescription[] stageDescs = description.ShaderSet.ShaderStages;
            StackList <VkPipelineShaderStageCreateInfo> stages = new StackList <VkPipelineShaderStageCreateInfo>();

            foreach (ShaderStageDescription stageDesc in stageDescs)
            {
                VkShader vkShader = Util.AssertSubtype <Shader, VkShader>(stageDesc.Shader);
                VkPipelineShaderStageCreateInfo stageCI = VkPipelineShaderStageCreateInfo.New();
                stageCI.module = vkShader.ShaderModule;
                stageCI.stage  = VkFormats.VdToVkShaderStages(stageDesc.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;

            if (outputDesc.ColorAttachments.Length > 1)
            {
                throw new NotImplementedException("Laziness");
            }

            VkAttachmentDescription colorAttachmentDesc = new VkAttachmentDescription();

            colorAttachmentDesc.format = outputDesc.ColorAttachments.Length > 0
                ? VkFormats.VdToVkPixelFormat(outputDesc.ColorAttachments[0].Format) : 0;
            colorAttachmentDesc.samples        = VkSampleCountFlags.Count1;
            colorAttachmentDesc.loadOp         = VkAttachmentLoadOp.Clear;
            colorAttachmentDesc.storeOp        = VkAttachmentStoreOp.Store;
            colorAttachmentDesc.stencilLoadOp  = VkAttachmentLoadOp.DontCare;
            colorAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare;
            colorAttachmentDesc.initialLayout  = VkImageLayout.Undefined;
            colorAttachmentDesc.finalLayout    = VkImageLayout.PresentSrcKHR;

            VkAttachmentReference colorAttachmentRef = new VkAttachmentReference();

            colorAttachmentRef.attachment = 0;
            colorAttachmentRef.layout     = VkImageLayout.ColorAttachmentOptimal;

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

            if (outputDesc.DepthAttachment != null)
            {
                depthAttachmentDesc.format         = VkFormats.VdToVkPixelFormat(outputDesc.DepthAttachment.Value.Format, toDepthFormat: true);
                depthAttachmentDesc.samples        = VkSampleCountFlags.Count1;
                depthAttachmentDesc.loadOp         = VkAttachmentLoadOp.Clear;
                depthAttachmentDesc.storeOp        = VkAttachmentStoreOp.Store;
                depthAttachmentDesc.stencilLoadOp  = VkAttachmentLoadOp.DontCare;
                depthAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare;
                depthAttachmentDesc.initialLayout  = VkImageLayout.Undefined;
                depthAttachmentDesc.finalLayout    = VkImageLayout.DepthStencilAttachmentOptimal;

                depthAttachmentRef.attachment = outputDesc.ColorAttachments.Length == 0 ? 0u : 1u;
                depthAttachmentRef.layout     = VkImageLayout.DepthStencilAttachmentOptimal;
            }

            VkSubpassDescription subpass = new VkSubpassDescription();
            StackList <VkAttachmentDescription, Size512Bytes> attachments = new StackList <VkAttachmentDescription, Size512Bytes>();

            subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics;
            if (outputDesc.ColorAttachments.Length > 0)
            {
                subpass.colorAttachmentCount = 1;
                subpass.pColorAttachments    = &colorAttachmentRef;
                attachments.Add(colorAttachmentDesc);
            }

            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;
        }
Example #16
0
        void preparePipelines()
        {
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
                Initializers.pipelineInputAssemblyStateCreateInfo(
                    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
                    0,
                    VK_FALSE);

            VkPipelineRasterizationStateCreateInfo rasterizationState =
                Initializers.pipelineRasterizationStateCreateInfo(
                    VK_POLYGON_MODE_FILL,
                    VK_CULL_MODE_FRONT_BIT,
                    VK_FRONT_FACE_CLOCKWISE,
                    0);

            VkPipelineColorBlendAttachmentState blendAttachmentState =
                Initializers.pipelineColorBlendAttachmentState(
                    0xf,
                    VK_FALSE);

            VkPipelineColorBlendStateCreateInfo colorBlendState =
                Initializers.pipelineColorBlendStateCreateInfo(
                    1,
                    &blendAttachmentState);

            VkPipelineDepthStencilStateCreateInfo depthStencilState =
                Initializers.pipelineDepthStencilStateCreateInfo(
                    VK_TRUE,
                    VK_TRUE,
                    VK_COMPARE_OP_LESS_OR_EQUAL);

            VkPipelineViewportStateCreateInfo viewportState =
                Initializers.pipelineViewportStateCreateInfo(1, 1, 0);

            VkPipelineMultisampleStateCreateInfo multisampleState =
                Initializers.pipelineMultisampleStateCreateInfo(
                    VkSampleCountFlags.Count1,
                    0);

            FixedArray2<VkDynamicState> dynamicStateEnables = new FixedArray2<VkDynamicState>(
                VK_DYNAMIC_STATE_VIEWPORT,
                VK_DYNAMIC_STATE_SCISSOR);

            VkPipelineDynamicStateCreateInfo dynamicState =
                Initializers.pipelineDynamicStateCreateInfo(
                    &dynamicStateEnables.First,
                    dynamicStateEnables.Count,
                    0);

            // Solid rendering pipeline
            // Load shaders
            FixedArray2<VkPipelineShaderStageCreateInfo> shaderStages = new FixedArray2<VkPipelineShaderStageCreateInfo>(
                loadShader(getAssetPath() + "shaders/offscreen/quad.vert.spv", VK_SHADER_STAGE_VERTEX_BIT),
                loadShader(getAssetPath() + "shaders/offscreen/quad.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT));

            VkGraphicsPipelineCreateInfo pipelineCreateInfo =
                Initializers.pipelineCreateInfo(
                    pipelineLayouts_textured,
                    renderPass,
                    0);

            var vis = vertices_inputState;
            pipelineCreateInfo.pVertexInputState = &vis;
            pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
            pipelineCreateInfo.pRasterizationState = &rasterizationState;
            pipelineCreateInfo.pColorBlendState = &colorBlendState;
            pipelineCreateInfo.pMultisampleState = &multisampleState;
            pipelineCreateInfo.pViewportState = &viewportState;
            pipelineCreateInfo.pDepthStencilState = &depthStencilState;
            pipelineCreateInfo.pDynamicState = &dynamicState;
            pipelineCreateInfo.stageCount = shaderStages.Count;
            pipelineCreateInfo.pStages = &shaderStages.First;

            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_debug));

            // Mirror
            shaderStages.First = loadShader(getAssetPath() + "shaders/offscreen/mirror.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
            shaderStages.Second = loadShader(getAssetPath() + "shaders/offscreen/mirror.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
            rasterizationState.cullMode = VK_CULL_MODE_NONE;
            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_mirror));

            // Flip culling
            rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT;

            // Phong shading pipelines
            pipelineCreateInfo.layout = pipelineLayouts_shaded;
            // Scene
            shaderStages.First = loadShader(getAssetPath() + "shaders/offscreen/phong.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
            shaderStages.Second = loadShader(getAssetPath() + "shaders/offscreen/phong.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_shaded));
            // Offscreen
            // Flip culling
            rasterizationState.cullMode = VK_CULL_MODE_FRONT_BIT;
            pipelineCreateInfo.renderPass = offscreenPass.renderPass;
            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_shadedOffscreen));

        }
Example #17
0
        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()
        {
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
                Initializers.pipelineInputAssemblyStateCreateInfo(
                    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
                    0,
                    VK_FALSE);

            VkPipelineRasterizationStateCreateInfo rasterizationState =
                Initializers.pipelineRasterizationStateCreateInfo(
                    VK_POLYGON_MODE_FILL,
                    VK_CULL_MODE_NONE,
                    VK_FRONT_FACE_COUNTER_CLOCKWISE,
                    0);

            VkPipelineColorBlendAttachmentState blendAttachmentState =
                Initializers.pipelineColorBlendAttachmentState(
                    0xf,
                    VK_FALSE);

            VkPipelineColorBlendStateCreateInfo colorBlendState =
                Initializers.pipelineColorBlendStateCreateInfo(
                    1,
                    &blendAttachmentState);

            VkPipelineDepthStencilStateCreateInfo depthStencilState =
                Initializers.pipelineDepthStencilStateCreateInfo(
                    VK_TRUE,
                    VK_TRUE,
                    VK_COMPARE_OP_LESS_OR_EQUAL);

            VkPipelineViewportStateCreateInfo viewportState =
                Initializers.pipelineViewportStateCreateInfo(1, 1, 0);

            VkPipelineMultisampleStateCreateInfo multisampleState =
                Initializers.pipelineMultisampleStateCreateInfo(
                    VK_SAMPLE_COUNT_1_BIT,
                    0);

            FixedArray2 <VkDynamicState> dynamicStateEnables = new FixedArray2 <VkDynamicState>(
                VK_DYNAMIC_STATE_VIEWPORT,
                VK_DYNAMIC_STATE_SCISSOR);

            VkPipelineDynamicStateCreateInfo dynamicState =
                Initializers.pipelineDynamicStateCreateInfo(
                    &dynamicStateEnables.First,
                    dynamicStateEnables.Count,
                    0);

            // Load shaders
            FixedArray2 <VkPipelineShaderStageCreateInfo> shaderStages = new FixedArray2 <VkPipelineShaderStageCreateInfo>(
                loadShader(getAssetPath() + "shaders/dynamicuniformbuffer/base.vert.spv", VK_SHADER_STAGE_VERTEX_BIT),
                loadShader(getAssetPath() + "shaders/dynamicuniformbuffer/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT));

            VkGraphicsPipelineCreateInfo pipelineCreateInfo =
                Initializers.pipelineCreateInfo(
                    pipelineLayout,
                    renderPass,
                    0);

            var vis = vertices_inputState;

            pipelineCreateInfo.pVertexInputState   = &vis;
            pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
            pipelineCreateInfo.pRasterizationState = &rasterizationState;
            pipelineCreateInfo.pColorBlendState    = &colorBlendState;
            pipelineCreateInfo.pMultisampleState   = &multisampleState;
            pipelineCreateInfo.pViewportState      = &viewportState;
            pipelineCreateInfo.pDepthStencilState  = &depthStencilState;
            pipelineCreateInfo.pDynamicState       = &dynamicState;
            pipelineCreateInfo.stageCount          = shaderStages.Count;
            pipelineCreateInfo.pStages             = &shaderStages.First;

            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipeline));
        }
Example #19
0
        void preparePipelines()
        {
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
                Initializers.pipelineInputAssemblyStateCreateInfo(
                    VkPrimitiveTopology.TriangleList,
                    0,
                    False);

            VkPipelineRasterizationStateCreateInfo rasterizationState =
                Initializers.pipelineRasterizationStateCreateInfo(
                    VkPolygonMode.Fill,
                    VkCullModeFlags.Back,
                    VkFrontFace.Clockwise,
                    0);

            VkPipelineColorBlendAttachmentState blendAttachmentState =
                Initializers.pipelineColorBlendAttachmentState(
                    0xf,
                    False);

            VkPipelineColorBlendStateCreateInfo colorBlendState =
                Initializers.pipelineColorBlendStateCreateInfo(
                    1,
                    &blendAttachmentState);

            VkPipelineDepthStencilStateCreateInfo depthStencilState =
                Initializers.pipelineDepthStencilStateCreateInfo(
                    True,
                    True,
                    VkCompareOp.LessOrEqual);

            VkPipelineViewportStateCreateInfo viewportState =
                Initializers.pipelineViewportStateCreateInfo(1, 1, 0);

            VkPipelineMultisampleStateCreateInfo multisampleState =
                Initializers.pipelineMultisampleStateCreateInfo(
                    VkSampleCountFlags.Count1,
                    0);

            FixedArray2 <VkDynamicState> dynamicStateEnables = new FixedArray2 <VkDynamicState>(
                VkDynamicState.Viewport,
                VkDynamicState.Scissor);
            VkPipelineDynamicStateCreateInfo dynamicState =
                Initializers.pipelineDynamicStateCreateInfo(
                    &dynamicStateEnables.First,
                    dynamicStateEnables.Count,
                    0);

            // Solid rendering pipeline
            // Load shaders
            FixedArray2 <VkPipelineShaderStageCreateInfo> shaderStages = new FixedArray2 <VkPipelineShaderStageCreateInfo>(
                loadShader(getAssetPath() + "shaders/mesh/mesh.vert.spv", VkShaderStageFlags.Vertex),
                loadShader(getAssetPath() + "shaders/mesh/mesh.frag.spv", VkShaderStageFlags.Fragment));

            VkGraphicsPipelineCreateInfo pipelineCreateInfo =
                Initializers.pipelineCreateInfo(
                    pipelineLayout,
                    renderPass,
                    0);

            var via = vertices_inputState;

            pipelineCreateInfo.pVertexInputState   = &via;
            pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
            pipelineCreateInfo.pRasterizationState = &rasterizationState;
            pipelineCreateInfo.pColorBlendState    = &colorBlendState;
            pipelineCreateInfo.pMultisampleState   = &multisampleState;
            pipelineCreateInfo.pViewportState      = &viewportState;
            pipelineCreateInfo.pDepthStencilState  = &depthStencilState;
            pipelineCreateInfo.pDynamicState       = &dynamicState;
            pipelineCreateInfo.stageCount          = shaderStages.Count;
            pipelineCreateInfo.pStages             = &shaderStages.First;

            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_solid));

            // Wire frame rendering pipeline
            if (DeviceFeatures.fillModeNonSolid == 1)
            {
                rasterizationState.polygonMode = VkPolygonMode.Line;
                rasterizationState.lineWidth   = 1.0f;
                Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_wireframe));
            }
        }
Example #20
0
        private void createGraphicsPipeline()
        {
            var vertShaderModule = createShaderModule(typeof(Shader_Vert_03));
            var fragShaderModule = createShaderModule(typeof(Shader_Frag_03));

            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;

            var bindingDescription    = Vertex.getBindingDescription();
            var attributeDescriptions = Vertex.getAttributeDescriptions();

            vertexInputInfo.vertexBindingDescriptionCount   = 1;
            vertexInputInfo.vertexAttributeDescriptionCount = attributeDescriptions.Length;
            vertexInputInfo.pVertexBindingDescriptions      = new VkVertexInputBindingDescription[] { bindingDescription };
            vertexInputInfo.pVertexAttributeDescriptions    = attributeDescriptions;

            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);
        }
Example #21
0
        private unsafe void Recreate()
        {
            if (Description.RootSignature == null)
            {
                return;
            }

            CreateRenderPass(Description);

            CreatePipelineLayout(Description);

            // Create shader stages
            Dictionary <int, string> inputAttributeNames;

            // Note: important to pin this so that stages[x].Name is valid during this whole function
            void *defaultEntryPointData = Core.Interop.Fixed(defaultEntryPoint);
            var   stages = CreateShaderStages(Description, out inputAttributeNames);

            var inputAttributes     = new VkVertexInputAttributeDescription[Description.InputElements.Length];
            int inputAttributeCount = 0;
            var inputBindings       = new VkVertexInputBindingDescription[inputAttributes.Length];
            int inputBindingCount   = 0;

            for (int inputElementIndex = 0; inputElementIndex < inputAttributes.Length; inputElementIndex++)
            {
                var inputElement = Description.InputElements[inputElementIndex];
                var slotIndex    = inputElement.InputSlot;

                if (inputElement.InstanceDataStepRate > 1)
                {
                    throw new NotImplementedException();
                }

                VkFormat format;
                int      size;
                bool     isCompressed;
                VulkanConvertExtensions.ConvertPixelFormat(inputElement.Format, out format, out size, out isCompressed);

                var location = inputAttributeNames.FirstOrDefault(x => x.Value == inputElement.SemanticName && inputElement.SemanticIndex == 0 || x.Value == inputElement.SemanticName + inputElement.SemanticIndex);
                if (location.Value != null)
                {
                    inputAttributes[inputAttributeCount++] = new VkVertexInputAttributeDescription
                    {
                        format   = format,
                        offset   = (uint)inputElement.AlignedByteOffset,
                        binding  = (uint)inputElement.InputSlot,
                        location = (uint)location.Key
                    };
                }

                inputBindings[slotIndex].binding   = (uint)slotIndex;
                inputBindings[slotIndex].inputRate = inputElement.InputSlotClass == InputClassification.Vertex ? VkVertexInputRate.Vertex : VkVertexInputRate.Instance;

                // TODO VULKAN: This is currently an argument to Draw() overloads.
                if (inputBindings[slotIndex].stride < inputElement.AlignedByteOffset + size)
                {
                    inputBindings[slotIndex].stride = (uint)(inputElement.AlignedByteOffset + size);
                }

                if (inputElement.InputSlot >= inputBindingCount)
                {
                    inputBindingCount = inputElement.InputSlot + 1;
                }
            }

            var inputAssemblyState = new VkPipelineInputAssemblyStateCreateInfo
            {
                sType    = VkStructureType.PipelineInputAssemblyStateCreateInfo,
                topology = VulkanConvertExtensions.ConvertPrimitiveType(Description.PrimitiveType),
                primitiveRestartEnable = VulkanConvertExtensions.ConvertPrimitiveRestart(Description.PrimitiveType),
            };

            // TODO VULKAN: Tessellation and multisampling
            var multisampleState = new VkPipelineMultisampleStateCreateInfo
            {
                sType = VkStructureType.PipelineMultisampleStateCreateInfo,
                rasterizationSamples = VkSampleCountFlags.Count1,
            };

            var tessellationState = new VkPipelineTessellationStateCreateInfo
            {
                sType = VkStructureType.PipelineTessellationStateCreateInfo,
            };

            var rasterizationState = CreateRasterizationState(Description.RasterizerState);

            var depthStencilState = CreateDepthStencilState(Description);

            var description = Description.BlendState;

            var renderTargetCount     = Description.Output.RenderTargetCount;
            var colorBlendAttachments = new VkPipelineColorBlendAttachmentState[renderTargetCount];

            var renderTargetBlendState = &description.RenderTarget0;

            for (int i = 0; i < renderTargetCount; i++)
            {
                colorBlendAttachments[i] = new VkPipelineColorBlendAttachmentState
                {
                    blendEnable         = renderTargetBlendState->BlendEnable,
                    alphaBlendOp        = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->AlphaBlendFunction),
                    colorBlendOp        = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->ColorBlendFunction),
                    dstAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaDestinationBlend),
                    dstColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorDestinationBlend),
                    srcAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaSourceBlend),
                    srcColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorSourceBlend),
                    colorWriteMask      = VulkanConvertExtensions.ConvertColorWriteChannels(renderTargetBlendState->ColorWriteChannels),
                };

                if (description.IndependentBlendEnable)
                {
                    renderTargetBlendState++;
                }
            }

            var viewportState = new VkPipelineViewportStateCreateInfo
            {
                sType         = VkStructureType.PipelineViewportStateCreateInfo,
                scissorCount  = 1,
                viewportCount = 1,
            };

            fixed(VkDynamicState *dynamicStatesPointer = &dynamicStates[0])
            {
                var vertexInputState = new VkPipelineVertexInputStateCreateInfo
                {
                    sType = VkStructureType.PipelineVertexInputStateCreateInfo,
                    vertexAttributeDescriptionCount = (uint)inputAttributeCount,
                    pVertexAttributeDescriptions    = inputAttributes.Length > 0 ? (VkVertexInputAttributeDescription *)Core.Interop.Fixed(inputAttributes) : null,
                    vertexBindingDescriptionCount   = (uint)inputBindingCount,
                    pVertexBindingDescriptions      = inputBindings.Length > 0 ? (VkVertexInputBindingDescription *)Core.Interop.Fixed(inputBindings) : null,
                };

                var colorBlendState = new VkPipelineColorBlendStateCreateInfo
                {
                    sType           = VkStructureType.PipelineColorBlendStateCreateInfo,
                    attachmentCount = (uint)renderTargetCount,
                    pAttachments    = colorBlendAttachments.Length > 0 ? (VkPipelineColorBlendAttachmentState *)Core.Interop.Fixed(colorBlendAttachments) : null,
                };

                var dynamicState = new VkPipelineDynamicStateCreateInfo
                {
                    sType             = VkStructureType.PipelineDynamicStateCreateInfo,
                    dynamicStateCount = (uint)dynamicStates.Length,
                    pDynamicStates    = dynamicStatesPointer,
                };

                var createInfo = new VkGraphicsPipelineCreateInfo
                {
                    sType      = VkStructureType.GraphicsPipelineCreateInfo,
                    layout     = NativeLayout,
                    stageCount = (uint)stages.Length,
                    pStages    = stages.Length > 0 ? (VkPipelineShaderStageCreateInfo *)Core.Interop.Fixed(stages) : null,
                    //tessellationState = &tessellationState,
                    pVertexInputState   = &vertexInputState,
                    pInputAssemblyState = &inputAssemblyState,
                    pRasterizationState = &rasterizationState,
                    pMultisampleState   = &multisampleState,
                    pDepthStencilState  = &depthStencilState,
                    pColorBlendState    = &colorBlendState,
                    pDynamicState       = &dynamicState,
                    pViewportState      = &viewportState,
                    renderPass          = NativeRenderPass,
                    subpass             = 0,
                };

                fixed(VkPipeline *nativePipelinePtr = &NativePipeline)
                vkCreateGraphicsPipelines(GraphicsDevice.NativeDevice, VkPipelineCache.Null, 1, &createInfo, null, nativePipelinePtr);
            }

            // Cleanup shader modules
            foreach (var stage in stages)
            {
                vkDestroyShaderModule(GraphicsDevice.NativeDevice, stage.module, null);
            }
        }
Example #22
0
        //[HandleProcessCorruptedStateExceptionsAttribute, SecurityCriticalAttribute]
        private unsafe void Recreate()
        {
            errorDuringCreate = false;

            if (Description.RootSignature == null)
            {
                return;
            }

            VkPipelineShaderStageCreateInfo[] stages;

            // create render pass
            bool hasDepthStencilAttachment = Description.Output.DepthStencilFormat != PixelFormat.None;

            var renderTargetCount = Description.Output.RenderTargetCount;

            var attachmentCount = renderTargetCount;

            if (hasDepthStencilAttachment)
            {
                attachmentCount++;
            }

            var attachments = new VkAttachmentDescription[attachmentCount];
            var colorAttachmentReferences = new VkAttachmentReference[renderTargetCount];

            fixed(PixelFormat *renderTargetFormat = &Description.Output.RenderTargetFormat0)
            fixed(BlendStateRenderTargetDescription * blendDescription = &Description.BlendState.RenderTarget0)
            {
                for (int i = 0; i < renderTargetCount; i++)
                {
                    var currentBlendDesc = Description.BlendState.IndependentBlendEnable ? (blendDescription + i) : blendDescription;

                    attachments[i] = new VkAttachmentDescription
                    {
                        format         = VulkanConvertExtensions.ConvertPixelFormat(*(renderTargetFormat + i)),
                        samples        = VkSampleCountFlags.Count1,
                        loadOp         = currentBlendDesc->BlendEnable ? VkAttachmentLoadOp.Load : VkAttachmentLoadOp.DontCare, // TODO VULKAN: Only if any destination blend?
                        storeOp        = VkAttachmentStoreOp.Store,
                        stencilLoadOp  = VkAttachmentLoadOp.DontCare,
                        stencilStoreOp = VkAttachmentStoreOp.DontCare,
                        initialLayout  = VkImageLayout.ColorAttachmentOptimal,
                        finalLayout    = VkImageLayout.ColorAttachmentOptimal,
                    };

                    colorAttachmentReferences[i] = new VkAttachmentReference
                    {
                        attachment = (uint)i,
                        layout     = VkImageLayout.ColorAttachmentOptimal,
                    };
                }
            }

            if (hasDepthStencilAttachment)
            {
                attachments[attachmentCount - 1] = new VkAttachmentDescription
                {
                    format         = Texture.GetFallbackDepthStencilFormat(GraphicsDevice, VulkanConvertExtensions.ConvertPixelFormat(Description.Output.DepthStencilFormat)),
                    samples        = VkSampleCountFlags.Count1,
                    loadOp         = VkAttachmentLoadOp.Load,     // TODO VULKAN: Only if depth read enabled?
                    storeOp        = VkAttachmentStoreOp.Store,   // TODO VULKAN: Only if depth write enabled?
                    stencilLoadOp  = VkAttachmentLoadOp.DontCare, // TODO VULKAN: Handle stencil
                    stencilStoreOp = VkAttachmentStoreOp.DontCare,
                    initialLayout  = VkImageLayout.DepthStencilAttachmentOptimal,
                    finalLayout    = VkImageLayout.DepthStencilAttachmentOptimal,
                };
            }

            var depthAttachmentReference = new VkAttachmentReference
            {
                attachment = (uint)attachments.Length - 1,
                layout     = VkImageLayout.DepthStencilAttachmentOptimal,
            };

            var subpass = new VkSubpassDescription
            {
                pipelineBindPoint       = VkPipelineBindPoint.Graphics,
                colorAttachmentCount    = (uint)renderTargetCount,
                pColorAttachments       = colorAttachmentReferences.Length > 0 ? (VkAttachmentReference *)Core.Interop.Fixed(colorAttachmentReferences) : null,
                pDepthStencilAttachment = hasDepthStencilAttachment ? &depthAttachmentReference : null,
            };

            var renderPassCreateInfo = new VkRenderPassCreateInfo
            {
                sType           = VkStructureType.RenderPassCreateInfo,
                attachmentCount = (uint)attachmentCount,
                pAttachments    = attachments.Length > 0 ? (VkAttachmentDescription *)Core.Interop.Fixed(attachments) : null,
                subpassCount    = 1,
                pSubpasses      = &subpass,
            };

            // create pipeline layout
            // Remap descriptor set indices to those in the shader. This ordering generated by the ShaderCompiler
            var resourceGroups = Description.EffectBytecode.Reflection.ResourceBindings.Select(x => x.ResourceGroup ?? "Globals").Distinct().ToList();

            ResourceGroupCount = resourceGroups.Count;

            var layouts = Description.RootSignature.EffectDescriptorSetReflection.Layouts;

            // Get binding indices used by the shader
            var destinationBindings = Description.EffectBytecode.Stages
                                      .SelectMany(x => BinarySerialization.Read <ShaderInputBytecode>(x.Data).ResourceBindings)
                                      .GroupBy(x => x.Key, x => x.Value)
                                      .ToDictionary(x => x.Key, x => x.First());

            var maxBindingIndex    = destinationBindings.Max(x => x.Value);
            var destinationEntries = new DescriptorSetLayoutBuilder.Entry[maxBindingIndex + 1];

            DescriptorBindingMapping = new List <DescriptorSetInfo>();

            for (int i = 0; i < resourceGroups.Count; i++)
            {
                var resourceGroupName = resourceGroups[i] == "Globals" ? Description.RootSignature.EffectDescriptorSetReflection.DefaultSetSlot : resourceGroups[i];
                var layoutIndex       = resourceGroups[i] == null ? 0 : layouts.FindIndex(x => x.Name == resourceGroupName);

                // Check if the resource group is used by the shader
                if (layoutIndex == -1)
                {
                    continue;
                }

                var sourceEntries = layouts[layoutIndex].Layout.Entries;

                for (int sourceBinding = 0; sourceBinding < sourceEntries.Count; sourceBinding++)
                {
                    var sourceEntry = sourceEntries[sourceBinding];

                    int destinationBinding;
                    if (destinationBindings.TryGetValue(sourceEntry.Key.Name, out destinationBinding))
                    {
                        destinationEntries[destinationBinding] = sourceEntry;

                        // No need to umpdate immutable samplers
                        if (sourceEntry.Class == EffectParameterClass.Sampler && sourceEntry.ImmutableSampler != null)
                        {
                            continue;
                        }

                        DescriptorBindingMapping.Add(new DescriptorSetInfo
                        {
                            SourceSet          = layoutIndex,
                            SourceBinding      = sourceBinding,
                            DestinationBinding = destinationBinding,
                            DescriptorType     = VulkanConvertExtensions.ConvertDescriptorType(sourceEntry.Class, sourceEntry.Type)
                        });
                    }
                }
            }

            // Create default sampler, used by texture and buffer loads
            destinationEntries[0] = new DescriptorSetLayoutBuilder.Entry
            {
                Class            = EffectParameterClass.Sampler,
                Type             = EffectParameterType.Sampler,
                ImmutableSampler = GraphicsDevice.SamplerStates.PointWrap,
                ArraySize        = 1,
            };

            // Create descriptor set layout
            NativeDescriptorSetLayout = DescriptorSetLayout.CreateNativeDescriptorSetLayout(GraphicsDevice, destinationEntries, out DescriptorTypeCounts);

            // Create pipeline layout
            var nativeDescriptorSetLayout = NativeDescriptorSetLayout;
            var pipelineLayoutCreateInfo  = new VkPipelineLayoutCreateInfo
            {
                sType          = VkStructureType.PipelineLayoutCreateInfo,
                setLayoutCount = 1,
                pSetLayouts    = &nativeDescriptorSetLayout,
            };

            // Create shader stages
            Dictionary <int, string> inputAttributeNames;

            // Note: important to pin this so that stages[x].Name is valid during this whole function
            void *defaultEntryPointData = Core.Interop.Fixed(defaultEntryPoint);

            stages = CreateShaderStages(Description, out inputAttributeNames);

            var inputAttributes     = new VkVertexInputAttributeDescription[Description.InputElements.Length];
            int inputAttributeCount = 0;
            var inputBindings       = new VkVertexInputBindingDescription[inputAttributes.Length];
            int inputBindingCount   = 0;

            for (int inputElementIndex = 0; inputElementIndex < inputAttributes.Length; inputElementIndex++)
            {
                var inputElement = Description.InputElements[inputElementIndex];
                var slotIndex    = inputElement.InputSlot;

                if (inputElement.InstanceDataStepRate > 1)
                {
                    throw new NotImplementedException();
                }

                VkFormat format;
                int      size;
                bool     isCompressed;
                VulkanConvertExtensions.ConvertPixelFormat(inputElement.Format, out format, out size, out isCompressed);

                var location = inputAttributeNames.FirstOrDefault(x => x.Value == inputElement.SemanticName && inputElement.SemanticIndex == 0 || x.Value == inputElement.SemanticName + inputElement.SemanticIndex);
                if (location.Value != null)
                {
                    inputAttributes[inputAttributeCount++] = new VkVertexInputAttributeDescription
                    {
                        format   = format,
                        offset   = (uint)inputElement.AlignedByteOffset,
                        binding  = (uint)inputElement.InputSlot,
                        location = (uint)location.Key
                    };
                }

                inputBindings[slotIndex].binding   = (uint)slotIndex;
                inputBindings[slotIndex].inputRate = inputElement.InputSlotClass == InputClassification.Vertex ? VkVertexInputRate.Vertex : VkVertexInputRate.Instance;

                // TODO VULKAN: This is currently an argument to Draw() overloads.
                if (inputBindings[slotIndex].stride < inputElement.AlignedByteOffset + size)
                {
                    inputBindings[slotIndex].stride = (uint)(inputElement.AlignedByteOffset + size);
                }

                if (inputElement.InputSlot >= inputBindingCount)
                {
                    inputBindingCount = inputElement.InputSlot + 1;
                }
            }

            var inputAssemblyState = new VkPipelineInputAssemblyStateCreateInfo
            {
                sType    = VkStructureType.PipelineInputAssemblyStateCreateInfo,
                topology = VulkanConvertExtensions.ConvertPrimitiveType(Description.PrimitiveType),
                primitiveRestartEnable = VulkanConvertExtensions.ConvertPrimitiveRestart(Description.PrimitiveType) ? (uint)1 : (uint)0,
            };

            // TODO VULKAN: Tessellation and multisampling
            var multisampleState = new VkPipelineMultisampleStateCreateInfo
            {
                sType = VkStructureType.PipelineMultisampleStateCreateInfo,
                rasterizationSamples = VkSampleCountFlags.Count1,
            };

            var rasterizationState = new VkPipelineRasterizationStateCreateInfo
            {
                sType                   = VkStructureType.PipelineRasterizationStateCreateInfo,
                cullMode                = VulkanConvertExtensions.ConvertCullMode(Description.RasterizerState.CullMode),
                frontFace               = Description.RasterizerState.FrontFaceCounterClockwise ? VkFrontFace.CounterClockwise : VkFrontFace.Clockwise,
                polygonMode             = VulkanConvertExtensions.ConvertFillMode(Description.RasterizerState.FillMode),
                depthBiasEnable         = 1, // TODO VULKAN
                depthBiasConstantFactor = Description.RasterizerState.DepthBias,
                depthBiasSlopeFactor    = Description.RasterizerState.SlopeScaleDepthBias,
                depthBiasClamp          = Description.RasterizerState.DepthBiasClamp,
                lineWidth               = 1.0f,
                depthClampEnable        = Description.RasterizerState.DepthClipEnable ? (uint)0 : (uint)1,
                rasterizerDiscardEnable = 0,
            };

            var depthStencilState = new VkPipelineDepthStencilStateCreateInfo
            {
                sType             = VkStructureType.PipelineDepthStencilStateCreateInfo,
                depthTestEnable   = Description.DepthStencilState.DepthBufferEnable ? (uint)1 : (uint)0,
                stencilTestEnable = Description.DepthStencilState.StencilEnable ? (uint)1 : (uint)0,
                depthWriteEnable  = Description.DepthStencilState.DepthBufferWriteEnable ? (uint)1 : (uint)0,

                minDepthBounds = 0.0f,
                maxDepthBounds = 1.0f,
                depthCompareOp = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.DepthBufferFunction),
                front          =
                {
                    compareOp   = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.FrontFace.StencilFunction),
                    depthFailOp = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilDepthBufferFail),
                    failOp      = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilFail),
                    passOp      = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilPass),
                    compareMask = Description.DepthStencilState.StencilMask,
                    writeMask   = Description.DepthStencilState.StencilWriteMask
                },
                back =
                {
                    compareOp   = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.BackFace.StencilFunction),
                    depthFailOp = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilDepthBufferFail),
                    failOp      = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilFail),
                    passOp      = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilPass),
                    compareMask = Description.DepthStencilState.StencilMask,
                    writeMask   = Description.DepthStencilState.StencilWriteMask
                }
            };

            var description = Description.BlendState;

            var colorBlendAttachments = new VkPipelineColorBlendAttachmentState[renderTargetCount];

            var renderTargetBlendState = &description.RenderTarget0;

            for (int i = 0; i < renderTargetCount; i++)
            {
                colorBlendAttachments[i] = new VkPipelineColorBlendAttachmentState
                {
                    blendEnable         = renderTargetBlendState->BlendEnable ? (uint)1 : (uint)0,
                    alphaBlendOp        = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->AlphaBlendFunction),
                    colorBlendOp        = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->ColorBlendFunction),
                    dstAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaDestinationBlend),
                    dstColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorDestinationBlend),
                    srcAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaSourceBlend),
                    srcColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorSourceBlend),
                    colorWriteMask      = VulkanConvertExtensions.ConvertColorWriteChannels(renderTargetBlendState->ColorWriteChannels),
                };

                if (description.IndependentBlendEnable)
                {
                    renderTargetBlendState++;
                }
            }

            var viewportState = new VkPipelineViewportStateCreateInfo
            {
                sType         = VkStructureType.PipelineViewportStateCreateInfo,
                scissorCount  = 1,
                viewportCount = 1,
            };

            fixed(void *dynamicStatesPointer   = dynamicStates.Length == 0?null : dynamicStates,
                  inputAttributesPointer       = inputAttributes.Length == 0?null : inputAttributes,
                  inputBindingsPointer         = inputBindings.Length == 0?null : inputBindings,
                  colorBlendAttachmentsPointer = colorBlendAttachments.Length == 0?null : colorBlendAttachments,
                  stagesPointer = stages.Length == 0?null : stages)
            {
                var vertexInputState = new VkPipelineVertexInputStateCreateInfo
                {
                    sType = VkStructureType.PipelineVertexInputStateCreateInfo,
                    vertexAttributeDescriptionCount = (uint)inputAttributeCount,
                    pVertexAttributeDescriptions    = (Vortice.Vulkan.VkVertexInputAttributeDescription *)inputAttributesPointer,
                    vertexBindingDescriptionCount   = (uint)inputBindingCount,
                    pVertexBindingDescriptions      = (Vortice.Vulkan.VkVertexInputBindingDescription *)inputBindingsPointer,
                };

                var colorBlendState = new VkPipelineColorBlendStateCreateInfo
                {
                    sType           = VkStructureType.PipelineColorBlendStateCreateInfo,
                    attachmentCount = (uint)renderTargetCount,
                    pAttachments    = (Vortice.Vulkan.VkPipelineColorBlendAttachmentState *)colorBlendAttachmentsPointer,
                };

                var dynamicState = new VkPipelineDynamicStateCreateInfo
                {
                    sType             = VkStructureType.PipelineDynamicStateCreateInfo,
                    dynamicStateCount = (uint)dynamicStates.Length,
                    pDynamicStates    = (Vortice.Vulkan.VkDynamicState *)dynamicStatesPointer,
                };

                var createInfo = new VkGraphicsPipelineCreateInfo
                {
                    sType               = VkStructureType.GraphicsPipelineCreateInfo,
                    layout              = NativeLayout,
                    stageCount          = (uint)stages.Length,
                    pVertexInputState   = &vertexInputState,
                    pInputAssemblyState = &inputAssemblyState,
                    pRasterizationState = &rasterizationState,
                    pMultisampleState   = &multisampleState,
                    pDepthStencilState  = &depthStencilState,
                    pColorBlendState    = &colorBlendState,
                    pDynamicState       = &dynamicState,
                    pStages             = (Vortice.Vulkan.VkPipelineShaderStageCreateInfo *)stagesPointer,
                    pViewportState      = &viewportState,
                    renderPass          = NativeRenderPass,
                    subpass             = 0,
                };

                using (GraphicsDevice.QueueLock.ReadLock())
                {
                    vkCreateRenderPass(GraphicsDevice.NativeDevice, &renderPassCreateInfo, null, out NativeRenderPass);
                    vkCreatePipelineLayout(GraphicsDevice.NativeDevice, &pipelineLayoutCreateInfo, null, out NativeLayout);

                    createInfo.layout     = NativeLayout;
                    createInfo.renderPass = NativeRenderPass;

                    try {
                        fixed(VkPipeline *nativePipelinePtr = &NativePipeline)
                        vkCreateGraphicsPipelines(GraphicsDevice.NativeDevice, VkPipelineCache.Null, 1, &createInfo, null, nativePipelinePtr);
                    } catch (Exception e) {
                        errorDuringCreate = true;
                        NativePipeline    = VkPipeline.Null;
                    }
                }
            }

            // Cleanup shader modules
            for (int i = 0; i < stages.Length; i++)
            {
                vkDestroyShaderModule(GraphicsDevice.NativeDevice, stages[i].module, null);
            }
        }
Example #23
0
        protected void init(GraphicPipelineConfig cfg)
        {
            if (state != ActivableState.Activated)
            {
                Layout.Activate();
                RenderPass.Activate();
                Cache?.Activate();

                List <VkPipelineShaderStageCreateInfo> shaderStages = new List <VkPipelineShaderStageCreateInfo> ();
                foreach (ShaderInfo shader in cfg.Shaders)
                {
                    shaderStages.Add(shader.Info);
                }

                using (PinnedObjects pctx = new PinnedObjects()) {
                    VkPipelineColorBlendStateCreateInfo colorBlendInfo = VkPipelineColorBlendStateCreateInfo.New();
                    colorBlendInfo.logicOpEnable = cfg.ColorBlendLogicOpEnable;
                    colorBlendInfo.logicOp       = cfg.ColorBlendLogicOp;
                    unsafe {
                        colorBlendInfo.blendConstants[0] = cfg.ColorBlendConstants.X;
                        colorBlendInfo.blendConstants[1] = cfg.ColorBlendConstants.Y;
                        colorBlendInfo.blendConstants[2] = cfg.ColorBlendConstants.Z;
                        colorBlendInfo.blendConstants[3] = cfg.ColorBlendConstants.W;
                    }
                    colorBlendInfo.attachmentCount = (uint)cfg.blendAttachments.Count;
                    colorBlendInfo.pAttachments    = cfg.blendAttachments.Pin(pctx);

                    VkPipelineDynamicStateCreateInfo dynStatesInfo = VkPipelineDynamicStateCreateInfo.New();
                    dynStatesInfo.dynamicStateCount = (uint)cfg.dynamicStates.Count;
                    dynStatesInfo.pDynamicStates    = cfg.dynamicStates.Cast <int> ().ToArray().Pin(pctx);

                    VkPipelineVertexInputStateCreateInfo vertInputInfo = VkPipelineVertexInputStateCreateInfo.New();
                    vertInputInfo.vertexBindingDescriptionCount   = (uint)cfg.vertexBindings.Count;
                    vertInputInfo.pVertexBindingDescriptions      = cfg.vertexBindings.Pin(pctx);
                    vertInputInfo.vertexAttributeDescriptionCount = (uint)cfg.vertexAttributes.Count;
                    vertInputInfo.pVertexAttributeDescriptions    = cfg.vertexAttributes.Pin(pctx);

                    VkPipelineViewportStateCreateInfo viewportState = VkPipelineViewportStateCreateInfo.New();
                    if (cfg.Viewports.Count > 0)
                    {
                        viewportState.viewportCount = (uint)cfg.Viewports.Count;
                        viewportState.pViewports    = cfg.Viewports.Pin(pctx);
                    }
                    else
                    {
                        viewportState.viewportCount = 1;
                    }

                    if (cfg.Scissors.Count > 0)
                    {
                        viewportState.scissorCount = (uint)cfg.Scissors.Count;
                        viewportState.pScissors    = cfg.Scissors.Pin(pctx);
                    }
                    else
                    {
                        viewportState.scissorCount = 1;
                    }

                    VkGraphicsPipelineCreateInfo info = VkGraphicsPipelineCreateInfo.New();
                    info.renderPass          = RenderPass.handle;
                    info.layout              = Layout.handle;
                    info.pVertexInputState   = vertInputInfo.Pin(pctx);
                    info.pInputAssemblyState = cfg.inputAssemblyState.Pin(pctx);
                    info.pRasterizationState = cfg.rasterizationState.Pin(pctx);
                    info.pColorBlendState    = colorBlendInfo.Pin(pctx);
                    info.pMultisampleState   = cfg.multisampleState.Pin(pctx);
                    info.pViewportState      = viewportState.Pin(pctx);
                    info.pDepthStencilState  = cfg.depthStencilState.Pin(pctx);
                    info.pDynamicState       = dynStatesInfo.Pin(pctx);
                    info.stageCount          = (uint)cfg.Shaders.Count;
                    info.pStages             = shaderStages.Pin(pctx);
                    info.subpass             = cfg.SubpassIndex;

                    Utils.CheckResult(vkCreateGraphicsPipelines(Dev.VkDev, Cache == null ? VkPipelineCache.Null : Cache.handle, 1, ref info, IntPtr.Zero, out handle));
                }
            }
            base.Activate();
        }
        void preparePipelines()
        {
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
                Initializers.pipelineInputAssemblyStateCreateInfo(
                    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
                    0,
                    False);

            VkPipelineRasterizationStateCreateInfo rasterizationState =
                Initializers.pipelineRasterizationStateCreateInfo(
                    VK_POLYGON_MODE_FILL,
                    VK_CULL_MODE_NONE,
                    VK_FRONT_FACE_CLOCKWISE,
                    0);

            VkPipelineColorBlendAttachmentState blendAttachmentState =
                Initializers.pipelineColorBlendAttachmentState(
                    0xf,
                    False);

            VkPipelineColorBlendStateCreateInfo colorBlendState =
                Initializers.pipelineColorBlendStateCreateInfo(
                    1,
                    &blendAttachmentState);

            VkPipelineDepthStencilStateCreateInfo depthStencilState =
                Initializers.pipelineDepthStencilStateCreateInfo(
                    True,
                    True,
                    VK_COMPARE_OP_LESS_OR_EQUAL);

            VkPipelineViewportStateCreateInfo viewportState =
                Initializers.pipelineViewportStateCreateInfo(1, 1, 0);

            VkPipelineMultisampleStateCreateInfo multisampleState =
                Initializers.pipelineMultisampleStateCreateInfo(
                    VK_SAMPLE_COUNT_1_BIT,
                    0);

            FixedArray3 <VkDynamicState> dynamicStateEnables = new FixedArray3 <VkDynamicState>(
                VK_DYNAMIC_STATE_VIEWPORT,
                VK_DYNAMIC_STATE_SCISSOR,
                VK_DYNAMIC_STATE_LINE_WIDTH);

            VkPipelineDynamicStateCreateInfo dynamicState =
                Initializers.pipelineDynamicStateCreateInfo(
                    &dynamicStateEnables.First,
                    dynamicStateEnables.Count,
                    0);

            FixedArray2 <VkPipelineShaderStageCreateInfo> shaderStages = new FixedArray2 <VkPipelineShaderStageCreateInfo>();

            VkGraphicsPipelineCreateInfo pipelineCreateInfo =
                Initializers.pipelineCreateInfo(
                    pipelineLayout,
                    renderPass,
                    0);

            var vis = vertices_inputState;

            pipelineCreateInfo.pVertexInputState   = &vis;
            pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
            pipelineCreateInfo.pRasterizationState = &rasterizationState;
            pipelineCreateInfo.pColorBlendState    = &colorBlendState;
            pipelineCreateInfo.pMultisampleState   = &multisampleState;
            pipelineCreateInfo.pViewportState      = &viewportState;
            pipelineCreateInfo.pDepthStencilState  = &depthStencilState;
            pipelineCreateInfo.pDynamicState       = &dynamicState;
            pipelineCreateInfo.stageCount          = shaderStages.Count;
            pipelineCreateInfo.pStages             = &shaderStages.First;

            // Prepare specialization data

            SpecializationData specializationData = SpecializationData.Default;

            // Each shader constant of a shader stage corresponds to one map entry
            FixedArray2 <VkSpecializationMapEntry> specializationMapEntries = new FixedArray2 <VkSpecializationMapEntry>();

            // Shader bindings based on specialization constants are marked by the new "constant_id" layout qualifier:
            //	layout (constant_id = 0) const int LIGHTING_MODEL = 0;
            //	layout (constant_id = 1) const float PARAM_TOON_DESATURATION = 0.0f;

            // Map entry for the lighting model to be used by the fragment shader
            specializationMapEntries.First.constantID = 0;
            specializationMapEntries.First.size       = (UIntPtr)sizeof(uint);
            specializationMapEntries.First.offset     = 0;

            // Map entry for the toon shader parameter
            specializationMapEntries.Second.constantID = 1;
            specializationMapEntries.Second.size       = (UIntPtr)sizeof(float);
            specializationMapEntries.Second.offset     = (sizeof(uint));

            // Prepare specialization info block for the shader stage
            VkSpecializationInfo specializationInfo = new VkSpecializationInfo();

            specializationInfo.dataSize      = (UIntPtr)sizeof(SpecializationData);
            specializationInfo.mapEntryCount = specializationMapEntries.Count;
            specializationInfo.pMapEntries   = &specializationMapEntries.First;
            specializationInfo.pData         = &specializationData;

            // Create pipelines
            // All pipelines will use the same "uber" shader and specialization constants to change branching and parameters of that shader
            shaderStages.First  = loadShader(getAssetPath() + "shaders/specializationconstants/uber.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
            shaderStages.Second = loadShader(getAssetPath() + "shaders/specializationconstants/uber.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
            // Specialization info is assigned is part of the shader stage (modul) and must be set after creating the module and before creating the pipeline
            shaderStages.Second.pSpecializationInfo = &specializationInfo;

            // Solid phong shading
            specializationData.lightingModel = 0;

            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_phong));

            // Phong and textured
            specializationData.lightingModel = 1;

            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_toon));

            // Textured discard
            specializationData.lightingModel = 2;

            Util.CheckResult(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, null, out pipelines_textured));
        }
Example #25
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();

            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.Clockwise;

            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();

            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();
        }
Example #26
0
        private void CreateGraphicsPipeline()
        {
            var vertShaderModule = CreateShaderModule(File.ReadAllBytes("../../Resources/Shaders/vert.spv"));
            var fragShaderModule = CreateShaderModule(File.ReadAllBytes("../../Resources/Shaders/frag.spv"));

            var vertShaderStageInfo = new VkPipelineShaderStageCreateInfo()
            {
                Stage  = VkShaderStage.Vertex,
                Module = vertShaderModule,
                Name   = "main"
            };

            var fragShaderStageInfo = new VkPipelineShaderStageCreateInfo()
            {
                Stage  = VkShaderStage.Fragment,
                Module = fragShaderModule,
                Name   = "main"
            };

            var shaderStages    = new[] { vertShaderStageInfo, fragShaderStageInfo };
            var vertexInputInfo = new VkPipelineVertexInputStateCreateInfo
            {
                VertexBindingDescriptions   = new[] { Vertex.GetBindingDescription(0) },
                VertexAttributeDescriptions = Vertex.GetAttributeDescriptions(0)
            };
            var inputAssemblyInfo = new VkPipelineInputAssemblyStateCreateInfo
            {
                Topology = VkPrimitiveTopology.TriangleList,
                PrimitiveRestartEnable = false
            };
            var viewport = new VkViewport
            {
                X        = 0,
                Y        = 0,
                Width    = swapChainExtent.Width,
                Height   = swapChainExtent.Height,
                MinDepth = 0,
                MaxDepth = 1
            };
            var scissor           = new VkRect2D(new VkOffset2D(0, 0), swapChainExtent);
            var viewportStateInfo = new VkPipelineViewportStateCreateInfo
            {
                Viewports = new [] { viewport },
                Scissors  = new [] { scissor }
            };
            var rasterizerInfo = new VkPipelineRasterizationStateCreateInfo
            {
                DepthClampEnable        = false,
                RasterizerDiscardEnable = false,
                PolygonMode             = VkPolygonMode.Fill,
                LineWidth               = 1f,
                CullMode                = VkCullMode.Back,
                FrontFace               = VkFrontFace.Clockwise,
                DepthBiasEnable         = false,
                DepthBiasConstantFactor = 0f,
                DepthBiasClamp          = 0f,
                DepthBiasSlopeFactor    = 0f
            };
            var multisamplingInfo = new VkPipelineMultisampleStateCreateInfo
            {
                SampleShadingEnable   = false,
                RasterizationSamples  = VkSampleCount.B1,
                MinSampleShading      = 1f,
                SampleMask            = null,
                AlphaToCoverageEnable = false,
                AlphaToOneEnable      = false
            };
            var colorBlendAttachment = new VkPipelineColorBlendAttachmentState
            {
                ColorWriteMask      = VkColorComponent.R | VkColorComponent.G | VkColorComponent.B | VkColorComponent.A,
                BlendEnable         = (VkBool32)false,
                SrcColorBlendFactor = VkBlendFactor.One,
                SrcAlphaBlendFactor = VkBlendFactor.One,
                ColorBlendOp        = VkBlendOp.Add,
                AlphaBlendOp        = VkBlendOp.Add,
                DstColorBlendFactor = VkBlendFactor.Zero,
                DstAlphaBlendFactor = VkBlendFactor.Zero
            };
            var colorBlendingInfo = new VkPipelineColorBlendStateCreateInfo
            {
                LogicOpEnable  = false,
                LogicOp        = VkLogicOp.Copy,
                Attachments    = new[] { colorBlendAttachment },
                BlendConstants = new VkColor4(0, 0, 0, 0)
            };
            var dynamicStates = new[]
            {
                VkDynamicState.Viewport,
                VkDynamicState.LineWidth,
            };
            var dynamicStateInfo = new VkPipelineDynamicStateCreateInfo
            {
                DynamicStates = dynamicStates
            };
            var pipelineLayoutInfo = new VkPipelineLayoutCreateInfo
            {
                SetLayouts         = null,
                PushConstantRanges = null
            };

            pipelineLayout = device.CreatePipelineLayout(pipelineLayoutInfo, null).Object;

            var pipelineInfo = new VkGraphicsPipelineCreateInfo
            {
                Stages             = shaderStages,
                VertexInputState   = vertexInputInfo,
                InputAssemblyState = inputAssemblyInfo,
                TessellationState  = null,
                ViewportState      = viewportStateInfo,
                RasterizationState = rasterizerInfo,
                MultisampleState   = multisamplingInfo,
                DepthStencilState  = null,
                ColorBlendState    = colorBlendingInfo,
                DynamicState       = null,
                Layout             = pipelineLayout,
                RenderPass         = renderPass,
                Subpass            = 0,
                BasePipelineHandle = null,
                BasePipelineIndex  = -1,
                Flags = VkPipelineCreateFlags.None
            };

            graphicsPipeline = device.CreateGraphicsPipelines(null, new[] { pipelineInfo }, null).Object.Single();

            vertShaderModule.Dispose();
            fragShaderModule.Dispose();
        }
Example #27
0
        public VkPipeline(VkGraphicsDevice gd, ref GraphicsPipelineDescription description)
            : base(ref description)
        {
            _gd = gd;
            IsComputePipeline = false;
            RefCount          = new ResourceRefCount(DisposeCore);

            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.compareOp   = VkFormats.VdToVkCompareOp(vdDssDesc.StencilFront.Comparison);
            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.compareOp   = VkFormats.VdToVkCompareOp(vdDssDesc.StencilBack.Comparison);
            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;
            multisampleCI.alphaToCoverageEnable = description.BlendState.AlphaToCoverageEnabled;

            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   = inputElement.Offset != 0 ? inputElement.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

            VkSpecializationInfo specializationInfo;

            SpecializationConstant[] specDescs = description.ShaderSet.Specializations;
            if (specDescs != null)
            {
                uint specDataSize = 0;
                foreach (SpecializationConstant spec in specDescs)
                {
                    specDataSize += VkFormats.GetSpecializationConstantSize(spec.Type);
                }
                byte *fullSpecData                   = stackalloc byte[(int)specDataSize];
                int   specializationCount            = specDescs.Length;
                VkSpecializationMapEntry *mapEntries = stackalloc VkSpecializationMapEntry[specializationCount];
                uint specOffset = 0;
                for (int i = 0; i < specializationCount; i++)
                {
                    ulong data     = specDescs[i].Data;
                    byte *srcData  = (byte *)&data;
                    uint  dataSize = VkFormats.GetSpecializationConstantSize(specDescs[i].Type);
                    Unsafe.CopyBlock(fullSpecData + specOffset, srcData, dataSize);
                    mapEntries[i].constantID = specDescs[i].ID;
                    mapEntries[i].offset     = specOffset;
                    mapEntries[i].size       = (UIntPtr)dataSize;
                    specOffset += dataSize;
                }
                specializationInfo.dataSize      = (UIntPtr)specDataSize;
                specializationInfo.pData         = fullSpecData;
                specializationInfo.mapEntryCount = (uint)specializationCount;
                specializationInfo.pMapEntries   = mapEntries;
            }

            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
                stageCI.pName = new FixedUtf8String(shader.EntryPoint); // TODO: DONT ALLOCATE HERE
                stageCI.pSpecializationInfo = &specializationInfo;
                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;

            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;
            DynamicOffsetsCount = 0;
            foreach (VkResourceLayout layout in description.ResourceLayouts)
            {
                DynamicOffsetsCount += layout.DynamicBufferCount;
            }
        }
Example #28
0
        void CreateGraphicsPipeline()
        {
            VkShaderModule vert = CreateShaderModule(File.ReadAllBytes("vert.spv"));
            VkShaderModule frag = CreateShaderModule(File.ReadAllBytes("frag.spv"));

            InteropString entry = new InteropString("main");

            var vertInfo = new VkPipelineShaderStageCreateInfo();

            vertInfo.sType  = CSGL.Vulkan.VkStructureType.PipelineShaderStageCreateInfo;
            vertInfo.stage  = CSGL.Vulkan.VkShaderStageFlags.VertexBit;
            vertInfo.module = vert;
            vertInfo.pName  = entry.Address;

            var fragInfo = new VkPipelineShaderStageCreateInfo();

            fragInfo.sType  = CSGL.Vulkan.VkStructureType.PipelineShaderStageCreateInfo;
            fragInfo.stage  = CSGL.Vulkan.VkShaderStageFlags.FragmentBit;
            fragInfo.module = frag;
            fragInfo.pName  = entry.Address;

            var shaderStages = new NativeArray <VkPipelineShaderStageCreateInfo>(2);

            shaderStages[0] = vertInfo;
            shaderStages[1] = fragInfo;

            var vertexInputInfo = new VkPipelineVertexInputStateCreateInfo();

            vertexInputInfo.sType = CSGL.Vulkan.VkStructureType.PipelineVertexInputStateCreateInfo;

            var vertexInputNative = new Native <VkPipelineVertexInputStateCreateInfo>(vertexInputInfo);

            var inputAssembly = new VkPipelineInputAssemblyStateCreateInfo();

            inputAssembly.sType    = CSGL.Vulkan.VkStructureType.PipelineInputAssemblyStateCreateInfo;
            inputAssembly.topology = CSGL.Vulkan.VkPrimitiveTopology.TriangleList;

            var inputAssemblyNative = new Native <VkPipelineInputAssemblyStateCreateInfo>(inputAssembly);

            var viewport = new VkViewport();

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

            var viewportNative = new Native <VkViewport>(viewport);

            var scissor = new VkRect2D();

            scissor.extent = swapchainExtent;

            var scissorNative = new Native <VkRect2D>(scissor);

            var viewportState = new VkPipelineViewportStateCreateInfo();

            viewportState.sType         = CSGL.Vulkan.VkStructureType.PipelineViewportStateCreateInfo;
            viewportState.viewportCount = 1;
            viewportState.pViewports    = viewportNative.Address;
            viewportState.scissorCount  = 1;
            viewportState.pScissors     = scissorNative.Address;

            var viewportStateNative = new Native <VkPipelineViewportStateCreateInfo>(viewportState);

            var rasterizer = new VkPipelineRasterizationStateCreateInfo();

            rasterizer.sType       = CSGL.Vulkan.VkStructureType.PipelineRasterizationStateCreateInfo;
            rasterizer.polygonMode = CSGL.Vulkan.VkPolygonMode.Fill;
            rasterizer.lineWidth   = 1f;
            rasterizer.cullMode    = CSGL.Vulkan.VkCullModeFlags.BackBit;
            rasterizer.frontFace   = CSGL.Vulkan.VkFrontFace.Clockwise;

            var rasterizerNative = new Native <VkPipelineRasterizationStateCreateInfo>(rasterizer);

            var multisampling = new VkPipelineMultisampleStateCreateInfo();

            multisampling.sType = CSGL.Vulkan.VkStructureType.PipelineMultisampleStateCreateInfo;
            multisampling.rasterizationSamples = CSGL.Vulkan.VkSampleCountFlags._1_Bit;
            multisampling.minSampleShading     = 1f;

            var multisamplingNative = new Native <VkPipelineMultisampleStateCreateInfo>(multisampling);

            var colorBlendAttachment = new VkPipelineColorBlendAttachmentState();

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

            var colorBlendAttachmentNative = new Native <VkPipelineColorBlendAttachmentState>(colorBlendAttachment);

            var colorBlending = new VkPipelineColorBlendStateCreateInfo();

            colorBlending.sType           = CSGL.Vulkan.VkStructureType.PipelineColorBlendStateCreateInfo;
            colorBlending.logicOp         = CSGL.Vulkan.VkLogicOp.Copy;
            colorBlending.attachmentCount = 1;
            colorBlending.pAttachments    = colorBlendAttachmentNative.Address;

            var colorBlendingNative = new Native <VkPipelineColorBlendStateCreateInfo>(colorBlending);

            var pipelineLayoutInfo = new VkPipelineLayoutCreateInfo();

            pipelineLayoutInfo.sType = CSGL.Vulkan.VkStructureType.PipelineLayoutCreateInfo;

            if (pipelineLayout != VkPipelineLayout.Null)
            {
                VK.DestroyPipelineLayout(device, pipelineLayout, alloc);
            }
            var result = VK.CreatePipelineLayout(device, ref pipelineLayoutInfo, alloc, out pipelineLayout);

            var info = new VkGraphicsPipelineCreateInfo();

            info.sType               = CSGL.Vulkan.VkStructureType.GraphicsPipelineCreateInfo;
            info.stageCount          = 2;
            info.pStages             = shaderStages.Address;
            info.pVertexInputState   = vertexInputNative.Address;
            info.pInputAssemblyState = inputAssemblyNative.Address;
            info.pViewportState      = viewportStateNative.Address;
            info.pRasterizationState = rasterizerNative.Address;
            info.pMultisampleState   = multisamplingNative.Address;
            info.pColorBlendState    = colorBlendingNative.Address;
            info.layout              = pipelineLayout;
            info.renderPass          = renderPass;
            info.subpass             = 0;
            info.basePipelineHandle  = VkPipeline.Null;
            info.basePipelineIndex   = -1;

            var infoNative = new Native <VkGraphicsPipelineCreateInfo>(info);
            var temp       = new Native <VkPipeline>();

            if (pipeline != VkPipeline.Null)
            {
                VK.DestroyPipeline(device, pipeline, alloc);
            }

            result   = VK.CreateGraphicsPipelines(device, VkPipelineCache.Null, 1, infoNative.Address, alloc, temp.Address);
            pipeline = temp.Value;

            infoNative.Dispose();
            temp.Dispose();

            entry.Dispose();
            shaderStages.Dispose();
            vertexInputNative.Dispose();
            inputAssemblyNative.Dispose();
            viewportNative.Dispose();
            scissorNative.Dispose();
            viewportStateNative.Dispose();
            rasterizerNative.Dispose();
            multisamplingNative.Dispose();
            colorBlendingNative.Dispose();
            colorBlendAttachmentNative.Dispose();
            VK.DestroyShaderModule(device, vert, alloc);
            VK.DestroyShaderModule(device, frag, alloc);
        }
Example #29
0
        VkPipeline CreatePipeline(VkDevice device, VkSurfaceCapabilitiesKHR surfaceCapabilities,
                                  VkRenderPass renderPass, VkPipelineLayout pipelineLayout)
        {
            //VkShaderModule vertexShaderModule = device.CreateShaderModule(LoadResource(@"Shaders\shader.vert.spv"));
            VkShaderModule vsModule;
            {
                var info = new VkShaderModuleCreateInfo {
                    sType = VkStructureType.ShaderModuleCreateInfo
                };
                byte[] bytes = LoadResource(@"Shaders\shader.vert.spv");
                info.code = bytes;
                //vkAPI.vkCreateShaderModule(device, bytes);
                vkAPI.vkCreateShaderModule(device, &info, null, &vsModule).Check();
                info.Free();
            }
            //VkShaderModule fragmentShaderModule = device.CreateShaderModule(LoadResource(@"Shaders\shader.frag.spv"));
            VkShaderModule fsModule;
            {
                var info = new VkShaderModuleCreateInfo {
                    sType = VkStructureType.ShaderModuleCreateInfo
                };
                byte[] bytes = LoadResource(@"Shaders\shader.frag.spv");
                info.code = bytes;
                //vkAPI.vkCreateShaderModule(device, bytes);
                vkAPI.vkCreateShaderModule(device, &info, null, &fsModule).Check();
                info.Free();
            }
            var shaderStages = new VkPipelineShaderStageCreateInfo[2];
            {
                shaderStages[0].sType  = VkStructureType.PipelineShaderStageCreateInfo;
                shaderStages[0].stage  = VkShaderStageFlagBits.Vertex;
                shaderStages[0].module = vsModule;
                //"main".Set(ref shaderStages[0].pName);
                shaderStages[0].pName  = "main";
                shaderStages[1].sType  = VkStructureType.PipelineShaderStageCreateInfo;
                shaderStages[1].stage  = VkShaderStageFlagBits.Fragment;
                shaderStages[1].module = fsModule;
                //"main".Set(ref shaderStages[1].pName);
                shaderStages[1].pName = "main";
            }
            var viewport = new VkPipelineViewportStateCreateInfo {
                sType = VkStructureType.PipelineViewportStateCreateInfo
            };

            viewport.viewports = new VkViewport(surfaceCapabilities.currentExtent, 0.0f, 1.0f);
            viewport.scissors  = new VkRect2D(surfaceCapabilities.currentExtent);

            var multisample = new VkPipelineMultisampleStateCreateInfo {
                sType = VkStructureType.PipelineMultisampleStateCreateInfo
            };

            multisample.rasterizationSamples = VkSampleCountFlagBits._1;

            var colorBlend = new VkPipelineColorBlendStateCreateInfo {
                sType = VkStructureType.PipelineColorBlendStateCreateInfo
            };

            colorBlend.logicOp = VkLogicOp.Copy;
            var blend = new VkPipelineColorBlendAttachmentState(
                colorWriteMask: VkColorComponentFlagBits.R | VkColorComponentFlagBits.G
                | VkColorComponentFlagBits.B | VkColorComponentFlagBits.A,
                blendEnable: false);

            colorBlend.attachments = blend;

            var rasterization = new VkPipelineRasterizationStateCreateInfo {
                sType = VkStructureType.PipelineRasterizationStateCreateInfo
            };

            rasterization.polygonMode = VkPolygonMode.Fill;
            rasterization.cullMode    = VkCullModeFlagBits.None;
            rasterization.frontFace   = VkFrontFace.Clockwise;
            rasterization.lineWidth   = 1.0f;

            var inputAssem = new VkPipelineInputAssemblyStateCreateInfo {
                sType = VkStructureType.PipelineInputAssemblyStateCreateInfo
            };

            inputAssem.topology = VkPrimitiveTopology.TriangleList;

            var input = new VkPipelineVertexInputStateCreateInfo {
                sType = VkStructureType.PipelineVertexInputStateCreateInfo
            };

            // static readonly float[] Vertices = { .. }
            input.vertexBindingDescriptions = new VkVertexInputBindingDescription(
                binding: 0,
                stride: 2 * sizeof(float),
                inputRate: VkVertexInputRate.Vertex);
            // layout(location = 0) in vec2 inPos;
            input.vertexAttributeDescriptions = new VkVertexInputAttributeDescription(
                location: 0,
                binding: 0,
                format: VkFormat.R32g32Sfloat,
                offset: 0);

            //VkPipelineCache cache = device.CreatePipelineCache(ref cacheInfo);
            VkPipelineCache cache;
            {
                var info = VkPipelineCacheCreateInfo.Alloc();
                vkAPI.vkCreatePipelineCache(device, info, null, &cache).Check();
                Marshal.FreeHGlobal((IntPtr)info);
            }
            //var infos = new VkGraphicsPipelineCreateInfo[] { pipelineCreateInfo };
            //return device.CreateGraphicsPipelines(ref cache, infos);
            VkPipeline pipeline;

            {
                var info = new VkGraphicsPipelineCreateInfo {
                    sType = VkStructureType.GraphicsPipelineCreateInfo
                };
                info.layout              = pipelineLayout;
                info.pViewportState      = &viewport;
                info.stages              = shaderStages;
                info.pMultisampleState   = &multisample;
                info.pColorBlendState    = &colorBlend;
                info.pRasterizationState = &rasterization;
                info.pInputAssemblyState = &inputAssem;
                info.pVertexInputState   = &input;
                info.renderPass          = renderPass;
                vkAPI.vkCreateGraphicsPipelines(device, cache, 1, &info, null, &pipeline).Check();
                info.Free();
            }

            shaderStages[0].Free();
            shaderStages[1].Free();
            viewport.Free();
            colorBlend.Free();
            input.Free();

            return(pipeline);
        }
        public void Build(int deviceIndex)
        {
            if (!locked)
            {
                unsafe
                {
                    //create pipeline shader stages
                    var shaderStages                   = new VkPipelineShaderStageCreateInfo[Shaders.Length];
                    var shaderSpecializations          = new ManagedPtr <VkSpecializationInfo> [Shaders.Length];
                    var shaderSpecializationBufferPtrs = new MemoryHandle[Shaders.Length];
                    for (int i = 0; i < shaderStages.Length; i++)
                    {
                        if (SpecializationData != null)
                        {
                            shaderSpecializationBufferPtrs[i] = SpecializationData[i].Pin();

                            shaderSpecializations[i] = new VkSpecializationInfo()
                            {
                                mapEntryCount = (uint)SpecializationData[i].Length,
                                pMapEntries   = Shaders[i].Specialize(),
                                dataSize      = (uint)SpecializationData[i].Length * sizeof(int),
                                pData         = (IntPtr)shaderSpecializationBufferPtrs[i].Pointer
                            }.Pointer();
                        }

                        shaderStages[i].sType  = VkStructureType.StructureTypePipelineShaderStageCreateInfo;
                        shaderStages[i].stage  = (VkShaderStageFlags)Shaders[i].ShaderType;
                        shaderStages[i].module = Shaders[i].ids[deviceIndex];
                        shaderStages[i].pName  = "main";
                        shaderStages[i].pSpecializationInfo = shaderSpecializations[i] != null ? shaderSpecializations[i] : IntPtr.Zero;
                    }
                    var shaderStages_ptr = shaderStages.Pointer();

                    //VkPipelineVertexInputStateCreateInfo - dummy, engine doesn't support fix function vertex input
                    var vertexInputInfo = new VkPipelineVertexInputStateCreateInfo()
                    {
                        sType = VkStructureType.StructureTypePipelineVertexInputStateCreateInfo,
                        vertexBindingDescriptionCount   = 0,
                        vertexAttributeDescriptionCount = 0,
                    };
                    var vertexInputInfo_ptr = vertexInputInfo.Pointer();

                    //VkPipelineInputAssemblyStateCreateInfo - state
                    var inputAssembly = new VkPipelineInputAssemblyStateCreateInfo()
                    {
                        sType    = VkStructureType.StructureTypePipelineInputAssemblyStateCreateInfo,
                        topology = (VkPrimitiveTopology)Topology,
                        primitiveRestartEnable = false,
                    };
                    var inputAssembly_ptr = inputAssembly.Pointer();

                    //VkPipelineViewportStateCreateInfo - dynamic state, no scissor
                    var viewport = new VkViewport()
                    {
                        x        = ViewportX,
                        y        = ViewportY,
                        width    = ViewportWidth,
                        height   = ViewportHeight,
                        minDepth = ViewportMinDepth,
                        maxDepth = ViewportMaxDepth,
                    };

                    var scissor = new VkRect2D()
                    {
                        offset = new VkOffset2D()
                        {
                            x = (int)ViewportX,
                            y = (int)ViewportY
                        },
                        extent = new VkExtent2D()
                        {
                            width  = ViewportWidth,
                            height = ViewportHeight
                        }
                    };

                    var viewport_ptr       = viewport.Pointer();
                    var scissor_ptr        = scissor.Pointer();
                    var viewportCreateInfo = new VkPipelineViewportStateCreateInfo()
                    {
                        sType         = VkStructureType.StructureTypePipelineViewportStateCreateInfo,
                        viewportCount = 1,
                        pViewports    = viewport_ptr,
                        scissorCount  = 1,
                        pScissors     = scissor_ptr
                    };
                    var viewportCreateInfo_ptr = viewportCreateInfo.Pointer();

                    //VkPipelineRasterizationStateCreateInfo - state
                    var rasterizer = new VkPipelineRasterizationStateCreateInfo()
                    {
                        sType                   = VkStructureType.StructureTypePipelineRasterizationStateCreateInfo,
                        depthClampEnable        = DepthClamp,
                        rasterizerDiscardEnable = RasterizerDiscard,
                        polygonMode             = (VkPolygonMode)Fill,
                        lineWidth               = LineWidth,
                        cullMode                = (VkCullModeFlags)CullMode,
                        frontFace               = VkFrontFace.FrontFaceCounterClockwise, //OpenGL default
                        depthBiasEnable         = false,
                        depthBiasConstantFactor = 0,
                        depthBiasClamp          = 0,
                        depthBiasSlopeFactor    = 0,
                    };
                    var rasterizer_ptr = rasterizer.Pointer();

                    //VkPipelineMultisampleStateCreateInfo - don't support for now
                    var multisampling = new VkPipelineMultisampleStateCreateInfo()
                    {
                        sType = VkStructureType.StructureTypePipelineMultisampleStateCreateInfo,
                        sampleShadingEnable   = false,
                        rasterizationSamples  = VkSampleCountFlags.SampleCount1Bit,
                        minSampleShading      = 1,
                        pSampleMask           = null,
                        alphaToCoverageEnable = false,
                        alphaToOneEnable      = false
                    };
                    var multisampling_ptr = multisampling.Pointer();

                    //VkPipelineDepthStencilStateCreateInfo - state
                    var depthStencil = new VkPipelineDepthStencilStateCreateInfo()
                    {
                        sType                 = VkStructureType.StructureTypePipelineDepthStencilStateCreateInfo,
                        depthTestEnable       = true,
                        depthCompareOp        = (VkCompareOp)DepthTest,
                        depthWriteEnable      = DepthWrite,
                        depthBoundsTestEnable = false,
                        stencilTestEnable     = false,
                        maxDepthBounds        = ViewportMaxDepth,
                        minDepthBounds        = ViewportMinDepth,
                    };
                    var depthStencil_ptr = depthStencil.Pointer();


                    //VkPipelineColorBlendStateCreateInfo - state
                    var colorBlendStates = new VkPipelineColorBlendAttachmentState[RenderPass.ColorAttachments == null ? 0 : RenderPass.ColorAttachments.Length];
                    for (int i = 0; i < colorBlendStates.Length; i++)
                    {
                        colorBlendStates[i] = new VkPipelineColorBlendAttachmentState()
                        {
                            colorWriteMask = VkColorComponentFlags.ColorComponentRBit | VkColorComponentFlags.ColorComponentGBit | VkColorComponentFlags.ColorComponentBBit | VkColorComponentFlags.ColorComponentABit,
                            blendEnable    = false,
                        };
                    }
                    var colorBlendStates_ptr = colorBlendStates.Pointer();

                    var colorBlend = new VkPipelineColorBlendStateCreateInfo()
                    {
                        sType           = VkStructureType.StructureTypePipelineColorBlendStateCreateInfo,
                        logicOpEnable   = false,
                        logicOp         = VkLogicOp.LogicOpCopy,
                        attachmentCount = (uint)colorBlendStates.Length,
                        pAttachments    = colorBlendStates_ptr,
                    };
                    colorBlend.blendConstants[0] = 0;
                    colorBlend.blendConstants[1] = 0;
                    colorBlend.blendConstants[2] = 0;
                    colorBlend.blendConstants[3] = 0;
                    var colorBlend_ptr = colorBlend.Pointer();

                    var dynamicStates = stackalloc VkDynamicState[]
                    {
                        VkDynamicState.DynamicStateViewport
                    };

                    var dynamicState = new VkPipelineDynamicStateCreateInfo()
                    {
                        sType             = VkStructureType.StructureTypePipelineDynamicStateCreateInfo,
                        dynamicStateCount = ViewportDynamic ? 1u : 0u,
                        pDynamicStates    = dynamicStates
                    };
                    var dynamicState_ptr = dynamicState.Pointer();

                    //Setup graphics pipeline
                    var pipelineInfo = new VkGraphicsPipelineCreateInfo()
                    {
                        sType               = VkStructureType.StructureTypeGraphicsPipelineCreateInfo,
                        stageCount          = (uint)shaderStages.Length,
                        pStages             = shaderStages_ptr,
                        pVertexInputState   = vertexInputInfo_ptr,
                        pInputAssemblyState = inputAssembly_ptr,
                        pViewportState      = viewportCreateInfo_ptr,
                        pRasterizationState = rasterizer_ptr,
                        pMultisampleState   = multisampling_ptr,
                        pDepthStencilState  = depthStencil_ptr,
                        pColorBlendState    = colorBlend_ptr,
                        pDynamicState       = dynamicState_ptr,
                        layout              = PipelineLayout.hndl,
                        renderPass          = RenderPass.hndl,
                        subpass             = 0,
                        basePipelineHandle  = IntPtr.Zero,
                        basePipelineIndex   = -1,
                    };

                    IntPtr pipeline_l = IntPtr.Zero;
                    if (vkCreateGraphicsPipelines(GraphicsDevice.GetDeviceInfo(deviceIndex).Device, IntPtr.Zero, 1, pipelineInfo.Pointer(), null, &pipeline_l) != VkResult.Success)
                    {
                        throw new Exception("Failed to create graphics pipeline.");
                    }
                    hndl = pipeline_l;

                    if (GraphicsDevice.EnableValidation)
                    {
                        var objName = new VkDebugUtilsObjectNameInfoEXT()
                        {
                            sType        = VkStructureType.StructureTypeDebugUtilsObjectNameInfoExt,
                            pObjectName  = Name,
                            objectType   = VkObjectType.ObjectTypePipeline,
                            objectHandle = (ulong)hndl
                        };
                        GraphicsDevice.SetDebugUtilsObjectNameEXT(GraphicsDevice.GetDeviceInfo(deviceIndex).Device, objName.Pointer());
                    }

                    devID  = deviceIndex;
                    locked = true;
                }
            }
            else
            {
                throw new Exception("Pipeline is locked.");
            }
        }