Graphics‎ > ‎Graphic API‎ > ‎Direct3D‎ > ‎

HLSL

The High Level Shading Language (HLSL) is a shading language used in Direct3D and DirectX12. It's a C/C++ style language. On these pages the focus on shader model 5.1 (SM5.1) that are used in DX 12.

HLSL source code use the .hlsl extension. The code can then be compiled at buildtime with the FXC compiler or at runtime using D3DCompileFromFile() or D3DCompile() . When compiled by directx they are in a format called DXBC or bytecode. Compiled shaders are given the .cso (compiled shader object) extension. To the compiler one give the type of shader to build, known as the Shader profile and also the name of the function to use. That way it is possible to have multiple shaders in the same .hlsl file.

When using Create*Shader (DX11) or CreateGraphicsPipelineState (DX12) the graphic driver compile the DXBC bytecode to GPU shader code. This is a operation that takes time so it but the driver might have a disk cache that help. The PSO depends on the pso description, the hardware and the driver. 


Functions
The built-in functions in HLSL is called the Intrinsic Functions. They have been optimized and tested by the best minds at Microsoft so it is better to use them then to write custom ones that do the same thing.

Variables
Similar to variables in the C programming language. The syntax for a variable is in the form below.

[Storage_Class] [Type_Modifier] Type Name[Index] [= Initial_Value]

Storage_Class
extern:
uniform:

Type
Scalar: bool, int, uint, dword, half, float and double.
Vector: A vector type name is made up of a scalar name with the number of components (1-4) at the end. Ex, int3 or float2.
Matrix: A matrix type name is made up of a scalar name with the number of row of columns after separated by an x. Ex int3x2 or float2x2.
Buffer: Buffers are in the form Buffer<type> where type is a HLSL scalar, vector or matrix type. The matrix must fit in 4*32 bit's.
Sampler: sampler1D, sampler2D, sampler3D, samplerCUBE, sampler_state and  SamplerState.
Texture: Texture1D, Texture1DArray, Texture2D, Texture2DArray, Texture3D and TextureCube.


Control Flow
HLSL use the standard c++ style of statements.

Selection: if and switch.
Iteration: do, for and while.
Jump: break, continue and discard.
Exit: discard, Can only be used in a pixel shader. It will discard and not output the result of the current pixel. Using this disables early-z so it should only be used when really needed.


Semantics

As data moves along the shaders in the graphic pipeline there need to be a way to know how the output of one shader arrives as the input of another. In HLSL Semantics are used for that purpose. A Semantics is a string used on a variable. The HLSL compiler connects the same semantics string in the output of a shader with the input of the next shaders. So if the vertex shaders write something to a variable with the TEXCOORD0 semantic it will find the variable in the fragment shader with the same TEXCOORD0 semantic and put the value into it. Semantics can only be used on on global variables or on parameters passed into the shader. Semantics are tags so what matter is that the sting is the same. Even if it possible to make up any tag it's a good idea to keep them logical so it is easy to know what they contain. No one is helped by a color being passed on with the semantic IDrinkYourMilkshake.

There are some special system Semantics and they all start with the SV_ prefix. Some of them can only be used in specific shaders and it's a best to avoid making custom semantic that use the SV_ prefix.

Start
The vertex shader is the first shader stage and it links it's semantics with the semantic name in the Input Layout.

Middle

End
At the end of the pipeline is the pixel shader and there are two semantics one can write to, SV_Target[n] and SV_Depth. SV_Target selects the render target to write to and n can be 0-7. SV_Depth is the depth buffer data.


Resource Binding

In DX12 one sets the value of resources using root signature slot number. The root signature bound to the pipeline map these slot numbers to virtual registers within logical register spaces. In HLSL the register keyword is then used ti tell the compiler what register and space a variable should use. Each register is describe by a single letter and a number. The letter is given by the type of resource in the register so there are four of them, one for each resource that can be used from a shader.
  • t - Shader resource views (SRV)
  • b - Constant buffer views (CBV)
  • u - Unordered access views (UAV)
  • s - Samplers

FXC
Fxc.exe is the tool to compile HLSL shaders offline.

    fxc SwitchOptions Filenames

 /T <profile> The shader profile to use to compile the shader.
 /E <name> The name of entry point in shader. If not given main is used.
 /Fo name
 The name of the output file to created.
 /Fc name
 Name of a assembly file to create (for debugging and checking out the generated code).
 /Zi Enable debugging information.
 /Zpr Pack matrices in row-major order.
 /nologo Hide display of logo.
 /Qstrip_debug Strip debug data from bytecode.
 /Qstrip_reflect Strip reflection data from bytecode
 /Qstrip_rootsignatures Strip rootsignature from bytecode.

Reference


Links

Compilation Pipeline in the DirectX Compiler - 2017
https://blogs.msdn.microsoft.com/marcelolr/2017/10/13/compilation-pipeline-in-the-directx-compiler/
SM3.0 flakiness
Subpages (1): Shader profile
Comments