#pragma once #include namespace orange { struct MiniPipelineInfo { VkShaderModule vs; VkShaderModule fs; VkPipelineLayout pipelineLayout; VkFormat colorFormat; VkFormat depthFormat; bool enableDepthTest; bool enableDepthWrites; Span vertexAttributes; }; static VulkanResult CreateGraphicsPipeline(VkDevice device, const MiniPipelineInfo& info) { VkPipelineShaderStageCreateInfo stages[] = { { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .stage = VK_SHADER_STAGE_VERTEX_BIT, .module = info.vs, .pName = "main", }, { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .stage = VK_SHADER_STAGE_FRAGMENT_BIT, .module = info.fs, .pName = "main", }, }; Array dynamicStates = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, }; VkPipelineDynamicStateCreateInfo dynamicStateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, .dynamicStateCount = uint32_t(dynamicStates.size()), .pDynamicStates = dynamicStates.data(), }; VkVertexInputBindingDescription inputBindingDescription = { .binding = 0, .stride = sizeof(StaticVertex), .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, }; VkPipelineVertexInputStateCreateInfo vertexInputInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .vertexBindingDescriptionCount = info.vertexAttributes.size ? 1u : 0u, .pVertexBindingDescriptions = &inputBindingDescription, .vertexAttributeDescriptionCount = uint32_t(info.vertexAttributes.size), .pVertexAttributeDescriptions = info.vertexAttributes.data, }; VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, .primitiveRestartEnable = VK_FALSE, }; VkPipelineViewportStateCreateInfo viewportStateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, .viewportCount = 1, .scissorCount = 1, }; VkPipelineRasterizationStateCreateInfo rasterizationInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .cullMode = VK_CULL_MODE_BACK_BIT, .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, .lineWidth = 1.0f, }; VkPipelineMultisampleStateCreateInfo multisampleInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, }; VkPipelineDepthStencilStateCreateInfo depthStencilInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, .depthTestEnable = info.enableDepthTest, .depthWriteEnable = info.enableDepthWrites, .depthCompareOp = VK_COMPARE_OP_LESS, .minDepthBounds = 0.0f, .maxDepthBounds = 1.0f, }; VkPipelineColorBlendAttachmentState attachmentBlendState = { .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, }; VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, .attachmentCount = 1, .pAttachments = &attachmentBlendState, }; VkPipelineRenderingCreateInfo renderingInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, .viewMask = 0u, .colorAttachmentCount = 1u, .pColorAttachmentFormats = &info.colorFormat, .depthAttachmentFormat = info.depthFormat, }; VkGraphicsPipelineCreateInfo pipelineInfo = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = &renderingInfo, .stageCount = Size(stages), .pStages = stages, .pVertexInputState = &vertexInputInfo, .pInputAssemblyState = &inputAssemblyInfo, .pViewportState = &viewportStateInfo, .pRasterizationState = &rasterizationInfo, .pMultisampleState = &multisampleInfo, .pDepthStencilState = &depthStencilInfo, .pColorBlendState = &colorBlendStateInfo, .pDynamicState = &dynamicStateInfo, .layout = info.pipelineLayout, }; VkPipeline pipeline = VK_NULL_HANDLE; VkResult res = VK_SUCCESS; if ((res = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline)) != VK_SUCCESS) return VulkanResult::Error(res); return VulkanResult::Success(pipeline); } }