Directx 9 Hardware Instancing Trouble.

Started by
2 comments, last by cgrant 10 years, 3 months ago

It seems like I am not the only one who is having trouble with Hardware Instancing on Directx9. So here is my code only draws 1 Instance instead of 1000. When I compile other Directx9 hardware Instancing projects It renders fine. Eventhough I tried various things I still can't figured it out. Any help will be appreciated.


 #define MAXINSTANCE 1000

LPD3DXEFFECT            Effect;
LPDIRECT3DVERTEXBUFFER9 InstanceVB;
LPDIRECT3DVERTEXDECLARATION9 InstanceDecl;

LPD3DXMESH Box;
LPDIRECT3DVERTEXBUFFER9 BoxVB;
LPDIRECT3DINDEXBUFFER9  BoxIB;
LPDIRECT3DTEXTURE9 Texture;

struct CInstanceData
{
    D3DXMATRIX Transform;
};
CInstanceData *InstanceData[MAXINSTANCE];
bool GenerateInstanceInfo();
bool GenerateInstanceInfo()
{
    Engine->GetDevice()->CreateVertexBuffer(sizeof(CInstanceData)*MAXINSTANCE,
    D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,0,D3DPOOL_DEFAULT,&InstanceVB,0);
    
    CInstanceData *PInstances;
    InstanceVB->Lock(0,0,(void**)&PInstances,D3DLOCK_DISCARD);

// THIS IS THE PLACE I GENERATE RANDOM INSTANCE POSITIONS
    for(int i=0;i<MAXINSTANCE;i++)
    {
        InstanceData[i]=new CInstanceData();
        D3DXMATRIX RandomMatrix;
D3DXMatrixTranslation(&InstanceData[i]->Transform,Engine->GetRandom(0,200),1.0f,Engine->GetRandom(0,200));

    }
    InstanceVB->Unlock();

    D3DVERTEXELEMENT9 VertexElements[] ={
    {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,  0},
    {0, 12, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,    0},
    {0, 24, D3DDECLTYPE_FLOAT2,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,  0},
    {1, 0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,  1},
    D3DDECL_END()
    };

    if(FAILED(D3DXCreateEffectFromFile(Engine->GetDevice(),"ManagedInstancing.fx",0,0,0,0,&Effect,0)))
    {
        ::MessageBox(Engine->GetHWND(),"Failed D3DXCreateEffectFromFile(InstanceEffect)","ERROR",MB_OK);
    }
    if(FAILED(Engine->GetDevice()->CreateVertexDeclaration(VertexElements, &InstanceDecl)))
    {
        ::MessageBox(Engine->GetHWND(),"Failed CreateVertexDeclaration(InstanceDecl)","ERROR",MB_OK);
        return false;
    }
    D3DXLoadMeshFromX("Box.x",0,Engine->GetDevice(),0,0,0,0,&Box);

    if(FAILED(Box->GetVertexBuffer(&BoxVB)))
    {
        ::MessageBox(0,"Box->GetVertexBuffer()","ERROR",MB_OK);
        return false;
    }
    if(FAILED(Box->GetIndexBuffer(&BoxIB)))
    {
        ::MessageBox(Engine->GetHWND(),"Box->GetIndexBuffer()","ERROR",MB_OK);
        return false;
    }
    return true;
    D3DXCreateTextureFromFile(Engine->GetDevice(),"Box.jpg",&Texture);
}
bool SetupScene()
{
    Engine->Setup(1024,768,false);
    Camera->SetProjection(45.0f,1024/768,1.0f,5000.0f);    
    Engine->SetupFps();

    GenerateInstanceInfo();

    return true;
}

