Request to disable burn-in protection — medical use case (PTSD eye therapy)

Homepage Forums Technical Support Request to disable burn-in protection — medical use case (PTSD eye therapy)

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #222920
    Maximus0079
    Participant

    Hi Ralph,

    I’m using vorpX with a Bigscreen Beyond while lying down and staying perfectly still. This is part of a medical protocol — I’m treating post-traumatic stress from a polytraumatized eye and maintaining bifocal fusion through VR. The immersive environment allows me to enter self-hypnosis, which is essential for my therapy.

    The burn-in protection kicks in after a few seconds of immobility and stops frame submission, which breaks the immersion and makes the therapeutic process impossible. I cannot move my head — that defeats the entire purpose.

    Could you please provide a way to disable the burn-in protection? A config toggle, a hidden setting, a command-line flag — anything would work.

    I want to be transparent: I’ve spent considerable time trying to work around this on my end, without success. Here’s what I’ve tried through a proxy DLL replacing vpenvr_api.dll:

    Hooked IVRSystem::GetTrackedDeviceActivityLevel (vtable slot 15), force-returning UserInteraction
    → 0 calls observed across entire sessions, despite correct hook installation with readback verification

    Injected pose jitter via IVRCompositor::WaitGetPoses and IVRInput::GetPoseRelativeToNow/GetPoseForNextFrame (up to ±50mm / ±5°)
    → no effect

    Async thread writing Block B of vpx_vorpxinterprocess shared memory at 70Hz during Submit gaps
    → no effect

    Hooked LoadLibraryA/W/ExA/ExW to intercept any separate loading of openvr_api.dll
    → 0 redirections, not used
    Binary analysis: no “idle”/”burn-in” strings found, GetTrackedDeviceActivityLevel string absent from the injected DLL, vorpControl.exe contains zero OpenVR strings
    None of the OpenVR API channels are involved in the idle detection — I’ve eliminated every one systematically. The mechanism appears to be entirely internal to the injected DLL.

    I completely understand the rationale behind burn-in protection for OLED panels. But in my case, the content is never truly static (game scenes have ambient animation), and my medical need for complete immobility overrides the display concern.

    Would it be possible to add a toggle to disable this feature, or could you point me in the right direction?

    Thank you for your time and for an otherwise excellent piece of software.

    Best regards

    #222930
    Ralf
    Keymaster

    Forcing a GetTrackedDeviceActivityLevel() hook to return UserInteraction should work. That’s what vorpX queries to get the device activity from SteamVR.

    Caveat: vorpX loads its own openxr_api.dll renamed to vpenvr_api.dll to avoid potential version conflicts with a couple of games that also load OpenVR. Not sure where you are injecting your hook, but that might affect what you have to hook.

    Disabling this on the vorpX end is not really an option, sorry. Would cost me at least a week to do that safely since it’s used as trigger for the virtual display monitor auto activation/deactivation. Even miniscule changes affecting that require an insane amount of testing to ensure noone ends up with both a black headset and black (actual) monitor.

    #222958
    Maximus0079
    Participant

    Hi Ralf,

    Thanks for the insight — that confirms what we experienced. We actually tried hooking GetTrackedDeviceActivityLevel first but could never intercept the calls. Your note about vpenvr_api.dll being a renamed openxr_api.dll explains why we were hooking the wrong thing!

    What ended up working is patching vpenvr_api.dll directly at runtime. We identified the function that gates frame submission (we’re calling it PrepFrame internally). It has three nested conditionals that all need to pass before Submit gets called:

    1. A range check on an internal state variable (JA)
    2. A result check from an internal validation call (JZ)
    3. A flag check on a struct member (another JZ)

    We NOP all three jumps via a proxy DLL (yours gets renamed to vpenvr_api_real.dll, we forward all OpenVR calls transparently). This forces PrepFrame to always reach the success path → Submit proceeds → no more idle/GAP trigger.

    Works great with **Z-Buffer rendering** — rock solid, zero idle triggers. But we’ve noticed it **doesn’t work in Geometry 3D mode** — the idle behavior comes back. Same game, same setup, only the vorpX rendering mode changes. Does Geometry mode use a different frame submission pipeline that would bypass PrepFrame entirely?

    Any pointer would be much appreciated. Thanks again!

Viewing 3 posts - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.

Spread the word. Share this post!