UNPKG

pixi.js

Version:

<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">

203 lines (200 loc) 6.68 kB
import { ExtensionType } from '../../../../extensions/Extensions.mjs'; import { BufferUsage } from '../../shared/buffer/const.mjs'; import { BUFFER_TYPE } from './const.mjs'; import { GlBuffer } from './GlBuffer.mjs'; "use strict"; class GlBufferSystem { /** * @param {Renderer} renderer - The renderer this System works for. */ constructor(renderer) { this._gpuBuffers = /* @__PURE__ */ Object.create(null); /** Cache keeping track of the base bound buffer bases */ this._boundBufferBases = /* @__PURE__ */ Object.create(null); this._minBaseLocation = 0; this._nextBindBaseIndex = this._minBaseLocation; this._bindCallId = 0; this._renderer = renderer; this._renderer.renderableGC.addManagedHash(this, "_gpuBuffers"); } /** @ignore */ destroy() { this._renderer = null; this._gl = null; this._gpuBuffers = null; this._boundBufferBases = null; } /** Sets up the renderer context and necessary buffers. */ contextChange() { this._gl = this._renderer.gl; this._gpuBuffers = /* @__PURE__ */ Object.create(null); this._maxBindings = this._renderer.limits.maxUniformBindings; } getGlBuffer(buffer) { return this._gpuBuffers[buffer.uid] || this.createGLBuffer(buffer); } /** * This binds specified buffer. On first run, it will create the webGL buffers for the context too * @param buffer - the buffer to bind to the renderer */ bind(buffer) { const { _gl: gl } = this; const glBuffer = this.getGlBuffer(buffer); gl.bindBuffer(glBuffer.type, glBuffer.buffer); } /** * Binds an uniform buffer to at the given index. * * A cache is used so a buffer will not be bound again if already bound. * @param glBuffer - the buffer to bind * @param index - the base index to bind it to. */ bindBufferBase(glBuffer, index) { const { _gl: gl } = this; if (this._boundBufferBases[index] !== glBuffer) { this._boundBufferBases[index] = glBuffer; glBuffer._lastBindBaseLocation = index; gl.bindBufferBase(gl.UNIFORM_BUFFER, index, glBuffer.buffer); } } nextBindBase(hasTransformFeedback) { this._bindCallId++; this._minBaseLocation = 0; if (hasTransformFeedback) { this._boundBufferBases[0] = null; this._minBaseLocation = 1; if (this._nextBindBaseIndex < 1) { this._nextBindBaseIndex = 1; } } } freeLocationForBufferBase(glBuffer) { let freeIndex = this.getLastBindBaseLocation(glBuffer); if (freeIndex >= this._minBaseLocation) { glBuffer._lastBindCallId = this._bindCallId; return freeIndex; } let loop = 0; let nextIndex = this._nextBindBaseIndex; while (loop < 2) { if (nextIndex >= this._maxBindings) { nextIndex = this._minBaseLocation; loop++; } const curBuf = this._boundBufferBases[nextIndex]; if (curBuf && curBuf._lastBindCallId === this._bindCallId) { nextIndex++; continue; } break; } freeIndex = nextIndex; this._nextBindBaseIndex = nextIndex + 1; if (loop >= 2) { return -1; } glBuffer._lastBindCallId = this._bindCallId; this._boundBufferBases[freeIndex] = null; return freeIndex; } getLastBindBaseLocation(glBuffer) { const index = glBuffer._lastBindBaseLocation; if (this._boundBufferBases[index] === glBuffer) { return index; } return -1; } /** * Binds a buffer whilst also binding its range. * This will make the buffer start from the offset supplied rather than 0 when it is read. * @param glBuffer - the buffer to bind * @param index - the base index to bind at, defaults to 0 * @param offset - the offset to bind at (this is blocks of 256). 0 = 0, 1 = 256, 2 = 512 etc * @param size - the size to bind at (this is blocks of 256). */ bindBufferRange(glBuffer, index, offset, size) { const { _gl: gl } = this; offset || (offset = 0); index || (index = 0); this._boundBufferBases[index] = null; gl.bindBufferRange(gl.UNIFORM_BUFFER, index || 0, glBuffer.buffer, offset * 256, size || 256); } /** * Will ensure the data in the buffer is uploaded to the GPU. * @param {Buffer} buffer - the buffer to update */ updateBuffer(buffer) { const { _gl: gl } = this; const glBuffer = this.getGlBuffer(buffer); if (buffer._updateID === glBuffer.updateID) { return glBuffer; } glBuffer.updateID = buffer._updateID; gl.bindBuffer(glBuffer.type, glBuffer.buffer); const data = buffer.data; const drawType = buffer.descriptor.usage & BufferUsage.STATIC ? gl.STATIC_DRAW : gl.DYNAMIC_DRAW; if (data) { if (glBuffer.byteLength >= data.byteLength) { gl.bufferSubData(glBuffer.type, 0, data, 0, buffer._updateSize / data.BYTES_PER_ELEMENT); } else { glBuffer.byteLength = data.byteLength; gl.bufferData(glBuffer.type, data, drawType); } } else { glBuffer.byteLength = buffer.descriptor.size; gl.bufferData(glBuffer.type, glBuffer.byteLength, drawType); } return glBuffer; } /** dispose all WebGL resources of all managed buffers */ destroyAll() { const gl = this._gl; for (const id in this._gpuBuffers) { gl.deleteBuffer(this._gpuBuffers[id].buffer); } this._gpuBuffers = /* @__PURE__ */ Object.create(null); } /** * Disposes buffer * @param {Buffer} buffer - buffer with data * @param {boolean} [contextLost=false] - If context was lost, we suppress deleteVertexArray */ onBufferDestroy(buffer, contextLost) { const glBuffer = this._gpuBuffers[buffer.uid]; const gl = this._gl; if (!contextLost) { gl.deleteBuffer(glBuffer.buffer); } this._gpuBuffers[buffer.uid] = null; } /** * creates and attaches a GLBuffer object tied to the current context. * @param buffer * @protected */ createGLBuffer(buffer) { const { _gl: gl } = this; let type = BUFFER_TYPE.ARRAY_BUFFER; if (buffer.descriptor.usage & BufferUsage.INDEX) { type = BUFFER_TYPE.ELEMENT_ARRAY_BUFFER; } else if (buffer.descriptor.usage & BufferUsage.UNIFORM) { type = BUFFER_TYPE.UNIFORM_BUFFER; } const glBuffer = new GlBuffer(gl.createBuffer(), type); this._gpuBuffers[buffer.uid] = glBuffer; buffer.on("destroy", this.onBufferDestroy, this); return glBuffer; } resetState() { this._boundBufferBases = /* @__PURE__ */ Object.create(null); } } /** @ignore */ GlBufferSystem.extension = { type: [ ExtensionType.WebGLSystem ], name: "buffer" }; export { GlBufferSystem }; //# sourceMappingURL=GlBufferSystem.mjs.map