TIC-80 icon indicating copy to clipboard operation
TIC-80 copied to clipboard

VSYNC makes HTML export run fast when on monitors with high refresh rates? (latest dev version)

Open Gate88 opened this issue 2 years ago • 18 comments

I'm currently using the HTML export feature to embed my TIC-80 game for playtesting on itch.io. I noticed with the current stable version (version 0.90.1723 Pro (9c38a80)) the audio gets really choppy and slows down the game when in the background.

To try to fix this, I pulled the latest version (version 1.0.2128-dev Pro (551cf2d)) and the audio seems a lot better! However, I'm having an issue that seems specific to the HTML export (the executable export seems to work fine) that was not happening in the previous stable version.

On a high refresh monitor (144hz) the game runs super fast in the HTML export. If I press ESC, go to "options" and turn off "VSYNC" then it seems to run normally again. I think VSYNC may cause the game to run too fast in the HTML export when on a high refresh rate monitor. This does not seem to happen in the native .exe, nor when I export natively.

If you have a high-refresh rate monitor, you can see the issue reproduced here: https://gate.itch.io/tic80-workspace?password=new-tic-80-build

Also, is there any way to get the HTML export to launch with different default settings (e.g. VSYNC off or different controls)?

EDIT: one other issue I noticed: with vsync on and music playing, alt-tabbing away (or minimizing the browser) will like hold the music note rather than pausing the sound.

Gate88 avatar Apr 07 '22 21:04 Gate88

Unfortunately, we can't vsync properly on a high refresh rate monitor (this applies only to html export), alternatively, we can make vsync=false the default in the HTML export, or you can use the command line argument --vsync 0 to turn it off in your special case.

var Module = {canvas: document.getElementById('canvas'), arguments:['cart.tic', '--vsync=0']}

https://github.com/nesbox/TIC-80/blob/main/build/html/export.html#L35

nesbox avatar Apr 08 '22 06:04 nesbox

I disabled vsync by default for html export 6718e82ed0b2fdafca5d853475c2fc1795f54a37

nesbox avatar Apr 08 '22 11:04 nesbox

... and let's make TIC workable on a high refresh rate monitor in the next version.

nesbox avatar Apr 08 '22 12:04 nesbox

I might be interested in this, where can I find tic80.js?

joshgoebel avatar Apr 08 '22 21:04 joshgoebel

Nice, thanks for the help and quick response @nesbox!

Gate88 avatar Apr 08 '22 21:04 Gate88

OK -- I pulled latest release candidate and tried again.

I think it's working better, but frame timing in general seems to drift a little more in the new version than it did the previous one.

The first time I ran the game here, the music was slow and it never recovered. Subsequent runs it's running a little better, but if you alt+tab and do something else for a bit the game will get into the same state. https://gate.itch.io/tic80-workspace?password=new-tic-80-build

You can compare to the old version, running the same code, if that helps. https://gate.itch.io/ghost?password=ghosttime

Sorry that this bug report isn't super exact -- it's hard to pin down. Oh, and I'm using Firefox, just in case the issue is browser-specific.

EDIT: hmm just got it to happen in the old build too, but it seems to happen less frequently.

Gate88 avatar Apr 08 '22 22:04 Gate88

I think it's working better, but frame timing in general seems to drift a little more in the new version than it did the previous one.

It definitely would/could. I assume "vsync" is using the Window.requestAnimationFrame API which is the only way the browser makes any real "guarantees" about the framerate and timings... if we're just falling back to old school setTimeout then things could well be all over the map.

If wonder if we shouldn't consider always using Window.requestAnimationFrame and just dole out the frames at the best approximation of 60 FPS possible, though that's not going to be even for something like 144hz, etc... and I have no idea if that would feel "weird" or not... I believe that's what WASM-4 decided on recently, but I'm not 100% sure.

joshgoebel avatar Apr 08 '22 23:04 joshgoebel

In general I don't notice many artifacts with 60hz games on my 144hz monitor. I can tell when something is running around 60fps vs. a higher framerate (e.g. my mouse moves a lot smoother in 144hz), but I don't perceive slightly different frame timings for 60fps games.

I think what you're suggesting could work. If 60hz falls between a 144hz frame, then worst case scenario is a delay of like 1/144 seconds (7 milliseconds), right? I think that's going to be tough to perceive. I guess it would get "worse" the lower the max refresh rate of the monitor if that refresh rate isn't evenly divisible by 60.

