github djules75/OFXR-Bridge 0.2.2_beta4
OFXR Bridge v0.2.2_beta4 (V157) — Frame pacing beta

latest releases: 0.2.14.3, 0.2.14.2, 0.2.14.1...
one month ago

An unofficial beta built on
tig3rmast3r's v0.2.1.

Use the NVIDIA backend if you have an NVIDIA card

Recommended: set the backend to NVIDIA in the tray. The shipped default
is still FidelityFX, which works on any card, but almost everything gained in
this release is on the NVIDIA path.

The reason is where the optical flow runs. NVIDIA cards have a dedicated
hardware engine for it - the Optical Flow Accelerator - which is idle while
your game renders, so frame generation costs you almost none of the GPU the
game is using. About 86% of the work goes there. FidelityFX computes the same
flow in ordinary compute shaders, on the very same shader cores the game is
drawing with, so it competes with your frame rate instead of hiding behind it.

That is why the headroom improvement below - needing roughly 48 FPS natively
rather than 57 to hold a steady 90 - is NVIDIA-only. On FidelityFX the work
cannot overlap, so there is nothing to win by moving it.

New in beta4

Jitter and dropped frames in demanding areas, after a minute of playing
well.
If you are on beta3, this is worth taking.

The mod paces itself against your headset's refresh, and the moment in each
refresh when it hands its frame over is also the window your runtime measures
the game across. Beta3 stopped that moment drifting to the very end of the
refresh, which was the beta2 problem. It did not stop it drifting to the very
beginning — and there the window closes to nothing, so the runtime is told the
game costs about a millisecond. It then schedules as if the game were idle:
asks for each frame late, assumes it will be ready, and reprojects when it is
not. That reads as jitter and dropped frames while the counter still says 90.

Two things made it hard to spot. It only happens when the mod is pacing
well — the drift needs a long clean run of frames to accumulate, so a game
that hitches never gets there, and the best-behaved sessions are the ones that
slide into it. And it only hurts when the scene is genuinely demanding, so it
can be invisible in one area and obvious in the next.

Measured in The Witcher 3 in Novigrad: the measured window fell from 8.0 ms to
0.06 ms over fifteen seconds, with 97.3% of frames reporting under a
millisecond — while the mod's own view was a flawless 45 frames in, 90 out,
nothing skipped and nothing bunched. The moment is now held in a band, away
from both ends of the refresh.

How to tell it is working: in fpsVR or any overlay, the CPU frame time
should read several milliseconds rather than about one. If you see roughly a
millisecond while the game is visibly working hard, that is the fault, and a
flight log would be very welcome.

New in beta3

  • Generated frames now actually reach your headset. The mod hands the
    headset two frames per game frame, and they have to land one refresh apart.
    Its internal schedule for that could only ever slide later — every hiccup
    nudged it back and nothing brought it forward — until it was handing each
    frame over a fraction of a millisecond before the display needed it. At that
    point the headset has already committed to the refresh, so the generated
    frame waits for the next one and collides with the real frame. You see one of
    the two. The result was a game that reported the full rate, showed half of
    it, and could be slower than running without the mod at all.
  • Games that got nothing from the mod, or got less than nothing. A related
    case with a different cause: on some titles the mod handed both frames over a
    few milliseconds apart from the very start, with the same outcome. It now
    measures how far apart the two actually arrive and switches delivery methods
    when they are too close, which takes about a quarter of a second at the start
    of a session. Confirmed on Atomic Heart, which was affected on every runtime
    tested.
  • Steadier frame times, and no more regular spikes. The same schedule could
    also drift slowly out of step with the display and then snap back by a whole
    frame, losing a slot each time it did. On a frame-time graph that showed up
    as a repeating sawtooth or a regular spike.

Measured on a 45-second session after these changes: 45 real frames in, 90
delivered out, 99.7% of them landing on the display's own cadence, 0.2%
arriving a whole refresh late, and none of them bunched together.

Who beta3 and beta4 affect most: anyone on a runtime other than SteamVR —
Meta and Virtual Desktop included — anyone whose game drives VR from a single
thread, and anyone who saw the frame counter say 90 while the headset plainly
showed less. If beta2 seemed to do nothing for you, or made things worse, try
again.

Also new since the first beta

  • It recovers. The most common complaint about beta1 was that a demanding
    scene would knock it down and it would stay down — back in an easy scene, or
    even back at the menu, it would sit at a lower frame rate until you restarted
    the game. The layer paced its own frames against an internal schedule that
    could drift out of step with the headset's refresh and had no way to drift
    back. It now corrects itself against the timing the runtime reports, every
    frame, so a bad patch lasts seconds rather than the rest of the session.
  • More headroom before it gives up. The frame generation work used to be
    queued behind the game's own rendering, so the game had to reach roughly
    57 FPS on its own before the layer could hold 90. On NVIDIA it now runs
    alongside the game's rendering instead, which brings that down to roughly
    48 FPS. If you were just short of a steady 90, this is the change most
    likely to get you there.
  • Fewer frames thrown away. When a frame ran long the layer would often
    skip the next display slot entirely rather than fill it, which reads as a
    hitch. It now only skips when a submission would genuinely land on top of
    the previous one.
  • Synthetic frames placed where they are actually shown. The generated
    frame was always the exact midpoint between two rendered frames, which is
    only correct when the game runs at exactly half the refresh rate. Away from
    that it was shown slightly early or late, and — because the error follows
    your frame time — alternately early and late as frame times swing. A
    constant offset would be invisible; an alternating one reads as judder.
    It is now placed to match when it is actually displayed.
  • Stability fixes in the new NVIDIA path: GPU work is properly drained when
    a swapchain or session goes away, and the generated frame is prepared in the
    right resource state rather than relying on the driver to tolerate it.

