diff --git a/vulkano/src/command_buffer/auto.rs b/vulkano/src/command_buffer/auto.rs index a6d822eb1..a952daa90 100644 --- a/vulkano/src/command_buffer/auto.rs +++ b/vulkano/src/command_buffer/auto.rs @@ -40,6 +40,9 @@ impl AutoCommandBufferBuilder> { pub fn new(device: Arc, queue_family: QueueFamily) -> Result>, OomError> { + let supports_graphics = queue_family.supports_graphics(); + let supports_compute = queue_family.supports_compute(); + let pool = Device::standard_command_pool(&device, queue_family); let cmd = unsafe { @@ -49,7 +52,7 @@ impl AutoCommandBufferBuilder> { let c = cb::SubmitSyncBuilderLayer::new(c); let c = cb::StateCacheLayer::new(c); let c = cb::ContextCheckLayer::new(c); - let c = cb::QueueTyCheckLayer::new(c); + let c = cb::QueueTyCheckLayer::new(c, supports_graphics, supports_compute); let c = cb::DeviceCheckLayer::new(c); c }; @@ -119,6 +122,15 @@ unsafe impl

CommandBufferBuilder for AutoCommandBufferBuilder

where Cb

: CommandBufferBuilder, P: CommandPool { + #[inline] + fn supports_graphics(&self) -> bool { + self.inner.supports_graphics() + } + + #[inline] + fn supports_compute(&self) -> bool { + self.inner.supports_compute() + } } macro_rules! pass_through { diff --git a/vulkano/src/command_buffer/builder.rs b/vulkano/src/command_buffer/builder.rs index a89c82a21..d176a61cd 100644 --- a/vulkano/src/command_buffer/builder.rs +++ b/vulkano/src/command_buffer/builder.rs @@ -198,6 +198,12 @@ pub unsafe trait CommandBufferBuilder: DeviceOwned { { CommandBufferBuild::build(self) } + + /// Returns true if the pool of the builder supports graphics operations. + fn supports_graphics(&self) -> bool; + + /// Returns true if the pool of the builder supports compute operations. + fn supports_compute(&self) -> bool; } pub unsafe trait CommandBufferBuilderBuffered { diff --git a/vulkano/src/command_buffer/cb/abstract_storage.rs b/vulkano/src/command_buffer/cb/abstract_storage.rs index 99cc62b30..cf5fda946 100644 --- a/vulkano/src/command_buffer/cb/abstract_storage.rs +++ b/vulkano/src/command_buffer/cb/abstract_storage.rs @@ -95,7 +95,16 @@ unsafe impl CommandBufferBuild for AbstractStorageLayer } } -unsafe impl CommandBufferBuilder for AbstractStorageLayer where I: DeviceOwned { +unsafe impl CommandBufferBuilder for AbstractStorageLayer where I: CommandBufferBuilder { + #[inline] + fn supports_graphics(&self) -> bool { + self.inner.supports_graphics() + } + + #[inline] + fn supports_compute(&self) -> bool { + self.inner.supports_compute() + } } macro_rules! pass_through { diff --git a/vulkano/src/command_buffer/cb/auto_barriers.rs b/vulkano/src/command_buffer/cb/auto_barriers.rs index 73011a57a..ade76ba81 100644 --- a/vulkano/src/command_buffer/cb/auto_barriers.rs +++ b/vulkano/src/command_buffer/cb/auto_barriers.rs @@ -65,6 +65,15 @@ unsafe impl DeviceOwned for AutoPipelineBarriersLayer unsafe impl CommandBufferBuilder for AutoPipelineBarriersLayer where I: CommandBufferBuilder { + #[inline] + fn supports_graphics(&self) -> bool { + self.inner.supports_graphics() + } + + #[inline] + fn supports_compute(&self) -> bool { + self.inner.supports_compute() + } } macro_rules! pass_through { diff --git a/vulkano/src/command_buffer/cb/context_check.rs b/vulkano/src/command_buffer/cb/context_check.rs index 33385405d..4df6096f8 100644 --- a/vulkano/src/command_buffer/cb/context_check.rs +++ b/vulkano/src/command_buffer/cb/context_check.rs @@ -64,6 +64,15 @@ unsafe impl DeviceOwned for ContextCheckLayer unsafe impl CommandBufferBuilder for ContextCheckLayer where I: CommandBufferBuilder { + #[inline] + fn supports_graphics(&self) -> bool { + self.inner.supports_graphics() + } + + #[inline] + fn supports_compute(&self) -> bool { + self.inner.supports_compute() + } } // TODO: actually implement diff --git a/vulkano/src/command_buffer/cb/device_check.rs b/vulkano/src/command_buffer/cb/device_check.rs index 10371b3f7..fd5b6005e 100644 --- a/vulkano/src/command_buffer/cb/device_check.rs +++ b/vulkano/src/command_buffer/cb/device_check.rs @@ -50,6 +50,15 @@ unsafe impl DeviceOwned for DeviceCheckLayer unsafe impl CommandBufferBuilder for DeviceCheckLayer where I: CommandBufferBuilder { + #[inline] + fn supports_graphics(&self) -> bool { + self.inner.supports_graphics() + } + + #[inline] + fn supports_compute(&self) -> bool { + self.inner.supports_compute() + } } unsafe impl CommandBufferBuild for DeviceCheckLayer diff --git a/vulkano/src/command_buffer/cb/queue_ty_check.rs b/vulkano/src/command_buffer/cb/queue_ty_check.rs index 6ab0221c9..dec1cc436 100644 --- a/vulkano/src/command_buffer/cb/queue_ty_check.rs +++ b/vulkano/src/command_buffer/cb/queue_ty_check.rs @@ -22,14 +22,22 @@ use device::DeviceOwned; /// that support graphical or compute operations. This is what this layer verifies. pub struct QueueTyCheckLayer { inner: I, + supports_graphics: bool, + supports_compute: bool, } impl QueueTyCheckLayer { /// Builds a new `QueueTyCheckLayer`. + /// + /// Note that this layer will only protect you if you pass correct values for + /// `supports_graphics` and `supports_compute`. It is not unsafe to pass wrong values, but if + /// you do so then the layer will be inefficient as a safety tool. #[inline] - pub fn new(inner: I) -> QueueTyCheckLayer { + pub fn new(inner: I, supports_graphics: bool, supports_compute: bool) -> QueueTyCheckLayer { QueueTyCheckLayer { inner: inner, + supports_graphics: supports_graphics, + supports_compute: supports_compute, } } @@ -38,6 +46,22 @@ impl QueueTyCheckLayer { pub fn into_inner(self) -> I { self.inner } + + /// Returns true if graphical operations can be added to this layer. + /// + /// This returns the same value as what was passed to the constructor. + #[inline] + pub fn supports_graphics(&self) -> bool { + self.supports_graphics + } + + /// Returns true if compute operations can be added to this layer. + /// + /// This returns the same value as what was passed to the constructor. + #[inline] + pub fn supports_compute(&self) -> bool { + self.supports_compute + } } unsafe impl DeviceOwned for QueueTyCheckLayer @@ -49,9 +73,16 @@ unsafe impl DeviceOwned for QueueTyCheckLayer } } -unsafe impl CommandBufferBuilder for QueueTyCheckLayer - where I: CommandBufferBuilder -{ +unsafe impl CommandBufferBuilder for QueueTyCheckLayer where I: DeviceOwned { + #[inline] + fn supports_graphics(&self) -> bool { + self.supports_graphics + } + + #[inline] + fn supports_compute(&self) -> bool { + self.supports_compute + } } unsafe impl CommandBufferBuild for QueueTyCheckLayer @@ -68,7 +99,10 @@ unsafe impl CommandBufferBuild for QueueTyCheckLayer // TODO: actually implement -macro_rules! pass_through { +// TODO: implement CmdExecuteCommands +//q_ty_impl!((C), commands_raw::CmdExecuteCommands); + +macro_rules! q_ty_impl_always { (($($param:ident),*), $cmd:ty) => { unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for QueueTyCheckLayer where I: AddCommand<$cmd, Out = O> @@ -79,32 +113,136 @@ macro_rules! pass_through { fn add(self, command: $cmd) -> Self::Out { QueueTyCheckLayer { inner: self.inner.add(command), + supports_graphics: self.supports_graphics, + supports_compute: self.supports_compute, } } } } } -pass_through!((Rp, F), commands_raw::CmdBeginRenderPass); -pass_through!((S, Pl), commands_raw::CmdBindDescriptorSets); -pass_through!((B), commands_raw::CmdBindIndexBuffer); -pass_through!((Pl), commands_raw::CmdBindPipeline); -pass_through!((V), commands_raw::CmdBindVertexBuffers); -pass_through!((S, D), commands_raw::CmdBlitImage); -pass_through!((), commands_raw::CmdClearAttachments); -pass_through!((S, D), commands_raw::CmdCopyBuffer); -pass_through!((S, D), commands_raw::CmdCopyBufferToImage); -pass_through!((S, D), commands_raw::CmdCopyImage); -pass_through!((), commands_raw::CmdDispatchRaw); -pass_through!((), commands_raw::CmdDrawIndexedRaw); -pass_through!((B), commands_raw::CmdDrawIndirectRaw); -pass_through!((), commands_raw::CmdDrawRaw); -pass_through!((), commands_raw::CmdEndRenderPass); -pass_through!((C), commands_raw::CmdExecuteCommands); -pass_through!((B), commands_raw::CmdFillBuffer); -pass_through!((), commands_raw::CmdNextSubpass); -pass_through!((Pc, Pl), commands_raw::CmdPushConstants); -pass_through!((S, D), commands_raw::CmdResolveImage); -pass_through!((), commands_raw::CmdSetEvent); -pass_through!((), commands_raw::CmdSetState); -pass_through!((B, D), commands_raw::CmdUpdateBuffer); +q_ty_impl_always!((S, D), commands_raw::CmdCopyBuffer); +q_ty_impl_always!((S, D), commands_raw::CmdCopyBufferToImage); +q_ty_impl_always!((S, D), commands_raw::CmdCopyImage); +q_ty_impl_always!((B), commands_raw::CmdFillBuffer); +q_ty_impl_always!((B, D), commands_raw::CmdUpdateBuffer); + +macro_rules! q_ty_impl_graphics { + (($($param:ident),*), $cmd:ty) => { + unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for QueueTyCheckLayer + where I: AddCommand<$cmd, Out = O> + { + type Out = QueueTyCheckLayer; + + #[inline] + fn add(self, command: $cmd) -> Self::Out { + assert!(self.supports_graphics()); // TODO: proper error + QueueTyCheckLayer { + inner: self.inner.add(command), + supports_graphics: self.supports_graphics, + supports_compute: self.supports_compute, + } + } + } + } +} + +q_ty_impl_graphics!((Rp, F), commands_raw::CmdBeginRenderPass); +q_ty_impl_graphics!((B), commands_raw::CmdBindIndexBuffer); +q_ty_impl_graphics!((V), commands_raw::CmdBindVertexBuffers); +q_ty_impl_graphics!((S, D), commands_raw::CmdBlitImage); +q_ty_impl_graphics!((), commands_raw::CmdClearAttachments); +q_ty_impl_graphics!((), commands_raw::CmdDrawIndexedRaw); +q_ty_impl_graphics!((B), commands_raw::CmdDrawIndirectRaw); +q_ty_impl_graphics!((), commands_raw::CmdDrawRaw); +q_ty_impl_graphics!((), commands_raw::CmdEndRenderPass); +q_ty_impl_graphics!((), commands_raw::CmdNextSubpass); +q_ty_impl_graphics!((S, D), commands_raw::CmdResolveImage); + +macro_rules! q_ty_impl_compute { + (($($param:ident),*), $cmd:ty) => { + unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for QueueTyCheckLayer + where I: AddCommand<$cmd, Out = O> + { + type Out = QueueTyCheckLayer; + + #[inline] + fn add(self, command: $cmd) -> Self::Out { + assert!(self.supports_compute()); // TODO: proper error + QueueTyCheckLayer { + inner: self.inner.add(command), + supports_graphics: self.supports_graphics, + supports_compute: self.supports_compute, + } + } + } + } +} + +q_ty_impl_compute!((), commands_raw::CmdDispatchRaw); + +macro_rules! q_ty_impl_graphics_or_compute { + (($($param:ident),*), $cmd:ty) => { + unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for QueueTyCheckLayer + where I: AddCommand<$cmd, Out = O> + { + type Out = QueueTyCheckLayer; + + #[inline] + fn add(self, command: $cmd) -> Self::Out { + assert!(self.supports_graphics() || self.supports_compute()); // TODO: proper error + QueueTyCheckLayer { + inner: self.inner.add(command), + supports_graphics: self.supports_graphics, + supports_compute: self.supports_compute, + } + } + } + } +} + +q_ty_impl_graphics_or_compute!((Pc, Pl), commands_raw::CmdPushConstants); +q_ty_impl_graphics_or_compute!((), commands_raw::CmdSetEvent); +q_ty_impl_graphics_or_compute!((), commands_raw::CmdSetState); + +unsafe impl AddCommand> for QueueTyCheckLayer + where I: AddCommand, Out = O> +{ + type Out = QueueTyCheckLayer; + + #[inline] + fn add(self, command: commands_raw::CmdBindPipeline) -> Self::Out { + if command.is_graphics() { + assert!(self.supports_graphics()); // TODO: proper error + } else { + assert!(self.supports_compute()); // TODO: proper error + } + + QueueTyCheckLayer { + inner: self.inner.add(command), + supports_graphics: self.supports_graphics, + supports_compute: self.supports_compute, + } + } +} + +unsafe impl AddCommand> for QueueTyCheckLayer + where I: AddCommand, Out = O> +{ + type Out = QueueTyCheckLayer; + + #[inline] + fn add(self, command: commands_raw::CmdBindDescriptorSets) -> Self::Out { + if command.is_graphics() { + assert!(self.supports_graphics()); // TODO: proper error + } else { + assert!(self.supports_compute()); // TODO: proper error + } + + QueueTyCheckLayer { + inner: self.inner.add(command), + supports_graphics: self.supports_graphics, + supports_compute: self.supports_compute, + } + } +} diff --git a/vulkano/src/command_buffer/cb/state_cache.rs b/vulkano/src/command_buffer/cb/state_cache.rs index 3a844e804..73b8e3868 100644 --- a/vulkano/src/command_buffer/cb/state_cache.rs +++ b/vulkano/src/command_buffer/cb/state_cache.rs @@ -78,6 +78,15 @@ unsafe impl DeviceOwned for StateCacheLayer unsafe impl CommandBufferBuilder for StateCacheLayer where I: CommandBufferBuilder { + #[inline] + fn supports_graphics(&self) -> bool { + self.inner.supports_graphics() + } + + #[inline] + fn supports_compute(&self) -> bool { + self.inner.supports_compute() + } } unsafe impl AddCommand> for StateCacheLayer diff --git a/vulkano/src/command_buffer/cb/submit_sync.rs b/vulkano/src/command_buffer/cb/submit_sync.rs index ac155bb9b..75cfbd6c9 100644 --- a/vulkano/src/command_buffer/cb/submit_sync.rs +++ b/vulkano/src/command_buffer/cb/submit_sync.rs @@ -106,6 +106,15 @@ unsafe impl DeviceOwned for SubmitSyncBuilderLayer unsafe impl CommandBufferBuilder for SubmitSyncBuilderLayer where I: CommandBufferBuilder { + #[inline] + fn supports_graphics(&self) -> bool { + self.inner.supports_graphics() + } + + #[inline] + fn supports_compute(&self) -> bool { + self.inner.supports_compute() + } } // FIXME: implement manually diff --git a/vulkano/src/command_buffer/commands_raw/bind_descriptor_sets.rs b/vulkano/src/command_buffer/commands_raw/bind_descriptor_sets.rs index e639188f4..93ac9365c 100644 --- a/vulkano/src/command_buffer/commands_raw/bind_descriptor_sets.rs +++ b/vulkano/src/command_buffer/commands_raw/bind_descriptor_sets.rs @@ -95,6 +95,15 @@ impl CmdBindDescriptorSets } } +impl CmdBindDescriptorSets { + /// True if we bind to the graphics pipeline. False if the compute pipeline. + // TODO: should be an enum? + #[inline] + pub fn is_graphics(&self) -> bool { + self.pipeline_ty == vk::PIPELINE_BIND_POINT_GRAPHICS + } +} + unsafe impl DeviceOwned for CmdBindDescriptorSets where Pl: DeviceOwned {