示例#1
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)) { }
                            }
        }
        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);
            }
        }
        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);
            }
        }