Still in from beta1

  • Steady 90 FPS at high headset resolution. At 27 Mpx per eye the layer
    previously produced fewer frames per second than running without it. The
    runtime was being told the layer's frame cost about a millisecond when the
    real work was around 15 ms, so it scheduled against numbers that described an
    empty loop. It now measures the real work, which is also what makes fpsVR's
    GPU and CPU frame times meaningful again.
  • Frame generation engages immediately. It could previously sit idle for
    minutes on a demanding scene — generating frames the whole time, at full GPU
    cost, with none of them being displayed — and then suddenly start working when
    you looked at something simple. The layer now decides it needs to pace itself
    by measuring the runtime rather than by guessing from the game's frame loop.
  • No more one-second dropouts. Changing settings, loading a world, or the
    game recreating its swapchains each cost a full second of generation.
    Transitions are now seamless.
  • Generation no longer stops permanently after a menu or loading screen.
    A clock inside the layer could drift a second per second until the game was
    predicting poses ten minutes into the future; once there, it never recovered
    for the rest of the session.
  • Games that would not start in VR now start. Titles that create many
    swapchains — The Callisto Protocol under UEVR, for example — exhausted the
    runtime's swapchain budget and failed at session creation. The layer now only
    takes resources for swapchains that actually carry the image you see.
  • Luke Ross mods: black flashes and double vision fixed. Cyberpunk 2077 was
    tearing down and restarting the layer's internals about three times a second,
    and separately publishing the previous pair's frame as the current one.
  • Higher resolution ceiling. Roughly 340 MB of per-frame copying moved off
    the critical path, taking the workable ceiling from about 15 to about
    24.5 Mpx.

Changed default

Unchanged from beta1, repeated here because it still catches people out:

FidelityFX honours the Optical flow resolution tray setting, which it
previously ignored and ran at full resolution. With the shipped default of 50%
this makes FidelityFX noticeably cheaper, at some cost in motion-vector detail.
Set nvidia_input_scale=100 in ofxr_bridge.ini to restore the old behaviour.

The tray menu entry is called Optical flow resolution rather than
"NVIDIA OFA resolution", because it applies to both backends. The ini key name
is unchanged.

A note on frame times in fpsVR

The mod deliberately holds your game to half the refresh rate and fills the
gaps. That hold happens inside a call fpsVR counts as the game's own CPU time,
so the CPU frame time it reports goes up when OFXR is on, and moves around,
without your game having got any slower.
Whatever your game does not spend
rendering, the hold absorbs. What matters is that the game's own frame rate
sits at half your refresh and stays there.

The GPU frame time reads low for a different reason, and is also expected:
on the NVIDIA backend the frame generation work runs on its own queue and on
the optical flow engine, neither of which your runtime measures. That is the
same separation that buys the headroom improvement above.

Installing

Unzip anywhere and run OFXRBridgeTray.exe, then Arm bridge. Keep
OFXRBridgeTray.exe and the ofxr folder together. If you have an earlier
version armed, disarm it first.

Known issues

  • The frame generation work sharing the GPU with your game is new. If a game
    that was steady on beta1 is worse here, please say so and include a flight
    log — that is the case most worth hearing about.
  • Very high per-eye resolutions remain the limit. If frame times are erratic,
    drop the resolution first before changing anything else; the layer's cost
    scales with it.
  • Selecting the NVIDIA backend without an NVIDIA card silently does
    nothing.
    The NVIDIA option drives a hardware engine that only exists on
    NVIDIA GPUs; on any other card the layer cannot start and passes every frame
    through untouched, with no warning. If you are on AMD or Intel, leave the
    backend on FidelityFX, which is the shipped default.

Tested

Microsoft Flight Simulator 2024, The Witcher 3 (tig3rmast3r's VR mod),
Cyberpunk 2077 (Luke Ross mod), and UEVR titles including The Callisto
Protocol, on SteamVR with a Pimax Crystal Super at up to 4172×3268 per eye, on
both the NVIDIA OFA and FidelityFX backends. VDXR is covered by the earlier
work this builds on; PimaxXR is not tested.

This is an experimental beta and compatibility is not universal. Please report
results — working and not — on this fork's
GitHub Issues, with an OFXR flight log where you can. Enable one
by setting logging_enabled=1 under [diagnostics] in ofxr_bridge.ini; logs
are written next to the armed layer under
%LOCALAPPDATA%\OFXR Bridge\RuntimeLayer\v157\.

Upstream results are collected in the
OFXR Bridge Compatibility Chart.

Don't miss a new OFXR-Bridge release

NewReleases is sending notifications on new releases.