diff --git a/vulkano/src/command_buffer/std/mod.rs b/vulkano/src/command_buffer/std/mod.rs index 1987d798..bc939496 100644 --- a/vulkano/src/command_buffer/std/mod.rs +++ b/vulkano/src/command_buffer/std/mod.rs @@ -19,6 +19,7 @@ use descriptor::PipelineLayout; use descriptor::descriptor_set::collection::TrackedDescriptorSetsCollection; use framebuffer::Framebuffer; use framebuffer::RenderPass; +use framebuffer::RenderPassClearValues; use image::traits::TrackedImage; use instance::QueueFamily; use pipeline::ComputePipeline; @@ -68,13 +69,19 @@ pub unsafe trait StdCommandsList { /// Adds a command that starts a render pass. /// + /// If `secondary` is true, then you will only be able to add secondary command buffers while + /// you're inside the first subpass on the render pass. If `secondary` is false, you will only + /// be able to add inline draw commands and not secondary command buffers. + /// /// You must call this before you can add draw commands. #[inline] - fn begin_render_pass(self, framebuffer: Arc>) - -> render_pass::BeginRenderPassCommand - where Self: Sized + OutsideRenderPass, Rp: RenderPass + fn begin_render_pass(self, framebuffer: Arc>, secondary: bool, + clear_values: C) + -> render_pass::BeginRenderPassCommand + where Self: Sized + OutsideRenderPass, + Rp: RenderPass + RenderPassClearValues { - render_pass::BeginRenderPassCommand::new(self, framebuffer) + render_pass::BeginRenderPassCommand::new(self, framebuffer, secondary, clear_values) } /// Adds a command that jumps to the next subpass of the current render pass. @@ -179,6 +186,10 @@ pub unsafe trait InsideRenderPass: StdCommandsList { /// The value should always be strictly inferior to the number of subpasses in the render pass. fn current_subpass(&self) -> u32; + /// If true, only secondary command buffers can be added inside the subpass. If false, only + /// inline draw commands can be added. + fn secondary_subpass(&self) -> bool; + // TODO: don't use Arc fn render_pass(&self) -> &Arc; diff --git a/vulkano/src/command_buffer/std/render_pass.rs b/vulkano/src/command_buffer/std/render_pass.rs index 454bda68..333af905 100644 --- a/vulkano/src/command_buffer/std/render_pass.rs +++ b/vulkano/src/command_buffer/std/render_pass.rs @@ -9,6 +9,8 @@ use std::iter; use std::sync::Arc; +use std::ops::Range; +use smallvec::SmallVec; use buffer::traits::TrackedBuffer; use command_buffer::std::InsideRenderPass; @@ -20,8 +22,10 @@ use command_buffer::sys::PipelineBarrierBuilder; use command_buffer::sys::UnsafeCommandBuffer; use command_buffer::sys::UnsafeCommandBufferBuilder; use device::Queue; +use format::ClearValue; use framebuffer::Framebuffer; use framebuffer::RenderPass; +use framebuffer::RenderPassClearValues; use image::traits::TrackedImage; use instance::QueueFamily; use sync::Fence; @@ -32,6 +36,10 @@ pub struct BeginRenderPassCommand { // Parent commands list. previous: L, + // True if only secondary command buffers can be added. + secondary: bool, + rect: [Range; 2], + clear_values: SmallVec<[ClearValue; 6]>, render_pass: Arc, framebuffer: Arc>, } @@ -40,13 +48,21 @@ impl BeginRenderPassCommand where L: StdCommandsList + OutsideRenderPass, Rp: RenderPass { /// See the documentation of the `begin_render_pass` method. - pub fn new(previous: L, framebuffer: Arc>) - -> BeginRenderPassCommand + // TODO: allow setting more parameters + pub fn new(previous: L, framebuffer: Arc>, secondary: bool, clear_values: C) + -> BeginRenderPassCommand + where Rp: RenderPassClearValues { // FIXME: transition states of the images in the framebuffer + let clear_values = framebuffer.render_pass().convert_clear_values(clear_values) + .collect(); + BeginRenderPassCommand { previous: previous, + secondary: secondary, + rect: [0 .. framebuffer.width(), 0 .. framebuffer.height()], + clear_values: clear_values, render_pass: framebuffer.render_pass().clone(), framebuffer: framebuffer.clone(), } @@ -99,25 +115,25 @@ unsafe impl StdCommandsList for BeginRenderPassCommand where F: FnOnce(&mut UnsafeCommandBufferBuilder), I: Iterator { - // We need to flush all the barriers because regular (ie. non-self-referencing) barriers - // aren't allowed inside render passes. + let my_command_num = self.num_commands(); + let barriers = barriers.map(move |(n, b)| { assert!(n < my_command_num); (n, b) }); - let mut pipeline_barrier = PipelineBarrierBuilder::new(); - for (num, barrier) in barriers { - debug_assert!(num <= self.num_commands()); - pipeline_barrier.merge(barrier); - } + let my_render_pass = self.render_pass; + let my_framebuffer = self.framebuffer; + let mut my_clear_values = self.clear_values; + let my_rect = self.rect; + let my_secondary = self.secondary; let parent = self.previous.raw_build(|cb| { - cb.end_render_pass(); - cb.pipeline_barrier(pipeline_barrier); + cb.begin_render_pass(my_render_pass.inner(), &my_framebuffer, + my_clear_values.into_iter(), my_rect, my_secondary); additional_elements(cb); - }, iter::empty(), final_barrier); + }, barriers, final_barrier); BeginRenderPassCommandCb { previous: parent, - render_pass: self.render_pass, - framebuffer: self.framebuffer, + render_pass: my_render_pass, + framebuffer: my_framebuffer, } } } @@ -133,6 +149,11 @@ unsafe impl InsideRenderPass for BeginRenderPassCommand 0 } + #[inline] + fn secondary_subpass(&self) -> bool { + self.secondary + } + #[inline] fn render_pass(&self) -> &Arc { &self.render_pass @@ -180,6 +201,7 @@ unsafe impl CommandBuffer for BeginRenderPassCommandCb pub struct NextSubpassCommand where L: StdCommandsList { // Parent commands list. previous: L, + // True if only secondary command buffers can be added. secondary: bool, } @@ -266,6 +288,11 @@ unsafe impl InsideRenderPass for NextSubpassCommand self.previous.current_subpass() + 1 } + #[inline] + fn secondary_subpass(&self) -> bool { + self.secondary + } + #[inline] fn render_pass(&self) -> &Arc { self.previous.render_pass()