From 199b7bf4e13579e53b89efd7eb7c39af2dd5c715 Mon Sep 17 00:00:00 2001 From: Don McCurdy Date: Sun, 13 Nov 2022 15:26:10 -0500 Subject: [PATCH] KTX2Loader: Replace manual transcoder path with dynamic imports. --- examples/js/libs/basis/basis_transcoder.js | 7 +- examples/jsm/loaders/KTX2Loader.js | 125 ++++++++++----------- examples/webgl_loader_texture_ktx2.html | 4 +- 3 files changed, 61 insertions(+), 75 deletions(-) diff --git a/examples/js/libs/basis/basis_transcoder.js b/examples/js/libs/basis/basis_transcoder.js index 9e285ddc9515bd..347edba3c80ad8 100644 --- a/examples/js/libs/basis/basis_transcoder.js +++ b/examples/js/libs/basis/basis_transcoder.js @@ -13,9 +13,4 @@ var Module=typeof BASIS!=="undefined"?BASIS:{};var readyPromiseResolve,readyProm } ); })(); -if (typeof exports === 'object' && typeof module === 'object') - module.exports = BASIS; -else if (typeof define === 'function' && define['amd']) - define([], function() { return BASIS; }); -else if (typeof exports === 'object') - exports["BASIS"] = BASIS; +export { BASIS }; diff --git a/examples/jsm/loaders/KTX2Loader.js b/examples/jsm/loaders/KTX2Loader.js index 38b87cbc3978cf..f33a6be73191be 100644 --- a/examples/jsm/loaders/KTX2Loader.js +++ b/examples/jsm/loaders/KTX2Loader.js @@ -61,6 +61,9 @@ import { } from '../libs/ktx-parse.module.js'; import { ZSTDDecoder } from '../libs/zstddec.module.js'; +const TRANSCODER_JS_PATH = new URL( '../../js/libs/basis/basis_transcoder.js', import.meta.url ).href; +const TRANSCODER_WASM_PATH = new URL( '../../js/libs/basis/basis_transcoder.wasm', import.meta.url ).href; + const _taskCache = new WeakMap(); let _activeLoaders = 0; @@ -73,13 +76,12 @@ class KTX2Loader extends Loader { super( manager ); - this.transcoderPath = ''; - this.transcoderBinary = null; - this.transcoderPending = null; - this.workerPool = new WorkerPool(); this.workerSourceURL = ''; - this.workerConfig = null; + this.workerConfig = { + jsPath: TRANSCODER_JS_PATH, + wasmPath: TRANSCODER_WASM_PATH, + }; if ( typeof MSC_TRANSCODER !== 'undefined' ) { @@ -96,7 +98,8 @@ class KTX2Loader extends Loader { setTranscoderPath( path ) { - this.transcoderPath = path; + this.workerConfig.jsPath = `${path}basis_transcoder.js`; + this.workerConfig.wasmPath = `${path}basis_transcoder.wasm`; return this; @@ -113,6 +116,7 @@ class KTX2Loader extends Loader { detectSupport( renderer ) { this.workerConfig = { + ...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' ), @@ -136,71 +140,45 @@ class KTX2Loader extends Loader { init() { - if ( ! this.transcoderPending ) { - - // Load transcoder wrapper. - const jsLoader = new 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 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( ( [ jsContent, binaryContent ] ) => { + if ( this.workerSourceURL ) return; - const fn = KTX2Loader.BasisWorker.toString(); + 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' ); + const body = [ + '/* constants */', + 'let _EngineFormat = ' + JSON.stringify( KTX2Loader.EngineFormat ), + 'let _TranscoderFormat = ' + JSON.stringify( KTX2Loader.TranscoderFormat ), + 'let _BasisFormat = ' + JSON.stringify( KTX2Loader.BasisFormat ), + '/* worker */', + fn.substring( fn.indexOf( '{' ) + 1, fn.lastIndexOf( '}' ) ) + ].join( '\n' ); - this.workerSourceURL = URL.createObjectURL( new Blob( [ body ] ) ); - this.transcoderBinary = binaryContent; + this.workerSourceURL = URL.createObjectURL( new Blob( [ body ] ) ); - this.workerPool.setWorkerCreator( () => { + this.workerPool.setWorkerCreator( () => { - const worker = new Worker( this.workerSourceURL ); - const transcoderBinary = this.transcoderBinary.slice( 0 ); + const worker = new Worker( this.workerSourceURL ); - worker.postMessage( { type: 'init', config: this.workerConfig, transcoderBinary }, [ transcoderBinary ] ); + worker.postMessage( { type: 'init', config: this.workerConfig } ); - return worker; + return worker; - } ); - - } ); - - if ( _activeLoaders > 0 ) { - - // Each instance loads a transcoder and allocates workers, increasing network and memory cost. + } ); - console.warn( + if ( _activeLoaders > 0 ) { - 'THREE.KTX2Loader: Multiple active KTX2 loaders may cause performance issues.' - + ' Use a single KTX2Loader instance, or call .dispose() on old instances.' + // 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; + _activeLoaders ++; } @@ -277,11 +255,11 @@ class KTX2Loader extends Loader { // const taskConfig = config; - const texturePending = this.init().then( () => { - return this.workerPool.postMessage( { type: 'transcode', buffer, taskConfig: taskConfig }, [ buffer ] ); + this.init(); - } ).then( ( e ) => this._createTextureFrom( e.data, container ) ); + const texturePending = this.workerPool.postMessage( { type: 'transcode', buffer, taskConfig, }, [ buffer ] ) + .then( ( e ) => this._createTextureFrom( e.data, container ) ); // Cache the task result. _taskCache.set( buffer, { promise: texturePending } ); @@ -347,11 +325,12 @@ KTX2Loader.EngineFormat = { /* WEB WORKER */ -KTX2Loader.BasisWorker = function () { +KTX2Loader.BasisWorker = async function () { let config; let transcoderPending; let BasisModule; + let BASIS; const EngineFormat = _EngineFormat; // eslint-disable-line no-undef const TranscoderFormat = _TranscoderFormat; // eslint-disable-line no-undef @@ -365,7 +344,7 @@ KTX2Loader.BasisWorker = function () { case 'init': config = message.config; - init( message.transcoderBinary ); + init(); break; case 'transcode': @@ -400,14 +379,26 @@ KTX2Loader.BasisWorker = function () { } ); - function init( wasmBinary ) { + async function init() { + + let resolve; + + transcoderPending = new Promise( ( _resolve ) => ( resolve = _resolve ) ); + + Promise.all( [ - transcoderPending = new Promise( ( resolve ) => { + import( config.jsPath ), + fetch( config.wasmPath ).then( ( response ) => response.arrayBuffer() ), - BasisModule = { wasmBinary, onRuntimeInitialized: resolve }; - BASIS( BasisModule ); // eslint-disable-line no-undef + ] ).then( ( [ { BASIS: _BASIS }, wasmBinary ] ) => { - } ).then( () => { + BASIS = _BASIS; + BasisModule = { wasmBinary, onRuntimeInitialized }; + BASIS( BasisModule ); + + } ); + + function onRuntimeInitialized() { BasisModule.initializeBasis(); @@ -417,7 +408,9 @@ KTX2Loader.BasisWorker = function () { } - } ); + resolve(); + + } } diff --git a/examples/webgl_loader_texture_ktx2.html b/examples/webgl_loader_texture_ktx2.html index 7231c0de9ad516..9403681ea14a05 100644 --- a/examples/webgl_loader_texture_ktx2.html +++ b/examples/webgl_loader_texture_ktx2.html @@ -76,9 +76,7 @@ }; // Samples: sample_etc1s.ktx2, sample_uastc.ktx2, sample_uastc_zstd.ktx2 - const loader = new KTX2Loader() - .setTranscoderPath( 'js/libs/basis/' ) - .detectSupport( renderer ); + const loader = new KTX2Loader().detectSupport( renderer ); animate();