gpuweb / gpuweb

Where the GPU for the Web work happens!
http://webgpu.io
Other
4.77k stars 315 forks source link

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

Closed juj closed 1 year ago

juj commented 4 years ago

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

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?

kvark commented 4 years ago

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).

pjoe commented 4 years ago

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/)

johnkslang commented 4 years ago

Some updates/corrections to that:

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

Kangz commented 4 years ago

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.

pjoe commented 4 years ago

@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

pjoe commented 4 years ago

See https://github.com/kainino0x/glslang.js/issues/1

pjoe commented 4 years ago

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.

Kangz commented 4 years ago

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

pjoe commented 4 years ago

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

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

johnkslang commented 4 years ago

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.

pjoe commented 4 years ago

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.

magcius commented 4 years ago

(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"?

juj commented 4 years ago

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"?

pjoe commented 4 years ago

@juj totally agree, also did a rant in that issue (https://github.com/gpuweb/gpuweb/issues/593#issuecomment-598772788).

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/

dj2 commented 4 years ago

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.

kvark commented 4 years ago

@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:

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.

pjoe commented 4 years ago

@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 😄

johnkslang commented 4 years ago

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:

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.

magcius commented 4 years ago

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.

dj2 commented 4 years ago

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?

magcius commented 4 years ago

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.

dj2 commented 4 years ago

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.

johnkslang commented 4 years ago

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.

kevincrans commented 2 years ago

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.

Daasin commented 1 year ago

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

kainino0x commented 1 year ago

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.

kevincrans commented 1 year ago

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.