VOGONS


First post, by franpa

User metadata
Rank Oldbie
Rank
Oldbie

http://rocknes.phpbbnow.com/viewtopic.php?t=275
http://rocknes.phpbbnow.com/viewtopic.php?p=469#469 (Specifically here)

Please implement proper support for the DWM as it causes periodic visual stutter without the proper support D: (Only work-around for me is to disable Aero which means I have to put up with an ugly Windows theme)

Information and a link to the official documentation is provided by Ver Greeneyes in that thread I link to, I would be extremely grateful if support for it could be implemented.

Last edited by franpa on 2014-10-26, 10:28. Edited 1 time in total.

AMD Ryzen 3700X | ASUS Crosshair Hero VIII (WiFi) | 16GB DDR4 3600MHz RAM | MSI Geforce 1070Ti 8GB | Windows 10 Pro x64.

my website

Reply 2 of 11, by franpa

User metadata
Rank Oldbie
Rank
Oldbie

I dunno, I just thought I'd present the problem and the documentation for a solution to said problem, to you guys in one fell swoop. I've noticed the problem ever since moving to Windows 7 in very early 2010 but didn't fully understand what was wrong until I communicated the issue with the Bsnes forum where a Ver Greeneyes happily explained the cause of my problems and what is required to resolve them, sadly the solutions require work from the developers of any and all programs as I don't know how to code and thus can't fix it my self.

I can't fix it my self so I am literally at the mercy of the various developers of applications which experience this problem which is pretty frustrating to say the least.

AMD Ryzen 3700X | ASUS Crosshair Hero VIII (WiFi) | 16GB DDR4 3600MHz RAM | MSI Geforce 1070Ti 8GB | Windows 10 Pro x64.

my website

Reply 4 of 11, by franpa

User metadata
Rank Oldbie
Rank
Oldbie

Well yeah but like I said, that leaves me with horrible Windows Themes to use. I've looked at tons of custom non-aero themes and either non are to my liking or the website fails to make it easy to identify which themes are for Aero and which are not (I skip over such sites).

AMD Ryzen 3700X | ASUS Crosshair Hero VIII (WiFi) | 16GB DDR4 3600MHz RAM | MSI Geforce 1070Ti 8GB | Windows 10 Pro x64.

my website

Reply 6 of 11, by franpa

User metadata
Rank Oldbie
Rank
Oldbie
Verduga Greeneyes wrote:
There is no sure fire way to detect exactly when VBlank will occur because Windows doesn't expose a VBlank interrupt, and displa […]
Show full quote

There is no sure fire way to detect exactly when VBlank will occur because Windows doesn't expose a VBlank interrupt, and displays/GPU aren't necessarily required to generate one anyway (in addition, 'current scanline' information as given by e.g. IDirect3DDevice9::GetRasterStatus may not be accurate). As a result, programs generally poll for VBlank or rely on Direct3D/OpenGL to do it for them.

Programs present video frames during VBlank to avoid tearing, since the monitor will happily switch to the new frame mid-draw. With the compositor in Windows Vista and later versions of Windows, these programs will still detect VBlank and only present frames during it, as they think they are presenting video frames directly, when in reality the video frames are feeding into the compositor first. Frames sent to the compositor (from any running programs on the PC) will be queued up by the compositor, and merged together to be swapped/copied into place during VBlank.

Problems that can occur with this system:

1) A program polling for VBlank may miss composition. This will cause the frame to be queued up for the next composition, meaning the previous frame will be shown twice as long.

2) Worse, the next frame may not miss composition, and end up overwriting the previously queued up frame - so you end up with a duplicate frame followed by a skipped frame.

3) The program's VSync implementation may naturally fail to detect VBlank (which has only a short duration), causing it to wait until the next VBlank and risk problems 1 and/or 2.

4) These problems may even combine to generate a 'perfect storm' of duplicate and/or missed frames.

As you can see, this polling setup is not ideal, and far worse when a compositor is present. There are multiple problems that can cause a new video frame to fail to be displayed, causing a previous frame to be displayed for longer than intended and potentially skipping the new frame altogether!

The solution is to work with the compositor instead of against it. Present a new video frame immediately and afterward, call a command that will block until the compositor has completed it's task (DwmFlush). This will ensure that at most 1 new video frame is presented to the compositor between each VBlank period. As long as the compositor is active, you also won't have to worry about polling for VBlank yourself anymore.

Of course, since Windows XP doesn't have a compositor and not all users on Vista and 7 run with the compositor enabled, you will need to retain the old method of VSync detection as a fallback. But the changes required will be minor additions to your existing code, so why not handle things this way under Vista and newer?

verduga greeneyes wrote:
It might be good to give an example of the change - you're basically moving to: […]
Show full quote

