private Pipeline CreateGraphicsPipeline()
        {
            ShaderModule vertexShader           = Content.Load <ShaderModule>("Shader.vert.spv");
            ShaderModule fragmentShader         = Content.Load <ShaderModule>("Shader.frag.spv");
            var          shaderStageCreateInfos = new[]
            {
                new PipelineShaderStageCreateInfo(ShaderStages.Vertex, vertexShader, "main"),
                new PipelineShaderStageCreateInfo(ShaderStages.Fragment, fragmentShader, "main")
            };

            var vertexInputStateCreateInfo   = new PipelineVertexInputStateCreateInfo();
            var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo(PrimitiveTopology.TriangleList);
            var viewportStateCreateInfo      = new PipelineViewportStateCreateInfo(
                new Viewport(0, 0, Host.Width, Host.Height),
                new Rect2D(0, 0, Host.Width, Host.Height));
            var rasterizationStateCreateInfo = new PipelineRasterizationStateCreateInfo
            {
                PolygonMode = PolygonMode.Fill,
                CullMode    = CullModes.Back,
                FrontFace   = FrontFace.CounterClockwise,
                LineWidth   = 1.0f
            };
            var multisampleStateCreateInfo = new PipelineMultisampleStateCreateInfo
            {
                RasterizationSamples = SampleCounts.Count1,
                MinSampleShading     = 1.0f
            };
            var colorBlendAttachmentState = new PipelineColorBlendAttachmentState
            {
                SrcColorBlendFactor = BlendFactor.One,
                DstColorBlendFactor = BlendFactor.Zero,
                ColorBlendOp        = BlendOp.Add,
                SrcAlphaBlendFactor = BlendFactor.One,
                DstAlphaBlendFactor = BlendFactor.Zero,
                AlphaBlendOp        = BlendOp.Add,
                ColorWriteMask      = ColorComponents.All
            };
            var colorBlendStateCreateInfo = new PipelineColorBlendStateCreateInfo(
                new[] { colorBlendAttachmentState });

            var pipelineCreateInfo = new GraphicsPipelineCreateInfo(
                _pipelineLayout, _renderPass, 0,
                shaderStageCreateInfos,
                inputAssemblyStateCreateInfo,
                vertexInputStateCreateInfo,
                rasterizationStateCreateInfo,
                viewportState: viewportStateCreateInfo,
                multisampleState: multisampleStateCreateInfo,
                colorBlendState: colorBlendStateCreateInfo);

            return(Context.Device.CreateGraphicsPipeline(pipelineCreateInfo));
        }
Beispiel #2
0
        private unsafe Pipeline(PipelineSettings settings, VulkanRenderer renderer)
        {
            _renderer = renderer;

            Device device = _renderer.Params.Device;
            AllocationCallbacks *allocator = (AllocationCallbacks *)_renderer.Params.AllocationCallbacks.ToPointer();
            Vk vk = _renderer.Vk;

            PipelineShaderStageCreateInfo *shaderStages = stackalloc PipelineShaderStageCreateInfo[2]
            {
                _renderer.Shader.VertexShaderStage,
                _renderer.Shader.FragmentShaderStage
            };
            PipelineVertexInputStateCreateInfo   vertexInputState           = VertexInputState(_bindingDescription, _attributeDescriptions);
            PipelineInputAssemblyStateCreateInfo inputAssemblyState         = InputAssemblyState(settings);
            PipelineRasterizationStateCreateInfo rasterizationState         = RasterizationState(settings);
            PipelineMultisampleStateCreateInfo   multisampleState           = MultisampleState();
            PipelineColorBlendAttachmentState    colourBlendAttachmentState = ColorBlendAttachmentState(settings);
            PipelineColorBlendStateCreateInfo    colourBlendState           = ColourBlendState(colourBlendAttachmentState);
            PipelineViewportStateCreateInfo      viewportState     = ViewportState();
            PipelineDynamicStateCreateInfo       dynamicState      = DynamicStates(DynamicState.Viewport, DynamicState.Scissor);
            PipelineDepthStencilStateCreateInfo  depthStencilState = DepthStencilState(settings);

            GraphicsPipelineCreateInfo pipelineCreateInfo = new()
            {
                SType = StructureType.GraphicsPipelineCreateInfo,

                StageCount = 2,
                PStages    = shaderStages,

                PVertexInputState   = &vertexInputState,
                PInputAssemblyState = &inputAssemblyState,
                PRasterizationState = &rasterizationState,
                PMultisampleState   = &multisampleState,
                PColorBlendState    = &colourBlendState,
                PViewportState      = &viewportState,
                PDynamicState       = &dynamicState,
                PDepthStencilState  = &depthStencilState,
                PTessellationState  = null,

                Layout = _renderer.Shader.PipelineLayout,

                RenderPass = _renderer.Params.RenderPass,
                Subpass    = _renderer.Params.SubpassIndex,

                BasePipelineIndex  = -1,
                BasePipelineHandle = default
            };

            _renderer.AssertVulkan(vk.CreateGraphicsPipelines(device, default, 1, pipelineCreateInfo, allocator, out _handle));
        private 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 = Interop.Fixed(defaultEntryPoint);
            var   stages = CreateShaderStages(Description, out inputAttributeNames);

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

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

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

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

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

                inputBindings[slotIndex].Binding   = (uint)slotIndex;
                inputBindings[slotIndex].InputRate = inputElement.InputSlotClass == InputClassification.Vertex ? VertexInputRate.Vertex : VertexInputRate.Instance;

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

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

            var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo
            {
                StructureType          = StructureType.PipelineInputAssemblyStateCreateInfo,
                Topology               = VulkanConvertExtensions.ConvertPrimitiveType(Description.PrimitiveType),
                PrimitiveRestartEnable = VulkanConvertExtensions.ConvertPrimitiveRestart(Description.PrimitiveType),
            };

            // TODO VULKAN: Tessellation and multisampling
            var multisampleState = new PipelineMultisampleStateCreateInfo
            {
                StructureType        = StructureType.PipelineMultisampleStateCreateInfo,
                RasterizationSamples = SampleCountFlags.Sample1
            };

            var tessellationState = new PipelineTessellationStateCreateInfo();

            var rasterizationState = CreateRasterizationState(Description.RasterizerState);

            var depthStencilState = CreateDepthStencilState(Description);

            var description = Description.BlendState;

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

            var renderTargetBlendState = &description.RenderTarget0;

            for (int i = 0; i < renderTargetCount; i++)
            {
                colorBlendAttachments[i] = new PipelineColorBlendAttachmentState
                {
                    BlendEnable                 = renderTargetBlendState->BlendEnable,
                    AlphaBlendOperation         = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->AlphaBlendFunction),
                    ColorBlendOperation         = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->ColorBlendFunction),
                    DestinationAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaDestinationBlend),
                    DestinationColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorDestinationBlend),
                    SourceAlphaBlendFactor      = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaSourceBlend),
                    SourceColorBlendFactor      = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorSourceBlend),
                    ColorWriteMask              = VulkanConvertExtensions.ConvertColorWriteChannels(renderTargetBlendState->ColorWriteChannels),
                };

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

            var viewportState = new PipelineViewportStateCreateInfo
            {
                StructureType = StructureType.PipelineViewportStateCreateInfo,
                ScissorCount  = 1,
                ViewportCount = 1,
            };

            fixed(DynamicState *dynamicStatesPointer = &dynamicStates[0])
            {
                var vertexInputState = new PipelineVertexInputStateCreateInfo
                {
                    StructureType = StructureType.PipelineVertexInputStateCreateInfo,
                    VertexAttributeDescriptionCount = (uint)inputAttributeCount,
                    VertexAttributeDescriptions     = inputAttributes.Length > 0 ? new IntPtr(Interop.Fixed(inputAttributes)) : IntPtr.Zero,
                    VertexBindingDescriptionCount   = (uint)inputBindingCount,
                    VertexBindingDescriptions       = inputBindings.Length > 0 ? new IntPtr(Interop.Fixed(inputBindings)) : IntPtr.Zero,
                };

                var colorBlendState = new PipelineColorBlendStateCreateInfo
                {
                    StructureType   = StructureType.PipelineColorBlendStateCreateInfo,
                    AttachmentCount = (uint)renderTargetCount,
                    Attachments     = colorBlendAttachments.Length > 0 ? new IntPtr(Interop.Fixed(colorBlendAttachments)) : IntPtr.Zero,
                };

                var dynamicState = new PipelineDynamicStateCreateInfo
                {
                    StructureType     = StructureType.PipelineDynamicStateCreateInfo,
                    DynamicStateCount = (uint)dynamicStates.Length,
                    DynamicStates     = new IntPtr(dynamicStatesPointer)
                };

                var createInfo = new GraphicsPipelineCreateInfo
                {
                    StructureType = StructureType.GraphicsPipelineCreateInfo,
                    Layout        = NativeLayout,
                    StageCount    = (uint)stages.Length,
                    Stages        = stages.Length > 0 ? new IntPtr(Interop.Fixed(stages)) : IntPtr.Zero,
                    //TessellationState = new IntPtr(&tessellationState),
                    VertexInputState   = new IntPtr(&vertexInputState),
                    InputAssemblyState = new IntPtr(&inputAssemblyState),
                    RasterizationState = new IntPtr(&rasterizationState),
                    MultisampleState   = new IntPtr(&multisampleState),
                    DepthStencilState  = new IntPtr(&depthStencilState),
                    ColorBlendState    = new IntPtr(&colorBlendState),
                    DynamicState       = new IntPtr(&dynamicState),
                    ViewportState      = new IntPtr(&viewportState),
                    RenderPass         = NativeRenderPass,
                    Subpass            = 0,
                };

                NativePipeline = GraphicsDevice.NativeDevice.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo);
            }

            // Cleanup shader modules
            foreach (var stage in stages)
            {
                GraphicsDevice.NativeDevice.DestroyShaderModule(stage.Module);
            }
        }
