"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.KTX2Loader = void 0;
var _three = require("three");
var _WorkerPool = require("../utils/WorkerPool.js");
var _ktxParseModule = require("../libs/ktx-parse.module.js");
var _zstddecModule = require("../libs/zstddec.module.js");
/**
 * Loader for KTX 2.0 GPU Texture containers.
 *
 * KTX 2.0 is a container format for various GPU texture formats. The loader
 * supports Basis Universal GPU textures, which can be quickly transcoded to
 * a wide variety of GPU texture compression formats, as well as some
 * uncompressed DataTexture and Data3DTexture formats.
 *
 * References:
 * - KTX: http://github.khronos.org/KTX-Specification/
 * - DFD: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#basicdescriptor
 */

const _taskCache = new WeakMap();
let _activeLoaders = 0;
let _zstd;
class KTX2Loader extends _three.Loader {
  constructor(manager) {
    super(manager);
    this.transcoderPath = '';
    this.transcoderBinary = null;
    this.transcoderPending = null;
    this.workerPool = new _WorkerPool.WorkerPool();
    this.workerSourceURL = '';
    this.workerConfig = null;
    if (typeof MSC_TRANSCODER !== 'undefined') {
      console.warn('THREE.KTX2Loader: Please update to latest "basis_transcoder".' + ' "msc_basis_transcoder" is no longer supported in three.js r125+.');
    }
  }
  setTranscoderPath(path) {
    this.transcoderPath = path;
    return this;
  }
  setWorkerLimit(num) {
    this.workerPool.setWorkerLimit(num);
    return this;
  }
  detectSupport(renderer) {
    if (renderer.isWebGPURenderer === true) {
      this.workerConfig = {
        astcSupported: renderer.hasFeature('texture-compression-astc'),
        etc1Supported: false,
        etc2Supported: renderer.hasFeature('texture-compression-etc2'),
        dxtSupported: renderer.hasFeature('texture-compression-bc'),
        bptcSupported: false,
        pvrtcSupported: false
      };
    } else {
      this.workerConfig = {
        astcSupported: renderer.extensions.has('WEBGL_compressed_texture_astc'),
        etc1Supported: renderer.extensions.has('WEBGL_compressed_texture_etc1'),
        etc2Supported: renderer.extensions.has('WEBGL_compressed_texture_etc'),
        dxtSupported: renderer.extensions.has('WEBGL_compressed_texture_s3tc'),
        bptcSupported: renderer.extensions.has('EXT_texture_compression_bptc'),
        pvrtcSupported: renderer.extensions.has('WEBGL_compressed_texture_pvrtc') || renderer.extensions.has('WEBKIT_WEBGL_compressed_texture_pvrtc')
      };
      if (renderer.capabilities.isWebGL2) {
        // https://github.com/mrdoob/three.js/pull/22928
        this.workerConfig.etc1Supported = false;
      }
    }
    return this;
  }
  init() {
    if (!this.transcoderPending) {
      // Load transcoder wrapper.
      const jsLoader = new _three.FileLoader(this.manager);
      jsLoader.setPath(this.transcoderPath);
      jsLoader.setWithCredentials(this.withCredentials);
      const jsContent = jsLoader.loadAsync('basis_transcoder.js');

      // Load transcoder WASM binary.
      const binaryLoader = new _three.FileLoader(this.manager);
      binaryLoader.setPath(this.transcoderPath);
      binaryLoader.setResponseType('arraybuffer');
      binaryLoader.setWithCredentials(this.withCredentials);
      const binaryContent = binaryLoader.loadAsync('basis_transcoder.wasm');
      this.transcoderPending = Promise.all([jsContent, binaryContent]).then(_ref => {
        let [jsContent, binaryContent] = _ref;
        const fn = KTX2Loader.BasisWorker.toString();
        const body = ['/* constants */', 'let _EngineFormat = ' + JSON.stringify(KTX2Loader.EngineFormat), 'let _TranscoderFormat = ' + JSON.stringify(KTX2Loader.TranscoderFormat), 'let _BasisFormat = ' + JSON.stringify(KTX2Loader.BasisFormat), '/* basis_transcoder.js */', jsContent, '/* worker */', fn.substring(fn.indexOf('{') + 1, fn.lastIndexOf('}'))].join('\n');
        this.workerSourceURL = URL.createObjectURL(new Blob([body]));
        this.transcoderBinary = binaryContent;
        this.workerPool.setWorkerCreator(() => {
          const worker = new Worker(this.workerSourceURL);
          const transcoderBinary = this.transcoderBinary.slice(0);
          worker.postMessage({
            type: 'init',
            config: this.workerConfig,
            transcoderBinary
          }, [transcoderBinary]);
          return worker;
        });
      });
      if (_activeLoaders > 0) {
        // Each instance loads a transcoder and allocates workers, increasing network and memory cost.

        console.warn('THREE.KTX2Loader: Multiple active KTX2 loaders may cause performance issues.' + ' Use a single KTX2Loader instance, or call .dispose() on old instances.');
      }
      _activeLoaders++;
    }
    return this.transcoderPending;
  }
  load(url, onLoad, onProgress, onError) {
    if (this.workerConfig === null) {
      throw new Error('THREE.KTX2Loader: Missing initialization with `.detectSupport( renderer )`.');
    }
    const loader = new _three.FileLoader(this.manager);
    loader.setResponseType('arraybuffer');
    loader.setWithCredentials(this.withCredentials);
    loader.load(url, buffer => {
      // Check for an existing task using this buffer. A transferred buffer cannot be transferred
      // again from this thread.
      if (_taskCache.has(buffer)) {
        const cachedTask = _taskCache.get(buffer);
        return cachedTask.promise.then(onLoad).catch(onError);
      }
      this._createTexture(buffer).then(texture => onLoad ? onLoad(texture) : null).catch(onError);
    }, onProgress, onError);
  }
  _createTextureFrom(transcodeResult, container) {
    const {
      faces,
      width,
      height,
      format,
      type,
      error,
      dfdFlags
    } = transcodeResult;
    if (type === 'error') return Promise.reject(error);
    let texture;
    if (container.faceCount === 6) {
      texture = new _three.CompressedCubeTexture(faces, format, _three.UnsignedByteType);
    } else {
      const mipmaps = faces[0].mipmaps;
      texture = container.layerCount > 1 ? new _three.CompressedArrayTexture(mipmaps, width, height, container.layerCount, format, _three.UnsignedByteType) : new _three.CompressedTexture(mipmaps, width, height, format, _three.UnsignedByteType);
    }
    texture.minFilter = faces[0].mipmaps.length === 1 ? _three.LinearFilter : _three.LinearMipmapLinearFilter;
    texture.magFilter = _three.LinearFilter;
    texture.generateMipmaps = false;
    texture.needsUpdate = true;
    texture.colorSpace = parseColorSpace(container);
    texture.premultiplyAlpha = !!(dfdFlags & _ktxParseModule.KHR_DF_FLAG_ALPHA_PREMULTIPLIED);
    return texture;
  }

