Developing with OpenXR and Monado
After installing the OpenXR SDK and Monado with the Getting Started Guide it is time to develop an OpenXR application.
The OpenXR SDK
On Archlinux, the OpenXR loader installs these files
- /usr/lib/libopenxr_loader.so*
- The library that applications use for linking to OpenXR. Usually with soname symlinks: libopenxr_loader.so, libopenxr_loader.so.1 and libopenxr_loader.so.1.0.11
- /usr/lib/cmake/openxr/*.cmake
- cmake files that enable cmake directives like
PKG_SEARCH_MODULE(OPENXR REQUIRED openxr)
- cmake files that enable cmake directives like
- /usr/lib/pkgconfig/openxr.pc
- pkg-config files that can be used by cmake with
FindPkgConfig
or non-cmake build systems. - Run
pkg-config --libs --cflags openxr
to see what it provides.
- pkg-config files that can be used by cmake with
Other distributions may use different paths like /usr/lib/x86_64-linux-gnu/...
.
The OpenXR headers
- /usr/include/openxr/openxr.h
- The main OpenXR API header.
- /usr/include/openxr/openxr_platform_defines.h
- Various platform defines used by the main OpenXR API header. Usually you don’t need to use it directly.
- /usr/include/openxr/openxr_platform.h
- The part of the OpenXR API that is platform specific.
- Before including this header, add defines for the parts you want to use, e.g.
#define XR_USE_PLATFORM_XLIB
#define XR_USE_GRAPHICS_API_OPENGL
- /usr/include/openxr/openxr_reflection.h
- Not necessary, but useful for iterating over OpenXR enums, or getting string representations of OpenXR enum values.
To start developing for OpenXR only those components are necessary. Similar to how Vulkan applications are developed by including Khronos’ Vulkan headers and linking to Khronos’ Vulkan loader, OpenXR applications include Khronos’ OpenXR headers and link to Khronos’ OpenXR loader. Just like compiling a Vulkan application does not require any Vulkan driver to be installed, compiling an OpenXR application does not require any OpenXR runtime to be installed.
Khronos has not released a reference implementation for OpenXR, so for actually running an OpenXR application some vendor’s OpenXR runtime (for example Monado) has to be installed.
Setting up the project
CMake
Here is a minimal cmake example to compile an example
executable that can include OpenXR headers and links to the OpenXR loader.
cmake_minimum_required(VERSION 3.0.0)
project(Example)
add_executable(example main.c)
find_package(OpenXR REQUIRED)
if(OpenXR_FOUND)
target_include_directories(example PRIVATE OpenXR::Headers)
target_link_libraries(example PRIVATE OpenXR::openxr_loader)
else()
MESSAGE(FATAL_ERROR "Please verify your OpenXR SDK installation")
endif()
As an alternative you can use OpenXR’s pkg-config file with CMake’s FindPkgConfig module.
cmake_minimum_required(VERSION 3.0.0)
project(Example)
add_executable(example main.c)
INCLUDE(FindPkgConfig)
PKG_SEARCH_MODULE(OpenXR REQUIRED openxr)
if(OpenXR_FOUND)
target_link_libraries(example PRIVATE ${OpenXR_LIBRARIES})
target_include_directories(example PRIVATE ${OpenXR_HEADERS})
else()
MESSAGE(FATAL_ERROR "Please verify your OpenXR SDK installation")
endif()
If you prefer using your own FindOpenXR.cmake file, the xrtraits utility has an example.
meson
Meson uses pkg-config by default for its dependency() mechanism.
project('Example', ['c'])
openxr_dep = dependency('openxr')
executable('example', ['main.c'], dependencies: [openxr_dep])
Application
With this project setup you can start including the <openxr/openx.h>
header and start calling OpenXR functions.
As a starting point, here is a minimal C example for starting an OpenGL application on Linux with the xlib graphics binding.
// openxr_platform.h does not include all its dependencies, we have to include some headers before it
#include <string.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
// before including openxr_platform.h we have to define which platform specific parts we want enabled
#define XR_USE_PLATFORM_XLIB
#define XR_USE_GRAPHICS_API_OPENGL
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>
int main()
{
char *extensions[] = { XR_KHR_OPENGL_ENABLE_EXTENSION_NAME };
int extension_count = sizeof(extensions) / sizeof(extensions[0]);
XrInstanceCreateInfo instanceCreateInfo = {
.type = XR_TYPE_INSTANCE_CREATE_INFO,
.next = NULL,
.createFlags = 0,
.enabledExtensionCount = extension_count,
.enabledExtensionNames = (const char * const *) extensions,
.enabledApiLayerCount = 0,
.applicationInfo = {
.applicationVersion = 1,
.engineVersion = 0,
.apiVersion = XR_CURRENT_API_VERSION,
},
};
strncpy(instanceCreateInfo.applicationInfo.applicationName, "Example Application", XR_MAX_APPLICATION_NAME_SIZE);
strncpy(instanceCreateInfo.applicationInfo.engineName, "Example Engine", XR_MAX_APPLICATION_NAME_SIZE);
XrInstance instance;
xrCreateInstance(&instanceCreateInfo, &instance);
return 0;
}
Explaining the entire basic OpenXR API is no short task. Instead, the commented OpenXR-Simple-Example tries to be as straightforward as possible in dealing with the OpenXR API.
You can also look at the list of open source examples and applications or a recording of the OpenXR Master Class at Laval Virtual.
Your most important reference of course will be the OpenXR specification: https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html