playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
80 lines (79 loc) • 2.77 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import { DynamicBuffers } from "../dynamic-buffers.js";
import { WebglDynamicBuffer } from "./webgl-dynamic-buffer.js";
class WebglDynamicBuffers extends DynamicBuffers {
/**
* @param {WebglGraphicsDevice} device - The graphics device.
*/
constructor(device) {
super(device, 0, 0);
/**
* Free buffers available for allocation, keyed by byte size.
*
* @type {Map<number, WebglDynamicBuffer[]>}
*/
__publicField(this, "free", /* @__PURE__ */ new Map());
/**
* Buffers handed out during the current frame, returned to the free pool at frame end.
*
* @type {WebglDynamicBuffer[]}
*/
__publicField(this, "used", []);
}
destroy() {
this.used.forEach((buffer) => buffer.destroy(this.device));
this.free.forEach((buffers) => buffers.forEach((buffer) => buffer.destroy(this.device)));
this.used = null;
this.free = null;
}
/**
* Allocate a whole buffer of the given size for this frame.
*
* @param {DynamicBufferAllocation} allocation - The allocation info to fill.
* @param {number} size - The size of the allocation.
*/
alloc(allocation, size) {
let buffer = this.free.get(size)?.pop();
if (!buffer) {
buffer = new WebglDynamicBuffer(this.device, size);
}
this.used.push(buffer);
allocation.gpuBuffer = buffer;
allocation.offset = 0;
allocation.storage = buffer.storage;
}
/**
* Return the frame's buffers to the free pool. Called at the end of the frame, so it runs after
* all allocations (including any made before frameStart, e.g. from app update handlers).
*/
onFrameEnd() {
const used = this.used;
for (let i = 0; i < used.length; i++) {
const buffer = used[i];
let pool = this.free.get(buffer.size);
if (!pool) {
pool = [];
this.free.set(buffer.size, pool);
}
pool.push(buffer);
}
used.length = 0;
}
/**
* Called when the rendering context is lost. Returns any in-flight buffers to the free pool and
* drops every buffer's GL handle (without deleting - the context is invalid). The buffer objects
* and their CPU storage are kept, so they are reused and their GL buffers recreated on the next
* upload after the context is restored.
*/
loseContext() {
this.onFrameEnd();
this.free.forEach((buffers) => {
buffers.forEach((buffer) => buffer.loseContext());
});
}
}
export {
WebglDynamicBuffers
};