Repository navigation
Conversation
`ShaderSource::MetalLibrary` takes the bytes of a library compiled ahead of time, as `xcrun metal` writes one, holding `vertexShader` and `fragmentShader`. The Metal backend loads it with `newLibraryWithData:error:` instead of compiling MSL source with `newLibraryWithSource:options:error:`. OpenGL panics on it, as it does on MSL source. A device that hasn't cached a shader compiles its MSL in tens of milliseconds: 21 to 155 ms, about 70 on average, on an iPhone 17 Pro. An app pays that for every shader on its first launch, after a system update, and for each shader an update changes. A library compiled as the app builds skips it, leaving only the pipelines to build. A macroquad game (CHOMP) with 29 materials, which compiles and draws each once on its loading screen: on an iPhone 17 Pro just after installing it, that took 2.50 to 2.56 s from source and 0.57 to 0.59 s from libraries. Its deterministic captures on macOS draw the same pixels either way. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`new_shader` panicked when Metal couldn't load a `MetalLibrary`, as it does on MSL that fails to compile. A library is a file the app ships, though, and if it's damaged, the app can still compile the shader's MSL. So it now returns a `ShaderError::LinkError` with Metal's description, such as "Invalid library file". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
On Metal,
new_shadercompiles MSL source at runtime (newLibraryWithSource:options:error:). On a device that hasn't cached a shader yet, that takes tens of milliseconds a shader: 21 to 155 ms, about 70 on average, on an iPhone 17 Pro. An app pays it for every shader on its first launch, after a system update, and for each shader an update changes.Apple's answer is to compile shaders as the app builds, into a library the app loads with
newLibraryWithData:error:. miniquad had no way to make a shader from one.Change
ShaderSource::MetalLibrary { data: &[u8] }takes the bytes of a library compiled ahead of time, asxcrun metalwrites one, holdingvertexShaderandfragmentShader, the same functions an MSL source must define. The Metal backend wraps the bytes in adispatch_data_t(copied, so the slice needn't outlive the call), loads the library from them, and goes on exactly as it does for a library compiled from source. If Metal can't load the library,new_shaderreturns aShaderError::LinkErrorwith Metal's description, such as "Invalid library file", rather than panicking as it does on MSL that fails to compile: a library is a file the app ships, and if it's damaged, the app can still compile the shader's MSL. OpenGL panics on it, as it does on MSL source.Adding a variant breaks an exhaustive
matchonShaderSourceoutside miniquad. macroquad'sQuadGl::make_pipelinehas one, which looks for_ScreenTexturein the source; a library has none to look in, and_ScreenTexturedoesn't work on Metal yet anyway. I'll open the one-line macroquad change once a miniquad release has this.Measurements
A macroquad game (CHOMP) with 29 materials compiles and draws with each once on its loading screen. On an iPhone 17 Pro just after installing it, three launches each:
What's left is mostly Metal building the pipelines. Once the device has cached everything, it takes 25 to 28 ms either way.
Verification
xcrun --sdk macosx metal.xcrun --sdk iphoneos metal.cargo checkpasses foraarch64-apple-darwin,aarch64-apple-iosandaarch64-apple-tvos.🤖 Generated with Claude Code