@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
160 lines (145 loc) • 5.25 kB
JavaScript
import { Debug } from '../../core/debug.js';
import { TRACEID_VRAM_VB } from '../../core/constants.js';
import { BUFFER_STATIC } from './constants.js';
let id = 0;
/**
* A vertex buffer is the mechanism via which the application specifies vertex data to the graphics
* hardware.
*
* @category Graphics
*/
class VertexBuffer {
/**
* Create a new VertexBuffer instance.
*
* @param {import('./graphics-device.js').GraphicsDevice} graphicsDevice - The graphics device
* used to manage this vertex buffer.
* @param {import('./vertex-format.js').VertexFormat} format - The vertex format of this vertex
* buffer.
* @param {number} numVertices - The number of vertices that this vertex buffer will hold.
* @param {object} [options] - Object for passing optional arguments.
* @param {number} [options.usage] - The usage type of the vertex buffer (see BUFFER_*).
* Defaults to BUFFER_STATIC.
* @param {ArrayBuffer} [options.data] - Initial data.
* @param {boolean} [options.storage] - Defines if the vertex buffer can be used as a storage
* buffer by a compute shader. Defaults to false. Only supported on WebGPU.
*/
constructor(graphicsDevice, format, numVertices, options) {
this.usage = BUFFER_STATIC;
// By default, vertex buffers are static (better for performance since buffer data can be cached in VRAM)
let initialData;
if (typeof options === 'object') {
var _options$usage;
this.usage = (_options$usage = options.usage) != null ? _options$usage : BUFFER_STATIC;
initialData = options.data;
} else if (arguments.length > 3) {
var _arguments$;
// handle backwards compatibility
Debug.deprecated('VertexBuffer: usage and initialData parameters are deprecated, use options object instead');
this.usage = (_arguments$ = arguments[3]) != null ? _arguments$ : BUFFER_STATIC;
initialData = arguments[4];
}
this.device = graphicsDevice;
this.format = format;
this.numVertices = numVertices;
this.id = id++;
this.impl = graphicsDevice.createVertexBufferImpl(this, format, options);
// Calculate the size. If format contains verticesByteSize (non-interleaved format), use it
this.numBytes = format.verticesByteSize ? format.verticesByteSize : format.size * numVertices;
this.adjustVramSizeTracking(graphicsDevice._vram, this.numBytes);
// Allocate the storage
if (initialData) {
this.setData(initialData);
} else {
this.storage = new ArrayBuffer(this.numBytes);
}
this.device.buffers.push(this);
}
/**
* Frees resources associated with this vertex buffer.
*/
destroy() {
// stop tracking the vertex buffer
const device = this.device;
const idx = device.buffers.indexOf(this);
if (idx !== -1) {
device.buffers.splice(idx, 1);
}
if (this.impl.initialized) {
this.impl.destroy(device);
this.adjustVramSizeTracking(device._vram, -this.storage.byteLength);
}
}
adjustVramSizeTracking(vram, size) {
Debug.trace(TRACEID_VRAM_VB, `${this.id} size: ${size} vram.vb: ${vram.vb} => ${vram.vb + size}`);
vram.vb += size;
}
/**
* Called when the rendering context was lost. It releases all context related resources.
*
* @ignore
*/
loseContext() {
this.impl.loseContext();
}
/**
* Returns the data format of the specified vertex buffer.
*
* @returns {import('./vertex-format.js').VertexFormat} The data format of the specified vertex
* buffer.
*/
getFormat() {
return this.format;
}
/**
* Returns the usage type of the specified vertex buffer. This indicates whether the buffer can
* be modified once and used many times {@link BUFFER_STATIC}, modified repeatedly and used
* many times {@link BUFFER_DYNAMIC} or modified once and used at most a few times
* {@link BUFFER_STREAM}.
*
* @returns {number} The usage type of the vertex buffer (see BUFFER_*).
*/
getUsage() {
return this.usage;
}
/**
* Returns the number of vertices stored in the specified vertex buffer.
*
* @returns {number} The number of vertices stored in the vertex buffer.
*/
getNumVertices() {
return this.numVertices;
}
/**
* Returns a mapped memory block representing the content of the vertex buffer.
*
* @returns {ArrayBuffer} An array containing the byte data stored in the vertex buffer.
*/
lock() {
return this.storage;
}
/**
* Notifies the graphics engine that the client side copy of the vertex buffer's memory can be
* returned to the control of the graphics driver.
*/
unlock() {
// Upload the new vertex data
this.impl.unlock(this);
}
/**
* Copies data into vertex buffer's memory.
*
* @param {ArrayBuffer} [data] - Source data to copy.
* @returns {boolean} True if function finished successfully, false otherwise.
*/
setData(data) {
if (data.byteLength !== this.numBytes) {
Debug.error(`VertexBuffer: wrong initial data size: expected ${this.numBytes}, got ${data.byteLength}`);
return false;
}
this.storage = data;
this.unlock();
return true;
}
}
export { VertexBuffer };