gpuweb / gpuweb

Where the GPU for the Web work happens!

Home Page:http://webgpu.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Possibility of SPIR-V and/or GLSL as a WebGPU extension?

juj opened this issue · comments

commented

Adopting WGSL may be intractable for some users due to large porting overhead and maintenance burden. E.g.

  • rewriting all shaders from existing language to WGSL may be too much time, and double maintenance cost,
  • converting GLSL shaders offline may be infeasible if shader permutations have been managed using C preprocessing (which is common in GLSL),
  • converting shaders online may be too costly to ship (current estimate look like it may be on the order of +600kB extra code size to ship a converter). (translating may also be too slow and repeat the path of WebGL shader compilation problems)

Has it been considered to offer SPIR-V, and/or GLSL as an extension to some WebGPU implementations in scenarios where WGSL would be a detriment?

SPIR-V: If you have SPIR-V shaders, means you already have some sort of an offline shader pipeline. Then you'd add SPIRV -> WGSL step in there (once the tooling is ready).

GLSL: we can't accept the same GLSL that WebGL accepts. We at the very least need a Vulkan-flavored GLSL with separate textures and samplers, as well as, explicit bindings. So some rewriting or plumbing needs to happen. I do agree that this is still a much easier target than rewriting all the shaders.

The first estimation on the code size is just a start. There is a lot of work ahead to bring this number down. Don't take it as an approximation of the end result (just yet).

