diff --git a/benchmark/space/__init__.py b/benchmark/space/__init__.py index 13821a2..3f59653 100644 --- a/benchmark/space/__init__.py +++ b/benchmark/space/__init__.py @@ -5,8 +5,7 @@ import platform import subprocess import sys import tempfile -from threading import Thread, Lock -import blf +from threading import Thread import bpy from bpy.types import Panel, Scene from bpy.props import EnumProperty, IntProperty, FloatProperty @@ -17,8 +16,9 @@ from ..foundation import (benchrunner, util) from ..foundation import context as benchmark_context -################################################################################ -# Global state. +from .global_state import G +from . import draw + QUICK_SCENES = ["bmw27", "classroom"] @@ -30,230 +30,8 @@ COMPLETE_SCENES = ["barbershop_interior", "koro", "pavillon_barcelona"] - -class G: - """Global state of the Benchmark Client.""" - result_platform = None - progress_status = None - result_stats = None - result_dict = None - background_image_path = "" - scene_status = {} - cancel = False - - cached_system_info = None - cached_compute_devices = None - results_submitted = False - - images = {} - current_progress = 0.0 - progress_lock = Lock() - - @classmethod - def reset(cls): - """Reset the global state.""" - cls.result_platform = None - cls.progress_status = None - cls.result_stats = None - cls.result_dict = None - cls.background_image_path = "" - cls.scene_status = {} - cls.results_submitted = False - - -WELCOME_TEXT = "Run the Quick Benchmark on the selected device to\n" \ - "get a fast measurement of your hardware's performance.\n" \ - "Usually takes less than 30 minutes." - -BLURB_TEXT = "Share your results with the world!\n" \ - "Manage the uploaded benchmark data on your Blender ID." - -################################################################################ -# Draw Utilities. - - -font_id = 0 - - -def viewport_size(): - import bgl - viewport = bgl.Buffer(bgl.GL_INT, 4) - bgl.glGetIntegerv(bgl.GL_VIEWPORT, viewport) - return viewport[2], viewport[3] - - -def draw_text_center(text, x, y, shadow=False): - dim = blf.dimensions(font_id, text) - cx = x - int(dim[0] / 2) - cy = y - int(dim[1] / 2) - if shadow: - delta = 1 - blf.color(font_id, 0.2, 0.2, 0.2, 1.0) - blf.position(font_id, cx + delta, cy - delta, 0) - blf.draw(font_id, text) - blf.color(font_id, 1.0, 1.0, 1.0, 1.0) - blf.position(font_id, cx, cy, 0) - blf.draw(font_id, text) - - -def draw_text_multiline(text, x, y, shadow=False): - ui_scale = bpy.context.user_preferences.system.ui_scale - height = int(blf.dimensions(font_id, "Dummy Text")[1]) - space = int(8 * ui_scale) - - for line in text.split('\n'): - if shadow: - delta = 1 - blf.color(font_id, 0.2, 0.2, 0.2, 1.0) - blf.position(font_id, x + delta, y - height - delta, 0) - blf.draw(font_id, line) - blf.color(font_id, 1.0, 1.0, 1.0, 1.0) - blf.position(font_id, x, y - height, 0) - blf.draw(font_id, line) - y -= height + space - - -def draw_rect(x, y, w, h, color): - import gpu - gpu.draw.rect(x, y, x + w, y + h, color[0], color[1], color[2], color[3]) - - -def draw_image(filepath, x, y, w, h): - if filepath not in G.images: - ima = bpy.data.images.load(filepath) - G.images[filepath] = ima - import gpu - gpu.draw.image(G.images[filepath], x, y, x + w, y + h) - - -################################################################################ -# Draw. - -def benchmark_draw_post_pixel(arg1, arg2): - G.progress_lock.acquire() - progress_status = G.progress_status - result_platform = G.result_platform - result_stats = G.result_stats - result_dict = G.result_dict - G.progress_lock.release() - - ui_scale = bpy.context.user_preferences.system.ui_scale - blf.color(font_id, 1.0, 1.0, 1.0, 1.0) - - window_width, window_height = viewport_size() - - # Image - image_h = 370 * ui_scale - image_y = window_height - image_h - - if G.background_image_path: - draw_image(G.background_image_path, 0, image_y, window_width, image_h) - else: - splash_dir = os.path.dirname(os.path.abspath(__file__)) - splash_filepath = os.path.join(splash_dir, 'splash.png') - draw_image(splash_filepath, 0, image_y, window_width, image_h) - - if result_dict: - x = 0.5 * window_width - y = 0.70 * window_height - - score = 0 - for name_stats in G.result_dict["scenes"]: - stat = name_stats['stats'] - if stat["result"] == "OK": - score += stat["total_render_time"] - else: - score = -1 - - if score >= 0: - blf.size(font_id, int(32 * ui_scale), 72) - draw_text_center("Your Time: {}".format( - util.humanReadableTimeDifference(score)), x, y, shadow=True) - else: - blf.size(font_id, int(18 * ui_scale), 72) - draw_text_center("Unfortunately, crash happened :(", x, y, shadow=True) - blf.size(font_id, int(24 * ui_scale), 72) - draw_text_center("You can still share data of succeeded scenes!", - x, y - 26 * ui_scale, shadow=True) - - x = 50.0 * ui_scale - y = image_y - (image_y - 52 * ui_scale - 18 * 3 * ui_scale) * 0.5 - blf.size(font_id, int(12 * ui_scale), 72) - draw_text_multiline(BLURB_TEXT, x, y) - elif result_stats or result_platform or progress_status: - blf.size(font_id, int(12 * ui_scale), 72) - - x = 50.0 * ui_scale - y = image_y - 20 * ui_scale - - # Stats - if result_platform: - draw_text_multiline(result_platform, 0.5 * window_width + x, y) - if result_stats: - draw_text_multiline(result_stats, x, y) - - # Progress - progress_x = 0.0 - progress_y = image_y + 1 - progress_w = window_width * G.current_progress - progress_h = 15.0 * ui_scale - progress_color = [0.8, 1.0, 1.0, 0.2] - - draw_rect(progress_x, progress_y, progress_w, progress_h, progress_color) - - # Current status - if G.progress_status: - blf.size(font_id, int(18 * ui_scale), 72) - draw_text_multiline(G.progress_status, - progress_x + 8.0 * ui_scale, - progress_y + progress_h + int(22 * ui_scale), - shadow=True) - else: - # Title - x = 0.5 * window_width - y = 0.70 * window_height - - blf.size(font_id, int(32 * ui_scale), 72) - draw_text_center("Blender Benchmark 1.0 Beta", x, y, shadow=True) - - y -= 32 * ui_scale - - blf.size(font_id, int(12 * ui_scale), 72) - draw_text_center("Free and Open Data for everyone.", - x, y, shadow=True) - - x = 50.0 * ui_scale - y = image_y - (image_y - 52 * ui_scale - 18 * 3 * ui_scale) * 0.5 - blf.size(font_id, int(12 * ui_scale), 72) - draw_text_multiline(WELCOME_TEXT, x, y) - - # Bottom bar - bottom_x = 0 - bottom_y = 0 - bottom_w = window_width - bottom_h = 52 * ui_scale - bottom_color = [0.2, 0.2, 0.2, 1.0] - - draw_rect(bottom_x, bottom_y, bottom_w, bottom_h, bottom_color) - - # Logo - logo_width_unscaled = 326 - logo_height_unscaled = 104 - logo_dir = os.path.dirname(os.path.abspath(__file__)) - logo_filepath = os.path.join(logo_dir, 'blender.png') - logo_scale_factor = 1.0 - while logo_height_unscaled * logo_scale_factor > bottom_h: - logo_scale_factor *= 0.5 - logo_width = logo_width_unscaled * logo_scale_factor - logo_height = logo_height_unscaled * logo_scale_factor - logo_padding = (bottom_h - logo_height) * 0.5 - draw_image(logo_filepath, - logo_padding, logo_padding, - logo_width, logo_height) - - handle_draw = bpy.types.SpaceBenchmark.draw_handler_add( - benchmark_draw_post_pixel, (None, None), 'WINDOW', 'POST_PIXEL') + draw.benchmark_draw_post_pixel, (None, None), 'WINDOW', 'POST_PIXEL') ################################################################################ diff --git a/benchmark/space/draw.py b/benchmark/space/draw.py new file mode 100644 index 0000000..d1ad739 --- /dev/null +++ b/benchmark/space/draw.py @@ -0,0 +1,199 @@ +import os.path + +import blf +import bpy + +from ..foundation import util + +from . import G + + +WELCOME_TEXT = "Run the Quick Benchmark on the selected device to\n" \ + "get a fast measurement of your hardware's performance.\n" \ + "Usually takes less than 30 minutes." + +BLURB_TEXT = "Share your results with the world!\n" \ + "Manage the uploaded benchmark data on your Blender ID." + +################################################################################ +# Draw Utilities. + + +font_id = 0 + + +def viewport_size(): + import bgl + viewport = bgl.Buffer(bgl.GL_INT, 4) + bgl.glGetIntegerv(bgl.GL_VIEWPORT, viewport) + return viewport[2], viewport[3] + + +def draw_text_center(text, x, y, shadow=False): + dim = blf.dimensions(font_id, text) + cx = x - int(dim[0] / 2) + cy = y - int(dim[1] / 2) + if shadow: + delta = 1 + blf.color(font_id, 0.2, 0.2, 0.2, 1.0) + blf.position(font_id, cx + delta, cy - delta, 0) + blf.draw(font_id, text) + blf.color(font_id, 1.0, 1.0, 1.0, 1.0) + blf.position(font_id, cx, cy, 0) + blf.draw(font_id, text) + + +def draw_text_multiline(text, x, y, shadow=False): + ui_scale = bpy.context.user_preferences.system.ui_scale + height = int(blf.dimensions(font_id, "Dummy Text")[1]) + space = int(8 * ui_scale) + + for line in text.split('\n'): + if shadow: + delta = 1 + blf.color(font_id, 0.2, 0.2, 0.2, 1.0) + blf.position(font_id, x + delta, y - height - delta, 0) + blf.draw(font_id, line) + blf.color(font_id, 1.0, 1.0, 1.0, 1.0) + blf.position(font_id, x, y - height, 0) + blf.draw(font_id, line) + y -= height + space + + +def draw_rect(x, y, w, h, color): + import gpu + gpu.draw.rect(x, y, x + w, y + h, color[0], color[1], color[2], color[3]) + + +def draw_image(filepath, x, y, w, h): + if filepath not in G.images: + ima = bpy.data.images.load(filepath) + G.images[filepath] = ima + import gpu + gpu.draw.image(G.images[filepath], x, y, x + w, y + h) + + +################################################################################ +# Draw. + +def benchmark_draw_post_pixel(arg1, arg2): + G.progress_lock.acquire() + progress_status = G.progress_status + result_platform = G.result_platform + result_stats = G.result_stats + result_dict = G.result_dict + G.progress_lock.release() + + ui_scale = bpy.context.user_preferences.system.ui_scale + blf.color(font_id, 1.0, 1.0, 1.0, 1.0) + + window_width, window_height = viewport_size() + + # Image + image_h = 370 * ui_scale + image_y = window_height - image_h + + if G.background_image_path: + draw_image(G.background_image_path, 0, image_y, window_width, image_h) + else: + splash_dir = os.path.dirname(os.path.abspath(__file__)) + splash_filepath = os.path.join(splash_dir, 'splash.png') + draw_image(splash_filepath, 0, image_y, window_width, image_h) + + if result_dict: + x = 0.5 * window_width + y = 0.70 * window_height + + score = 0 + for name_stats in G.result_dict["scenes"]: + stat = name_stats['stats'] + if stat["result"] == "OK": + score += stat["total_render_time"] + else: + score = -1 + + if score >= 0: + blf.size(font_id, int(32 * ui_scale), 72) + draw_text_center("Your Time: {}".format( + util.humanReadableTimeDifference(score)), x, y, shadow=True) + else: + blf.size(font_id, int(18 * ui_scale), 72) + draw_text_center("Unfortunately, crash happened :(", x, y, shadow=True) + blf.size(font_id, int(24 * ui_scale), 72) + draw_text_center("You can still share data of succeeded scenes!", + x, y - 26 * ui_scale, shadow=True) + + x = 50.0 * ui_scale + y = image_y - (image_y - 52 * ui_scale - 18 * 3 * ui_scale) * 0.5 + blf.size(font_id, int(12 * ui_scale), 72) + draw_text_multiline(BLURB_TEXT, x, y) + elif result_stats or result_platform or progress_status: + blf.size(font_id, int(12 * ui_scale), 72) + + x = 50.0 * ui_scale + y = image_y - 20 * ui_scale + + # Stats + if result_platform: + draw_text_multiline(result_platform, 0.5 * window_width + x, y) + if result_stats: + draw_text_multiline(result_stats, x, y) + + # Progress + progress_x = 0.0 + progress_y = image_y + 1 + progress_w = window_width * G.current_progress + progress_h = 15.0 * ui_scale + progress_color = [0.8, 1.0, 1.0, 0.2] + + draw_rect(progress_x, progress_y, progress_w, progress_h, progress_color) + + # Current status + if G.progress_status: + blf.size(font_id, int(18 * ui_scale), 72) + draw_text_multiline(G.progress_status, + progress_x + 8.0 * ui_scale, + progress_y + progress_h + int(22 * ui_scale), + shadow=True) + else: + # Title + x = 0.5 * window_width + y = 0.70 * window_height + + blf.size(font_id, int(32 * ui_scale), 72) + draw_text_center("Blender Benchmark 1.0 Beta", x, y, shadow=True) + + y -= 32 * ui_scale + + blf.size(font_id, int(12 * ui_scale), 72) + draw_text_center("Free and Open Data for everyone.", + x, y, shadow=True) + + x = 50.0 * ui_scale + y = image_y - (image_y - 52 * ui_scale - 18 * 3 * ui_scale) * 0.5 + blf.size(font_id, int(12 * ui_scale), 72) + draw_text_multiline(WELCOME_TEXT, x, y) + + # Bottom bar + bottom_x = 0 + bottom_y = 0 + bottom_w = window_width + bottom_h = 52 * ui_scale + bottom_color = [0.2, 0.2, 0.2, 1.0] + + draw_rect(bottom_x, bottom_y, bottom_w, bottom_h, bottom_color) + + # Logo + logo_width_unscaled = 326 + logo_height_unscaled = 104 + logo_dir = os.path.dirname(os.path.abspath(__file__)) + logo_filepath = os.path.join(logo_dir, 'blender.png') + logo_scale_factor = 1.0 + while logo_height_unscaled * logo_scale_factor > bottom_h: + logo_scale_factor *= 0.5 + logo_width = logo_width_unscaled * logo_scale_factor + logo_height = logo_height_unscaled * logo_scale_factor + logo_padding = (bottom_h - logo_height) * 0.5 + draw_image(logo_filepath, + logo_padding, logo_padding, + logo_width, logo_height) diff --git a/benchmark/space/global_state.py b/benchmark/space/global_state.py new file mode 100644 index 0000000..5ad8289 --- /dev/null +++ b/benchmark/space/global_state.py @@ -0,0 +1,31 @@ +import threading + + +class G: + """Global state of the Benchmark Client.""" + result_platform = None + progress_status = None + result_stats = None + result_dict = None + background_image_path = "" + scene_status = {} + cancel = False + + cached_system_info = None + cached_compute_devices = None + results_submitted = False + + images = {} + current_progress = 0.0 + progress_lock = threading.Lock() + + @classmethod + def reset(cls): + """Reset the global state.""" + cls.result_platform = None + cls.progress_status = None + cls.result_stats = None + cls.result_dict = None + cls.background_image_path = "" + cls.scene_status = {} + cls.results_submitted = False