?/TD>
Microsoft DirectX 9.0

Decoupling Vertex Shaders and Vertex Declarations


In Microsoft?DirectX?9.0, vertex shaders and vertex declarations are no longer bound together at shader create (CreateVertexShader) time. The shader validation has been broken up into two parts. The first part is run at shader creation time and the other is run at draw (DrawPrimitive) time.

Vertex shaders and vertex declarations are represented by objects. To make this work with a DirectX 8.x driver, some caching is done. At "draw time" the runtime checks to see if a combined shader object that encapsulated the current declaration and shader exists. If it does, it sends it down to the driver, or else it will create a new one for that combination of shader and declaration. Additionally, to address application programming interface (API) usability issues, there will be a separate SetFVF call that is equivalent to the SetVertexDeclaration call. This is a convenience function. When this call is made, it will clobber the currently set declaration and vice versa. If the driver is pre-DirectX 8.0 (the number of stream is 0) SetVertexDeclaration might fail for declarations that cannot be converted to an flexible vertex format (FVF).

A subset of declarations are allowed on DirectX 8.x drivers (numstreams is not zero but does not support stream offset), only those that can be converted to DirectX 8.x-style declaration can be created. Hence the CreateVertexDeclaration call may fail if the declaration provided cannot be converted. For a mixed-mode device, this failure will happen at Drawxxx time because that is the only time it can be known whether this shader is being used with hardware or software vertex processing. This conversion is summarized in the table.

A further subset of decls are allowed on pre-DirectX 8.0 drivers (numstreams is zero); only those declarations that can be converted to an appropriate FVF are allowed. If that conversion is not possible, the CreateVertexDeclaration might fail. For a mixed-mode device, this failure will happen at Drawxxx time because that is the only time it can be known whether this shader is being used with hardware or software vertex processing. This conversion is summarized in the table. Only stream 0 should be used (evident from the MaxStreams cap).

The order of vertex elements should correspond to the order of the FVF codes. The usage index for D3DDECLUSAGE_POSITION and D3DDECLUSAGE_NORMAL should be 0. When switching vertex processing mode for a device with mixed vertex processing, there is no need to reset all input vertex (and index) streams, the vertex declaration, and the vertex function. NULL is an invalid input to SetVertexDeclaration. When using software vertex processing, all usages mentioned in the shader code for the programmable vertex pipeline need to be present in the declaration (or the FVF) bound at the draw time.

Declarations that use the following rules can be rendered with the fixed function pipeline (this assumes no tessellation is required).

Mapping a DirectX 8.x Vertex Declaration to a DirectX 9.0 Vertex Declaration

DirectX 8.xDirectX 9.0 usageDirectX 9.0 usage index
D3DVSDE_POSITIOND3DDECLUSAGE_POSITION0
D3DVSDE_POSITION2D3DDECLUSAGE_POSITION1
D3DVSDE_NORMALD3DDECLUSAGE_NORMAL0
D3DVSDE_NORMAL2D3DDECLUSAGE_NORMAL1
D3DVSDE_BLENDWEIGHTD3DDECLUSAGE_BLENDWEIGHT0
D3DVSDE_BLENDINDICESD3DDECLUSAGE_BLENDINDICES0
D3DVSDE_PSIZED3DDECLUSAGE_PSIZE0
D3DVSDE_DIFFUSED3DDECLUSAGE_COLOR0
D3DVSDE_SPECULARD3DDECLUSAGE_COLOR1
D3DVSDE_TEXCOORDnD3DDECLUSAGE_TEXCOORDn

Mapping an FVF code to a DirectX 9.0 Vertex Declaration

