From df4914388513417adc4769dc00e499e5c9c82604 Mon Sep 17 00:00:00 2001 From: John Doty Date: Sun, 27 Aug 2023 09:28:14 -0700 Subject: [PATCH] [oden] Some perhaps unadvised factoring Traits for fun and profit. I was nervous about the amount of magic "you have to get this right" coupling between runtime structures (the draw mode) and types (the various instance types) and I didn't want to get them wrong. So now some things are more generic than they were before, and maybe that's good? Who can say in the end. --- src/lib.rs | 78 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 6c65e39c..f8544a87 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -692,6 +692,34 @@ enum DrawMode { Circles, } +trait DrawModeInstance: Sized { + const MODE: DrawMode; + fn get_vertex_buffer<'a>( + state: &'a mut State, + vb: &VertexBufferHandle, + ) -> &'a mut VertexBuffer; +} + +impl DrawModeInstance for SpriteInstance { + const MODE: DrawMode = DrawMode::Sprites; + fn get_vertex_buffer<'a>( + state: &'a mut State, + vb: &VertexBufferHandle, + ) -> &'a mut VertexBuffer { + state.sprite_instance_buffers.get_mut(&vb) + } +} + +impl DrawModeInstance for CircleInstance { + const MODE: DrawMode = DrawMode::Circles; + fn get_vertex_buffer<'a>( + state: &'a mut State, + vb: &VertexBufferHandle, + ) -> &'a mut VertexBuffer { + state.circle_instance_buffers.get_mut(&vb) + } +} + #[derive(Debug)] struct DrawCall { mode: DrawMode, @@ -891,7 +919,16 @@ impl<'a> FrameBuilder<'a> { } fn start_pass(&mut self, color: Option<[f64; 4]>, target: Rc) { + // NOTE: We're not changing drawing modes here which means we can preserve the + // buffer tail if we want to. + let first_call = match self.draw_calls.last() { + Some(call) => call.new_at_buffer_tail(), + None => DrawCall::new(self.mode, self.new_instance_buffer(), 0), + }; + self.flush(); + + self.draw_calls.push(first_call); self.color = color; self.target = target; } @@ -935,19 +972,15 @@ impl<'a> FrameBuilder<'a> { } } - fn switch_mode(&mut self, mode: DrawMode) { - if self.mode != mode { + fn get_instance_buffer(&mut self) -> &mut VertexBuffer { + if self.mode != T::MODE { self.flush(); - self.draw_calls.clear(); - self.mode = mode; + self.mode = T::MODE; } - } - fn get_sprite_instance_buffer(&mut self) -> &mut VertexBuffer { - self.switch_mode(DrawMode::Sprites); match self.draw_calls.last_mut() { Some(call) => match call.allocate_capacity(1) { - Some(vb) => return self.state.sprite_instance_buffers.get_mut(&vb), + Some(vb) => return T::get_vertex_buffer(self.state, &vb), None => {} }, None => {} @@ -956,34 +989,19 @@ impl<'a> FrameBuilder<'a> { let mut call = DrawCall::new(self.mode, self.new_instance_buffer(), 0); let vb = call.allocate_capacity(1).unwrap(); self.draw_calls.push(call); - self.state.sprite_instance_buffers.get_mut(&vb) + T::get_vertex_buffer(self.state, &vb) } fn push_sprite(&mut self, si: SpriteInstance) { - let vertex_buffer = self.get_sprite_instance_buffer(); + let vertex_buffer = self.get_instance_buffer(); vertex_buffer.vec.push(si); } - fn get_circle_instance_buffer(&mut self) -> &mut VertexBuffer { - self.switch_mode(DrawMode::Circles); - match self.draw_calls.last_mut() { - Some(call) => match call.allocate_capacity(1) { - Some(vb) => return self.state.circle_instance_buffers.get_mut(&vb), - None => {} - }, - None => {} - }; - - let mut call = DrawCall::new(self.mode, self.new_instance_buffer(), 0); - let vb = call.allocate_capacity(1).unwrap(); - self.draw_calls.push(call); - self.state.circle_instance_buffers.get_mut(&vb) - } - fn push_circle(&mut self, cc: script::graphics::CircleCommand) { let stroke_color = self.stroke_color.clone(); let fill_color = self.fill_color.clone(); - let vertex_buffer = self.get_circle_instance_buffer(); + + let vertex_buffer = self.get_instance_buffer(); vertex_buffer.vec.push(CircleInstance { center: cc.center, radius: cc.radius, @@ -994,11 +1012,6 @@ impl<'a> FrameBuilder<'a> { } fn flush(&mut self) { - let first_call = match self.draw_calls.last() { - Some(call) => call.new_at_buffer_tail(), - None => DrawCall::new(self.mode, self.new_instance_buffer(), 0), - }; - if self.draw_calls.len() > 0 { let mut pass = self.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Render Pass"), @@ -1034,7 +1047,6 @@ impl<'a> FrameBuilder<'a> { self.color = None; self.draw_calls.clear(); - self.draw_calls.push(first_call); } }