Exemple #1
0
        /// <summary>
        /// Create a new pipeline with the given description, for use in the given renderer and subpass.
        /// </summary>
        /// <param name="description">The description of the pipeline states to build into the pipeline.</param>
        /// <param name="renderer">The renderer to use the pipeline in.</param>
        /// <param name="subpass">The subpass index within the renderer to use the pipeline in.</param>
        public Pipeline(PipelineDescription description, Renderer renderer, uint subpass)
            : base(ResourceType.Pipeline)
        {
            // Create the pipeline handle
            Handle = CreatePipeline(description, renderer, subpass, out var cache);
            if (renderer.MSAALayout is not null)
            {
                BuildCache = cache;                 // Only save cache if we might rebuild from MSAA change
            }

            // Assign fields
            Layout = description.Shader !.Layout;
            Layout.IncRefCount();
            ShaderProgram = description.Shader.Program;
            ShaderProgram.IncRefCount();
            Renderer = renderer;
            Subpass  = subpass;

            // Assign values
            VertexBindingCount = (uint)cache.VertexBindings.Length;

            // Register to the renderer
            renderer.AddPipeline(this);
        }
Exemple #2
0
        // Internal constructor
        internal Material(ShaderLayout layout, ShaderProgram program, MaterialInput input, MaterialOutput output)
        {
            // Assign objects
            Layout  = layout;
            Program = program;
            Layout.IncRefCount();
            Program.IncRefCount();
            Input  = input;
            Output = output;

            // Validate vertex inputs
            if (input.Vertices.Count > 0)
            {
                uint vmask = 0;
                foreach (var vd in input.Vertices)
                {
                    if ((vmask & vd.LocationMask) != 0)
                    {
                        throw new ArgumentException("Duplicate vertex location in descriptions", nameof(input));
                    }
                    vmask |= vd.LocationMask;
                }
                if (vmask != Layout.VertexLocationMask)
                {
                    throw new ArgumentException(
                              $"Missing vertex location in material descriptions ({vmask:X8} != {Layout.VertexLocationMask:X8})",
                              nameof(input));
                }
            }

            // Validate outputs
            if (output.BlendStates.Count != layout.FragmentOutputs.Count)
            {
                throw new ArgumentException("Output count mismatch", nameof(output));
            }
        }
Exemple #3
0
        // Create a pipeline from a set of build states and a shader
        private static VkPipeline CreatePipeline(BuildStates states, Renderer renderer, uint subpass,
                                                 ShaderLayout shaderLayout, ShaderProgram shaderProgram)
        {
            var MAIN_STR = stackalloc byte[5] {
                (byte)'m', (byte)'a', (byte)'i', (byte)'n', (byte)'\0'
            };

            // Color blends
            var cblends = stackalloc VkPipelineColorBlendAttachmentState[states.ColorBlends.Length];

            for (int i = 0; i < states.ColorBlends.Length; ++i)
            {
                states.ColorBlends[i].ToVk(out cblends[i]);
            }
            VkPipelineColorBlendStateCreateInfo colorBlendCI = new(
                flags : VkPipelineColorBlendStateCreateFlags.NoFlags,
                logicOpEnable : false,                // TODO: Maybe enable this in the future
                logicOp : VkLogicOp.Clear,
                attachmentCount : (uint)states.ColorBlends.Length,
                attachments : cblends,
                blendConstants_0 : states.BlendConstants.R,
                blendConstants_1 : states.BlendConstants.G,
                blendConstants_2 : states.BlendConstants.B,
                blendConstants_3 : states.BlendConstants.A
                );

            // Inferred state objects
            VkPipelineMultisampleStateCreateInfo msaaCI = new(
                flags : VkPipelineMultisampleStateCreateFlags.NoFlags,
                rasterizationSamples : (VkSampleCountFlags)renderer.MSAA,
                sampleShadingEnable : false,                // TODO: Allow sample shading
                minSampleShading : 0,
                sampleMask : null,
                alphaToCoverageEnable : false,
                alphaToOneEnable : false
                );

            // Constant state objects
            var dynstates = stackalloc VkDynamicState[2] {
                VkDynamicState.Viewport, VkDynamicState.Scissor
            };
            VkViewport viewport = new();
            VkRect2D   scissor  = new();
            VkPipelineViewportStateCreateInfo viewportCI = new(             // Dummy value b/c dynamic state
                flags : VkPipelineViewportStateCreateFlags.NoFlags,
                viewportCount : 1,
                viewports : &viewport,
                scissorCount : 1,
                scissors : &scissor
                );
            VkPipelineDynamicStateCreateInfo dynamicCI = new(
                flags : VkPipelineDynamicStateCreateFlags.NoFlags,
                dynamicStateCount : 2,
                dynamicStates : dynstates
                );

            // Shader create info
            var stageCIs = shaderProgram.EnumerateModules().Select(mod => new VkPipelineShaderStageCreateInfo(
                                                                       flags: VkPipelineShaderStageCreateFlags.NoFlags,
                                                                       stage: (VkShaderStageFlags)mod.stage,
                                                                       module: mod.mod,
                                                                       name: MAIN_STR,
                                                                       specializationInfo: null // TODO: Public API for specialization
                                                                       )).ToArray();

            VkPipelineTessellationStateCreateInfo.New(out var tessCI);

            // State cached objects
            states.DepthStencil.ToVk(out var depthStencilCI);
            states.VertexInput.ToVk(out var vertexInputCI);
            states.RasterizerState.ToVk(out var rasterCI);

            // Create the pipeline
            fixed(VkPipelineShaderStageCreateInfo *stagePtr = stageCIs)
            fixed(VkVertexInputAttributeDescription * attributePtr = states.VertexAttributes)
            fixed(VkVertexInputBindingDescription * bindingPtr     = states.VertexBindings)
            {
                // Additional create objects
                VkPipelineVertexInputStateCreateInfo vertexCI = new(
                    flags : VkPipelineVertexInputStateCreateFlags.NoFlags,
                    vertexBindingDescriptionCount : (uint)states.VertexBindings.Length,
                    vertexBindingDescriptions : bindingPtr,
                    vertexAttributeDescriptionCount : (uint)states.VertexAttributes.Length,
                    vertexAttributeDescriptions : attributePtr
                    );

                // Create info
                VkGraphicsPipelineCreateInfo ci = new(
                    flags : VkPipelineCreateFlags.NoFlags,                    // TODO: see if we can utilize some of the flags
                    stageCount : (uint)stageCIs.Length,
                    stages : stagePtr,
                    vertexInputState : &vertexCI,
                    inputAssemblyState : &vertexInputCI,
                    tessellationState : &tessCI,
                    viewportState : &viewportCI,
                    rasterizationState : &rasterCI,
                    multisampleState : &msaaCI,
                    depthStencilState : &depthStencilCI,
                    colorBlendState : &colorBlendCI,
                    dynamicState : &dynamicCI,
                    layout : shaderLayout.PipelineLayout,
                    renderPass : renderer.RenderPass,
                    subpass : subpass,
                    basePipelineHandle : VulkanHandle <VkPipeline> .Null,
                    basePipelineIndex : 0
                    );
                VulkanHandle <VkPipeline> pipelineHandle;

                renderer.Graphics.Resources.PipelineCache.CreateGraphicsPipelines(1, &ci, null, &pipelineHandle)
                .Throw("Failed to recreate pipeline object");
                return(new(pipelineHandle, renderer.Graphics.VkDevice));
            }
        }