Use ktx2 texture without workers

I am trying to use a ktx2 texture without using web workers (I need to run it on a scope where is not possible to use them). For doing it I am setting:

BABYLON.KhronosTextureContainer2.DefaultNumWorkers = 0;

But then I am getting an error (on version 4.2.0) or a warning (version 5.0.0-alpha.42) saying “KTX2DECODER is not defined”

I created a simple playground to show the issue Babylon.js Playground

I am missing something? or is there something else I need to configure in order to use the ktx2 without workers?

Thank you

The playground doesn’t load the ktx loader (@Deltakosh - want to add that to the playground?)

However, even when including it there seems to be an issue - ktx2 without workers | Babylon.js Playground (babylonjs.com). @Evgeni_Popov , i noticed you did some work with the ktx loader, do you have an idea what’s happening there?

Yes!

1 Like

The playground is loading on demand, we should not change this part :slight_smile: https://playground.babylonjs.com/#EIJH8L#36

The issue might be with the file itself, @Evgeni_Popov will have a look on Monday :slight_smile:

1 Like

Scratch my previous answer, It is a bug when not using worker where we are not loading the lib dynamically :slight_smile:

I will try to make a fix soon.

Nightly will be up in one hour with the fix in :slight_smile:

For reference and review from @Evgeni_Popov on Tuesday :slight_smile: https://github.com/BabylonJS/Babylon.js/pull/11003/commits/dfd62b41356864117d3ae1d69866d9472721d6b7

Thanks @sebavan.

I had assumed that in the case of using ktx2 without worker threads, the user would load the required modules themselves.

np now it handles the three cases :wink:

2 Likes

Thanks a lot!!

Sorry to reopen this but we didn’t manage to make it work… and somehow looking at the khronosTextureContainer2.js code I see:

if (numWorkers === void 0) { numWorkers = KhronosTextureContainer2.DefaultNumWorkers; }

does this mean that is not possible to load ktx2 textures without a worker as when setting it to 0 will use the default number?

The line means if numWorkers is undefined (void 0 === undefined) we set it to BABYLON.KhronosTextureContainer2.DefaultNumWorkers;

By setting BABYLON.KhronosTextureContainer2.DefaultNumWorkers = 0; at the start of your program you should not get any worker thread created.

Oh ok! then I might be doing something else wrong…
We are using tree shaking so we don’t have the BABYLON.KhronosTextureContainer2 available so to set it I am importing:

import * as BABYLON from "@babylonjs/core/Legacy/legacy";

and then setting:

BABYLON.KhronosTextureContainer2.DefaultNumWorkers = 0;

But then it continues to fail to load the textures with the error Failed to load KTX2 texture data: KTX2DECODER is not defined.

Screenshot 2022-05-06 at 16.27.10

The texture is loaded via new Texture(textureName, scene); in case that is relevant.

Is there anything else we need to load or import for it to work? Thank you!

I’m not sure the “Legacy” pass should be used (but I have 0 knowledge about ES6)…

Doesn’t this import work?

import { KhronosTextureContainer2  } from "@babylonjs/core/Misc/khronosTextureContainer2";

I tried that as well with the same result… :confused:

Setting the DefaultNumWorkers is working as it then fails to load it (it loads correctly without setting the number of workers) but then I get this error about KTX2DECODER not being defined.

On the fix provided, there is this on the commit:

else if (typeof(KTX2DECODER) === "undefined") {
            KhronosTextureContainer2._NoWorkerPromise = Tools.LoadScriptAsync(KhronosTextureContainer2.URLConfig.jsDecoderModule).then(() => {
                KTX2DECODER.MSCTranscoder.UseFromWorkerThread = false;
                KTX2DECODER.WASMMemoryManager.LoadBinariesFromCurrentThread = true;

                const urls = KhronosTextureContainer2.URLConfig;
                if (urls.wasmUASTCToASTC !== null) {
                    KTX2DECODER.LiteTranscoder_UASTC_ASTC.WasmModuleURL = urls.wasmUASTCToASTC;
                }
                if (urls.wasmUASTCToBC7 !== null) {
                    KTX2DECODER.LiteTranscoder_UASTC_BC7.WasmModuleURL = urls.wasmUASTCToBC7;
                }
                if (urls.wasmUASTCToRGBA_UNORM !== null) {
                    KTX2DECODER.LiteTranscoder_UASTC_RGBA_UNORM.WasmModuleURL = urls.wasmUASTCToRGBA_UNORM;
                }
                if (urls.wasmUASTCToRGBA_SRGB !== null) {
                    KTX2DECODER.LiteTranscoder_UASTC_RGBA_SRGB.WasmModuleURL = urls.wasmUASTCToRGBA_SRGB;
                }
                if (urls.jsMSCTranscoder !== null) {
                    KTX2DECODER.MSCTranscoder.JSModuleURL = urls.jsMSCTranscoder;
                }
                if (urls.wasmMSCTranscoder !== null) {
                    KTX2DECODER.MSCTranscoder.WasmModuleURL = urls.wasmMSCTranscoder;
                }
                if (urls.wasmZSTDDecoder !== null) {
                    KTX2DECODER.ZSTDDecoder.WasmModuleURL = urls.wasmZSTDDecoder;
                }
            });
        } 

maybe I am missing something but if KTX2DECODER is undefined we cannot set “MSCTranscoder” on it or is it a global that would be set on loading the js decoder?

I am also seeing that there was recently a refactor to it which might have broke the previous fix… I’ll tell if I find something else Add and use AutoReleaseWorkerPool for auto cleanup (#12096) · BabylonJS/Babylon.js@b291839 · GitHub

cc @bghgary

The Tools.LoadScriptAsync call should have added the KTX2DECODER as a module into the global space.

@Joel_Corominas I’m not sure how to repro. The OP’s playground works with the latest code. What’s the repro?