three.js: SRGB8_ALPHA8 blocks the main thread

Describe the bug

The introduction of SRGB8_ALPHA8 in #22551 improved the render quality of sRGB textures, but also added significant synchronous conversion times that block the main thread. Every sRGB texture adds to the total blocking time, resulting in a poor user experience, especially when the scene contains many textures.

To Reproduce

Steps to reproduce the behavior:

  1. Set encoding of any Uint8 RGBA texture to sRGBEncoding. (WebGL 2 context is required.)
  2. Render a scene that uses the texture.
  3. See the main thread being blocked for a noticeable period of time during the first frame.

Code

The following example loads a cube map and sets its encoding to sRGBEncoding: https://codesandbox.io/s/srgb8-alpha8-wv3jf?runonclick=1&file=/index.js

Live example

The blocking behaviour can also be observed in live examples that load GLTF models, such as https://threejs.org/examples/?q=gltf#webgl_loader_gltf.

Expected behavior

Ideally, the main thread should not be blocked at all. Blocking time should at least be reduced as much as possible.

Screenshots

With LinearEncoding or sRGBEncoding pre r133 With sRGBEncoding since r133
Longest blocking time = 160 ms Longest blocking time = 1496 ms

Platform:

  • Device: Desktop
  • OS: Windows
  • Browser: Chrome, Brave, Firefox
  • Three.js version: r133

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 18 (6 by maintainers)

Most upvoted comments

As I’ve mentioned on https://bugs.chromium.org/p/chromium/issues/detail?id=1256340 this appears to be an issue with how ANGLE generates mipmaps for sRGB textures.

An effective workaround for this bug (while an ANGLE fix is pending) would be to either:

A) Not use gl.generateMipmaps() with sRGB textures or B) Use texStorage2D when creating the textures.

For those with an affected system, you can see the issue with this (non-Three.js) test page: https://toji.github.io/web-texture-tool/demo/srgb-test.html

Generally I see that it runs fine with the exception of when I select sRGB textures, have it generate mipmaps, and turn off useTexStorage, at which point it janks like crazy.

Yes, please file on https://crbug.com/ . The problem might be on the Chromium or ANGLE side, so filing under Chromium is more general. Please include about:gpu in your report, and the zip archive you posted above, and post the bug ID here once filed - thanks in advance.

On what platform is this reproduced?

I’m experiencing the stall on a Windows 10 system with an NVIDIA GTX 1050 Ti. Here’s my about-gpu.txt

The freeze occurs in Chrome 94.0.4606.71 (Official Build) (64-bit) (cohort: 94_win_54) and Brave 1.30.87 Chromium: 94.0.4606.71 (Official Build) (64-bit). I’ve checked with Firefox 92.0.1, build 20210922161155 and can confirm that it also has the same blocking behaviour.

This could be an ANGLE thing. Should I still open a new issue in the Chromium bug tracker?

Also, can you provide a zip archive containing all of the sources for this example, unminified, so we can easily edit them?

Sure! srgb-blocking-example.zip (Needs to be served locally with npm start for the texture loader to work.)

I’ve filed a PR so it’s easier to see the necessary changes: #22759

@Mugen87 Yeah, that sounds reasonable. I have no idea when that Chrome bug might get fixed, but even if it was tomorrow, we’d be dealing with this for months. If it’s actually a problem in Firefox too, then it’s even stickier.

Bug ID → 1256340

I can’t reproduce this on my (macOS) machine either, but would be curious whether texture.format using RGBFormat vs RGBAFormat makes any difference.

it seems there is not much we can do on engine level to avoid this overhead

Yeah, looks like there’s no way around this since the API is synchronous (texImage2D). So, in a way, it’s working as intended.

This is probably something we should report to the Chromium team.

I can do that later unless someone else beats me to it.

It seems the overhead is way smaller on macOS. I’ve tested both live examples with Chrome/FF and barely see a difference. Can somebody else verify this with a Mac?