Shaders and the FXC Shader Compiler

There are several shaders in Direct3D and in the Xbox One GPU. The FXC shader compiler has options for HLSL tools and for PIX.

To see an alphabetical list of these Xbox extension compiler flags, in the Index, see “compiler flags”.

Types of Shaders

Types of Shaders in Direct3D

There are six types of shaders implemented in DirectX 11.1 and supported by the Xbox One XDK. The six shader types are the logical components used in Direct3D.

Shader name Acronym Description
Vertex shader VS Runs one instance per vertex in a SIMD-like way.
Hull shader HS Prepares data for tessellation.
Domain shader DS Generates vertices from tessellated data.
Geometry shader GS Runs on primitives and may produce zero or more output primitives.
Pixel shader PS Runs one instance per pixel in a SIMD-like way.
Compute shader CS A general-purpose shader program that uses no render state. For example, a GPGPU shader.

Types of Shaders on the GPU

There are seven shader types on the Xbox One GPU:

Shader name Acronym Description
Vertex shader VS Not a direct match to Direct3D's VS.
Hull shader HS Corresponds to Direct3D's HS.
Geometry shader GS Corresponds to Direct3D's GS.
Pixel shader PS Corresponds to Direct3D's PS.
Compute shader CS Corresponds to Direct3D's CS.
Load Shader LS Direct3D doesn't have this.
Export Shader ES Direct3D doesn't have this.

There is no Domain shader on the GPU.

Compiling Shaders Using FXC

Shaders are pre-compiled by default by the Xbox One XDK tools that add to Visual Studio on the Development PC. The pre-compiled shaders are loaded by the Xbox One User Mode graphics driver on the Xbox One hardware when the title is being instantiated. Pre-compiling avoids the one-time runtime cost of compiling the shaders to GPU instructions.

With each XDK release, shader code should be re-compiled, because all precompiled shaders from previous releases become obsolete. If the shaders are not re-compiled an error will not occur but this will provoke the run-time cost of compilation. The fxc/dumpbin utility has been updated to print out disassembled pre-compiled shaders that may be embedded in the output of d3dcompiler.

The tool for pre-compiling shaders is FXC, which is the Microsoft Direct3D Shader Compiler. FXC for Xbox One provides similar functionality to the tool with the same name for Direct3D on Windows, but the tools are not the same and cannot be used interchangeably. FXC for Windows is described in Effect-Compiler Tool.

By default, FXC.exe is installed to the following folder:

C:\Program Files (x86)\Microsoft Durango XDK\[release]\xdk\FXC\amd64  

Note [release] is the release number (e.g. 161002 for October 2016 QFE 2).

FXC for Xbox One has the same options as the tool for Windows, with the addition of the following switches:

Switch Description
-noprecompile Disables precompilation of shaders to GPU instructions, instead the shaders will be compiled to Direct X byte code (DXBC). The shader will be compiled from DXBC to GPU instructions at runtime. For shader model 5.1 a root signature must be specified in order to compile shaders offline. If you get an error message stating that the root signature was not provided, provide one so pre-compilation can occur down to the GPU instructions, or set the <mark type="param">-noprecompile</mark> switch if you intent only to precompile down to bytecode and perform the GPU compile at run-time.
-Vd Validation disable. This disables strict checking of race conditions by d3dcompiler. This can be used to create racy shaders, but can also be used when d3dcompiler falsely accuses a shader of being racy (due to limitations in d3dcompiler and the halting problem).

The following table gives examples of the use of FXC to set an internal flag.

Command Line Description
Fxc cs.hlsl –T cs_5_0 –D__XBOX_CONTROL_NONIEEE=0
Sets internal flag to 0.
Fxc cs.hlsl –T cs_5_0 –D__XBOX_CONTROL_NONIEEE=1
Sets internal flag to 1.
Fxc cs.hlsl –T cs_5_0 –D__XBOX_CONTROL_NONIEEE
Sets internal flag to 1.
Fxc cs.hlsl –T cs_5_0 –D__XBOX_CONTROL_NONIEEE=999
Setting is IGNORED since this flag requires value of 0 or 1.

