Skip to content

Commit

Permalink
Process Intel driver version under official schema
Browse files Browse the repository at this point in the history
In Intel graphics driver version schema, the build number that
determines if you have the latest driver installed is only part
of whole version number. The others are the identifier numbers
that represents operation system version or other information,
which are meaningless when comparing two version numbers.

Bug: 1015647, 363721, 908069, 890227
Change-Id: I121ebab2e401c85a01a2bc37b10bebfcb788cc5e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2124108
Commit-Queue: Lin Sun <lin.sun@intel.com>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Brian Sheedy <bsheedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#754422}
  • Loading branch information
Lin Sun authored and Commit Bot committed Mar 30, 2020
1 parent a5dc8e3 commit 03e50f4
Show file tree
Hide file tree
Showing 13 changed files with 518 additions and 23 deletions.
31 changes: 28 additions & 3 deletions content/test/gpu/gpu_tests/gpu_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,16 +185,41 @@ def MatchDriverTag(tag):
return DRIVER_TAG_MATCHER.match(tag.lower())


def EvaluateVersionComparison(version1, operation, version2):
def EvaluateVersionComparison(version, operation, ref_version,
os_name=None, driver_vendor=None):
def parse_version(ver):
if ver.isdigit():
return int(ver), ''
for i in range(0, len(ver)):
if not ver[i].isdigit():
return int(ver[:i]) if i > 0 else 0, ver[i:]

ver_list1 = version1.split('.')
ver_list2 = version2.split('.')
def is_old_intel_driver(ver_list):
assert len(ver_list) == 4
num, suffix = parse_version(ver_list[2])
assert not suffix
return num < 100

ver_list1 = version.split('.')
ver_list2 = ref_version.split('.')
# On Windows, if the driver vendor is Intel, the driver version should be
# compared based on the Intel graphics driver version schema.
# https://www.intel.com/content/www/us/en/support/articles/000005654/graphics-drivers.html
if os_name == 'win' and driver_vendor == 'intel':
# If either of the two versions doesn't match the Intel driver version
# schema, or they belong to different generation of version schema, they
# should not be compared.
if len(ver_list1) != 4 or len(ver_list2) != 4:
return operation == 'ne'
if is_old_intel_driver(ver_list1) != is_old_intel_driver(ver_list2):
return operation == 'ne'
if is_old_intel_driver(ver_list1):
ver_list1 = ver_list1[3:]
ver_list2 = ver_list2[3:]
else:
ver_list1 = ver_list1[2:]
ver_list2 = ver_list2[2:]

for i in range(0, max(len(ver_list1), len(ver_list2))):
ver1 = ver_list1[i] if i < len(ver_list1) else '0'
ver2 = ver_list2[i] if i < len(ver_list2) else '0'
Expand Down
74 changes: 73 additions & 1 deletion content/test/gpu/gpu_tests/test_expectations_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,39 @@
ResultType = json_results.ResultType


INTEL_DRIVER_VERSION_SCHEMA = '''
The version format of Intel graphics driver is AA.BB.CCC.DDDD.
DDDD(old schema) or CCC.DDDD(new schema) is the build number. That is,
indicates the actual driver number. The comparison between old schema
and new schema is NOT valid. In such a condition the only comparison
operator that returns true is "not equal".
AA.BB: You are free to specify the real number here, but they are meaningless
when comparing two version numbers. Usually it's okay to leave it to "0.0".
CCC: It's necessary for new schema. Regarding to old schema, you can specify
the real number or any number less than 100 in order to differentiate from
new schema.
DDDD: It's always meaningful. It must not be "0" under old schema.
Legal: "24.20.100.7000", "0.0.100.7000", "0.0.0.7000", "0.0.100.0"
Illegal: "24.0.0.0", "24.20.0.0", "0.0.99.0"
'''


def check_intel_driver_version(version):
ver_list = version.split('.')
if len(ver_list) != 4:
return False
for ver in ver_list:
if not ver.isdigit():
return False
if int(ver_list[2]) < 100 and ver_list[3] == '0':
return False
return True


