Skip to content

WebGPURenderer: Provide a mechanism for reading a sub-portion of an array buffer with getArrayBufferAsync #33282

@gkjohnson

Description

@gkjohnson

Description

Currently when using the "WebGPURenderer.readArrayBufferAsync" it's only possible to map and readback the full buffer. However it's possible that only a portion of that buffer will need to actually be read back to the CPU for processing - as when treating a storage buffer as a "queue"-style data structure and it may not be full.

Notionally:

// run some kernel that conditionally pushes data no the "data" storage buffer,
// incrementing the head ptr along the way
const kernel = wgslFn( /* wgsl */`
  fn compute() -> void {
    // ...
    if ( myCondition ) {
        let index = atomicLoad( &dataPtr[ 0 ], 1u );
        data[ index ] = myProcessedData;
    }
  }
` )().computeKernel( [ 1, 1, 1 ] );

renderer.compute( kernel, [ 20000, 1, 1 ] );

// read the amount of elements added to the data buffer
const count = new Uint32Array( await renderer.getArrayBufferAsync( dataPtrAttr ) )[ 0 ];

// read the actual data back - note we have to read the FULL set of
// data back even if we only need the written data
const output = new Uint32Array( await renderer.getArrayBufferAsync( dataAttr ) );

for ( let i = 0; i < count; i ++ ) {
  // do something with the data
}

Note this means the data buffers are larger than necessary, creating more unnecessary CPU memory, and will presumably take longer than necessary due to more memory needing to be copied.

Solution

  1. add options to the function for readback allowing for specifying the offset and count of the buffer:
renderer.getArrayBufferAsync( storageAttribute, offset, count );
  1. Relating to #33281, this could be fixed by leveraging the same "MappedStoragedBufferData" construct to infer the requested buffer size along with an optional "offset" parameter (defaulting to zero):
const mappedData = new MappedStorageBuffer( storageAttribute.count * storageAttribute.itemSize );
renderer.getArrayBufferAsync( storageAttribute, mappedData, offset );

Alternatives

None

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions