Moved global state into a class G

This allows other modules to do `from benchmark.space import G` and use
the global state too. This is possible because the name `G` keeps
referencing the same object (a class) even when resetting (contrary to
the old `global_xxx = None`, which assigns a new object reference).
This commit is contained in:
2018-08-14 13:33:56 +02:00
parent cfbbc912e7
commit 9af1ca1c49

View File

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