From 52543be9a6a4398a3cb5ec19df3659aa42a38727 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Mon, 20 Jul 2020 13:56:29 +0200 Subject: Python API: option to use OpenGL context in RenderEngine.render When bl_use_gpu_context is set, an OpenGL context will be available for OpenGL based render engines. Differential Revision: https://developer.blender.org/D8305 --- source/blender/draw/DRW_engine.h | 4 + source/blender/draw/engines/eevee/eevee_engine.c | 2 +- source/blender/draw/engines/select/select_engine.c | 2 +- .../draw/engines/workbench/workbench_engine.c | 2 +- source/blender/draw/intern/draw_manager.c | 94 +++++++++------------- source/blender/editors/gpencil/gpencil_convert.c | 2 +- source/blender/makesrna/intern/rna_render.c | 8 ++ source/blender/render/extern/include/RE_engine.h | 1 + .../blender/render/intern/source/external_engine.c | 8 ++ 9 files changed, 65 insertions(+), 58 deletions(-) diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 6c835c6d7ae..bc4efd82a03 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -43,6 +43,7 @@ struct GPUViewport; struct ID; struct Main; struct Object; +struct Render; struct RenderEngine; struct RenderEngineType; struct Scene; @@ -137,6 +138,9 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph struct DRWInstanceDataList *DRW_instance_data_list_create(void); void DRW_instance_data_list_free(struct DRWInstanceDataList *idatalist); +void DRW_render_context_enable(struct Render *render); +void DRW_render_context_disable(struct Render *render); + void DRW_opengl_context_create(void); void DRW_opengl_context_destroy(void); void DRW_opengl_context_enable(void); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index bac96ab1079..f42c60b04bf 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -601,7 +601,7 @@ RenderEngineType DRW_engine_viewport_eevee_type = { NULL, EEVEE_ENGINE, N_("Eevee"), - RE_INTERNAL | RE_USE_PREVIEW | RE_USE_STEREO_VIEWPORT, + RE_INTERNAL | RE_USE_PREVIEW | RE_USE_STEREO_VIEWPORT | RE_USE_GPU_CONTEXT, NULL, &DRW_render_to_image, NULL, diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c index bb7c947a0b9..8cee6c4ee9f 100644 --- a/source/blender/draw/engines/select/select_engine.c +++ b/source/blender/draw/engines/select/select_engine.c @@ -378,7 +378,7 @@ RenderEngineType DRW_engine_viewport_select_type = { NULL, SELECT_ENGINE, N_("Select ID"), - RE_INTERNAL | RE_USE_STEREO_VIEWPORT, + RE_INTERNAL | RE_USE_STEREO_VIEWPORT | RE_USE_GPU_CONTEXT, NULL, NULL, NULL, diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index 5fff55e2f26..53119723fab 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -641,7 +641,7 @@ RenderEngineType DRW_engine_viewport_workbench_type = { NULL, WORKBENCH_ENGINE, N_("Workbench"), - RE_INTERNAL | RE_USE_STEREO_VIEWPORT, + RE_INTERNAL | RE_USE_STEREO_VIEWPORT | RE_USE_GPU_CONTEXT, NULL, &DRW_render_to_image, NULL, diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 08fb80c11d2..712a93e8880 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1660,24 +1660,8 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph RenderEngineType *engine_type = engine->type; RenderData *r = &scene->r; Render *render = engine->re; - /* Changing Context */ - if (G.background && DST.gl_context == NULL) { - WM_init_opengl(G_MAIN); - } - void *re_gl_context = RE_gl_context_get(render); - void *re_gpu_context = NULL; - - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_opengl_render_context_enable(re_gl_context); - /* We need to query gpu context after a gl context has been bound. */ - re_gpu_context = RE_gpu_context_get(render); - DRW_gpu_render_context_enable(re_gpu_context); - } - else { - DRW_opengl_context_enable(); - } + DRW_render_context_enable(render); /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); @@ -1729,14 +1713,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph /* Restore Drawing area. */ GPU_framebuffer_restore(); - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_gpu_render_context_disable(re_gpu_context); - DRW_opengl_render_context_disable(re_gl_context); - } - else { - DRW_opengl_context_disable(); - } + DRW_render_context_disable(render); DST.buffer_finish_called = false; } @@ -1749,24 +1726,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) DrawEngineType *draw_engine_type = engine_type->draw_engine; Render *render = engine->re; - if (G.background && DST.gl_context == NULL) { - WM_init_opengl(G_MAIN); - } - - void *re_gl_context = RE_gl_context_get(render); - void *re_gpu_context = NULL; - - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_opengl_render_context_enable(re_gl_context); - /* We need to query gpu context after a gl context has been bound. */ - re_gpu_context = RE_gpu_context_get(render); - DRW_gpu_render_context_enable(re_gpu_context); - } - else { - DRW_opengl_context_enable(); - } - /* IMPORTANT: We don't support immediate mode in render mode! * This shall remain in effect until immediate mode supports * multiple threads. */ @@ -1842,15 +1801,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) /* Reset state after drawing */ DRW_state_reset(); - - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_gpu_render_context_disable(re_gpu_context); - DRW_opengl_render_context_disable(re_gl_context); - } - else { - DRW_opengl_context_disable(); - } } void DRW_render_object_iter( @@ -2763,6 +2713,42 @@ void DRW_engines_free(void) DRW_opengl_context_disable(); } +void DRW_render_context_enable(Render *render) +{ + if (G.background && DST.gl_context == NULL) { + WM_init_opengl(G_MAIN); + } + + void *re_gl_context = RE_gl_context_get(render); + + /* Changing Context */ + if (re_gl_context != NULL) { + DRW_opengl_render_context_enable(re_gl_context); + /* We need to query gpu context after a gl context has been bound. */ + void *re_gpu_context = NULL; + re_gpu_context = RE_gpu_context_get(render); + DRW_gpu_render_context_enable(re_gpu_context); + } + else { + DRW_opengl_context_enable(); + } +} + +void DRW_render_context_disable(Render *render) +{ + void *re_gl_context = RE_gl_context_get(render); + + if (re_gl_context != NULL) { + void *re_gpu_context = NULL; + re_gpu_context = RE_gpu_context_get(render); + DRW_gpu_render_context_disable(re_gpu_context); + DRW_opengl_render_context_disable(re_gl_context); + } + else { + DRW_opengl_context_disable(); + } +} + /** \} */ /** \name Init/Exit (DRW_opengl_ctx) @@ -2903,8 +2889,8 @@ void DRW_gpu_render_context_disable(void *UNUSED(re_gpu_context)) * switch to it just to submit the final frame, which has notable performance impact. * * We could "inject" a context through DRW_opengl_render_context_enable(), but that would have to - * work from the main thread, which is tricky to get working too. The preferable solution would be - * using a separate thread for VR drawing where a single context can stay active. */ + * work from the main thread, which is tricky to get working too. The preferable solution would + * be using a separate thread for VR drawing where a single context can stay active. */ void *DRW_xr_opengl_context_get(void) { return DST.gl_context; diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 52e9a437830..d4d37e7a9b7 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -400,7 +400,7 @@ static void gpencil_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, static void gpencil_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, - Depsgraph *depsgraph, + Depsgraph *depsgraph, FCurve *fcu, Curve *cu, tGpTimingData *gtd, diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index ab8fc8936c0..5b77632be79 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -845,6 +845,14 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Use Eevee Viewport", "Uses Eevee for viewport shading in LookDev shading mode"); + prop = RNA_def_property(srna, "bl_use_gpu_context", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_GPU_CONTEXT); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + RNA_def_property_ui_text( + prop, + "Use GPU Context", + "Enable OpenGL context for the render method, for engines that render using OpenGL"); + prop = RNA_def_property(srna, "bl_use_shading_nodes_custom", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_SHADING_NODES_CUSTOM); RNA_def_property_boolean_default(prop, true); diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 77a60854616..51eb290b0b8 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -60,6 +60,7 @@ struct bNodeTree; #define RE_USE_SHADING_NODES_CUSTOM 64 #define RE_USE_SPHERICAL_STEREO 128 #define RE_USE_STEREO_VIEWPORT 256 +#define RE_USE_GPU_CONTEXT 512 /* RenderEngine.flag */ #define RE_ENGINE_ANIMATION 1 diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index e1fbf6d19de..633b9324d9f 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -863,8 +863,16 @@ int RE_engine_render(Render *re, int do_all) re->draw_lock(re->dlh, 0); } + if (engine->type->flag & RE_USE_GPU_CONTEXT) { + DRW_render_context_enable(engine->re); + } + type->render(engine, engine->depsgraph); + if (engine->type->flag & RE_USE_GPU_CONTEXT) { + DRW_render_context_disable(engine->re); + } + /* Grease pencil render over previous render result. * * NOTE: External engine might have been requested to free its -- cgit v1.2.3