Commit 57167a3a authored by Brian Sheedy's avatar Brian Sheedy Committed by Commit Bot

Update XR perf runtimes

Adds an OpenXR perf runtime and removes the OpenVR/WMR/Oculus ones since
the latter are removed or on their way out and the former is becoming
the default.

Bug: 1124425
Change-Id: Id2c0a03e3d6ff002ce22afe9c1c7e012ee3f04e0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2392939
Commit-Queue: Brian Sheedy <bsheedy@chromium.org>
Auto-Submit: Brian Sheedy <bsheedy@chromium.org>
Reviewed-by: default avatarAlexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#804451}
parent e49b3f41
......@@ -46,8 +46,8 @@ group("vr_perf_tests") {
}
if (is_win) {
if (enable_openvr) {
deps += [ "//device/vr:openvr_mock" ]
if (enable_openxr) {
deps += [ "//device/vr:openxr_mock" ]
}
}
}
......
......@@ -2,11 +2,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import os
import sys
ALL_RUNTIMES = frozenset(['OculusVR', 'OpenVR', 'WindowsMixedReality'])
ALL_RUNTIMES = frozenset(['OpenXR'])
SANDBOX_FEATURE = 'XRSandbox'
......@@ -32,6 +33,15 @@ class DesktopRuntimeBase(object):
self._finder_options.browser_options.AppendExtraBrowserArgs(
'--disable-features=%s' % SANDBOX_FEATURE)
if self._finder_options.mock_runtime_directory:
self._mock_runtime_directory = os.path.abspath(
self._finder_options.mock_runtime_directory)
else:
self._mock_runtime_directory = os.path.abspath(
os.path.join(self._possible_browser.browser_directory,
'mock_vr_clients'))
logging.warning('Using mock directory %s', self._mock_runtime_directory)
def Setup(self):
"""Called once before any stories are run."""
raise NotImplementedError(
......
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import os
import subprocess
from contrib.vr_benchmarks.desktop_runtimes import base_runtime
# pylint: disable=abstract-method
class _BaseOculusRuntime(base_runtime.DesktopRuntimeBase):
"""Base class for all Oculus runtimes."""
def __init__(self, *args, **kwargs):
super(_BaseOculusRuntime, self).__init__(*args, **kwargs)
def GetFeatureName(self):
return 'OculusVR'
class OculusRuntimeReal(_BaseOculusRuntime):
"""Class for using the real Oculus runtime for desktop tests."""
OCULUS_BASE_ENVIRONMENT_VARIABLE = 'OculusBase'
def __init__(self, *args, **kwargs):
super(OculusRuntimeReal, self).__init__(*args, **kwargs)
self._runtime_handle = None
def Setup(self):
# We need to launch the Oculus client before running any tests to ensure
# that the runtime is ready when we try to enter VR.
self._runtime_handle = subprocess.Popen([self._GetOculusClientPath()])
def WillRunStory(self):
if not self._runtime_handle:
raise RuntimeError(
'Somehow called real Oculus pre-story without calling setup')
if self._runtime_handle.poll() != None:
logging.warning(
'Oculus client closed prematurely with code %d, restarting',
self._runtime_handle.returncode)
self._runtime_handle = subprocess.Popen([self._GetOculusClientPath()])
def TearDown(self):
if not self._runtime_handle:
raise RuntimeError(
'Somehow called real Oculus tear down without calling setup')
if self._runtime_handle.poll() is None:
self._runtime_handle.terminate()
def _GetOculusClientPath(self):
# The install location of the Oculus runtime is set in the OculusBase
# environment variable at install time.
if self.OCULUS_BASE_ENVIRONMENT_VARIABLE not in os.environ:
raise RuntimeError('Failed to find the Oculus install location. Are you '
'sure it\'s installed?')
return os.path.join(os.environ[self.OCULUS_BASE_ENVIRONMENT_VARIABLE],
'Support', 'oculus-client', 'OculusClient.exe')
class OculusRuntimeMock(base_runtime.DesktopRuntimeBase):
"""Class for using a mock Oculus runtime for desktop tests."""
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import os
# Note that this doesn't work with old psutil versions, as Process.name was
# changed to Process.name() at some point. This is known to work with psutil
# 5.2.2, which is the version used by vpython at the time of writing.
import psutil # pylint: disable=import-error
import subprocess
# We expect this to be missing on all non-Windows platforms.
try:
import _winreg
except ImportError:
pass
from contrib.vr_benchmarks.desktop_runtimes import base_runtime
# pylint: disable=abstract-method
class _OpenVRRuntimeBase(base_runtime.DesktopRuntimeBase):
"""Base class for all OpenVR runtimes."""
def GetFeatureName(self):
return 'OpenVR'
class OpenVRRuntimeReal(_OpenVRRuntimeBase):
"""Class for using the real OpenVR runtime for desktop tests.
In order for this to work properly, room setup must have been completed,
otherwise OpenVR won't properly show/render content. Unfortunately, there's no
way to tell whether that's been done or not, so we can't enforce it during
setup.
"""
STEAM_REGISTRY_PATH = 'Software\\Valve\\Steam'
STEAM_EXE_REGISTRY_KEY = 'SteamExe'
STEAM_VR_APP_ID = 250820
STEAM_VR_PROCESS_NAME = 'vrmonitor.exe'
# Arbitrary but reasonable amount of time to wait for SteamVR to gracefully
# shut down when told to.
STEAM_VR_SHUTDOWN_TIME_S = 20
def __init__(self, *args, **kwargs):
super(OpenVRRuntimeReal, self).__init__(*args, **kwargs)
# Check if Steam is installed for all users, and if not, for the current
# user.
self._steam_path = self._GetSteamExePath(_winreg.HKEY_LOCAL_MACHINE)
if not self._steam_path:
self._steam_path = self._GetSteamExePath(_winreg.HKEY_CURRENT_USER)
if not self._steam_path:
raise RuntimeError(
'Unable to retrieve Steam install location - are you sure it\'s '
'installed?')
def Setup(self):
self._StartSteamVr()
def WillRunStory(self):
steam_vr_process = self._GetSteamVrProcess()
if not steam_vr_process:
logging.warning('SteamVR closed prematurely, restarting')
self._StartSteamVr()
def TearDown(self):
steam_vr_process = self._GetSteamVrProcess()
if steam_vr_process:
try:
steam_vr_process.terminate()
steam_vr_process.wait(self.STEAM_VR_SHUTDOWN_TIME_S)
except psutil.TimeoutExpired:
logging.warning('Failed to kill SteamVR in %d seconds',
self.STEAM_VR_SHUTDOWN_TIME_S)
def _GetSteamExePath(self, hkey):
try:
registry_key = _winreg.OpenKey(hkey, self.STEAM_REGISTRY_PATH)
value, _ = _winreg.QueryValueEx(registry_key, self.STEAM_EXE_REGISTRY_KEY)
return value
except OSError:
return None
def _StartSteamVr(self):
# Launch Steam (if it's not already open) and launch SteamVR through it.
subprocess.call([self._steam_path, '-applaunch', str(self.STEAM_VR_APP_ID)])
def _GetSteamVrProcess(self):
for proc in psutil.process_iter():
if proc.name() == self.STEAM_VR_PROCESS_NAME:
return proc
return None
class OpenVRRuntimeMock(_OpenVRRuntimeBase):
"""Class for using the mock OpenVR runtime for desktop tests."""
OPENVR_OVERRIDE_ENV_VAR = "VR_OVERRIDE"
OPENVR_CONFIG_PATH = "VR_CONFIG_PATH"
OPENVR_LOG_PATH = "VR_LOG_PATH"
def __init__(self, *args, **kwargs):
super(OpenVRRuntimeMock, self).__init__(*args, **kwargs)
if self._finder_options.mock_runtime_directory:
self._mock_runtime_directory = os.path.abspath(
self._finder_options.mock_runtime_directory)
else:
self._mock_runtime_directory = os.path.abspath(os.path.join(
self._possible_browser.browser_directory, 'mock_vr_clients'))
logging.warning('Using mock directory %s', self._mock_runtime_directory)
def Setup(self):
# All that's necessary to use the mock OpenVR runtime is to set a few
# environment variables pointing towards the mock implementation. When
# OpenVR starts, it checks if these are set, and if so, uses the
# implementation that they specify instead of loading the real one.
# TODO(https://crbug.com/944890): Switch to setting these only when the
# browser is started once the functionality is added.
os.environ[self.OPENVR_OVERRIDE_ENV_VAR] = self._mock_runtime_directory
# We don't really care about what these are set to, but they need to be set
# in order for the mock to work.
os.environ[self.OPENVR_CONFIG_PATH] = os.getcwd()
os.environ[self.OPENVR_LOG_PATH] = os.getcwd()
def WillRunStory(self):
pass
def TearDown(self):
# os.environ is limited to this Python process and its subprocesses, so
# we don't need to clean up anything.
pass
def GetSandboxSupported(self):
return True
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
from contrib.vr_benchmarks.desktop_runtimes import base_runtime
# pylint: disable=abstract-method
class _OpenXRRuntimeBase(base_runtime.DesktopRuntimeBase):
"""Base class for all OpenXR runtimes."""
def GetFeatureName(self):
return 'OpenXR'
class OpenXRRuntimeReal(_OpenXRRuntimeBase):
"""Class for using the real OpenXR runtime for desktop tests.
Currently unimplemented due to:
* Not having access to hardware setup to test on.
* Many OpenXR implementations are still in beta.
* Implementations being available from multiple sources, which may all
have different performance.
"""
# pylint: enable=abstract-method
class OpenXRRuntimeMock(_OpenXRRuntimeBase):
"""Class for using the mock OpenXR runtime for desktop tests."""
OPENXR_CONFIG_PATH = 'XR_RUNTIME_JSON'
# Relative to the path specified by the --mock-runtime-directory.
OPENXR_CONFIG_PATH_VALUE = os.path.join('bin', 'openxr', 'openxr.json')
def Setup(self):
# All that's necessary to use the mock OpenXR runtime is to set an
# environment variable pointing towards the mock implementation. When OpenXR
# starts, it checks if this is set, and if so, uses the specified
# implementation.
# TODO(https://crbug.com/944890): Switch to setting these only when the
# browser is started once the functionality is added.
os.environ[self.OPENXR_CONFIG_PATH] = os.path.join(
self._mock_runtime_directory, self.OPENXR_CONFIG_PATH_VALUE)
def WillRunStory(self):
pass
def TearDown(self):
pass
def GetSandboxSupported(self):
return True
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import os
# Note that this doesn't work with old psutil versions, as Process.name was
# changed to Process.name() at some point. This is known to work with psutil
# 5.2.2, which is the version used by vpython at the time of writing.
import psutil # pylint: disable=import-error
import subprocess
from contrib.vr_benchmarks.desktop_runtimes import base_runtime
# pylint: disable=abstract-method
class _WMRRuntimeBase(base_runtime.DesktopRuntimeBase):
"""Base class for all WMR runtimes."""
def GetFeatureName(self):
return 'WindowsMixedReality'
class WMRRuntimeReal(_WMRRuntimeBase):
"""Class for using the real Windows Mixed Reality runtime for desktop tests.
"""
WINDOWS_SYSTEM_APP_DIRECTORY = os.path.join(
'c:', '\\', 'Windows', 'SystemApps')
WMR_DIRECTORY_PREFIX = 'Microsoft.Windows.HolographicFirstRun'
WMR_PROCESS_NAME = 'MixedRealityPortal.exe'
# Arbitrary but reasonable amount of time to wait for WMR to gracefully
# shut down when told to.
WMR_SHUTDOWN_TIME_S = 20
def __init__(self, *args, **kwargs):
super(WMRRuntimeReal, self).__init__(*args, **kwargs)
self._wmr_portal_executable = None
def Setup(self):
# We need to launch the WMR Portal before running any tests to ensure that
# the runtime is ready when we try to enter VR.
self._StartWMR()
def WillRunStory(self):
if not self._GetWMRProcess():
logging.warning('WMR closed prematurely, restarting')
self._StartWMR()
def TearDown(self):
wmr_process = self._GetWMRProcess()
if wmr_process:
try:
wmr_process.terminate()
wmr_process.wait(self.WMR_SHUTDOWN_TIME_S)
except psutil.TimeoutExpired:
logging.warning('Failed to kill WMR in %d seconds',
self.WMR_SHUTDOWN_TIME_S)
def GetSandboxSupported(self):
return True
def _StartWMR(self):
# The WMR Portal is a UWP app, so starting it is a bit weird.
return subprocess.Popen(['explorer.exe', self._GetWMRExecutable()])
def _GetWMRExecutable(self):
if self._wmr_portal_executable:
return self._wmr_portal_executable
for entry in os.listdir(self.WINDOWS_SYSTEM_APP_DIRECTORY):
if entry.startswith(self.WMR_DIRECTORY_PREFIX):
self._wmr_portal_executable = os.path.join(
'shell:appsFolder', '%s!App' % entry)
break
if not self._wmr_portal_executable:
raise RuntimeError('Unable to find WMR executable - is WMR installed?')
return self._wmr_portal_executable
def _GetWMRProcess(self):
for proc in psutil.process_iter():
if proc.name() == self.WMR_PROCESS_NAME:
return proc
return None
class WMRRuntimeMock(_WMRRuntimeBase):
"""Class for using the mock Windows Mixed Reality runtime for desktop tests.
"""
......@@ -11,9 +11,7 @@ from pylib.utils import shared_preference_utils
from telemetry.core import android_platform
from telemetry.core import util
from telemetry.page import shared_page_state
from contrib.vr_benchmarks.desktop_runtimes import oculus_runtimes
from contrib.vr_benchmarks.desktop_runtimes import openvr_runtimes
from contrib.vr_benchmarks.desktop_runtimes import wmr_runtimes
from contrib.vr_benchmarks.desktop_runtimes import openxr_runtimes
CARDBOARD_PATH = os.path.join('chrome', 'android', 'shared_preference_files',
......@@ -214,17 +212,9 @@ class WindowsSharedVrPageState(_SharedVrPageState):
# to be installed, i.e. exactly how a real user would use VR. Mock runtimes
# avoid this, but can't necessarily be implemented.
DESKTOP_RUNTIMES = {
'oculus': {
MOCK_RUNTIME: oculus_runtimes.OculusRuntimeMock,
REAL_RUNTIME: oculus_runtimes.OculusRuntimeReal,
},
'openvr': {
MOCK_RUNTIME: openvr_runtimes.OpenVRRuntimeMock,
REAL_RUNTIME: openvr_runtimes.OpenVRRuntimeReal
},
'wmr': {
MOCK_RUNTIME: wmr_runtimes.WMRRuntimeMock,
REAL_RUNTIME: wmr_runtimes.WMRRuntimeReal,
'openxr': {
MOCK_RUNTIME: openxr_runtimes.OpenXRRuntimeMock,
REAL_RUNTIME: openxr_runtimes.OpenXRRuntimeReal,
},
}
......
......@@ -76,7 +76,7 @@ class _BaseVRBenchmark(perf_benchmark.PerfBenchmark):
'benchmark to run without issues.')
parser.add_option(
'--desktop-runtime',
default='openvr',
default='openxr',
choices=vr_state.WindowsSharedVrPageState.DESKTOP_RUNTIMES.keys(),
help='Which VR runtime to use on Windows. Defaults to %default')
parser.add_option(
......
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