Skip to content

Commit b9eeb34

Browse files
authored
Merge pull request #3070 from edwloef/cheap_mesh_clone
Introduce `draw_mesh_cache` in `mesh::Renderer`
2 parents be79690 + afb3b8f commit b9eeb34

File tree

7 files changed

+110
-56
lines changed

7 files changed

+110
-56
lines changed

graphics/src/mesh.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ use crate::gradient;
55

66
use bytemuck::{Pod, Zeroable};
77

8+
use std::sync::atomic::{self, AtomicU64};
9+
use std::sync::{Arc, Weak};
10+
811
/// A low-level primitive to render a mesh of triangles.
912
#[derive(Debug, Clone, PartialEq)]
1013
pub enum Mesh {
@@ -141,8 +144,67 @@ pub fn attribute_count_of(meshes: &[Mesh]) -> AttributeCount {
141144
})
142145
}
143146

147+
/// A cache of multiple meshes.
148+
#[derive(Debug, Clone)]
149+
pub struct Cache {
150+
id: Id,
151+
batch: Arc<[Mesh]>,
152+
version: usize,
153+
}
154+
155+
/// The unique id of a [`Cache`].
156+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
157+
pub struct Id(u64);
158+
159+
impl Cache {
160+
/// Creates a new [`Cache`] for the given meshes.
161+
pub fn new(meshes: Arc<[Mesh]>) -> Self {
162+
static NEXT_ID: AtomicU64 = AtomicU64::new(0);
163+
164+
Self {
165+
id: Id(NEXT_ID.fetch_add(1, atomic::Ordering::Relaxed)),
166+
batch: meshes,
167+
version: 0,
168+
}
169+
}
170+
171+
/// Returns the [`Id`] of the [`Cache`].
172+
pub fn id(&self) -> Id {
173+
self.id
174+
}
175+
176+
/// Returns the current version of the [`Cache`].
177+
pub fn version(&self) -> usize {
178+
self.version
179+
}
180+
181+
/// Returns the batch of meshes in the [`Cache`].
182+
pub fn batch(&self) -> &[Mesh] {
183+
&self.batch
184+
}
185+
186+
/// Returns a [`Weak`] reference to the contents of the [`Cache`].
187+
pub fn downgrade(&self) -> Weak<[Mesh]> {
188+
Arc::downgrade(&self.batch)
189+
}
190+
191+
/// Returns true if the [`Cache`] is empty.
192+
pub fn is_empty(&self) -> bool {
193+
self.batch.is_empty()
194+
}
195+
196+
/// Updates the [`Cache`] with the given meshes.
197+
pub fn update(&mut self, meshes: Arc<[Mesh]>) {
198+
self.batch = meshes;
199+
self.version += 1;
200+
}
201+
}
202+
144203
/// A renderer capable of drawing a [`Mesh`].
145204
pub trait Renderer {
146205
/// Draws the given [`Mesh`].
147206
fn draw_mesh(&mut self, mesh: Mesh);
207+
208+
/// Draws the given [`Cache`].
209+
fn draw_mesh_cache(&mut self, cache: Cache);
148210
}

renderer/src/fallback.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ where
224224
fn draw_mesh(&mut self, mesh: graphics::Mesh) {
225225
delegate!(self, renderer, renderer.draw_mesh(mesh));
226226
}
227+
228+
fn draw_mesh_cache(&mut self, cache: mesh::Cache) {
229+
delegate!(self, renderer, renderer.draw_mesh_cache(cache));
230+
}
227231
}
228232

229233
/// A compositor `A` with a fallback strategy `B`.

tiny_skia/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ impl graphics::mesh::Renderer for Renderer {
373373
fn draw_mesh(&mut self, _mesh: graphics::Mesh) {
374374
log::warn!("iced_tiny_skia does not support drawing meshes");
375375
}
376+
377+
fn draw_mesh_cache(&mut self, _cache: iced_graphics::mesh::Cache) {
378+
log::warn!("iced_tiny_skia does not support drawing meshes");
379+
}
376380
}
377381

