Introduce draw_mesh_cache in mesh::Renderer
This commit is contained in:
parent
42bc4af972
commit
afb3b8fce6
8 changed files with 119 additions and 69 deletions
|
|
@ -100,7 +100,7 @@ mod rainbow {
|
||||||
|
|
||||||
let mesh = Mesh::Solid {
|
let mesh = Mesh::Solid {
|
||||||
buffers: mesh::Indexed {
|
buffers: mesh::Indexed {
|
||||||
vertices: [
|
vertices: vec![
|
||||||
SolidVertex2D {
|
SolidVertex2D {
|
||||||
position: posn_center,
|
position: posn_center,
|
||||||
color: color::pack([1.0, 1.0, 1.0, 1.0]),
|
color: color::pack([1.0, 1.0, 1.0, 1.0]),
|
||||||
|
|
@ -137,9 +137,8 @@ mod rainbow {
|
||||||
position: posn_l,
|
position: posn_l,
|
||||||
color: color::pack(color_v),
|
color: color::pack(color_v),
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
.into(),
|
indices: vec![
|
||||||
indices: [
|
|
||||||
0, 1, 2, // TL
|
0, 1, 2, // TL
|
||||||
0, 2, 3, // T
|
0, 2, 3, // T
|
||||||
0, 3, 4, // TR
|
0, 3, 4, // TR
|
||||||
|
|
@ -148,8 +147,7 @@ mod rainbow {
|
||||||
0, 6, 7, // B
|
0, 6, 7, // B
|
||||||
0, 7, 8, // BL
|
0, 7, 8, // BL
|
||||||
0, 8, 1, // L
|
0, 8, 1, // L
|
||||||
]
|
],
|
||||||
.into(),
|
|
||||||
},
|
},
|
||||||
transformation: Transformation::IDENTITY,
|
transformation: Transformation::IDENTITY,
|
||||||
clip_bounds: Rectangle::INFINITE,
|
clip_bounds: Rectangle::INFINITE,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ use crate::gradient;
|
||||||
|
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::atomic::{self, AtomicU64};
|
||||||
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
/// A low-level primitive to render a mesh of triangles.
|
/// A low-level primitive to render a mesh of triangles.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
|
@ -72,12 +73,12 @@ impl Mesh {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Indexed<T> {
|
pub struct Indexed<T> {
|
||||||
/// The vertices of the mesh
|
/// The vertices of the mesh
|
||||||
pub vertices: Arc<[T]>,
|
pub vertices: Vec<T>,
|
||||||
|
|
||||||
/// The list of vertex indices that defines the triangles of the mesh.
|
/// The list of vertex indices that defines the triangles of the mesh.
|
||||||
///
|
///
|
||||||
/// Therefore, this list should always have a length that is a multiple of 3.
|
/// Therefore, this list should always have a length that is a multiple of 3.
|
||||||
pub indices: Arc<[u32]>,
|
pub indices: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A two-dimensional vertex with a color.
|
/// A two-dimensional vertex with a color.
|
||||||
|
|
@ -143,8 +144,67 @@ pub fn attribute_count_of(meshes: &[Mesh]) -> AttributeCount {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A cache of multiple meshes.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Cache {
|
||||||
|
id: Id,
|
||||||
|
batch: Arc<[Mesh]>,
|
||||||
|
version: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The unique id of a [`Cache`].
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct Id(u64);
|
||||||
|
|
||||||
|
impl Cache {
|
||||||
|
/// Creates a new [`Cache`] for the given meshes.
|
||||||
|
pub fn new(meshes: Arc<[Mesh]>) -> Self {
|
||||||
|
static NEXT_ID: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
id: Id(NEXT_ID.fetch_add(1, atomic::Ordering::Relaxed)),
|
||||||
|
batch: meshes,
|
||||||
|
version: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the [`Id`] of the [`Cache`].
|
||||||
|
pub fn id(&self) -> Id {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the current version of the [`Cache`].
|
||||||
|
pub fn version(&self) -> usize {
|
||||||
|
self.version
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the batch of meshes in the [`Cache`].
|
||||||
|
pub fn batch(&self) -> &[Mesh] {
|
||||||
|
&self.batch
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a [`Weak`] reference to the contents of the [`Cache`].
|
||||||
|
pub fn downgrade(&self) -> Weak<[Mesh]> {
|
||||||
|
Arc::downgrade(&self.batch)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the [`Cache`] is empty.
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.batch.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the [`Cache`] with the given meshes.
|
||||||
|
pub fn update(&mut self, meshes: Arc<[Mesh]>) {
|
||||||
|
self.batch = meshes;
|
||||||
|
self.version += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A renderer capable of drawing a [`Mesh`].
|
/// A renderer capable of drawing a [`Mesh`].
|
||||||
pub trait Renderer {
|
pub trait Renderer {
|
||||||
/// Draws the given [`Mesh`].
|
/// Draws the given [`Mesh`].
|
||||||
fn draw_mesh(&mut self, mesh: Mesh);
|
fn draw_mesh(&mut self, mesh: Mesh);
|
||||||
|
|
||||||
|
/// Draws the given [`Cache`].
|
||||||
|
fn draw_mesh_cache(&mut self, cache: Cache);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,10 @@ where
|
||||||
fn draw_mesh(&mut self, mesh: graphics::Mesh) {
|
fn draw_mesh(&mut self, mesh: graphics::Mesh) {
|
||||||
delegate!(self, renderer, renderer.draw_mesh(mesh));
|
delegate!(self, renderer, renderer.draw_mesh(mesh));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_mesh_cache(&mut self, cache: mesh::Cache) {
|
||||||
|
delegate!(self, renderer, renderer.draw_mesh_cache(cache));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A compositor `A` with a fallback strategy `B`.
|
/// A compositor `A` with a fallback strategy `B`.
|
||||||
|
|
|
||||||
|
|
@ -373,6 +373,10 @@ impl graphics::mesh::Renderer for Renderer {
|
||||||
fn draw_mesh(&mut self, _mesh: graphics::Mesh) {
|
fn draw_mesh(&mut self, _mesh: graphics::Mesh) {
|
||||||
log::warn!("iced_tiny_skia does not support drawing meshes");
|
log::warn!("iced_tiny_skia does not support drawing meshes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_mesh_cache(&mut self, _cache: iced_graphics::mesh::Cache) {
|
||||||
|
log::warn!("iced_tiny_skia does not support drawing meshes");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "image")]
|
#[cfg(feature = "image")]
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ use crate::graphics::gradient::{self, Gradient};
|
||||||
use crate::graphics::mesh::{self, Mesh};
|
use crate::graphics::mesh::{self, Mesh};
|
||||||
use crate::graphics::{Image, Text};
|
use crate::graphics::{Image, Text};
|
||||||
use crate::text;
|
use crate::text;
|
||||||
use crate::triangle;
|
|
||||||
|
|
||||||
use lyon::geom::euclid;
|
use lyon::geom::euclid;
|
||||||
use lyon::tessellation;
|
use lyon::tessellation;
|
||||||
|
|
@ -33,7 +32,7 @@ pub enum Geometry {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct Cache {
|
pub struct Cache {
|
||||||
pub meshes: Option<triangle::Cache>,
|
pub meshes: Option<mesh::Cache>,
|
||||||
pub images: Option<Arc<[Image]>>,
|
pub images: Option<Arc<[Image]>>,
|
||||||
pub text: Option<text::Cache>,
|
pub text: Option<text::Cache>,
|
||||||
}
|
}
|
||||||
|
|
@ -62,11 +61,17 @@ impl Cached for Geometry {
|
||||||
Some(Arc::from(images))
|
Some(Arc::from(images))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let meshes = Arc::from(meshes);
|
||||||
|
|
||||||
if let Some(mut previous) = previous {
|
if let Some(mut previous) = previous {
|
||||||
if let Some(cache) = &mut previous.meshes {
|
if let Some(cache) = &mut previous.meshes {
|
||||||
cache.update(meshes);
|
cache.update(meshes);
|
||||||
} else {
|
} else {
|
||||||
previous.meshes = triangle::Cache::new(meshes);
|
previous.meshes = if meshes.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(mesh::Cache::new(meshes))
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(cache) = &mut previous.text {
|
if let Some(cache) = &mut previous.text {
|
||||||
|
|
@ -80,7 +85,11 @@ impl Cached for Geometry {
|
||||||
previous
|
previous
|
||||||
} else {
|
} else {
|
||||||
Cache {
|
Cache {
|
||||||
meshes: triangle::Cache::new(meshes),
|
meshes: if meshes.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(mesh::Cache::new(meshes))
|
||||||
|
},
|
||||||
images,
|
images,
|
||||||
text: text::Cache::new(group, text),
|
text: text::Cache::new(group, text),
|
||||||
}
|
}
|
||||||
|
|
@ -547,8 +556,8 @@ impl BufferStack {
|
||||||
Buffer::Solid(buffer) if !buffer.indices.is_empty() => {
|
Buffer::Solid(buffer) if !buffer.indices.is_empty() => {
|
||||||
Some(Mesh::Solid {
|
Some(Mesh::Solid {
|
||||||
buffers: mesh::Indexed {
|
buffers: mesh::Indexed {
|
||||||
vertices: buffer.vertices.into(),
|
vertices: buffer.vertices,
|
||||||
indices: buffer.indices.into(),
|
indices: buffer.indices,
|
||||||
},
|
},
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
transformation: Transformation::IDENTITY,
|
transformation: Transformation::IDENTITY,
|
||||||
|
|
@ -557,8 +566,8 @@ impl BufferStack {
|
||||||
Buffer::Gradient(buffer) if !buffer.indices.is_empty() => {
|
Buffer::Gradient(buffer) if !buffer.indices.is_empty() => {
|
||||||
Some(Mesh::Gradient {
|
Some(Mesh::Gradient {
|
||||||
buffers: mesh::Indexed {
|
buffers: mesh::Indexed {
|
||||||
vertices: buffer.vertices.into(),
|
vertices: buffer.vertices,
|
||||||
indices: buffer.indices.into(),
|
indices: buffer.indices,
|
||||||
},
|
},
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
transformation: Transformation::IDENTITY,
|
transformation: Transformation::IDENTITY,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use crate::graphics;
|
||||||
use crate::graphics::Mesh;
|
use crate::graphics::Mesh;
|
||||||
use crate::graphics::color;
|
use crate::graphics::color;
|
||||||
use crate::graphics::layer;
|
use crate::graphics::layer;
|
||||||
|
use crate::graphics::mesh;
|
||||||
use crate::graphics::text::{Editor, Paragraph};
|
use crate::graphics::text::{Editor, Paragraph};
|
||||||
use crate::image::{self, Image};
|
use crate::image::{self, Image};
|
||||||
use crate::primitive::{self, Primitive};
|
use crate::primitive::{self, Primitive};
|
||||||
|
|
@ -230,7 +231,7 @@ impl Layer {
|
||||||
|
|
||||||
pub fn draw_mesh_cache(
|
pub fn draw_mesh_cache(
|
||||||
&mut self,
|
&mut self,
|
||||||
cache: triangle::Cache,
|
cache: mesh::Cache,
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
self.flush_meshes();
|
self.flush_meshes();
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ use crate::core::renderer;
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
|
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
|
||||||
};
|
};
|
||||||
|
use crate::graphics::mesh;
|
||||||
use crate::graphics::text::{Editor, Paragraph};
|
use crate::graphics::text::{Editor, Paragraph};
|
||||||
use crate::graphics::{Shell, Viewport};
|
use crate::graphics::{Shell, Viewport};
|
||||||
|
|
||||||
|
|
@ -845,6 +846,11 @@ impl graphics::mesh::Renderer for Renderer {
|
||||||
let (layer, transformation) = self.layers.current_mut();
|
let (layer, transformation) = self.layers.current_mut();
|
||||||
layer.draw_mesh(mesh, transformation);
|
layer.draw_mesh(mesh, transformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_mesh_cache(&mut self, cache: mesh::Cache) {
|
||||||
|
let (layer, transformation) = self.layers.current_mut();
|
||||||
|
layer.draw_mesh_cache(cache, transformation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "geometry")]
|
#[cfg(feature = "geometry")]
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@ use crate::graphics::mesh::{self, Mesh};
|
||||||
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::collections::hash_map;
|
use std::collections::hash_map;
|
||||||
use std::sync::atomic::{self, AtomicU64};
|
use std::sync::Weak;
|
||||||
use std::sync::{self, Arc};
|
|
||||||
|
|
||||||
const INITIAL_INDEX_COUNT: usize = 1_000;
|
const INITIAL_INDEX_COUNT: usize = 1_000;
|
||||||
const INITIAL_VERTEX_COUNT: usize = 1_000;
|
const INITIAL_VERTEX_COUNT: usize = 1_000;
|
||||||
|
|
@ -24,52 +23,21 @@ pub enum Item {
|
||||||
},
|
},
|
||||||
Cached {
|
Cached {
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
cache: Cache,
|
cache: mesh::Cache,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Cache {
|
|
||||||
id: Id,
|
|
||||||
batch: Arc<[Mesh]>,
|
|
||||||
version: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub struct Id(u64);
|
|
||||||
|
|
||||||
impl Cache {
|
|
||||||
pub fn new(meshes: Vec<Mesh>) -> Option<Self> {
|
|
||||||
static NEXT_ID: AtomicU64 = AtomicU64::new(0);
|
|
||||||
|
|
||||||
if meshes.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(Self {
|
|
||||||
id: Id(NEXT_ID.fetch_add(1, atomic::Ordering::Relaxed)),
|
|
||||||
batch: Arc::from(meshes),
|
|
||||||
version: 0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self, meshes: Vec<Mesh>) {
|
|
||||||
self.batch = Arc::from(meshes);
|
|
||||||
self.version += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Upload {
|
struct Upload {
|
||||||
layer: Layer,
|
layer: Layer,
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
version: usize,
|
version: usize,
|
||||||
batch: sync::Weak<[Mesh]>,
|
batch: Weak<[Mesh]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Storage {
|
pub struct Storage {
|
||||||
uploads: FxHashMap<Id, Upload>,
|
uploads: FxHashMap<mesh::Id, Upload>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Storage {
|
impl Storage {
|
||||||
|
|
@ -77,12 +45,12 @@ impl Storage {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self, cache: &Cache) -> Option<&Upload> {
|
fn get(&self, cache: &mesh::Cache) -> Option<&Upload> {
|
||||||
if cache.batch.is_empty() {
|
if cache.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.uploads.get(&cache.id)
|
self.uploads.get(&cache.id())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(
|
fn prepare(
|
||||||
|
|
@ -92,15 +60,15 @@ impl Storage {
|
||||||
belt: &mut wgpu::util::StagingBelt,
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
solid: &solid::Pipeline,
|
solid: &solid::Pipeline,
|
||||||
gradient: &gradient::Pipeline,
|
gradient: &gradient::Pipeline,
|
||||||
cache: &Cache,
|
cache: &mesh::Cache,
|
||||||
new_transformation: Transformation,
|
new_transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
match self.uploads.entry(cache.id) {
|
match self.uploads.entry(cache.id()) {
|
||||||
hash_map::Entry::Occupied(entry) => {
|
hash_map::Entry::Occupied(entry) => {
|
||||||
let upload = entry.into_mut();
|
let upload = entry.into_mut();
|
||||||
|
|
||||||
if !cache.batch.is_empty()
|
if !cache.is_empty()
|
||||||
&& (upload.version != cache.version
|
&& (upload.version != cache.version()
|
||||||
|| upload.transformation != new_transformation)
|
|| upload.transformation != new_transformation)
|
||||||
{
|
{
|
||||||
upload.layer.prepare(
|
upload.layer.prepare(
|
||||||
|
|
@ -109,12 +77,12 @@ impl Storage {
|
||||||
belt,
|
belt,
|
||||||
solid,
|
solid,
|
||||||
gradient,
|
gradient,
|
||||||
&cache.batch,
|
cache.batch(),
|
||||||
new_transformation,
|
new_transformation,
|
||||||
);
|
);
|
||||||
|
|
||||||
upload.batch = Arc::downgrade(&cache.batch);
|
upload.batch = cache.downgrade();
|
||||||
upload.version = cache.version;
|
upload.version = cache.version();
|
||||||
upload.transformation = new_transformation;
|
upload.transformation = new_transformation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -127,7 +95,7 @@ impl Storage {
|
||||||
belt,
|
belt,
|
||||||
solid,
|
solid,
|
||||||
gradient,
|
gradient,
|
||||||
&cache.batch,
|
cache.batch(),
|
||||||
new_transformation,
|
new_transformation,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -135,12 +103,12 @@ impl Storage {
|
||||||
layer,
|
layer,
|
||||||
transformation: new_transformation,
|
transformation: new_transformation,
|
||||||
version: 0,
|
version: 0,
|
||||||
batch: Arc::downgrade(&cache.batch),
|
batch: cache.downgrade(),
|
||||||
});
|
});
|
||||||
|
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"New mesh upload: {} (total: {})",
|
"New mesh upload: {:?} (total: {})",
|
||||||
cache.id.0,
|
cache.id(),
|
||||||
self.uploads.len()
|
self.uploads.len()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -278,7 +246,7 @@ impl State {
|
||||||
|
|
||||||
Some((
|
Some((
|
||||||
&upload.layer,
|
&upload.layer,
|
||||||
&cache.batch,
|
cache.batch(),
|
||||||
screen_transformation * *transformation,
|
screen_transformation * *transformation,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue