diff --git a/examples/custom_shader/src/scene.rs b/examples/custom_shader/src/scene.rs index 88f72970..d5515e49 100644 --- a/examples/custom_shader/src/scene.rs +++ b/examples/custom_shader/src/scene.rs @@ -128,16 +128,7 @@ impl Primitive { } impl shader::Primitive for Primitive { - type Renderer = Pipeline; - - fn initialize( - &self, - device: &wgpu::Device, - queue: &wgpu::Queue, - format: wgpu::TextureFormat, - ) -> Pipeline { - Pipeline::new(device, queue, format) - } + type Pipeline = Pipeline; fn prepare( &self, @@ -183,3 +174,13 @@ fn rnd_origin() -> Vec3 { rand::thread_rng().gen_range(-4.0..2.0), ) } + +impl shader::Pipeline for Pipeline { + fn new( + device: &wgpu::Device, + queue: &wgpu::Queue, + format: wgpu::TextureFormat, + ) -> Pipeline { + Self::new(device, queue, format) + } +} diff --git a/wgpu/src/engine.rs b/wgpu/src/engine.rs index 4bc30b7f..d86499eb 100644 --- a/wgpu/src/engine.rs +++ b/wgpu/src/engine.rs @@ -66,4 +66,13 @@ impl Engine { &self._shell, ) } + + pub fn trim(&mut self) { + self.text_pipeline.trim(); + + self.primitive_storage + .write() + .expect("primitive storage should be writable") + .trim(); + } } diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 8f2faa62..977a3add 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -149,8 +149,8 @@ impl Renderer { self.triangle.trim(); self.text.trim(); - // TODO: Move to runtime! - self.engine.text_pipeline.trim(); + // TODO: Provide window id (?) + self.engine.trim(); #[cfg(any(feature = "svg", feature = "image"))] { diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs index cb2c02c7..4c18bb6a 100644 --- a/wgpu/src/primitive.rs +++ b/wgpu/src/primitive.rs @@ -19,23 +19,12 @@ pub trait Primitive: Debug + MaybeSend + MaybeSync + 'static { /// /// All instances of this [`Primitive`] type will share the same /// [`Renderer`]. - type Renderer: MaybeSend + MaybeSync; - - /// Initializes the [`Renderer`](Self::Renderer) of the [`Primitive`]. - /// - /// This will only be called once, when the first [`Primitive`] of this kind - /// is encountered. - fn initialize( - &self, - device: &wgpu::Device, - queue: &wgpu::Queue, - format: wgpu::TextureFormat, - ) -> Self::Renderer; + type Pipeline: Pipeline + MaybeSend + MaybeSync; /// Processes the [`Primitive`], allowing for GPU buffer allocation. fn prepare( &self, - renderer: &mut Self::Renderer, + pipeline: &mut Self::Pipeline, device: &wgpu::Device, queue: &wgpu::Queue, bounds: &Rectangle, @@ -57,7 +46,7 @@ pub trait Primitive: Debug + MaybeSend + MaybeSync + 'static { /// By default, it does nothing and returns `false`. fn draw( &self, - _renderer: &Self::Renderer, + _pipeline: &Self::Pipeline, _render_pass: &mut wgpu::RenderPass<'_>, ) -> bool { false @@ -70,7 +59,7 @@ pub trait Primitive: Debug + MaybeSend + MaybeSync + 'static { /// By default, it does nothing. fn render( &self, - _renderer: &Self::Renderer, + _pipeline: &Self::Pipeline, _encoder: &mut wgpu::CommandEncoder, _target: &wgpu::TextureView, _clip_bounds: &Rectangle, @@ -78,6 +67,26 @@ pub trait Primitive: Debug + MaybeSend + MaybeSync + 'static { } } +/// The pipeline of a graphics [`Primitive`]. +pub trait Pipeline: Any + MaybeSend + MaybeSync { + /// Creates the [`Pipeline`] of a [`Primitive`]. + /// + /// This will only be called once, when the first [`Primitive`] with this kind + /// of [`Pipeline`] is encountered. + fn new( + device: &wgpu::Device, + queue: &wgpu::Queue, + format: wgpu::TextureFormat, + ) -> Self + where + Self: Sized; + + /// Trims any cached data in the [`Pipeline`]. + /// + /// This will normally be called at the end of a frame. + fn trim(&mut self) {} +} + pub(crate) trait Stored: Debug + MaybeSend + MaybeSync + 'static { @@ -122,15 +131,13 @@ impl Stored for BlackBox

{ viewport: &Viewport, ) { if !storage.has::

() { - storage.store::( - self.primitive.initialize(device, queue, format), - ); + storage.store::(P::Pipeline::new(device, queue, format)); } let renderer = storage .get_mut::

() .expect("renderer should be initialized") - .downcast_mut::() + .downcast_mut::() .expect("renderer should have the proper type"); self.primitive @@ -145,7 +152,7 @@ impl Stored for BlackBox

{ let renderer = storage .get::

() .expect("renderer should be initialized") - .downcast_ref::() + .downcast_ref::() .expect("renderer should have the proper type"); self.primitive.draw(renderer, render_pass) @@ -161,7 +168,7 @@ impl Stored for BlackBox

{ let renderer = storage .get::

() .expect("renderer should be initialized") - .downcast_ref::() + .downcast_ref::() .expect("renderer should have the proper type"); self.primitive @@ -198,7 +205,7 @@ pub trait Renderer: core::Renderer { /// Stores custom, user-provided types. #[derive(Default)] pub struct Storage { - pipelines: FxHashMap>, + pipelines: FxHashMap>, } impl Storage { @@ -208,11 +215,8 @@ impl Storage { } /// Inserts the data `T` in to [`Storage`]. - pub fn store( - &mut self, - data: D, - ) { - let _ = self.pipelines.insert(TypeId::of::(), Box::new(data)); + pub fn store(&mut self, pipeline: P) { + let _ = self.pipelines.insert(TypeId::of::(), Box::new(pipeline)); } /// Returns a reference to the data with type `T` if it exists in [`Storage`]. @@ -228,8 +232,11 @@ impl Storage { .get_mut(&TypeId::of::()) .map(|pipeline| pipeline.as_mut() as &mut dyn Any) } + + /// Trims the cache of all the pipelines in the [`Storage`]. + pub fn trim(&mut self) { + for pipeline in self.pipelines.values_mut() { + pipeline.trim(); + } + } } - -trait AnyConcurrent: Any + MaybeSend + MaybeSync {} - -impl AnyConcurrent for T where T: Any + MaybeSend + MaybeSync {} diff --git a/widget/src/shader.rs b/widget/src/shader.rs index 7ce06964..bd05504e 100644 --- a/widget/src/shader.rs +++ b/widget/src/shader.rs @@ -16,7 +16,7 @@ use std::marker::PhantomData; pub use crate::Action; pub use crate::graphics::Viewport; -pub use primitive::{Primitive, Storage}; +pub use primitive::{Pipeline, Primitive, Storage}; /// A widget which can render custom shaders with Iced's `wgpu` backend. ///