Fix windows fighting over shared image::Cache
Image caches are local to each window now.
This commit is contained in:
parent
a94984d681
commit
547446f0de
8 changed files with 77 additions and 70 deletions
|
|
@ -70,7 +70,8 @@ fn benchmark(
|
|||
Some(Antialiasing::MSAAx4),
|
||||
);
|
||||
|
||||
let mut renderer = Renderer::new(&engine, Font::DEFAULT, Pixels::from(16));
|
||||
let mut renderer =
|
||||
Renderer::new(&device, &engine, Font::DEFAULT, Pixels::from(16));
|
||||
|
||||
let viewport =
|
||||
graphics::Viewport::with_physical_size(Size::new(3840, 2160), 2.0);
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let mut debug = Debug::new();
|
||||
let mut engine = Engine::new(&adapter, &device, &queue, format, None);
|
||||
let mut renderer =
|
||||
Renderer::new(&engine, Font::default(), Pixels::from(16));
|
||||
Renderer::new(&device, &engine, Font::default(), Pixels::from(16));
|
||||
|
||||
let mut state = program::State::new(
|
||||
controls,
|
||||
|
|
|
|||
|
|
@ -59,8 +59,11 @@ impl Engine {
|
|||
}
|
||||
|
||||
#[cfg(any(feature = "image", feature = "svg"))]
|
||||
pub fn image_cache(&self) -> &crate::image::cache::Shared {
|
||||
self.image_pipeline.cache()
|
||||
pub fn create_image_cache(
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
) -> crate::image::Cache {
|
||||
self.image_pipeline.create_cache(device)
|
||||
}
|
||||
|
||||
pub fn submit(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
}],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ use crate::core::{
|
|||
use crate::graphics::text::{Editor, Paragraph};
|
||||
use crate::graphics::Viewport;
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
/// A [`wgpu`] graphics renderer for [`iced`].
|
||||
///
|
||||
/// [`wgpu`]: https://github.com/gfx-rs/wgpu-rs
|
||||
|
|
@ -82,11 +84,12 @@ pub struct Renderer {
|
|||
|
||||
// TODO: Centralize all the image feature handling
|
||||
#[cfg(any(feature = "svg", feature = "image"))]
|
||||
image_cache: image::cache::Shared,
|
||||
image_cache: RefCell<image::Cache>,
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
pub fn new(
|
||||
_device: &wgpu::Device,
|
||||
_engine: &Engine,
|
||||
default_font: Font,
|
||||
default_text_size: Pixels,
|
||||
|
|
@ -100,7 +103,7 @@ impl Renderer {
|
|||
text_storage: text::Storage::new(),
|
||||
|
||||
#[cfg(any(feature = "svg", feature = "image"))]
|
||||
image_cache: _engine.image_cache().clone(),
|
||||
image_cache: RefCell::new(_engine.create_image_cache(_device)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -191,6 +194,7 @@ impl Renderer {
|
|||
device,
|
||||
encoder,
|
||||
&mut engine.staging_belt,
|
||||
&mut self.image_cache.borrow_mut(),
|
||||
&layer.images,
|
||||
viewport.projection(),
|
||||
scale_factor,
|
||||
|
|
@ -246,6 +250,8 @@ impl Renderer {
|
|||
|
||||
#[cfg(any(feature = "svg", feature = "image"))]
|
||||
let mut image_layer = 0;
|
||||
#[cfg(any(feature = "svg", feature = "image"))]
|
||||
let image_cache = self.image_cache.borrow();
|
||||
|
||||
let scale_factor = viewport.scale_factor() as f32;
|
||||
let physical_bounds = Rectangle::<f32>::from(Rectangle::with_size(
|
||||
|
|
@ -359,6 +365,7 @@ impl Renderer {
|
|||
#[cfg(any(feature = "svg", feature = "image"))]
|
||||
if !layer.images.is_empty() {
|
||||
engine.image_pipeline.render(
|
||||
&image_cache,
|
||||
image_layer,
|
||||
scissor_rect,
|
||||
&mut render_pass,
|
||||
|
|
@ -509,7 +516,7 @@ impl core::image::Renderer for Renderer {
|
|||
type Handle = core::image::Handle;
|
||||
|
||||
fn measure_image(&self, handle: &Self::Handle) -> Size<u32> {
|
||||
self.image_cache.lock().measure_image(handle)
|
||||
self.image_cache.borrow_mut().measure_image(handle)
|
||||
}
|
||||
|
||||
fn draw_image(
|
||||
|
|
@ -535,7 +542,7 @@ impl core::image::Renderer for Renderer {
|
|||
#[cfg(feature = "svg")]
|
||||
impl core::svg::Renderer for Renderer {
|
||||
fn measure_svg(&self, handle: &core::svg::Handle) -> Size<u32> {
|
||||
self.image_cache.lock().measure_svg(handle)
|
||||
self.image_cache.borrow_mut().measure_svg(handle)
|
||||
}
|
||||
|
||||
fn draw_svg(
|
||||
|
|
|
|||
|
|
@ -290,6 +290,7 @@ impl graphics::Compositor for Compositor {
|
|||
|
||||
fn create_renderer(&self) -> Self::Renderer {
|
||||
Renderer::new(
|
||||
&self.device,
|
||||
&self.engine,
|
||||
self.settings.default_font,
|
||||
self.settings.default_text_size,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue