D3D Hardware Instance

hardware_instance-300x238

This demo shows how D3D hardware instance works. HW Instance means call DrawIndexedPrimitive on time, but with a group of geometry rendered. Those geometries could be positioned in different place and different appearance. With this technology, you could gain a lots of performance improved than draw those group of geometry with a loop. HW Instance will split those geometry into two part, one part is shared by all geometries and the other part is specified one that hold all different properties for each. Usually, those shared part will be created on the vertex stream 0, and the other part called instance data will be placed on the vertex stream 1. So the vertex declaration will be look like this:

static D3DVERTEXELEMENT9 _2_tex_normal_decl[] =
{
    // offsets in bytes
    {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_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,     1}, // translation
    {1, 12,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,    2}, // color
    D3DDECL_END()
};

 

Of course, two vertex buffer will be created. And they will be filled with corresponding data. At the rendering time, vertex buffers will be set up with frequency, just like following:

Device->SetStreamSource(0, mVetexBuffer, 0, mVertexSize);

Device->SetStreamSourceFreq( 0, D3DSTREAMSOURCE_INDEXEDDATA | mNumInstance );

Device->SetStreamSource( 1, mInstanceVB, 0, mInstanceVSize );
Device->SetStreamSourceFreq( 1, D3DSTREAMSOURCE_INSTANCEDATA | 1ul ) ;

Device->SetIndices(mIndexBuffer);

Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0,
    mNumVertices, 0, mPrimitiveCount);

 

Very similar with the Non HW instance rendering one.  One thing need to mention here is that HW Instance need vs 3.0 shader mode support. There is no hardware device acceleration  work with DrawPrimitve, only DrawIndexedPrimitive could do that.

 

Something More

In addition to HW Instance technology, here are something that I need to write down:

1) D3D Vertex layout or FVF.  Most of time, we will customize our vertex layout struct. For example:

struct MyVertex
{
    float3 _Pos;
    float3 _Normal;
    float2 _UV;
};

We SHULD NOT switch any two of them, that means you could not put the uv set at the first place and vertex position at last position in this struct. Their orders already defined in the D3D header file, from top to bottom means from first element to the last element. Just as what you see from the following snapt of code from D3D header files.
// Flexible vertex format bits
//
#define D3DFVF_RESERVED0        0×001
#define D3DFVF_POSITION_MASK    0x400E
#define D3DFVF_XYZ              0×002
#define D3DFVF_XYZRHW           0×004
#define D3DFVF_XYZB1            0×006
#define D3DFVF_XYZB2            0×008
#define D3DFVF_XYZB3            0x00a
#define D3DFVF_XYZB4            0x00c
#define D3DFVF_XYZB5            0x00e
#define D3DFVF_XYZW             0×4002

#define D3DFVF_NORMAL           0×010
#define D3DFVF_PSIZE            0×020
#define D3DFVF_DIFFUSE          0×040
#define D3DFVF_SPECULAR         0×080

#define D3DFVF_TEXCOUNT_MASK    0xf00
#define D3DFVF_TEXCOUNT_SHIFT   8
#define D3DFVF_TEX0             0×000
#define D3DFVF_TEX1             0×100
#define D3DFVF_TEX2             0×200

2) D3DFVF_TEX0 means no texture uv set. You could find the following line in D3D header files:
#define D3DFVF_TEX0             0×000

ZERO 0×000 will not give any effect for an OR operation. Do not be confused with TEXCOORD0 that appeared in the shader source code. They are two different things.

3) Try to use the same version for Vertex shader and Pixel shader. If you want to use ps_3_0 for pxiel shader, then you need to set vs_3_0 in used. I tried to use vs_3_0 for vertex shader and ps_2_0 for the pixel shader, but it did not work at all.

4) To make the HW Instance work correctly, you should at least write some code to make those instance vertex elements are used in the vertex shader or pixel shader. Otherwise, there will be nothing display on the screen. No instance data need to deal with, so no geometry need to display. It make sense.

 

The full source code could be download from here.

posted @ 2012-08-24 08:48  opencoder  阅读(372)  评论(0编辑  收藏  举报