Skip to content
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

Eliminating unnecessary Uniform updates #14004

Closed
oguzeroglu opened this issue May 6, 2018 · 13 comments
Closed

Eliminating unnecessary Uniform updates #14004

oguzeroglu opened this issue May 6, 2018 · 13 comments

Comments

@oguzeroglu
Copy link
Contributor

Hello!

Using the WebGL Inspector tool on Chrome I realized that WebGL uniform functions are called even though the uniforms are not changed:
ekran resmi 2018-05-06 11 12 49

I remember watching a guy from Sony talking about how they integrated the WebGL into the PS4 and how eliminating these redundant calls helped them improving the performance. Since WebGL is simply a state machine, calls that make no change in the current state should be ignored. As this can be simply achieved with an IF condition before the WebGL call another idea would be to add dynamic or shouldUpdate flag to the uniforms.

Any opinions, ideas or comments on that?

@Mugen87
Copy link
Collaborator

Mugen87 commented May 6, 2018

Yes, three.js could work in a more efficient way to avoid such redundant calls. Some time ago, I've read in a book (WebGL Insights) an interesting chapter about WebGL engines in context of mobile devices. The author said:

It (three.js) often does redundant or inefficient updates to the GL state, particularly to uniform values, and due to how it's structured, this is unlikely to improve without some very significant changes.

Babylon.js for instance handles an update of a color3 uniform like this:

Effect.prototype.setColor3 = function(uniformName, color3) {

	 if (this._valueCache[uniformName] &&
	     this._valueCache[uniformName][0] == color3.r &&
	     this._valueCache[uniformName][1] == color3.g &&
	     this._valueCache[uniformName][2] == color3.b)
	 return this;

	 this._cacheFloat3(uniformName, color3.r, color3.g, color3.b);
	 this._engine.setColor3(this.getUniform(uniformName), color3);

         return this;
};

I'm not sure the code is up to date but it illustrates the general idea behind a uniform cache. Maybe we can enhance WebGLUniforms in order to implement a similar caching system?

BTW: I think it would be useful if WebGLInfo could count uniform updates/changes per frame.

@Mugen87
Copy link
Collaborator

Mugen87 commented May 6, 2018

@oguzeroglu I'd like to rephrase the title since it makes more sense to focus on uniforms in this issue. Prerender optimization is a wide topic and three.js already performs caching to avoid redundant WebGL state changes.

@Mugen87 Mugen87 changed the title Eliminating unnecessary WebGL calls Eliminating unnecessary Uniform updates May 6, 2018
@oguzeroglu
Copy link
Contributor Author

oguzeroglu commented May 6, 2018

Yes sure, the title makes more sense like this :)

I'm gonna try to experiment with uniform caching this week, I'll post the results here.

@pailhead
Copy link
Contributor

pailhead commented May 7, 2018

I remember watching a guy from Sony talking about how they integrated the WebGL into the PS4

Was this Don Olmstead? Webgl meetup at google a while ago?

It would be useful for something like this to make a meaningful test case. Stress out and cause the most redundancy, and then we could have something to try to optimize.

@oguzeroglu
Copy link
Contributor Author

Was this Don Olmstead? Webgl meetup at google a while ago?

Yes, here's the video: https://www.youtube.com/watch?v=QVvHtWePQdA

It would be useful for something like this to make a meaningful test case. Stress out and cause the most redundancy, and then we could have something to try to optimize.

I don't know the maximum number of allowed uniforms in WebGL, it might be even hardware specific but I'm going to try to test with loads of mat4 uniforms. I hope I can get some sort of FPS drop like that :)

@pailhead
Copy link
Contributor

pailhead commented May 7, 2018

This isn't an issue of maximum allowed uniforms, but more of setting the state of three.js to incur the most uniform changes? I might be misunderstanding something though.

@oguzeroglu
Copy link
Contributor Author

but more of setting the state of three.js to incur the most uniform changes

Well that's the case actually, more the uniforms more the WebGL calls since THREE.js does not seem to do uniform caching. In the screenshot I put to the issue I was not updating fogfar, diffuse etc.

@Mugen87
Copy link
Collaborator

Mugen87 commented May 7, 2018

To clarify this: The issue is about only updating uniforms if values actually changed.

@makc
Copy link
Contributor

makc commented May 9, 2018

I can see it could be easily hacked for ShaderMaterial with something like

material.uniforms = {
    myVar : { type : '...', value : ..., needsUpdate : false },
    ...

and whenever needsUpdate is not set to false, do the call as before.

@Mugen87
Copy link
Collaborator

Mugen87 commented May 9, 2018

The idea is to do caching automatically. three.js should only perform an update if values actually changed. Similar to WebGLState.

@Mugen87
Copy link
Collaborator

Mugen87 commented May 9, 2018

The needsUpdate flag for uniforms might be redundant at a certain point.

@pailhead
Copy link
Contributor

Yeah this is more for the stuff in between calls, like, Camera, is shared by all the shaders, it shouldn't be set in between draw calls.

@oguzeroglu
Copy link
Contributor Author

It seems like the PR fixed it, so I'm closing the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants