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">

1 lines 36 kB
{"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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"}