MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Sinks.cpp
Go to the documentation of this file.
1#include "Sinks.hpp"
2
9
11
12namespace MayaFlux::Nexus {
13
14// =============================================================================
15// Audio
16// =============================================================================
17
19 std::vector<AudioSink>& sinks,
21 uint32_t channel,
22 std::function<Kakshya::DataVariant(const InfluenceContext&)> fn,
23 std::string fn_name)
24{
25 auto buf = std::make_shared<Buffers::AudioBuffer>(channel, Buffers::s_preferred_buffer_size);
26 auto writer = std::make_shared<Buffers::AudioWriteProcessor>();
27 buf->set_default_processor(writer);
28
30
31 sinks.push_back(AudioSink {
32 .buf = std::move(buf),
33 .writer = std::move(writer),
34 .fn = std::move(fn),
35 .fn_name = std::move(fn_name),
36 .channel = channel,
37 });
38
40 "Nexus: audio sink added on channel {}", channel);
41}
42
44 std::vector<AudioSink>& sinks,
46 uint32_t channel)
47{
48 auto it = std::ranges::find_if(sinks,
49 [channel](const AudioSink& s) { return s.channel == channel; });
50
51 if (it == sinks.end()) {
53 "Nexus: remove_audio_sink called for channel {} but no sink found", channel);
54 return;
55 }
56
58 sinks.erase(it);
59
61 "Nexus: audio sink removed from channel {}", channel);
62}
63
64void push_audio_data(std::vector<AudioSink>& sinks, std::span<const double> samples)
65{
66 for (auto& s : sinks) {
67 s.writer->set_data(samples);
68 }
69}
70
71void dispatch_audio_sinks(std::vector<AudioSink>& sinks, const InfluenceContext& ctx)
72{
73 for (auto& s : sinks) {
74 if (!s.fn) {
75 continue;
76 }
77 auto variant = s.fn(ctx);
78
79 if (auto* vec = std::get_if<std::vector<double>>(&variant)) {
80 s.writer->set_data(std::span<const double>(*vec));
81 } else {
82 Kakshya::EigenAccess acc(variant);
83 const Eigen::VectorXd v = acc.to_vector();
84 std::vector<double> samples(static_cast<size_t>(v.size()));
85 Eigen::Map<Eigen::VectorXd>(samples.data(), v.size()) = v;
86 s.writer->set_data(std::span<const double>(samples));
87 }
88 }
89}
90
91// =============================================================================
92// Render
93// =============================================================================
94
96 std::vector<RenderSink>& sinks,
99 RenderFn fn,
100 std::string fn_name,
101 const std::optional<glm::vec3>& initial_position)
102{
103 constexpr size_t k_initial_bytes = 4096;
104
105 auto buf = std::make_shared<Buffers::VKBuffer>(
106 k_initial_bytes,
109
110 auto writer = std::make_shared<Buffers::GeometryWriteProcessor>();
111
112 const bool is_line = config.topology == Portal::Graphics::PrimitiveTopology::LINE_LIST
116
117 if (is_line) {
118 writer->set_mode(Buffers::GeometryWriteMode::LINE);
119 } else if (is_mesh) {
120 writer->set_mode(Buffers::GeometryWriteMode::MESH);
121 } else {
122 writer->set_mode(Buffers::GeometryWriteMode::POINT);
123 }
124
125 buf->set_default_processor(writer);
126
128
129 std::string vert = config.vertex_shader;
130 std::string frag = config.fragment_shader;
131 std::string geom = config.geometry_shader;
132
133 if (vert.empty() || frag.empty()) {
134 switch (config.topology) {
137 if (frag.empty())
138 frag = "line.frag.spv";
139#ifndef MAYAFLUX_PLATFORM_MACOS
140 if (vert.empty())
141 vert = "line.vert.spv";
142 if (geom.empty())
143 geom = "line.geom.spv";
144#else
145 if (vert.empty())
146 vert = "line_fallback.vert.spv";
147#endif
148 break;
151 if (vert.empty())
152 vert = "triangle.vert.spv";
153 if (frag.empty())
154 frag = "triangle.frag.spv";
155 break;
156 default:
157 if (vert.empty())
158 vert = "point.vert.spv";
159 if (frag.empty())
160 frag = "point.frag.spv";
161 break;
162 }
163 }
164
165 auto renderer = std::make_shared<Buffers::RenderProcessor>(Buffers::ShaderConfig { vert });
166 renderer->set_fragment_shader(frag);
167 if (!geom.empty())
168 renderer->set_geometry_shader(geom);
169
170 renderer->set_primitive_topology(config.topology);
171 renderer->set_polygon_mode(config.polygon_mode);
172 renderer->set_cull_mode(config.cull_mode);
173 renderer->set_target_window(config.target_window, buf);
174 buf->get_processing_chain()->add_final_processor(renderer, buf);
175
176 auto& sink = sinks.emplace_back(RenderSink {
177 .buf = buf,
178 .writer = std::move(writer),
179 .renderer = std::move(renderer),
180 .fn = std::move(fn),
181 .fn_name = std::move(fn_name),
182 .window = config.target_window,
183 });
184
185 if (!sink.fn && initial_position.has_value()) {
186 sink.writer->set_data(
187 Kakshya::DataVariant { std::vector<glm::vec3> { *initial_position } });
188 }
189
191 "Nexus: render sink added");
192}
193
195 std::vector<RenderSink>& sinks,
197 const std::shared_ptr<Core::Window>& window)
198{
199 auto it = std::ranges::find_if(sinks,
200 [&window](const RenderSink& s) { return s.window == window; });
201
202 if (it == sinks.end()) {
204 "Nexus: remove_render_sink called but no sink found for given window");
205 return;
206 }
207
209 sinks.erase(it);
210
212 "Nexus: render sink removed");
213}
214
216 std::vector<RenderSink>& sinks,
217 const void* data, size_t byte_count,
218 const Kakshya::VertexLayout& layout)
219{
220 for (auto& s : sinks) {
221 s.writer->set_vertices(data, byte_count, layout);
222 }
223}
224
225void dispatch_render_sinks(std::vector<RenderSink>& sinks, const InfluenceContext& ctx)
226{
227 for (auto& s : sinks) {
228 if (s.fn) {
229 s.fn(ctx);
230 }
231 }
232}
233
234} // namespace MayaFlux::Nexus
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
uint32_t channel
std::string fn_name
void remove_buffer(const std::shared_ptr< Buffer > &buffer, ProcessingToken token, uint32_t channel=0)
Removes a buffer from a token.
void add_buffer(const std::shared_ptr< Buffer > &buffer, ProcessingToken token, uint32_t channel=0)
Adds a buffer to a token and channel.
Token-based multimodal buffer management system for unified data stream processing.
Eigen::VectorXd to_vector() const
Convert DataVariant to Eigen column vector.
Type-erased accessor for converting DataVariant to Eigen types.
uint32_t s_preferred_buffer_size
Global default buffer size.
@ AUDIO_BACKEND
Standard audio processing backend configuration.
@ GRAPHICS_BACKEND
Standard graphics processing backend configuration.
@ LINE
Interpret vertex data as Nodes::LineVertex.
@ MESH
Interpret vertex data as Nodes::MeshVertex.
@ POINT
Interpret vertex data as Nodes::PointVertex.
@ Init
Engine/subsystem initialization.
@ Buffers
Buffers, Managers, processors and processing chains.
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:76
void remove_render_sink(std::vector< RenderSink > &sinks, Buffers::BufferManager &mgr, const std::shared_ptr< Core::Window > &window)
Unregister and destroy the render sink targeting window.
Definition Sinks.cpp:194
void add_audio_sink(std::vector< AudioSink > &sinks, Buffers::BufferManager &mgr, uint32_t channel, std::function< Kakshya::DataVariant(const InfluenceContext &)> fn, std::string fn_name)
Create and register an audio sink on channel.
Definition Sinks.cpp:18
void dispatch_audio_sinks(std::vector< AudioSink > &sinks, const InfluenceContext &ctx)
For each sink that has a producer fn, call it and push the result.
Definition Sinks.cpp:71
void add_render_sink(std::vector< RenderSink > &sinks, Buffers::BufferManager &mgr, const Portal::Graphics::RenderConfig &config, RenderFn fn, std::string fn_name, const std::optional< glm::vec3 > &initial_position)
Create and register a render sink targeting window.
Definition Sinks.cpp:95
std::function< void(const InfluenceContext &)> RenderFn
Definition Sinks.hpp:28
void push_audio_data(std::vector< AudioSink > &sinks, std::span< const double > samples)
Push samples to every audio sink in sinks.
Definition Sinks.cpp:64
void remove_audio_sink(std::vector< AudioSink > &sinks, Buffers::BufferManager &mgr, uint32_t channel)
Unregister and destroy the audio sink on channel.
Definition Sinks.cpp:43
void push_vertices(std::vector< RenderSink > &sinks, const void *data, size_t byte_count, const Kakshya::VertexLayout &layout)
Push pre-resolved vertex bytes to every render sink.
Definition Sinks.cpp:215
void dispatch_render_sinks(std::vector< RenderSink > &sinks, const InfluenceContext &ctx)
For each sink that has a producer fn, call it and push the result.
Definition Sinks.cpp:225
Complete description of vertex data layout in a buffer.
std::shared_ptr< Buffers::AudioBuffer > buf
Definition Sinks.hpp:43
Holds the plumbing for one audio output registered from a Nexus object.
Definition Sinks.hpp:42
Data passed to an Emitter or Agent influence function on each commit.
std::shared_ptr< Core::Window > window
Definition Sinks.hpp:71
std::shared_ptr< Buffers::VKBuffer > buf
Definition Sinks.hpp:66
Holds the plumbing for one graphics output registered from a Nexus object.
Definition Sinks.hpp:65
std::shared_ptr< Core::Window > target_window
Unified rendering configuration for graphics buffers.