-
Notifications
You must be signed in to change notification settings - Fork 0
Introduction
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. Therefore it is assumed in the following that OpenVR is implemented in terms of SteamVR.
Apple/Valve announced SteamVR/Vive support for macOS High Sierra at WWDC 2017 and again at WWDC 2018 with improved Metal support for macOS Mojave. Because of those advanced features, the platform specific Metal advantages over OpenGL, as well as Apple retiring OpenGL support without getting behind Vulkan, Metal is the choice for any new VR development for macOS. With that in mind let's take a look at the Metal specific and Metal related parts of the OpenVR API.
The Metal specific part of OpenVR is quite small:
-
IVRCompositor::Submit
acceptsTexture_t
descriptors of type:-
TextureType_IOSurface
(macOS 11.13) -
TextureType_Metal
(macOS 10.14+)
-
-
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.
- The
kIOSurfaceIsGlobal
property must be set to true/yes on creation of theIOSurface
. WhilekIOSurfaceIsGlobal
was deprecated in favor of usingIOSurfaceCreateMachPort
orIOSurfaceCreateXPCObject
, as of August 2018 SteamVR still uses good old shared memory to submitIOSurface
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 frameIVRCompositor::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 ask32RGBAPixelFormat
,kIO32RGBAPixelFormat
orkCVPixelFormatType_32RGBA
) and 'BGRA' (k32BGRAPixelFormat
,kIO32BGRAPixelFormat
,kCVPixelFormatType_32BGRA
, ...). These map toMTLPixelFormatRGBA8Unorm
,MTLPixelFormatRGBA8Unorm_sRGB
,MTLPixelFormatRGBA8Uint
andMTLPixelFormatBGRA8Unorm
,MTLPixelFormatBGRA8Unorm_sRGB
respectively.
- 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 anIOSurface
internally but does not set the publiciosurface
property as would be the case for a Metal texture created directly from anIOSurface
usingMTLDevice::newTextureWithDescriptor
. For the curious the privateiosurface
property can still be read for analyzing the properties of the backingIOSurface
. - Supports
MTLTextureType2DArray
.
There are a few generic OpenVR types that need to be converted for use with the Metal framework:
- Math Types (vectors, matrices, ...)
- Hidden Area Meshes
- Render Models