Skip to content

Commit

Permalink
[*] Add a graphics pipeline wrapper and builder
Browse files Browse the repository at this point in the history
  • Loading branch information
IAmNotHanni committed Mar 12, 2023
1 parent 7d2fc47 commit 0efd073
Show file tree
Hide file tree
Showing 8 changed files with 551 additions and 85 deletions.
4 changes: 3 additions & 1 deletion include/inexor/vulkan-renderer/render_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "inexor/vulkan-renderer/wrapper/fence.hpp"
#include "inexor/vulkan-renderer/wrapper/framebuffer.hpp"
#include "inexor/vulkan-renderer/wrapper/image.hpp"
#include "inexor/vulkan-renderer/wrapper/pipeline.hpp"
#include "inexor/vulkan-renderer/wrapper/pipeline_builder.hpp"
#include "inexor/vulkan-renderer/wrapper/pipeline_layout.hpp"
#include "inexor/vulkan-renderer/wrapper/renderpass.hpp"
#include "inexor/vulkan-renderer/wrapper/semaphore.hpp"
Expand Down Expand Up @@ -349,8 +351,8 @@ class PhysicalStage : public RenderGraphObject {
friend RenderGraph;

private:
VkPipeline m_pipeline{VK_NULL_HANDLE};
std::unique_ptr<wrapper::PipelineLayout> m_pipeline_layout;
std::unique_ptr<wrapper::GraphicsPipeline> m_pipeline;

protected:
const wrapper::Device &m_device;
Expand Down
39 changes: 39 additions & 0 deletions include/inexor/vulkan-renderer/wrapper/pipeline.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include <vulkan/vulkan_core.h>

#include <string>

namespace inexor::vulkan_renderer::wrapper {

// Forward declaration
class Device;

// TODO: Compute pipelines

/// RAII wrapper for VkPipeline
class GraphicsPipeline {
private:
const Device &m_device;
VkPipeline m_pipeline{VK_NULL_HANDLE};
std::string m_name;

public:
/// Default constructor
/// @param device The device wrapper
/// @param pipeline_ci The pipeline create info
/// @param name The internal debug name of the graphics pipeline
GraphicsPipeline(const Device &device, const VkGraphicsPipelineCreateInfo &pipeline_ci, std::string name);
GraphicsPipeline(const GraphicsPipeline &) = delete;
GraphicsPipeline(GraphicsPipeline &&) noexcept;
~GraphicsPipeline();

GraphicsPipeline &operator=(const GraphicsPipeline &) = delete;
GraphicsPipeline &operator=(GraphicsPipeline &&) = delete;

[[nodiscard]] VkPipeline pipeline() const noexcept {
return m_pipeline;
}
};

} // namespace inexor::vulkan_renderer::wrapper
214 changes: 214 additions & 0 deletions include/inexor/vulkan-renderer/wrapper/pipeline_builder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
#pragma once

#include <vulkan/vulkan_core.h>

#include "inexor/vulkan-renderer/wrapper/make_info.hpp"
#include "inexor/vulkan-renderer/wrapper/pipeline.hpp"

#include <memory>
#include <string>
#include <vector>

namespace inexor::vulkan_renderer::wrapper {

// Forward declarations
class Device;

/// Builder class for VkPipelineCreateInfo
class GraphicsPipelineBuilder {
private:
const Device &m_device;
VkPipelineVertexInputStateCreateInfo m_vertex_input_sci{make_info<VkPipelineVertexInputStateCreateInfo>()};

VkPipelineInputAssemblyStateCreateInfo m_input_assembly_sci{make_info<VkPipelineInputAssemblyStateCreateInfo>({
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
.primitiveRestartEnable = VK_FALSE,
})};

VkPipelineTessellationStateCreateInfo m_tesselation_sci{make_info<VkPipelineTessellationStateCreateInfo>()};
VkPipelineViewportStateCreateInfo m_viewport_sci{make_info<VkPipelineViewportStateCreateInfo>()};

VkPipelineRasterizationStateCreateInfo m_rasterization_sci{make_info<VkPipelineRasterizationStateCreateInfo>({
.polygonMode = VK_POLYGON_MODE_FILL,
.cullMode = VK_CULL_MODE_BACK_BIT,
.frontFace = VK_FRONT_FACE_CLOCKWISE,
.lineWidth = 1.0f,
})};

// TODO: Support more options for multisampling
VkPipelineMultisampleStateCreateInfo m_multisample_sci{make_info<VkPipelineMultisampleStateCreateInfo>({
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
.minSampleShading = 1.0f,
})};

VkPipelineDepthStencilStateCreateInfo m_depth_stencil_sci{make_info<VkPipelineDepthStencilStateCreateInfo>()};
VkPipelineColorBlendStateCreateInfo m_color_blend_sci{make_info<VkPipelineColorBlendStateCreateInfo>()};
VkPipelineDynamicStateCreateInfo m_dynamic_states_sci{make_info<VkPipelineDynamicStateCreateInfo>()};

VkPipelineLayout m_pipeline_layout{VK_NULL_HANDLE};
VkRenderPass m_render_pass{VK_NULL_HANDLE};

std::vector<VkDynamicState> m_dynamic_states;
std::vector<VkViewport> m_viewports;
std::vector<VkRect2D> m_scissors;
std::vector<VkPipelineShaderStageCreateInfo> m_shader_stages;
std::vector<VkVertexInputBindingDescription> m_vertex_input_binding_descriptions;
std::vector<VkVertexInputAttributeDescription> m_vertex_input_attribute_descriptions;
std::vector<VkPipelineColorBlendAttachmentState> m_color_blend_attachment_states;

public:
/// Default constructor
/// @param device The device wrapper
GraphicsPipelineBuilder(const Device &device);
GraphicsPipelineBuilder(const GraphicsPipelineBuilder &) = delete;
GraphicsPipelineBuilder(GraphicsPipelineBuilder &&other) noexcept;
~GraphicsPipelineBuilder() = default;

GraphicsPipelineBuilder &operator=(const GraphicsPipelineBuilder &) = delete;
GraphicsPipelineBuilder &operator=(GraphicsPipelineBuilder &&) = delete;

/// Add a shader stage
/// @param shader_stage The shader stage to add
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &add_shader(const VkPipelineShaderStageCreateInfo &shader_stage);

/// Add a vertex input attribute description
/// @param description The vertex input attribute description
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &
add_vertex_input_attribute(const VkVertexInputAttributeDescription &description);

/// Add a vertex input binding description
/// @param description The vertex input binding descriptions
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &add_vertex_input_binding(const VkVertexInputBindingDescription &description);

/// Add a color blend attachment
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &
add_color_blend_attachment(const VkPipelineColorBlendAttachmentState &attachment);

/// Build the graphics pipeline with specified pipeline create flags
/// @param create_flags The pipeline create flags
/// @param name The debug name of the graphics pipeline
[[nodiscard]] std::unique_ptr<GraphicsPipeline> build(std::string name);

/// Set the color blend state manually
/// @param color_blend_state The color blend state
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &
set_color_blend(const VkPipelineColorBlendStateCreateInfo &color_blend_state);

/// Set all color blend attachments manually
/// @note You should prefer to use `add_color_blend_attachment` instead
/// @param attachments The color blend attachments
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &
set_color_blend_attachments(const std::vector<VkPipelineColorBlendAttachmentState> &attachments);

/// Enables or disabled culling
/// @warning Disabling culling will have a significant performance impact
/// @param culling_enabled ``true`` if culling is enabled
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_culling_mode(VkBool32 culling_enabled);

/// Set the depth stencil state
/// @param depth_stencil The depth stencil state
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &
set_depth_stencil(const VkPipelineDepthStencilStateCreateInfo &depth_stencil);

/// Set the dynamic states of the graphics pipeline
/// @param dynamic_states The dynamic states of the graphics pipeline
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_dynamic_states(const std::vector<VkDynamicState> &dynamic_states);

/// Set the input assembly state create info
/// @note If you just want to set the triangle topology, call ``set_triangle_topology`` instead, because this is the
/// most powerful method of this method in case you really need to overwrite it
/// @param input_assembly_sci The pipeline input state create info
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &
set_input_assembly(const VkPipelineInputAssemblyStateCreateInfo &input_assembly_sci);

/// Set the line width of rasterization
/// @param line_width The line width of rasterization
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_line_width(float width);

/// Store the pipeline layout
/// @param layout The pipeline layout
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_pipeline_layout(VkPipelineLayout layout);

/// Set the triangle topology
/// @param topology the primitive topology
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_primitive_topology(VkPrimitiveTopology topology);

/// Set the rasterization state of the graphics pipeline manually
/// @param rasterization_state The rasterization state
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &
set_rasterization(const VkPipelineRasterizationStateCreateInfo &rasterization);

/// Set the render pass
/// @param render_pass The render pass
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_render_pass(VkRenderPass render_pass);

/// Set the scissor data in VkPipelineViewportStateCreateInfo
/// There is another method called set_scissors in case multiple scissors will be used
/// @param scissors The scissors in in VkPipelineViewportStateCreateInfo
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_scissor(const VkRect2D &scissor);

/// Set the viewport data in VkPipelineViewportStateCreateInfo
/// There is another method called set_scissors in case multiple scissors will be used
/// @param scissor The scissor in in VkPipelineViewportStateCreateInfo
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_scissors(const std::vector<VkRect2D> &scissors);

/// Set the shader stage
/// @param shader_stages The shader stages
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &
set_shaders(const std::vector<VkPipelineShaderStageCreateInfo> &shader_stages);

/// Set the tesselation state create info
/// @param control_points The tesselation control point count
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_tesselation(std::uint32_t control_points);

/// Set the vertex input attribute descriptions manually
/// You should prefer to use ``add_vertex_input_attribute`` instead
/// @param descriptions The vertex input attribute descriptions
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &
set_vertex_input_attributes(const std::vector<VkVertexInputAttributeDescription> &descriptions);

/// Set the vertex input binding descriptions manually
/// You should prefer to use ``add_vertex_input_binding`` instead
/// @param descriptions The vertex input binding descriptions
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &
set_vertex_input_bindings(const std::vector<VkVertexInputBindingDescription> &descriptions);

/// Set the viewport in VkPipelineViewportStateCreateInfo
/// There is another method called set_viewports in case multiple viewports will be used
/// @param viewport The viewport in VkPipelineViewportStateCreateInfo
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_viewport(const VkViewport &viewport);

/// Set the viewport in VkPipelineViewportStateCreateInfo
/// @param viewports The viewports in VkPipelineViewportStateCreateInfo
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_viewports(const std::vector<VkViewport> &viewports);

/// Set the wireframe mode
/// @param wireframe ``true`` if wireframe is enabled
/// @return A reference to the dereferenced this pointer (allows method calls to be chained)
[[nodiscard]] GraphicsPipelineBuilder &set_wireframe(VkBool32 wireframe);
};

} // namespace inexor::vulkan_renderer::wrapper
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ set(INEXOR_SOURCE_FILES
vulkan-renderer/wrapper/gpu_texture.cpp
vulkan-renderer/wrapper/image.cpp
vulkan-renderer/wrapper/instance.cpp
vulkan-renderer/wrapper/pipeline.cpp
vulkan-renderer/wrapper/pipeline_builder.cpp
vulkan-renderer/wrapper/pipeline_layout.cpp
vulkan-renderer/wrapper/make_info.cpp
vulkan-renderer/wrapper/renderpass.cpp
Expand Down
Loading

0 comments on commit 0efd073

Please sign in to comment.