{"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 { deprecation } from '../../../utils/logging/deprecation';\nimport { GlobalResourceRegistry } from '../../../utils/pool/GlobalResourceRegistry';\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 { Topology } from '../../renderers/shared/geometry/const';\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\n/**\n * The action types for a batch.\n * @category rendering\n * @advanced\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 * @category rendering\n * @advanced\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    public topology: Topology = 'triangle-strip';\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    /** Elements contained in this batch. Used by the Canvas renderer. */\n    public elements: BatchableElement[];\n\n    public destroy()\n    {\n        this.textures = null;\n        this.gpuBindGroup = null;\n        this.bindGroup = null;\n        this.batcher = null;\n        this.elements = null;\n    }\n}\n\n// inlined pool for SPEEEEEEEEEED :D\nconst batchPool: Batch[] = [];\nlet batchPoolIndex = 0;\n\nGlobalResourceRegistry.register({\n    clear: () =>\n    {\n        // check if the first element has a destroy method\n        if (batchPool.length > 0)\n        {\n            for (const item of batchPool)\n            {\n                if (item) item.destroy();\n            }\n        }\n        batchPool.length = 0; // clear the array\n        batchPoolIndex = 0;\n    },\n});\n\nfunction getBatchFromPool()\n{\n    return batchPoolIndex > 0 ? batchPool[--batchPoolIndex] : new Batch();\n}\n\nfunction returnBatchToPool(batch: Batch)\n{\n    batch.elements = null;\n    batchPool[batchPoolIndex++] = batch;\n}\n\n/**\n * Represents an element that can be batched for rendering.\n * @interface\n * @category rendering\n * @advanced\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     * The topology to be used for rendering.\n     * @type {Topology}\n     */\n    topology: Topology\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/**\n * Represents a batchable quad element.\n * @extends BatchableElement\n * @category rendering\n * @advanced\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 * @category rendering\n * @advanced\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 * @category rendering\n * @advanced\n */\nexport interface BatcherOptions\n{\n    /** The maximum number of textures per batch. */\n    maxTextures: number;\n    /** The initial size of the attribute buffer. */\n    attributesInitialSize?: number;\n    /** The initial size of the index buffer. */\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 * @category rendering\n * @advanced\n */\nexport abstract class Batcher\n{\n    public static defaultOptions: Partial<BatcherOptions> = {\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        options = { ...Batcher.defaultOptions, ...options };\n\n        if (!options.maxTextures)\n        {\n            deprecation('v8.8.0', 'maxTextures is a required option for Batcher now, please pass it in the options');\n            options.maxTextures = getMaxTexturesPerBatch();\n        }\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\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        let topology = firstElement.topology;\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        let batchElements: BatchableElement[] = [];\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 || topology !== element.topology;\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                batchElements.push(element);\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                    topology,\n                    instructionSet,\n                    action,\n                    batchElements\n                );\n\n                action = 'renderBatch';\n                start = size;\n                // create a batch...\n                blendMode = adjustedBlendMode;\n                topology = element.topology;\n\n                batch = getBatchFromPool();\n                textureBatch = batch.textures;\n                textureBatch.clear();\n                batchElements = [];\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            batchElements.push(element);\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                topology,\n                instructionSet,\n                action,\n                batchElements\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        topology: Topology,\n        instructionSet: InstructionSet,\n        action: BatchAction,\n        elements?: BatchableElement[]\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        batch.topology = topology;\n        batch.start = indexStart;\n        batch.size = indexSize;\n        batch.elements = elements;\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 as ArrayBuffer, 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    /**\n     * Destroys the batch and its resources.\n     * @param options - destruction options\n     * @param options.shader - whether to destroy the associated shader\n     */\n    public destroy(options: {shader?: boolean} = {})\n    {\n        if (this.batches === null) return;\n\n        for (let i = 0; i < this.batchIndex; i++)\n        {\n            returnBatchToPool(this.batches[i]);\n        }\n\n        this.batches = null;\n        this.geometry.destroy(true);\n        this.geometry = null;\n\n        if (options.shader)\n        {\n            this.shader?.destroy();\n            this.shader = null;\n        }\n\n        for (let i = 0; i < this._elements.length; i++)\n        {\n            if (this._elements[i]) 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"],"names":[],"mappings":"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"}