SV_Position vs User-Defined Semantics in DirectX
In DirectX High-Level Shading Language (HLSL), vertex shader outputs
are tagged with semantics that dictate how data travels through the
graphics pipeline. While user-defined semantics serve as generic
carriers for custom data like texture coordinates or surface normals
that simply undergo interpolation, SV_Position is a
specialized System Value semantic with a strict, hardware-enforced
purpose. This article explains the technical differences between
SV_Position and user-defined semantics, covering their
coordinate space requirements, pipeline behavior, and hardware
integration.
Hardware Consumption vs. Generic Data Passing
The primary difference lies in how the GPU's fixed-function hardware interprets the semantic:
SV_Position(System Value): This semantic signals the GPU's rasterizer stage directly. The rasterization hardware requires a position output to determine where a primitive lies on the screen, handle frustum clipping, perform back-face culling, and execute perspective division. It is mandatory for the final pre-rasterization stage (Vertex, Geometry, or Domain Shader).- User-Defined Semantics: Semantics such as
TEXCOORD,NORMAL, or custom names likeTANGENTare not interpreted by the rasterization hardware. The GPU treats them as generic payloads of floating-point or integer data that must be forwarded to the Pixel Shader.
Coordinate Space Requirements
Because SV_Position directly feeds the rasterization
stage, it must conform to a strict coordinate format:
- Clip Space Output: When output by a vertex shader
(or the last stage before the rasterizer),
SV_Positionmust be in homogeneous clip space, expressed as a four-component vector \((x, y, z, w)\). - User-Defined Flexibility: User-defined semantics can store values in any mathematical space desired by the developer, such as local space, world space, view space, or normalized UV coordinates. The graphics pipeline enforces no mathematical conventions on these values.
Transformation Between Shader Stages
How these values arrive in the Pixel Shader highlights another critical divergence in behavior:
SV_Positionin the Pixel Shader: Between the vertex and pixel shader stages, the GPU performs perspective divide (dividing \(x, y, z\) by \(w\)) and viewport mapping onSV_Position. Consequently, if a pixel shader readsSV_Positionas an input, it receives screen-space (pixel) coordinates where \(x\) and \(y\) correspond to the pixel's location in the render target (with pixel centers offset by 0.5), \(z\) represents the depth buffer value, and \(w\) holds \(1/w\) for perspective interpolation.- User-Defined Interpolation: User-defined semantics
undergo perspective-correct interpolation across the surface of the
triangle. Unless overridden by interpolation modifiers (such as
nointerpolationornoperspective), the data arrives at the pixel shader smoothly blended across vertices without any automatic screen-space transformations.
Pipeline Validation and Constraints
The DirectX compiler and runtime enforce strict rules regarding
SV_Position:
- Uniqueness and Presence: Exactly one active
position semantic (
SV_Position) must be output prior to the rasterizer. Failing to provideSV_Positionresults in a compilation error or runtime pipeline failure. - Arbitrary Definition: User-defined semantics can be
arbitrarily declared, named, indexed (e.g.,
TEXCOORD0throughTEXCOORD7), or omitted entirely depending on the requirements of the rendering pass.