For reference: glslang.js GLSL > SPIR- V for just vert/frag shaders without proper error msgs and no preprocessor is ~450KB wasm (https://unpkg.com/browse/@webgpu/glslang@0.0.15/dist/web-min-nocompute/)

Some updates/corrections to that:

  • compute stage: glslangs small GLSL -> SPIR-V also includes compute stage and the tools useful for doing compute
  • preprocessor: the preprocessor is still present and working
  • size: I think there's another 3X reduction in there due to compression.

So, it's more like 150KB with vertex/fragment/compute and a preprocessor.

SPIRV -> WGSL is something that @dneto0 is building as part of Tint (translator for Chromium), and I think Naga (translator for Firefox) might support that path too.

To answer your question about the possibility of an extension, there is no appetite to do that at this moment. The group spent a long time debating about which shading language WebGPU should ingest and thinks it reached a good compromise in WGSL. To give WGSL a fair chance of success and to not weaken the compromise, all implementers said they would only support WGSL ingestion initially (unless we receive overwhelming feedback after the first version of WebGPU). In particular once WGSL and Tint are ready, the SPIR-V path will be removed from Chromium.

@johnkslang: I don't think the preprocessor is working in https://github.com/kainino0x/glslang.js as it is not trivial to implement the interface for fetching additional files through wasm <> JS when running in the browser - it could e.g. need to fetch the included file over network in an async manner.

The docs also specifically mention that compute is not included in the minimal build of glslang.js, but that may be a config issue :D

Sorry guess the rest of the pre-processor is working, just not #include... though that is pretty important function when putting together shaders dynamically from smaller code snippets. I know e.g. Three.js does that a lot.

WebGL GLSL doesn't have #include, so all existing WebGL engines handle #include on their own already.

Gah you're right 🤦‍♂️ never mind my babbling then. Must be Monday.

Guess I'm just so used to #include just working :D

Compute was added much later than the original first pass, so I wouldn't be surprised if documentation is out of date.

#include is in glslang, just not the GLSLANG_WEB build for a small footprint. It would be pretty easy to turn it back on. That's true of almost any feature. If you turn them all on, footprint will be much bigger. If you turn just a couple more on, footprint will be about the same small size.

Yeah, compute is included in other configs of glslang.js, just not in web-min-nocompute (see https://unpkg.com/browse/@webgpu/glslang@0.0.15/dist/). I even think ray tracing shaders are also included in some of the larger bundles.

(unless we receive overwhelming feedback after the first version of WebGPU)

Apologies if this is considered bait, but I feel like existing public feedback of this choice has been somewhere between extremely negative and moderately disappointed, with most IHVs and ISVs all displeased with the decision to make another shading language. Engineers from NVIDIA, Unity, Epic Games, EA, Adobe and Valve have all expressed this opinion publicly, and I can get more opinions on public record as well. We've all felt our feedback and experience has been completely ignored or strongly undervalued by the committee, however our opinions on this matter have not changed. What additional feedback is necessary for it to become "overwhelming"?

commented

That was well phrased @magcius. I am the technical lead of Unity web platforms - from our end the conversations have ranged between shock among the web-knowledged people, to ridicule among the non-web engineers ("well of course the web people will do something diy").

We have been a strong proponent of SPIR-V, and like others surprised about the adoption of ~Rust. The comments among the company have been perceiving the decision as the "non-graphics-developers" (pardon the labeling) going after the "next shiny thing" without basis on reality on existing GPU development ecosystems, or tangible merit. Even after following #593, it has been a surprise that if WebGPU really wanted to have a text-based shading language, why not reuse the syntax of HLSL or GLSL.

The rationale of why SPIR-V, HLSL or GLSL could not be made to work (with less effort than WGSL) has not really sunk to us.

There are two camps of web GPU developers: the ones who develop only web-focused software, who can target web APIs "in a void", and then there are those like Unity, Unreal and Godot, who target multiple platforms at the same time. The feeling here is that companies wanting to target multiple platforms are not being addressed.

The rationale "Apple cannot do X" also seems bad and unjustified basis to make decisions. It feels sad that WebGPU/WGSL is being developed as an after-the-fact layering on top of existing native APIs (unchanged), rather than getting vendor buy-in to building a safe & secure native driver foundation WebGPU could comfortably be built on.

To give WGSL a fair chance of success and to not weaken the compromise, all implementers said they would only support WGSL ...

Sorry, I know you did not mean it, but this statement does read like admitting that other paths are already known to be superior, so they were not allowed to compete.. 😕

If the extra download times, conversion times, compilation times, development time, and maintenance time overhead of working with WGSL prove to all be negligible, I believe the dissatisfaction will go away on its own. Those are the metrics that WGSL should be diligently measured against.

However I wish not to focus the conversation in this ticket on viability of WGSL itself, as that has flamed elsewhere, but rather to focus the conversation on discussing the feasibility of shipping SPIR-V and/or GLSL as an extension.

I hope binary shaders with specialization constants would be entertained at some point, e.g. a web-safe subset of SPIR-V? That way we could ship the half a meg converter JSes from SPIR-V -> WGSL on-demand on Apple devices only, and keep shader compilation times fast and download footprint light on other platforms. The "lowest common denominator only" approach to web spec development would be hurting the web.

I also hope that Chrome will retain and develop the SPIR-V path in WebGPU long enough that the coexistence of SPIR-V and WGSL shader conversion and compilation times can be compared and benchmarked. E.g. by having a debug flag in the browser that enables SPIR-V support, instead of removing it too soon. That would give the possibility to obtain data of "here is what WGSL is costing us", and perhaps motivate proponents of WGSL to admit that the solution is not appropriate, or perhaps mute the concerns of "is it good enough"?

@juj totally agree, also did a rant in that issue (#593 (comment)).

My best suggestion is for more interested parties to join the W3C community group and make their voices heard during the weekly meetings where most decisions are made: https://www.w3.org/community/gpu/

The statement about a fair chance isn't that one solution is superior, it's that we have finite development resources and we can either build one path with all our resources, or put half as much effort into two paths. If we want WGSL to work well, we think splitting the development resources in half isn't a feasible path forward.

For your comment about shipping SPIR-V and converting on Apple, both Naga and Tint will have tools to convert to WGSL. For the Naga case, I believe there will be multiple input languages and multiple output languages. For Tint, you will be able to convert from SPIR-V to WGSL. So, you can convert offline, and then just ship the WGSL directly in the browser, which saves shipping the extra bundle.

I will also point out, that even if SPIR-V was the input language we'd still be doing the translation on most platforms. When targeting Metal, we'd have to convert the SPIR-V to Metal Shading Language. When targeting DirectX we'd either be converting to HLSL or DXIL. Only on platforms running Vulkan would we be able to us the SPIR-V directly, even then, it would be the WebGPU environment of SPIR-V, which would be a subset.

@magcius @juj it's easy to mock the group for this decision, without considering all the nasty details in the lengthy discussions we had within the group. We know there is a large group of developers who would prefer SPIR-V to be digested, we know there is a group that wanted GLSL to be that langue for ease of porting from WebGL, we know there are people who just want to run HLSL everywhere. And yet, the Web poses additional requirements on the language on top of that, namely: security and portability. There is no solution that would make everyone happy.

Apple explored the possibility of adopting and standardizing HLSL with the WebHLSL initiative, in collaboration with Microsoft. They also tried to design a new language from the ground up: both of these experiments helped the group to make an informed decision. There is much more to it than just "Apple cannot do X" that often shows up.

rather than getting vendor buy-in to building a safe & secure native driver foundation WebGPU could comfortably be built on.

This is not an option for the group, and never was. We are not in Khronos, and therefore we have limited participation from IHVs (only Intel and Apple are active). WebGPU was never designed to be implemented by the drivers. I mean, it would totally be rad, in the context of how usable WebGPU can be on native, but it couldn't be the requirement from the start.

If the extra download times, conversion times, compilation times, development time, and maintenance time overhead of working with WGSL prove to all be negligible, I believe the dissatisfaction will go away on its own. Those are the metrics that WGSL should be diligently measured against.

We are thinking about these metrics all the time:

  • "download times" - there is no indication that WGSL will have more bytes to download than SPIR-V.
  • "conversion times" - there is no indication that converting WGSL to the backends will be slower, on average, than converting SPIR-V to the backends. Consider the fact that we need to load the source code, analyze it, do a few transformations, and translate it, even for SPIR-V.
  • "development/maintenance time" - what the group agreed to on the last F2F is to take the semantics of SPIR-V where it makes sense. This helps reducing our time designing the language. In terms of tooling, we figured that SPIRV-Cross is too hard to adopt for in-browser use anyway, so developing tooling was inevitable.

Now, let me switch the gears and put on the devil's advocate's hat. Here are the reasons why I think adopting SPIR-V directly would be bad for the API. Arguments pro-SPIRV are well understood. I'm hoping to bring clarity about the other side of the fence:

  1. SPIR-V is too low level. It's meant to be translated to machine bytecode, while we need to target MSL and HLSL/DXIR. When doing this, it becomes awkward quickly, since nobody writes SPIR-V. Think of the control flow, for example, which SPIR-V represents as a graph (CFG). People write shaders in high-level languages, where control flow is structured, then compile it to SPIR-V with a CFG that looks unstructured but is actually guaranteed to be one, and then we have to parse it and recover the structure back in order to produce HLSL and MSL, both of which have structured control flow. That's unnecessary work for our shader translation.

  2. SPIR-V has a lot of instructions for every little bit of hardware support that's out there. WebGPU is more interested in portability and security than exposing all those bits. We can't have instructions with undefined behavior. We don't want to have instructions that are difficult to run on some platforms we target. as a result, we need a reduced (and potentially different) instruction set.

  3. SPIR-V doesn't answer the question of how we write documentation, examples, and tests, for the API. Khronos used GLSL in Vulkan flavor for this, which has the downside of the tests being biased towards the logic of glslang.

  4. We have different goals with Khronos, and it's hard to make sure that SPIR-V will be developed in the direction we need. Say, a potential raytracing instruction set may be further from what we want, or a mesh shader one, you name it. So we'd always be on the verge of forking SPIR-V in some way.

This all comes down to the fact SPIR-V has different goals from what we need. Even if we digest it directly, there is an equal amount of work to be done parsing the structure out of it, transforming it, validating it, and translating into the backend shaders. And there is still work that has to be done on the language design and tooling. We thought, Tint was a great idea, as a result. What's happening today though is that we are sliding more and more into the "design a new language from the ground up" territory, and I'm equally worried as you are.

I still haven't made my mind on whether accepting SPIR-V as an extension is a good idea. Naga will be able to work with it, regardless, but it's IR is much closer to WGSL today.

@dj2 Hoping SPIR-V support does stay around a bit longer. Would be a pity for all the ray-tracing work that was done (https://github.com/maierfelix/chromium-ray-tracing) to go to waste. Of course also hoping WGSL will get RT support at some point 😄

SPIR-V was a poor choice, because people wouldn't write in SPIR-V? Of course people won't write shaders in SPIR-V, it's an IR. They won't want to write in any IR. Let's don't waste bandwidth going in great depth on that rather than discuss the real reasons.

Serious shader authoring won't occur in any language that's so low-level that it satisfies the goal for super-high portability based simplicity and having only low-level explicit constructs. Real workloads will be authored in sugary implicit constructs in languages that make it easy to write large bodies of cooperative code, but in exchange get more variance across compiler implementations. Yet, that HLL compilation variance isn't a big problem when using an IR: Each vendor picks a compiler and sticks to it. The real problem is having variance at the API boundary, which is why you'll pick an IR, textual or not, that is super simple/explicit to implement in a portable way.

Similarly for security issues, which is also wasting bandwidth on straw man arguments instead of on what's really happening. Security is not solved by language syntax, despite flawed attempts to conflate the two.

If we want to communicate what's really going on, let's not start by raising and rehashing flawed arguments. What are the real reasons? SPIR-V should not be the scapegoat for whatever the real reasons are.

If the real reason is wanting super-portable textual input, that's easy to state, with implications:

  • super-portable means not HLSL/GLSL with all their useful constructs like preprocessors, compile-time constant folding, implicit conversions, etc.
  • textual means not SPIR-V (see, that was easy)

So, that pretty much implies creating a new language that's too low-level to write seriously in, yet is textual, making it bit easier to tweak something after you compile, should you find yourself lacking a compiler or the original source, or working around a bug somewhere.

There is definitely a design space between these two extremes. One example is the old ARB_fragment_program textual syntax, or the textual disassembly of SPIR-V/DXBC. To use an example from the ARB_fragment_program specification:

      TEX     L, light_tc, texture[4], CUBE; # Sample cube map normalizer

      # Calculate diffuse lighting (N.L)
      SUB     L, L, half;              # Bias L and then multiply by 2
      ADD     L, L, L;
      DP3     diffuse, norm_tc, L;     # N.L

      # Calculate specular lighting component { (N.H), |H|^2 }
      DP3     NdotH.x, norm_tc, half_tc;
      DP3     NdotH.y, half_tc, half_tc;

      DP3     lV.x, lv_tc, lv_tc;     # lV = (|light to vertex|)^2

These were very different languages that were more DSP-like in semantics, and had very limited support for flow control, or even anything less than a single write at the end of the pipeline, but it shows a different consideration to the design space: more designed as the output of a toolchain process than something to be hand-written directly.

The original Tint proposal from Google was more along these lines, with a strong focus on "bijectivity to SPIR-V", that design goal coming from concerns from ISVs that their shaders need to be represented exactly and precisely, since such semantics are extremely tricky and we, admittedly, have limited faith in browser vendors to get such details right.

However, despite this initial promise that the language would remain more in that design space, the committee has been debating things like adding syntax sugar for features that no compiler toolchain would emit, often completely divorced from any real use case, or feedback from ISVs/users. In fact, there has been zero feedback from users, yet! Implementations are still not done, the toolchains have not finished being built, and yet the committee continues to expand the scope of WGSL, all the while WebGPU is multiple years behind schedule.

The textual vs. binary debate is uninteresting to me, I have some preferences but I honestly think it's overblown. I care far more about the semantics than the spelling, and I would prefer to see a small collection of syntax and semantics implemented so that real users can provide feedback.

committee has been debating things like adding syntax sugar for features that no compiler toolchain would emit, often completely divorced from any real use case, or feedback from ISVs/users

Can you provide examples? We've been pushing things off until post MVP and receiving more user feedback. Are there particular things we've let through you're referring too?

Anything that's mostly bikeshedding on syntax, e.g. #739, I see as mostly extraneous. Namespaces, preprocessor, how loops and control flow are serialized, etc. Tooling can handle whatever's chosen, and I'd rather punt on superficial difference until after we have working implementations and tooling authors tell us what's unfortunate. Just ask anyone who's ever had to emit MSL about what makes tooling difficult; it's rarely minor spelling differences.

We have to get the syntax in to a mostly correct ordering before releasing as we can't really change it afterwards. We're trying to find the minimal things we can do that give us the ability to expand later. What we don't want to do is add something in we're forced to remove as that would break any shaders that were written.

Tint is a mostly working implementation at this point, there are a few features missing, and validation is also missing, but for getting a feel for WGSL folks could try it out now.

If you have examples of what makes tooling difficult they could be useful to know so we can see what issues have been found in other places.

One thing to do to be safe WRT future additions to the language is to follow normal phases of tokenization/parsing so that something isn't accidentally precluded. (A number of other issues seem to suggest not doing that, and I've responded there.):

  1. character analysis, logic characters -> actual characters etc.
  2. line number is noted
  3. back slash before newline and line merging... does WGSL have that?
  4. comment stripping, with space substitution, or whatever the rules for WGSL are for that
  5. tokenization into a preprocessing token stream
  6. trivial preprocessing, expandable to the future, just to avoid accidental preclusions
  7. validate that the results in is the WGSL character set, forming a proper WGSL token stream
  8. parsing

E.g., one non-obvious thing might be that string escape sequences are handled early above, not late, and getting the escape sequences to be the exact correct set now will help.

Why do webgpu shaders need to be textual, web-assembly isn't so textual itself for one.
Not adding vulkan shaders to webgpu Looks to me like the dumbest limitation of a modern portable rendering api.
I didn't want to say that, but I don't see a reason not to.

Also, glsl shaders can be compiled to spir-v, just like Wasm text can be compiled to wasm.

commented

Is SPIR-V still going to be supported in any form for WebGPU?

WebGPU does not accept SPIR-V, and it's extremely unlikely it ever will.

Tint (Chromium/Dawn's WGSL tooling) and Naga (Firefox/wgpu's WGSL tooling) have capabilities to translate SPIR-V into WGSL, so if you need that, please investigate those.

Too bad the exciting spir-v and modern shader language consistency is undersnowed by WGSL, however happy that this is there.

What did happen however is that Nintendo made a shader object extention to vulkan that doesn't need pipelines optionally.
Thought that might be interesting and related to what @kvark said.