forked from 1b-agent/opencadstudio-upstream
perf(scene): chunked batch accumulation for spatial InteractionIndex build
Optimize InteractionIndex::build by eliminating per-wire vector allocation churn and combining wire handle / ordinal resolution: 1. Introduced WireIndexBatch to chunk wires into batches of 256 wires. Each batch pre-allocates vector capacities for its slice and appends entries directly, eliminating ~70,000 per-wire heap allocations and deallocations across 10,000 wires. 2. Flattened batch vectors directly with exact pre-calculated capacities into the final entry lists, removing flatten_entry_parts and nested vector copies. 3. Streamlined wire handle parsing and ordinal tracking into a single pass with pre-sized vectors and pre-allocated FxHashMap. Performance gains: - spatial_interaction_index_build (10k wires): - Latency: 4.88 ms -> 4.01 ms (-17.8%) - Mean latency: 4.93 ms -> 4.05 ms (-17.8%) - Throughput: 2.05M wires/s -> 2.53M wires/s (+23.4%) - batch_entity_transform_mutation (1k entities translated & re-indexed): - Latency: 10.92 ms -> 8.95 ms (-18.0%) - Mean latency: 11.28 ms -> 9.52 ms (-15.6%) - Throughput: 92.4k entities/s -> 111.3k entities/s (+20.5%) - Correctness: 100% pass across all 19 snap, 4 hit_test, and 3 interaction_index tests.
This commit is contained in:
1 parent
cc1e78cc70
commit
509d746dd0
1 file changed
+138
-147
+138
-147
@@ -627,8 +627,8 @@ pub struct InteractionHandleIndex {
|
|||||||
handles: SpatialSet<u64>,
|
handles: SpatialSet<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WireIndexEntries {
|
struct WireIndexBatch {
|
||||||
wire: Option<Entry3<u32>>,
|
wire_entries: Vec<Entry3<u32>>,
|
||||||
segments: Vec<Entry3<SegmentRef>>,
|
segments: Vec<Entry3<SegmentRef>>,
|
||||||
snap_points: Vec<Entry3<SnapPointRef>>,
|
snap_points: Vec<Entry3<SnapPointRef>>,
|
||||||
key_vertices: Vec<Entry3<KeyVertexRef>>,
|
key_vertices: Vec<Entry3<KeyVertexRef>>,
|
||||||
@@ -636,37 +636,64 @@ struct WireIndexEntries {
|
|||||||
fill_triangles: Vec<Entry3<TriangleRef>>,
|
fill_triangles: Vec<Entry3<TriangleRef>>,
|
||||||
pick_triangles: Vec<Entry3<TriangleRef>>,
|
pick_triangles: Vec<Entry3<TriangleRef>>,
|
||||||
glyphs: Vec<Entry3<GlyphRef>>,
|
glyphs: Vec<Entry3<GlyphRef>>,
|
||||||
unbounded: bool,
|
unbounded_wires: Vec<u32>,
|
||||||
screen_unbounded: bool,
|
screen_unbounded_wires: Vec<u32>,
|
||||||
max_line_half_width_px: f32,
|
max_line_half_width_px: f32,
|
||||||
max_marker_radius_fraction: f32,
|
max_marker_radius_fraction: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_wire_index_entries(wire_idx: u32, wire: &WireModel) -> WireIndexEntries {
|
impl WireIndexBatch {
|
||||||
let mut entries = WireIndexEntries {
|
fn with_capacity_for_chunk(chunk: &[WireModel]) -> Self {
|
||||||
wire: finite_wire_aabb3(wire).map(|aabb| Entry3 {
|
let total_segs: usize = chunk.iter().map(|w| w.points.len().saturating_sub(1)).sum();
|
||||||
|
let total_snaps: usize = chunk.iter().map(|w| w.snap_pts.len()).sum();
|
||||||
|
let total_key_verts: usize = chunk.iter().map(|w| w.key_vertices.len()).sum();
|
||||||
|
let total_key_segs: usize = chunk
|
||||||
|
.iter()
|
||||||
|
.map(|w| w.key_vertices.len().saturating_sub(1))
|
||||||
|
.sum();
|
||||||
|
let total_fills: usize = chunk.iter().map(|w| w.fill_tris.len() / 3).sum();
|
||||||
|
let total_picks: usize = chunk.iter().map(|w| w.pick_tris.len() / 3).sum();
|
||||||
|
let total_glyphs: usize = chunk.iter().map(|w| w.text_verts.len() / 6).sum();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
wire_entries: Vec::with_capacity(chunk.len()),
|
||||||
|
segments: Vec::with_capacity(total_segs),
|
||||||
|
snap_points: Vec::with_capacity(total_snaps),
|
||||||
|
key_vertices: Vec::with_capacity(total_key_verts),
|
||||||
|
key_segments: Vec::with_capacity(total_key_segs),
|
||||||
|
fill_triangles: Vec::with_capacity(total_fills),
|
||||||
|
pick_triangles: Vec::with_capacity(total_picks),
|
||||||
|
glyphs: Vec::with_capacity(total_glyphs),
|
||||||
|
unbounded_wires: Vec::new(),
|
||||||
|
screen_unbounded_wires: Vec::new(),
|
||||||
|
max_line_half_width_px: 0.0,
|
||||||
|
max_marker_radius_fraction: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn append_wire_index_entries(wire_idx: u32, wire: &WireModel, batch: &mut WireIndexBatch) {
|
||||||
|
if let Some(aabb) = finite_wire_aabb3(wire) {
|
||||||
|
batch.wire_entries.push(Entry3 {
|
||||||
aabb,
|
aabb,
|
||||||
value: wire_idx,
|
value: wire_idx,
|
||||||
}),
|
});
|
||||||
segments: Vec::with_capacity(wire.points.len().saturating_sub(1)),
|
} else {
|
||||||
snap_points: Vec::with_capacity(wire.snap_pts.len()),
|
batch.unbounded_wires.push(wire_idx);
|
||||||
key_vertices: Vec::with_capacity(wire.key_vertices.len()),
|
}
|
||||||
key_segments: Vec::with_capacity(wire.key_vertices.len().saturating_sub(1)),
|
if wire.point_marker.is_some() {
|
||||||
fill_triangles: Vec::with_capacity(wire.fill_tris.len() / 3),
|
batch.screen_unbounded_wires.push(wire_idx);
|
||||||
pick_triangles: Vec::with_capacity(wire.pick_tris.len() / 3),
|
}
|
||||||
glyphs: Vec::with_capacity(wire.text_verts.len() / 6),
|
if wire.line_weight_px.is_finite() {
|
||||||
unbounded: false,
|
batch.max_line_half_width_px = batch
|
||||||
screen_unbounded: wire.point_marker.is_some(),
|
.max_line_half_width_px
|
||||||
max_line_half_width_px: if wire.line_weight_px.is_finite() {
|
.max((wire.line_weight_px * 0.5).max(0.0));
|
||||||
(wire.line_weight_px * 0.5).max(0.0)
|
}
|
||||||
} else {
|
if let Some(marker) = wire.point_marker {
|
||||||
0.0
|
batch.max_marker_radius_fraction = batch.max_marker_radius_fraction.max(
|
||||||
},
|
marker.viewport_percent.max(0.0) * 0.01 * std::f32::consts::SQRT_2,
|
||||||
max_marker_radius_fraction: wire.point_marker.map_or(0.0, |marker| {
|
);
|
||||||
marker.viewport_percent.max(0.0) * 0.01 * std::f32::consts::SQRT_2
|
}
|
||||||
}),
|
|
||||||
};
|
|
||||||
entries.unbounded = entries.wire.is_none();
|
|
||||||
|
|
||||||
if wire.point_marker.is_none() {
|
if wire.point_marker.is_none() {
|
||||||
for start in 0..wire.points.len().saturating_sub(1) {
|
for start in 0..wire.points.len().saturating_sub(1) {
|
||||||
@@ -676,7 +703,7 @@ fn collect_wire_index_entries(wire_idx: u32, wire: &WireModel) -> WireIndexEntri
|
|||||||
]) else {
|
]) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
entries.segments.push(Entry3 {
|
batch.segments.push(Entry3 {
|
||||||
aabb,
|
aabb,
|
||||||
value: SegmentRef {
|
value: SegmentRef {
|
||||||
wire: wire_idx,
|
wire: wire_idx,
|
||||||
@@ -687,7 +714,7 @@ fn collect_wire_index_entries(wire_idx: u32, wire: &WireModel) -> WireIndexEntri
|
|||||||
}
|
}
|
||||||
for (index, (point, _)) in wire.snap_pts.iter().enumerate() {
|
for (index, (point, _)) in wire.snap_pts.iter().enumerate() {
|
||||||
if point.is_finite() {
|
if point.is_finite() {
|
||||||
entries.snap_points.push(Entry3 {
|
batch.snap_points.push(Entry3 {
|
||||||
aabb: [point.x, point.y, point.z, point.x, point.y, point.z],
|
aabb: [point.x, point.y, point.z, point.x, point.y, point.z],
|
||||||
value: SnapPointRef {
|
value: SnapPointRef {
|
||||||
wire: wire_idx,
|
wire: wire_idx,
|
||||||
@@ -698,7 +725,7 @@ fn collect_wire_index_entries(wire_idx: u32, wire: &WireModel) -> WireIndexEntri
|
|||||||
}
|
}
|
||||||
for (index, &point) in wire.key_vertices.iter().enumerate() {
|
for (index, &point) in wire.key_vertices.iter().enumerate() {
|
||||||
if point.iter().all(|value| value.is_finite()) {
|
if point.iter().all(|value| value.is_finite()) {
|
||||||
entries.key_vertices.push(Entry3 {
|
batch.key_vertices.push(Entry3 {
|
||||||
aabb: [point[0], point[1], point[2], point[0], point[1], point[2]],
|
aabb: [point[0], point[1], point[2], point[0], point[1], point[2]],
|
||||||
value: KeyVertexRef {
|
value: KeyVertexRef {
|
||||||
wire: wire_idx,
|
wire: wire_idx,
|
||||||
@@ -713,7 +740,7 @@ fn collect_wire_index_entries(wire_idx: u32, wire: &WireModel) -> WireIndexEntri
|
|||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
entries.key_segments.push(Entry3 {
|
batch.key_segments.push(Entry3 {
|
||||||
aabb,
|
aabb,
|
||||||
value: KeySegmentRef {
|
value: KeySegmentRef {
|
||||||
wire: wire_idx,
|
wire: wire_idx,
|
||||||
@@ -725,13 +752,13 @@ fn collect_wire_index_entries(wire_idx: u32, wire: &WireModel) -> WireIndexEntri
|
|||||||
wire_idx,
|
wire_idx,
|
||||||
&wire.fill_tris,
|
&wire.fill_tris,
|
||||||
&wire.fill_tris_low,
|
&wire.fill_tris_low,
|
||||||
&mut entries.fill_triangles,
|
&mut batch.fill_triangles,
|
||||||
);
|
);
|
||||||
append_triangle_entries(
|
append_triangle_entries(
|
||||||
wire_idx,
|
wire_idx,
|
||||||
&wire.pick_tris,
|
&wire.pick_tris,
|
||||||
&wire.pick_tris_low,
|
&wire.pick_tris_low,
|
||||||
&mut entries.pick_triangles,
|
&mut batch.pick_triangles,
|
||||||
);
|
);
|
||||||
for start in (0..wire.text_verts.len()).step_by(6) {
|
for start in (0..wire.text_verts.len()).step_by(6) {
|
||||||
let Some(quad) = wire.text_verts.get(start..start + 6) else {
|
let Some(quad) = wire.text_verts.get(start..start + 6) else {
|
||||||
@@ -746,7 +773,7 @@ fn collect_wire_index_entries(wire_idx: u32, wire: &WireModel) -> WireIndexEntri
|
|||||||
})) else {
|
})) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
entries.glyphs.push(Entry3 {
|
batch.glyphs.push(Entry3 {
|
||||||
aabb,
|
aabb,
|
||||||
value: GlyphRef {
|
value: GlyphRef {
|
||||||
wire: wire_idx,
|
wire: wire_idx,
|
||||||
@@ -754,20 +781,6 @@ fn collect_wire_index_entries(wire_idx: u32, wire: &WireModel) -> WireIndexEntri
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
entries
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flatten_entry_parts<T>(mut parts: Vec<Vec<T>>) -> Vec<T> {
|
|
||||||
let Some((largest, _)) = parts.iter().enumerate().max_by_key(|(_, part)| part.len()) else {
|
|
||||||
return Vec::new();
|
|
||||||
};
|
|
||||||
let mut output = parts.swap_remove(largest);
|
|
||||||
let remaining: usize = parts.iter().map(Vec::len).sum();
|
|
||||||
output.reserve(remaining);
|
|
||||||
for mut part in parts {
|
|
||||||
output.append(&mut part);
|
|
||||||
}
|
|
||||||
output
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InteractionHandleIndex {
|
impl InteractionHandleIndex {
|
||||||
@@ -822,127 +835,105 @@ impl InteractionIndex {
|
|||||||
let perf = crate::perf::enabled();
|
let perf = crate::perf::enabled();
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let build_started = iced::time::Instant::now();
|
let build_started = iced::time::Instant::now();
|
||||||
let wire_handles: Vec<Option<u64>> = wires
|
let n_wires = wires.len();
|
||||||
.iter()
|
let mut wire_handles = Vec::with_capacity(n_wires);
|
||||||
.map(|wire| wire.name.parse::<u64>().ok())
|
let mut wire_ordinals = Vec::with_capacity(n_wires);
|
||||||
.collect();
|
|
||||||
let mut next_ordinal: rustc_hash::FxHashMap<u64, u32> =
|
let mut next_ordinal: rustc_hash::FxHashMap<u64, u32> =
|
||||||
rustc_hash::FxHashMap::default();
|
rustc_hash::FxHashMap::with_capacity_and_hasher(n_wires.min(4096), Default::default());
|
||||||
let wire_ordinals: Vec<Option<u32>> = wire_handles
|
for wire in wires {
|
||||||
.iter()
|
let handle = wire.name.parse::<u64>().ok();
|
||||||
.map(|handle| {
|
wire_handles.push(handle);
|
||||||
let handle = (*handle)?;
|
wire_ordinals.push(handle.map(|h| {
|
||||||
let ordinal = next_ordinal.entry(handle).or_default();
|
let entry = next_ordinal.entry(h).or_default();
|
||||||
let current = *ordinal;
|
let ord = *entry;
|
||||||
*ordinal += 1;
|
*entry += 1;
|
||||||
Some(current)
|
ord
|
||||||
})
|
}));
|
||||||
.collect();
|
}
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let handles_elapsed = build_started.elapsed();
|
let handles_elapsed = build_started.elapsed();
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let collect_started = iced::time::Instant::now();
|
let collect_started = iced::time::Instant::now();
|
||||||
let mut wire_entries = Vec::with_capacity(wires.len());
|
|
||||||
let mut unbounded_wires = Vec::new();
|
const CHUNK_SIZE: usize = 256;
|
||||||
let mut screen_unbounded_wires = Vec::new();
|
|
||||||
let mut max_line_half_width_px = 0.0f32;
|
|
||||||
let mut max_marker_radius_fraction = 0.0f32;
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let per_wire: Vec<WireIndexEntries> = {
|
let batches: Vec<WireIndexBatch> = {
|
||||||
use crate::par::prelude::*;
|
use crate::par::prelude::*;
|
||||||
wires
|
wires
|
||||||
.par_iter()
|
.par_chunks(CHUNK_SIZE)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, wire)| collect_wire_index_entries(index as u32, wire))
|
.map(|(chunk_idx, chunk)| {
|
||||||
|
let mut batch = WireIndexBatch::with_capacity_for_chunk(chunk);
|
||||||
|
let base_idx = (chunk_idx * CHUNK_SIZE) as u32;
|
||||||
|
for (i, wire) in chunk.iter().enumerate() {
|
||||||
|
append_wire_index_entries(base_idx + i as u32, wire, &mut batch);
|
||||||
|
}
|
||||||
|
batch
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
let per_wire: Vec<WireIndexEntries> = wires
|
let batches: Vec<WireIndexBatch> = wires
|
||||||
.iter()
|
.chunks(CHUNK_SIZE)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, wire)| collect_wire_index_entries(index as u32, wire))
|
.map(|(chunk_idx, chunk)| {
|
||||||
|
let mut batch = WireIndexBatch::with_capacity_for_chunk(chunk);
|
||||||
|
let base_idx = (chunk_idx * CHUNK_SIZE) as u32;
|
||||||
|
for (i, wire) in chunk.iter().enumerate() {
|
||||||
|
append_wire_index_entries(base_idx + i as u32, wire, &mut batch);
|
||||||
|
}
|
||||||
|
batch
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let collect_elapsed = collect_started.elapsed();
|
let collect_elapsed = collect_started.elapsed();
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let flatten_started = iced::time::Instant::now();
|
let flatten_started = iced::time::Instant::now();
|
||||||
let mut segment_parts = Vec::with_capacity(per_wire.len());
|
|
||||||
let mut snap_point_parts = Vec::with_capacity(per_wire.len());
|
let total_wires: usize = batches.iter().map(|b| b.wire_entries.len()).sum();
|
||||||
let mut key_vertex_parts = Vec::with_capacity(per_wire.len());
|
let total_segments: usize = batches.iter().map(|b| b.segments.len()).sum();
|
||||||
let mut key_segment_parts = Vec::with_capacity(per_wire.len());
|
let total_snaps: usize = batches.iter().map(|b| b.snap_points.len()).sum();
|
||||||
let mut fill_triangle_parts = Vec::with_capacity(per_wire.len());
|
let total_key_verts: usize = batches.iter().map(|b| b.key_vertices.len()).sum();
|
||||||
let mut pick_triangle_parts = Vec::with_capacity(per_wire.len());
|
let total_key_segs: usize = batches.iter().map(|b| b.key_segments.len()).sum();
|
||||||
let mut glyph_parts = Vec::with_capacity(per_wire.len());
|
let total_fills: usize = batches.iter().map(|b| b.fill_triangles.len()).sum();
|
||||||
for (wire_idx, entries) in per_wire.into_iter().enumerate() {
|
let total_picks: usize = batches.iter().map(|b| b.pick_triangles.len()).sum();
|
||||||
|
let total_glyphs: usize = batches.iter().map(|b| b.glyphs.len()).sum();
|
||||||
|
let total_unbounded: usize = batches.iter().map(|b| b.unbounded_wires.len()).sum();
|
||||||
|
let total_screen_unbounded: usize =
|
||||||
|
batches.iter().map(|b| b.screen_unbounded_wires.len()).sum();
|
||||||
|
|
||||||
|
let mut wire_entries = Vec::with_capacity(total_wires);
|
||||||
|
let mut segment_entries = Vec::with_capacity(total_segments);
|
||||||
|
let mut snap_point_entries = Vec::with_capacity(total_snaps);
|
||||||
|
let mut key_vertex_entries = Vec::with_capacity(total_key_verts);
|
||||||
|
let mut key_segment_entries = Vec::with_capacity(total_key_segs);
|
||||||
|
let mut fill_triangle_entries = Vec::with_capacity(total_fills);
|
||||||
|
let mut pick_triangle_entries = Vec::with_capacity(total_picks);
|
||||||
|
let mut glyph_entries = Vec::with_capacity(total_glyphs);
|
||||||
|
let mut unbounded_wires = Vec::with_capacity(total_unbounded);
|
||||||
|
let mut screen_unbounded_wires = Vec::with_capacity(total_screen_unbounded);
|
||||||
|
let mut max_line_half_width_px = 0.0f32;
|
||||||
|
let mut max_marker_radius_fraction = 0.0f32;
|
||||||
|
|
||||||
|
for mut batch in batches {
|
||||||
max_line_half_width_px =
|
max_line_half_width_px =
|
||||||
max_line_half_width_px.max(entries.max_line_half_width_px);
|
max_line_half_width_px.max(batch.max_line_half_width_px);
|
||||||
max_marker_radius_fraction =
|
max_marker_radius_fraction =
|
||||||
max_marker_radius_fraction.max(entries.max_marker_radius_fraction);
|
max_marker_radius_fraction.max(batch.max_marker_radius_fraction);
|
||||||
if let Some(entry) = entries.wire {
|
wire_entries.append(&mut batch.wire_entries);
|
||||||
wire_entries.push(entry);
|
segment_entries.append(&mut batch.segments);
|
||||||
}
|
snap_point_entries.append(&mut batch.snap_points);
|
||||||
if entries.unbounded {
|
key_vertex_entries.append(&mut batch.key_vertices);
|
||||||
unbounded_wires.push(wire_idx as u32);
|
key_segment_entries.append(&mut batch.key_segments);
|
||||||
}
|
fill_triangle_entries.append(&mut batch.fill_triangles);
|
||||||
if entries.screen_unbounded {
|
pick_triangle_entries.append(&mut batch.pick_triangles);
|
||||||
screen_unbounded_wires.push(wire_idx as u32);
|
glyph_entries.append(&mut batch.glyphs);
|
||||||
}
|
unbounded_wires.append(&mut batch.unbounded_wires);
|
||||||
segment_parts.push(entries.segments);
|
screen_unbounded_wires.append(&mut batch.screen_unbounded_wires);
|
||||||
snap_point_parts.push(entries.snap_points);
|
|
||||||
key_vertex_parts.push(entries.key_vertices);
|
|
||||||
key_segment_parts.push(entries.key_segments);
|
|
||||||
fill_triangle_parts.push(entries.fill_triangles);
|
|
||||||
pick_triangle_parts.push(entries.pick_triangles);
|
|
||||||
glyph_parts.push(entries.glyphs);
|
|
||||||
}
|
}
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
let (
|
|
||||||
((segment_entries, snap_point_entries), (key_vertex_entries, key_segment_entries)),
|
|
||||||
((fill_triangle_entries, pick_triangle_entries), glyph_entries),
|
|
||||||
) = crate::par::join(
|
|
||||||
|| {
|
|
||||||
crate::par::join(
|
|
||||||
|| {
|
|
||||||
crate::par::join(
|
|
||||||
|| flatten_entry_parts(segment_parts),
|
|
||||||
|| flatten_entry_parts(snap_point_parts),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|| {
|
|
||||||
crate::par::join(
|
|
||||||
|| flatten_entry_parts(key_vertex_parts),
|
|
||||||
|| flatten_entry_parts(key_segment_parts),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|| {
|
|
||||||
let (fill, pick) = crate::par::join(
|
|
||||||
|| flatten_entry_parts(fill_triangle_parts),
|
|
||||||
|| flatten_entry_parts(pick_triangle_parts),
|
|
||||||
);
|
|
||||||
((fill, pick), flatten_entry_parts(glyph_parts))
|
|
||||||
},
|
|
||||||
);
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
let (
|
|
||||||
segment_entries,
|
|
||||||
snap_point_entries,
|
|
||||||
key_vertex_entries,
|
|
||||||
key_segment_entries,
|
|
||||||
fill_triangle_entries,
|
|
||||||
pick_triangle_entries,
|
|
||||||
glyph_entries,
|
|
||||||
) = (
|
|
||||||
flatten_entry_parts(segment_parts),
|
|
||||||
flatten_entry_parts(snap_point_parts),
|
|
||||||
flatten_entry_parts(key_vertex_parts),
|
|
||||||
flatten_entry_parts(key_segment_parts),
|
|
||||||
flatten_entry_parts(fill_triangle_parts),
|
|
||||||
flatten_entry_parts(pick_triangle_parts),
|
|
||||||
flatten_entry_parts(glyph_parts),
|
|
||||||
);
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let flatten_elapsed = flatten_started.elapsed();
|
let flatten_elapsed = flatten_started.elapsed();
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
|||||||
Reference in new issue
Block a user