Files
basalt/include/vulkan/basalt_pipeline.h
Riley King-Saunders 4ad064578d Renamed argument when providing array of vertex binding attributes to reflect that they are, in fact attributes and not the binding description
Extended pipeline to support adding vertex bindings
Vertex bindings can now be added via a template function that assumes that the type implements the following;
 - A function matching the signature of PFN_GetVertexInputBindingDescription and with the name get_binding_description
 - A function matching the signature of PFN_GetVertexAttributeDescriptions and with the name get_attribute_descriptions
GetVertexAttributeDescriptions should set the num_attachments to the number of attachments if and only if the attachment output pointer is nullptr. If the output pointer is not nullptr, num_attachments should be treated as a size. Return VK_SUCCESS on success, or a different value otherwise.
2025-07-10 21:56:14 +10:00

92 lines
3.9 KiB
C++

#pragma once
#include "vulkan/basalt_render_pass.h"
namespace basalt
{
typedef VkVertexInputBindingDescription (*PFN_GetVertexInputBindingDescription)(void);
typedef VkResult(*PFN_GetVertexAttributeDescriptions)(VkVertexInputAttributeDescription* out_attachments, u32* num_attachments);
class Pipeline
{
public:
Pipeline(const Pipeline& src) = delete;
Pipeline& operator =(const Pipeline& src) = delete;
Pipeline(Pipeline&& other) noexcept;
Pipeline& operator =(Pipeline&& other) noexcept;
Pipeline(basalt::Device& device, VkPipeline pipeline, VkPipelineLayout layout);
~Pipeline();
void swap(Pipeline& other) noexcept;
VkPipeline vk = VK_NULL_HANDLE;
VkPipelineLayout layout = VK_NULL_HANDLE;
basalt::Device* device = nullptr;
bool should_free = true;
};
class PipelineBuilder
{
public:
PipelineBuilder(basalt::Device& device, VkExtent2D extent, VkPipeline previous_pipeline=VK_NULL_HANDLE);
~PipelineBuilder();
PipelineBuilder& add_shader(const char* fpath, VkShaderStageFlagBits stage, const char* entry="main");
PipelineBuilder& add_dynamic_state(const VkDynamicState state);
PipelineBuilder& add_dynamic_states(const VkDynamicState* states, const u32 num_states);
PipelineBuilder& add_dynamic_states(const basalt::darray<VkDynamicState>& states);
PipelineBuilder& set_render_pass(VkRenderPass render_pass);
PipelineBuilder& add_colour_attachment(VkPipelineColorBlendAttachmentState attachment);
PipelineBuilder& add_vertex_binding(VkVertexInputBindingDescription binding, VkVertexInputAttributeDescription* attributes, u32 num_attributes);
template <typename T>
PipelineBuilder& add_vertex_binding(void);
Pipeline build();
VkPipelineRasterizationStateCreateInfo raster_ci;
VkPipelineColorBlendStateCreateInfo colour_blend_ci;
VkPipelineLayoutCreateInfo layout_ci;
VkPipelineVertexInputStateCreateInfo vertex_ci;
VkPipelineMultisampleStateCreateInfo multisample_ci;
VkPipelineViewportStateCreateInfo viewport_ci;
VkPipelineInputAssemblyStateCreateInfo assembly_ci;
VkPipelineDynamicStateCreateInfo dynamic_state_ci;
basalt::darray<VkVertexInputAttributeDescription> vertex_input_attributes;
basalt::darray<VkVertexInputBindingDescription> vertex_binding_description;
basalt::darray<VkShaderModule> shader_modules;
basalt::darray<VkPipelineShaderStageCreateInfo> shader_stages;
basalt::darray<VkPipelineColorBlendAttachmentState> colour_attachments;
basalt::darray<VkDynamicState> dynamic_states;
VkViewport viewport;
VkRect2D scissor;
basalt::Device& device;
VkRenderPass render_pass = VK_NULL_HANDLE;
VkPipeline previous_pipeline = VK_NULL_HANDLE;
protected:
/// <summary>
/// Will read all of the contents of a file into outptr
/// Should outptr not be big enough or nullptr, it will be allocated
/// If it is not big enough it will be reallocated
/// </summary>
/// <param name="fpath">Path to the file to read</param>
/// <param name="outptr">A reference to a pointer that may be updated</param>
/// <param name="size">Size of an existing allocation associated with outptr</param>
/// <returns>Number of bytes read from the file</returns>
static size_t read_file(const char* fpath, char*& outptr, size_t& outptr_size);
};
template<typename T>
inline PipelineBuilder& PipelineBuilder::add_vertex_binding(void)
{
VkResult err = VK_SUCCESS;
this->vertex_binding_description.push_back(T::get_binding_description());
u32 sz = 0;
VK_ASSERT(T::get_attribute_descriptions(nullptr, &sz), "Failed to get number of vertex attribute descriptions for object\n\tAt %s:%d\n\tError %s\n\tObject %s\n", typeid(T).name());
this->vertex_input_attributes.expand(sz);
VK_ASSERT(T::get_attribute_descriptions(this->vertex_input_attributes.end(), &sz), "Failed to get vertex attribute descriptions for object\n\tAt %s:%d\n\tError %s\n\tObject %s\n", typeid(T).name());
this->vertex_input_attributes.resize(this->vertex_input_attributes.m_nelements + sz);
return *this;
}
}