Gate88 avatar Apr 08 '22 23:04 Gate88

I think that's going to be tough to perceive.

I dunno, vision and how this stuff "feels" is often surprising, but who knows.

I'd worry more about the audio and how much extra audio we generate each frame and whether it could survive waiting an extra ~7ms or not. If we run out of audio then we end up with weird issues... (possibly what some people are already describing here)

But I think it'd be 7ms /2 or /3... I think for the best results you'd want to get a frame as close as possible to it's "target time" which sometimes might mean if you were "close enough" when the 1/144 frame hits that you'd fire the next 60FPS frame 1-3ms early rather than waiting and making it a whole 7ms LATE.

All this stuff is so much simpler on raw hardware. :)

joshgoebel avatar Apr 09 '22 00:04 joshgoebel

Unfortunately, I don't have a way to fix this without a high-frequency monitor, I'll try experimenting with it when I find a >60hz monitor.

nesbox avatar Apr 10 '22 07:04 nesbox

I'm seeing issues on current gen MacBook Pro (120hz screen) with the native Tic-80 app that seem related - with a TIC cart that uses a fixed time step per frame, dragging the tic window between 60hz and 120hz screens literally changes the speed it runs at by a factor of 2. I can happily test at least, since I have both standard and 120hz screens.

Alia-Traces avatar Feb 16 '23 22:02 Alia-Traces

I don't understand why, because we measure time between ticks and use delay() function to sync with the refresh rate in native build. https://github.com/nesbox/TIC-80/blob/eb59272ed93352c7e4f472a293347080af2a5db4/src/system/sdl/main.c#L1784

nesbox avatar Feb 17 '23 10:02 nesbox

Ooookay that's very weird. I saw this when testing an entry for lovebyte for a friend - ran it on my 120hz screen, reported back "it runs, but it's too fast". Then realised it was running at 120hz - I was literally dragging the window between the two screens and seeing the speed double (it's not a CPU heavy effect so definitely not that). Running the same cart now tho, it runs at 60hz as expected?! I've tested on all versions of Tic (I do byte jams and battles so I have a few), all behave the same. Since the issue definitely exists, but I can't repro it, I'm guessing this is either an odd issue maybe relating to which screen Tic is started on, or maybe an SDL issue if it's running for a very long time (since I often leave Tic open for days at a time). Anyway, seems it's hopefully rare, I'll report back if I figure anything out.

Alia-Traces avatar Feb 17 '23 14:02 Alia-Traces

For my 160Hz screen laptop, the game usually runs at normal speed, but sometimes it locks itself into a fast mode for a duration of few seconds to a few minutes.

Here's a recording; it's easiest to reproduce when you grab the game window for a few seconds. https://github.com/nesbox/TIC-80/assets/19384640/59215f90-daa9-40d7-b351-e14f270f8204

(And yeah, this isn't the HTML build but the 1.1-pro Windows build! The issue persists even if Vsync is on or off.)

borbware avatar Nov 08 '23 15:11 borbware

Ok I think I've narrowed this down, and written a very simple repro cart that captures it. What seems to happen:

  1. Something stalls execution for a while (in my repro cart I run a long calculation in BOOT(), looks like dragging the window can also cause it on some systems). I'm assuming it's building up a backlog of frames during this time, or similar.
  2. When execution resumes, the app runs at the maximum frame rate of the screen while it 'catches up' on that backlog
  3. When the backlog is clear, it runs at normal speed

Can see exactly that on my system, the code I put in BOOT takes ~5 seconds to run during which time it's stalled. It then runs at double speed (120fps) for 5 seconds, then returns to normal. Side note: If I run this on my 60hz monitor it runs at normal speed. If I then drag the window to the 120hz screen while it's showing the animation, it runs at double speed for 5 seconds then. fpsissue.tic.zip

Alia-Traces avatar Nov 08 '23 15:11 Alia-Traces

@Alia-Traces you're right - it must be some kind of a catch-up mechanism that is related to real time. My laptop was just in sleep mode overnight with TIC-80 on - I started to run the game and now it just runs at ludicrous speed, with no end in sight :D

borbware avatar Nov 09 '23 11:11 borbware

had some help from friend and created a PR that fixes non-emscripten builds - at least on my laptop! @Alia-Traces if you can, please try the fix with your multi-screen setup.

borbware avatar Nov 10 '23 19:11 borbware