diff --git a/src/drawable_pipeline.rs b/src/drawable_pipeline.rs index ee298f6..d1f9758 100644 --- a/src/drawable_pipeline.rs +++ b/src/drawable_pipeline.rs @@ -16,6 +16,25 @@ pub(crate) struct DrawablePipeline { render_mask_pipeline: Option, } +pub(crate) struct DrawableContext<'a> { + pub queue: &'a Queue, + pub universal_bind_group: &'a BindGroup, +} + +pub(crate) struct RenderContentParams<'a> { + pub constants: ShaderConstants, + pub resources: &'a Resources, + pub clip: Option>, + pub batch: &'a PrimitiveBatch, +} + +pub(crate) struct RenderDrawableParams<'a> { + pub constants: ShaderConstants, + pub resources: &'a Resources, + pub clip: Option>, + pub batch: &'a PrimitiveBatch, +} + impl DrawablePipeline { pub fn new(Renderer { device, .. }: &Renderer, drawable: T) -> Self { let drawable = Box::new(drawable); @@ -184,51 +203,55 @@ impl DrawablePipeline { pub fn draw_content<'b, 'a: 'b>( &'a mut self, - queue: &Queue, + draw_context: &DrawableContext, render_pass: &mut RenderPass<'b>, - constants: ShaderConstants, - universal_bind_group: &'a BindGroup, - resources: &Resources, - clip: Option>, - batch: &PrimitiveBatch, + render_params: &RenderContentParams<'a>, ) { render_pass.set_pipeline(self.render_content_pipeline.as_ref().unwrap()); render_pass.set_push_constants( ShaderStages::VERTEX_FRAGMENT, 0, - bytemuck::cast_slice(&[constants]), + bytemuck::cast_slice(&[render_params.constants]), ); render_pass.set_bind_group(0, &self.bind_group, &[]); - render_pass.set_bind_group(1, universal_bind_group, &[]); + render_pass.set_bind_group(1, draw_context.universal_bind_group, &[]); - self.drawable - .draw(queue, render_pass, constants, resources, clip, batch); + self.drawable.draw( + draw_context.queue, + render_pass, + render_params.constants, + render_params.resources, + render_params.clip, + render_params.batch, + ); } pub fn draw_mask<'b, 'a: 'b>( &'a mut self, - queue: &Queue, + draw_context: &DrawableContext, render_pass: &mut RenderPass<'b>, - constants: ShaderConstants, - universal_bind_group: &'a BindGroup, - resources: &Resources, - clip: Option>, - batch: &PrimitiveBatch, + render_params: &RenderDrawableParams<'a>, ) { render_pass.set_pipeline(self.render_mask_pipeline.as_ref().unwrap()); render_pass.set_push_constants( ShaderStages::VERTEX_FRAGMENT, 0, - bytemuck::cast_slice(&[constants]), + bytemuck::cast_slice(&[render_params.constants]), ); render_pass.set_bind_group(0, &self.bind_group, &[]); - render_pass.set_bind_group(1, universal_bind_group, &[]); + render_pass.set_bind_group(1, draw_context.universal_bind_group, &[]); - self.drawable - .draw(queue, render_pass, constants, resources, clip, batch); + self.drawable.draw( + draw_context.queue, + render_pass, + render_params.constants, + render_params.resources, + render_params.clip, + render_params.batch, + ); } } diff --git a/src/renderer.rs b/src/renderer.rs index 6b62ce3..8d63b8b 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -9,12 +9,21 @@ use wgpu_profiler::{GpuProfiler, GpuProfilerSettings}; use crate::{ default_drawables::{BlurState, GlyphState, PathState, QuadState, SpriteState}, drawable::Drawable, - drawable_pipeline::DrawablePipeline, + drawable_pipeline::{ + DrawableContext, DrawablePipeline, RenderContentParams, RenderDrawableParams, + }, drawable_reference::ATLAS_SIZE, shader::{ShaderConstants, ShaderLoader}, LayerContents, Resources, Scene, }; +pub struct DrawContext<'a> { + pub encoder: &'a mut CommandEncoder, + pub first: &'a mut bool, + pub frame: &'a Texture, + pub frame_view: &'a TextureView, +} + pub struct Renderer { pub adapter: Adapter, pub device: Device, @@ -332,12 +341,16 @@ impl Renderer { &scene.resources, ); + let draw_context = DrawContext { + encoder: &mut encoder, + first: &mut first, + frame, + frame_view: &frame_view, + }; + self.draw_content( &layer.contents, - &mut encoder, - &mut first, - frame, - &frame_view, + draw_context, layer.clip, constants, &scene.resources, @@ -427,15 +440,19 @@ impl Renderer { drawable_scope.set_scissor_rect(x, y, w, h); } - drawable.draw_mask( - &self.queue, - &mut drawable_scope, + let draw_context = DrawableContext { + queue: &self.queue, + universal_bind_group: &self.universal_mask_bind_group, + }; + + let render_params = RenderDrawableParams { constants, - &self.universal_mask_bind_group, resources, clip, batch, - ); + }; + + drawable.draw_mask(&draw_context, &mut drawable_scope, &render_params); } } } else { @@ -486,17 +503,16 @@ impl Renderer { pub fn draw_content( &mut self, contents: &LayerContents, - encoder: &mut CommandEncoder, - first: &mut bool, - frame: &Texture, - frame_view: &TextureView, + context: DrawContext, clip: Option>, constants: ShaderConstants, resources: &Resources, ) { - let mut content_scope = self.profiler.scope("content", encoder, &self.device); + let mut content_scope = self + .profiler + .scope("content", context.encoder, &self.device); - if *first { + if *context.first { content_scope.scoped_render_pass( "Clear Offscreen Texture", &self.device, @@ -518,31 +534,29 @@ impl Renderer { } else { 'offscreen_copy: for batch in contents.primitives.iter() { for drawable in self.drawables.iter() { - if drawable.has_work(batch) { - if drawable.requires_offscreen_copy() { - let mut copy_scope = - content_scope.scope("Copy Frame to Offscreen", &self.device); - copy_scope.copy_texture_to_texture( - ImageCopyTexture { - texture: frame, - mip_level: 0, - origin: Origin3d::ZERO, - aspect: Default::default(), - }, - ImageCopyTexture { - texture: &self.offscreen_texture.texture, - mip_level: 0, - origin: Origin3d::ZERO, - aspect: Default::default(), - }, - Extent3d { - width: self.width, - height: self.height, - depth_or_array_layers: 1, - }, - ); - break 'offscreen_copy; - } + if drawable.has_work(batch) && drawable.requires_offscreen_copy() { + let mut copy_scope = + content_scope.scope("Copy Frame to Offscreen", &self.device); + copy_scope.copy_texture_to_texture( + ImageCopyTexture { + texture: context.frame, + mip_level: 0, + origin: Origin3d::ZERO, + aspect: Default::default(), + }, + ImageCopyTexture { + texture: &self.offscreen_texture.texture, + mip_level: 0, + origin: Origin3d::ZERO, + aspect: Default::default(), + }, + Extent3d { + width: self.width, + height: self.height, + depth_or_array_layers: 1, + }, + ); + break 'offscreen_copy; } } } @@ -555,7 +569,7 @@ impl Renderer { } // The first drawable should clear the output texture - let attachment_op = if *first { + let attachment_op = if *context.first { Operations:: { load: LoadOp::<_>::Clear(Color::WHITE), store: StoreOp::Store, @@ -573,7 +587,7 @@ impl Renderer { RenderPassDescriptor { label: Some("Render Pass"), color_attachments: &[Some(RenderPassColorAttachment { - view: frame_view, + view: context.frame_view, resolve_target: None, ops: attachment_op, })], @@ -596,17 +610,21 @@ impl Renderer { drawable_scope.set_scissor_rect(x, y, w, h); } - drawable.draw_content( - &self.queue, - &mut drawable_scope, + let draw_context = DrawableContext { + queue: &self.queue, + universal_bind_group: &self.universal_content_bind_group, + }; + + let render_params = RenderContentParams { constants, - &self.universal_content_bind_group, resources, clip, batch, - ); + }; + + drawable.draw_content(&draw_context, &mut drawable_scope, &render_params); - *first = false; + *context.first = false; } } } diff --git a/src/scene/layer.rs b/src/scene/layer.rs index df500b0..e993eba 100644 --- a/src/scene/layer.rs +++ b/src/scene/layer.rs @@ -216,7 +216,7 @@ impl Layer { } } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, Default)] pub struct LayerContents { #[serde(default)] #[serde(skip_serializing_if = "Vec::is_empty")] @@ -324,14 +324,6 @@ impl LayerContents { } } -impl Default for LayerContents { - fn default() -> Self { - Self { - primitives: Vec::new(), - } - } -} - #[derive(Clone, Debug)] pub enum PrimitiveBatch { Mutable(MutablePrimitiveBatch),