MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
GeometryBindingsProcessor.cpp
Go to the documentation of this file.
2
7
8namespace MayaFlux::Buffers {
9
15
17 const std::string& name,
18 const std::shared_ptr<Nodes::GpuSync::GeometryWriterNode>& node,
19 const std::shared_ptr<VKBuffer>& vertex_buffer)
20{
21 if (!node) {
22 error<std::invalid_argument>(
25 std::source_location::current(),
26 "Cannot bind null geometry node '{}'", name);
27 }
28
29 if (!vertex_buffer) {
30 error<std::invalid_argument>(
33 std::source_location::current(),
34 "Cannot bind geometry node '{}' to null vertex buffer", name);
35 }
36
37 size_t vertex_data_size = node->get_vertex_buffer_size_bytes();
38
39 if (vertex_buffer->get_size_bytes() < vertex_data_size) {
41 "Vertex buffer for '{}' may be too small: {} bytes required, {} available. "
42 "Will upload partial data.",
43 name, vertex_data_size, vertex_buffer->get_size_bytes());
44 }
45
46 std::shared_ptr<VKBuffer> staging = nullptr;
47 if (!vertex_buffer->is_host_visible()) {
48 size_t staging_size = std::max<size_t>(vertex_buffer->get_size_bytes(), vertex_data_size);
49 staging = create_staging_buffer(staging_size);
50
52 "Created staging buffer for device-local geometry '{}' ({} bytes)",
53 name, staging_size);
54 } else {
56 "No staging needed for host-visible geometry '{}'", name);
57 }
58
59 std::shared_ptr<VKBuffer> index_buf = nullptr;
60 std::shared_ptr<VKBuffer> index_staging_buf = nullptr;
61
62 if (node->has_indices()) {
63 const size_t index_data_size = node->get_index_count() * sizeof(uint32_t);
64 index_buf = std::make_shared<VKBuffer>(
65 index_data_size,
68
69 ensure_initialized(index_buf);
70
71 index_staging_buf = create_staging_buffer(index_data_size);
73 "Created index staging buffer for device-local geometry '{}' ({} bytes)",
74 name, index_data_size);
75 }
76
78 .node = node,
79 .gpu_vertex_buffer = vertex_buffer,
80 .staging_buffer = staging,
81 .gpu_index_buffer = index_buf,
82 .index_staging_buffer = index_staging_buf
83 };
84
86 "Bound geometry node '{}' ({} vertices, {} bytes, stride: {}, indices: {})",
87 name, node->get_vertex_count(), vertex_data_size, node->get_vertex_stride(),
88 node->get_index_count());
89}
90
92{
93 if (m_bindings.erase(name) == 0) {
95 "Attempted to unbind non-existent geometry node '{}'", name);
96 } else {
98 "Unbound geometry node '{}'", name);
99 }
100}
101
102bool GeometryBindingsProcessor::has_binding(const std::string& name) const
103{
104 return m_bindings.contains(name);
105}
106
107std::vector<std::string> GeometryBindingsProcessor::get_binding_names() const
108{
109 std::vector<std::string> names;
110 names.reserve(m_bindings.size());
111 for (const auto& [name, _] : m_bindings) {
112 names.push_back(name);
113 }
114 return names;
115}
116
118{
119 return m_bindings.size();
120}
121
122std::optional<GeometryBindingsProcessor::GeometryBinding>
123GeometryBindingsProcessor::get_binding(const std::string& name) const
124{
125 auto it = m_bindings.find(name);
126 if (it != m_bindings.end()) {
127 return it->second;
128 }
129 return std::nullopt;
130}
131
132void GeometryBindingsProcessor::processing_function(const std::shared_ptr<Buffer>& buffer)
133{
134 if (m_bindings.empty()) {
135 return;
136 }
137
138 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
139 if (!vk_buffer) {
141 "GeometryBindingsProcessor requires VKBuffer, got different buffer type");
142 return;
143 }
144
145 for (auto& [name, binding] : m_bindings) {
146 if (!binding.node->needs_gpu_update()) {
148 "Geometry '{}' unchanged, skipping upload", name);
149 continue;
150 }
151
152 auto vertices = binding.node->get_vertex_data();
153
154 if (vertices.empty()) {
155 if (binding.gpu_vertex_buffer->is_host_visible()) {
156 binding.gpu_vertex_buffer->clear();
157 }
158
159 if (binding.node->get_vertex_layout()) {
160 binding.gpu_vertex_buffer->set_vertex_layout(
161 binding.node->get_vertex_layout().value());
162 }
163
165 "Geometry '{}' cleared", name);
166 continue;
167 }
168
170 vertices.data(),
171 vertices.size_bytes(),
172 binding.gpu_vertex_buffer,
173 binding.staging_buffer);
174
175 if (binding.node->get_vertex_layout()) {
176 binding.gpu_vertex_buffer->set_vertex_layout(
177 binding.node->get_vertex_layout().value());
178
180 "Set vertex layout for '{}' ({} vertices, {} attributes)",
181 name,
182 binding.node->get_vertex_count(),
183 binding.node->get_vertex_layout()->attributes.size());
184 } else {
186 "Geometry node '{}' has no vertex layout. "
187 "RenderProcessor may fail without layout info.",
188 name);
189 }
190
191 upload_index_data(name, binding);
192 binding.node->clear_gpu_update_flag();
193 }
194
195 bool attached_is_target = false;
196 for (const auto& [name, binding] : m_bindings) {
197 if (binding.gpu_vertex_buffer == vk_buffer) {
198 attached_is_target = true;
199 break;
200 }
201 }
202
203 if (!attached_is_target && !m_bindings.empty()) {
204 auto& first_binding = m_bindings.begin()->second;
205 if (first_binding.node->needs_gpu_update()) {
206 auto vertices = first_binding.node->get_vertex_data();
207
208 if (!vertices.empty()) {
210 vertices.data(),
211 vertices.size_bytes(),
212 vk_buffer,
213 first_binding.staging_buffer);
214
215 if (first_binding.node->get_vertex_layout()) {
216 vk_buffer->set_vertex_layout(
217 first_binding.node->get_vertex_layout().value());
218 }
219 }
220 upload_index_data(m_bindings.begin()->first, first_binding);
221 first_binding.node->clear_gpu_update_flag();
222 }
223 }
224}
225
227 const std::string& name,
228 GeometryBinding& binding)
229{
230 if (!binding.node->has_indices()) {
231 return;
232 }
233
234 const auto indices = binding.node->get_index_data();
235 const size_t required = indices.size_bytes();
236
237 if (required == 0) {
238 return;
239 }
240
241 if (!binding.gpu_index_buffer) {
242 binding.gpu_index_buffer = std::make_shared<VKBuffer>(
243 required,
246
248
250
252 "Lazily created index buffer for '{}' ({} bytes)", name, required);
253 }
254
256 indices.data(),
257 required,
258 binding.gpu_index_buffer,
259 binding.index_staging_buffer);
260
261 binding.gpu_vertex_buffer->set_index_resources(
262 binding.gpu_index_buffer->get_buffer(),
263 binding.gpu_index_buffer->get_buffer_resources().memory,
264 binding.gpu_index_buffer->get_size_bytes());
265
267 "Uploaded {} indices ({} bytes) for '{}'",
268 binding.node->get_index_count(), required, name);
269}
270
271} // namespace MayaFlux::Buffers
#define MF_RT_WARN(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
#define MF_TRACE(comp, ctx,...)
#define MF_RT_TRACE(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
std::optional< GeometryBinding > get_binding(const std::string &name) const
Get a specific binding.
std::unordered_map< std::string, GeometryBinding > m_bindings
void upload_index_data(const std::string &name, GeometryBinding &binding)
Upload index data for one binding, creating or growing the GPU index buffer as needed.
std::vector< std::string > get_binding_names() const
Get all binding names.
size_t get_binding_count() const
Get number of active bindings.
void processing_function(const std::shared_ptr< Buffer > &buffer) override
BufferProcessor interface - uploads all bound geometries.
void bind_geometry_node(const std::string &name, const std::shared_ptr< Nodes::GpuSync::GeometryWriterNode > &node, const std::shared_ptr< VKBuffer > &vertex_buffer)
Bind a geometry node to a GPU vertex buffer.
bool has_binding(const std::string &name) const
Check if a binding exists.
void unbind_geometry_node(const std::string &name)
Remove a geometry binding.
void ensure_initialized(const std::shared_ptr< VKBuffer > &buffer)
Definition VKBuffer.cpp:462
void upload_resizing(const void *data, size_t size, const std::shared_ptr< VKBuffer > &target, const std::shared_ptr< VKBuffer > &staging, float growth_factor)
Upload size bytes to target, growing both buffers first if needed.
@ GRAPHICS_BACKEND
Standard graphics processing backend configuration.
std::shared_ptr< VKBuffer > create_staging_buffer(size_t size)
Create staging buffer for transfers.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
@ UNKNOWN
Unknown or undefined modality.
std::shared_ptr< Nodes::GpuSync::GeometryWriterNode > node
Holds GPU resources for one GeometryWriterNode binding.