From ff71ee8419e08657d7cff19b60e4307a5537868e Mon Sep 17 00:00:00 2001 From: Ben Richards Date: Fri, 31 May 2024 21:08:32 +1200 Subject: [PATCH] Associate data and data views with buffers. --- .../webgl/renderNodes/BatchHandler.js | 17 +++- .../webgl/renderNodes/LightBatchHandler.js | 5 +- .../webgl/renderNodes/QuadBatchHandler.js | 18 ++-- .../webgl/wrappers/WebGLBufferWrapper.js | 83 +++++++++++++++---- .../WebGLVertexBufferLayoutWrapper.js | 18 ---- 5 files changed, 91 insertions(+), 50 deletions(-) diff --git a/src/renderer/webgl/renderNodes/BatchHandler.js b/src/renderer/webgl/renderNodes/BatchHandler.js index fc3a7cc24..b3ef2f4bc 100644 --- a/src/renderer/webgl/renderNodes/BatchHandler.js +++ b/src/renderer/webgl/renderNodes/BatchHandler.js @@ -202,6 +202,15 @@ var BatchHandler = new Class({ this.vertexBufferLayout ]); + /** + * The number of bytes per instance, used to determine how much of the vertex buffer to upload. + * + * @name Phaser.Renderer.WebGL.RenderNodes.BatchHandler#bytesPerInstance + * @type {number} + * @since 3.90.0 + */ + this.bytesPerInstance = this.vertexBufferLayout.layout.stride * this.verticesPerInstance; + /** * The number of floats per instance, used to determine how much of the vertex buffer to update. * @@ -209,7 +218,7 @@ var BatchHandler = new Class({ * @type {number} * @since 3.90.0 */ - this.floatsPerInstance = this.vertexBufferLayout.layout.stride * this.verticesPerInstance / Float32Array.BYTES_PER_ELEMENT; + this.floatsPerInstance = this.bytesPerInstance / Float32Array.BYTES_PER_ELEMENT; /** * The current batch entry being filled with textures. @@ -331,12 +340,12 @@ var BatchHandler = new Class({ * @since 3.90.0 * @private * @param {number} instances - The number of instances to define. - * @return {Uint16Array} The index buffer data. + * @return {ArrayBuffer} The index buffer data. */ _generateElementIndices: function (instances) { - // This is meaningless and should be overridden by subclasses. - return new Uint16Array(instances); + // This is empty and should be overridden by subclasses. + return new ArrayBuffer(instances * this.bytesPerInstance); }, /** diff --git a/src/renderer/webgl/renderNodes/LightBatchHandler.js b/src/renderer/webgl/renderNodes/LightBatchHandler.js index 19b7bccea..3026fd217 100644 --- a/src/renderer/webgl/renderNodes/LightBatchHandler.js +++ b/src/renderer/webgl/renderNodes/LightBatchHandler.js @@ -316,8 +316,9 @@ var LightBatchHandler = new Class({ // Update the vertex buffer. var vertexOffset32 = this.instanceCount * this.floatsPerInstance; - var vertexViewF32 = this.vertexBufferLayout.viewFloat32; - var vertexViewU32 = this.vertexBufferLayout.viewUint32; + var vertexBuffer = this.vertexBufferLayout.buffer; + var vertexViewF32 = vertexBuffer.viewF32; + var vertexViewU32 = vertexBuffer.viewU32; // Top-left vertexViewF32[vertexOffset32++] = x0; diff --git a/src/renderer/webgl/renderNodes/QuadBatchHandler.js b/src/renderer/webgl/renderNodes/QuadBatchHandler.js index 8378184e7..cda64099e 100644 --- a/src/renderer/webgl/renderNodes/QuadBatchHandler.js +++ b/src/renderer/webgl/renderNodes/QuadBatchHandler.js @@ -89,11 +89,12 @@ var QuadBatchHandler = new Class({ * @since 3.90.0 * @private * @param {number} instances - The number of instances to define. - * @return {Uint16Array} The index buffer data. + * @return {ArrayBuffer} The index buffer data. */ _generateElementIndices: function (instances) { - var indices = new Uint16Array(instances * 6); + var buffer = new ArrayBuffer(instances * 6 * 2); + var indices = new Uint16Array(buffer); var offset = 0; for (var i = 0; i < instances; i++) { @@ -105,7 +106,7 @@ var QuadBatchHandler = new Class({ indices[offset++] = index + 3; indices[offset++] = index + 3; } - return indices; + return buffer; }, /** @@ -226,13 +227,11 @@ var QuadBatchHandler = new Class({ // Update vertex buffers. if (this.instanceCount < this.instancesPerBatch) { - // We use a subarray to avoid copying the buffer, but still - // control the length. - vertexBuffer.update(this.vertexBufferLayout.viewFloat32.subarray(0, this.instanceCount * this.floatsPerInstance)); + vertexBuffer.update(this.instanceCount * this.bytesPerInstance); } else { - vertexBuffer.update(this.vertexBufferLayout.data); + vertexBuffer.update(); } var subBatches = this.batchEntries.length; @@ -325,8 +324,9 @@ var QuadBatchHandler = new Class({ // Update the vertex buffer. var vertexOffset32 = this.instanceCount * this.floatsPerInstance; - var vertexViewF32 = this.vertexBufferLayout.viewFloat32; - var vertexViewU32 = this.vertexBufferLayout.viewUint32; + var vertexBuffer = this.vertexBufferLayout.buffer; + var vertexViewF32 = vertexBuffer.viewF32; + var vertexViewU32 = vertexBuffer.viewU32; // Top-left vertexViewF32[vertexOffset32++] = x0; diff --git a/src/renderer/webgl/wrappers/WebGLBufferWrapper.js b/src/renderer/webgl/wrappers/WebGLBufferWrapper.js index 0ca36e808..df1039d9f 100644 --- a/src/renderer/webgl/wrappers/WebGLBufferWrapper.js +++ b/src/renderer/webgl/wrappers/WebGLBufferWrapper.js @@ -21,7 +21,7 @@ var Class = require('../../../utils/Class'); * @since 3.80.0 * * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer instance that owns this wrapper. - * @param {ArrayBuffer|number} initialDataOrSize - Either an ArrayBuffer of data, or the size of the buffer to create. + * @param {ArrayBuffer} dataBuffer - An ArrayBuffer of data to store. The buffer will be permanently associated with this data. * @param {GLenum} bufferType - The type of the buffer being created. * @param {GLenum} bufferUsage - The usage of the buffer being created. gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW. */ @@ -29,7 +29,7 @@ var WebGLBufferWrapper = new Class({ initialize: - function WebGLBufferWrapper (renderer, initialDataOrSize, bufferType, bufferUsage) + function WebGLBufferWrapper (renderer, dataBuffer, bufferType, bufferUsage) { /** * The WebGLRenderer instance that owns this wrapper. @@ -55,15 +55,51 @@ var WebGLBufferWrapper = new Class({ this.webGLBuffer = null; /** - * The initial data or size of the buffer. + * The data associated with the buffer. * * Note that this will be used to recreate the buffer if the WebGL context is lost. * - * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#initialDataOrSize - * @type {ArrayBuffer|number} - * @since 3.80.0 + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#dataBuffer + * @type {ArrayBuffer} + * @since 3.90.0 */ - this.initialDataOrSize = initialDataOrSize; + this.dataBuffer = dataBuffer; + + /** + * A Float32Array view of the dataBuffer. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#viewF32 + * @type {Float32Array} + * @since 3.90.0 + */ + this.viewF32 = new Float32Array(dataBuffer); + + /** + * A Uint8Array view of the dataBuffer. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#viewU8 + * @type {Uint8Array} + * @since 3.90.0 + */ + this.viewU8 = new Uint8Array(dataBuffer); + + /** + * A Uint16Array view of the dataBuffer. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#viewU16 + * @type {Uint16Array} + * @since 3.90.0 + */ + this.viewU16 = new Uint16Array(dataBuffer); + + /** + * A Uint32Array view of the dataBuffer. + * + * @name Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#viewU32 + * @type {Uint32Array} + * @since 3.90.0 + */ + this.viewU32 = new Uint32Array(dataBuffer); /** * The type of the buffer. @@ -97,11 +133,6 @@ var WebGLBufferWrapper = new Class({ */ createResource: function () { - if (this.initialDataOrSize === null) - { - return; - } - var gl = this.renderer.gl; var bufferType = this.bufferType; @@ -110,7 +141,7 @@ var WebGLBufferWrapper = new Class({ this.webGLBuffer = webGLBuffer; this.bind(); - gl.bufferData(bufferType, this.initialDataOrSize, this.bufferUsage); + gl.bufferData(bufferType, this.dataBuffer, this.bufferUsage); this.bind(true); }, @@ -144,13 +175,15 @@ var WebGLBufferWrapper = new Class({ /** * Updates the data in this WebGLBufferWrapper. + * The dataBuffer must contain the new data to be uploaded to the GPU. + * Data will preserve its range from dataBuffer to the WebGLBuffer. * * @method Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper#update * @since 3.90.0 - * @param {ArrayBuffer} data - The new data to update the buffer with. + * @param {number} [bytes] - The number of bytes to update in the buffer. If not specified, the entire buffer will be updated. * @param {number} [offset=0] - The offset into the buffer to start updating data at. */ - update: function (data, offset) + update: function (bytes, offset) { var gl = this.renderer.gl; @@ -161,7 +194,23 @@ var WebGLBufferWrapper = new Class({ offset = 0; } - gl.bufferSubData(this.bufferType, offset, data); + if (bytes === undefined) + { + gl.bufferSubData( + this.bufferType, + offset, + this.dataBuffer + ); + } + else + { + gl.bufferSubData( + this.bufferType, + offset, + this.viewU8.subarray(offset, offset + bytes) + ); + } + }, /** @@ -174,7 +223,7 @@ var WebGLBufferWrapper = new Class({ { this.renderer.gl.deleteBuffer(this.webGLBuffer); this.webGLBuffer = null; - this.initialDataOrSize = null; + this.dataBuffer = null; this.renderer = null; } }); diff --git a/src/renderer/webgl/wrappers/WebGLVertexBufferLayoutWrapper.js b/src/renderer/webgl/wrappers/WebGLVertexBufferLayoutWrapper.js index 2001c7307..2d9464f00 100644 --- a/src/renderer/webgl/wrappers/WebGLVertexBufferLayoutWrapper.js +++ b/src/renderer/webgl/wrappers/WebGLVertexBufferLayoutWrapper.js @@ -63,24 +63,6 @@ var WebGLVertexBufferLayoutWrapper = new Class({ */ this.data = new ArrayBuffer(layout.stride * layout.count); - /** - * A Float32Array view of the ArrayBuffer. - * - * @name Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper#viewFloat32 - * @type {Float32Array} - * @since 3.90.0 - */ - this.viewFloat32 = new Float32Array(this.data); - - /** - * A Uint32Array view of the ArrayBuffer. - * - * @name Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper#viewUint32 - * @type {Uint32Array} - * @since 3.90.0 - */ - this.viewUint32 = new Uint32Array(this.data); - /** * The WebGLBuffer that this layout is based on. *