KhronosGroup / MoltenVK

MoltenVK is a Vulkan Portability implementation. It layers a subset of the high-performance, industry-standard Vulkan graphics and compute API over Apple's Metal graphics framework, enabling Vulkan applications to run on macOS, iOS and tvOS.
Apache License 2.0
4.84k stars 429 forks source link

MoltenVK

Copyright (c) 2015-2024 The Brenwill Workshop Ltd.

Build Status

Table of Contents

Introduction to MoltenVK

MoltenVK is a layered implementation of Vulkan 1.2 graphics and compute functionality, that is built on Apple's Metal graphics and compute framework on macOS, iOS, tvOS, and visionOS. MoltenVK allows you to use Vulkan graphics and compute functionality to develop modern, cross-platform, high-performance graphical games and applications, and to run them across many platforms, including macOS, iOS, tvOS, visionOS, Simulators, and Mac Catalyst on macOS 11.0+, and all Apple architectures, including Apple Silicon.

Metal uses a different shading language, the Metal Shading Language (MSL), than Vulkan, which uses SPIR-V. MoltenVK automatically converts your SPIR-V shaders to their MSL equivalents.

To provide Vulkan capability to the macOS, iOS, tvOS, and visionOS platforms, MoltenVK uses Apple's publicly available API's, including Metal. MoltenVK does not use any private or undocumented API calls or features, so your app will be compatible with all standard distribution channels, including Apple's App Store.

The MoltenVK runtime package contains two products:

Developing Vulkan Applications for macOS, iOS, tvOS, and visionOS

Using the Vulkan SDK

The recommended method for developing a Vulkan application for macOS is to use the Vulkan SDK.

The Vulkan SDK includes a MoltenVK runtime library for macOS. Vulkan is a layered architecture that allows applications to add additional functionality without modifying the application itself. The Validation Layers included in the Vulkan SDK are an essential debugging tool for application developers because they identify inappropriate use of the Vulkan API. If you are developing a Vulkan application for macOS, it is highly recommended that you use the Vulkan SDK and the MoltenVK library included in it. Refer to the Vulkan SDK Getting Started document for more info.

Because MoltenVK supports the VK_KHR_portability_subset extension, when using the Vulkan Loader from the Vulkan SDK to run MoltenVK on macOS, the Vulkan Loader will only include MoltenVK VkPhysicalDevices in the list returned by vkEnumeratePhysicalDevices() if the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR flag is enabled in vkCreateInstance(). See the description of the VK_KHR_portability_enumeration extension in the Vulkan specification for more information about the use of the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR flag.

Using MoltenVK Directly

If you are developing a Vulkan application for iOS, tvOS, or visionOS, or are developing a Vulkan application for macOS and want to use a different version or build of the MoltenVK runtime library than provided in the macOS Vulkan SDK, you can access a pre-built MoltenVK binary library from the MoltenVK repository, by selecting a repository commit from the list, and downloading the associated MoltenVK runtime library artifact.

Finally, if you want a customized build of MoltenVK, you can follow the instructions below to create a MoltenVK runtime library by fetching and building the MoltenVK source code.

To learn how to integrate the MoltenVK runtime library into a game or application, see the MoltenVK_Runtime_UserGuide.md document in the Docs directory.

Fetching MoltenVK Source Code

To fetch MoltenVK source code, clone this MoltenVK repository, and then run the fetchDependencies script to retrieve and build several external open-source libraries on which MoltenVK relies:

  1. Ensure you have cmake and python3 installed:

    brew install cmake
    brew install python3

    For faster dependency builds, you can also optionally install ninja:

    brew install ninja
  2. Clone the MoltenVK repository:

    git clone https://github.com/KhronosGroup/MoltenVK.git
  3. Retrieve and build the external libraries:

    cd MoltenVK
    ./fetchDependencies [platform...]

When running the fetchDependencies script, you must specify one or more platforms for which to build the external libraries. The platform choices include:

--all
--macos
--ios
--iossim
--maccat
--tvos
--tvossim

You can specify multiple of these selections. The result is a single XCFramework for each external dependency library, with each XCFramework containing binaries for each of the requested platforms.

The --all selection is the same as entering all of the other platform choices, and will result in a single XCFramework for each external dependency library, with each XCFramework containing binaries for all supported platforms and simulators.

Running fetchDependencies repeatedly with different platforms will accumulate targets in the XCFramework, if the --keep-cache option is used on each invocation.

For more information about the external open-source libraries used by MoltenVK, see the ExternalRevisions/README.md document.

Building MoltenVK

During building, MoltenVK references the latest Apple SDK frameworks. To access these frameworks, and to avoid build errors, be sure to use the latest publicly available version of Xcode.

Note: Xcode 14 introduced a new static linkage model that is not compatible with previous versions of Xcode. If you link to a MoltenVK.xcframework that was built with Xcode 14 or later, also use Xcode 14 or later to link it to your app or game.

