Creating and filling a vertex buffer with data is only one of the ways to render geometry in DirectX. Sometimes, especially for testing purposes, you will simply want to allocate a memory buffer in user memory space and tell DirectX to render its contents without the burden of locking and copying it to the APIs space.
Logically, working with user memory pointers requires less effort from the programmer. There is no need for vertex buffers, locking, and so on. But this ease of use comes at a performance cost. Sometimes, data in user memory won't be copied to the graphics subsystem, and thus it will be hard to reach maximum performance. But for some cases, like geometry that changes on a frame-by-frame basis, the copy and lock operations might also be imposing a significant penalty, so user memory primitives will be the way to go.
User memory primitives are exposed through the DrawPrimitiveUP and DrawIndexedPrimtitiveUP calls. Here is the syntax for DrawPrimitiveUP:
HRESULT DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void *pVertexStreamZeroData, UINT VertexStreamZeroStride);
As usual, the first parameter should contain the primitive type, which is the same as in regular DrawPrimitive calls. Then, we need the primitive count, which also has the same geometric interpretation as in the classic DrawPrimitive. As a third parameter, we will need a pointer to the data. We didn't use a pointer on DrawPrimitive because we passed the vertex buffer instead, so that is the main difference between the two calls. In addition, we will need to specify the stride. Note, however, that the pointer must still use DirectX's conventions for vertex structures. The structure of the data must be exactly the structure used in vertex buffers.
Indexed primitives can also work this way. In this case, the call is
HRESULT DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertexIndices, UINT PrimitiveCount, const void *pIndexData, D3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride);
The parameters in the preceding call are also very similar to the regular DrawIndexedPrimitive call. The only difference is the pointer to the index buffer on parameter five and the pointer to the vertices on parameter seven. Other than that, it works exactly like IndexedPrimitive.