Re: Initial thoughts porting a decently complex WebGL2 application to WebGPU

On Wed, Nov 6, 2019 at 5:22 PM Kai Ninomiya <kainino@google.com> wrote:

> Thank you for all this input!
>
> On Wed, Nov 6, 2019 at 9:50 AM Jasper St. Pierre <jstpierre@mecheye.net>
> wrote:
>

... snip ...


> # Shaders
>
>>
>> This is where I expected most of the trouble to be, and indeed, it was.
>> Most of my shaders were hand-written in GLSL, a choice made out of
>> necessity for WebGL more than a desire. GLSL is a very unfortunate language
>> to develop in, and the variations between profiles means it's honestly just
>> as annoying as a clean break to a new shading language. To list some points:
>>
>> * This is not a problem with GLSL per se, but I had to try multiple
>> different versions of glslang before I found a combination that worked.
>> This is partially due to the immaturity of JS build tooling and WebAssembly
>> together, but also found lots of buggy versions in the wild, including the
>> version in "@webgpu/glslang". I ended up vendoring my own glslang, based on
>> the version shipped in BabylonJS.
>>
> That one should be a copy of one of the published versions on npm, but I
> don't know which one.
>
>
>> This still has some minor issues (compileGLSLZeroCopy returns an object
>> whose "free" method has been renamed to "fa", probably as a result of
>> minifying the code), but was workable for my purposes.
>>
> Oops. I'll fix this.
>

There's still issues with JS tooling for me. The wrapper generated requires
"import.meta" which isn't supported by my build tooling yet (Parcel 1.
Parcel 2 supposedly supported it better but it's still not workable for
me), and it has some assumptions on how the WASM file is loaded and
distributed which is unfortunate, but this isn't your fault per se. I note
that the BabylonJS guys put in their own hand-written wrapper:
https://github.com/BabylonJS/Babylon.js/blob/WebGPU/dist/preview%20release/glslang/glslang.js#L60-L117

So I'll probably still have to vendor @webgpu/glslang but hopefully the new
version will be more drop-in than before.

... snip ...


> "GLSL" is not one language but instead a vague idea of one, with arbitrary
>> restrictions necessitated by simple compiler implementations, without any
>> concern for developer ergonomics. This is something
>> decently-well-understood in the porting community, but not as much by the
>> graphics systems community at large. I cannot emphasize how difficult it is
>> to work with multiple profiles of GLSL without going insane. For now, you
>> can see most of my hacks here as regular expression preprocessing on the
>> text [3]. It is ugly and brittle. I do not like it. A proper shader
>> compilation pipeline is desperately needed.
>>
> Do you mean that you'd like to have one shading language that you can
> compile for both WebGPU and WebGL?
>

No, but it does put a huge damper on "just use GLSLang" in terms of a
compatibility story. And it's empirical evidence of something we've all
been saying: Shader languages are *super* dependent on the environment they
live within.

To be clear, I think combined texture/samplers are a terrible GL mistake,
as are non-explicit uniform locations. I prefer WebGPU's choices. I don't
know why the sampler2D constructor restriction is there, other than it
being written in the spec to make vendor compilation simple, despite us
having a controlled environment (SPIR-V can certainly support it). If we
could change the sampler2D constructor restriction upstream in GLSLang,
that would make me super happy.


> # Other notes
>>
>> These are minor things that bit me during the port.
>>
>> * An error message along the lines of "Pipeline attachments do not
>> match". This turned out to be that I was missing sampleCount in my pipeline
>> state. I did not realize it was actually a parameter in the pipeline state.
>> This should probably be marked required, as otherwise it is easy to not
>> realize it is there.
>>
> If the error message was good (e.g. 'pipeline attachment sampleCount
> doesn't match pipeline layout') do you think this would still be necessary?
> Sorry our error messages for these giant objects are really bad right now.
>

I still think it's weird to default to sampleCount = 1 unless we expect
most users not to be using MSAA... but better error messages would
definitely help here.


> * "Row pitch is not a multiple of 256". There is currently no wording in
>> the spec about limits of rowPitch, but a row-pitch of 256 seems like a
>> large number to me, especially when we get down into the mipmaps below that
>> size. 128, 64, 32, 16, 8, 4, 2, 1 will all require padding which is
>> expensive.
>>
> This is a D3D12 restriction: D3D12_TEXTURE_DATA_PITCH_ALIGNMENT
> We've talked about emulating it, but would that be the right approach?
> I don't know how D3D12 apps deal with this problem.
>

... snip ...


> * Trying to run WebGPU under RenderDoc on Windows showed that Chrome was
>> using both D3D11 and D3D12, with D3D12 marked as "not presenting". I don't
>> expect too much yet, but debuggability is a strong point from me.
>>
> This is probably because the D3D12 context is just producing textures for
> D3D11 to present. Does RenderDoc need the D3D12 context to be presenting in
> order to debug it at all? Can we artificially insert a frame boundary that
> RenderDoc can detect?
>

I'm guessing that RenderDoc can only capture one API at a time, and if it's
in D3D11 mode, it can't capture D3D12. Might be helpful to talk with Baldur
about the best way to do this going forward.


> * I did not adjust my projection matrix for WebGPU and yet I seem to be
>> getting OK results. Perhaps I'm missing something, but I thought that the
>> output clip space should be 0...1, rather than the -1...1 generated by
>> gl-matrix. Getting RenderDoc up and running would help me adjust my
>> bearings.
>>
> I believe the output clip space z should be 0..1. Depending on how small
> your near-z is, it might not look significantly different. Or maybe we just
> have a bug.
>

This was my bug. I implemented reversed-depth for improved depth precision,
but my math was off and was accidentally halving the near plane. So that
accidentally canceled things out :)


> * The result is still a bit slow and crash-y. I expect this is simply as
>> the backend is not ready yet, but it is possible I am doing something
>> wrong. Do let me know.
>>
> I would doubt you're doing something wrong. The performance in Chrome is
> expected to be better on Metal because there are a lot of totally
> unoptimized parts of the Vulkan and D3D12 backends.
> Unfortunately, I can't try it on Metal because we're passing something
> invalid down to the driver:
> > stencilAttachmentPixelFormat MTLPixelFormatDepth32Float is not stencil
> renderable.
> so we'll have to look into that.
>
> There is also an assert in my local build of Chromium because we don't
> handle canvas resizes correctly.
>
>
>> # Final thoughts
>>
>> This was a very simple API for me to port to, but I also have a lot of
>> experience with more modern graphics APIs, and also some ability to "see
>> the future" when I built my graphics portability layer. Porting from raw
>> WebGL 2 to my Gfx layer took months of continued effort, and I can imagine
>> other libraries not equipped for the transition having a harder time.
>>
>> Still, having been involved in D3D12 -> Vulkan ports, getting a scene up
>> and running in a few nights is fantastic turnaround. Huge round of applause
>> to the whole team for the design of the API so far. Looking forward to
>> what's next.
>>
> I'm very glad to hear it. Thank you for all of your contributions to the
> design as well!
>
>
>> [0]
>> https://github.com/magcius/noclip.website/blob/213466e4f7c975b7bb6cee9ecd0b5fdcc3f04ed9/src/gfx/platform/GfxPlatformWebGL2.ts#L1589-L1598
>> [1]
>> https://dawn.googlesource.com/dawn/+/refs/heads/master/src/dawn_native/vulkan/BindGroupVk.cpp#48
>> [2]
>> https://github.com/magcius/noclip.website/blob/213466e4f7c975b7bb6cee9ecd0b5fdcc3f04ed9/src/BanjoKazooie/render.ts#L102-L121
>> [3]
>> https://github.com/magcius/noclip.website/blob/213466e4f7c975b7bb6cee9ecd0b5fdcc3f04ed9/src/Program.ts#L68-L90
>>
>> --
>>   Jasper
>>
>>

-- 
  Jasper

Received on Thursday, 7 November 2019 18:21:16 UTC