Getting started with Metal-cpp

Metal-cpp is a low-overhead C++ interface for Metal that helps developers add Metal functionality to graphics apps, games, and game engines that are written in C++.

Highlights

  • Drop in C++ alternative interface to the Metal Objective-C headers.
  • Direct mapping of all Metal Objective-C classes, constants and enums to C++ in the MTL C++ namespace.
  • No measurable overhead compared to calling Metal Objective-C headers, due to inlining of C++ function calls.
  • No usage of wrapper containers that require additional allocations.
  • Identical header files and function/constant/enum availability for iOS, iPadOS, macOS and tvOS.
  • Backwards compatibility: All bool MTL::Device::supports...() functions check if their required selectors exist and automatically return false if not.
  • String (ErrorDomain) constants are weak linked and automatically set to nullptr if not available.

Installation instructions

Step 1. Prepare your Mac

  • Open Xcode on your Mac. Xcode 9.3 or later includes C++17, which is the minimum required by Metal-cpp because of the use of constexpr in NS::Object.
  • Download and extract the contents of the follow zip file.

    metal-cpp_macOS12_iOS15.zip

Step 2. Add the metal-cpp folder to your build system’s header search path

  • In Xcode
    • Click on the Project Navigator
    • Click the Project
    • Click “Build Settings”
    • Search for “Header Search Paths”
    • Add the path to the extracted folder, metal-cpp/ Screenshot of path being entered in Xcode
    • Search for “C++ Language Dialect” and make sure it is set to C++17 or higher: Screenshot of highlighted setting in Xcode
    • Finally, make sure to add the Foundation, QuartzCore, and Metal frameworks to the list of frameworks to be linked under the Build Phases tab: Screenshot of highlighted library in Xcode

Step 3. Generate the implementation

  • metal-cpp is a header-only library. To generate the implementation, in one of your .cpp files add the following code:
    #define NS_PRIVATE_IMPLEMENTATION
    #define CA_PRIVATE_IMPLEMENTATION
    #define MTL_PRIVATE_IMPLEMENTATION
    #include <Foundation/Foundation.hpp>
    #include <Metal/Metal.hpp>
    #include <QuartzCore/QuartzCore.hpp>
  • Note: it is also possible to include the metal-cpp headers with quote marks.

Step 4. Use metal-cpp

  • From any files that need to reference metal-cpp objects or types, simply include the headers to make the symbols available.
    #include <Foundation/Foundation.hpp>
    #include <Metal/Metal.hpp>
    #include <QuartzCore/QuartzCore.hpp>
  • Important: do not define the NS, MTL or CA _PRIVATE_IMPLEMENTATION macros more than once.

Metal-cpp single header alternative

For convenience, you can alternatively use metal-cpp as a single-header include in your project.

After you have extracted the zip file contents, run the following command from the terminal to generate a single include header:

./SingleHeader/MakeSingleHeader.py Foundation/Foundation.hpp QuartzCore/QuartzCore.hpp Metal/Metal.hpp

Once completed, the command will have generated a single file ./SingleHeader/Metal.hpp that includes everything you need to use metal-cpp in your project.

Do remember to generate the implementation in one .cpp file:

#define NS_PRIVATE_IMPLEMENTATION
#define CA_PRIVATE_IMPLEMENTATION
#define MTL_PRIVATE_IMPLEMENTATION
#include <Metal/Metal.hpp>

Memory management considerations

Metal-cpp follows the object allocation policies of Cocoa and Cocoa Touch. Understanding those rules is especially important when using metal-cpp because C++ objects are not eligible for automatic reference counting (ARC). For more information, refer to the readme file in the metal-cpp download.