diff options
Diffstat (limited to '')
-rw-r--r-- | wgpu/src/primitive.rs | 43 | ||||
-rw-r--r-- | wgpu/src/primitive/pipeline.rs | 117 |
2 files changed, 125 insertions, 35 deletions
diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs index 4347dcda..fff927ea 100644 --- a/wgpu/src/primitive.rs +++ b/wgpu/src/primitive.rs @@ -1,10 +1,12 @@ //! Draw using different graphical primitives. +pub mod pipeline; + +pub use pipeline::Pipeline; + use crate::core::Rectangle; -use crate::custom; use crate::graphics::{Damage, Mesh}; -use std::any::Any; + use std::fmt::Debug; -use std::sync::Arc; /// The graphical primitives supported by `iced_wgpu`. pub type Primitive = crate::graphics::Primitive<Custom>; @@ -14,44 +16,15 @@ pub type Primitive = crate::graphics::Primitive<Custom>; pub enum Custom { /// A mesh primitive. Mesh(Mesh), - /// A custom shader primitive - Shader(Shader), -} - -impl Custom { - /// Create a custom [`Shader`] primitive. - pub fn shader<P: custom::Primitive>( - bounds: Rectangle, - primitive: P, - ) -> Self { - Self::Shader(Shader { - bounds, - primitive: Arc::new(primitive), - }) - } + /// A custom pipeline primitive. + Pipeline(Pipeline), } impl Damage for Custom { fn bounds(&self) -> Rectangle { match self { Self::Mesh(mesh) => mesh.bounds(), - Self::Shader(shader) => shader.bounds, + Self::Pipeline(pipeline) => pipeline.bounds, } } } - -#[derive(Clone, Debug)] -/// A custom primitive which can be used to render primitives associated with a custom pipeline. -pub struct Shader { - /// The bounds of the [`Shader`]. - pub bounds: Rectangle, - - /// The [`custom::Primitive`] to render. - pub primitive: Arc<dyn custom::Primitive>, -} - -impl PartialEq for Shader { - fn eq(&self, other: &Self) -> bool { - self.primitive.type_id() == other.primitive.type_id() - } -} diff --git a/wgpu/src/primitive/pipeline.rs b/wgpu/src/primitive/pipeline.rs new file mode 100644 index 00000000..b59aeff1 --- /dev/null +++ b/wgpu/src/primitive/pipeline.rs @@ -0,0 +1,117 @@ +//! Draw primitives using custom pipelines. +use crate::core::{Rectangle, Size}; +use crate::graphics::Transformation; + +use std::any::{Any, TypeId}; +use std::collections::HashMap; +use std::fmt::Debug; +use std::sync::Arc; + +#[derive(Clone, Debug)] +/// A custom primitive which can be used to render primitives associated with a custom pipeline. +pub struct Pipeline { + /// The bounds of the [`Shader`]. + pub bounds: Rectangle, + + /// The [`custom::Primitive`] to render. + pub primitive: Arc<dyn Primitive>, +} + +impl Pipeline { + /// Creates a new [`Pipeline`] with the given [`Primitive`]. + pub fn new(bounds: Rectangle, primitive: impl Primitive) -> Self { + Pipeline { + bounds, + primitive: Arc::new(primitive), + } + } +} + +impl PartialEq for Pipeline { + fn eq(&self, other: &Self) -> bool { + self.primitive.type_id() == other.primitive.type_id() + } +} + +/// A set of methods which allows a [`Primitive`] to be rendered. +pub trait Primitive: Debug + Send + Sync + 'static { + /// Processes the [`Primitive`], allowing for GPU buffer allocation. + fn prepare( + &self, + format: wgpu::TextureFormat, + device: &wgpu::Device, + queue: &wgpu::Queue, + target_size: Size<u32>, + scale_factor: f32, + transform: Transformation, + storage: &mut Storage, + ); + + /// Renders the [`Primitive`]. + fn render( + &self, + storage: &Storage, + bounds: Rectangle<u32>, + target: &wgpu::TextureView, + target_size: Size<u32>, + encoder: &mut wgpu::CommandEncoder, + ); +} + +/// A renderer than can draw custom pipeline primitives. +pub trait Renderer: crate::core::Renderer { + /// Draws a custom pipeline primitive. + fn draw_pipeline_primitive( + &mut self, + bounds: Rectangle, + primitive: impl Primitive, + ); +} + +impl<Theme> Renderer for crate::Renderer<Theme> { + fn draw_pipeline_primitive( + &mut self, + bounds: Rectangle, + primitive: impl Primitive, + ) { + self.draw_primitive(super::Primitive::Custom(super::Custom::Pipeline( + Pipeline::new(bounds, primitive), + ))); + } +} + +/// Stores custom, user-provided pipelines. +#[derive(Default, Debug)] +pub struct Storage { + pipelines: HashMap<TypeId, Box<dyn Any>>, +} + +impl Storage { + /// Returns `true` if `Storage` contains a pipeline with type `T`. + pub fn has<T: 'static>(&self) -> bool { + self.pipelines.get(&TypeId::of::<T>()).is_some() + } + + /// Inserts the pipeline `T` in to [`Storage`]. + pub fn store<T: 'static>(&mut self, pipeline: T) { + let _ = self.pipelines.insert(TypeId::of::<T>(), Box::new(pipeline)); + } + + /// Returns a reference to pipeline with type `T` if it exists in [`Storage`]. + pub fn get<T: 'static>(&self) -> Option<&T> { + self.pipelines.get(&TypeId::of::<T>()).map(|pipeline| { + pipeline + .downcast_ref::<T>() + .expect("Pipeline with this type does not exist in Storage.") + }) + } + + /// Returns a mutable reference to pipeline `T` if it exists in [`Storage`]. + pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> { + self.pipelines.get_mut(&TypeId::of::<T>()).map(|pipeline| { + pipeline + .downcast_mut::<T>() + .expect("Pipeline with this type does not exist in Storage.") + }) + } +} |