diff --git a/crates/bevy_render/src/render_graph/command.rs b/crates/bevy_render/src/render_graph/command.rs index 466b4897f56bd8..d098db74aa1f67 100644 --- a/crates/bevy_render/src/render_graph/command.rs +++ b/crates/bevy_render/src/render_graph/command.rs @@ -23,6 +23,24 @@ pub enum Command { destination_mip_level: u32, size: Extent3d, }, + CopyTextureToTexture { + source_texture: TextureId, + source_origin: [u32; 3], + source_mip_level: u32, + destination_texture: TextureId, + destination_origin: [u32; 3], + destination_mip_level: u32, + size: Extent3d, + }, + CopyTextureToBuffer { + source_texture: TextureId, + source_origin: [u32; 3], + source_mip_level: u32, + destination_buffer: BufferId, + destination_offset: u64, + destination_bytes_per_row: u32, + size: Extent3d, + }, // TODO: Frees probably don't need to be queued? FreeBuffer(BufferId), } @@ -77,6 +95,50 @@ impl CommandQueue { }); } + #[allow(clippy::too_many_arguments)] + pub fn copy_texture_to_buffer( + &mut self, + source_texture: TextureId, + source_origin: [u32; 3], + source_mip_level: u32, + destination_buffer: BufferId, + destination_offset: u64, + destination_bytes_per_row: u32, + size: Extent3d, + ) { + self.push(Command::CopyTextureToBuffer { + source_texture, + source_origin, + source_mip_level, + destination_buffer, + destination_offset, + destination_bytes_per_row, + size, + }) + } + + #[allow(clippy::too_many_arguments)] + pub fn copy_texture_to_texture( + &mut self, + source_texture: TextureId, + source_origin: [u32; 3], + source_mip_level: u32, + destination_texture: TextureId, + destination_origin: [u32; 3], + destination_mip_level: u32, + size: Extent3d, + ) { + self.push(Command::CopyTextureToTexture { + source_texture, + source_origin, + source_mip_level, + destination_texture, + destination_origin, + destination_mip_level, + size, + }) + } + pub fn free_buffer(&mut self, buffer: BufferId) { self.push(Command::FreeBuffer(buffer)); } @@ -118,6 +180,40 @@ impl CommandQueue { destination_mip_level, size, ), + Command::CopyTextureToTexture { + source_texture, + source_origin, + source_mip_level, + destination_texture, + destination_origin, + destination_mip_level, + size, + } => render_context.copy_texture_to_texture( + source_texture, + source_origin, + source_mip_level, + destination_texture, + destination_origin, + destination_mip_level, + size, + ), + Command::CopyTextureToBuffer { + source_texture, + source_origin, + source_mip_level, + destination_buffer, + destination_offset, + destination_bytes_per_row, + size, + } => render_context.copy_texture_to_buffer( + source_texture, + source_origin, + source_mip_level, + destination_buffer, + destination_offset, + destination_bytes_per_row, + size, + ), Command::FreeBuffer(buffer) => render_context.resources().remove_buffer(buffer), } } diff --git a/crates/bevy_render/src/renderer/render_context.rs b/crates/bevy_render/src/renderer/render_context.rs index 2da15a49a61e7f..b82149e54b6d49 100644 --- a/crates/bevy_render/src/renderer/render_context.rs +++ b/crates/bevy_render/src/renderer/render_context.rs @@ -27,6 +27,28 @@ pub trait RenderContext { destination_mip_level: u32, size: Extent3d, ); + #[allow(clippy::too_many_arguments)] + fn copy_texture_to_buffer( + &mut self, + source_texture: TextureId, + source_origin: [u32; 3], + source_mip_level: u32, + destination_buffer: BufferId, + destination_offset: u64, + destination_bytes_per_row: u32, + size: Extent3d, + ); + #[allow(clippy::too_many_arguments)] + fn copy_texture_to_texture( + &mut self, + source_texture: TextureId, + source_origin: [u32; 3], + source_mip_level: u32, + destination_texture: TextureId, + destination_origin: [u32; 3], + destination_mip_level: u32, + size: Extent3d, + ); fn begin_pass( &mut self, pass_descriptor: &PassDescriptor, diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs index f4efbcad7b2a19..69a9ae7691930b 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs @@ -114,6 +114,50 @@ impl RenderContext for WgpuRenderContext { ) } + fn copy_texture_to_buffer( + &mut self, + source_texture: TextureId, + source_origin: [u32; 3], + source_mip_level: u32, + destination_buffer: BufferId, + destination_offset: u64, + destination_bytes_per_row: u32, + size: Extent3d, + ) { + self.render_resource_context.copy_texture_to_buffer( + self.command_encoder.get_or_create(&self.device), + source_texture, + source_origin, + source_mip_level, + destination_buffer, + destination_offset, + destination_bytes_per_row, + size, + ) + } + + fn copy_texture_to_texture( + &mut self, + source_texture: TextureId, + source_origin: [u32; 3], + source_mip_level: u32, + destination_texture: TextureId, + destination_origin: [u32; 3], + destination_mip_level: u32, + size: Extent3d, + ) { + self.render_resource_context.copy_texture_to_texture( + self.command_encoder.get_or_create(&self.device), + source_texture, + source_origin, + source_mip_level, + destination_texture, + destination_origin, + destination_mip_level, + size, + ) + } + fn resources(&self) -> &dyn RenderResourceContext { &self.render_resource_context } diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs index f235c359ce0365..bd1be8db72260a 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs @@ -65,6 +65,83 @@ impl WgpuRenderResourceContext { ); } + #[allow(clippy::too_many_arguments)] + pub fn copy_texture_to_texture( + &self, + command_encoder: &mut wgpu::CommandEncoder, + source_texture: TextureId, + source_origin: [u32; 3], // TODO: replace with math type + source_mip_level: u32, + destination_texture: TextureId, + destination_origin: [u32; 3], // TODO: replace with math type + destination_mip_level: u32, + size: Extent3d, + ) { + let textures = self.resources.textures.read(); + let source = textures.get(&source_texture).unwrap(); + let destination = textures.get(&destination_texture).unwrap(); + command_encoder.copy_texture_to_texture( + wgpu::TextureCopyView { + texture: source, + mip_level: source_mip_level, + origin: wgpu::Origin3d { + x: source_origin[0], + y: source_origin[1], + z: source_origin[2], + }, + }, + wgpu::TextureCopyView { + texture: destination, + mip_level: destination_mip_level, + origin: wgpu::Origin3d { + x: destination_origin[0], + y: destination_origin[1], + z: destination_origin[2], + }, + }, + size.wgpu_into(), + ) + } + + #[allow(clippy::too_many_arguments)] + pub fn copy_texture_to_buffer( + &self, + command_encoder: &mut wgpu::CommandEncoder, + source_texture: TextureId, + source_origin: [u32; 3], // TODO: replace with math type + source_mip_level: u32, + destination_buffer: BufferId, + destination_offset: u64, + destination_bytes_per_row: u32, + size: Extent3d, + ) { + let buffers = self.resources.buffers.read(); + let textures = self.resources.textures.read(); + + let source = textures.get(&source_texture).unwrap(); + let destination = buffers.get(&destination_buffer).unwrap(); + command_encoder.copy_texture_to_buffer( + wgpu::TextureCopyView { + texture: source, + mip_level: source_mip_level, + origin: wgpu::Origin3d { + x: source_origin[0], + y: source_origin[1], + z: source_origin[2], + }, + }, + wgpu::BufferCopyView { + buffer: destination, + layout: wgpu::TextureDataLayout { + offset: destination_offset, + bytes_per_row: destination_bytes_per_row, + rows_per_image: size.height, + }, + }, + size.wgpu_into(), + ); + } + #[allow(clippy::too_many_arguments)] pub fn copy_buffer_to_texture( &self,