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?
vsync x timeslice in Windows - C code?
Moderator: Moderators
Re: vsync x timeslice in Windows - C code?
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.
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!
Re: vsync x timeslice in Windows - C code?
Last I checked, Zepper's RockNES used Allegro 4. Is the workaround to rewrite it for Allegro 5?
Re: vsync x timeslice in Windows - C code?
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.
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!
Re: vsync x timeslice in Windows - C code?
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.tepples wrote:Last I checked, Zepper's RockNES used Allegro 4. Is the workaround to rewrite it for Allegro 5?
Currently, I'm looking for DirectX stuff to write a vsync function - for replacing Allegro's vsync.
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: vsync x timeslice in Windows - C code?
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.
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.
Re: vsync x timeslice in Windows - C code?
And how is this done (vsync) in other emulators, like puNES? It has a vsync option.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.
Re: vsync x timeslice in Windows - C code?
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!
- rainwarrior
- Posts: 8732
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: vsync x timeslice in Windows - C code?
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.)Zepper wrote:And how is this done (vsync) in other emulators, like puNES? It has a vsync option.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.
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.