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