Within an HLSL source file, set flags using the following syntax:

#define __XBOX_CONTROL_NONIEEE 0    // sets internal flag to 0
#define __XBOX_CONTROL_NONIEEE 1    // sets internal flag to 1
#define __XBOX_CONTROL_NONIEEE      // sets internal flag to 1
#define __XBOX_CONTROL_NONIEEE 9999 // setting is IGNORED since this flag requires value of 0 or 1  

The code module defined by d3dcompiler.h is used both by running titles to compile shaders to GPU instructions, and by the FXC tool to precompile the shaders. There are significant code changes to d3dcompiler between the Windows and Xbox One version of d3dcompiler. In particular, FXC takes a number of parameters specified in defines, which are often passed through to d3dcompiler.

For reference, the Windows version of d3dcompiler is documented here D3DCompile function.

Disabling Pre-compilation

There are a range of flags that can be used to disable the pre-compilation of a shader stage. The Direct3D software shaders listed above often map to a single hardware shader stage, though the following table shows some of the more complex mappings.

Direct3D Process Pipeline          
    Step 1 Step 2 Step 3 Step 4 Step 5
Direct3D 9 Direct3D VS PS      
  GPU VS PS      
 
Direct3D 10 Direct3D VS GS PS    
  GPU ES GS, VS PS    
 
Direct3D 11 Tessellation Direct3D VS HS DS PS  
  GPU LS HS VS PS  
 
Direct3D 11 Tessellation and Geometry Direct3D VS HS DS GS PS
  GPU LS HS ES GS, VS PS
 
Direct3D 11 Compute shader Direct3D CS        
  GPU CS        

This means that if, for example, the LS stage of tessellation is disabled, then pre-compilation of the other hardware stages will still be generated.

Disabling pre-compilation reduces the size of the code generated and could potentially increase efficiency. For example, if a Vertex shader will never be used with tessellation, then pre-compiling the LS is inefficient because the LS code will never be used. Set the following flags to 1 to disable the various shader stages, for example, to disable the LS stage in the game.hlsl shader:

Fxc game.hlsl –T cs_5_0 –D __XBOX_DISABLE_PRECOMPILE_LS=1  

Alternatively, provide these flags to the d3dcompilers definearray. Do not set the flags in source code.

Flag Description
__XBOX_DISABLE_PRECOMPILE_LS Disable pre-compilation of the LS hardware stage.
__XBOX_DISABLE_PRECOMPILE_HS Disable pre-compilation of the HS hardware stage.
__XBOX_DISABLE_PRECOMPILE_HS_HSOFFCHIP Disable precompilation of shaders for HS_HSOFFCHIP hardware stage.
__XBOX_DISABLE_PRECOMPILE_HS_HSALWAYSOFFCHIP Disable precompilation of shaders for HS_HSALWAYSOFFCHIP hardware stage.
__XBOX_DISABLE_PRECOMPILE_ES Disable pre-compilation of the ES hardware stage.
__XBOX_DISABLE_PRECOMPILE_ES_HSOFFCHIP Disable precompilation of shaders for ES_HSOFFCHIP hardware stage.
__XBOX_DISABLE_PRECOMPILE_ES_GSONCHIP Disable precompilation of shaders for ES_GSONCHIP hardware stage.
__XBOX_DISABLE_PRECOMPILE_ES_HSOFFCHIP_GSONCHIP Disable precompilation of shaders for ES_HSOFFCHIP_GSONCHIP hardware stage.
__XBOX_DISABLE_PRECOMPILE_ES_HSALWAYSOFFCHIP Disable precompilation of shaders for ES_HSALWAYSOFFCHIP hardware stage.
__XBOX_DISABLE_PRECOMPILE_ES_HSALWAYSOFFCHIP_GSONCHIP Disable precompilation of shaders for ES_HSALWAYSOFFCHIP_GSONCHIP hardware stage.
__XBOX_DISABLE_PRECOMPILE_GS Disable pre-compilation of the GS hardware stage.
__XBOX_DISABLE_PRECOMPILE_GS_GSONCHIP Disable precompilation of shaders for GS_GSONCHIP hardware stage.
__XBOX_DISABLE_PRECOMPILE_VS Disable pre-compilation of the VS hardware stage.
__XBOX_DISABLE_PRECOMPILE_VS_PSPRIMID Disable precompilation of shaders for VS_PSPRIMID hardware stage.
__XBOX_DISABLE_PRECOMPILE_VS_HSOFFCHIP Disable precompilation of shaders for VS_HSOFFCHIP hardware stage.
__XBOX_DISABLE_PRECOMPILE_VS_HSOFFCHIP_PSPRIMID Disable precompilation of shaders for VS_HSOFFCHIP_PSPRIMID hardware stage.
__XBOX_DISABLE_PRECOMPILE_VS_HSALWAYSOFFCHIP Disable precompilation of shaders for VS_HSALWAYSOFFCHIP hardware stage.
__XBOX_DISABLE_PRECOMPILE_VS_HSALWAYSOFFCHIP_PSPRIMID Disable precompilation of shaders for VS_HSALWAYSOFFCHIP_PSPRIMID hardware stage.
__XBOX_DISABLE_PRECOMPILE_PS Disable pre-compilation of the PS hardware stage.
__XBOX_DISABLE_PRECOMPILE_PS_PSPRIMID Disable precompilation of shaders for PS_PSPRIMID hardware stage.
__XBOX_DISABLE_PRECOMPILE_CS Disable pre-compilation of the CS hardware stage.
__XBOX_DISABLE_PRECOMPILE Disable precompilation of all shaders.

