Jump to content
  • Advertisement
Sign in to follow this  
ktuluorion

Truly terrible rendering performance...

This topic is 4517 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm starting to pull my hair out over this terrible performance I am getting. If anyone is willing to take a look at this stuff and see if they can figure out why it is rendering so slowly, I would appreciate it. Here is some information that can help: Here is some of the pix information from a frame. This is similar to what is rendered: My main rendering function:
int gameclass::render()
{

if( NULL == d3ddevice )
        return 1;

d3ddevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,               
				 D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );


 d3ddevice->BeginScene();
setupmatrices(x,20,y);//y);
                   

my=my-300; //  convert the world x and y coordinates into a
mx=mx-400; //  grid


if (bx<10) bx=10;
if (bx>13) bx=13;

if (by<10) by=10;
if (by>13) by=13;


rendermodel(skybox,camx,15,camy,0.0f,0.0f,0.0f,5.0f,false);  
if (alive) rendermodel(tanks[0],(float)x,(float)(height-1),(float)y,0.0f,(float)(rot),0.0f,1.0f,false);

for (int i =by-10;i<by+7;i++)
 for (int j=bx-10;j<bx+7;j++)	 
 	 for (int c=0;c<heights[j];c++)	   
       	 if (blocks[j]>-1)rendermodel(block[blocks[j]],(float)(j-10)*2,(float)c,(float)(i-10)*2,0.0f,0.0f,0.0f,1.1f,false);  
   

for ( i =by-10;i<by+7;i++)
 for ( int j=bx-10;j<bx+7;j++)	 
 { 	 
	 if (build[j]==1) rendermodel(city,(float)(j-10)*2,(float)heights[j]-1,(float)(i-10)*2,0.0f,0.0f,0.0f,1.1f,false);  
	 if (build[j]==2) rendermodel(xxx,(float)(j-10)*2,(float)heights[j]-1,(float)(i-10)*2,0.0f,0.0f,0.0f,1.1f,false);  
 }

for ( i =by-10;i<by+7;i++)
 for (int j=bx-10;j<bx+7;j++)	  
     if ((tops[j]>0)||(heights[j]>0)){
			rendermodel(top[tops[j]],(float)(j-10)*2,(float)heights[j]-1,(float)(i-10)*2,0.0f,0.0f,0.0f,1.1f,false);  
	 }



//rendermodel(expl,(float)2,(float)heights[2][2]-1,(float)(2),0.0f,0.0f,0.0f,1.0f,true);  

 


	  
RECT srcrect;
srcrect.top=0;
srcrect.left=0;
srcrect.right=800;
srcrect.bottom=50;
hudsprite->Draw(hud,&srcrect,NULL,NULL,NULL,&D3DXVECTOR2(0,548.0),D3DCOLOR_ARGB(200,255,255,255));

srcrect.right=51;
srcrect.bottom=45;
srcrect.top=0;
srcrect.left=0;
hudselsprite->Draw(hudsel,&srcrect,NULL,NULL,NULL,&D3DXVECTOR2((sel*50)+2,550.0),D3DCOLOR_ARGB(75,255,255,255));
char buffer[10];

char buffer2[5];
sprintf(buffer2,"%d",fps);
sprintf(buffer,"FPS: %s",&buffer2);//[strlen(buffer)-8]);	

drawtext(buffer,D3DCOLOR_RGBA(255,0,0,105),0,0,600,50);

  char buffer3[10];
char buffer4[5];

setupmatrices(40,20,0);
POINT lp;
GetCursorPos(&lp);
mousex=lp.x;
mousey=lp.y;
D3DXVECTOR3 v,vf,vn;
D3DVIEWPORT9 vp;
d3ddevice->GetViewport(&vp);
D3DXMATRIX matproj;
D3DXMATRIX matview;
D3DXMATRIX matworld;
D3DXMatrixIdentity(&matworld);
if (d3ddevice->GetTransform(D3DTS_VIEW,&matview)!=D3D_OK) quit=1;
if (d3ddevice->GetTransform(D3DTS_PROJECTION,&matproj)!=D3D_OK)quit=1;

