Fix layer transformations
This commit is contained in:
parent
cc05cb9be4
commit
394e599c3a
6 changed files with 203 additions and 161 deletions
|
|
@ -106,23 +106,28 @@ impl Frame {
|
||||||
.buffers
|
.buffers
|
||||||
.stack
|
.stack
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|buffer| match buffer {
|
.filter_map(|buffer| match buffer {
|
||||||
Buffer::Solid(buffer) => Mesh::Solid {
|
Buffer::Solid(buffer) if !buffer.indices.is_empty() => {
|
||||||
buffers: mesh::Indexed {
|
Some(Mesh::Solid {
|
||||||
vertices: buffer.vertices,
|
buffers: mesh::Indexed {
|
||||||
indices: buffer.indices,
|
vertices: buffer.vertices,
|
||||||
},
|
indices: buffer.indices,
|
||||||
transformation: Transformation::IDENTITY,
|
},
|
||||||
size: self.size,
|
transformation: Transformation::IDENTITY,
|
||||||
},
|
size: self.size,
|
||||||
Buffer::Gradient(buffer) => Mesh::Gradient {
|
})
|
||||||
buffers: mesh::Indexed {
|
}
|
||||||
vertices: buffer.vertices,
|
Buffer::Gradient(buffer) if !buffer.indices.is_empty() => {
|
||||||
indices: buffer.indices,
|
Some(Mesh::Gradient {
|
||||||
},
|
buffers: mesh::Indexed {
|
||||||
transformation: Transformation::IDENTITY,
|
vertices: buffer.vertices,
|
||||||
size: self.size,
|
indices: buffer.indices,
|
||||||
},
|
},
|
||||||
|
transformation: Transformation::IDENTITY,
|
||||||
|
size: self.size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,17 +13,17 @@ use std::rc::Rc;
|
||||||
|
|
||||||
pub enum Layer<'a> {
|
pub enum Layer<'a> {
|
||||||
Live(&'a Live),
|
Live(&'a Live),
|
||||||
Cached(cell::Ref<'a, Cached>),
|
Cached(Transformation, cell::Ref<'a, Cached>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum LayerMut<'a> {
|
pub enum LayerMut<'a> {
|
||||||
Live(&'a mut Live),
|
Live(&'a mut Live),
|
||||||
Cached(cell::RefMut<'a, Cached>),
|
Cached(Transformation, cell::RefMut<'a, Cached>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Stack {
|
pub struct Stack {
|
||||||
live: Vec<Live>,
|
live: Vec<Live>,
|
||||||
cached: Vec<Rc<RefCell<Cached>>>,
|
cached: Vec<(Transformation, Rc<RefCell<Cached>>)>,
|
||||||
order: Vec<Kind>,
|
order: Vec<Kind>,
|
||||||
transformations: Vec<Transformation>,
|
transformations: Vec<Transformation>,
|
||||||
previous: Vec<usize>,
|
previous: Vec<usize>,
|
||||||
|
|
@ -92,7 +92,7 @@ impl Stack {
|
||||||
position,
|
position,
|
||||||
color,
|
color,
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
transformation: self.transformations.last().copied().unwrap(),
|
transformation: self.transformation(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.live[self.current].text.push(paragraph);
|
self.live[self.current].text.push(paragraph);
|
||||||
|
|
@ -178,36 +178,31 @@ impl Stack {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_cached_layer(&mut self, layer: &Rc<RefCell<Cached>>) {
|
pub fn draw_cached_layer(&mut self, layer: &Rc<RefCell<Cached>>) {
|
||||||
{
|
self.cached.push((self.transformation(), layer.clone()));
|
||||||
let mut layer = layer.borrow_mut();
|
|
||||||
layer.transformation = self.transformation() * layer.transformation;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.cached.push(layer.clone());
|
|
||||||
self.order.push(Kind::Cache);
|
self.order.push(Kind::Cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_clip(&mut self, bounds: Option<Rectangle>) {
|
pub fn push_clip(&mut self, bounds: Option<Rectangle>) {
|
||||||
self.previous.push(self.current);
|
// self.previous.push(self.current);
|
||||||
self.order.push(Kind::Live);
|
// self.order.push(Kind::Live);
|
||||||
|
|
||||||
self.current = self.live_count;
|
// self.current = self.live_count;
|
||||||
self.live_count += 1;
|
// self.live_count += 1;
|
||||||
|
|
||||||
let bounds = bounds.map(|bounds| bounds * self.transformation());
|
// let bounds = bounds.map(|bounds| bounds * self.transformation());
|
||||||
|
|
||||||
if self.current == self.live.len() {
|
// if self.current == self.live.len() {
|
||||||
self.live.push(Live {
|
// self.live.push(Live {
|
||||||
bounds,
|
// bounds,
|
||||||
..Live::default()
|
// ..Live::default()
|
||||||
});
|
// });
|
||||||
} else {
|
// } else {
|
||||||
self.live[self.current].bounds = bounds;
|
// self.live[self.current].bounds = bounds;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop_clip(&mut self) {
|
pub fn pop_clip(&mut self) {
|
||||||
self.current = self.previous.pop().unwrap();
|
// self.current = self.previous.pop().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_transformation(&mut self, transformation: Transformation) {
|
pub fn push_transformation(&mut self, transformation: Transformation) {
|
||||||
|
|
@ -224,13 +219,17 @@ impl Stack {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = LayerMut<'_>> {
|
pub fn iter_mut(&mut self) -> impl Iterator<Item = LayerMut<'_>> {
|
||||||
|
dbg!(self.order.len());
|
||||||
let mut live = self.live.iter_mut();
|
let mut live = self.live.iter_mut();
|
||||||
let mut cached = self.cached.iter_mut();
|
let mut cached = self.cached.iter_mut();
|
||||||
|
|
||||||
self.order.iter().map(move |kind| match kind {
|
self.order.iter().map(move |kind| match kind {
|
||||||
Kind::Live => LayerMut::Live(live.next().unwrap()),
|
Kind::Live => LayerMut::Live(live.next().unwrap()),
|
||||||
Kind::Cache => {
|
Kind::Cache => {
|
||||||
LayerMut::Cached(cached.next().unwrap().borrow_mut())
|
let (transformation, layer) = cached.next().unwrap();
|
||||||
|
let layer = layer.borrow_mut();
|
||||||
|
|
||||||
|
LayerMut::Cached(*transformation * layer.transformation, layer)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -241,7 +240,12 @@ impl Stack {
|
||||||
|
|
||||||
self.order.iter().map(move |kind| match kind {
|
self.order.iter().map(move |kind| match kind {
|
||||||
Kind::Live => Layer::Live(live.next().unwrap()),
|
Kind::Live => Layer::Live(live.next().unwrap()),
|
||||||
Kind::Cache => Layer::Cached(cached.next().unwrap().borrow()),
|
Kind::Cache => {
|
||||||
|
let (transformation, layer) = cached.next().unwrap();
|
||||||
|
let layer = layer.borrow();
|
||||||
|
|
||||||
|
Layer::Cached(*transformation * layer.transformation, layer)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -288,7 +292,6 @@ impl Live {
|
||||||
Cached {
|
Cached {
|
||||||
bounds: self.bounds,
|
bounds: self.bounds,
|
||||||
transformation: self.transformation,
|
transformation: self.transformation,
|
||||||
last_transformation: None,
|
|
||||||
quads: quad::Cache::Staged(self.quads),
|
quads: quad::Cache::Staged(self.quads),
|
||||||
meshes: triangle::Cache::Staged(self.meshes),
|
meshes: triangle::Cache::Staged(self.meshes),
|
||||||
text: text::Cache::Staged(self.text),
|
text: text::Cache::Staged(self.text),
|
||||||
|
|
@ -301,7 +304,6 @@ impl Live {
|
||||||
pub struct Cached {
|
pub struct Cached {
|
||||||
pub bounds: Option<Rectangle>,
|
pub bounds: Option<Rectangle>,
|
||||||
pub transformation: Transformation,
|
pub transformation: Transformation,
|
||||||
pub last_transformation: Option<Transformation>,
|
|
||||||
pub quads: quad::Cache,
|
pub quads: quad::Cache,
|
||||||
pub meshes: triangle::Cache,
|
pub meshes: triangle::Cache,
|
||||||
pub text: text::Cache,
|
pub text: text::Cache,
|
||||||
|
|
@ -311,7 +313,6 @@ pub struct Cached {
|
||||||
impl Cached {
|
impl Cached {
|
||||||
pub fn update(&mut self, live: Live) {
|
pub fn update(&mut self, live: Live) {
|
||||||
self.bounds = live.bounds;
|
self.bounds = live.bounds;
|
||||||
self.transformation = live.transformation;
|
|
||||||
|
|
||||||
self.quads.update(live.quads);
|
self.quads.update(live.quads);
|
||||||
self.meshes.update(live.meshes);
|
self.meshes.update(live.meshes);
|
||||||
|
|
|
||||||
152
wgpu/src/lib.rs
152
wgpu/src/lib.rs
|
|
@ -116,32 +116,10 @@ impl Renderer {
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
overlay: &[T],
|
overlay: &[T],
|
||||||
) {
|
) {
|
||||||
let target_size = viewport.physical_size();
|
|
||||||
let scale_factor = viewport.scale_factor() as f32;
|
|
||||||
let transformation = viewport.projection();
|
|
||||||
|
|
||||||
self.draw_overlay(overlay, viewport);
|
self.draw_overlay(overlay, viewport);
|
||||||
|
|
||||||
self.prepare(
|
self.prepare(engine, device, queue, format, encoder, viewport);
|
||||||
engine,
|
self.render(engine, device, encoder, frame, clear_color, viewport);
|
||||||
device,
|
|
||||||
queue,
|
|
||||||
format,
|
|
||||||
encoder,
|
|
||||||
scale_factor,
|
|
||||||
target_size,
|
|
||||||
transformation,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.render(
|
|
||||||
engine,
|
|
||||||
device,
|
|
||||||
encoder,
|
|
||||||
frame,
|
|
||||||
clear_color,
|
|
||||||
scale_factor,
|
|
||||||
target_size,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(
|
fn prepare(
|
||||||
|
|
@ -151,10 +129,10 @@ impl Renderer {
|
||||||
queue: &wgpu::Queue,
|
queue: &wgpu::Queue,
|
||||||
_format: wgpu::TextureFormat,
|
_format: wgpu::TextureFormat,
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
scale_factor: f32,
|
viewport: &Viewport,
|
||||||
target_size: Size<u32>,
|
|
||||||
transformation: Transformation,
|
|
||||||
) {
|
) {
|
||||||
|
let scale_factor = viewport.scale_factor() as f32;
|
||||||
|
|
||||||
for layer in self.layers.iter_mut() {
|
for layer in self.layers.iter_mut() {
|
||||||
match layer {
|
match layer {
|
||||||
LayerMut::Live(live) => {
|
LayerMut::Live(live) => {
|
||||||
|
|
@ -164,7 +142,7 @@ impl Renderer {
|
||||||
encoder,
|
encoder,
|
||||||
&mut engine.staging_belt,
|
&mut engine.staging_belt,
|
||||||
&live.quads,
|
&live.quads,
|
||||||
transformation,
|
viewport.projection(),
|
||||||
scale_factor,
|
scale_factor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +153,7 @@ impl Renderer {
|
||||||
encoder,
|
encoder,
|
||||||
&mut engine.staging_belt,
|
&mut engine.staging_belt,
|
||||||
&live.meshes,
|
&live.meshes,
|
||||||
transformation
|
viewport.projection()
|
||||||
* Transformation::scale(scale_factor),
|
* Transformation::scale(scale_factor),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -187,10 +165,11 @@ impl Renderer {
|
||||||
encoder,
|
encoder,
|
||||||
&live.text,
|
&live.text,
|
||||||
live.bounds.unwrap_or(Rectangle::with_size(
|
live.bounds.unwrap_or(Rectangle::with_size(
|
||||||
Size::INFINITY,
|
viewport.logical_size(),
|
||||||
)),
|
)),
|
||||||
scale_factor,
|
live.transformation
|
||||||
target_size,
|
* Transformation::scale(scale_factor),
|
||||||
|
viewport.physical_size(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -201,38 +180,46 @@ impl Renderer {
|
||||||
encoder,
|
encoder,
|
||||||
&mut engine.staging_belt,
|
&mut engine.staging_belt,
|
||||||
&live.images,
|
&live.images,
|
||||||
transformation,
|
viewport.projection(),
|
||||||
scale_factor,
|
scale_factor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LayerMut::Cached(mut cached) => {
|
LayerMut::Cached(layer_transformation, mut cached) => {
|
||||||
if !cached.quads.is_empty() {
|
if !cached.quads.is_empty() {
|
||||||
engine.quad_pipeline.prepare_cache(
|
engine.quad_pipeline.prepare_cache(
|
||||||
device,
|
device,
|
||||||
encoder,
|
encoder,
|
||||||
&mut engine.staging_belt,
|
&mut engine.staging_belt,
|
||||||
&mut cached.quads,
|
&mut cached.quads,
|
||||||
transformation,
|
viewport.projection(),
|
||||||
scale_factor,
|
scale_factor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !cached.meshes.is_empty() {
|
if !cached.meshes.is_empty() {
|
||||||
|
let transformation =
|
||||||
|
Transformation::scale(scale_factor)
|
||||||
|
* layer_transformation;
|
||||||
|
|
||||||
engine.triangle_pipeline.prepare_cache(
|
engine.triangle_pipeline.prepare_cache(
|
||||||
device,
|
device,
|
||||||
encoder,
|
encoder,
|
||||||
&mut engine.staging_belt,
|
&mut engine.staging_belt,
|
||||||
&mut cached.meshes,
|
&mut cached.meshes,
|
||||||
transformation
|
viewport.projection(),
|
||||||
* Transformation::scale(scale_factor),
|
transformation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !cached.text.is_empty() {
|
if !cached.text.is_empty() {
|
||||||
let bounds = cached
|
let bounds = cached.bounds.unwrap_or(
|
||||||
.bounds
|
Rectangle::with_size(viewport.logical_size()),
|
||||||
.unwrap_or(Rectangle::with_size(Size::INFINITY));
|
);
|
||||||
|
|
||||||
|
let transformation =
|
||||||
|
Transformation::scale(scale_factor)
|
||||||
|
* layer_transformation;
|
||||||
|
|
||||||
engine.text_pipeline.prepare_cache(
|
engine.text_pipeline.prepare_cache(
|
||||||
device,
|
device,
|
||||||
|
|
@ -240,8 +227,8 @@ impl Renderer {
|
||||||
encoder,
|
encoder,
|
||||||
&mut cached.text,
|
&mut cached.text,
|
||||||
bounds,
|
bounds,
|
||||||
scale_factor,
|
transformation,
|
||||||
target_size,
|
viewport.physical_size(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,7 +239,7 @@ impl Renderer {
|
||||||
encoder,
|
encoder,
|
||||||
&mut engine.staging_belt,
|
&mut engine.staging_belt,
|
||||||
&cached.images,
|
&cached.images,
|
||||||
transformation,
|
viewport.projection(),
|
||||||
scale_factor,
|
scale_factor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -268,8 +255,7 @@ impl Renderer {
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
frame: &wgpu::TextureView,
|
frame: &wgpu::TextureView,
|
||||||
clear_color: Option<Color>,
|
clear_color: Option<Color>,
|
||||||
scale_factor: f32,
|
viewport: &Viewport,
|
||||||
target_size: Size<u32>,
|
|
||||||
) {
|
) {
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
|
|
||||||
|
|
@ -312,22 +298,37 @@ impl Renderer {
|
||||||
let mut image_layer = 0;
|
let mut image_layer = 0;
|
||||||
|
|
||||||
// TODO: Can we avoid collecting here?
|
// TODO: Can we avoid collecting here?
|
||||||
|
let scale_factor = viewport.scale_factor() as f32;
|
||||||
|
let screen_bounds = Rectangle::with_size(viewport.logical_size());
|
||||||
|
let physical_bounds = Rectangle::<f32>::from(Rectangle::with_size(
|
||||||
|
viewport.physical_size(),
|
||||||
|
));
|
||||||
|
|
||||||
let layers: Vec<_> = self.layers.iter().collect();
|
let layers: Vec<_> = self.layers.iter().collect();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|
||||||
|
// println!("RENDER");
|
||||||
|
|
||||||
while i < layers.len() {
|
while i < layers.len() {
|
||||||
match layers[i] {
|
match layers[i] {
|
||||||
Layer::Live(live) => {
|
Layer::Live(live) => {
|
||||||
let bounds = live
|
let layer_transformation =
|
||||||
.bounds
|
Transformation::scale(scale_factor)
|
||||||
.map(|bounds| bounds * scale_factor)
|
* live.transformation;
|
||||||
|
|
||||||
|
let layer_bounds = live.bounds.unwrap_or(screen_bounds);
|
||||||
|
|
||||||
|
let Some(physical_bounds) = physical_bounds
|
||||||
|
.intersection(&(layer_bounds * layer_transformation))
|
||||||
.map(Rectangle::snap)
|
.map(Rectangle::snap)
|
||||||
.unwrap_or(Rectangle::with_size(target_size));
|
else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
if !live.quads.is_empty() {
|
if !live.quads.is_empty() {
|
||||||
engine.quad_pipeline.render_batch(
|
engine.quad_pipeline.render_batch(
|
||||||
quad_layer,
|
quad_layer,
|
||||||
bounds,
|
physical_bounds,
|
||||||
&live.quads,
|
&live.quads,
|
||||||
&mut render_pass,
|
&mut render_pass,
|
||||||
);
|
);
|
||||||
|
|
@ -336,6 +337,7 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !live.meshes.is_empty() {
|
if !live.meshes.is_empty() {
|
||||||
|
// println!("LIVE PASS");
|
||||||
let _ = ManuallyDrop::into_inner(render_pass);
|
let _ = ManuallyDrop::into_inner(render_pass);
|
||||||
|
|
||||||
engine.triangle_pipeline.render_batch(
|
engine.triangle_pipeline.render_batch(
|
||||||
|
|
@ -343,10 +345,10 @@ impl Renderer {
|
||||||
encoder,
|
encoder,
|
||||||
frame,
|
frame,
|
||||||
mesh_layer,
|
mesh_layer,
|
||||||
target_size,
|
viewport.physical_size(),
|
||||||
&live.meshes,
|
&live.meshes,
|
||||||
bounds,
|
physical_bounds,
|
||||||
scale_factor,
|
&layer_transformation,
|
||||||
);
|
);
|
||||||
|
|
||||||
mesh_layer += 1;
|
mesh_layer += 1;
|
||||||
|
|
@ -375,7 +377,7 @@ impl Renderer {
|
||||||
if !live.text.is_empty() {
|
if !live.text.is_empty() {
|
||||||
engine.text_pipeline.render_batch(
|
engine.text_pipeline.render_batch(
|
||||||
text_layer,
|
text_layer,
|
||||||
bounds,
|
physical_bounds,
|
||||||
&mut render_pass,
|
&mut render_pass,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -386,7 +388,7 @@ impl Renderer {
|
||||||
if !live.images.is_empty() {
|
if !live.images.is_empty() {
|
||||||
engine.image_pipeline.render(
|
engine.image_pipeline.render(
|
||||||
image_layer,
|
image_layer,
|
||||||
bounds,
|
physical_bounds,
|
||||||
&mut render_pass,
|
&mut render_pass,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -395,25 +397,35 @@ impl Renderer {
|
||||||
|
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
Layer::Cached(_) => {
|
Layer::Cached(_, _) => {
|
||||||
let group_len = layers[i..]
|
let group_len = layers[i..]
|
||||||
.iter()
|
.iter()
|
||||||
.position(|layer| matches!(layer, Layer::Live(_)))
|
.position(|layer| matches!(layer, Layer::Live(_)))
|
||||||
.unwrap_or(layers.len());
|
.unwrap_or(layers.len() - i);
|
||||||
|
|
||||||
let group = layers[i..i + group_len].iter().map(|layer| {
|
let group =
|
||||||
let Layer::Cached(cached) = layer else {
|
layers[i..i + group_len].iter().filter_map(|layer| {
|
||||||
unreachable!()
|
let Layer::Cached(transformation, cached) = layer
|
||||||
};
|
else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
let bounds = cached
|
let physical_bounds = cached
|
||||||
.bounds
|
.bounds
|
||||||
.map(|bounds| bounds * scale_factor)
|
.and_then(|bounds| {
|
||||||
.map(Rectangle::snap)
|
physical_bounds.intersection(
|
||||||
.unwrap_or(Rectangle::with_size(target_size));
|
&(bounds
|
||||||
|
* *transformation
|
||||||
|
* Transformation::scale(
|
||||||
|
scale_factor,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or(physical_bounds)
|
||||||
|
.snap();
|
||||||
|
|
||||||
(cached, bounds)
|
Some((cached, physical_bounds))
|
||||||
});
|
});
|
||||||
|
|
||||||
for (cached, bounds) in group.clone() {
|
for (cached, bounds) in group.clone() {
|
||||||
if !cached.quads.is_empty() {
|
if !cached.quads.is_empty() {
|
||||||
|
|
@ -430,17 +442,17 @@ impl Renderer {
|
||||||
.any(|(cached, _)| !cached.meshes.is_empty());
|
.any(|(cached, _)| !cached.meshes.is_empty());
|
||||||
|
|
||||||
if group_has_meshes {
|
if group_has_meshes {
|
||||||
|
// println!("CACHE PASS");
|
||||||
let _ = ManuallyDrop::into_inner(render_pass);
|
let _ = ManuallyDrop::into_inner(render_pass);
|
||||||
|
|
||||||
engine.triangle_pipeline.render_cache_group(
|
engine.triangle_pipeline.render_cache_group(
|
||||||
device,
|
device,
|
||||||
encoder,
|
encoder,
|
||||||
frame,
|
frame,
|
||||||
target_size,
|
viewport.physical_size(),
|
||||||
group.clone().map(|(cached, bounds)| {
|
group.clone().map(|(cached, bounds)| {
|
||||||
(&cached.meshes, bounds)
|
(&cached.meshes, bounds)
|
||||||
}),
|
}),
|
||||||
scale_factor,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
render_pass =
|
render_pass =
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ pub enum Cache {
|
||||||
renderer: glyphon::TextRenderer,
|
renderer: glyphon::TextRenderer,
|
||||||
atlas: Option<glyphon::TextAtlas>,
|
atlas: Option<glyphon::TextAtlas>,
|
||||||
buffer_cache: Option<BufferCache>,
|
buffer_cache: Option<BufferCache>,
|
||||||
scale_factor: f32,
|
transformation: Transformation,
|
||||||
target_size: Size<u32>,
|
target_size: Size<u32>,
|
||||||
needs_reupload: bool,
|
needs_reupload: bool,
|
||||||
},
|
},
|
||||||
|
|
@ -95,7 +95,7 @@ impl Pipeline {
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
sections: &Batch,
|
sections: &Batch,
|
||||||
layer_bounds: Rectangle,
|
layer_bounds: Rectangle,
|
||||||
scale_factor: f32,
|
layer_transformation: Transformation,
|
||||||
target_size: Size<u32>,
|
target_size: Size<u32>,
|
||||||
) {
|
) {
|
||||||
if self.renderers.len() <= self.prepare_layer {
|
if self.renderers.len() <= self.prepare_layer {
|
||||||
|
|
@ -117,7 +117,7 @@ impl Pipeline {
|
||||||
&mut self.cache,
|
&mut self.cache,
|
||||||
sections,
|
sections,
|
||||||
layer_bounds,
|
layer_bounds,
|
||||||
scale_factor,
|
layer_transformation,
|
||||||
target_size,
|
target_size,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -140,7 +140,7 @@ impl Pipeline {
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
cache: &mut Cache,
|
cache: &mut Cache,
|
||||||
layer_bounds: Rectangle,
|
layer_bounds: Rectangle,
|
||||||
new_scale_factor: f32,
|
new_transformation: Transformation,
|
||||||
new_target_size: Size<u32>,
|
new_target_size: Size<u32>,
|
||||||
) {
|
) {
|
||||||
match cache {
|
match cache {
|
||||||
|
|
@ -186,7 +186,7 @@ impl Pipeline {
|
||||||
buffer_cache.as_mut().unwrap_or(&mut self.cache),
|
buffer_cache.as_mut().unwrap_or(&mut self.cache),
|
||||||
&batch,
|
&batch,
|
||||||
layer_bounds,
|
layer_bounds,
|
||||||
new_scale_factor,
|
new_transformation,
|
||||||
new_target_size,
|
new_target_size,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -196,7 +196,7 @@ impl Pipeline {
|
||||||
renderer,
|
renderer,
|
||||||
atlas,
|
atlas,
|
||||||
buffer_cache,
|
buffer_cache,
|
||||||
scale_factor: new_scale_factor,
|
transformation: new_transformation,
|
||||||
target_size: new_target_size,
|
target_size: new_target_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -206,13 +206,13 @@ impl Pipeline {
|
||||||
renderer,
|
renderer,
|
||||||
atlas,
|
atlas,
|
||||||
buffer_cache,
|
buffer_cache,
|
||||||
scale_factor,
|
transformation,
|
||||||
target_size,
|
target_size,
|
||||||
} => {
|
} => {
|
||||||
if *needs_reupload
|
if *needs_reupload
|
||||||
|| atlas.is_none()
|
|| atlas.is_none()
|
||||||
|| buffer_cache.is_none()
|
|| buffer_cache.is_none()
|
||||||
|| new_scale_factor != *scale_factor
|
|| new_transformation != *transformation
|
||||||
|| new_target_size != *target_size
|
|| new_target_size != *target_size
|
||||||
{
|
{
|
||||||
let _ = prepare(
|
let _ = prepare(
|
||||||
|
|
@ -224,11 +224,11 @@ impl Pipeline {
|
||||||
buffer_cache.as_mut().unwrap_or(&mut self.cache),
|
buffer_cache.as_mut().unwrap_or(&mut self.cache),
|
||||||
batch,
|
batch,
|
||||||
layer_bounds,
|
layer_bounds,
|
||||||
*scale_factor,
|
new_transformation,
|
||||||
*target_size,
|
new_target_size,
|
||||||
);
|
);
|
||||||
|
|
||||||
*scale_factor = new_scale_factor;
|
*transformation = new_transformation;
|
||||||
*target_size = new_target_size;
|
*target_size = new_target_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -297,7 +297,7 @@ fn prepare(
|
||||||
buffer_cache: &mut BufferCache,
|
buffer_cache: &mut BufferCache,
|
||||||
sections: &Batch,
|
sections: &Batch,
|
||||||
layer_bounds: Rectangle,
|
layer_bounds: Rectangle,
|
||||||
scale_factor: f32,
|
layer_transformation: Transformation,
|
||||||
target_size: Size<u32>,
|
target_size: Size<u32>,
|
||||||
) -> Result<(), glyphon::PrepareError> {
|
) -> Result<(), glyphon::PrepareError> {
|
||||||
let mut font_system = font_system().write().expect("Write font system");
|
let mut font_system = font_system().write().expect("Write font system");
|
||||||
|
|
@ -349,7 +349,7 @@ fn prepare(
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let layer_bounds = layer_bounds * scale_factor;
|
let layer_bounds = layer_bounds * layer_transformation;
|
||||||
|
|
||||||
let text_areas = sections.iter().zip(allocations.iter()).filter_map(
|
let text_areas = sections.iter().zip(allocations.iter()).filter_map(
|
||||||
|(section, allocation)| {
|
|(section, allocation)| {
|
||||||
|
|
@ -456,7 +456,7 @@ fn prepare(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let bounds = bounds * transformation * scale_factor;
|
let bounds = bounds * transformation * layer_transformation;
|
||||||
|
|
||||||
let left = match horizontal_alignment {
|
let left = match horizontal_alignment {
|
||||||
alignment::Horizontal::Left => bounds.x,
|
alignment::Horizontal::Left => bounds.x,
|
||||||
|
|
@ -470,14 +470,16 @@ fn prepare(
|
||||||
alignment::Vertical::Bottom => bounds.y - bounds.height,
|
alignment::Vertical::Bottom => bounds.y - bounds.height,
|
||||||
};
|
};
|
||||||
|
|
||||||
let clip_bounds = layer_bounds
|
let clip_bounds = layer_bounds.intersection(
|
||||||
.intersection(&(clip_bounds * transformation * scale_factor))?;
|
&(clip_bounds * transformation * layer_transformation),
|
||||||
|
)?;
|
||||||
|
|
||||||
Some(glyphon::TextArea {
|
Some(glyphon::TextArea {
|
||||||
buffer,
|
buffer,
|
||||||
left,
|
left,
|
||||||
top,
|
top,
|
||||||
scale: scale_factor * transformation.scale_factor(),
|
scale: transformation.scale_factor()
|
||||||
|
* layer_transformation.scale_factor(),
|
||||||
bounds: glyphon::TextBounds {
|
bounds: glyphon::TextBounds {
|
||||||
left: clip_bounds.x as i32,
|
left: clip_bounds.x as i32,
|
||||||
top: clip_bounds.y as i32,
|
top: clip_bounds.y as i32,
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,11 @@ impl Pipeline {
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
belt: &mut wgpu::util::StagingBelt,
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
cache: &mut Cache,
|
cache: &mut Cache,
|
||||||
transformation: Transformation,
|
new_projection: Transformation,
|
||||||
|
new_transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
|
let new_projection = new_projection * new_transformation;
|
||||||
|
|
||||||
match cache {
|
match cache {
|
||||||
Cache::Staged(_) => {
|
Cache::Staged(_) => {
|
||||||
let Cache::Staged(batch) =
|
let Cache::Staged(batch) =
|
||||||
|
|
@ -86,21 +89,25 @@ impl Pipeline {
|
||||||
&self.solid,
|
&self.solid,
|
||||||
&self.gradient,
|
&self.gradient,
|
||||||
&batch,
|
&batch,
|
||||||
transformation,
|
new_projection,
|
||||||
);
|
);
|
||||||
|
|
||||||
*cache = Cache::Uploaded {
|
*cache = Cache::Uploaded {
|
||||||
layer,
|
layer,
|
||||||
batch,
|
batch,
|
||||||
|
transformation: new_transformation,
|
||||||
|
projection: new_projection,
|
||||||
needs_reupload: false,
|
needs_reupload: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Cache::Uploaded {
|
Cache::Uploaded {
|
||||||
batch,
|
batch,
|
||||||
layer,
|
layer,
|
||||||
|
transformation,
|
||||||
|
projection,
|
||||||
needs_reupload,
|
needs_reupload,
|
||||||
} => {
|
} => {
|
||||||
if *needs_reupload {
|
if *needs_reupload || new_projection != *projection {
|
||||||
layer.prepare(
|
layer.prepare(
|
||||||
device,
|
device,
|
||||||
encoder,
|
encoder,
|
||||||
|
|
@ -108,9 +115,11 @@ impl Pipeline {
|
||||||
&self.solid,
|
&self.solid,
|
||||||
&self.gradient,
|
&self.gradient,
|
||||||
batch,
|
batch,
|
||||||
transformation,
|
new_projection,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
*transformation = new_transformation;
|
||||||
|
*projection = new_projection;
|
||||||
*needs_reupload = false;
|
*needs_reupload = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +135,7 @@ impl Pipeline {
|
||||||
target_size: Size<u32>,
|
target_size: Size<u32>,
|
||||||
meshes: &Batch,
|
meshes: &Batch,
|
||||||
bounds: Rectangle<u32>,
|
bounds: Rectangle<u32>,
|
||||||
scale_factor: f32,
|
transformation: &Transformation,
|
||||||
) {
|
) {
|
||||||
Self::render(
|
Self::render(
|
||||||
device,
|
device,
|
||||||
|
|
@ -136,8 +145,12 @@ impl Pipeline {
|
||||||
&self.solid,
|
&self.solid,
|
||||||
&self.gradient,
|
&self.gradient,
|
||||||
target_size,
|
target_size,
|
||||||
std::iter::once((&self.layers[layer], meshes, bounds)),
|
std::iter::once((
|
||||||
scale_factor,
|
&self.layers[layer],
|
||||||
|
meshes,
|
||||||
|
transformation,
|
||||||
|
bounds,
|
||||||
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,9 +163,14 @@ impl Pipeline {
|
||||||
target_size: Size<u32>,
|
target_size: Size<u32>,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
bounds: Rectangle<u32>,
|
bounds: Rectangle<u32>,
|
||||||
scale_factor: f32,
|
|
||||||
) {
|
) {
|
||||||
let Cache::Uploaded { batch, layer, .. } = cache else {
|
let Cache::Uploaded {
|
||||||
|
batch,
|
||||||
|
layer,
|
||||||
|
transformation,
|
||||||
|
..
|
||||||
|
} = cache
|
||||||
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -164,8 +182,7 @@ impl Pipeline {
|
||||||
&self.solid,
|
&self.solid,
|
||||||
&self.gradient,
|
&self.gradient,
|
||||||
target_size,
|
target_size,
|
||||||
std::iter::once((layer, batch, bounds)),
|
std::iter::once((layer, batch, transformation, bounds)),
|
||||||
scale_factor,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,11 +193,16 @@ impl Pipeline {
|
||||||
target: &wgpu::TextureView,
|
target: &wgpu::TextureView,
|
||||||
target_size: Size<u32>,
|
target_size: Size<u32>,
|
||||||
group: impl Iterator<Item = (&'a Cache, Rectangle<u32>)>,
|
group: impl Iterator<Item = (&'a Cache, Rectangle<u32>)>,
|
||||||
scale_factor: f32,
|
|
||||||
) {
|
) {
|
||||||
let group = group.filter_map(|(cache, bounds)| {
|
let group = group.filter_map(|(cache, bounds)| {
|
||||||
if let Cache::Uploaded { batch, layer, .. } = cache {
|
if let Cache::Uploaded {
|
||||||
Some((layer, batch, bounds))
|
batch,
|
||||||
|
layer,
|
||||||
|
transformation,
|
||||||
|
..
|
||||||
|
} = cache
|
||||||
|
{
|
||||||
|
Some((layer, batch, transformation, bounds))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
@ -195,7 +217,6 @@ impl Pipeline {
|
||||||
&self.gradient,
|
&self.gradient,
|
||||||
target_size,
|
target_size,
|
||||||
group,
|
group,
|
||||||
scale_factor,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -207,8 +228,9 @@ impl Pipeline {
|
||||||
solid: &solid::Pipeline,
|
solid: &solid::Pipeline,
|
||||||
gradient: &gradient::Pipeline,
|
gradient: &gradient::Pipeline,
|
||||||
target_size: Size<u32>,
|
target_size: Size<u32>,
|
||||||
group: impl Iterator<Item = (&'a Layer, &'a Batch, Rectangle<u32>)>,
|
group: impl Iterator<
|
||||||
scale_factor: f32,
|
Item = (&'a Layer, &'a Batch, &'a Transformation, Rectangle<u32>),
|
||||||
|
>,
|
||||||
) {
|
) {
|
||||||
{
|
{
|
||||||
let (attachment, resolve_target, load) = if let Some(blit) =
|
let (attachment, resolve_target, load) = if let Some(blit) =
|
||||||
|
|
@ -244,13 +266,13 @@ impl Pipeline {
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
for (layer, meshes, bounds) in group {
|
for (layer, meshes, transformation, bounds) in group {
|
||||||
layer.render(
|
layer.render(
|
||||||
solid,
|
solid,
|
||||||
gradient,
|
gradient,
|
||||||
meshes,
|
meshes,
|
||||||
bounds,
|
bounds,
|
||||||
scale_factor,
|
*transformation,
|
||||||
&mut render_pass,
|
&mut render_pass,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -272,6 +294,8 @@ pub enum Cache {
|
||||||
Uploaded {
|
Uploaded {
|
||||||
batch: Batch,
|
batch: Batch,
|
||||||
layer: Layer,
|
layer: Layer,
|
||||||
|
transformation: Transformation,
|
||||||
|
projection: Transformation,
|
||||||
needs_reupload: bool,
|
needs_reupload: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -390,6 +414,7 @@ impl Layer {
|
||||||
|
|
||||||
for mesh in meshes {
|
for mesh in meshes {
|
||||||
let indices = mesh.indices();
|
let indices = mesh.indices();
|
||||||
|
|
||||||
let uniforms =
|
let uniforms =
|
||||||
Uniforms::new(transformation * mesh.transformation());
|
Uniforms::new(transformation * mesh.transformation());
|
||||||
|
|
||||||
|
|
@ -448,7 +473,7 @@ impl Layer {
|
||||||
gradient: &'a gradient::Pipeline,
|
gradient: &'a gradient::Pipeline,
|
||||||
meshes: &Batch,
|
meshes: &Batch,
|
||||||
layer_bounds: Rectangle<u32>,
|
layer_bounds: Rectangle<u32>,
|
||||||
scale_factor: f32,
|
transformation: Transformation,
|
||||||
render_pass: &mut wgpu::RenderPass<'a>,
|
render_pass: &mut wgpu::RenderPass<'a>,
|
||||||
) {
|
) {
|
||||||
let mut num_solids = 0;
|
let mut num_solids = 0;
|
||||||
|
|
@ -457,15 +482,12 @@ impl Layer {
|
||||||
|
|
||||||
for (index, mesh) in meshes.iter().enumerate() {
|
for (index, mesh) in meshes.iter().enumerate() {
|
||||||
let Some(clip_bounds) = Rectangle::<f32>::from(layer_bounds)
|
let Some(clip_bounds) = Rectangle::<f32>::from(layer_bounds)
|
||||||
.intersection(&(mesh.clip_bounds() * scale_factor))
|
.intersection(&(mesh.clip_bounds() * transformation))
|
||||||
.map(Rectangle::snap)
|
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
if clip_bounds.width < 1 || clip_bounds.height < 1 {
|
let clip_bounds = clip_bounds.snap();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
render_pass.set_scissor_rect(
|
render_pass.set_scissor_rect(
|
||||||
clip_bounds.x,
|
clip_bounds.x,
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ use crate::core::mouse;
|
||||||
use crate::core::renderer;
|
use crate::core::renderer;
|
||||||
use crate::core::widget::tree::{self, Tree};
|
use crate::core::widget::tree::{self, Tree};
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
Clipboard, Element, Length, Rectangle, Shell, Size, Transformation, Widget,
|
Clipboard, Element, Length, Rectangle, Shell, Size, Vector, Widget,
|
||||||
};
|
};
|
||||||
use crate::graphics::geometry;
|
use crate::graphics::geometry;
|
||||||
|
|
||||||
|
|
@ -222,8 +222,8 @@ where
|
||||||
|
|
||||||
let state = tree.state.downcast_ref::<P::State>();
|
let state = tree.state.downcast_ref::<P::State>();
|
||||||
|
|
||||||
renderer.with_transformation(
|
renderer.with_translation(
|
||||||
Transformation::translate(bounds.x, bounds.y),
|
Vector::new(bounds.x, bounds.y),
|
||||||
|renderer| {
|
|renderer| {
|
||||||
let layers =
|
let layers =
|
||||||
self.program.draw(state, renderer, theme, bounds, cursor);
|
self.program.draw(state, renderer, theme, bounds, cursor);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue