Primitive Assembly

Primitive assembly is a crucial stage in the DirectX rendering pipeline. It takes the processed vertices from the vertex shader and organizes them into primitives (points, lines, or triangles) that can then be rasterized.

The Role of Primitive Assembly

After vertices have been transformed and lit by the vertex shader, they exist as individual data points in clip space. Primitive assembly's primary responsibility is to group these vertices into geometric primitives. The type of primitive is determined by the graphics hardware and the application's settings.

Primitive Types

Topology

The way vertices are connected to form primitives is defined by the primitive topology. Common topologies include:

Diagram illustrating primitive assembly
Conceptual representation of vertex grouping into triangles.

Input Assembler

The Input Assembler (IA) stage is responsible for fetching vertex data from memory (typically vertex buffers) and assembling it into the primitives specified by the primitive topology. This stage reads vertex data, applies any necessary indexing if an index buffer is used, and outputs a stream of geometric primitives to the next stage of the pipeline.

Vertex Buffers and Index Buffers

The Input Assembler uses the primitive topology setting to know how to interpret the incoming vertex stream. For example, if D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST is set, the IA will read vertices three at a time to form triangles.

Example Pseudocode

This pseudocode illustrates how the Input Assembler might conceptually process vertices for a TRIANGLELIST:


// Assuming vertices are in a contiguous array and topology is TRIANGLELIST
function AssembleTriangles(vertex_data) {
    primitives = [];
    for (i = 0; i < vertex_data.length; i += 3) {
        // Fetch three vertices
        v0 = vertex_data[i];
        v1 = vertex_data[i+1];
        v2 = vertex_data[i+2];

        // Form a triangle primitive
        triangle = { v0, v1, v2 };
        primitives.push(triangle);
    }
    return primitives;
}
            

When using an index buffer, the process involves reading indices and using them to fetch vertices from the vertex buffer, allowing for significant reuse of vertex data.

Next Steps

Once primitives are assembled, they are passed to the next stage, which is typically the Rasterizer. The rasterizer determines which pixels on the screen are covered by the primitives.