vsync x timeslice in Windows - C code?

You can talk about almost anything that you want to on this board.

Moderator: Moderators

Post Reply
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

vsync x timeslice in Windows - C code?

Post by Zepper »

How do I write a vsync code in Windows, preferably in C?
You know... I use Allegro's vsync(), but since there's no timeslicing, the CPU usage is a bit higher (30%).

Any suggestions?
User avatar
Dwedit
Posts: 4924
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: vsync x timeslice in Windows - C code?

Post by Dwedit »

In Windows, vsyncing is done as part of the call that draws the image to the screen. This makes the screen copy call into a blocking call that will resume once vblank has happened.
In Direct3D 9, IDirect3DDevice9::Present performs the draw and vsync wait.
In Direct3D 10, it's IDXGISwapChain::Present instead.
In OpenGL, SwapBuffers will do a vblank wait if a particular OpenGL extension (WGL_EXT_swap_control) is activated.

Allegro 5 uses OpenGL. In Allegro 5, you would call "al_flip_display" to do your drawing, and before doing that, you would call "al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_SUGGEST)" before creating the display. That makes it engage the OpenGL extension to do vsync waiting. I don't know which version of Allegro you're using though, and which backend it uses to draw to the screen.

If all else fails, you can call Sleep(1) and GetTickCount() in a loop waiting for the timer value in milliseconds to be what you want, but that is not recommended at all.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: vsync x timeslice in Windows - C code?

Post by tepples »

Last I checked, Zepper's RockNES used Allegro 4. Is the workaround to rewrite it for Allegro 5?
User avatar
Dwedit
Posts: 4924
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: vsync x timeslice in Windows - C code?

Post by Dwedit »

Allegro 4 is DirectDraw based, you're pretty much screwed if you want Vsync with that API. There is no function that does Display and Vsync at the same time in DirectDraw.
If you are complete masochist, you can try reading the status of the raster if the video driver actually provides accurate information there.
Otherwise, use the loop with Sleep(1) and GetTickCount() to see if 16.666ms have passed.

You might be able to create a dummy Direct3D 9 device and have it present to an invisible window, that will kinda give you a vsync function.

edit: Oh yeah, there's also one crazy hack that works on Windows 10. (Haven't tested it on Vista, 7, or 8, and it won't work on XP or earlier)
If you call GDI GetPixel on the screen, it forces a vblank wait. This is an undocumented side effect, and may not necessarily work on all computers.

Code: Select all

HDC dc = GetDC(NULL);  //get device context of the screen itself
GetPixel(dc, 0, 0);  //get color of pixel at 0,0 of screen (triggers a vblank wait)
ReleaseDC(NULL, dc);  //release the DC
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: vsync x timeslice in Windows - C code?

Post by Zepper »

tepples wrote:Last I checked, Zepper's RockNES used Allegro 4. Is the workaround to rewrite it for Allegro 5?
Nope. In my opinion, Allegro 5 is annoying, more complicated than 4. So, I want to start writting my own stuff to get rid of it.

Currently, I'm looking for DirectX stuff to write a vsync function - for replacing Allegro's vsync.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: vsync x timeslice in Windows - C code?

Post by rainwarrior »

There's not direct access to vsync. You can't do anything meaningful / reliable in response to a vsync signal, because the GPU is in control of that stuff anyway.

As Dwedit said, Present / SwapBuffers tell the rendered image sitting in the draw buffer to be passed to the GPU, which will display it when it's ready, and these functions have the option to block to prevent them from being called more than once per vsync.

It's not really a "wait until vsync" function though, it's a "wait until the previous buffer has been presented" function. Not quite the same. Basically guarantees that in aggregate it won't go faster than your vsync rate, but doesn't actually guarantee specific timing frame to frame.

If you want it just for a stable timing of non-graphics stuff, you should really be using a regular timer of some sort. If you just want basic vsync rate limiting, though, present/swap blocking is good enough usually.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: vsync x timeslice in Windows - C code?

Post by Zepper »

rainwarrior wrote:There's not direct access to vsync. You can't do anything meaningful / reliable in response to a vsync signal, because the GPU is in control of that stuff anyway.
And how is this done (vsync) in other emulators, like puNES? It has a vsync option.
User avatar
Dwedit
Posts: 4924
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: vsync x timeslice in Windows - C code?

Post by Dwedit »

Punes uses IDirect3DDevice9::Present for D3D mode, and SwapBuffers for OpenGL mode.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: vsync x timeslice in Windows - C code?

Post by rainwarrior »

Zepper wrote:
rainwarrior wrote:There's not direct access to vsync. You can't do anything meaningful / reliable in response to a vsync signal, because the GPU is in control of that stuff anyway.
And how is this done (vsync) in other emulators, like puNES? It has a vsync option.
In general it just means the GPU's buffer present will be vsynced (i.e. no tearing), instead of just as fast as it can manage. It doesn't literally mean the code calls some kinda "vsync" function. (It can also mean more than one thing.)

For games that run at variable framerates, a lot of people prefer "vsync off" so that the game can update at, say, 200fps, polling input a lot more often and maybe having more accurate or slightly more responsive physics or something. In this case vsync is framerate limiting entirely to prevent visual tearing. (e.g. byuu seems to prefer vsync off for responsiveness' sake)

For emulators, since the framerate of the original console might not match your system's framerate, so you may want to run the emulation at the original rate and don't vsync the present so you get tearing but an accurate framerate. Or you could run the emulation at the original rate but vsync the present, so you get no tearing, but slightly less immediate visual response. Or you could run the emulation at the system's vsync rate instead, so you see every frame and it runs smoothly and polls input on each visible frame, but maybe not at the exact original frequency. So... there's at least 2 different things a "vsync" option might mean in an emulator.
Post Reply