Oberon Community Platform Forum
December 12, 2019, 08:40:00 AM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News:
 
   Home   Help Search Login Register  
Pages: [1]
  Print  
Author Topic: Kernel32.GetTickCount() has very poor precision  (Read 10754 times)
sage
Full Member
***
Posts: 170



WWW
« on: June 27, 2011, 09:17:36 PM »

Hi guys,
Kernel32.GetTickCount() has very poor precision and as result Win32.Kernel.GetTicks() has poor precision too.
Typical measurements (time of some frames rendering) using Kernel32.GetTickCount() compared to values obtained using precise timer:
Quote
Win32.Kernel.GetTicks(): 31  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 26
Win32.Kernel.GetTicks(): 31  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 29
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 20
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 20
Win32.Kernel.GetTicks(): 31  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 20
Win32.Kernel.GetTicks(): 31  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 19
Win32.Kernel.GetTicks(): 15  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 19
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 16
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 16
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 16
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 16
Win32.Kernel.GetTicks(): 15  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 16
Win32.Kernel.GetTicks(): 15  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 16
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 15
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 15
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 14
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 14
Win32.Kernel.GetTicks(): 15  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 12
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 12
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 12
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 14
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 13
Win32.Kernel.GetTicks(): 15  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 6
Win32.Kernel.GetTicks(): 15  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 6
Win32.Kernel.GetTicks(): 0  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 7
Win32.Kernel.GetTicks(): 0  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 7
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 5
Win32.Kernel.GetTicks(): 0  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 7
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 7
Win32.Kernel.GetTicks(): 16  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 6
Win32.Kernel.GetTicks(): 15  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 6
Win32.Kernel.GetTicks(): 0  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 13
Win32.Kernel.GetTicks(): 15  ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5): 14
It's evident that values obtained using Win32.Kernel.GetTicks() every time is multiple of 15(16)!
Following replacement of Win32.Kernel.GetTicks() makes ticks counter more precise:
Code:
PROCEDURE GetTicks*() : LONGINT;
BEGIN
RETURN ENTIER((1000 * QueryPerformanceCounter() / QueryPerformanceFrequency()) + 0.5)
END GetTicks;
It requires two functions:
Code:
PROCEDURE QueryPerformanceCounter(): HUGEINT;
VAR
t: HUGEINT;
res: Kernel32.BOOL;
BEGIN
res := Kernel32.QueryPerformanceCounter(SYSTEM.VAL(Kernel32.LargeInteger, t));
RETURN t
END QueryPerformanceCounter;

PROCEDURE QueryPerformanceFrequency(): HUGEINT;
VAR
t: HUGEINT;
res: Kernel32.BOOL;
BEGIN
res := Kernel32.QueryPerformanceFrequency(SYSTEM.VAL(Kernel32.LargeInteger, t));
RETURN t
END QueryPerformanceFrequency;
Logged
sage
Full Member
***
Posts: 170



WWW
« Reply #1 on: June 28, 2011, 07:56:04 AM »

Or, as possible better solution to provide additional module for precision timer or new functions to existing Kernel module with preserving cross-platform capability.
Logged
sage
Full Member
***
Posts: 170



WWW
« Reply #2 on: June 30, 2011, 10:42:27 PM »

I want to contribute a small demo to A2 system Wink
It's ray-casting Wolfenstein like engine, and also cross-platform PreciseTimer module.
Engine still lacks of game logic, but anyway may be useful.
« Last Edit: July 07, 2011, 09:43:23 AM by sage » Logged
sage
Full Member
***
Posts: 170



WWW
« Reply #3 on: July 07, 2011, 09:44:35 AM »

WMRaycaster.Mod now able to use multiple threads for rendering.

* WMRaycaster.zip (27.62 KB - downloaded 469 times.)
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!