Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a raster estimator method (beam racing, raster interrupt style) #1

Open
mdrejhon opened this issue Jul 13, 2023 · 3 comments
Open
Assignees

Comments

@mdrejhon
Copy link
Member

mdrejhon commented Jul 13, 2023

Raster estimator is possible with VSYNC timestamps.

  • Properties needed: Screen height, screen VBI size.
  • VBI size can be assumed as 45 by default, unless overriden by user of module (e.g. platform specific VBI-size-detecting APIs)
// Run this after a 10-second refresh cycle counting initialization at startup (but keep counting beyond, to incrementally improve accuracy sufficiently enough for beam racing apps)
var accurateRefreshRate = hertz.getCurrentFrequency();
var scanoutPercentage = hertz.getRasterScanoutPercentage();

// Common VBI size for maximum raster accuracy, adjust as needed.  VGA 480p has 45, and HDTV 1080p has 45
// Or optionally use #ifdef type for plat-specific APIs like Linux modelines or Windows QueryDisplayConfig()
var blanking = 45;   

// Vertical screen resolution
var height = screen.height;

// Signal vertical total.  You could ignore blanking, with a bit more error margin 
// (fine for frameslice beamracing for emulators, ala WinUAE lagless sync, but in a more crossplatform way)
var verticalTotal = height + blanking;

// Estimated current raster scan line number at this instant on the GPU output, assuming portrait-mode display
var raster = scanoutPercentage * verticalTotal;

//   OPTIONAL: If your VSYNC timestamp is end-of-VBI rather than start-of-VBI, then compensate
//     However, most frame presentation APIs (running at max rate) unblock at end of refresh cycle (beginning of VBI)
// raster += blanking
// raster = (raster % verticaltotal);

While you can guesstimate the raster during javascript, you can't do any rasterdemos because you can't use VSYNC OFF + high framerates in a web browser outside requestAnimationFrame(). But this generic math code is highly portable to other languages.

@mdrejhon
Copy link
Member Author

mdrejhon commented Jul 14, 2023

Setting up Google Chrome for high performance VSYNC OFF

Breakthrough: You can beam race VSYNC OFF tearline position in a web browser! These instructions are a prelude to beam racing.

Incidentally, it is possible to run Chrome in VSYNC OFF mode, so it is actually possible to beamrace in a web browser! A bit unwieldly, but it works on modern powerful GPUs!

One needs to run two separate instances of Chrome -- one in VSYNC ON mode (to get the refresh rate heartbeat) and another in VSYNC OFF mode (for beamracing tearlines or 'lagless vsync' algorithms in a browser emulator, like WinUAE). A WebSocket can communciate a VSYNC heartbeat from the VSYNC ON instance to the VSYNC OFF instance on the same computer (under Windows).

  1. Close all browsers and applications.
  2. Quit any background software that generates CPU spikes (e.g. Dropbox, RGB-controller software, Razer Synapse, etc)
  3. Make sure NVIDIA Control Panel -> Manage 3D Settings -> Global Settings is configured with the following:
    | * "Vertical sync" = "Use Application Setting"
    | * "Power management mode" = "Prefer maximum performance"
  4. Create a desktop shortcut with this:

"C:\Program Files\Google\Chrome\Application\chrome" --user-data-dir=c:\windows\temp\vsync-off --disable-gpu-vsync --disable-frame-rate-limit https://testufo.com/blurtrail#thickness=8&ppf=8

  • Once launched, use Task Manager to set the chrome process to HIGH priority. (Can use a PowerShell command to automatically do this)
  • Switch to a very low refresh rate (24Hz, 25Hz, 50Hz or 60Hz) for best beamracing results, if attempting to create rasterdemo stuff in a browser.
  • If you can, run MSI Afterburner in the background. It helps keeps the GPU from going into power management.
  • You can run nvidia-smi.exe in Administrator Mode to lock GPU clocks high. Make sure you know the default maximum clock for your GPU. An RTX 3080 Founder's Edition defaults to 1710 MHz:

"C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe" -lgc 1710

