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 //! Recording commands to execute on the device. 11 //! 12 //! With Vulkan, to get the device to perform work, even relatively simple tasks, you must create a 13 //! command buffer. A command buffer is a list of commands that will executed by the device. 14 //! You must first record commands to a command buffer builder, then build it into an actual 15 //! command buffer, and then it can be used. Depending on how a command buffer is created, it can 16 //! be used only once, or reused many times. 17 //! 18 //! # Command pools and allocators 19 //! 20 //! Command buffers are allocated from *command pools*. A command pool holds memory that is used to 21 //! record the sequence of commands in a command buffer. Command pools are not thread-safe, and 22 //! therefore commands cannot be recorded to a single command buffer from multiple threads at a 23 //! time. 24 //! 25 //! Raw command pools are unsafe to use, so Vulkano uses [command buffer allocators] to manage 26 //! command buffers and pools, to ensure their memory is used efficiently, and to protect against 27 //! invalid usage. Vulkano provides the [`StandardCommandBufferAllocator`] for this purpose, but 28 //! you can also create your own by implementing the [`CommandBufferAllocator`] trait. 29 //! 30 //! # Primary and secondary command buffers 31 //! 32 //! There are two levels of command buffers: 33 //! 34 //! - [`PrimaryCommandBufferAbstract`] can be executed on a queue, and is the main command buffer 35 //! type. It cannot be executed within another command buffer. 36 //! - [`SecondaryCommandBufferAbstract`] can only be executed within a primary command buffer, 37 //! not directly on a queue. 38 //! 39 //! Using secondary command buffers, there is slightly more overhead than using primary command 40 //! buffers alone, but there are also advantages. A single command buffer cannot be recorded 41 //! from multiple threads at a time, so if you want to divide the recording work among several 42 //! threads, each thread must record its own command buffer. While it is possible for these to be 43 //! all primary command buffers, there are limitations: a render pass or query cannot span multiple 44 //! primary command buffers, while secondary command buffers can [inherit] this state from their 45 //! parent primary command buffer. Therefore, to have a single render pass or query that is shared 46 //! across all the command buffers, you must record secondary command buffers. 47 //! 48 //! # Recording a command buffer 49 //! 50 //! To record a new command buffer, the most direct way is to create a new 51 //! [`AutoCommandBufferBuilder`]. You can then call methods on this object to record new commands to 52 //! the command buffer. When you are done recording, you call [`build`] to finalise the command 53 //! buffer and turn it into either a [`PrimaryCommandBufferAbstract`] or a 54 //! [`SecondaryCommandBufferAbstract`]. 55 //! 56 // //! Using the standard `CommandBufferBuilder`, you must enter synchronization commands such as 57 // //! [pipeline barriers], to ensure that there are no races and memory access hazards. This can be 58 // //! difficult to do manually, so Vulkano also provides an alternative builder, 59 // //! [`AutoCommandBufferBuilder`]. Using this builder, you do not have to worry about managing 60 // //! synchronization, but the end result may not be quite as efficient. 61 //! 62 //! # Submitting a primary command buffer 63 //! 64 //! Once primary a command buffer is recorded and built, you can use the 65 //! [`PrimaryCommandBufferAbstract`] trait to submit the command buffer to a queue. Submitting a 66 //! command buffer returns an object that implements the [`GpuFuture`] trait and that represents 67 //! the moment when the execution will end on the GPU. 68 //! 69 //! ``` 70 //! use vulkano::command_buffer::AutoCommandBufferBuilder; 71 //! use vulkano::command_buffer::CommandBufferUsage; 72 //! use vulkano::command_buffer::PrimaryCommandBufferAbstract; 73 //! use vulkano::command_buffer::SubpassContents; 74 //! 75 //! # use vulkano::{buffer::BufferContents, pipeline::graphics::vertex_input::Vertex}; 76 //! 77 //! # #[derive(BufferContents, Vertex)] 78 //! # #[repr(C)] 79 //! # struct PosVertex { 80 //! # #[format(R32G32B32_SFLOAT)] 81 //! # position: [f32; 3] 82 //! # }; 83 //! # let device: std::sync::Arc<vulkano::device::Device> = return; 84 //! # let queue: std::sync::Arc<vulkano::device::Queue> = return; 85 //! # let vertex_buffer: vulkano::buffer::Subbuffer<[PosVertex]> = return; 86 //! # let render_pass_begin_info: vulkano::command_buffer::RenderPassBeginInfo = return; 87 //! # let graphics_pipeline: std::sync::Arc<vulkano::pipeline::graphics::GraphicsPipeline> = return; 88 //! # let command_buffer_allocator: vulkano::command_buffer::allocator::StandardCommandBufferAllocator = return; 89 //! let cb = AutoCommandBufferBuilder::primary( 90 //! &command_buffer_allocator, 91 //! queue.queue_family_index(), 92 //! CommandBufferUsage::MultipleSubmit 93 //! ).unwrap() 94 //! .begin_render_pass(render_pass_begin_info, SubpassContents::Inline).unwrap() 95 //! .bind_pipeline_graphics(graphics_pipeline.clone()) 96 //! .bind_vertex_buffers(0, vertex_buffer.clone()) 97 //! .draw(vertex_buffer.len() as u32, 1, 0, 0).unwrap() 98 //! .end_render_pass().unwrap() 99 //! .build().unwrap(); 100 //! 101 //! let _future = cb.execute(queue.clone()); 102 //! ``` 103 //! 104 //! [`StandardCommandBufferAllocator`]: self::allocator::StandardCommandBufferAllocator 105 //! [`CommandBufferAllocator`]: self::allocator::CommandBufferAllocator 106 //! [inherit]: CommandBufferInheritanceInfo 107 //! [`build`]: CommandBufferBuilder::build 108 //! [pipeline barriers]: CommandBufferBuilder::pipeline_barrier 109 //! [`GpuFuture`]: crate::sync::GpuFuture 110 111 #[doc(no_inline)] 112 pub(crate) use self::standard::{PrimaryCommandBuffer, SecondaryCommandBuffer}; 113 pub use self::{ 114 auto::{ 115 AutoCommandBufferBuilder, BuildError, CommandBufferBeginError, PrimaryAutoCommandBuffer, 116 SecondaryAutoCommandBuffer, 117 }, 118 commands::{ 119 clear::{ClearColorImageInfo, ClearDepthStencilImageInfo, ClearError}, 120 copy::{ 121 BlitImageInfo, BufferCopy, BufferImageCopy, CopyBufferInfo, CopyBufferInfoTyped, 122 CopyBufferToImageInfo, CopyError, CopyErrorResource, CopyImageInfo, 123 CopyImageToBufferInfo, ImageBlit, ImageCopy, ImageResolve, ResolveImageInfo, 124 }, 125 debug::DebugUtilsError, 126 pipeline::PipelineExecutionError, 127 query::QueryError, 128 render_pass::{ 129 ClearAttachment, ClearRect, RenderPassBeginInfo, RenderPassError, 130 RenderingAttachmentInfo, RenderingAttachmentResolveInfo, RenderingInfo, 131 }, 132 secondary::ExecuteCommandsError, 133 }, 134 traits::{ 135 CommandBufferExecError, CommandBufferExecFuture, PrimaryCommandBufferAbstract, 136 SecondaryCommandBufferAbstract, 137 }, 138 }; 139 use crate::{ 140 buffer::{Buffer, Subbuffer}, 141 format::Format, 142 image::{sys::Image, ImageAccess, ImageLayout, ImageSubresourceRange, SampleCount}, 143 macros::vulkan_enum, 144 query::{QueryControlFlags, QueryPipelineStatisticFlags}, 145 range_map::RangeMap, 146 render_pass::{Framebuffer, Subpass}, 147 sync::{semaphore::Semaphore, PipelineMemoryAccess, PipelineStages}, 148 DeviceSize, 149 }; 150 use ahash::HashMap; 151 use bytemuck::{Pod, Zeroable}; 152 use std::{ops::Range, sync::Arc}; 153 154 pub mod allocator; 155 mod auto; 156 mod commands; 157 pub mod pool; 158 pub(crate) mod standard; 159 pub mod synced; 160 pub mod sys; 161 mod traits; 162 163 #[repr(C)] 164 #[derive(Clone, Copy, Debug, Default, Zeroable, Pod, PartialEq, Eq)] 165 pub struct DrawIndirectCommand { 166 pub vertex_count: u32, 167 pub instance_count: u32, 168 pub first_vertex: u32, 169 pub first_instance: u32, 170 } 171 172 #[repr(C)] 173 #[derive(Clone, Copy, Debug, Default, Zeroable, Pod, PartialEq, Eq)] 174 pub struct DrawIndexedIndirectCommand { 175 pub index_count: u32, 176 pub instance_count: u32, 177 pub first_index: u32, 178 pub vertex_offset: u32, 179 pub first_instance: u32, 180 } 181 182 #[repr(C)] 183 #[derive(Clone, Copy, Debug, Default, Zeroable, Pod, PartialEq, Eq)] 184 pub struct DispatchIndirectCommand { 185 pub x: u32, 186 pub y: u32, 187 pub z: u32, 188 } 189 190 vulkan_enum! { 191 #[non_exhaustive] 192 193 /// Describes what a subpass in a command buffer will contain. 194 SubpassContents = SubpassContents(i32); 195 196 /// The subpass will only directly contain commands. 197 Inline = INLINE, 198 199 /// The subpass will only contain secondary command buffers invocations. 200 SecondaryCommandBuffers = SECONDARY_COMMAND_BUFFERS, 201 } 202 203 impl From<SubpassContents> for ash::vk::RenderingFlags { 204 #[inline] from(val: SubpassContents) -> Self205 fn from(val: SubpassContents) -> Self { 206 match val { 207 SubpassContents::Inline => Self::empty(), 208 SubpassContents::SecondaryCommandBuffers => Self::CONTENTS_SECONDARY_COMMAND_BUFFERS, 209 } 210 } 211 } 212 213 vulkan_enum! { 214 /// Determines the kind of command buffer to create. 215 CommandBufferLevel = CommandBufferLevel(i32); 216 217 /// Primary command buffers can be executed on a queue, and can call secondary command buffers. 218 /// Render passes must begin and end within the same primary command buffer. 219 Primary = PRIMARY, 220 221 /// Secondary command buffers cannot be executed on a queue, but can be executed by a primary 222 /// command buffer. If created for a render pass, they must fit within a single render subpass. 223 Secondary = SECONDARY, 224 } 225 226 /// The context that a secondary command buffer can inherit from the primary command 227 /// buffer it's executed in. 228 #[derive(Clone, Debug)] 229 pub struct CommandBufferInheritanceInfo { 230 /// If `Some`, the secondary command buffer is required to be executed within a render pass 231 /// instance, and can only call draw operations. 232 /// If `None`, it must be executed outside a render pass instance, and can execute dispatch and 233 /// transfer operations, but not drawing operations. 234 /// 235 /// The default value is `None`. 236 pub render_pass: Option<CommandBufferInheritanceRenderPassType>, 237 238 /// If `Some`, the secondary command buffer is allowed to be executed within a primary that has 239 /// an occlusion query active. The inner `QueryControlFlags` specifies which flags the 240 /// active occlusion is allowed to have enabled. 241 /// If `None`, the primary command buffer cannot have an occlusion query active when this 242 /// secondary command buffer is executed. 243 /// 244 /// The `inherited_queries` feature must be enabled if this is `Some`. 245 /// 246 /// The default value is `None`. 247 pub occlusion_query: Option<QueryControlFlags>, 248 249 /// Which pipeline statistics queries are allowed to be active on the primary command buffer 250 /// when this secondary command buffer is executed. 251 /// 252 /// If this value is not empty, the [`pipeline_statistics_query`] feature must be enabled on 253 /// the device. 254 /// 255 /// The default value is [`QueryPipelineStatisticFlags::empty()`]. 256 /// 257 /// [`pipeline_statistics_query`]: crate::device::Features::pipeline_statistics_query 258 pub query_statistics_flags: QueryPipelineStatisticFlags, 259 260 pub _ne: crate::NonExhaustive, 261 } 262 263 impl Default for CommandBufferInheritanceInfo { 264 #[inline] default() -> Self265 fn default() -> Self { 266 Self { 267 render_pass: None, 268 occlusion_query: None, 269 query_statistics_flags: QueryPipelineStatisticFlags::empty(), 270 _ne: crate::NonExhaustive(()), 271 } 272 } 273 } 274 275 /// Selects the type of render pass for command buffer inheritance. 276 #[derive(Clone, Debug)] 277 pub enum CommandBufferInheritanceRenderPassType { 278 /// The secondary command buffer will be executed within a render pass begun with 279 /// `begin_render_pass`, using a `RenderPass` object and `Framebuffer`. 280 BeginRenderPass(CommandBufferInheritanceRenderPassInfo), 281 282 /// The secondary command buffer will be executed within a render pass begun with 283 /// `begin_rendering`, using dynamic rendering. 284 BeginRendering(CommandBufferInheritanceRenderingInfo), 285 } 286 287 impl From<Subpass> for CommandBufferInheritanceRenderPassType { 288 #[inline] from(val: Subpass) -> Self289 fn from(val: Subpass) -> Self { 290 Self::BeginRenderPass(val.into()) 291 } 292 } 293 294 impl From<CommandBufferInheritanceRenderPassInfo> for CommandBufferInheritanceRenderPassType { 295 #[inline] from(val: CommandBufferInheritanceRenderPassInfo) -> Self296 fn from(val: CommandBufferInheritanceRenderPassInfo) -> Self { 297 Self::BeginRenderPass(val) 298 } 299 } 300 301 impl From<CommandBufferInheritanceRenderingInfo> for CommandBufferInheritanceRenderPassType { 302 #[inline] from(val: CommandBufferInheritanceRenderingInfo) -> Self303 fn from(val: CommandBufferInheritanceRenderingInfo) -> Self { 304 Self::BeginRendering(val) 305 } 306 } 307 308 /// The render pass context that a secondary command buffer is created for. 309 #[derive(Clone, Debug)] 310 pub struct CommandBufferInheritanceRenderPassInfo { 311 /// The render subpass that this secondary command buffer must be executed within. 312 /// 313 /// There is no default value. 314 pub subpass: Subpass, 315 316 /// The framebuffer object that will be used when calling the command buffer. 317 /// This parameter is optional and is an optimization hint for the implementation. 318 /// 319 /// The default value is `None`. 320 pub framebuffer: Option<Arc<Framebuffer>>, 321 } 322 323 impl CommandBufferInheritanceRenderPassInfo { 324 /// Returns a `CommandBufferInheritanceRenderPassInfo` with the specified `subpass`. 325 #[inline] subpass(subpass: Subpass) -> Self326 pub fn subpass(subpass: Subpass) -> Self { 327 Self { 328 subpass, 329 framebuffer: None, 330 } 331 } 332 } 333 334 impl From<Subpass> for CommandBufferInheritanceRenderPassInfo { 335 #[inline] from(subpass: Subpass) -> Self336 fn from(subpass: Subpass) -> Self { 337 Self { 338 subpass, 339 framebuffer: None, 340 } 341 } 342 } 343 344 /// The dynamic rendering context that a secondary command buffer is created for. 345 #[derive(Clone, Debug)] 346 pub struct CommandBufferInheritanceRenderingInfo { 347 /// If not `0`, indicates that multiview rendering will be enabled, and specifies the view 348 /// indices that are rendered to. The value is a bitmask, so that that for example `0b11` will 349 /// draw to the first two views and `0b101` will draw to the first and third view. 350 /// 351 /// If set to a nonzero value, then the [`multiview`] feature must be enabled on the device. 352 /// 353 /// The default value is `0`. 354 /// 355 /// [`multiview`]: crate::device::Features::multiview 356 pub view_mask: u32, 357 358 /// The formats of the color attachments that will be used during rendering. 359 /// 360 /// If an element is `None`, it indicates that the attachment will not be used. 361 /// 362 /// The default value is empty. 363 pub color_attachment_formats: Vec<Option<Format>>, 364 365 /// The format of the depth attachment that will be used during rendering. 366 /// 367 /// If set to `None`, it indicates that no depth attachment will be used. 368 /// 369 /// The default value is `None`. 370 pub depth_attachment_format: Option<Format>, 371 372 /// The format of the stencil attachment that will be used during rendering. 373 /// 374 /// If set to `None`, it indicates that no stencil attachment will be used. 375 /// 376 /// The default value is `None`. 377 pub stencil_attachment_format: Option<Format>, 378 379 /// The number of samples that the color, depth and stencil attachments will have. 380 /// 381 /// The default value is [`SampleCount::Sample1`] 382 pub rasterization_samples: SampleCount, 383 } 384 385 impl Default for CommandBufferInheritanceRenderingInfo { 386 #[inline] default() -> Self387 fn default() -> Self { 388 Self { 389 view_mask: 0, 390 color_attachment_formats: Vec::new(), 391 depth_attachment_format: None, 392 stencil_attachment_format: None, 393 rasterization_samples: SampleCount::Sample1, 394 } 395 } 396 } 397 398 /// Usage flags to pass when creating a command buffer. 399 /// 400 /// The safest option is `SimultaneousUse`, but it may be slower than the other two. 401 // NOTE: The ordering is important: the variants are listed from least to most permissive! 402 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] 403 #[repr(u32)] 404 pub enum CommandBufferUsage { 405 /// The command buffer can only be submitted once before being destroyed. Any further submit is 406 /// forbidden. This makes it possible for the implementation to perform additional 407 /// optimizations. 408 OneTimeSubmit = ash::vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT.as_raw(), 409 410 /// The command buffer can be used multiple times, but must not execute or record more than once 411 /// simultaneously. In other words, it is as if executing the command buffer borrows it mutably. 412 MultipleSubmit = 0, 413 414 /// The command buffer can be executed multiple times in parallel on different queues. 415 /// If it's a secondary command buffer, it can be recorded to multiple primary command buffers 416 /// at once. 417 SimultaneousUse = ash::vk::CommandBufferUsageFlags::SIMULTANEOUS_USE.as_raw(), 418 } 419 420 impl From<CommandBufferUsage> for ash::vk::CommandBufferUsageFlags { 421 #[inline] from(val: CommandBufferUsage) -> Self422 fn from(val: CommandBufferUsage) -> Self { 423 Self::from_raw(val as u32) 424 } 425 } 426 427 /// Parameters to submit command buffers to a queue. 428 #[derive(Clone, Debug)] 429 pub struct SubmitInfo { 430 /// The semaphores to wait for before beginning the execution of this batch of 431 /// command buffer operations. 432 /// 433 /// The default value is empty. 434 pub wait_semaphores: Vec<SemaphoreSubmitInfo>, 435 436 /// The command buffers to execute. 437 /// 438 /// The default value is empty. 439 pub command_buffers: Vec<Arc<dyn PrimaryCommandBufferAbstract>>, 440 441 /// The semaphores to signal after the execution of this batch of command buffer operations 442 /// has completed. 443 /// 444 /// The default value is empty. 445 pub signal_semaphores: Vec<SemaphoreSubmitInfo>, 446 447 pub _ne: crate::NonExhaustive, 448 } 449 450 impl Default for SubmitInfo { 451 #[inline] default() -> Self452 fn default() -> Self { 453 Self { 454 wait_semaphores: Vec::new(), 455 command_buffers: Vec::new(), 456 signal_semaphores: Vec::new(), 457 _ne: crate::NonExhaustive(()), 458 } 459 } 460 } 461 462 /// Parameters for a semaphore signal or wait operation in a command buffer submission. 463 #[derive(Clone, Debug)] 464 pub struct SemaphoreSubmitInfo { 465 /// The semaphore to signal or wait for. 466 pub semaphore: Arc<Semaphore>, 467 468 /// For a semaphore wait operation, specifies the pipeline stages in the second synchronization 469 /// scope: stages of queue operations following the wait operation that can start executing 470 /// after the semaphore is signalled. 471 /// 472 /// For a semaphore signal operation, specifies the pipeline stages in the first synchronization 473 /// scope: stages of queue operations preceding the signal operation that must complete before 474 /// the semaphore is signalled. 475 /// If this value does not equal [`ALL_COMMANDS`], then the [`synchronization2`] feature must 476 /// be enabled on the device. 477 /// 478 /// The default value is [`ALL_COMMANDS`]. 479 /// 480 /// [`ALL_COMMANDS`]: PipelineStages::ALL_COMMANDS 481 /// [`synchronization2`]: crate::device::Features::synchronization2 482 pub stages: PipelineStages, 483 484 pub _ne: crate::NonExhaustive, 485 } 486 487 impl SemaphoreSubmitInfo { 488 /// Returns a `SemaphoreSubmitInfo` with the specified `semaphore`. 489 #[inline] semaphore(semaphore: Arc<Semaphore>) -> Self490 pub fn semaphore(semaphore: Arc<Semaphore>) -> Self { 491 Self { 492 semaphore, 493 stages: PipelineStages::ALL_COMMANDS, 494 _ne: crate::NonExhaustive(()), 495 } 496 } 497 } 498 499 #[derive(Debug, Default)] 500 pub struct CommandBufferState { 501 has_been_submitted: bool, 502 pending_submits: u32, 503 } 504 505 impl CommandBufferState { has_been_submitted(&self) -> bool506 pub(crate) fn has_been_submitted(&self) -> bool { 507 self.has_been_submitted 508 } 509 is_submit_pending(&self) -> bool510 pub(crate) fn is_submit_pending(&self) -> bool { 511 self.pending_submits != 0 512 } 513 add_queue_submit(&mut self)514 pub(crate) unsafe fn add_queue_submit(&mut self) { 515 self.has_been_submitted = true; 516 self.pending_submits += 1; 517 } 518 set_submit_finished(&mut self)519 pub(crate) unsafe fn set_submit_finished(&mut self) { 520 self.pending_submits -= 1; 521 } 522 } 523 524 #[doc(hidden)] 525 #[derive(Debug)] 526 pub struct CommandBufferResourcesUsage { 527 pub(crate) buffers: Vec<CommandBufferBufferUsage>, 528 pub(crate) images: Vec<CommandBufferImageUsage>, 529 pub(crate) buffer_indices: HashMap<Arc<Buffer>, usize>, 530 pub(crate) image_indices: HashMap<Arc<Image>, usize>, 531 } 532 533 #[derive(Debug)] 534 pub(crate) struct CommandBufferBufferUsage { 535 pub(crate) buffer: Arc<Buffer>, 536 pub(crate) ranges: RangeMap<DeviceSize, CommandBufferBufferRangeUsage>, 537 } 538 539 #[derive(Clone, Debug, PartialEq, Eq)] 540 pub(crate) struct CommandBufferBufferRangeUsage { 541 pub(crate) first_use: Option<ResourceUseRef>, 542 pub(crate) mutable: bool, 543 } 544 545 #[derive(Debug)] 546 pub(crate) struct CommandBufferImageUsage { 547 pub(crate) image: Arc<Image>, 548 pub(crate) ranges: RangeMap<DeviceSize, CommandBufferImageRangeUsage>, 549 } 550 551 #[derive(Clone, Debug, PartialEq, Eq)] 552 pub(crate) struct CommandBufferImageRangeUsage { 553 pub(crate) first_use: Option<ResourceUseRef>, 554 pub(crate) mutable: bool, 555 pub(crate) expected_layout: ImageLayout, 556 pub(crate) final_layout: ImageLayout, 557 } 558 559 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 560 pub struct ResourceUseRef { 561 pub command_index: usize, 562 pub command_name: &'static str, 563 pub resource_in_command: ResourceInCommand, 564 pub secondary_use_ref: Option<SecondaryResourceUseRef>, 565 } 566 567 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 568 pub struct SecondaryResourceUseRef { 569 pub command_index: usize, 570 pub command_name: &'static str, 571 pub resource_in_command: ResourceInCommand, 572 } 573 574 impl From<ResourceUseRef> for SecondaryResourceUseRef { 575 #[inline] from(val: ResourceUseRef) -> Self576 fn from(val: ResourceUseRef) -> Self { 577 let ResourceUseRef { 578 command_index, 579 command_name, 580 resource_in_command, 581 secondary_use_ref, 582 } = val; 583 584 debug_assert!(secondary_use_ref.is_none()); 585 586 SecondaryResourceUseRef { 587 command_index, 588 command_name, 589 resource_in_command, 590 } 591 } 592 } 593 594 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 595 #[non_exhaustive] 596 pub enum ResourceInCommand { 597 ColorAttachment { index: u32 }, 598 ColorResolveAttachment { index: u32 }, 599 DepthStencilAttachment, 600 DepthStencilResolveAttachment, 601 DescriptorSet { set: u32, binding: u32, index: u32 }, 602 Destination, 603 FramebufferAttachment { index: u32 }, 604 ImageMemoryBarrier { index: u32 }, 605 IndexBuffer, 606 IndirectBuffer, 607 SecondaryCommandBuffer { index: u32 }, 608 Source, 609 VertexBuffer { binding: u32 }, 610 } 611 612 #[doc(hidden)] 613 #[derive(Debug, Default)] 614 pub struct SecondaryCommandBufferResourcesUsage { 615 pub(crate) buffers: Vec<SecondaryCommandBufferBufferUsage>, 616 pub(crate) images: Vec<SecondaryCommandBufferImageUsage>, 617 } 618 619 #[derive(Debug)] 620 pub(crate) struct SecondaryCommandBufferBufferUsage { 621 pub(crate) use_ref: ResourceUseRef, 622 pub(crate) buffer: Subbuffer<[u8]>, 623 pub(crate) range: Range<DeviceSize>, 624 pub(crate) memory: PipelineMemoryAccess, 625 } 626 627 #[derive(Debug)] 628 pub(crate) struct SecondaryCommandBufferImageUsage { 629 pub(crate) use_ref: ResourceUseRef, 630 pub(crate) image: Arc<dyn ImageAccess>, 631 pub(crate) subresource_range: ImageSubresourceRange, 632 pub(crate) memory: PipelineMemoryAccess, 633 pub(crate) start_layout: ImageLayout, 634 pub(crate) end_layout: ImageLayout, 635 } 636