MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
DescriptorBindingsProcessor.cpp
Go to the documentation of this file.
2
5
8
10
11namespace MayaFlux::Buffers {
12
14 : ShaderProcessor(shader_path)
15{
16}
17
22
23//==============================================================================
24// Binding Methods
25//==============================================================================
26
28 const std::string& name,
29 const std::shared_ptr<Nodes::Node>& node,
30 const std::string& descriptor_name,
31 uint32_t set,
32 vk::DescriptorType type)
33{
34 if (!node) {
36 "Cannot bind null node '{}'", name);
37 return;
38 }
39
40 if (m_config.bindings.find(descriptor_name) == m_config.bindings.end()) {
42 "Descriptor '{}' not found in shader config", descriptor_name);
43 return;
44 }
45
46 const auto& binding_config = m_config.bindings[descriptor_name];
47
48 auto gpu_buffer = create_descriptor_buffer(sizeof(float), type);
49
51 .node = node,
52 .descriptor_name = descriptor_name,
53 .set_index = set,
54 .binding_index = binding_config.binding,
55 .type = type,
56 .binding_type = BindingType::SCALAR,
57 .gpu_buffer = gpu_buffer,
58 .buffer_offset = 0,
59 .buffer_size = sizeof(float)
60 };
61
62 bind_buffer(descriptor_name, gpu_buffer);
63
65
67 "Bound scalar node '{}' to descriptor '{}'", name, descriptor_name);
68}
69
71 const std::string& name,
72 const std::shared_ptr<Nodes::Node>& node,
73 const std::string& descriptor_name,
74 uint32_t set,
75 vk::DescriptorType type)
76{
77 if (!node) {
79 "Cannot bind null node '{}'", name);
80 return;
81 }
82
83 if (m_config.bindings.find(descriptor_name) == m_config.bindings.end()) {
85 "Descriptor '{}' not found in shader config", descriptor_name);
86 return;
87 }
88
89 const auto& binding_config = m_config.bindings[descriptor_name];
90
91 size_t initial_size = 4096 * sizeof(float);
92 auto gpu_buffer = create_descriptor_buffer(initial_size, type);
93
95 .node = node,
96 .descriptor_name = descriptor_name,
97 .set_index = set,
98 .binding_index = binding_config.binding,
99 .type = type,
100 .binding_type = BindingType::VECTOR,
101 .gpu_buffer = gpu_buffer,
102 .buffer_offset = 0,
103 .buffer_size = initial_size
104 };
105
106 bind_buffer(descriptor_name, gpu_buffer);
107
109
111 "Bound vector node '{}' to descriptor '{}'", name, descriptor_name);
112}
113
115 const std::string& name,
116 const std::shared_ptr<Nodes::Node>& node,
117 const std::string& descriptor_name,
118 uint32_t set,
119 vk::DescriptorType type)
120{
121 if (!node) {
123 "Cannot bind null node '{}'", name);
124 return;
125 }
126
127 if (m_config.bindings.find(descriptor_name) == m_config.bindings.end()) {
129 "Descriptor '{}' not found in shader config", descriptor_name);
130 return;
131 }
132
133 const auto& binding_config = m_config.bindings[descriptor_name];
134
135 size_t initial_size = static_cast<long>(1024) * 1024 * sizeof(float);
136 auto gpu_buffer = create_descriptor_buffer(initial_size, type);
137
139 .node = node,
140 .descriptor_name = descriptor_name,
141 .set_index = set,
142 .binding_index = binding_config.binding,
143 .type = type,
144 .binding_type = BindingType::MATRIX,
145 .gpu_buffer = gpu_buffer,
146 .buffer_offset = 0,
147 .buffer_size = initial_size
148 };
149
150 bind_buffer(descriptor_name, gpu_buffer);
151
153
155 "Bound matrix node '{}' to descriptor '{}'", name, descriptor_name);
156}
157
158void DescriptorBindingsProcessor::unbind_node(const std::string& name)
159{
160 auto it = m_bindings.find(name);
161 if (it != m_bindings.end()) {
162 unbind_buffer(it->second.descriptor_name);
163 m_bindings.erase(it);
164
166
168 "Unbound node '{}'", name);
169 }
170}
171
172bool DescriptorBindingsProcessor::has_binding(const std::string& name) const
173{
174 return m_bindings.find(name) != m_bindings.end();
175}
176
178{
179 std::vector<std::string> names;
180 names.reserve(m_bindings.size());
181 for (const auto& [name, _] : m_bindings) {
182 names.push_back(name);
183 }
184 return names;
185}
186
187//==============================================================================
188// Protected Hooks
189//==============================================================================
190
191void DescriptorBindingsProcessor::execute_shader(const std::shared_ptr<VKBuffer>& buffer)
192{
193 auto& bindings_list = buffer->get_pipeline_context().descriptor_buffer_bindings;
194
195 for (auto& [name, binding] : m_bindings) {
197
198 bool found = false;
199 for (auto& existing_binding : bindings_list) {
200 if (existing_binding.set == binding.set_index && existing_binding.binding == binding.binding_index) {
201 existing_binding.buffer_info.buffer = binding.gpu_buffer->get_buffer();
202 existing_binding.buffer_info.offset = binding.buffer_offset;
203 existing_binding.buffer_info.range = binding.buffer_size;
204 found = true;
205 break;
206 }
207 }
208
209 if (!found) {
210 bindings_list.push_back({ .set = binding.set_index,
211 .binding = binding.binding_index,
212 .type = binding.type,
213 .buffer_info = vk::DescriptorBufferInfo {
214 binding.gpu_buffer->get_buffer(),
215 binding.buffer_offset,
216 binding.buffer_size } });
217 }
218 }
219}
220
222{
224 "Pipeline created for DescriptorBindingsProcessor (ID: {}, {} node bindings)",
225 pipeline_id, m_bindings.size());
226
228}
229
230//==============================================================================
231// Private Implementation
232//==============================================================================
233
235{
236 if (!binding.node) {
238 "Binding has null node");
239 return;
240 }
241
242 Nodes::NodeContext& ctx = binding.node->get_last_context();
243
244 switch (binding.binding_type) {
245 case BindingType::SCALAR: {
246 auto value = static_cast<float>(binding.node->get_last_output());
247 ensure_buffer_capacity(binding, sizeof(float));
248
249 upload_to_gpu(&value, sizeof(float), binding.gpu_buffer, nullptr);
250 break;
251 }
252
253 case BindingType::VECTOR: {
254 auto* gpu_vec = dynamic_cast<Nodes::GpuVectorData*>(&ctx);
255 if (!gpu_vec || !gpu_vec->has_gpu_data()) {
257 "Node context does not provide GpuVectorData");
258 return;
259 }
260
261 auto data = gpu_vec->gpu_data();
262
263 ensure_buffer_capacity(binding, data.size_bytes());
264 upload_to_gpu(data.data(), data.size_bytes(), binding.gpu_buffer, nullptr);
265 break;
266 }
267
268 case BindingType::MATRIX: {
269 auto* gpu_mat = dynamic_cast<Nodes::GpuMatrixData*>(&ctx);
270 if (!gpu_mat || !gpu_mat->has_gpu_data()) {
272 "Node context does not provide GpuMatrixData");
273 return;
274 }
275
276 auto data = gpu_mat->gpu_data();
277 ensure_buffer_capacity(binding, data.size_bytes());
278 upload_to_gpu(data.data(), data.size_bytes(), binding.gpu_buffer, nullptr);
279 break;
280 }
281
283 auto* gpu_struct = dynamic_cast<Nodes::GpuStructuredData*>(&ctx);
284 if (!gpu_struct || !gpu_struct->has_gpu_data()) {
286 "Node context does not provide GpuStructuredData");
287 return;
288 }
289
290 auto data = gpu_struct->gpu_data();
291 ensure_buffer_capacity(binding, data.size_bytes());
292 upload_to_gpu(data.data(), data.size_bytes(), binding.gpu_buffer, nullptr);
293 break;
294 }
295 }
296}
297
299 const std::string& name,
300 const std::shared_ptr<Nodes::Node>& node,
301 const std::string& descriptor_name,
302 uint32_t set,
303 vk::DescriptorType type)
304{
305 if (!node) {
307 "Cannot bind null node '{}'", name);
308 return;
309 }
310
311 if (m_config.bindings.find(descriptor_name) == m_config.bindings.end()) {
313 "Descriptor '{}' not found in shader config", descriptor_name);
314 return;
315 }
316
317 const auto& binding_config = m_config.bindings[descriptor_name];
318
319 size_t initial_size = static_cast<long>(1024) * 64;
320 auto gpu_buffer = create_descriptor_buffer(initial_size, type);
321
323 .node = node,
324 .descriptor_name = descriptor_name,
325 .set_index = set,
326 .binding_index = binding_config.binding,
327 .type = type,
328 .binding_type = BindingType::STRUCTURED,
329 .gpu_buffer = gpu_buffer,
330 .buffer_offset = 0,
331 .buffer_size = initial_size
332 };
333
334 bind_buffer(descriptor_name, gpu_buffer);
335
337 "Bound structured node '{}' to descriptor '{}'", name, descriptor_name);
338}
339
341 DescriptorBinding& binding,
342 size_t required_size)
343{
344 if (required_size <= binding.gpu_buffer->get_size_bytes()) {
345 return;
346 }
347
348 size_t new_size = required_size * 3 / 2;
349
351 "Resizing descriptor buffer '{}': {} → {} bytes",
352 binding.descriptor_name, binding.buffer_size, new_size);
353
354 binding.gpu_buffer->resize(new_size, false);
355
356 binding.buffer_size = new_size;
357
359}
360
362 size_t size,
363 vk::DescriptorType type)
364{
365 VKBuffer::Usage usage {};
366
367 if (type == vk::DescriptorType::eUniformBuffer) {
369 } else { // SSBO
371 }
372
373 auto buffer = std::make_shared<VKBuffer>(
374 size,
375 usage,
377
378 auto buffer_service = Registry::BackendRegistry::instance()
380
381 if (!buffer_service) {
382 error<std::runtime_error>(
385 std::source_location::current(),
386 "create_descriptor_buffer requires a valid BufferService");
387 }
388
389 buffer_service->initialize_buffer(buffer);
390
391 return buffer;
392}
393
394} // namespace MayaFlux::Buffers
#define MF_ERROR(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
void update_descriptor_from_node(DescriptorBinding &binding)
Update descriptor from node context.
void unbind_node(const std::string &name)
Remove a binding.
void bind_scalar_node(const std::string &name, const std::shared_ptr< Nodes::Node > &node, const std::string &descriptor_name, uint32_t set, vk::DescriptorType type=vk::DescriptorType::eUniformBuffer)
Bind scalar node output to descriptor.
void execute_shader(const std::shared_ptr< VKBuffer > &buffer) override
void bind_matrix_node(const std::string &name, const std::shared_ptr< Nodes::Node > &node, const std::string &descriptor_name, uint32_t set, vk::DescriptorType type=vk::DescriptorType::eStorageBuffer)
Bind matrix node (MatrixContext) to descriptor.
void on_pipeline_created(Portal::Graphics::ComputePipelineID pipeline_id) override
Called after pipeline creation - allocates GPU buffers for descriptors.
void ensure_buffer_capacity(DescriptorBinding &binding, size_t required_size)
Ensure descriptor buffer has sufficient capacity.
std::shared_ptr< VKBuffer > create_descriptor_buffer(size_t size, vk::DescriptorType type)
Create GPU buffer for a descriptor binding.
bool has_binding(const std::string &name) const
Check if binding exists.
void bind_structured_node(const std::string &name, const std::shared_ptr< Nodes::Node > &node, const std::string &descriptor_name, uint32_t set, vk::DescriptorType type=vk::DescriptorType::eStorageBuffer)
Bind structured node (arrays of POD structs) to descriptor.
std::unordered_map< std::string, DescriptorBinding > m_bindings
void bind_vector_node(const std::string &name, const std::shared_ptr< Nodes::Node > &node, const std::string &descriptor_name, uint32_t set, vk::DescriptorType type=vk::DescriptorType::eStorageBuffer)
Bind vector node (VectorContext) to descriptor.
@ STRUCTURED
Array of structs from StructuredContext.
DescriptorBindingsProcessor(const std::string &shader_path)
Create DescriptorBindingsProcessor with shader path.
std::vector< std::string > get_binding_names() const
Get all binding names.
void unbind_buffer(const std::string &descriptor_name)
Unbind a buffer from a descriptor.
virtual void on_pipeline_created(Portal::Graphics::ComputePipelineID pipeline_id)
Called after pipeline is created.
void bind_buffer(const std::string &descriptor_name, const std::shared_ptr< VKBuffer > &buffer)
Bind a VKBuffer to a named shader descriptor.
Abstract base class for shader-based buffer processing.
@ UNIFORM
Uniform buffer (host-visible when requested)
@ COMPUTE
Storage buffer for compute shaders.
GPU-uploadable 2D grid data interface.
GPU-uploadable structured data (arrays of POD structs)
GPU-uploadable 1D array data interface.
Base context class for node callbacks.
Definition Node.hpp:30
Interface * get_service()
Query for a backend service.
static BackendRegistry & instance()
Get the global registry instance.
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.
@ UNKNOWN
Unknown or undefined modality.
std::shared_ptr< VKBuffer > gpu_buffer
UBO/SSBO backing storage.
std::unordered_map< std::string, ShaderBinding > bindings
Backend buffer management service interface.