sandbox
Loading...
Searching...
No Matches
graphics_module.hpp
1#ifndef LIBSBX_GRAPHICS_GRAPHICS_MODULE_HPP_
2#define LIBSBX_GRAPHICS_GRAPHICS_MODULE_HPP_
3
4#include <memory>
5#include <unordered_map>
6#include <vector>
7#include <typeindex>
8
9#include <vk_mem_alloc.h>
10
11#include <libsbx/core/module.hpp>
13
14#include <libsbx/math/uuid.hpp>
15
16#include <libsbx/devices/devices_module.hpp>
17
19#include <libsbx/utility/concepts.hpp>
20
21#include <libsbx/signals/signal.hpp>
22
23#include <libsbx/graphics/devices/instance.hpp>
24#include <libsbx/graphics/devices/physical_device.hpp>
25#include <libsbx/graphics/devices/logical_device.hpp>
26#include <libsbx/graphics/devices/surface.hpp>
27
28#include <libsbx/graphics/commands/command_pool.hpp>
29#include <libsbx/graphics/commands/command_buffer.hpp>
30
31#include <libsbx/graphics/render_pass/swapchain.hpp>
32
33#include <libsbx/graphics/pipeline/pipeline.hpp>
34#include <libsbx/graphics/pipeline/shader.hpp>
35#include <libsbx/graphics/pipeline/graphics_pipeline.hpp>
36#include <libsbx/graphics/pipeline/compute_pipeline.hpp>
37
38#include <libsbx/graphics/buffers/buffer.hpp>
39#include <libsbx/graphics/buffers/storage_buffer.hpp>
40
41#include <libsbx/graphics/images/image2d.hpp>
42#include <libsbx/graphics/images/cube_image.hpp>
43
44#include <libsbx/graphics/renderer.hpp>
45#include <libsbx/graphics/render_stage.hpp>
46
47#include <libsbx/graphics/resource_storage.hpp>
48
49namespace sbx::graphics {
50
56auto validate(VkResult result) -> void;
57
58template<typename VkEnum, typename Enum>
59requires ((std::is_enum_v<VkEnum> || std::is_same_v<VkEnum, VkFlags>) && std::is_enum_v<Enum>)
60constexpr auto to_vk_enum(Enum value) -> VkEnum {
61 return static_cast<VkEnum>(value);
62}
63
69class graphics_module final : public core::module<graphics_module> {
70
71 inline static const auto is_registered = register_module(stage::rendering, dependencies<devices::devices_module>{});
72
73 inline static constexpr auto max_deletion_queue_size = std::size_t{16u};
74
75public:
76
78
79 ~graphics_module() override;
80
81 auto update() -> void override;
82
83 auto instance() -> instance&;
84
86
88
89 auto surface() -> surface&;
90
91 auto command_pool(VkQueueFlagBits queue_type = VK_QUEUE_GRAPHICS_BIT, const std::thread::id& thread_id = std::this_thread::get_id()) -> const std::shared_ptr<command_pool>&;
92
93 auto swapchain() -> swapchain&;
94
95 template<utility::implements<renderer> Renderer, typename... Args>
96 requires (std::is_constructible_v<Renderer, Args...>)
97 auto set_renderer(Args&&... args) -> void {
98 _renderer = std::make_unique<Renderer>(std::forward<Args>(args)...);
99 _reset_render_stages();
100 _renderer->initialize();
101 }
102
104
105 auto current_frame() const noexcept -> std::uint32_t {
106 return _current_frame;
107 }
108
109 auto attachment(const std::string& name) const -> const descriptor&;
110
111 template<typename Type, typename... Args>
112 requires (std::is_constructible_v<Type, Args...>)
113 auto add_resource(Args&&... args) -> resource_handle<Type> {
114 return _storage<Type>().emplace(std::forward<Args>(args)...);
115 }
116
117 template<typename Type>
118 auto get_resource(const resource_handle<Type>& handle) -> Type& {
119 return _storage<Type>().get(handle);
120 }
121
122 template<typename Type>
123 auto get_resource(const resource_handle<Type>& handle) const -> const Type& {
124 return _storage<Type>().get(handle);
125 }
126
127 auto allocator() const noexcept -> VmaAllocator {
128 return _allocator;
129 }
130
131 template<queue::type Source, queue::type Destination, typename Type>
132 requires (std::is_same_v<Type, graphics::buffer> || std::is_same_v<Type, graphics::storage_buffer>)
133 auto transfer_ownership(const resource_handle<Type>& handle, const VkPipelineStageFlagBits2 stage = VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT) -> void {
134 auto& buffer = get_resource<Type>(handle);
135
136 _release_ownership_data.push_back(command_buffer::release_ownership_data{
137 .src_stage_mask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
138 .src_access_mask = VK_ACCESS_2_SHADER_WRITE_BIT,
139 .src_queue_family = _logical_device->queue<Source>().family(),
140 .dst_queue_family = _logical_device->queue<Destination>().family(),
141 .buffer = buffer
142 });
143
144 _acquire_ownership_data.push_back(command_buffer::acquire_ownership_data{
145 .dst_stage_mask = stage,
146 .dst_access_mask = _access_mask_from_stage(stage),
147 .src_queue_family = _logical_device->queue<Source>().family(),
148 .dst_queue_family = _logical_device->queue<Destination>().family(),
149 .buffer = buffer
150 });
151 }
152
153 template<typename Callable>
154 requires (std::is_invocable_r_v<math::vector2u, Callable>)
155 auto set_dynamic_size_callback(Callable&& callback) -> void {
156 _dynamic_size_callback = std::forward<Callable>(callback);
157 }
158
159private:
160
161 static constexpr auto _access_mask_from_stage(VkPipelineStageFlagBits2 stage) -> VkAccessFlagBits2 {
162 switch (stage) {
163 case VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT: {
164 return VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT;
165 }
166 case VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT:
167 case VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT:
168 case VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT:
169 case VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT:
170 case VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT: {
171 return VK_ACCESS_2_SHADER_READ_BIT;
172 }
173 case VK_PIPELINE_STAGE_2_TRANSFER_BIT: {
174 return VK_ACCESS_2_TRANSFER_READ_BIT;
175 }
176 default: {
177 return VK_ACCESS_2_MEMORY_READ_BIT;
178 }
179 }
180 }
181
183
185
186 auto _reset_render_stages() -> void;
187
188 auto _recreate_swapchain() -> void;
189
190 auto _recreate_per_frame_data() -> void;
191
192 auto _recreate_per_image_data() -> void;
193
194 auto _recreate_command_buffers() -> void;
195
196 auto _recreate_attachments() -> void;
197
198 struct per_frame_data {
199 // graphics
200 VkSemaphore image_available_semaphore{};
201 VkFence graphics_in_flight_fence{};
202 // compute
203 VkSemaphore compute_finished_semaphore{};
204 VkFence compute_in_flight_fence{};
205 }; // struct per_frame_data
206
207 struct per_image_data {
208 VkSemaphore render_finished_semaphore{};
209 }; // struct per_image_data
210
211 struct command_pool_key {
212 VkQueueFlagBits queue_type;
213 std::thread::id thread_id;
214 }; // struct command_pool_key
215
216 struct command_pool_key_hash {
217 auto operator()(const command_pool_key& key) const noexcept -> std::size_t {
218 auto hast = std::size_t{0};
219 utility::hash_combine(hast, key.queue_type, key.thread_id);
220 return hast;
221 }
222 }; // struct command_pool_key_hash
223
224 struct command_pool_key_equality {
225 auto operator()(const command_pool_key& lhs, const command_pool_key& rhs) const noexcept -> bool {
226 return lhs.queue_type == rhs.queue_type && lhs.thread_id == rhs.thread_id;
227 }
228 }; // struct command_pool_key_equal
229
230
231 static_assert(std::is_class_v<graphics::graphics_pipeline>, "graphics_pipeline is not a class in sbx::graphics");
232
233 template<typename Type>
234 auto _storage() -> resource_storage<Type>& {
235 if constexpr (std::is_same_v<Type, shader>) {
236 return _shaders;
237 } else if constexpr (std::is_same_v<Type, graphics_pipeline>) {
238 return _graphics_pipelines;
239 } else if constexpr (std::is_same_v<Type, compute_pipeline>) {
240 return _compute_pipelines;
241 } else if constexpr (std::is_same_v<Type, buffer>) {
242 return _buffers;
243 } else if constexpr (std::is_same_v<Type, storage_buffer>) {
244 return _storage_buffers;
245 } else if constexpr (std::is_same_v<Type, image2d>) {
246 return _images;
247 } else if constexpr (std::is_same_v<Type, cube_image>) {
248 return _cube_image;
249 }
250
251 utility::assert_that(false, "Invalid resource type");
252 }
253
254 template<typename Type>
255 auto _storage() const -> const resource_storage<Type>& {
256 if constexpr (std::is_same_v<Type, shader>) {
257 return _shaders;
258 } else if constexpr (std::is_same_v<Type, graphics_pipeline>) {
259 return _graphics_pipelines;
260 } else if constexpr (std::is_same_v<Type, compute_pipeline>) {
261 return _compute_pipelines;
262 } else if constexpr (std::is_same_v<Type, buffer>) {
263 return _buffers;
264 } else if constexpr (std::is_same_v<Type, storage_buffer>) {
265 return _storage_buffers;
266 } else if constexpr (std::is_same_v<Type, image2d>) {
267 return _images;
268 } else if constexpr (std::is_same_v<Type, cube_image>) {
269 return _cube_image;
270 }
271
272 utility::assert_that(false, "Invalid resource type");
273 }
274
275 std::unique_ptr<graphics::instance> _instance{};
276 std::unique_ptr<graphics::physical_device> _physical_device{};
277 std::unique_ptr<graphics::logical_device> _logical_device{};
278
279 std::unordered_map<command_pool_key, std::shared_ptr<graphics::command_pool>, command_pool_key_hash, command_pool_key_equality> _command_pools{};
280
281 std::map<std::string, memory::observer_ptr<const descriptor>> _attachments{};
282
283 std::unique_ptr<graphics::surface> _surface{};
284
285 std::unique_ptr<graphics::swapchain> _swapchain{};
286
287 std::vector<per_frame_data> _per_frame_data{};
288 std::vector<per_image_data> _per_image_data{};
289 // std::vector<std::unique_ptr<graphics::command_buffer>> _graphics_command_buffers{};
290 // std::vector<std::unique_ptr<graphics::command_buffer>> _compute_command_buffers{};
291 std::vector<graphics::command_buffer> _graphics_command_buffers{};
292 std::vector<graphics::command_buffer> _compute_command_buffers{};
293
294 std::unique_ptr<graphics::renderer> _renderer{};
295
296 VmaAllocator _allocator;
297
305
306 std::vector<command_buffer::acquire_ownership_data> _acquire_ownership_data;
307 std::vector<command_buffer::release_ownership_data> _release_ownership_data;
308
309 std::uint32_t _current_frame{};
310 bool _is_framebuffer_resized{};
311
312 core::delegate<math::vector2u()> _dynamic_size_callback;
313
314}; // class graphics_module
315
316} // namespace sbx::graphics
317
318#endif // LIBSBX_GRAPHICS_GRAPHICS_MODULE_HPP_
Definition: delegate.hpp:55
Definition: module.hpp:72
Definition: render_stage.hpp:40
Definition: buffer.hpp:20
Definition: command_buffer.hpp:14
Definition: command_pool.hpp:12
Definition: descriptor.hpp:37
Module for managing rendering specific tasks.
Definition: graphics_module.hpp:69
Definition: instance.hpp:10
Definition: logical_device.hpp:60
Definition: physical_device.hpp:16
Definition: render_stage.hpp:251
Definition: resource_storage.hpp:17
Definition: resource_storage.hpp:65
Definition: surface.hpp:14
Definition: swapchain.hpp:12
A vector in two-dimensional space.
Definition: vector2.hpp:27
Definition: pipeline.hpp:22