Windowed VSync

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

WedNESday
Posts: 1284
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany
Contact:

Windowed VSync

Post by WedNESday »

I know that a lot of people say this that is not possible.

Is it possible? I could SWEAR that I have seen some NES emulators achieve it. DirectDraw is now dead so I can't use WaitForVerticalBlank anymore.

Are there any work-arounds for this?
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Windowed VSync

Post by rainwarrior »

WaitForVerticalBlank didn't eliminate tearing in windows anyway, so there's no need to lament its passing. It was more or less the same as what Present can do (except Present has many more options).

I've heard stories about getting it to work on Vista or Windows 7, but they always involved the user doing weird things to his graphics drivers. I don't know of any way to guarantee it via the game software.

My advice is to just use the standard API for double buffering with vsync, make sure it works in Fullscreen, and then forget about it for windowed mode-- at that point it's in the user's hands.

I could be wrong though; the situation may have changed in Windows 7, but if it has I haven't seen any documentation on it yet.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: Windowed VSync

Post by Near »

Direct3D 9+ has an InVBlank RenderStatus value that can be used, but it won't work on Vista/7 unless you disable Aero, and it won't work on 8 period. Forget about it with OpenGL =(

Lots of bad drivers though where they report Vblank start too far in, so you get permanent tearing near the top of the screen, should the window happen to be there.

Lastly, you can look into the DWM APIs. I haven't tried it because it's Vista+ only.
User avatar
Dwedit
Posts: 4922
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Windowed VSync

Post by Dwedit »

XNA did vsync in windowed mode using only calls to present.
But if you're really trying to avoid using Direct3D, you could use timers, polling what scanline is currently being displayed, Sleep(1), and timeBeginPeriod.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
WedNESday
Posts: 1284
Joined: Thu Sep 15, 2005 9:23 am
Location: Berlin, Germany
Contact:

Re: Windowed VSync

Post by WedNESday »

Dwedit wrote:XNA did vsync in windowed mode using only calls to present.
But if you're really trying to avoid using Direct3D, you could use timers, polling what scanline is currently being displayed, Sleep(1), and timeBeginPeriod.
How can I poll scanlines without Directdraw? Btw I'm not avoiding Direct3D far from it in fact.
User avatar
Dwedit
Posts: 4922
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Windowed VSync

Post by Dwedit »

Looks like you use "IDirect3DDevice9::GetRasterStatus" or something like that.
But figuring out how to use Present seems like the way to go.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Windowed VSync

Post by tepples »

So let me get this straight: "Present" is accented on the second syllable (pre-ZENT the verb, not PREZ-ent the adjective), and it's related to what GL calls "swapping buffers". Am I correct?
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Windowed VSync

Post by rainwarrior »

Yes, Present() is a function, and is intended in the verb sense, as most function names tend to be. Under most setups it is flipping the double buffer and displaying it to the screen.

I wouldn't try to do anything based on scanlines; scanlines are not generally relevant to modern display programming techniques, and I seriously doubt you can get reliable/useful results from GetRasterStatus, though it might be useful if you're targetting a very specific hardware setup.

You don't really have direct access to the buffer the hardware displays to the screen in windowed mode, so it really doesn't matter how you time your own stuff; the OS updates that on its own terms, you're rendering to a different buffer that gets copied onto the real screen buffer by the OS. That timing can be indirectly affected by what you do, and it might seem to give a consistent lack or tearing under certain circumstances, but it probably won't work in others. I'm not aware of any robust API for doing a proper swap during vblank, other than taking control of the screen via fullscreen mode.
User avatar
Dwedit
Posts: 4922
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Windowed VSync

Post by Dwedit »

When I tested out a minimal XNA program (one that rapidly flashes the screen red and blue every frame), I was seeing a hiccup (dropped frame) every few seconds, at other times, it was smooth and tear-free. Sometimes it ran for 11 seconds without a hiccup, other times it hiccuped after 2 seconds.
That's what direct3d Present(...) will do.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Windowed VSync

Post by rainwarrior »

Windowed mode is supposed to allow many applications share the screen space, and this may be the reason why there has never been an API for vsync the windowed display. Consider this:

1. For the majority of applications, tearing is not a problem. The only applications which require monolithic screen updates are things like animation, video, and games (and these kinds of applications tend to offer fullscreen modes, where vsync is not a problem).

2. Waiting for vsync slows down your application. It cannot continue updating until the vsync has passed. For a program that does not require vsync, this would reduce program performance with no benefit. So, the default behaviour for most applications must be not to vsync.

3. In fullscreen mode, one application has exclusive use of the screen. Your application has the option to wait for vsync, but none of the backround applications need to, and will run unimpeded. Exclusivity makes the problem of providing vsync very simple.

4. In windowed mode, you have a lot more requirements to fulfil. You don't want to slow down programs that don't need to vsync, but it's not very easy to do this. Most windowed programs are written in such a way that their screen updates need to be posted immediately before the program can proceed; forcing the OS to update its screen only at vsync, and then giving one window the ability to pre-empt that update means that all other programs are occasionally going to be waiting on the vsynced window. I dunno, it's possible to do I think, but in the context of operating system design I don't think it's an easy problem to solve. Anything I can think of at the moment carries a lot of complications.

I dunno, maybe there is a simple/elegant way to implement windowed vsync in an OS without hindering other programs, but if there is it escapes me. I suspect the implementers of Windows have felt that it's just more trouble than it's worth, and that fullscreen mode already addresses the problem of tearing sufficiently.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Windowed VSync

Post by tepples »

rainwarrior wrote:1. For the majority of applications, tearing is not a problem. The only applications which require monolithic screen updates are things like animation, video, and games (and these kinds of applications tend to offer fullscreen modes, where vsync is not a problem).
Which says what about in-webpage video (e.g. YouTube) and in-webpage games (whether Flash or HTML5)?
2. Waiting for vsync slows down your application. It cannot continue updating until the vsync has passed.
Ideally, other programs running on the system can continue updating.
For a program that does not require vsync, this would reduce program performance with no benefit.
So does waiting for a mouse click or a keypress.
3. In fullscreen mode, one application has exclusive use of the screen.
One of the screens or all of the screens? What if I have a walkthrough video running full-screen on one monitor and a game running full-screen on another, and these monitors have different refresh rates? But I guess multiple monitors on a home PC itself is an edge case that's so uncommon it's economically a rounding error.
Your application has the option to wait for vsync, but none of the backround applications need to, and will run unimpeded.
If PC vsync were an interrupt as opposed to a spinlock, they would have run unimpeded anyway.
Most windowed programs are written in such a way that their screen updates need to be posted immediately before the program can proceed; forcing the OS to update its screen only at vsync, and then giving one window the ability to pre-empt that update means that all other programs are occasionally going to be waiting on the vsynced window.
When a program calls "wait for next event", and there isn't a timer event due in the next 20 ms, then the program expects to wait.
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Windowed VSync

Post by rainwarrior »

tepples wrote:Which says what about in-webpage video (e.g. YouTube) and in-webpage games (whether Flash or HTML5)?
YouTube and a lot of other web video applications appropriately offer fullscreen modes. Flash has a fullscreen mode as part of its API, though not a lot of in-browser games use it because it does not allow use of the keyboard at the same time. I dunno if HTML5 addresses this. As a whole, people are quite used to the choppiness and tearing of video/animation in a browser window. It's ugly, but it's ubiquitous. Do you think there's a general understanding that watching video on a television is a smoother experience than watching it in a web browser?
tepples wrote:Ideally, other programs running on the system can continue updating.
That's what I said, isn't it? Actually what I'm saying is that it's critical that they do so.
tepples wrote:So does waiting for a mouse click or a keypress.
...and? I'm talking about the performance of programs that want to continue running. Programs that have halted themselves waiting on user input aren't a performance concern.
tepples wrote:One of the screens or all of the screens?
This is a good question. I do not know how well (or if) vsync works with multiple monitors. It's something I've never had to deal with. I think multiple monitor PC systems are not uncommon, but I don't think most game developers want to make that a requirement to play their game.
tepples wrote:If PC vsync were an interrupt as opposed to a spinlock, they would have run unimpeded anyway.
Yes, effective use of an interrupt is an essential part of implementing this. This is why it's good to use something like D3D's Present instead of rolling your own, since this is its normal behaviour.
tepples wrote:When a program calls "wait for next event", and there isn't a timer event due in the next 20 ms, then the program expects to wait.
The vsynced program expects to wait for a vsync, but other programs should run unimpeded. My point was that attempting to provide vsync for just windows that request it would most likely infringe on the performance of the other running programs because of how the shared screen resource must be managed. Programs can survive being forced to wait now and then, that's expected by the programmer, but for an operating system it may be a bad policy to allow a feature like vsync to cause systematic waiting that reduces performance across the board.

Smooth animation is apparently not Windows' highest priority when it's trying to provide multiple running programs access to the screen, and I think this is probably the right thing to do in the general case.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Windowed VSync

Post by tepples »

rainwarrior wrote:
tepples wrote:So does waiting for a mouse click or a keypress.
...and? I'm talking about the performance of programs that want to continue running. Programs that have halted themselves waiting on user input aren't a performance concern.
A mouse click is an event. A key press is an event. Data received on a socket is an event. The completion of a frame on a given monitor is an event. Fundamentally, these events can be waited for with the same API call, which might end up resembling select() from POSIX. Perhaps such an event might result from completion of Present().
tepples wrote:When a program calls "wait for next event", and there isn't a timer event due in the next 20 ms, then the program expects to wait.
The vsynced program expects to wait for a vsync, but other programs should run unimpeded. My point was that attempting to provide vsync for just windows that request it would most likely infringe on the performance of the other running programs because of how the shared screen resource must be managed.
Even in a modern composited environment? If a repaint handler hasn't finished, just use the texture saved when the repaint handler began. It's sort of like triple buffering.
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Windowed VSync

Post by rainwarrior »

If you design your operating system's use of video around being able to provide vsync, and thus create an API that requires that all programs that need to update the screen can be buffered and have a reasonable expectation of interacting with vsync timing, then it'd probably be relatively easy to provide vsync in windowed applications. I don't really think this is the case with Windows. It is the case with Direct3D, and other APIs developed around games or animation specifically, but the Windows API itself offers a lot of ways to get things done.

Programs that double buffer are generally already set up to operate in a way that is germane to vsync, and a common API for double buffering is really all that is needed. However, while double buffering is almost always a requirement for animation programs (even when vsync isn't expected), this is not the case at all for general UI programming. You could wrap everything in double buffers, but when you start wrapping single buffered behaviour in double buffers you end up doing a lot of duplicating actions, blitting unnecessary data, etc., and there are a lot of programming patterns sensible in single buffering that would become pathological performance cases when shoehorned into a double buffering system.


Anyhow, I'm no expert on the inner workings of Windows' implementation. I'm just speculating that the design decision not to provide a mechanism for vsync in windowed applications may have been a sensible choice to make.
doynax
Posts: 162
Joined: Mon Nov 22, 2004 3:24 pm
Location: Sweden
Contact:

Re: Windowed VSync

Post by doynax »

You can always try rendering to video overlays instead of the regular back-buffer. These basically provide an independent swapping chain on top of the regular display, typically used for video playback by media players.

There's plenty of downsides though. They're optional, have only one channel, use hardware-dependent YUV formats, are unsupported on Vista, use a new interface on Windows 7, won't work across multiple-monitors, etc.

If you're dead-set on avoiding tearing at all costs then they're probably the way to go. Just be sure to have a fallback.

Or, you know, just pray your users have Aero enabled and a properly configured system..
Post Reply