16 const std::string& name,
17 const std::shared_ptr<Nodes::GpuSync::GeometryWriterNode>& node,
18 const std::shared_ptr<VKBuffer>& vertex_buffer)
21 error<std::invalid_argument>(
24 std::source_location::current(),
25 "Cannot bind null geometry node '{}'", name);
29 error<std::invalid_argument>(
32 std::source_location::current(),
33 "Cannot bind geometry node '{}' to null vertex buffer", name);
36 size_t vertex_data_size = node->get_vertex_buffer_size_bytes();
38 if (vertex_buffer->get_size_bytes() < vertex_data_size) {
40 "Vertex buffer for '{}' may be too small: {} bytes required, {} available. "
41 "Will upload partial data.",
42 name, vertex_data_size, vertex_buffer->get_size_bytes());
45 std::shared_ptr<VKBuffer> staging =
nullptr;
46 if (!vertex_buffer->is_host_visible()) {
47 size_t staging_size = std::max<size_t>(vertex_buffer->get_size_bytes(), vertex_data_size);
51 "Created staging buffer for device-local geometry '{}' ({} bytes)",
55 "No staging needed for host-visible geometry '{}'", name);
60 .gpu_vertex_buffer = vertex_buffer,
61 .staging_buffer = staging
65 "Bound geometry node '{}' ({} vertices, {} bytes, stride: {})",
66 name, node->get_vertex_count(), vertex_data_size, node->get_vertex_stride());
116 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
119 "GeometryBindingsProcessor requires VKBuffer, got different buffer type");
124 if (!binding.node->needs_gpu_update()) {
126 "Geometry '{}' unchanged, skipping upload", name);
130 auto vertices = binding.node->get_vertex_data();
132 if (vertices.empty()) {
133 binding.gpu_vertex_buffer->clear();
135 if (binding.node->get_vertex_layout()) {
136 binding.gpu_vertex_buffer->set_vertex_layout(
137 binding.node->get_vertex_layout().value());
141 "Geometry '{}' cleared", name);
145 size_t required_size = vertices.size_bytes();
146 size_t available_size = binding.gpu_vertex_buffer->get_size_bytes();
148 if (required_size > available_size) {
149 auto new_size =
static_cast<size_t>(required_size * 1.5F);
152 "Geometry '{}' growing: resizing GPU buffer from {} → {} bytes",
153 name, available_size, new_size);
155 binding.gpu_vertex_buffer->resize(new_size,
false);
156 available_size = new_size;
158 if (binding.staging_buffer) {
159 binding.staging_buffer->resize(new_size,
false);
161 "Resized staging buffer for '{}' to {} bytes", name, new_size);
165 size_t upload_size = std::min<size_t>(required_size, available_size);
170 binding.gpu_vertex_buffer,
171 binding.staging_buffer);
173 if (binding.node->get_vertex_layout()) {
174 binding.gpu_vertex_buffer->set_vertex_layout(
175 binding.node->get_vertex_layout().value());
178 "Set vertex layout for '{}' ({} vertices, {} attributes)",
180 binding.node->get_vertex_count(),
181 binding.node->get_vertex_layout()->attributes.size());
184 "Geometry node '{}' has no vertex layout. "
185 "RenderProcessor may fail without layout info.",
188 binding.node->clear_gpu_update_flag();
191 bool attached_is_target =
false;
192 for (
const auto& [name, binding] :
m_bindings) {
193 if (binding.gpu_vertex_buffer == vk_buffer) {
194 attached_is_target =
true;
199 if (!attached_is_target && !
m_bindings.empty()) {
200 auto& first_binding =
m_bindings.begin()->second;
201 if (first_binding.node->needs_gpu_update()) {
202 auto vertices = first_binding.node->get_vertex_data();
204 if (!vertices.empty()) {
205 size_t required_size = vertices.size_bytes();
206 size_t available_size = vk_buffer->get_size_bytes();
208 if (required_size > available_size) {
209 auto new_size =
static_cast<size_t>(required_size * 1.5F);
212 "Fallback geometry growing: resizing GPU buffer from {} → {} bytes",
213 available_size, new_size);
215 vk_buffer->resize(new_size,
false);
216 available_size = new_size;
219 size_t upload_size = std::min<size_t>(required_size, available_size);
221 std::shared_ptr<VKBuffer> staging = vk_buffer->is_host_visible() ? nullptr : first_binding.staging_buffer;
229 if (first_binding.node->get_vertex_layout()) {
230 vk_buffer->set_vertex_layout(
231 first_binding.node->get_vertex_layout().value());
234 first_binding.node->clear_gpu_update_flag();
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)