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