19 Shader Model 6
Chuck Walbourn редактировал(а) эту страницу 2022-04-26 16:56:25 -07:00
DirectXTK

As of the June 2021 release, DirectX Tool Kit for DX12 defaults to using Shader Model 6 for VS 2019 projects. As of the October 2021 release, the VS 2017 projects use Shader Model 6. The directx-vs-templates for DirectX 12 check for Shader Model 6 support as of May 2021.

Shader Model 6 is the latest HLSL compiler technology. It is required for DirectX Raytracing, DirectML, DirectX Mesh & Amplification Shaders, and a number of other DirectX 12 features. The DXIL compiler (DXC ) generates Shader Model 6 programs, and the compiler is based on LLVM and is hosted on GitHub. A prebuilt version of DXC.EXE is provided in the Windows 10 SDK (17134 or later).

DirectX 11 does not support Shader Model 6 shaders.

Checking for Shader Model 6 support level

While most modern DirectX 12 drivers support Shader Model 6, you need to verify the level of support required by your program.

D3D12_FEATURE_DATA_SHADER_MODEL shaderModel = { D3D_SHADER_MODEL_6_0 };
if (FAILED(device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shaderModel, sizeof(shaderModel)))
    || (shaderModel.HighestShaderModel < D3D_SHADER_MODEL_6_0))
{
#ifdef _DEBUG
    OutputDebugStringA("ERROR: Shader Model 6.0 is not supported!\n");
#endif
    throw std::exception("Shader Model 6.0 is not supported!");
}

For higher shader models, you may be running on a system that doesn't recognize them, so the logic is slightly more complex in this case. This code finds the highest possible supported level, which is overkill in most cases, but is a useful reference:

D3D12_FEATURE_DATA_SHADER_MODEL shaderModel = {};

#if defined(NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB)
shaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_6;
#elif defined(NTDDI_WIN10_19H1) && (NTDDI_VERSION >= NTDDI_WIN10_19H1)
shaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_5;
#elif defined(NTDDI_WIN10_RS5) && (NTDDI_VERSION >= NTDDI_WIN10_RS5)
shaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_4;
#elif defined(NTDDI_WIN10_RS4) && (NTDDI_VERSION >= NTDDI_WIN10_RS4)
shaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_2;
#elif defined(NTDDI_WIN10_RS3) && (NTDDI_VERSION >= NTDDI_WIN10_RS3)
shaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_1;
#else
shaderModel.HighestShaderModel = D3D_SHADER_MODEL_6_0;
#endif

HRESULT hr = device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shaderModel, sizeof(shaderModel));
while (hr == E_INVALIDARG && shaderModel.HighestShaderModel > D3D_SHADER_MODEL_6_0)
{
    shaderModel.HighestShaderModel = static_cast<D3D_SHADER_MODEL>(static_cast<int>(shaderModel.HighestShaderModel) - 1);
    hr = device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &shaderModel, sizeof(shaderModel));
}

if (FAILED(hr))
{
    shaderModel.HighestShaderModel = D3D_SHADER_MODEL_5_1;
}

Note that a number of Shader Model levels were defined originally as 'experimental' so were not supported by the released DXC compiler or production drivers until later releases of Windows.

The code above assumes you are building with Windows 10 SDK (14393) or later. Shader Model 6 was not supported prior to Windows 10 Anniversary Update (14393).

Using Shader Model 6 shaders for DirectX Tool Kit

By default shaders are built with FXC for Shader Model 5.1 (using Root Signature 1.1). To use Shader Model 6, invoke the CompileScripts.cmd with dxil:

CompileShaders dxil

Be sure your application verifies that Shader Model 6 is supported before using the DirectX Tool Kit effects, SpriteBatch, or any other shader-using class or you will get runtime errors/C++ exceptions that may be harder to diagnose.

If you wish to modify the Visual Studio vcxproj that invokes the shader build to use DXIL, modify the Exec statement near the bottom of the file as follows:

<Target Name="ATGEnsureShaders" BeforeTargets="PrepareForBuild">
    <Exec Condition="!Exists('src/Shaders/Compiled/SpriteEffect_SpriteVertexShader.inc')"
          WorkingDirectory="$(ProjectDir)src/Shaders"
          Command="CompileShaders dxil"
          EnvironmentVariables="WindowsSdkVerBinPath=$(WDKBinRoot)" />
</Target>

Visual Studio HLSL integration

The FXCCompile task in Visual Studio is used automatically for .hlsl files. If set to Shader Model 6 or later, MSBuild will invoke the DXC.EXE compiler rather than FXC.EXE.

If you plan to use Shader Model 6 in your project, it's a good idea to edit your vcxproj file in a text editor and update the ItemDefinitionGroup entries each platform to set a reasonable default value:

<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Link>
...
    </Link>
    <ClCompile>
...
    </ClCompile>
    <FXCompile>
      <ShaderModel>6.0</ShaderModel>
      <EnableDebuggingInformation>true</EnableDebuggingInformation>
      <AdditionalOptions>/Fd "$(OutDir)%(Filename).pdb" %(AdditionalOptions)</AdditionalOptions>
    </FXCompile>
/ItemDefinitionGroup>

Be sure to update all the configurations in your project (Release|x64, Debug|Win32, Release|Win32, etc.).

External PDBs

The FXC.EXE compiler defaulted to putting the shader debug information inside the shader blob which is simple, but can lead to 'bloaty' shader blobs. The recommendation is to use external PDBs instead, and the newer versions of DXC.EXE will generate warnings if you use embedded symbols. The /Fd statement above supports external PDBs above.

Be careful about name collisions between shader files and C/C++ source files. While MyFile.cso and MyFile.obj won't collide, their corresponding MyFile.pdb will collide which can result in very weird linker/debug symbol errors.

Shader Model levels

VS 2017 supports setting Shader Model 6.0, 6.1, 6.2, or 6.3. VS 2019 supports 6.0 - 6.4. They support Vertex Shader, Pixel Shader, Geometry Shader, Hull Shader, Domain Shader, and Compute Shader.

VS 2019 (16.8) or later supports 6.5, Mesh Shader, and Amplification Shaders as long as you have the Windows SDK (20348) or later in the path for the updated DXC.EXE compiler. VS 2022 adds 6.6 if using the Windows SDK (22000) or later.

If you need to build with a higher shader model or a shader type that is not supported by the property pages, the workaround is to (a) set the highest level supported (such as Shader Model 6.3 for a VS 2017 project):

Shader Model 6.3 set in General property page

Then (b) use the Additional Options area to provide the correct target parameter (here we are building a Shader Model 6.5 Mesh Shader):

Shader Model 6.5 set in Additional Options property page

Further reading

Microsoft Docs: Shader Model 6

DirectXShaderCompiler GitHub

Announcing Microsoft DirectX Raytracing! (requires Shader Model 6.3 or later)

Direct Machine Learning (DirectML) (requires Shader Model 6.4 or later)

Mesh Shaders and Amplification Shaders: Reinventing the Geometry Pipeline (requires Shader Model 6.5 or later)