Render: Create a separate gl context for rendering.
authorClément Foucault <foucault.clem@gmail.com>
Mon, 11 Jun 2018 11:54:31 +0000 (13:54 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Mon, 11 Jun 2018 11:55:02 +0000 (13:55 +0200)
This should take care of all the threading stability issues some people
are reporting.

source/blender/draw/intern/draw_manager.c
source/blender/editors/render/render_internal.c
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/source/pipeline.c

index 5f059f9..054d070 100644 (file)
@@ -1464,8 +1464,24 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
                WM_init_opengl();
        }
 
+       void *re_gl_context = RE_gl_context_get(render);
+       void *re_gwn_context = NULL;
+
        /* Changing Context */
-       DRW_opengl_context_enable();
+       if (re_gl_context != NULL) {
+               /* TODO get rid of the blocking. Only here because of the static global DST. */
+               BLI_mutex_lock(&DST.gl_context_mutex);
+               WM_opengl_context_activate(re_gl_context);
+               re_gwn_context = RE_gwn_context_get(render);
+               if (GWN_context_active_get() == NULL) {
+                       GWN_context_active_set(re_gwn_context);
+               }
+               DRW_shape_cache_reset(); /* XXX fix that too. */
+       }
+       else {
+               DRW_opengl_context_enable();
+       }
+
        /* IMPORTANT: We dont support immediate mode in render mode!
         * This shall remain in effect until immediate mode supports
         * multiple threads. */
@@ -1533,7 +1549,17 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
        GPU_framebuffer_restore();
 
        /* Changing Context */
-       DRW_opengl_context_disable();
+       if (re_gl_context != NULL) {
+               DRW_shape_cache_reset(); /* XXX fix that too. */
+               glFlush();
+               GWN_context_active_set(NULL);
+               WM_opengl_context_release(re_gl_context);
+               /* TODO get rid of the blocking. */
+               BLI_mutex_unlock(&DST.gl_context_mutex);
+       }
+       else {
+               DRW_opengl_context_disable();
+       }
 
 #ifdef DEBUG
        /* Avoid accidental reuse. */
index 2d65b36..ad546b6 100644 (file)
@@ -1015,6 +1015,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
        RE_current_scene_update_cb(re, rj, current_scene_update);
        RE_stats_draw_cb(re, rj, image_renderinfo_cb);
        RE_progress_cb(re, rj, render_progress_update);
+       RE_gl_context_create(re);
 
        rj->re = re;
        G.is_break = false;
index 660e81e..5563847 100644 (file)
@@ -311,6 +311,11 @@ void RE_draw_lock_cb               (struct Render *re, void *handle, void (*f)(void *handle,
 void RE_test_break_cb  (struct Render *re, void *handle, int (*f)(void *handle));
 void RE_current_scene_update_cb(struct Render *re, void *handle, void (*f)(void *handle, struct Scene *scene));
 
+void  RE_gl_context_create(Render *re);
+void  RE_gl_context_destroy(Render *re);
+void *RE_gl_context_get(Render *re);
+void *RE_gwn_context_get(Render *re);
+
 /* should move to kernel once... still unsure on how/where */
 float RE_filter_value(int type, float x);
 
index fd24f4e..34535fb 100644 (file)
@@ -157,6 +157,10 @@ struct Render {
 
        void **movie_ctx_arr;
        char viewname[MAX_NAME];
+
+       /* TODO replace by a whole draw manager. */
+       void *gl_context;
+       void *gwn_context;
 };
 
 /* **************** defines ********************* */
index c9f1300..0ca9aa4 100644 (file)
@@ -94,6 +94,9 @@
 #include "RE_pipeline.h"
 #include "RE_render_ext.h"
 
+#include "../../../windowmanager/WM_api.h" /* XXX */
+#include "../../../intern/gawain/gawain/gwn_context.h"
+
 #ifdef WITH_FREESTYLE
 #  include "FRS_freestyle.h"
 #endif
@@ -1020,6 +1023,40 @@ void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle))
        re->tbh = handle;
 }
 
+/* ********* GL Context ******** */
+
+void RE_gl_context_create(Render *re)
+{
+       /* Needs to be created in the main ogl thread. */
+       re->gl_context = WM_opengl_context_create();
+}
+
+void RE_gl_context_destroy(Render *re)
+{
+       /* Needs to be called from the thread which used the ogl context for rendering. */
+       if (re->gwn_context) {
+               GWN_context_active_set(re->gwn_context);
+               GWN_context_discard(re->gwn_context);
+               re->gwn_context = NULL;
+       }
+       if (re->gl_context) {
+               WM_opengl_context_dispose(re->gl_context);
+               re->gl_context = NULL;
+       }
+}
+
+void *RE_gl_context_get(Render *re)
+{
+       return re->gl_context;
+}
+
+void *RE_gwn_context_get(Render *re)
+{
+       if (re->gwn_context == NULL) {
+               re->gwn_context = GWN_context_create();
+       }
+       return re->gwn_context;
+}
 
 /* ********* add object data (later) ******** */
 
@@ -2224,6 +2261,9 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, ViewLayer *single_la
 
        BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
 
+       /* Destroy the opengl context in the correct thread. */
+       RE_gl_context_destroy(re);
+
        /* UGLY WARNING */
        G.is_rendering = false;
 }
@@ -2779,6 +2819,9 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
        BLI_callback_exec(re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
        BKE_sound_reset_scene_specs(scene);
 
+       /* Destroy the opengl context in the correct thread. */
+       RE_gl_context_destroy(re);
+
        /* UGLY WARNING */
        G.is_rendering = false;
 }