diff --git a/.gitignore b/.gitignore index beb033e..39d18ff 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ y-cruncher v0.8.2.9522/ y-cruncher v0.8.2.9522.zip csgo-benchmark-master/ csgo-benchmark-master.zip +*.blend # python __pycache__/ \ No newline at end of file diff --git a/blender_render/blender.py b/blender_render/blender.py new file mode 100644 index 0000000..805fc2a --- /dev/null +++ b/blender_render/blender.py @@ -0,0 +1,68 @@ +"""Blender render test script""" +from blender_utils import download_and_install_blender, \ + download_barbershop_scene, run_blender_render +from argparse import ArgumentParser +import logging +import os.path +import sys +import time + +sys.path.insert(1, os.path.join(sys.path[0], '..')) +from harness_utils.output import write_report_json + +MSI_NAME = "blender-3.6.4-windows-x64.msi" +DOWNLOAD_URL = f"https://mirrors.ocf.berkeley.edu/blender/release/Blender3.6/{MSI_NAME}" +ABSOLUTE_PATH = "C:\\Program Files\\Blender Foundation\\Blender 3.6\\blender.exe" + +SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) +LOG_DIRECTORY = os.path.join(SCRIPT_DIR, "run") +if not os.path.isdir(LOG_DIRECTORY): + os.mkdir(LOG_DIRECTORY) +LOGGING_FORMAT = '%(asctime)s %(levelname)-s %(message)s' +logging.basicConfig(filename=f'{LOG_DIRECTORY}/harness.log', + format=LOGGING_FORMAT, + datefmt='%m-%d %H:%M', + level=logging.DEBUG) +console = logging.StreamHandler() +formatter = logging.Formatter(LOGGING_FORMAT) +console.setFormatter(formatter) +logging.getLogger('').addHandler(console) + +VALID_DEVICES = ["CPU", "CUDA", "OPTIX", "HIP", "ONEAPI", "METAL"] +parser = ArgumentParser() +parser.add_argument("-s", "--scene", dest="scene", + help="blender scene", metavar="scene", required=True) +parser.add_argument("-d", "--device", dest="device", + help="device", metavar="device", required=True) + +args = parser.parse_args() + +if args.device not in VALID_DEVICES: + logging.error("Invalid device selection!") + sys.exit(1) + +if os.path.isfile(ABSOLUTE_PATH) is False: + download_and_install_blender(DOWNLOAD_URL, MSI_NAME) +download_barbershop_scene() + +try: + start_time = time.time() + score = run_blender_render( + ABSOLUTE_PATH, LOG_DIRECTORY, args.device.upper()) + end_time = time.time() + + if score is None: + logging.error("No duration was found in the log to use as the score") + sys.exit(1) + + report = { + "score": score, + "start_time": round((start_time * 1000)), + "end_time": round((end_time * 1000)) + } + + write_report_json(LOG_DIRECTORY, "report.json", report) +except Exception as e: + logging.error("Something went wrong running the benchmark!") + logging.exception(e) + sys.exit(1) diff --git a/blender_render/blender_utils.py b/blender_render/blender_utils.py new file mode 100644 index 0000000..61a3987 --- /dev/null +++ b/blender_render/blender_utils.py @@ -0,0 +1,59 @@ +"""Blender render test script""" +import logging +import os +import re +import subprocess +import requests + + +def download_and_install_blender(url: str, msi_name: str): + """Downloads blender msi""" + root_dir = os.path.dirname(os.path.realpath(__file__)) + dest_path = os.path.join(root_dir, msi_name) + if os.path.isfile(dest_path) is not True: + logging.info("Downloading Blender MSI for installation") + response = requests.get(url, allow_redirects=True, timeout=120) + with open(dest_path, 'wb') as file: + file.write(response.content) + subprocess.call(f"MsiExec.exe /i {dest_path} ALLUSERS=1 /qn") + + +def download_barbershop_scene(): + """Downloads blender scene to render""" + blend_file_name = "barbershop_interior.blend" + download_url = f"https://svn.blender.org/svnroot/bf-blender/trunk/lib/benchmarks/cycles/barbershop_interior/{blend_file_name}" + root_dir = os.path.dirname(os.path.realpath(__file__)) + dest_path = os.path.join(root_dir, blend_file_name) + + if os.path.isfile(dest_path) is not True: + logging.info("Downloading barbershop scene") + response = requests.get( + download_url, allow_redirects=True, timeout=120) + with open(dest_path, 'wb') as file: + file.write(response.content) + + +def run_blender_render(executable_path: str, log_directory: str, device: str) -> str: + """Execute the blender render of barbershop, returns the duration as string""" + blend_log = os.path.join(log_directory, "blender.log") + root_dir = os.path.dirname(os.path.realpath(__file__)) + blend_path = os.path.join(root_dir, "barbershop_interior.blend") + cmd_line = f"{executable_path} -b -E CYCLES -y {blend_path} -f 1 -- --cycles-device {device} --cycles-print-stats" + with open(blend_log, 'w', encoding="utf-8") as f_obj: + subprocess.run(cmd_line, stdout=f_obj, text=True, check=True) + + # example: Time: 02:59.57 (Saving: 00:00.16) + time_regex = r"Time: (.*) \(Saving.*\)" + + time = None + with open(blend_log, 'r', encoding="utf-8") as file: + lines = file.readlines() + lines.reverse() + count = 0 + for line in lines: + count += 1 + match = re.match(time_regex, line.strip()) + if match: + time = match.group(1) + break + return time diff --git a/blender_render/manifest.yaml b/blender_render/manifest.yaml new file mode 100644 index 0000000..927d637 --- /dev/null +++ b/blender_render/manifest.yaml @@ -0,0 +1,13 @@ +friendly_name: "Blender Render" +executable: "blender.py" +process_name: "blender.exe" +disable_presentmon: true +hidden: 0 +output_dir: "run" +options: + - name: scene + type: select + values: ['barbershop'] + - name: device + type: select + values: ["CPU", "CUDA", "OPTIX", "HIP", "ONEAPI", "METAL"] diff --git a/blenderbenchmark/manifest.yaml b/blenderbenchmark/manifest.yaml index 2c749f8..ee77b01 100644 --- a/blenderbenchmark/manifest.yaml +++ b/blenderbenchmark/manifest.yaml @@ -7,9 +7,7 @@ output_dir: "run" options: - name: scene type: select - # presets disabled in favor of manual process for now values: [all, classroom, junkshop, monster] - tooltip: Don't forget to set graphics settings! - name: version type: select values: ["3.6.0", "3.5.0", "3.4.0", "3.3.0"] diff --git a/cspell.json b/cspell.json index e72c423..227b72b 100644 --- a/cspell.json +++ b/cspell.json @@ -7,6 +7,10 @@ "csgo", "pycache", "OPTIX", - "CUDA" -] + "CUDA", + "psutil" + ], + "ignoreRegExpList": [ + "import .*" + ] } \ No newline at end of file diff --git a/pylintrc b/pylintrc new file mode 100644 index 0000000..cedfe79 --- /dev/null +++ b/pylintrc @@ -0,0 +1,7 @@ +[MESSAGES CONTROL] +disable= + import-error, + wrong-import-order, + wrong-import-position, + broad-exception-caught, + line-too-long \ No newline at end of file