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
This commit is contained in:
Miguel Pozo 2020-07-20 13:56:29 +02:00 committed by Brecht Van Lommel
parent a9644c812f
commit 52543be9a6
9 changed files with 65 additions and 58 deletions

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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