Beispiel #4
0
        private unsafe void Recreate()
        {
            errorDuringCreate = false;

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

            PipelineShaderStageCreateInfo[] stages;

            // try to recover from a rare failure?
            bool retry = false;

            // it appears pipeline creation is just not thread safe :(
            lock (PipeLock) {
                Xenko.Shaders.Compiler.EffectCompilerCache.CompileSynchronization.Wait();

                CreateRenderPass(Description);

                CreatePipelineLayout(Description);

                // Create shader stages
                Dictionary <int, string> inputAttributeNames;
                stages = CreateShaderStages(Description, out inputAttributeNames);

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

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

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

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

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

                    inputBindings[slotIndex].Binding   = (uint)slotIndex;
                    inputBindings[slotIndex].InputRate = inputElement.InputSlotClass == InputClassification.Vertex ? VertexInputRate.Vertex : VertexInputRate.Instance;

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

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

                var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo
                {
                    StructureType          = StructureType.PipelineInputAssemblyStateCreateInfo,
                    Topology               = VulkanConvertExtensions.ConvertPrimitiveType(Description.PrimitiveType),
                    PrimitiveRestartEnable = true,
                };

                // TODO VULKAN: Tessellation and multisampling
                var multisampleState = new PipelineMultisampleStateCreateInfo
                {
                    StructureType        = StructureType.PipelineMultisampleStateCreateInfo,
                    RasterizationSamples = SampleCountFlags.Sample1
                };

                //var tessellationState = new PipelineTessellationStateCreateInfo();

                var rasterizationState = CreateRasterizationState(Description.RasterizerState);

                var depthStencilState = CreateDepthStencilState(Description);

                var description = Description.BlendState;

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

                var renderTargetBlendState = &description.RenderTarget0;
                for (int i = 0; i < renderTargetCount; i++)
                {
                    colorBlendAttachments[i] = new PipelineColorBlendAttachmentState
                    {
                        BlendEnable                 = renderTargetBlendState->BlendEnable,
                        AlphaBlendOperation         = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->AlphaBlendFunction),
                        ColorBlendOperation         = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->ColorBlendFunction),
                        DestinationAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaDestinationBlend),
                        DestinationColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorDestinationBlend),
                        SourceAlphaBlendFactor      = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaSourceBlend),
                        SourceColorBlendFactor      = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorSourceBlend),
                        ColorWriteMask              = VulkanConvertExtensions.ConvertColorWriteChannels(renderTargetBlendState->ColorWriteChannels),
                    };

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

                var viewportState = new PipelineViewportStateCreateInfo
                {
                    StructureType = StructureType.PipelineViewportStateCreateInfo,
                    ScissorCount  = 1,
                    ViewportCount = 1,
                };

                fixed(void *dynamicStatesPointer   = dynamicStates.Length == 0?null : dynamicStates,
                      inputAttributesPointer       = inputAttributes.Length == 0?null : inputAttributes,
                      inputBindingsPointer         = inputBindings.Length == 0?null : inputBindings,
                      colorBlendAttachmentsPointer = colorBlendAttachments.Length == 0?null : colorBlendAttachments,
                      stagesPointer = stages.Length == 0?null : stages)
                {
                    var vertexInputState = new PipelineVertexInputStateCreateInfo
                    {
                        StructureType = StructureType.PipelineVertexInputStateCreateInfo,
                        VertexAttributeDescriptionCount = (uint)inputAttributeCount,
                        VertexAttributeDescriptions     = (IntPtr)inputAttributesPointer,
                        VertexBindingDescriptionCount   = (uint)inputBindingCount,
                        VertexBindingDescriptions       = (IntPtr)inputBindingsPointer,
                    };

                    var colorBlendState = new PipelineColorBlendStateCreateInfo
                    {
                        StructureType   = StructureType.PipelineColorBlendStateCreateInfo,
                        AttachmentCount = (uint)renderTargetCount,
                        Attachments     = (IntPtr)colorBlendAttachmentsPointer,
                    };

                    var dynamicState = new PipelineDynamicStateCreateInfo
                    {
                        StructureType     = StructureType.PipelineDynamicStateCreateInfo,
                        DynamicStateCount = (uint)dynamicStates.Length,
                        DynamicStates     = (IntPtr)dynamicStatesPointer,
                    };

                    var createInfo = new GraphicsPipelineCreateInfo
                    {
                        StructureType = StructureType.GraphicsPipelineCreateInfo,
                        Layout        = NativeLayout,
                        StageCount    = (uint)stages.Length,
                        Stages        = (IntPtr)stagesPointer,
                        //TessellationState = new IntPtr(&tessellationState),
                        VertexInputState   = new IntPtr(&vertexInputState),
                        InputAssemblyState = new IntPtr(&inputAssemblyState),
                        RasterizationState = new IntPtr(&rasterizationState),
                        MultisampleState   = new IntPtr(&multisampleState),
                        DepthStencilState  = new IntPtr(&depthStencilState),
                        ColorBlendState    = new IntPtr(&colorBlendState),
                        DynamicState       = new IntPtr(&dynamicState),
                        ViewportState      = new IntPtr(&viewportState),
                        RenderPass         = NativeRenderPass,
                        Subpass            = 0,
                    };

                    try {
                        lock (GraphicsDevice.QueueLock) {
                            NativePipeline = GraphicsDevice.NativeDevice.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo);
                        }
                    } catch (AccessViolationException ae) {
                        // this happens extremely rarely and might be recoverable by reattempting the recreate
                        retry = true;
                    } catch (Exception e) {
                        errorDuringCreate = true;
                        NativePipeline    = Pipeline.Null;
                    }
                }
            }

            // Cleanup shader modules
            for (int i = 0; i < stages.Length; i++)
            {
                GraphicsDevice.NativeDevice.DestroyShaderModule(stages[i].Module);
            }

            if (retry)
            {
                Recreate();
            }
        }
Beispiel #5
0
        private void CreatePipeline()
        {
            var dynamicStates = new [] { DynamicState.Viewport, DynamicState.Scissor };

            var entryPointName = System.Text.Encoding.UTF8.GetBytes("main\0");

            fixed (byte* entryPointNamePointer = &entryPointName[0])
            fixed (DynamicState* dynamicStatesPointer = &dynamicStates[0])
            fixed (VertexInputAttributeDescription* vertexAttibutesPointer = &vertexAttributes[0])
            fixed (VertexInputBindingDescription* vertexBindingsPointer = &vertexBindings[0])
            {
                var dynamicState = new PipelineDynamicStateCreateInfo
                {
                    StructureType = StructureType.PipelineDynamicStateCreateInfo,
                    DynamicStateCount = (uint)dynamicStates.Length,
                    DynamicStates = new IntPtr(dynamicStatesPointer)
                };

                var viewportState = new PipelineViewportStateCreateInfo
                {
                    StructureType = StructureType.PipelineViewportStateCreateInfo,
                    ScissorCount = 1,
                    ViewportCount = 1,
                };

                var vertexInputState = new PipelineVertexInputStateCreateInfo
                {
                    StructureType = StructureType.PipelineVertexInputStateCreateInfo,
                    VertexAttributeDescriptionCount = (uint)vertexAttributes.Length,
                    VertexAttributeDescriptions = new IntPtr(vertexAttibutesPointer),
                    VertexBindingDescriptionCount = (uint)vertexBindings.Length,
                    VertexBindingDescriptions = new IntPtr(vertexBindingsPointer),
                };

                var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo
                {
                    StructureType = StructureType.PipelineInputAssemblyStateCreateInfo,
                    Topology = PrimitiveTopology.TriangleList
                };

                var rasterizerState = new PipelineRasterizationStateCreateInfo
                {
                    StructureType = StructureType.PipelineRasterizationStateCreateInfo,
                    PolygonMode = PolygonMode.Fill,
                    CullMode = CullModeFlags.None,
                    FrontFace = FrontFace.Clockwise,
                    LineWidth = 1.0f,
                };

                var colorBlendAttachment = new PipelineColorBlendAttachmentState { ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A };
                var blendState = new PipelineColorBlendStateCreateInfo
                {
                    StructureType = StructureType.PipelineColorBlendStateCreateInfo,
                    AttachmentCount = 1,
                    Attachments = new IntPtr(&colorBlendAttachment)
                };

                var depthStencilState = new PipelineDepthStencilStateCreateInfo
                {
                    StructureType = StructureType.PipelineDepthStencilStateCreateInfo,
                    DepthTestEnable = false,
                    DepthWriteEnable = true,
                    DepthCompareOperation = CompareOperation.LessOrEqual,
                    Back = new StencilOperationState { CompareOperation = CompareOperation.Always },
                    Front = new StencilOperationState { CompareOperation = CompareOperation.Always }
                };

                var multisampleState = new PipelineMultisampleStateCreateInfo
                {
                    StructureType = StructureType.PipelineMultisampleStateCreateInfo,
                    RasterizationSamples = SampleCountFlags.Sample1,
                };

                var shaderStages = new[]
                {
                    new PipelineShaderStageCreateInfo
                    {
                        StructureType = StructureType.PipelineShaderStageCreateInfo,
                        Name = new IntPtr(entryPointNamePointer),
                        Stage = ShaderStageFlags.Vertex,
                        Module = CreateVertexShader()
                    },
                    new PipelineShaderStageCreateInfo
                    {
                        StructureType = StructureType.PipelineShaderStageCreateInfo,
                        Name = new IntPtr(entryPointNamePointer),
                        Stage = ShaderStageFlags.Fragment,
                        Module = CreateFragmentShader()
                    }
                };

                fixed (PipelineShaderStageCreateInfo* shaderStagesPointer = &shaderStages[0])
                {
                    var createInfo = new GraphicsPipelineCreateInfo
                    {
                        StructureType = StructureType.GraphicsPipelineCreateInfo,
                        Layout = pipelineLayout,
                        DynamicState = new IntPtr(&dynamicState),
                        ViewportState = new IntPtr(&viewportState),
                        VertexInputState = new IntPtr(&vertexInputState),
                        InputAssemblyState = new IntPtr(&inputAssemblyState),
                        RasterizationState = new IntPtr(&rasterizerState),
                        ColorBlendState = new IntPtr(&blendState),
                        DepthStencilState = new IntPtr(&depthStencilState),
                        MultisampleState = new IntPtr(&multisampleState),
                        StageCount = (uint)shaderStages.Length,
                        Stages = new IntPtr(shaderStagesPointer),
                        RenderPass = renderPass
                    };
                    pipeline = device.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo);
                }

                foreach (var shaderStage in shaderStages)
                {
                    device.DestroyShaderModule(shaderStage.Module);
                }
            }
        }
Beispiel #6
0
        private void CreatePipeline()
        {
            var dynamicStates = new [] { DynamicState.Viewport, DynamicState.Scissor };

            var entryPointName = System.Text.Encoding.UTF8.GetBytes("main\0");

            fixed(byte *entryPointNamePointer = &entryPointName[0])
            fixed(DynamicState * dynamicStatesPointer = &dynamicStates[0])
            fixed(VertexInputAttributeDescription * vertexAttibutesPointer = &vertexAttributes[0])
            fixed(VertexInputBindingDescription * vertexBindingsPointer    = &vertexBindings[0])
            {
                var dynamicState = new PipelineDynamicStateCreateInfo
                {
                    StructureType     = StructureType.PipelineDynamicStateCreateInfo,
                    DynamicStateCount = (uint)dynamicStates.Length,
                    DynamicStates     = new IntPtr(dynamicStatesPointer)
                };

                var viewportState = new PipelineViewportStateCreateInfo
                {
                    StructureType = StructureType.PipelineViewportStateCreateInfo,
                    ScissorCount  = 1,
                    ViewportCount = 1,
                };

                var vertexInputState = new PipelineVertexInputStateCreateInfo
                {
                    StructureType = StructureType.PipelineVertexInputStateCreateInfo,
                    VertexAttributeDescriptionCount = (uint)vertexAttributes.Length,
                    VertexAttributeDescriptions     = new IntPtr(vertexAttibutesPointer),
                    VertexBindingDescriptionCount   = (uint)vertexBindings.Length,
                    VertexBindingDescriptions       = new IntPtr(vertexBindingsPointer),
                };

                var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo
                {
                    StructureType = StructureType.PipelineInputAssemblyStateCreateInfo,
                    Topology      = PrimitiveTopology.TriangleList
                };

                var rasterizerState = new PipelineRasterizationStateCreateInfo
                {
                    StructureType = StructureType.PipelineRasterizationStateCreateInfo,
                    PolygonMode   = PolygonMode.Fill,
                    CullMode      = CullModeFlags.None,
                    FrontFace     = FrontFace.Clockwise,
                    LineWidth     = 1.0f,
                };

                var colorBlendAttachment = new PipelineColorBlendAttachmentState {
                    ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A
                };
                var blendState = new PipelineColorBlendStateCreateInfo
                {
                    StructureType   = StructureType.PipelineColorBlendStateCreateInfo,
                    AttachmentCount = 1,
                    Attachments     = new IntPtr(&colorBlendAttachment)
                };

                var depthStencilState = new PipelineDepthStencilStateCreateInfo
                {
                    StructureType         = StructureType.PipelineDepthStencilStateCreateInfo,
                    DepthTestEnable       = false,
                    DepthWriteEnable      = true,
                    DepthCompareOperation = CompareOperation.LessOrEqual,
                    Back = new StencilOperationState {
                        CompareOperation = CompareOperation.Always
                    },
                    Front = new StencilOperationState {
                        CompareOperation = CompareOperation.Always
                    }
                };

                var multisampleState = new PipelineMultisampleStateCreateInfo
                {
                    StructureType        = StructureType.PipelineMultisampleStateCreateInfo,
                    RasterizationSamples = SampleCountFlags.Sample1,
                };

                var shaderStages = new[]
                {
                    new PipelineShaderStageCreateInfo
                    {
                        StructureType = StructureType.PipelineShaderStageCreateInfo,
                        Name          = new IntPtr(entryPointNamePointer),
                        Stage         = ShaderStageFlags.Vertex,
                        Module        = CreateVertexShader()
                    },
                    new PipelineShaderStageCreateInfo
                    {
                        StructureType = StructureType.PipelineShaderStageCreateInfo,
                        Name          = new IntPtr(entryPointNamePointer),
                        Stage         = ShaderStageFlags.Fragment,
                        Module        = CreateFragmentShader()
                    }
                };

                fixed(PipelineShaderStageCreateInfo *shaderStagesPointer = &shaderStages[0])
                {
                    var createInfo = new GraphicsPipelineCreateInfo
                    {
                        StructureType      = StructureType.GraphicsPipelineCreateInfo,
                        Layout             = pipelineLayout,
                        DynamicState       = new IntPtr(&dynamicState),
                        ViewportState      = new IntPtr(&viewportState),
                        VertexInputState   = new IntPtr(&vertexInputState),
                        InputAssemblyState = new IntPtr(&inputAssemblyState),
                        RasterizationState = new IntPtr(&rasterizerState),
                        ColorBlendState    = new IntPtr(&blendState),
                        DepthStencilState  = new IntPtr(&depthStencilState),
                        MultisampleState   = new IntPtr(&multisampleState),
                        StageCount         = (uint)shaderStages.Length,
                        Stages             = new IntPtr(shaderStagesPointer),
                        RenderPass         = renderPass
                    };

                    pipeline = device.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo);
                }

                foreach (var shaderStage in shaderStages)
                {
                    device.DestroyShaderModule(shaderStage.Module);
                }
            }
        }
Beispiel #7
0
        protected virtual void CreateGraphicsPipeline()
        {
            var shaderStages = CreateShaderStages();

            var vertexInputInfo = GetVertexInputInfo();

            var inputAssembly = new PipelineInputAssemblyStateCreateInfo
            {
                Topology = PrimitiveTopology.TriangleList,
                PrimitiveRestartEnable = false
            };

            var viewport = new Viewport
            {
                X        = 0f,
                Y        = 0f,
                Width    = extent.Width,
                Height   = extent.Height,
                MinDepth = 0f,
                MaxDepth = 1f
            };

            var scissor = new Rect2D
            {
                Offset = new Offset2D
                {
                    X = 0,
                    Y = 0
                },
                Extent = extent
            };

            var viewportState = new PipelineViewportStateCreateInfo
            {
                ViewportCount = 1,
                Viewports     = new Viewport[] { viewport },
                ScissorCount  = 1,
                Scissors      = new Rect2D[] { scissor }
            };

            var rasterizer = new PipelineRasterizationStateCreateInfo
            {
                DepthClampEnable        = false,
                RasterizerDiscardEnable = false,
                PolygonMode             = PolygonMode.Fill,
                LineWidth               = 1f,
                CullMode                = CullModeFlags.Back,
                FrontFace               = FrontFace.CounterClockwise,
                DepthBiasEnable         = false,
                DepthBiasConstantFactor = 0f,
                DepthBiasClamp          = 0f,
                DepthBiasSlopeFactor    = 0f
            };

            var msaa = new PipelineMultisampleStateCreateInfo
            {
                SampleShadingEnable   = false,
                RasterizationSamples  = SampleCountFlags.Count1,
                MinSampleShading      = 1f,
                AlphaToCoverageEnable = false,
                AlphaToOneEnable      = false
            };

            var colorBlendAttachment = new PipelineColorBlendAttachmentState
            {
                ColorWriteMask      = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A,
                BlendEnable         = false,
                SrcColorBlendFactor = BlendFactor.One,
                DstColorBlendFactor = BlendFactor.Zero,
                ColorBlendOp        = BlendOp.Add,
                SrcAlphaBlendFactor = BlendFactor.One,
                DstAlphaBlendFactor = BlendFactor.Zero,
                AlphaBlendOp        = BlendOp.Add
            };

            var colorBlending = new PipelineColorBlendStateCreateInfo
            {
                LogicOpEnable   = false,
                LogicOp         = LogicOp.Copy,
                AttachmentCount = 1,
                Attachments     = new PipelineColorBlendAttachmentState[] { colorBlendAttachment },
            };

            var layoutInfo = GetPipelineLayoutInfo();

            pipelineLayout = device.CreatePipelineLayout(layoutInfo);

            var pipelineCreateInfo = new GraphicsPipelineCreateInfo
            {
                StageCount         = (shaderStages == null ? 0 : (uint)shaderStages.Length),
                Stages             = shaderStages,
                VertexInputState   = vertexInputInfo,
                InputAssemblyState = inputAssembly,
                ViewportState      = viewportState,
                RasterizationState = rasterizer,
                MultisampleState   = msaa,
                ColorBlendState    = colorBlending,
                Layout             = pipelineLayout,
                RenderPass         = renderPass,
                Subpass            = 0,
                BasePipelineHandle = null,
                BasePipelineIndex  = -1
            };

            graphicsPipeline = device.CreateGraphicsPipelines(null, new GraphicsPipelineCreateInfo[] { pipelineCreateInfo })[0];

            if (shaderStages == null)
            {
                return;
            }
            foreach (var stage in shaderStages)
            {
                device.DestroyShaderModule(stage.Module);
            }
        }
Beispiel #8
0
        public void CreateGraphicsPipeline()
        {
            var attachment = new AttachmentDescription
            {
                Samples        = SampleCounts.Count1,
                Format         = Format.B8G8R8A8UNorm,
                InitialLayout  = ImageLayout.Undefined,
                FinalLayout    = ImageLayout.PresentSrcKhr,
                LoadOp         = AttachmentLoadOp.Clear,
                StoreOp        = AttachmentStoreOp.Store,
                StencilLoadOp  = AttachmentLoadOp.DontCare,
                StencilStoreOp = AttachmentStoreOp.DontCare
            };
            var subpass    = new SubpassDescription(new[] { new AttachmentReference(0, ImageLayout.ColorAttachmentOptimal) });
            var createInfo = new RenderPassCreateInfo(new[] { subpass }, new[] { attachment });

            using (PipelineCache cache = Device.CreatePipelineCache())
                using (RenderPass renderPass = Device.CreateRenderPass(createInfo))
                    using (PipelineLayout layout = Device.CreatePipelineLayout())
                        using (ShaderModule vertexShader = Device.CreateShaderModule(new ShaderModuleCreateInfo(ReadAllBytes("Shader.vert.spv"))))
                            using (ShaderModule fragmentShader = Device.CreateShaderModule(new ShaderModuleCreateInfo(ReadAllBytes("Shader.frag.spv"))))
                            {
                                var shaderStageCreateInfos = new[]
                                {
                                    new PipelineShaderStageCreateInfo(ShaderStages.Vertex, vertexShader, "main"),
                                    new PipelineShaderStageCreateInfo(ShaderStages.Fragment, fragmentShader, "main")
                                };
                                var vertexInputStateCreateInfo   = new PipelineVertexInputStateCreateInfo();
                                var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo(PrimitiveTopology.TriangleList);
                                var viewportStateCreateInfo      = new PipelineViewportStateCreateInfo(
                                    new Viewport(0, 0, 32, 32),
                                    new Rect2D(0, 0, 32, 32));
                                var rasterizationStateCreateInfo = new PipelineRasterizationStateCreateInfo
                                {
                                    PolygonMode = PolygonMode.Fill,
                                    CullMode    = CullModes.Back,
                                    FrontFace   = FrontFace.CounterClockwise,
                                    LineWidth   = 1.0f
                                };
                                var tessellationStateCreateInfo = new PipelineTessellationStateCreateInfo(4);
                                var multisampleStateCreateInfo  = new PipelineMultisampleStateCreateInfo
                                {
                                    RasterizationSamples = SampleCounts.Count1,
                                    MinSampleShading     = 1.0f
                                };
                                var colorBlendAttachmentState = new PipelineColorBlendAttachmentState
                                {
                                    SrcColorBlendFactor = BlendFactor.One,
                                    DstColorBlendFactor = BlendFactor.Zero,
                                    ColorBlendOp        = BlendOp.Add,
                                    SrcAlphaBlendFactor = BlendFactor.One,
                                    DstAlphaBlendFactor = BlendFactor.Zero,
                                    AlphaBlendOp        = BlendOp.Add,
                                    ColorWriteMask      = ColorComponents.All
                                };
                                var depthStencilStateCreateInfo = new PipelineDepthStencilStateCreateInfo();
                                var colorBlendStateCreateInfo   = new PipelineColorBlendStateCreateInfo(
                                    new[] { colorBlendAttachmentState });
                                var dynamicStateCreateInfo = new PipelineDynamicStateCreateInfo(DynamicState.LineWidth);

                                var pipelineCreateInfo = new GraphicsPipelineCreateInfo(
                                    layout, renderPass, 0,
                                    shaderStageCreateInfos,
                                    inputAssemblyStateCreateInfo,
                                    vertexInputStateCreateInfo,
                                    rasterizationStateCreateInfo,
                                    tessellationStateCreateInfo,
                                    viewportStateCreateInfo,
                                    multisampleStateCreateInfo,
                                    depthStencilStateCreateInfo,
                                    colorBlendStateCreateInfo,
                                    dynamicStateCreateInfo);
                                using (Device.CreateGraphicsPipelines(new[] { pipelineCreateInfo })[0]) { }
                                using (Device.CreateGraphicsPipelines(new[] { pipelineCreateInfo }, cache)[0]) { }
                                using (Device.CreateGraphicsPipelines(new[] { pipelineCreateInfo }, allocator: CustomAllocator)[0]) { }
                                using (Device.CreateGraphicsPipelines(new[] { pipelineCreateInfo }, cache, CustomAllocator)[0]) { }
                                using (Device.CreateGraphicsPipeline(pipelineCreateInfo)) { }
                                using (Device.CreateGraphicsPipeline(pipelineCreateInfo, allocator: CustomAllocator)) { }
                                using (Device.CreateGraphicsPipeline(pipelineCreateInfo, cache)) { }
                                using (Device.CreateGraphicsPipeline(pipelineCreateInfo, cache, CustomAllocator)) { }
                            }
        }
