private VkPipeline CreateNewGraphicsPipeline(ref VkPipelineCacheKey cacheKey) { VkGraphicsPipelineCreateInfo pipelineCI = VkGraphicsPipelineCreateInfo.New(); // RenderPass pipelineCI.renderPass = cacheKey.RenderPass; pipelineCI.subpass = 0; pipelineCI.layout = cacheKey.PipelineLayout; // DynamicState VkPipelineDynamicStateCreateInfo dynamicStateCI = VkPipelineDynamicStateCreateInfo.New(); VkDynamicState *dynamicStates = stackalloc VkDynamicState[2]; dynamicStates[0] = VkDynamicState.Viewport; dynamicStates[1] = VkDynamicState.Scissor; dynamicStateCI.dynamicStateCount = 2; dynamicStateCI.pDynamicStates = dynamicStates; pipelineCI.pDynamicState = &dynamicStateCI; // ColorBlendState VkPipelineColorBlendAttachmentState colorBlendAttachementState = new VkPipelineColorBlendAttachmentState(); colorBlendAttachementState.colorWriteMask = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A; colorBlendAttachementState.blendEnable = cacheKey.BlendState.IsBlendEnabled; colorBlendAttachementState.srcColorBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.SourceColorBlend); colorBlendAttachementState.dstColorBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.DestinationColorBlend); colorBlendAttachementState.colorBlendOp = VkFormats.VeldridToVkBlendOp(cacheKey.BlendState.ColorBlendFunction); colorBlendAttachementState.srcAlphaBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.SourceAlphaBlend); colorBlendAttachementState.dstAlphaBlendFactor = VkFormats.VeldridToVkBlendFactor(cacheKey.BlendState.DestinationAlphaBlend); colorBlendAttachementState.alphaBlendOp = VkFormats.VeldridToVkBlendOp(cacheKey.BlendState.AlphaBlendFunction); VkPipelineColorBlendStateCreateInfo colorBlendStateCI = VkPipelineColorBlendStateCreateInfo.New(); if (cacheKey.Framebuffer.ColorTexture != null) { colorBlendStateCI.attachmentCount = 1; colorBlendStateCI.pAttachments = &colorBlendAttachementState; colorBlendStateCI.blendConstants_0 = cacheKey.BlendState.BlendFactor.R; colorBlendStateCI.blendConstants_1 = cacheKey.BlendState.BlendFactor.G; colorBlendStateCI.blendConstants_2 = cacheKey.BlendState.BlendFactor.B; colorBlendStateCI.blendConstants_3 = cacheKey.BlendState.BlendFactor.A; pipelineCI.pColorBlendState = &colorBlendStateCI; } // DepthStencilState VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = VkPipelineDepthStencilStateCreateInfo.New(); depthStencilStateCI.depthCompareOp = VkFormats.VeldridToVkDepthComparison(cacheKey.DepthStencilState.DepthComparison); depthStencilStateCI.depthWriteEnable = cacheKey.DepthStencilState.IsDepthWriteEnabled; depthStencilStateCI.depthTestEnable = cacheKey.DepthStencilState.IsDepthEnabled; pipelineCI.pDepthStencilState = &depthStencilStateCI; // MultisampleState VkPipelineMultisampleStateCreateInfo multisampleStateCI = VkPipelineMultisampleStateCreateInfo.New(); multisampleStateCI.rasterizationSamples = VkSampleCountFlags.Count1; pipelineCI.pMultisampleState = &multisampleStateCI; // RasterizationState VkPipelineRasterizationStateCreateInfo rasterizationStateCI = ((VkRasterizerState)cacheKey.RasterizerState).RasterizerStateCreateInfo; rasterizationStateCI.lineWidth = 1f; pipelineCI.pRasterizationState = &rasterizationStateCI; // ViewportState VkPipelineViewportStateCreateInfo viewportStateCI = VkPipelineViewportStateCreateInfo.New(); viewportStateCI.viewportCount = 1; viewportStateCI.scissorCount = 1; pipelineCI.pViewportState = &viewportStateCI; // InputAssemblyState VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = VkPipelineInputAssemblyStateCreateInfo.New(); inputAssemblyStateCI.topology = cacheKey.PrimitiveTopology; pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; // VertexInputState VkPipelineVertexInputStateCreateInfo vertexInputStateCI = VkPipelineVertexInputStateCreateInfo.New(); VertexInputDescription[] inputDescriptions = cacheKey.ShaderSet.InputLayout.InputDescriptions; uint bindingCount = (uint)inputDescriptions.Length; uint attributeCount = (uint)inputDescriptions.Sum(desc => desc.Elements.Length); VkVertexInputBindingDescription * bindingDescs = stackalloc VkVertexInputBindingDescription[(int)bindingCount]; VkVertexInputAttributeDescription *attributeDescs = stackalloc VkVertexInputAttributeDescription[(int)attributeCount]; int targetIndex = 0; int targetLocation = 0; for (int binding = 0; binding < inputDescriptions.Length; binding++) { VertexInputDescription inputDesc = inputDescriptions[binding]; bindingDescs[targetIndex] = new VkVertexInputBindingDescription() { binding = (uint)binding, inputRate = (inputDesc.Elements[0].StorageClassifier == VertexElementInputClass.PerInstance) ? VkVertexInputRate.Instance : VkVertexInputRate.Vertex, stride = ((VkVertexBuffer)cacheKey.VertexBindings[binding]).Stride }; uint currentOffset = 0; for (int location = 0; location < inputDesc.Elements.Length; location++) { VertexInputElement inputElement = inputDesc.Elements[location]; attributeDescs[targetIndex] = new VkVertexInputAttributeDescription() { format = VkFormats.VeldridToVkVertexElementFormat(inputElement.ElementFormat), binding = (uint)binding, location = (uint)(targetLocation + location), offset = currentOffset }; targetIndex += 1; currentOffset += inputElement.SizeInBytes; } targetLocation += inputDesc.Elements.Length; } vertexInputStateCI.vertexBindingDescriptionCount = bindingCount; vertexInputStateCI.pVertexBindingDescriptions = bindingDescs; vertexInputStateCI.vertexAttributeDescriptionCount = attributeCount; vertexInputStateCI.pVertexAttributeDescriptions = attributeDescs; pipelineCI.pVertexInputState = &vertexInputStateCI; // ShaderStage StackList <VkPipelineShaderStageCreateInfo> shaderStageCIs = new StackList <VkPipelineShaderStageCreateInfo>(); VkPipelineShaderStageCreateInfo vertexStage = VkPipelineShaderStageCreateInfo.New(); vertexStage.stage = VkShaderStageFlags.Vertex; vertexStage.module = cacheKey.ShaderSet.VertexShader.ShaderModule; vertexStage.pName = CommonStrings.main; shaderStageCIs.Add(vertexStage); VkPipelineShaderStageCreateInfo fragmentStage = VkPipelineShaderStageCreateInfo.New(); fragmentStage.stage = VkShaderStageFlags.Fragment; fragmentStage.module = cacheKey.ShaderSet.FragmentShader.ShaderModule; fragmentStage.pName = CommonStrings.main; shaderStageCIs.Add(fragmentStage); if (cacheKey.ShaderSet.TessellationControlShader != null) { VkPipelineShaderStageCreateInfo tcStage = VkPipelineShaderStageCreateInfo.New(); tcStage.stage = VkShaderStageFlags.TessellationControl; tcStage.module = cacheKey.ShaderSet.TessellationControlShader.ShaderModule; tcStage.pName = CommonStrings.main; shaderStageCIs.Add(tcStage); } if (cacheKey.ShaderSet.TessellationEvaluationShader != null) { VkPipelineShaderStageCreateInfo teStage = VkPipelineShaderStageCreateInfo.New(); teStage.stage = VkShaderStageFlags.TessellationEvaluation; teStage.module = cacheKey.ShaderSet.TessellationEvaluationShader.ShaderModule; teStage.pName = CommonStrings.main; shaderStageCIs.Add(teStage); } if (cacheKey.ShaderSet.GeometryShader != null) { VkPipelineShaderStageCreateInfo geometryStage = VkPipelineShaderStageCreateInfo.New(); geometryStage.stage = VkShaderStageFlags.Geometry; geometryStage.module = cacheKey.ShaderSet.GeometryShader.ShaderModule; geometryStage.pName = CommonStrings.main; shaderStageCIs.Add(geometryStage); } pipelineCI.stageCount = shaderStageCIs.Count; pipelineCI.pStages = (VkPipelineShaderStageCreateInfo *)shaderStageCIs.Data; VkResult result = vkCreateGraphicsPipelines(_device, VkPipelineCache.Null, 1, ref pipelineCI, null, out VkPipeline ret); CheckResult(result); return(ret); }