{"version":3,"file":"Batcher.mjs","sources":["../../../../src/rendering/batcher/shared/Batcher.ts"],"sourcesContent":["import { uid } from '../../../utils/data/uid';\nimport { ViewableBuffer } from '../../../utils/data/ViewableBuffer';\nimport { fastCopy } from '../../renderers/shared/buffer/utils/fastCopy';\nimport { type BLEND_MODES } from '../../renderers/shared/state/const';\nimport { getAdjustedBlendModeBlend } from '../../renderers/shared/state/getAdjustedBlendModeBlend';\nimport { getMaxTexturesPerBatch } from '../gl/utils/maxRecommendedTextures';\nimport { BatchTextureArray } from './BatchTextureArray';\n\nimport type { BoundsData } from '../../../scene/container/bounds/Bounds';\nimport type { BindGroup } from '../../renderers/gpu/shader/BindGroup';\nimport type { Geometry, IndexBufferArray } from '../../renderers/shared/geometry/Geometry';\nimport type { Instruction } from '../../renderers/shared/instructions/Instruction';\nimport type { InstructionSet } from '../../renderers/shared/instructions/InstructionSet';\nimport type { Shader } from '../../renderers/shared/shader/Shader';\nimport type { Texture } from '../../renderers/shared/texture/Texture';\n\nexport type BatchAction = 'startBatch' | 'renderBatch';\n\n/**\n * A batch pool is used to store batches when they are not currently in use.\n * @memberof rendering\n */\nexport class Batch implements Instruction\n{\n public renderPipeId = 'batch';\n public action: BatchAction = 'startBatch';\n\n // TODO - eventually this could be useful for flagging batches as dirty and then only rebuilding those ones\n // public elementStart = 0;\n // public elementSize = 0;\n\n // for drawing..\n public start = 0;\n public size = 0;\n public textures: BatchTextureArray = new BatchTextureArray();\n\n public blendMode: BLEND_MODES = 'normal';\n\n public canBundle = true;\n\n /**\n * breaking rules slightly here in the name of performance..\n * storing references to these bindgroups here is just faster for access!\n * keeps a reference to the GPU bind group to set when rendering this batch for WebGPU. Will be null is using WebGL.\n */\n public gpuBindGroup: GPUBindGroup;\n /**\n * breaking rules slightly here in the name of performance..\n * storing references to these bindgroups here is just faster for access!\n * keeps a reference to the bind group to set when rendering this batch for WebGPU. Will be null if using WebGl.\n */\n public bindGroup: BindGroup;\n\n public batcher: Batcher;\n\n public destroy()\n {\n this.textures = null;\n this.gpuBindGroup = null;\n this.bindGroup = null;\n this.batcher = null;\n }\n}\n\n// inlined pool for SPEEEEEEEEEED :D\nconst batchPool: Batch[] = [];\nlet batchPoolIndex = 0;\n\nfunction getBatchFromPool()\n{\n return batchPoolIndex > 0 ? batchPool[--batchPoolIndex] : new Batch();\n}\n\nfunction returnBatchToPool(batch: Batch)\n{\n batchPool[batchPoolIndex++] = batch;\n}\n\n/**\n * Represents an element that can be batched for rendering.\n * @interface\n * @memberof rendering\n */\nexport interface BatchableElement\n{\n /**\n * The name of the batcher to use. Must be registered.\n * @type {string}\n */\n batcherName: string;\n\n /**\n * The texture to be used for rendering.\n * @type {Texture}\n */\n texture: Texture;\n\n /**\n * The blend mode to be applied.\n * @type {BLEND_MODES}\n */\n blendMode: BLEND_MODES;\n\n /**\n * The size of the index data.\n * @type {number}\n */\n indexSize: number;\n\n /**\n * The size of the attribute data.\n * @type {number}\n */\n attributeSize: number;\n\n /**\n * Whether the element should be packed as a quad for better performance.\n * @type {boolean}\n */\n packAsQuad: boolean;\n\n /**\n * The texture ID, stored for efficient updating.\n * @type {number}\n * @private\n */\n _textureId: number;\n\n /**\n * The starting position in the attribute buffer.\n * @type {number}\n * @private\n */\n _attributeStart: number;\n\n /**\n * The starting position in the index buffer.\n * @type {number}\n * @private\n */\n _indexStart: number;\n\n /**\n * Reference to the batcher.\n * @type {Batcher}\n * @private\n */\n _batcher: Batcher;\n\n /**\n * Reference to the batch.\n * @type {Batch}\n * @private\n */\n _batch: Batch;\n}\n\n/**\n * Represents a batchable quad element.\n * @extends BatchableElement\n * @memberof rendering\n */\nexport interface BatchableQuadElement extends BatchableElement\n{\n /**\n * Indicates that this element should be packed as a quad.\n * @type {true}\n */\n packAsQuad: true;\n\n /**\n * The size of the attribute data for this quad element.\n * @type {4}\n */\n attributeSize: 4;\n\n /**\n * The size of the index data for this quad element.\n * @type {6}\n */\n indexSize: 6;\n\n /**\n * The bounds data for this quad element.\n * @type {BoundsData}\n */\n bounds: BoundsData;\n}\n\n/**\n * Represents a batchable mesh element.\n * @extends BatchableElement\n * @memberof rendering\n */\nexport interface BatchableMeshElement extends BatchableElement\n{\n /**\n * The UV coordinates of the mesh.\n * @type {number[] | Float32Array}\n */\n uvs: number[] | Float32Array;\n\n /**\n * The vertex positions of the mesh.\n * @type {number[] | Float32Array}\n */\n positions: number[] | Float32Array;\n\n /**\n * The indices of the mesh.\n * @type {number[] | Uint16Array | Uint32Array}\n */\n indices: number[] | Uint16Array | Uint32Array;\n\n /**\n * The offset in the index buffer.\n * @type {number}\n */\n indexOffset: number;\n\n /**\n * The offset in the attribute buffer.\n * @type {number}\n */\n attributeOffset: number;\n\n /**\n * Indicates that this element should not be packed as a quad.\n * @type {false}\n */\n packAsQuad: false;\n}\n\nlet BATCH_TICK = 0;\n\n/**\n * The options for the batcher.\n * @memberof rendering\n */\nexport interface BatcherOptions\n{\n /** The maximum number of textures per batch. */\n maxTextures?: number;\n attributesInitialSize?: number;\n indicesInitialSize?: number;\n}\n\n/**\n * A batcher is used to batch together objects with the same texture.\n * It is an abstract class that must be extended. see DefaultBatcher for an example.\n * @memberof rendering\n */\nexport abstract class Batcher\n{\n public static defaultOptions: Partial = {\n maxTextures: null,\n attributesInitialSize: 4,\n indicesInitialSize: 6,\n };\n\n /** unique id for this batcher */\n public readonly uid: number = uid('batcher');\n\n /** The buffer containing attribute data for all elements in the batch. */\n public attributeBuffer: ViewableBuffer;\n\n /** The buffer containing index data for all elements in the batch. */\n public indexBuffer: IndexBufferArray;\n\n /** The current size of the attribute data in the batch. */\n public attributeSize: number;\n\n /** The current size of the index data in the batch. */\n public indexSize: number;\n\n /** The total number of elements currently in the batch. */\n public elementSize: number;\n\n /** The starting index of elements in the current batch. */\n public elementStart: number;\n\n /** Indicates whether the batch data has been modified and needs updating. */\n public dirty = true;\n\n /** The current index of the batch being processed. */\n public batchIndex = 0;\n\n /** An array of all batches created during the current rendering process. */\n public batches: Batch[] = [];\n\n private _elements: BatchableElement[] = [];\n\n private _batchIndexStart: number;\n private _batchIndexSize: number;\n\n /** The maximum number of textures per batch. */\n public readonly maxTextures: number;\n\n /** The name of the batcher. Must be implemented by subclasses. */\n public abstract name: string;\n /** The vertex size of the batcher. Must be implemented by subclasses. */\n protected abstract vertexSize: number;\n\n /** The geometry used by this batcher. Must be implemented by subclasses. */\n public abstract geometry: Geometry;\n\n /**\n * The shader used by this batcher. Must be implemented by subclasses.\n * this can be shared by multiple batchers of the same type.\n */\n public abstract shader: Shader;\n\n /**\n * Packs the attributes of a BatchableMeshElement into the provided views.\n * Must be implemented by subclasses.\n * @param element - The BatchableMeshElement to pack.\n * @param float32View - The Float32Array view to pack into.\n * @param uint32View - The Uint32Array view to pack into.\n * @param index - The starting index in the views.\n * @param textureId - The texture ID to use.\n */\n public abstract packAttributes(\n element: BatchableMeshElement,\n float32View: Float32Array,\n uint32View: Uint32Array,\n index: number,\n textureId: number\n ): void;\n\n /**\n * Packs the attributes of a BatchableQuadElement into the provided views.\n * Must be implemented by subclasses.\n * @param element - The BatchableQuadElement to pack.\n * @param float32View - The Float32Array view to pack into.\n * @param uint32View - The Uint32Array view to pack into.\n * @param index - The starting index in the views.\n * @param textureId - The texture ID to use.\n */\n public abstract packQuadAttributes(\n element: BatchableQuadElement,\n float32View: Float32Array,\n uint32View: Uint32Array,\n index: number,\n textureId: number\n ): void;\n\n constructor(options: BatcherOptions = {})\n {\n Batcher.defaultOptions.maxTextures = Batcher.defaultOptions.maxTextures ?? getMaxTexturesPerBatch();\n options = { ...Batcher.defaultOptions, ...options };\n\n const { maxTextures, attributesInitialSize, indicesInitialSize } = options;\n\n this.attributeBuffer = new ViewableBuffer(attributesInitialSize * 4);\n\n this.indexBuffer = new Uint16Array(indicesInitialSize);\n\n this.maxTextures = maxTextures;\n }\n\n public begin()\n {\n this.elementSize = 0;\n this.elementStart = 0;\n this.indexSize = 0;\n this.attributeSize = 0;\n\n for (let i = 0; i < this.batchIndex; i++)\n {\n returnBatchToPool(this.batches[i]);\n }\n\n this.batchIndex = 0;\n this._batchIndexStart = 0;\n this._batchIndexSize = 0;\n\n this.dirty = true;\n }\n\n public add(batchableObject: BatchableElement)\n {\n this._elements[this.elementSize++] = batchableObject;\n\n batchableObject._indexStart = this.indexSize;\n batchableObject._attributeStart = this.attributeSize;\n batchableObject._batcher = this;\n\n this.indexSize += batchableObject.indexSize;\n this.attributeSize += ((batchableObject.attributeSize) * this.vertexSize);\n }\n\n public checkAndUpdateTexture(batchableObject: BatchableElement, texture: Texture): boolean\n {\n const textureId = batchableObject._batch.textures.ids[texture._source.uid];\n\n // TODO could try to be a bit smarter if there are spare textures..\n // but need to figure out how to alter the bind groups too..\n if (!textureId && textureId !== 0) return false;\n\n batchableObject._textureId = textureId;\n batchableObject.texture = texture;\n\n return true;\n }\n\n public updateElement(batchableObject: BatchableElement)\n {\n this.dirty = true;\n\n const attributeBuffer = this.attributeBuffer;\n\n if (batchableObject.packAsQuad)\n {\n this.packQuadAttributes(\n batchableObject as BatchableQuadElement,\n attributeBuffer.float32View,\n attributeBuffer.uint32View,\n batchableObject._attributeStart, batchableObject._textureId);\n }\n else\n {\n this.packAttributes(\n batchableObject as BatchableMeshElement,\n attributeBuffer.float32View,\n attributeBuffer.uint32View,\n batchableObject._attributeStart, batchableObject._textureId);\n }\n }\n\n /**\n * breaks the batcher. This happens when a batch gets too big,\n * or we need to switch to a different type of rendering (a filter for example)\n * @param instructionSet\n */\n public break(instructionSet: InstructionSet)\n {\n const elements = this._elements;\n\n // length 0??!! (we broke without adding anything)\n if (!elements[this.elementStart]) return;\n\n let batch = getBatchFromPool();\n let textureBatch = batch.textures;\n\n textureBatch.clear();\n\n const firstElement = elements[this.elementStart];\n let blendMode = getAdjustedBlendModeBlend(firstElement.blendMode, firstElement.texture._source);\n\n if (this.attributeSize * 4 > this.attributeBuffer.size)\n {\n this._resizeAttributeBuffer(this.attributeSize * 4);\n }\n\n if (this.indexSize > this.indexBuffer.length)\n {\n this._resizeIndexBuffer(this.indexSize);\n }\n\n const f32 = this.attributeBuffer.float32View;\n const u32 = this.attributeBuffer.uint32View;\n const indexBuffer = this.indexBuffer;\n\n let size = this._batchIndexSize;\n let start = this._batchIndexStart;\n\n let action: BatchAction = 'startBatch';\n\n const maxTextures = this.maxTextures;\n\n for (let i = this.elementStart; i < this.elementSize; ++i)\n {\n const element = elements[i];\n\n elements[i] = null;\n\n const texture = element.texture;\n const source = texture._source;\n\n const adjustedBlendMode = getAdjustedBlendModeBlend(element.blendMode, source);\n\n const breakRequired = blendMode !== adjustedBlendMode;\n\n if (source._batchTick === BATCH_TICK && !breakRequired)\n {\n element._textureId = source._textureBindLocation;\n\n size += element.indexSize;\n\n if (element.packAsQuad)\n {\n this.packQuadAttributes(\n element as BatchableQuadElement,\n f32, u32,\n element._attributeStart, element._textureId\n );\n this.packQuadIndex(\n indexBuffer,\n element._indexStart,\n element._attributeStart / this.vertexSize\n );\n }\n else\n {\n this.packAttributes(\n element as BatchableMeshElement,\n f32, u32,\n element._attributeStart,\n element._textureId\n );\n this.packIndex(\n element as BatchableMeshElement,\n indexBuffer,\n element._indexStart,\n element._attributeStart / this.vertexSize\n );\n }\n\n element._batch = batch;\n\n continue;\n }\n\n source._batchTick = BATCH_TICK;\n\n if (textureBatch.count >= maxTextures || breakRequired)\n {\n this._finishBatch(\n batch,\n start,\n size - start,\n textureBatch,\n blendMode,\n instructionSet,\n action\n );\n\n action = 'renderBatch';\n start = size;\n // create a batch...\n blendMode = adjustedBlendMode;\n\n batch = getBatchFromPool();\n textureBatch = batch.textures;\n textureBatch.clear();\n\n ++BATCH_TICK;\n }\n\n element._textureId = source._textureBindLocation = textureBatch.count;\n textureBatch.ids[source.uid] = textureBatch.count;\n textureBatch.textures[textureBatch.count++] = source;\n element._batch = batch;\n\n size += element.indexSize;\n\n if (element.packAsQuad)\n {\n this.packQuadAttributes(\n element as BatchableQuadElement,\n f32, u32,\n element._attributeStart, element._textureId\n );\n this.packQuadIndex(\n indexBuffer,\n element._indexStart,\n element._attributeStart / this.vertexSize\n );\n }\n else\n {\n this.packAttributes(element as BatchableMeshElement,\n f32, u32,\n element._attributeStart, element._textureId\n );\n\n this.packIndex(\n element as BatchableMeshElement,\n indexBuffer,\n element._indexStart,\n element._attributeStart / this.vertexSize\n );\n }\n }\n\n if (textureBatch.count > 0)\n {\n this._finishBatch(\n batch,\n start,\n size - start,\n textureBatch,\n blendMode,\n instructionSet,\n action\n );\n\n start = size;\n ++BATCH_TICK;\n }\n\n this.elementStart = this.elementSize;\n this._batchIndexStart = start;\n this._batchIndexSize = size;\n }\n\n private _finishBatch(\n batch: Batch,\n indexStart: number,\n indexSize: number,\n textureBatch: BatchTextureArray,\n blendMode: BLEND_MODES,\n instructionSet: InstructionSet,\n action: BatchAction\n )\n {\n batch.gpuBindGroup = null;\n batch.bindGroup = null;\n batch.action = action;\n\n batch.batcher = this;\n batch.textures = textureBatch;\n batch.blendMode = blendMode;\n\n batch.start = indexStart;\n batch.size = indexSize;\n\n ++BATCH_TICK;\n\n // track for returning later!\n this.batches[this.batchIndex++] = batch;\n instructionSet.add(batch);\n }\n\n public finish(instructionSet: InstructionSet)\n {\n this.break(instructionSet);\n }\n\n /**\n * Resizes the attribute buffer to the given size (1 = 1 float32)\n * @param size - the size in vertices to ensure (not bytes!)\n */\n public ensureAttributeBuffer(size: number)\n {\n if (size * 4 <= this.attributeBuffer.size) return;\n\n this._resizeAttributeBuffer(size * 4);\n }\n\n /**\n * Resizes the index buffer to the given size (1 = 1 float32)\n * @param size - the size in vertices to ensure (not bytes!)\n */\n public ensureIndexBuffer(size: number)\n {\n if (size <= this.indexBuffer.length) return;\n\n this._resizeIndexBuffer(size);\n }\n\n private _resizeAttributeBuffer(size: number)\n {\n const newSize = Math.max(size, this.attributeBuffer.size * 2);\n\n const newArrayBuffer = new ViewableBuffer(newSize);\n\n fastCopy(this.attributeBuffer.rawBinaryData, newArrayBuffer.rawBinaryData);\n\n this.attributeBuffer = newArrayBuffer;\n }\n\n private _resizeIndexBuffer(size: number)\n {\n const indexBuffer = this.indexBuffer;\n\n let newSize = Math.max(size, indexBuffer.length * 1.5);\n\n newSize += newSize % 2;\n\n // this, is technically not 100% accurate, as really we should\n // be checking the maximum value in the buffer. This approximation\n // does the trick though...\n\n // make sure buffer is always an even number..\n const newIndexBuffer = (newSize > 65535) ? new Uint32Array(newSize) : new Uint16Array(newSize);\n\n if (newIndexBuffer.BYTES_PER_ELEMENT !== indexBuffer.BYTES_PER_ELEMENT)\n {\n for (let i = 0; i < indexBuffer.length; i++)\n {\n newIndexBuffer[i] = indexBuffer[i];\n }\n }\n else\n {\n fastCopy(indexBuffer.buffer, newIndexBuffer.buffer);\n }\n\n this.indexBuffer = newIndexBuffer;\n }\n\n public packQuadIndex(indexBuffer: IndexBufferArray, index: number, indicesOffset: number)\n {\n indexBuffer[index] = indicesOffset + 0;\n indexBuffer[index + 1] = indicesOffset + 1;\n indexBuffer[index + 2] = indicesOffset + 2;\n\n indexBuffer[index + 3] = indicesOffset + 0;\n indexBuffer[index + 4] = indicesOffset + 2;\n indexBuffer[index + 5] = indicesOffset + 3;\n }\n\n public packIndex(element: BatchableMeshElement, indexBuffer: IndexBufferArray, index: number, indicesOffset: number)\n {\n const indices = element.indices;\n const size = element.indexSize;\n const indexOffset = element.indexOffset;\n const attributeOffset = element.attributeOffset;\n\n for (let i = 0; i < size; i++)\n {\n indexBuffer[index++] = indicesOffset + indices[i + indexOffset] - attributeOffset;\n }\n }\n\n public destroy()\n {\n for (let i = 0; i < this.batches.length; i++)\n {\n returnBatchToPool(this.batches[i]);\n }\n\n this.batches = null;\n\n for (let i = 0; i < this._elements.length; i++)\n {\n this._elements[i]._batch = null;\n }\n\n this._elements = null;\n\n this.indexBuffer = null;\n\n this.attributeBuffer.destroy();\n this.attributeBuffer = null;\n }\n}\n\n"],"names":[],"mappings":"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"}