Smooth scrolling possible?

Monkey Forums/Monkey Programming/Smooth scrolling possible?

Gianmichele(Posted 2014) [#1]
Hi,

I've been experimenting a lot with Monkey and while trying all sorts of frameworks and examples I couldn't help but notice that in everyone of them, compiled for GLFW on Mac OSX Mavericks, the scroll is never smooth (Flixel, Diddy, fEngine)

While digging through the forums I've found various threads where this problem has been raised (something to do with the timing and sync of the OnUpdate and OnRender), but no real solution has been found. The threads were a bit old, so I thought I'll keep exploring.

So far, I've found two examples that have a really smooth scrolling, one is the game Tiny Thor (which looks great BTW!) and the other is a small example of a platformer (for which I don't remember the link).

Would be great to know which strategies have been used to achieve such a result.

Also is there any plan from Mark to tackle this? I see it as a very serious thing.

Thanks,
Gianmichele


AdamRedwoods(Posted 2014) [#2]
try
#GLFW_SWAP_INTERVAL=0

may introduce tearing for windows users, but since you're on osx, no worries.


Nobuyuki(Posted 2014) [#3]
@AdamRedwoods
didn't know that one existed. Is there a place in the help docs that goes over every preprocessor variable and directive?


Gianmichele(Posted 2014) [#4]
Yep, experimented with the swap interval, but that makes no noticeable difference.


AdamRedwoods(Posted 2014) [#5]
didn't know that one existed. Is there a place in the help docs that goes over every preprocessor variable and directive?

it's not in the docs, yet:
http://monkey-x.com/docs/html/Programming_App%20config%20settings.html

Yep, experimented with the swap interval, but that makes no noticeable difference.

does your test "skip" a lot? i wonder if the GC is bugging. try #CPP_GC_MODE=2 to see if that effects it at all.


Sub_Zero(Posted 2014) [#6]
Are you doing any "scrolling" in OnUpdate?


therevills(Posted 2014) [#7]
Have you an example of your scrolling? In the Platformer demo for Diddy we use the delta timing to scroll the game and its pretty smooth:

http://www.monkeycoder.co.nz/Community/posts.php?topic=7295&app_id=47


smilertoo(Posted 2014) [#8]
Use pools so there's no GC during gameplay.


Gianmichele(Posted 2014) [#9]
I only have a small circle and a very simple tilemap in it.

The code from this post works really well for me (extremely smooth)

http://monkeycoder.co.nz/Community/posts.php?topic=449&post=3453

while the one here is not as smooth

http://monkeycoder.co.nz/Community/posts.php?topic=449


Gianmichele(Posted 2014) [#10]
On a side note, the GC directive helps a bit, but still not silky smooth (something I would expect from this kind of tests)


AdamRedwoods(Posted 2014) [#11]
oh, and one last note: "debug" mode is slow compared to release mode. so always try "release" mode if you suspect your game is stuttering/slow.


Gianmichele(Posted 2014) [#12]
Yeah I know release mode is faster :D


AdamRedwoods(Posted 2014) [#13]
Yeah I know release mode is faster :D

cool. i try to be as thorough as possible. which reminds me, this is good stuff to go in the FAQ.
https://github.com/blitz-research/monkey/wiki/Monkey-FAQ


marksibly(Posted 2014) [#14]

The code from this post works really well for me (extremely smooth)

http://monkeycoder.co.nz/Community/posts.php?topic=449&post=3453

while the one here is not as smooth

http://monkeycoder.co.nz/Community/posts.php?topic=449



Interesting...the difference between the 2 seems to be that the 'smooth' one only ever scrolls in integer increments, while the 'lumpy' one scrolls in fractional increments. If you change the parameters passed to scrollHorizontal in the lumpy version to -1,1, the scrolling becomes smooth, although of course the player gets out of sync.

I guess this makes sense as with fractional scrolls values your tilemap is being draw at something like, say, integer x coords=10,20,31(1),40,50,61(!) etc. I guess antialiasing might help here, but I suspect you'd still notice a slight visual 'glitch' when an integer border is crossed. I also suspect it also wouldn't matter so much with just a player object, but with a tilemap there is a lot of visual error on screen for the eye to catch.

Moral of the story is probably to make sure you scroll in integer increments if you want 100% smoothness...

Also: It shouldn't generally be necessary to add 'delta time' code to your update stuff. Monkey guarantees that enough updates are called to 'catch up' with the renders, so you can assume a constant update delta. If anything, in a vsynced environment (seems to be the default here on MacOS, and most devices nowadays) this could make things worse, because renders (well, the final 'flip') will ALWAYS be executing at 60FPS or whatever, so unless updates also assume 1/60 of a second has passed, what you'll end up viewing will be 'out of sync' (even if it catches up eventually). It's true that very early versions of Monkey had trouble synching updates with renders, but that shouldn't be true anymore(!).


Gianmichele(Posted 2014) [#15]
Thanks Mark, that helps quite a bit!


Sammy(Posted 2014) [#16]
My main reason for being stuck with delta timing is that my game is multi platform, which means that each platform has it's own update rate and FPS, to adjust for the general lack of hardware resources. Delta timing provides a steadying influence for game timing in general.


Gerry Quinn(Posted 2014) [#17]
I was curious about this, and I found an interesting link about how things currently work on Android:
http://www.androidpolice.com/2012/07/12/getting-to-know-android-4-1-part-3-project-butter-how-it-works-and-what-it-added/


Liquid(Posted 2014) [#18]
Hi all.

Well, I still didn't see something that I could call a smooth scroll in Monkey. The first example in 9th post is the smoothest scroll I got in my machine, from all tests I made/see, but it still has some stutter.

For example, TinyThor stutters as hell. So I am surprised to know that it runs well in another machine.

I have a recent GPU (GTX 660 Ti) and all games I have run without any visible problems. Scrolls made in Blitzmax, XNA, MonoGame, Libgdx run smoothly... but not in Monkey.

I still didn't buy Monkey because of this issue.

I would like to find out what is causing this.


muddy_shoes(Posted 2014) [#19]
The only way of knowing "what's causing this" is to look at a specific example on a specific platform. There's no one cause of the issues that get vaguely described as "stutter" because they're not all the same issue. Things that can cause stuttery or jerky scrolling:

* Uneven frame rendering at a platform level. Some platforms just don't offer an even render rate. HTML5 and Flash in particular can show wobbly framerates. Note that neither HTML5 or Flash define a singular platform with known behaviour either. Flash on Chrome is far worse than Flash on IE for me. With HTML5 the situation is reversed. This can all change from one browser version to another.

* Sub-pixel rendering strategies. If you're scrolling by fractional increments then you're at the mercy of how the underlying render engine deals with sub-pixel accuracy. This can produce perceptible wobble and seaming with tiled scrollers. If you round the values off yourself you can avoid seams but still end up with visibly uneven scrolling as the approximation hops back and fore across the "real" scroll position.

* Missing the frame due to code performance. The most obvious source of issues and where GC problems might be at the root.

* Missing the frame due to a mismatch between Mojo's update timing and actual frame rendering. Mojo regulates the update via wall-time, not via a frame-sync. Real-world refresh rates aren't exact. This means that, even if your code runs well within the frame, Mojo's timing will eventually drift off the displayed frame and either you'll get a double render of a game state or a double update which effectively drops a frame. Again, this behaviour will be variable across platforms and devices.

So, for any given example of a glitchy scroll you should first determine which of these situations you're in (or some other situation I haven't accounted for). With any luck you discover that your code is running too slow to hit the frame, you're spinning off too many short-lived objects and causing GC issues or that you can pin your scroll speed to an integer to fix your stutter. If you're unlucky you'll discover that you're trying to create a frame-locked arcade-smooth scroll in a browser.


Grey Alien(Posted 2014) [#20]
Back in the day I made my BlitzMax framework do totally smooth scrolling with a weird combo of fixed rate logic and delta timing plus making sure that VSync was used in Windowed mode (or course people can override a game's vSync usage in their videocard driver and so your timing system needs to work with VSync off as well).

However, I've seen many casual and indie games that have bad scrolling do REALLY well and make tons of money and so I've come to the sad conclusion that it doesn't really matter. Most customers either don't really notice or don't care as what grabs them is the game story/theme/graphics/mechanics etc. not the scrolling tech.

As I was mostly planning to use Monkey for Flash games, which never really run smoothly but still can get millions of plays, I decided to not care about the issue.

However I did notice that scrolling in Monkey, or in fact just moving a sprite smoothly across the screen, is a bit jerky for GLFW windowed mode builds on PC (it's fine on iPhone/iPad and improved on Mac but not perfect). It doesn't matter if I move a fixed integer amount or a fixed floating point amount (sprite is anti-aliased when draw at fractional pixel coords), there is still some stuttering. Of course if you move a non-fixed amount like Mark says, it will look jittery no matter what, but I've not been doing that. This is on the same PC that runs my BlitzMax stuff smoothly btw.

It should be noted that I use an Update Rate of 60.

To be specific, what seems to happens is it's smooth for a while, then gets jittery then cycles back to smooth although there can also be random jerks. Sometimes the game starts smooth and other times it starts jittery. It even happens on therevill's platformer code above which looks horrible and jerky most of the time on my PC (as well as my own more simple stuff).

This led me to conclude the same as muddy_shoes's final point: Yes the OS/system sometimes causes a dropped frame, but it's not that. It's using OpenGL and that works fine in BMax, so it's not that. The code can be extremely simple so there's no GC issue/code performance issue. Basically it seems like the update and drawing go slowly out of sync then back into sync. Probably my video card is rendering at 59 or 61FPS or the 60Hz monkey timer is out a by a few ms per frame and those errors accumulate over time, or both.

VSync does appear to be on in windowed mode as I don't see any tearing if I draw a giant vertical moving rectangle. That's normally the best test case.


RetroRusty(Posted 2014) [#21]
Although I agree with what Grey is saying that it doesn't seem to bother most gamer's about smooth scrolling, as a programmer, it does bother me. Would you not think that your game was not as professional or well polished it could be with smooth scrolling?

I would say that Tiny Thor is the smoothest I've seen, but it's not perfect. Is it simply that Monkey has to cater for many platforms or is it something different? With that being said it does concern me that Monkey perhaps isn't suitable for Windows/Mac games but more suitable for mobile platforms. I could be completely wrong on this and I truly hope that I am, but from what I've seen, Monkey/GLFW seems limited in capabilities. Anyone think the same as this or have an opinion about it?


Liquid(Posted 2014) [#22]
Hi muddy_shoes,

Yes I know the routine...I made my post in a hurry and probably I didn't express correctly.

Until now real life didn't allow me to spend needed time for testing Monkey. I ran several examples (in GLFW) and what I saw was stuttering in most of them. I was to make a post to check if this was happening to someone else but never did that post.

When I saw this thread where the poster said that in tiny thor the scroll was smooth I had the confirmation that something is wrong. Why? Because when I talk about stuttering in tiny thor I'm referring of big jumps in the scroll/animation. So when I wrote the sentence "I would like to find out what is causing this" in reality it was a note to myself.

I find out why I don't see a smooth scroll. I don't know why it happens but tiny thor is running at 30 FPS in my machine. For 2 or 3 times I ran the game and it was at 60 FPS, and yes, it was butter smooth. But the normal scenario is that I run the game and it runs at 30 FPS, and obviously, it has an horrendous scroll. A side effect I see when the game is running at 30 FPS is that it consumes more cpu cycles than at 60 FPS.

I thought about being something related with the gpu driver and updated to the last version but without any change (and also this doesn't happen to any other game I have).

So, does someone else having a similar issue?


muddy_shoes(Posted 2014) [#23]
My opinion about windowed-mode OpenGL games is that it's unpredictable what sort of behaviour you'll get. Simple tests on my laptop show what looks very much to me like uneven redraw at the compositing stage, which would pretty much put you in the same boat as you are with Flash/HTML5. XNA builds give me much better (although not perfect) results. I would imagine that there's going to be driver variability, which might explain why some think Tiny Thor has smooth scrolling and others don't.

As far as I'm aware this isn't something unique to Monkey. Windowed GUIs and multi-tasking OSes in general aren't really designed with guaranteed frame rates for games in mind.

Edit: I've had a try switching compositing off and it seems to confirm that the stutter is the same timing as the redraw tear so it looks to be down to Monkey's redraw timing wandering out of sync with the actual screen redraw.


Liquid(Posted 2014) [#24]
Probably you're right in your assumptions... but I can get a pretty smooth experience in windowed-mode OpenGL using, at some degree MonoGame, and Libgdx (libgdx is amazing in this regard).

But it still doesn't explain such a big difference between the frame rates. We are talking about constant 30 FPS or constant 60 FPS...


Gerry Quinn(Posted 2014) [#25]
If it's a sync issue affecting the way mojo handles updates, it should be possible to tweak mojo, at least for specific targets.


muddy_shoes(Posted 2014) [#26]
I wasn't trying to explain your issue. Whatever your problem is seems specific to Tiny Thor and/or your machine.


Grey Alien(Posted 2014) [#27]
If it is the Monkey timer drifting out of sync with VSync (and I strongly suspect it is), then it could be solved by running update way faster than 60Hz, like 200+. If that still wasn't smooth enough then adding in some fixed rate logic or delta timing/tweening to that should probably finish the job.


Nobuyuki(Posted 2014) [#28]
If it is the Monkey timer drifting out of sync with VSync (and I strongly suspect it is), then it could be solved by running update way faster than 60Hz, like 200+. If that still wasn't smooth enough then adding in some fixed rate logic or delta timing/tweening to that should probably finish the job.


I'm agreeing with this one. Just did a quick visual test of my own to see if I could validate my suspicions with a simple sine scroller. There were much less hiccups with double the update rate. I was still using frame timing using a frame time multiplier -- you can delta-time with Millisecs() but I haven't tested yet whether increasing the update rate will make this much smoother, since I don't know what the polling rate is for the Millisecs() timer. If it's not accurate to better than 13ms then some people are going to notice stuttering no matter the update rate.

P.S. I still experienced tearing with the test at both 60 and 120 fps. According to things I've read, GLFW v2 isn't supposed to have vSync in windowed mode at all (at least on Windows), so this makes sense. When the desktop target is moved to GLFW3, this issue should go away.


muddy_shoes(Posted 2014) [#29]
It's a way to improve matters but it's a strategy with significant downsides. You're reducing your frame budget, therefore reducing the amount of stuff you can do. The result is that you end up running the user's computer hot in order to show them a fraction of the frames of a sparse game. I'd also point out that some of the targets are device refresh locked, so you'll end up with cross platform oddities if you're not careful.

GLFW 2 doesn't sync in windowed mode, but GLFW 3 doesn't guarantee it either. GL sync behaviour is driver dependent. GLFW also explicitly disallows it when windows compositing is on. That's true even in GLFW3 unless you compile with an option to allow it (which has a warning about jitter attached). If you see tearing then you've got windows composition switched off. Since Vista composition has ensured that windows are all synced to the refresh and the issue is that mojo's drawing isn't synced in the same way. Mojo renders to some memory and Windows just displays the last finished frame when it refreshes.

If you just do a few searches about vsync in windowed mode you'll see that loads of games have problems with this being unreliable. While I think mojo really should support the attempt to use it ( by doing something like calling SetUpdate(-1)) the reality is that the games dev will have to make it optional and accept that some users will have to live with stutter/tearing.

Although, saying all that, the bigger issue is getting a working fullscreen mode where vsync is fairly reliable.


Grey Alien(Posted 2014) [#30]
I'm definitely not experiencing tearing in windowed mode, so that's a bit weird (perhaps I need to test more. I'm running Windows 7). However, it's true that Full Screen is the mode that really needs VSync the most and then a reliable timing method to avoid jerking due to missing frames and double updates.

I used the 200Hz update for all my commercial casual games in BlitzMax and it has worked fine but it's true that CPU power is indeed being wasted and that it limits what I can reasonable compute in one logic frame. However, that's not actually been an issue for me so far (even back when my target was 800MHz PCs)

Anyway back to a timing method, there's NO way to scroll by an integer amount every frame and keep it the same speed on all computers as you *cannot* know what the refresh rate of the target computer is. Back in the Amiga days you knew that it was 50Hz for PAL systems and 60Hz for NTSC, and these days you can know the fresh rates of consoles and iDevices for example, so you can can code an iPhone game that has perfectly smooth integer scrolling, but you can't for PC. That's why you have to basically draw at fractional pixel coordinates to get it to look smooth, but then you run into other issues with things like tilemaps looking weird on the tile joins if all the tiles are drawn separately instead of compositing all tiles first on a texture and then "blitting" en mass to the screen at a fractional coordinate, OR using some kind of mesh thing which I never got round to doing.


Nobuyuki(Posted 2014) [#31]
I'm running XP, there is no hardware compositor, LOL. Windows 8 wouldn't have one, either, in desktop mode.
I'm sure the update rate can be finagled relative to the platform with directives -- running the game "hot" on desktop doesn't seem like it's a problem, since most machines these days should be able to handle hundreds of updates a second easily with little taxing to the frame budget. On mobile that's a different story, but also on mobile you're pretty much guaranteed to have vsync. On Android, I read in another thread that triple buffering can be forced on by requiring a higher API level than the default, and render priority on IOS is so high that if you're seeing problems there, it's probably something else, so this trick probably isn't necessary on those platforms anyway.


Grey Alien(Posted 2014) [#32]
@Nobuyuki Seems we posted at the same time as each other. Yeah agree that running "hot" on a modern PC/Mac isn't an issue unless your game is CRAZY, and that there's no need on iOS due to 60Hz fixed refresh, although they could potentially change that in the future...


marksibly(Posted 2014) [#33]
Ok, I've just pushed a version of the desktop target file 'glfwgame.cpp' containing a tweak that might help with smoothness here:

https://github.com/blitz-research/monkey/blob/develop/targets/glfw/modules/native/glfwgame.cpp

You'll also need to comment out the 'glfwSwapBuffers' lines from modules/mojo/native/mojo.glfw.cpp for it to work, or you'll get REALLY bad flickering! This is kind of a WIP...

The basic idea is that update rate 0 is for 'free running' sync, and means your app will simply run as fast as it can. OnUpdate/OnRender will be called in sequence (one update per render) with the internal 'flip' functioning as timing. This will(?) generally mean vsynced 60hz behavior for all targets, except possibly for exotic desktops or if you force vsync off with something like GLFW_SWAP_INTERVAL=0.

I also knocked up a little smoothscroll demo, with both monkey and bmx versions. Neither is 100% absolutely smooth on Windows 7, but I think the monkey one is an improvement! Anyway, it should be running logically equivalent to the bmx one.

It's hard to tell precisely how this will work on 'all' PCs. By default, my PC seems to sync at 60hz by default when you flip, and you can set swap interval to 0 for crazy fast behavior - but I'm not sure how universal this is. I'm hoping it'll all pretty consistent on Vista and later...guess we'll find out.

I also think update rate 0 should probably be the default update rate - 'no updates' has always been a bit of a bummer update rate wise!

Monkey version - desktop target only right now!


Bmx version:



muddy_shoes(Posted 2014) [#34]
"I'm running XP, there is no hardware compositor, LOL. Windows 8 wouldn't have one, either, in desktop mode."

As far as I'm aware the situation is actually completely the opposite. The DWM compositor is always on and without an option to switch it off in Windows 8.

I'm also not sure what you mean by machines being able to handle hundred of updates per second easily. Updates doing what? There's no modern machine magic that gives infinite rendering and CPU up to x FPS. Sure, simple games on powerful machines might be able to get away with pumping out wasted frames. More complex games with a bunch of visual effects going off being played on a low-end machine won't. I can assure you that I notice if a game kicks my laptop's fan into high gear and starts eating the battery for no apparently good reason.


muddy_shoes(Posted 2014) [#35]
Mark, the windowed vsync doesn't work on my not very exotic Intel chipset laptop.


marksibly(Posted 2014) [#36]
> Mark, the windowed vsync doesn't work on my not very exotic Intel chipset laptop.

What OS? Xp, Vista etc?

I'm hoping that at least Vista+ might be consistent, but maybe not...

How does it look with GLFW_SWAP_INTERVAL=0 and SetUpdateRate 60? OK-ish?

Is fullscreen OK?


muddy_shoes(Posted 2014) [#37]
Windows 7.

SWAP 0 and Update 60 looks the same as before your change.

Fullscreen with SWAP 1 works, in that the rate is limited but it's not smooth.

Edit: I don't think the hiccups in fullscreen are sync related though. They're not neatly periodic like the windowed jumps.


Grey Alien(Posted 2014) [#38]
Sorry Mark I couldn't get it to compile after downloading your new file and modifying the module. Probably I screwed up or it's because I'm using Visual Studio to compile or something else dumb, I'm not good with this stuff. Currently I have to put #GLFW_USE_MINGW=False at the start of all my monkey code otherwise nothing compiles, I guess I don't have MinGW properly installed although I thought I had it installed for BlitzMax to work.

I get this error on compile:

..\main.cpp(2380): error C3861: 'gc_ext_malloced': identifier not found [C:\Dropbox\Monkey\Jake\Test\marksscrolltest.build\glfw\vc2010\MonkeyGame.vcxproj]

Happy to test a bit if I can get past this error.


Grey Alien(Posted 2014) [#39]
The occasional OS/background task hiccup is normal and can't be avoided. But frequent jerking is due to mistiming. It should be fairly obvious to see the difference.


Grey Alien(Posted 2014) [#40]
Anyone wanting to exit from the full screen version should probably add import os to the top of Mark's code and then

		If KeyHit(KEY_ESCAPE) Then os.ExitApp(0)


inside the Update loop unless there's an easier way.


marksibly(Posted 2014) [#41]
> ..\main.cpp(2380): error C3861: 'gc_ext_malloced': identifier not found [C:\Dropbox\Monkey\Jake\Test\marksscrolltest.build\glfw\vc2010\MonkeyGame.vcxproj]

You'll need to install it on top of v77b.


muddy_shoes(Posted 2014) [#42]
The differentiator is more predictability than frequency. Even that isn't a definite as you could have a regularly cycle stealing background task or a performance issue in your code that triggers in a cyclic manner.

Alt+F4 works for closing the full-screen app, by the way.

Or this avoids importing os:

If KeyHit(KEY_ESCAPE) Error ""


As for your compile issues, did you put the code changes into 77b?


Grey Alien(Posted 2014) [#43]
@Mark re: 77b: Oh Ok thx.

Btw, I tested your code as is, without module changes (but with SetUpdateRate 60), and I get occasionally patches of stuttering in Windowed mode (on my Win 7 machines) though it comes and goes as mentioned before - often it's totally smooth for quite a while. However I haven't seen any stuttering at all in full-screen mode.

I'm also not seeing any tearing at all in windowed or full-screen mode with #GLFW_SWAP_INTERVAL=1 I even sped up the scrolling and made all rectangles min 500 pixels tall which should show it up. So it's definitely VSyncing. As expected when I use #GLFW_SWAP_INTERVAL=0 I can clearly see tearing in full screen mode BUT I don't see it at all in windowed mode, which is a bit weird... Perhaps Windows is forcing VSync in windowed mode and won't allow it to be turned off?


muddy_shoes(Posted 2014) [#44]
" As expected when I use #GLFW_SWAP_INTERVAL=0 I can clearly see tearing in full screen mode BUT I don't see it at all in windowed mode, which is a bit weird... "

That's exactly what you expect in a composited window environment. The app isn't writing to the screen, it's writing to a buffer and Windows constructs the final synced screen update.


Grey Alien(Posted 2014) [#45]
Ah Ok makes sense.

I just ran the BMax example and in Windowed mode it stutters badly all the time, worse than Monkey, but is nice and smooth in DirectX if I comment out the SetGraphicsDriver line. In Full Screen mode it's fine with OpenGL and DX. Totally smooth.

Also for a wacky experiment I ran the DX BMax version in windowed mode alongside the Monkey windowed version. The DX version remained smooth and I could see the Monkey version go through patches of stuttering.

So anyway, with the unmodified version on Monkey on my system I'd say it's 1) as good as BMax when in Full-screen mode, 2) better than BMax OpenGL in Windowed mode, 3) worse than BMax with DX in Windowed mode. If that makes sense.

Of course that's just my system and it may be totally different on other people's.


Nobuyuki(Posted 2014) [#46]
curious to know: if SetUpdateRate(0) sets a 'free running sync', will we have to rely purely on Millisecs() to achieve a steady movement? increments in OnUpdate() can potentially go uncapped into hundreds of updates between frames, with OnRender() still being called at max hz rate of device? Or is UpdateRate locked maximum to whatever the max render rate is.....

I wonder if this would be a sound way to use delta timing to move things on a simulated frame-time target. The higher the update rate, the higher resolution Millisecs() has to be to provide a smooth/accurate experience. Particularly, when going into the hundreds of updates per frame, the difference between 3 and 4ms in the elapsed time between update cycles translates to a whopping 83 simulated frames (over a whole frame's worth of movement at a 60fps target):
Const TARGET_FRAMERATE = 60
Field DT:Float = 1.0 / float(TARGET_FRAMERATE)  'Delta time target
Field lastMs

Field x  'moving target

Method OnUpdate()
  Local framesElapsed:Float = (Millisecs() -lastMs) / (DT * 1000.0)    'Frame time multiplier
  x += 1*framesElapsed  'move X across the screen steadily as if moving 1px every frame at a simulated frame rate of 60fps.

  lastMs = Millisecs()
End Method


(Edit: to elaborate, if uncapped speed provides over 250 updates a second, the smallest unit of resolution we can currently hope to achieve from our timer can tell the difference between 250 updates/sec and 333 updates/sec, but no finer. 83 updates can occur in this span, and the delta multiplier will be off by a maximum of 6.25% per update at the simulated framerate we've set. Maybe elapsed time should be determined in OnRender() instead.... hmm....)

P.S. Cool feature, nonetheless. I'm curious about whether we will be able to set a "cap" on this new update rate, since it'll no longer be fixed to a hard update target, if it ever was. I admit I don't know what running SetUpdateRate() at speeds higher than the device can handle actually does.....


Grey Alien(Posted 2014) [#47]
@Mark: OK got the modified modules working, Unfortunately it stutters worse in windowed mode for me with SetUpdateRate 0 and #GLFW_SWAP_INTERVAL=1 (with interval=0 I get super fast scrolling due to no vysnc or internal timing). The stutter actually seems to have a regular pulsing to it. It's fine in full-screen mode.

Perhaps I should just conclude that:

- OpenGL in windowed mode is screwed on my machine in Monkey and BMax.
- DX windowed mode is fine in BMax
- Full screen is fine in monkey and BMax.

Ok it's 5am here, I gotta bail!


muddy_shoes(Posted 2014) [#48]
@Nobuyuki

No, the point isn't to enable the app to run at max_fps. That only occurs if vsync is off (or not working). The point is to try and ensure exactly one update and render per screen refresh (providing your code runs fast enough).

In such an environment you do need to time the frame, even if only to work out what your base fixed rate is. You're also still left with the usual issues of what to do if a particle effect or collision or whatever causes you to miss frames and that's where you still might want delta timing. There are also other strategies like adaptive vsync where you vsync unless you're missing the frame, at which point you remove the sync to avoid dropping to half the frame-rate.

I think Monkey could do with offering higher precision timing where the target supports it anyway. Millisecs are far too coarse for timing a lot of things.


Grey Alien(Posted 2014) [#49]
There are a lot of issues with high precision timers including on multi-core CPUs etc. Also there are older depreciated precision timers and newer ones in Windows. Had a discussion about it with a bunch of Vancouver devs recently. It may not have a proper solution that works everywhere. I have found Millisecs() to be fine for my purposes to be honest in BMax, It isn't out by more than 16.7ms (a single 60Hz frame) that's for sure though I heard some reports that it might only be accurate to 3-4ms on some systems. Still, that's good enough for most timing purposes.


marksibly(Posted 2014) [#50]
> Mark, the windowed vsync doesn't work on my not very exotic Intel chipset laptop.

Just to clarify, by 'doesn't work' do you mean everything just wizzes by really fast, or it's going at 60fps but it's 'lumpy'?

Another thing for people to try in windowed mode is update rate 0 with #GLFW_SWAP_INTERVAL=-1 (this is actually the default, it means don't set swap interval at all).

According to the glfw guys, setting swap interval on vista+ can cause jittering. I get minor jittering here either way but it's probably worth a shot.


muddy_shoes(Posted 2014) [#51]
Doesn't work as in the frame rate isn't limited. SWAP -1 is no different.

As I mentioned above you need to compile GLFW with a specific switch to enable sync with DWM.


Nobuyuki(Posted 2014) [#52]
I derped a bit here and was using v75d instead of 76d, so vSync wasn't working because #GLFW_SWAP_INTERVAL wasn't implemented yet. vSync works fine over here. I can see what people mean about the slowdowns, though. It chugs a lot for me during startup. Though that could also be from differences between msbuild/mingw, since this is the first version I've built with mingw.


marksibly(Posted 2014) [#53]
> As I mentioned above you need to compile GLFW with a specific switch to enable sync with DWM.

That's for glfw3 only I think - coming soon! Even then, it just enables/disables the 'normal' gl swapinterval extension used by glfw2, it doesn't using a different swap API AFAICT. This is apparently because DWM vsyncs anyway and using gl swapinterval can cause jitters.

Which suggests you can't enable vsync in windowed mode at all on your machine?

Have you got DWM/'desktop composition' disabled in the OS.

Have you got vsync 'always disabled' in the graphics driver control panel?


muddy_shoes(Posted 2014) [#54]
The reports from above are with composition enabled, which is why I mentioned GLFW's compile option.

VSync is enabled (or in, Intel terminology, Async is disabled). On or off makes no difference.


Grey Alien(Posted 2014) [#55]
@Mark as requested I did some testing with update rate 0 with #GLFW_SWAP_INTERVAL=-1

I found no difference in windowed mode (still stuttering) and full screen mode (perfect).