H-uru / Plasma

Cyan Worlds's Plasma game engine
http://h-uru.github.io/Plasma/
GNU General Public License v3.0
202 stars 80 forks source link

Try moving Metal Layer handling to the pipeline #1554

Open dpogue opened 5 months ago

dpogue commented 5 months ago

The goal here is to make the pipeline implementation responsible for constructing the renderer layer, so that everything related to Metal can be handled by the Metal pipeline and (eventually) everything related to GL can be handled by the GL pipeline. The client just has a layer as part of its view and doesn't need to care what renderer is being used.

colincornaby commented 5 months ago

I'll add my misgivings here that I've said elsewhere - but also admit what is proposed might be the best way.

CAMetalLayer is not part of Metal - it's part of the window server API. Which is why I originally bumped it into the client. The client has a 1:1 relationship with the window server. If we wanted to support a new type of window server we'd write a new client.

Apple's window servers have all agreed on a common layer for Metal so far. So that's at least good. But they have not agreed on a common OpenGL layer (which may also be due to their OpenGL and OpenGL ES vendor specific APIs being vastly different.) So we're starting to push more window server specific details into the pipeline, which is kind of meh.

For both Metal and OpenGL on Apple platforms - there are higher level abstractions such as MLKView and NSOpenGLView. NSOpenGLView has fallen out of favor, but MTKView is still widely used and wouldn't be compatible with this change. MTKView wants to supply its own layer. However - I don't have any plans to run Plasma under MTKView on any platform.

Another misgiving on iOS it might be preferred that the view create it's layer directly via layerClass, which this would prevent. https://developer.apple.com/documentation/uikit/uiview/1622626-layerclass?language=objc

But my understanding is all these issues are shared by the GL pipeline as well in a much larger way. GL has to communicate with multiple window servers from multiple vendors to jumpstart a GL viewport and context.

I guess one question I would have is: At least for GL - the GL layer will only work on macOS. Is there a disadvantage to leaving the layer type selection within the macOS client?

dpogue commented 5 months ago

It's mostly a separation of concerns thing: the client shouldn't need to care what renderer is being used and handle special cases for each renderer.

Ideally everything related to a given renderer should be implemented in its pipeline implementation, and that seems to work fine everywhere except macOS where they want different UI things used for different renderer types :(

colincornaby commented 5 months ago

I'm going to put in some more time on this review this weekend. Still thinking it over. But I need to put in some work to get some more concrete thoughts on this.

I think maybe one thing I was thinking before is that PLSView would be the glue code that matched the renderer to a layer. The view is macOS specific, but we're already in a decent amount of macOS specificity. Layers aren't technically part of SwiftUI, so it provided some level of abstraction and swappability for whenever Apple gets around to replacing layers. (For now, Metal and OpenGL still require layers to operate on macOS.)

I know I've run into issues with this approach on macOS, and you may be as well. Metal needs to talk to the layer to set the framebuffer size for resolution switches, and it also needs to make a request of the layer to swap framebuffers and get a new back buffer. I used to try to abstract that more to with interfaces back to the client - but recently I think I've been allowing the pipeline to talk directly to the layer.

I don't know what you're thinking with OpenGL - but there are probably similar issues. OpenGL also comes with the complication that context creation is managed by the layer as well. I think macOS takes a reasonable position of setting the current context within a callback. OpenGL doesn't have a cross platform context type built in so it's reasonable for macOS to abstract that away. Trying to work with contexts directly will introduce a whole bunch of platform specific code in the renderer. However - not all window managers agree on that. Some window managers encourage direct context manipulation.

If it's helpful in general or here - it may be beneficial to not manage contexts within the GL renderer. I think the context problem is kind of similar to this problem. Contexts are platform specific and will introduce platform code into the renderer - and the client itself is already a pretty good heap of platform code. Multiple contexts also shouldn't be needed - we should be ok with the system provided context. Multiple contexts are only needed for rendering in multiple threads at once. In theory - things like shadow buffers and other offscreen buffers could be rendered in a multithreaded manner. But Plasma has been pretty serial so far.

I'll think about it more. I'm still stuck on PLSView being meant to solve this, but PLSView not necessarily solving it in practice.