  /**
   * @param {ArrayBuffer} buffer
   * @param {object?} config
   * @return {Promise<CompressedTexture|CompressedArrayTexture|DataTexture|Data3DTexture>}
   */
  async _createTexture(buffer) {
    let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
    const container = (0, _ktxParseModule.read)(new Uint8Array(buffer));
    if (container.vkFormat !== _ktxParseModule.VK_FORMAT_UNDEFINED) {
      return createRawTexture(container);
    }

    //

    const texturePending = this.init().then(() => {
      return this.workerPool.postMessage({
        type: 'transcode',
        buffer,
        taskConfig: config
      }, [buffer]);
    }).then(e => this._createTextureFrom(e.data, container));

    // Cache the task result.
    _taskCache.set(buffer, {
      promise: texturePending
    });
    return texturePending;
  }
  dispose() {
    this.workerPool.dispose();
    if (this.workerSourceURL) URL.revokeObjectURL(this.workerSourceURL);
    _activeLoaders--;
    return this;
  }
}

/* CONSTANTS */
exports.KTX2Loader = KTX2Loader;
KTX2Loader.BasisFormat = {
  ETC1S: 0,
  UASTC_4x4: 1
};
KTX2Loader.TranscoderFormat = {
  ETC1: 0,
  ETC2: 1,
  BC1: 2,
  BC3: 3,
  BC4: 4,
  BC5: 5,
  BC7_M6_OPAQUE_ONLY: 6,
  BC7_M5: 7,
  PVRTC1_4_RGB: 8,
  PVRTC1_4_RGBA: 9,
  ASTC_4x4: 10,
  ATC_RGB: 11,
  ATC_RGBA_INTERPOLATED_ALPHA: 12,
  RGBA32: 13,
  RGB565: 14,
  BGR565: 15,
  RGBA4444: 16
};
KTX2Loader.EngineFormat = {
  RGBAFormat: _three.RGBAFormat,
  RGBA_ASTC_4x4_Format: _three.RGBA_ASTC_4x4_Format,
  RGBA_BPTC_Format: _three.RGBA_BPTC_Format,
  RGBA_ETC2_EAC_Format: _three.RGBA_ETC2_EAC_Format,
  RGBA_PVRTC_4BPPV1_Format: _three.RGBA_PVRTC_4BPPV1_Format,
  RGBA_S3TC_DXT5_Format: _three.RGBA_S3TC_DXT5_Format,
  RGB_ETC1_Format: _three.RGB_ETC1_Format,
  RGB_ETC2_Format: _three.RGB_ETC2_Format,
  RGB_PVRTC_4BPPV1_Format: _three.RGB_PVRTC_4BPPV1_Format,
  RGB_S3TC_DXT1_Format: _three.RGB_S3TC_DXT1_Format
};

/* WEB WORKER */

KTX2Loader.BasisWorker = function () {
  let config;
  let transcoderPending;
  let BasisModule;
  const EngineFormat = _EngineFormat; // eslint-disable-line no-undef
  const TranscoderFormat = _TranscoderFormat; // eslint-disable-line no-undef
  const BasisFormat = _BasisFormat; // eslint-disable-line no-undef

  self.addEventListener('message', function (e) {
    const message = e.data;
    switch (message.type) {
      case 'init':
        config = message.config;
        init(message.transcoderBinary);
        break;
      case 'transcode':
        transcoderPending.then(() => {
          try {
            const {
              faces,
              buffers,
              width,
              height,
              hasAlpha,
              format,
              dfdFlags
            } = transcode(message.buffer);
            self.postMessage({
              type: 'transcode',
              id: message.id,
              faces,
              width,
              height,
              hasAlpha,
              format,
              dfdFlags
            }, buffers);
          } catch (error) {
            console.error(error);
            self.postMessage({
              type: 'error',
              id: message.id,
              error: error.message
            });
          }
        });
        break;
    }
  });
  function init(wasmBinary) {
    transcoderPending = new Promise(resolve => {
      BasisModule = {
        wasmBinary,
        onRuntimeInitialized: resolve
      };
      BASIS(BasisModule); // eslint-disable-line no-undef
    }).then(() => {
      BasisModule.initializeBasis();
      if (BasisModule.KTX2File === undefined) {
        console.warn('THREE.KTX2Loader: Please update Basis Universal transcoder.');
      }
    });
  }
  function transcode(buffer) {
    const ktx2File = new BasisModule.KTX2File(new Uint8Array(buffer));
    function cleanup() {
      ktx2File.close();
      ktx2File.delete();
    }
    if (!ktx2File.isValid()) {
      cleanup();
      throw new Error('THREE.KTX2Loader:	Invalid or unsupported .ktx2 file');
    }
    const basisFormat = ktx2File.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
    const width = ktx2File.getWidth();
    const height = ktx2File.getHeight();
    const layerCount = ktx2File.getLayers() || 1;
    const levelCount = ktx2File.getLevels();
    const faceCount = ktx2File.getFaces();
    const hasAlpha = ktx2File.getHasAlpha();
    const dfdFlags = ktx2File.getDFDFlags();
    const {
      transcoderFormat,
      engineFormat
    } = getTranscoderFormat(basisFormat, width, height, hasAlpha);
    if (!width || !height || !levelCount) {
      cleanup();
      throw new Error('THREE.KTX2Loader:	Invalid texture');
    }
    if (!ktx2File.startTranscoding()) {
      cleanup();
      throw new Error('THREE.KTX2Loader: .startTranscoding failed');
    }
    const faces = [];
    const buffers = [];
    for (let face = 0; face < faceCount; face++) {
      const mipmaps = [];
      for (let mip = 0; mip < levelCount; mip++) {
        const layerMips = [];
        let mipWidth, mipHeight;
        for (let layer = 0; layer < layerCount; layer++) {
          const levelInfo = ktx2File.getImageLevelInfo(mip, layer, face);
          if (face === 0 && mip === 0 && layer === 0 && (levelInfo.origWidth % 4 !== 0 || levelInfo.origHeight % 4 !== 0)) {
            console.warn('THREE.KTX2Loader: ETC1S and UASTC textures should use multiple-of-four dimensions.');
          }
          if (levelCount > 1) {
            mipWidth = levelInfo.origWidth;
            mipHeight = levelInfo.origHeight;
          } else {
            // Handles non-multiple-of-four dimensions in textures without mipmaps. Textures with
            // mipmaps must use multiple-of-four dimensions, for some texture formats and APIs.
            // See mrdoob/three.js#25908.
            mipWidth = levelInfo.width;
            mipHeight = levelInfo.height;
          }
          const dst = new Uint8Array(ktx2File.getImageTranscodedSizeInBytes(mip, layer, 0, transcoderFormat));
          const status = ktx2File.transcodeImage(dst, mip, layer, face, transcoderFormat, 0, -1, -1);
          if (!status) {
            cleanup();
            throw new Error('THREE.KTX2Loader: .transcodeImage failed.');
          }
          layerMips.push(dst);
        }
        const mipData = concat(layerMips);
        mipmaps.push({
          data: mipData,
          width: mipWidth,
          height: mipHeight
        });
        buffers.push(mipData.buffer);
      }
      faces.push({
        mipmaps,
        width,
        height,
        format: engineFormat
      });
    }
    cleanup();
    return {
      faces,
      buffers,
      width,
      height,
      hasAlpha,
      format: engineFormat,
      dfdFlags
    };
  }

  //

  // Optimal choice of a transcoder target format depends on the Basis format (ETC1S or UASTC),
  // device capabilities, and texture dimensions. The list below ranks the formats separately
  // for ETC1S and UASTC.
  //
  // In some cases, transcoding UASTC to RGBA32 might be preferred for higher quality (at
  // significant memory cost) compared to ETC1/2, BC1/3, and PVRTC. The transcoder currently
  // chooses RGBA32 only as a last resort and does not expose that option to the caller.
  const FORMAT_OPTIONS = [{
    if: 'astcSupported',
    basisFormat: [BasisFormat.UASTC_4x4],
    transcoderFormat: [TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4],
    engineFormat: [EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format],
    priorityETC1S: Infinity,
    priorityUASTC: 1,
    needsPowerOfTwo: false
  }, {
    if: 'bptcSupported',
    basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
    transcoderFormat: [TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5],
    engineFormat: [EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format],
    priorityETC1S: 3,
    priorityUASTC: 2,
    needsPowerOfTwo: false
  }, {
    if: 'dxtSupported',
    basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
    transcoderFormat: [TranscoderFormat.BC1, TranscoderFormat.BC3],
    engineFormat: [EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format],
    priorityETC1S: 4,
    priorityUASTC: 5,
    needsPowerOfTwo: false
  }, {
    if: 'etc2Supported',
    basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
    transcoderFormat: [TranscoderFormat.ETC1, TranscoderFormat.ETC2],
    engineFormat: [EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format],
    priorityETC1S: 1,
    priorityUASTC: 3,
    needsPowerOfTwo: false
  }, {
    if: 'etc1Supported',
    basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
    transcoderFormat: [TranscoderFormat.ETC1],
    engineFormat: [EngineFormat.RGB_ETC1_Format],
    priorityETC1S: 2,
    priorityUASTC: 4,
    needsPowerOfTwo: false
  }, {
    if: 'pvrtcSupported',
    basisFormat: [BasisFormat.ETC1S, BasisFormat.UASTC_4x4],
    transcoderFormat: [TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA],
    engineFormat: [EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format],
    priorityETC1S: 5,
    priorityUASTC: 6,
    needsPowerOfTwo: true
  }];
  const ETC1S_OPTIONS = FORMAT_OPTIONS.sort(function (a, b) {
    return a.priorityETC1S - b.priorityETC1S;
  });
  const UASTC_OPTIONS = FORMAT_OPTIONS.sort(function (a, b) {
    return a.priorityUASTC - b.priorityUASTC;
  });
  function getTranscoderFormat(basisFormat, width, height, hasAlpha) {
    let transcoderFormat;
    let engineFormat;
    const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS;
    for (let i = 0; i < options.length; i++) {
      const opt = options[i];
      if (!config[opt.if]) continue;
      if (!opt.basisFormat.includes(basisFormat)) continue;
      if (hasAlpha && opt.transcoderFormat.length < 2) continue;
      if (opt.needsPowerOfTwo && !(isPowerOfTwo(width) && isPowerOfTwo(height))) continue;
      transcoderFormat = opt.transcoderFormat[hasAlpha ? 1 : 0];
      engineFormat = opt.engineFormat[hasAlpha ? 1 : 0];
      return {
        transcoderFormat,
        engineFormat
      };
    }
    console.warn('THREE.KTX2Loader: No suitable compressed texture format found. Decoding to RGBA32.');
    transcoderFormat = TranscoderFormat.RGBA32;
    engineFormat = EngineFormat.RGBAFormat;
    return {
      transcoderFormat,
      engineFormat
    };
  }
  function isPowerOfTwo(value) {
    if (value <= 2) return true;
    return (value & value - 1) === 0 && value !== 0;
  }

  /** Concatenates N byte arrays. */
  function concat(arrays) {
    if (arrays.length === 1) return arrays[0];
    let totalByteLength = 0;
    for (let i = 0; i < arrays.length; i++) {
      const array = arrays[i];
      totalByteLength += array.byteLength;
    }
    const result = new Uint8Array(totalByteLength);
    let byteOffset = 0;
    for (let i = 0; i < arrays.length; i++) {
      const array = arrays[i];
      result.set(array, byteOffset);
      byteOffset += array.byteLength;
    }
    return result;
  }
};

//
// Parsing for non-Basis textures. These textures are may have supercompression
// like Zstd, but they do not require transcoding.

const UNCOMPRESSED_FORMATS = new Set([_three.RGBAFormat, _three.RGFormat, _three.RedFormat]);
const FORMAT_MAP = {
  [_ktxParseModule.VK_FORMAT_R32G32B32A32_SFLOAT]: _three.RGBAFormat,
  [_ktxParseModule.VK_FORMAT_R16G16B16A16_SFLOAT]: _three.RGBAFormat,
  [_ktxParseModule.VK_FORMAT_R8G8B8A8_UNORM]: _three.RGBAFormat,
  [_ktxParseModule.VK_FORMAT_R8G8B8A8_SRGB]: _three.RGBAFormat,
  [_ktxParseModule.VK_FORMAT_R32G32_SFLOAT]: _three.RGFormat,
  [_ktxParseModule.VK_FORMAT_R16G16_SFLOAT]: _three.RGFormat,
  [_ktxParseModule.VK_FORMAT_R8G8_UNORM]: _three.RGFormat,
  [_ktxParseModule.VK_FORMAT_R8G8_SRGB]: _three.RGFormat,
  [_ktxParseModule.VK_FORMAT_R32_SFLOAT]: _three.RedFormat,
  [_ktxParseModule.VK_FORMAT_R16_SFLOAT]: _three.RedFormat,
  [_ktxParseModule.VK_FORMAT_R8_SRGB]: _three.RedFormat,
  [_ktxParseModule.VK_FORMAT_R8_UNORM]: _three.RedFormat,
  [_ktxParseModule.VK_FORMAT_ASTC_6x6_SRGB_BLOCK]: _three.RGBA_ASTC_6x6_Format,
  [_ktxParseModule.VK_FORMAT_ASTC_6x6_UNORM_BLOCK]: _three.RGBA_ASTC_6x6_Format
};
const TYPE_MAP = {
  [_ktxParseModule.VK_FORMAT_R32G32B32A32_SFLOAT]: _three.FloatType,
  [_ktxParseModule.VK_FORMAT_R16G16B16A16_SFLOAT]: _three.HalfFloatType,
  [_ktxParseModule.VK_FORMAT_R8G8B8A8_UNORM]: _three.UnsignedByteType,
  [_ktxParseModule.VK_FORMAT_R8G8B8A8_SRGB]: _three.UnsignedByteType,
  [_ktxParseModule.VK_FORMAT_R32G32_SFLOAT]: _three.FloatType,
  [_ktxParseModule.VK_FORMAT_R16G16_SFLOAT]: _three.HalfFloatType,
  [_ktxParseModule.VK_FORMAT_R8G8_UNORM]: _three.UnsignedByteType,
  [_ktxParseModule.VK_FORMAT_R8G8_SRGB]: _three.UnsignedByteType,
  [_ktxParseModule.VK_FORMAT_R32_SFLOAT]: _three.FloatType,
  [_ktxParseModule.VK_FORMAT_R16_SFLOAT]: _three.HalfFloatType,
  [_ktxParseModule.VK_FORMAT_R8_SRGB]: _three.UnsignedByteType,
  [_ktxParseModule.VK_FORMAT_R8_UNORM]: _three.UnsignedByteType,
  [_ktxParseModule.VK_FORMAT_ASTC_6x6_SRGB_BLOCK]: _three.UnsignedByteType,
  [_ktxParseModule.VK_FORMAT_ASTC_6x6_UNORM_BLOCK]: _three.UnsignedByteType
};
async function createRawTexture(container) {
  const {
    vkFormat
  } = container;
  if (FORMAT_MAP[vkFormat] === undefined) {
    throw new Error('THREE.KTX2Loader: Unsupported vkFormat.');
  }

  //

  let zstd;
  if (container.supercompressionScheme === _ktxParseModule.KHR_SUPERCOMPRESSION_ZSTD) {
    if (!_zstd) {
      _zstd = new Promise(async resolve => {
        const zstd = new _zstddecModule.ZSTDDecoder();
        await zstd.init();
        resolve(zstd);
      });
    }
    zstd = await _zstd;
  }

  //

  const mipmaps = [];
  for (let levelIndex = 0; levelIndex < container.levels.length; levelIndex++) {
    const levelWidth = Math.max(1, container.pixelWidth >> levelIndex);
    const levelHeight = Math.max(1, container.pixelHeight >> levelIndex);
    const levelDepth = container.pixelDepth ? Math.max(1, container.pixelDepth >> levelIndex) : 0;
    const level = container.levels[levelIndex];
    let levelData;
    if (container.supercompressionScheme === _ktxParseModule.KHR_SUPERCOMPRESSION_NONE) {
      levelData = level.levelData;
    } else if (container.supercompressionScheme === _ktxParseModule.KHR_SUPERCOMPRESSION_ZSTD) {
      levelData = zstd.decode(level.levelData, level.uncompressedByteLength);
    } else {
      throw new Error('THREE.KTX2Loader: Unsupported supercompressionScheme.');
    }
    let data;
    if (TYPE_MAP[vkFormat] === _three.FloatType) {
      data = new Float32Array(levelData.buffer, levelData.byteOffset, levelData.byteLength / Float32Array.BYTES_PER_ELEMENT);
    } else if (TYPE_MAP[vkFormat] === _three.HalfFloatType) {
      data = new Uint16Array(levelData.buffer, levelData.byteOffset, levelData.byteLength / Uint16Array.BYTES_PER_ELEMENT);
    } else {
      data = levelData;
    }
    mipmaps.push({
      data: data,
      width: levelWidth,
      height: levelHeight,
      depth: levelDepth
    });
  }
  let texture;
  if (UNCOMPRESSED_FORMATS.has(FORMAT_MAP[vkFormat])) {
    texture = container.pixelDepth === 0 ? new _three.DataTexture(mipmaps[0].data, container.pixelWidth, container.pixelHeight) : new _three.Data3DTexture(mipmaps[0].data, container.pixelWidth, container.pixelHeight, container.pixelDepth);
  } else {
    if (container.pixelDepth > 0) throw new Error('THREE.KTX2Loader: Unsupported pixelDepth.');
    texture = new _three.CompressedTexture(mipmaps, container.pixelWidth, container.pixelHeight);
  }
  texture.mipmaps = mipmaps;
  texture.type = TYPE_MAP[vkFormat];
  texture.format = FORMAT_MAP[vkFormat];
  texture.colorSpace = parseColorSpace(container);
  texture.needsUpdate = true;

  //

  return Promise.resolve(texture);
}
function parseColorSpace(container) {
  const dfd = container.dataFormatDescriptor[0];
  if (dfd.colorPrimaries === _ktxParseModule.KHR_DF_PRIMARIES_BT709) {
    return dfd.transferFunction === _ktxParseModule.KHR_DF_TRANSFER_SRGB ? _three.SRGBColorSpace : _three.LinearSRGBColorSpace;
  } else if (dfd.colorPrimaries === _ktxParseModule.KHR_DF_PRIMARIES_DISPLAYP3) {
    return dfd.transferFunction === _ktxParseModule.KHR_DF_TRANSFER_SRGB ? _three.DisplayP3ColorSpace : _three.LinearDisplayP3ColorSpace;
  } else if (dfd.colorPrimaries === _ktxParseModule.KHR_DF_PRIMARIES_UNSPECIFIED) {
    return _three.NoColorSpace;
  } else {
    console.warn(`THREE.KTX2Loader: Unsupported color primaries, "${dfd.colorPrimaries}"`);
    return _three.NoColorSpace;
  }
}