[Bf-blender-cvs] [f7d38e2e642] blender-v2.90-release: Fix T77346: GPU Workaround Always Render Using Main Context

Jeroen Bakker noreply at git.blender.org
Wed Aug 5 15:46:38 CEST 2020


Commit: f7d38e2e6426a21f4b91bedc0fe635aba4692ff2
Author: Jeroen Bakker
Date:   Wed Aug 5 15:26:49 2020 +0200
Branches: blender-v2.90-release
https://developer.blender.org/rBf7d38e2e6426a21f4b91bedc0fe635aba4692ff2

Fix T77346: GPU Workaround Always Render Using Main Context

In Blender 2.90 EEVEE materials were refactored that introduced crashes on Intel
GPUs on Windows. The crash happened in the `local_context_workaround` that temporary
stored compiled materials in a binary form to reload it in the main GL context.

It has been tested that the workaround isn't needed anymore for HD6xx GPUs, but it
is still needed for HD4000.

After several unsuccesfull fixes we came to the conclusion that we could not support
the local context workaround and needed to come with a different workaround. The idea
of this patch is that in these cases there is only a single context that is used for
rendering. Threads that uses these contextes are guarded by a mutex and will block.

Impact on User Level:
* Due to main mutex lock the UI freezes when rendering or baking or feel less snappy

Reviewed By: Clément Foucault, Brecht van Lommel

Differential Revision: https://developer.blender.org/D8410

===================================================================

M	source/blender/draw/engines/eevee/eevee_lightcache.c
M	source/blender/draw/intern/draw_manager.c
M	source/blender/draw/intern/draw_manager_shader.c
M	source/blender/gpu/GPU_context.h
M	source/blender/gpu/GPU_extensions.h
M	source/blender/gpu/intern/gpu_codegen.c
M	source/blender/gpu/intern/gpu_codegen.h
M	source/blender/gpu/intern/gpu_context.cpp
M	source/blender/gpu/intern/gpu_extensions.c
M	source/blender/windowmanager/intern/wm_draw.c

===================================================================

diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index d3a47c2641c..e4922bd85ed 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -531,6 +531,12 @@ void EEVEE_lightcache_free(LightCache *lcache)
 
 static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake)
 {
+  if (GPU_use_main_context_workaround() && !BLI_thread_is_main()) {
+    GPU_context_main_lock();
+    DRW_opengl_context_enable();
+    return;
+  }
+
   if (lbake->gl_context) {
     DRW_opengl_render_context_enable(lbake->gl_context);
     if (lbake->gpu_context == NULL) {
@@ -545,6 +551,12 @@ static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake)
 
 static void eevee_lightbake_context_disable(EEVEE_LightBake *lbake)
 {
+  if (GPU_use_main_context_workaround() && !BLI_thread_is_main()) {
+    DRW_opengl_context_disable();
+    GPU_context_main_unlock();
+    return;
+  }
+
   if (lbake->gl_context) {
     DRW_gpu_render_context_disable(lbake->gpu_context);
     DRW_opengl_render_context_disable(lbake->gl_context);
@@ -697,7 +709,7 @@ wmJob *EEVEE_lightbake_job_create(struct wmWindowManager *wm,
     lbake->delay = delay;
     lbake->frame = frame;
 
-    if (lbake->gl_context == NULL) {
+    if (lbake->gl_context == NULL && !GPU_use_main_context_workaround()) {
       lbake->gl_context = WM_opengl_context_create();
       wm_window_reset_drawable();
     }
@@ -742,7 +754,7 @@ void *EEVEE_lightbake_job_data_alloc(struct Main *bmain,
   lbake->mutex = BLI_mutex_alloc();
   lbake->frame = frame;
 
-  if (run_as_job) {
+  if (run_as_job && !GPU_use_main_context_workaround()) {
     lbake->gl_context = WM_opengl_context_create();
     wm_window_reset_drawable();
   }
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index cea5dea6029..70c117d55b4 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -2719,6 +2719,12 @@ void DRW_render_context_enable(Render *render)
     WM_init_opengl(G_MAIN);
   }
 
+  if (GPU_use_main_context_workaround()) {
+    GPU_context_main_lock();
+    DRW_opengl_context_enable();
+    return;
+  }
+
   void *re_gl_context = RE_gl_context_get(render);
 
   /* Changing Context */
@@ -2736,6 +2742,12 @@ void DRW_render_context_enable(Render *render)
 
 void DRW_render_context_disable(Render *render)
 {
+  if (GPU_use_main_context_workaround()) {
+    DRW_opengl_context_disable();
+    GPU_context_main_unlock();
+    return;
+  }
+
   void *re_gl_context = RE_gl_context_get(render);
 
   if (re_gl_context != NULL) {
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 0bb20631537..34069438e47 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -34,6 +34,7 @@
 
 #include "DEG_depsgraph_query.h"
 
+#include "GPU_extensions.h"
 #include "GPU_material.h"
 #include "GPU_shader.h"
 
@@ -106,6 +107,12 @@ static void drw_deferred_shader_compilation_exec(
   BLI_assert(gl_context != NULL);
 #endif
 
+  const bool use_main_context_workaround = GPU_use_main_context_workaround();
+  if (use_main_context_workaround) {
+    BLI_assert(gl_context == DST.gl_context);
+    GPU_context_main_lock();
+  }
+
   WM_opengl_context_activate(gl_context);
 
   while (true) {
@@ -154,6 +161,9 @@ static void drw_deferred_shader_compilation_exec(
   }
 
   WM_opengl_context_release(gl_context);
+  if (use_main_context_workaround) {
+    GPU_context_main_unlock();
+  }
 }
 
 static void drw_deferred_shader_compilation_free(void *custom_data)
@@ -196,6 +206,8 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
     GPU_material_compile(mat);
     return;
   }
+  const bool use_main_context = GPU_use_main_context_workaround();
+  const bool job_own_context = !use_main_context;
 
   DRWDeferredShader *dsh = MEM_callocN(sizeof(DRWDeferredShader), "Deferred Shader");
 
@@ -227,7 +239,7 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
     if (old_comp->gl_context) {
       comp->gl_context = old_comp->gl_context;
       old_comp->own_context = false;
-      comp->own_context = true;
+      comp->own_context = job_own_context;
     }
   }
 
@@ -235,9 +247,14 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
 
   /* Create only one context. */
   if (comp->gl_context == NULL) {
-    comp->gl_context = WM_opengl_context_create();
-    WM_opengl_context_activate(DST.gl_context);
-    comp->own_context = true;
+    if (use_main_context) {
+      comp->gl_context = DST.gl_context;
+    }
+    else {
+      comp->gl_context = WM_opengl_context_create();
+      WM_opengl_context_activate(DST.gl_context);
+    }
+    comp->own_context = job_own_context;
   }
 
   WM_jobs_customdata_set(wm_job, comp, drw_deferred_shader_compilation_free);
diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h
index 9876aa6998c..6af150b4660 100644
--- a/source/blender/gpu/GPU_context.h
+++ b/source/blender/gpu/GPU_context.h
@@ -42,6 +42,14 @@ void GPU_context_discard(GPUContext *);
 void GPU_context_active_set(GPUContext *);
 GPUContext *GPU_context_active_get(void);
 
+/* Legacy GPU (Intel HD4000 series) do not support sharing GPU objects between GPU
+ * contexts. EEVEE/Workbench can create different contexts for image/preview rendering, baking or
+ * compiling. When a legacy GPU is detected (`GPU_use_main_context_workaround()`) any worker
+ * threads should use the draw manager opengl context and make sure that they are the only one
+ * using it by locking the main context using these two functions. */
+void GPU_context_main_lock(void);
+void GPU_context_main_unlock(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 263deeaf28d..4b44ba1b76f 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -48,7 +48,7 @@ bool GPU_arb_texture_cube_map_array_is_supported(void);
 bool GPU_mip_render_workaround(void);
 bool GPU_depth_blitting_workaround(void);
 bool GPU_unused_fb_slot_workaround(void);
-bool GPU_context_local_shaders_workaround(void);
+bool GPU_use_main_context_workaround(void);
 bool GPU_texture_copy_workaround(void);
 bool GPU_crappy_amd_driver(void);
 
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 0a1d6f560b6..155179205c5 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -1228,21 +1228,9 @@ bool GPU_pass_compile(GPUPass *pass, const char *shname)
         shader = NULL;
       }
     }
-    else if (!BLI_thread_is_main() && GPU_context_local_shaders_workaround()) {
-      pass->binary.content = GPU_shader_get_binary(
-          shader, &pass->binary.format, &pass->binary.len);
-      GPU_shader_free(shader);
-      shader = NULL;
-    }
-
     pass->shader = shader;
     pass->compiled = true;
   }
-  else if (pass->binary.content && BLI_thread_is_main()) {
-    pass->shader = GPU_shader_load_from_binary(
-        pass->binary.content, pass->binary.format, pass->binary.len, shname);
-    MEM_SAFE_FREE(pass->binary.content);
-  }
 
   return success;
 }
@@ -1263,9 +1251,6 @@ static void gpu_pass_free(GPUPass *pass)
   MEM_SAFE_FREE(pass->geometrycode);
   MEM_SAFE_FREE(pass->vertexcode);
   MEM_SAFE_FREE(pass->defines);
-  if (pass->binary.content) {
-    MEM_freeN(pass->binary.content);
-  }
   MEM_freeN(pass);
 }
 
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index ce20f495ba3..e12e0c0ba08 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -43,11 +43,6 @@ typedef struct GPUPass {
   char *defines;
   uint refcount; /* Orphaned GPUPasses gets freed by the garbage collector. */
   uint32_t hash; /* Identity hash generated from all GLSL code. */
-  struct {
-    char *content;
-    uint format;
-    int len;
-  } binary;
   bool compiled; /* Did we already tried to compile the attached GPUShader. */
 } GPUPass;
 
diff --git a/source/blender/gpu/intern/gpu_context.cpp b/source/blender/gpu/intern/gpu_context.cpp
index 0b9104e5349..e6356580ea3 100644
--- a/source/blender/gpu/intern/gpu_context.cpp
+++ b/source/blender/gpu/intern/gpu_context.cpp
@@ -62,6 +62,7 @@ static std::vector<GLuint> orphaned_buffer_ids;
 static std::vector<GLuint> orphaned_texture_ids;
 
 static std::mutex orphans_mutex;
+static std::mutex main_context_mutex;
 
 struct GPUContext {
   GLuint default_vao;
@@ -345,3 +346,13 @@ struct GPUMatrixState *gpu_context_active_matrix_state_get()
   BLI_assert(active_ctx);
   return active_ctx->matrix_state;
 }
+
+void GPU_context_main_lock(void)
+{
+  main_context_mutex.lock();
+}
+
+void GPU_context_main_unlock(void)
+{
+  main_context_mutex.unlock();
+}
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 9aa3becef1d..9c37cc32e1d 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -95,7 +95,7 @@ static struct GPUGlobal {
   bool broken_amd_driver;
   /* Some crappy Intel drivers don't work well with shaders created in different
    * rendering contexts. */
-  bool context_local_shaders_workaround;
+  bool use_main_context_workaround;
   /* Intel drivers exhibit artifacts when using #glCopyImageSubData & workbench anti-aliasing.
    * (see T76273) */
   bool texture_copy_workaround;
@@ -222,9 +222,9 @@ bool GPU_unused_fb_slot_workaround(void)
   return GG.unused_fb_slot_workaround;
 }
 
-bool GPU_context_local_shaders_workaround(void)
+bool GPU_use_main_context_workaround(void)
 {
-  return GG.context_local_shaders_workaround;
+  return GG.use_main_context_workaround;
 }
 
 bool GPU_texture_copy_workaround(void)
@@ -381,12 +381,12 @@ void gpu_extensions_init(void)
       /* Maybe not all of these drivers have problems with `GLEW_ARB_base_instance`.
        * But it's hard to test each case. */
     

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list