• ### Announcements

#### Archived

This topic is now archived and is closed to further replies.

# Framerate to low..why??

## Recommended Posts

Hi, i am trying to make a little Engine by myself (my first steps in 3D)..D3D is amazing. But I have a little (big?) problem with the Framerates. I have a single textured Cube and the Framerates I get dont go above 25 on my GeForce2MX. The Direct3D Examples in the SDK are so much faster! I have tryed a lot...here is the Code of the D3D Init and the Renderloop. I hope you can see whats wrong. Thanks!! The Direct3D Init-Part:

//3D Device init

HRESULT DX3D::InitialiseD3D(HWND hWnd)
{

g_Font = NULL;
//create D3D Object

g_pD3D = NULL;
g_pD3DDevice = NULL;
g_pD3D = Direct3DCreate8(D3D_SDK_VERSION);
if(g_pD3D == NULL)
{
}

//get Screenmode

D3DDISPLAYMODE d3ddm;
d3ddm.Format = CheckDisplayMode(resx,resy,32);
d3ddm.Width = resx;
d3ddm.Height = resy;

//Properties

D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));

if(ScreenMode == 1)
{
d3dpp.Windowed = TRUE;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.EnableAutoDepthStencil = TRUE;
}
else
{
d3dpp.Windowed = FALSE;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.BackBufferWidth = d3ddm.Width;
d3dpp.BackBufferHeight = d3ddm.Height;
d3dpp.hDeviceWindow = hWnd;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.EnableAutoDepthStencil = TRUE;
}

//pure HARDWARE

D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &d3dpp, &g_pD3DDevice)))
{
}

//turn on Z-Buffer

g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
//back face culling

g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

//turn off Cursor

ShowCursor(false);
return S_OK;
}
//Mmethod for getting the displaymode

D3DFORMAT DX3D::CheckDisplayMode(UINT nWidth, UINT nHeight, UINT nDepth)
{
UINT x;
D3DDISPLAYMODE d3ddm;

for(x = 0; x < g_pD3D->GetAdapterModeCount(0); x++)
{
if(d3ddm.Width == nWidth)
{
if(d3ddm.Height == nHeight)
{
if((d3ddm.Format == D3DFMT_R5G6B5) || (d3ddm.Format == D3DFMT_X1R5G5B5) || (d3ddm.Format == D3DFMT_X4R4G4B4))
{
if(nDepth == 16)
{
return d3ddm.Format;
}
}
else if((d3ddm.Format == D3DFMT_R8G8B8) || (d3ddm.Format == D3DFMT_X8R8G8B8))
{
if(nDepth == 32)
{
return d3ddm.Format;
}
}
}
}
}

return D3DFMT_UNKNOWN;
}

//Renderloop:

void Render()
{
char* fr = GetFrameRate();

if(ddo.g_pD3DDevice == NULL)
{
return;
}
//clear Backbuffer

ddo.g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x000000, 1.0f, 0);
//begin Frame

ddo.g_pD3DDevice->BeginScene();
/*Todo*/
//set camera & perpective

ddo.SetupCamera(playerpos_x,playerpos_y,playerpos_z);
ddo.SetupPerspective();

cube.rot_y+= 0.5f;
cube.posx = 81.7f;
cube.posy = 51.7f;
cube.posz = playerpos_z+5.5f;
cube.meshRender(0x3FFFFFFF);

//Textout

ddo.TextOut("FPS: ",10,10, 18);
ddo.TextOut(fr,50,10, 18);

//End the scene

ddo.g_pD3DDevice->EndScene();
//Hintergrundbuffer flippen

ddo.g_pD3DDevice->Present(NULL, NULL, NULL, NULL);

}

[edited by - AxelFR on May 7, 2003 1:39:07 AM]

##### Share on other sites
I''m not familiar with whatever library you''re using, but if TextOut is like the Win32 TextOut function and uses the HDC of the screen then that might be slowing things down. Grabbing the screen DC is very slow.

