Sign in to follow this  
CBT

Slow engine. Have 6 fps displaying 300 triangles untextured

Recommended Posts

Seems to have a major problem with my direct3d (directx 9) engine. Have implemented a very basic engine and have tried to display a number of triangles to see how fast it could run. Ony triangle runs with approximate 130 fps. Adding two triangles more, placing them somewhat behind the previous ones, I get 100 fps. When drawing 300 triangles, I get 6 fps. I have enabled the Z buffer. some code: // Filling up my vertex buffer with 300 triangles Vertex vertex[2000]; for(int j=0; j<300;j++) { z+=0.01; initVertex(vertex, i++, -4.0f, -3.0f, z, D3DCOLOR_XRGB(255,0,0)); initVertex(vertex, i++, 3.0f, 1.0f, z, D3DCOLOR_XRGB(255,0,0)); initVertex(vertex, i++, 3.0f, -3.0f, z, D3DCOLOR_XRGB(255,0,0)); } dxDev->CreateVertexBuffer(nrVertices*sizeof(Vertex), D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT, &dxVB, NULL); VOID* pVertices = NULL; dxVB->Lock(0, sizeof(vertex), (void**)&pVertices, 0); memcpy(pVertices, vertex, sizeof(Vertex)*nrVertices); dxVB->Unlock(); This is done only once ( in the start of main) Then in the main loop I just call drawPrimitive with 300 triangles. Z buffer is enabled. viewmat, projmat, worldmat is initialized. How many triangles should a basic engine be able to handle?

Share this post


Link to post
Share on other sites
Is that in your game loop?

I don't think your supposed to initialize the vertex every iteration...

I don't know what you're doing with z, but it looks like your trying to achieve maybe transformations of some sort (i have no clue), and you really should use matrix transformations for transformations of any type instead of just rendering the vertex in the transformed spot.

Maybe you can post more code ?

Share this post


Link to post
Share on other sites
it sounds like you're calling a 'for' loop with a DrawPrimitive inside it. If so, then that's really bad unless you must draw one triangle at a time. You should batch as many in as few DrawPrimitive calls as possible because it's an expensive (but necessary) function. Any standard engine should handle at least 100,000 triangles at 60 fps on today's hardware (if not using too much fancy stuff).

Share this post


Link to post
Share on other sites
This for loop is for batching the vertexbuffer with 300 triangles. This for loop is done once only in the beginning of main. The render loop looks like this:

directx.dxDev->Clear(0, NULL, D3DCLEAR_TARGET| D3DCLEAR_ZBUFFER , 0x00FFFFFF, 1.0f, 0 );

directx.dxDev->BeginScene();

dxDev->SetFVF(D3DFVF_CUSTOMVERTEX);
dxDev->SetStreamSource(0, dxVB, 0, sizeof(Vertex));
dxDev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 300);

font.drawFPS();

directx.dxDev->EndScene();
directx.dxDev->Present(NULL, NULL, NULL, NULL );


Share this post


Link to post
Share on other sites
Does someone have code to display a couple of thousands of polygon. Can't figure out what the problem is... Would be nice be nice to download sourcecode for such a basic engine/program

Share this post


Link to post
Share on other sites
Set your PresentationInterval in the present parameters to D3DPRESENT_INTERVAL_IMMEDIATE. If it should still be running higher, i would think it is an initialization error with some params to dx.

Share this post


Link to post
Share on other sites
It may be a fillrate bottleneck. I have thought about this. Because it seems to be really slow when drawing large triangles ( filling the screen), with small triangles it gets much faster. But it i still very slow I think. How do you handle fillerate bottlenecks?

I have also ran the program in NVIDIAS NVPerfhud which is a program to test possible bottlenecks in your engine. And I get quite strange results there. It says that the gpu is constantly idle..

graphic card is NVIDIA GeForce 3

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
if CreateDevice() fails, what do you do?
you have written that the GPU is (almost?) Idle. it seems that it is not used at all!

Share this post


Link to post
Share on other sites
I'm thinking one of two things is wrong.

Option A:
You're using the debug runtime and your code is generating many many warnings through the debug console. This would slow your app significantly.
To check if this is the case, go to the Control Panel, open up DirectX, go to the Direct3D tab and on the top right, select the Retail Version. This would increase your render speed to normal (using the debug runtimes is still recommended, this is just to check what the problem is).

Option B:
You're not calling your render loop enough. This could be many things, really, like a sleep() call somewhere, or maybe something else. If option A doesn't work, try posting your message pumping function and all window related code you think might be related, especially your main While loop (hopefully you have one :)).

Good luck.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I'm not doing anything :-) Is that bad?
The gpu is idle alwas (says NVIDIA NvPerhud program..)

Share this post


Link to post
Share on other sites
Here is some code:

