Disable Vulkan backend on old Intel Windows driver version
Skip enabling Vulkan backend on Intel Windows driver version < 30.0.101.2111 due to many flaky issue.
Bug: chromium:1338622, dawn:1392
Change-Id: I6975783bdc18d8a94d6c35e134756e3713833a29
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/105741
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Hao Li <hao.x.li@intel.com>
diff --git a/src/dawn/common/GPUInfo.cpp b/src/dawn/common/GPUInfo.cpp
index 8a6f75d..4b80876 100644
--- a/src/dawn/common/GPUInfo.cpp
+++ b/src/dawn/common/GPUInfo.cpp
@@ -15,6 +15,9 @@
#include "dawn/common/GPUInfo.h"
#include <algorithm>
+#include <array>
+#include <iterator>
+#include <sstream>
#include "dawn/common/Assert.h"
@@ -33,18 +36,52 @@
// last two fields.
// See https://www.intel.com/content/www/us/en/support/articles/000005654/graphics.html for
// more details.
-uint32_t GetIntelD3DDriverBuildNumber(const D3DDriverVersion& driverVersion) {
- return driverVersion[2] * 10000 + driverVersion[3];
+uint32_t GetIntelWindowsDriverBuildNumber(const DriverVersion& driverVersion) {
+ size_t size = driverVersion.size();
+ ASSERT(size >= 2);
+ return driverVersion[size - 2] * 10000 + driverVersion[size - 1];
}
} // anonymous namespace
-int CompareD3DDriverVersion(PCIVendorID vendorId,
- const D3DDriverVersion& version1,
- const D3DDriverVersion& version2) {
+DriverVersion::DriverVersion() = default;
+
+DriverVersion::DriverVersion(const std::initializer_list<uint16_t>& version) {
+ ASSERT(version.size() <= kMaxVersionFields);
+ mDriverVersion->assign(version.begin(), version.end());
+}
+
+uint16_t& DriverVersion::operator[](size_t i) {
+ return mDriverVersion->operator[](i);
+}
+
+const uint16_t& DriverVersion::operator[](size_t i) const {
+ return mDriverVersion->operator[](i);
+}
+
+uint32_t DriverVersion::size() const {
+ return mDriverVersion->size();
+}
+
+std::string DriverVersion::ToString() const {
+ std::ostringstream oss;
+ if (mDriverVersion->size() > 0) {
+ // Convert all but the last element to avoid a trailing "."
+ std::copy(mDriverVersion->begin(), mDriverVersion->end() - 1,
+ std::ostream_iterator<uint16_t>(oss, "."));
+ // Add the last element
+ oss << mDriverVersion->back();
+ }
+
+ return oss.str();
+}
+
+int CompareWindowsDriverVersion(PCIVendorID vendorId,
+ const DriverVersion& version1,
+ const DriverVersion& version2) {
if (IsIntel(vendorId)) {
- uint32_t buildNumber1 = GetIntelD3DDriverBuildNumber(version1);
- uint32_t buildNumber2 = GetIntelD3DDriverBuildNumber(version2);
+ uint32_t buildNumber1 = GetIntelWindowsDriverBuildNumber(version1);
+ uint32_t buildNumber2 = GetIntelWindowsDriverBuildNumber(version2);
return buildNumber1 < buildNumber2 ? -1 : (buildNumber1 == buildNumber2 ? 0 : 1);
}
diff --git a/src/dawn/common/GPUInfo.h b/src/dawn/common/GPUInfo.h
index a96b907..855d05c 100644
--- a/src/dawn/common/GPUInfo.h
+++ b/src/dawn/common/GPUInfo.h
@@ -15,22 +15,42 @@
#ifndef SRC_DAWN_COMMON_GPUINFO_H_
#define SRC_DAWN_COMMON_GPUINFO_H_
-#include "dawn/common/GPUInfo_autogen.h"
+#include <string>
-#include <array>
+#include "dawn/common/GPUInfo_autogen.h"
+#include "dawn/common/StackContainer.h"
namespace gpu_info {
-using D3DDriverVersion = std::array<uint16_t, 4>;
+// Four uint16 fields could cover almost all driver version schemas:
+// D3D12: AA.BB.CCC.DDDD
+// Vulkan: AAA.BBB.CCC.DDD on Nvidia, CCC.DDDD for Intel Windows, and AA.BB.CCC for others,
+// See https://vulkan.gpuinfo.org/
+static constexpr uint32_t kMaxVersionFields = 4;
+
+class DriverVersion {
+ public:
+ DriverVersion();
+ DriverVersion(const std::initializer_list<uint16_t>& version);
+
+ uint16_t& operator[](size_t i);
+ const uint16_t& operator[](size_t i) const;
+
+ uint32_t size() const;
+ std::string ToString() const;
+
+ private:
+ StackVector<uint16_t, kMaxVersionFields> mDriverVersion;
+};
// Do comparison between two driver versions. Currently we only support the comparison between
-// Intel D3D driver versions.
+// Intel Windows driver versions.
// - Return -1 if build number of version1 is smaller
// - Return 1 if build number of version1 is bigger
// - Return 0 if version1 and version2 represent same driver version
-int CompareD3DDriverVersion(PCIVendorID vendorId,
- const D3DDriverVersion& version1,
- const D3DDriverVersion& version2);
+int CompareWindowsDriverVersion(PCIVendorID vendorId,
+ const DriverVersion& version1,
+ const DriverVersion& version2);
// Intel architectures
bool IsSkylake(PCIDeviceID deviceId);
diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp
index 2c3fafb..426b284 100644
--- a/src/dawn/native/Adapter.cpp
+++ b/src/dawn/native/Adapter.cpp
@@ -169,6 +169,10 @@
return mDeviceId;
}
+const gpu_info::DriverVersion& AdapterBase::GetDriverVersion() const {
+ return mDriverVersion;
+}
+
wgpu::BackendType AdapterBase::GetBackendType() const {
return mBackend;
}
diff --git a/src/dawn/native/Adapter.h b/src/dawn/native/Adapter.h
index 8bef321..67b4e88 100644
--- a/src/dawn/native/Adapter.h
+++ b/src/dawn/native/Adapter.h
@@ -19,6 +19,7 @@
#include "dawn/native/DawnNative.h"
+#include "dawn/common/GPUInfo.h"
#include "dawn/common/RefCounted.h"
#include "dawn/common/ityp_span.h"
#include "dawn/native/Error.h"
@@ -50,6 +51,7 @@
uint32_t GetVendorId() const;
uint32_t GetDeviceId() const;
+ const gpu_info::DriverVersion& GetDriverVersion() const;
wgpu::BackendType GetBackendType() const;
InstanceBase* GetInstance() const;
@@ -72,6 +74,7 @@
uint32_t mDeviceId = 0xFFFFFFFF;
std::string mName;
wgpu::AdapterType mAdapterType = wgpu::AdapterType::Unknown;
+ gpu_info::DriverVersion mDriverVersion;
std::string mDriverDescription;
// Features set that CAN be supported by devices of this adapter. Some features in this set may
diff --git a/src/dawn/native/d3d12/AdapterD3D12.cpp b/src/dawn/native/d3d12/AdapterD3D12.cpp
index 2e749de..0b9d284 100644
--- a/src/dawn/native/d3d12/AdapterD3D12.cpp
+++ b/src/dawn/native/d3d12/AdapterD3D12.cpp
@@ -14,7 +14,7 @@
#include "dawn/native/d3d12/AdapterD3D12.h"
-#include <sstream>
+#include <string>
#include "dawn/common/Constants.h"
#include "dawn/common/WindowsUtils.h"
@@ -57,10 +57,6 @@
return mD3d12Device;
}
-const gpu_info::D3DDriverVersion& Adapter::GetDriverVersion() const {
- return mDriverVersion;
-}
-
MaybeError Adapter::InitializeImpl() {
// D3D12 cannot check for feature support without a device.
// Create the device to populate the adapter properties then reuse it when needed for actual
@@ -94,14 +90,12 @@
if (mHardwareAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &umdVersion) !=
DXGI_ERROR_UNSUPPORTED) {
uint64_t encodedVersion = umdVersion.QuadPart;
-
- std::ostringstream o;
- o << "D3D12 driver version ";
- for (size_t i = 0; i < mDriverVersion.size(); ++i) {
- mDriverVersion[i] = (encodedVersion >> (48 - 16 * i)) & 0xFFFF;
- o << mDriverVersion[i] << ".";
- }
- mDriverDescription = o.str();
+ uint16_t mask = 0xFFFF;
+ mDriverVersion = {static_cast<uint16_t>((encodedVersion >> 48) & mask),
+ static_cast<uint16_t>((encodedVersion >> 32) & mask),
+ static_cast<uint16_t>((encodedVersion >> 16) & mask),
+ static_cast<uint16_t>(encodedVersion & mask)};
+ mDriverDescription = std::string("D3D12 driver version ") + mDriverVersion.ToString();
}
return {};
diff --git a/src/dawn/native/d3d12/AdapterD3D12.h b/src/dawn/native/d3d12/AdapterD3D12.h
index 2c8a377..aa3538c 100644
--- a/src/dawn/native/d3d12/AdapterD3D12.h
+++ b/src/dawn/native/d3d12/AdapterD3D12.h
@@ -17,7 +17,6 @@
#include "dawn/native/Adapter.h"
-#include "dawn/common/GPUInfo.h"
#include "dawn/native/d3d12/D3D12Info.h"
#include "dawn/native/d3d12/d3d12_platform.h"
@@ -37,7 +36,6 @@
IDXGIAdapter3* GetHardwareAdapter() const;
Backend* GetBackend() const;
ComPtr<ID3D12Device> GetDevice() const;
- const gpu_info::D3DDriverVersion& GetDriverVersion() const;
private:
ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
@@ -60,7 +58,6 @@
ComPtr<IDXGIAdapter3> mHardwareAdapter;
ComPtr<ID3D12Device> mD3d12Device;
- gpu_info::D3DDriverVersion mDriverVersion;
Backend* mBackend;
D3D12DeviceInfo mDeviceInfo = {};
diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp
index f01915d..e8c6fe1 100644
--- a/src/dawn/native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn/native/d3d12/DeviceD3D12.cpp
@@ -688,9 +688,9 @@
// Currently this workaround is only needed on Intel Gen9, Gen9.5 and Gen11 GPUs.
// See http://crbug.com/1161355 for more information.
if (gpu_info::IsIntelGen9(vendorId, deviceId) || gpu_info::IsIntelGen11(vendorId, deviceId)) {
- constexpr gpu_info::D3DDriverVersion kFixedDriverVersion = {31, 0, 101, 2114};
- if (gpu_info::CompareD3DDriverVersion(vendorId, ToBackend(GetAdapter())->GetDriverVersion(),
- kFixedDriverVersion) < 0) {
+ const gpu_info::DriverVersion kFixedDriverVersion = {31, 0, 101, 2114};
+ if (gpu_info::CompareWindowsDriverVersion(vendorId, GetAdapter()->GetDriverVersion(),
+ kFixedDriverVersion) < 0) {
SetToggle(
Toggle::UseTempBufferInSmallFormatTextureToTextureCopyFromGreaterToLessMipLevel,
true);
@@ -721,9 +721,9 @@
// This workaround is only needed on Intel Gen12LP with driver prior to 30.0.101.1692.
// See http://crbug.com/dawn/949 for more information.
if (gpu_info::IsIntelGen12LP(vendorId, deviceId)) {
- constexpr gpu_info::D3DDriverVersion kFixedDriverVersion = {30, 0, 101, 1692};
- if (gpu_info::CompareD3DDriverVersion(vendorId, ToBackend(GetAdapter())->GetDriverVersion(),
- kFixedDriverVersion) == -1) {
+ const gpu_info::DriverVersion kFixedDriverVersion = {30, 0, 101, 1692};
+ if (gpu_info::CompareWindowsDriverVersion(vendorId, GetAdapter()->GetDriverVersion(),
+ kFixedDriverVersion) == -1) {
SetToggle(Toggle::D3D12AllocateExtraMemoryFor2DArrayTexture, true);
}
}
diff --git a/src/dawn/native/vulkan/AdapterVk.cpp b/src/dawn/native/vulkan/AdapterVk.cpp
index b05f03e..be468e8 100644
--- a/src/dawn/native/vulkan/AdapterVk.cpp
+++ b/src/dawn/native/vulkan/AdapterVk.cpp
@@ -17,14 +17,45 @@
#include <algorithm>
#include <string>
+#include "dawn/common/GPUInfo.h"
#include "dawn/native/Limits.h"
#include "dawn/native/vulkan/BackendVk.h"
#include "dawn/native/vulkan/DeviceVk.h"
-#include "dawn/common/GPUInfo.h"
-
namespace dawn::native::vulkan {
+namespace {
+
+gpu_info::DriverVersion DecodeVulkanDriverVersion(uint32_t vendorID, uint32_t versionRaw) {
+ gpu_info::DriverVersion driverVersion;
+ switch (vendorID) {
+ case gpu_info::kVendorID_Nvidia:
+ driverVersion = {static_cast<uint16_t>((versionRaw >> 22) & 0x3FF),
+ static_cast<uint16_t>((versionRaw >> 14) & 0x0FF),
+ static_cast<uint16_t>((versionRaw >> 6) & 0x0FF),
+ static_cast<uint16_t>(versionRaw & 0x003F)};
+ break;
+ case gpu_info::kVendorID_Intel:
+#if DAWN_PLATFORM_IS(WINDOWS)
+ // Windows Vulkan driver releases together with D3D driver, so they share the same
+ // version. But only CCC.DDDD is encoded in 32-bit driverVersion.
+ driverVersion = {static_cast<uint16_t>(versionRaw >> 14),
+ static_cast<uint16_t>(versionRaw & 0x3FFF)};
+ break;
+#endif
+ default:
+ // Use Vulkan driver conversions for other vendors
+ driverVersion = {static_cast<uint16_t>(versionRaw >> 22),
+ static_cast<uint16_t>((versionRaw >> 12) & 0x3FF),
+ static_cast<uint16_t>(versionRaw & 0xFFF)};
+ break;
+ }
+
+ return driverVersion;
+}
+
+} // anonymous namespace
+
Adapter::Adapter(InstanceBase* instance,
VulkanInstance* vulkanInstance,
VkPhysicalDevice physicalDevice)
@@ -59,14 +90,35 @@
MaybeError Adapter::InitializeImpl() {
DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this));
+ mDriverVersion = DecodeVulkanDriverVersion(mDeviceInfo.properties.vendorID,
+ mDeviceInfo.properties.driverVersion);
+ const std::string driverVersionStr = mDriverVersion.ToString();
+
+#if DAWN_PLATFORM_IS(WINDOWS)
+ // Disable Vulkan adapter on Windows Intel driver < 30.0.101.2111 due to flaky
+ // issues.
+ const gpu_info::DriverVersion kDriverVersion({30, 0, 101, 2111});
+ if (gpu_info::IsIntel(mDeviceInfo.properties.vendorID) &&
+ gpu_info::CompareWindowsDriverVersion(mDeviceInfo.properties.vendorID, mDriverVersion,
+ kDriverVersion) == -1) {
+ return DAWN_FORMAT_INTERNAL_ERROR(
+ "Disable Intel Vulkan adapter on Windows driver version %s. See "
+ "https://crbug.com/1338622.",
+ driverVersionStr);
+ }
+#endif
+
if (mDeviceInfo.HasExt(DeviceExt::DriverProperties)) {
mDriverDescription = mDeviceInfo.driverProperties.driverName;
if (mDeviceInfo.driverProperties.driverInfo[0] != '\0') {
mDriverDescription += std::string(": ") + mDeviceInfo.driverProperties.driverInfo;
}
+ // There may be no driver version in driverInfo.
+ if (mDriverDescription.find(driverVersionStr) == std::string::npos) {
+ mDriverDescription += std::string(" ") + driverVersionStr;
+ }
} else {
- mDriverDescription =
- "Vulkan driver version: " + std::to_string(mDeviceInfo.properties.driverVersion);
+ mDriverDescription = std::string("Vulkan driver version ") + driverVersionStr;
}
mDeviceId = mDeviceInfo.properties.deviceID;
diff --git a/src/dawn/tests/DawnTest.cpp b/src/dawn/tests/DawnTest.cpp
index 7e18885..e7638e0 100644
--- a/src/dawn/tests/DawnTest.cpp
+++ b/src/dawn/tests/DawnTest.cpp
@@ -387,16 +387,6 @@
(properties.backendType == wgpu::BackendType::Null);
}
-#if DAWN_PLATFORM_IS(WINDOWS)
- if (selected && !mRunSuppressedTests &&
- properties.backendType == wgpu::BackendType::Vulkan &&
- gpu_info::IsIntel(properties.vendorID)) {
- dawn::WarningLog()
- << "Deselecting Windows Intel Vulkan adapter. See https://crbug.com/1338622.";
- selected &= false;
- }
-#endif
-
// In Windows Remote Desktop sessions we may be able to discover multiple adapters that
// have the same name and backend type. We will just choose one adapter from them in our
// tests.
diff --git a/src/dawn/tests/unittests/GPUInfoTests.cpp b/src/dawn/tests/unittests/GPUInfoTests.cpp
index 42f12cb..be01489 100644
--- a/src/dawn/tests/unittests/GPUInfoTests.cpp
+++ b/src/dawn/tests/unittests/GPUInfoTests.cpp
@@ -18,14 +18,26 @@
namespace {
const PCIVendorID vendorID = 0x8086;
-const gpu_info::D3DDriverVersion version1 = {20, 19, 15, 5107};
-const gpu_info::D3DDriverVersion version2 = {21, 20, 16, 5077};
-const gpu_info::D3DDriverVersion version3 = {27, 20, 100, 9946};
-const gpu_info::D3DDriverVersion version4 = {27, 20, 101, 2003};
+// Intel D3D12
+const gpu_info::DriverVersion version1 = {20, 19, 15, 5107};
+const gpu_info::DriverVersion version2 = {21, 20, 16, 5077};
+const gpu_info::DriverVersion version3 = {27, 20, 100, 9946};
+const gpu_info::DriverVersion version4 = {27, 20, 101, 2003};
+// Intel Vulkan
+const gpu_info::DriverVersion version5 = {100, 9466};
+const gpu_info::DriverVersion version6 = {101, 3222};
+const gpu_info::DriverVersion version7 = {101, 3790};
+
} // anonymous namespace
-TEST(GPUInfo, CompareD3DDriverVersion) {
- EXPECT_EQ(gpu_info::CompareD3DDriverVersion(vendorID, version1, version2), -1);
- EXPECT_EQ(gpu_info::CompareD3DDriverVersion(vendorID, version2, version3), -1);
- EXPECT_EQ(gpu_info::CompareD3DDriverVersion(vendorID, version3, version4), -1);
+TEST(GPUInfo, CompareWindowsDriverVersion) {
+ EXPECT_EQ(gpu_info::CompareWindowsDriverVersion(vendorID, version1, version2), -1);
+ EXPECT_EQ(gpu_info::CompareWindowsDriverVersion(vendorID, version2, version3), -1);
+ EXPECT_EQ(gpu_info::CompareWindowsDriverVersion(vendorID, version3, version4), -1);
+ EXPECT_EQ(gpu_info::CompareWindowsDriverVersion(vendorID, version5, version6), -1);
+ EXPECT_EQ(gpu_info::CompareWindowsDriverVersion(vendorID, version6, version7), -1);
+ // Windows Vulkan driver releases together with D3D12 driver, so they share the same version.
+ // Expect Intel D3D12 driver and Vulkan driver to be comparable.
+ EXPECT_EQ(gpu_info::CompareWindowsDriverVersion(vendorID, version3, version6), -1);
+ EXPECT_EQ(gpu_info::CompareWindowsDriverVersion(vendorID, version4, version7), -1);
}