def _MapGpuDevicesToVendors(tag_sets):
for tag_set in tag_sets:
if any(gpu in tag_set for gpu in GPU_CONDITIONS):
Expand Down Expand Up @@ -297,7 +330,12 @@ def testWebglTestExpectationsForDriverTags(self):
for tag_set in parser.tag_sets:
if gpu_helper.MatchDriverTag(list(tag_set)[0]):
for tag in tag_set:
assert gpu_helper.MatchDriverTag(tag)
match = gpu_helper.MatchDriverTag(tag)
assert match
if match.group(1) == 'intel':
if not check_intel_driver_version(match.group(3)):
assert False, INTEL_DRIVER_VERSION_SCHEMA

assert not driver_tag_set
driver_tag_set = tag_set
else:
Expand Down Expand Up @@ -416,3 +454,37 @@ def testFoundBrokenExpectations(self):
self.assertIn('3: Expectation with pattern \'a/b/d\' does not match'
' any tests in the GpuIntegrationTest test suite',
str(context.exception))

def testDriverVersionComparision(self):
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.100.7000', 'eq', '24.20.100.7000'))
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.100', 'ne', '24.20.100.7000'))
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.100.7000', 'gt', '24.20.100'))
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.100.7000a', 'gt', '24.20.100.7000'))
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.100.7000', 'lt', '24.20.100.7001'))
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.100.7000', 'lt', '24.20.200.6000'))
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.100.7000', 'lt', '25.30.100.6000', 'linux', 'intel'))
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.100.7000', 'gt', '25.30.100.6000', 'win', 'intel'))
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.101.6000', 'gt', '25.30.100.7000', 'win', 'intel'))
self.assertFalse(gpu_helper.EvaluateVersionComparison(
'24.20.99.7000', 'gt', '24.20.100.7000', 'win', 'intel'))
self.assertFalse(gpu_helper.EvaluateVersionComparison(
'24.20.99.7000', 'lt', '24.20.100.7000', 'win', 'intel'))
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.99.7000', 'ne', '24.20.100.7000', 'win', 'intel'))
self.assertFalse(gpu_helper.EvaluateVersionComparison(
'24.20.100', 'lt', '24.20.100.7000', 'win', 'intel'))
self.assertFalse(gpu_helper.EvaluateVersionComparison(
'24.20.100', 'gt', '24.20.100.7000', 'win', 'intel'))
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.100', 'ne', '24.20.100.7000', 'win', 'intel'))
self.assertTrue(gpu_helper.EvaluateVersionComparison(
'24.20.100.7000', 'eq', '25.20.100.7000', 'win', 'intel'))
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,8 @@ def GetPlatformTags(cls, browser):
assert match
if (driver_vendor == match.group(1) and
gpu_helper.EvaluateVersionComparison(
driver_version, match.group(2), match.group(3))):
driver_version, match.group(2), match.group(3),
browser.platform.GetOSName(), driver_vendor)):
tags.append(tag)
return tags

Expand Down
87 changes: 81 additions & 6 deletions gpu/config/gpu_control_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ int CompareLexicalNumberStrings(
return 0;
}

bool isOldIntelDriver(const std::vector<std::string>& version) {
DCHECK_EQ(4u, version.size());
unsigned value = 0;
bool valid = base::StringToUint(version[2], &value);
DCHECK(valid);
return value < 100;
}

// A mismatch is identified only if both |input| and |pattern| are not empty.
bool StringMismatch(const std::string& input, const std::string& pattern) {
if (input.empty() || pattern.empty())
Expand Down Expand Up @@ -234,14 +242,59 @@ void GpuControlList::Entry::LogControlListMatch(
control_list_logging_name.c_str());
}

