diff --git a/vulkano/src/command_buffer/cmd/dispatch.rs b/vulkano/src/command_buffer/cmd/dispatch.rs index d7dd28f5..20b7a041 100644 --- a/vulkano/src/command_buffer/cmd/dispatch.rs +++ b/vulkano/src/command_buffer/cmd/dispatch.rs @@ -11,14 +11,17 @@ use std::iter; use std::sync::Arc; use smallvec::SmallVec; +use command_buffer::DynamicState; use command_buffer::StatesManager; use command_buffer::SubmitInfo; -use command_buffer::cmd::CommandsListPossibleOutsideRenderPass; -use command_buffer::cmd::CommandsList; -use command_buffer::cmd::CommandsListConcrete; -use command_buffer::cmd::CommandsListOutput; -use command_buffer::sys::PipelineBarrierBuilder; -use command_buffer::sys::UnsafeCommandBufferBuilder; +use command_buffer::cmd::CmdBindDescriptorSets; +use command_buffer::cmd::CmdBindPipeline; +use command_buffer::cmd::CmdBindVertexBuffers; +use command_buffer::cmd::CmdPushConstants; +use command_buffer::cmd::CmdSetState; +use command_buffer::RawCommandBufferPrototype; +use command_buffer::CommandsList; +use command_buffer::CommandsListSink; use descriptor::PipelineLayoutRef; use descriptor::descriptor::ShaderStages; use descriptor::descriptor_set::collection::TrackedDescriptorSetsCollection; @@ -26,226 +29,63 @@ use device::Device; use device::Queue; use instance::QueueFamily; use pipeline::ComputePipeline; +use pipeline::vertex::Source; use sync::Fence; use VulkanObject; +use VulkanPointers; use vk; /// Wraps around a commands list and adds a dispatch command at the end of it. -pub struct DispatchCommand<'a, L, Pl, S, Pc> - where L: CommandsList, Pl: PipelineLayoutRef, S: TrackedDescriptorSetsCollection, Pc: 'a +pub struct CmdDispatch + where L: CommandsList, Pl: PipelineLayoutRef, S: TrackedDescriptorSetsCollection { // Parent commands list. - previous: L, - // The compute pipeline. - pipeline: Arc>, - // The descriptor sets to bind. - sets: S, - // Pipeline barrier to inject in the final command buffer. - pipeline_barrier: (usize, PipelineBarrierBuilder), - // The push constants. TODO: use Cow - push_constants: &'a Pc, + previous: CmdPushConstants< + CmdBindDescriptorSets< + CmdBindPipeline>>, + S, Arc> + >, + Pc, Arc> + >, + // Dispatch dimensions. dimensions: [u32; 3], - // States of the resources, or `None` if it has been extracted. - resources_states: Option, } -impl<'a, L, Pl, S, Pc> DispatchCommand<'a, L, Pl, S, Pc> - where L: CommandsList + CommandsListPossibleOutsideRenderPass, - Pl: PipelineLayoutRef, - S: TrackedDescriptorSetsCollection, Pc: 'a +impl CmdDispatch + where L: CommandsList, Pl: PipelineLayoutRef, S: TrackedDescriptorSetsCollection { /// See the documentation of the `dispatch` method. - pub fn new(mut previous: L, pipeline: Arc>, sets: S, dimensions: [u32; 3], - push_constants: &'a Pc) -> DispatchCommand<'a, L, Pl, S, Pc> + pub fn new(previous: L, pipeline: Arc>, sets: S, dimensions: [u32; 3], + push_constants: Pc) -> CmdDispatch { - assert!(previous.is_outside_render_pass()); + let previous = CmdBindPipeline::bind_compute_pipeline(previous, pipeline.clone()); + let device = previous.device().clone(); + let previous = CmdBindDescriptorSets::new(previous, false, pipeline.clone(), sets).unwrap() /* TODO: error */; + let previous = CmdPushConstants::new(previous, pipeline.clone(), push_constants).unwrap() /* TODO: error */; - let mut states = previous.extract_states(); + // TODO: check dimensions limits - let (barrier_loc, barrier) = unsafe { - sets.transition(&mut states) - }; - - DispatchCommand { + CmdDispatch { previous: previous, - pipeline: pipeline, - sets: sets, - pipeline_barrier: (barrier_loc, barrier), - push_constants: push_constants, dimensions: dimensions, - resources_states: Some(states), } } } -unsafe impl<'a, L, Pl, S, Pc> CommandsList for DispatchCommand<'a, L, Pl, S, Pc> - where L: CommandsList, Pl: PipelineLayoutRef, S: TrackedDescriptorSetsCollection, Pc: 'a +unsafe impl CommandsList for CmdDispatch + where L: CommandsList, Pl: PipelineLayoutRef, S: TrackedDescriptorSetsCollection { #[inline] - fn num_commands(&self) -> usize { - self.previous.num_commands() + 1 - } + fn append<'a>(&'a self, builder: &mut CommandsListSink<'a>) { + self.previous.append(builder); - #[inline] - fn check_queue_validity(&self, queue: QueueFamily) -> Result<(), ()> { - if !queue.supports_compute() { - return Err(()); - } - - self.previous.check_queue_validity(queue) - } - - #[inline] - fn is_compute_pipeline_bound(&self, pipeline: vk::Pipeline) -> bool { - self.pipeline.internal_object() == pipeline - } - - #[inline] - fn is_graphics_pipeline_bound(&self, pipeline: vk::Pipeline) -> bool { - self.previous.is_graphics_pipeline_bound(pipeline) - } - - #[inline] - fn extract_states(&mut self) -> StatesManager { - self.resources_states.take().unwrap() - } - - #[inline] - fn buildable_state(&self) -> bool { - true - } -} - -unsafe impl<'a, L, Pl, S, Pc> CommandsListConcrete for DispatchCommand<'a, L, Pl, S, Pc> - where L: CommandsListConcrete, Pl: PipelineLayoutRef, S: TrackedDescriptorSetsCollection, Pc: 'a -{ - type Pool = L::Pool; - type Output = DispatchCommandCb; - - unsafe fn raw_build(self, in_s: &mut StatesManager, out: &mut StatesManager, - additional_elements: F, barriers: I, - mut final_barrier: PipelineBarrierBuilder) -> Self::Output - where F: FnOnce(&mut UnsafeCommandBufferBuilder), - I: Iterator - { - let my_command_num = self.num_commands(); - - // Computing the finished state of the sets. - final_barrier.merge(self.sets.finish(in_s, out)); - - // We split the barriers in two: those to apply after our command, and those to - // transfer to the parent so that they are applied before our command. - - // The transitions to apply immediately after our command. - let mut transitions_to_apply = PipelineBarrierBuilder::new(); - - // The barriers to transfer to the parent. - let barriers = barriers.filter_map(|(after_command_num, barrier)| { - if after_command_num >= my_command_num || !transitions_to_apply.is_empty() { - transitions_to_apply.merge(barrier); - None - } else { - Some((after_command_num, barrier)) + builder.add_command(Box::new(move |raw: &mut RawCommandBufferPrototype| { + unsafe { + let vk = raw.device.pointers(); + let cmd = raw.command_buffer.clone().take().unwrap(); + vk.CmdDispatch(cmd, self.dimensions[0], self.dimensions[1], self.dimensions[2]); } - }).collect::>(); - - // Moving out some values, otherwise Rust complains that the closure below uses `self` - // while it's partially moved out. - let my_barrier = self.pipeline_barrier; - let my_pipeline = self.pipeline; - let my_sets = self.sets; - let my_push_constants = self.push_constants; - let my_dimensions = self.dimensions; - let bind_pipeline = !self.previous.is_compute_pipeline_bound(my_pipeline.internal_object()); - - // Passing to the parent. - let parent = self.previous.raw_build(in_s, out, |cb| { - // TODO: is the pipeline layout always the same as in the compute pipeline? - if bind_pipeline { - cb.bind_pipeline_compute(&my_pipeline); - } - - cb.bind_descriptor_sets(false, my_pipeline.layout(), 0, // TODO: shouldn't unwrap - (0 .. my_sets.num_sets()).map(|n| my_sets.descriptor_set(n).unwrap()), iter::empty()); // TODO: dynamic ranges, and don't bind if not necessary - cb.push_constants(my_pipeline.layout(), ShaderStages::all(), 0, // TODO: stages - &my_push_constants); - cb.dispatch(my_dimensions[0], my_dimensions[1], my_dimensions[2]); - cb.pipeline_barrier(transitions_to_apply); - additional_elements(cb); - }, Some(my_barrier).into_iter().chain(barriers.into_iter()), final_barrier); - - DispatchCommandCb { - previous: parent, - pipeline: my_pipeline, - sets: my_sets, - } - } -} - -unsafe impl<'a, L, Pl, S, Pc> CommandsListPossibleOutsideRenderPass for DispatchCommand<'a, L, Pl, S, Pc> - where L: CommandsList, Pl: PipelineLayoutRef, S: TrackedDescriptorSetsCollection, Pc: 'a -{ - #[inline] - fn is_outside_render_pass(&self) -> bool { - true - } -} - -/// Wraps around a command buffer and adds an update buffer command at the end of it. -pub struct DispatchCommandCb - where L: CommandsListOutput, Pl: PipelineLayoutRef, S: TrackedDescriptorSetsCollection -{ - // The previous commands. - previous: L, - // The barrier. We store it here to keep it alive. - pipeline: Arc>, - // The descriptor sets. Stored here to keep them alive. - sets: S, -} - -unsafe impl CommandsListOutput for DispatchCommandCb - where L: CommandsListOutput, Pl: PipelineLayoutRef, S: TrackedDescriptorSetsCollection -{ - #[inline] - fn inner(&self) -> vk::CommandBuffer { - self.previous.inner() - } - - #[inline] - fn device(&self) -> &Arc { - self.previous.device() - } - - unsafe fn on_submit(&self, states: &StatesManager, queue: &Arc, - fence: &mut FnMut() -> Arc) -> SubmitInfo - { - // We query the parent. - let mut parent = self.previous.on_submit(states, queue, fence); - - // We query our sets. - let my_infos = self.sets.on_submit(states, queue, fence); - - // We merge the two. - SubmitInfo { - semaphores_wait: { - parent.semaphores_wait.extend(my_infos.semaphores_wait.into_iter()); - parent.semaphores_wait - }, - semaphores_signal: { - parent.semaphores_signal.extend(my_infos.semaphores_signal.into_iter()); - parent.semaphores_signal - }, - pre_pipeline_barrier: { - let mut b = parent.pre_pipeline_barrier; - b.merge(my_infos.pre_pipeline_barrier); - b - }, - post_pipeline_barrier: { - let mut b = parent.post_pipeline_barrier; - b.merge(my_infos.post_pipeline_barrier); - b - }, - } + })); } } diff --git a/vulkano/src/command_buffer/cmd/mod.rs b/vulkano/src/command_buffer/cmd/mod.rs index cf1e73fc..be167b88 100644 --- a/vulkano/src/command_buffer/cmd/mod.rs +++ b/vulkano/src/command_buffer/cmd/mod.rs @@ -45,6 +45,7 @@ pub use self::bind_vertex_buffers::CmdBindVertexBuffers; pub use self::blit_image_unsynced::{BlitRegion, BlitRegionAspect}; pub use self::blit_image_unsynced::{CmdBlitImageUnsynced, CmdBlitImageUnsyncedError}; pub use self::copy_buffer::{CmdCopyBuffer, CmdCopyBufferError}; +pub use self::dispatch::CmdDispatch; pub use self::draw::CmdDraw; pub use self::empty::{empty, EmptyCommandsList}; pub use self::end_render_pass::CmdEndRenderPass; @@ -61,7 +62,7 @@ mod bind_pipeline; mod bind_vertex_buffers; mod blit_image_unsynced; mod copy_buffer; -pub mod dispatch; +mod dispatch; mod draw; mod empty; mod end_render_pass; @@ -131,13 +132,13 @@ pub unsafe trait CommandsList { /// The `pipeline` is the compute pipeline that will be executed, and the sets and push /// constants will be accessible to all the invocations. #[inline] - fn dispatch<'a, Pl, S, Pc>(self, pipeline: Arc>, sets: S, - dimensions: [u32; 3], push_constants: &'a Pc) - -> dispatch::DispatchCommand<'a, Self, Pl, S, Pc> - where Self: Sized + CommandsList + CommandsListPossibleOutsideRenderPass, Pl: PipelineLayoutRef, - S: TrackedDescriptorSetsCollection, Pc: 'a + fn dispatch(self, pipeline: Arc>, sets: S, + dimensions: [u32; 3], push_constants: Pc) + -> CmdDispatch + where Self: Sized + CommandsList, Pl: PipelineLayoutRef, + S: TrackedDescriptorSetsCollection { - dispatch::DispatchCommand::new(self, pipeline, sets, dimensions, push_constants) + CmdDispatch::new(self, pipeline, sets, dimensions, push_constants) } /// Adds a command that starts a render pass.