Skip to the content.
Posts

macOS and Vulkan isn’t a place that I go to often, but sometimes it’s fun to take a walk in those parts and see how things are.

After installing the SDK, I ran vulkaninfo to make sure that at least that was working on my system - and it did. Then I proceeded to write some C++ code to create a VkInstance object and immediately, I got myself into trouble.

I use CMake for pretty much everything and for the most part it works out. On macOS, there are certain things I get to relearn everytime since I don’t code on macOS that often. One of these things is using Framework (macOS/Frameworks/vulkan.framework) or using a dylib shared library (macOS/lib/libvulkan.dylib). I opted for the dylib path since I was lazy and didn’t want to setup the framework stuff. And down this path, I learned a few things along the way.

VK_KHR_portability_enumeration

The last time I played around with Vulkan on macOS, this extension wasn’t required. I didn’t know this before starting this time, so I got VK_ERROR_INCOMPATIBLE_DRIVER when trying to create a VkInstance object. Thanks to Nathan Reed’s answer on Stack Overflow, I quicky sorted myself out. TL;DR; Starting with Vulkan SDK 1.3.216, VK_KHR_portability_enumeration and VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR is a required extension for VkInstance creation:

std::vector<const char*> enabledExtensionNames = {
    VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
};

VkInstanceCreateInfo createInfo    = {};
createInfo.flags                   = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
createInfo.enabledExtensionCount   = static_cast<uint32_t>(enabledExtensionNames.size());
createInfo.ppEnabledExtensionNames = enabledExtensionNames.data();

GLFW: VK_EXT_metal_surface vs VK_MVK_macos_surface

GLFW is also another thing that I use for pretty much everything. But before I tell you what I learned, if you’re planning to use GLFW with anything other than OpenGL - that is GLFW with Direct3D 12, Metal, or Vulkan you must set the GLFW_CLIENT_API hint to GLFW_NO_API unless you want possible hours of debugging fun:

glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

So for some reason I had picked VK_MVK_macos_surface, I don’t remember why. I probably saw the VK_USE_PLATFORM_MACOS_MVK section in vulkan.h first and just went with it. Welp, as it turns out both VK_EXT_metal_surface and VK_MVK_macos_surface are present on my system and GLFW just picks VK_EXT_metal_surface first. This took me longer than I’d like to admit to figure out.

I had decided to use glfwCreateWindowSurface() to create the VkSurfaceKHR object to avoid having to get Objective-C or Object-C++ involved. In my tunnel vision, I also thought VK_MVK_macos_surface was the only surface extension for macOS. After seeing VK_ERROR_EXTENSION_NOT_PRESENT from glfwCreateWindowSurface(), I figured that: 1) I forgot to add the extension or 2) I possibly had the wrong extension.

Walking through the call stack for glfwCreateWindowSurface() helped me quickly realize that I had the wrong extension. At one point I wasn’t sure if it was possibly due to using the dylib instead of the framework. Turns out that wasn’t an issue.

install_vulkan.py

I haven’t tried using this script to install the SDK components in to the system directories. I suspect this script makes it possible/easier to use vulkan.framework.