Shader Registers

The following flags define control behavior of the shader compiler by lowering the number of estimated lifetimes that will be tolerated by the shader compiler’s pre-allocation instruction scheduler. These limits are not a hard rule and merely guide the scheduler’s heuristics, the shader compiler will use more registers if necessary.

By restricting the instruction scheduler you can prevent extra overlapping lifetimes from being created, which can help reduce the number of registers that are needed to execute the shader. By lowering the number of registers that are required by a shader, the shader’s occupancy can be increased (that is, more copies of the same shader can run at the same time).

These flags are used internally by both __XBOX_ATTEMPT_WAVE_WIDENING and __XBOX_WAVESIM_ITERATION (see below). Both of these flags evaluate a range of settings to find a likely improvement.

To set a shader flag, enter it when running the Fxc compiler. For example, to set the VGPR limit to 64:

Fxc game.hlsl –T cs_5_0 –D __XBOX_REGALLOC_VGPR_LIMIT=64  

Note Register thresholds are also used by the scheduler, so sometimes the compiler will not use all the registers when the threshold is lowered.

Flag Description
__XBOX_REGALLOC_SGPR_LIMIT and __XBOX_REGALLOC_FORCE_SGPR_LIMIT Sets an upper limit on SGPR register usage by the shader compiler. This currently also feeds the heuristics in the shader compiler's instruction scheduler. Values should be in the range 32-256 (inclusive). The actual lower bound depends on the shader, if the value is set too low the shader compilation will not be able to allocate and compilation will fail. The flag without "FORCE" is treated as a suggestion to the scheduler, with "FORCE" there is a much harder limit, though there is still no guarantee the limit will be met.
__XBOX_REGALLOC_VGPR_LIMIT and __XBOX_REGALLOC_FORCE_VGPR_LIMIT Sets an upper limit on VGPR register usage by the shader compiler. This currently also feeds the heuristics in the shader compiler's instruction scheduler. Values should be in the range 32-256 (inclusive). The actual lower bound depends on the shader, if the value is set too low the shader compilation will not be able to allocate and compilation will fail. The flag without "FORCE" is treated as a suggestion to the scheduler, with "FORCE" there is a much harder limit, though there is still no guarantee the limit will be met.
__XBOX_LIMIT_OCCUPANCY_WITH_HARD_LIMIT This flag can be used in conjunction with __XBOX_REGALLOC_FORCE_SGPR_LIMIT and __XBOX_REGALLOC_FORCE_VGPR_LIMIT to tell the compiler to report the requested register usage, regardless of whether the shader actually needs that many registers. This can be used to artificially raise register usage limits and so reduce occupancy.

Additional Shader Objects

If any of the following flags are set, additional shader objects will be produced. For example, if a vertex shader is compiled with the __XBOX_ENABLE_PSPRIMID define, the HLSL tools will produce both a VS and a VS_PSPRIMID shader object. If it is known that the non-psprimid shader object is not needed, its production can be disabled by defining __XBOX_DISABLE_PRECOMPILE_VS.

All produced shader objects and their types can be seen in the disassembly listing using the FXC tool (for example: fxc /dumpbin).

Flag Description
__XBOX_ENABLE_HSOFFCHIP Used with only hull or domain shaders, to instruct these shaders to support offchip tessellation. See Tessellation.
__XBOX_ENABLE_HSALWAYSOFFCHIP Used with only hull or domain shaders, to instruct these shaders to only use offchip tessellation. See Tessellation.
__XBOX_ENABLE_GSONCHIP Specifies that geometry shaders are compiled to use on chip memory.
__XBOX_ENABLE_PSPRIMID Specifies that pixel shaders are compiled to pass through SV_PrimitiveID. Also called vertex ID. This is a number that tells the pixel shader the vertex of the pixel it is acting on. On Xbox One, this ID is passed explicitly by shader code.

Read-only Shader defines

The following defines are made inside the D3DCompiler and are there for the developer to rely on. They should never be set by a developer.

Flag Description
__XBOX_ONE Used when developing for multiple platforms, to #ifdef shaders for features specific to xbox_one tools. This define should not be set by the developer, it is set by the Xbox One version of the d3dcompiler.
__XBOX_SHADER_OBJECT_VERSION Provides an unsigned integer value representing the current shader object version. This define should not be set by the developer; this define is set by the Xbox One version of the d3dcompiler.

Miscellaneous Shader Options

The following miscellaneous flags are available. Long flag names are wrapped into two lines.

