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

Optimize shader processor #6067

Merged
merged 1 commit into from Feb 19, 2024
Merged

Optimize shader processor #6067

merged 1 commit into from Feb 19, 2024

Conversation

mvaligursky
Copy link
Contributor

@mvaligursky mvaligursky commented Feb 19, 2024

  • execute metal specific workaround only on iOS and MacOS
  • process array sizes on the whole source instead of per line for large speed up

before:
before

after:
after

For 100 shaders this makes about 1.5s difference.

@mvaligursky mvaligursky self-assigned this Feb 19, 2024
@mvaligursky mvaligursky added performance Relating to load times or frame rate area: graphics Graphics related issue labels Feb 19, 2024
@mvaligursky mvaligursky requested a review from a team February 19, 2024 16:41
@mvaligursky mvaligursky merged commit fbe60ca into main Feb 19, 2024
7 checks passed
@mvaligursky mvaligursky deleted the mv-optimize-shader-processing branch February 19, 2024 16:49
@MAG-AdrianMeredith
Copy link

Thank god, I'm having so many issues with this right now! looks forward to trying it.
p.s. I'm also seeing large amount of time in generating shader keys wonder if theres a faster way somehow to hash them.

Any reason I couldn't write these cached shader files to disk / localstorage? Would be nice if it could be skipped on subsequent runs

@LeXXik
Copy link
Contributor

LeXXik commented Feb 20, 2024

@MAG-AdrianMeredith it looks like its only for iOS15. If you are on iOS16, it should already be running at optimal speed.

Now that you brought it up, I'm also curious if there is a way to reuse once compiled shader / keys on subsequent runs of the same application. Can some of those be reused by another app, if they share a storage? We have a native wrapper that hosts multiple apps, and it could share data between them.

@mvaligursky
Copy link
Contributor Author

We have some code that can store the generated shaders to a file, and load it / precompile ahead of time. Not a public API, and not really well implemented, so it's disabled at the moment. But I keep thinking about how to do this in a better way.

Modifying material properties and then calling update() on the material is another thing that does not work too well, as it often makes the engine to reevaluate material options to see if the existing shader can still be used. This is expensive.

@LeXXik
Copy link
Contributor

LeXXik commented Feb 20, 2024

Modifying material properties and then calling update() on the material is another thing that does not work too well, as it often makes the engine to reevaluate material options to see if the existing shader can still be used. This is expensive.

Good point. We've noticed it as well and generally try to avoid updating or changing a material at runtime. We have a limited set of materials that all of our assets are using across all our games. They are always the same.

@MAG-AdrianMeredith
Copy link

right now I'm seeing it take almost a minute from loading (and seeing the world) to actually being able to move around because its hitching so much. Seems to be spending most of its time in "generateKey". Hopefully I'll get time to look into it further soon so I'll get back to you if I find anything. might not be be for a few weeks though

@mvaligursky
Copy link
Contributor Author

What device are you running this on @MAG-AdrianMeredith ?

@LeXXik
Copy link
Contributor

LeXXik commented Feb 20, 2024

I am considering to monkey-patch the key generation for our project. If none of our games is using e.g. a clear coat factor, then there is no need to check its value. Building around this premise, perhaps we could explicitly tell which fields can be different and used by the generator. The rest would be ignored, and assumed to be the same across all materials. However, if the majority of time is coming from say linking the program, then that won't help much.

@mvaligursky
Copy link
Contributor Author

From my profiling, I could not see this taking too much time .. options generation is about 1ms or less. Can you please post some screenshots of what you see?

@LeXXik
Copy link
Contributor

LeXXik commented Feb 20, 2024

Just tried to run on one of the games. The key generation took less than 1ms, like you said, Martin. Its the getProgramParameter in most cases for us.

image

@mvaligursky
Copy link
Contributor Author

yeah and that is the blocking call waiting for the shader to finish compiling :(

You can enable tracing to see how many shaders are compiled, and how long the blocking duration is as well. In case you have many shaders, you could aim at reducing that number.

Note that some browsers cache this compilation .. so often it's only expensive on the first run, and when dev tools are opened.

@MAG-AdrianMeredith
Copy link

MAG-AdrianMeredith commented Feb 21, 2024

I'm on apple macbook m1 playcanvas 1.65.3 oddly enough I'm not seeing genereate key as much as previously but its mostly in getProgram
Screenshot 2024-02-21 at 10 26 38
Screenshot 2024-02-21 at 10 30 56
Screenshot 2024-02-21 at 10 31 05

The actual shader compilation part is by far the smallest part of the whole thing

@mvaligursky
Copy link
Contributor Author

The shader compilation / linking runs in the background browser threads. When we need the result, we call getProgramParameter to get info about the shader, and this is blocking till the shader is done compiling. So this is part of the compilation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: graphics Graphics related issue performance Relating to load times or frame rate
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants