diff --git a/src/lib.rs b/src/lib.rs index f8544a87..410dea38 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -277,6 +277,22 @@ impl VertexBufferPool { self.next_free_buffer = 0; } + fn get_a_buffer(&mut self, device: &wgpu::Device) -> (u32, VertexBufferHandle) { + if self.next_free_buffer > 0 { + let vb = &mut self.buffers[self.next_free_buffer - 1]; + if vb.vec.len() < vb.capacity { + let draw_start = vb.vec.len(); + let handle = VertexBufferHandle { + index: self.next_free_buffer - 1, + capacity: vb.capacity, + }; + return (draw_start.try_into().unwrap(), handle); + } + } + + (0, self.new_buffer(device)) + } + fn new_buffer(&mut self, device: &wgpu::Device) -> VertexBufferHandle { if self.next_free_buffer >= self.buffers.len() { let max_sprites: usize = 4096; @@ -694,6 +710,7 @@ enum DrawMode { trait DrawModeInstance: Sized { const MODE: DrawMode; + fn get_vertex_buffer<'a>( state: &'a mut State, vb: &VertexBufferHandle, @@ -702,6 +719,7 @@ trait DrawModeInstance: Sized { impl DrawModeInstance for SpriteInstance { const MODE: DrawMode = DrawMode::Sprites; + fn get_vertex_buffer<'a>( state: &'a mut State, vb: &VertexBufferHandle, @@ -712,6 +730,7 @@ impl DrawModeInstance for SpriteInstance { impl DrawModeInstance for CircleInstance { const MODE: DrawMode = DrawMode::Circles; + fn get_vertex_buffer<'a>( state: &'a mut State, vb: &VertexBufferHandle, @@ -921,31 +940,22 @@ 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. + // TODO: Do we need to do this actually? 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), + Some(call) => Some(call.new_at_buffer_tail()), + None => None, }; self.flush(); - self.draw_calls.push(first_call); + match first_call { + Some(fc) => self.draw_calls.push(fc), + None => {} + } self.color = color; self.target = target; } - fn new_instance_buffer(&mut self) -> VertexBufferHandle { - match self.mode { - DrawMode::Sprites => self - .state - .sprite_instance_buffers - .new_buffer(&self.state.device), - DrawMode::Circles => self - .state - .circle_instance_buffers - .new_buffer(&self.state.device), - } - } - fn use_texture(&mut self, texture_id: u32) { match self.draw_calls.last_mut() { Some(call) => match call.texture_id { @@ -965,28 +975,47 @@ impl<'a> FrameBuilder<'a> { } }, None => { - let mut call = DrawCall::new(self.mode, self.new_instance_buffer(), 0); + let (draw_start, buffer) = self.new_instance_buffer(); + let mut call = DrawCall::new(self.mode, buffer, draw_start); call.texture_id = Some(texture_id); self.draw_calls.push(call); } } } - fn get_instance_buffer(&mut self) -> &mut VertexBuffer { - if self.mode != T::MODE { - self.flush(); - self.mode = T::MODE; - } + fn new_instance_buffer(&mut self) -> (u32, VertexBufferHandle) { + match self.mode { + DrawMode::Sprites => self + .state + .sprite_instance_buffers + .get_a_buffer(&self.state.device), + DrawMode::Circles => self + .state + .circle_instance_buffers + .get_a_buffer(&self.state.device), + } + } + + fn get_instance_buffer(&mut self) -> &mut VertexBuffer { + // TODO: Re-work the mode shuffle. Keep the most recent vertex buffer + // around from the + + self.mode = T::MODE; match self.draw_calls.last_mut() { - Some(call) => match call.allocate_capacity(1) { - Some(vb) => return T::get_vertex_buffer(self.state, &vb), - None => {} - }, + Some(call) => { + if call.mode == T::MODE { + match call.allocate_capacity(1) { + Some(vb) => return T::get_vertex_buffer(self.state, &vb), + None => {} + } + } + } None => {} }; - let mut call = DrawCall::new(self.mode, self.new_instance_buffer(), 0); + let (draw_start, buffer) = self.new_instance_buffer(); + let mut call = DrawCall::new(self.mode, buffer, draw_start); let vb = call.allocate_capacity(1).unwrap(); self.draw_calls.push(call); T::get_vertex_buffer(self.state, &vb) @@ -1035,12 +1064,19 @@ impl<'a> FrameBuilder<'a> { depth_stencil_attachment: None, }); - match self.mode { - DrawMode::Sprites => pass.set_pipeline(&self.state.sprite_pipeline), - DrawMode::Circles => pass.set_pipeline(&self.state.circle_pipeline), - } - + let mut last_mode = None; for call in &self.draw_calls { + let need_set_pipeline = match last_mode { + None => true, + Some(m) => call.mode != m, + }; + if need_set_pipeline { + match call.mode { + DrawMode::Sprites => pass.set_pipeline(&self.state.sprite_pipeline), + DrawMode::Circles => pass.set_pipeline(&self.state.circle_pipeline), + } + last_mode = Some(call.mode); + } call.draw(&self.state, &mut pass); } }