From 6e0883e9b604c5e44cad12049f705df55b8be977 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Sat, 23 May 2020 15:43:55 -0700 Subject: [PATCH] Move pipeline name and bind groups to DrawCommand --- src/application.rs | 35 ++++++++++++----------------------- src/draw_command.rs | 6 +++++- src/gui_node.rs | 10 ++++++++-- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/application.rs b/src/application.rs index 42ecdd9f..fdfaedd4 100644 --- a/src/application.rs +++ b/src/application.rs @@ -138,19 +138,12 @@ impl Application { let mut command_encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("Render Encoder") }); // Build an array of draw commands - let gui_node = self.gui_root.borrow_mut(); - let mut nodes = vec![gui_node]; // TODO: Generate the DrawCommands as a list by recursively traversing the gui node tree - - let device = &mut self.device; - - // let commands: Vec = nodes.map(|mut node| node.build_draw_command(dev)).collect(); + let mut nodes = vec![self.gui_root.borrow_mut()]; // TODO: Generate the DrawCommands as a list by recursively traversing the gui node tree let mut commands = Vec::::with_capacity(nodes.len()); - let mut bind_groups = Vec::>::with_capacity(nodes.len()); for i in 0..nodes.len() { - let new_pipeline = self.pipeline_cache.get("gui_rect").unwrap(); - - commands.push(nodes[i].build_draw_command(device)); - bind_groups.push(nodes[i].build_bind_groups(device, &mut self.queue, new_pipeline, &mut self.texture_cache)); + let pipeline_name = nodes[i].get_pipeline_name(); + let pipeline = self.pipeline_cache.get(&pipeline_name[..]).unwrap(); + commands.push(nodes[i].build_draw_command(&mut self.device, &mut self.queue, pipeline, &mut self.texture_cache)); } // Recording of commands while in "rendering mode" that go into a command buffer @@ -167,28 +160,24 @@ impl Application { depth_stencil_attachment: None, }); - // Prepare a variable to cache the pipeline name - let mut bound_pipeline = self.pipeline_cache.get("gui_rect").unwrap(); //nodes[0].get_pipeline(&self.pipeline_cache); - render_pass.set_pipeline(&bound_pipeline.render_pipeline); + // Prepare a variable to reuse the pipeline based on its name + let mut pipeline_name = String::new(); // Turn the queue of pipelines each into a command buffer and submit it to the render queue - for i in 0..nodes.len() { - // let command = commands[i]; + for i in 0..commands.len() { // If the previously set pipeline can't be reused, send the GPU the new pipeline to draw with - let new_pipeline = self.pipeline_cache.get("gui_rect").unwrap(); //node.get_pipeline(&self.pipeline_cache); - if bound_pipeline.render_pipeline != new_pipeline.render_pipeline { - render_pass.set_pipeline(&new_pipeline.render_pipeline); - bound_pipeline = new_pipeline; + if pipeline_name != commands[i].pipeline_name { + let pipeline = self.pipeline_cache.get(&commands[i].pipeline_name[..]).unwrap(); + render_pass.set_pipeline(&pipeline.render_pipeline); + pipeline_name = commands[i].pipeline_name.clone(); } // Send the GPU the vertices and triangle indices render_pass.set_vertex_buffer(0, &commands[i].vertex_buffer, 0, 0); render_pass.set_index_buffer(&commands[i].index_buffer, 0, 0); - // let bind_groups = nodes[i].build_bind_groups(&self.device, &mut self.queue, new_pipeline, &mut self.texture_cache); - // Send the GPU the bind group resources - for (index, bind_group) in bind_groups[i].iter().enumerate() { + for (index, bind_group) in commands[i].bind_groups.iter().enumerate() { render_pass.set_bind_group(index as u32, bind_group, &[]); } diff --git a/src/draw_command.rs b/src/draw_command.rs index 320fef13..318f0781 100644 --- a/src/draw_command.rs +++ b/src/draw_command.rs @@ -1,18 +1,22 @@ // use crate::bind_group_resource::BindGroupResource; pub struct DrawCommand { + pub pipeline_name: String, + pub bind_groups: Vec, pub vertex_buffer: wgpu::Buffer, pub index_buffer: wgpu::Buffer, pub index_count: u32, } impl DrawCommand { - pub fn new(device: &wgpu::Device, vertices: &[[f32; 2]], indices: &[u16]) -> Self { + pub fn new(device: &wgpu::Device, pipeline_name: String, bind_groups: Vec, vertices: &[[f32; 2]], indices: &[u16]) -> Self { let vertex_buffer = device.create_buffer_with_data(bytemuck::cast_slice(vertices), wgpu::BufferUsage::VERTEX); let index_buffer = device.create_buffer_with_data(bytemuck::cast_slice(indices), wgpu::BufferUsage::INDEX); let index_count = indices.len() as u32; Self { + pipeline_name, + bind_groups, vertex_buffer, index_buffer, index_count, diff --git a/src/gui_node.rs b/src/gui_node.rs index 9c77556e..5d25b2f7 100644 --- a/src/gui_node.rs +++ b/src/gui_node.rs @@ -20,7 +20,11 @@ impl GuiNode { // pipeline_cache.get("gui_rect").unwrap() // } - pub fn build_draw_command(&mut self, device: &wgpu::Device) -> DrawCommand { + pub fn get_pipeline_name(&self) -> String { + String::from("gui_rect") + } + + pub fn build_draw_command(&mut self, device: &wgpu::Device, queue: &mut wgpu::Queue, pipeline: &Pipeline, texture_cache: &mut ResourceCache) -> DrawCommand { const VERTICES: &[[f32; 2]] = &[ [-0.5, 0.5], [0.5, 0.5], @@ -31,9 +35,11 @@ impl GuiNode { 0, 1, 2, 0, 2, 3, ]; + + let bind_groups = self.build_bind_groups(device, queue, pipeline, texture_cache); // Create a draw command with the vertex data then push it to the GPU command queue - DrawCommand::new(device, VERTICES, INDICES) + DrawCommand::new(device, self.get_pipeline_name(), bind_groups, VERTICES, INDICES) } pub fn build_bind_groups(&mut self, device: &wgpu::Device, queue: &mut wgpu::Queue, pipeline: &Pipeline, texture_cache: &mut ResourceCache) -> Vec {