sokol icon indicating copy to clipboard operation
sokol copied to clipboard

Reminder: update WebGPU swapchain code in sokol_app.h

Open floooh opened this issue 1 year ago • 13 comments

...use the new surface functions instead of the deprecated swapchain functions.

See the updated wgpu_entry_* code in sokol-samples.

PS: while at it, also add 'native' support to the sokol_app.h WebGPU backend so that it is possible to use sokol_app.h with Dawn. It's not much code needed to connect WebGPU to the OS window system, see:

https://github.com/eliemichel/glfw3webgpu/blob/main/glfw3webgpu.c

floooh avatar Sep 30 '24 12:09 floooh

NOTE: on macOS this requires to drop MTKView because WebGPU wants a CAMetalLayer object to setup the swapchain surface, but MTKView doesn't seem to allow access to its internal CAMetalLayer.

...so probably better to move the 'native Dawn support in sokol_app.h' stuff into a separate update after the bindings cleanup.

floooh avatar Oct 01 '24 12:10 floooh

@floooh Hi! Did you have a chance to start a CAMetalLayer thing yet? Maybe I can help if you could tell me roughly which parts of sokol app we need to adjust?

hb3p8 avatar Oct 11 '24 07:10 hb3p8

Not yet, in any case, search for _sapp_macos_view and _sapp_ios_view in sokol_app.h these are 'subclasses' of MTKView and this stuff needs to be ripped out.

Also here's a (too simple) example which just uses a fixed-size CAMetalLayer without also managing depth-stencil and msaa-surface.

https://github.com/floooh/sokol-samples/blob/master/glfw/metal-glfw.m

E.g. what's missing is:

  • also create a depth-stencil-surface and if sample_count > 1 a MSAA surface
  • on window size change, discard and create all surfaces (I think the lifetime problems I had been seeing in earlier attempts are now solved inside sokol-gfx, because sokol-gfx convervatively holds a reference to all swapchain surfaces until they are guaranteed to be no longer in flight)

I think you can also look at the D3D11 and WebGPU swapchain management code both in sokol_app.h and in the 'raw' D3D11 and WebGPU samples for inspiration because their swapchain management looks quite similar, e.g.:

  • D3D11: https://github.com/floooh/sokol-samples/blob/0502fa1fb840e502235518af94e7ab27b7a7adb3/d3d11/d3d11entry.c#L163-L210
  • WebGPU: https://github.com/floooh/sokol-samples/blob/0502fa1fb840e502235518af94e7ab27b7a7adb3/wgpu/wgpu_entry_swapchain.c#L9-L87

floooh avatar Oct 11 '24 09:10 floooh

Argh, I had written a comment here that was for another issue (deleted now), sorry for the confusion :D

floooh avatar Oct 11 '24 09:10 floooh

PS: I guess to actually drive the frame callback we might also need a DisplayLink object... (which isn't needed in the GLFW example because that just runs the rendering in a loop).

I had tinkered with CVDisplayLink in the abandondend multiwindow branch here:

https://github.com/floooh/sokol/blob/sapp-multiwindow/sokol_app.h

...just search for CVDisplayLink and you'll find all the relevant places.

...or maybe we can continue to just hook into the NSView's drawRect method? Not sure tbh, don't know enough Cocoa for that...

https://github.com/floooh/sokol/blob/38e4c9a516f8808d706343a5c525acfe7007fe67/sokol_app.h#L4208-L4222

floooh avatar Oct 11 '24 09:10 floooh

...I think I used this documentation page as reference when I worked on the CVDisplayLink stuff in the multiwindow-branch:

https://developer.apple.com/documentation/metal/onscreen_presentation/creating_a_custom_metal_view?language=objc

...maybe googling around a bit with the keywords Metal and CADisplayLink or CVDisplayLink also helps, e.g. bringing things like https://www.delasign.com/blog/metal-animations-cadisplaylink/

floooh avatar Oct 11 '24 09:10 floooh

Hmm, also apparently the macOS specific CVDisplayLink is deprecated, and the common CADisplayLink is now supposed to be also used on macOS, but only since macOS 14 (which is too recent IMHO)... not sure what to do about that, probably best to use CVDisplayLink for a little longer if it is not available before macOS 14...

https://developer.apple.com/documentation/quartzcore/cadisplaylink?language=objc

floooh avatar Oct 11 '24 09:10 floooh

At times like this I kind of appreciate Win32 API 😅 I'll make some attempts next week, will see if anything works!

hb3p8 avatar Oct 11 '24 10:10 hb3p8

Btw, one thing I didn't think of when arguing that WebGPU can't be used together with MTKView.

Since MTKView is a subclass of NSView, maybe we can access the CAMetalLayer needed by WebGPU via the parent class NSView.layer member. But I'm not sure if it's as simple as that, because I think both the MTKView and the WebGPU swapchain code need to call the nextDrawable method on the CAMetalLayer and that might confuse the view. Worth a try though and would require only little code.

...maybe I get around trying that in a separate branch. Long term I think it's a better idea to get rid of MTKView because it was a constant source of regressions between macOS updates.

floooh avatar Oct 12 '24 09:10 floooh

@floooh It works! So here is roughly what I have so far: https://github.com/floooh/sokol/pull/1136 In a nutshell, I've tried merge WGPU and Metal backends as much as possible.

  • Grabbed some helpers from emscripten one.
  • Created CAMetalLayer and used CVDisplayLink to make a render loop.
  • Uncommented _sapp_macos_poll_input_events for events to work (was a wild guess).
  • Made lots of silly mistakes along the way (likely still a lot).

Hope it helps a bit!

hb3p8 avatar Oct 21 '24 19:10 hb3p8

Just linking this here as reminder in case we run into a similar issue with the new code (see comment at the bottom):

https://github.com/gfx-rs/gfx/issues/2460#issue-377659238

floooh avatar Oct 29 '24 10:10 floooh

Didn't noticed anything like this yet. Though I had to add manual sync with wgpuQueueOnSubmittedWorkDone and

  while (!IsFrameReady)
  {
    usleep(1000);
    wgpuInstanceProcessEvents ((WGPUInstance) sapp_wgpu_get_instance());
  }

Otherwise it would accumulate a multiple frames worth of work before finally blocking and waiting for it to be done. Strangely on Windows it was not necessary.

hb3p8 avatar Oct 30 '24 07:10 hb3p8

Hmm, that looks very hacky :D

But now that you say it, I've seen Dawn queuing up to 4 (or was it even 8?) frames. I noticed this when building my own 'buffer conveyor belt' in early sokol-gfx WebGPU backends (that conveyor belt got very long with 4 or 8 buffers in flight).

In the web browser this extreme frame latency doesn't seem to exists...

(this was also on macOS btw, I didn't try to get the native wgpu samples in sokol-samples run anywhere else yet).

floooh avatar Oct 30 '24 09:10 floooh

Closing this via https://github.com/floooh/sokol/pull/1326

floooh avatar Sep 08 '25 16:09 floooh