stride3d/stride · error · Exception

OculusOvr.GetError()

Error message

OculusOvr.GetError()

What it means

OculusOverlay's constructor calls OculusOvr.CreateQuadLayerTexturesDx to create the LibOVR quad-layer swapchain bound to the app's D3D11 device. If the native call fails it returns a null overlay pointer, and the wrapper throws an Exception carrying the last LibOVR error string (ovr_GetLastError), since no richer exception type is available across the P/Invoke boundary.

Solutions

  1. Ensure the Oculus OVR session is created and the HMD is enabled (OculusOvrHmd.Enable) before constructing the overlay.
  2. Verify the GraphicsDevice is a D3D11 device and its native handle is passed correctly.
  3. Check width/height/mipLevels/sampleCount are within device limits reported by the runtime.
  4. Confirm the Oculus runtime software is installed and running; read the returned error string for the native cause.
Defensive patterns

Strategy: try-catch

Validate before calling

// C#
bool ready = hmd != null && hmd.State == VRState.Ready && GraphicsDevice.GraphicsBackend == GraphicsBackend.Direct3D11;

Try / catch

// C#
try { overlay = new OculusOverlay(device, session, w, h, mip, samples); }
catch (Exception ex) { Logger.Warning("Oculus overlay init failed: " + ex.Message); overlay = null; }

Prevention

When it happens

Trigger: Creating an OculusOverlay when the native CreateQuadLayerTexturesDx call returns IntPtr.Zero — e.g. no active OVR session, an invalid D3D11 device handle, unsupported width/height/mipLevels/sampleCount, or the OVR runtime not being initialized.

Common situations: Using the Oculus backend without a headset/runtime running; creating the overlay before the HMD session is enabled; mixing D3D11 devices (passing a device from another adapter); requesting invalid texture parameters.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/0d74c069c3831ca3. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.VirtualReality/OculusOVR/OculusOverlay.cs:25

using Stride.Graphics;
using CommandList = Stride.Graphics.CommandList;

namespace Stride.VirtualReality
{
    internal class OculusOverlay : VROverlay, IDisposable
    {
        private readonly IntPtr ovrSession;
        internal IntPtr OverlayPtr;
        private readonly Texture[] textures;

        public unsafe OculusOverlay(IntPtr ovrSession, GraphicsDevice device, int width, int height, int mipLevels, int sampleCount)
        {
            this.ovrSession = ovrSession;

            OverlayPtr = OculusOvr.CreateQuadLayerTexturesDx(ovrSession, (nint) device.NativeDevice.Handle, out var textureCount, width, height, mipLevels, sampleCount);
            if (OverlayPtr == IntPtr.Zero)
            {
                throw new Exception(OculusOvr.GetError());
            }

            textures = new Texture[textureCount];
            for (var i = 0; i < textureCount; i++)
            {
                var dxTexture2D = (ID3D11Texture2D*) OculusOvr.GetQuadLayerTextureDx(ovrSession, OverlayPtr, OculusOvrHmd.Dx11Texture2DGuid, i);
                if (dxTexture2D is null)
                {
                    throw new Exception(OculusOvr.GetError());
                }

                textures[i] = new Texture(device).InitializeFromImpl(dxTexture2D, treatAsSrgb: false);

                // We don't need to take ownership of the COM pointer.
                //   We are already AddRef()ing in Texture.InitializeFromImpl when storing the COM pointer;
                //   compensate with Release() to return the reference count to its previous value
                dxTexture2D->Release();
            }

View on GitHub (pinned to 96fad776d2)