luma.gl

Buffer

A Buffer is a WebGL object that stores an chunk of memory allocated by the GPU. This memory can be accessed directly by the GPU and is used to store things like vertex data, pixel data retrieved from images or the framebuffer, etc. The Buffer class provides mechanism for allocating such memory, together with facilities for copying data to and from the GPU (usually via JavaScript typed arrays).

For additional information, see OpenGL Wiki.

Usage

import {Buffer} from '@luma.gl/core';

Creating a generic buffer

const buffer = new Buffer(gl);

Creating an elements buffer

const buffer = new Buffer(gl, {target: GL.ELEMENT_ARRAY_BUFFER});

Allocating memory in a buffer

const buffer = new Buffer(gl, {byteLength: 200});
const buffer = new Buffer(gl).initialize({byteLength: 200});

Allocating and initializing a buffer

const buffer = new Buffer(gl, {
  target: GL.ELEMENTS_ARRAY_BUFFER,
  data: new Uint32Array([1, 2, 3])
});
const buffer = new Buffer(gl, new Float32Array([1, 2, 3])); // Allocate+init 12 bytes of GPU memory
const buffer = new Buffer(gl, 200); // Allocate 200 bytes of GPU memory

Updating a buffer

const buffer = new Buffer(gl, {byteLength: 200})
buffer.subData(new Float32Array(...));

Copying data between buffers (WebGL2)

const sourceBuffer = ...
const destinationBuffer = ...

// To copy 32 bytes from sourceBuffer to destinationBuffer
destinationBuffer.copyData({sourceBuffer, size: 32});

// To copy 32 bytes from sourceBuffer at 8 byte offset into
// destinationBuffer at 16 byte offset.
destinationBuffer.copyData({
  sourceBuffer,
  readOffset: 8,
  writeOffset: 16,
  size: 32
});

Getting data from a buffer (WebGL2)

const buffer = ...;

// To get all the data from buffer
const data = buffer.getData();

// To get all the data from buffer starting from byteOffset 8
// into existing ArrayBufferView.
const existingArray = ...
const data = buffer.getData({dstData: existingArray, srcByteOffset: 8});
// Maximum possible elements will be copied based buffer and dstData size.

// To get 5 elements from source buffer starting from byteOffset 8
// into existing ArrayBufferView starting from 3rd element position.
const existingArray = ...
const data = buffer.getData({dstData: existingArray, srcByteOffset: 8, dstOffset: 3, length: 5});

Members

handle : WebGLBuffer

Holds the underlying WebGL object reference.

byteLength : Number

Number of bytes of allocated memory.

bytesUsed : Number

Same as byteLength unless the Buffer.reallocate has been called with a value smaller than the actual length of the buffer.

accessor : Accessor

Holds an Accessor instance. By default it contains type information that is automatically deducted from the type of data used to initialize the buffer, but the application can store any Accessor it wants with the Buffer. This can simplify handling of buffer related data in many basic use cases (e.g. when buffers are not shared by multiple attributes etc).

Constructor

Buffer(gl : WebGLRenderingContext, props : Object | TypedArray | Number)

Creates a new Buffer. Multiple signatures are supported:

const buffer = new Buffer(gl, {target, ...initOptions, accessor, ...accessorOptions});
const buffer = new Buffer(gl, typedArray);
const buffer = new Buffer(gl, byteLength);

The newly constructed buffer will either be a an “element” buffer used for storing vertex indices, or a “generic” buffer that can be used to store other things. To create an element buffer, specify target: GL.ELEMENT_ARRAY_BUFFER. If target is not specified, it will be a generic buffer that can be used in a variety of situations.

Methods

initialize(props : Object) : Buffer

Allocates and optionally initializes buffer memory/data store (releasing any previously allocated memory).

Also extracts characteristics of stored data, hints for vertex attribute.

Buffer.initialize({data, byteLength, usage=, dataType=, size=, accessor=, ...accessorOptions})
Buffer(gl, typedArray);
Buffer(gl, byteLength);

reallocate(byteLength : Number) : Buffer

If necessary, increases buffer size to byteLength. Does not decrease the buffer’s size if already long enough.

Returns:

subData({data , offset=, srcOffset=, length=}) : Buffer

Updates part or all of a buffer’s allocated memory.

Buffer.subData({data, offset=, srcOffset=, length=})

copyData(options : Object) : Buffer (WebGL2)

Copies part of the data of another buffer into this buffer. The copy happens on the GPU and is expected to be efficient.

Buffer.copyData({sourceBuffer, readOffset=, writeOffset=, size})

Note:

getData() : TypedArray (WebGL2)

Reads data from buffer into an ArrayBufferView or SharedArrayBuffer.

Buffer.getData({dstData, srcByteOffset, srcOffset, length})

Returns a typed array containing the data from the buffer (if dstData was supplied it will be returned, otherwise this will be a freshly allocated array).

getElementCount([accessor : Accessor]) : Number

Returns number of elements in the buffer. In a buffer created with Float32Array typed array, each float is an element and takes 4 bytes (or 32 bits).

setAccessor(accessor : Accessor | Object) : Buffer

Allows you to optionally describe the accessor properties of the data in the buffer. This does not affect the buffer itself, but if supplied can avoid having to supply this data again when you use this buffer as an attribute later (see VertexArray.setAttributes).

For details on accessor props, see the documentation for the Accessor class.

Types

Usage

Usage WebGL2 WebGL1 Description
GL.STATIC_DRAW Yes Yes Buffer will be used often and not change often. Contents are written to the buffer, but not read.
GL.DYNAMIC_DRAW Yes Yes Buffer will be used often and change often. Contents are written to the buffer, but not read.
GL.STREAM_DRAW Yes Yes Buffer will not be used often. Contents are written to the buffer, but not read.
GL.STATIC_READ Yes No Buffer will be used often and not change often. Contents are read from the buffer, but not written.
GL.DYNAMIC_READ Yes No Buffer will be used often and change often. Contents are read from the buffer, but not written.
GL.STREAM_READ Yes No Buffer will not be used often. Contents are read from the buffer, but not written.
GL.STATIC_COPY Yes No Buffer will be used often and not change often. Contents are neither written or read by the user.
GL.DYNAMIC_COPY Yes No Buffer will be used often and change often. Contents are neither written or read by the user.
GL.STREAM_COPY Yes No Buffer will be used often and not change often. Contents are neither written or read by the user.

Parameters

Parameter Type Value
GL.BUFFER_SIZE GLint The size of the buffer in bytes
GL.BUFFER_USAGE GLenum The usage pattern of the buffer

“Manually” Binding Buffers

If you are an experienced WebGL or OpenGL programmer you are probably used to constantly binding buffers. Buffer binding and unbinding is handled internal by luma.gl methods and applications typically do not need to bind buffers.

To support use cases integrating with external libraries or raw webgl code, it is of course possible to “manually” bind and unbind luma.gl Buffer instances:

const buffer = ...;
buffer.bind({target: GL.ARRAY_BUFFER});
...
buffer.unbind({target: GL.ARRAY_BUFFER});

WebGL2 examples

buffer.bind({target: GL.PIXEL_PACK_BUFFER});
buffer.bind({target: GL.PIXEL_UNPACK_BUFFER});
buffer.bind({target: GL.TRANSFORM_FEEDBACK_BUFFER, index: 0});
buffer.bind({target: GL.UNIFORM_BUFFER, index: 0, offset: ..., size: ...});
buffer.unbind({target: GL.UNIFORM_BUFFER, index: 0});

Remarks

Note that in WebGL, there are two types of buffers:

For more on the GL.ELEMENT_ARRAY_BUFFER restrictions in WebGL, see this page for WebGL1 and this page for WebGL2.