Here is my first contribution to the Game Development project. :biggrin:
A fast MultimediaTimers ( release version ) routine you can use in your Games and Demos.
15 resettable timers to control your animations and other time based routines.
A FrameDelta timer to create smooth and stutter free animated scenes.
If you need a routine that also displays the frames per second, download the "MultimediaTimers.zip" in this thread:
http://masm32.com/board/index.php?topic=7060.msg75835#msg75835
.const
QPinteger struct
Low32bit dd ?
High32bit dd ?
QPinteger ends
fp1 real4 1.0
MEDIATIMERS struct ; don't change the order of the members!
Timer1 real4 ? ; 15 resettable timers to time control your animations or other routines.
Timer2 real4 ? ; The timers are updated every screen refresh.
Timer3 real4 ? ; Clear them to reset a timer.
Timer4 real4 ? ;
Timer5 real4 ?
Timer6 real4 ?
Timer7 real4 ?
Timer8 real4 ?
Timer9 real4 ?
Timer10 real4 ?
Timer11 real4 ?
Timer12 real4 ?
Timer13 real4 ?
Timer14 real4 ?
Timer15 real4 ?
TotalTime real4 ? ; Time elapsed from the start of your application.
FrameTimeDelta real4 ? ; Use this to synchronize your routines for a stutter free animation.
TicksPerSecondReciprocal real4 ? ; The next 3 members are used for internal control, don't write to it!
FrameTimeOld QPinteger <?>
FrameTimeNew QPinteger <?>
MEDIATIMERS ends
.data?
align 16
Timers MEDIATIMERS <?> ; must be 16 bytes aligned!
.code
align 4 ; Call this routine once at the start of your application
InitTimers proc uses esi ; Get frequency of the performance counter and set the time to seconds units
mov esi,offset Timers
invoke QueryPerformanceFrequency,addr [esi].MEDIATIMERS.FrameTimeNew
movss xmm0,fp1
cvtsi2ss xmm1,[esi].MEDIATIMERS.FrameTimeNew.Low32bit
divss xmm0,xmm1 ; calculate the reciprocal to get rid of a divss instruction in the UpdateTimers function
movss [esi].MEDIATIMERS.TicksPerSecondReciprocal,xmm0
invoke QueryPerformanceCounter,addr [esi].MEDIATIMERS.FrameTimeOld ; start time value
ret
InitTimers endp
align 4 ; Call this routine before the other routines at every new screen refresh
UpdateTimers proc uses esi
mov esi,offset Timers
invoke QueryPerformanceCounter,addr [esi].MEDIATIMERS.FrameTimeNew
mov eax,[esi].MEDIATIMERS.FrameTimeNew.Low32bit ; calculate the time elapsed between screen refreshes
mov edx,eax
sub eax,[esi].MEDIATIMERS.FrameTimeOld.Low32bit
mov [esi].MEDIATIMERS.FrameTimeOld.Low32bit,edx
cvtsi2ss xmm0,eax
mulss xmm0,[esi].MEDIATIMERS.TicksPerSecondReciprocal ; calculate the Frame Time Delta
movss [esi].MEDIATIMERS.FrameTimeDelta,xmm0 ; time between screen refresh updates ( multiply "FrameTimeDelta" with your animation speed for smooth animations )
shufps xmm0,xmm0,0 ; 4 copies of the FrameTimeDelta
movaps xmm1,oword ptr[esi] ; read all 15 timers and TotalTime
movaps xmm2,oword ptr[esi+16]
movaps xmm3,oword ptr[esi+32]
movaps xmm4,oword ptr[esi+48]
addps xmm1,xmm0 ; increase timers 1 - 4 with the FrameTimeDelta
addps xmm2,xmm0 ; increase timers 5 - 8 with the FrameTimeDelta
addps xmm3,xmm0 ; increase timers 9 - 12 with the FrameTimeDelta
addps xmm4,xmm0 ; increase timers 13 - 15 and TotalTime with the FrameTimeDelta
movaps oword ptr[esi],xmm1 ; update all 15 timers and TotalTime
movaps oword ptr[esi+16],xmm2
movaps oword ptr[esi+32],xmm3
movaps oword ptr[esi+48],xmm4
ret
UpdateTimers endp
Wow! Now this looks like it will be a very useful piece of code for game dev. :t
I myself have never had much success at making graphics move, but since the Game Development board opened, I've been itching to give it another shot. But sadly must wait - still no 'puter here yet. :(
Nice Siekmanski 8)
Hoping to get back on to my game today too. Wife's having visitors over - bloody housework :icon_confused:
(the capital letters are intended in a good way)
THANK YOU VERY MUCH MY FRIEND!!
The game forum is definitely taking off with everyone in full mood.
Marinus, your code will be used in my game immediately. Credit will be obviously given!
Alex, all source code I post in this forum is under the SHARE & ENJOY licence. Do whatever you want with it. :t
As ( future ) game developers we all know that on multitasking systems like Windows there is no stable vertical retrace interrupt available.
This is noticeable when animations are stuttering.
We can make the animations smooth by multiplying the frame time delta to the speed update factors.
This has some disadvantages when you want to rotate an exact amount of degrees or move an object the exact number of pixels per time unit.
So, we need a vertical retrace jitter correction factor of +/- 1.0
When we multiply this factor with our animation speed factors, we can do exact calculations that are very smooth, pixel and time precise.
I have a solution for this and will demonstrate it with a source code example in a couple of weeks from now. ( always too busy... :lol:)
In the attachment an example of the vertical retrace jitter correction factor.
With the sync thing, if you are using DX or OpenGL you can enable vSync and/or additional buffers. This will kill any jitters most of the time.
Not sure if this is possible with GDI though.
I make habit of using delta time also to make animations frame time independent.
Quote from: Lonewolff on April 14, 2018, 12:50:07 PM
With the sync thing, if you are using DX or OpenGL you can enable vSync and/or additional buffers.
Yes, but it is not stable enough.
Quote
Not sure if this is possible with GDI though.
It's been a long time ago since I have done some coding with GDI.
I think it is possible with double buffering and a nano interrupt timer to get it smooth.
Maybe caballero can provide me the masm GDI source code of the FloorWF01.exe, this would be a great example to try it on.
I will ask him.
I mean you always have varying times between screen refreshes.
On non multitasking sytems like MS-DOS you could use the hardware vertical retrace interrupt without varying times between screen refreshes and have a smooth animated scene.
Ah ok. Get where you are coming from.
I have always just divided the animation time against delta time. This way it doesn't matter if the frame rate fluctuates in extremes like 5000 FPS or 30 FPS. Animation and movement speed remains consistent.
great work Marinus :t
wouldnt it be better to put timecritical code in a workerthread so its less risk of when mainthread is switched to another process/program that you miss vertical retrace, what about setthreadpriority?
what about peekmessage with one thread switched to getmessage and workerthreads?
too much work when you use peekmessage, makes all functions in messagehandler unresponsive, if you prefer a cpu rasterizer code
I think timercode like that would be useful for synchronize everything in your game, if you decide to use several threads for different tasks so your enemy AI you put in separate thread isnt unsynchronized with animation thread etc
Isn't SetThreadAfinity a 'serving suggestion' only?
From what I understand Windows has the discretion to assign threads to another core regardless of where you tell it to run.
Quote from: daydreamer on April 14, 2018, 09:22:19 PM
great work Marinus :t
wouldnt it be better to put timecritical code in a workerthread so its less risk of when mainthread is switched to another process/program that you miss vertical retrace, what about setthreadpriority?
what about peekmessage with one thread switched to getmessage and workerthreads?
too much work when you use peekmessage, makes all functions in messagehandler unresponsive, if you prefer a cpu rasterizer code
I think timercode like that would be useful for synchronize everything in your game, if you decide to use several threads for different tasks so your enemy AI you put in separate thread isnt unsynchronized with animation thread etc
Hi Magnus,
Maybe you can discard the whole message pump in certain Games.
As long the application is fast and the human eye and brain doesn't detect stutter in animations I'm happy.
Many years ago ( 15 or so ) I played with the Raster Status on video cards to check if the raster was in the vertical blank period or else on what scanline the rasterizer was.
I remember that the scanline position was a rough approximation so I used the timing code again.
It was not really a success because not every video card supported that function in those days.
It's worth investigate all of this stuff again and also find a way to get stutter free GDI for the people who use GDI for their games.
Yes, you can make smooth graphics with GDI. Almost the 90% of what my production is with GDI.
DirectX seems to use a buffer rectangle determinated, let's say 600x400 and if you want to see it in full screen what it does is stretch this buffer to the whole screen. That is what I have done here with the GDI templates. Some time ago made this full screen fire demo (http://abreojosensamblador.net/Productos/AOW32_/html/Pags_en/Chap03.html#VentanaPantallaCompleta), no tricky involved here, the program calculates your screen dimension and makes a buffer with this size (full screen), in my computer runs smootly. This is a very big buffer where to write to.
I wonder how faster is DirectX than GDI in fact. When I have time I will make this proof.
There's no doubt that DirectX has some advantages over GDI. It is a big library of functions prepared to be used in graphics programming such 2d and 3d that you have already installed in your pc, so the programs you made with DirectX are smaller that those made with GDI for these themes. In GDI you have to make your own graphics functions, what I find more attractive.
Regards
PS: Don't know if it is possible to make a no suttering at all graphic demo with GDI, maybe it depends on the workload of the processor at all times. I can not tell if DirectX is able to monopolize all that capacity.
GDI is a long time ago for me but, just like you I also liked it to make my own graphic functions in the old MS-DOS days.
Did some conversions of my old Amiga demo routines.
I have run your GDI FloorWF01.exe and it does stutter on my machine, does it run smooth on yours?
So for me thats an example to test if I can come up with a routine to get rid of the stutter.
About GDI vs. DirectX.
Direct3D9 is 100% hardware accelerated and you have total access to the video card so, you are not restricted to use the full capabilities of the video card.
About the big DirectX wrapper lib.
I don't like it and don't use it because there are more than 20 versions and the user needs to download the right version first before he/she can run your application.
I only use d3d9.dll ( at least available from XP up to Win10 ) and my own math and texture loader libs.
That's all I need to do fast hardware accelerated graphics programming.
I have some ideas which I still need to test and proof and if it works out, to make a function to wait for the Vertical Retrace signal from the monitor and use that in GDI applications to blit the backbuffer(s) to the frontbuffer.
I believe that the stutter in the floor demo is due to the stretching mixing one colors with others. If you increases the size of the window it runs smoothly. Please, if you have time, check it out and tell me.
Most of flickers dissapear using a double buffer, but bearing in mind that what you do between to frames has to be finished before the next starts. Another flickers appear because in two consecutive frames don't join.
If you try this version of floor demo with rigid frames, doesn't appear the flickering
The colors are stable now, but there are still stutters.
I am doing my game in GDI with plans to port it to something else in the future.
But with all the Dx talk I'm getting munchies to do it sooner.
I'm basically just blitting to back buffer and them to the window. I guess it wouldn't be too hard to implement it, would it?
First I thought of Opengl, but what the hack, I would not be able to port the masm anyway, so that wouldn't make sense.
Hi Marinus,
What's the unit for your timers and how can I output it to console?
Further, would it be possible to return the milliseconds taken by the loop and the FPS? Usually I'd like to know the milliseconds, and put it to sleep the remaining milliseconds in order to keep the FPS/milliseconds constant.
By the way, do you deal with Sleep granularity with TimeBeginTime?
The unit is in seconds.
A way to print floats in a console application:
( Possibly there are routines for this in the masm lib? )
includelib \masm32\lib\msvcrt.lib
sprintf proto C :vararg ; from msvcrt.lib
TEXT_ MACRO your_text:VARARG
LOCAL text_string
.data
text_string db your_text,0
.code
EXITM <addr text_string>
ENDM
.data?
szString_buffer db 512 dup (?)
fp8value real8 ?
.code
align 4
StdOut proc lpszText:DWORD
LOCAL hOutPut :DWORD
LOCAL bWritten :DWORD
LOCAL sl :DWORD
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov hOutPut, eax
invoke lstrlen,lpszText
mov sl, eax
invoke WriteFile,hOutPut,lpszText,sl,ADDR bWritten,NULL
mov eax, bWritten
ret
StdOut endp
PrintTimer proc
fld Timers.Timer1 ; Real4 format -> convert to real8 format
fstp fp8value ; save as Real8 format for use with sprintf function
invoke sprintf,addr szString_buffer,TEXT_("Timer: %0.06f",13,10),fp8value
invoke StdOut,addr szString_buffer
PrintTimer endp
TimeBeginTime is just wrapper code, better deal directly with,
QueryPerformanceFrequency and QueryPerformanceCounter
NtQueryTimerResolution
NtSetTimerResolution
NtDelayExecution ( 500 microseconds delay )
No, I use Sleep with the standard granularity for normal occasions
But for threaded interrupt timers ( 100 nanosecond units ) I use the 500 microseconds Sleep version to do fast synchronizations.
Which I will use in the vertical blank routine I'm writing ( hope to show it next week or a week later )
Hi Marinus!
So, I modified your first timing routine into a multi-timer for code profiling. It's still your original code,I simply made a structure from all globals so I could save individual timings in various part of the code. I intend to plot them later.
Would you review and polish it for me?
:t
Quote from: Siekmanski on May 26, 2018, 04:10:00 AM
:t
I sent you my modded code for you through MP, so we can save forum space.
Quote from: LordAdef on May 27, 2018, 09:52:07 PM
Quote from: Siekmanski on May 26, 2018, 04:10:00 AM
:t
I sent you my modded code for you through MP, so we can save forum space.
Sounds like a "don't want to share" thing... :( Shouldn't be PM? (is MP some kind of code obfuscation tactic?).
Please don't take it too personal...I was just kidding... :icon_mrgreen:
We are on a secret mission. :badgrin:
Quote from: Siekmanski on May 28, 2018, 05:10:18 AM
We are on a secret mission. :badgrin:
...to rule the world :badgrin:
Quote from: Siekmanski on May 28, 2018, 05:10:18 AM
We are on a secret mission. :badgrin:
Yep, Brazil and Holland joining to take over!
Quote from: felipe on May 28, 2018, 04:43:36 AM
Quote from: LordAdef on May 27, 2018, 09:52:07 PM
Quote from: Siekmanski on May 26, 2018, 04:10:00 AM
:t
I sent you my modded code for you through MP, so we can save forum space.
Sounds like a "don't want to share" thing... :( Shouldn't be PM? (is MP some kind of code obfuscation tactic?).
Please don't take it too personal...I was just kidding... :icon_mrgreen:
Hi Felipe, MP is Portuguese for PM, I mixed up.The code will be shared of course! And hopefully very useful
Thanks LordAdef. :t
Quote from: caballero on April 15, 2018, 05:50:42 PM
Yes, you can make smooth graphics with GDI. Almost the 90% of what my production is with GDI.
DirectX seems to use a buffer rectangle determinated, let's say 600x400 and if you want to see it in full screen what it does is stretch this buffer to the whole screen. That is what I have done here with the GDI templates. Some time ago made this full screen fire demo (http://abreojosensamblador.net/Productos/AOW32_/html/Pags_en/Chap03.html#VentanaPantallaCompleta), no tricky involved here, the program calculates your screen dimension and makes a buffer with this size (full screen), in my computer runs smootly. This is a very big buffer where to write to.
I wonder how faster is DirectX than GDI in fact. When I have time I will make this proof.
There's no doubt that DirectX has some advantages over GDI. It is a big library of functions prepared to be used in graphics programming such 2d and 3d that you have already installed in your pc, so the programs you made with DirectX are smaller that those made with GDI for these themes. In GDI you have to make your own graphics functions, what I find more attractive.
Regards
PS: Don't know if it is possible to make a no suttering at all graphic demo with GDI, maybe it depends on the workload of the processor at all times. I can not tell if DirectX is able to monopolize all that capacity.
question is,should it be possible to move GDI drawing to a workerthread for a software renderer,so on a modern multicore it ends up running on second core,not competing with GUI programming,so that ends up with the more cpu intensive graphics,the GUI gets extremely laggy???
also timer controlled code that controls so you get a steady fps only,is good,instead of unecesary ridicoulus fps is good
I ran the last zip file and had no stuttering at all, I have a Nvidia 960 that is about 2.5 years old as the single graphics card and even running the default window size for a minute or so, there were no problems at all. Win10 64 Pro OS Version.