News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Vertical Retrace Sync with GDI/Win32

Started by johnsa, July 13, 2015, 11:36:46 PM

Previous topic - Next topic

johnsa

I always use a frame time delta to control animations (mainly to get it frame rate independent). But if you try and do this in software rendering (without D3D etc) i always find you get the occasional stutter..
a really classic example would be a scroller.. in the old vga days (ignoring the fact that we'd use unchained mode and latch transfers and true h/w page flipping and all the other cool stuff) you could have a full screen scroller that was 100% "smooth scrolling". I'm trying to be able to get the same degree of smoothness with s/w rendering under windows (if possible) and I think this retrace sync is the key. A long time ago even with retrace it wasn't possible under windows because context switches and things that happened even while using directdraw caused stutters.. I had a couple platformer games built with ddraw, and they always had the same issue...
smooth..smooth..smooth.. glitch... smooth..smooth..glitch while scrolling.
It looks to me thus far that these days that isn't the case because of the overall system performance and improvements in the scheduling, context switching etc that the delays are so small that it shouldn't affect a full frame (assuming you're not running a load of other cpu hungry stuff in the background).


Siekmanski

QuoteI'm trying to be able to get the same degree of smoothness with s/w rendering under windows (if possible) and I think this retrace sync is the key.

I don't think so. The only way to get 100 % smooth animation, is on a non-multitasking OS where only your program is running.
On a multitasking OS the only thing you can do to get the best "smoothness", is using the frame time delta.
And it doesn't matter if you wait for the vertical blank or not on a multitasking OS.

It's always a good thing to use double frame buffering and wait for the vertical blank interrupt to prevent "tearing".
Creative coders use backward thinking techniques as a strategy.

johnsa

Just a little demo..

Requires 64bit+avx, must run on primary monitor @ 1920x1080.

The checkerboard is "copper" generated
you can use the mouse to move it around..

The background copper bars are generated in a "fake mode" (similar fashion to Panic or 2nd Reality pseudo 15bit plasmas from the old Dos demo days) by creating 2 interlaced images and flipping them quickly and combining R/G/Bs.
2 reasons for doing it this way... 1... it's cool... and 2 ... because of the flipping and selection of colors ANY dropped frame is extremely visible to the human eye.

FPS in the top left corner.. startups with new spiffy vsync timer+rasterline timing on (so you'll see 60/61fps).

INSERT key toggles vsync/rastersync on/off.
With it off you'll see the FPS doubles (about 140fps for me).

All animations are time-delta based, so regardless of FPS for example it takes 5 seconds for the red raster bar to make full cos cycle.

this is totally un-optimised and single threaded.. I could make it a lot faster, but it doesn't need to be for the quick example.

What you'll notice, and this is the point i was trying to make.. is how much better everything is with vsync on, smoother animation (due to no dropped frames).

I've figured the way it works in windows if you're doing soft-rendering is that the DWM composites are already vsync'ed, whether you like it or not (which is why you don't see tearing), BUT it will only process 60 frames per second and will drop others, which can be intermittent depending on how the timing all works out..

For example.. if you quickly drew a red then green screen in succession..and you were getting 100fps.. you might land up with a frame sequence like:
red, green, red, red, green ..


Siekmanski

Can't test it, my monitor has a max. resolution of 1680 X 1050.
Creative coders use backward thinking techniques as a strategy.

johnsa

My bad,

I've attached a new zip with both 1920x1080 and 1680x1050 versions.
(Oddly for me the 1680 version does stutter now and then, perhaps because that's not my monitors native resolution but the 1920 is smooth smooth).

Siekmanski

Both versions crashed on my computer....
Intel(R) Core(TM) i7-4930K CPU @ 3.40GHz
Windows 8.1 64bit and AVX

Made 2 test progs, one with vsync on and one with vsync off.
Frames per second in the left upper corner.
On my computer both have smooth animations.

Creative coders use backward thinking techniques as a strategy.

rrr314159

johnsa, your program hung both my machines ... had to actually unplug, task manager was useless on one machine, the other, it wouldn't even come up. Impressive! I manage to hang them up like that once in a while also, but I'm a seasoned expert, and even I can't do it so reliably. My hat is off to you! BTW b4 it crapped out totally the debugger showed the line "mov qword ptr [rsi], rax", C00000005. Probably rsi had a 0 in it,  but couldn't check that.

But seriously - I have problems like this often (as you'll see if you check past threads) something works fine on my machine but not on others'. And it seems to happen a lot more with 64-bit. Found out recently that if I take the source code to the other machine and re-compile there, it often fixes the problem. Would love to know how to avoid it.

Have a question, you mention DWM is already v-synced (which I supposed), "BUT it will only process 60 frames per second and will drop others, which can be intermittent depending on how the timing all works out..". Now, if you're producing more than 60 FPS it's inevitable there will be dropped frames - regardless of DWM or anything else - right? There's simply no point in making frames faster than that. Or am I missing something here?

siekmanski, both your progs work fine. Both perfectly smooth. (BTW glad to see you're back to programming after goofing off for weeks :biggrin: )
I am NaN ;)

johnsa

Siekmanksi: I assume you're using D3D for your demo apps?
If so I believe the situation with hardware accelerated api's and software rendering with BitBlt type operations are quite different in this regard.
I myself have never noticed dropped frames when using ogl/d3d etc but i have seen tearing when the step sizes are large.
With software I've not seen tearing but you do get stutters.
So my belief is that due to how the gpu works and it's proximity to the framebuffer and lack of any windows compositing manager in the way it will (much like in the old vga/dos days) simply push out frames as fast as it gets it.. if the monitor happens to be half way through a draw.. tough luck you'll tear.
Software I suspect however is all being forced through the OSes normal window manager (DWM in this case with compositing) and this is internally v-synced. Making calls to StretchDiBits for example or others probably then feed data to the OS, which then drops it because it's already in the middle of a frame as it has no capability to "tear" a software buffer.

I think dropped frames is the only possibly way it can work in software if there is any part of the chain that limits the frame rate (via vsync or any other method). Unless you had an infinite queue so frames were always taken in order!

On a gpu based app, the only reasons i can see to NOT limit to vsync is that due to how vsync works, if you slightly miss it (15ms per frame) you can't get 55fps for example, it has to wait another full cycle and drop to 30fps.. which for gamers wouldn't be great. So I think the preference is to be able to achieve values between 30fps and 60fps in a game, even if it means tearing.
If you have a high enough spec and you know empirically that you always get way over 60fps, you could enable vsync on the gpu to remove the tearing.
Of course this is all starting to change now with adaptive v-sync, like gsync etc where the monitor only refreshes when it's told to .. so it's not technically running at 60hz but rather what ever the app requires.

I see that it does indeed bomb out completely on both another win8 and win7 machine but is fine on mine.
I'll try to see what is causing it.


Siekmanski

@ rrr314159
Quote(BTW glad to see you're back to programming after goofing off for weeks :biggrin: )
Hahaha... started this week with the FFT again, had some ideas for the first 2 log2 loops.
But your trick is smarter and faster than mine. Have some more ideas to improve speed.

@ johnsa
Yes, I'm using D3D9.
Maybe some other solution in software rendering is using more then one backbuffer, to average the stutter.
Although I'm not sure...

Your demo works fine now on my computer. But it's jerky.
Creative coders use backward thinking techniques as a strategy.

johnsa

For interest sake, before running the exe, try pressing Windows-D to minimize all open windows then run it and see if that makes any difference.
I assume it's jerky by default with the fps at 60 ? (I expect it be very jerky after pressing INSERT and having 100+ fps due to the dropped frames).

Siekmanski

Closing all windows makes a big difference, it's much smoother. ( now and then a stutter )
Did you have a look at my FrameTimeDelta code ?
Maybe we do it both differently, you could try my code.

You could also use D3D9 to do 2D stuff and write directly to the backbuffer or a rendersurface.
Creative coders use backward thinking techniques as a strategy.

johnsa

I'm still trying to work out why having other windows not minimized sometimes affects the vsync/stutter... it only does it now and then for me, but a win-d switch back seems to sort it out.

I normally use webgl or dx11, but this is all about non-gpu experimenting otherwise the whole vsync would have been a non-issue in the first place! :)

My delta is basically :

; For a full cos / sin cycle:
delta = (6.2832 / (FPS * secondsToAnimate) )

so if it's 60fps, and I want the animation sequence to run for 10sec, 6.2822 / 600 =  0.06deg per frame to complete the full cycle in 10 seconds. FPS is calculated each frame as 1000 / (endMs - startMs)

Siekmanski

I just calculate the time between the previous and the current frame, and use that as a smoothing factor.
It is just multiplied with whatever update speed you use. So the actual animation step is totally smooth.

See my VSyncOFF.exe example and see how the frame rate varies but the animation still runs smooth
Creative coders use backward thinking techniques as a strategy.

rrr314159

johnsa,

that version works fine. There's some stutter (I think that's what it's called). The front object in particular, when moving fastest, shows about 5 borders at once (the edge is indistinct), closely spaced. Happens a little on the checkerboard also. Minimizing other windows, also insert key, make little or no difference. Looks pretty good, not perfect
I am NaN ;)