If you need to use Xcode 13 or earlier to link MoltenVK.xcframework to your app or game, first build MoltenVK with Xcode 13 or earlier.

Or, if you want to use Xcode 14 or later to build MoltenVK, in order to be able to use the latest Metal capabilities, but need to use Xcode 13 or earlier to link MoltenVK.xcframework to your app or game, first add the value -fno-objc-msgsend-selector-stubs to the OTHER_CFLAGS Xcode build setting in the MoltenVK.xcodeproj and MoltenVKShaderConverter.xcodeproj Xcode projects, build MoltenVK with Xcode 14 or later, and then link MoltenVK.xcframework to your app or game using Xcode 13 or earlier.

Once built, the MoltenVK libraries can be run on macOS, iOS, tvOS, or visionOS devices that support Metal,or on the Xcode iOS Simulator, tvOS Simulator, or visionOS Simulator.

Building With Xcode

The MoltenVKPackaging.xcodeproj Xcode project contains targets and schemes to build and package the entire MoltenVK runtime distribution package, or to build individual MoltenVK or MoltenVKShaderConverter components.

To build a MoltenVK runtime distribution package, suitable for testing and integrating into an app, open MoltenVKPackaging.xcodeproj in Xcode, and use one of the following Xcode Schemes, depending on whether you want a Release or Debug configuration, and whether you want to build for all platforms, or just one platform (in Release configuration):

Each of theseMoltenVKPackaging.xcodeproj Xcode project Schemes puts the resulting packages in the Package directory, creating it if necessary. This directory contains separate Release and Debug directories, holding the most recent Release and Debug builds, respectively.

Note: Due to technical limitations in the dynamic library build tools, dynamic frameworks and libraries cannot be created for the tvOS Simulator, or MacCatalyst platforms. Static frameworks are created for these, and all other, platforms.

A separate Latest directory links to the most recent build, regardless of whether it was a Release or Debug build. Effectively, the Package/Latest directory points to whichever of the Package/Release or Package/Debug directories was most recently updated.

With this packaging structure, you can follow the instructions below to link your application to the MoltenVK libraries and frameworks in the Package/Latest directory, to provide the flexibility to test your app with either a Debug build, or a higher-performance Release build.

Building From the Command Line

If you prefer to build MoltenVK from the command line, or to include the activity in a larger build script, you can do so by executing a command similar to the following command within the MoltenVK repository folder, and identifying one of the Xcode Schemes from the list above. For example, the following command will build MoltenVK in the Debug configuration for macOS only:

xcodebuild build -quiet -project MoltenVKPackaging.xcodeproj -scheme "MoltenVK Package (macOS only)" -configuration "Debug"

Alternately, you can use the basic Makefile in the MoltenVK repository folder to build MoltenVK from the command line. The following make targets are provided:

make
make all
make macos
make ios
make iossim
make maccat
make tvos
make tvossim

make all-debug
make macos-debug
make ios-debug
make iossim-debug
make maccat-debug
make tvos-debug
make tvossim-debug

make clean
make install

The make targets all require that Xcode is installed on your system.

Note: Due to technical limitations within Xcode, a dynamic framework is not created for the MacCatalyst platform.

Building from the command line creates the same Package folder structure described above when building from within Xcode.

When building from the command line, you can set any of the build settings documented in the MoltenVK_Configuration_Parameters.md file, by passing them in the command line, as in the following examples:

make MVK_CONFIG_LOG_LEVEL=0

or make macos MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=1

...etc.

Hiding Vulkan API Symbols

You can optionally build MoltenVK with the Vulkan API static call symbols (vk*) hidden, to avoid library linking conflicts when statically bound to a Vulkan loader that also exports identical symbols.

To do so, when building MoltenVK, set the build setting MVK_HIDE_VULKAN_SYMBOLS=1. This build setting can be set in the MoltenVK.xcodeproj Xcode project, or it can be included in any of the make command-line build commands mentioned above.

With MVK_HIDE_VULKAN_SYMBOLS=1, the Vulkan vkGetInstanceProcAddr() call remains statically bound, to provide the application with the ability to retrieve the remaining Vulkan API calls as function pointers.

Accessing Metal Private API Calls

You can optionally build MoltenVK with access to private Metal API calls, also known as "Service Provider Interfaces" (SPIs). Doing so will allow MoltenVK to extend its functionality by using certain private Metal API calls, but it will also disqualify the app from being distributed via Apple App Stores.

To do so, when building MoltenVK, set the build setting MVK_USE_METAL_PRIVATE_API=1. This build setting can be set in the MoltenVK.xcodeproj Xcode project, or it can be included in any of the make command-line build commands mentioned above.

Functionality added with MVK_USE_METAL_PRIVATE_API enabled includes:

Install MoltenVK to Replace the Vulkan SDK libMoltenVK.dylib