Beispiel #9
0
        public static Pipeline CreateGraphicsPipeline(Graphics g, PipelineLayout pl, RenderPass rp, string[] shaderNames, bool depthTest, bool depthWrite, bool instancing, Type instanceInfoType, BlendMode blendMode, PrimitiveType primType, PrimitiveRenderMode pmode, PrimitiveCullMode cmode, float lineWidth, Vector2 viewportPos, Vector2 viewportSize)
        {
            if (instancing && instanceInfoType == null)
            {
                throw new NullReferenceException("Instance info type cannot be null");
            }

            var shaderStageCreateInfos = new PipelineShaderStageCreateInfo[shaderNames.Length];

            for (var i = 0; i < shaderNames.Length; i++)
            {
                var shader     = g.Context.Content.Get <ShaderModule>(shaderNames[i]);
                var shaderName = Path.GetFileNameWithoutExtension(shaderNames[i]);
                switch (Path.GetExtension(shaderName))
                {
                case ".vert":
                    shaderStageCreateInfos[i] = new PipelineShaderStageCreateInfo(ShaderStages.Vertex, shader, "main");
                    break;

                case ".frag":
                    shaderStageCreateInfos[i] = new PipelineShaderStageCreateInfo(ShaderStages.Fragment, shader, "main");
                    break;

                default:
                    throw new NotImplementedException($"Unreognized shader type for file \"{shaderNames[i]}\"");
                }
            }

            var fields = typeof(Vertex).GetFields();
            var offset = 0;
            var loci   = 0;
            List <VertexInputAttributeDescription> vertexAttributes = new List <VertexInputAttributeDescription>(fields.Length);

            for (var i = 0; i < fields.Length; i++)
            {
                var ftype = fields[i].FieldType;
                if (ftype == typeof(Vector3) || ftype == typeof(Angle))
                {
                    vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32SFloat, offset));
                    offset += 12;
                    loci++;
                }
                else if (ftype == typeof(Vector2))
                {
                    vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32SFloat, offset));
                    offset += 8;
                    loci++;
                }
                else if (ftype == typeof(Color4))
                {
                    vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32A32SFloat, offset));
                    offset += 16;
                    loci++;
                }
                else if (ftype == typeof(float))
                {
                    vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32SFloat, offset));
                    offset += 4;
                    loci++;
                }
                else if (ftype == typeof(Matrix4))
                {
                    vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32A32SFloat, offset));
                    loci++;
                    offset += 16;
                    vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32A32SFloat, offset));
                    loci++;
                    offset += 16;
                    vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32A32SFloat, offset));
                    loci++;
                    offset += 16;
                    vertexAttributes.Add(new VertexInputAttributeDescription(loci, 0, Format.R32G32B32A32SFloat, offset));
                    loci++;
                    offset += 16;
                }
                else
                {
                    throw new Exception("Field " + fields[i] + " of vertex struct is an illegal type");
                }
            }
            var vertexFieldsLength = fields.Length;

            if (instancing)
            {
                fields = instanceInfoType.GetFields();
                offset = 0;
                for (var i = 0; i < fields.Length; i++)
                {
                    var ftype = fields[i].FieldType;
                    if (ftype == typeof(Vector3) || ftype == typeof(Angle))
                    {
                        vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32SFloat, offset));
                        loci++;
                        offset += 12;
                    }
                    else if (ftype == typeof(Vector2))
                    {
                        vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32SFloat, offset));
                        loci++;
                        offset += 8;
                    }
                    else if (ftype == typeof(Color4))
                    {
                        vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32A32SFloat, offset));
                        loci++;
                        offset += 16;
                    }
                    else if (ftype == typeof(float))
                    {
                        vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32SFloat, offset));
                        loci++;
                        offset += 4;
                    }
                    else if (ftype == typeof(Matrix4))
                    {
                        vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32A32SFloat, offset));
                        loci++;
                        offset += 16;
                        vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32A32SFloat, offset));
                        loci++;
                        offset += 16;
                        vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32A32SFloat, offset));
                        loci++;
                        offset += 16;
                        vertexAttributes.Add(new VertexInputAttributeDescription(loci, 1, Format.R32G32B32A32SFloat, offset));
                        loci++;
                        offset += 16;
                    }
                    else
                    {
                        throw new Exception("Field " + fields[i] + " of instance info struct is an illegal type");
                    }
                }
            }

            var vertexInputStateCreateInfo = new PipelineVertexInputStateCreateInfo(
                (instancing ? new[]
            {
                new VertexInputBindingDescription(0, Interop.SizeOf <Vertex>(), VertexInputRate.Vertex),
                new VertexInputBindingDescription(1, System.Runtime.InteropServices.Marshal.SizeOf(instanceInfoType), VertexInputRate.Instance)
            } :
                 new[]
            {
                new VertexInputBindingDescription(0, Interop.SizeOf <Vertex>(), VertexInputRate.Vertex)
            }),
                vertexAttributes.ToArray()
                );
            var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo((PrimitiveTopology)primType);
            var viewportStateCreateInfo      = new PipelineViewportStateCreateInfo(
                new Viewport(viewportPos.X + viewportSize.X, viewportPos.Y + viewportSize.Y, -viewportSize.X, -viewportSize.Y),
                new Rect2D((int)viewportPos.X, (int)viewportPos.Y, (int)viewportSize.X, (int)viewportSize.Y));
            var rasterizationStateCreateInfo = new PipelineRasterizationStateCreateInfo
            {
                PolygonMode = (PolygonMode)pmode,
                CullMode    = (CullModes)cmode,
                FrontFace   = FrontFace.Clockwise,
                LineWidth   = lineWidth
            };
            var multisampleStateCreateInfo = new PipelineMultisampleStateCreateInfo
            {
                RasterizationSamples =
                    g.Samples >= 48 ? SampleCounts.Count64 :
                    g.Samples >= 24 ? SampleCounts.Count32 :
                    g.Samples >= 12 ? SampleCounts.Count16 :
                    g.Samples >= 6 ? SampleCounts.Count8 :
                    g.Samples >= 3 ? SampleCounts.Count4 :
                    g.Samples == 2 ? SampleCounts.Count2 :
                    SampleCounts.Count1,
                MinSampleShading = 1.0f
            };
            var depthStencilCreateInfo = new PipelineDepthStencilStateCreateInfo
            {
                DepthTestEnable  = depthTest,
                DepthWriteEnable = depthWrite,
                DepthCompareOp   = CompareOp.LessOrEqual,
                Back             = new StencilOpState
                {
                    FailOp    = StencilOp.Keep,
                    PassOp    = StencilOp.Keep,
                    CompareOp = CompareOp.Always
                },
                Front = new StencilOpState
                {
                    FailOp    = StencilOp.Keep,
                    PassOp    = StencilOp.Keep,
                    CompareOp = CompareOp.Always
                }
            };
            var colorBlendAttachmentState = new PipelineColorBlendAttachmentState
            {
                SrcColorBlendFactor = BlendMode.GetBlendFactor(blendMode.SrcColorFactor),
                DstColorBlendFactor = BlendMode.GetBlendFactor(blendMode.DstColorFactor),
                ColorBlendOp        = BlendMode.GetBlendOp(blendMode.ColorOp),
                SrcAlphaBlendFactor = BlendMode.GetBlendFactor(blendMode.SrcAlphaFactor),
                DstAlphaBlendFactor = BlendMode.GetBlendFactor(blendMode.DstAlphaFactor),
                AlphaBlendOp        = BlendMode.GetBlendOp(blendMode.AlphaOp),
                ColorWriteMask      = BlendMode.GetColorWriteMask(blendMode.Mask),
                BlendEnable         = true
            };
            var colorBlendStateCreateInfo = new PipelineColorBlendStateCreateInfo(
                new[] { colorBlendAttachmentState });

            var pipelineCreateInfo = new GraphicsPipelineCreateInfo(
                pl, rp, 0,
                shaderStageCreateInfos,
                inputAssemblyStateCreateInfo,
                vertexInputStateCreateInfo,
                rasterizationStateCreateInfo,
                viewportState: viewportStateCreateInfo,
                multisampleState: multisampleStateCreateInfo,
                depthStencilState: depthStencilCreateInfo,
                colorBlendState: colorBlendStateCreateInfo//,
                //dynamicState: new PipelineDynamicStateCreateInfo(DynamicState.Viewport)
                );

            return(g.Context.Device.CreateGraphicsPipeline(pipelineCreateInfo));
        }
