Skip to content

[BUG] OpenVR overlays (IVROverlay) render behind scene application on Linux - invisible during gameplay #849

@PhialsBasement

Description

@PhialsBasement

Description

Custom OpenVR overlays created via IVROverlay::createOverlay() render behind the scene application (game) on Linux, making them invisible during gameplay. The overlays work correctly in the SteamVR grid/void environment and appear grayed out in the dashboard when pressed, confirming they are loaded and active but rendered at the wrong depth/layer.

The same overlay code works correctly on Windows where overlays render in front of the game scene as expected.

Steps to Reproduce

  1. Create a simple OpenVR overlay application using openvr.init(openvr.VRApplication_Overlay)
  2. Create an overlay with IVROverlay().createOverlay()
  3. Set overlay properties (color, alpha, width, texture via setOverlayFromFile)
  4. Set overlay transform with setOverlayTransformAbsolute() using TrackingUniverseSeated
  5. Call showOverlay()
  6. Launch any VR game (tested with DCS World via Proton and MSFS via Proton)
  7. Observe that the overlay is invisible during gameplay
  8. Press the system/menu button to open the dashboard
  9. Observe that the overlay appears grayed out in the dashboard view, confirming it exists but is rendered behind the scene

Expected Behavior

Overlays created via IVROverlay::createOverlay() should render in front of the game scene during gameplay, as they do on Windows. Per OpenVR documentation: "The vr::IVROverlay
interface provides access to draw 2D images over the 3D scene no matter which application is running."

Actual Behavior

Overlays render behind the scene application and are invisible during gameplay. They only become visible when:

  • In the SteamVR void/grid environment (no scene app running)
  • When the dashboard is activated (overlay appears grayed out)

Minimal Reproduction Code

import openvr
import time
import os

# Initialize as overlay application
openvr.init(openvr.VRApplication_Overlay)
overlay = openvr.IVROverlay()

# Create overlay
handle = overlay.createOverlay('test_overlay', 'test_overlay')

# Configure overlay
overlay.setOverlayColor(handle, 1, 1, 1)
overlay.setOverlayAlpha(handle, 1)
overlay.setOverlayWidthInMeters(handle, 0.5)
overlay.setOverlayFromFile(handle, '/path/to/image.png')

# Position in front of user
transform = openvr.HmdMatrix34_t()
transform[0][0] = 1.0
transform[1][1] = 1.0
transform[2][2] = 1.0
transform[0][3] = 0.0   # x
transform[1][3] = 0.0   # y
transform[2][3] = -1.0  # z (1m in front)

overlay.setOverlayTransformAbsolute(handle, openvr.TrackingUniverseSeated, transform)
overlay.showOverlay(handle)

# Keep running
while True:
time.sleep(0.1)

Flags/Settings Tested (None Fixed the Issue)

  • VRApplication_Overlay (vs VRApplication_Background) - no change
  • setOverlaySortOrder(handle, 100) - no change
  • setOverlayFlag(handle, VROverlayFlags_SortWithNonSceneOverlays, True) - no change
  • setOverlayFlag(handle, VROverlayFlags_VisibleInDashboard, False) - no change

System Information

  • Linux Distribution: Garuda Linux (Arch-based, rolling)
  • Kernel: 6.17.9-zen1-1-zen
  • GPU: AMD Radeon RX 9070 XT (RDNA4, gfx1201)
  • GPU Driver: Mesa radeonsi, LLVM 21.1.5, DRM 3.64
  • SteamVR Version: 2.14.3
  • Steam Client: Latest stable
  • HMD: Quest 3S

Games Tested

  • DCS World (via Proton)
  • Microsoft Flight Simulator (via Proton)

Both exhibit identical behavior - overlays invisible during gameplay.

Additional Context

  • Working Windows application (steam-vr-wheel) uses identical overlay code with no special flags and overlays work correctly on Windows
  • This appears to be a compositor layering issue specific to Linux SteamVR where overlay layers are composited behind the scene layer instead of in front

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions