Files
test/tests/performance/tests/cycles.py
Campbell Barton c434782e3a File headers: SPDX License migration
Use a shorter/simpler license convention, stops the header taking so
much space.

Follow the SPDX license specification: https://spdx.org/licenses

- C/C++/objc/objc++
- Python
- Shell Scripts
- CMake, GNUmakefile

While most of the source tree has been included

- `./extern/` was left out.
- `./intern/cycles` & `./intern/atomic` are also excluded because they
  use different header conventions.

doc/license/SPDX-license-identifiers.txt has been added to list SPDX all
used identifiers.

See P2788 for the script that automated these edits.

Reviewed By: brecht, mont29, sergey

Ref D14069
2022-02-11 09:14:36 +11:00

113 lines
3.5 KiB
Python

# SPDX-License-Identifier: Apache-2.0
import api
import os
def _run(args):
import bpy
import time
device_type = args['device_type']
device_index = args['device_index']
scene = bpy.context.scene
scene.render.engine = 'CYCLES'
scene.render.filepath = args['render_filepath']
scene.render.image_settings.file_format = 'PNG'
scene.cycles.device = 'CPU' if device_type == 'CPU' else 'GPU'
if scene.cycles.use_adaptive_sampling:
# Render samples specified in file, no other way to measure
# adaptive sampling performance reliably.
scene.cycles.time_limit = 0.0
else:
# Render for fixed amount of time so it's adaptive to the
# machine and devices.
scene.cycles.samples = 16384
scene.cycles.time_limit = 10.0
if scene.cycles.device == 'GPU':
# Enable specified GPU in preferences.
prefs = bpy.context.preferences
cprefs = prefs.addons['cycles'].preferences
cprefs.compute_device_type = device_type
devices = cprefs.get_devices_for_type(device_type)
for device in devices:
device.use = False
index = 0
for device in devices:
if device.type == device_type:
if index == device_index:
device.use = True
break
else:
index += 1
# Render
bpy.ops.render.render(write_still=True)
return None
class CyclesTest(api.Test):
def __init__(self, filepath):
self.filepath = filepath
def name(self):
return self.filepath.stem
def category(self):
return "cycles"
def use_device(self):
return True
def run(self, env, device_id):
tokens = device_id.split('_')
device_type = tokens[0]
device_index = int(tokens[1]) if len(tokens) > 1 else 0
args = {'device_type': device_type,
'device_index': device_index,
'render_filepath': str(env.log_file.parent / (env.log_file.stem + '.png'))}
_, lines = env.run_in_blender(_run, args, ['--debug-cycles', '--verbose', '2', self.filepath])
# Parse render time from output
prefix_time = "Render time (without synchronization): "
prefix_memory = "Peak: "
prefix_time_per_sample = "Average time per sample: "
time = None
time_per_sample = None
memory = None
for line in lines:
line = line.strip()
offset = line.find(prefix_time)
if offset != -1:
time = line[offset + len(prefix_time):]
time = float(time)
offset = line.find(prefix_time_per_sample)
if offset != -1:
time_per_sample = line[offset + len(prefix_time_per_sample):]
time_per_sample = time_per_sample.split()[0]
time_per_sample = float(time_per_sample)
offset = line.find(prefix_memory)
if offset != -1:
memory = line[offset + len(prefix_memory):]
memory = memory.split()[0].replace(',', '')
memory = float(memory)
if time_per_sample:
time = time_per_sample
if not (time and memory):
raise Exception("Error parsing render time output")
return {'time': time, 'peak_memory': memory}
def generate(env):
filepaths = env.find_blend_files('cycles/*')
return [CyclesTest(filepath) for filepath in filepaths]