Three.js: PMREM envMap bad performance

Created on 29 May 2020  路  6Comments  路  Source: mrdoob/three.js

Recently I've been migrating my app from normal cubemap to PMREM and noticing 3-5x drop in performance (it was 50fps, but now is just 11fps using PMREM).

After looking around in the source code to find out the difference, I see in fragment shader, function textureCubeUV has 1 to 2 calls to bilinearCubeUV, each call will access the envMap 4 times:
https://github.com/mrdoob/three.js/blob/c1ea11e4ff7aaa41334cd8d2154a5cd55b94b641/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js#L118
So each pixel will access envMap texture 4 or 8 times per frame? I guess this is where the performance drop come from.

Could the PMREM code can be improved somehow to achieve better performance?

Most helpful comment

@Ben-Mack 100s of different materials? The draw call overhead alone could be a bigger problem. Is there no way to combine them with texture atlasing? In any case, if you can share an example we can test with/without PMREM then we'll have a much better chance of improving the performance.

All 6 comments

/ping @elalish

FYI @bhouston

@Ben-Mack Thanks for giving us some performance feedback! Any texture lookup with LINEAR_MIPMAP_LINEAR also accesses 8 texels, so the hope is that this compiles to machine code that isn't too much less efficient than what a plain GLSL texture lookup compiles to. However, I'll be the first to admit this hasn't been measured or optimized enough. Could you give us a glitch where we can compare your PMREM and non-PMREM versions with framerate displays? It's also entirely possible that this works better on some GPUs than others.

It's a quite heavy model with ~500k triangles, more than 100s MeshPhysicalMaterial, benchmarked on Samsung S7.

@Ben-Mack 100s of different materials? The draw call overhead alone could be a bigger problem. Is there no way to combine them with texture atlasing? In any case, if you can share an example we can test with/without PMREM then we'll have a much better chance of improving the performance.

I am pretty sure texture interpolation, including even mipmap interpolation can be handled fully within a texture unit. By doing multiple non-interpolated requests and then manual interpolation, we are by passing full hardware accelaration.

GPU technology keeps changing but this was at least the case at one point recently:

https://www.researchgate.net/post/What_is_the_underlying_hardware_implementation_of_texture_memory_in_GPUs_Is_it_just_compiled_to_something_like_gather_instructions

https://www.iquilezles.org/www/articles/texture/texture.htm

https://www.iquilezles.org/www/articles/hwinterpolation/hwinterpolation.htm

I wouldn't be surprised if NVIDIA gpus handle this differently that mobile GPUs.

@bhouston recently I also was working on envMaps (switched from cubemap to PMREM). No matter one or many objects use the material.envMap I am having a huge fps drop (60 to 20~25).

I'm running on GPU GTX1060 6gb. When I was using cubemaps (I was getting warnings in the console) but envMaps were working fine.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Horray picture Horray  路  3Comments

danieljack picture danieljack  路  3Comments

clawconduce picture clawconduce  路  3Comments

akshaysrin picture akshaysrin  路  3Comments

filharvey picture filharvey  路  3Comments