bool b=false;
for (int I =0;I<20;I++)
 for (int J=0;J<20;J++)	 
	 {


int C=heights[J];


	// int	C=heights[J*2+11][I*2+9];
	 
D3DXVec3Unproject(&vn,&D3DXVECTOR3(lp.x,lp.y,0),&vp,&matproj,&matview,&matworld);
D3DXVec3Unproject(&vf,&D3DXVECTOR3(lp.x,lp.y,1),&vp,&matproj,&matview,&matworld);
D3DXVec3Subtract(&v,&vf,&vn);


int close=0;
BOOL hit1=false;
BOOL hit2=false;
float dist;
hit1= D3DXBoxBoundProbe(&D3DXVECTOR3((J-10)*2-1,1,(I-10)*2-1),
    &D3DXVECTOR3((J-10)*2+1,C,(I-10)*2+1),
    &D3DXVECTOR3(cos(rad(camrot))*20+camx,camh+20,sin(rad(camrot))*20+camy),
    &v
);


if (((b==false) || (I<close))&& ((hit1)||(hit2))) {mxa=J;mya=I;close=I;b=true; rendermodel(select,(J-10)*2,C-1,(I-10)*2,0.0f,0,0.0f,1.1f,false);	
 sprintf(buffer4,"%d",C);
 
 
 sprintf(buffer3,"Coords: %s",&buffer4);//[strlen(buffer)-8]);	
    
	 drawtext(buffer3,D3DCOLOR_RGBA(255,0,0,105),0,50,150,100);
}	 
}	

	 d3ddevice->EndScene();
d3ddevice->Present(NULL,NULL,NULL,NULL);

return 0;
}




Which calls this to render models:
int gameclass::rendermodel(model mod,float x=0,float y=0,float z=0, float rx=0, float ry=0, float rz=0,float sc=0, bool tr=false)
{  
    D3DXMATRIX matWorld,matTrans;
    
D3DXMatrixTransformation( &matTrans,NULL,NULL,NULL,NULL,NULL,
&D3DXVECTOR3(x,y,z));

D3DXMatrixRotationYawPitchRoll(&matWorld,(float)rad(ry),(float)rad(rx),(float)rad(rz));

D3DXMatrixMultiply( &matWorld, &matWorld, &matTrans );

D3DXMatrixScaling( &matTrans,sc,sc,sc);
D3DXMatrixMultiply( &matWorld, &matWorld, &matTrans );

    d3ddevice->SetTransform( D3DTS_WORLD, &matWorld );
    

//d3ddevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE,   D3DMCS_MATERIAL );


for( DWORD i=0; i<mod.num; i++ )
    {
        //Set the material and texture for this subset
        D3DMATERIAL9 m = mod.materials;
	    //if (infront)
		 D3DCOLORVALUE c;
		 
		 c.r =mod.materials.Diffuse.r;
		 c.g=mod.materials.Diffuse.g;
		 c.b=mod.materials.Diffuse.b;

  if (tr==1) c.a= .5; else c.a=1;
	
		m.Diffuse=c;
        
		c.r =mod.materials.Ambient.r+.02;
		c.g=mod.materials.Ambient.g+.02;
		c.b=mod.materials.Ambient.b+.02;
		
		  if (tr==1) c.a= .5; else c.a=1;
		/*	c.r =1;
		c.g=1;
		c.b=1;
		  */
		m.Ambient=c;

        c.r =mod.materials.Specular.r;
		 c.g=mod.materials.Specular.g;
		 c.b=mod.materials.Specular.b;
		if (tr==1) c.a= .5; else c.a=1;
		m.Specular=c;


		//d3ddevice->SetMaterial( &mod.materials );
        d3ddevice->SetMaterial( &m);
		d3ddevice->SetTexture( 0, mod.textures );      
if (tr==1)   d3ddevice->SetTextureStageState(0,D3DTSS_ALPHAOP,.5); 
		//Draw the mesh subset
        mod.mesh->DrawSubset( i );
    }
if (tr==1)        d3ddevice->SetTextureStageState(0,D3DTSS_ALPHAOP,1); 
return 0;
}





