MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Bridge.hpp
Go to the documentation of this file.
1#pragma once
2
4
6
7namespace MayaFlux::Core {
8class Window;
9}
10
11namespace MayaFlux::Vruta {
12class TaskScheduler;
13}
14
15namespace MayaFlux::Buffers {
16class BufferManager;
17class ShaderProcessor;
18class AudioWriteProcessor;
19class DataWriteProcessor;
20class FormaBindingsProcessor;
21}
22
23namespace MayaFlux::Nodes {
24class Node;
25class Constant;
26}
27
29
30/**
31 * @brief Layer-scoped element identity. Element ids are unique only within
32 * their Layer, so the owning Layer is half of the key.
33 */
34using ElementRef = std::pair<std::weak_ptr<Layer>, uint32_t>;
35
36/**
37 * @class Bridge
38 * @brief Two-way binding orchestrator for Forma elements.
39 *
40 * One Bridge instance serves the full application. It owns all inbound
41 * GraphicsRoutine tasks and all outbound FormaBindingsProcessor instances.
42 * Layer and Context are created via the Forma free functions and passed in
43 * — Bridge does not own or create them.
44 *
45 * Inbound (what drives an element's MappedState each frame):
46 * - bind(ref, Node) — reads Node::get_last_output() via GraphicsRoutine
47 * - bind(ref, lambda) — calls std::function<float()> via GraphicsRoutine
48 *
49 * Outbound (where the element's value goes each frame):
50 * - write(ref, ShaderProcessor, offset) — push constant staging
51 * - write(ref, descriptor_name, ...) — descriptor binding
52 * - write(ref, AudioWriteProcessor) — audio buffer
53 * - write(ref, DataWriteProcessor) — vertex buffer
54 * - write(ref, Constant) — node graph value carrier
55 *
56 * Element ids are unique only within their Layer, so every element is
57 * addressed by an ElementRef. All overloads also accept
58 * shared_ptr<MappedState<T>> in place of the ElementRef; the state carries
59 * both halves once registered.
60 *
61 * Usage:
62 * @code
63 * auto [layer, ctx] = Forma::create_layer(window, "hud", event_manager);
64 * auto el = Forma::create_element<float>(*layer, window, bm, geom, 0.5f);
65 *
66 * Bridge bridge(scheduler, buffer_manager);
67 * bridge.bind(el.state, envelope);
68 * bridge.write(el.state, compute_proc, offsetof(PC, cutoff));
69 *
70 * ctx->on_press(el.element.id, IO::MouseButtons::LEFT,
71 * [](uint32_t, glm::vec2){});
72 * @endcode
73 */
74class MAYAFLUX_API Bridge {
75public:
76 Bridge(
77 Vruta::TaskScheduler& scheduler,
78 Buffers::BufferManager& buffer_manager);
79
80 ~Bridge();
81
82 Bridge(const Bridge&) = delete;
83 Bridge& operator=(const Bridge&) = delete;
84 Bridge(Bridge&&) = delete;
85 Bridge& operator=(Bridge&&) = delete;
86
87 // =========================================================================
88 // Inbound — ElementRef overloads (primary implementation)
89 // =========================================================================
90
91 /**
92 * @brief Drive element value from a Node's output each frame.
93 *
94 * Spawns a GraphicsRoutine that reads node->get_last_output() every tick,
95 * applies @p project, and writes into the element's MappedState.
96 * Node must be processed externally (EXTERNAL mode read).
97 * Replaces any existing inbound binding on this element.
98 *
99 * @param ref Owning Layer and element id (from Layer::add / Mapped::element.id).
100 * @param node Node to read from.
101 * @param project Optional double -> float projection. Identity if empty.
102 */
103 void bind(const ElementRef& ref,
104 std::shared_ptr<Nodes::Node> node,
105 std::function<float(double)> project = {});
106
107 /**
108 * @brief Drive element value from an arbitrary per-frame callable.
109 *
110 * Spawns a GraphicsRoutine that calls @p source every tick and writes
111 * the result into the element's MappedState.
112 * Replaces any existing inbound binding on this element.
113 *
114 * @param ref Owning Layer and element id.
115 * @param source Callable returning current float value.
116 */
117 void bind(const ElementRef& ref, std::function<float()> source);
118
119 // =========================================================================
120 // Inbound — MappedState overloads
121 // =========================================================================
122
123 template <typename T>
124 void bind(std::shared_ptr<MappedState<T>> state,
125 std::shared_ptr<Nodes::Node> node,
126 std::function<float(double)> project = {})
127 {
128 bind(ref_of(state), std::move(node), std::move(project));
129 }
130
131 template <typename T>
132 void bind(std::shared_ptr<MappedState<T>> state, std::function<float()> source)
133 {
134 bind(ref_of(state), std::move(source));
135 }
136
137 template <typename T>
138 void write(std::shared_ptr<MappedState<T>> state,
139 std::function<void(std::span<const float>)> sink)
140 {
141 write(ref_of(state), std::move(sink));
142 }
143
144 // =========================================================================
145 // Outbound — ElementRef overloads (primary implementation)
146 // =========================================================================
147
148 /**
149 * @brief Route element value to a push constant slot on a ShaderProcessor.
150 * @param ref Owning Layer and element id.
151 * @param target VKBuffer whose push_constant staging receives the value.
152 * @param offset Byte offset in the push constant struct.
153 * @param size Byte width. Defaults to sizeof(float).
154 */
155 void write(
156 const ElementRef& ref,
157 const std::shared_ptr<Buffers::VKBuffer>& target_buffer,
158 const std::string& shader_path,
159 uint32_t offset,
160 size_t size = sizeof(float));
161
162 /**
163 * @brief Route element value to a push constant slot described by a
164 * GpuDataFormat.
165 *
166 * When the element's own value type is exactly this format, the value is
167 * written as it is, so a vec3 or mat4 state keeps every component.
168 * Otherwise the element's float value is converted to the format with
169 * integers saturating, which needs a single component format.
170 *
171 * @param format Layout written at the offset.
172 */
173 void write(
174 const ElementRef& ref,
175 const std::shared_ptr<Buffers::VKBuffer>& target_buffer,
176 const std::string& shader_path,
177 uint32_t offset,
179
180 /**
181 * @brief Route element value to a descriptor binding on @p target_buffer.
182 *
183 * Creates a FormaBindingsProcessor if one does not yet exist for this element
184 * and attaches it to @p target_buffer. If a processor already exists from a
185 * prior write() call, @p target_buffer must be the same buffer — a second
186 * attachment is not made.
187 *
188 * @param ref Owning Layer and element id.
189 * @param target_buffer Buffer whose pipeline context receives the descriptor update.
190 * @param shader_path Shader path used to construct FormaBindingsProcessor if needed.
191 * @param descriptor_name Descriptor name in the shader config.
192 * @param binding_index Vulkan binding index.
193 * @param set Descriptor set index.
194 * @param role UNIFORM or STORAGE.
195 */
196 void write(const ElementRef& ref,
197 const std::shared_ptr<Buffers::VKBuffer>& target_buffer,
198 const std::string& shader_path,
199 const std::string& descriptor_name,
200 uint32_t binding_index,
201 uint32_t set,
202 Portal::Graphics::DescriptorRole role = Portal::Graphics::DescriptorRole::UNIFORM);
203
204 /**
205 * @brief Route element value to an AudioWriteProcessor each frame.
206 * @param ref Owning Layer and element id.
207 * @param target AudioWriteProcessor to call set_data() on.
208 */
209 void write(const ElementRef& ref, std::shared_ptr<Buffers::AudioWriteProcessor> target);
210
211 /**
212 * @brief Route element value to a DataWriteProcessor each frame.
213 * @param ref Owning Layer and element id.
214 * @param target DataWriteProcessor to call set_data() on.
215 */
216 void write(const ElementRef& ref, std::shared_ptr<Buffers::DataWriteProcessor> target);
217
218 /**
219 * @brief Route element value into a Constant node via set_constant().
220 * @param ref Owning Layer and element id.
221 * @param node Constant node updated each frame.
222 */
223 void write(const ElementRef& ref, std::shared_ptr<Nodes::Constant> node);
224
225 /**
226 * @brief Route element bulk value to a caller-supplied sink each frame.
227 *
228 * When the element's MappedState<T> has a bulk_reader (T is vector<float>,
229 * vector<double> or a glm vector), the full value is forwarded as a span.
230 * For scalar T the sink receives a single-element span of the scalar value.
231 *
232 * Intended for consumers that operate on coefficient arrays or other
233 * N-element state: FIR/IIR coefficient vectors, Random node bounds,
234 * any function accepting a contiguous float range.
235 *
236 * @param ref Owning Layer and element id.
237 * @param sink Callable invoked each frame with the current value span.
238 */
239 void write(const ElementRef& ref, std::function<void(std::span<const float>)> sink);
240
241 /**
242 * @brief Route an ordered set of scalar states as one float range each frame.
243 *
244 * The range order is exactly the order of @p states. This is a
245 * layer-owned route rather than an element-owned one: it does not consume
246 * an element id, replace a control's existing outbound bindings, or
247 * require a synthetic owner element. The task stops when @p layer stops.
248 *
249 * @param layer Layer whose lifetime owns the aggregate route.
250 * @param states Non-null scalar states to sample in range order.
251 * @param sink Consumer of the sampled range. The span is valid only
252 * for the duration of the call.
253 */
254 void write(
255 Layer& layer,
256 const std::vector<std::shared_ptr<MappedState<float>>>& states,
257 std::function<void(std::span<const float>)> sink);
258
259 /**
260 * @brief Assemble a typed state range into DataVariant for a write processor.
261 *
262 * Each tick copies the current values of @p states, in order, into a
263 * contiguous span of their native @p T type. @p assemble authors the
264 * conversion from that span to DataVariant. Bridge owns the repeated
265 * sampling, layer lifetime, and delivery through
266 * @c Processor::set_data(DataVariant).
267 *
268 * @tparam T Mapped state value type.
269 * @tparam Processor Destination exposing set_data(DataVariant).
270 * @tparam Assemble Callable returning DataVariant from span<const T>.
271 * @param layer Layer whose lifetime owns the aggregate route.
272 * @param states Non-null states to sample in range order.
273 * @param assemble Author-supplied conversion into DataVariant.
274 * @param target Processor receiving each assembled result.
275 */
276 template <typename T, typename Processor, typename Assemble>
277 void write(
278 Layer& layer,
279 const std::vector<std::shared_ptr<MappedState<T>>>& states,
280 Assemble assemble,
281 std::shared_ptr<Processor> target)
282 {
283 static_assert(std::is_same_v<
284 std::remove_cvref_t<std::invoke_result_t<Assemble&, std::span<const T>>>,
286 "Bridge aggregate assembly must return Kakshya::DataVariant");
287
288 auto sources = states;
289 auto assembler = std::make_shared<Assemble>(std::move(assemble));
290 auto values = std::make_shared<std::vector<T>>();
291
292 write_assembled_data(layer, [sources = std::move(sources), assembler, values]() mutable {
293 values->resize(sources.size());
294 for (size_t i = 0; i < sources.size(); ++i)
295 (*values)[i] = sources[i]->value;
296 return (*assembler)(std::span<const T>(*values)); }, [target = std::move(target)](Kakshya::DataVariant data) { target->set_data(std::move(data)); });
297 }
298
299 // =========================================================================
300 // Outbound — MappedState overloads
301 // =========================================================================
302
303 template <typename T>
304 void write(std::shared_ptr<MappedState<T>> state,
305 std::shared_ptr<Buffers::VKBuffer> target_buffer,
306 const std::string& shader_path,
307 uint32_t offset,
308 size_t size = sizeof(float))
309 {
310 write(ref_of(state), std::move(target_buffer), shader_path, offset, size);
311 }
312
313 template <typename T>
314 void write(std::shared_ptr<MappedState<T>> state,
315 std::shared_ptr<Buffers::VKBuffer> target_buffer,
316 const std::string& shader_path,
317 uint32_t offset,
319 {
320 write(ref_of(state), std::move(target_buffer), shader_path, offset, format);
321 }
322
323 template <typename T>
324 void write(std::shared_ptr<MappedState<T>> state,
325 std::shared_ptr<Buffers::VKBuffer> target_buffer,
326 const std::string& shader_path,
327 const std::string& descriptor_name,
328 uint32_t binding_index,
329 uint32_t set,
330 Portal::Graphics::DescriptorRole role = Portal::Graphics::DescriptorRole::UNIFORM)
331 {
332 write(ref_of(state), std::move(target_buffer), shader_path,
333 descriptor_name, binding_index, set, role);
334 }
335
336 template <typename T>
337 void write(std::shared_ptr<MappedState<T>> state,
338 std::shared_ptr<Buffers::AudioWriteProcessor> target)
339 {
340 write(ref_of(state), std::move(target));
341 }
342
343 template <typename T>
344 void write(std::shared_ptr<MappedState<T>> state,
345 std::shared_ptr<Buffers::DataWriteProcessor> target)
346 {
347 write(ref_of(state), std::move(target));
348 }
349
350 template <typename T>
351 void write(std::shared_ptr<MappedState<T>> state,
352 std::shared_ptr<Nodes::Constant> node)
353 {
354 write(ref_of(state), std::move(node));
355 }
356
357 // =========================================================================
358 // Registration — called by Forma::create_element to make state findable
359 // =========================================================================
360
361 /**
362 * @brief Register a MappedState<T> so that MappedState overloads and
363 * outbound bindings can resolve to the correct element and reader.
364 *
365 * Called by Forma::create_element. The reader closes over the MappedState
366 * and is stored type-erased as std::function<float()>. The state records
367 * @p ref so later calls made through it address the same element.
368 * Rejected, with an error logged, when the Layer in @p ref has no
369 * shared_ptr owner.
370 *
371 * @tparam T MappedState value type.
372 * @param ref Owning Layer and the element id from Layer::add.
373 * @param state MappedState to register.
374 * @param buffer FormaBuffer the element renders into.
375 * @param project Optional T -> float projection. Identity cast if empty.
376 */
377 template <typename T>
379 const ElementRef& ref,
380 std::shared_ptr<MappedState<T>> state,
381 std::shared_ptr<Buffers::FormaBuffer> buffer,
382 std::function<float(T)> project = {})
383 {
384 if (ref.first.expired()) {
385 MF_ERROR(Journal::Component::Portal, Journal::Context::Init,
386 "Bridge::register_element: element {} belongs to a Layer with no shared owner", ref.second);
387 return;
388 }
389
390 const uint32_t id = ref.second;
391
392 std::function<float()> reader;
393 if (project) {
394 reader = [s = state, p = std::move(project)] {
395 return p(s->value);
396 };
397 } else if constexpr (std::is_convertible_v<T, float>) {
398 reader = [s = state] {
399 return static_cast<float>(s->value);
400 };
401 } else {
402 reader = [id, reported = std::make_shared<bool>(false)] {
403 if (!*reported) {
404 *reported = true;
405 MF_RT_WARN(Journal::Component::Portal, Journal::Context::Init,
406 "Bridge: element {} has state type '{}' with no float conversion and no projection; its outbound reader yields 0",
407 id, typeid(T).name());
408 }
409 return 0.F;
410 };
411 }
412
413 std::function<std::vector<float>()> bulk_reader;
414 if constexpr (std::is_same_v<T, std::vector<float>>) {
415 bulk_reader = [s = state] { return s->value; };
416 } else if constexpr (std::is_same_v<T, std::vector<double>>) {
417 bulk_reader = [s = state] {
418 std::vector<float> out;
419 out.reserve(s->value.size());
420 for (double v : s->value)
421 out.push_back(static_cast<float>(v));
422 return out;
423 };
424 } else if constexpr (std::is_same_v<T, glm::vec2> || std::is_same_v<T, glm::vec3> || std::is_same_v<T, glm::vec4>) {
425 bulk_reader = [s = state] {
426 return std::vector<float>(&s->value[0], &s->value[0] + T::length());
427 };
428 }
429
430 std::function<Kakshya::GpuValue()> typed_reader;
431 std::optional<Kakshya::GpuDataFormat> typed_format;
432 if constexpr (Kakshya::GpuFormatElement<T>) {
433 typed_reader = [s = state] { return Kakshya::GpuValue { s->value }; };
434 typed_format = Kakshya::gpu_data_format_v<T>;
435 }
436
437 std::function<void(float)> writer;
438 if constexpr (std::is_convertible_v<float, T>) {
439 writer = [s = state](float v) {
440 s->write(static_cast<T>(v));
441 };
442 } else {
443 writer = [id, reported = std::make_shared<bool>(false)](float) {
444 if (!*reported) {
445 *reported = true;
446 MF_RT_WARN(Journal::Component::Portal, Journal::Context::Init,
447 "Bridge: element {} has state type '{}' with no float conversion and no projection; its inbound writer does nothing",
448 id, typeid(T).name());
449 }
450 };
451 }
452
453 state->id = id;
454 state->layer = ref.first;
455 m_records[ref.first][id] = ElementRecord {
456 .buffer = std::move(buffer),
457 .bindings = nullptr,
458 .reader = std::move(reader),
459 .bulk_reader = std::move(bulk_reader),
460 .writer = std::move(writer),
461 .inbound_task = {},
462 .outbound_tasks = {},
463 .binding_names = {},
464 .typed_reader = std::move(typed_reader),
465 .typed_format = typed_format,
466 };
467 }
468
469 /**
470 * @brief Register a Mapped element and scope its presentation sync to a Layer.
471 *
472 * Each frame's sync pushes the geometry function's bounds_hint and
473 * contains back into @p layer, so hit testing follows the drawn shape.
474 * The Layer scope also stops presentation sync when its Surface closes.
475 * unbind(ref) cancels the sync task as well.
476 *
477 * @p layer must be owned by a shared_ptr, as Surface and
478 * Forma::create_layer do; otherwise the call logs an error and does nothing.
479 *
480 * @param layer Layer owning the element.
481 * @param mapped Fully constructed Mapped element.
482 * @param project Optional T to float projection for outbound readers.
483 */
484 template <typename T>
486 Layer& layer,
487 Mapped<T> mapped,
488 std::function<float(T)> project = {})
489 {
490 auto owner = layer.weak_from_this();
491 if (owner.expired()) {
492 MF_ERROR(Journal::Component::Portal, Journal::Context::Init,
493 "Bridge::register_element: element {} belongs to a Layer with no shared owner", mapped.element.id);
494 return;
495 }
496
497 register_element(ElementRef { std::move(owner), mapped.element.id },
498 mapped.state, mapped.element.buffer.buffer(), std::move(project));
499 spawn_sync(layer, mapped.element.id,
500 [m = std::move(mapped), target = &layer]() mutable { m.sync(target); });
501 }
502
503 // =========================================================================
504 // Binding lifecycle
505 // =========================================================================
506
507 /**
508 * @brief Cancel all inbound and outbound bindings for an element.
509 * The element remains in its layer.
510 */
511 void unbind(const ElementRef& ref);
512
513 /**
514 * @brief Stop Bridge tasks owned by a Layer.
515 *
516 * Stops presentation sync and aggregate routes. Element-owned
517 * bindings associated with individual ids remain active.
518 *
519 * @param layer Layer whose Bridge tasks should stop.
520 */
521 void stop_sync(Layer& layer);
522
523 template <typename T>
524 void unbind(std::shared_ptr<MappedState<T>> state)
525 {
526 unbind(ref_of(state));
527 }
528
529 // =========================================================================
530 // Binding handle
531 // =========================================================================
532
533 /**
534 * @class Binding
535 * @brief Non-owning handle for all bind/write/unbind operations on one element.
536 *
537 * Obtained via Bridge::at(ref) or Bridge::at(state). Closes over the
538 * Bridge reference and the ElementRef so the caller never repeats either.
539 * Every method forwards directly to the corresponding Bridge overload:
540 * there is no deferred execution, no new mechanism.
541 *
542 * Binding holds a reference to its Bridge and must not outlive it.
543 *
544 * @code
545 * bridge.at(el.state)
546 * .bind(envelope_node)
547 * .write(compute_buf, shader_path, offsetof(PC, cutoff))
548 * .write(audio_proc);
549 * @endcode
550 */
551 class Binding {
552 public:
553 Binding(Bridge& bridge, ElementRef ref) noexcept
554 : m_bridge(bridge)
555 , m_ref(std::move(ref))
556 {
557 }
558
559 [[nodiscard]] uint32_t id() const noexcept { return m_ref.second; }
560
561 Binding& bind(std::shared_ptr<Nodes::Node> node,
562 std::function<float(double)> project = {})
563 {
564 m_bridge.bind(m_ref, std::move(node), std::move(project));
565 return *this;
566 }
567
568 Binding& bind(std::function<float()> source)
569 {
570 m_bridge.bind(m_ref, std::move(source));
571 return *this;
572 }
573
575 const std::shared_ptr<Buffers::VKBuffer>& target,
576 const std::string& shader_path,
577 uint32_t offset,
578 size_t size = sizeof(float))
579 {
580 m_bridge.write(m_ref, target, shader_path, offset, size);
581 return *this;
582 }
583
585 const std::shared_ptr<Buffers::VKBuffer>& target,
586 const std::string& shader_path,
587 uint32_t offset,
589 {
590 m_bridge.write(m_ref, target, shader_path, offset, format);
591 return *this;
592 }
593
595 const std::shared_ptr<Buffers::VKBuffer>& target,
596 const std::string& shader_path,
597 const std::string& descriptor_name,
598 uint32_t binding_index,
599 uint32_t set,
600 Portal::Graphics::DescriptorRole role = Portal::Graphics::DescriptorRole::UNIFORM)
601 {
602 m_bridge.write(m_ref, target, shader_path,
603 descriptor_name, binding_index, set, role);
604 return *this;
605 }
606
607 Binding& write(std::shared_ptr<Buffers::AudioWriteProcessor> target)
608 {
609 m_bridge.write(m_ref, std::move(target));
610 return *this;
611 }
612
613 Binding& write(std::shared_ptr<Buffers::DataWriteProcessor> target)
614 {
615 m_bridge.write(m_ref, std::move(target));
616 return *this;
617 }
618
619 Binding& write(std::shared_ptr<Nodes::Constant> node)
620 {
621 m_bridge.write(m_ref, std::move(node));
622 return *this;
623 }
624
625 Binding& write(std::function<void(std::span<const float>)> sink)
626 {
627 m_bridge.write(m_ref, std::move(sink));
628 return *this;
629 }
630
631 void unbind()
632 {
633 m_bridge.unbind(m_ref);
634 }
635
636 private:
639 };
640
641 // =========================================================================
642 // at() — entry point for the Binding handle
643 // =========================================================================
644
645 /**
646 * @brief Return a Binding handle for the element registered under @p ref.
647 *
648 * The handle is lightweight and non-owning. Prefer this over repeated
649 * bind(ref, ...) / write(ref, ...) calls when wiring one element to
650 * multiple sources or destinations.
651 */
652 [[nodiscard]] Binding at(ElementRef ref)
653 {
654 return Binding { *this, std::move(ref) };
655 }
656
657 /**
658 * @brief Return a Binding handle resolved from a MappedState.
659 */
660 template <typename T>
661 [[nodiscard]] Binding at(const std::shared_ptr<MappedState<T>>& state)
662 {
663 return Binding(*this, ref_of(state));
664 }
665
666 /**
667 * @brief Spawn a presentation sync task scoped to a Layer.
668 *
669 * The task name is also stored in the outbound_tasks of the record for
670 * @p id, when one exists, so that unbind() cancels it. @p layer must be
671 * owned by a shared_ptr.
672 *
673 * @param layer Layer that owns the task.
674 * @param id Element id used for task naming and diagnostics.
675 * @param sync_fn Function invoked once per graphics frame.
676 */
677 void spawn_sync(Layer& layer, uint32_t id, std::function<void()> sync_fn);
678
679private:
681 std::shared_ptr<Buffers::FormaBuffer> buffer;
682 std::shared_ptr<Buffers::FormaBindingsProcessor> bindings;
683 std::function<float()> reader; ///< reads current value from MappedState (outbound)
684 std::function<std::vector<float>()> bulk_reader; ///< populated for vector<float>/vector<double> T
685 std::function<void(float)> writer; ///< writes new value into MappedState (inbound)
686 std::string inbound_task;
687 std::vector<std::string> outbound_tasks;
688 std::vector<std::string> binding_names;
689 std::function<Kakshya::GpuValue()> typed_reader; ///< populated when T is a GpuFormatElement
690 std::optional<Kakshya::GpuDataFormat> typed_format; ///< format of T when typed_reader is populated
691 };
692
695
696 mutable uint32_t m_next_id { 0 };
697
698 std::map<std::weak_ptr<Layer>, std::unordered_map<uint32_t, ElementRecord>, std::owner_less<>> m_records;
699 std::map<std::weak_ptr<Layer>, std::vector<std::string>, std::owner_less<>> m_layer_tasks;
700
701 template <typename T>
702 [[nodiscard]] static ElementRef ref_of(const std::shared_ptr<MappedState<T>>& state)
703 {
704 return { state->layer, state->id };
705 }
706
707 [[nodiscard]] ElementRecord* find_record(const ElementRef& ref);
708 std::string make_task_name(uint32_t id, const char* suffix) const;
709 std::string make_layer_task_name(const char* suffix) const;
710 void cancel_inbound(ElementRecord& rec);
711 void cancel_outbound(ElementRecord& rec);
712 void spawn_inbound(const ElementRef& ref, std::function<float()> source);
713 void write_aggregate(
714 Layer& layer,
715 std::vector<std::function<float()>> readers,
716 std::function<void(std::span<const float>)> sink);
717 void write_assembled_data(
718 Layer& layer,
719 std::function<Kakshya::DataVariant()> assemble,
720 std::function<void(Kakshya::DataVariant)> write);
721};
722
723} // namespace MayaFlux::Portal::Forma
#define MF_ERROR(comp, ctx,...)
#define MF_RT_WARN(comp, ctx,...)
uint64_t offset
Definition Composite.cpp:10
bool format
bool size
std::shared_ptr< NetworkGeometryBuffer > buffer
std::vector< float > * out
glm::vec3 value
std::vector< std::byte > values
Definition VDBWriter.cpp:26
std::string name
Definition VKDevice.cpp:123
Token-based multimodal buffer management system for unified data stream processing.
Binding & write(std::function< void(std::span< const float >)> sink)
Definition Bridge.hpp:625
Binding & bind(std::shared_ptr< Nodes::Node > node, std::function< float(double)> project={})
Definition Bridge.hpp:561
Binding & write(std::shared_ptr< Buffers::AudioWriteProcessor > target)
Definition Bridge.hpp:607
Binding & bind(std::function< float()> source)
Definition Bridge.hpp:568
Binding & write(const std::shared_ptr< Buffers::VKBuffer > &target, const std::string &shader_path, const std::string &descriptor_name, uint32_t binding_index, uint32_t set, Portal::Graphics::DescriptorRole role=Portal::Graphics::DescriptorRole::UNIFORM)
Definition Bridge.hpp:594
uint32_t id() const noexcept
Definition Bridge.hpp:559
Binding & write(std::shared_ptr< Buffers::DataWriteProcessor > target)
Definition Bridge.hpp:613
Binding & write(std::shared_ptr< Nodes::Constant > node)
Definition Bridge.hpp:619
Binding & write(const std::shared_ptr< Buffers::VKBuffer > &target, const std::string &shader_path, uint32_t offset, size_t size=sizeof(float))
Definition Bridge.hpp:574
Binding(Bridge &bridge, ElementRef ref) noexcept
Definition Bridge.hpp:553
Binding & write(const std::shared_ptr< Buffers::VKBuffer > &target, const std::string &shader_path, uint32_t offset, Kakshya::GpuDataFormat format)
Definition Bridge.hpp:584
Non-owning handle for all bind/write/unbind operations on one element.
Definition Bridge.hpp:551
std::map< std::weak_ptr< Layer >, std::vector< std::string >, std::owner_less<> > m_layer_tasks
Definition Bridge.hpp:699
std::map< std::weak_ptr< Layer >, std::unordered_map< uint32_t, ElementRecord >, std::owner_less<> > m_records
Definition Bridge.hpp:698
void write(std::shared_ptr< MappedState< T > > state, std::shared_ptr< Buffers::VKBuffer > target_buffer, const std::string &shader_path, const std::string &descriptor_name, uint32_t binding_index, uint32_t set, Portal::Graphics::DescriptorRole role=Portal::Graphics::DescriptorRole::UNIFORM)
Definition Bridge.hpp:324
void write(std::shared_ptr< MappedState< T > > state, std::function< void(std::span< const float >)> sink)
Definition Bridge.hpp:138
void write(std::shared_ptr< MappedState< T > > state, std::shared_ptr< Buffers::VKBuffer > target_buffer, const std::string &shader_path, uint32_t offset, size_t size=sizeof(float))
Definition Bridge.hpp:304
static ElementRef ref_of(const std::shared_ptr< MappedState< T > > &state)
Definition Bridge.hpp:702
void write(std::shared_ptr< MappedState< T > > state, std::shared_ptr< Buffers::VKBuffer > target_buffer, const std::string &shader_path, uint32_t offset, Kakshya::GpuDataFormat format)
Definition Bridge.hpp:314
void write(Layer &layer, const std::vector< std::shared_ptr< MappedState< T > > > &states, Assemble assemble, std::shared_ptr< Processor > target)
Assemble a typed state range into DataVariant for a write processor.
Definition Bridge.hpp:277
void register_element(const ElementRef &ref, std::shared_ptr< MappedState< T > > state, std::shared_ptr< Buffers::FormaBuffer > buffer, std::function< float(T)> project={})
Register a MappedState<T> so that MappedState overloads and outbound bindings can resolve to the corr...
Definition Bridge.hpp:378
Vruta::TaskScheduler & m_scheduler
Definition Bridge.hpp:693
Bridge & operator=(Bridge &&)=delete
void register_element(Layer &layer, Mapped< T > mapped, std::function< float(T)> project={})
Register a Mapped element and scope its presentation sync to a Layer.
Definition Bridge.hpp:485
Bridge(const Bridge &)=delete
void write(std::shared_ptr< MappedState< T > > state, std::shared_ptr< Nodes::Constant > node)
Definition Bridge.hpp:351
void bind(std::shared_ptr< MappedState< T > > state, std::shared_ptr< Nodes::Node > node, std::function< float(double)> project={})
Definition Bridge.hpp:124
void write(std::shared_ptr< MappedState< T > > state, std::shared_ptr< Buffers::DataWriteProcessor > target)
Definition Bridge.hpp:344
Buffers::BufferManager & m_buffer_manager
Definition Bridge.hpp:694
void unbind(std::shared_ptr< MappedState< T > > state)
Definition Bridge.hpp:524
Binding at(ElementRef ref)
Return a Binding handle for the element registered under ref.
Definition Bridge.hpp:652
void bind(std::shared_ptr< MappedState< T > > state, std::function< float()> source)
Definition Bridge.hpp:132
Binding at(const std::shared_ptr< MappedState< T > > &state)
Return a Binding handle resolved from a MappedState.
Definition Bridge.hpp:661
void write(std::shared_ptr< MappedState< T > > state, std::shared_ptr< Buffers::AudioWriteProcessor > target)
Definition Bridge.hpp:337
Bridge & operator=(const Bridge &)=delete
Two-way binding orchestrator for Forma elements.
Definition Bridge.hpp:74
const std::shared_ptr< Buffers::FormaBuffer > & buffer() const noexcept
The underlying buffer; null for an empty handle.
Definition Target.cpp:40
Flat registry of Elements on a surface.
Definition Layer.hpp:24
Token-based multimodal task scheduling system for unified coroutine processing.
Definition Scheduler.hpp:51
std::variant< float, glm::vec2, glm::vec3, glm::vec4, double, glm::dvec2, glm::dvec3, glm::dvec4, int32_t, uint32_t, uint8_t, uint16_t, glm::mat4 > GpuValue
One value of any GpuDataFormat.
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:70
GpuDataFormat
GPU data formats with explicit precision levels.
Contains the node-based computational processing system components.
Definition Chronie.hpp:14
std::pair< std::weak_ptr< Layer >, uint32_t > ElementRef
Layer-scoped element identity.
Definition Bridge.hpp:34
DescriptorRole
Semantic descriptor type — maps to Vulkan descriptor types internally.
std::function< std::vector< float >()> bulk_reader
populated for vector<float>/vector<double> T
Definition Bridge.hpp:684
std::shared_ptr< Buffers::FormaBuffer > buffer
Definition Bridge.hpp:681
std::vector< std::string > outbound_tasks
Definition Bridge.hpp:687
std::function< float()> reader
reads current value from MappedState (outbound)
Definition Bridge.hpp:683
std::function< void(float)> writer
writes new value into MappedState (inbound)
Definition Bridge.hpp:685
std::optional< Kakshya::GpuDataFormat > typed_format
format of T when typed_reader is populated
Definition Bridge.hpp:690
std::shared_ptr< Buffers::FormaBindingsProcessor > bindings
Definition Bridge.hpp:682
std::vector< std::string > binding_names
Definition Bridge.hpp:688
std::function< Kakshya::GpuValue()> typed_reader
populated when T is a GpuFormatElement
Definition Bridge.hpp:689
FormaTarget buffer
Where this region's rendered output is written: a buffer of its own, or a slice of one it shares.
Definition Element.hpp:82
uint32_t id
Stable id assigned by Layer::add. Never zero.
Definition Element.hpp:63
Value carrier for a Mapped primitive.
Definition Mapped.hpp:40
std::shared_ptr< MappedState< T > > state
Shared value carrier. External systems hold a copy of this ptr.
Definition Mapped.hpp:98
Element element
The Element registered with the Layer.
Definition Mapped.hpp:105
Infrastructure for a continuously-mapped value whose GPU geometry tracks it.
Definition Mapped.hpp:96