Beispiel #10
0
        void CreatePipeline()
        {
            ShaderModule vertex_shader_module   = CreateShaderModule("assets/shader03.vert.spv");
            ShaderModule fragment_shader_module = CreateShaderModule("assets/shader03.frag.spv");

            var shader_stage_create_infos = stackalloc PipelineShaderStageCreateInfo[2];

            // Vertex shader
            shader_stage_create_infos[0] = new PipelineShaderStageCreateInfo
            {
                sType  = StructureType.PipelineShaderStageCreateInfo,                  // VkStructureType                                sType
                pNext  = IntPtr.Zero,                                                  // const void                                    *pNext
                flags  = 0,                                                            // VkPipelineShaderStageCreateFlagBits               flags
                stage  = ShaderStageFlagBits.VertexBit,                                // VkShaderStageFlagBits                          stage
                module = vertex_shader_module,                                         // VkShaderModule                                 module
                pName  = (byte *)Marshal.StringToHGlobalAnsi("main"),                  // const char                                    *pName
                pSpecializationInfo = (SpecializationInfo *)0                          // const VkSpecializationInfo                    *pSpecializationInfo
            };
            // Fragment shader
            shader_stage_create_infos[1] = new PipelineShaderStageCreateInfo
            {
                sType  = StructureType.PipelineShaderStageCreateInfo,                  // VkStructureType                                sType
                pNext  = IntPtr.Zero,                                                  // const void                                    *pNext
                flags  = 0,                                                            // VkPipelineShaderStageCreateFlagBits               flags
                stage  = ShaderStageFlagBits.FragmentBit,                              // VkShaderStageFlagBits                          stage
                module = fragment_shader_module,                                       // VkShaderModule                                 module
                pName  = (byte *)Marshal.StringToHGlobalAnsi("main"),                  // const char                                    *pName
                pSpecializationInfo = (SpecializationInfo *)0                          // const VkSpecializationInfo                    *pSpecializationInfo
            };

            var vertex_input_state_create_info = new PipelineVertexInputStateCreateInfo
            {
                sType = StructureType.PipelineVertexInputStateCreateInfo,                           // VkStructureType                                sType
                pNext = IntPtr.Zero,                                                                // const void                                    *pNext
                flags = 0,                                                                          // VkPipelineVertexInputStateCreateFlagBits          flags;
                vertexBindingDescriptionCount   = 0,                                                // uint32_t                                       vertexBindingDescriptionCount
                pVertexBindingDescriptions      = (VertexInputBindingDescription *)0,               // const VkVertexInputBindingDescription         *pVertexBindingDescriptions
                vertexAttributeDescriptionCount = 0,                                                // uint32_t                                       vertexAttributeDescriptionCount
                pVertexAttributeDescriptions    = (VertexInputAttributeDescription *)0              // const VkVertexInputAttributeDescription       *pVertexAttributeDescriptions
            };

            var input_assembly_state_create_info = new PipelineInputAssemblyStateCreateInfo
            {
                sType    = StructureType.PipelineInputAssemblyStateCreateInfo,              // VkStructureType                                sType
                pNext    = IntPtr.Zero,                                                     // const void                                    *pNext
                flags    = 0,                                                               // VkPipelineInputAssemblyStateCreateFlagBits        flags
                topology = PrimitiveTopology.TriangleList,                                  // VkPrimitiveTopology                            topology
                primitiveRestartEnable = false                                              // VkBool32                                       primitiveRestartEnable
            };

            Viewport viewport = new Viewport
            {
                x        = 0.0f,                        // float       x
                y        = 0.0f,                        // float       y
                width    = 300.0f,                      // float       width
                height   = 300.0f,                      // float       height
                minDepth = 0.0f,                        // float       minDepth
                maxDepth = 1.0f                         // float       maxDepth
            };

            Rect2D scissor = new Rect2D
            {
                offset = new Offset2D
                {                                       // VkOffset2D  offset
                    x = 0,                              // int32_t     x
                    y = 0                               // int32_t     y
                },
                extent = new Extent2D
                {                                       // VkExtent2D  extent
                    width  = 300,                       // int32_t     width
                    height = 300                        // int32_t     height
                }
            };

            var viewport_state_create_info = new PipelineViewportStateCreateInfo
            {
                sType         = StructureType.PipelineViewportStateCreateInfo,         // VkStructureType                                sType
                pNext         = IntPtr.Zero,                                           // const void                                    *pNext
                flags         = 0,                                                     // VkPipelineViewportStateCreateFlagBits             flags
                viewportCount = 1,                                                     // uint32_t                                       viewportCount
                pViewports    = &viewport,                                             // const VkViewport                              *pViewports
                scissorCount  = 1,                                                     // uint32_t                                       scissorCount
                pScissors     = &scissor                                               // const VkRect2D                                *pScissors
            };

            var rasterization_state_create_info = new PipelineRasterizationStateCreateInfo
            {
                sType                   = StructureType.PipelineRasterizationStateCreateInfo, // VkStructureType                                sType
                pNext                   = IntPtr.Zero,                                        // const void                                    *pNext
                flags                   = 0,                                                  // VkPipelineRasterizationStateCreateFlagBits        flags
                depthClampEnable        = false,                                              // VkBool32                                       depthClampEnable
                rasterizerDiscardEnable = false,                                              // VkBool32                                       rasterizerDiscardEnable
                polygonMode             = PolygonMode.Fill,                                   // VkPolygonMode                                  polygonMode
                cullMode                = CullModeFlagBits.BackBit,                           // VkCullModeFlagBits                                cullMode
                frontFace               = FrontFace.CounterClockwise,                         // VkFrontFace                                    frontFace
                depthBiasEnable         = false,                                              // VkBool32                                       depthBiasEnable
                depthBiasConstantFactor = 0.0f,                                               // float                                          depthBiasConstantFactor
                depthBiasClamp          = 0.0f,                                               // float                                          depthBiasClamp
                depthBiasSlopeFactor    = 0.0f,                                               // float                                          depthBiasSlopeFactor
                lineWidth               = 1.0f                                                // float                                          lineWidth
            };

            var multisample_state_create_info = new PipelineMultisampleStateCreateInfo
            {
                sType = StructureType.PipelineMultisampleStateCreateInfo,                 // VkStructureType                                sType
                pNext = IntPtr.Zero,                                                      // const void                                    *pNext
                flags = 0,                                                                // VkPipelineMultisampleStateCreateFlagBits          flags
                rasterizationSamples  = SampleCountFlagBits._1Bit,                        // VkSampleCountFlagBits                          rasterizationSamples
                sampleShadingEnable   = false,                                            // VkBool32                                       sampleShadingEnable
                minSampleShading      = 1.0f,                                             // float                                          minSampleShading
                pSampleMask           = (uint *)0,                                        // const VkSampleMask                            *pSampleMask
                alphaToCoverageEnable = false,                                            // VkBool32                                       alphaToCoverageEnable
                alphaToOneEnable      = false                                             // VkBool32                                       alphaToOneEnable
            };

            var color_blend_attachment_state = new PipelineColorBlendAttachmentState
            {
                blendEnable                 = false,                                                    // VkBool32                                       blendEnable
                sourceColorBlendFactor      = BlendFactor.One,                                          // VkBlendFactor                                  srcColorBlendFactor
                destinationColorBlendFactor = BlendFactor.Zero,                                         // VkBlendFactor                                  dstColorBlendFactor
                colorBlendOperation         = BlendOperation.Add,                                       // VkBlendOp                                      colorBlendOp
                sourceAlphaBlendFactor      = BlendFactor.One,                                          // VkBlendFactor                                  srcAlphaBlendFactor
                destinationAlphaBlendFactor = BlendFactor.Zero,                                         // VkBlendFactor                                  dstAlphaBlendFactor
                alphaBlendOperation         = BlendOperation.Add,                                       // VkBlendOp                                      alphaBlendOp
                colorWriteMask              = ColorComponentFlagBits.RBit | ColorComponentFlagBits.GBit // VkColorComponentFlagBits                          colorWriteMask
                                              | ColorComponentFlagBits.BBit | ColorComponentFlagBits.ABit
            };

            var color_blend_state_create_info = new PipelineColorBlendStateCreateInfo
            {
                sType = StructureType.PipelineColorBlendStateCreateInfo,                 // VkStructureType                                sType
                pNext = IntPtr.Zero,                                                     // const void                                    *pNext
                flags = 0,                                                               // VkPipelineColorBlendStateCreateFlagBits           flags
                logicOperationEnable = false,                                            // VkBool32                                       logicOpEnable
                logicOperation       = LogicOperation.Copy,                              // VkLogicOp                                      logicOp
                attachmentCount      = 1,                                                // uint32_t                                       attachmentCount
                pAttachments         = &color_blend_attachment_state,                    // const VkPipelineColorBlendAttachmentState     *pAttachments
            };

            //blendConstants = { 0.0f, 0.0f, 0.0f, 0.0f }              // float                                          blendConstants[4]
            color_blend_state_create_info.blendConstants[0] = 0;
            color_blend_state_create_info.blendConstants[1] = 0;
            color_blend_state_create_info.blendConstants[2] = 0;
            color_blend_state_create_info.blendConstants[3] = 0;

            var pipeline_layout = CreatePipelineLayout();

            var pipeline_create_info = new GraphicsPipelineCreateInfo
            {
                sType               = StructureType.GraphicsPipelineCreateInfo,               // VkStructureType                                sType
                pNext               = IntPtr.Zero,                                            // const void                                    *pNext
                flags               = 0,                                                      // VkPipelineCreateFlagBits                          flags
                stageCount          = 2,                                                      // uint32_t                                       stageCount
                pStages             = shader_stage_create_infos,                              // const VkPipelineShaderStageCreateInfo         *pStages
                pVertexInputState   = &vertex_input_state_create_info,                        // const VkPipelineVertexInputStateCreateInfo    *pVertexInputState;
                pInputAssemblyState = &input_assembly_state_create_info,                      // const VkPipelineInputAssemblyStateCreateInfo  *pInputAssemblyState
                pTessellationState  = (PipelineTessellationStateCreateInfo *)0,               // const VkPipelineTessellationStateCreateInfo   *pTessellationState
                pViewportState      = &viewport_state_create_info,                            // const VkPipelineViewportStateCreateInfo       *pViewportState
                pRasterizationState = &rasterization_state_create_info,                       // const VkPipelineRasterizationStateCreateInfo  *pRasterizationState
                pMultisampleState   = &multisample_state_create_info,                         // const VkPipelineMultisampleStateCreateInfo    *pMultisampleState
                pDepthStencilState  = (PipelineDepthStencilStateCreateInfo *)0,               // const VkPipelineDepthStencilStateCreateInfo   *pDepthStencilState
                pColorBlendState    = &color_blend_state_create_info,                         // const VkPipelineColorBlendStateCreateInfo     *pColorBlendState
                pDynamicState       = (PipelineDynamicStateCreateInfo *)0,                    // const VkPipelineDynamicStateCreateInfo        *pDynamicState
                layout              = pipeline_layout,                                        // VkPipelineLayout                               layout
                renderPass          = Vulkan.RenderPass,                                      // VkRenderPass                                   renderPass
                subpass             = 0,                                                      // uint32_t                                       subpass
                basePipelineHandle  = default(Pipeline),                                      // VkPipeline                                     basePipelineHandle
                basePipelineIndex   = -1                                                      // int32_t                                        basePipelineIndex
            };

            vk.CreateGraphicsPipelines(GetDevice, default(PipelineCache), 1, &pipeline_create_info, (AllocationCallbacks *)0, out Vulkan.GraphicsPipeline).CheckError();

            Marshal.FreeHGlobal((IntPtr)shader_stage_create_infos[0].pName);
            Marshal.FreeHGlobal((IntPtr)shader_stage_create_infos[1].pName);
        }
        private Pipeline CreateGraphicsPipeline()
        {
            using var pName = SilkMarshal.StringToMemory("main");

            var shaderStages = stackalloc PipelineShaderStageCreateInfo[2]
            {
                new PipelineShaderStageCreateInfo
                {
                    SType  = StructureType.PipelineShaderStageCreateInfo,
                    Stage  = ShaderStageFlags.ShaderStageVertexBit,
                    Module = this.VertexShader,
                    PName  = (byte *)pName
                },

                new PipelineShaderStageCreateInfo
                {
                    SType  = StructureType.PipelineShaderStageCreateInfo,
                    Stage  = ShaderStageFlags.ShaderStageFragmentBit,
                    Module = this.FragmentShader,
                    PName  = (byte *)pName
                }
            };

            var dynamicStates = stackalloc DynamicState[2] {
                DynamicState.Viewport, DynamicState.Scissor
            };

            PipelineDynamicStateCreateInfo dynamicState = new PipelineDynamicStateCreateInfo
            {
                SType             = StructureType.PipelineDynamicStateCreateInfo,
                DynamicStateCount = 2,
                PDynamicStates    = dynamicStates
            };

            var vertexBindings = stackalloc VertexInputBindingDescription[2]
            {
                new VertexInputBindingDescription(0, (uint)sizeof(PositionColorVertex), VertexInputRate.Vertex),
                new VertexInputBindingDescription(1, (uint)sizeof(InstanceData), VertexInputRate.Instance)
            };

            var vertexAttributes = stackalloc VertexInputAttributeDescription[3]
            {
                new VertexInputAttributeDescription(0, 0, Format.R32G32B32Sfloat, 0),
                new VertexInputAttributeDescription(1, 0, Format.R32G32B32Sfloat, (uint)sizeof(System.Numerics.Vector3)),
                new VertexInputAttributeDescription(2, 1, Format.R32G32B32Sfloat, 0)
            };

            var vertexInputInfo = new PipelineVertexInputStateCreateInfo
            {
                SType = StructureType.PipelineVertexInputStateCreateInfo,
                VertexBindingDescriptionCount   = 2,
                PVertexBindingDescriptions      = vertexBindings,
                VertexAttributeDescriptionCount = 3,
                PVertexAttributeDescriptions    = vertexAttributes
            };

            var inputAssembly = new PipelineInputAssemblyStateCreateInfo
            {
                SType    = StructureType.PipelineInputAssemblyStateCreateInfo,
                Topology = PrimitiveTopology.TriangleList,
                PrimitiveRestartEnable = false
            };

            //Marked as dynamic state, will be specified in the command buffer
            var viewportState = new PipelineViewportStateCreateInfo
            {
                SType         = StructureType.PipelineViewportStateCreateInfo,
                ViewportCount = 1,
                ScissorCount  = 1,
            };

            var rasterizer = new PipelineRasterizationStateCreateInfo
            {
                SType                   = StructureType.PipelineRasterizationStateCreateInfo,
                DepthClampEnable        = Vk.False,
                RasterizerDiscardEnable = Vk.False,
                PolygonMode             = PolygonMode.Fill,
                LineWidth               = 1.0f,
                CullMode                = CullModeFlags.CullModeNone,
                FrontFace               = FrontFace.Clockwise,
                DepthBiasEnable         = Vk.False
            };

            var multisampling = new PipelineMultisampleStateCreateInfo
            {
                SType = StructureType.PipelineMultisampleStateCreateInfo,
                SampleShadingEnable  = false,
                RasterizationSamples = SampleCountFlags.SampleCount1Bit
            };

            var colorBlendAttachment = new PipelineColorBlendAttachmentState
            {
                ColorWriteMask = ColorComponentFlags.ColorComponentRBit |
                                 ColorComponentFlags.ColorComponentGBit |
                                 ColorComponentFlags.ColorComponentBBit |
                                 ColorComponentFlags.ColorComponentABit,
                BlendEnable = Vk.False
            };

            var colorBlending = new PipelineColorBlendStateCreateInfo
            {
                SType           = StructureType.PipelineColorBlendStateCreateInfo,
                LogicOpEnable   = Vk.False,
                LogicOp         = LogicOp.Copy,
                AttachmentCount = 1,
                PAttachments    = &colorBlendAttachment
            };

            colorBlending.BlendConstants[0] = 0.0f;
            colorBlending.BlendConstants[1] = 0.0f;
            colorBlending.BlendConstants[2] = 0.0f;
            colorBlending.BlendConstants[3] = 0.0f;

            var depthState = new PipelineDepthStencilStateCreateInfo
            {
                SType                 = StructureType.PipelineDepthStencilStateCreateInfo,
                DepthTestEnable       = true,
                DepthWriteEnable      = true,
                DepthCompareOp        = CompareOp.LessOrEqual,
                DepthBoundsTestEnable = false,
                MinDepthBounds        = 0,
                MaxDepthBounds        = 0,
                StencilTestEnable     = false,
                Back =
                {
                    FailOp      = StencilOp.Keep,
                    PassOp      = StencilOp.Keep,
                    CompareOp   = CompareOp.Always,
                    CompareMask =                0,
                    Reference   =                0,
                    DepthFailOp = StencilOp.Keep,
                    WriteMask   = 0
                }
            };

            depthState.Front = depthState.Back;

            var pipelineInfo = new GraphicsPipelineCreateInfo
            {
                SType               = StructureType.GraphicsPipelineCreateInfo,
                StageCount          = 2,
                PStages             = shaderStages,
                PDynamicState       = &dynamicState,
                PDepthStencilState  = &depthState,
                PVertexInputState   = &vertexInputInfo,
                PInputAssemblyState = &inputAssembly,
                PViewportState      = &viewportState,
                PRasterizationState = &rasterizer,
                PMultisampleState   = &multisampling,
                PColorBlendState    = &colorBlending,
                Layout              = this.GraphicsPipelineLayout,
                RenderPass          = RenderPass,
                Subpass             = 0,
                BasePipelineHandle  = default
            };

            Pipeline pipeline;
            var      res = VkApi.CreateGraphicsPipelines(Device, default, 1, &pipelineInfo, null, &pipeline);
Beispiel #12
0
        public bool Create(string vsName, string fsName,
                           VertexInputBindingDescription [] vbind,
                           VertexInputAttributeDescription [] vatts)
        {
            Device dv = mDevices.GetLogicalDevice();

            PipelineShaderStageCreateInfo plssciv = new PipelineShaderStageCreateInfo(
                ShaderStages.Vertex, mShaders[vsName], "main", null);

            PipelineShaderStageCreateInfo plsscif = new PipelineShaderStageCreateInfo(
                ShaderStages.Fragment, mShaders[fsName], "main", null);

            PipelineVertexInputStateCreateInfo plvisci = new PipelineVertexInputStateCreateInfo(
                vbind, vatts);

            PipelineInputAssemblyStateCreateInfo pliasci = new PipelineInputAssemblyStateCreateInfo(
                PrimitiveTopology.TriangleList);

            Viewport vp = new Viewport(0, 0, 1280, 720, 0f, 1f);

            Rect2D scissor = new Rect2D(Offset2D.Zero, mDevices.GetChainExtent());

            PipelineViewportStateCreateInfo plvpsci = new PipelineViewportStateCreateInfo(
                new Viewport[1] {
                vp
            }, new Rect2D[1] {
                scissor
            });

            PipelineRasterizationStateCreateInfo plrsci = new PipelineRasterizationStateCreateInfo();

            plrsci.LineWidth = 1;

            PipelineMultisampleStateCreateInfo plmssci = new PipelineMultisampleStateCreateInfo();

            plmssci.RasterizationSamples = SampleCounts.Count1;

            PipelineColorBlendAttachmentState plcbas = new PipelineColorBlendAttachmentState();

            plcbas.ColorWriteMask = ColorComponents.All;
            plcbas.BlendEnable    = false;

            PipelineColorBlendStateCreateInfo plcbsci = new PipelineColorBlendStateCreateInfo();

            plcbsci.LogicOpEnable = false;
            plcbsci.LogicOp       = LogicOp.Copy;
            plcbsci.Attachments   = new PipelineColorBlendAttachmentState[1] {
                plcbas
            };
            plcbsci.BlendConstants = ColorF4.Zero;

            PipelineLayoutCreateInfo pllci = new PipelineLayoutCreateInfo(
                mDevices.GetDSLs());

            mPipeLayout = dv.CreatePipelineLayout(pllci);

            AttachmentDescription ad = new AttachmentDescription();

            ad.Format         = Format.B8G8R8A8UNorm;
            ad.Samples        = SampleCounts.Count1;
            ad.LoadOp         = AttachmentLoadOp.Clear;
            ad.StoreOp        = AttachmentStoreOp.Store;
            ad.StencilLoadOp  = AttachmentLoadOp.DontCare;
            ad.StencilStoreOp = AttachmentStoreOp.DontCare;
            ad.InitialLayout  = ImageLayout.Undefined;
            ad.FinalLayout    = ImageLayout.PresentSrcKhr;

            AttachmentReference ar = new AttachmentReference(0, ImageLayout.ColorAttachmentOptimal);

            SubpassDescription spd = new SubpassDescription();

            spd.ColorAttachments = new AttachmentReference[1] {
                ar
            };

            SubpassDependency spdc = new SubpassDependency();

            spdc.SrcSubpass    = Constant.SubpassExternal;
            spdc.DstSubpass    = 0;
            spdc.SrcStageMask  = PipelineStages.ColorAttachmentOutput;
            spdc.SrcAccessMask = 0;
            spdc.DstStageMask  = PipelineStages.ColorAttachmentOutput;
            spdc.DstAccessMask = Accesses.ColorAttachmentRead | Accesses.ColorAttachmentWrite;


            RenderPassCreateInfo rpci = new RenderPassCreateInfo(
                new SubpassDescription[1] {
                spd
            },
                new AttachmentDescription[1] {
                ad
            },
                new SubpassDependency[1] {
                spdc
            });

            mRenderPass = dv.CreateRenderPass(rpci);

            GraphicsPipelineCreateInfo gplci = new GraphicsPipelineCreateInfo();

            gplci.Stages = new PipelineShaderStageCreateInfo[2] {
                plssciv, plsscif
            };
            gplci.VertexInputState   = plvisci;
            gplci.InputAssemblyState = pliasci;
            gplci.ViewportState      = plvpsci;
            gplci.RasterizationState = plrsci;
            gplci.MultisampleState   = plmssci;
            gplci.DepthStencilState  = null;
            gplci.ColorBlendState    = plcbsci;
            gplci.DynamicState       = null;
            gplci.Layout             = mPipeLayout;
            gplci.RenderPass         = mRenderPass;
            gplci.Subpass            = 0;
            gplci.BasePipelineHandle = null;
            gplci.BasePipelineIndex  = -1;

            mPipe = dv.CreateGraphicsPipeline(gplci);

            CreateSyncObjects();

            return(true);
        }
        private Pipeline CreatePipelineFromData(EngineRenderer.RenderPass aPass, PipelineVertexInputStateCreateInfo myState, PipelineLayout myLayout, List <PipelineShaderStageCreateInfo> myStages)
        {
            var scissor = new Rect2D {
                Extent = VulkanRenderer.Surface.SurfaceCapabilities.CurrentExtent
            };
            var viewportCreateInfo = new PipelineViewportStateCreateInfo
            {
                Viewports = new Viewport[] { VulkanRenderer.Viewport },
                Scissors  = new Rect2D[] { scissor }
            };

            var multisampleCreateInfo = new PipelineMultisampleStateCreateInfo
            {
                RasterizationSamples = SampleCountFlags.Count1
            };
            var colorBlendAttachmentState = new PipelineColorBlendAttachmentState
            {
                ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A
            };

            var colorBlendStateCreatInfo = new PipelineColorBlendStateCreateInfo
            {
                LogicOp     = LogicOp.Copy,
                Attachments = new PipelineColorBlendAttachmentState[] { colorBlendAttachmentState }
            };

            var rasterizationStateCreateInfo = new PipelineRasterizationStateCreateInfo
            {
                PolygonMode = PolygonMode.Fill,
                CullMode    = CullModeFlags.None,
                FrontFace   = FrontFace.Clockwise, //Todo: flip?
                LineWidth   = 1.0f
            };

            var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo
            {
                Topology = PrimitiveTopology.TriangleList
            };


            var pipelineCreateInfo = new GraphicsPipelineCreateInfo
            {
                Layout             = myLayout,
                ViewportState      = viewportCreateInfo,
                Stages             = myStages.ToArray(),
                MultisampleState   = multisampleCreateInfo,
                ColorBlendState    = colorBlendStateCreatInfo,
                RasterizationState = rasterizationStateCreateInfo,
                InputAssemblyState = inputAssemblyStateCreateInfo,
                VertexInputState   = myState,// myBuilder.GetDefaultStateCreateInfo(),
                RenderPass         = aPass,
                DepthStencilState  = new PipelineDepthStencilStateCreateInfo()
                {
                }
            };


            Debug.Assert(pipelineCreateInfo.Stages[0].Module.m == myStages[0].Module.m);
            var Result = VulkanRenderer.SelectedLogicalDevice.CreateGraphicsPipelines(myPipelineCache, new GraphicsPipelineCreateInfo[] { pipelineCreateInfo });

            pipelineCreateInfo.Dispose();
            inputAssemblyStateCreateInfo.Dispose();
            rasterizationStateCreateInfo.Dispose();
            colorBlendStateCreatInfo.Dispose();
            Debug.Assert(Result.Length == 1);
            return(Result[0]);
        }
Beispiel #14
0
        //[HandleProcessCorruptedStateExceptionsAttribute, SecurityCriticalAttribute]
        private unsafe void Recreate()
        {
            errorDuringCreate = false;

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

            PipelineShaderStageCreateInfo[] stages;

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

            var renderTargetCount = Description.Output.RenderTargetCount;

            var attachmentCount = renderTargetCount;

            if (hasDepthStencilAttachment)
            {
                attachmentCount++;
            }

            var attachments = new AttachmentDescription[attachmentCount];
            var colorAttachmentReferences = new AttachmentReference[renderTargetCount];

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

                    attachments[i] = new AttachmentDescription
                    {
                        Format                = VulkanConvertExtensions.ConvertPixelFormat(*(renderTargetFormat + i)),
                        Samples               = SampleCountFlags.Sample1,
                        LoadOperation         = currentBlendDesc->BlendEnable ? AttachmentLoadOperation.Load : AttachmentLoadOperation.DontCare, // TODO VULKAN: Only if any destination blend?
                        StoreOperation        = AttachmentStoreOperation.Store,
                        StencilLoadOperation  = AttachmentLoadOperation.DontCare,
                        StencilStoreOperation = AttachmentStoreOperation.DontCare,
                        InitialLayout         = ImageLayout.ColorAttachmentOptimal,
                        FinalLayout           = ImageLayout.ColorAttachmentOptimal,
                    };

                    colorAttachmentReferences[i] = new AttachmentReference
                    {
                        Attachment = (uint)i,
                        Layout     = ImageLayout.ColorAttachmentOptimal,
                    };
                }
            }

            if (hasDepthStencilAttachment)
            {
                attachments[attachmentCount - 1] = new AttachmentDescription
                {
                    Format                = Texture.GetFallbackDepthStencilFormat(GraphicsDevice, VulkanConvertExtensions.ConvertPixelFormat(Description.Output.DepthStencilFormat)),
                    Samples               = SampleCountFlags.Sample1,
                    LoadOperation         = AttachmentLoadOperation.Load,     // TODO VULKAN: Only if depth read enabled?
                    StoreOperation        = AttachmentStoreOperation.Store,   // TODO VULKAN: Only if depth write enabled?
                    StencilLoadOperation  = AttachmentLoadOperation.DontCare, // TODO VULKAN: Handle stencil
                    StencilStoreOperation = AttachmentStoreOperation.DontCare,
                    InitialLayout         = ImageLayout.DepthStencilAttachmentOptimal,
                    FinalLayout           = ImageLayout.DepthStencilAttachmentOptimal,
                };
            }

            var depthAttachmentReference = new AttachmentReference
            {
                Attachment = (uint)attachments.Length - 1,
                Layout     = ImageLayout.DepthStencilAttachmentOptimal,
            };

            var subpass = new SubpassDescription
            {
                PipelineBindPoint      = PipelineBindPoint.Graphics,
                ColorAttachmentCount   = (uint)renderTargetCount,
                ColorAttachments       = colorAttachmentReferences.Length > 0 ? new IntPtr(Interop.Fixed(colorAttachmentReferences)) : IntPtr.Zero,
                DepthStencilAttachment = hasDepthStencilAttachment ? new IntPtr(&depthAttachmentReference) : IntPtr.Zero,
            };

            var renderPassCreateInfo = new RenderPassCreateInfo
            {
                StructureType   = StructureType.RenderPassCreateInfo,
                AttachmentCount = (uint)attachmentCount,
                Attachments     = attachments.Length > 0 ? new IntPtr(Interop.Fixed(attachments)) : IntPtr.Zero,
                SubpassCount    = 1,
                Subpasses       = new IntPtr(&subpass)
            };

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

            ResourceGroupCount = resourceGroups.Count;

            var layouts = Description.RootSignature.EffectDescriptorSetReflection.Layouts;

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

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

            DescriptorBindingMapping = new List <DescriptorSetInfo>();

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

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

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

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

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

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

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

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

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

            // Create pipeline layout
            var nativeDescriptorSetLayout = NativeDescriptorSetLayout;
            var pipelineLayoutCreateInfo  = new PipelineLayoutCreateInfo
            {
                StructureType  = StructureType.PipelineLayoutCreateInfo,
                SetLayoutCount = 1,
                SetLayouts     = new IntPtr(&nativeDescriptorSetLayout)
            };

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

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

            stages = CreateShaderStages(Description, out inputAttributeNames);

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

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

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

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

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

                inputBindings[slotIndex].Binding   = (uint)slotIndex;
                inputBindings[slotIndex].InputRate = inputElement.InputSlotClass == InputClassification.Vertex ? VertexInputRate.Vertex : VertexInputRate.Instance;

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

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

            var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo
            {
                StructureType          = StructureType.PipelineInputAssemblyStateCreateInfo,
                Topology               = VulkanConvertExtensions.ConvertPrimitiveType(Description.PrimitiveType),
                PrimitiveRestartEnable = VulkanConvertExtensions.ConvertPrimitiveRestart(Description.PrimitiveType),
            };

            // TODO VULKAN: Tessellation and multisampling
            var multisampleState = new PipelineMultisampleStateCreateInfo
            {
                StructureType        = StructureType.PipelineMultisampleStateCreateInfo,
                RasterizationSamples = SampleCountFlags.Sample1
            };

            //var tessellationState = new PipelineTessellationStateCreateInfo();

            var rasterizationState = new PipelineRasterizationStateCreateInfo
            {
                StructureType           = StructureType.PipelineRasterizationStateCreateInfo,
                CullMode                = VulkanConvertExtensions.ConvertCullMode(Description.RasterizerState.CullMode),
                FrontFace               = Description.RasterizerState.FrontFaceCounterClockwise ? FrontFace.CounterClockwise : FrontFace.Clockwise,
                PolygonMode             = VulkanConvertExtensions.ConvertFillMode(Description.RasterizerState.FillMode),
                DepthBiasEnable         = true, // TODO VULKAN
                DepthBiasConstantFactor = Description.RasterizerState.DepthBias,
                DepthBiasSlopeFactor    = Description.RasterizerState.SlopeScaleDepthBias,
                DepthBiasClamp          = Description.RasterizerState.DepthBiasClamp,
                LineWidth               = 1.0f,
                DepthClampEnable        = !Description.RasterizerState.DepthClipEnable,
                RasterizerDiscardEnable = false,
            };

            var depthStencilState = new PipelineDepthStencilStateCreateInfo
            {
                StructureType     = StructureType.PipelineDepthStencilStateCreateInfo,
                DepthTestEnable   = Description.DepthStencilState.DepthBufferEnable,
                StencilTestEnable = Description.DepthStencilState.StencilEnable,
                DepthWriteEnable  = Description.DepthStencilState.DepthBufferWriteEnable,

                MinDepthBounds        = 0.0f,
                MaxDepthBounds        = 1.0f,
                DepthCompareOperation = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.DepthBufferFunction),
                Front = new StencilOperationState
                {
                    CompareOperation   = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.FrontFace.StencilFunction),
                    DepthFailOperation = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilDepthBufferFail),
                    FailOperation      = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilFail),
                    PassOperation      = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilPass),
                    CompareMask        = Description.DepthStencilState.StencilMask,
                    WriteMask          = Description.DepthStencilState.StencilWriteMask
                },
                Back = new StencilOperationState
                {
                    CompareOperation   = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.BackFace.StencilFunction),
                    DepthFailOperation = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilDepthBufferFail),
                    FailOperation      = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilFail),
                    PassOperation      = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilPass),
                    CompareMask        = Description.DepthStencilState.StencilMask,
                    WriteMask          = Description.DepthStencilState.StencilWriteMask
                }
            };

            var description = Description.BlendState;

            var colorBlendAttachments = new PipelineColorBlendAttachmentState[renderTargetCount];

            var renderTargetBlendState = &description.RenderTarget0;

            for (int i = 0; i < renderTargetCount; i++)
            {
                colorBlendAttachments[i] = new PipelineColorBlendAttachmentState
                {
                    BlendEnable                 = renderTargetBlendState->BlendEnable,
                    AlphaBlendOperation         = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->AlphaBlendFunction),
                    ColorBlendOperation         = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->ColorBlendFunction),
                    DestinationAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaDestinationBlend),
                    DestinationColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorDestinationBlend),
                    SourceAlphaBlendFactor      = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaSourceBlend),
                    SourceColorBlendFactor      = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorSourceBlend),
                    ColorWriteMask              = VulkanConvertExtensions.ConvertColorWriteChannels(renderTargetBlendState->ColorWriteChannels),
                };

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

            var viewportState = new PipelineViewportStateCreateInfo
            {
                StructureType = StructureType.PipelineViewportStateCreateInfo,
                ScissorCount  = 1,
                ViewportCount = 1,
            };

            fixed(void *dynamicStatesPointer   = dynamicStates.Length == 0?null : dynamicStates,
                  inputAttributesPointer       = inputAttributes.Length == 0?null : inputAttributes,
                  inputBindingsPointer         = inputBindings.Length == 0?null : inputBindings,
                  colorBlendAttachmentsPointer = colorBlendAttachments.Length == 0?null : colorBlendAttachments,
                  stagesPointer = stages.Length == 0?null : stages)
            {
                var vertexInputState = new PipelineVertexInputStateCreateInfo
                {
                    StructureType = StructureType.PipelineVertexInputStateCreateInfo,
                    VertexAttributeDescriptionCount = (uint)inputAttributeCount,
                    VertexAttributeDescriptions     = (IntPtr)inputAttributesPointer,
                    VertexBindingDescriptionCount   = (uint)inputBindingCount,
                    VertexBindingDescriptions       = (IntPtr)inputBindingsPointer,
                };

                var colorBlendState = new PipelineColorBlendStateCreateInfo
                {
                    StructureType   = StructureType.PipelineColorBlendStateCreateInfo,
                    AttachmentCount = (uint)renderTargetCount,
                    Attachments     = (IntPtr)colorBlendAttachmentsPointer,
                };

                var dynamicState = new PipelineDynamicStateCreateInfo
                {
                    StructureType     = StructureType.PipelineDynamicStateCreateInfo,
                    DynamicStateCount = (uint)dynamicStates.Length,
                    DynamicStates     = (IntPtr)dynamicStatesPointer,
                };

                var createInfo = new GraphicsPipelineCreateInfo
                {
                    StructureType = StructureType.GraphicsPipelineCreateInfo,
                    StageCount    = (uint)stages.Length,
                    Stages        = (IntPtr)stagesPointer,
                    //TessellationState = new IntPtr(&tessellationState),
                    VertexInputState   = new IntPtr(&vertexInputState),
                    InputAssemblyState = new IntPtr(&inputAssemblyState),
                    RasterizationState = new IntPtr(&rasterizationState),
                    MultisampleState   = new IntPtr(&multisampleState),
                    DepthStencilState  = new IntPtr(&depthStencilState),
                    ColorBlendState    = new IntPtr(&colorBlendState),
                    DynamicState       = new IntPtr(&dynamicState),
                    ViewportState      = new IntPtr(&viewportState),
                    Subpass            = 0,
                };

                using (GraphicsDevice.QueueLock.ReadLock())
                {
                    NativeRenderPass = GraphicsDevice.NativeDevice.CreateRenderPass(ref renderPassCreateInfo);
                    NativeLayout     = GraphicsDevice.NativeDevice.CreatePipelineLayout(ref pipelineLayoutCreateInfo);

                    createInfo.Layout     = NativeLayout;
                    createInfo.RenderPass = NativeRenderPass;

                    try {
                        NativePipeline = GraphicsDevice.NativeDevice.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo);
                    } catch (Exception e) {
                        errorDuringCreate = true;
                        NativePipeline    = Pipeline.Null;
                    }
                }
            }

            // Cleanup shader modules
            for (int i = 0; i < stages.Length; i++)
            {
                GraphicsDevice.NativeDevice.DestroyShaderModule(stages[i].Module);
            }
        }
        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 = vkDevice.CreateShaderModule(vertShaderCode);
            var fragShaderModule = vkDevice.CreateShaderModule(fragShaderCode);

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

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

            var shaderStages = new PipelineShaderStageCreateInfo[] { vertShaderStageInfo, fragShaderStageInfo };

            // VertexInput
            var vertexInputInfo = new PipelineVertexInputStateCreateInfo()
            {
                VertexBindingDescriptionCount   = 0,
                VertexBindingDescriptions       = null,
                VertexAttributeDescriptionCount = 0,
                VertexAttributeDescriptions     = null,
            };

            var inputAssembly = new PipelineInputAssemblyStateCreateInfo()
            {
                Topology = PrimitiveTopology.TriangleList,
                PrimitiveRestartEnable = false,
            };

            var viewport = new Viewport()
            {
                X        = 0f,
                Y        = 0f,
                Width    = (float)vkSwapChainExtent.Width,
                Height   = (float)vkSwapChainExtent.Height,
                MinDepth = 0f,
                MaxDepth = 1f,
            };

            var scissor = new Rect2D()
            {
                Offset = new Offset2D()
                {
                    X = 0, Y = 0
                },
                Extent = vkSwapChainExtent,
            };

            var viewportState = new PipelineViewportStateCreateInfo()
            {
                ViewportCount = 1,
                Viewports     = new Viewport[] { viewport },
                ScissorCount  = 1,
                Scissors      = new Rect2D[] { scissor },
            };

            var rasterizer = new PipelineRasterizationStateCreateInfo()
            {
                DepthClampEnable        = false,
                RasterizerDiscardEnable = false,
                PolygonMode             = PolygonMode.Fill,
                LineWidth               = 1f,
                CullMode                = CullModeFlags.Back,
                FrontFace               = FrontFace.Clockwise,
                DepthBiasEnable         = false,
                DepthBiasConstantFactor = 0f,
                DepthBiasClamp          = 0f,
                DepthBiasSlopeFactor    = 0f,
            };

            var multisampling = new PipelineMultisampleStateCreateInfo()
            {
                SampleShadingEnable   = false,
                RasterizationSamples  = SampleCountFlags.Count1,
                MinSampleShading      = 1f,
                SampleMask            = null,
                AlphaToCoverageEnable = false,
                AlphaToOneEnable      = false,
            };

            var colorBlendAttachmend = new PipelineColorBlendAttachmentState()
            {
                ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A,
                BlendEnable    = false,
            };

            var colorBlending = new PipelineColorBlendStateCreateInfo()
            {
                LogicOpEnable  = false,
                LogicOp        = LogicOp.Copy,
                Attachments    = new PipelineColorBlendAttachmentState[] { colorBlendAttachmend },
                BlendConstants = new float[] { 0f, 0f, 0f, 0f },
            };

            var pipelineLayoutInfo = new PipelineLayoutCreateInfo()
            {
                SetLayoutCount         = 0,
                PushConstantRangeCount = 0,
            };

            vkPipelineLayout = vkDevice.CreatePipelineLayout(pipelineLayoutInfo);

            var pipelineInfo = new GraphicsPipelineCreateInfo()
            {
                StageCount         = 2,
                Stages             = shaderStages,
                VertexInputState   = vertexInputInfo,
                InputAssemblyState = inputAssembly,
                ViewportState      = viewportState,
                RasterizationState = rasterizer,
                MultisampleState   = multisampling,
                DepthStencilState  = null,
                ColorBlendState    = colorBlending,
                DynamicState       = null,
                Layout             = vkPipelineLayout,
                RenderPass         = vkRenderPass,
                Subpass            = 0,
                BasePipelineHandle = null,
                BasePipelineIndex  = -1,
            };

            vkGraphicsPipeline = vkDevice.CreateGraphicsPipelines(null, new GraphicsPipelineCreateInfo[] { pipelineInfo })[0];
        }
