It is currently Sun Mar 26, 2017 7:50 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 9 posts ] 
Author Message
PostPosted: Sun Mar 05, 2017 5:36 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 2962
Location: Brazil
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?


Top
 Profile  
 
PostPosted: Sun Mar 05, 2017 6:45 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3791
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!


Top
 Profile  
 
PostPosted: Sun Mar 05, 2017 6:49 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 17984
Location: NE Indiana, USA (NTSC)
Last I checked, Zepper's RockNES used Allegro 4. Is the workaround to rewrite it for Allegro 5?


Top
 Profile  
 
PostPosted: Sun Mar 05, 2017 7:06 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3791
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:
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!


Top
 Profile  
 
PostPosted: Sun Mar 05, 2017 7:28 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 2962
Location: Brazil
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.


Top
 Profile  
 
PostPosted: Sun Mar 05, 2017 7:53 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 4906
Location: Canada
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.


Top
 Profile  
 
PostPosted: Sun Mar 05, 2017 7:57 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 2962
Location: Brazil
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.


Top
 Profile  
 
PostPosted: Sun Mar 05, 2017 9:02 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3791
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!


Top
 Profile  
 
PostPosted: Sun Mar 05, 2017 9:17 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 4906
Location: Canada
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group