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",
"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'],
G.result_stats += "{}: {}".format(name_stat['name'],
util.humanReadableTimeDifference(
stat["total_render_time"]))
else:
global_result_stats += "{}: {}" . format(name_stat['name'],
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
################################################################################