Beispiel #16
0
        Pipeline[] CreatePipelines()
        {
            var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo {
                SetLayouts = new DescriptorSetLayout [] { descriptorSetLayout }
            };

            pipelineLayout = device.CreatePipelineLayout(pipelineLayoutCreateInfo);
            var vertexShaderModule   = device.CreateShaderModule(LoadResource("XLogo.Shaders.shader.vert.spv"));
            var fragmentShaderModule = device.CreateShaderModule(LoadResource("XLogo.Shaders.shader.frag.spv"));

            PipelineShaderStageCreateInfo [] pipelineShaderStages =
            {
                new PipelineShaderStageCreateInfo {
                    Stage  = ShaderStageFlags.Vertex,
                    Module = vertexShaderModule,
                    Name   = "main"
                },
                new PipelineShaderStageCreateInfo {
                    Stage  = ShaderStageFlags.Fragment,
                    Module = fragmentShaderModule,
                    Name   = "main"
                }
            };
            var viewport = new Viewport {
                MinDepth = 0,
                MaxDepth = 1.0f,
                Width    = surfaceCapabilities.CurrentExtent.Width,
                Height   = surfaceCapabilities.CurrentExtent.Height
            };
            var scissor = new Rect2D {
                Extent = surfaceCapabilities.CurrentExtent
            };
            var viewportCreateInfo = new PipelineViewportStateCreateInfo {
                Viewports = new Viewport [] { viewport },
                Scissors  = new Rect2D [] { scissor }
            };

            var multisampleCreateInfo = new PipelineMultisampleStateCreateInfo {
                RasterizationSamples = SampleCountFlags.Count1,
                SampleMask           = new uint [] { ~0u }
            };
            var colorBlendAttachmentState = new PipelineColorBlendAttachmentState {
                ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A
            };
            var colorBlendStateCreatInfo = new PipelineColorBlendStateCreateInfo {
                LogicOp     = LogicOp.Copy,
                Attachments = new PipelineColorBlendAttachmentState [] { colorBlendAttachmentState }
            };
            var rasterizationStateCreateInfo = new PipelineRasterizationStateCreateInfo {
                PolygonMode = PolygonMode.Fill,
                CullMode    = (uint)CullModeFlags.None,
                FrontFace   = FrontFace.Clockwise,
                LineWidth   = 1.0f
            };
            var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo {
                Topology = PrimitiveTopology.TriangleList
            };
            var vertexInputBindingDescription = new VertexInputBindingDescription {
                Stride    = 3 * sizeof(float),
                InputRate = VertexInputRate.Vertex
            };
            var vertexInputAttributeDescription = new VertexInputAttributeDescription {
                Format = Format.R32g32b32Sfloat
            };
            var vertexInputStateCreateInfo = new PipelineVertexInputStateCreateInfo {
                VertexBindingDescriptions   = new VertexInputBindingDescription [] { vertexInputBindingDescription },
                VertexAttributeDescriptions = new VertexInputAttributeDescription [] { vertexInputAttributeDescription }
            };

            var pipelineCreateInfo = new GraphicsPipelineCreateInfo {
                Layout             = pipelineLayout,
                ViewportState      = viewportCreateInfo,
                Stages             = pipelineShaderStages,
                MultisampleState   = multisampleCreateInfo,
                ColorBlendState    = colorBlendStateCreatInfo,
                RasterizationState = rasterizationStateCreateInfo,
                InputAssemblyState = inputAssemblyStateCreateInfo,
                VertexInputState   = vertexInputStateCreateInfo,
                DynamicState       = new PipelineDynamicStateCreateInfo(),
                RenderPass         = renderPass
            };

            return(device.CreateGraphicsPipelines(device.CreatePipelineCache(new PipelineCacheCreateInfo()), new GraphicsPipelineCreateInfo [] { pipelineCreateInfo }));
        }
