Framerate to low..why??

Started by
15 comments, last by AxelFR 20 years, 11 months ago
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)
    {
        error("DirectX 8.1 not found!");
    }

    //get Screenmode

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

    //Properties

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


	d3dpp.SwapEffect     = D3DSWAPEFFECT_DISCARD; 
	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

		if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 
                                   D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &d3dpp, &g_pD3DDevice)))
		{
			error("Your Card is not supported.");
		}

	//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++)
	{
		g_pD3D->EnumAdapterModes(0, x, &d3ddm);
		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]
Advertisement
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( );

~CGameProgrammer( );Developer Image Exchange -- New Features: Upload screenshots of your games (size is unlimited) and upload the game itself (up to 10MB). Free. No registration needed.
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();}  
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
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?

(>-<)
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
<$1,000,000 signature goes here>
Thanks for your suggestions. I have made these changes:

- 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. :-(
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
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..
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( );

~CGameProgrammer( );Developer Image Exchange -- New Features: Upload screenshots of your games (size is unlimited) and upload the game itself (up to 10MB). Free. No registration needed.

This topic is closed to new replies.

Advertisement