(&self, cpu_buffer: &mut [u8])
| 125 | } |
| 126 | |
| 127 | pub fn copy_texture_to_buffer(&self, cpu_buffer: &mut [u8]) { |
| 128 | let mut encoder = self |
| 129 | .device() |
| 130 | .create_command_encoder(&CommandEncoderDescriptor { |
| 131 | label: Some("Copy out buffer"), |
| 132 | }); |
| 133 | let row_byte_width = self.config.width as usize * 4; |
| 134 | let padded_row_byte_width = row_byte_width.next_multiple_of(256); |
| 135 | |
| 136 | let texture = self.texture_view.texture(); |
| 137 | encoder.copy_texture_to_buffer( |
| 138 | texture.as_image_copy(), |
| 139 | TexelCopyBufferInfo { |
| 140 | buffer: &self.gpu_buffer, |
| 141 | layout: TexelCopyBufferLayout { |
| 142 | offset: 0, |
| 143 | bytes_per_row: Some(padded_row_byte_width as u32), |
| 144 | rows_per_image: None, |
| 145 | }, |
| 146 | }, |
| 147 | texture.size(), |
| 148 | ); |
| 149 | |
| 150 | self.queue().submit([encoder.finish()]); |
| 151 | let buf_slice = self.gpu_buffer.slice(..); |
| 152 | |
| 153 | let (sender, receiver) = futures_intrusive::channel::shared::oneshot_channel(); |
| 154 | buf_slice.map_async(wgpu::MapMode::Read, move |v| sender.send(v).unwrap()); |
| 155 | |
| 156 | if let Ok(recv_result) = |
| 157 | block_on_wgpu(self.device(), receiver.receive()).inspect_err(|err| { |
| 158 | panic!("channel inaccessible: {:#}", err); |
| 159 | }) |
| 160 | { |
| 161 | let _ = recv_result.unwrap(); |
| 162 | } |
| 163 | |
| 164 | let data = buf_slice.get_mapped_range(); |
| 165 | |
| 166 | // Pad result |
| 167 | for row in 0..(self.config.height as usize) { |
| 168 | let src_start = row * padded_row_byte_width; |
| 169 | let src = &data[src_start..(src_start + row_byte_width)]; |
| 170 | |
| 171 | let dest_start = row * row_byte_width; |
| 172 | cpu_buffer[dest_start..(dest_start + row_byte_width)].clone_from_slice(src); |
| 173 | } |
| 174 | |
| 175 | // Unmap buffer |
| 176 | drop(data); |
| 177 | self.gpu_buffer.unmap(); |
| 178 | } |
| 179 | } |
no test coverage detected