Bug 1700693 - Add wrench test for successful shader compilation. r=jrmuizel

Add a new `test_init` subcommand to wrench that tests for successful
initialization. This can then be used in combination with the
`--precache` flag to ensure that all shaders are compiled
successfully. Run this with and without `--use-unoptimized-shaders` to
ensure that both variants of the shaders compile.

For android we need to ensure that wrench terminates the process when
it completes successfully otherwise it will run forever. We also must
ensure that the test harness stops the old process before relaunching
the activity one in the case of a timeout.

Depends on D109773

Differential Revision: https://phabricator.services.mozilla.com/D109774
This commit is contained in:
Jamie Nicol 2021-03-25 18:43:23 +00:00
Родитель 594e13f33b
Коммит b696e62540
7 изменённых файлов: 82 добавлений и 14 удалений

Просмотреть файл

@ -16,6 +16,10 @@ set -o xtrace
CARGOFLAGS=${CARGOFLAGS:-""} # default to empty if not set CARGOFLAGS=${CARGOFLAGS:-""} # default to empty if not set
pushd wrench pushd wrench
# Test that all shaders compile successfully.
python script/headless.py --precache test_init
python script/headless.py --precache --use-unoptimized-shaders test_init
python script/headless.py reftest python script/headless.py reftest
python script/headless.py rawtest python script/headless.py rawtest
python script/headless.py test_invalidation python script/headless.py test_invalidation

Просмотреть файл

@ -20,6 +20,10 @@ WRENCH_BINARY=${WRENCH_BINARY:-""}
pushd wrench pushd wrench
# Test that all shaders compile successfully.
python script/headless.py --precache test_init
python script/headless.py --precache --use-unoptimized-shaders test_init
python script/headless.py reftest python script/headless.py reftest
python script/headless.py test_invalidation python script/headless.py test_invalidation
if [[ -z "${WRENCH_BINARY}" ]]; then if [[ -z "${WRENCH_BINARY}" ]]; then

Просмотреть файл

@ -21,6 +21,13 @@ popd
pushd wrench pushd wrench
cargo test --verbose cargo test --verbose
if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL% if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL%
:: Test that all shaders compile successfully. --precache compiles all shaders
:: during initialization, therefore if init is successful then the shaders compile.
cargo run --release -- --angle --precache test_init
if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL%
cargo run --release -- --angle --precache --use-unoptimized-shaders test_init
if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL%
cargo run --release -- --angle reftest cargo run --release -- --angle reftest
if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL% if %ERRORLEVEL% NEQ 0 EXIT /b %ERRORLEVEL%
popd popd

Просмотреть файл

