#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& 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 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 vertex_input_attributes; basalt::darray vertex_binding_description; basalt::darray shader_modules; basalt::darray shader_stages; basalt::darray colour_attachments; basalt::darray dynamic_states; VkViewport viewport; VkRect2D scissor; basalt::Device& device; VkRenderPass render_pass = VK_NULL_HANDLE; VkPipeline previous_pipeline = VK_NULL_HANDLE; protected: /// /// 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 /// /// Path to the file to read /// A reference to a pointer that may be updated /// Size of an existing allocation associated with outptr /// Number of bytes read from the file static size_t read_file(const char* fpath, char*& outptr, size_t& outptr_size); }; template 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; } }