diff --git a/examples/swap_chain/main.rs b/examples/swap_chain/main.rs index e9819f1..80a2573 100644 --- a/examples/swap_chain/main.rs +++ b/examples/swap_chain/main.rs @@ -1,3 +1,5 @@ +use hotline_rs::gfx::CmdBuf; +use hotline_rs::gfx::RenderPassInfo; use hotline_rs::gfx::SwapChain; use hotline_rs::*; @@ -48,18 +50,53 @@ fn main() -> Result<(), hotline_rs::Error> { let swap_chain_info = gfx::SwapChainInfo { num_buffers, format: gfx::Format::RGBA8n, - clear_colour: Some(gfx::ClearColour { - r: 0.45, - g: 0.55, - b: 0.60, - a: 1.00, - }), + clear_colour: None }; let mut swap_chain = device.create_swap_chain::(&swap_chain_info, &window)?; let mut cmd = device.create_cmd_buf(num_buffers); + let colours = [ + gfx::ClearColour { + r: 1.00, + g: 0.00, + b: 0.00, + a: 1.00 + }, + gfx::ClearColour { + r: 0.00, + g: 1.00, + b: 0.00, + a: 1.00 + }, + gfx::ClearColour { + r: 0.00, + g: 0.00, + b: 1.00, + a: 1.00 + }, + gfx::ClearColour { + r: 0.00, + g: 1.00, + b: 1.00, + a: 1.00 + }, + gfx::ClearColour { + r: 1.00, + g: 0.00, + b: 1.00, + a: 1.00 + }, + gfx::ClearColour { + r: 1.00, + g: 1.00, + b: 0.00, + a: 1.00 + } + ]; + let mut col_index = 0; let mut counter = 0; + while app.run() { // update the swap chain swap_chain.update::(&mut device, &window, &mut cmd); @@ -67,13 +104,29 @@ fn main() -> Result<(), hotline_rs::Error> { // update window and swap chain window.update(&mut app); + let render_pass = device.create_render_pass(&RenderPassInfo{ + rt_clear: Some(colours[col_index]), + render_targets: vec![swap_chain.get_backbuffer_texture()], + depth_stencil: None, + ds_clear: None, + discard: false, + resolve: false, + array_slice: 0 + })?; + // render pass to clear + cmd.reset(&swap_chain); + cmd.begin_render_pass(&render_pass); + cmd.end_render_pass(); + cmd.close()?; + println!("swap {}", counter); swap_chain.swap(&device); - // sleep? - println!("sleep"); - std::thread::sleep(std::time::Duration::from_millis(16)); + // swap colours and inc counter counter += 1; + if counter % 30 == 0 { + col_index = (col_index + 1) % colours.len(); + } } Ok(()) diff --git a/src/gfx.rs b/src/gfx.rs index ca9cd07..1155855 100644 --- a/src/gfx.rs +++ b/src/gfx.rs @@ -1187,9 +1187,9 @@ pub trait CmdBuf: Send + Sync + Clone { /// to complete, this value indicates the buffer number you should `write` to during the current frame fn get_backbuffer_index(&self) -> u32; /// Begins a render pass, end must be called - fn begin_render_pass(&self, render_pass: &D::RenderPass); + fn begin_render_pass(&mut self, render_pass: &D::RenderPass); /// End a render pass must be called after `begin_render_pass` has been called - fn end_render_pass(&self); + fn end_render_pass(&mut self); /// Begin a names marker event which will be visible in tools such as PIX or RenderDoc fn begin_event(&mut self, colour: u32, name: &str); /// End an event that was started with `begin_event` diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 18e7068..42c8ff1 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -36,12 +36,6 @@ pub struct SwapChain { backbuffer_pass_no_clear: RenderPass, } -impl SwapChain { - fn create_backbuffer_passes() { - - } -} - impl super::SwapChain for SwapChain { fn new_frame(&mut self) { } @@ -109,14 +103,20 @@ impl super::SwapChain for SwapChain { #[derive(Clone)] pub struct CmdBuf { - + cmd_queue: metal::CommandQueue, + cmd: Option, + render_encoder: Option, + compute_encoder: Option } impl super::CmdBuf for CmdBuf { fn reset(&mut self, swap_chain: &SwapChain) { + self.cmd = Some(self.cmd_queue.new_command_buffer().to_owned()); } fn close(&mut self) -> result::Result<(), super::Error> { + self.cmd.as_ref().expect("hotline_rs::gfx::mtl expected call to CmdBuf::reset before close").commit(); + self.cmd = None; Ok(()) } @@ -124,10 +124,25 @@ impl super::CmdBuf for CmdBuf { 0 } - fn begin_render_pass(&self, render_pass: &RenderPass) { + fn begin_render_pass(&mut self, render_pass: &RenderPass) { + // catch double begin + assert!(self.render_encoder.is_none(), + "hotline_rs::gfx::mtl begin_render_pass called without matching CmdBuf::end_render_pass"); + + // catch mismatched close/reset + let render_encoder = self.cmd.as_ref() + .expect("hotline_rs::gfx::mtl expected call to CmdBuf::reset after close") + .new_render_command_encoder(&render_pass.desc).to_owned(); + + // new encoder + self.render_encoder = Some(render_encoder); } - fn end_render_pass(&self) { + fn end_render_pass(&mut self) { + self.render_encoder.as_ref() + .expect("hotline_rs::gfx::mtl end_render_pass called without matching begin") + .end_encoding(); + self.render_encoder = None; } fn begin_event(&mut self, colour: u32, name: &str) { @@ -372,7 +387,7 @@ impl super::ReadBackRequest for ReadBackRequest { #[derive(Clone)] pub struct RenderPass { - + desc: metal::RenderPassDescriptor } impl super::RenderPass for RenderPass { @@ -524,7 +539,10 @@ impl super::Device for Device { fn create_cmd_buf(&self, num_buffers: u32) -> CmdBuf { CmdBuf { - + cmd_queue: self.command_queue.clone(), + cmd: None, + render_encoder: None, + compute_encoder: None } } @@ -609,28 +627,29 @@ impl super::Device for Device { &self, info: &super::RenderPassInfo, ) -> result::Result { - /* - fn prepare_render_pass_descriptor(descriptor: &RenderPassDescriptorRef, texture: &TextureRef) { - let color_attachment = descriptor.color_attachments().object_at(0).unwrap(); - - color_attachment.set_texture(Some(texture)); - color_attachment.set_load_action(MTLLoadAction::Clear); - color_attachment.set_clear_color(MTLClearColor::new(0.2, 0.2, 0.25, 1.0)); - color_attachment.set_store_action(MTLStoreAction::Store); - */ - + // new desc let descriptor = metal::RenderPassDescriptor::new(); + + // colour attachments for rt in &info.render_targets { let color_attachment = descriptor.color_attachments().object_at(0).unwrap(); - // color_attachment.set_texture(Some(texture)); + color_attachment.set_texture(Some(&rt.metal_texture)); - color_attachment.set_load_action(metal::MTLLoadAction::Clear); - color_attachment.set_clear_color(metal::MTLClearColor::new(0.2, 0.2, 0.25, 1.0)); - color_attachment.set_store_action(metal::MTLStoreAction::Store); + if let Some(cc) = info.rt_clear { + color_attachment.set_load_action(metal::MTLLoadAction::Clear); + color_attachment.set_clear_color(metal::MTLClearColor::new(cc.r as f64, cc.g as f64, cc.b as f64, 1.0)); + color_attachment.set_store_action(metal::MTLStoreAction::Store); + } + else { + color_attachment.set_load_action(metal::MTLLoadAction::Load); + color_attachment.set_store_action(metal::MTLStoreAction::Store); + } } - Ok(RenderPass{ + // TODO: depth + Ok(RenderPass{ + desc: descriptor.to_owned() }) }