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 if (binding.gpu_vertex_buffer->is_host_visible()) {
134 binding.gpu_vertex_buffer->clear();
137 if (binding.node->get_vertex_layout()) {
138 binding.gpu_vertex_buffer->set_vertex_layout(
139 binding.node->get_vertex_layout().value());
143 "Geometry '{}' cleared", name);
147 size_t required_size = vertices.size_bytes();
148 size_t available_size = binding.gpu_vertex_buffer->get_size_bytes();
150 if (required_size > available_size) {
151 auto new_size =
static_cast<size_t>(required_size * 1.5F);
154 "Geometry '{}' growing: resizing GPU buffer from {} → {} bytes",
155 name, available_size, new_size);
157 binding.gpu_vertex_buffer->resize(new_size,
false);
158 available_size = new_size;
160 if (binding.staging_buffer) {
161 binding.staging_buffer->resize(new_size,
false);
163 "Resized staging buffer for '{}' to {} bytes", name, new_size);
167 size_t upload_size = std::min<size_t>(required_size, available_size);
172 binding.gpu_vertex_buffer,
173 binding.staging_buffer);
175 if (binding.node->get_vertex_layout()) {
176 binding.gpu_vertex_buffer->set_vertex_layout(
177 binding.node->get_vertex_layout().value());
180 "Set vertex layout for '{}' ({} vertices, {} attributes)",
182 binding.node->get_vertex_count(),
183 binding.node->get_vertex_layout()->attributes.size());
186 "Geometry node '{}' has no vertex layout. "
187 "RenderProcessor may fail without layout info.",
190 binding.node->clear_gpu_update_flag();
193 bool attached_is_target =
false;
194 for (
const auto& [name, binding] :
m_bindings) {
195 if (binding.gpu_vertex_buffer == vk_buffer) {
196 attached_is_target =
true;
201 if (!attached_is_target && !
m_bindings.empty()) {
202 auto& first_binding =
m_bindings.begin()->second;
203 if (first_binding.node->needs_gpu_update()) {
204 auto vertices = first_binding.node->get_vertex_data();
206 if (!vertices.empty()) {
207 size_t required_size = vertices.size_bytes();
208 size_t available_size = vk_buffer->get_size_bytes();
210 if (required_size > available_size) {
211 auto new_size =
static_cast<size_t>(required_size * 1.5F);
214 "Fallback geometry growing: resizing GPU buffer from {} → {} bytes",
215 available_size, new_size);
217 vk_buffer->resize(new_size,
false);
218 available_size = new_size;
221 size_t upload_size = std::min<size_t>(required_size, available_size);
223 std::shared_ptr<VKBuffer> staging = vk_buffer->is_host_visible() ? nullptr : first_binding.staging_buffer;
231 if (first_binding.node->get_vertex_layout()) {
232 vk_buffer->set_vertex_layout(
233 first_binding.node->get_vertex_layout().value());
236 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)