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:
- Set
encoding
of any Uint8 RGBA texture tosRGBEncoding
. (WebGL 2 context is required.) - Render a scene that uses the texture.
- 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
- LinearEncoding (0.16 seconds blocking) (Refresh to see small freeze)
- sRGBEncoding (1.49 seconds blocking) (Refresh to see long freeze)
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)
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.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)
andBrave 1.30.87 Chromium: 94.0.4606.71 (Official Build) (64-bit)
. I’ve checked withFirefox 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?
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
usingRGBFormat
vsRGBAFormat
makes any difference.Yeah, looks like there’s no way around this since the API is synchronous (
texImage2D
). So, in a way, it’s working as intended.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?