MoltenVK Runtime User Guide =========================== Copyright (c) 2014-2017 [The Brenwill Workshop Ltd.](http://www.brenwill.com) *This document is written in [Markdown](http://en.wikipedia.org/wiki/Markdown) format. For best results, use a Markdown reader.* Table of Contents ----------------- - [About This Document](#about_this) - [About **MoltenVK**](#about_moltenvk) - [Running the **MoltenVK** Demo Applications](#demos) - [Installing **MoltenVK** in Your *Vulkan* Application](#install) - [Install as Static Library Framework](#install_static_lib) - [Install as Dynamic Library](#install_dynamic_lib) - [Interacting with the **MoltenVK** Runtime](#interaction) - [MoltenVK Extension](#moltenvk_extension) - [*Metal Shading Language* Shaders](#shaders) - [MoltenVKShaderConverter Shader Converter Tool](#shader_converter_tool) - [Troubleshooting Shader Conversion](#spv_vs_msl) - [Performance Considerations](#performance) - [Shader Loading Time](#shader_load_time) - [Xcode Configuration](#xcode_config) - [Metal System Trace Tool](#trace_tool) - [Known **MoltenVK** Limitations](#limitations) - [Third-Party Credits](#credits) About This Document ------------------- This document describes how to integrate the **MoltenVK** runtime distribution package into a game or application, once **MoltenVK** has been built into a framework or library for *iOS* or *macOS*. To learn how to use the **MoltenVK** open-source repository to build a **MoltenVK** runtime distribution package, see the main [**README**](../README.md) document in the `MoltenVK` repository. About **MoltenVK** ------------------ **MoltenVK** is an implementation of the [*Vulkan*](https://www.khronos.org/vulkan) graphics and compute API, that runs on Apple's [*Metal*](https://developer.apple.com/metal) graphics and compute framework on both *iOS* and *macOS*. **MoltenVK** allows you to use the *Vulkan* graphics and compute API to develop modern, cross-platform, high-performance graphical games and applications, and to run them across many platforms, including both *iOS* and *macOS*. *Metal* uses a different shading language, the *Metal Shading Language (MSL)*, than *Vulkan*, which uses *SPIR-V*. However, fear not, as **MoltenVK** will automatically convert your *SPIR-V* shaders to their *MSL* equivalents. This can be performed transparently at run time, using the **Runtime Shader Conversion** feature of **MoltenVK**, or at development time using the [**MoltenVKShaderConverter**](#shader_converter_tool) tool provided with this **MoltenVK** distribution package. Running the **MoltenVK** Demo Applications ------------------------------------------ You can explore how **MoltenVK** provides *Vulkan* support on *iOS* and *macOS* by investigating and running the demo applications that are supported with this **MoltenVK** distribution package. The **MoltenVK** demo apps are located in the `Demos` folder within the **MoltenVK** distribution package. Each demo app is available as an *Xcode* project. To review and run many of the available demo apps, open the `Demos/Demos.xcworkspace` workspace in *Xcode*. Please read the [Demos/README_MoltenVK_Demos.md](Demos/README_MoltenVK_Demos.md) document for a description of each demo app, and instructions on downloading and running the demo apps. Many of the **MoltenVK** demos make use of third-party demo examples, which must be downloaded from an external repository. Several of the demo apps allow you to explore a variety of *Vulkan* features by modifying *Xcode* build settings. All of this is explained in the [README_MoltenVK_Demos.md](Demos/README_MoltenVK_Demos.md) document. Installing **MoltenVK** in Your *Vulkan* Application ---------------------------------------------------- >***Note:*** **MoltenVK** can be run on *iOS 9* and *macOS 11.0* devices, but it does reference advanced OS frameworks during building. *Xcode 9* or above is required to build and link **MoltenVK** projects. ###Install as Static Library Framework Installation of **MoltenVK** is straightforward and easy! For most applications, you can install **MoltenVK** as a *static library framework* that will be embedded directly in your application executable, or a component library within your application. This is simple and straightforward, and is the recommended installation approach for all applications. To add **MoltenVK** as a *static library framework* to your existing *Vulkan* application, follow the steps in this section. If you're new to **MoltenVK**, it is recommended that you start with a smaller project to help you understand the transition, and to reduce the possibility of needing to make modifications to your [shaders](#shaders) to ensure their compatibility with the *Metal* environment. 1. Open your application in *Xcode* and select your application's target in the *Project Navigator* panel. 2. Open the *Build Settings* tab, and in the **Framework Search Paths** (aka `FRAMEWORK_SEARCH_PATHS`) setting: - If building for *iOS*, add an entry that points to the `MoltenVK/iOS` folder, found in the **MoltenVK** distribution package. - If building for *macOS*, add an entry that points to the `MoltenVK/macOS` folder, found in the **MoltenVK** distribution package. 3. On the *Build Phases* tab, open the *Link Binary With Libraries* list. 1. Drag the `MoltenVK/iOS/MoltenVK.framework` or `MoltenVK/macOS/MoltenVK.framework` folder, found in the **MoltenVK** distribution package, to the *Link Binary With Libraries* list. 2. Click the **+** button, and (selecting from the list of system libraries) add `libc++.tbd`. 3. If you do not have the **Link Frameworks Automatically** (aka `CLANG_MODULES_AUTOLINK`) and **Enable Modules (C and Objective-C** (aka `CLANG_ENABLE_MODULES`) settings enabled, click the **+** button, and (selecting from the list of system frameworks) add `Metal.framework`, `IOSurface.framework`, and `QuartzCore.framework`. 4. When a *Metal* app is running from *Xcode*, the default ***Scheme*** settings reduce performance. To improve performance and gain the benefits of *Metal*, perform the following in *Xcode*: 1. Open the ***Scheme Editor*** for building your main application. You can do this by selecting ***Edit Scheme...*** from the ***Scheme*** drop-down menu, or select ***Product -> Scheme -> Edit Scheme...*** from the main menu. 2. On the ***Info*** tab, set the ***Build Configuration*** to ***Release***, and disable the ***Debug executable*** check-box. 3. On the ***Options*** tab, disable both the ***Metal API Validation*** and ***GPU Frame Capture*** options. For optimal performance, you may also consider disabling the other simulation and debugging options on this tab. For further information, see the [Xcode Scheme Settings and Performance](https://developer.apple.com/library/ios/documentation/Miscellaneous/Conceptual/MetalProgrammingGuide/Dev-Technique/Dev-Technique.html#//apple_ref/doc/uid/TP40014221-CH8-SW3) section of Apple's *Metal Programming Guide* documentation. ###Install as Dynamic Library For some applications, you may prefer to install **MoltenVK** as a dynamic library. This is only recommended for developers who are used to working with dynamic libraries, and even then, the preferred approach is to link the **MoltenVK** [*static library framework*](#install_static_lib) into a dynamic library of your own creation, in order to give you the most flexibility for organizing your dynamic libraries. In order to install **MoltenVK** as its own dynamic library in your application, follow these instructions: 1. Open your application in *Xcode* and select your application's target in the *Project Navigator* panel. 2. On the *Build Settings* tab: 1. In the **Header Search Paths** (aka `HEADER_SEARCH_PATHS`) setting, add an entry that points to the `MoltenVK/include` folder, found in the **MoltenVK** distribution package. 2. In the **Library Search Paths** (aka `HEADER_SEARCH_PATHS`) setting, add an entry that points to either the `MoltenVK/iOS` or `MoltenVK/macOS` folder, found in the **MoltenVK** distribution package. 3. In the **Runpath Search Paths** (aka `LD_RUNPATH_SEARCH_PATHS`) setting, add a path that matches the library destination you established in **Step 2** above. If the dynamic library is to be embedded within your application, you would typically set this value to either `@executable_path` or `@loader_path`. The `libMoltenVK.dylib` library is internally configured to be located at `@rpath/libMoltenVK.dylib`. 3. On the *Build Phases* tab, open the *Link Binary With Libraries* list. 1. Drag the `MoltenVK/iOS/libMoltenVK.dylib` or `MoltenVK/macOS/libMoltenVK.dylib` file, found in the **MoltenVK** distribution package, to the *Link Binary With Libraries* list. 2. Click the **+** button, and (selecting from the list of system libraries) add `libc++.tbd`. 3. If you do not have the **Link Frameworks Automatically** (aka `CLANG_MODULES_AUTOLINK`) and **Enable Modules (C and Objective-C** (aka `CLANG_ENABLE_MODULES`) settings enabled, click the **+** button, and (selecting from the list of system frameworks) add `Metal.framework`, `IOSurface.framework`, and `QuartzCore.framework`. 4. Arrange to install the `libMoltenVK.dylib` file in your application environment: - To copy the `libMoltenVK.dylib` file into your application or component library: 1. On the *Build Phases* tab, add a new *Copy Files* build phase. 2. Set the *Destination* into which you want to place the `libMoltenVK.dylib` file. Typically this will be *Executables*. 3. Drag the `MoltenVK/iOS/libMoltenVK.dylib` or `MoltenVK/macOS/libMoltenVK.dylib` file to the *Copy Files* list in this new build phase. - Alternately, you may create your own installation mechanism to install the `MoltenVK/iOS/libMoltenVK.dylib` or `MoltenVK/macOS/libMoltenVK.dylib` file into a standard *iOS* or *macOS* system library folder on the user's device. The `Cube-iOS` and `Cube-macOS` **MoltenVK** demo apps, found in the `Demos.xcworkspace`, located in the `Demos` folder within the **MoltenVK** distribution package, are simple examples of installing *MoltenVK* as a dynamic library embedded within an *iOS* or *macOS* application, respectively. Interacting with the **MoltenVK** Runtime ----------------------------------------- You programmatically configure and interact with the **MoltenVK** runtime through function calls, enumeration values, and capabilities, in exactly the same way you do with other *Vulkan* implementations. The `MoltenVK.framework` contains several header files that define access to *Vulkan* and **MoltenVK** function calls. In your application code, you access *Vulkan* features through the API defined in the standard `vulkan.h` header file. This file is included in the **MoltenVK** framework, and can be included in your source code files as follows: #include In addition to the core *Vulkan* API, **MoltenVK** also supports the following *Vulkan* extensions: - `VK_MVK_moltenvk` - `VK_KHR_swapchain` - `VK_KHR_surface` - `VK_MVK_ios_surface` (iOS) - `VK_MVK_macos_surface` (macOS) - `VK_AMD_negative_viewport_height` - `VK_IMG_format_pvrtc` (iOS) In order to visibly display your content on *iOS* or *macOS*, you must enable the `VK_MVK_ios_surface` or `VK_MVK_macos_surface` extension, respectively, and use the functions defined for that extension to create a *Vulkan* rendering surface. You can enable each of these extensions by defining the `VK_USE_PLATFORM_IOS_MVK` or `VK_USE_PLATFORM_MACOS_MVK` guard macro in your compiler build settings. See the description of the `mvk_vulkan.h` file below for a convenient way to enable these extensions automatically. The *Vulkan* API, including the `VK_MVK_ios_surface` and `VK_MVK_macos_surface` surface extensions, and other *Vulkan* extensions supported by **MoltenVK** (except `VK_MVK_moltenvk`), is described in the [*Vulkan 1.0 Spec with MoltenVK Extensions*](Vulkan_1.0_Spec_with_MoltenVK_Extensions.html) document found in the `MoltenVK/Vulkan` folder of the **MoltenVK** distribution. ###MoltenVK Extension The `VK_MVK_moltenvk` *Vulkan* extension provides functionality beyond the standard *Vulkan* API, to support configuration options, license registration, and behaviour that is specific to the **MoltenVK** implementation of *Vulkan*. You can access this functionality by including the `vk_mvk_moltenvk.h` header file in your code. The `vk_mvk_moltenvk.h` file also includes the API documentation for this `VK_MVK_moltenvk` extension. The following API header files are included in the **MoltenVK** package, each of which can be included in your application source code as follows: #include where `HEADER_FILE` is one of the following: - `vk_mvk_moltenvk.h` - Contains declarations and documenation for the functions, structures, and enumerations that define the behaviour of the `VK_MVK_moltenvk` *Vulkan* extension. - `mvk_vulkan.h` - This is a convenience header file that loads the `vulkan.h` header file with the appropriate **MoltenVK** *Vulkan* platform surface extension automatically enabled for *iOS* or *macOS*. Use this header file in place of the `vulkan.h` header file, where access to a **MoltenVK** platform surface extension is required. - When building for *iOS*, the `mvk_vulkan.h` header file automatically enables the `VK_USE_PLATFORM_IOS_MVK` build setting and `VK_MVK_ios_surface` *Vulkan* extension. - When building for *macOS*, the `mvk_vulkan.h` header file automatically enables the `VK_USE_PLATFORM_MACOS_MVK` build setting and `VK_MVK_macos_surface` *Vulkan* extension. - `mvk_datatypes.h` - Contains helpful functions for converting between *Vulkan* and *Metal* data types. You do not need to use this functionality to use **MoltenVK**, as **MoltenVK** converts between *Vulkan* and *Metal* datatypes automatically (using the functions declared in this header). These functions are exposed in this header for your own purposes such as interacting with *Metal* directly, or simply logging data values. *Metal Shading Language* Shaders -------------------------------- *Metal* uses a different shader language than *Vulkan*. *Vulkan* uses the new *SPIR-V Shading Language (SPIR-V)*, whereas *Metal* uses the *Metal Shading Language (MSL)*. **MoltenVK** provides several options for creating and running *MSL* versions of your existing *SPIR-V* shaders. The following options are presented in order of increasing sophistication and difficulty: - You can use the automatic **Runtime Shader Conversion** feature of **MoltenVK** to automatically and transparently convert your *SPIR-V* shaders to *MSL* at runtime, by simply loading your *SPIR-V* shaders as you always have, using the standard *Vulkan* `vkCreateShaderModule()` function. **MoltenVK** will automatically convert the *SPIR-V* code to *MSL* at runtime. - You can use the standard *Vulkan* `vkCreateShaderModule()` function to provide your own *MSL* shader code. To do so, set the value of the *magic number* element of the *SPIR-V* stream to one of the values in the `MVKMSLMagicNumber` enumeration found in the `vk_mvk_moltenvk.h` header file. The *magic number* element of the *SPIR-V* stream is the first element of the stream, and by setting the value of this element to either `kMVKMagicNumberMSLSourceCode` or `kMVKMagicNumberMSLCompiledCode`, on *SPIR-V* code that you submit to the `vkCreateShaderModule()` function, you are indicating that the remainder of the *SPIR-V* stream contains either *MSL* source code, or *MSL* compiled code, respectively. You can use the `MoltenVKShaderConverter` command-line tool found in this **MoltenVK** distribution package to convert your *SPIR-V* shaders to *MSL* source code, offline at development time, in order to create the appropriate *MSL* code to load at runtime. The [section below](#shaders) discusses how to use this tool in more detail. You can mix and match these options in your application. For example, a convenient approach is to use **Runtime Shader Conversion** for most *SPIR-V* shaders, and provide pre-converted *MSL* shader source code for the odd *SPIR-V* shader that proves problematic for runtime conversion. ###MoltenVKShaderConverter Shader Converter Tool The **MoltenVK** distribution package includes the `MoltenVKShaderConverter` command line tool, which allows you to convert your *SPIR-V* shader source code to *MSL* at development time, and then supply the *MSL* code to **MoltenVK** using one of the methods described in the [*Metal Shading Language* Shaders](#shaders) section above. The `MoltenVKShaderConverter` tool uses the same conversion technology as the **Runtime Shader Conversion** feature of **MoltenVK**. The `MoltenVKShaderConverter` tool has a number of options available from the command line: - The tool can be used to convert a single *SPIR-V* file to *MSL*, or an entire directory tree of *SPIR-V* files to *MSL*. - The tool can be used to convert a single *OpenGL GLSL* file, or an entire directory tree of *GLSL* files to either *SPIR-V* or *MSL*. To see a complete list of options, run the `MoltenVKShaderConverter` tool from the command line with no arguments. ###Troubleshooting Shader Conversion --------------------------------- The shader converter technology in **MoltenVK** is quite robust, and most *SPIR-V* shaders can be converted to *MSL* without any problems. In the case where a conversion issue arises, you can address the issue as follows: - Errors encountered during **Runtime Shader Conversion** are logged to the console. - To help understand conversion issues during **Runtime Shader Conversion**, you can enable the logging of the *SPIR-V* and *MSL* shader source code during conversion as follows: #include ... MVKDeviceConfiguration mvkConfig; vkGetMoltenVKDeviceConfigurationMVK(vkDevice, &mvkConfig); mvkConfig.debugMode = true; vkSetMoltenVKDeviceConfigurationMVK(vkDevice, &mvkConfig); Performing these steps will enable debug mode in **MoltenVK**, which includes shader conversion logging, and causes both the incoming *SPIR-V* code and the converted *MSL* source code to be logged to the console (in human-readable form). This allows you to manually verify the conversions, and can help you diagnose issues that might occur during shader conversion. - For minor issues, you may be able to adjust your *SPIR-V* code so that it behaves the same under *Vulkan*, but is easier to automatically convert to *MSL*. - For more significant issues, you can use the `MoltenVKShaderConverter` tool to convert the shaders at development time, adjust the *MSL* code manually so that it compiles correctly, and use the *MSL* shader code instead of the *SPIR-V* code, using the techniques described in the [*Metal Shading Language* Shaders](#shaders) section above. - You are also encouraged to report issues with shader conversion to the [*SPIRV-Cross*](https://github.com/KhronosGroup/SPIRV-Cross/issues) project. **MoltenVK** and **MoltenVKShaderConverter** make use of *SPIRV-Cross* to convert *SPIR-V* shaders to *MSL* shaders. Performance Considerations -------------------------- This section discusses various options for improving performance when using **MoltenVK**. ###Shader Loading Time *Metal* supports pre-compiled shaders, which can improve shader loading and set-up performance, allowing you to reduce your scene loading time. See the [*Metal Shading Language* Shaders](#shaders) and [MoltenVKShaderConverter Shader Converter Tool](#shader_converter_tool) sections above for more information about how to use the `MoltenVKShaderConverter` tool to create and load pre-compiled *Metal* shaders into **MoltenVK**. ###Xcode Configuration When a *Metal* app is running from *Xcode*, the default ***Scheme*** settings reduce performance. Be sure to follow the instructions for configuring your application's ***Scheme*** within *Xcode*, found in the in the [installation](#install) section above. ###Metal System Trace Tool To help you get the best performance from your graphics app, the *Xcode Instruments* profiling tool includes the *Metal System Trace* template. This template can be used to provide detailed tracing of the CPU and GPU behaviour of your application, allowing you unprecedented performance measurement and tuning capabilities for apps using *Metal*. Known **MoltenVK** Limitations ----------------------------- This section documents the known limitations in this version of **MoltenVK**. - **MoltenVK** is a Layer-0 driver implementation of *Vulkan*, and currently does not support the loading of higher level *Vulkan Layers*. The following *Vulkan* features have not been implemented in this version of **MoltenVK**: - Tessellation and Geometry shader stages. - Events: - vkCreateEvent() - vkDestroyEvent() - vkGetEventStatus() - vkSetEvent() - vkResetEvent() - vkCmdSetEvent() - vkCmdResetEvent() - vkCmdWaitEvents() - Application-controlled memory allocations: - VkAllocationCallbacks are ignored - Sparse memory: - vkGetImageSparseMemoryRequirements() - vkGetPhysicalDeviceSparseImageFormatProperties() - vkQueueBindSparse() - Pipeline statistics query pool: - vkCreateQueryPool(VK_QUERY_TYPE_PIPELINE_STATISTICS) - VkImageViewCreateInfo::VkComponentMapping supports only the following per-texture swizzles: - VK_FORMAT_R8_UNORM: VkComponentMapping.r = VK_COMPONENT_SWIZZLE_R - VK_FORMAT_R8G8B8A8_UNORM <-> VK_FORMAT_B8G8R8A8_UNORM - VK_FORMAT_R8G8B8A8_SRGB <-> VK_FORMAT_B8G8R8A8_SRGB Third-Party Credits ------------------- **MoltenVK** uses technology from the following open-source frameworks: - [*Vulkan-Hpp*](https://github.com/KhronosGroup/Vulkan-Hpp) - [*Vulkan-Docs*](https://github.com/KhronosGroup/Vulkan-Docs) - [*tinyxml2*](https://github.com/leethomason/tinyxml2) **MoltenVKShaderConverter** uses technology from the following open-source frameworks: - [*SPIRV-Cross*](https://github.com/KhronosGroup/SPIRV-Cross) - [*SPIRV-Tools*](https://github.com/KhronosGroup/SPIRV-Tools) - [*glslang*](https://github.com/KhronosGroup/glslang)