-
Notifications
You must be signed in to change notification settings - Fork 329
Description
(Thanks to @kvark for bringing this up!)
The Problem
Just like WebGPU, Metal has a two-stage shader compilation pipeline. First, you create a MTLLibrary
from a source string, and then once that has finished, you can create MTLFunction
s from it. The MTLFunction
s are the objects you pass to the pipeline creation routines. In WebGPU, you first create a GPUShaderModule
, and then pass the result to the pipeline creation routines.
There is a bit of a mismatch, though: the pipeline creation routines in WebGPU accept additional information about the shader in the form of the GPUPipelineLayout
(and others), which in Metal is defined by the text of the shader itself. Naively, this would mean that we can't generate the MSL shader source until pipeline creation time. I think we can and should do better, though.
It's important to do better because the first stage of compilation is expected to be more heavyweight and less frequent than the second stage of compilation. If we delay all of compilation until pipeline creation, we end up doing a lot of unnecessary duplicate compilation work in the more frequent second stage, and forcing web apps to load more slowly on Metal. This problem should be solved.
There are a few different mechanisms we could use to solve this. We're not particular about which one, but the method that is used should be agreed upon by the group.
Options
Option 1: Make the WGSL's source text at least as specific as MSL's source text at entry point boundaries, thereby encoding all the necessary information to generate a MTLLibrary inside the source text of the WGSL string.
This not only would affect the set of types, but would also affect layout of argument buffers. For example, if you have:
[[[binding 0]]] var a : texture_sampled_2d<float>;
[[[binding 2]]] var b : texture_sampled_2d<float>;
We'll have to know, just from the source text, whether a
and b
have to reside in the same argument buffer, whether that argument buffer should have a hole in between them, and if so, how big the whole should be. This is information that is currently included in the GPUPipelineLayout
, but we'd have to have a way of recreating it from the text of the shader.
Option 2: Pass in extra information as arguments to createShaderModule()
. This would be a subset of the information that is currently passed to create*Pipeline()
. It would probably have to be in a different form, though, because there can be multiple entry points inside the shader module text. Perhaps a map like <DOMString, GPUPipelineLayout>
or <DOMString, (GPUPipelineLayout, GPUVertexStageDescriptor, sequence<GPUColorStateDescriptor>, GPUDepthStencilStateDescriptor)
.
Option 3: Maybe there's another way of solving this problem I haven't thought of. Suggestions welcome.