i
i
i
i
i
i
i
i
3.2. The Programmable Shader Stage 31
vertex, pixel, and geometry shaders share a programming model. We dif-
ferentiate in this book between the common-shader core, the functional
description seen by the applications programmer, and unified shaders, a
GPU architecture that maps well to this core. See Section 18.4. The
common-shader core is the API; having unified shaders is a GPU feature.
Earlier GPUs had less commonality between vertex and pixel shaders and
did not have geometry shaders. Nonetheless, most of the design elements
for this model are shared by older hardware; for the most part, older ver-
sions’ design elements are either simpler or missing, not radically different.
So, for now we will focus on Shader Model 4.0 and discuss older GPUs’
shader models in later sections.
Describing the entire programming model is well beyond the scope of
this book, and there are many documents, books, and websites that al-
ready do so [261, 338, 647, 1084]. However, a few comments are in order.
Shaders are programmed using C-like shading languages such as HLSL, Cg,
and GLSL. These are compiled to a machine-independent assembly lan-
guage, also called the intermediate language (IL). Previous shader models
allowed programming directly in the assembly language, but as of DirectX
10, programs in this language are visible as debug output only [123]. This
assembly language is converted to the actual machine language in a sep-
arate step, usually in the drivers. This arrangement allows compatibility
across different hardware implementations. This assembly language can
be seen as defining a virtual machine, which is targeted by the shading
language compiler.
This virtual machine is a processor with various types of registers and
data sources, programmed with a set of instructions. Since many graph-
ics operations are done on short vectors (up to length 4), the processor
has 4-way SIMD (single-instruction multiple-data) capabilities. Each regis-
ter contains four independent values. 32-bit single-precision floating-point
scalars and vectors are the basic data types; support for 32-bit integers has
recently been added, as well. Floating-point vectors typically contain data
such as positions (xyzw), normals, matrix rows, colors (rgba), or texture
coordinates (uvwq). Integers are most often used to represent counters,
indices, or bit masks. Aggregate data types such as structures, arrays,
and matrices are also supported. To facilitate working with vectors, swiz-
zling, the replication of any vector component, is also supported. That
is, a vector’s elements can be reordered or duplicated as desired. Simi-
larly, masking, where only the specified vector elements are used, is also
supported.
A draw call invokes the graphics API to draw a group of primitives,
so causing the graphics pipeline to execute. Each programmable shader
stage has two types of inputs: uniform inputs, with values that remain
constant throughout a draw call (but can be changed between draw calls),