20 const std::string&
name,
21 const std::shared_ptr<Nodes::Network::NodeNetwork>&
network,
22 const std::shared_ptr<VKBuffer>& vertex_buffer)
25 error<std::invalid_argument>(
28 std::source_location::current(),
29 "Cannot bind null network '{}'",
name);
33 error<std::invalid_argument>(
36 std::source_location::current(),
37 "Cannot bind network '{}' to null vertex buffer",
name);
40 std::shared_ptr<VKBuffer> staging =
nullptr;
41 if (!vertex_buffer->is_host_visible()) {
45 "Created staging buffer for device-local network geometry '{}' ({} bytes)",
46 name, vertex_buffer->get_size_bytes());
49 "No staging needed for host-visible network geometry '{}'",
name);
54 .gpu_vertex_buffer = vertex_buffer,
55 .staging_buffer = staging
59 "Bound network '{}' ({} nodes, {} bytes buffer)",
60 name,
network->get_node_count(), vertex_buffer->get_size_bytes());
109 auto vk_buffer = std::dynamic_pointer_cast<VKBuffer>(buffer);
112 "NetworkGeometryProcessor requires VKBuffer");
117 if (!binding.network || !binding.network->is_enabled()) {
119 "Network '{}' disabled, skipping upload",
name);
123 const auto* chain = binding.network->get_operator_chain().get();
124 const bool has_chain = chain && !chain->empty();
128 binding.network->get_operator());
130 if (primary_op && primary_op->supports_incremental_upload()) {
132 const size_t total =
static_cast<size_t>(primary_op->get_vertex_count())
136 binding, vk_buffer, total,
name)) {
142 if (gpu_data.vertex_data.empty() || gpu_data.vertex_count == 0) {
143 if (vk_buffer->is_host_visible())
148 size_t total = gpu_data.vertex_data.size();
150 if (total > vk_buffer->get_size_bytes()) {
151 vk_buffer->resize(
static_cast<size_t>(
static_cast<float>(total) * 1.5F),
false);
155 upload_to_gpu(gpu_data.vertex_data.data(), total, vk_buffer, binding.staging_buffer);
158 vk_buffer->set_vertex_layout(*gpu_data.layout);
160 binding.last_total_bytes = total;
163 "Uploaded {} vertices from network '{}' ({} bytes)",
164 gpu_data.vertex_count,
name, total);
169 std::span<const uint8_t> bytes;
170 size_t vertex_count {};
171 std::optional<Kakshya::VertexLayout> layout;
174 std::vector<SliceData> slices;
175 slices.reserve(1 + chain->size());
178 slices.push_back({ .bytes = primary.vertex_data, .vertex_count = primary.vertex_count, .layout = primary.layout });
180 for (
const auto& op : chain->operators()) {
183 slices.push_back({ .bytes = {}, .vertex_count = 0, .layout = std::nullopt });
187 if (!gfx->participates_in_rendering())
190 slices.push_back({ .bytes = gfx->get_vertex_data(), .vertex_count = gfx->get_vertex_count(), .layout = gfx->get_vertex_layout() });
193 size_t total_bytes = 0;
194 for (
const auto& s : slices)
195 total_bytes += s.bytes.size();
197 if (total_bytes == 0) {
198 if (vk_buffer->is_host_visible())
203 bool chain_gfx_dirty =
false;
204 bool needs_full_restore =
false;
205 for (
const auto& op : chain->operators()) {
206 if (op && op->demands_full_vertex_restore())
207 needs_full_restore =
true;
210 if (gfx && gfx->participates_in_rendering() && gfx->is_vertex_data_dirty())
211 chain_gfx_dirty =
true;
214 if (!needs_full_restore && !chain_gfx_dirty && primary.layout.has_value()
217 primary.layout->stride_bytes, binding, vk_buffer, total_bytes,
name)) {
221 if (total_bytes > vk_buffer->get_size_bytes()) {
222 vk_buffer->resize(
static_cast<size_t>(
static_cast<float>(total_bytes) * 1.5F),
false);
226 size_t byte_offset = 0;
227 for (
const auto& s : slices) {
228 if (!s.bytes.empty())
230 byte_offset += s.bytes.size();
236 for (
auto& slice : std::views::reverse(slices)) {
238 vk_buffer->set_vertex_layout(*slice.layout);
243 auto ngb = std::dynamic_pointer_cast<NetworkGeometryBuffer>(buffer);
246 for (
size_t i = 0; i < slices.size(); ++i) {
247 const auto& s = slices[i];
248 const uint32_t stride = s.layout ? s.layout->stride_bytes
249 : (slices[0].layout ? slices[0].layout->stride_bytes : 0);
250 const uint32_t vert_offset = stride > 0
251 ?
static_cast<uint32_t
>(byte_offset / stride)
254 ngb->update_chain_render_range(i, vert_offset,
255 static_cast<uint32_t
>(s.vertex_count), s.layout);
257 byte_offset += s.bytes.size();
261 binding.last_total_bytes = total_bytes;
264 "Uploaded {} bytes ({} slices) from network '{}'",
265 total_bytes, slices.size(),
name);