Commit 67932a99 authored by Zhenyao Mo's avatar Zhenyao Mo Committed by Commit Bot

Test videos trigger the expected presentation mode on Windows.

We add a trace event when we present the video swapchain. These events
includes presentation mode and pixel format. Based on existence of such
events and their params, we can decide if the expected video frame
presentation happened.

Note that we found out that GetFrameStatisticsMedia is flaky and this is
out of our control. So if a test fails because of this, we repeat it a
couple times.

BUG=867136
TEST=GPU bots
R=kbr@chromium.org,piman@chromium.org,sunnyps@chromium.org

Change-Id: I1f0972f2887a72ad46f533edda274ffc7608790b
Reviewed-on: https://chromium-review.googlesource.com/c/1441374Reviewed-by: default avatarSunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Reviewed-by: default avatarKenneth Russell <kbr@chromium.org>
Commit-Queue: Zhenyao Mo <zmo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#628563}
parent 921ff0b9
...@@ -13,6 +13,13 @@ from gpu_tests import gpu_test_expectations ...@@ -13,6 +13,13 @@ from gpu_tests import gpu_test_expectations
_START_BROWSER_RETRIES = 3 _START_BROWSER_RETRIES = 3
# Please expand the following lists when we expand to new bot configs.
_SUPPORTED_WIN_VERSIONS = ['win7', 'win10']
_SUPPORTED_WIN_VERSIONS_WITH_DIRECT_COMPOSITION = ['win10']
_SUPPORTED_WIN_GPU_VENDORS = [0x8086, 0x10de, 0x1002]
_SUPPORTED_WIN_INTEL_GPUS = [0x5912]
_SUPPORTED_WIN_INTEL_GPUS_WITH_YUY2_OVERLAYS = [0x5912]
_SUPPORTED_WIN_INTEL_GPUS_WITH_NV12_OVERLAYS = [0x5912]
class GpuIntegrationTest( class GpuIntegrationTest(
serially_executed_browser_test_case.SeriallyExecutedBrowserTestCase): serially_executed_browser_test_case.SeriallyExecutedBrowserTestCase):
...@@ -254,6 +261,50 @@ class GpuIntegrationTest( ...@@ -254,6 +261,50 @@ class GpuIntegrationTest(
""" """
raise NotImplementedError raise NotImplementedError
def GetOverlayBotConfig(self):
"""Returns expected bot config for DirectComposition and overlay support.
This is only meaningful on Windows platform.
The rules to determine bot config are:
1) Only win10 or newer supports DirectComposition
2) Only Intel supports hardware overlays with DirectComposition
3) Currently the Win/Intel GPU bot supports YUY2 and NV12 overlays
"""
if self.browser is None:
raise Exception("Browser doesn't exist")
system_info = self.browser.GetSystemInfo()
if system_info is None:
raise Exception("Browser doesn't support GetSystemInfo")
gpu = system_info.gpu.devices[0]
if gpu is None:
raise Exception("System Info doesn't have a gpu")
gpu_vendor_id = gpu.vendor_id
gpu_device_id = gpu.device_id
os_version = self.browser.platform.GetOSVersionName()
if os_version is None:
raise Exception("browser.platform.GetOSVersionName() returns None")
os_version = os_version.lower()
config = {
'direct_composition': False,
'supports_overlays': False,
'overlay_cap_yuy2': 'NONE',
'overlay_cap_nv12': 'NONE',
}
assert os_version in _SUPPORTED_WIN_VERSIONS
assert gpu_vendor_id in _SUPPORTED_WIN_GPU_VENDORS
if os_version in _SUPPORTED_WIN_VERSIONS_WITH_DIRECT_COMPOSITION:
config['direct_composition'] = True
if gpu_vendor_id == 0x8086:
config['supports_overlays'] = True
assert gpu_device_id in _SUPPORTED_WIN_INTEL_GPUS
if gpu_device_id in _SUPPORTED_WIN_INTEL_GPUS_WITH_YUY2_OVERLAYS:
config['overlay_cap_yuy2'] = 'SCALING'
if gpu_device_id in _SUPPORTED_WIN_INTEL_GPUS_WITH_NV12_OVERLAYS:
config['overlay_cap_nv12'] = 'SCALING'
return config
@classmethod @classmethod
def GetExpectations(cls): def GetExpectations(cls):
if not cls._cached_expectations: if not cls._cached_expectations:
......
...@@ -7,14 +7,6 @@ from gpu_tests.gpu_test_expectations import GpuTestExpectations ...@@ -7,14 +7,6 @@ from gpu_tests.gpu_test_expectations import GpuTestExpectations
import sys import sys
# Please expand the following lists when we expand to new bot configs.
_SUPPORTED_WIN_VERSIONS = ['win7', 'win10']
_SUPPORTED_WIN_VERSIONS_WITH_DIRECT_COMPOSITION = ['win10']
_SUPPORTED_WIN_GPU_VENDORS = [0x8086, 0x10de, 0x1002]
_SUPPORTED_WIN_INTEL_GPUS = [0x5912]
_SUPPORTED_WIN_INTEL_GPUS_WITH_YUY2_OVERLAYS = [0x5912]
_SUPPORTED_WIN_INTEL_GPUS_WITH_NV12_OVERLAYS = [0x5912]
# There are no expectations for info_collection # There are no expectations for info_collection
class InfoCollectionExpectations(GpuTestExpectations): class InfoCollectionExpectations(GpuTestExpectations):
def SetExpectations(self): def SetExpectations(self):
...@@ -43,32 +35,6 @@ class InfoCollectionTest(gpu_integration_test.GpuIntegrationTest): ...@@ -43,32 +35,6 @@ class InfoCollectionTest(gpu_integration_test.GpuIntegrationTest):
cls.CustomizeBrowserArgs([]) cls.CustomizeBrowserArgs([])
cls.StartBrowser() cls.StartBrowser()
def _GetOverlayExpectations(self, os_version, gpu_vendor_id, gpu_device_id):
# The rules to set up per bot expectations are:
# 1) Only win10 or newer supports DirectComposition
# 2) Only Intel supports hardware overlays with DirectComposition
# 3) Currently the Win/Intel GPU bot supports YUY2 and NV12 overlays
expectations = {
'direct_composition': False,
'supports_overlays': False,
'overlay_cap_yuy2': 'NONE',
'overlay_cap_nv12': 'NONE',
}
assert os_version is not None
os_version = os_version.lower()
assert os_version in _SUPPORTED_WIN_VERSIONS
assert gpu_vendor_id in _SUPPORTED_WIN_GPU_VENDORS
if os_version in _SUPPORTED_WIN_VERSIONS_WITH_DIRECT_COMPOSITION:
expectations['direct_composition'] = True
if gpu_vendor_id == 0x8086:
expectations['supports_overlays'] = True
assert gpu_device_id in _SUPPORTED_WIN_INTEL_GPUS
if gpu_device_id in _SUPPORTED_WIN_INTEL_GPUS_WITH_YUY2_OVERLAYS:
expectations['overlay_cap_yuy2'] = 'SCALING'
if gpu_device_id in _SUPPORTED_WIN_INTEL_GPUS_WITH_NV12_OVERLAYS:
expectations['overlay_cap_nv12'] = 'SCALING'
return expectations
def RunActualGpuTest(self, test_path, *args): def RunActualGpuTest(self, test_path, *args):
# Make sure the GPU process is started # Make sure the GPU process is started
self.tab.action_runner.Navigate('chrome:gpu') self.tab.action_runner.Navigate('chrome:gpu')
...@@ -103,15 +69,13 @@ class InfoCollectionTest(gpu_integration_test.GpuIntegrationTest): ...@@ -103,15 +69,13 @@ class InfoCollectionTest(gpu_integration_test.GpuIntegrationTest):
os_name = self.browser.platform.GetOSName() os_name = self.browser.platform.GetOSName()
if os_name and os_name.lower() == 'win': if os_name and os_name.lower() == 'win':
expectations = self._GetOverlayExpectations( overlay_bot_config = self.GetOverlayBotConfig()
self.browser.platform.GetOSVersionName(),
detected_vendor_id, detected_device_id)
aux_attributes = system_info.gpu.aux_attributes aux_attributes = system_info.gpu.aux_attributes
if not aux_attributes: if not aux_attributes:
self.fail('GPU info does not have aux_attributes.') self.fail('GPU info does not have aux_attributes.')
for (field, expected) in expectations.iteritems(): for field, expected in overlay_bot_config.iteritems():
detected = aux_attributes.get(field, 'NONE') detected = aux_attributes.get(field, 'NONE')
if expected != detected: if expected != detected:
self.fail('%s mismatch, expected %s but got %s.' % self.fail('%s mismatch, expected %s but got %s.' %
......
...@@ -10,7 +10,8 @@ class PixelTestPage(object): ...@@ -10,7 +10,8 @@ class PixelTestPage(object):
""" """
def __init__(self, url, name, test_rect, revision, def __init__(self, url, name, test_rect, revision,
tolerance=2, browser_args=None, expected_colors=None, tolerance=2, browser_args=None, expected_colors=None,
gpu_process_disabled=False, optional_action=None): gpu_process_disabled=False, optional_action=None,
other_args=None):
super(PixelTestPage, self).__init__() super(PixelTestPage, self).__init__()
self.url = url self.url = url
self.name = name self.name = name
...@@ -35,6 +36,8 @@ class PixelTestPage(object): ...@@ -35,6 +36,8 @@ class PixelTestPage(object):
# action here is "CrashGpuProcess" then it would be defined in a # action here is "CrashGpuProcess" then it would be defined in a
# "_CrashGpuProcess" method in PixelIntegrationTest. # "_CrashGpuProcess" method in PixelIntegrationTest.
self.optional_action = optional_action self.optional_action = optional_action
# Whatever other settings a test need to specify.
self.other_args = other_args
def CopyWithNewBrowserArgsAndSuffix(self, browser_args, suffix): def CopyWithNewBrowserArgsAndSuffix(self, browser_args, suffix):
return PixelTestPage( return PixelTestPage(
...@@ -1269,8 +1272,8 @@ def DirectCompositionPages(base_name): ...@@ -1269,8 +1272,8 @@ def DirectCompositionPages(base_name):
'size': [55, 110], 'size': [55, 110],
'color': [12, 12, 255], 'color': [12, 12, 255],
'tolerance': tolerance_dc 'tolerance': tolerance_dc
} }],
]), other_args={'video_is_rotated': True}),
PixelTestPage( PixelTestPage(
'pixel_video_mp4_four_colors_rot_180.html', 'pixel_video_mp4_four_colors_rot_180.html',
...@@ -1306,8 +1309,8 @@ def DirectCompositionPages(base_name): ...@@ -1306,8 +1309,8 @@ def DirectCompositionPages(base_name):
'size': [110, 57], 'size': [110, 57],
'color': [255, 255, 15], 'color': [255, 255, 15],
'tolerance': tolerance_dc 'tolerance': tolerance_dc
} }],
]), other_args={'video_is_rotated': True}),
PixelTestPage( PixelTestPage(
'pixel_video_mp4_four_colors_rot_270.html', 'pixel_video_mp4_four_colors_rot_270.html',
...@@ -1357,8 +1360,8 @@ def DirectCompositionPages(base_name): ...@@ -1357,8 +1360,8 @@ def DirectCompositionPages(base_name):
'size': [55, 110], 'size': [55, 110],
'color': [255, 17, 24], 'color': [255, 17, 24],
'tolerance': tolerance_dc 'tolerance': tolerance_dc
} }],
]), other_args={'video_is_rotated': True}),
PixelTestPage( PixelTestPage(
'pixel_video_vp9.html', 'pixel_video_vp9.html',
...@@ -1526,6 +1529,6 @@ def DirectCompositionPages(base_name): ...@@ -1526,6 +1529,6 @@ def DirectCompositionPages(base_name):
'size': [65, 30], 'size': [65, 30],
'color': [44, 255, 16], 'color': [44, 255, 16],
'tolerance': tolerance_dc 'tolerance': tolerance_dc
} }],
]), other_args={'video_is_rotated': True}),
] ]
...@@ -21,3 +21,6 @@ class TraceTestExpectations(GpuTestExpectations): ...@@ -21,3 +21,6 @@ class TraceTestExpectations(GpuTestExpectations):
# context loss which results in hardware decoder loss. # context loss which results in hardware decoder loss.
self.Skip('*_Video_Context_Loss_MP4', ['android'], bug=580386) self.Skip('*_Video_Context_Loss_MP4', ['android'], bug=580386)
# Skip on platforms where DirectComposition isn't supported
self.Skip('VideoTraceTest_*',
['mac', 'linux', 'android', 'chromeos', 'win7'], bug=867136)
...@@ -1238,9 +1238,10 @@ bool DCLayerTree::SwapChainPresenter::PresentToSwapChain( ...@@ -1238,9 +1238,10 @@ bool DCLayerTree::SwapChainPresenter::PresentToSwapChain(
return false; return false;
} }
UMA_HISTOGRAM_ENUMERATION( OverlayFormat swap_chain_format =
"GPU.DirectComposition.SwapChainFormat2", is_yuv_swapchain_ ? g_overlay_format_used : OverlayFormat::kBGRA;
is_yuv_swapchain_ ? g_overlay_format_used : OverlayFormat::kBGRA); UMA_HISTOGRAM_ENUMERATION("GPU.DirectComposition.SwapChainFormat2",
swap_chain_format);
frames_since_color_space_change_++; frames_since_color_space_change_++;
...@@ -1248,10 +1249,25 @@ bool DCLayerTree::SwapChainPresenter::PresentToSwapChain( ...@@ -1248,10 +1249,25 @@ bool DCLayerTree::SwapChainPresenter::PresentToSwapChain(
if (SUCCEEDED(swap_chain_.CopyTo(swap_chain_media.GetAddressOf()))) { if (SUCCEEDED(swap_chain_.CopyTo(swap_chain_media.GetAddressOf()))) {
DCHECK(swap_chain_media); DCHECK(swap_chain_media);
DXGI_FRAME_STATISTICS_MEDIA stats = {}; DXGI_FRAME_STATISTICS_MEDIA stats = {};
if (SUCCEEDED(swap_chain_media->GetFrameStatisticsMedia(&stats))) { // GetFrameStatisticsMedia fails with DXGI_ERROR_FRAME_STATISTICS_DISJOINT
// sometimes, which means an event (such as power cycle) interrupted the
// gathering of presentation statistics. In this situation, calling the
// function again succeeds but returns with CompositionMode = NONE.
// Waiting for the DXGI adapter to finish presenting before calling the
// function doesn't get rid of the failure.
HRESULT hr = swap_chain_media->GetFrameStatisticsMedia(&stats);
if (SUCCEEDED(hr)) {
base::UmaHistogramSparse("GPU.DirectComposition.CompositionMode", base::UmaHistogramSparse("GPU.DirectComposition.CompositionMode",
stats.CompositionMode); stats.CompositionMode);
presentation_history_.AddSample(stats.CompositionMode); presentation_history_.AddSample(stats.CompositionMode);
TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("gpu.service"),
"SwapChainFrameInfo", TRACE_EVENT_SCOPE_THREAD,
"SwapChain.PresentationMode", stats.CompositionMode,
"SwapChain.PixelFormat", swap_chain_format);
} else {
TRACE_EVENT_INSTANT1(
TRACE_DISABLED_BY_DEFAULT("gpu.service"), "SwapChainFrameInfoInvalid",
TRACE_EVENT_SCOPE_THREAD, "ErrorCode", static_cast<uint32_t>(hr));
} }
} }
return true; return true;
......
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