MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
AggregateBindingsProcessor.cpp
Go to the documentation of this file.
2
6
7namespace MayaFlux::Buffers {
8
10 const std::string& aggregate_name,
11 const std::shared_ptr<Nodes::Node>& node,
12 const std::shared_ptr<VKBuffer>& target)
13{
14 if (!node) {
16 "Attempted to add null node to aggregate '{}'", aggregate_name);
17 return;
18 }
19
20 if (!target) {
21 error<std::invalid_argument>(
24 std::source_location::current(),
25 "Cannot add node to aggregate '{}' with null target buffer", aggregate_name);
26 }
27
28 auto& aggregate = m_aggregates[aggregate_name];
29
30 if (aggregate.nodes.empty()) {
31 aggregate.target_buffer = target;
32 } else if (aggregate.target_buffer != target) {
34 "Aggregate '{}' already has a different target buffer. Ignoring new target.",
35 aggregate_name);
36 }
37
38 aggregate.nodes.push_back(node);
39 aggregate.staging_data.resize(aggregate.nodes.size());
40
41 size_t required_size = aggregate.nodes.size() * sizeof(float);
42 if (aggregate.target_buffer->get_size_bytes() < required_size) {
44 "Target buffer for aggregate '{}' may be too small: {} nodes require {} bytes, buffer has {} bytes",
45 aggregate_name, aggregate.nodes.size(), required_size,
46 aggregate.target_buffer->get_size_bytes());
47 }
48
50 "Added node to aggregate '{}' (total: {})", aggregate_name, aggregate.nodes.size());
51}
52
54 const std::string& aggregate_name,
55 const std::shared_ptr<Nodes::Node>& node)
56{
57 auto agg_it = m_aggregates.find(aggregate_name);
58 if (agg_it == m_aggregates.end()) {
60 "Attempted to remove node from non-existent aggregate '{}'", aggregate_name);
61 return;
62 }
63
64 auto& nodes = agg_it->second.nodes;
65 auto node_it = std::ranges::find(nodes, node);
66
67 if (node_it != nodes.end()) {
68 nodes.erase(node_it);
69 agg_it->second.staging_data.resize(nodes.size());
70
72 "Removed node from aggregate '{}' (remaining: {})",
73 aggregate_name, nodes.size());
74
75 if (nodes.empty()) {
76 m_aggregates.erase(agg_it);
78 "Removed empty aggregate '{}'", aggregate_name);
79 }
80 } else {
82 "Attempted to remove node not in aggregate '{}'", aggregate_name);
83 }
84}
85
86void AggregateBindingsProcessor::clear_aggregate(const std::string& aggregate_name)
87{
88 if (m_aggregates.erase(aggregate_name) == 0) {
90 "Attempted to clear non-existent aggregate '{}'", aggregate_name);
91 } else {
93 "Cleared aggregate '{}'", aggregate_name);
94 }
95}
96
98{
99 size_t count = m_aggregates.size();
100 m_aggregates.clear();
101
103 "Cleared all aggregates ({})", count);
104}
105
106size_t AggregateBindingsProcessor::get_node_count(const std::string& aggregate_name) const
107{
108 auto it = m_aggregates.find(aggregate_name);
109 return it != m_aggregates.end() ? it->second.nodes.size() : 0;
110}
111
113{
114 size_t total = 0;
115 for (const auto& [name, aggregate] : m_aggregates) {
116 total += aggregate.nodes.size();
117 }
118 return total;
119}
120
122{
123 std::vector<std::string> names;
124 names.reserve(m_aggregates.size());
125 for (const auto& [name, _] : m_aggregates) {
126 names.push_back(name);
127 }
128 return names;
129}
130
132{
133 return m_aggregates.size();
134}
135
136void AggregateBindingsProcessor::processing_function(std::shared_ptr<Buffer> buffer)
137{
138 if (m_aggregates.empty()) {
139 return;
140 }
141
142 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
143 if (!vk_buffer) {
145 "AggregateBindingsProcessor requires VKBuffer, got different buffer type");
146 return;
147 }
148
149 for (auto& [aggregate_name, aggregate] : m_aggregates) {
150 if (aggregate.nodes.empty()) {
151 continue;
152 }
153
154 for (size_t i = 0; i < aggregate.nodes.size(); i++) {
155 aggregate.staging_data[i] = static_cast<float>(
156 aggregate.nodes[i]->get_last_output());
157 }
158
160 aggregate.staging_data.data(),
161 aggregate.staging_data.size() * sizeof(float),
162 aggregate.target_buffer);
163 }
164
165 bool attached_is_target = false;
166 for (const auto& [name, aggregate] : m_aggregates) {
167 if (aggregate.target_buffer == vk_buffer) {
168 attached_is_target = true;
169 break;
170 }
171 }
172
173 if (!attached_is_target && !m_aggregates.empty()) {
174 auto& first_aggregate = m_aggregates.begin()->second;
175
176 if (!first_aggregate.nodes.empty()) {
178 first_aggregate.staging_data.data(),
179 first_aggregate.staging_data.size() * sizeof(float),
180 vk_buffer);
181 }
182 }
183}
184
185} // namespace MayaFlux::Buffers
#define MF_RT_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
size_t get_node_count(const std::string &aggregate_name) const
Get number of nodes in an aggregate.
std::vector< std::string > get_aggregate_names() const
Get all aggregate names.
void processing_function(std::shared_ptr< Buffer > buffer) override
BufferProcessor interface - uploads all aggregates.
std::unordered_map< std::string, AggregateBinding > m_aggregates
void clear_aggregate(const std::string &aggregate_name)
Clear all nodes from an aggregate.
size_t get_total_node_count() const
Get total number of nodes across all aggregates.
size_t get_aggregate_count() const
Get number of aggregates.
void remove_node(const std::string &aggregate_name, const std::shared_ptr< Nodes::Node > &node)
Remove a node from an aggregate.
void add_node(const std::string &aggregate_name, const std::shared_ptr< Nodes::Node > &node, const std::shared_ptr< VKBuffer > &target)
Add a node to a named aggregate.
void upload_to_gpu(const void *data, size_t size, const std::shared_ptr< VKBuffer > &target, const std::shared_ptr< VKBuffer > &staging)
Upload raw data to GPU buffer (auto-detects host-visible vs device-local)
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.