Flag Description
__XBOX_DISABLE_SC_UNROLL HLSL [Loop] and [unroll] attributes are ignored by the shader compiler - it will unroll loops when it sees a benefit. The shader compiler loop unroll can be disabled with this flag, meaning the HLSL [loop] attribute will be honored.
__XBOX_ENABLE_ DOM_LIFETIME_SHORTENING __XBOX_ENABLE_DOM_LIFETIME_SHORTENING produces a minor improvement to lifetime shortening. The compiler moves definitions of values down to block that dominates all uses. This can reduce register usage in some cases. Be aware that shortening lifetimes can increase stall due to latency, so this flag’s runtime benefit should be measured.
__XBOX_FORCE_PS_ZORDER_ LATE_Z __XBOX_FORCE_PS_ZORDER_ EARLY_Z_THEN_LATE_Z __XBOX_FORCE_PS_ZORDER_ RE_Z __XBOX_FORCE_PS_ZORDER_ EARLY_Z_THEN_RE_Z Used to force zorder mode without regard for correct culling of UAV writes. A compiler error is generated if more than one is set. Flag names: __XBOX_FORCE_PS_ZORDER_LATE_Z __XBOX_FORCE_PS_ZORDER_EARLY_Z_THEN_LATE_Z __XBOX_FORCE_PS_ZORDER_RE_Z __XBOX_FORCE_PS_ZORDER_EARLY_Z_THEN_RE_Z
__XBOX_FULL_PRECOMPILE_PROMISE Runtime compilation can occur if the user disables precompilation of the shader object for a necessary hardware stage, or forgets to enable precompilation of shader objects that support a runtime selected feature (for example __XBOX_ENABLE_HS_ALWAYSOFFCHIP.) By default, the Xbox One graphics driver holds copies of shader bytecode if it detects a potential need for future runtime compilation. The __XBOX_FULL_PRECOMPILE_PROMISE define is a compile-time guarantee to the graphics driver that shader bytecode will not be needed after the initial call to CreateShader. With this guarantee the graphics driver avoids holding copies of shader bytecode, which can provide a significant reduction in driver heap use. It is a fatal error if the __XBOX_FULL_PRECOMPILE_PROMISE is set but the graphics driver finds itself later requiring the shader bytecode. If this condition occurs the graphics driver will print a warning message, will debug break, and eventually the GPU will crash.
__XBOX_ENABLE_ EXTENDED_TYPED_UAV __XBOX_ENABLE_EXTENDED_TYPED_UAV disables the d3dcompiler restriction error: "X3676: typed UAV loads are only allowed for single-component 32-bit element types" The following is example source code that will compile when this define is provided:
RWTexture2D <uint2> uav;
[numthreads(8,8,1)]
void main(uint3 invoc : SV_GroupThreadID)
{
  uav[invoc.xy] = uav[invoc.xy] + uint2(1,2);
}
__XBOX_DISABLE_ SHADER_OBJECT_COMPRESSION __XBOX_DISABLE_SHADER_OBJECT_COMPRESSION disables shader object compression. By default, shader objects are compressed before storing in dxbc. If shaders are compressed by the app, this secondary compression can be removed. Removing this secondary compression results in a shader object size increase of 3x, but with a 9x speedup in shader object instantiation.
__XBOX_DISABLE_ SHADER_NAME_EMPLACEMENT By default, the Xbox One d3dcompiler stores each shader’s filename and entry point within the precompiled shader object. This information is used to improve runtime error messages. This __XBOX_DISABLE_SHADER_NAME_EMPLACEMENT flag can be used to disable the shader name emplacement.
__XBOX_DISABLE_ SCRATCH_TO_ARRAY __XBOX_DISABLE_SCRATCH_TO_ARRAY is used to disable late optimization that hoists constant arrays into registers. While this optimization helps in some cases, it can cause large increases in register usage which will limit the size of GPU waves.
__XBOX_PDBFILENAME Used to embed the pdb path name into the shader object. If this define is set to a string value (a descriptive name, for example), that value will be stored in the shader object and then recovered and used by PIX. If the -Fd flag is passed to fxc then this define is set automatically. For a descriptive string to be propagated, it must be wrapped in quotes. For example, to set this flag on the command line using fxc:
-D__XBOX_PDBFILENAME="\"foo bar\""
This example embeds "foo bar" into the precompiled shader objects. If d3dcompiler is being linked directly, __XBOX_PDBFILENAME can be added to the pDefines array.
__XBOX_PRESERVE_ALL_INPUTS This can be used with both the d3dcompiler and the (HLSL) shader compiler to attempt to preserve all inputs to the shader. This can be used to force shaders to have the same input signature, thus avoid provoking driver context rolls. Normally the HLSL tool chain will aggressively remove unused inputs.
__XBOX_ATTEMPT_WAVE_WIDENING Used with the HLSL tools to attempt to improve wave occupancy by driving down register usage. If this flag is set, the tools work by adjusting the instruction scheduler. This flag can significantly increase compile time. Performance of generated shaders can fall since increased occupancy can increase pressure on contended GPU components, such as the L2 cache. This flag is ignored if the __XBOX_WAVESIM_ITERATION or __XBOX_WAVESIM_ITERATION_N flags are set.
__XBOX_WAVESIM_ITERATION Optimize for single thread latency. The shader compiler attempts additional instruction schedules attempting to reduce estimated shader latency. This causes slower compile times than __XBOX_ATTEMPT_WAVE_WIDENING but generally finds better solutions. Consider trying this flag, or __XBOX_WAVESIM_ITERATION_N, on important shaders, such as for post-effects. Both these flags can significantly improve shader performance, driving down register usage and increasing occupancy, but are not enabled by default because they add to compile time and can make shader performance worse in some cases.
__XBOX_WAVESIM_ITERATION_N Optimize for throughput taking into account the effect of occupancy on execution on the CU.
__XBOX_PS_USE_RE_Z This is a compile time hint that the depth buffer should be run in RE_Z mode. This is generally helpful for large pixel shaders.
__XBOX_SKIP_SYNC_CHECKS Used to disable synchronization checks.
__XBOX_DISABLE_OPTIMISTIC_SCALAR_ALLOCATION Always reserve scalar registers for vector spill.
__XBOX_CONTROL_NONIEEE By default, the shader compiler will perform non-IEEE optimizations, mostly by ignoring the possibility of Nan. The shader compiler’s IEEE strictness can be specifically controlled by defining this flag. Globally this behavior is controlled with the –Gis switch to FXC, which will enable or disable non-IEEE strictness. If the __XBOX_CONTROL_NONIEEE flag is set it will override the Gis flag for the shader compiler. The following options are available.
Compile line D3dcompiler IEEE strict Shader compiler IEEE strict
default No No
-Gis Yes Yes
-D__XBOX_CONTROL_NONIEEE=0 No Yes
-Gis –D__XBOX_CONTROL_NONIEEE=1 Yes No
__XBOX_DISABLE_NONIEEE_ OPTIMIZATION_MASK0 __XBOX_DISABLE_NONIEEE_OPTIMIZATION_MASK is a bit mask. Setting the bits of the define can be used to disable some non-IEEE optimizations that are enabled by default. Masks are:
  • 0x1: Disable automatic use of vop2 min/max instructions (not compatible with nan).
  • 0x2: Disable automatic use of vop2 mad/mac instructions (not compatible with nan).
  • 0x4: Disable automatic use of rsq instruction (low precision).
