use alloc::vec::Vec; use core::mem; use core::ops::Range; use super::{Api, Buffer, DeviceResult, Resource}; /// Command buffer type, which performs double duty as the command encoder type too. #[derive(Debug)] pub struct CommandBuffer { commands: Vec, } #[derive(Debug)] enum Command { ClearBuffer { buffer: Buffer, range: crate::MemoryRange, }, CopyBufferToBuffer { src: Buffer, dst: Buffer, regions: Vec, }, } impl CommandBuffer { /// # Safety /// /// Must be called with appropriate synchronization for the resources affected by the command, /// such as ensuring that buffers are not accessed by a command while aliasing references exist. pub(crate) unsafe fn execute(&self) { for command in &self.commands { unsafe { command.execute() }; } } pub(crate) fn new() -> Self { Self { commands: Vec::new(), } } } impl crate::CommandEncoder for CommandBuffer { type A = Api; unsafe fn begin_encoding(&mut self, label: crate::Label) -> DeviceResult<()> { assert!(self.commands.is_empty()); Ok(()) } unsafe fn discard_encoding(&mut self) { self.commands.clear(); } unsafe fn end_encoding(&mut self) -> DeviceResult { Ok(CommandBuffer { commands: mem::take(&mut self.commands), }) } unsafe fn reset_all(&mut self, command_buffers: I) {} unsafe fn transition_buffers<'a, T>(&mut self, barriers: T) where T: Iterator>, { } unsafe fn transition_textures<'a, T>(&mut self, barriers: T) where T: Iterator>, { } unsafe fn clear_buffer(&mut self, buffer: &Buffer, range: crate::MemoryRange) { self.commands.push(Command::ClearBuffer { buffer: buffer.clone(), range, }) } unsafe fn copy_buffer_to_buffer(&mut self, src: &Buffer, dst: &Buffer, regions: T) where T: Iterator, { self.commands.push(Command::CopyBufferToBuffer { src: src.clone(), dst: dst.clone(), regions: regions.collect(), }); } #[cfg(webgl)] unsafe fn copy_external_image_to_texture( &mut self, src: &wgt::CopyExternalImageSourceInfo, dst: &Resource, dst_premultiplication: bool, regions: T, ) where T: Iterator, { } unsafe fn copy_texture_to_texture( &mut self, src: &Resource, src_usage: wgt::TextureUses, dst: &Resource, regions: T, ) { // TODO: consider implementing this and other texture manipulation } unsafe fn copy_buffer_to_texture(&mut self, src: &Buffer, dst: &Resource, regions: T) { // TODO: consider implementing this and other texture manipulation } unsafe fn copy_texture_to_buffer( &mut self, src: &Resource, src_usage: wgt::TextureUses, dst: &Buffer, regions: T, ) { // TODO: consider implementing this and other texture manipulation } unsafe fn begin_query(&mut self, set: &Resource, index: u32) {} unsafe fn end_query(&mut self, set: &Resource, index: u32) {} unsafe fn write_timestamp(&mut self, set: &Resource, index: u32) {} unsafe fn read_acceleration_structure_compact_size( &mut self, acceleration_structure: &Resource, buf: &Buffer, ) { } unsafe fn reset_queries(&mut self, set: &Resource, range: Range) {} unsafe fn copy_query_results( &mut self, set: &Resource, range: Range, buffer: &Buffer, offset: wgt::BufferAddress, stride: wgt::BufferSize, ) { } // render unsafe fn begin_render_pass( &mut self, desc: &crate::RenderPassDescriptor, ) -> DeviceResult<()> { Ok(()) } unsafe fn end_render_pass(&mut self) {} unsafe fn set_bind_group( &mut self, layout: &Resource, index: u32, group: &Resource, dynamic_offsets: &[wgt::DynamicOffset], ) { } unsafe fn set_immediates(&mut self, layout: &Resource, offset_bytes: u32, data: &[u32]) {} unsafe fn insert_debug_marker(&mut self, label: &str) {} unsafe fn begin_debug_marker(&mut self, group_label: &str) {} unsafe fn end_debug_marker(&mut self) {} unsafe fn set_render_pipeline(&mut self, pipeline: &Resource) {} unsafe fn set_index_buffer<'a>( &mut self, binding: crate::BufferBinding<'a, Buffer>, format: wgt::IndexFormat, ) { } unsafe fn set_vertex_buffer<'a>( &mut self, index: u32, binding: crate::BufferBinding<'a, Buffer>, ) { } unsafe fn set_viewport(&mut self, rect: &crate::Rect, depth_range: Range) {} unsafe fn set_scissor_rect(&mut self, rect: &crate::Rect) {} unsafe fn set_stencil_reference(&mut self, value: u32) {} unsafe fn set_blend_constants(&mut self, color: &[f32; 4]) {} unsafe fn draw( &mut self, first_vertex: u32, vertex_count: u32, first_instance: u32, instance_count: u32, ) { } unsafe fn draw_indexed( &mut self, first_index: u32, index_count: u32, base_vertex: i32, first_instance: u32, instance_count: u32, ) { } unsafe fn draw_mesh_tasks( &mut self, group_count_x: u32, group_count_y: u32, group_count_z: u32, ) { } unsafe fn draw_indirect( &mut self, buffer: &Buffer, offset: wgt::BufferAddress, draw_count: u32, ) { } unsafe fn draw_indexed_indirect( &mut self, buffer: &Buffer, offset: wgt::BufferAddress, draw_count: u32, ) { } unsafe fn draw_mesh_tasks_indirect( &mut self, buffer: &::Buffer, offset: wgt::BufferAddress, draw_count: u32, ) { } unsafe fn draw_indirect_count( &mut self, buffer: &Buffer, offset: wgt::BufferAddress, count_buffer: &Buffer, count_offset: wgt::BufferAddress, max_count: u32, ) { } unsafe fn draw_indexed_indirect_count( &mut self, buffer: &Buffer, offset: wgt::BufferAddress, count_buffer: &Buffer, count_offset: wgt::BufferAddress, max_count: u32, ) { } unsafe fn draw_mesh_tasks_indirect_count( &mut self, buffer: &::Buffer, offset: wgt::BufferAddress, count_buffer: &::Buffer, count_offset: wgt::BufferAddress, max_count: u32, ) { } // compute unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) {} unsafe fn end_compute_pass(&mut self) {} unsafe fn set_compute_pipeline(&mut self, pipeline: &Resource) {} unsafe fn dispatch(&mut self, count: [u32; 3]) {} unsafe fn dispatch_indirect(&mut self, buffer: &Buffer, offset: wgt::BufferAddress) {} unsafe fn build_acceleration_structures<'a, T>( &mut self, _descriptor_count: u32, descriptors: T, ) where Api: 'a, T: IntoIterator>, { } unsafe fn place_acceleration_structure_barrier( &mut self, _barriers: crate::AccelerationStructureBarrier, ) { } unsafe fn copy_acceleration_structure_to_acceleration_structure( &mut self, src: &Resource, dst: &Resource, copy: wgt::AccelerationStructureCopy, ) { } unsafe fn set_acceleration_structure_dependencies( command_buffers: &[&CommandBuffer], dependencies: &[&Resource], ) { } } impl Command { /// # Safety /// /// Must be called with appropriate synchronization for the resources affected by the command, /// such as ensuring that buffers are not accessed by a command while aliasing references exist. unsafe fn execute(&self) { match self { Command::ClearBuffer { ref buffer, range } => { // SAFETY: // Caller is responsible for ensuring this does not alias. let buffer_slice: &mut [u8] = unsafe { &mut *buffer.get_slice_ptr(range.clone()) }; buffer_slice.fill(0); } Command::CopyBufferToBuffer { src, dst, regions } => { for &crate::BufferCopy { src_offset, dst_offset, size, } in regions { // SAFETY: // Caller is responsible for ensuring this does not alias. let src_region: &[u8] = unsafe { &*src.get_slice_ptr(src_offset..src_offset + size.get()) }; let dst_region: &mut [u8] = unsafe { &mut *dst.get_slice_ptr(dst_offset..dst_offset + size.get()) }; dst_region.copy_from_slice(src_region); } } } } }