sandbox
Loading...
Searching...
No Matches
graphics_pipeline.hpp
1#ifndef LIBSBX_GRAPHICS_PIPELINE_GRAPHICS_PIPELINE_HPP_
2#define LIBSBX_GRAPHICS_PIPELINE_GRAPHICS_PIPELINE_HPP_
3
4#include <optional>
5#include <filesystem>
6#include <cinttypes>
7#include <vector>
8#include <unordered_map>
9#include <map>
10#include <memory>
11
12#include <vulkan/vulkan.hpp>
13
14#include <fmt/format.h>
15
16#include <libsbx/utility/enum.hpp>
17
18#include <libsbx/containers/static_vector.hpp>
19
20#include <libsbx/graphics/buffers/buffer.hpp>
21#include <libsbx/graphics/buffers/uniform_handler.hpp>
22
23#include <libsbx/graphics/pipeline/shader.hpp>
24#include <libsbx/graphics/pipeline/pipeline.hpp>
25#include <libsbx/graphics/pipeline/compiler.hpp>
26#include <libsbx/graphics/pipeline/vertex_input_description.hpp>
27
28#include <libsbx/graphics/descriptor/descriptor.hpp>
29#include <libsbx/graphics/descriptor/descriptor_set.hpp>
30
31#include <libsbx/graphics/images/image2d.hpp>
32
33#include <libsbx/graphics/render_graph.hpp>
34#include <libsbx/graphics/resource_storage.hpp>
35
36namespace sbx::graphics {
37
38enum class polygon_mode : std::uint8_t {
39 fill = VK_POLYGON_MODE_FILL,
40 line = VK_POLYGON_MODE_LINE,
41 point = VK_POLYGON_MODE_POINT
42}; // enum class polygon_mode
43
44enum class cull_mode : std::uint8_t {
45 none = VK_CULL_MODE_NONE,
46 front = VK_CULL_MODE_FRONT_BIT,
47 back = VK_CULL_MODE_BACK_BIT,
48 front_and_back = VK_CULL_MODE_FRONT_AND_BACK
49}; // enum class cull_mode
50
51enum class front_face : std::uint8_t {
52 counter_clockwise = VK_FRONT_FACE_COUNTER_CLOCKWISE,
53 clockwise = VK_FRONT_FACE_CLOCKWISE
54}; // enum class front_face
55
56struct depth_bias {
57 std::float_t constant_factor{0.0f};
58 std::float_t clamp{0.0f};
59 std::float_t slope_factor{0.0f};
60}; // struct depth_bias
61
63 graphics::polygon_mode polygon_mode{graphics::polygon_mode::fill};
64 std::float_t line_width{1.0f};
65 graphics::cull_mode cull_mode{graphics::cull_mode::back};
66 graphics::front_face front_face{graphics::front_face::counter_clockwise};
67 std::optional<graphics::depth_bias> depth_bias{};
68}; // struct rasterization_state
69
70enum class primitive_topology : std::uint8_t {
71 point_list = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
72 line_list = VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
73 line_strip = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
74 triangle_list = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
75 triangle_strip = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
76 triangle_fan = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
77 line_list_with_adjacency = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
78 line_strip_with_adjacency = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
79 triangle_list_with_adjacency = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
80 triangle_strip_with_adjacency = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
81 patch_list = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
82}; // enum class primitive_topology
83
84enum class depth : std::uint8_t {
85 disabled = 0,
86 read_write = 1,
87 read_only = 2
88}; // enum class depth_test
89
90enum class compare_operation : std::uint8_t {
91 never = VK_COMPARE_OP_NEVER,
92 less = VK_COMPARE_OP_LESS,
93 equal = VK_COMPARE_OP_EQUAL,
94 less_or_equal = VK_COMPARE_OP_LESS_OR_EQUAL,
95 greater = VK_COMPARE_OP_GREATER,
96 not_equal = VK_COMPARE_OP_NOT_EQUAL,
97 greater_or_equal = VK_COMPARE_OP_GREATER_OR_EQUAL,
98 always = VK_COMPARE_OP_ALWAYS
99}; // enum class compare_operation
100
102 graphics::depth depth{graphics::depth::read_write};
103 graphics::compare_operation compare_operation{graphics::compare_operation::less_or_equal};
104 bool uses_transparency{false};
106 graphics::primitive_topology primitive_topology{graphics::primitive_topology::triangle_list};
108}; // struct pipeline_definition
109
111
112 using base = pipeline;
113
114 struct rendering_create_info {
115 VkPipelineRenderingCreateInfo info;
116 std::vector<VkFormat> color_formats;
117 VkFormat depth_format;
118 VkFormat stencil_format;
119 }; // struct rendering_create_info
120
121public:
122
124 std::string name{};
125 std::unordered_map<SlangStage, std::vector<std::uint32_t>> shader_codes{};
126 }; // struct compiled_shaders
127
128 graphics_pipeline(const std::filesystem::path& path, const render_graph::graphics_pass& pass, const pipeline_definition& default_definition = pipeline_definition{}, const VkSpecializationInfo* specialization_info = nullptr);
129
130 graphics_pipeline(const compiled_shaders& shaders, const render_graph::graphics_pass& pass, const pipeline_definition& default_definition = pipeline_definition{}, const VkSpecializationInfo* specialization_info = nullptr);
131
132 ~graphics_pipeline() override;
133
134 auto handle() const noexcept -> VkPipeline override;
135
136 auto has_variable_descriptors() const noexcept -> bool override {
137 return _has_variable_descriptors;
138 }
139
140 auto descriptor_counts(std::uint32_t set) const noexcept -> std::vector<std::uint32_t> override {
141 auto counts = std::vector<std::uint32_t>{};
142
143 for (const auto& binding_data : _set_data[set].binding_data) {
144 counts.push_back(binding_data.descriptor_count);
145 }
146
147 return counts;
148 }
149
150 auto descriptor_set_layout(std::uint32_t set) const noexcept -> VkDescriptorSetLayout override;
151
152 auto descriptor_pool() const noexcept -> VkDescriptorPool override;
153
154 auto layout() const noexcept -> VkPipelineLayout override;
155
156 auto bind_point() const noexcept -> VkPipelineBindPoint override;
157
158 auto descriptor_block(const std::string& name, std::uint32_t set) const -> const shader::uniform_block& override {
159 if (auto it = _set_data[set].uniform_blocks.find(name); it != _set_data[set].uniform_blocks.end()) {
160 return it->second;
161 }
162
163 throw std::runtime_error(fmt::format("Failed to find descriptor block '{}' in graphics pipeline '{}'", name, _name));
164 }
165
166 auto push_constant() const noexcept -> const std::optional<shader::uniform_block>& override {
167 return _push_constant;
168 }
169
170 auto find_descriptor_binding(const std::string& name, std::uint32_t set) const -> std::optional<std::uint32_t> override {
171 if (auto it = _set_data[set].descriptor_bindings.find(name); it != _set_data[set].descriptor_bindings.end()) {
172 return it->second;
173 }
174
175 return std::nullopt;
176 }
177
178 auto find_descriptor_type_at_binding(std::uint32_t set, std::uint32_t binding) const -> std::optional<VkDescriptorType> override {
179 if (_set_data[set].binding_data.size() <= binding) {
180 return std::nullopt;
181 }
182
183 return _set_data[set].binding_data[binding].descriptor_type;
184 }
185
186 auto rendering_info() -> const rendering_create_info& {
187 return _rendering_info;
188 }
189
190private:
191
192 struct per_binding_data {
193 VkDescriptorType descriptor_type;
194 std::uint32_t descriptor_count;
195 }; // struct per_binding_data
196
197 struct per_set_data {
198 std::unordered_map<std::string, shader::uniform> uniforms;
199 std::unordered_map<std::string, shader::uniform_block> uniform_blocks;
200 std::unordered_map<std::string, std::uint32_t> descriptor_bindings;
201 std::unordered_map<std::string, std::uint32_t> descriptor_sizes;
202 std::vector<per_binding_data> binding_data;
203 VkDescriptorSetLayout layout;
204 }; // struct per_set_data
205
206 auto _initialize(const pipeline_definition& definition, const VkSpecializationInfo* specialization_info) -> void;
207
208 auto _update_definition(const std::filesystem::path& path, const pipeline_definition default_definition) -> pipeline_definition;
209
210 auto _get_stage_from_name(const std::string& name) const noexcept -> VkShaderStageFlagBits;
211
212 render_graph::graphics_pass _pass;
213
214 std::unordered_map<VkShaderStageFlagBits, std::unique_ptr<shader>> _shaders{};
215
216 std::vector<per_set_data> _set_data;
217 std::optional<shader::uniform_block> _push_constant;
218
219 std::string _name{};
220 VkPipelineLayout _layout{};
221 VkPipeline _handle{};
222 VkPipelineBindPoint _bind_point{};
223 bool _has_variable_descriptors{};
224
225 rendering_create_info _rendering_info;
226
227 VkDescriptorPool _descriptor_pool{};
228
229}; // class graphics_pipeline
230
231using graphics_pipeline_handle = resource_handle<graphics_pipeline>;
232
233} // namespace sbx::graphics
234
235template<>
236struct sbx::utility::enum_mapping<sbx::graphics::polygon_mode> {
237
239
240 static constexpr auto values = std::array<entry_type, 3u>{
241 entry_type{sbx::graphics::polygon_mode::fill, "fill"},
242 entry_type{sbx::graphics::polygon_mode::line, "line"},
243 entry_type{sbx::graphics::polygon_mode::point, "point"}
244 };
245
246}; // struct sbx::utility::enum_mapping
247
248template<>
249struct sbx::utility::enum_mapping<sbx::graphics::depth> {
250
252
253 static constexpr auto values = std::array<entry_type, 3u>{
254 entry_type{sbx::graphics::depth::disabled, "disabled"},
255 entry_type{sbx::graphics::depth::read_write, "read_write"},
256 entry_type{sbx::graphics::depth::read_only, "read_only"}
257 };
258
259}; // struct sbx::utility::enum_mapping
260
261template<>
262struct sbx::utility::enum_mapping<sbx::graphics::cull_mode> {
263
265
266 static constexpr auto values = std::array<entry_type, 4u>{
267 entry_type{sbx::graphics::cull_mode::back, "back"},
268 entry_type{sbx::graphics::cull_mode::front, "front"},
269 entry_type{sbx::graphics::cull_mode::front_and_back, "front_and_back"},
270 entry_type{sbx::graphics::cull_mode::none, "none"}
271 };
272
273}; // struct sbx::utility::enum_mapping
274
275template<>
276struct sbx::utility::enum_mapping<sbx::graphics::front_face> {
277
279
280 static constexpr auto values = std::array<entry_type, 2u>{
281 entry_type{sbx::graphics::front_face::clockwise, "clockwise"},
282 entry_type{sbx::graphics::front_face::counter_clockwise, "counter_clockwise"}
283 };
284
285}; // struct sbx::utility::enum_mapping
286
287#endif // LIBSBX_GRAPHICS_PIPELINE_GRAPHICS_PIPELINE_HPP_
Definition: render_graph.hpp:199
Definition: graphics_pipeline.hpp:110
Definition: pipeline.hpp:20
Definition: graphics_pipeline.hpp:56
Definition: graphics_pipeline.hpp:123
Definition: graphics_pipeline.hpp:101
Definition: graphics_pipeline.hpp:62
Definition: vertex_input_description.hpp:12
Definition: vertex_input_description.hpp:18
Definition: enum.hpp:143
Definition: enum.hpp:150