From db34c78910773b9a5b092bf53bf5232582f1310e Mon Sep 17 00:00:00 2001 From: Xinghua Cao Date: Mon, 6 Jul 2020 08:28:00 +0000 Subject: [PATCH] Check FP16 support on D3D backend True FP16 is only supported in DXC through Shader Model 6.2, also check the value of the Native16BitShaderOpsSupported member of D3D12_FEATURE_DATA_D3D12_OPTIONS4 to view whether hardware actually supports FP16 operations. BUG=dawn:426 TEST=dawn_end2end_tests Change-Id: If675f7ba650cb1bd8c792928b70619b9ccda048a Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/23243 Reviewed-by: Corentin Wallez Commit-Queue: Xinghua Cao --- src/dawn_native/d3d12/AdapterD3D12.cpp | 3 ++ src/dawn_native/d3d12/D3D12Info.cpp | 59 ++++++++++++++++++++- src/dawn_native/d3d12/D3D12Info.h | 6 +++ src/dawn_native/d3d12/ShaderModuleD3D12.cpp | 54 ++++++++++--------- 4 files changed, 97 insertions(+), 25 deletions(-) diff --git a/src/dawn_native/d3d12/AdapterD3D12.cpp b/src/dawn_native/d3d12/AdapterD3D12.cpp index 68fa27c2e5..c6078e59b1 100644 --- a/src/dawn_native/d3d12/AdapterD3D12.cpp +++ b/src/dawn_native/d3d12/AdapterD3D12.cpp @@ -102,6 +102,9 @@ namespace dawn_native { namespace d3d12 { mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC); mSupportedExtensions.EnableExtension(Extension::PipelineStatisticsQuery); mSupportedExtensions.EnableExtension(Extension::TimestampQuery); + if (mDeviceInfo.supportsShaderFloat16 && GetBackend()->GetFunctions()->IsDXCAvailable()) { + mSupportedExtensions.EnableExtension(Extension::ShaderFloat16); + } } MaybeError Adapter::InitializeDebugLayerFilters() { diff --git a/src/dawn_native/d3d12/D3D12Info.cpp b/src/dawn_native/d3d12/D3D12Info.cpp index 6505e44aef..2ca6429b0c 100644 --- a/src/dawn_native/d3d12/D3D12Info.cpp +++ b/src/dawn_native/d3d12/D3D12Info.cpp @@ -59,6 +59,63 @@ namespace dawn_native { namespace d3d12 { } } - return info; + D3D12_FEATURE_DATA_SHADER_MODEL knownShaderModels[] = {{D3D_SHADER_MODEL_6_2}, + {D3D_SHADER_MODEL_6_1}, + {D3D_SHADER_MODEL_6_0}, + {D3D_SHADER_MODEL_5_1}}; + for (D3D12_FEATURE_DATA_SHADER_MODEL shaderModel : knownShaderModels) { + if (SUCCEEDED(adapter.GetDevice()->CheckFeatureSupport( + D3D12_FEATURE_SHADER_MODEL, &shaderModel, sizeof(shaderModel)))) { + if (shaderModel.HighestShaderModel < D3D_SHADER_MODEL_5_1) { + return DAWN_INTERNAL_ERROR( + "Driver could not support Shader Model 5.1 or higher"); + } + + switch (shaderModel.HighestShaderModel) { + case D3D_SHADER_MODEL_6_2: { + info.shaderModel = 62; + info.shaderProfiles[SingleShaderStage::Vertex] = L"vs_6_2"; + info.shaderProfiles[SingleShaderStage::Fragment] = L"ps_6_2"; + info.shaderProfiles[SingleShaderStage::Compute] = L"cs_6_2"; + + D3D12_FEATURE_DATA_D3D12_OPTIONS4 featureData4 = {}; + if (SUCCEEDED(adapter.GetDevice()->CheckFeatureSupport( + D3D12_FEATURE_D3D12_OPTIONS4, &featureData4, + sizeof(featureData4)))) { + info.supportsShaderFloat16 = + shaderModel.HighestShaderModel >= D3D_SHADER_MODEL_6_2 && + featureData4.Native16BitShaderOpsSupported; + } + break; + } + case D3D_SHADER_MODEL_6_1: { + info.shaderModel = 61; + info.shaderProfiles[SingleShaderStage::Vertex] = L"vs_6_1"; + info.shaderProfiles[SingleShaderStage::Fragment] = L"ps_6_1"; + info.shaderProfiles[SingleShaderStage::Compute] = L"cs_6_1"; + break; + } + case D3D_SHADER_MODEL_6_0: { + info.shaderModel = 60; + info.shaderProfiles[SingleShaderStage::Vertex] = L"vs_6_0"; + info.shaderProfiles[SingleShaderStage::Fragment] = L"ps_6_0"; + info.shaderProfiles[SingleShaderStage::Compute] = L"cs_6_0"; + break; + } + default: { + info.shaderModel = 51; + info.shaderProfiles[SingleShaderStage::Vertex] = L"vs_5_1"; + info.shaderProfiles[SingleShaderStage::Fragment] = L"ps_5_1"; + info.shaderProfiles[SingleShaderStage::Compute] = L"cs_5_1"; + break; + } + } + + // Successfully find the maximum supported shader model. + break; + } + } + + return std::move(info); } }} // namespace dawn_native::d3d12 diff --git a/src/dawn_native/d3d12/D3D12Info.h b/src/dawn_native/d3d12/D3D12Info.h index 78d3820816..cce74b17c5 100644 --- a/src/dawn_native/d3d12/D3D12Info.h +++ b/src/dawn_native/d3d12/D3D12Info.h @@ -16,6 +16,7 @@ #define DAWNNATIVE_D3D12_D3D12INFO_H_ #include "dawn_native/Error.h" +#include "dawn_native/PerStage.h" #include "dawn_native/d3d12/d3d12_platform.h" namespace dawn_native { namespace d3d12 { @@ -26,6 +27,11 @@ namespace dawn_native { namespace d3d12 { bool isUMA; uint32_t resourceHeapTier; bool supportsRenderPass; + bool supportsShaderFloat16; + // shaderModel indicates the maximum supported shader model, for example, the value 62 + // indicates that current driver supports the maximum shader model is D3D_SHADER_MODEL_6_2. + uint32_t shaderModel; + PerStage shaderProfiles; }; ResultOrError GatherDeviceInfo(const Adapter& adapter); diff --git a/src/dawn_native/d3d12/ShaderModuleD3D12.cpp b/src/dawn_native/d3d12/ShaderModuleD3D12.cpp index 770a006fb4..0bdbafa12c 100644 --- a/src/dawn_native/d3d12/ShaderModuleD3D12.cpp +++ b/src/dawn_native/d3d12/ShaderModuleD3D12.cpp @@ -31,7 +31,7 @@ namespace dawn_native { namespace d3d12 { namespace { - std::vector GetDXCArguments(uint32_t compileFlags) { + std::vector GetDXCArguments(uint32_t compileFlags, bool enable16BitTypes) { std::vector arguments; if (compileFlags & D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY) { arguments.push_back(L"/Gec"); @@ -70,9 +70,15 @@ namespace dawn_native { namespace d3d12 { if (compileFlags & D3DCOMPILE_RESOURCES_MAY_ALIAS) { arguments.push_back(L"/res_may_alias"); } - // Enable FXC backward compatibility by setting the language version to 2016 - arguments.push_back(L"-HV"); - arguments.push_back(L"2016"); + + if (enable16BitTypes) { + // enable-16bit-types are only allowed in -HV 2018 (default) + arguments.push_back(L"/enable-16bit-types"); + } else { + // Enable FXC backward compatibility by setting the language version to 2016 + arguments.push_back(L"-HV"); + arguments.push_back(L"2016"); + } return arguments; } @@ -98,7 +104,12 @@ namespace dawn_native { namespace d3d12 { shaderc_spvc::CompileOptions options = GetCompileOptions(); options.SetForceZeroInitializedVariables(true); - options.SetHLSLShaderModel(51); + if (GetDevice()->IsExtensionEnabled(Extension::ShaderFloat16)) { + options.SetHLSLShaderModel(ToBackend(GetDevice())->GetDeviceInfo().shaderModel); + options.SetHLSLEnable16BitTypes(true); + } else { + options.SetHLSLShaderModel(51); + } // PointCoord and PointSize are not supported in HLSL // TODO (hao.x.li@intel.com): The point_coord_compat and point_size_compat are // required temporarily for https://bugs.chromium.org/p/dawn/issues/detail?id=146, @@ -138,7 +149,12 @@ namespace dawn_native { namespace d3d12 { options_glsl.force_zero_initialized_variables = true; spirv_cross::CompilerHLSL::Options options_hlsl; - options_hlsl.shader_model = 51; + if (GetDevice()->IsExtensionEnabled(Extension::ShaderFloat16)) { + options_hlsl.shader_model = ToBackend(GetDevice())->GetDeviceInfo().shaderModel; + options_hlsl.enable_16bit_types = true; + } else { + options_hlsl.shader_model = 51; + } // PointCoord and PointSize are not supported in HLSL // TODO (hao.x.li@intel.com): The point_coord_compat and point_size_compat are // required temporarily for https://bugs.chromium.org/p/dawn/issues/detail?id=146, @@ -210,19 +226,6 @@ namespace dawn_native { namespace d3d12 { const std::string& hlslSource, const char* entryPoint, uint32_t compileFlags) { - const wchar_t* targetProfile = nullptr; - switch (stage) { - case SingleShaderStage::Vertex: - targetProfile = L"vs_6_0"; - break; - case SingleShaderStage::Fragment: - targetProfile = L"ps_6_0"; - break; - case SingleShaderStage::Compute: - targetProfile = L"cs_6_0"; - break; - } - IDxcLibrary* dxcLibrary; DAWN_TRY_ASSIGN(dxcLibrary, ToBackend(GetDevice())->GetOrCreateDxcLibrary()); @@ -237,13 +240,16 @@ namespace dawn_native { namespace d3d12 { std::wstring entryPointW; DAWN_TRY_ASSIGN(entryPointW, ConvertStringToWstring(entryPoint)); - std::vector arguments = GetDXCArguments(compileFlags); + std::vector arguments = GetDXCArguments( + compileFlags, GetDevice()->IsExtensionEnabled(Extension::ShaderFloat16)); ComPtr result; - DAWN_TRY(CheckHRESULT( - dxcCompiler->Compile(sourceBlob.Get(), nullptr, entryPointW.c_str(), targetProfile, - arguments.data(), arguments.size(), nullptr, 0, nullptr, &result), - "DXC compile")); + DAWN_TRY( + CheckHRESULT(dxcCompiler->Compile( + sourceBlob.Get(), nullptr, entryPointW.c_str(), + ToBackend(GetDevice())->GetDeviceInfo().shaderProfiles[stage].c_str(), + arguments.data(), arguments.size(), nullptr, 0, nullptr, &result), + "DXC compile")); HRESULT hr; DAWN_TRY(CheckHRESULT(result->GetStatus(&hr), "DXC get status"));