FVFData typeUsageUsage index
D3DFVF_XYZD3DDECLTYPE_FLOAT3D3DDECLUSAGE_POSITION0
D3DFVF_XYZRHWD3DDECLTYPE_FLOAT4D3DDECLUSAGE_POSITIONT0
D3DFVF_XYZWD3DDECLTYPE_FLOAT4D3DDECLUSAGE_POSITIONT0
D3DFVF_XYZB5 and D3DFVF_LASTBETA_UBYTE4D3DVSDT_FLOAT3, D3DVSDT_FLOAT4, D3DVSDT_UBYTE4D3DDECLUSAGE_POSITION, D3DDECLUSAGE_BLENDWEIGHT, D3DDECLUSAGE_BLENDINDICES0
D3DFVF_XYZB5D3DDECLTYPE_FLOAT3, D3DDECLTYPE_FLOAT4, D3DDECLTYPE_FLOAT1D3DDECLUSAGE_POSITION, D3DDECLUSAGE_BLENDWEIGHT, D3DDECLUSAGE_BLENDINDICES0
D3DFVF_XYZBn (n=1..4)D3DDECLTYPE_FLOAT3 D3DDECLTYPE_FLOATnD3DDECLUSAGE_POSITION, D3DDECLUSAGE_BLENDWEIGHT0
D3DFVF_XYZBn (n=1..4) and D3DFVF_LASTBETA_UBYTE4D3DDECLTYPE_FLOAT3 D3DDECLTYPE_FLOAT(n-1) D3DDECLTYPE_UBYTE4D3DDECLUSAGE_POSITION, D3DDECLUSAGE_BLENDWEIGHT, D3DDECLUSAGE_BLENDINDICES0
D3DFVF_NORMALD3DDECLTYPE_FLOAT3D3DDECLUSAGE_NORMAL0
D3DFVF_PSIZED3DDECLTYPE_FLOAT1D3DDECLUSAGE_PSIZE0
D3DFVF_DIFFUSED3DDECLTYPE_D3DCOLORD3DDECLUSAGE_COLOR0
D3DFVF_SPECULARD3DDECLTYPE_D3DCOLORD3DDECLUSAGE_COLOR1
D3DFVF_TEXCOORDSIZEm(n)D3DDECLTYPE_FLOATmD3DDECLUSAGE_TEXCOORDn

Mapping a DirectX 9.0 Vertex Declaration to a DirectX 8.x Vertex Declaration

UsageUsage indexDirectX decl
D3DDECLUSAGE_POSITION 0 D3DVSDE_POSITION
D3DDECLUSAGE_POSITION 1 D3DVSDE_POSITION2
D3DDECLUSAGE_BLENDWEIGHT 0 D3DVSDE_BLENDWEIGHT
D3DDECLUSAGE_BLENDINDICES 0 D3DVSDE_BLENDINDICES
D3DDECLUSAGE_NORMAL 0 D3DVSDE_NORMAL
D3DDECLUSAGE_NORMAL 1 D3DVSDE_NORMAL2
D3DDECLUSAGE_PSIZE 0 D3DVSDE_PSIZE
D3DDECLUSAGE_COLOR 0 D3DVSDE_DIFFUSE
D3DDECLUSAGE_COLOR 1 D3DVSDE_SPECULAR
D3DDECLUSAGE_TEXCOORD n D3DVSDE_TEXTUREn, n <= 7

Mapping a DirectX 9.0 Vertex Declaration to FVF codes

Additional types can be successfully converted to a valid declaration on DirectX 8.0 and newer drivers, and hence can be used by fixed function vertex processing.

Data typeUsageUsage indexFVF
D3DDECLTYPE_FLOAT3D3DDECLUSAGE_POSITION0D3DFVF_XYZ
D3DDECLTYPE_FLOATnD3DDECLUSAGE_BLENDWEIGHT0D3DFVF_XYZBn
D3DDECLTYPE_UBYTE4D3DDECLUSAGE_BLENDINDICES0D3DFVF_XYZB (nWeights+1)
D3DDECLTYPE_FLOAT3D3DDECLUSAGE_NORMAL0D3DFVF_NORMAL
D3DDECLTYPE_FLOAT1D3DDECLUSAGE_PSIZE0D3DFVF_PSIZE
D3DDECLTYPE_D3DCOLORD3DDECLUSAGE_COLOR0D3DFVF_DIFFUSE
D3DDECLTYPE_D3DCOLORD3DDECLUSAGE_COLOR1D3DFVF_SPECULAR
D3DDECLTYPE_FLOATmD3DDECLUSAGE_TEXCOORDnD3DFVF_TEXCOORDSIZEm(n)
D3DDECLTYPE_FLOAT3D3DDECLUSAGE_POSITION1N/A
D3DDECLTYPE_FLOAT3D3DDECLUSAGE_NORMAL 1N/A


© 2002 Microsoft Corporation. All rights reserved.