Strange slowdown when model(s) goes off screen

Started by
18 comments, last by CarlML 7 years, 4 months ago

Got a pretty strange issue, perhaps someone recognizes it.

I have a model that I created the vertex and index buffers for and that I render using DrawIndexedPrimitive, after that I render a bunch of models that are loaded from .x files. Whatever I render after the first model gets really slow when all the models goes off screen, the fps goes from 150 to 20. What could be causing this?

If I render the first model after the "bunch of other models" the issue goes away but if I render another bunch of models after that the issue is seen again.

Advertisement

What does your debugger and graphics debugger tell you?

Sean Middleditch – Game Systems Engineer – Join my team!

What does your debugger and graphics debugger tell you?

I'm figuring out how to use PIX directx debugging tool now (I'm using directx 9), comparing the calls of different frames, but have not found anything useful so far. Any tips on what to look for?

Any tips on what to look for?

It should show some amount of timing information indicating whether the slowdown is on the GPU/shader or in the driver. You'll possibly have to use a CPU-side profiler as well and correlate date to see some types of problems.

If you have DX warning levels turned up, you should also see anything about misuse of the APIs that could lead to issues.

I'm not sure I fully understand your problem; it sounds super weird. At this point I'd just be digging for every piece of information I could get my hands on and looking for anything that seems remotely abnormal.

Sean Middleditch – Game Systems Engineer – Join my team!

According to PIX, in the frames where it is slow there are thousands of more calls to:

IDirect3DQuery9::GetData(NULL, 0x00000000, 0x00000001)

The rest seems to be the same between the fast and slow frames.

Edit: This was because I was flushing commands between each render call for profiling purposes. When I remove all such calls all the GetData commands go away but the slowdown issue remains. The search continues...

How are you storing and updating your objects?

How are you storing and updating your objects?

The object that seems to be causing the issue is setup like this:

A model is loaded form an .x file, then x number of instances of that model is stored in a batch model.

The class basically looks like this:


class Model
{
public:
    LPDIRECT3DVERTEXBUFFER9 vertexBuffer;
    LPDIRECT3DINDEXBUFFER9 indexBuffer;
    DWORD numBytesPerVertex;
    int numVerts;
    int numFaces;

    LPDIRECT3DTEXTURE9 diffuseTexture;
    LPDIRECT3DTEXTURE9 normalTexture;

    //Some functions here
};

The .x model mesh is loaded like this:


LPD3DXBUFFER materialBuffer;
D3DXLoadMeshFromX(meshFileName, D3DXMESH_SYSTEMMEM, d3d.device, NULL, &materialBuffer, NULL, &numSubsets, &mesh);

The vertex and index buffers are intitialized like this:


numBytesPerVertex = mesh->GetNumBytesPerVertex();
int numModelVerts = mesh->GetNumVertices();
int numModelFaces = mesh->GetNumFaces();
numVerts = numModelVerts * numInstances;
numFaces = numModelFaces * numInstances;

//Create vertex buffer
d3d.device->CreateVertexBuffer(numVerts * numBytesPerVertex, D3DUSAGE_WRITEONLY, FVF_MESHVERTEX, D3DPOOL_DEFAULT, &vertexBuffer, NULL));

//Fill vertex buffer
MeshVertex* vertBuf = NULL;
vertexBuffer->Lock(0, 0, (void**)&vertBuf, 0);

MeshVertex* modelVertBuf = NULL;
mesh->LockVertexBuffer(0, (VOID**)&modelVertBuf);

int currentVertex = 0;
for(int i=0; i < numInstances; i++)
{
    for(int d=0; d < numModelVerts; d++)
    {
        vertBuf[currentVertex] = modelVertBuf[d];
        currentVertex++;
    }
}

mesh->UnlockVertexBuffer();
vertexBuffer->Unlock();


//Create index buffer
d3d.device->CreateIndexBuffer(numFaces * 3 * sizeof(short), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &indexBuffer, NULL);


//Fill in index buffer
int currentStartIndex = 0;
int currentIndexIndex = 0;
int numIndices = numModelFaces * 3;

short* indexBuf = NULL;
indexBuffer->Lock(0, 0, (void**)&indexBuf, 0);

short* modelIndeXBuf = NULL;
mesh->LockIndexBuffer(0, (void**)&modelIndeXBuf);
for(int i=0; i < numInstances; i++)
{
    for(int d=0; d < numIndices; d++)
    {
        indexBuf[currentIndexIndex] = modelIndeXBuf[d] + currentStartIndex;
        currentIndexIndex++;
    }
    currentStartIndex += numModelVerts;
}

mesh->UnlockIndexBuffer();
indexBuffer->Unlock();

The vertex declaration looks like this:


#define FVF_MESHVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE3(2) | D3DFVF_TEXCOORDSIZE2(3))

struct MeshVertex
{
    D3DXVECTOR3 pos;
    D3DXVECTOR3 normal;
    D3DXVECTOR3 tangent;
    D3DXVECTOR3 binormal;
    D3DXVECTOR2 tex;
};

const D3DVERTEXELEMENT9 vertexDecl[] =
{
    { 0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
    { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   0 },
    { 0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,  0 },
    { 0, 36, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0 },
    { 0, 48, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
    D3DDECL_END()
};

The model is rendered like this:


d3d.effectScene->SetTexture( "diffuseMap", diffuseTexture );
d3d.effectScene->SetTexture( "normalMap", normalTexture );

D3DXMATRIX worldMat;
D3DXMatrixIdentity(&worldMat);

d3d.effectScene->SetMatrix( "worldMatrix", &worldMat);
D3DXMATRIX worldViewProjMatrix = worldMat * camera.viewMatrix * camera.projMatrix;
d3d.effectScene->SetMatrix( "worldViewProjMatrix", &worldViewProjMatrix);
d3d.effectScene->CommitChanges();

d3d.device->SetVertexDeclaration(d3d.vertDecl);
d3d.device->SetStreamSource(0, vertexBuffer, 0, numBytesPerVertex);
d3d.device->SetIndices(indexBuffer);

d3d.device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numVerts, 0, numFaces);

It has something to do with clipping because if I move the camera back until part of an object (or sometimes all of the objects) goes outside the view frustum the slowdown happens (as well as if I move to the side). I'm guessing the vertex buffer is not setup correctly for clipping or something like that. If you see an issue with how it is setup above let me know.

The slowdown happens in the GPU during the Present() call. My vertex and pixel shaders for testing are pretty simple though.

PIX shows the same function calls for the fast and slow frames, although as I pointed out, if I use:

pEvent->Issue(D3DISSUE_END); while(S_FALSE == pEvent->GetData( NULL, 0, D3DGETDATA_FLUSH ));

...before the Present() PIX shows that a lot more of GetData calls are made in the slow frames than in the fast frames.

The issue goes away if I set:


device->SetRenderState(D3DRS_CLIPPING, FALSE);

That is probably not the solution I want since it probably just hides the bug. It at least shows that the issue is related to clipping.

I doubt it has to do with clipping for many reasons including if it was clipping the order of draws wouldn't matter. Stick with profiling to give you hints as to what is happening.

edit - also what videocard are you running on?

-potential energy is easily made kinetic-

This topic is closed to new replies.

Advertisement