It might be good to give an example of the change - you're basically moving to:

if (DWM.isEnabled()) {
present();
DWM.DwmFlush();
} else {
waitForVBlank();
present();
}

... where you might want to cache the 'isEnabled()' state (though it can change over time, so beware).

Another problem is that if you use the audio driver to synchronize your emulator, as higan does, this will block execution for at least 10ms at a time (because those are the increments in which Windows' audio service drains the buffers, except in exclusive mode WASAPI where you can set it yourself, down to 3ms or so), so if you disable video synchronization or move it off the main thread, you'll get video frames once every 10 or 20ms (depending on whether emulation progressed far enough to make one available before waiting on the audio driver for a buffer to become available).

One way to address that is to systematically insert smaller pauses (e.g. Sleep(1) with timeBeginPeriod set to 1ms), so you don't feed the audio driver in 10ms bursts. Of course you have to be careful that you don't underrun your audio buffers while doing this. My memory is a little hazy on how I implemented this in my 'vsync driver' build, but I'm sure other programmers can figure it out.

Ver Greeneyes wrote:
Right. Let's say frame n is currently being displayed. Frame n+1 misses composition and so frame n is displayed twice as long. T […]
Show full quote
Franpa wrote:

Edit: I guess a missed frame = previous frame displayed twice, and if the process was to repeat end to end it would effectively cut fps in half to 30fps with every odd* frame being displayed twice and every even* frame being undisplayed (*I can't just say "every other frame" in this example).

Right. Let's say frame n is currently being displayed. Frame n+1 misses composition and so frame n is displayed twice as long. Then frame n+2 doesn't miss composition, overwriting frame n+1 - thus frame n+1 is never displayed. Obviously this can happen for any 3 consecutive frames. If you're racing with the compositor, this is bound to happen.

Let's say you hit composition 98.33% of the time and miss it 1.67% of the time. Every time you miss it, you will eventually get an event like this, duplicating the last frame and skipping the next - in this case, it could happen as often as once a second, stuttering visibly each time. You don't need to miss often for it to be bad.

1) Let's say you have a program that polls for VBlank and only presents during VBlank, when the program detects VBlank is it detecting a signal from the compositor or the actual VBlank event it self?

That depends on the compositor. For instance IIRC the one on OSX offers a simulated VBlank somewhere halfway between composition events, so you shouldn't ever race with it. As far as I know Windows, at least with Direct3D 9, has no such protection - you get the actual VBlank even with the compositor active.

2) In addition to the above question, if the program is 100% unaware of the compositor then that means the program will only present during the actual VBlank event which means that in order for the compositor to capture the video frame and present it to the video hardware, it too must capture frames during vblank and manage to present them before the VBlank period is over... correct? There must be some pretty tight timing of events going on during that (supposed) 5ms window of opportunity (VBlank) which would be quite impressive stuff.

The compositor will always receive frames for composition, even if it can only get to them later - they just might be delayed by a refresh interval (16.7ms on a 60Hz screen). Obviously this can still cause problems, as I explained above. Also, VBlank is closer to 0.5ms in length from my measurements (it's possible there's a rounding error in there so that it could be between 0ms and 1ms, but it's definitely short). But yes, even a millisecond of work on a modern PC is a fair bit 😉 For instance on a 3GHz CPU, 1ms is 3 million cycles, and even PCIe 1.1 can transfer 250MiB/s (your GPU might not be able to keep up though). Latency between components is usually measured in microseconds (except for magnetic HDDs, which have an access time in the realm of milliseconds).

Last edited by franpa on 2017-01-22, 20:06. Edited 3 times in total.

AMD Ryzen 3700X | ASUS Crosshair Hero VIII (WiFi) | 16GB DDR4 3600MHz RAM | MSI Geforce 1070Ti 8GB | Windows 10 Pro x64.

my website

Reply 7 of 11, by franpa

User metadata
Rank Oldbie
Rank
Oldbie
aqrit wrote:
disable the dwm service or set the compatibility option "Disable Desktop Composition" for affected applications and see if th […]
Show full quote

at the mercy of...

disable the dwm service
or
set the compatibility option
"Disable Desktop Composition" for affected applications
and see if that helps

Your solution would work if switching to a Basic desktop theme or disabling the Compositor didn't strangely completely break vsync functionality in various programs that feature their own vsync implementation, including DOSBox.

AMD Ryzen 3700X | ASUS Crosshair Hero VIII (WiFi) | 16GB DDR4 3600MHz RAM | MSI Geforce 1070Ti 8GB | Windows 10 Pro x64.

my website

Reply 8 of 11, by franpa

User metadata
Rank Oldbie
Rank
Oldbie

Just an fyi, it seems WDDM 2.0 resolves the stutter issue I experience in non-exclusive fullscreen display modes as well as windowed software. It took a ridiculously long time for this problem to be solved but at least it did get resolved, and I was right all along that the problem isn't caused by ME or my hardware.

WDDM 2.0 was introduced with Windows 10 but support for WDDM 2.0 wasn't introduced to Nvidia Fermi video cards until now (Their latest drivers as of right now). So yeah, many, many patient years of waiting and hooray I can has consistent frame rendering thanks to changes to the DWM (caused by the upgrade to WDDM 2.0)!

The downside? Vista, 7, 8.0 and 8.1 will never feature the fix (WDDM 2.0 is very unlikely to be back ported) so I'm stuck with Windows 10 if I want a great desktop experience (Windows XP has lots of screen tearing on its non-vsync'd desktop).

