/*
VulkanFramework
by John Ryland
Copyright (c) 2023
*/
////////////////////////////////////////////////////////////////////////////////////
// Vulkan Pipeline
#include "VulkanPipeline.h"
namespace Vulkan {
Pipeline::Pipeline()
: m_pipeline(nullptr)
, m_pipelineLayout(nullptr)
{
}
// virtual
Pipeline::~Pipeline()
{
Destroy();
}
// virtual
void Pipeline::Destroy()
{
if (m_pipeline)
vkDestroyPipeline(m_owner->m_device, m_pipeline, nullptr);
if (m_pipelineLayout)
vkDestroyPipelineLayout(m_owner->m_device, m_pipelineLayout, nullptr);
m_pipeline = nullptr;
m_pipelineLayout = nullptr;
}
// virtual
void Pipeline::CreateLayout(Device* device)
{
m_owner = device;
VkPipelineLayoutCreateInfo pipelineLayoutInfo {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = m_descriptorSetLayout;
m_owner->CheckResult(vkCreatePipelineLayout(m_owner->m_device, &pipelineLayoutInfo, m_owner->m_allocator, &m_pipelineLayout), "failed to create pipeline layout!");
}
// ImGui, cullEnabled = false, depthEnabled = false, blendEnabled = true
// virtual
void Pipeline::Initialize(Device* device,
VkShaderModule vertexShader,
VkShaderModule fragmentShader,
VkSampleCountFlagBits msaaSamples,
bool cullEnabled,
bool depthEnabled,
bool blendEnabled)
{
m_owner = device;
VkPipelineShaderStageCreateInfo shaderStages[2] {};
shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shaderStages[0].module = vertexShader;
shaderStages[0].pName = "main";
shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
shaderStages[1].module = fragmentShader;
shaderStages[1].pName = "main";
VkPipelineVertexInputStateCreateInfo vertexInputInfo {};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = static_cast<uint32_t>(m_vertexBindingDescriptions.size());
vertexInputInfo.pVertexBindingDescriptions = m_vertexBindingDescriptions.data();
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(m_vertexAttributeDescriptions.size());
vertexInputInfo.pVertexAttributeDescriptions = m_vertexAttributeDescriptions.data();
VkPipelineInputAssemblyStateCreateInfo inputAssembly {};
inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
inputAssembly.primitiveRestartEnable = VK_FALSE;
VkPipelineViewportStateCreateInfo viewportState {};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
VkPipelineRasterizationStateCreateInfo rasterizer {};
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.cullMode = (cullEnabled) ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_NONE;
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
VkPipelineMultisampleStateCreateInfo multisampling {};
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = (msaaSamples) ? msaaSamples : VK_SAMPLE_COUNT_1_BIT;
VkPipelineDepthStencilStateCreateInfo depthStencil {};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = (depthEnabled) ? VK_TRUE : VK_FALSE;
depthStencil.depthWriteEnable = (depthEnabled) ? VK_TRUE : VK_FALSE;
depthStencil.depthCompareOp = (depthEnabled) ? VK_COMPARE_OP_LESS : VK_COMPARE_OP_NEVER;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.stencilTestEnable = VK_FALSE;
VkPipelineColorBlendAttachmentState colorBlendAttachment {};
colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
colorBlendAttachment.blendEnable = (blendEnabled) ? VK_TRUE : VK_FALSE;
colorBlendAttachment.srcColorBlendFactor = (blendEnabled) ? VK_BLEND_FACTOR_SRC_ALPHA : VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.dstColorBlendFactor = (blendEnabled) ? VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA : VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
colorBlendAttachment.srcAlphaBlendFactor = (blendEnabled) ? VK_BLEND_FACTOR_ONE : VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.dstAlphaBlendFactor = (blendEnabled) ? VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA : VK_BLEND_FACTOR_ZERO;
colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
VkPipelineColorBlendStateCreateInfo colorBlending {};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.logicOpEnable = VK_FALSE;
colorBlending.logicOp = (blendEnabled) ? VK_LOGIC_OP_CLEAR : VK_LOGIC_OP_COPY;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f;
colorBlending.blendConstants[1] = 0.0f;
colorBlending.blendConstants[2] = 0.0f;
colorBlending.blendConstants[3] = 0.0f;
VkDynamicState dynamicStates[] = { VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR };
VkPipelineDynamicStateCreateInfo dynamicState {};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = static_cast<uint32_t>(std::size(dynamicStates));
dynamicState.pDynamicStates = dynamicStates;
VkGraphicsPipelineCreateInfo pipelineInfo {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.flags = m_pipelineFlags;
pipelineInfo.stageCount = std::size(shaderStages);
pipelineInfo.pStages = shaderStages;
pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pDepthStencilState = &depthStencil;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = m_pipelineLayout;
pipelineInfo.renderPass = m_renderPass;
pipelineInfo.subpass = m_subpass;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
m_owner->CheckResult(vkCreateGraphicsPipelines(m_owner->m_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &m_pipeline), "failed to create graphics pipeline!");
}
} // Vulkan namespace