aboutsummaryrefslogtreecommitdiff
path: root/src/command_buffer/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/command_buffer/mod.rs')
-rw-r--r--src/command_buffer/mod.rs326
1 files changed, 326 insertions, 0 deletions
diff --git a/src/command_buffer/mod.rs b/src/command_buffer/mod.rs
new file mode 100644
index 0000000..b439a4d
--- /dev/null
+++ b/src/command_buffer/mod.rs
@@ -0,0 +1,326 @@
+// Copyright (c) 2016 The vulkano developers
+// Licensed under the Apache License, Version 2.0
+// <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
+// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
+// at your option. All files in the project carrying such
+// notice may not be copied, modified, or distributed except
+// according to those terms.
+
+//! Commands that the GPU will execute (includes draw commands).
+//!
+//! With Vulkan, before the GPU can do anything you must create a `CommandBuffer`. A command buffer
+//! is a list of commands that will executed by the GPU. Once a command buffer is created, you can
+//! execute it. A command buffer must always be created even for the most simple tasks.
+//!
+//! # Primary and secondary command buffers.
+//!
+//! There are three types of command buffers:
+//!
+//! - **Primary command buffers**. They can contain any command. They are the only type of command
+//! buffer that can be submitted to a queue.
+//! - **Secondary "graphics" command buffers**. They can only contain draw and clear commands.
+//! They can only be called from a primary command buffer when inside a render pass.
+//! - **Secondary "compute" command buffers**. They can only contain non-render-pass-related
+//! commands (ie. everything but drawing, clearing, etc.) and cannot enter a render pass. They
+//! can only be called from a primary command buffer outside of a render pass.
+//!
+//! Using secondary command buffers leads to slightly lower performance on the GPU, but they have
+//! two advantages on the CPU side:
+//!
+//! - Building a command buffer is a single-threaded operation, but by using secondary command
+//! buffers you can build multiple secondary command buffers in multiple threads simultaneously.
+//! - Secondary command buffers can be kept alive between frames. When you always repeat the same
+//! operations, it might be a good idea to build a secondary command buffer once at
+//! initialization and then reuse it afterwards.
+//!
+//! # The `AutoCommandBufferBuilder`
+//!
+//! The most basic (and recommended) way to create a command buffer is to create a
+//! [`AutoCommandBufferBuilder`](struct.AutoCommandBufferBuilder.html), then record commands to it.
+//! When you are done adding commands, build it to obtain either a `PrimaryAutoCommandBuffer` or
+//! `SecondAutoCommandBuffer`.
+//!
+//! Once built, use [the `PrimaryCommandBuffer` trait](trait.PrimaryCommandBuffer.html) to submit the
+//! command buffer. Submitting a command buffer returns an object that implements the `GpuFuture` trait
+//! and that represents the moment when the execution will end on the GPU.
+//!
+//! ```
+//! use vulkano::command_buffer::AutoCommandBufferBuilder;
+//! use vulkano::command_buffer::CommandBufferUsage;
+//! use vulkano::command_buffer::PrimaryCommandBuffer;
+//!
+//! # let device: std::sync::Arc<vulkano::device::Device> = return;
+//! # let queue: std::sync::Arc<vulkano::device::Queue> = return;
+//! let cb = AutoCommandBufferBuilder::primary(
+//! device.clone(),
+//! queue.family(),
+//! CommandBufferUsage::MultipleSubmit
+//! ).unwrap()
+//! // TODO: add an actual command to this example
+//! .build().unwrap();
+//!
+//! let _future = cb.execute(queue.clone());
+//! ```
+//!
+//! # Internal architecture of vulkano
+//!
+//! The `commands_raw` and `commands_extra` modules contain structs that correspond to various
+//! commands that can be added to command buffer builders. A command can be added to a command
+//! buffer builder by using the `AddCommand<C>` trait, where `C` is the command struct.
+//!
+//! The `AutoCommandBufferBuilder` internally uses a `UnsafeCommandBufferBuilder` wrapped around
+//! multiple layers. See the `cb` module for more information.
+//!
+//! Command pools are automatically handled by default, but vulkano also allows you to use
+//! alternative command pool implementations and use them. See the `pool` module for more
+//! information.
+
+pub use self::auto::AutoCommandBufferBuilder;
+pub use self::auto::AutoCommandBufferBuilderContextError;
+pub use self::auto::BeginError;
+pub use self::auto::BeginQueryError;
+pub use self::auto::BeginRenderPassError;
+pub use self::auto::BlitImageError;
+pub use self::auto::BuildError;
+pub use self::auto::ClearColorImageError;
+pub use self::auto::CopyBufferError;
+pub use self::auto::CopyBufferImageError;
+pub use self::auto::CopyImageError;
+pub use self::auto::CopyQueryPoolResultsError;
+pub use self::auto::DebugMarkerError;
+pub use self::auto::DispatchError;
+pub use self::auto::DispatchIndirectError;
+pub use self::auto::DrawError;
+pub use self::auto::DrawIndexedError;
+pub use self::auto::DrawIndexedIndirectError;
+pub use self::auto::DrawIndirectError;
+pub use self::auto::EndQueryError;
+pub use self::auto::ExecuteCommandsError;
+pub use self::auto::FillBufferError;
+pub use self::auto::PrimaryAutoCommandBuffer;
+pub use self::auto::ResetQueryPoolError;
+pub use self::auto::SecondaryAutoCommandBuffer;
+pub use self::auto::UpdateBufferError;
+pub use self::auto::WriteTimestampError;
+pub use self::state_cacher::StateCacher;
+pub use self::state_cacher::StateCacherOutcome;
+pub use self::traits::CommandBufferExecError;
+pub use self::traits::CommandBufferExecFuture;
+pub use self::traits::PrimaryCommandBuffer;
+pub use self::traits::SecondaryCommandBuffer;
+use crate::pipeline::depth_stencil::DynamicStencilValue;
+use crate::pipeline::viewport::{Scissor, Viewport};
+use crate::query::QueryControlFlags;
+use crate::query::QueryPipelineStatisticFlags;
+use crate::render_pass::{Framebuffer, Subpass};
+use std::sync::Arc;
+
+mod auto;
+pub mod pool;
+mod state_cacher;
+pub mod submit;
+pub mod synced;
+pub mod sys;
+mod traits;
+pub mod validity;
+
+#[derive(Debug, Clone, Copy)]
+pub enum ImageUninitializedSafe {
+ Safe,
+ Unsafe,
+}
+
+impl ImageUninitializedSafe {
+ pub fn is_safe(&self) -> bool {
+ match self {
+ Self::Safe => true,
+ Self::Unsafe => false,
+ }
+ }
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct DrawIndirectCommand {
+ pub vertex_count: u32,
+ pub instance_count: u32,
+ pub first_vertex: u32,
+ pub first_instance: u32,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct DrawIndexedIndirectCommand {
+ pub index_count: u32,
+ pub instance_count: u32,
+ pub first_index: u32,
+ pub vertex_offset: u32,
+ pub first_instance: u32,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct DispatchIndirectCommand {
+ pub x: u32,
+ pub y: u32,
+ pub z: u32,
+}
+
+/// The dynamic state to use for a draw command.
+// TODO: probably not the right location
+#[derive(Debug, Clone)]
+pub struct DynamicState {
+ pub line_width: Option<f32>,
+ pub viewports: Option<Vec<Viewport>>,
+ pub scissors: Option<Vec<Scissor>>,
+ pub compare_mask: Option<DynamicStencilValue>,
+ pub write_mask: Option<DynamicStencilValue>,
+ pub reference: Option<DynamicStencilValue>,
+}
+
+impl DynamicState {
+ #[inline]
+ pub fn none() -> DynamicState {
+ DynamicState {
+ line_width: None,
+ viewports: None,
+ scissors: None,
+ compare_mask: None,
+ write_mask: None,
+ reference: None,
+ }
+ }
+}
+
+impl Default for DynamicState {
+ #[inline]
+ fn default() -> DynamicState {
+ DynamicState::none()
+ }
+}
+
+/// Describes what a subpass in a command buffer will contain.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+#[repr(i32)]
+pub enum SubpassContents {
+ /// The subpass will only directly contain commands.
+ Inline = ash::vk::SubpassContents::INLINE.as_raw(),
+ /// The subpass will only contain secondary command buffers invocations.
+ SecondaryCommandBuffers = ash::vk::SubpassContents::SECONDARY_COMMAND_BUFFERS.as_raw(),
+}
+
+impl From<SubpassContents> for ash::vk::SubpassContents {
+ #[inline]
+ fn from(val: SubpassContents) -> Self {
+ Self::from_raw(val as i32)
+ }
+}
+
+/// Determines the kind of command buffer to create.
+#[derive(Debug, Clone)]
+pub enum CommandBufferLevel<F> {
+ /// Primary command buffers can be executed on a queue, and can call secondary command buffers.
+ /// Render passes must begin and end within the same primary command buffer.
+ Primary,
+
+ /// Secondary command buffers cannot be executed on a queue, but can be executed by a primary
+ /// command buffer. If created for a render pass, they must fit within a single render subpass.
+ Secondary(CommandBufferInheritance<F>),
+}
+
+/// The context that a secondary command buffer can inherit from the primary command
+/// buffer it's executed in.
+#[derive(Clone, Debug, Default)]
+pub struct CommandBufferInheritance<F> {
+ /// If `Some`, the secondary command buffer is required to be executed within a specific
+ /// render subpass, and can only call draw operations.
+ /// If `None`, it must be executed outside a render pass, and can execute dispatch and transfer
+ /// operations, but not drawing operations.
+ render_pass: Option<CommandBufferInheritanceRenderPass<F>>,
+
+ /// If `Some`, the secondary command buffer is allowed to be executed within a primary that has
+ /// an occlusion query active. The inner `QueryControlFlags` specifies which flags the
+ /// active occlusion is allowed to have enabled.
+ /// If `None`, the primary command buffer cannot have an occlusion query active when this
+ /// secondary command buffer is executed.
+ ///
+ /// The `inherited_queries` feature must be enabled if this is `Some`.
+ occlusion_query: Option<QueryControlFlags>,
+
+ /// Which pipeline statistics queries are allowed to be active on the primary command buffer
+ /// when this secondary command buffer is executed.
+ ///
+ /// The `pipeline_statistics_query` feature must be enabled if any of the flags of this value
+ /// are set.
+ query_statistics_flags: QueryPipelineStatisticFlags,
+}
+
+/// The render pass context that a secondary command buffer is created for.
+#[derive(Debug, Clone)]
+pub struct CommandBufferInheritanceRenderPass<F> {
+ /// The render subpass that this secondary command buffer must be executed within.
+ pub subpass: Subpass,
+
+ /// The framebuffer object that will be used when calling the command buffer.
+ /// This parameter is optional and is an optimization hint for the implementation.
+ pub framebuffer: Option<F>,
+}
+
+impl CommandBufferLevel<Framebuffer<()>> {
+ /// Equivalent to `Kind::Primary`.
+ ///
+ /// > **Note**: If you use `let kind = Kind::Primary;` in your code, you will probably get a
+ /// > compilation error because the Rust compiler couldn't determine the template parameters
+ /// > of `Kind`. To solve that problem in an easy way you can use this function instead.
+ #[inline]
+ pub fn primary() -> CommandBufferLevel<Arc<Framebuffer<()>>> {
+ CommandBufferLevel::Primary
+ }
+
+ /// Equivalent to `Kind::Secondary`.
+ ///
+ /// > **Note**: If you use `let kind = Kind::Secondary;` in your code, you will probably get a
+ /// > compilation error because the Rust compiler couldn't determine the template parameters
+ /// > of `Kind`. To solve that problem in an easy way you can use this function instead.
+ #[inline]
+ pub fn secondary(
+ occlusion_query: Option<QueryControlFlags>,
+ query_statistics_flags: QueryPipelineStatisticFlags,
+ ) -> CommandBufferLevel<Arc<Framebuffer<()>>> {
+ CommandBufferLevel::Secondary(CommandBufferInheritance {
+ render_pass: None,
+ occlusion_query,
+ query_statistics_flags,
+ })
+ }
+}
+
+/// Usage flags to pass when creating a command buffer.
+///
+/// The safest option is `SimultaneousUse`, but it may be slower than the other two.
+// NOTE: The ordering is important: the variants are listed from least to most permissive!
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[repr(u32)]
+pub enum CommandBufferUsage {
+ /// The command buffer can only be submitted once before being destroyed. Any further submit is
+ /// forbidden. This makes it possible for the implementation to perform additional
+ /// optimizations.
+ OneTimeSubmit = ash::vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT.as_raw(),
+
+ /// The command buffer can be used multiple times, but must not execute or record more than once
+ /// simultaneously. In other words, it is as if executing the command buffer borrows it mutably.
+ MultipleSubmit = 0,
+
+ /// The command buffer can be executed multiple times in parallel on different queues.
+ /// If it's a secondary command buffer, it can be recorded to multiple primary command buffers
+ /// at once.
+ SimultaneousUse = ash::vk::CommandBufferUsageFlags::SIMULTANEOUS_USE.as_raw(),
+}
+
+impl From<CommandBufferUsage> for ash::vk::CommandBufferUsageFlags {
+ #[inline]
+ fn from(val: CommandBufferUsage) -> Self {
+ Self::from_raw(val as u32)
+ }
+}