If you don't have nvidia-smi.exe, download the latest NVIDIA drivers again, then open the driver .EXE in 7-zip (it's a self extracting EXE, don't need to reinstall drivers), and copy nvidia-smi.exe out of it. Note, you will need to reboot to undo the clock-locking done by nvidia-smi.exe

if you setup correctly, you will see massive tearing in the vertical moving line, and ultra high frame rates:

TestUFO Tearing

@mdrejhon mdrejhon changed the title Add a raster estimator method Add a raster estimator method (beam racing, raster interrupt style) Jul 14, 2023
@mdrejhon
Copy link
Member Author

mdrejhon commented Jul 15, 2023

Beam racing works in Chrome only, not FireFox (for now)

Tried to test FireFox, it doesn't work like it does in Chrome;
Tried to force a few about:config settings in FireFox.

  • gfx.vsync.force-disable-waitforvblank true
  • layout.frame_rate 2000
  • layout.throttled_frame_rate 2000
  • layout.throttle_in_process_iframes false
  • layout.lower_priority_refresh_driver_during_load false

I get higher frame rates in FireFox, but only about 2-3x frame rate over refresh rate, and no tearing appears.

Spinoff Usefulnesses Beyond Browsers

I simply do the audacity of beamracing in a web browser as a stupidly-HLE that nobody believes can do beam racing. It's just to showoff that lesser languages are capable of beam racing usefulnesses (e.g. WinUAE's Lagless VSYNC mode).

Here is the Lagless VSYNC algorithm that is implemented by WinUAE, but could actually be ported to other emulators in a more cross-platform manner, with the help of the algorithms in RefreshRateCalculator.js

@mdrejhon
Copy link
Member Author

mdrejhon commented Jul 26, 2023

Raster estimator has been added.
Meanwhile, copying and pasting from another forum (for myself and others):

Possible sources of refresh cycle heartbeats (signal VSYNC)

VSYNC heartbeats can be obtained from multiple sources, as follows:

  • Generic Method: (Does not always work), Create a VSYNC ON window and a VSYNC OFF window, if your framework allows creating multiple separate VSYNC configurations in different contexts (separate apps / thread / process). Communcate the VSYNC timestamps from VSYNC ON context to the VSYNC OFF context.
  • Microsoft documentation on waitable swapchains
  • C# XBox/MonoGame: Update()+Draw() generally tries to tick to VSYNC during VSYNC ON
  • JavaScript/HTML5: requestAnimationFrame() generally tries to tick to VSYNC during VSYNC ON
    (Note: You can do VSYNC OFF in a browser with --disable-gpu-vsync --disable-frame-throttle)
  • DirectX: Timestamping the exit from max-framerate Present() (exit from blocking behavior = timestamp of VSYNC). But try to use waitable swapchains instead to reduce lag!
  • OpenGL: Timestamping the exit from max-framerate glFinish/glSwapBuffers for blocking behaviors (exit from blocking behavior = timestamp of VSYNC). (See above, though)
  • Windows Compositor Clock (which may vary, e.g. battery management)
  • Alternatively, there's sidechannel APIs to find timestamps from GPU's VSYNC:
    .....Windows: D3DKMTWaitForVerticalBlankEvent()
    You don't have to use D3D for the rest, still works in a headless app! And independently during OpenGL or Vulkan.
    .....Android: SurfaceFlinger callback
    .....MacOS/iOS: CADisplayLink or CVDisplayLink
    .....Linux: XRRGetCrtcInfo (xrandr)
    Remember that not all window managers are vsync'd, but kwin-lowlatency fork did a fantastic job and its works is now upstream in a few window managers

The sidechannel methods are the best for a background library / daemon. Keep in mind certain GPUs (e.g. M2/M3) do not currently seem to let you do any tearing (even though you can still do latency reduction tricks from knowing VSYNC timestamps). But it works on Intel/AMD/NVIDIA GPUs just fine.

For true beamracing tricks, it is a conundrum -- needing both VSYNC ON and VSYNC OFF for different reasons. Beam racing can only be done in VSYNC OFF mode, but successful VSYNC timestamps are easier with VSYNC ON. So as long as the problem is solvable one way or another (via small hooks via platform specific #ifdef-ing), you can beamrace tearlines on any platform!

@mdrejhon mdrejhon self-assigned this Aug 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant