Tests: speed up render tests by running multiple in the same process
[blender.git] / tests / python / cycles_render_tests.py
1 #!/usr/bin/env python3
2 # Apache License, Version 2.0
3
4 import argparse
5 import os
6 import shlex
7 import shutil
8 import subprocess
9 import sys
10
11
12 def render_files(filepaths, output_filepaths):
13     command = [BLENDER, "--background"]
14
15     # OSL and GPU examples
16     # custom_args += ["--python-expr", "import bpy; bpy.context.scene.cycles.shading_system = True"]
17     # custom_args += ["--python-expr", "import bpy; bpy.context.scene.cycles.device = 'GPU'"]
18     custom_args = os.getenv('CYCLESTEST_ARGS')
19     custom_args = shlex.split(custom_args) if custom_args else []
20
21     for filepath, output_filepath in zip(filepaths, output_filepaths):
22         dirname = os.path.dirname(filepath)
23         basedir = os.path.dirname(dirname)
24         subject = os.path.basename(dirname)
25
26         frame_filepath = output_filepath + '0001.png'
27
28         common_args = [
29             "-noaudio",
30             "--factory-startup",
31             "--enable-autoexec",
32             filepath,
33             "-E", "CYCLES",
34             "-o", output_filepath,
35             "-F", "PNG"]
36
37         common_args += custom_args
38
39         if subject == 'bake':
40             command.extend(common_args)
41             command.extend(['--python', os.path.join(basedir, "util", "render_bake.py")])
42         elif subject == 'denoise_animation':
43             command.extend(common_args)
44             command.extend(['--python', os.path.join(basedir, "util", "render_denoise.py")])
45         else:
46             command.extend(common_args)
47             command.extend(["-f", "1"])
48
49     error = None
50     try:
51         # Success
52         output = subprocess.check_output(command)
53         if VERBOSE:
54             print(" ".join(command))
55             print(output.decode("utf-8"))
56     except subprocess.CalledProcessError as e:
57         # Error
58         if VERBOSE:
59             print(" ".join(command))
60             print(e.output.decode("utf-8"))
61         error = "CRASH"
62     except BaseException as e:
63         # Crash
64         if VERBOSE:
65             print(" ".join(command))
66             print(e.decode("utf-8"))
67         error = "CRASH"
68
69     # Detect missing filepaths and consider those errors
70     errors = []
71     for output_filepath in output_filepaths:
72         frame_filepath = output_filepath + '0001.png'
73         if os.path.exists(frame_filepath):
74             shutil.copy(frame_filepath, output_filepath)
75             os.remove(frame_filepath)
76             errors.append(None)
77         else:
78             errors.append(error)
79             error = 'SKIPPED'
80
81     return errors
82
83 def create_argparse():
84     parser = argparse.ArgumentParser()
85     parser.add_argument("-blender", nargs="+")
86     parser.add_argument("-testdir", nargs=1)
87     parser.add_argument("-outdir", nargs=1)
88     parser.add_argument("-idiff", nargs=1)
89     return parser
90
91
92 def main():
93     parser = create_argparse()
94     args = parser.parse_args()
95
96     global BLENDER, VERBOSE
97
98     BLENDER = args.blender[0]
99     VERBOSE = os.environ.get("BLENDER_VERBOSE") is not None
100
101     test_dir = args.testdir[0]
102     idiff = args.idiff[0]
103     output_dir = args.outdir[0]
104
105     from modules import render_report
106     report = render_report.Report("Cycles Test Report", output_dir, idiff)
107     report.set_pixelated(True)
108     report.set_reference_dir("cycles_renders")
109     report.set_compare_engines('cycles', 'eevee')
110     ok = report.run(test_dir, render_files)
111
112     sys.exit(not ok)
113
114
115 if __name__ == "__main__":
116     main()