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

Add disk cache for shader compilations #5829

Merged
merged 7 commits into from
Jun 12, 2023
Merged

Conversation

smoogipoo
Copy link
Contributor

@smoogipoo smoogipoo commented Jun 9, 2023

Shader compilation dominates our startup time, so they're now cached to disk (spirv + cross-compile + reflection) at cache/shaders/.

Test Before After (cold) After (hot)
framework image image image
osu image image image
  • For framework, only the main thread is pictured. Snapshot lasts until the game is loaded.
  • For osu, all threads are pictured because we use the async loader spinner to load shaders at startup. Snapshot lasts until the intro starts displaying (after the loading spinner).

On Vulkan, the refactoring means only one compilation occurs now:

Before After (cold)
image image

The results are also significant on the D3D and Metal surfaces which have to compile twice - once to GLSL for reflection and a second time to the destination platform. I haven't added profiling results for these but they can be imagined by doubling every duration from the first table.

@smoogipoo smoogipoo changed the title Add global cache for shader compilations Add disk cache for shader compilations Jun 9, 2023
@peppy
Copy link
Member

peppy commented Jun 9, 2023

Awesome stuff.

For the record, if a user was to change their hardware, could this cause an issue? Put another way, is there already a pathway to recovery if a cached shader file is corrupt in some way?

@smoogipoo
Copy link
Contributor Author

The compilations are hardware-agnostic. We could even distribute these files ourselves if it came to it.

Both data and a checksum of the data is written. If there's hardware-induced/OS-induced corruption, the file is abandoned and recompilation takes place, with the result of that then replacing the corrupt files.

Copy link
Collaborator

@bdach bdach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Source looks good except for a few parts I'm not getting. I'll give this a test spin on the platforms I have access to later.

return compilation;
}

public ComputeProgramCompilation CompileCompute(string programText, CrossCompileTarget target)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks unused - is this intended for future consumption somewhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was thinking it could be used for #5757 for example.

@@ -123,10 +121,10 @@ private string loadFile(byte[] bytes, bool mainFile)

if (!string.IsNullOrEmpty(backbufferCode))
{
string realMainName = "real_main_" + Guid.NewGuid().ToString("N");
const string real_main_name = "__internal_real_main";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this main name change significant in any way? I'm not sure what the guid was doing, and blame doesn't help, since it was added in, of all things, b9406dd, which just barely predates me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's significant by keeping the shader code deterministic. The guid was only present to avoid naming collisions.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right, good point. I'm assuming the naming collisions you mention are no longer relevant. Makes sense 👍

Copy link
Contributor Author

@smoogipoo smoogipoo Jun 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__internal_ should be as effective as guid, and if not then we could suffix an incrementing value like __internal_real_main_1, but I doubt that'll happen.

One case I can realistically think of is if we end up wanting multiple main trampolines, but there's no support for that right now.

@bdach
Copy link
Collaborator

bdach commented Jun 10, 2023

Tested on Windows and Android. Can confirm sizeable gains in startup time on both. I don't have profiles to show from Android because Android but it does look significantly snappier when launching.

This is pretty much good to go as far as I'm concerned, but I won't push the button yet pending potentially an iOS check and maybe a decision as to when we want to get this out, I guess.

bdach
bdach previously approved these changes Jun 10, 2023
@peppy peppy self-requested a review June 11, 2023 03:13
The previous output was always implying that a compilation happened,
even when it wasn't.

I also removed the pre-compilation log output, as that was mostly there
to gauge performance of shader compiles, which is less of an issue now.
If we still want performance metrics in logs, I'd instead consider
adding a `Stopwatch` and including the elapsed time in the "loaded" log
line.

But this is probably unnecessary.
@peppy
Copy link
Member

peppy commented Jun 11, 2023

Tested to work well here.

I've updated the logging around shader compilation to read better. I think this is fine to be merged, but will leave it approved for someone to check my latest commit.

@bdach bdach self-requested a review June 12, 2023 15:49
@bdach bdach enabled auto-merge June 12, 2023 16:04
@bdach bdach merged commit 26b36db into ppy:master Jun 12, 2023
@smoogipoo smoogipoo deleted the spirv-cache branch September 11, 2023 02:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants