Skip to content
Chris Birkhold edited this page Aug 29, 2018 · 4 revisions

OpenVRMetal is a collection of utility classes to make it easier to work with OpenVR + Metal on macOS. As of August 2018 Vive/SteamVR is the only officially supported combination of HMD/runtime for VR on macOS.

OpenVR as it relates to Metal

Metal Specifics

The Metal specific part of OpenVR is quite small:

  1. IVRCompositor::Submit accepts Texture_t descriptors of type:
    1. TextureType_IOSurface (macOS 11.13)
    2. TextureType_Metal (macOS 10.14+)
  2. IVRSystem::GetOutputDevice returns the Metal device representing the GPU the HMD is connected to.

Though however small the API surfaces may be there is a few details to be aware of. The following is not based on direct knowledge of the internal workings of SteamVR but rather on analysis, observations and experiments.

TextureType_IOSurface

  • The kIOSurfaceIsGlobal property must be set to true/yes on creation of the IOSurface. While kIOSurfaceIsGlobal was deprecated in favor of using IOSurfaceCreateMachPort or IOSurfaceCreateXPCObject, as of August 2018 SteamVR still uses good old shared memory to submit IOSurface-backed textures to the compositor so this property must be set for the compositor process to be able to access the surface.
  • The same two IOSurface backed Metal texture (one for each eye) must be used for all frames submitted to the compositor. If this is not done SteamVR appears to ignore all but the first submitted texture or present them at the wrong times. For instance submitting a triple-buffered texture appears to result in only index zero being displayed across three frames (effectively cutting the frame rate down to a third). Even though the same textures will be used every frame IVRCompositor::Submit must still be called once per frame for each eye. Of course if either distortion or color space conversion is left to the SteamVR runtime then the submitted textures could not be used for direct-to-display read-out anyways.
  • The two supported IOSurface pixel formats appear to be 'RGBA' (know as k32RGBAPixelFormat, kIO32RGBAPixelFormat or kCVPixelFormatType_32RGBA) and 'BGRA' (k32BGRAPixelFormat, kIO32BGRAPixelFormat, kCVPixelFormatType_32BGRA, ...). These map to MTLPixelFormatRGBA8Unorm, MTLPixelFormatRGBA8Unorm_sRGB, MTLPixelFormatRGBA8Uint and MTLPixelFormatBGRA8Unorm, MTLPixelFormatBGRA8Unorm_sRGB respectively.

TextureType_Metal

  • As of August 2018 (SteamVR mainline, macOS 10.14 Beta) support for this feature is incomplete.
  • Textures must be created using MTLDevice::newSharedTextureWithDescriptor. The Metal framework creates an IOSurface internally but does not set the public iosurface property as would be the case for a Metal texture created directly from an IOSurface using MTLDevice::newTextureWithDescriptor. For the curious the private iosurface property can still be read for analyzing the properties of the backing IOSurface.
  • Supports MTLTextureType2DArray.

Metal Related

There are a few generic OpenVR types that need to be converted for use with the Metal framework:

  1. Math Types (vectors, matrices, ...)
  2. Hidden Area Meshes
  3. Render Models
Clone this wiki locally