|Microsoft DirectX 9.0|
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).
|DirectX 8.x||DirectX 9.0 usage||DirectX 9.0 usage index|
|FVF||Data type||Usage||Usage index|
|D3DFVF_XYZB5 and D3DFVF_LASTBETA_UBYTE4||D3DVSDT_FLOAT3, D3DVSDT_FLOAT4, D3DVSDT_UBYTE4||D3DDECLUSAGE_POSITION, D3DDECLUSAGE_BLENDWEIGHT, D3DDECLUSAGE_BLENDINDICES||0|
|D3DFVF_XYZB5||D3DDECLTYPE_FLOAT3, D3DDECLTYPE_FLOAT4, D3DDECLTYPE_FLOAT1||D3DDECLUSAGE_POSITION, D3DDECLUSAGE_BLENDWEIGHT, D3DDECLUSAGE_BLENDINDICES||0|
|D3DFVF_XYZBn (n=1..4)||D3DDECLTYPE_FLOAT3 D3DDECLTYPE_FLOATn||D3DDECLUSAGE_POSITION, D3DDECLUSAGE_BLENDWEIGHT||0|
|D3DFVF_XYZBn (n=1..4) and D3DFVF_LASTBETA_UBYTE4||D3DDECLTYPE_FLOAT3 D3DDECLTYPE_FLOAT(n-1) D3DDECLTYPE_UBYTE4||D3DDECLUSAGE_POSITION, D3DDECLUSAGE_BLENDWEIGHT, D3DDECLUSAGE_BLENDINDICES||0|
|Usage||Usage index||DirectX decl|
|D3DDECLUSAGE_TEXCOORD||n||D3DVSDE_TEXTUREn, n <= 7|
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 type||Usage||Usage index||FVF|