void RenderScene()
{    

    GameInput->detectInput();
    SceneInput();    
    Engine->BEGINRENDER(119,136,153);
    Engine->ShowFPS();
    
    D3DXMATRIX PWorld;
    D3DXMatrixIdentity(&PWorld);
    D3DXMatrixTranslation(&PWorld,0,0,0);
    
    Effect->SetTechnique( "BatchedShaderInstancing" );
    Effect->SetMatrix( "ViewProjection", &(Camera->GetViewProj()));    
    Effect->SetTexture("Tex0",Texture);
    UINT Pass, Passes;
    Effect->Begin(&Passes, 0);
    for (Pass = 0; Pass < Passes; Pass++)
    {
        Engine->GetDevice()->SetStreamSourceFreq(0,D3DSTREAMSOURCE_INDEXEDDATA | MAXINSTANCE);
        Engine->GetDevice()->SetStreamSource(0,BoxVB,0,Box->GetNumBytesPerVertex());
        
        Engine->GetDevice()->SetStreamSourceFreq(1,D3DSTREAMSOURCE_INSTANCEDATA | 1);
        Engine->GetDevice()->SetStreamSource(1,InstanceVB,0,sizeof(InstanceData));
        
        Engine->GetDevice()->SetVertexDeclaration(InstanceDecl);
        Engine->GetDevice()->SetIndices(BoxIB);
        
        Engine->GetDevice()->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0,Box->GetNumVertices(), 0, Box->GetNumFaces() );
    
        Engine->GetDevice()->SetStreamSourceFreq( 0, 1 );
        Engine->GetDevice()->SetStreamSourceFreq( 1, 1 );
        Effect->EndPass();
    }
    Effect->End();
    Engine->ENDRENDER();
}

And here is the shader I am Using.


//--------------------------------------------------------------------------------------
// File: ManagedInstancing.fx
//
// The effect file for the ManagedInstancing sample.  
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------


//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
float4x4 ViewProjection;    // View * Projection matrix

texture Tex0;
sampler Tex0Sampler=
sampler_state
{
    Texture = <Tex0>;
    
    MinFilter = Linear;
    MagFilter = Linear;
    MipFilter = Linear;    
};


//application to vertex structure
struct a2v
{
    float4 position     : POSITION0;
    float3 normal        : NORMAL;
    float2 tex0         : TEXCOORD0;    
    float4 instanceData : COLOR0;
};
 
//vertex to pixel shader structure
struct v2p
{       
    float4 position    : POSITION0;
    float2 tex0        : TEXCOORD0;
    float texIndex       : TEXCOORD1; // yeah, right
};
 
//pixel shader to screen
struct p2f
{
    float4 color    : COLOR0;
};

void ps( in v2p IN,  out p2f OUT)
{    
    float2 tex0 = IN.tex0;
    tex0.x = (tex0.x + IN.texIndex) / 4; // shift u texcoord to appropriate index
    OUT.color = tex2D(Tex0Sampler, tex0);
};

void vs( in a2v IN, out v2p OUT )
{       
    float4 data = IN.instanceData;    
    float4 instancePos = IN.position;    
    instancePos.x += data.x;
    instancePos.y += data.y;
    instancePos.z += data.z;    
        
    OUT.texIndex = data.w;
    OUT.position = mul(instancePos, ViewProjection);       
    OUT.tex0 = IN.tex0;
};


//--------------------------------------------------------------------------------------
// Techniques
//--------------------------------------------------------------------------------------
technique BatchedShaderInstancing
{
    pass P0
    {      
        VertexShader = compile vs_2_0 vs();           
        PixelShader  = compile ps_2_0 ps();          
    }
}
 
Advertisement

Don't call SetStreamSourceFreq back to the default values before you end the pass. Move those calls to after effect end. I don't know if it helps, but it won't hurt to minimize redundant state sets if you have a multi-pass effect.

Also, you want to call Effect->BeginPass(Pass); at the beginning of the for-statement.

Kjell Andersson,? have fixed the issues you mentioned about an hour ago.Although I tried many various things

it will not work.Seems like directx9 doesn't like Hardware Instancing. Time to move Directx 10-11.

Thanks for your time.

DX9 does support for instancing as long the as the HW support Shader Model 3.0 and above. Everything seem ok for the most part from the code you posted.

I would keep Kjell Anderssson suggestion since thats the correct way to do it...and I would also avoid passing the position data via the COLOR semantic, its probably getting normalized or something like that. For generic data just use the TEXCOORD semantic.

This topic is closed to new replies.

Advertisement