1 // Copyright (c) 2016 The vulkano developers 2 // Licensed under the Apache License, Version 2.0 3 // <LICENSE-APACHE or 4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT 5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, 6 // at your option. All files in the project carrying such 7 // notice may not be copied, modified, or distributed except 8 // according to those terms. 9 10 //! Commands that the GPU will execute (includes draw commands). 11 //! 12 //! With Vulkan, before the GPU can do anything you must create a `CommandBuffer`. A command buffer 13 //! is a list of commands that will executed by the GPU. Once a command buffer is created, you can 14 //! execute it. A command buffer must always be created even for the most simple tasks. 15 //! 16 //! # Primary and secondary command buffers. 17 //! 18 //! There are three types of command buffers: 19 //! 20 //! - **Primary command buffers**. They can contain any command. They are the only type of command 21 //! buffer that can be submitted to a queue. 22 //! - **Secondary "graphics" command buffers**. They can only contain draw and clear commands. 23 //! They can only be called from a primary command buffer when inside a render pass. 24 //! - **Secondary "compute" command buffers**. They can only contain non-render-pass-related 25 //! commands (ie. everything but drawing, clearing, etc.) and cannot enter a render pass. They 26 //! can only be called from a primary command buffer outside of a render pass. 27 //! 28 //! Using secondary command buffers leads to slightly lower performance on the GPU, but they have 29 //! two advantages on the CPU side: 30 //! 31 //! - Building a command buffer is a single-threaded operation, but by using secondary command 32 //! buffers you can build multiple secondary command buffers in multiple threads simultaneously. 33 //! - Secondary command buffers can be kept alive between frames. When you always repeat the same 34 //! operations, it might be a good idea to build a secondary command buffer once at 35 //! initialization and then reuse it afterwards. 36 //! 37 //! # The `AutoCommandBufferBuilder` 38 //! 39 //! The most basic (and recommended) way to create a command buffer is to create a 40 //! [`AutoCommandBufferBuilder`](struct.AutoCommandBufferBuilder.html), then record commands to it. 41 //! When you are done adding commands, build it to obtain either a `PrimaryAutoCommandBuffer` or 42 //! `SecondAutoCommandBuffer`. 43 //! 44 //! Once built, use [the `PrimaryCommandBuffer` trait](trait.PrimaryCommandBuffer.html) to submit the 45 //! command buffer. Submitting a command buffer returns an object that implements the `GpuFuture` trait 46 //! and that represents the moment when the execution will end on the GPU. 47 //! 48 //! ``` 49 //! use vulkano::command_buffer::AutoCommandBufferBuilder; 50 //! use vulkano::command_buffer::CommandBufferUsage; 51 //! use vulkano::command_buffer::PrimaryCommandBuffer; 52 //! 53 //! # let device: std::sync::Arc<vulkano::device::Device> = return; 54 //! # let queue: std::sync::Arc<vulkano::device::Queue> = return; 55 //! let cb = AutoCommandBufferBuilder::primary( 56 //! device.clone(), 57 //! queue.family(), 58 //! CommandBufferUsage::MultipleSubmit 59 //! ).unwrap() 60 //! // TODO: add an actual command to this example 61 //! .build().unwrap(); 62 //! 63 //! let _future = cb.execute(queue.clone()); 64 //! ``` 65 //! 66 //! # Internal architecture of vulkano 67 //! 68 //! The `commands_raw` and `commands_extra` modules contain structs that correspond to various 69 //! commands that can be added to command buffer builders. A command can be added to a command 70 //! buffer builder by using the `AddCommand<C>` trait, where `C` is the command struct. 71 //! 72 //! The `AutoCommandBufferBuilder` internally uses a `UnsafeCommandBufferBuilder` wrapped around 73 //! multiple layers. See the `cb` module for more information. 74 //! 75 //! Command pools are automatically handled by default, but vulkano also allows you to use 76 //! alternative command pool implementations and use them. See the `pool` module for more 77 //! information. 78 79 pub use self::auto::AutoCommandBufferBuilder; 80 pub use self::auto::AutoCommandBufferBuilderContextError; 81 pub use self::auto::BeginError; 82 pub use self::auto::BeginQueryError; 83 pub use self::auto::BeginRenderPassError; 84 pub use self::auto::BlitImageError; 85 pub use self::auto::BuildError; 86 pub use self::auto::ClearColorImageError; 87 pub use self::auto::CopyBufferError; 88 pub use self::auto::CopyBufferImageError; 89 pub use self::auto::CopyImageError; 90 pub use self::auto::CopyQueryPoolResultsError; 91 pub use self::auto::DebugMarkerError; 92 pub use self::auto::DispatchError; 93 pub use self::auto::DispatchIndirectError; 94 pub use self::auto::DrawError; 95 pub use self::auto::DrawIndexedError; 96 pub use self::auto::DrawIndexedIndirectError; 97 pub use self::auto::DrawIndirectError; 98 pub use self::auto::EndQueryError; 99 pub use self::auto::ExecuteCommandsError; 100 pub use self::auto::FillBufferError; 101 pub use self::auto::PrimaryAutoCommandBuffer; 102 pub use self::auto::ResetQueryPoolError; 103 pub use self::auto::SecondaryAutoCommandBuffer; 104 pub use self::auto::UpdateBufferError; 105 pub use self::auto::WriteTimestampError; 106 pub use self::state_cacher::StateCacher; 107 pub use self::state_cacher::StateCacherOutcome; 108 pub use self::traits::CommandBufferExecError; 109 pub use self::traits::CommandBufferExecFuture; 110 pub use self::traits::PrimaryCommandBuffer; 111 pub use self::traits::SecondaryCommandBuffer; 112 use crate::pipeline::depth_stencil::DynamicStencilValue; 113 use crate::pipeline::viewport::{Scissor, Viewport}; 114 use crate::query::QueryControlFlags; 115 use crate::query::QueryPipelineStatisticFlags; 116 use crate::render_pass::{Framebuffer, Subpass}; 117 use std::sync::Arc; 118 119 mod auto; 120 pub mod pool; 121 mod state_cacher; 122 pub mod submit; 123 pub mod synced; 124 pub mod sys; 125 mod traits; 126 pub mod validity; 127 128 #[derive(Debug, Clone, Copy)] 129 pub enum ImageUninitializedSafe { 130 Safe, 131 Unsafe, 132 } 133 134 impl ImageUninitializedSafe { is_safe(&self) -> bool135 pub fn is_safe(&self) -> bool { 136 match self { 137 Self::Safe => true, 138 Self::Unsafe => false, 139 } 140 } 141 } 142 143 #[repr(C)] 144 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 145 pub struct DrawIndirectCommand { 146 pub vertex_count: u32, 147 pub instance_count: u32, 148 pub first_vertex: u32, 149 pub first_instance: u32, 150 } 151 152 #[repr(C)] 153 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 154 pub struct DrawIndexedIndirectCommand { 155 pub index_count: u32, 156 pub instance_count: u32, 157 pub first_index: u32, 158 pub vertex_offset: u32, 159 pub first_instance: u32, 160 } 161 162 #[repr(C)] 163 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 164 pub struct DispatchIndirectCommand { 165 pub x: u32, 166 pub y: u32, 167 pub z: u32, 168 } 169 170 /// The dynamic state to use for a draw command. 171 // TODO: probably not the right location 172 #[derive(Debug, Clone)] 173 pub struct DynamicState { 174 pub line_width: Option<f32>, 175 pub viewports: Option<Vec<Viewport>>, 176 pub scissors: Option<Vec<Scissor>>, 177 pub compare_mask: Option<DynamicStencilValue>, 178 pub write_mask: Option<DynamicStencilValue>, 179 pub reference: Option<DynamicStencilValue>, 180 } 181 182 impl DynamicState { 183 #[inline] none() -> DynamicState184 pub fn none() -> DynamicState { 185 DynamicState { 186 line_width: None, 187 viewports: None, 188 scissors: None, 189 compare_mask: None, 190 write_mask: None, 191 reference: None, 192 } 193 } 194 } 195 196 impl Default for DynamicState { 197 #[inline] default() -> DynamicState198 fn default() -> DynamicState { 199 DynamicState::none() 200 } 201 } 202 203 /// Describes what a subpass in a command buffer will contain. 204 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 205 #[repr(i32)] 206 pub enum SubpassContents { 207 /// The subpass will only directly contain commands. 208 Inline = ash::vk::SubpassContents::INLINE.as_raw(), 209 /// The subpass will only contain secondary command buffers invocations. 210 SecondaryCommandBuffers = ash::vk::SubpassContents::SECONDARY_COMMAND_BUFFERS.as_raw(), 211 } 212 213 impl From<SubpassContents> for ash::vk::SubpassContents { 214 #[inline] from(val: SubpassContents) -> Self215 fn from(val: SubpassContents) -> Self { 216 Self::from_raw(val as i32) 217 } 218 } 219 220 /// Determines the kind of command buffer to create. 221 #[derive(Debug, Clone)] 222 pub enum CommandBufferLevel<F> { 223 /// Primary command buffers can be executed on a queue, and can call secondary command buffers. 224 /// Render passes must begin and end within the same primary command buffer. 225 Primary, 226 227 /// Secondary command buffers cannot be executed on a queue, but can be executed by a primary 228 /// command buffer. If created for a render pass, they must fit within a single render subpass. 229 Secondary(CommandBufferInheritance<F>), 230 } 231 232 /// The context that a secondary command buffer can inherit from the primary command 233 /// buffer it's executed in. 234 #[derive(Clone, Debug, Default)] 235 pub struct CommandBufferInheritance<F> { 236 /// If `Some`, the secondary command buffer is required to be executed within a specific 237 /// render subpass, and can only call draw operations. 238 /// If `None`, it must be executed outside a render pass, and can execute dispatch and transfer 239 /// operations, but not drawing operations. 240 render_pass: Option<CommandBufferInheritanceRenderPass<F>>, 241 242 /// If `Some`, the secondary command buffer is allowed to be executed within a primary that has 243 /// an occlusion query active. The inner `QueryControlFlags` specifies which flags the 244 /// active occlusion is allowed to have enabled. 245 /// If `None`, the primary command buffer cannot have an occlusion query active when this 246 /// secondary command buffer is executed. 247 /// 248 /// The `inherited_queries` feature must be enabled if this is `Some`. 249 occlusion_query: Option<QueryControlFlags>, 250 251 /// Which pipeline statistics queries are allowed to be active on the primary command buffer 252 /// when this secondary command buffer is executed. 253 /// 254 /// The `pipeline_statistics_query` feature must be enabled if any of the flags of this value 255 /// are set. 256 query_statistics_flags: QueryPipelineStatisticFlags, 257 } 258 259 /// The render pass context that a secondary command buffer is created for. 260 #[derive(Debug, Clone)] 261 pub struct CommandBufferInheritanceRenderPass<F> { 262 /// The render subpass that this secondary command buffer must be executed within. 263 pub subpass: Subpass, 264 265 /// The framebuffer object that will be used when calling the command buffer. 266 /// This parameter is optional and is an optimization hint for the implementation. 267 pub framebuffer: Option<F>, 268 } 269 270 impl CommandBufferLevel<Framebuffer<()>> { 271 /// Equivalent to `Kind::Primary`. 272 /// 273 /// > **Note**: If you use `let kind = Kind::Primary;` in your code, you will probably get a 274 /// > compilation error because the Rust compiler couldn't determine the template parameters 275 /// > of `Kind`. To solve that problem in an easy way you can use this function instead. 276 #[inline] primary() -> CommandBufferLevel<Arc<Framebuffer<()>>>277 pub fn primary() -> CommandBufferLevel<Arc<Framebuffer<()>>> { 278 CommandBufferLevel::Primary 279 } 280 281 /// Equivalent to `Kind::Secondary`. 282 /// 283 /// > **Note**: If you use `let kind = Kind::Secondary;` in your code, you will probably get a 284 /// > compilation error because the Rust compiler couldn't determine the template parameters 285 /// > of `Kind`. To solve that problem in an easy way you can use this function instead. 286 #[inline] secondary( occlusion_query: Option<QueryControlFlags>, query_statistics_flags: QueryPipelineStatisticFlags, ) -> CommandBufferLevel<Arc<Framebuffer<()>>>287 pub fn secondary( 288 occlusion_query: Option<QueryControlFlags>, 289 query_statistics_flags: QueryPipelineStatisticFlags, 290 ) -> CommandBufferLevel<Arc<Framebuffer<()>>> { 291 CommandBufferLevel::Secondary(CommandBufferInheritance { 292 render_pass: None, 293 occlusion_query, 294 query_statistics_flags, 295 }) 296 } 297 } 298 299 /// Usage flags to pass when creating a command buffer. 300 /// 301 /// The safest option is `SimultaneousUse`, but it may be slower than the other two. 302 // NOTE: The ordering is important: the variants are listed from least to most permissive! 303 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] 304 #[repr(u32)] 305 pub enum CommandBufferUsage { 306 /// The command buffer can only be submitted once before being destroyed. Any further submit is 307 /// forbidden. This makes it possible for the implementation to perform additional 308 /// optimizations. 309 OneTimeSubmit = ash::vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT.as_raw(), 310 311 /// The command buffer can be used multiple times, but must not execute or record more than once 312 /// simultaneously. In other words, it is as if executing the command buffer borrows it mutably. 313 MultipleSubmit = 0, 314 315 /// The command buffer can be executed multiple times in parallel on different queues. 316 /// If it's a secondary command buffer, it can be recorded to multiple primary command buffers 317 /// at once. 318 SimultaneousUse = ash::vk::CommandBufferUsageFlags::SIMULTANEOUS_USE.as_raw(), 319 } 320 321 impl From<CommandBufferUsage> for ash::vk::CommandBufferUsageFlags { 322 #[inline] from(val: CommandBufferUsage) -> Self323 fn from(val: CommandBufferUsage) -> Self { 324 Self::from_raw(val as u32) 325 } 326 } 327