import { assert } from "../utils/assert.js"; import { BYTES, COMPONENTS } from "../gltf-utils/gltf-constants.js"; /** * Memory needed to store texture and all mipmap levels 1 + 1/4 + 1/16 + 1/64 + ... * Minimum 1.33, but due to GPU layout may be 1.5 */ const MIPMAP_FACTOR = 1.33; const TYPES = ['SCALAR', 'VEC2', 'VEC3', 'VEC4']; const ARRAY_CONSTRUCTOR_TO_WEBGL_CONSTANT = [ [Int8Array, 5120], [Uint8Array, 5121], [Int16Array, 5122], [Uint16Array, 5123], [Uint32Array, 5125], [Float32Array, 5126], [Float64Array, 5130] ]; const ARRAY_TO_COMPONENT_TYPE = new Map(ARRAY_CONSTRUCTOR_TO_WEBGL_CONSTANT); const ATTRIBUTE_TYPE_TO_COMPONENTS = { SCALAR: 1, VEC2: 2, VEC3: 3, VEC4: 4, MAT2: 4, MAT3: 9, MAT4: 16 }; const ATTRIBUTE_COMPONENT_TYPE_TO_BYTE_SIZE = { 5120: 1, 5121: 1, 5122: 2, 5123: 2, 5125: 4, 5126: 4 }; const ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY = { 5120: Int8Array, 5121: Uint8Array, 5122: Int16Array, 5123: Uint16Array, 5125: Uint32Array, 5126: Float32Array }; export function getAccessorTypeFromSize(size) { const type = TYPES[size - 1]; return type || TYPES[0]; } export function getComponentTypeFromArray(typedArray) { const componentType = ARRAY_TO_COMPONENT_TYPE.get(typedArray.constructor); if (!componentType) { throw new Error('Illegal typed array'); } return componentType; } export function getAccessorArrayTypeAndLength(accessor, bufferView) { const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[accessor.componentType]; const components = ATTRIBUTE_TYPE_TO_COMPONENTS[accessor.type]; const bytesPerComponent = ATTRIBUTE_COMPONENT_TYPE_TO_BYTE_SIZE[accessor.componentType]; const length = accessor.count * components; const byteLength = accessor.count * components * bytesPerComponent; assert(byteLength >= 0 && byteLength <= bufferView.byteLength); const componentByteSize = BYTES[accessor.componentType]; const numberOfComponentsInElement = COMPONENTS[accessor.type]; return { ArrayType, length, byteLength, componentByteSize, numberOfComponentsInElement }; } /** * Calculate the GPU memory used by a GLTF tile, for both buffer and texture memory * @param gltf - the gltf content of a GLTF tile * @returns - total memory usage in bytes */ export function getMemoryUsageGLTF(gltf) { let { images, bufferViews } = gltf; images = images || []; bufferViews = bufferViews || []; const imageBufferViews = images.map((i) => i.bufferView); bufferViews = bufferViews.filter((view) => !imageBufferViews.includes(view)); const bufferMemory = bufferViews.reduce((acc, view) => acc + view.byteLength, 0); // Assume each pixel of the texture is 4 channel with mimmaps (which add 33%) // TODO correctly handle compressed textures const pixelCount = images.reduce((acc, image) => { // @ts-ignore const { width, height } = image.image; return acc + width * height; }, 0); return bufferMemory + Math.ceil(4 * pixelCount * MIPMAP_FACTOR); }