diff --git a/all-is-cubes-gpu/src/in_wgpu.rs b/all-is-cubes-gpu/src/in_wgpu.rs index 39b83c60d..502eff49b 100644 --- a/all-is-cubes-gpu/src/in_wgpu.rs +++ b/all-is-cubes-gpu/src/in_wgpu.rs @@ -242,9 +242,9 @@ impl SurfaceRenderer { }; // Render info and postprocessing step. - // TODO: We should record the amount of time this takes, then display that - // next frame. - info.flaws |= self.everything.add_info_text_and_postprocess( + // TODO: We should record the amount of time this takes, then display that next frame. + // TODO(efficiency): combine draw_frame_linear and postprocess into one submission. + let (post_cmd, post_flaws) = self.everything.add_info_text_and_postprocess( &self.queue, &output.texture.create_view(&TextureViewDescriptor { format: Some(surface_view_format(self.everything.config.format)), @@ -252,6 +252,8 @@ impl SurfaceRenderer { }), &info_text_fn(&info), ); + info.flaws |= post_flaws; + self.queue.submit([post_cmd]); output.present(); Ok(info) } @@ -840,6 +842,8 @@ impl EverythingRenderer { // let postprocess_to_submit_time = Instant::now(); + // TODO(efficiency): allow this submit to happen externally and be combined with others + // (postprocessing, in particular). queue.submit(std::iter::once(encoder.finish())); self.staging_belt.recall(); @@ -864,7 +868,7 @@ impl EverythingRenderer { queue: &wgpu::Queue, output: &wgpu::TextureView, mut text: &str, - ) -> Flaws { + ) -> (wgpu::CommandBuffer, Flaws) { // Apply info text option if !self.cameras.cameras().world.options().debug_info_text { text = ""; @@ -880,12 +884,12 @@ impl EverythingRenderer { info_text_texture.upload(queue); } - let flaws = postprocess::postprocess(self, queue, output); + let (postprocess_cmd, flaws) = postprocess::postprocess(self, output); #[cfg(feature = "rerun")] self.rerun_image.finish_frame(); - flaws + (postprocess_cmd, flaws) } /// Activate logging performance information to a Rerun stream. diff --git a/all-is-cubes-gpu/src/in_wgpu/block_texture.rs b/all-is-cubes-gpu/src/in_wgpu/block_texture.rs index 9ba38a93f..8f6826697 100644 --- a/all-is-cubes-gpu/src/in_wgpu/block_texture.rs +++ b/all-is-cubes-gpu/src/in_wgpu/block_texture.rs @@ -413,6 +413,9 @@ impl AllocatorBacking { device: &wgpu::Device, queue: &wgpu::Queue, ) -> (Group>>, BlockTextureInfo) { + // TODO: Consider replacing all the queued texture writes and copies with `StagingBelt`. + // Will need to teach `StagingBelt` about copying to textures. + let mut backing_lock_guard = backing_mutex.lock().unwrap(); let backing = &mut *backing_lock_guard; @@ -486,6 +489,8 @@ impl AllocatorBacking { copy(&mut encoder, oe, ne); } + // TODO(efficiency): Eliminate this separated submit, without breaking things + // by reordering the copy_texture_to_texture() after the following write_texture()s. queue.submit([encoder.finish()]); } diff --git a/all-is-cubes-gpu/src/in_wgpu/headless.rs b/all-is-cubes-gpu/src/in_wgpu/headless.rs index 1516ae2f1..551fbb2ae 100644 --- a/all-is-cubes-gpu/src/in_wgpu/headless.rs +++ b/all-is-cubes-gpu/src/in_wgpu/headless.rs @@ -217,13 +217,14 @@ impl RendererImpl { } let draw_info = self.everything.draw_frame_linear(&self.queue); - let post_flaws = self.everything.add_info_text_and_postprocess( + let (post_cmd, post_flaws) = self.everything.add_info_text_and_postprocess( &self.queue, &self .color_texture .create_view(&wgpu::TextureViewDescriptor::default()), info_text, ); + self.queue.submit([post_cmd]); let image = init::get_image_from_gpu( &self.device, &self.queue, diff --git a/all-is-cubes-gpu/src/in_wgpu/light_texture.rs b/all-is-cubes-gpu/src/in_wgpu/light_texture.rs index 43e84fb8d..65f351ad8 100644 --- a/all-is-cubes-gpu/src/in_wgpu/light_texture.rs +++ b/all-is-cubes-gpu/src/in_wgpu/light_texture.rs @@ -484,10 +484,14 @@ impl LightTexture { total_count += 1; } - // TODO: use `StagingBelt` to write buffer instead. + // TODO(efficiency): use `StagingBelt` to write buffer instead. // To do this optimally, `StagingBelt` will need to be modified to allow // us accessing its buffers to issue a `copy_buffer_to_texture` instead of // it issuing a `copy_buffer_to_buffer`. + // + // It should be worth it, though, as I am informed that `submit()`ing repeatedly + // is costly, and by avoiding `write_buffer()` we can just use a single command + // buffer. queue.write_buffer( &self.copy_buffer, 0, diff --git a/all-is-cubes-gpu/src/in_wgpu/postprocess.rs b/all-is-cubes-gpu/src/in_wgpu/postprocess.rs index 02e7f9fce..11318f2f5 100644 --- a/all-is-cubes-gpu/src/in_wgpu/postprocess.rs +++ b/all-is-cubes-gpu/src/in_wgpu/postprocess.rs @@ -162,9 +162,8 @@ impl PostprocessUniforms { pub(crate) fn postprocess( // TODO: instead of accepting `EverythingRenderer`, pass smaller (but not too numerous) things ev: &mut super::EverythingRenderer, - queue: &wgpu::Queue, output: &wgpu::TextureView, -) -> Flaws { +) -> (wgpu::CommandBuffer, Flaws) { let mut encoder = ev .device .create_command_encoder(&wgpu::CommandEncoderDescriptor { @@ -173,7 +172,7 @@ pub(crate) fn postprocess( let Some(postprocess_render_pipeline) = ev.postprocess_render_pipeline.get() else { // This shouldn't happen, but if it does, don't panic. - return Flaws::UNFINISHED; + return (encoder.finish(), Flaws::UNFINISHED); }; // Render pass @@ -239,7 +238,5 @@ pub(crate) fn postprocess( render_pass.draw(0..3, 0..1); } - queue.submit(std::iter::once(encoder.finish())); - - Flaws::empty() + (encoder.finish(), Flaws::empty()) }