__XBOX_DISABLE_V_TO_S Vector to scalar promotion optimization is on by default. The performance of the shader compiler usually benefits if you mark scalar values with the __XB_MakeUniform intrinsic. However, if you need to disable this feature, use the fxc define /D __XBOX_DISABLE_V_TO_S.
__XBOX_IMPROVE_MAD In HLSL code, instructs the compiler to consider the impact on register pressure when forming mads (multiply-add operations).
__XBOX_PRESERVE_MAD_LEGACY Non-IEEE codegen freely converts mad_legacy to mad (multiply-add operations). This might change computation results when NaN is involved; this should not be an issue because NaN is not reliable with non-IEEE codgen. To disable this feature, set this flag in HLSL code.
__XBOX_LATENCY_SCHEDULE In HLSL code, enables an improved latency scheduler. This can improve the instruction schedule, but might also increase register usage.
__XBOX_SET_SRD_SIZE_FROM_HLSL In HLSL code, reduces the size of descriptors. The shader compiler will derive the descriptor size from the HLSL type, which can reduce some descriptors from eight registers to four registers and reduce sreg usage.
__XBOX_DISABLE_ITERATION The shader compiler spends a significant amount time optimizing by default. This extra optimization is tuned to find opportunities in complex shaders. Set this flag in HLSL code to disable the extra optimization and reduce compile time.
__XBOX_ENABLE_CYCLE_ESTIMATE By default, the shader compiler does not generate cycle count estimates. To enable estimate computation, set this flag in HLSL code.
__XBOX_ENABLE_IDMAP Generation of the debug assembly information for PIX Shader Register Lifetime Flow skips generation of the ID map for large shaders by default. To enable creation of the ID map for large shaders, use this flag in HLSL code.
__XBOX_DISABLE_IDMAP In HLSL code, disables ID map generation for all shaders.
__XBOX_DISABLE_NATIVE_FRACT In HLSL code, disables use of the v_fract_f32 instruction. The HLSL tools make use of the v_fract_f32 instruction, but there is a known issue that it can return 1 for small negative numbers. An alternative to setting this define is to compile with IEEE precision (use the -Gis flag when compiling with fxc, and define __XBOX_CONTROL_NONIEEE=0).
__XBOX_RA_PRIORITY_SIZE_GLOBALEnables new priority logic for register allocation, which can reduce register usage in some cases. This flag is independent of all other register allocation controls.
__XBOX_HIGH_LATENCY_VMEMInforms the shader compiler's static performance estimator that VMEM has high latency. This can improve the performance of generated code for shaders that execute with a large amount of memory latency.

See also

D3DCOMPILE Constants

D3Dcompiler Intrinsics

GPU and Shader Acronyms