bool GpuControlList::DriverInfo::Contains(const GPUInfo& gpu_info) const {
bool GpuControlList::DriverInfo::Contains(const GPUInfo& gpu_info,
VersionSchema version_schema) const {
const GPUInfo::GPUDevice& active_gpu = gpu_info.active_gpu();
if (StringMismatch(active_gpu.driver_vendor, driver_vendor)) {
return false;
}
if (driver_version.IsSpecified() && !active_gpu.driver_version.empty() &&
!driver_version.Contains(active_gpu.driver_version)) {
return false;
if (driver_version.IsSpecified() && !active_gpu.driver_version.empty()) {
if (version_schema == kCommon) {
if (!driver_version.Contains(active_gpu.driver_version))
return false;
} else if (version_schema == kIntelDriver) {
std::vector<std::string> version;
if (!ProcessVersionString(active_gpu.driver_version, '.', &version))
return false;
std::vector<std::string> ref_version, ref_version2;
bool valid = ProcessVersionString(driver_version.value1, '.',
&ref_version);
DCHECK(valid);
if (driver_version.value2) {
valid = ProcessVersionString(driver_version.value2, '.', &ref_version2);
DCHECK(valid);
}
// If either of the two versions doesn't match the Intel driver version + // schema, or they belong to different generation of version schema, they
// should not be compared.
if (version.size() != 4 || ref_version.size() != 4)
return false;
if (isOldIntelDriver(version) != isOldIntelDriver(ref_version))
return false;
if (!ref_version2.empty()) {
if (ref_version2.size() != 4
|| isOldIntelDriver(ref_version) != isOldIntelDriver(ref_version2))
return false;
}

std::string build_num, ref_build_num, ref_build_num2;
if (isOldIntelDriver(version)) {
build_num = version[3];
ref_build_num = ref_version[3];
if (!ref_version2.empty())
ref_build_num2 = ref_version2[3];
} else {
build_num = version[2] + "." + version[3];
ref_build_num = ref_version[2] + "." + ref_version[3];
if (!ref_version2.empty())
ref_build_num2 = ref_version2[2] + "." + ref_version2[3];
}
Version ref_driver_version(driver_version);
ref_driver_version.value1 = ref_build_num.c_str();
if (!ref_build_num2.empty())
ref_driver_version.value2 = ref_build_num2.c_str();
if (!ref_driver_version.Contains(build_num))
return false;
}
}
return true;
}
Expand Down Expand Up @@ -448,8 +501,30 @@ bool GpuControlList::Conditions::Contains(OsType target_os_type,
case kMultiGpuStyleNone:
break;
}
if (driver_info && !driver_info->Contains(gpu_info)) {
return false;

if (driver_info) {
// On Windows, if either current gpu or the gpu condition is from Intel,
// the driver version should be compared based on the Intel graphics driver
// version schema.
// https://www.intel.com/content/www/us/en/support/articles/000005654/graphics-drivers.html
VersionSchema version_schema = kCommon;
if (target_os_type == kOsWin) {
if (vendor_id == 0x8086
|| intel_gpu_series_list_size > 0
|| intel_gpu_generation.IsSpecified()
|| (driver_info->driver_vendor
&& std::string(driver_info->driver_vendor).find("Intel")
!= std::string::npos)) {
version_schema = kIntelDriver;
} else {
const GPUInfo::GPUDevice& active_gpu = gpu_info.active_gpu();
if (active_gpu.vendor_id == 0x8086
|| active_gpu.driver_vendor.find("Intel") != std::string::npos)
version_schema = kIntelDriver;
}
}
if (!driver_info->Contains(gpu_info, version_schema))
return false;
}
if (gl_strings && !gl_strings->Contains(gpu_info)) {
return false;
Expand Down
12 changes: 11 additions & 1 deletion gpu/config/gpu_control_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,15 @@ class GPU_EXPORT GpuControlList {
kVersionStyleUnknown
};

enum VersionSchema {
// All digits are meaningful when distinguishing versions.
kCommon,
// The version format of Intel graphics driver is AA.BB.CCC.DDDD.
// DDDD(old schema) or CCC.DDDD(new schema) is the build number.
// That is, indicates the actual driver number.
kIntelDriver,
};

enum SupportedOrNot {
kSupported,
kUnsupported,
Expand Down Expand Up @@ -124,7 +133,8 @@ class GPU_EXPORT GpuControlList {
const char* driver_vendor;
Version driver_version;

bool Contains(const GPUInfo& gpu_info) const;
bool Contains(const GPUInfo& gpu_info,
VersionSchema version_schema = kCommon) const;
};

struct GPU_EXPORT GLStrings {
Expand Down
55 changes: 55 additions & 0 deletions gpu/config/gpu_control_list_entry_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1111,4 +1111,59 @@ TEST_F(GpuControlListEntryTest, TestSubpixelFontRenderingDontCare) {
EXPECT_TRUE(entry.Contains(kOsChromeOS, "10.0", gpu_info));
}

TEST_F(GpuControlListEntryTest, IntelDriverVendorEntry) {
const Entry& entry =
GetEntry(kGpuControlListEntryTest_IntelDriverVendorEntry);
GPUInfo gpu_info;
gpu_info.gpu.driver_vendor = "Intel(R) UHD Graphics 630";
gpu_info.gpu.driver_version = "25.20.100.5000";
EXPECT_TRUE(entry.Contains(kOsLinux, "", gpu_info));
gpu_info.gpu.driver_version = "23.20.100.6500";
EXPECT_FALSE(entry.Contains(kOsLinux, "", gpu_info));

gpu_info.gpu.driver_version = "25.20.100.5000";
EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info));
gpu_info.gpu.driver_version = "23.20.100.6500";
EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info));
}

TEST_F(GpuControlListEntryTest, IntelDriverVersionEntry) {
const Entry& entry =
GetEntry(kGpuControlListEntryTest_IntelDriverVersionEntry);
GPUInfo gpu_info;
gpu_info.gpu.vendor_id = 0x8086;
gpu_info.gpu.driver_version = "23.20.100.8000";
EXPECT_TRUE(entry.Contains(kOsLinux, "", gpu_info));
gpu_info.gpu.driver_version = "25.20.100.6000";
EXPECT_FALSE(entry.Contains(kOsLinux, "", gpu_info));

gpu_info.gpu.driver_version = "23.20.100.8000";
EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info));
gpu_info.gpu.driver_version = "25.20.100.6000";
EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info));
gpu_info.gpu.driver_version = "24.20.99.6000";
EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info));
gpu_info.gpu.driver_version = "24.20.101.6000";
EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info));
gpu_info.gpu.driver_version = "25.20.100.7000";
EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info));
}

