I have the DirectX-based application. And recently I found that Now()
function returns a wrong value when being called from within the main loop of my graphics engine. It gives one value being called before engine initialized and different one (usually differs 2-3 minutes back or forward) when being called in my application when graphics is started.
I found that Now()
function is a wrapper for Windows API GetLocalTime()
function. Anyone can point out what can affect the return value of this very function? I heavily use timeGetTime()
function in the main loop of my app, can it be the source of problem? Also I need to use CheckSyncronize()
function in the main loop...
Any ideas? I'm out of clues... :(
code of the main loop:
procedure Td2dCore.System_Run;
var
l_Msg: TMsg;
l_Point: TPoint;
l_Rect : TRect;
l_Finish: Boolean;
begin
if f_WHandle = 0 then
begin
System_Log('Engine was not started!');
Exit;
end;
if not Assigned(f_OnFrame) then
begin
System_Log('Frame function is not assigned!');
Exit;
end;
// MAIN LOOP
l_Finish := False;
while not l_Finish do
begin
// dispatch messages
if PeekMessage(l_Msg, 0, 0, 0, PM_REMOVE) then
begin
if l_Msg.message = WM_QUIT then
l_Finish := True;
DispatchMessage(l_Msg);
Continue;
end;
GetCursorPos(l_Point);
GetClientRect(f_WHandle, l_Rect);
MapWindowPoints(f_WHandle, 0, l_Rect, 2);
f_MouseOver := f_MouseCaptured or (PtInRect(l_Rect, l_Point) and (WindowFromPoint(l_Point) = f_WHandle));
if f_Active or f_DontSuspend then
begin
repeat
f_DeltaTicks := timeGetTime - f_Time0;
if f_DeltaTicks <= f_FixedDelta then
Sleep(1);
until f_DeltaTicks > f_FixedDelta;
//if f_DeltaTicks >= f_FixedDelta then
begin
f_DeltaTime := f_DeltaTicks / 1000.0;
// if delay was too big, count it as if where was no delay
// (return from suspended state for instance)
if f_DeltaTime > 0.2 then
if f_FixedDelta > 0 then
f_DeltaTime := f_FixedDelta / 1000.0
else
f_DeltaTime := 0.01;
f_Time := f_Time + f_DeltaTime;
f_Time0 := timeGetTime;
if(f_Time0 - f_Time0FPS < 1000) then
Inc(f_FPSCount)
else
begin
f_FPS := f_FPSCount;
f_FPSCount := 0;
f_Time0FPS := f_Time0;
end;
f_OnFrame(f_DeltaTime, l_Finish);
if Assigned(f_OnRender) then
f_OnRender();
ClearQueue;
{
if (not f_Windowed) and (f_FixedFPS = D2D_FPS_VSYNC) then
Sleep(1);
}
end;
{
else
if (f_FixedDelta > 0) and (f_DeltaTicks+3 < f_FixedDelta) then
Sleep(1);
}
end
else
Sleep(1);
CheckSynchronize;
end;
end;
the Now() is called somewhere in f_OnFrame()
function.
Finally I've found the solution. I needed to specify th D3DCREATE_FPU_PRESERVE
flag when creating a D3D device by D3D.CreateDevice
.
Otherwise, without that flag, all floating point operations are performed with single precision. As the TDateTime
is a simple Double
, and Now()
functions is consist of simple addition of date value to time value, it all get messed up by DirectX "smart" override.
Problem solved. It was a tricky one indeed. :)
I use to run into these issues with OpenGL and the simulator and MapObjects. The timing sequence was found to be the differences between the equipment. Here is two links that might shed some light onto the subject:
http://delphi.about.com/od/windowsshellapi/a/delphi-high-performance-timer-tstopwatch.htm Zarko Gajic's article helped with the timer that I had to build for a serial interface. I used a variation of this code example to pull data for a tank sensor.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644900%28v=vs.85%29.aspx This is the microsoft information on using high end timers in your software. Generally timers will cycle out and be off sync. This article goes into two timers, the High-Resolution Timer and the Waitable Timer Objects. The High-Resolution is the timer variant that I used for the simulator.
As far as I've understood from the code, you are making decisions on
f_DeltaTicks := timeGetTime - f_Time0;
f_Time0 variable is initialized at a later stage in the loop.
f_Time0 := timeGetTime;
there might be a simple bug, that the f_Time0 is not initialized the way you want/require on the first entrance into the loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With