378382
#[cfg(feature = "image")]

wgpu/src/geometry.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use crate::graphics::gradient::{self, Gradient};
1313
use crate::graphics::mesh::{self, Mesh};
1414
use crate::graphics::{Image, Text};
1515
use crate::text;
16-
use crate::triangle;
1716

1817
use lyon::geom::euclid;
1918
use lyon::tessellation;
@@ -33,7 +32,7 @@ pub enum Geometry {
3332

3433
#[derive(Debug, Clone, Default)]
3534
pub struct Cache {
36-
pub meshes: Option<triangle::Cache>,
35+
pub meshes: Option<mesh::Cache>,
3736
pub images: Option<Arc<[Image]>>,
3837
pub text: Option<text::Cache>,
3938
}
@@ -62,11 +61,17 @@ impl Cached for Geometry {
6261
Some(Arc::from(images))
6362
};
6463

64+
let meshes = Arc::from(meshes);
65+
6566
if let Some(mut previous) = previous {
6667
if let Some(cache) = &mut previous.meshes {
6768
cache.update(meshes);
6869
} else {
69-
previous.meshes = triangle::Cache::new(meshes);
70+
previous.meshes = if meshes.is_empty() {
71+
None
72+
} else {
73+
Some(mesh::Cache::new(meshes))
74+
};
7075
}
7176

7277
if let Some(cache) = &mut previous.text {
@@ -80,7 +85,11 @@ impl Cached for Geometry {
8085
previous
8186
} else {
8287
Cache {
83-
meshes: triangle::Cache::new(meshes),
88+
meshes: if meshes.is_empty() {
89+
None
90+
} else {
91+
Some(mesh::Cache::new(meshes))
92+
},
8493
images,
8594
text: text::Cache::new(group, text),
8695
}

wgpu/src/layer.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::graphics;
55
use crate::graphics::Mesh;
66
use crate::graphics::color;
77
use crate::graphics::layer;
8+
use crate::graphics::mesh;
89
use crate::graphics::text::{Editor, Paragraph};
910
use crate::image::{self, Image};
1011
use crate::primitive::{self, Primitive};
@@ -230,7 +231,7 @@ impl Layer {
230231

231232
pub fn draw_mesh_cache(
232233
&mut self,
233-
cache: triangle::Cache,
234+
cache: mesh::Cache,
234235
transformation: Transformation,
235236
) {
236237
self.flush_meshes();

wgpu/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ use crate::core::renderer;
6565
use crate::core::{
6666
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
6767
};
68+
use crate::graphics::mesh;
6869
use crate::graphics::text::{Editor, Paragraph};
6970
use crate::graphics::{Shell, Viewport};
7071

@@ -845,6 +846,11 @@ impl graphics::mesh::Renderer for Renderer {
845846
let (layer, transformation) = self.layers.current_mut();
846847
layer.draw_mesh(mesh, transformation);
847848
}
849+
850+
fn draw_mesh_cache(&mut self, cache: mesh::Cache) {
851+
let (layer, transformation) = self.layers.current_mut();
852+
layer.draw_mesh_cache(cache, transformation);
853+
}
848854
}
849855

850856
#[cfg(feature = "geometry")]

wgpu/src/triangle.rs

Lines changed: 19 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use crate::graphics::mesh::{self, Mesh};
88

99
use rustc_hash::FxHashMap;
1010
use std::collections::hash_map;
11-
use std::sync::atomic::{self, AtomicU64};
12-
use std::sync::{self, Arc};
11+
use std::sync::Weak;
1312

1413
const INITIAL_INDEX_COUNT: usize = 1_000;
1514
const INITIAL_VERTEX_COUNT: usize = 1_000;
@@ -24,65 +23,34 @@ pub enum Item {
2423
},
2524
Cached {
2625
transformation: Transformation,
27-
cache: Cache,
26+
cache: mesh::Cache,
2827
},
2928
}
3029

31-
#[derive(Debug, Clone)]
32-
pub struct Cache {
33-
id: Id,
34-
batch: Arc<[Mesh]>,
35-
version: usize,
36-
}
37-
38-
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
39-
pub struct Id(u64);
40-
41-
impl Cache {
42-
pub fn new(meshes: Vec<Mesh>) -> Option<Self> {
43-
static NEXT_ID: AtomicU64 = AtomicU64::new(0);
44-
45-
if meshes.is_empty() {
46-
return None;
47-
}
48-
49-
Some(Self {
50-
id: Id(NEXT_ID.fetch_add(1, atomic::Ordering::Relaxed)),
51-
batch: Arc::from(meshes),
52-
version: 0,
53-
})
54-
}
55-
56-
pub fn update(&mut self, meshes: Vec<Mesh>) {
57-
self.batch = Arc::from(meshes);
58-
self.version += 1;
59-
}
60-
}
61-
6230
#[derive(Debug)]
6331
struct Upload {
6432
layer: Layer,
6533
transformation: Transformation,
6634
version: usize,
67-
batch: sync::Weak<[Mesh]>,
35+
batch: Weak<[Mesh]>,
6836
}
6937

7038
#[derive(Debug, Default)]
7139
pub struct Storage {
72-
uploads: FxHashMap<Id, Upload>,
40+
uploads: FxHashMap<mesh::Id, Upload>,
7341
}
7442

7543
impl Storage {
7644
pub fn new() -> Self {
7745
Self::default()
7846
}
7947

80-
fn get(&self, cache: &Cache) -> Option<&Upload> {
81-
if cache.batch.is_empty() {
48+
fn get(&self, cache: &mesh::Cache) -> Option<&Upload> {
49+
if cache.is_empty() {
8250
return None;
8351
}
8452

85-
self.uploads.get(&cache.id)
53+
self.uploads.get(&cache.id())
8654
}
8755

8856
fn prepare(
@@ -92,15 +60,15 @@ impl Storage {
9260
belt: &mut wgpu::util::StagingBelt,
9361
solid: &solid::Pipeline,
9462
gradient: &gradient::Pipeline,
95-
cache: &Cache,
63+
cache: &mesh::Cache,
9664
new_transformation: Transformation,
9765
) {
98-
match self.uploads.entry(cache.id) {
66+
match self.uploads.entry(cache.id()) {
9967
hash_map::Entry::Occupied(entry) => {
10068
let upload = entry.into_mut();
10169

102-
if !cache.batch.is_empty()
103-
&& (upload.version != cache.version
70+
if !cache.is_empty()
71+
&& (upload.version != cache.version()
10472
|| upload.transformation != new_transformation)
10573
{
10674
upload.layer.prepare(
@@ -109,12 +77,12 @@ impl Storage {
10977
belt,
11078
solid,
11179
gradient,
112-
&cache.batch,
80+
cache.batch(),
11381
new_transformation,
11482
);
11583

116-
upload.batch = Arc::downgrade(&cache.batch);
117-
upload.version = cache.version;
84+
upload.batch = cache.downgrade();
85+
upload.version = cache.version();
11886
upload.transformation = new_transformation;
11987
}
12088
}
@@ -127,20 +95,20 @@ impl Storage {
12795
belt,
12896
solid,
12997
gradient,
130-
&cache.batch,
98+
cache.batch(),
13199
new_transformation,
132100
);
133101

134102
let _ = entry.insert(Upload {
135103
layer,
136104
transformation: new_transformation,
137105
version: 0,
138-
batch: Arc::downgrade(&cache.batch),
106+
batch: cache.downgrade(),
139107
});
140108

141109
log::debug!(
142-
"New mesh upload: {} (total: {})",
143-
cache.id.0,
110+
"New mesh upload: {:?} (total: {})",
111+
cache.id(),
144112
self.uploads.len()
145113
);
146114
}
@@ -278,7 +246,7 @@ impl State {
278246

279247
Some((
280248
&upload.layer,
281-
&cache.batch,
249+
cache.batch(),
282250
screen_transformation * *transformation,
283251
))
284252
}

0 commit comments

Comments
 (0)