FusionWolf
22-02-2005, 11:04 AM
Hiya all,
I have been programming a simple 2D game with the DirectX API and created a "skeleton" for the rendering engine. Then I created a sprite manager system to handle my sprites and when I started to render a simple 32x32 sized sprite to the screen (with ID3DXSprite interface) I noticed that game slows down from time to time.
Then I put up a test program where is nothing more than mainloop, a timer and DirectX initialized. Mainloop uses Windows idle time to render. Timer uses QueryPerformanceCounter() to calculate time which has been passed between calls (and FPS of course) also IDirect3D9 and IDirect3DDevice9 interfaces are initialized.
First I sat display parameters so that rendering was locked to vsync. Then I rendered a blank scene (only backbuffer was cleared) and time was measured during rendering with QueryPerformanceCounter. I Got around 50 frames per second which drops to 30 frames from time to time. Test computer was a 1.6GHz laptop which had screen set to 60Hz.
Then I sat display parameters so that rendering occurs immediatel. Then I got approx. 1200 frames per second in windowed mode which drops to around 300 from time to time ("from time to time" I mean about every 3rd second)!?!?
What the hell happens there? I have been testing my program with various different kind of computers in the place where I'm working coz there's hundred of different kind of computers, but in every computer it does the same. Only number of the frames per second changes?!?
Why the frame drops so dramatically about every 3rd second?
Here's the code....
unit uTest;
interface
uses
uGameDX, uGameTimer, SysUtils, Forms;
type
TGame = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FExitLoop: Boolean;
FTimer: TGameTimer;
protected
procedure DoLoop(Sender: TObject; var Done: Boolean);
procedure DoActivate(Sender: TObject);
procedure DoDeactivate(Sender: TObject);
public
property Inactive: Boolean read FExitLoop write FExitLoop;
property Timer: TGameTimer read Ftimer write FTimer;
end;
var
Game: TGame;
implementation
{$R *.dfm}
// Game initialization.
procedure TGame.FormCreate(Sender: TObject);
begin
// Initialize high quality timer to measure time and frames per second.
Timer := TGameTimer.Create;
// Initialize IDirect3D and IDirect3DDevice interfaces to windowed mode.
GameDX := TGameDX.Create(Self, False);
// Set notify events to seek when application is active or not.
Application.OnDeactivate := DoDeactivate;
Application.OnActivate := DoActivate;
end;
// Release objects from memory.
procedure TGame.FormDestroy(Sender: TObject);
begin
GameDX.Free;
Timer.Free;
end;
// Mainloop.
procedure TGame.DoLoop(Sender: TObject; var Done: Boolean);
begin
// Calculate time which has been passed since last call.
Timer.Update;
// Render empty scene.
GameDX.Device.BeginScene($000000);
GameDX.Device.EndScene;
// Check the rendering time and FPS
Game.Caption := Timer.FrameTime + ' - ' + Timer.FPS;
// If application is active keep looping. Otherwise halt execution.
Done := FExitLoop;
end;
// Executed when application gains focus.
procedure TGame.DoActivate(Sender: TObject);
begin
// Game is active and main loop should be executed whenever Windows has a time.
Inactive := False;
// If this is first time when this method is executed, then timer is not paused and doesn't need to resume.
if Timer.Paused then
Timer.Resume;
// Start looping.
Application.OnIdle := DoLoop;
end;
// Executed when application loses focus.
procedure TGame.DoDeactivate(Sender: TObject);
begin
// Game is inactive so don't loop.
Inactive := True;
Application.OnIdle := nil;
// Do not try to measure time if idle loop is executed anyway.
Timer.Pause;
end;
end.
Here's the code of the test application (without the timer code, but that's not the reason for the drop downs). If I remove DirectX part of this code then I get over 30 000 frames per second. With DirectX begin - end calls frames drops down to ~1200 FPS and from there around 300 FPS from time to time?!?!
These frame amounts doesn't matter now, but if I render lot's of sprites then it does. If frames is somewhere around 60 per second and then it's drops down to 30 or 20 at the moment then game slows down dramatically? What is wrong and where? I'm using Clooties DirectX headers.
edit: Ouh, I must add here that DirectX interfaces are initialized excatly the same way as DX SDK teaches.
I have been programming a simple 2D game with the DirectX API and created a "skeleton" for the rendering engine. Then I created a sprite manager system to handle my sprites and when I started to render a simple 32x32 sized sprite to the screen (with ID3DXSprite interface) I noticed that game slows down from time to time.
Then I put up a test program where is nothing more than mainloop, a timer and DirectX initialized. Mainloop uses Windows idle time to render. Timer uses QueryPerformanceCounter() to calculate time which has been passed between calls (and FPS of course) also IDirect3D9 and IDirect3DDevice9 interfaces are initialized.
First I sat display parameters so that rendering was locked to vsync. Then I rendered a blank scene (only backbuffer was cleared) and time was measured during rendering with QueryPerformanceCounter. I Got around 50 frames per second which drops to 30 frames from time to time. Test computer was a 1.6GHz laptop which had screen set to 60Hz.
Then I sat display parameters so that rendering occurs immediatel. Then I got approx. 1200 frames per second in windowed mode which drops to around 300 from time to time ("from time to time" I mean about every 3rd second)!?!?
What the hell happens there? I have been testing my program with various different kind of computers in the place where I'm working coz there's hundred of different kind of computers, but in every computer it does the same. Only number of the frames per second changes?!?
Why the frame drops so dramatically about every 3rd second?
Here's the code....
unit uTest;
interface
uses
uGameDX, uGameTimer, SysUtils, Forms;
type
TGame = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FExitLoop: Boolean;
FTimer: TGameTimer;
protected
procedure DoLoop(Sender: TObject; var Done: Boolean);
procedure DoActivate(Sender: TObject);
procedure DoDeactivate(Sender: TObject);
public
property Inactive: Boolean read FExitLoop write FExitLoop;
property Timer: TGameTimer read Ftimer write FTimer;
end;
var
Game: TGame;
implementation
{$R *.dfm}
// Game initialization.
procedure TGame.FormCreate(Sender: TObject);
begin
// Initialize high quality timer to measure time and frames per second.
Timer := TGameTimer.Create;
// Initialize IDirect3D and IDirect3DDevice interfaces to windowed mode.
GameDX := TGameDX.Create(Self, False);
// Set notify events to seek when application is active or not.
Application.OnDeactivate := DoDeactivate;
Application.OnActivate := DoActivate;
end;
// Release objects from memory.
procedure TGame.FormDestroy(Sender: TObject);
begin
GameDX.Free;
Timer.Free;
end;
// Mainloop.
procedure TGame.DoLoop(Sender: TObject; var Done: Boolean);
begin
// Calculate time which has been passed since last call.
Timer.Update;
// Render empty scene.
GameDX.Device.BeginScene($000000);
GameDX.Device.EndScene;
// Check the rendering time and FPS
Game.Caption := Timer.FrameTime + ' - ' + Timer.FPS;
// If application is active keep looping. Otherwise halt execution.
Done := FExitLoop;
end;
// Executed when application gains focus.
procedure TGame.DoActivate(Sender: TObject);
begin
// Game is active and main loop should be executed whenever Windows has a time.
Inactive := False;
// If this is first time when this method is executed, then timer is not paused and doesn't need to resume.
if Timer.Paused then
Timer.Resume;
// Start looping.
Application.OnIdle := DoLoop;
end;
// Executed when application loses focus.
procedure TGame.DoDeactivate(Sender: TObject);
begin
// Game is inactive so don't loop.
Inactive := True;
Application.OnIdle := nil;
// Do not try to measure time if idle loop is executed anyway.
Timer.Pause;
end;
end.
Here's the code of the test application (without the timer code, but that's not the reason for the drop downs). If I remove DirectX part of this code then I get over 30 000 frames per second. With DirectX begin - end calls frames drops down to ~1200 FPS and from there around 300 FPS from time to time?!?!
These frame amounts doesn't matter now, but if I render lot's of sprites then it does. If frames is somewhere around 60 per second and then it's drops down to 30 or 20 at the moment then game slows down dramatically? What is wrong and where? I'm using Clooties DirectX headers.
edit: Ouh, I must add here that DirectX interfaces are initialized excatly the same way as DX SDK teaches.