Last edited by franpa on 2017-01-22, 19:55. Edited 1 time in total.

AMD Ryzen 3700X | ASUS Crosshair Hero VIII (WiFi) | 16GB DDR4 3600MHz RAM | MSI Geforce 1070Ti 8GB | Windows 10 Pro x64.

my website

Reply 9 of 11, by Scali

User metadata
Rank l33t
Rank
l33t

I think this is more a case of using Direct3D9Ex, and using D3DSWAPEFFECT_FLIPEX and D3DPRESENT_FORCEIMMEDIATE flag on Present().
This allows vsync'ed windowed D3D applications (as if they were exclusive fullscreen and pageflipping), and works on Windows 7 and up.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 10 of 11, by franpa

User metadata
Rank Oldbie
Rank
Oldbie
franpa wrote:

Just an fyi, it seems WDDM 2.0 resolves the stutter issue I experience in non-exclusive fullscreen display modes as well as windowed software. It took a ridiculously long time for this problem to be solved but at least it did get resolved, and I was right all along that the problem isn't caused by ME or my hardware.

WDDM 2.0 was introduced with Windows 10 but support for WDDM 2.0 wasn't introduced to Nvidia Fermi video cards until now (Their latest drivers as of right now). So yeah, many, many patient years of waiting and hooray I can has consistent frame rendering thanks to changes to the DWM (caused by the upgrade to WDDM 2.0)!

The downside? Vista, 7, 8.0 and 8.1 will never feature the fix (WDDM 2.0 is very unlikely to be back ported) so I'm stuck with Windows 10 if I want a great desktop experience (Windows XP has lots of screen tearing on its non-vsync'd desktop).

Just an FYI, I was wrong when I said WDDM 2.0 fixed the issue. Added some more info to Re: Enhanced support for Vista/7's Desktop Window Manager

AMD Ryzen 3700X | ASUS Crosshair Hero VIII (WiFi) | 16GB DDR4 3600MHz RAM | MSI Geforce 1070Ti 8GB | Windows 10 Pro x64.

my website

Reply 11 of 11, by franpa

User metadata
Rank Oldbie
Rank
Oldbie
franpa wrote:
franpa wrote:

Just an fyi, it seems WDDM 2.0 resolves the stutter issue I experience in non-exclusive fullscreen display modes as well as windowed software. It took a ridiculously long time for this problem to be solved but at least it did get resolved, and I was right all along that the problem isn't caused by ME or my hardware.

WDDM 2.0 was introduced with Windows 10 but support for WDDM 2.0 wasn't introduced to Nvidia Fermi video cards until now (Their latest drivers as of right now). So yeah, many, many patient years of waiting and hooray I can has consistent frame rendering thanks to changes to the DWM (caused by the upgrade to WDDM 2.0)!

The downside? Vista, 7, 8.0 and 8.1 will never feature the fix (WDDM 2.0 is very unlikely to be back ported) so I'm stuck with Windows 10 if I want a great desktop experience (Windows XP has lots of screen tearing on its non-vsync'd desktop).

Just an FYI, I was wrong when I said WDDM 2.0 fixed the issue. Added some more info to Re: Enhanced support for Vista/7's Desktop Window Manager

Actually, no it didn't resolve the issue 🤣. That being said, Windows 10 supports a new Presentation method that will fully resolve the anomaly, it's called DirectFlip (works best with Direct3D 11/12): https://docs.microsoft.com/en-us/windows/win3 … dxgi-flip-model

For Windows 8, 7, Vista and XP the below code snippet is still the best method according to Verduga Greeneyes.

if (DWM.isEnabled()) {
present();
DWM.DwmFlush();
} else {
waitForVBlank();
present();
}

AMD Ryzen 3700X | ASUS Crosshair Hero VIII (WiFi) | 16GB DDR4 3600MHz RAM | MSI Geforce 1070Ti 8GB | Windows 10 Pro x64.

my website