sandbox
Loading...
Searching...
No Matches
renderer.hpp
1// SPDX-License-Identifier: MIT
2#ifndef LIBSBX_GRAPHICS_RENDERER_HPP_
3#define LIBSBX_GRAPHICS_RENDERER_HPP_
4
5#include <memory>
6#include <vector>
7#include <typeindex>
8
9#include <easy/profiler.h>
10
11#include <libsbx/utility/noncopyable.hpp>
12#include <libsbx/utility/concepts.hpp>
14
15#include <libsbx/graphics/commands/command_buffer.hpp>
16
17#include <libsbx/graphics/pipeline/pipeline.hpp>
18
19#include <libsbx/graphics/task.hpp>
20#include <libsbx/graphics/subrenderer.hpp>
21#include <libsbx/graphics/render_graph.hpp>
22#include <libsbx/graphics/draw_list.hpp>
23#include <libsbx/graphics/viewport.hpp>
24
25namespace sbx::graphics {
26
28
29public:
30
31 renderer() = default;
32
33 virtual ~renderer() = default;
34
35 auto render(command_buffer& command_buffer, const swapchain& swapchain) -> void {
36 for (auto& [key, draw_list] : _draw_lists) {
37 draw_list->clear();
38 draw_list->update();
39 }
40
41 _graph.execute(command_buffer, swapchain, [this, &command_buffer](const pass_handle& pass) -> void {
42 const auto kind = _graph.pass_kind(pass);
43
44 if (kind == pass_node::kind::compute) {
45 if (pass.index >= _tasks.size()) {
46 return;
47 }
48
49 for (const auto& task : _tasks[pass.index]) {
50 task->execute(command_buffer);
51 }
52 } else {
53 if (pass.index >= _subrenderers.size()) {
54 return;
55 }
56
57 for (const auto& subrenderer : _subrenderers[pass.index]) {
58 subrenderer->render(command_buffer);
59 }
60 }
61
62 });
63 }
64
65 auto resize(const viewport::type flags) -> void {
66 _graph.resize(flags);
67 }
68
69 auto attachment(const std::string& name) const -> const descriptor& {
70 return _graph.find_attachment(name);
71 }
72
73 template<typename Type>
74 requires (std::is_base_of_v<draw_list, Type>)
75 auto draw_list(const utility::hashed_string& name) -> Type& {
76 if (auto entry = _draw_lists.find(name); entry != _draw_lists.end()) {
77 return *static_cast<Type*>(entry->second.get());
78 }
79
80 throw utility::runtime_error{"Draw list with name '{}' not found", name.str()};
81 }
82
83protected:
84
85 template<typename Type, typename... Args>
86 requires (std::is_base_of_v<graphics::subrenderer, Type> && std::is_constructible_v<Type, const std::vector<sbx::graphics::attachment_description>&, Args...>)
87 auto add_subrenderer(const pass_handle handle, Args&&... args) -> Type& {
88 utility::assert_that(handle.is_valid(), "Invalid pass handle in add_subrenderer()");
89
90 if (_graph.pass_kind(handle) != pass_node::kind::graphics) {
91 throw utility::runtime_error{"add_subrenderer() can only be used with graphics passes"};
92 }
93
94 _subrenderers.resize(std::max(_subrenderers.size(), static_cast<std::size_t>(handle.index + 1)));
95
96 auto& subrenderers = _subrenderers[handle.index];
97
98 subrenderers.emplace_back(std::make_unique<Type>(_graph.attachment_descriptions(handle), std::forward<Args>(args)...));
99
100 return *static_cast<Type*>(subrenderers.back().get());
101 }
102
103 template<typename Type, typename... Args>
104 requires (std::is_base_of_v<graphics::task, Type> && std::is_constructible_v<Type, Args...>)
105 auto add_task(const pass_handle handle, Args&&... args) -> Type& {
106 utility::assert_that(handle.is_valid(), "Invalid pass handle in add_compute_task()");
107
108 if (_graph.pass_kind(handle) != pass_node::kind::compute) {
109 throw utility::runtime_error{"add_compute_task() can only be used with compute passes"};
110 }
111
112 _tasks.resize(std::max(_tasks.size(), static_cast<std::size_t>(handle.index + 1)));
113
114 auto& tasks = _tasks[handle.index];
115
116 tasks.emplace_back(std::make_unique<Type>(std::forward<Args>(args)...));
117
118 return *static_cast<Type*>(tasks.back().get());
119 }
120
121 template<typename Type, typename... Args>
122 requires (std::is_constructible_v<Type, Args...>)
123 auto add_draw_list(const utility::hashed_string& name, Args&&... args) -> Type& {
124 auto result = _draw_lists.emplace(name, std::make_unique<Type>(std::forward<Args>(args)...));
125
126 return *static_cast<Type*>(result.first->second.get());
127 }
128
129 template<typename... Args>
130 auto create_attachment(Args&&... args) -> attachment_handle {
131 return _graph.create_attachment(std::forward<Args>(args)...);
132 }
133
134 template<typename Callable>
135 auto create_pass(Callable&& callable) -> pass_handle {
136 return _graph.create_pass(std::forward<Callable>(callable));
137 }
138
139 auto build_render_graph() -> void {
140 _graph.build();
141 }
142
143 auto attachment_descriptions(const pass_handle handle) const -> std::vector<attachment_description> {
144 return _graph.attachment_descriptions(handle);
145 }
146
147private:
148
149 std::vector<std::vector<std::unique_ptr<graphics::subrenderer>>> _subrenderers;
150 std::vector<std::vector<std::unique_ptr<graphics::task>>> _tasks;
151
152 std::unordered_map<utility::hashed_string, std::unique_ptr<graphics::draw_list>> _draw_lists;
153
154 render_graph _graph;
155
156}; // class renderer
157
158} // namespace sbx::graphics
159
160#endif // LIBSBX_GRAPHICS_RENDERER_HPP_
Definition: render_graph.hpp:93
Definition: command_buffer.hpp:15
Definition: descriptor.hpp:38
Definition: draw_list.hpp:28
Definition: render_graph.hpp:235
Definition: renderer.hpp:27
Definition: subrenderer.hpp:14
Definition: swapchain.hpp:15
Definition: task.hpp:9
Definition: hashed_string.hpp:17
Definition: render_graph.hpp:138
Definition: render_graph.hpp:148
Definition: noncopyable.hpp:7
Definition: exception.hpp:18