From e6ebe07765774a95213acbdd7b54e53f5614cf92 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 2 Nov 2023 20:50:45 -0700 Subject: [PATCH 1/3] Clean up scene included modules --- examples/scene/main.rs | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/examples/scene/main.rs b/examples/scene/main.rs index 374b9bfd..e5394718 100644 --- a/examples/scene/main.rs +++ b/examples/scene/main.rs @@ -2,7 +2,6 @@ #![cfg(not(target_arch = "wasm32"))] use blade_graphics as gpu; -use blade_render::{AssetHub, Camera, RenderConfig, Renderer}; use std::{ collections::VecDeque, fmt, fs, @@ -41,8 +40,8 @@ struct TransformComponents { rotation: glam::Quat, translation: glam::Vec3, } -impl From for TransformComponents { - fn from(bm: blade_graphics::Transform) -> Self { +impl From for TransformComponents { + fn from(bm: gpu::Transform) -> Self { let transposed = glam::Mat4 { x_axis: bm.x.into(), y_axis: bm.y.into(), @@ -58,14 +57,14 @@ impl From for TransformComponents { } } impl TransformComponents { - fn to_blade(&self) -> blade_graphics::Transform { + fn to_blade(&self) -> gpu::Transform { let m = glam::Mat4::from_scale_rotation_translation( self.scale, self.rotation, self.translation, ) .transpose(); - blade_graphics::Transform { + gpu::Transform { x: m.x_axis.into(), y: m.y_axis.into(), z: m.z_axis.into(), @@ -94,12 +93,7 @@ struct ConfigCamera { } fn default_transform() -> mint::RowMatrix3x4 { - [ - [1.0, 0.0, 0.0, 0.0], - [0.0, 1.0, 0.0, 0.0], - [0.0, 0.0, 1.0, 0.0], - ] - .into() + gpu::IDENTITY_TRANSFORM } fn default_luminocity() -> f32 { 1.0 @@ -128,11 +122,11 @@ struct Example { prev_temp_buffers: Vec, prev_acceleration_structures: Vec, prev_sync_point: Option, - renderer: Renderer, + renderer: blade_render::Renderer, scene_load_task: Option, gui_painter: blade_egui::GuiPainter, command_encoder: Option, - asset_hub: AssetHub, + asset_hub: blade_render::AssetHub, context: Arc, environment_map: Option>, objects: Vec, @@ -160,11 +154,9 @@ struct Example { } impl Example { - fn make_surface_config( - physical_size: winit::dpi::PhysicalSize, - ) -> blade_graphics::SurfaceConfig { - blade_graphics::SurfaceConfig { - size: blade_graphics::Extent { + fn make_surface_config(physical_size: winit::dpi::PhysicalSize) -> gpu::SurfaceConfig { + gpu::SurfaceConfig { + size: gpu::Extent { width: physical_size.width, height: physical_size.height, depth: 1, @@ -200,7 +192,7 @@ impl Example { .map(|i| choir.add_worker(&format!("Worker-{}", i))) .collect(); - let asset_hub = AssetHub::new(Path::new("asset-cache"), &choir, &context); + let asset_hub = blade_render::AssetHub::new(Path::new("asset-cache"), &choir, &context); let (shaders, shader_task) = blade_render::Shaders::load("blade-render/code/".as_ref(), &asset_hub); @@ -211,12 +203,12 @@ impl Example { buffer_count: 2, }); command_encoder.start(); - let render_config = RenderConfig { + let render_config = blade_render::RenderConfig { screen_size, surface_format, max_debug_lines: 1000, }; - let renderer = Renderer::new( + let renderer = blade_render::Renderer::new( &mut command_encoder, &context, shaders, @@ -321,7 +313,7 @@ impl Example { ron::de::from_bytes(&fs::read(scene_path).expect("Unable to open the scene file")) .expect("Unable to parse the scene file"); - self.camera = Camera { + self.camera = blade_render::Camera { pos: config_scene.camera.position, rot: glam::Quat::from(config_scene.camera.orientation) .normalize() @@ -339,7 +331,7 @@ impl Example { if !config_scene.environment_map.is_empty() { let meta = blade_render::texture::Meta { - format: blade_graphics::TextureFormat::Rgba32Float, + format: gpu::TextureFormat::Rgba32Float, generate_mips: false, y_flip: false, }; @@ -997,7 +989,7 @@ impl Example { ); self.scene_load_task = Some(model_task.clone()); self.objects.push(blade_render::Object { - transform: blade_graphics::IDENTITY_TRANSFORM, + transform: gpu::IDENTITY_TRANSFORM, model, }); self.object_extras.push(ObjectExtra { From 51eb1e910fbc116b4efa5fe8751824a3b4e37390 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 2 Nov 2023 22:55:59 -0700 Subject: [PATCH 2/3] Clean up shader loading --- blade-egui/src/lib.rs | 10 ++++---- .../{env-preproc.wgsl => env-prepare.wgsl} | 0 blade-render/src/render/env_map.rs | 25 +++++++++++-------- blade-render/src/render/mod.rs | 11 +++++--- examples/init/main.rs | 23 +++++++++++++---- examples/particle/main.rs | 23 +++++++++-------- examples/ray-query/main.rs | 1 + examples/scene/main.rs | 2 +- 8 files changed, 60 insertions(+), 35 deletions(-) rename blade-render/code/{env-preproc.wgsl => env-prepare.wgsl} (100%) diff --git a/blade-egui/src/lib.rs b/blade-egui/src/lib.rs index e7c7cbc5..bc821437 100644 --- a/blade-egui/src/lib.rs +++ b/blade-egui/src/lib.rs @@ -15,10 +15,12 @@ mod belt; +const SHADER_SOURCE: &'static str = include_str!("../shader.wgsl"); + use belt::{BeltDescriptor, BufferBelt}; use std::{ collections::hash_map::{Entry, HashMap}, - fs, mem, ptr, + mem, ptr, }; #[repr(C)] @@ -118,14 +120,12 @@ impl GuiPainter { /// and this attachment format must be The `output_format`. #[profiling::function] pub fn new( - context: &blade_graphics::Context, output_format: blade_graphics::TextureFormat, + context: &blade_graphics::Context, ) -> Self { - let shader_source = fs::read_to_string("blade-egui/shader.wgsl").unwrap(); let shader = context.create_shader(blade_graphics::ShaderDesc { - source: &shader_source, + source: SHADER_SOURCE, }); - let globals_layout = ::layout(); let locals_layout = ::layout(); let pipeline = context.create_render_pipeline(blade_graphics::RenderPipelineDesc { diff --git a/blade-render/code/env-preproc.wgsl b/blade-render/code/env-prepare.wgsl similarity index 100% rename from blade-render/code/env-preproc.wgsl rename to blade-render/code/env-prepare.wgsl diff --git a/blade-render/src/render/env_map.rs b/blade-render/src/render/env_map.rs index 43f6fe49..4e1256d3 100644 --- a/blade-render/src/render/env_map.rs +++ b/blade-render/src/render/env_map.rs @@ -1,4 +1,4 @@ -use std::{fs, num::NonZeroU32}; +use std::num::NonZeroU32; use crate::DummyResources; @@ -21,21 +21,20 @@ pub struct EnvironmentMap { pub weight_texture: blade_graphics::Texture, pub weight_view: blade_graphics::TextureView, pub weight_mips: Vec, - pub preproc_pipeline: blade_graphics::ComputePipeline, + pub prepare_pipeline: blade_graphics::ComputePipeline, } impl EnvironmentMap { pub fn init_pipeline( + shader: &blade_graphics::Shader, gpu: &blade_graphics::Context, ) -> Result { - let source = fs::read_to_string("blade-render/code/env-preproc.wgsl").unwrap(); - let shader = gpu.try_create_shader(blade_graphics::ShaderDesc { source: &source })?; let layout = ::layout(); shader.check_struct_size::(); Ok( gpu.create_compute_pipeline(blade_graphics::ComputePipelineDesc { - name: "env-preproc", + name: "env-prepare", data_layouts: &[&layout], compute: shader.at("downsample"), }), @@ -44,7 +43,7 @@ impl EnvironmentMap { pub fn with_pipeline( dummy: &DummyResources, - preproc_pipeline: blade_graphics::ComputePipeline, + prepare_pipeline: blade_graphics::ComputePipeline, ) -> Self { Self { main_view: dummy.white_view, @@ -52,12 +51,16 @@ impl EnvironmentMap { weight_texture: blade_graphics::Texture::default(), weight_view: dummy.red_view, weight_mips: Vec::new(), - preproc_pipeline, + prepare_pipeline, } } - pub fn new(dummy: &DummyResources, gpu: &blade_graphics::Context) -> Self { - Self::with_pipeline(dummy, Self::init_pipeline(gpu).unwrap()) + pub fn new( + shader: &blade_graphics::Shader, + dummy: &DummyResources, + gpu: &blade_graphics::Context, + ) -> Self { + Self::with_pipeline(dummy, Self::init_pipeline(shader, gpu).unwrap()) } fn weight_size(&self) -> blade_graphics::Extent { @@ -134,10 +137,10 @@ impl EnvironmentMap { encoder.init_texture(self.weight_texture); for target_level in 0..mip_level_count { let groups = self - .preproc_pipeline + .prepare_pipeline .get_dispatch_for(weight_extent.at_mip_level(target_level)); let mut compute = encoder.compute(); - let mut pass = compute.with(&self.preproc_pipeline); + let mut pass = compute.with(&self.prepare_pipeline); pass.bind( 0, &EnvPreprocData { diff --git a/blade-render/src/render/mod.rs b/blade-render/src/render/mod.rs index c9b13671..45cd5793 100644 --- a/blade-render/src/render/mod.rs +++ b/blade-render/src/render/mod.rs @@ -550,6 +550,7 @@ struct HitEntry { #[derive(Clone, PartialEq)] pub struct Shaders { + env_prepare: blade_asset::Handle, fill_gbuf: blade_asset::Handle, ray_trace: blade_asset::Handle, blur: blade_asset::Handle, @@ -562,6 +563,7 @@ impl Shaders { pub fn load(path: &Path, asset_hub: &crate::AssetHub) -> (Self, choir::RunningTask) { let mut ctx = asset_hub.open_context(path, "shader finish"); let shaders = Self { + env_prepare: ctx.load_shader("env-prepare.wgsl"), fill_gbuf: ctx.load_shader("fill-gbuf.wgsl"), ray_trace: ctx.load_shader("ray-trace.wgsl"), blur: ctx.load_shader("blur.wgsl"), @@ -581,7 +583,7 @@ struct ShaderPipelines { post_proc: blade_graphics::RenderPipeline, debug_draw: blade_graphics::RenderPipeline, debug_blit: blade_graphics::RenderPipeline, - env_preproc: blade_graphics::ComputePipeline, + env_prepare: blade_graphics::ComputePipeline, debug_line_size: u32, debug_buffer_size: u32, reservoir_size: u32, @@ -735,7 +737,10 @@ impl ShaderPipelines { config.surface_format, gpu, ), - env_preproc: EnvironmentMap::init_pipeline(gpu)?, + env_prepare: EnvironmentMap::init_pipeline( + shader_man[shaders.env_prepare].raw.as_ref().unwrap(), + gpu, + )?, debug_line_size: sh_main.get_struct_size("DebugLine"), debug_buffer_size: sh_main.get_struct_size("DebugBuffer"), reservoir_size: sh_main.get_struct_size("StoredReservoir"), @@ -866,7 +871,7 @@ impl Renderer { atrous_pipeline: sp.atrous, }, acceleration_structure: blade_graphics::AccelerationStructure::default(), - env_map: EnvironmentMap::with_pipeline(&dummy, sp.env_preproc), + env_map: EnvironmentMap::with_pipeline(&dummy, sp.env_prepare), dummy, hit_buffer: blade_graphics::Buffer::default(), vertex_buffers: blade_graphics::BufferArray::new(), diff --git a/examples/init/main.rs b/examples/init/main.rs index 1325113d..0ddec649 100644 --- a/examples/init/main.rs +++ b/examples/init/main.rs @@ -156,10 +156,16 @@ fn main() { println!("Populating the scene"); let mut load_finish = choir.spawn("load finish").init_dummy(); - let (shader_handle, shader_task) = asset_hub + let (shader_main_handle, shader_main_task) = asset_hub .shaders .load("examples/init/env-sample.wgsl", blade_render::shader::Meta); - load_finish.depend_on(shader_task); + load_finish.depend_on(shader_main_task); + let (shader_init_handle, shader_init_task) = asset_hub.shaders.load( + "blade-render/code/env-prepare.wgsl", + blade_render::shader::Meta, + ); + load_finish.depend_on(shader_init_task); + for arg in env::args().skip(1) { if arg.ends_with(".exr") { println!("\tenvironment map = {}", arg); @@ -198,7 +204,11 @@ fn main() { let mut temp_buffers = Vec::new(); asset_hub.flush(&mut command_encoder, &mut temp_buffers); - let mut env_map = blade_render::EnvironmentMap::new(&dummy, &context); + let mut env_map = blade_render::EnvironmentMap::new( + asset_hub.shaders[shader_init_handle].raw.as_ref().unwrap(), + &dummy, + &context, + ); let env_size = match environment_map { Some(handle) => { let texture = &asset_hub.textures[handle]; @@ -207,8 +217,11 @@ fn main() { } None => dummy.size, }; - let env_shader = asset_hub.shaders[shader_handle].raw.as_ref().unwrap(); - let env_sampler = EnvMapSampler::new(env_size, env_shader, &context); + let env_sampler = EnvMapSampler::new( + env_size, + asset_hub.shaders[shader_main_handle].raw.as_ref().unwrap(), + &context, + ); env_sampler.accumulate(&mut command_encoder, env_map.main_view, env_map.weight_view); let sync_point = context.submit(&mut command_encoder); diff --git a/examples/particle/main.rs b/examples/particle/main.rs index 76baee61..2e8b06ae 100644 --- a/examples/particle/main.rs +++ b/examples/particle/main.rs @@ -5,7 +5,7 @@ use blade_graphics as gpu; mod particle; struct Example { - command_encoder: gpu::CommandEncoder, + command_encoder: Option, prev_sync_point: Option, context: gpu::Context, gui_painter: blade_egui::GuiPainter, @@ -35,7 +35,7 @@ impl Example { usage: gpu::TextureUsage::TARGET, frame_count: 3, }); - let gui_painter = blade_egui::GuiPainter::new(&context, surface_format); + let gui_painter = blade_egui::GuiPainter::new(surface_format, &context); let particle_system = particle::System::new( &context, particle::SystemDesc { @@ -54,7 +54,7 @@ impl Example { let sync_point = context.submit(&mut command_encoder); Self { - command_encoder, + command_encoder: Some(command_encoder), prev_sync_point: Some(sync_point), context, gui_painter, @@ -66,6 +66,8 @@ impl Example { if let Some(sp) = self.prev_sync_point.take() { self.context.wait_for(&sp, !0); } + let encoder = self.command_encoder.take().unwrap(); + self.context.destroy_command_encoder(encoder); self.gui_painter.destroy(&self.context); self.particle_system.destroy(&self.context); } @@ -77,16 +79,17 @@ impl Example { screen_desc: &blade_egui::ScreenDescriptor, ) { let frame = self.context.acquire_frame(); + let encoder = self.command_encoder.as_mut().unwrap(); - self.command_encoder.start(); - self.command_encoder.init_texture(frame.texture()); + encoder.start(); + encoder.init_texture(frame.texture()); self.gui_painter - .update_textures(&mut self.command_encoder, gui_textures, &self.context); + .update_textures(encoder, gui_textures, &self.context); - self.particle_system.update(&mut self.command_encoder); + self.particle_system.update(encoder); - if let mut pass = self.command_encoder.render(gpu::RenderTargetSet { + if let mut pass = encoder.render(gpu::RenderTargetSet { colors: &[gpu::RenderTarget { view: frame.texture_view(), init_op: gpu::InitOp::Clear(gpu::TextureColor::TransparentBlack), @@ -98,8 +101,8 @@ impl Example { self.gui_painter .paint(&mut pass, gui_primitives, screen_desc, &self.context); } - self.command_encoder.present(frame); - let sync_point = self.context.submit(&mut self.command_encoder); + encoder.present(frame); + let sync_point = self.context.submit(encoder); self.gui_painter.after_submit(sync_point.clone()); if let Some(sp) = self.prev_sync_point.take() { diff --git a/examples/ray-query/main.rs b/examples/ray-query/main.rs index 79e95f8e..4778eaa5 100644 --- a/examples/ray-query/main.rs +++ b/examples/ray-query/main.rs @@ -249,6 +249,7 @@ impl Example { if let Some(sp) = self.prev_sync_point { self.context.wait_for(&sp, !0); } + self.context.destroy_command_encoder(self.command_encoder); self.context.destroy_texture_view(self.target_view); self.context.destroy_texture(self.target); self.context.destroy_acceleration_structure(self.blas); diff --git a/examples/scene/main.rs b/examples/scene/main.rs index e5394718..7634a05c 100644 --- a/examples/scene/main.rs +++ b/examples/scene/main.rs @@ -217,7 +217,7 @@ impl Example { ); let sync_point = context.submit(&mut command_encoder); - let gui_painter = blade_egui::GuiPainter::new(&context, surface_format); + let gui_painter = blade_egui::GuiPainter::new(surface_format, &context); Self { scene_path: PathBuf::new(), From b8255d7bb8b6ed1ed340e076d8bea30468750792 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 2 Nov 2023 23:45:43 -0700 Subject: [PATCH 3/3] Add FramePacer utility helper --- blade-egui/src/belt.rs | 2 +- blade-egui/src/lib.rs | 2 +- blade-render/src/lib.rs | 1 + blade-render/src/render/mod.rs | 21 ++++++--- blade-render/src/util/frame_pacer.rs | 68 ++++++++++++++++++++++++++++ blade-render/src/util/mod.rs | 3 ++ examples/particle/main.rs | 2 +- examples/scene/main.rs | 63 ++++++-------------------- 8 files changed, 103 insertions(+), 59 deletions(-) create mode 100644 blade-render/src/util/frame_pacer.rs create mode 100644 blade-render/src/util/mod.rs diff --git a/blade-egui/src/belt.rs b/blade-egui/src/belt.rs index 1b5594be..0f0946f9 100644 --- a/blade-egui/src/belt.rs +++ b/blade-egui/src/belt.rs @@ -85,7 +85,7 @@ impl BufferBelt { bp } - pub fn flush(&mut self, sp: blade_graphics::SyncPoint) { + pub fn flush(&mut self, sp: &blade_graphics::SyncPoint) { self.buffers .extend(self.active.drain(..).map(|(rb, _)| (rb, sp.clone()))); } diff --git a/blade-egui/src/lib.rs b/blade-egui/src/lib.rs index bc821437..fac41a03 100644 --- a/blade-egui/src/lib.rs +++ b/blade-egui/src/lib.rs @@ -349,7 +349,7 @@ impl GuiPainter { /// Call this after submitting work at the given `sync_point`. #[profiling::function] - pub fn after_submit(&mut self, sync_point: blade_graphics::SyncPoint) { + pub fn after_submit(&mut self, sync_point: &blade_graphics::SyncPoint) { self.textures_to_delete.extend( self.textures_dropped .drain(..) diff --git a/blade-render/src/lib.rs b/blade-render/src/lib.rs index db414309..0d664053 100644 --- a/blade-render/src/lib.rs +++ b/blade-render/src/lib.rs @@ -14,6 +14,7 @@ pub mod model; mod render; pub mod shader; pub mod texture; +pub mod util; pub use asset_hub::*; pub use model::Model; diff --git a/blade-render/src/render/mod.rs b/blade-render/src/render/mod.rs index 45cd5793..281f6f49 100644 --- a/blade-render/src/render/mod.rs +++ b/blade-render/src/render/mod.rs @@ -748,6 +748,13 @@ impl ShaderPipelines { } } +/// Temporary resources associated with a GPU frame. +#[derive(Default)] +pub struct FrameResources { + pub buffers: Vec, + pub acceleration_structures: Vec, +} + impl Renderer { /// Create a new renderer with a given configuration. /// @@ -1043,8 +1050,7 @@ impl Renderer { env_map: Option>, asset_hub: &crate::AssetHub, gpu: &blade_graphics::Context, - temp_buffers: &mut Vec, - temp_acceleration_structures: &mut Vec, + temp: &mut FrameResources, ) { let (env_view, env_extent) = match env_map { Some(handle) => { @@ -1057,7 +1063,8 @@ impl Renderer { .assign(env_view, env_extent, command_encoder, gpu); if self.acceleration_structure != blade_graphics::AccelerationStructure::default() { - temp_acceleration_structures.push(self.acceleration_structure); + temp.acceleration_structures + .push(self.acceleration_structure); } let geometry_count = objects @@ -1070,7 +1077,7 @@ impl Renderer { let hit_size = (geometry_count.max(1) * mem::size_of::()) as u64; //TODO: reuse the hit buffer if self.hit_buffer != blade_graphics::Buffer::default() { - temp_buffers.push(self.hit_buffer); + temp.buffers.push(self.hit_buffer); } self.hit_buffer = gpu.create_buffer(blade_graphics::BufferDesc { name: "hit entries", @@ -1082,7 +1089,7 @@ impl Renderer { size: hit_size, memory: blade_graphics::Memory::Upload, }); - temp_buffers.push(hit_staging); + temp.buffers.push(hit_staging); { let mut transfers = command_encoder.transfer(); transfers.copy_buffer_to_buffer(hit_staging.at(0), self.hit_buffer.at(0), hit_size); @@ -1222,8 +1229,8 @@ impl Renderer { scratch_buf.at(0), ); - temp_buffers.push(instance_buf); - temp_buffers.push(scratch_buf); + temp.buffers.push(instance_buf); + temp.buffers.push(scratch_buf); } /// Prepare to render a frame. diff --git a/blade-render/src/util/frame_pacer.rs b/blade-render/src/util/frame_pacer.rs new file mode 100644 index 00000000..41938dee --- /dev/null +++ b/blade-render/src/util/frame_pacer.rs @@ -0,0 +1,68 @@ +use crate::render::FrameResources; +use std::mem; + +/// Utility object that encapsulates the logic +/// of always rendering 1 frame at a time, and +/// cleaning up the temporary resources. +pub struct FramePacer { + frame_index: usize, + prev_resources: FrameResources, + prev_sync_point: Option, + command_encoder: Option, + next_resources: FrameResources, +} + +impl FramePacer { + pub fn new(context: &blade_graphics::Context) -> Self { + let encoder = context.create_command_encoder(blade_graphics::CommandEncoderDesc { + name: "main", + buffer_count: 2, + }); + Self { + frame_index: 0, + prev_resources: FrameResources::default(), + prev_sync_point: None, + command_encoder: Some(encoder), + next_resources: FrameResources::default(), + } + } + + #[profiling::function] + pub fn wait_for_previous_frame(&mut self, context: &blade_graphics::Context) { + if let Some(sp) = self.prev_sync_point.take() { + context.wait_for(&sp, !0); + } + for buffer in self.prev_resources.buffers.drain(..) { + context.destroy_buffer(buffer); + } + for accel_structure in self.prev_resources.acceleration_structures.drain(..) { + context.destroy_acceleration_structure(accel_structure); + } + } + + pub fn last_sync_point(&self) -> Option<&blade_graphics::SyncPoint> { + self.prev_sync_point.as_ref() + } + + pub fn destroy(&mut self, context: &blade_graphics::Context) { + self.wait_for_previous_frame(context); + context.destroy_command_encoder(self.command_encoder.take().unwrap()); + } + + pub fn begin_frame(&mut self) -> (&mut blade_graphics::CommandEncoder, &mut FrameResources) { + let encoder = self.command_encoder.as_mut().unwrap(); + encoder.start(); + (encoder, &mut self.next_resources) + } + + pub fn end_frame(&mut self, context: &blade_graphics::Context) -> &blade_graphics::SyncPoint { + let sync_point = context.submit(self.command_encoder.as_mut().unwrap()); + self.frame_index += 1; + // Wait for the previous frame immediately - this ensures that we are + // only processing one frame at a time, and yet not stalling. + self.wait_for_previous_frame(context); + self.prev_sync_point = Some(sync_point); + mem::swap(&mut self.prev_resources, &mut self.next_resources); + self.prev_sync_point.as_ref().unwrap() + } +} diff --git a/blade-render/src/util/mod.rs b/blade-render/src/util/mod.rs new file mode 100644 index 00000000..3cae34a9 --- /dev/null +++ b/blade-render/src/util/mod.rs @@ -0,0 +1,3 @@ +mod frame_pacer; + +pub use self::frame_pacer::*; diff --git a/examples/particle/main.rs b/examples/particle/main.rs index 2e8b06ae..294a3df1 100644 --- a/examples/particle/main.rs +++ b/examples/particle/main.rs @@ -103,7 +103,7 @@ impl Example { } encoder.present(frame); let sync_point = self.context.submit(encoder); - self.gui_painter.after_submit(sync_point.clone()); + self.gui_painter.after_submit(&sync_point); if let Some(sp) = self.prev_sync_point.take() { self.context.wait_for(&sp, !0); diff --git a/examples/scene/main.rs b/examples/scene/main.rs index 7634a05c..6735038f 100644 --- a/examples/scene/main.rs +++ b/examples/scene/main.rs @@ -119,13 +119,10 @@ struct ConfigScene { struct Example { scene_path: PathBuf, scene_environment_map: String, - prev_temp_buffers: Vec, - prev_acceleration_structures: Vec, - prev_sync_point: Option, + pacer: blade_render::util::FramePacer, renderer: blade_render::Renderer, scene_load_task: Option, gui_painter: blade_egui::GuiPainter, - command_encoder: Option, asset_hub: blade_render::AssetHub, context: Arc, environment_map: Option>, @@ -198,37 +195,30 @@ impl Example { log::info!("Spinning up the renderer"); shader_task.join(); - let mut command_encoder = context.create_command_encoder(gpu::CommandEncoderDesc { - name: "main", - buffer_count: 2, - }); - command_encoder.start(); + let mut pacer = blade_render::util::FramePacer::new(&context); + let (command_encoder, _) = pacer.begin_frame(); let render_config = blade_render::RenderConfig { screen_size, surface_format, max_debug_lines: 1000, }; let renderer = blade_render::Renderer::new( - &mut command_encoder, + command_encoder, &context, shaders, &asset_hub.shaders, &render_config, ); - let sync_point = context.submit(&mut command_encoder); - + pacer.end_frame(&context); let gui_painter = blade_egui::GuiPainter::new(surface_format, &context); Self { scene_path: PathBuf::new(), scene_environment_map: String::new(), - prev_temp_buffers: Vec::new(), - prev_acceleration_structures: Vec::new(), - prev_sync_point: Some(sync_point), + pacer, renderer, scene_load_task: None, gui_painter, - command_encoder: Some(command_encoder), asset_hub, context, environment_map: None, @@ -289,12 +279,10 @@ impl Example { fn destroy(&mut self) { self.workers.clear(); - self.wait_for_previous_frame(); + self.pacer.destroy(&self.context); self.gui_painter.destroy(&self.context); self.renderer.destroy(&self.context); self.asset_hub.destroy(); - self.context - .destroy_command_encoder(self.command_encoder.take().unwrap()); } pub fn load_scene(&mut self, scene_path: &Path) { @@ -391,19 +379,6 @@ impl Example { log::info!("Saving scene to: {}", scene_path.display()); } - #[profiling::function] - fn wait_for_previous_frame(&mut self) { - if let Some(sp) = self.prev_sync_point.take() { - self.context.wait_for(&sp, !0); - } - for buffer in self.prev_temp_buffers.drain(..) { - self.context.destroy_buffer(buffer); - } - for accel_structure in self.prev_acceleration_structures.drain(..) { - self.context.destroy_acceleration_structure(accel_structure); - } - } - #[profiling::function] fn render( &mut self, @@ -416,7 +391,7 @@ impl Example { self.need_accumulation_reset |= self.renderer.hot_reload( &self.asset_hub, &self.context, - self.prev_sync_point.as_ref().unwrap(), + self.pacer.last_sync_point().unwrap(), ); } @@ -426,12 +401,11 @@ impl Example { let new_render_size = surface_config.size; if new_render_size != self.renderer.get_screen_size() { log::info!("Resizing to {}", new_render_size); - self.wait_for_previous_frame(); + self.pacer.wait_for_previous_frame(&self.context); self.context.resize(surface_config); } - let command_encoder = self.command_encoder.as_mut().unwrap(); - command_encoder.start(); + let (command_encoder, temp) = self.pacer.begin_frame(); if new_render_size != self.renderer.get_screen_size() { self.renderer .resize_screen(new_render_size, command_encoder, &self.context); @@ -441,9 +415,7 @@ impl Example { self.gui_painter .update_textures(command_encoder, gui_textures, &self.context); - let mut temp_buffers = Vec::new(); - let mut temp_acceleration_structures = Vec::new(); - self.asset_hub.flush(command_encoder, &mut temp_buffers); + self.asset_hub.flush(command_encoder, &mut temp.buffers); if let Some(ref task) = self.scene_load_task { if task.is_done() { @@ -464,8 +436,7 @@ impl Example { self.environment_map, &self.asset_hub, &self.context, - &mut temp_buffers, - &mut temp_acceleration_structures, + temp, ); self.have_objects_changed = false; } @@ -522,14 +493,8 @@ impl Example { } command_encoder.present(frame); - let sync_point = self.context.submit(command_encoder); - self.gui_painter.after_submit(sync_point.clone()); - - self.wait_for_previous_frame(); - self.prev_sync_point = Some(sync_point); - self.prev_temp_buffers.extend(temp_buffers); - self.prev_acceleration_structures - .extend(temp_acceleration_structures); + let sync_point = self.pacer.end_frame(&self.context); + self.gui_painter.after_submit(sync_point); } fn add_manipulation_gizmo(&mut self, obj_index: usize, ui: &mut egui::Ui) {