What I did before creating a font engine was silently log the number of frames rendered and the time elapsed. When the user presses a key, I save the value (NumFrames/TimeElapsed) to a file. That value is the average FPS and this method doesn''t slow things down at all.

~CGameProgrammer( );

##### Share on other sites
I am not using the Win32 Function. I have this from a tutorial:

  void DX3D::TextOut(char* string, int posx, int posy, int fontSize){	//font-definition	LOGFONT LogFont = {fontSize,0,0,0,FW_NORMAL,false,false,false,DEFAULT_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH,"Arial"};	RECT FontPosition;	//fill font structure	FontPosition.top = 10;	FontPosition.left = 10;	FontPosition.right = resx;	FontPosition.bottom = resy;	D3DXCreateFontIndirect(g_pD3DDevice,&LogFont,&g_Font);	g_Font->Begin();											FontPosition.top = posy;	FontPosition.left = posx;	g_Font->DrawText(string,-1,&FontPosition,DT_LEFT,0xffffffff);	g_Font->End();}

##### Share on other sites
Why are you creating the font every time you want to draw text?

And there''s a much much better way to do text. Basically you draw all the characters in a font (128 or so is all you need) to a texture and keep track of where all the letters are using Win32 functions. Then during runtime you just reference the texture and draw letters using quads. It''s significantly faster. As an added bonus the complete source for doing that is included with the DX8 SDK. With a bit of tweaking it works with OpenGL as well.

For now, stop drawing text and see what frame rate you get by logging it as was suggested. Worry about fancy font tricks after you get your framerate to a reasonable level.

Ben

##### Share on other sites
Unless SetupCamera is just for updating the camera it would be called in a setup function rather than internally. Although it should still make no or little difference to the framerate. I also notice that unless you''re going for some trippy special camera-effects, changes to the perspective should also be avoided in the main render loop - should only be done once. (Although if a call to UpdatePerspective was added you could make add to some effects like dreaming, halicinations, warping or nightmare distortions, etc.. )
I''ve also noticed that some text/font rendering classes can cause some considerable slowdown (5-10fps). A really optimized font renderer would be handy.
One thing I''d definately try to do though, is create an external module that intelligently enumerates the devices and display modes for the most optimal settings possible at startup (with option to manually modify settings). You want as much hardware processing and as little default software buffer/reference rasterization as possible.
Still, I find myself puzzled by this 25fps phenomenon. Must be something big. Some huge hidden bottleneck. Maybe some loop that''s nest-looping more than it needs to unoticed somewhere else? I dunno?

##### Share on other sites
Yep, ID3DXFont is very slow !
I suggest that you use the CD3DFont (d3dfont.cpp/h) included in the DX SDK. Much faster!

Secondly, creating the font with each call to TextOut is a performance killer.

So,

a) Don''t use ID3DXFont, create your own or use the SDK''s
b) Create your Font Object once at Init time

##### Share on other sites

- font creation in the D3D-init-method..not every frame
- killed setupPerpective and setupCamera from the Renderloop

The result is a gain of 1 single frame/s. :-(

##### Share on other sites
Just start remming out lines and see what happens. If the bottleneck isn''t readily apparent then you just have to start taking things out and see how performance is affected.

Ben

##### Share on other sites
Ok..the empty Renderloop without any Objects results in 45 Frames/s. I think 450 would be more real.

Maybe the Problem is in the D3DInit Method? Mmhh..

##### Share on other sites
Ah, I think I got it. You''re using vsync! For fullscreen, the presentation interval should be D3DPRESENT_INTERVAL_IMMEDIATE.

Otherwise, the problem could be that the Render() function is not called often enough; in other words, your Windows message-loop code could be wrong. You should show us the code that calls Render(), in case it is the problem.

~CGameProgrammer( );

##### Share on other sites
Are you sure you are calculating the frame rate correctly? Maybe you''re just off by a factor of ten in the calculation. I doubt the problem is vsync, since 25Hz would be a rather uncommon refresh rate

##### Share on other sites
Yeah but technically it was a problem so I pointed it out. But you're right; the framerate counter could be wrong. However if you count a number of frames and take the time elapsed, that will minimize the effect of unprecise timers... if that is the problem.

~CGameProgrammer( );

[edited by - CGameProgrammer on May 7, 2003 7:01:09 PM]

##### Share on other sites
why is fr a char*?

You should be returning an int and then sprintf to store the result in a string which is then outputted instead of using 2 TextOuts.

char fr[256];
sprintf (fr,"FPS: %i",GetFrameRate());
TextOut(fr);

Also, how is your framerate being calculated? It''s probably wrong. An empty render loop should get you thousands of frames per second since you''re not drawing anything and therefor not limited by VSYNC.

45 is also not a valid VSYNC. He should be getting at least 60fps if that were the bottleneck.

Ben

##### Share on other sites
True, but if he did fix the bottleneck then he''d wonder why it only added 15 fps, so I''m just mentioning the vsync thing now

~CGameProgrammer( );

##### Share on other sites
Hi..its me again. :-) I dont think the calculated framerates are wrong. You SEE it..nearly a slide-show. Maybe the GeForce2 100 cant get any more fps. I changed the D3D Init Method a little bit. Original copy from a tutorial. But no result. Still only 100 fps in an empty scene.
Here are the code-snippets for the FrameCounter and the GameLoop Methods:

  //calculate the frameratechar* GetFrameRate(){	CurrentTime = timeGetTime();	TimeElapsed = (int)(CurrentTime - LastTime); 	FrameCount++;			if(TimeElapsed > 1000)	{		Frames     = (int)(FrameCount /  TimeElapsed);		LastTime = CurrentTime;		infoFrame = FrameCount;		FrameCount = 0;	}	sprintf(fps,"%d",infoFrame);	return fps;}//starts the gameloopINT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT){	    //registry windows class    WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WinProc, 0L, 0L,                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,                     "Axel1", NULL};    RegisterClassEx(&wc);    //create window	int width = GetSystemMetrics(SM_CXFULLSCREEN);	int height = GetSystemMetrics(SM_CXFULLSCREEN);    HWND hWnd;	hWnd= CreateWindow("Axel1", "Axels 3D Engine V0.1a",                               WS_OVERLAPPEDWINDOW, 0,0,resx,resy,                              GetDesktopWindow(), NULL, wc.hInstance, NULL);	//Direct Input	dInput.InitDirectInput(hWnd);    //D3D Init    if(ddo.InitialiseD3D(hWnd))    {         //show window        ShowWindow(hWnd, SW_SHOWDEFAULT);        UpdateWindow(hWnd);		        //start gameloop		initObjects();		GameLoop();    }    else	{		error("Error");	}	deInit();    UnregisterClass("Axel1", wc.hInstance);    return 0;}//the gameloopvoid GameLoop(){    //Gameloop    MSG msg;     BOOL fMessage;    PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);        while(msg.message != WM_QUIT)    {        fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);        if(fMessage)        {            //WinAPI Nachrichten abfangen            TranslateMessage(&msg);            DispatchMessage(&msg);        }        else        {            //Rendern            Render();        }    }}

##### Share on other sites
OK, the first step is to find a Direct3D tutorial which, when compiled, runs fast. Now modify it to make it more and more like your original code and find out what causes the sudden slowdown.

~CGameProgrammer( );

##### Share on other sites
All, right. Now we may be looking at vsync. 100 fps for an empty scene. 100-ish Hz is fairly common. Originally, only 45 fps was reported for the empty scene. In your D3DPRESENT_PARAMETERS you have PRESENT_INTERVAL_ONE, which is once per vsync. Try PRESENT_INTERVAL_IMMEDIATE and see if your empty scene fps goes up.

CGameProgrammer: "Mr.Saavik, you go right on quoting regulations."

<

[edited by - Dave Hunt on May 8, 2003 10:31:06 AM]

• ## Partner Spotlight

• ### Forum Statistics

• Total Topics
627637
• Total Posts
2978336

• 10
• 12
• 22
• 13
• 33