@ -1928,7 +1928,12 @@ impl Device {
self.gl.get_shader_iv(id, gl::COMPILE_STATUS, &mut status); self.gl.get_shader_iv(id, gl::COMPILE_STATUS, &mut status);
} }
if status[0] == 0 { if status[0] == 0 {
error!("Failed to compile shader: {}\n{}", name, log); let type_str = match shader_type {
gl::VERTEX_SHADER => "vertex",
gl::FRAGMENT_SHADER => "fragment",
_ => panic!("Unexpected shader type {:x}", shader_type),
};
error!("Failed to compile {} shader: {}\n{}", type_str, name, log);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
Self::print_shader_errors(source, &log); Self::print_shader_errors(source, &log);
Err(ShaderError::Compilation(name.to_string(), log)) Err(ShaderError::Compilation(name.to_string(), log))
@ -2241,7 +2246,7 @@ impl Device {
if build_program { if build_program {
// Compile the vertex shader // Compile the vertex shader
let vs_source = info.compute_source(self, ShaderKind::Vertex); let vs_source = info.compute_source(self, ShaderKind::Vertex);
let vs_id = match self.compile_shader(&info.base_filename, gl::VERTEX_SHADER, &vs_source) { let vs_id = match self.compile_shader(&info.full_name(), gl::VERTEX_SHADER, &vs_source) {
Ok(vs_id) => vs_id, Ok(vs_id) => vs_id,
Err(err) => return Err(err), Err(err) => return Err(err),
}; };
@ -2249,7 +2254,7 @@ impl Device {
// Compile the fragment shader // Compile the fragment shader
let fs_source = info.compute_source(self, ShaderKind::Fragment); let fs_source = info.compute_source(self, ShaderKind::Fragment);
let fs_id = let fs_id =
match self.compile_shader(&info.base_filename, gl::FRAGMENT_SHADER, &fs_source) { match self.compile_shader(&info.full_name(), gl::FRAGMENT_SHADER, &fs_source) {
Ok(fs_id) => fs_id, Ok(fs_id) => fs_id,
Err(err) => { Err(err) => {
self.gl.delete_shader(vs_id); self.gl.delete_shader(vs_id);

Просмотреть файл

@ -192,3 +192,5 @@ subcommands:
help: second benchmark file to compare help: second benchmark file to compare
required: true required: true
index: 2 index: 2
- test_init:
about: Test for successful initialization then exit immediately

Просмотреть файл

@ -762,11 +762,19 @@ fn main() {
let second_filename = subargs.value_of("second_filename").unwrap(); let second_filename = subargs.value_of("second_filename").unwrap();
perf::compare(first_filename, second_filename); perf::compare(first_filename, second_filename);
return; return;
} else if let Some(_) = args.subcommand_matches("test_init") {
// Wrench::new() unwraps the Renderer initialization, so if
// we reach this point then we have initialized successfully.
println!("Initialization successful");
} else { } else {
panic!("Should never have gotten here! {:?}", args); panic!("Should never have gotten here! {:?}", args);
}; };
wrench.renderer.deinit(); wrench.renderer.deinit();
// On android force-exit the process otherwise it stays running forever.
#[cfg(target_os = "android")]
process::exit(0);
} }
fn render<'a>( fn render<'a>(

Просмотреть файл

@ -7,6 +7,7 @@
from __future__ import absolute_import from __future__ import absolute_import
import datetime import datetime
import enum
import os import os
import subprocess import subprocess
import sys import sys
@ -25,6 +26,12 @@ from mozharness.mozilla.testing.android import AndroidMixin
from mozharness.mozilla.testing.testbase import TestingMixin from mozharness.mozilla.testing.testbase import TestingMixin
class TestMode(enum.Enum):
OPTIMIZED_SHADER_COMPILATION = 0
UNOPTIMIZED_SHADER_COMPILATION = 1
REFTEST = 2
class AndroidWrench(TestingMixin, BaseScript, MozbaseMixin, AndroidMixin): class AndroidWrench(TestingMixin, BaseScript, MozbaseMixin, AndroidMixin):
def __init__(self, require_config_file=False): def __init__(self, require_config_file=False):
# code in BaseScript.__init__ iterates all the properties to attach # code in BaseScript.__init__ iterates all the properties to attach
@ -122,30 +129,46 @@ class AndroidWrench(TestingMixin, BaseScript, MozbaseMixin, AndroidMixin):
end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout) end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
while self.device.process_exist(process_name, timeout=timeout): while self.device.process_exist(process_name, timeout=timeout):
if datetime.datetime.now() > end_time: if datetime.datetime.now() > end_time:
stop_cmd = [
self.adb_path,
"-s",
self.device_serial,
"shell",
"am",
"force-stop",
process_name,
]
subprocess.check_call(stop_cmd)
return False return False
time.sleep(5) time.sleep(5)
return True return True
def setup_sdcard(self): def setup_sdcard(self, test_mode):
# Note that we hard-code /sdcard/wrench as the path here, rather than # Note that we hard-code /sdcard/wrench as the path here, rather than
# using something like self.device.test_root, because it needs to be # using something like self.device.test_root, because it needs to be
# kept in sync with the path hard-coded inside the wrench source code. # kept in sync with the path hard-coded inside the wrench source code.
self.device.rm("/sdcard/wrench", recursive=True, force=True) self.device.rm("/sdcard/wrench", recursive=True, force=True)
self.device.mkdir("/sdcard/wrench", parents=True) self.device.mkdir("/sdcard/wrench", parents=True)
self.device.push( if test_mode == TestMode.REFTEST:
self.query_abs_dirs()["abs_reftests_path"], "/sdcard/wrench/reftests" self.device.push(
) self.query_abs_dirs()["abs_reftests_path"], "/sdcard/wrench/reftests"
)
args_file = os.path.join(self.query_abs_dirs()["abs_work_dir"], "wrench_args") args_file = os.path.join(self.query_abs_dirs()["abs_work_dir"], "wrench_args")
with open(args_file, "w") as argfile: with open(args_file, "w") as argfile:
if self.is_emulator: if self.is_emulator:
argfile.write("env: WRENCH_REFTEST_CONDITION_EMULATOR=1\n") argfile.write("env: WRENCH_REFTEST_CONDITION_EMULATOR=1\n")
else: else:
argfile.write("env: WRENCH_REFTEST_CONDITION_DEVICE=1\n") argfile.write("env: WRENCH_REFTEST_CONDITION_DEVICE=1\n")
argfile.write("reftest") if test_mode == TestMode.OPTIMIZED_SHADER_COMPILATION:
argfile.write("--precache test_init")
elif test_mode == TestMode.UNOPTIMIZED_SHADER_COMPILATION:
argfile.write("--precache --use-unoptimized-shaders test_init")
elif test_mode == TestMode.REFTEST:
argfile.write("reftest")
self.device.push(args_file, "/sdcard/wrench/args") self.device.push(args_file, "/sdcard/wrench/args")
def run_tests(self): def run_tests(self, timeout):
self.timed_screenshots(None) self.timed_screenshots(None)
self.device.launch_application( self.device.launch_application(
app_name="org.mozilla.wrench", app_name="org.mozilla.wrench",
@ -153,7 +176,7 @@ class AndroidWrench(TestingMixin, BaseScript, MozbaseMixin, AndroidMixin):
intent=None, intent=None,
) )
self.info("App launched") self.info("App launched")
done = self.wait_until_process_done("org.mozilla.wrench", timeout=60 * 30) done = self.wait_until_process_done("org.mozilla.wrench", timeout=timeout)
if not done: if not done:
self._errored = True self._errored = True
self.error("Wrench still running after timeout") self.error("Wrench still running after timeout")
@ -235,10 +258,25 @@ class AndroidWrench(TestingMixin, BaseScript, MozbaseMixin, AndroidMixin):
self.info(self.shell_output("getprop")) self.info(self.shell_output("getprop"))
self.info("Installing APK...") self.info("Installing APK...")
self.install_apk(self.query_abs_dirs()["abs_apk_path"], replace=True) self.install_apk(self.query_abs_dirs()["abs_apk_path"], replace=True)
self.info("Setting up SD card...")
self.setup_sdcard() if not self._errored:
self.info("Running tests...") self.info("Setting up SD card...")
self.run_tests() self.setup_sdcard(TestMode.OPTIMIZED_SHADER_COMPILATION)
self.info("Running optimized shader compilation tests...")
self.run_tests(60)
if not self._errored:
self.info("Setting up SD card...")
self.setup_sdcard(TestMode.UNOPTIMIZED_SHADER_COMPILATION)
self.info("Running unoptimized shader compilation tests...")
self.run_tests(60)
if not self._errored:
self.info("Setting up SD card...")
self.setup_sdcard(TestMode.REFTEST)
self.info("Running reftests...")
self.run_tests(60 * 30)
self.info("Tests done; parsing logcat...") self.info("Tests done; parsing logcat...")
self.logcat_stop() self.logcat_stop()
self.scrape_logcat() self.scrape_logcat()