KTX loading seems to take too long

Hi,

I’ve noticed that loading .ktx2 takes more than 10 times slower than loading .jpp/png on my machine. Not sure if this is expected or not so I’m here.

Followings are details and info that I’ve found so far:

I was wondering if this is expected behavior. Any insight would be appreciated!

A few things that might be confusing here:

First, one of more common reasons to choose KTX2 textures is because they upload to the GPU more quickly than PNG/JPEG, which must be fully decompressed and uploaded while blocking the main thread. The timing shown above does not include GPU upload, and so the transcoding time for KTX2 mistakenly looks like an unmitigated cost. Upload happens automatically on first render with the texture, or you may be able to force it with initTexture.

Second, both loaders are capable of downloading in parallel, and KTX2Loader is capable of using Web Workers for parallel transcoding. GPU upload (slower for PNG/JPEG) is synchronous and non-parallel. By restructuring your loops to run in parallel you may see a fairly different result.

console.time('Task');
await Promise.all(urls.map((url) => {
  const texture = await textureLoader.load(url);
  renderer.initTexture(texture);
  // ...
});
console.timeEnd('Task');

Thanks @donmccurdy,

Yea I understand compressed textures are decompressed on the fly so they are uploaded faster when shaders are compiled. My question is more of wondering why specifically the transcoding from ETC to DXT takes significantly more time than others (although I only have one data of other case at this moment, which is ETC to BPTC. I can collect more data if it could be helpful).

Also, thanks for the code sample for parallel tasks! It does help reduce the time noticeably! Thought I let them work in parallel by the await instruction for each texture loading but then I realized they are handling the promise one by one as you pointed out. Thanks again!

I’ve updated my code, now it addresses compile time as well. The result on my machine is following:

  • jpg download: 2ms (from 130ms)
  • jpg upload: 350ms
  • ktx download and transcode: 920ms (from 1700ms)
  • ktx upload: 5ms

It does have significant saving on uploading time but transcoding time takes more than what it saves. Is this normal though? I’m curious because it looks like ETC to BPTC transcoding (see the screenshot below) doesn’t take much time unlike ETC to DXT. Looking forward to your answer. Thanks again!

Screen Shot 2022-03-12 at 4.25.10 PM

Transcoding to some formats is faster than others (in particular, ETC1S → ETC1 is basically free), but I’m not sure why ETC1S → DXT would be particularly slow. Some time would also be spent downloading the KTX2 transcoder, so if you want to isolate that time you could run await ktxLoader.init() before beginning to load textures.

There are some lightweight transcoders available that are smaller and probably faster than the one we currently use, but these don’t yet support the transcoding modes you’re comparing here. Perhaps in the future.

Finally, since the transcoding time does not block rendering and upload does, 900ms of non-blocking delay could be preferable to 300ms of blocking delay in some cases. Particularly WebXR/VR APIs, where dropping frames is very noticeable to users once the app has begun rendering.

Thanks for getting back to me @donmccurdy

I actually do load the loader beforehand the benchmark at the beginning of the code cause that was my first guess where the delay comes from. It doesn’t seem like taking too long to init the loader.

Makes sense that it doesn’t hang the main thread so the longer transcoding time might be acceptable than less time that hangs the main thread. Although, I need to render the final look of the asset on the screen as fast as possible so I might still need solutions or get-arounds for this…

Thanks for the suggestions for other transcoders, that sounds about a good start! I’ll try them to see if they any help, if so hopefully I could use three’s loader as a fallback to support cross platforms for other formats.

Thanks again for your answers even it was on the weekends. Also huge thanks for your works in threejs and glTransform tool. It’s so convenient and also beautiful documentation :heart_eyes: have a nice the rest of weekends!

1 Like