18class AudioWriteProcessor;
19class DataWriteProcessor;
20class FormaBindingsProcessor;
34using ElementRef = std::pair<std::weak_ptr<Layer>, uint32_t>;
104 std::shared_ptr<Nodes::Node> node,
105 std::function<
float(
double)> project = {});
117 void bind(
const ElementRef& ref, std::function<
float()> source);
123 template <
typename T>
125 std::shared_ptr<Nodes::Node> node,
126 std::function<
float(
double)> project = {})
128 bind(ref_of(state), std::move(node), std::move(project));
131 template <
typename T>
134 bind(ref_of(state), std::move(source));
137 template <
typename T>
139 std::function<
void(std::span<const float>)> sink)
141 write(ref_of(state), std::move(sink));
157 const std::shared_ptr<Buffers::VKBuffer>& target_buffer,
158 const std::string& shader_path,
160 size_t size =
sizeof(
float));
175 const std::shared_ptr<Buffers::VKBuffer>& target_buffer,
176 const std::string& shader_path,
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,
209 void write(
const ElementRef& ref, std::shared_ptr<Buffers::AudioWriteProcessor> target);
216 void write(
const ElementRef& ref, std::shared_ptr<Buffers::DataWriteProcessor> target);
223 void write(
const ElementRef& ref, std::shared_ptr<Nodes::Constant> node);
239 void write(
const ElementRef& ref, std::function<
void(std::span<const float>)> sink);
257 std::function<
void(std::span<const float>)> sink);
276 template <
typename T,
typename Processor,
typename Assemble>
281 std::shared_ptr<Processor> target)
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");
288 auto sources = states;
289 auto assembler = std::make_shared<Assemble>(std::move(assemble));
290 auto values = std::make_shared<std::vector<T>>();
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)); });
303 template <
typename T>
305 std::shared_ptr<Buffers::VKBuffer> target_buffer,
306 const std::string& shader_path,
308 size_t size =
sizeof(
float))
310 write(ref_of(state), std::move(target_buffer), shader_path,
offset,
size);
313 template <
typename T>
315 std::shared_ptr<Buffers::VKBuffer> target_buffer,
316 const std::string& shader_path,
320 write(ref_of(state), std::move(target_buffer), shader_path,
offset,
format);
323 template <
typename T>
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,
332 write(ref_of(state), std::move(target_buffer), shader_path,
333 descriptor_name, binding_index, set, role);
336 template <
typename T>
338 std::shared_ptr<Buffers::AudioWriteProcessor> target)
340 write(ref_of(state), std::move(target));
343 template <
typename T>
345 std::shared_ptr<Buffers::DataWriteProcessor> target)
347 write(ref_of(state), std::move(target));
350 template <
typename T>
352 std::shared_ptr<Nodes::Constant> node)
354 write(ref_of(state), std::move(node));
377 template <
typename T>
381 std::shared_ptr<Buffers::FormaBuffer>
buffer,
382 std::function<
float(T)> project = {})
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);
390 const uint32_t
id = ref.second;
392 std::function<float()> reader;
394 reader = [s = state, p = std::move(project)] {
397 }
else if constexpr (std::is_convertible_v<T, float>) {
398 reader = [s = state] {
399 return static_cast<float>(s->value);
402 reader = [id, reported = std::make_shared<bool>(
false)] {
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());
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));
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());
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>;
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));
443 writer = [id, reported = std::make_shared<bool>(
false)](float) {
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());
454 state->layer = ref.first;
455 m_records[ref.first][id] = ElementRecord {
456 .buffer = std::move(
buffer),
458 .reader = std::move(reader),
459 .bulk_reader = std::move(bulk_reader),
460 .writer = std::move(writer),
462 .outbound_tasks = {},
464 .typed_reader = std::move(typed_reader),
465 .typed_format = typed_format,
484 template <
typename T>
488 std::function<
float(T)> project = {})
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);
497 register_element(ElementRef { std::move(owner), mapped.
element.
id },
500 [m = std::move(mapped), target = &layer]()
mutable { m.sync(target); });
511 void unbind(
const ElementRef& ref);
521 void stop_sync(Layer& layer);
523 template <
typename T>
526 unbind(ref_of(state));
555 , m_ref(std::move(ref))
559 [[nodiscard]] uint32_t
id() const noexcept {
return m_ref.second; }
562 std::function<
float(
double)> project = {})
564 m_bridge.
bind(m_ref, std::move(node), std::move(project));
570 m_bridge.
bind(m_ref, std::move(source));
575 const std::shared_ptr<Buffers::VKBuffer>& target,
576 const std::string& shader_path,
578 size_t size =
sizeof(
float))
585 const std::shared_ptr<Buffers::VKBuffer>& target,
586 const std::string& shader_path,
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,
602 m_bridge.
write(m_ref, target, shader_path,
603 descriptor_name, binding_index, set, role);
609 m_bridge.
write(m_ref, std::move(target));
615 m_bridge.
write(m_ref, std::move(target));
621 m_bridge.
write(m_ref, std::move(node));
627 m_bridge.
write(m_ref, std::move(sink));
633 m_bridge.unbind(m_ref);
654 return Binding { *
this, std::move(ref) };
660 template <
typename T>
663 return Binding(*
this, ref_of(state));
677 void spawn_sync(
Layer& layer, uint32_t
id, std::function<
void()> sync_fn);
681 std::shared_ptr<Buffers::FormaBuffer>
buffer;
682 std::shared_ptr<Buffers::FormaBindingsProcessor>
bindings;
696 mutable uint32_t m_next_id { 0 };
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;
701 template <
typename T>
704 return { state->layer, state->id };
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(
715 std::vector<std::function<
float()>> readers,
716 std::function<
void(std::span<const float>)> sink);
717 void write_assembled_data(
#define MF_ERROR(comp, ctx,...)
#define MF_RT_WARN(comp, ctx,...)
std::shared_ptr< NetworkGeometryBuffer > buffer
std::vector< float > * out
std::vector< std::byte > values
Token-based multimodal buffer management system for unified data stream processing.
Token-based multimodal task scheduling system for unified coroutine processing.
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.
GpuDataFormat
GPU data formats with explicit precision levels.
Contains the node-based computational processing system components.
DescriptorRole
Semantic descriptor type — maps to Vulkan descriptor types internally.