-
-
Notifications
You must be signed in to change notification settings - Fork 35.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added needsUpdate checks to WebGLRenderer.compile #17116
Conversation
The only example that uses renderer.compile is https://threejs.org/examples/webgl_materials_compile.html. http://eliashasle.github.io/three.js/examples/webgl_materials_compile.html runs with both this and #17117. Doing a profiling of the page load in Google Chrome gives no clear difference, although the profiling runs for at least 3 seconds, which adds a lot of uncertainty sources. I think that differences may show more clearly in a tailored example where the compile takes a lot of time and there are really many objects and many that share material instances. |
Stress test that shows improvement: This is a rather extreme test with 600 000 meshes sharing a single RawShaderMaterial instance with extremely simple code, and the same simple geometry. It remains to be seen whether any real applications can benefit from this. That would be applications that precompile large scenes with heavy reuse of material instances. (Wouldn't have to be only a single material.) |
@Usnul Do you have any take on this, considering the scale and relative homogeneity of your game world? |
Hey, I just caught up with what's happening. I think it's a step in the right direction. Mybe it would be better to have a function called With respect to string, I wrote a small static material cache a few weeks ago. It avoids the strings completely. There are still computationally intensive operations there, and it completely ignores Here's the topic with some musings on the subject: #16798 I haven't seen the checks themselves cause too much trouble for a while, mostly it's the shader compilation and texture image decoding that causes spikes in my case. I use quite a few different meshes in the game, they aren't prepared in any special way, just plain gltf files, so each has its own material and textures. Using the method I mentioned earlier I managed to reduce number of duplicate materials and textures, it doesn't really impact memory usage that much, but it does improve runtime performance considerably. In my case I got about 10% FPS increase on lower-end hardware. |
Fix d.ts signatures for setCrossOrigin and transformUv
Remove non-breaking space from code.
BufferGeometryUtils.js: Non-breaking space replaced with normal space
Update TypedGeometryExporter.d.ts
TS: Add missing types: is***
Deprecate Matrix*.applyToBufferAttribute() methods
Examples: added instancing_modified example
TS: Matrix4.decompose returns the original matrix
Update broken URL in comments.
Docs: Clarify Box2/3 descriptions and code example.
TS: Clean up Skeleton.d.ts.
WebGLBackground: recompile background material when tone mapping changes
WebGLRenderer: Refactor invocation of initMaterial().
WebGLPrograms: Fix typo in getParameters().
This PR needs an update because of #17968.
As you can see at the new code in three.js/src/renderers/WebGLRenderer.js Lines 1657 to 1692 in 515f212
In general, |
Thanks for your reply. I don't know exactly what changes would be needed. And I don't have time now. I doubt it is an important PR anyway, so far seeing results only on an extreme stress test. Should I just close the PR, or perhaps wait to see if anyone is interested in picking up on the "idea"? |
Displacement Example: Properly implement damping
I think we can close the PR until somebody else want's this feature. I mean |
The "feature" is/was to shave off a few unneeded updates during |
Yes, that's true.
I think it would be good if you can have a look. If it's not much code to add, we can still make the change. |
EDIT: Nevermind, I used a local |
Before: initMaterial is called on every instance of every material: 1. initMaterial invariably calls programCache.getProgramCode, which builds a large string from the shader. 2. Then the WebGLProperties object is queried with the material to obtain a copy of the previous code used for this material. 3. If a code is found and it matches the one newly built, done. 4. If, on the other hand, no code is found or they do not match, the code string is rebuilt once more after calling material.onBeforeCompile (NOTE: This could have been avoided if onBeforeCompile were null or undefined by default and the onBeforeCompile and getProgramCode calls were wrapped in a conditional), 5. and then programCache.acquireProgram is called. 6. acquireProgram invariably loops over the array of program codes, checking the new code against them, and breaking early only if it finds a match. The array is not ordered by usage frequency, so one can expect to loop over on average half the programs if there is a match, and (invariably) all the programs if there is no match. (Many string comparisons will obviously break early, or be "optimized away" by a good JS implementation.) After: Shared materials will be `initMaterial`ed only once. Performance: Not measured. Side effects: Not tested.
Wait, this is just a mess. I will make a new PR from the correct base. |
Before: initMaterial is called on every instance of every material:
After: Shared materials will be
initMaterial
ed only once. But they will all beinitMaterial
ed, unless the user has overwritten the defaultneedsUpdate=true
.Performance: Not measured on applications from the wild, but a stress test has been made (see comment further down) that demonstrates an improvement.
Side effects: Unknown. It puzzles me that initMaterial does not set needsUpdate=false itself. When is it useful to not set needsUpdate=false after initMaterial?