To replace the version of the MoltenVK installed on macOS via the Vulkan SDK standard install process, perform the following steps:

  1. Build a macOS version of MoltenVK, as described above. The default config for command-line MoltenVK build has verbose logging info turned on. If you want MoltenVK to log like the original Vulkan SDK install, use this command when building MoltenVK:

    $ make macos MVK_CONFIG_LOG_LEVEL=1
  2. From a command line terminal, execute the following command:

    $ sudo make install

This will copy your latest macOS build of MoltenVK into /usr/local/lib/libMoltenVK.dylib, overwriting the file installed by the Vulkan SDK install process.

Running MoltenVK Demo Applications

Once you have compiled and built the MoltenVK runtime distribution package from this MoltenVK repository, as described in the Building MoltenVK section, you can explore how MoltenVK provides Vulkan support on macOS, iOS, and tvOS by investigating and running the demo application that is included in MoltenVK.

The MoltenVK Cube demo app is located in the Demos folder. The demo app is available as an Xcode project. To review and run the included demo app, open the Demos/Demos.xcworkspace workspace in Xcode.

Please read the Demos/README.md document for a description and instructions for running the included Cube demo app, and for external links to more sophisticated demo applications that can be run on MoltenVK.

Using MoltenVK in Your Application

Once you have compiled and built the MoltenVK runtime distribution package from this MoltenVK repository, as described in the Building MoltenVK section, follow the instructions in the Installation section of the Docs/MoltenVK_Runtime_UserGuide.md document in the Docs directory, to link the MoltenVK libraries and frameworks to your application.

The runtime distribution package in the Package/Latest directory is a stand-alone package, and you can copy the contents of that directory out of this MoltenVK repository into your own application building environment.

MoltenVK and Vulkan Compliance

MoltenVK is designed to be an implementation of a Vulkan 1.2 subset that runs on macOS, iOS, tvOS, and visionOS platforms by mapping Vulkan capability to native Metal capability.

The fundamental design and development goal of MoltenVK is to provide this capability in a way that is both maximally compliant with the Vulkan 1.2 specification, and maximally performant.

Such compliance and performance is inherently affected by the capability available through Metal, as the native graphics driver on macOS, iOS, tvOS, and visionOS platforms. Vulkan compliance may fall into one of the following categories:

The MoltenVK development team welcomes you to post Issues of non-compliance, and engage in discussions about how compliance can be improved, and non-compliant features can be implemented or worked around.

MoltenVK is a key component of the Khronos Vulkan Portability Initiative, whose intention is to provide specifications, resources, and tools to allow developers to understand and design their Vulkan apps for maximum cross-platform compatibility and portability, including on platforms, such as macOS, iOS, tvOS, and visionOS, where a native Vulkan driver is not available.

Getting Support

Contributing to MoltenVK Development

As a public open-source project, MoltenVK benefits from code contributions from a wide range of developers, and we encourage you to get involved and contribute code to this MoltenVK repository.

To contribute your code, submit a Pull Request to this repository. The first time you do this, you will be asked to agree to the MoltenVK Contributor License Agreement.

Licensing

MoltenVK is licensed under the Apache 2.0 license. All new source code files should include a copyright header at the top, containing your authorship copyright and the Apache 2.0 licensing stub. You may copy the text from an existing source code file as a template.

The Apache 2.0 license guarantees that code in the MoltenVK repository is free of Intellectual Property encumbrances. In submitting code to this repository, you are agreeing that the code is free of any Intellectual Property claims.

Vulkan Validation

Despite running on top of Metal, MoltenVK operates as a Vulkan core layer. As such, as per the error handling guidelines of the Vulkan specification, MoltenVK should not perform Vulkan validation. When adding functionality to MoltenVK, avoid adding unnecessary validation code.

Validation and error generation is appropriate within MoltenVK in cases where MoltenVK deviates from behavior defined by the Vulkan specification. This most commonly occurs when required behavior cannot be mapped to functionality available within Metal. In that situation, it is important to provide feedback to the application developer to that effect, by performing the necessary validation, and reporting an error.

Currently, there is some excess Vulkan validation and error reporting code within MoltenVK, added before this guideline was introduced. You are encouraged to remove such code if you encounter it while performing other MoltenVK development. Do not remove validation and error reporting code that is covering a deviation in behavior from the Vulkan specification.

Memory Management

Metal, and other Objective-C objects in Apple's SDK frameworks, use reference counting for memory management. As a contributor to MoltenVK, when instantiating Objective-C objects, it is important that you do not rely on the app providing autorelease pools to do memory management for you. Because many Vulkan games and apps may be ported from other platforms, they will often not automatically include autorelease pools in their threading models.

As a contributor to MoltenVK, avoid the use of the Metal autorelease method, or any object Metal creation methods that imply internal use of autorelease, (eg- [NSString stringWithFormat: ], etc). Instead, favor object creation methods that return a retained object (eg- [[NSString alloc] initWithFormat: ], etc), and manually track and release those objects. If you need to use autoreleased objects, wrap your code in an @autoreleasepool {...} block.

Code Formatting

When contributing code, please honour the code formatting style found in existing MoltenVK source code. In future, this will formally be enforced using clang-format.