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
.