Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update VulkanHelper to support surface creation on macOS #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

taleks
Copy link

@taleks taleks commented Sep 23, 2022

Overview

This PR updates VulkanHelper class to support creation of surfaces on macOS and introduces SimpleCocoaWindow to work with NSWindow.

VulkanHelper changes:

  • adds methods to create Vulkan surface on macOS using both deprecated and newer Vulkan extensions;
  • alters Vulkan library loading to try MoltenVk first, then generic libvulkan;
  • slightly refactors CreateWindowSurface() method to split it into a set of platform specific methods and thus reduce complexity a bit.

SimpleCocoaWindow:

  • is macOS only, does not support CocoaTouch;
  • uses a basic Objective-C runtime interop layer to invoke methods on classes like NSView and NSWindow.

Testing

I've written this while trying to make Ryujinx workable on macOS after fixing JIT memory access issues on M1.

Unfortunately Ryujinx requires Vulkan extensions that are not implemented by MoltenVk. So logic is tested by running Ryujinx up to the moment where it checks extensions and throws error on failure to find VK_EXT_transform_feedback not implemented by MoltenVk. This means that initialisation logic in VulkanHelper itself works fine and devices enumeration, extensions enumeration, etc in Ryujinx have no issues.

There are two major parts in this commit:
* basic Objective-C runtime layer;
* `SimpleCocoaWindow` that makes use of it.

The former one relies on Objective-C runtime (`libobjc`) methods
to perform a few basic operations. The most important ones
are `objc_msgSend` bindings that differ in number
of input arguments and return value yet invoke the same function
exported by `libobjc`.

See more on runtime in Apple documentation:
https://developer.apple.com/documentation/objectivec/objective-c_runtime

`SimpleCocoaWindow` invokes `Cocoa` object methods to acquire
Metal layer and show/hide window. Note that it uses `AppKit` types
such as `NSWindow` or `NSView` and thus is macOS-specific. iOS devices
use `UIKit` (`Cocoa Touch`) and thus initialisation should be
done by sending messages to `UIView`.
Uses MoltenVk implementation of Vulkan API, see:
https://github.com/KhronosGroup/MoltenVK

Supports both deprecated `VK_MVK_macos_surface` and
actual `VK_EXT_metal_surface` extensions to create Vulkan surface.

Also slightly refactors helper to allow specification of multiple
dynamic libraries to probe.
@taleks taleks marked this pull request as ready for review September 23, 2022 06:34
@riperiperi
Copy link

riperiperi commented Sep 23, 2022

I think it's probably a better idea to pass an NSView as the "window" for this one. I've messed with this and GTK, and it seems that our approach for trying to pull an embedded window out of a DrawingArea doesn't work. What did work is creating an NSView, adding it as a child and positioning it manually to match the GTK component (recaluclates when component moves). I can imagine a similar approach working for Avalonia.

Were you able to get embedded window creation working on the GTK side?

As for general stuff, code comments are generally correctly capitalized and well punctuated, like // Example comment.

@taleks
Copy link
Author

taleks commented Sep 26, 2022

I think it's probably a better idea to pass an NSView as the "window" for this one

NSWindow is needed for Show()/Hide() implementation. I believe it is possible to get NSWindow through NSView.window (if NSView is attached to window) but seems like an extra hop. The change is small though, should be easy to implement.

Were you able to get embedded window creation working on the GTK side?

Can you elaborate on what do you mean by embedded window?
I've tested complete Vulkan initialisation with Silk, surface creation aside (for which I used SPB VulkanHelper) and rendering of triangle in main window of GTK#/Glade app plus showing/hiding it on key press event through SimpleCocoaWindow methods.

If you can reference a simple GTK# project that has embedded window you are talking about, I can test it later this week (the troublesome part of Vulkan initialisation boilerplate is already done, so it is just a matter of copy-pasting and passing window or view handle to verify code in PR).

As for general stuff, code comments are generally correctly capitalized and well punctuated, like // Example comment.

Sure, will fix it.

- Changes comments punctuation to the suggested.
- Allows to pass either `NSView` or `NSWindow` into
  SimpleCocoaWindow constructor.
@riperiperi
Copy link

Sorry for the unusually long delay, the example project would be Ryujinx.
image
The embedded window is the DrawingArea that the game is rendered into. Our strategy for doing that is getting a native representation of the widget's Window and creating the context with that, though when I tried this on macos it gave me the whole window rather than just the drawing area. When creating a metal context with that, it replaced all GTK elements, which wasn't great as it made it impossible to see the status bar and menus.

I don't really have a simpler example on hand.

@riperiperi
Copy link

Since 21b6f4b is a thing now...

It might still be a good idea to port use the more fleshed out ObjectiveC class in this PR rather than the rather simple MacOS one for interop.

Supporting generating the layer from a window could also be useful.

@taleks
Copy link
Author

taleks commented Oct 19, 2022

Sorry, a bit busy week. Will catch up with comments later.

I get your concern now. I am not sure that GTK widgets are mapped to per-widget NSView (as GTK layout/rendering is used instead and thus all drawing area, including menu, is the same view). Will check it.

@marysaka
Copy link
Owner

Sorry, a bit busy week. Will catch up with comments later.

I get your concern now. I am not sure that GTK widgets are mapped to per-widget NSView (as GTK layout/rendering is used instead and thus all drawing area, including menu, is the same view). Will check it.

I may have forgot about that PR and made some changes on 21b6f4b while working on my GBA emu 😅

Could you maybe rebase or maybe close and split the changes?

I think the surface creation split in the VulkanHelper class could be nice to have.

I still am not to sure with the design of SimpleMetalWindow I made, for now all CAMetalLayer creation need to be handled externally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants