fix(render): split oversized edge buffers

This commit is contained in:
Hakan Seven 2026-07-26 23:38:42 +03:00
commit b5f9a06e78

View file

@ -853,7 +853,37 @@ pub fn build_mesh_batch(device: &wgpu::Device, sets: &[MeshLodSet]) -> (Vec<Mesh
// the triangle edges so the mesh still shows a wireframe.
let has_feat = !set.edge_verts.is_empty();
if has_feat && part.include_edges {
for i in 0..set.edge_verts.len() {
// Feature edges use their own vertex buffer, so they need their
// own cap. Large ACIS models can have relatively few faces but
// millions of B-rep edge vertices; only checking `mesh.verts`
// allowed `edge_vbuf` to exceed wgpu's max_buffer_size.
let mut edge_start = 0;
let edge_end = set.edge_verts.len() & !1usize;
while edge_start < edge_end {
let available = max_verts.saturating_sub(edge_verts.len());
// LineList consumes pairs. Never split a segment between
// chunks even when the vertex budget is odd.
let take = available
.min(edge_end - edge_start)
& !1usize;
if take == 0 {
chunks.push(make_chunk(
device,
&verts,
&indices,
&transp_indices,
&wire_indices,
&edge_verts,
active_material,
));
verts.clear();
indices.clear();
transp_indices.clear();
wire_indices.clear();
edge_verts.clear();
continue;
}
for i in edge_start..edge_start + take {
edge_verts.push(MeshVertex {
position: set.edge_verts[i],
normal: [0.0, 1.0, 0.0],
@ -873,6 +903,24 @@ pub fn build_mesh_batch(device: &wgpu::Device, sets: &[MeshLodSet]) -> (Vec<Mesh
uv_normal: [0.0; 2],
});
}
edge_start += take;
if edge_start < edge_end {
chunks.push(make_chunk(
device,
&verts,
&indices,
&transp_indices,
&wire_indices,
&edge_verts,
active_material,
));
verts.clear();
indices.clear();
transp_indices.clear();
wire_indices.clear();
edge_verts.clear();
}
}
}
// A single mesh larger than a whole chunk: emit as triangle-soup