private void CreateGraphicsPipeline() { byte[] vertShaderCode = File.ReadAllBytes("Shaders/vert.spv"); byte[] fragShaderCode = File.ReadAllBytes("Shaders/frag.spv"); VkShaderModule vertShaderModule = this.CreateShaderModule(vertShaderCode); VkShaderModule fragShaderModule = this.CreateShaderModule(fragShaderCode); VkPipelineShaderStageCreateInfo vertShaderStageInfo = new VkPipelineShaderStageCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, stage = VkShaderStageFlags.VK_SHADER_STAGE_VERTEX_BIT, module = vertShaderModule, pName = "main".ToPointer(), }; VkPipelineShaderStageCreateInfo fragShaderStageInfo = new VkPipelineShaderStageCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, stage = VkShaderStageFlags.VK_SHADER_STAGE_FRAGMENT_BIT, module = fragShaderModule, pName = "main".ToPointer(), }; VkPipelineShaderStageCreateInfo *shaderStages = stackalloc VkPipelineShaderStageCreateInfo[] { vertShaderStageInfo, fragShaderStageInfo }; // Vertex Input VkPipelineVertexInputStateCreateInfo vertexInputInfo = new VkPipelineVertexInputStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, vertexBindingDescriptionCount = 0, pVertexBindingDescriptions = null, // Optional vertexAttributeDescriptionCount = 0, pVertexAttributeDescriptions = null, // Optional }; // Input assembly VkPipelineInputAssemblyStateCreateInfo inputAssembly = new VkPipelineInputAssemblyStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, topology = VkPrimitiveTopology.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, primitiveRestartEnable = false, }; // Viewports and scissors VkViewport viewport = new VkViewport() { x = 0.0f, y = 0.0f, width = (float)swapChainExtent.width, height = (float)swapChainExtent.height, minDepth = 0.0f, maxDepth = 1.0f, }; VkRect2D scissor = new VkRect2D() { offset = new VkOffset2D(0, 0), extent = swapChainExtent, }; VkPipelineViewportStateCreateInfo viewportState = new VkPipelineViewportStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, viewportCount = 1, pViewports = &viewport, scissorCount = 1, pScissors = &scissor, }; // Rasterizer VkPipelineRasterizationStateCreateInfo rasterizer = new VkPipelineRasterizationStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, depthClampEnable = false, rasterizerDiscardEnable = false, polygonMode = VkPolygonMode.VK_POLYGON_MODE_FILL, lineWidth = 1.0f, cullMode = VkCullModeFlags.VK_CULL_MODE_BACK_BIT, frontFace = VkFrontFace.VK_FRONT_FACE_CLOCKWISE, depthBiasEnable = false, depthBiasConstantFactor = 0.0f, // Optional depthBiasClamp = 0.0f, // Optional depthBiasSlopeFactor = 0.0f, // Optional }; VkPipelineMultisampleStateCreateInfo multisampling = new VkPipelineMultisampleStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, sampleShadingEnable = false, rasterizationSamples = VkSampleCountFlags.VK_SAMPLE_COUNT_1_BIT, minSampleShading = 1.0f, // Optional pSampleMask = null, // Optional alphaToCoverageEnable = false, // Optional alphaToOneEnable = false, // Optional }; // Depth and Stencil testing //VkPipelineDepthStencilStateCreateInfo // Color blending VkPipelineColorBlendAttachmentState colorBlendAttachment = new VkPipelineColorBlendAttachmentState() { colorWriteMask = VkColorComponentFlags.VK_COLOR_COMPONENT_R_BIT | VkColorComponentFlags.VK_COLOR_COMPONENT_G_BIT | VkColorComponentFlags.VK_COLOR_COMPONENT_B_BIT | VkColorComponentFlags.VK_COLOR_COMPONENT_A_BIT, blendEnable = false, srcColorBlendFactor = VkBlendFactor.VK_BLEND_FACTOR_ONE, // Optional dstColorBlendFactor = VkBlendFactor.VK_BLEND_FACTOR_ZERO, // Optional colorBlendOp = VkBlendOp.VK_BLEND_OP_ADD, // Optional srcAlphaBlendFactor = VkBlendFactor.VK_BLEND_FACTOR_ONE, // Optional dstAlphaBlendFactor = VkBlendFactor.VK_BLEND_FACTOR_ZERO, // Optional alphaBlendOp = VkBlendOp.VK_BLEND_OP_ADD, // Optional }; VkPipelineColorBlendStateCreateInfo colorBlending = new VkPipelineColorBlendStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, logicOpEnable = false, logicOp = VkLogicOp.VK_LOGIC_OP_COPY, // Optional attachmentCount = 1, pAttachments = &colorBlendAttachment, blendConstants_0 = 0.0f, // Optional blendConstants_1 = 0.0f, // Optional blendConstants_2 = 0.0f, // Optional blendConstants_3 = 0.0f, // Optional }; VkPipelineLayoutCreateInfo pipelineLayoutInfo = new VkPipelineLayoutCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, setLayoutCount = 0, // Optional pSetLayouts = null, // Optional pushConstantRangeCount = 0, // Optional pPushConstantRanges = null, // Optional }; fixed(VkPipelineLayout *pipelineLayoutPtr = &pipelineLayout) { Helpers.CheckErrors(VulkanNative.vkCreatePipelineLayout(device, &pipelineLayoutInfo, null, pipelineLayoutPtr)); } VkGraphicsPipelineCreateInfo pipelineInfo = new VkGraphicsPipelineCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, stageCount = 2, pStages = shaderStages, pVertexInputState = &vertexInputInfo, pInputAssemblyState = &inputAssembly, pViewportState = &viewportState, pRasterizationState = &rasterizer, pMultisampleState = &multisampling, pDepthStencilState = null, // Optional pColorBlendState = &colorBlending, pDynamicState = null, // Optional layout = this.pipelineLayout, renderPass = this.renderPass, subpass = 0, basePipelineHandle = 0, // Optional basePipelineIndex = -1, // Optional }; fixed(VkPipeline *graphicsPipelinePtr = &this.graphicsPipeline) { Helpers.CheckErrors(VulkanNative.vkCreateGraphicsPipelines(this.device, 0, 1, &pipelineInfo, null, graphicsPipelinePtr)); } VulkanNative.vkDestroyShaderModule(device, fragShaderModule, null); VulkanNative.vkDestroyShaderModule(device, vertShaderModule, null); }
private void CreateGraphicsPipeline() { // Shader stages var vertShaderCode = System.IO.File.ReadAllBytes("Shaders/vert.spv"); var fragShaderCode = System.IO.File.ReadAllBytes("Shaders/frag.spv"); var vertShaderModule = CreateShaderModule(vertShaderCode); var fragShaderModule = CreateShaderModule(fragShaderCode); string name = "main"; int byteCount = System.Text.Encoding.UTF8.GetByteCount(name); byte * utf8Ptr = stackalloc byte[byteCount]; fixed(char *namePtr = name) { System.Text.Encoding.UTF8.GetBytes(namePtr, name.Length, utf8Ptr, byteCount); } var vertShaderStageInfo = new VkPipelineShaderStageCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, stage = VkShaderStageFlagBits.VK_SHADER_STAGE_VERTEX_BIT, module = vertShaderModule, pName = utf8Ptr, }; var fragShaderStageInfo = new VkPipelineShaderStageCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, stage = VkShaderStageFlagBits.VK_SHADER_STAGE_FRAGMENT_BIT, module = fragShaderModule, pName = utf8Ptr, }; var shaderStages = stackalloc VkPipelineShaderStageCreateInfo[] { vertShaderStageInfo, fragShaderStageInfo }; // VertexInput var vertexInputInfo = new VkPipelineVertexInputStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, vertexBindingDescriptionCount = 0, pVertexBindingDescriptions = null, vertexAttributeDescriptionCount = 0, pVertexAttributeDescriptions = null, }; var inputAssembly = new VkPipelineInputAssemblyStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, topology = VkPrimitiveTopology.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, primitiveRestartEnable = false, }; var viewport = new VkViewport() { x = 0f, y = 0f, width = (float)vkSwapChainExtent.width, height = (float)vkSwapChainExtent.height, minDepth = 0f, maxDepth = 1f, }; var scissor = new VkRect2D() { offset = new VkOffset2D() { x = 0, y = 0 }, extent = vkSwapChainExtent, }; var viewportState = new VkPipelineViewportStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, viewportCount = 1, pViewports = &viewport, scissorCount = 1, pScissors = &scissor, }; var rasterizer = new VkPipelineRasterizationStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, depthClampEnable = false, rasterizerDiscardEnable = false, polygonMode = VkPolygonMode.VK_POLYGON_MODE_FILL, lineWidth = 1f, cullMode = VkCullModeFlagBits.VK_CULL_MODE_BACK_BIT, frontFace = VkFrontFace.VK_FRONT_FACE_CLOCKWISE, depthBiasEnable = false, depthBiasConstantFactor = 0f, depthBiasClamp = 0f, depthBiasSlopeFactor = 0f, }; var multisampling = new VkPipelineMultisampleStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, sampleShadingEnable = false, rasterizationSamples = VkSampleCountFlagBits.VK_SAMPLE_COUNT_1_BIT, minSampleShading = 1f, pSampleMask = null, alphaToCoverageEnable = false, alphaToOneEnable = false, }; var colorBlendAttachment = new VkPipelineColorBlendAttachmentState() { colorWriteMask = VkColorComponentFlagBits.VK_COLOR_COMPONENT_R_BIT | VkColorComponentFlagBits.VK_COLOR_COMPONENT_G_BIT | VkColorComponentFlagBits.VK_COLOR_COMPONENT_B_BIT | VkColorComponentFlagBits.VK_COLOR_COMPONENT_A_BIT, blendEnable = false, }; var colorBlending = new VkPipelineColorBlendStateCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, logicOpEnable = false, logicOp = VkLogicOp.VK_LOGIC_OP_COPY, pAttachments = &colorBlendAttachment, attachmentCount = 1, blendConstants_0 = 0f, blendConstants_1 = 0f, blendConstants_2 = 0f, blendConstants_3 = 0f, }; var pipelineLayoutInfo = new VkPipelineLayoutCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, setLayoutCount = 0, pushConstantRangeCount = 0, }; VkPipelineLayout newPipelineLayout; var result = VulkanNative.vkCreatePipelineLayout(vkDevice, &pipelineLayoutInfo, null, &newPipelineLayout); vkPipelineLayout = newPipelineLayout; Helpers.CheckErrors(result); var pipelineInfo = new VkGraphicsPipelineCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, stageCount = 2, pStages = shaderStages, pVertexInputState = &vertexInputInfo, pInputAssemblyState = &inputAssembly, pViewportState = &viewportState, pRasterizationState = &rasterizer, pMultisampleState = &multisampling, pDepthStencilState = null, pColorBlendState = &colorBlending, pDynamicState = null, layout = vkPipelineLayout, renderPass = vkRenderPass, subpass = 0, basePipelineHandle = 0, basePipelineIndex = -1, }; VkPipeline newPipeline; result = VulkanNative.vkCreateGraphicsPipelines(vkDevice, 0, 1, &pipelineInfo, null, &newPipeline); vkGraphicsPipeline = newPipeline; Helpers.CheckErrors(result); VulkanNative.vkDestroyShaderModule(vkDevice, vertShaderModule, null); VulkanNative.vkDestroyShaderModule(vkDevice, fragShaderModule, null); }
public unsafe GraphicsPipeline( Device device, RenderPass renderPass, List <DescriptorLayout> layouts, List <ShaderModule> shaders, PipelineInputBuilder pipelineInputBuilder, uint subPass = 0, PipelineOptions options = null ) : base(device, renderPass, VkPipelineLayout.Null, VkPipeline.Null) { if (options == null) { options = PipelineOptions.Default; } #region Pipeline Layout var setLayout = new NativeList <VkDescriptorSetLayout>(); foreach (var layout in layouts) { setLayout.Add(layout.Handle); } var pipelineLayoutInfo = new VkPipelineLayoutCreateInfo { sType = VkStructureType.PipelineLayoutCreateInfo, setLayoutCount = setLayout.Count, pSetLayouts = (VkDescriptorSetLayout *)setLayout.Data.ToPointer() }; VkPipelineLayout pipelineLayout; if (VulkanNative.vkCreatePipelineLayout( device.Handle, &pipelineLayoutInfo, null, &pipelineLayout ) != VkResult.Success) { throw new Exception("failed to create pipeline layout"); } _layout = pipelineLayout; #endregion var bindingDescriptions = pipelineInputBuilder.BindingDescriptions; var attributeDescriptions = pipelineInputBuilder.AttributeDescriptions; var vertexInputInfo = new VkPipelineVertexInputStateCreateInfo { sType = VkStructureType.PipelineVertexInputStateCreateInfo, vertexBindingDescriptionCount = bindingDescriptions.Count, pVertexBindingDescriptions = (VkVertexInputBindingDescription *)bindingDescriptions.Data.ToPointer(), vertexAttributeDescriptionCount = attributeDescriptions.Count, pVertexAttributeDescriptions = (VkVertexInputAttributeDescription *)attributeDescriptions.Data.ToPointer() }; var inputAssemble = new VkPipelineInputAssemblyStateCreateInfo { sType = VkStructureType.PipelineInputAssemblyStateCreateInfo, topology = options.Topology, primitiveRestartEnable = VkBool32.False }; var viewport = new VkViewport(); //dynamic (ignored) var scissor = new VkRect2D(); //dynamic (ignored) var viewportState = new VkPipelineViewportStateCreateInfo { sType = VkStructureType.PipelineViewportStateCreateInfo, viewportCount = 1, pViewports = &viewport, scissorCount = 1, pScissors = &scissor }; var rasterizer = new VkPipelineRasterizationStateCreateInfo { sType = VkStructureType.PipelineRasterizationStateCreateInfo, depthClampEnable = false, rasterizerDiscardEnable = VkBool32.False, polygonMode = options.PolygonMode, lineWidth = 1.0f, cullMode = options.CullMode, frontFace = options.FrontFace, depthBiasEnable = VkBool32.False }; var multisampling = new VkPipelineMultisampleStateCreateInfo { sType = VkStructureType.PipelineMultisampleStateCreateInfo, sampleShadingEnable = VkBool32.False, rasterizationSamples = VkSampleCountFlags.Count1, minSampleShading = 1.0f, pSampleMask = null, alphaToCoverageEnable = VkBool32.False, alphaToOneEnable = VkBool32.False }; bool hasDepthAttachment = false; var colorBlendAttachments = new NativeList <VkPipelineColorBlendAttachmentState>(); foreach (var attachment in renderPass.Attachments) { if ((attachment.ImageUsageFlags & VkImageUsageFlags.DepthStencilAttachment) != 0) { hasDepthAttachment = true; continue; } colorBlendAttachments.Add(new VkPipelineColorBlendAttachmentState { colorWriteMask = ( VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A ), blendEnable = VkBool32.False, }); } var depthStencil = new VkPipelineDepthStencilStateCreateInfo { sType = VkStructureType.PipelineDepthStencilStateCreateInfo, depthTestEnable = VkBool32.True, depthWriteEnable = VkBool32.True, depthCompareOp = VkCompareOp.Less, depthBoundsTestEnable = VkBool32.False, stencilTestEnable = VkBool32.False, }; var colorBlending = new VkPipelineColorBlendStateCreateInfo { sType = VkStructureType.PipelineColorBlendStateCreateInfo, logicOpEnable = VkBool32.False, logicOp = VkLogicOp.Copy, attachmentCount = colorBlendAttachments.Count, pAttachments = (VkPipelineColorBlendAttachmentState *)colorBlendAttachments.Data.ToPointer(), blendConstants_0 = 0.0f, blendConstants_1 = 0.0f, blendConstants_2 = 0.0f, blendConstants_3 = 0.0f }; var dynamicStates = new NativeList <VkDynamicState>(); dynamicStates.Add(VkDynamicState.Viewport); dynamicStates.Add(VkDynamicState.Scissor); dynamicStates.Add(VkDynamicState.LineWidth); var dynamicStateInfo = new VkPipelineDynamicStateCreateInfo { sType = VkStructureType.PipelineDynamicStateCreateInfo, dynamicStateCount = dynamicStates.Count, pDynamicStates = (VkDynamicState *)dynamicStates.Data.ToPointer() }; var shaderInfo = new NativeList <VkPipelineShaderStageCreateInfo>(); foreach (var shader in shaders) { shaderInfo.Add(new VkPipelineShaderStageCreateInfo { sType = VkStructureType.PipelineShaderStageCreateInfo, module = shader.Handle, stage = (VkShaderStageFlags)shader.Type, pName = GraphicsApiConstants.MAIN }); } var pipelineInfo = new VkGraphicsPipelineCreateInfo { sType = VkStructureType.GraphicsPipelineCreateInfo, stageCount = shaderInfo.Count, pStages = (VkPipelineShaderStageCreateInfo *)shaderInfo.Data.ToPointer(), pVertexInputState = &vertexInputInfo, pInputAssemblyState = &inputAssemble, pViewportState = &viewportState, pRasterizationState = &rasterizer, pMultisampleState = &multisampling, pDepthStencilState = hasDepthAttachment ? &depthStencil : null, pColorBlendState = &colorBlending, pDynamicState = &dynamicStateInfo, layout = _layout, renderPass = _renderPass.Handle, subpass = subPass, basePipelineHandle = VkPipeline.Null, basePipelineIndex = -1 }; VkPipeline pipeline; if (VulkanNative.vkCreateGraphicsPipelines( _device.Handle, VkPipelineCache.Null, 1, &pipelineInfo, null, &pipeline ) != VkResult.Success) { throw new Exception("faield to create graphics pipeline"); } _handle = pipeline; }