TEST_F(GpuControlListEntryTest, IntelOldDriverVersionEntry) {
const Entry& entry =
GetEntry(kGpuControlListEntryTest_IntelOldDriverVersionEntry);
GPUInfo gpu_info;
gpu_info.gpu.vendor_id = 0x8086;
gpu_info.gpu.driver_version = "23.20.10.8000";
EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info));
gpu_info.gpu.driver_version = "25.20.10.6000";
EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info));
gpu_info.gpu.driver_version = "24.20.100.6000";
EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info));
gpu_info.gpu.driver_version = "24.20.11.6000";
EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info));
gpu_info.gpu.driver_version = "25.20.9.7000";
EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info));
}

} // namespace gpu
39 changes: 38 additions & 1 deletion gpu/config/gpu_control_list_testing.json
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@
"vendor_id": "0x8086",
"driver_version": {
"op": "<",
"value": "10.7"
"value": "24.20.100.7000"
},
"features": [
"test_feature_1"
Expand Down Expand Up @@ -899,6 +899,43 @@
"features": [
"test_feature_0"
]
},
{
"id": 75,
"description": "GpuControlListEntryTest.IntelDriverVendorEntry",
"driver_vendor": "Intel.*",
"driver_version": {
"op": "between",
"value": "24.20.100.6000",
"value2": "26.20.100.7000"
},
"features": [
"test_feature_0"
]
},
{
"id": 76,
"description": "GpuControlListEntryTest.IntelDriverVersionEntry",
"vendor_id": "0x8086",
"driver_version": {
"op": "<=",
"value": "24.20.100.7000"
},
"features": [
"test_feature_0"
]
},
{
"id": 77,
"description": "GpuControlListEntryTest.IntelOldDriverVersionEntry",
"vendor_id": "0x8086",
"driver_version": {
"op": "<=",
"value": "24.20.10.7000"
},
"features": [
"test_feature_0"
]
}
]
}
Loading

0 comments on commit 03e50f4

Please sign in to comment.