void drawScene()
{
directx.dxDev->Clear(0, NULL, D3DCLEAR_TARGET| D3DCLEAR_ZBUFFER , 0x00FFFFFF, 1.0f, 0 );
directx.dxDev->BeginScene();

directx.drawPrimitives();
font.drawFPS();

directx.dxDev->EndScene();
directx.dxDev->Present(NULL, NULL, NULL, NULL );
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
{
window.createWindow(hInstance,CmdShow);
directx.direct3DInit(&window);
directx.createVertexBuffer(300*3); //create vertexbuffer containing 900 vertices
world.drawWorld(&directx);

font.initFont(&directx);


MSG msg;
while(1)
{
if (PeekMessage(&msg,0,0,0,PM_NOREMOVE))
{
int result = GetMessage(&msg,0,0,0);
if(!result) return msg.wParam;

TranslateMessage(&msg);
DispatchMessage(&msg);


if (GetAsyncKeyState(VK_ESCAPE))
{
PostQuitMessage(0);
return(0);
}
}

drawScene();
}

directx.release();
directx.releaseVB();
}

////////////////////////////////////////////////////////////

bool DirectX::direct3DInit(Window *pwindow)
{

dxD3D = Direct3DCreate9( D3D_SDK_VERSION);
D3DDISPLAYMODE displaymode;
dxD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displaymode);
D3DPRESENT_PARAMETERS pp;
ZeroMemory(&pp, sizeof(pp));

pp.BackBufferFormat= displaymode.Format;
pp.Windowed= TRUE;
pp.BackBufferCount= 1;
//pp.MultiSampleType= D3DMULTISAMPLE_NONE;
//pp.MultiSampleQuality= 0;
pp.SwapEffect= D3DSWAPEFFECT_DISCARD;
pp.hDeviceWindow= pwindow-> hWnd;
pp.FullScreen_RefreshRateInHz= D3DPRESENT_RATE_DEFAULT;
pp.PresentationInterval= D3DPRESENT_INTERVAL_IMMEDIATE;
pp.EnableAutoDepthStencil= TRUE;
pp.AutoDepthStencilFormat= D3DFMT_D16;

dxD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, pwindow->hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &dxDev);

dxD3D->CreateDevice(AdapterToUse, DeviceType, pwindow->hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &dxDev);

setupView();
setupRenderState();
}

//////////////////////
some code here setting upp viewmat and stuff
/////////////


void DirectX::createVertexBuffer(int maxNrVertices)
{
dxDev->CreateVertexBuffer(maxNrVertices*sizeof(Vertex), D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT, &dxVB, NULL);
}

void DirectX::fillVertexBuffer(Vertex vertex[], int nrVertices)
{
VOID* pVertices;
dxVB->Lock(0, 0, (void**)&pVertices, 0);
memcpy(pVertices, vertex, sizeof(Vertex)*nrVertices);
dxVB->Unlock();
}

void DirectX::drawPrimitives()
{
dxDev->SetFVF(D3DFVF_CUSTOMVERTEX);
dxDev->SetStreamSource(0, dxVB, 0, sizeof(Vertex));
dxDev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 300);
}
/////////////////////////////////////////////////

void World::drawWorld(DirectX *directx)
{
srand ( time(NULL) );

int r,b,g;

Vertex vertex[1000];
int i=0;
float y=1;
float z = 0;

for(int j=0; j<300;j++)
{
z+=0.01;
y+=0.01;
r = rand()%256;
g = rand()%256;
b = rand()%256;

initVertex(vertex, i++, 0.0f, 0.0f, z, D3DCOLOR_XRGB(r,g,b));
initVertex(vertex, i++, 1.0f, y, z, D3DCOLOR_XRGB(r,g,b));
initVertex(vertex, i++, 1.0f, 0.0f, z, D3DCOLOR_XRGB(r,g,b));
}

directx->fillVertexBuffer(vertex,300*3); // 300*3 = nrVertices
}

void World::initVertex(Vertex vertex[], int index, float x, float y, float z, unsigned long color)
{
vertex[index].color = color;
vertex[index].x = x;
vertex[index].y = y;
vertex[index].z = z;

}

Share this post


Link to post
Share on other sites
Noticed a little fault in the code I uploaded. I do not call CreateDevice twice! The second CreateDevice is not supposed to be there :-)

Share this post


Link to post
Share on other sites
I noticed two things, first you draw 300 triangles on top of each other, second i think you draw from back to front. Try setting Z to the max and then -= instead.

Though it doesn't seem to be that big a problem considering how many triangles you are drawing...

Share this post


Link to post
Share on other sites
Someone posted a reply about fillrate bottleneck..
I was starting to wonder more about that cause drawing the 300 polygons closer to the viewers standpoint slows down the application significant. 1 fps..

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You are fill limited. Use smaller triangles. Most games don't fill the screen 300 times per frame.

Share this post


Link to post
Share on other sites
"You are fill limited. Use smaller triangles. Most games don't fill the screen 300 times per frame."
.
.
Ok! maby that's the problem.. But should it really fill it 300 times consider the use of the Z buffer? Is the screen that limited to fillrate? Cause drawing only two big triangles (the second behind the first) slows down 5 fps.

But I think you are right so I will settle for that solutions because i can not come up with at better idea.

Thanks everyone for posting your replies!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this