question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unnecessary .initMaterial() calls if CubeCamera && [texture.encoding != output.Encoding || light-based-material]

See original GitHub issue
TLDR

If you render to a CubeCamera and

  • have renderer.outputEncoding != renderTarget.texture.encoding, at each render, for each material a .acuireProgram() will be called, which is slow. (Example) (covered by #19056)

  • have light-based materials, at each render for each material a new .initMaterial() will be called, which is slow due to .cloneUniforms()(Example) (covered by #13656, #14121 and now #19673)

Description of the problem

I noticed a severe performance regression when updating to latest THREE version (r117), causing my rendering times to increase from ~3ms to ~200ms. My scenes heavily rely on CubeCamera’s, and I noticed an unusually high amount of material recompiles.

It appears that if you render a CubeCamera and you either

  • have renderer.outputEncoding != renderTarget.texture.encoding or
  • have a light based material in your scene

that lightsStateVersion property will flip/flop between the CubeCamera and main cameras renderStates, causing unnecessary calls to initMaterial. Even if the material does not need to be recompiled, the calculation of programCacheKey takes longer than usual, probably because it now involves cloning of the material’s uniforms.


{
lightsStateVersion: 6,
materialProperties.lightsStateVersion: 5,
//^^^^^this causes the recompile^^^^^^

parameters.shaderID: "basic",
program: WebGLProgram {name: "MeshBasicMaterial", id: 81, getUniforms: ƒ, getAttributes: ƒ, destroy: ƒ, …},
program.cacheKey: "basic,highp,false,true,3000,false,false,3000,false,3000,false,,3000,false,false,3000,false,false,3000,false,false,false,false,false,false,false,false,false,false,false,false,false,0,false,,false,false,false,true,,false,,false,false,0,true,false,,8,4,false,0,0,0,0,0,0,0,0,false,1,0,false,0,false,false,0,0,false,false,false,3001,2,...",
programCacheKey: "basic,highp,false,true,3001,false,false,3000,false,3000,false,,3000,false,false,3000,false,false,3000,false,false,false,false,false,false,false,false,false,false,false,false,false,0,false,,false,false,false,true,,false,,false,false,0,true,false,,8,4,false,0,0,0,0,0,0,0,0,false,1,0,false,0,false,false,0,0,false,false,false,3001,2,...",
programChange: true
}

You can find an example here:

I didn’t bisect the commit in question, but it appears to have happened between [r112,r115].

TextureEncoding I don’t expect all involved renderTargets to have the same encodings, but if that should be the case, I would recommend a corresponding warning message. On the other hand, IMHO the encoding of the renderTarget should not affect caching of the object’s material at all? Although if it does, it might make sense to cache the material multiple times for each different encoding instead of flip/flopping between both encoding and causing a recompilation every time.

Thanks for investigating, please let me know if I can supply additional information.

Three.js version
  • Dev
  • r117
  • r116
  • [?] …
  • r111
Browser
  • [?] All of them
  • Chrome
  • Firefox
  • [?] Internet Explorer
OS
  • [?] All of them
  • [?] Windows
  • macOS
  • [?] Linux
  • Android
  • iOS

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
Mugen87commented, Jun 18, 2020

#19673 is an important step for better performance and should also help to achieve #15047. However, @sunag needs to help in refactoring NodeMaterial otherwise it will block the PR. Or the project accepts a broken node material.

1reaction
sciecodecommented, Jun 18, 2020

I don’t expect all involved renderTargets to have the same encodings, but if that should be the case, I would recommend a corresponding warning message. On the other hand, IMHO the encoding of the renderTarget should not affect caching of the object’s material at all? Although if it does, it might make sense to cache the material multiple times for each different encoding instead of flip/flopping between both encoding and causing a recompilation every time.

I’ve only now seen this issue, but I feel like it’s important to address this comment.

I was aware my PR ( #19129 ) could cause problems of that matter. The PR fix was necessary because not caching the RTT encoding leads to materials not rendering correctly for the set encoding, which is a lot more problematic than it may sound like.

However, I do agree that there’s a bit of a grey area, given that we also don’t want force recompiles when flip-flopping encodings, tone mappings etc… This is especially important for the post processing pipeline.

I’ve noticed that @Mugen87’s PR ( #19634 ) would be able to solve this problem, but unfortunately it also led to a big performance hit.

I think the other approach proposed by #15047 should be able to fix this, however the path to getting there requires some careful consideration of each program life-cycle and caching strategies. Given that we are smart about this, that should be the correct way of solving this problem. Which should be a priority, IMHO.

Read more comments on GitHub >

github_iconTop Results From Across the Web

THREE.js: Textures become grayish with renderer ...
The result is quite disappointing as the texture now renders very grayish due to the OutputEncoding of the renderer (sRGB Encoding).
Read more >
WebGLRenderer#outputEncoding – three.js docs
Defines the output encoding of the renderer. Default is THREE.LinearEncoding. If a render target has been set using .setRenderTarget then renderTarget.texture.
Read more >
FasTC: accelerated fixed-rate texture encoding - GAMMA
We present a new algorithm for encoding low dynamic range im- ages into fixed-rate texture compression formats. Our approach provides orders of magnitude ......
Read more >
TexNN: Fast Texture Encoding using Neural Networks - Wiley
We present a novel deep learning based method for fast encoding of textures into current texture compression formats. Our approach uses state-of-the-art ...
Read more >
Multi-level Texture Encoding and Representation (MuLTER ...
In comparison with state-of-the-art texture descriptors, the MuLTER network yields higher recognition accuracy on typical texture datasets ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found