Files
FGL-Engine/src/engine/rendering/pipelines/v2/PipelineBuilder.cpp
2024-10-12 08:33:17 -04:00

265 lines
8.6 KiB
C++

//
// Created by kj16609 on 10/10/24.
//
#include "PipelineBuilder.hpp"
#include "AttachmentBuilder.hpp"
#include "Pipeline.hpp"
#include "engine/descriptors/DescriptorSetLayout.hpp"
namespace fgl::engine
{
PipelineBuilder::PipelineBuilder( vk::raii::RenderPass& renderpass, const std::uint32_t subpass_stage ) :
m_render_pass( renderpass ),
subpass_idx( subpass_stage )
{
addDynamicState( vk::DynamicState::eViewport );
addDynamicState( vk::DynamicState::eScissor );
}
descriptors::DescriptorSetLayout empty_set_layout { descriptors::DescriptorSetLayout::createEmptySet() };
vk::raii::PipelineLayout PipelineBuilder::createLayout()
{
vk::PipelineLayoutCreateInfo info {};
std::vector< vk::DescriptorSetLayout > set_layouts {};
set_layouts.reserve( descriptor_set_layouts.size() );
SetID max_set_idx { 0 };
for ( const auto& [ set_idx, _ ] : descriptor_set_layouts )
{
max_set_idx = std::max( max_set_idx, set_idx );
}
// Any sets not used, Should be set to VK_NULL_HANDLE
set_layouts.resize( max_set_idx + 1 );
for ( std::size_t i = 0; i < set_layouts.size(); ++i )
{
auto itter { descriptor_set_layouts.find( static_cast< SetID >( i ) ) };
if ( itter == descriptor_set_layouts.end() )
{
// Could not find it. Empty
set_layouts[ i ] = empty_set_layout.layout();
continue;
}
else
{
set_layouts[ i ] = itter->second;
continue;
}
}
for ( const auto& [ set_idx, layout ] : descriptor_set_layouts )
{
log::debug( "{} populated", set_idx );
set_layouts[ set_idx ] = layout;
}
info.setSetLayouts( set_layouts );
return Device::getInstance()->createPipelineLayout( info );
}
void PipelineBuilder::
addDescriptorSet( const SetID idx, const vk::raii::DescriptorSetLayout& descriptor_set_layout )
{
FGL_ASSERT( !descriptor_set_layouts.contains( idx ), "Descriptor already set!" );
log::debug( "Setting descriptor layout for set idx {}", idx );
descriptor_set_layouts.insert( std::make_pair( idx, *descriptor_set_layout ) );
}
void PipelineBuilder::addDescriptorSet( descriptors::DescriptorSetLayout& descriptor )
{
return addDescriptorSet( descriptor.m_set_idx, descriptor.layout() );
}
void PipelineBuilder::addDynamicState( vk::DynamicState dynamic_state )
{
m_dynamic_state.emplace_back( dynamic_state );
}
[[nodiscard]] vk::PipelineColorBlendAttachmentState& PipelineBuilder::Config::addColorAttachment()
{
color_blend_attachment.emplace_back();
color_blend_info.setAttachments( color_blend_attachment );
return color_blend_attachment.back();
}
PipelineBuilder::Config::Config()
{
viewport_info.viewportCount = 1;
viewport_info.pViewports = nullptr;
viewport_info.scissorCount = 1;
viewport_info.pScissors = nullptr;
assembly_info.topology = vk::PrimitiveTopology::eTriangleList;
assembly_info.primitiveRestartEnable = VK_FALSE;
rasterization_info.depthClampEnable = VK_FALSE;
rasterization_info.rasterizerDiscardEnable = VK_FALSE;
rasterization_info.polygonMode = vk::PolygonMode::eFill;
rasterization_info.cullMode = vk::CullModeFlagBits::eBack;
rasterization_info.frontFace = vk::FrontFace::eClockwise;
rasterization_info.depthBiasEnable = VK_FALSE;
rasterization_info.depthBiasConstantFactor = 0.0f;
rasterization_info.depthBiasClamp = 0.0f;
rasterization_info.depthBiasSlopeFactor = 0.0f;
rasterization_info.lineWidth = 1.0f;
multisample_info.rasterizationSamples = vk::SampleCountFlagBits::e1;
multisample_info.sampleShadingEnable = VK_FALSE;
multisample_info.minSampleShading = 1.0f;
multisample_info.pSampleMask = nullptr;
multisample_info.alphaToCoverageEnable = VK_FALSE;
multisample_info.alphaToOneEnable = VK_FALSE;
color_blend_info.logicOpEnable = VK_FALSE;
color_blend_info.logicOp = vk::LogicOp::eCopy;
color_blend_info.attachmentCount = 0;
color_blend_info.pAttachments = nullptr;
color_blend_info.blendConstants[ 0 ] = 0.0f;
color_blend_info.blendConstants[ 1 ] = 0.0f;
color_blend_info.blendConstants[ 2 ] = 0.0f;
color_blend_info.blendConstants[ 3 ] = 0.0f;
depth_stencil_info.depthTestEnable = VK_TRUE;
depth_stencil_info.depthWriteEnable = VK_TRUE;
depth_stencil_info.depthCompareOp = vk::CompareOp::eLess;
depth_stencil_info.depthBoundsTestEnable = VK_FALSE;
depth_stencil_info.stencilTestEnable = VK_FALSE;
//depth_stencil_info.front = {};
//depth_stencil_info.back = {};
depth_stencil_info.minDepthBounds = 0.0f;
depth_stencil_info.maxDepthBounds = 1.0f;
dynamic_state_enables = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
dynamic_state_info.setDynamicStates( dynamic_state_enables );
//info.dynamic_state_info.flags = 0;
}
void PipelineBuilder::setTopology( const vk::PrimitiveTopology primitive_topology )
{
config.assembly_info.topology = primitive_topology;
}
void PipelineBuilder::disableVertexInput()
{
vertex_input_descriptions.bindings = {};
vertex_input_descriptions.attributes = {};
}
void PipelineBuilder::disableCulling()
{
config.rasterization_info.cullMode = vk::CullModeFlagBits::eNone;
}
AttachmentBuilder PipelineBuilder::addAttachment()
{
return { *this };
}
AttachmentBuilder PipelineBuilder::addColorAttachment()
{
AttachmentBuilder builder { addAttachment() };
return builder;
}
void PipelineBuilder::setBindingDescriptions( const std::vector< vk::VertexInputBindingDescription >& descriptions )
{
vertex_input_descriptions.bindings = descriptions;
}
void PipelineBuilder::setAttributeDescriptions( const std::vector< vk::VertexInputAttributeDescription >&
descriptions )
{
vertex_input_descriptions.attributes = descriptions;
}
std::unique_ptr< Pipeline > PipelineBuilder::create()
{
// Precheck
{
FGL_ASSERT( shaders.fragment, "Pipeline requires fragment shader" );
FGL_ASSERT( shaders.vertex, "Pipeline requires vertex shader" );
}
vk::raii::PipelineLayout layout { createLayout() };
vk::GraphicsPipelineCreateInfo info {};
info.pNext = VK_NULL_HANDLE;
info.flags = {};
m_stages.clear();
if ( shaders.vertex ) m_stages.emplace_back( shaders.vertex->stage_info );
if ( shaders.fragment ) m_stages.emplace_back( shaders.fragment->stage_info );
info.setStages( m_stages );
vk::PipelineVertexInputStateCreateInfo vertex_input_info {};
vertex_input_info.pNext = VK_NULL_HANDLE;
vertex_input_info.flags = {};
vertex_input_info.setVertexBindingDescriptions( vertex_input_descriptions.bindings );
vertex_input_info.setVertexAttributeDescriptions( vertex_input_descriptions.attributes );
info.setPVertexInputState( &vertex_input_info );
info.pInputAssemblyState = &config.assembly_info;
info.pTessellationState = &config.tesselation_state_info;
info.pViewportState = &config.viewport_info;
info.pRasterizationState = &config.rasterization_info;
info.pMultisampleState = &config.multisample_info;
info.pDepthStencilState = &config.depth_stencil_info;
config.color_blend_info.setAttachments( config.color_blend_attachment );
info.pColorBlendState = &config.color_blend_info;
info.pDynamicState = &config.dynamic_state_info;
info.layout = layout;
info.renderPass = m_render_pass;
info.subpass = subpass_idx;
//TODO: Figure out what these do
info.basePipelineHandle = VK_NULL_HANDLE;
info.basePipelineIndex = -1;
vk::PipelineDynamicStateCreateInfo dynamic_state_create_info {};
dynamic_state_create_info.setDynamicStates( m_dynamic_state );
if ( m_dynamic_state.size() > 0 ) info.setPDynamicState( &dynamic_state_create_info );
vk::raii::Pipeline pipeline { Device::getInstance()->createGraphicsPipeline( VK_NULL_HANDLE, info ) };
return std::make_unique< Pipeline >( std::move( pipeline ), std::move( layout ) );
}
void setGBufferOutputAttachments( PipelineBuilder::Config& config )
{
// In order for the pipeline to output, We need to ensure that we have enough attachments for the entire gbuffer (3)
FGL_ASSERT( config.color_blend_attachment.size() == 0, "GBuffer output expected there to be no other outputs" );
for ( int i = 0; i < 3; ++i )
{
auto& color_config { config.addColorAttachment() };
color_config.blendEnable = VK_FALSE;
color_config.srcColorBlendFactor = vk::BlendFactor::eOne;
color_config.dstColorBlendFactor = vk::BlendFactor::eZero;
color_config.colorBlendOp = vk::BlendOp::eAdd;
color_config.srcAlphaBlendFactor = vk::BlendFactor::eOne;
color_config.dstAlphaBlendFactor = vk::BlendFactor::eZero;
color_config.alphaBlendOp = vk::BlendOp::eAdd;
color_config.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG
| vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;
}
}
} // namespace fgl::engine