Beispiel #17
0
        private Pipeline CreateGraphicsPipeline()
        {
            // Create shader modules. Shader modules are one of the objects required to create the
            // graphics pipeline. But after the pipeline is created, we don't need these shader
            // modules anymore, so we dispose them.
            ShaderModule vertexShader           = Content.Load <ShaderModule>("Shader.vert.spv");
            ShaderModule fragmentShader         = Content.Load <ShaderModule>("Shader.frag.spv");
            var          shaderStageCreateInfos = new[]
            {
                new PipelineShaderStageCreateInfo(ShaderStages.Vertex, vertexShader, "main"),
                new PipelineShaderStageCreateInfo(ShaderStages.Fragment, fragmentShader, "main")
            };

            var vertexInputStateCreateInfo = new PipelineVertexInputStateCreateInfo(
                new[] { new VertexInputBindingDescription(0, Interop.SizeOf <Vertex>(), VertexInputRate.Vertex) },
                new[]
            {
                new VertexInputAttributeDescription(0, 0, Format.R32G32B32SFloat, 0),      // Position.
                new VertexInputAttributeDescription(1, 0, Format.R32G32B32SFloat, 12),     // Normal.
                new VertexInputAttributeDescription(2, 0, Format.R32G32SFloat, 24)         // TexCoord.
            }
                );
            var inputAssemblyStateCreateInfo = new PipelineInputAssemblyStateCreateInfo(PrimitiveTopology.TriangleList);
            var viewportStateCreateInfo      = new PipelineViewportStateCreateInfo(
                new Viewport(0, 0, Host.Width, Host.Height),
                new Rect2D(0, 0, Host.Width, Host.Height));
            var rasterizationStateCreateInfo = new PipelineRasterizationStateCreateInfo
            {
                PolygonMode = PolygonMode.Fill,
                CullMode    = CullModes.Back,
                FrontFace   = FrontFace.CounterClockwise,
                LineWidth   = 1.0f
            };
            var multisampleStateCreateInfo = new PipelineMultisampleStateCreateInfo
            {
                RasterizationSamples = SampleCounts.Count1,
                MinSampleShading     = 1.0f
            };
            var depthStencilCreateInfo = new PipelineDepthStencilStateCreateInfo
            {
                DepthTestEnable  = true,
                DepthWriteEnable = true,
                DepthCompareOp   = CompareOp.LessOrEqual,
                Back             = new StencilOpState
                {
                    FailOp    = StencilOp.Keep,
                    PassOp    = StencilOp.Keep,
                    CompareOp = CompareOp.Always
                },
                Front = new StencilOpState
                {
                    FailOp    = StencilOp.Keep,
                    PassOp    = StencilOp.Keep,
                    CompareOp = CompareOp.Always
                }
            };
            var colorBlendAttachmentState = new PipelineColorBlendAttachmentState
            {
                SrcColorBlendFactor = BlendFactor.One,
                DstColorBlendFactor = BlendFactor.Zero,
                ColorBlendOp        = BlendOp.Add,
                SrcAlphaBlendFactor = BlendFactor.One,
                DstAlphaBlendFactor = BlendFactor.Zero,
                AlphaBlendOp        = BlendOp.Add,
                ColorWriteMask      = ColorComponents.All
            };
            var colorBlendStateCreateInfo = new PipelineColorBlendStateCreateInfo(
                new[] { colorBlendAttachmentState });

            var pipelineCreateInfo = new GraphicsPipelineCreateInfo(
                _pipelineLayout, _renderPass, 0,
                shaderStageCreateInfos,
                inputAssemblyStateCreateInfo,
                vertexInputStateCreateInfo,
                rasterizationStateCreateInfo,
                viewportState: viewportStateCreateInfo,
                multisampleState: multisampleStateCreateInfo,
                depthStencilState: depthStencilCreateInfo,
                colorBlendState: colorBlendStateCreateInfo);

            return(Context.Device.CreateGraphicsPipeline(pipelineCreateInfo));
        }
        private unsafe void Recreate()
        {
            if (Description.RootSignature == null)
                return;

            CreateRenderPass(Description);

            CreatePipelineLayout(Description);

            // Create shader stages
            Dictionary<int, string> inputAttributeNames;
            var stages = CreateShaderStages(Description, out inputAttributeNames);

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

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

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

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

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

                inputBindings[slotIndex].Binding = (uint)slotIndex;
                inputBindings[slotIndex].InputRate = inputElement.InputSlotClass == InputClassification.Vertex ? VertexInputRate.Vertex : VertexInputRate.Instance;

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

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

            var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo
            {
                StructureType = StructureType.PipelineInputAssemblyStateCreateInfo,
                Topology = VulkanConvertExtensions.ConvertPrimitiveType(Description.PrimitiveType),
                PrimitiveRestartEnable = true,
            };

            // TODO VULKAN: Tessellation and multisampling
            var multisampleState = new PipelineMultisampleStateCreateInfo
            {
                StructureType = StructureType.PipelineMultisampleStateCreateInfo,
                RasterizationSamples = SampleCountFlags.Sample1
            };

            var tessellationState = new PipelineTessellationStateCreateInfo();

            var rasterizationState = CreateRasterizationState(Description.RasterizerState);

            var depthStencilState = CreateDepthStencilState(Description);

            var description = Description.BlendState;

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

            var renderTargetBlendState = &description.RenderTarget0;
            for (int i = 0; i < renderTargetCount; i++)
            {
                colorBlendAttachments[i] = new PipelineColorBlendAttachmentState
                {
                    BlendEnable = renderTargetBlendState->BlendEnable,
                    AlphaBlendOperation = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->AlphaBlendFunction),
                    ColorBlendOperation = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->ColorBlendFunction),
                    DestinationAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaDestinationBlend),
                    DestinationColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorDestinationBlend),
                    SourceAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaSourceBlend),
                    SourceColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorSourceBlend),
                    ColorWriteMask = VulkanConvertExtensions.ConvertColorWriteChannels(renderTargetBlendState->ColorWriteChannels),
                };

                if (description.IndependentBlendEnable)
                    renderTargetBlendState++;
            }

            var viewportState = new PipelineViewportStateCreateInfo
            {
                StructureType = StructureType.PipelineViewportStateCreateInfo,
                ScissorCount = 1,
                ViewportCount = 1,
            };

            fixed (DynamicState* dynamicStatesPointer = &dynamicStates[0])
            {
                var vertexInputState = new PipelineVertexInputStateCreateInfo
                {
                    StructureType = StructureType.PipelineVertexInputStateCreateInfo,
                    VertexAttributeDescriptionCount = (uint)inputAttributeCount,
                    VertexAttributeDescriptions = inputAttributes.Length > 0 ? new IntPtr(Interop.Fixed(inputAttributes)) : IntPtr.Zero,
                    VertexBindingDescriptionCount = (uint)inputBindingCount,
                    VertexBindingDescriptions = inputBindings.Length > 0 ? new IntPtr(Interop.Fixed(inputBindings)) : IntPtr.Zero,
                };

                var colorBlendState = new PipelineColorBlendStateCreateInfo
                {
                    StructureType = StructureType.PipelineColorBlendStateCreateInfo,
                    AttachmentCount = (uint)renderTargetCount,
                    Attachments = colorBlendAttachments.Length > 0 ? new IntPtr(Interop.Fixed(colorBlendAttachments)) : IntPtr.Zero,
                };

                var dynamicState = new PipelineDynamicStateCreateInfo
                {
                    StructureType = StructureType.PipelineDynamicStateCreateInfo,
                    DynamicStateCount = (uint)dynamicStates.Length,
                    DynamicStates = new IntPtr(dynamicStatesPointer)
                };

                var createInfo = new GraphicsPipelineCreateInfo
                {
                    StructureType = StructureType.GraphicsPipelineCreateInfo,
                    Layout = NativeLayout,
                    StageCount = (uint)stages.Length,
                    Stages = stages.Length > 0 ? new IntPtr(Interop.Fixed(stages)) : IntPtr.Zero,
                    //TessellationState = new IntPtr(&tessellationState),
                    VertexInputState = new IntPtr(&vertexInputState),
                    InputAssemblyState = new IntPtr(&inputAssemblyState),
                    RasterizationState = new IntPtr(&rasterizationState),
                    MultisampleState = new IntPtr(&multisampleState),
                    DepthStencilState = new IntPtr(&depthStencilState),
                    ColorBlendState = new IntPtr(&colorBlendState),
                    DynamicState = new IntPtr(&dynamicState),
                    ViewportState = new IntPtr(&viewportState),
                    RenderPass = NativeRenderPass,
                    Subpass = 0,
                };
                NativePipeline = GraphicsDevice.NativeDevice.CreateGraphicsPipelines(PipelineCache.Null, 1, &createInfo);
            }

            // Cleanup shader modules
            foreach (var stage in stages)
            {
                GraphicsDevice.NativeDevice.DestroyShaderModule(stage.Module);
            }
        }