Fix windows fighting over shared image::Cache

Image caches are local to each window now.
This commit is contained in:
Héctor Ramón Jiménez 2024-05-06 12:14:42 +02:00
parent a94984d681
commit 547446f0de
No known key found for this signature in database
GPG key ID: 4C07CEC81AFA161F
8 changed files with 77 additions and 70 deletions

View file

@ -15,15 +15,23 @@ pub const SIZE: u32 = 2048;
use crate::core::Size;
use crate::graphics::color;
use std::sync::Arc;
#[derive(Debug)]
pub struct Atlas {
texture: wgpu::Texture,
texture_view: wgpu::TextureView,
texture_bind_group: wgpu::BindGroup,
texture_layout: Arc<wgpu::BindGroupLayout>,
layers: Vec<Layer>,
}
impl Atlas {
pub fn new(device: &wgpu::Device, backend: wgpu::Backend) -> Self {
pub fn new(
device: &wgpu::Device,
backend: wgpu::Backend,
texture_layout: Arc<wgpu::BindGroupLayout>,
) -> Self {
let layers = match backend {
// On the GL backend we start with 2 layers, to help wgpu figure
// out that this texture is `GL_TEXTURE_2D_ARRAY` rather than `GL_TEXTURE_2D`
@ -60,15 +68,27 @@ impl Atlas {
..Default::default()
});
let texture_bind_group =
device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("iced_wgpu::image texture atlas bind group"),
layout: &texture_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(&texture_view),
}],
});
Atlas {
texture,
texture_view,
texture_bind_group,
texture_layout,
layers,
}
}
pub fn view(&self) -> &wgpu::TextureView {
&self.texture_view
pub fn bind_group(&self) -> &wgpu::BindGroup {
&self.texture_bind_group
}
pub fn layer_count(&self) -> usize {
@ -421,5 +441,17 @@ impl Atlas {
dimension: Some(wgpu::TextureViewDimension::D2Array),
..Default::default()
});
self.texture_bind_group =
device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("iced_wgpu::image texture atlas bind group"),
layout: &self.texture_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(
&self.texture_view,
),
}],
});
}
}

View file

@ -1,8 +1,7 @@
use crate::core::{self, Size};
use crate::image::atlas::{self, Atlas};
use std::cell::{RefCell, RefMut};
use std::rc::Rc;
use std::sync::Arc;
#[derive(Debug)]
pub struct Cache {
@ -14,9 +13,13 @@ pub struct Cache {
}
impl Cache {
pub fn new(device: &wgpu::Device, backend: wgpu::Backend) -> Self {
pub fn new(
device: &wgpu::Device,
backend: wgpu::Backend,
layout: Arc<wgpu::BindGroupLayout>,
) -> Self {
Self {
atlas: Atlas::new(device, backend),
atlas: Atlas::new(device, backend, layout),
#[cfg(feature = "image")]
raster: crate::image::raster::Cache::default(),
#[cfg(feature = "svg")]
@ -24,6 +27,10 @@ impl Cache {
}
}
pub fn bind_group(&self) -> &wgpu::BindGroup {
self.atlas.bind_group()
}
pub fn layer_count(&self) -> usize {
self.atlas.layer_count()
}
@ -69,21 +76,6 @@ impl Cache {
)
}
pub fn create_bind_group(
&self,
device: &wgpu::Device,
layout: &wgpu::BindGroupLayout,
) -> wgpu::BindGroup {
device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("iced_wgpu::image texture atlas bind group"),
layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(self.atlas.view()),
}],
})
}
pub fn trim(&mut self) {
#[cfg(feature = "image")]
self.raster.trim(&mut self.atlas);
@ -92,16 +84,3 @@ impl Cache {
self.vector.trim(&mut self.atlas);
}
}
#[derive(Debug, Clone)]
pub struct Shared(Rc<RefCell<Cache>>);
impl Shared {
pub fn new(cache: Cache) -> Self {
Self(Rc::new(RefCell::new(cache)))
}
pub fn lock(&self) -> RefMut<'_, Cache> {
self.0.borrow_mut()
}
}

View file

@ -13,7 +13,9 @@ use crate::core::{Rectangle, Size, Transformation};
use crate::Buffer;
use bytemuck::{Pod, Zeroable};
use std::mem;
use std::sync::Arc;
pub use crate::graphics::Image;
@ -22,13 +24,11 @@ pub type Batch = Vec<Image>;
#[derive(Debug)]
pub struct Pipeline {
pipeline: wgpu::RenderPipeline,
backend: wgpu::Backend,
nearest_sampler: wgpu::Sampler,
linear_sampler: wgpu::Sampler,
texture: wgpu::BindGroup,
texture_version: usize,
texture_layout: wgpu::BindGroupLayout,
texture_layout: Arc<wgpu::BindGroupLayout>,
constant_layout: wgpu::BindGroupLayout,
cache: cache::Shared,
layers: Vec<Layer>,
prepare_layer: usize,
}
@ -186,25 +186,20 @@ impl Pipeline {
multiview: None,
});
let cache = Cache::new(device, backend);
let texture = cache.create_bind_group(device, &texture_layout);
Pipeline {
pipeline,
backend,
nearest_sampler,
linear_sampler,
texture,
texture_version: cache.layer_count(),
texture_layout,
texture_layout: Arc::new(texture_layout),
constant_layout,
cache: cache::Shared::new(cache),
layers: Vec::new(),
prepare_layer: 0,
}
}
pub fn cache(&self) -> &cache::Shared {
&self.cache
pub fn create_cache(&self, device: &wgpu::Device) -> Cache {
Cache::new(device, self.backend, self.texture_layout.clone())
}
pub fn prepare(
@ -212,6 +207,7 @@ impl Pipeline {
device: &wgpu::Device,
encoder: &mut wgpu::CommandEncoder,
belt: &mut wgpu::util::StagingBelt,
cache: &mut Cache,
images: &Batch,
transformation: Transformation,
scale: f32,
@ -221,8 +217,6 @@ impl Pipeline {
let nearest_instances: &mut Vec<Instance> = &mut Vec::new();
let linear_instances: &mut Vec<Instance> = &mut Vec::new();
let mut cache = self.cache.lock();
for image in images {
match &image {
#[cfg(feature = "image")]
@ -288,16 +282,6 @@ impl Pipeline {
return;
}
let texture_version = cache.layer_count();
if self.texture_version != texture_version {
log::debug!("Atlas has grown. Recreating bind group...");
self.texture =
cache.create_bind_group(device, &self.texture_layout);
self.texture_version = texture_version;
}
if self.layers.len() <= self.prepare_layer {
self.layers.push(Layer::new(
device,
@ -323,6 +307,7 @@ impl Pipeline {
pub fn render<'a>(
&'a self,
cache: &'a Cache,
layer: usize,
bounds: Rectangle<u32>,
render_pass: &mut wgpu::RenderPass<'a>,
@ -337,14 +322,13 @@ impl Pipeline {
bounds.height,
);
render_pass.set_bind_group(1, &self.texture, &[]);
render_pass.set_bind_group(1, cache.bind_group(), &[]);
layer.render(render_pass);
}
}
pub fn end_frame(&mut self) {
self.cache.lock().trim();
self.prepare_layer = 0;
}
}