Which are stored in this:
int gameclass::createmesh(model &mod, char *file)
{
    LPD3DXBUFFER pD3DXMtrlBuffer;

    if( FAILED( D3DXLoadMeshFromX( file, D3DXMESH_SYSTEMMEM, 
                                   d3ddevice, NULL, 
                                   &pD3DXMtrlBuffer,NULL, &mod.num,
								   &mod.mesh)))
    {
        return 1;
    }

    D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
    mod.materials = new D3DMATERIAL9[mod.num];
    mod.textures  = new LPDIRECT3DTEXTURE9[mod.num];
 _chdir("textures");
    for( DWORD i=0; i<mod.num; i++ )
    {
        mod.materials = d3dxMaterials.MatD3D;

        //mod.materials.Ambient = mod.materials.Diffuse;
       
        if( FAILED( D3DXCreateTextureFromFile( d3ddevice, 
                                               d3dxMaterials.pTextureFilename, 
                                               &mod.textures ) ) )
        {
            mod.textures = NULL;
        }
    }

 
    pD3DXMtrlBuffer->Release();

D3DXComputeNormals(mod.mesh,NULL);

DWORD *pAdj=new DWORD[mod.mesh->GetNumFaces()*3];
        

mod.mesh->GenerateAdjacency(0.0f,pAdj);
            
        // optimize the mesh with attribute sorting
        // D3DXMESHOPT_ATTRSORT
        //pMesh->OptimizeInPlace(D3DXMESHOPT_VERTEXCACHE,pAdj,NULL,NULL,NULL) 
            
        // de-allocate adjacency data storage

mod.mesh->OptimizeInplace(D3DXMESHOPT_COMPACT || D3DXMESHOPT_ATTRSORT ||
						  D3DXMESHOPT_STRIPREORDER,pAdj,NULL,NULL,NULL);
 
	
D3DXCleanMesh(
  mod.mesh,
  pAdj,
  &mod.mesh,
  pAdj,
  NULL);
/*

D3DXSimplifyMesh(mod.mesh,
  pAdj,
  NULL,
  NULL,
  (mod.mesh->GetNumVertices()/5)*4,
  D3DXMESHSIMP_FACE,
  &mod.mesh);
*/
	delete pAdj;
_chdir("..");
	return 0;
}




Share this post


Link to post
Share on other sites
Advertisement
Hey,

Your top clickster is broken :).

I am finding it hard to tell what methods you are using for the rendering from that code.

- Are you rendering in big batches?
- Are you rendering using triangle strips?
- Are you creating/manually modifying the contents of non-dynamically create vertex buffers at run time?

Dave

Share this post


Link to post
Share on other sites
Top imageryOhtehyay fixed.

The middle code segment should show you how I am rendering using DrawSubset. that is the function I call each time I want to render a model (gameclass::rendermodel)

Share this post


Link to post
Share on other sites
I am only guess but is it possible that you render the blocks of your “terrain“ one by one?

Share this post


Link to post
Share on other sites
Quote:
Original post by Demirug
I am only guess but is it possible that you render the blocks of your “terrain“ one by one?


Yes, I render each block by calling rendermesh. is there some more efficient way that i should be rendering all of the blocks?

Share this post


Link to post
Share on other sites
That means that each block is done in at least one Draw[Indexed]Primitive() call, probably more. How many times is DrawSubset called per frame? Try adding a counter to check that. Any more than 500/frame is bad, anything more than 1000 is really bad.

The best way would be to not use meshes to render like this, and use raw triangles instead. Then you could render the whole map in N calls to Draw[Indexed]Primitive, where N is the number of textures in your map.

Share this post


Link to post
Share on other sites
While I'm no expert in optimization, I can see that you're constantly setting your materials and textures with each call to the renderMesh function. You should at the very least batch your rendering calls by texture/material.

This pseudo-code really is not the best way to do this (some far more knowledgable people on here can probably point out the best way) but it should give a rough idea:

void renderMesh(Mesh *mesh)
{
// Draw polygons...
}

void setShader(Shader *shader)
{
// Set material, set texture.
}

void sortByShader()
{
// Sort each model/mesh and group the ones that use the same texture.
// i.e.
// Mesh tank uses Tank_Shader (combination of your material/texture)
// Bricks 1 to (maximum brick count) uses Brick_Shader
// so you group the bricks together and set the texture/material ONCE.
}

void Render()
{
sortByShader(); // Call this only when you need it.

for every mesh in the sorted mesh list
{
if (lastShader != mesh->shader)
{
lastShader = mesh->shader;
setShader(mesh->shader);
}

// Set your transforms , blah
renderMesh(mesh);
}
}




Hopefully this will bring up those frame rates even just a little. Another thing to do is to batch your DrawPrimitive calls, that is put as much common vertex data/index data you can into a single vertex/index buffer and draw it once (this however will mean you MAY have to pre-transform your vertices). Again, I'm no expert and I'm probably way off. So use at your own risk.

Share this post


Link to post
Share on other sites
It looks like I am using drawsubset once for each "block", then when i draw a house or something it is like 19.

So i'm guessing i'm callig drawsubset ~800 times for a frame. Is that too much?

Share this post


Link to post
Share on other sites
Clicky
"10k - 40k batches/s = 100% 1GHz CPU"
I.e. 10,000 to 40,000 calls to Draw[Indexed]Primitive per second (not frame) uses up 100% of a 1GHz CPU, meaning the CPU is so busy submitting batches to the GPU, it doesn't have time for anything else.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!