MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Forma.cpp
Go to the documentation of this file.
1#include "Forma.hpp"
2
9
11
12#include "Inspect/Inspector.hpp"
13
15
17
19
20namespace {
21
22 std::optional<Surface> g_inspect_nodes_surface;
23 std::optional<Surface> g_inspect_buffers_surface;
24 std::optional<Surface> g_inspect_scheduler_surface;
25 std::optional<Surface> g_inspect_events_surface;
26 std::vector<std::unique_ptr<Surface>> g_inspect_surfaces;
27
28 constexpr uint32_t k_inspect_w = 480;
29 constexpr uint32_t k_inspect_h = 900;
30
31 void discard_inspect_surface(std::optional<Surface>& surface)
32 {
33 if (!surface)
34 return;
35
36 surface->layer().clear();
37 surface.reset();
38 }
39
40} // namespace
41
42// =============================================================================
43// Lifecycle
44// =============================================================================
45
47 std::shared_ptr<Nodes::NodeGraphManager> node_graph_manager,
48 std::shared_ptr<Buffers::BufferManager> buffer_manager,
49 std::shared_ptr<Vruta::TaskScheduler> scheduler,
50 std::shared_ptr<Vruta::EventManager> event_manager,
51 std::shared_ptr<Core::WindowManager> window_manager)
52{
54 std::move(node_graph_manager), std::move(buffer_manager),
55 std::move(scheduler), std::move(event_manager), std::move(window_manager));
56}
57
59{
60 g_inspect_nodes_surface.reset();
61 g_inspect_buffers_surface.reset();
62 g_inspect_scheduler_surface.reset();
63 g_inspect_events_surface.reset();
64 g_inspect_surfaces.clear();
65
67}
68
70
72
74
75// =============================================================================
76// Layer
77// =============================================================================
78
79std::pair<std::shared_ptr<Layer>, std::shared_ptr<Context>>
80create_layer(const std::shared_ptr<Core::Window>& window, std::string name)
81{
82 return internal::atelier().create_layer(window, std::move(name));
83}
84
86{
87 return internal::atelier().create_surface(std::move(config));
88}
89
90void destroy(Surface& surface, uint32_t id)
91{
92 for (uint32_t cid : surface.layer().closure(id)) {
93 surface.ctx().unbind(cid);
94 bridge().unbind({ surface.layer_ptr(), cid });
95 }
96 surface.layer().remove(id);
97}
98
99// =============================================================================
100// Standalone buffer
101// =============================================================================
102
103std::shared_ptr<Buffers::FormaBuffer> create_buffer(Graphics::RenderConfig render)
104{
105 return internal::atelier().create_buffer(std::move(render));
106}
107
108// =============================================================================
109// Plot
110// =============================================================================
111
112std::pair<Mapped<std::shared_ptr<Kakshya::PlotContainer>>, Surface>
114 std::string title,
115 uint32_t width,
116 uint32_t height,
117 std::shared_ptr<Kakshya::PlotContainer> container,
118 Plot::SeriesSpec spec)
119{
120 auto& atelier = internal::atelier();
121
122 auto window = atelier.create_window(
123 Core::WindowCreateInfo { .title = std::move(title), .width = width, .height = height });
124
125 auto surface = atelier.create_surface(SurfaceConfig {
126 .window = window,
127 .name = window->get_create_info().title,
128 });
129
130 const bool has_labels = !spec.labels.empty() || !spec.tick_labels.empty()
131 || (spec.legend && !spec.legend->entries.empty());
132 Graphics::RenderConfig render = surface.render_config();
133 if (has_labels) {
134 render.fragment_shader = "forma_plot.frag.spv";
135 render.additional_textures.emplace_back("text", nullptr);
136 }
137 const auto batch = atelier.create_buffer(std::move(render));
138
139 std::optional<uint32_t> background_id;
140 if (spec.background_fn) {
141 auto bg = atelier.create_element<float>(
142 surface,
144 *spec.background_fn, 0.F);
145 background_id = bg.element.id;
146 }
147
148 auto mapped = Plot::place(
149 surface, FormaTarget::slice_of(batch, spec.topology), spec, std::move(container));
150
151 if (background_id) {
152 surface.layer().relate(mapped.element.id, *background_id);
153 surface.layer().send_to_back(*background_id);
154 }
155
156 internal::atelier().place_adornments(surface, spec, mapped.element.id, batch);
157
158 return { std::move(mapped), std::move(surface) };
159}
160
161// =============================================================================
162// Bridge
163// =============================================================================
164
166{
167 auto& atelier = internal::atelier();
168
169 if (g_inspect_nodes_surface && g_inspect_nodes_surface->window()
170 && !g_inspect_nodes_surface->window()->should_close()) {
171 g_inspect_nodes_surface->window()->show();
172 return;
173 }
174
175 if (g_inspect_nodes_surface) {
176 LayoutCursor cursor;
177 atelier.inspector().destroy(
178 atelier.inspector().node_graph_manager(*g_inspect_nodes_surface, cursor));
179 discard_inspect_surface(g_inspect_nodes_surface);
180 }
181
182 auto window = atelier.create_window(
183 Core::WindowCreateInfo { .title = "NodeGraphManager", .width = k_inspect_w, .height = k_inspect_h });
184
185 auto [layer, ctx] = atelier.create_layer(window, "NodeGraphManager");
186 g_inspect_nodes_surface.emplace(SurfaceConfig {
187 .window = std::move(window),
188 .layer = std::move(layer),
189 .ctx = std::move(ctx),
190 });
191 LayoutCursor cursor;
192 auto& result = atelier.inspector().node_graph_manager(*g_inspect_nodes_surface, cursor);
193 atelier.bridge().spawn_sync(g_inspect_nodes_surface->layer(),
194 result.group.header.header_id, [&result] { result.tap_all(); });
195}
196
198{
199 auto& atelier = internal::atelier();
200
201 if (g_inspect_buffers_surface && g_inspect_buffers_surface->window()
202 && !g_inspect_buffers_surface->window()->should_close()) {
203 g_inspect_buffers_surface->window()->show();
204 return;
205 }
206
207 if (g_inspect_buffers_surface) {
208 LayoutCursor cursor;
209 atelier.inspector().destroy(
210 atelier.inspector().buffer_manager(*g_inspect_buffers_surface, cursor));
211 discard_inspect_surface(g_inspect_buffers_surface);
212 }
213
214 auto window = atelier.create_window(
215 Core::WindowCreateInfo { .title = "BufferManager", .width = k_inspect_w, .height = k_inspect_h });
216
217 auto [layer, ctx] = atelier.create_layer(window, "BufferManager");
218 g_inspect_buffers_surface.emplace(SurfaceConfig {
219 .window = std::move(window),
220 .layer = std::move(layer),
221 .ctx = std::move(ctx),
222 });
223 LayoutCursor cursor;
224 auto& result = atelier.inspector().buffer_manager(*g_inspect_buffers_surface, cursor);
225 atelier.bridge().spawn_sync(g_inspect_buffers_surface->layer(),
226 result.group.header.header_id, [&result] { result.tap_all(); });
227}
228
230{
231 auto& atelier = internal::atelier();
232
233 if (g_inspect_scheduler_surface && g_inspect_scheduler_surface->window()
234 && !g_inspect_scheduler_surface->window()->should_close()) {
235 g_inspect_scheduler_surface->window()->show();
236 return;
237 }
238
239 if (g_inspect_scheduler_surface) {
240 LayoutCursor cursor;
241 atelier.inspector().destroy(
242 atelier.inspector().scheduler(*g_inspect_scheduler_surface, cursor));
243 discard_inspect_surface(g_inspect_scheduler_surface);
244 }
245
246 auto window = atelier.create_window(
247 Core::WindowCreateInfo { .title = "TaskScheduler", .width = k_inspect_w, .height = k_inspect_h });
248
249 auto [layer, ctx] = atelier.create_layer(window, "TaskScheduler");
250 g_inspect_scheduler_surface.emplace(SurfaceConfig {
251 .window = std::move(window),
252 .layer = std::move(layer),
253 .ctx = std::move(ctx),
254 });
255 LayoutCursor cursor;
256 auto& result = atelier.inspector().scheduler(*g_inspect_scheduler_surface, cursor);
257 atelier.bridge().spawn_sync(g_inspect_scheduler_surface->layer(),
258 result.group.header.header_id, [&result] { result.tap_all(); });
259}
260
262{
263 auto& atelier = internal::atelier();
264
265 if (g_inspect_events_surface && g_inspect_events_surface->window()
266 && !g_inspect_events_surface->window()->should_close()) {
267 g_inspect_events_surface->window()->show();
268 return;
269 }
270
271 if (g_inspect_events_surface) {
272 LayoutCursor cursor;
273 atelier.inspector().destroy(
274 atelier.inspector().event_manager(*g_inspect_events_surface, cursor));
275 discard_inspect_surface(g_inspect_events_surface);
276 }
277
278 auto window = atelier.create_window(
279 Core::WindowCreateInfo { .title = "EventManager", .width = k_inspect_w, .height = k_inspect_h });
280
281 auto [layer, ctx] = atelier.create_layer(window, "EventManager");
282 g_inspect_events_surface.emplace(SurfaceConfig {
283 .window = std::move(window),
284 .layer = std::move(layer),
285 .ctx = std::move(ctx),
286 });
287 LayoutCursor cursor;
288 auto& result = atelier.inspector().event_manager(*g_inspect_events_surface, cursor);
289 atelier.bridge().spawn_sync(g_inspect_events_surface->layer(),
290 result.group.header.header_id, [&result] { result.tap_all(); });
291}
292
293void inspect(const std::shared_ptr<Nodes::Node>& node)
294{
295 auto& atelier = internal::atelier();
296 const std::string title = Reflect::short_dynamic_type_name(node);
297
298 auto window = atelier.create_window(
299 Core::WindowCreateInfo { .title = title, .width = k_inspect_w, .height = k_inspect_h });
300
301 auto [layer, ctx] = atelier.create_layer(window, title);
302 g_inspect_surfaces.push_back(std::make_unique<Surface>(SurfaceConfig {
303 .window = std::move(window),
304 .layer = std::move(layer),
305 .ctx = std::move(ctx),
306 }));
307 auto& surface = *g_inspect_surfaces.back();
308 LayoutCursor cursor;
309 auto result = std::make_shared<InspectResult>(atelier.inspector().node(node, surface, cursor));
310 atelier.bridge().spawn_sync(surface.layer(),
311 result->group.header.header_id, [result] { result->tap_all(); });
312}
313
314void inspect(const std::shared_ptr<Buffers::Buffer>& buf)
315{
316 auto& atelier = internal::atelier();
317 const std::string title = Reflect::short_dynamic_type_name(buf);
318
319 auto window = atelier.create_window(
320 Core::WindowCreateInfo { .title = title, .width = k_inspect_w, .height = k_inspect_h });
321
322 auto [layer, ctx] = atelier.create_layer(window, title);
323 g_inspect_surfaces.push_back(std::make_unique<Surface>(SurfaceConfig {
324 .window = std::move(window),
325 .layer = std::move(layer),
326 .ctx = std::move(ctx),
327 }));
328 auto& surface = *g_inspect_surfaces.back();
329 LayoutCursor cursor;
330 auto result = std::make_shared<InspectResult>(atelier.inspector().buffer(buf, surface, cursor));
331 atelier.bridge().spawn_sync(surface.layer(),
332 result->group.header.header_id, [result] { result->tap_all(); });
333}
334
335void inspect(const std::shared_ptr<Nodes::Network::NodeNetwork>& net)
336{
337 auto& atelier = internal::atelier();
338
339 auto window = atelier.create_window(
340 Core::WindowCreateInfo { .title = "NodeNetwork", .width = k_inspect_w, .height = k_inspect_h });
341
342 auto [layer, ctx] = atelier.create_layer(window, "NodeNetwork");
343 g_inspect_surfaces.push_back(std::make_unique<Surface>(SurfaceConfig {
344 .window = std::move(window),
345 .layer = std::move(layer),
346 .ctx = std::move(ctx),
347 }));
348 auto& surface = *g_inspect_surfaces.back();
349 LayoutCursor cursor;
350 auto result = std::make_shared<InspectResult>(atelier.inspector().node_network(net, surface, cursor));
351 atelier.bridge().spawn_sync(surface.layer(),
352 result->group.header.header_id, [result] { result->tap_all(); });
353}
354
355void inspect(const std::shared_ptr<Vruta::Event>& ev, std::string_view name)
356{
357 auto& atelier = internal::atelier();
358 const std::string title = name.empty() ? "Event" : "Event: " + std::string(name);
359
360 auto window = atelier.create_window(
361 Core::WindowCreateInfo { .title = title, .width = k_inspect_w, .height = k_inspect_h });
362
363 auto [layer, ctx] = atelier.create_layer(window, title);
364 g_inspect_surfaces.push_back(std::make_unique<Surface>(SurfaceConfig {
365 .window = std::move(window),
366 .layer = std::move(layer),
367 .ctx = std::move(ctx),
368 }));
369 auto& surface = *g_inspect_surfaces.back();
370 LayoutCursor cursor;
371 auto result = std::make_shared<InspectResult>(atelier.inspector().event(ev, name, surface, cursor));
372 atelier.bridge().spawn_sync(surface.layer(),
373 result->group.header.header_id, [result] { result->tap_all(); });
374}
375
376} // namespace MayaFlux::Portal::Forma
Factory free functions for the Forma surface system.
std::weak_ptr< Core::Window > window
Definition Picker.cpp:23
std::string name
Definition VKDevice.cpp:123
uint32_t width
uint32_t height
void unbind(const ElementRef &ref)
Cancel all inbound and outbound bindings for an element.
Definition Bridge.cpp:380
void spawn_sync(Layer &layer, uint32_t id, std::function< void()> sync_fn)
Spawn a presentation sync task scoped to a Layer.
Definition Bridge.cpp:450
Two-way binding orchestrator for Forma elements.
Definition Bridge.hpp:74
void unbind(uint32_t id)
Remove all callbacks registered for an element id.
Definition Context.cpp:168
static FormaTarget slice_of(const std::shared_ptr< Buffers::FormaBuffer > &buffer, std::optional< Graphics::PrimitiveTopology > topology=std::nullopt)
A new empty slice of buffer, drawn after the others.
Definition Target.cpp:19
InspectResult & buffer_manager(Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F)
Inspect the full BufferManager state across all active tokens.
InspectResult & node_graph_manager(Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F)
Inspect the full NodeGraphManager state across all active tokens.
InspectResult event(const std::shared_ptr< Vruta::Event > &ev, std::string_view name, Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F)
Inspect a single Event by name and pointer.
InspectResult & event_manager(Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F)
Inspect the full EventManager state.
void destroy(InspectResult &result)
Destroy an InspectResult and release its resources.
Definition Inspector.cpp:42
InspectResult node_network(const std::shared_ptr< Nodes::Network::NodeNetwork > &net, Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F, int depth=0)
Inspect a NodeNetwork and its per-network metadata.
InspectResult & scheduler(Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F)
Inspect the full TaskScheduler state.
InspectResult node(const std::shared_ptr< Nodes::Node > &n, Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F, int depth=0)
Inspect a single Node and its full modulator tree.
Definition NodeQuery.cpp:81
InspectResult buffer(const std::shared_ptr< Buffers::Buffer > &buf, Surface &surface, LayoutCursor &cursor, float x_min=-0.95F, float x_max=0.95F, float row_h=0.05F, int depth=0)
Inspect a single Buffer: default processor and full processing chain.
Forma subsystem for live introspection.
Definition Inspector.hpp:39
std::vector< uint32_t > closure(uint32_t id) const
Return id plus every id transitively related to it.
Definition Layer.cpp:243
bool remove(uint32_t id)
Remove an element by id, cascading to every related id.
Definition Layer.cpp:17
Reactive Y-position accumulator for vertical primitive stacking.
const std::shared_ptr< Layer > & layer_ptr() const noexcept
Shared handles for callers that need to keep components alive independently of the Surface (backgroun...
Definition Surface.hpp:188
Context & ctx() noexcept
Access the event router.
Definition Surface.hpp:170
Layer & layer() noexcept
Access the spatial registry.
Definition Surface.hpp:159
Named owner of a (Window, Layer, Context) triple: the Forma canvas.
Definition Surface.hpp:121
Surface create_surface(SurfaceConfig config)
Build a Surface from a SurfaceConfig, creating Layer and Context when config.layer/config....
Definition Atelier.cpp:160
bool initialize(std::shared_ptr< Nodes::NodeGraphManager > node_graph_manager, std::shared_ptr< Buffers::BufferManager > buffer_manager, std::shared_ptr< Vruta::TaskScheduler > scheduler, std::shared_ptr< Vruta::EventManager > event_manager, std::shared_ptr< Core::WindowManager > window_manager)
Definition Atelier.cpp:29
void place_adornments(Surface &surface, const Plot::SeriesSpec &spec, uint32_t relate_to, const std::shared_ptr< Buffers::FormaBuffer > &batch={})
Create and place every adornment declared on spec.
Definition Atelier.cpp:183
std::shared_ptr< Core::Window > create_window(const Core::WindowCreateInfo &info)
Create a window through the stored WindowManager and show it.
Definition Atelier.cpp:104
Mapped< T > create_element(Surface &surface, GeometryFn< T > geom, T initial, Graphics::PrimitiveTopology topology=Graphics::PrimitiveTopology::TRIANGLE_STRIP, std::function< float(T)> project={})
create_element on a buffer of its own, as a slice of topology, followed by one sync so bounds_hint an...
Definition Atelier.hpp:165
Inspector & inspector()
Inspector instance constructed during initialize.
Definition Atelier.cpp:90
std::shared_ptr< Buffers::FormaBuffer > create_buffer(Graphics::RenderConfig render)
The single buffer construction path.
Definition Atelier.cpp:117
Bridge & bridge()
Bridge instance constructed during initialize.
Definition Atelier.cpp:80
std::pair< std::shared_ptr< Layer >, std::shared_ptr< Context > > create_layer(const std::shared_ptr< Core::Window > &window, std::string name)
Construct a Layer and a Context wired to window.
Definition Atelier.cpp:150
void initialize()
Definition main.cpp:10
Mapped< std::shared_ptr< Kakshya::PlotContainer > > place(Surface &surface, FormaTarget buf, SeriesSpec spec, std::shared_ptr< Kakshya::PlotContainer > container)
Place a plot element onto a Surface using a FormaTarget.
Definition Plot.cpp:96
Atelier & atelier()
Accessor for the process-wide Atelier.
Definition Atelier.hpp:304
std::pair< Mapped< std::shared_ptr< Kakshya::PlotContainer > >, Surface > plot(std::string title, uint32_t width, uint32_t height, std::shared_ptr< Kakshya::PlotContainer > container, Plot::SeriesSpec spec)
Create a live plot in a new window.
Definition Forma.cpp:113
void inspect_buffers()
Open or show the BufferManager inspection window.
Definition Forma.cpp:197
void destroy(Surface &surface, uint32_t id)
Tear down an element and everything related to it.
Definition Forma.cpp:90
void shutdown()
Release stored references.
Definition Forma.cpp:58
std::shared_ptr< Buffers::FormaBuffer > create_buffer(Graphics::RenderConfig render)
Construct and register a FormaBuffer without creating a Mapped<T>.
Definition Forma.cpp:103
void inspect_node_graph()
Open or show the NodeGraphManager inspection window.
Definition Forma.cpp:165
bool is_initialized()
Whether initialize() has been called successfully.
Definition Forma.cpp:69
Inspector & inspector()
Access the Forma introspection subsystem.
Definition Forma.cpp:73
void inspect_scheduler()
Open or show the TaskScheduler inspection window.
Definition Forma.cpp:229
std::pair< std::shared_ptr< Layer >, std::shared_ptr< Context > > create_layer(const std::shared_ptr< Core::Window > &window, std::string name)
Construct a Layer and a Context wired to window.
Definition Forma.cpp:80
Bridge & bridge()
Return the application-level Bridge instance.
Definition Forma.cpp:71
Surface create_surface(SurfaceConfig config)
Construct a Surface from a SurfaceConfig.
Definition Forma.cpp:85
void inspect(const std::shared_ptr< Nodes::Node > &node)
Open a dedicated window inspecting a single Node and its modulator tree.
Definition Forma.cpp:293
void inspect_events()
Open or show the EventManager inspection window.
Definition Forma.cpp:261
std::string short_dynamic_type_name(const T &obj) noexcept
Returns the unqualified dynamic type name of obj.
Definition TypeInfo.hpp:95
std::string title
Window title/identifier.
Configuration for creating a single window instance.
std::optional< LegendSpec > legend
Optional legend to materialize when the plot is placed.
std::optional< GeometryFn< float > > background_fn
std::vector< TickLabelsSpec > tick_labels
Concrete tick label generation specs resolved at done() time.
std::vector< LabelSpec > labels
Explicit text labels to materialize when the plot is placed.
std::shared_ptr< Core::Window > window
Target window. Must outlive the Surface.
Definition Surface.hpp:28
The single argument every Surface-creating function in this module takes, at every level of abstracti...
Definition Surface.hpp:26
std::vector< std::pair< std::string, std::shared_ptr< Core::VKImage > > > additional_textures
Unified rendering configuration for graphics buffers.