MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
DescriptorBindingsProcessor.cpp
Go to the documentation of this file.
2
4
7
8namespace MayaFlux::Buffers {
9
11 const std::string& shader_path,
12 uint32_t workgroup_x)
13 : ShaderProcessor(shader_path, workgroup_x)
14{
15}
16
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 "Bound scalar node '{}' to descriptor '{}'", name, descriptor_name);
66}
67
69 const std::string& name,
70 const std::shared_ptr<Nodes::Node>& node,
71 const std::string& descriptor_name,
72 uint32_t set,
73 vk::DescriptorType type)
74{
75 if (!node) {
77 "Cannot bind null node '{}'", name);
78 return;
79 }
80
81 if (m_config.bindings.find(descriptor_name) == m_config.bindings.end()) {
83 "Descriptor '{}' not found in shader config", descriptor_name);
84 return;
85 }
86
87 const auto& binding_config = m_config.bindings[descriptor_name];
88
89 size_t initial_size = 4096 * sizeof(float);
90 auto gpu_buffer = create_descriptor_buffer(initial_size, type);
91
93 .node = node,
94 .descriptor_name = descriptor_name,
95 .set_index = set,
96 .binding_index = binding_config.binding,
97 .type = type,
98 .binding_type = BindingType::VECTOR,
99 .gpu_buffer = gpu_buffer,
100 .buffer_offset = 0,
101 .buffer_size = initial_size
102 };
103
104 bind_buffer(descriptor_name, gpu_buffer);
105
107 "Bound vector node '{}' to descriptor '{}'", name, descriptor_name);
108}
109
111 const std::string& name,
112 const std::shared_ptr<Nodes::Node>& node,
113 const std::string& descriptor_name,
114 uint32_t set,
115 vk::DescriptorType type)
116{
117 if (!node) {
119 "Cannot bind null node '{}'", name);
120 return;
121 }
122
123 if (m_config.bindings.find(descriptor_name) == m_config.bindings.end()) {
125 "Descriptor '{}' not found in shader config", descriptor_name);
126 return;
127 }
128
129 const auto& binding_config = m_config.bindings[descriptor_name];
130
131 size_t initial_size = static_cast<long>(1024) * 1024 * sizeof(float);
132 auto gpu_buffer = create_descriptor_buffer(initial_size, type);
133
135 .node = node,
136 .descriptor_name = descriptor_name,
137 .set_index = set,
138 .binding_index = binding_config.binding,
139 .type = type,
140 .binding_type = BindingType::MATRIX,
141 .gpu_buffer = gpu_buffer,
142 .buffer_offset = 0,
143 .buffer_size = initial_size
144 };
145
146 bind_buffer(descriptor_name, gpu_buffer);
147
149 "Bound matrix node '{}' to descriptor '{}'", name, descriptor_name);
150}
151
152void DescriptorBindingsProcessor::unbind_node(const std::string& name)
153{
154 auto it = m_bindings.find(name);
155 if (it != m_bindings.end()) {
156 unbind_buffer(it->second.descriptor_name);
157 m_bindings.erase(it);
158
160 "Unbound node '{}'", name);
161 }
162}
163
164bool DescriptorBindingsProcessor::has_binding(const std::string& name) const
165{
166 return m_bindings.find(name) != m_bindings.end();
167}
168
170{
171 std::vector<std::string> names;
172 names.reserve(m_bindings.size());
173 for (const auto& [name, _] : m_bindings) {
174 names.push_back(name);
175 }
176 return names;
177}
178
179//==============================================================================
180// Protected Hooks
181//==============================================================================
182
185 const std::shared_ptr<VKBuffer>& buffer)
186{
187 for (auto& [name, binding] : m_bindings) {
189 }
190
192}
193
195{
197 "Pipeline created for DescriptorBindingsProcessor (ID: {}, {} node bindings)",
198 pipeline_id, m_bindings.size());
199
201}
202
203//==============================================================================
204// Private Implementation
205//==============================================================================
206
208{
209 if (!binding.node) {
211 "Binding has null node");
212 return;
213 }
214
215 Nodes::NodeContext& ctx = binding.node->get_last_context();
216
217 switch (binding.binding_type) {
218 case BindingType::SCALAR: {
219 auto value = static_cast<float>(binding.node->get_last_output());
220 ensure_buffer_capacity(binding, sizeof(float));
221
222 upload_to_gpu(&value, sizeof(float), binding.gpu_buffer, nullptr);
223 break;
224 }
225
226 case BindingType::VECTOR: {
227 auto* gpu_vec = dynamic_cast<Nodes::GpuVectorData*>(&ctx);
228 if (!gpu_vec || !gpu_vec->has_gpu_data()) {
230 "Node context does not provide GpuVectorData");
231 return;
232 }
233
234 auto data = gpu_vec->gpu_data();
235
236 ensure_buffer_capacity(binding, data.size_bytes());
237 upload_to_gpu(data.data(), data.size_bytes(), binding.gpu_buffer, nullptr);
238 break;
239 }
240
241 case BindingType::MATRIX: {
242 auto* gpu_mat = dynamic_cast<Nodes::GpuMatrixData*>(&ctx);
243 if (!gpu_mat || !gpu_mat->has_gpu_data()) {
245 "Node context does not provide GpuMatrixData");
246 return;
247 }
248
249 auto data = gpu_mat->gpu_data();
250 ensure_buffer_capacity(binding, data.size_bytes());
251 upload_to_gpu(data.data(), data.size_bytes(), binding.gpu_buffer, nullptr);
252 break;
253 }
254
256 auto* gpu_struct = dynamic_cast<Nodes::GpuStructuredData*>(&ctx);
257 if (!gpu_struct || !gpu_struct->has_gpu_data()) {
259 "Node context does not provide GpuStructuredData");
260 return;
261 }
262
263 auto data = gpu_struct->gpu_data();
264 ensure_buffer_capacity(binding, data.size_bytes());
265 upload_to_gpu(data.data(), data.size_bytes(), binding.gpu_buffer, nullptr);
266 break;
267 }
268 }
269}
270
272 const std::string& name,
273 const std::shared_ptr<Nodes::Node>& node,
274 const std::string& descriptor_name,
275 uint32_t set,
276 vk::DescriptorType type)
277{
278 if (!node) {
280 "Cannot bind null node '{}'", name);
281 return;
282 }
283
284 if (m_config.bindings.find(descriptor_name) == m_config.bindings.end()) {
286 "Descriptor '{}' not found in shader config", descriptor_name);
287 return;
288 }
289
290 const auto& binding_config = m_config.bindings[descriptor_name];
291
292 size_t initial_size = static_cast<long>(1024) * 64;
293 auto gpu_buffer = create_descriptor_buffer(initial_size, type);
294
296 .node = node,
297 .descriptor_name = descriptor_name,
298 .set_index = set,
299 .binding_index = binding_config.binding,
300 .type = type,
301 .binding_type = BindingType::STRUCTURED,
302 .gpu_buffer = gpu_buffer,
303 .buffer_offset = 0,
304 .buffer_size = initial_size
305 };
306
307 bind_buffer(descriptor_name, gpu_buffer);
308
310 "Bound structured node '{}' to descriptor '{}'", name, descriptor_name);
311}
312
314 DescriptorBinding& binding,
315 size_t required_size)
316{
317 if (required_size <= binding.gpu_buffer->get_size_bytes()) {
318 return;
319 }
320
321 size_t new_size = required_size * 3 / 2;
322
324 "Resizing descriptor buffer '{}': {} → {} bytes",
325 binding.descriptor_name, binding.buffer_size, new_size);
326
327 binding.gpu_buffer->resize(new_size, false);
328
329 binding.buffer_size = new_size;
330
332}
333
335 size_t size,
336 vk::DescriptorType type)
337{
338 VKBuffer::Usage usage {};
339
340 if (type == vk::DescriptorType::eUniformBuffer) {
342 } else { // SSBO
344 }
345
346 return std::make_shared<VKBuffer>(
347 size,
348 usage,
350}
351
352} // 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.
DescriptorBindingsProcessor(const std::string &shader_path, uint32_t workgroup_x=256)
Create DescriptorBindingsProcessor with shader path.
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 on_before_dispatch(Portal::Graphics::CommandBufferID cmd_id, const std::shared_ptr< VKBuffer > &buffer) override
Called before shader dispatch - updates all descriptors.
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.
std::vector< std::string > get_binding_names() const
Get all binding names.
virtual void on_before_dispatch(Portal::Graphics::CommandBufferID cmd_id, const std::shared_ptr< VKBuffer > &buffer)
Called before each dispatch.
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.
Generic compute shader processor for VKBuffers.
@ 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
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
Complete configuration for shader processor.