 40c26f80aa
			
		
	
	
		40c26f80aa
		
			
		
	
	
	
	
		
			
			# Objective
Adds a new `Readback` component to request for readback of a
`Handle<Image>` or `Handle<ShaderStorageBuffer>` to the CPU in a future
frame.
## Solution
We track the `Readback` component and allocate a target buffer to write
the gpu resource into and map it back asynchronously, which then fires a
trigger on the entity in the main world. This proccess is asynchronous,
and generally takes a few frames.
## Showcase
```rust
let mut buffer = ShaderStorageBuffer::from(vec![0u32; 16]);
buffer.buffer_description.usage |= BufferUsages::COPY_SRC;
let buffer = buffers.add(buffer);
commands
    .spawn(Readback::buffer(buffer.clone()))
    .observe(|trigger: Trigger<ReadbackComplete>| {
        info!("Buffer data from previous frame {:?}", trigger.event());
    });
```
---------
Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>
		
	
			
		
			
				
	
	
		
			16 lines
		
	
	
		
			680 B
		
	
	
	
		
			WebGPU Shading Language
		
	
	
	
	
	
			
		
		
	
	
			16 lines
		
	
	
		
			680 B
		
	
	
	
		
			WebGPU Shading Language
		
	
	
	
	
	
| // This shader is used for the gpu_readback example
 | |
| // The actual work it does is not important for the example
 | |
| 
 | |
| // This is the data that lives in the gpu only buffer
 | |
| @group(0) @binding(0) var<storage, read_write> data: array<u32>;
 | |
| @group(0) @binding(1) var texture: texture_storage_2d<r32uint, write>;
 | |
| 
 | |
| @compute @workgroup_size(1)
 | |
| fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
 | |
|     // We use the global_id to index the array to make sure we don't
 | |
|     // access data used in another workgroup
 | |
|     data[global_id.x] += 1u;
 | |
|     // Write the same data to the texture
 | |
|     textureStore(texture, vec2<i32>(i32(global_id.x), 0), vec4<u32>(data[global_id.x], 0, 0, 0));
 | |
| }
 |