/** @internal NOTE: Internal APIs. Subject to change. Use of these APIs in production applications is not supported. */ /** */
import { MemoryBlock } from './MemoryBlock';
import { SeverityLevel } from '@microsoft/applicationinsights-web';
import { telemetry } from '../Telemetry';
const maxIndicesInUint16IndiceBuffer = 65535;
/**
 * Represents a block of reusable geometry memory.
 * It is expensive to allocate memory for geometry arrays (vertices, normals, indices) for each mesh.
 * By using this class we can allocate a large block of memory and then allocate smaller slices from this block
 * to write geometry data to. For example during mesh merging.
 */
export class GeometryBuffer {
    static _memoryBlockOptions = {
        onAllocate: (id, byteLength) => telemetry.trackEvent({ name: 'malloc' }, { id, byteLength, mbLength: Math.round((byteLength * 100.0) / (1024.0 * 1024.0)) / 100.0 }),
        onOutOfMemory: (id, requested, available) => telemetry.trackTrace({ message: 'Out of memory', severityLevel: SeverityLevel.Critical }, { id, overshoot: requested - available })
    };
    _verticesBlock = new MemoryBlock('mesh-merge-vertices', Float32Array, GeometryBuffer._memoryBlockOptions);
    _normalsBlock = new MemoryBlock('mesh-merge-normals', Float32Array, GeometryBuffer._memoryBlockOptions);
    _uint32IndiceBlock = new MemoryBlock('mesh-merge-uint32indices', Uint32Array, GeometryBuffer._memoryBlockOptions);
    /**
     * Total size in bytes of geometry memory.
     */
    get byteLength() {
        return this._verticesBlock.byteLength + this._normalsBlock.byteLength + this._uint32IndiceBlock.byteLength;
    }
    /**
     * Updates the maximum length of the geometry buffer to accommodate the given primitive count and indice count.
     * If the given counts are greater than the current maximum lengths, then the maximum size will be updated.
     *
     * @param primitiveCount - The desired primitive count.
     * @param indiceCount - The desired indice count.
     * @returns This  {@link GeometryBuffer} instance.
     */
    maximizeLength(primitiveCount, indiceCount) {
        // Update max values so we can allocate one large memory block during mesh merging
        primitiveCount = Math.max(primitiveCount, this._verticesBlock.length / 3);
        indiceCount = Math.max(indiceCount, this._uint32IndiceBlock.length);
        this._verticesBlock.length = primitiveCount * 3;
        this._normalsBlock.length = primitiveCount * 2;
        this._uint32IndiceBlock.length = indiceCount;
        return this;
    }
    /**
     * Allocate a block of geometry arrays ({@link GeometryArrays}). Only one allocation at a time may exist
     * Therefore next call to this method will invalidate contents of previous {@link GeometryArrays} instances.
     * @param primitiveCount Number of primitives to allocate.
     * @param indiceCount Number of indices to allocate.
     */
    malloc(primitiveCount, indiceCount) {
        // We can only allocate and use one block at any one time. So subsequent calls to malloc will
        // simply reset the offset to 0 and return slices from the beginning of the block.
        // this invalidates any previous GeometryArrays instances.
        this._verticesBlock.offset = this._normalsBlock.offset = this._uint32IndiceBlock.offset = 0;
        return {
            positions: this._verticesBlock.subarray(primitiveCount * 3),
            uvs: this._normalsBlock.subarray(primitiveCount * 2), // Normals are stored in the first 16 bits of of the second float in the uvs
            indices: this.indiceBlock(primitiveCount, indiceCount)
        };
    }
    /**
     * Frees the memory used by the geometry buffer.
     */
    free() {
        this._verticesBlock.free();
        this._normalsBlock.free();
        this._uint32IndiceBlock.free();
    }
    indiceBlock(primitiveCount, indiceCount) {
        if (primitiveCount > maxIndicesInUint16IndiceBuffer)
            return this._uint32IndiceBlock.subarray(indiceCount);
        return this._uint32IndiceBlock.subView(indiceCount, Uint16Array);
    }
}
//# sourceMappingURL=GeometryBuffer.js.map