Skip to content

WebGPURenderer: Fix "getArrayBufferAsync" to avoid severe GC pressure #33281

@gkjohnson

Description

@gkjohnson

Description

When using "getArrayBufferAsync" a new array buffer is always created and returned rather than either allowing the user to provide a buffer to write into, as WebGLRenderer's readRenderTargetPixels functions do (it looks like this has been removed from WebGPU's version, for some reason), or allowing the user to determine when to release the buffer back to the GPU.

If using this read back function frequently this can create a ton of unnecessary GC pressure.

I see that a new GPU buffer is also created every call, which feels unnecessary, and then is subsequently never destroyed, presumably leading to a memory leak.

Solution

  1. Add a "target buffer" argument to the getArrayBufferAsync function:
const data = new Uint32Array( storageAttribute.count * storageAttribute.itemSize );
renderer.getArrayBufferAsync( storageAttribute, data.buffer );
  1. Provide a new class that allows for managing the mapped data the data back to the GPU when the user is through with it. If the "MappedStoragedBufferData" is not provided when a new instance can be returned:
class MappedStoragedBufferData {
  size: number,
  array: ArrayBuffer,
  release(): void;
  dispose(): void;
}

// ...

const mappedData = new MappedStorageBuffer( storageAttribute.count * storageAttribute.itemSize );
renderer.getArrayBufferAsync( storageAttribute, mappedData );

// ... do something with the data including processing it, copying it...

mappedData.release();
// ...
mappedData.dispose();

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