From 05c56603a92b87cea8749fec6dc88200f06d5c7b Mon Sep 17 00:00:00 2001 From: Jason Fielder <jason-fielder@noreply.localhost> Date: Tue, 7 Nov 2023 15:35:42 +0100 Subject: [PATCH] Fix #114192: Resolve animation player greying out on resize in Metal Standalone animation player has inconsistent GPU context activation paradigm compared with standard rendering paths. The Metal backend utilises the context activation step to refresh target window swapchains from within the GHOST module. This PR adds activation and deactivation calls, and also aims to clean up GPU_render_begin/end setup to ensure all paths are covered. Also resolves a bug upon shutdown wherein GPU resources which may be tied to a GPU context are released during IMB_exit(), which is called after GPU context destruction. Authored by Apple: Michael Parkin-White Pull Request: https://projects.blender.org/blender/blender/pulls/114573 --- .../windowmanager/intern/wm_playanim.cc | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_playanim.cc b/source/blender/windowmanager/intern/wm_playanim.cc index b4e2adb692e..0b2f43e8d4d 100644 --- a/source/blender/windowmanager/intern/wm_playanim.cc +++ b/source/blender/windowmanager/intern/wm_playanim.cc @@ -624,7 +624,7 @@ static void draw_display_buffer(const PlayDisplayContext *display_ctx, * \param draw_flip: X/Y flipping (ignored when null). * \param indicator_factor: Display a vertical indicator (ignored when -1). */ -static void playanim_toscreen_ex(GHOST_WindowHandle ghost_window, +static void playanim_toscreen_ex(GhostData *data, const PlayDisplayContext *display_ctx, const PlayAnimPict *picture, ImBuf *ibuf, @@ -635,9 +635,11 @@ static void playanim_toscreen_ex(GHOST_WindowHandle ghost_window, const bool draw_flip[2], const float indicator_factor) { - GHOST_ActivateWindowDrawingContext(ghost_window); + GHOST_ActivateWindowDrawingContext(data->window); GPU_render_begin(); - GPU_render_step(); + + GPUContext *restore_context = GPU_context_active_get(); + GPU_context_active_set(data->gpu_context); GPU_clear_color(0.1f, 0.1f, 0.1f, 0.0f); @@ -689,7 +691,7 @@ static void playanim_toscreen_ex(GHOST_WindowHandle ghost_window, SNPRINTF(label, "%s | <failed to load buffer>", picture->filepath); } - playanim_window_get_size(ghost_window, &sizex, &sizey); + playanim_window_get_size(data->window, &sizex, &sizey); fsizex_inv = 1.0f / sizex; fsizey_inv = 1.0f / sizey; @@ -737,11 +739,17 @@ static void playanim_toscreen_ex(GHOST_WindowHandle ghost_window, GPU_matrix_pop_projection(); } - GHOST_SwapWindowBuffers(ghost_window); + GPU_render_step(); + if (GPU_backend_get_type() == GPU_BACKEND_METAL) { + GPU_flush(); + } + + GHOST_SwapWindowBuffers(data->window); + GPU_context_active_set(restore_context); GPU_render_end(); } -static void playanim_toscreen_on_load(GHOST_WindowHandle ghost_window, +static void playanim_toscreen_on_load(GhostData *ghost_data, const PlayDisplayContext *display_ctx, const PlayAnimPict *picture, ImBuf *ibuf) @@ -753,7 +761,7 @@ static void playanim_toscreen_on_load(GHOST_WindowHandle ghost_window, const bool *draw_flip = nullptr; playanim_toscreen_ex( - ghost_window, display_ctx, picture, ibuf, font_id, fstep, zoom, draw_flip, indicator_factor); + ghost_data, display_ctx, picture, ibuf, font_id, fstep, zoom, draw_flip, indicator_factor); } static void playanim_toscreen(PlayState *ps, const PlayAnimPict *picture, ImBuf *ibuf) @@ -779,7 +787,7 @@ static void playanim_toscreen(PlayState *ps, const PlayAnimPict *picture, ImBuf } BLI_assert(ps->loading == false); - playanim_toscreen_ex(ps->ghost_data.window, + playanim_toscreen_ex(&ps->ghost_data, &ps->display_ctx, picture, ibuf, @@ -804,7 +812,7 @@ static void build_pict_list_from_anim(GhostData *ghost_data, ImBuf *ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); if (ibuf) { - playanim_toscreen_on_load(ghost_data->window, display_ctx, nullptr, ibuf); + playanim_toscreen_on_load(ghost_data, display_ctx, nullptr, ibuf); IMB_freeImBuf(ibuf); } @@ -888,7 +896,7 @@ static void build_pict_list_from_image_sequence(GhostData *ghost_data, if (ibuf) { if (display_imbuf) { - playanim_toscreen_on_load(ghost_data->window, display_ctx, picture, ibuf); + playanim_toscreen_on_load(ghost_data, display_ctx, picture, ibuf); } #ifdef USE_FRAME_CACHE_LIMIT if (fill_cache) { @@ -1951,9 +1959,15 @@ static char *wm_main_playanim_intern(int argc, const char **argv) ps.next_frame = ps.direction; + GPU_render_begin(); + GPUContext *restore_context = GPU_context_active_get(); + GPU_context_active_set(ps.ghost_data.gpu_context); while ((has_event = GHOST_ProcessEvents(ps.ghost_data.system, false))) { GHOST_DispatchEvents(ps.ghost_data.system); } + GPU_render_end(); + GPU_context_active_set(restore_context); + if (ps.go == false) { break; } @@ -2055,6 +2069,10 @@ static char *wm_main_playanim_intern(int argc, const char **argv) BLF_exit(); + /* NOTE: Must happen before GPU Context destruction as GPU resources are released via + * Colour Management module. */ + IMB_exit(); + if (ps.ghost_data.gpu_context) { GPU_context_active_set(ps.ghost_data.gpu_context); GPU_exit(); @@ -2074,8 +2092,6 @@ static char *wm_main_playanim_intern(int argc, const char **argv) GHOST_DisposeSystem(ps.ghost_data.system); - IMB_exit(); - totblock = MEM_get_memory_blocks_in_use(); if (totblock != 0) { /* prints many bAKey, bArgument's which are tricky to fix */ -- GitLab