diff --git a/benchmark/space/__init__.py b/benchmark/space/__init__.py index e6b007a..5eafd65 100644 --- a/benchmark/space/__init__.py +++ b/benchmark/space/__init__.py @@ -30,19 +30,36 @@ COMPLETE_SCENES = ["barbershop_interior", "koro", "pavillon_barcelona"] -global_result_platform = None -global_progress_status = None -global_result_stats = None -global_result_dict = None -global_background_image_path = "" -global_scene_status = {} -global_cancel = False -global_cached_system_info = None -global_cached_compute_devices = None -global_results_submitted = False -images = {} -current_progress = 0.0 -progress_lock = Lock() + +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" \ @@ -52,22 +69,6 @@ BLURB_TEXT = "Share your results with the world!\n" \ "Manage the uploaded benchmark data on your Blender ID." -def reset_global_state(): - global global_result_platform - global global_progress_status - global global_result_stats - global global_result_dict - global global_background_image_path - global global_scene_status - global global_results_submitted - global_result_platform = None - global_progress_status = None - global_result_stats = None - global_result_dict = None - global_background_image_path = "" - global_scene_status = {} - global_results_submitted = False - ################################################################################ # Draw Utilities. @@ -119,26 +120,23 @@ def draw_rect(x, y, w, h, color): def draw_image(filepath, x, y, w, h): - global images - if filepath not in images: + if filepath not in G.images: ima = bpy.data.images.load(filepath) - images[filepath] = ima - + G.images[filepath] = ima import gpu - gpu.draw.image(images[filepath], x, y, x + w, y + h) + gpu.draw.image(G.images[filepath], x, y, x + w, y + h) ################################################################################ # Draw. def benchmark_draw_post_pixel(arg1, arg2): - global progress_lock - progress_lock.acquire() - progress_status = global_progress_status - result_platform = global_result_platform - result_stats = global_result_stats - result_dict = global_result_dict - progress_lock.release() + 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) @@ -149,8 +147,8 @@ def benchmark_draw_post_pixel(arg1, arg2): image_h = 370 * ui_scale image_y = window_height - image_h - if global_background_image_path: - draw_image(global_background_image_path, 0, image_y, window_width, 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') @@ -161,7 +159,7 @@ def benchmark_draw_post_pixel(arg1, arg2): y = 0.70 * window_height score = 0 - for name_stats in global_result_dict["scenes"]: + for name_stats in G.result_dict["scenes"]: stat = name_stats['stats'] if stat["result"] == "OK": score += stat["total_render_time"] @@ -198,16 +196,16 @@ def benchmark_draw_post_pixel(arg1, arg2): # Progress progress_x = 0.0 progress_y = image_y + 1 - progress_w = window_width * current_progress + 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 global_progress_status: + if G.progress_status: blf.size(font_id, int(18 * ui_scale), 72) - draw_text_multiline(global_progress_status, + draw_text_multiline(G.progress_status, progress_x + 8.0 * ui_scale, progress_y + progress_h + int(22 * ui_scale), shadow=True) @@ -274,49 +272,46 @@ class ProgressProviderSink: self.process = None def progress(self, count, total, prefix="", suffix=""): - progress_lock.acquire() + G.progress_lock.acquire() if total != 0: self.current_progress = float(count) / float(total) else: self.current_progress = 0.0 - progress_lock.release() + G.progress_lock.release() def clear(self): - progress_lock.acquire() + G.progress_lock.acquire() self.current_progress = 0 - progress_lock.release() + G.progress_lock.release() def step(self, step_name): - progress_lock.acquire() + G.progress_lock.acquire() if self.current_step != step_name: self.current_step = step_name self.current_progress = 0 - progress_lock.release() + G.progress_lock.release() def scene(self, scene_name): - progress_lock.acquire() + G.progress_lock.acquire() self.current_scene = scene_name if scene_name: - global global_scene_status - global_scene_status[scene_name] = "Rendering..." - progress_lock.release() + G.scene_status[scene_name] = "Rendering..." + G.progress_lock.release() def scene_stats(self, scene_name, stats): - progress_lock.acquire() - global global_scene_status + G.progress_lock.acquire() if stats: - global_scene_status[scene_name] = util.humanReadableTimeDifference( + G.scene_status[scene_name] = util.humanReadableTimeDifference( stats.total_render_time) else: - global_scene_status[scene_name] = "Crashed :(" - progress_lock.release() + G.scene_status[scene_name] = "Crashed :(" + G.progress_lock.release() def render_process(self, process): self.process = process def is_canceled(self): - global global_cancel - return global_cancel + return G.cancel class LoggerProviderSink: @@ -455,15 +450,12 @@ def modify_device_info(device_info): def benchmark_thread(ctx): - global progress_lock, global_result_platform, global_progress_status - global global_cancel - - progress_lock.acquire() - global_progress_status = "Collecting system information." - if global_cancel: - progress_lock.release() + G.progress_lock.acquire() + G.progress_status = "Collecting system information." + if G.cancel: + G.progress_lock.release() return - progress_lock.release() + G.progress_lock.release() blender_system_info = system_info_get(ctx) @@ -474,13 +466,13 @@ def benchmark_thread(ctx): # TODO(sergey): Report an error somehow. return - progress_lock.acquire() - global_result_platform = construct_platform_string(blender_system_info) - if global_cancel: - progress_lock.release() + G.progress_lock.acquire() + G.result_platform = construct_platform_string(blender_system_info) + if G.cancel: + G.progress_lock.release() return - global_progress_status = "Prepating render." - progress_lock.release() + G.progress_status = "Prepating render." + G.progress_lock.release() all_stats = benchrunner.benchmarkAll(ctx) # Gather all information together. @@ -493,14 +485,13 @@ def benchmark_thread(ctx): "scenes": all_stats if all_stats else {} }) - progress_lock.acquire() - if global_cancel: - progress_lock.release() + G.progress_lock.acquire() + if G.cancel: + G.progress_lock.release() return - progress_lock.release() + G.progress_lock.release() - global global_result_dict - global_result_dict = result + G.result_dict = result ################################################################################ @@ -550,7 +541,7 @@ class BENCHMARK_PT_main(Panel): sub.separator() compute_device_list_get(None, context) - if len(global_cached_compute_devices) > 1: + if len(G.cached_compute_devices) > 1: sub = col.row() sub.scale_y = 1.5 sub.prop(context.scene, "compute_device", text="") @@ -587,7 +578,7 @@ class BENCHMARK_PT_main(Panel): sub.separator() sub = col.row() - sub.enabled = not global_results_submitted + sub.enabled = not G.results_submitted sub.scale_y = 2.25 sub.operator("benchmark.share", text="SHARE ONLINE") @@ -606,13 +597,13 @@ class BENCHMARK_PT_main(Panel): def draw(self, context): screen_index = 0 - global progress_lock - progress_lock.acquire() - if global_result_dict: + + G.progress_lock.acquire() + if G.result_dict: screen_index = 2 - elif global_result_stats or global_progress_status: + elif G.result_stats or G.progress_status: screen_index = 1 - progress_lock.release() + G.progress_lock.release() if screen_index == 0: self.draw_welcome(context) @@ -673,39 +664,33 @@ class BENCHMARK_OT_run_base(bpy.types.Operator): logger.setProvider(self.logger_provider) def update_status(self, context): - global global_progress_status, global_background_image_path - global global_cancel - progress_lock.acquire() + G.progress_lock.acquire() step = self.progress_provider.current_step - if global_cancel: - global_progress_status = "Canceling..." + if G.cancel: + G.progress_status = "Canceling..." elif step == 'WARM_UP': - global_progress_status = "Rendering warm-up pass..." + G.progress_status = "Rendering warm-up pass..." elif step == 'RUN': - global current_progress - current_progress = self.progress_provider.current_progress - global_progress_status = "Rendering... Press Esc to stop." + G.current_progress = self.progress_provider.current_progress + G.progress_status = "Rendering... Press Esc to stop." context.area.tag_redraw() # Path to currently displayed background image. current_scene = self.progress_provider.current_scene if current_scene: - global_background_image_path = os.path.join( + G.background_image_path = os.path.join( self.benchmark_context.scenes_dir, current_scene, current_scene + ".png") else: - global_background_image_path = "" + G.background_image_path = "" # Update per-scene status string - global global_result_stats - global_result_stats = "" - for scene in global_scene_status: - global_result_stats += "{}: {}\n" . format( - scene, global_scene_status[scene]) - progress_lock.release() + G.result_stats = "" + for scene in G.scene_status: + G.result_stats += "{}: {}\n".format( + scene, G.scene_status[scene]) + G.progress_lock.release() def done(self, context): - global global_progress_status, global_result_stats, current_progress - global global_result_dict wm = context.window_manager wm.event_timer_remove(self.timer) # Restore all modifications to the benchmark foundation. @@ -717,30 +702,28 @@ class BENCHMARK_OT_run_base(bpy.types.Operator): self.progress_provider = None self.logger_provider = None # Construct final stats string - if global_cancel: - global_result_dict = None - reset_global_state() - elif global_result_dict: - global_result_stats = "" - for name_stat in global_result_dict["scenes"]: + if G.cancel: + G.reset() + elif G.result_dict: + G.result_stats = "" + for name_stat in G.result_dict["scenes"]: stat = name_stat["stats"] - if global_result_stats: - global_result_stats += "\n" + if G.result_stats: + G.result_stats += "\n" if stat["result"] == "OK": - global_result_stats += "{}: {}" . format(name_stat['name'], - util.humanReadableTimeDifference( - stat["total_render_time"])) + G.result_stats += "{}: {}".format(name_stat['name'], + util.humanReadableTimeDifference( + stat["total_render_time"])) else: - global_result_stats += "{}: {}" . format(name_stat['name'], - stat["result"]) + G.result_stats += "{}: {}".format(name_stat['name'], + stat["result"]) else: - global_result_stats = "" + G.result_stats = "" # TOGO(sergey): Use some more nice picture for the final slide. - global global_background_image_path - global_background_image_path = "" + G.background_image_path = "" # Tag for nice redraw - global_progress_status = None - current_progress = 0.0 + G.progress_status = None + G.current_progress = 0.0 context.area.tag_redraw() self.tmpdir = None @@ -758,11 +741,9 @@ class BENCHMARK_OT_run_base(bpy.types.Operator): return {'PASS_THROUGH'} def invoke(self, context, event): - global global_result_platform, global_progress_status - global global_scene_status, global_cancel - global_cancel = False - global_result_platform = "" - global_progress_status = "Initializing..." + G.cancel = False + G.result_platform = "" + G.progress_status = "Initializing..." context.area.tag_redraw() compute_device = context.scene.compute_device @@ -782,7 +763,7 @@ class BENCHMARK_OT_run_base(bpy.types.Operator): else: ctx.scenes = COMPLETE_SCENES for scene in ctx.scenes: - global_scene_status[scene] = "Queued" + G.scene_status[scene] = "Queued" ctx.scenes_dir = scenes_dir_get() ctx.device_type = device_type ctx.device_name = device_name @@ -806,11 +787,10 @@ class BENCHMARK_OT_run_base(bpy.types.Operator): return {'RUNNING_MODAL'} def cancel_request(self, context): - global global_cancel - progress_lock.acquire() - global_cancel = True + G.progress_lock.acquire() + G.cancel = True context.area.tag_redraw() - progress_lock.release() + G.progress_lock.release() if self.progress_provider.process: if platform.system() == "Windows": self.progress_provider.process.kill() @@ -819,7 +799,6 @@ class BENCHMARK_OT_run_base(bpy.types.Operator): self.progress_provider.process.send_signal(signal.SIGINT) def cancel(self, context): - global global_cancel self.cancel_request(context) if self.timer: wm = context.window_manager @@ -855,7 +834,7 @@ class BENCHMARK_OT_save(bpy.types.Operator): def execute(self, context): with open(self.filepath, "w") as f: - f.write(json.dumps(global_result_dict, sort_keys=True, indent=2)) + f.write(json.dumps(G.result_dict, sort_keys=True, indent=2)) make_buttons_green() return {'FINISHED'} @@ -881,18 +860,17 @@ class BENCHMARK_OT_share(bpy.types.Operator): def execute(self, context): from benchmark import submission - global global_results_submitted make_buttons_default() print('Submitting benchmark') try: - submission.submit_benchmark(global_result_dict) + submission.submit_benchmark(G.result_dict) except Exception as ex: self.report({'ERROR'}, f'Error submitting results:\n{str(ex)[:100]}') return {'CANCELLED'} print('Submission done') make_buttons_green() - global_results_submitted = True + G.results_submitted = True return {'FINISHED'} @@ -913,7 +891,7 @@ class BENCHMARK_OT_restart(bpy.types.Operator): bl_label = "Go to a home screen and choose another benchmark to run" def invoke(self, context, event): - reset_global_state() + G.reset() return {'FINISHED'} ################################################################################ @@ -954,19 +932,17 @@ def find_first_device_index(compute_units, device_name): def compute_device_list_get(self, context): - global global_cached_system_info - global global_cached_compute_devices - if global_cached_compute_devices: - return global_cached_compute_devices + if G.cached_compute_devices: + return G.cached_compute_devices compute_devices = [('CPU:::', "CPU", "")] - if not global_cached_system_info: + if not G.cached_system_info: ctx = benchmark_context.Context() ctx.blender = blender_executable_get() ctx.configure_script = configure_script_get() - global_cached_system_info = system_info_get(ctx) + G.cached_system_info = system_info_get(ctx) compute_units = query_opencl_compute_units() device_indices = {} - for device in global_cached_system_info["devices"]: + for device in G.cached_system_info["devices"]: raw_device_name = device["name"] device_type = device["type"] if raw_device_name in device_indices: @@ -997,7 +973,7 @@ def compute_device_list_get(self, context): device["name"], device_index) compute_devices.append((device_id, device_name, "")) - global_cached_compute_devices = compute_devices + G.cached_compute_devices = compute_devices return compute_devices ################################################################################