Commit 66c949d2 authored by brucedawson's avatar brucedawson Committed by Commit bot

Workaround DwmGetCompositionTimingInfo giving bad qpcRefreshPeriod

On at least one machine Chrome hits a problem where DwmGetCompositionTimingInfo
says that qpcRefreshPeriod is 60. This implies a refresh rate of ~34,000 fps.
Chrome dutifully tries to hit this frame rate leading to excessive CPU usage.

This change adds a couple of checks to detect bad values and fix them. In
parallel this bug is being reported.

R=piman@chromium.org
BUG=486226

Review URL: https://codereview.chromium.org/1141013004

Cr-Commit-Position: refs/heads/master@{#329983}
parent ea923596
......@@ -76,6 +76,19 @@ class WinVSyncProvider : public VSyncProvider {
HRESULT result = DwmGetCompositionTimingInfo(NULL, &timing_info);
if (result == S_OK) {
dwm_active = true;
// Calculate an interval value using the rateRefresh numerator and
// denominator.
base::TimeDelta rate_interval;
if (timing_info.rateRefresh.uiDenominator > 0 &&
timing_info.rateRefresh.uiNumerator > 0) {
// Swap the numerator/denominator to convert frequency to period.
rate_interval = base::TimeDelta::FromMicroseconds(
timing_info.rateRefresh.uiDenominator *
base::Time::kMicrosecondsPerSecond /
timing_info.rateRefresh.uiNumerator);
}
if (gfx::FrameTime::TimestampsAreHighRes()) {
// qpcRefreshPeriod is very accurate but noisy, and must be used with
// a high resolution timebase to avoid frequently missing Vsync.
......@@ -83,8 +96,18 @@ class WinVSyncProvider : public VSyncProvider {
static_cast<LONGLONG>(timing_info.qpcVBlank));
interval = base::TimeDelta::FromQPCValue(
static_cast<LONGLONG>(timing_info.qpcRefreshPeriod));
} else if (timing_info.rateRefresh.uiDenominator > 0 &&
timing_info.rateRefresh.uiNumerator > 0) {
// Check for interval values that are impossibly low. A 29 microsecond
// interval was seen (from a qpcRefreshPeriod of 60).
if (interval < base::TimeDelta::FromMilliseconds(1)) {
interval = rate_interval;
}
// Check for the qpcRefreshPeriod interval being improbably small
// compared to the rateRefresh calculated interval, as another
// attempt at detecting driver bugs.
if (!rate_interval.is_zero() && interval < rate_interval / 2) {
interval = rate_interval;
}
} else {
// If FrameTime is not high resolution, we do not want to translate
// the QPC value provided by DWM into the low-resolution timebase,
// which would be error prone and jittery. As a fallback, we assume
......@@ -92,12 +115,7 @@ class WinVSyncProvider : public VSyncProvider {
// isn't noisy like qpcRefreshPeriod, instead. The fact that we don't
// have a timebase here may lead to brief periods of jank when our
// scheduling becomes offset from the hardware vsync.
// Swap the numerator/denominator to convert frequency to period.
interval = base::TimeDelta::FromMicroseconds(
timing_info.rateRefresh.uiDenominator *
base::Time::kMicrosecondsPerSecond /
timing_info.rateRefresh.uiNumerator);
interval = rate_interval;
}
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment