Graphs
How Kestrel VR meets SteamVR, at the level of names and connections.
OpenXR and SteamVR
Where the application API sits, where the driver API sits, and how far apart they are. The boundary Kestrel is written against is at the bottom of this picture; OpenXR is at the top, in a different process, and nothing Kestrel does touches it.
Valve's code
Kestrel
Application API, public specification
The application
Game process
vrcompositor process
vrserver process
The game
VRChat, Half-Life: Alyx
OpenXR loader
libopenxr_loader, picks a runtime
SteamVR's runtime
inside vrclient.so, loaded
into this process
OpenXR calls
dispatch
Compositor
layers, reprojection,
the menu and overlays
Eye textures
shared GPU memory, fences
Present, PostPresent
frames, poses, over IPC
Device and property store
poses, input, settings
Driver host
loads registered drivers
Kestrel driver
direct mode component,
vsync grid, encode worker
openvr_driver.h only
Vulkan Video encoder
radv, HEVC and H264
QUIC to the headset
loads
the driver seam, 50 calls
Below this line is where Kestrel lives. Above it is where an OpenXR runtime lives.
The two never meet in one process.
A Kestrel runtime would replace everything above the line
the loader entry, the session and frame loop, swapchains, the compositor,
the device and input model. Monado is the working example.
The encoder and the transport carry over. The driver seam does not.
What lives on each side
Boundary Who defines it Who implements it Does Kestrel touch it
OpenXR, the application API Khronos, public specification SteamVR inside vrclient.so, in the game's own process; Monado in its own Not on the streamer. The headset client is an OpenXR application, which is the only OpenXR in the tree
OpenVR, the application API Valve, public headers The same vrclient.so, the same process No
The driver API Valve, openvr_driver.h, pinned at one commit vrserver loads the driver library into itself Yes. This is the whole of Kestrel's streamer seam
The compositor's shared textures, fences and per-image semaphores Nobody. Undocumented vrcompositor publishes, the driver consumes Yes, and this is the one fragile dependency, guarded by a fallback
Why the distinction matters
The driver seam
Every call between SteamVR and the Kestrel driver: the openvr_driver.h interface on the left, the part of Kestrel that handles it on the right. Hover a box to follow its calls.
All · 50 SteamVR calls Kestrel · 30 Kestrel calls SteamVR · 20 Never reached · 2
SteamVR interface call Kestrel part SteamVR calls Kestrel Kestrel calls SteamVR HmdDriverFactory · driver load · SteamVR calls Kestrel HmdDriverFactory Init · IServerTrackedDeviceProvider_004 · SteamVR calls Kestrel Init Cleanup · IServerTrackedDeviceProvider_004 · SteamVR calls Kestrel Cleanup GetInterfaceVersions · IServerTrackedDeviceProvider_004 · SteamVR calls Kestrel GetInterfaceVersions RunFrame · IServerTrackedDeviceProvider_004 · SteamVR calls Kestrel RunFrame ShouldBlockStandbyMode · IServerTrackedDeviceProvider_004 · SteamVR calls Kestrel ShouldBlockStandbyMode EnterStandby (provider) · IServerTrackedDeviceProvider_004 · SteamVR calls Kestrel EnterStandby (provider) LeaveStandby · IServerTrackedDeviceProvider_004 · SteamVR calls Kestrel LeaveStandby Activate · ITrackedDeviceServerDriver_005 · SteamVR calls Kestrel Activate Deactivate · ITrackedDeviceServerDriver_005 · SteamVR calls Kestrel Deactivate EnterStandby (device) · ITrackedDeviceServerDriver_005 · SteamVR calls Kestrel EnterStandby (device) GetComponent · ITrackedDeviceServerDriver_005 · SteamVR calls Kestrel GetComponent DebugRequest · ITrackedDeviceServerDriver_005 · SteamVR calls Kestrel DebugRequest GetPose · ITrackedDeviceServerDriver_005 · SteamVR calls Kestrel GetPose GetWindowBounds · IVRDisplayComponent_003 · SteamVR calls Kestrel GetWindowBounds IsDisplayOnDesktop · IVRDisplayComponent_003 · SteamVR calls Kestrel IsDisplayOnDesktop IsDisplayRealDisplay · IVRDisplayComponent_003 · SteamVR calls Kestrel IsDisplayRealDisplay GetRecommendedRenderTargetSize · IVRDisplayComponent_003 · SteamVR calls Kestrel GetRecommendedRenderTargetSize GetEyeOutputViewport · IVRDisplayComponent_003 · SteamVR calls Kestrel GetEyeOutputViewport GetProjectionRaw · IVRDisplayComponent_003 · SteamVR calls Kestrel GetProjectionRaw ComputeDistortion · IVRDisplayComponent_003 · SteamVR calls Kestrel ComputeDistortion ComputeInverseDistortion · IVRDisplayComponent_003 · SteamVR calls Kestrel ComputeInverseDistortion CreateSwapTextureSet · IVRDriverDirectModeComponent_009 · SteamVR calls Kestrel CreateSwapTextureSet DestroySwapTextureSet · IVRDriverDirectModeComponent_009 · SteamVR calls Kestrel DestroySwapTextureSet DestroyAllSwapTextureSets · IVRDriverDirectModeComponent_009 · SteamVR calls Kestrel DestroyAllSwapTextureSets GetNextSwapTextureSetIndex · IVRDriverDirectModeComponent_009 · SteamVR calls Kestrel GetNextSwapTextureSetIndex SubmitLayer · IVRDriverDirectModeComponent_009 · SteamVR calls Kestrel SubmitLayer Present · IVRDriverDirectModeComponent_009 · SteamVR calls Kestrel Present PostPresent · IVRDriverDirectModeComponent_009 · SteamVR calls Kestrel PostPresent GetFrameTiming · IVRDriverDirectModeComponent_009 · SteamVR calls Kestrel GetFrameTiming VR_INIT_SERVER_DRIVER_CONTEXT · driver context · Kestrel calls SteamVR VR_INIT_SERVER_DRIVER_CONTEXT VR_CLEANUP_SERVER_DRIVER_CONTEXT · driver context · Kestrel calls SteamVR VR_CLEANUP_SERVER_DRIVER_CONTEXT TrackedDeviceAdded · IVRServerDriverHost_006 · Kestrel calls SteamVR TrackedDeviceAdded TrackedDevicePoseUpdated · IVRServerDriverHost_006 · Kestrel calls SteamVR TrackedDevicePoseUpdated VsyncEvent · IVRServerDriverHost_006 · Kestrel calls SteamVR VsyncEvent VsyncEvent (SendVSync) · IVRServerDriverHost_006 · Kestrel calls SteamVR VsyncEvent (SendVSync) VendorSpecificEvent · IVRServerDriverHost_006 · Kestrel calls SteamVR VendorSpecificEvent PollNextEvent · IVRServerDriverHost_006 · Kestrel calls SteamVR PollNextEvent IsExiting · IVRServerDriverHost_006 · Kestrel calls SteamVR IsExiting SetDisplayEyeToHead · IVRServerDriverHost_006 · Kestrel calls SteamVR SetDisplayEyeToHead SetDisplayProjectionRaw · IVRServerDriverHost_006 · Kestrel calls SteamVR SetDisplayProjectionRaw SetBoolProperty · IVRProperties_001 · Kestrel calls SteamVR SetBoolProperty SetFloatProperty · IVRProperties_001 · Kestrel calls SteamVR SetFloatProperty TrackedDeviceToPropertyContainer · IVRProperties_001 · Kestrel calls SteamVR TrackedDeviceToPropertyContainer GetFloat · IVRSettings_003 · Kestrel calls SteamVR GetFloat SetFloat · IVRSettings_003 · Kestrel calls SteamVR SetFloat CreateBooleanComponent · IVRDriverInput_004 · Kestrel calls SteamVR CreateBooleanComponent CreateScalarComponent · IVRDriverInput_004 · Kestrel calls SteamVR CreateScalarComponent UpdateBooleanComponent · IVRDriverInput_004 · Kestrel calls SteamVR UpdateBooleanComponent UpdateScalarComponent · IVRDriverInput_004 · Kestrel calls SteamVR UpdateScalarComponent driver load IServerTrackedDeviceProvider_004 ITrackedDeviceServerDriver_005 IVRDisplayComponent_003 IVRDriverDirectModeComponent_009 driver context IVRServerDriverHost_006 IVRProperties_001 IVRSettings_003 IVRDriverInput_004 Rust core Driver entry Tracked device Tracker proxy Headset Linux direct display Play area Controllers
Which thread makes each call
The same seam, sorted by the SteamVR thread each call runs on. Frame delivery has a thread of its own, so a driver can pace frames without holding up the rest of SteamVR.
All · 52 SteamVR calls the driver · 30 The driver calls SteamVR · 22 Never reached · 5
thread call interface SteamVR calls the driver The driver calls SteamVR HmdDriverFactory · driver load · runs on: Startup HmdDriverFactory Init · IServerTrackedDeviceProvider_004 · runs on: Startup Init Cleanup · IServerTrackedDeviceProvider_004 · runs on: Server main loop Cleanup GetInterfaceVersions · IServerTrackedDeviceProvider_004 · runs on: Startup GetInterfaceVersions RunFrame · IServerTrackedDeviceProvider_004 · runs on: Server main loop RunFrame ShouldBlockStandbyMode · IServerTrackedDeviceProvider_004 · runs on: No caller found ShouldBlockStandbyMode EnterStandby (provider) · IServerTrackedDeviceProvider_004 · runs on: Server main loop EnterStandby (provider) LeaveStandby · IServerTrackedDeviceProvider_004 · runs on: Server main loop LeaveStandby Activate · ITrackedDeviceServerDriver_005 · runs on: Device activation Activate Deactivate · ITrackedDeviceServerDriver_005 · runs on: Server main loop Deactivate EnterStandby (device) · ITrackedDeviceServerDriver_005 · runs on: Server main loop EnterStandby (device) GetComponent · ITrackedDeviceServerDriver_005 · runs on: Device activation GetComponent DebugRequest · ITrackedDeviceServerDriver_005 · runs on: Compositor connection DebugRequest GetPose · ITrackedDeviceServerDriver_005 · runs on: No caller found GetPose GetWindowBounds · IVRDisplayComponent_003 · runs on: Device activation GetWindowBounds IsDisplayOnDesktop · IVRDisplayComponent_003 · runs on: Device activation IsDisplayOnDesktop IsDisplayRealDisplay · IVRDisplayComponent_003 · runs on: Device activation IsDisplayRealDisplay GetRecommendedRenderTargetSize · IVRDisplayComponent_003 · runs on: Device activation GetRecommendedRenderTargetSize GetEyeOutputViewport · IVRDisplayComponent_003 · runs on: Device activation GetEyeOutputViewport GetProjectionRaw · IVRDisplayComponent_003 · runs on: Device activation GetProjectionRaw ComputeDistortion · IVRDisplayComponent_003 · runs on: Compositor connection ComputeDistortion ComputeInverseDistortion · IVRDisplayComponent_003 · runs on: Compositor connection ComputeInverseDistortion CreateSwapTextureSet · IVRDriverDirectModeComponent_009 · runs on: Compositor connection CreateSwapTextureSet DestroySwapTextureSet · IVRDriverDirectModeComponent_009 · runs on: Compositor connection DestroySwapTextureSet DestroyAllSwapTextureSets · IVRDriverDirectModeComponent_009 · runs on: Compositor connection DestroyAllSwapTextureSets GetNextSwapTextureSetIndex · IVRDriverDirectModeComponent_009 · runs on: Frame submit thread GetNextSwapTextureSetIndex SubmitLayer · IVRDriverDirectModeComponent_009 · runs on: Frame submit thread SubmitLayer Present · IVRDriverDirectModeComponent_009 · runs on: Frame submit thread Present PostPresent · IVRDriverDirectModeComponent_009 · runs on: Frame submit thread PostPresent GetFrameTiming · IVRDriverDirectModeComponent_009 · runs on: Frame submit thread GetFrameTiming GetGenericInterface · IVRDriverContext · runs on: Startup GetGenericInterface TrackedDeviceAdded · IVRServerDriverHost_006 · runs on: Device activation TrackedDeviceAdded TrackedDevicePoseUpdated · IVRServerDriverHost_006 · runs on: Driver's own threads TrackedDevicePoseUpdated VsyncEvent · IVRServerDriverHost_006 · runs on: Driver's own threads VsyncEvent VendorSpecificEvent · IVRServerDriverHost_006 · runs on: Server main loop VendorSpecificEvent IsExiting · IVRServerDriverHost_006 · runs on: Server main loop IsExiting PollNextEvent · IVRServerDriverHost_006 · runs on: Server main loop PollNextEvent GetRawTrackedDevicePoses · IVRServerDriverHost_006 · runs on: Driver's own threads GetRawTrackedDevicePoses RequestRestart · IVRServerDriverHost_006 · runs on: Driver's own threads RequestRestart GetFrameTimings · IVRServerDriverHost_006 · runs on: No caller found GetFrameTimings SetDisplayEyeToHead · IVRServerDriverHost_006 · runs on: Driver's own threads SetDisplayEyeToHead SetDisplayProjectionRaw · IVRServerDriverHost_006 · runs on: Driver's own threads SetDisplayProjectionRaw SetRecommendedRenderTargetSize · IVRServerDriverHost_006 · runs on: Driver's own threads SetRecommendedRenderTargetSize TrackedDeviceToPropertyContainer · IVRProperties_001 · runs on: Driver's own threads TrackedDeviceToPropertyContainer ReadPropertyBatch · IVRProperties_001 · runs on: Driver's own threads ReadPropertyBatch WritePropertyBatch · IVRProperties_001 · runs on: Driver's own threads WritePropertyBatch GetFloat · IVRSettings_003 · runs on: Driver's own threads GetFloat SetFloat · IVRSettings_003 · runs on: Driver's own threads SetFloat CreateBooleanComponent · IVRDriverInput_004 · runs on: Device activation CreateBooleanComponent CreateScalarComponent · IVRDriverInput_004 · runs on: Device activation CreateScalarComponent UpdateBooleanComponent · IVRDriverInput_004 · runs on: Driver's own threads UpdateBooleanComponent UpdateScalarComponent · IVRDriverInput_004 · runs on: Driver's own threads UpdateScalarComponent Startup Server main loop No caller found Device activation Compositor connection Frame submit thread Driver's own threads driver load IServerTrackedDeviceProvider_004 ITrackedDeviceServerDriver_005 IVRDisplayComponent_003 IVRDriverDirectModeComponent_009 IVRDriverContext IVRServerDriverHost_006 IVRProperties_001 IVRSettings_003 IVRDriverInput_004
Inside the streamer: Rust and C++
The streamer is two languages in one library. These are the names that cross between them, as counted on 2026-09-08, with the part of each side that uses them.
All · 57 Rust implements, C++ calls · 24 C++ implements, Rust calls · 20 Rust writes, C++ reads · 13 Never reached · 6
C++ part name Rust part Rust implements, C++ calls C++ implements, Rust calls Rust writes, C++ reads LogError LogError LogWarn LogWarn LogInfo LogInfo LogDebug LogDebug LogEncoder LogEncoder LogPeriodically LogPeriodically DriverReadyIdle DriverReadyIdle SetVideoConfigNals SetVideoConfigNals VideoSend VideoSend HapticsSend HapticsSend ShutdownRuntime ShutdownRuntime SetEncoderMaxFrame SetEncoderMaxFrame SetIntraRefreshCycle SetIntraRefreshCycle SetEncoderFailedIdle SetEncoderFailedIdle PathStringToHash PathStringToHash ReportPresent ReportPresent ReportComposed ReportComposed GetDynamicEncoderParams GetDynamicEncoderParams GetClientDisplayPeriodNs GetClientDisplayPeriodNs GetSerialNumber GetSerialNumber SetOpenvrProps SetOpenvrProps RegisterButtons RegisterButtons WaitForVSync WaitForVSync InitializeRuntime InitializeRuntime CppInit CppInit CppOpenvrEntryPoint CppOpenvrEntryPoint InitializeStreaming InitializeStreaming DeinitializeStreaming DeinitializeStreaming SendVSync SendVSync RequestIDR RequestIDR SetTracking SetTracking RequestDriverResync RequestDriverResync ShutdownSteamvr ShutdownSteamvr SetOpenvrProperty SetOpenvrProperty SetOpenvrPropByDeviceID SetOpenvrPropByDeviceID RegisterButton RegisterButton SetLocalViewParams SetLocalViewParams SetBattery SetBattery SetButton SetButton SetProximityState SetProximityState InitOpenvrClient InitOpenvrClient ShutdownOpenvrClient ShutdownOpenvrClient SetChaperoneArea SetChaperoneArea CaptureFrame CaptureFrame FRAME_RENDER_VS_CSO_PTR/LEN FRAME_RENDER_VS_CSO_PTR/LEN FRAME_RENDER_PS_CSO_PTR/LEN FRAME_RENDER_PS_CSO_PTR/LEN QUAD_SHADER_CSO_PTR/LEN QUAD_SHADER_CSO_PTR/LEN COMPRESS_AXIS_ALIGNED_CSO_PTR/LEN COMPRESS_AXIS_ALIGNED_CSO_PTR/LEN COLOR_CORRECTION_CSO_PTR/LEN COLOR_CORRECTION_CSO_PTR/LEN RGBTOYUV420_CSO_PTR/LEN RGBTOYUV420_CSO_PTR/LEN QUAD_SHADER_COMP_SPV_PTR/LEN QUAD_SHADER_COMP_SPV_PTR/LEN FFR_SHADER_COMP_SPV_PTR/LEN FFR_SHADER_COMP_SPV_PTR/LEN RGBTOYUV420_SHADER_COMP_SPV_PTR/LEN RGBTOYUV420_SHADER_COMP_SPV_PTR/LEN QUAD_NV12_SHADER_COMP_SPV_PTR/LEN QUAD_NV12_SHADER_COMP_SPV_PTR/LEN FFR_NV12_SHADER_COMP_SPV_PTR/LEN FFR_NV12_SHADER_COMP_SPV_PTR/LEN g_sessionPath g_sessionPath g_driverRootDir g_driverRootDir Logging Headset Bitstream parsing Encoders Driver entry Linux direct display Input paths Controllers Windows display Tracked device Play area Windows renderer Rust core Properties Graphics