DRW / Render: Add support for render pipeline in drawmanager.

For simplicity we choose to execute the rendering of Opengl engines in the main thread and block the interface.
This might be addressed in the future at least for video rendering.

A drawmanager wrapper (DRW_render_to_image) is called by the render pipeline to set up the Opengl state and then call the specific draw_engine->render_to_image function.
This commit is contained in:
Clément Foucault 2018-01-29 14:56:16 +01:00 committed by Clément Foucault
parent 01a62515cb
commit b6dbd8723c
23 changed files with 129 additions and 12 deletions

View File

@ -46,6 +46,7 @@ struct View3D;
struct rcti;
struct GPUOffScreen;
struct GPUViewport;
struct RenderEngine;
struct RenderEngineType;
struct WorkSpace;
@ -67,6 +68,7 @@ typedef struct DefaultTextureList {
void DRW_engines_register(void);
void DRW_engines_free(void);
bool DRW_engine_render_support(struct DrawEngineType *draw_engine_type);
void DRW_engine_register(struct DrawEngineType *draw_engine_type);
void DRW_engine_viewport_data_size_get(
const void *engine_type,

View File

@ -264,6 +264,7 @@ DrawEngineType draw_engine_basic_type = {
&basic_draw_scene,
NULL,
NULL,
NULL,
};
/* Note: currently unused, we may want to register so we can see this when debugging the view. */

View File

@ -949,6 +949,7 @@ DrawEngineType draw_engine_clay_type = {
&clay_draw_scene,
NULL,
NULL,
NULL,
};
RenderEngineType DRW_engine_viewport_clay_type = {

View File

@ -218,6 +218,7 @@ DrawEngineType draw_engine_external_type = {
&external_draw_scene,
NULL,
NULL,
NULL,
};
/* Note: currently unused, we should not register unless we want to see this when debugging the view. */

View File

@ -139,6 +139,8 @@ typedef struct DrawEngineType {
void (*view_update)(void *vedata);
void (*id_update)(void *vedata, struct ID *id);
void (*render_to_image)(void *vedata, struct RenderEngine *engine, struct Depsgraph *graph);
} DrawEngineType;
#ifndef __DRW_ENGINE_H__
@ -386,6 +388,11 @@ struct DefaultTextureList *DRW_viewport_texture_list_get(void);
void DRW_viewport_request_redraw(void);
void DRW_render_to_image(struct RenderEngine *re, struct Depsgraph *depsgraph);
void DRW_render_object_iter(
void *vedata, struct RenderEngine *engine, struct Depsgraph *graph,
void (*callback)(void *vedata, struct Object *ob, struct RenderEngine *engine, struct Depsgraph *graph));
/* ViewLayers */
void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type);
void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*callback)(void *storage));

View File

@ -2365,7 +2365,9 @@ void DRW_framebuffer_init(
}
}
GPU_framebuffer_bind(DST.default_framebuffer);
if (DST.default_framebuffer != NULL) {
GPU_framebuffer_bind(DST.default_framebuffer);
}
}
}
@ -2626,14 +2628,17 @@ static void drw_viewport_var_init(void)
DST.default_framebuffer = NULL;
DST.vmempool = NULL;
}
/* Refresh DST.screenvecs */
copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
normalize_v3(DST.screenvecs[0]);
normalize_v3(DST.screenvecs[1]);
/* Refresh DST.pixelsize */
DST.pixsize = rv3d->pixsize;
if (rv3d != NULL) {
/* Refresh DST.screenvecs */
copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
normalize_v3(DST.screenvecs[0]);
normalize_v3(DST.screenvecs[1]);
/* Refresh DST.pixelsize */
DST.pixsize = rv3d->pixsize;
}
/* Reset facing */
DST.frontface = GL_CCW;
@ -2664,6 +2669,7 @@ void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type)
copy_m4_m4(mat, viewport_matrix_override.mat[type]);
}
else {
BLI_assert(rv3d != NULL); /* Can't use this in render mode. */
switch (type) {
case DRW_MAT_PERS:
copy_m4_m4(mat, rv3d->persmat);
@ -2704,6 +2710,7 @@ void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type)
bool DRW_viewport_is_persp_get(void)
{
RegionView3D *rv3d = DST.draw_ctx.rv3d;
BLI_assert(rv3d);
return rv3d->is_persp;
}
@ -3422,9 +3429,7 @@ void DRW_draw_render_loop_ex(
/* Init engines */
drw_engines_init();
/* TODO : tag to refresh by the dependency graph */
/* ideally only refresh when objects are added/removed */
/* or render properties / materials change */
/* Cache filling */
{
PROFILE_START(stime);
drw_engines_cache_init();
@ -3569,6 +3574,70 @@ void DRW_draw_render_loop_offscreen(
GPU_offscreen_bind(ofs, false);
}
void DRW_render_to_image(RenderEngine *re, struct Depsgraph *depsgraph)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
RenderEngineType *engine_type = re->type;
DrawEngineType *draw_engine_type = engine_type->draw_engine;
RenderData *r = &scene->r;
/* Reset before using it. */
memset(&DST, 0x0, sizeof(DST));
DST.options.is_image_render = true;
DST.draw_ctx = (DRWContextState){
NULL, NULL, NULL, scene, view_layer, OBACT(view_layer), engine_type, depsgraph, NULL
};
DST.viewport = GPU_viewport_create();
const int size[2] = {(r->size * r->xsch) / 100, (r->size * r->ysch) / 100};
GPU_viewport_size_set(DST.viewport, size);
drw_viewport_var_init();
ViewportEngineData *data = DRW_viewport_engine_data_ensure(draw_engine_type);
/* set default viewport */
gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
glDisable(GL_SCISSOR_TEST);
glViewport(0, 0, size[0], size[1]);
engine_type->draw_engine->render_to_image(data, re, depsgraph);
/* TODO grease pencil */
GPU_viewport_free(DST.viewport);
MEM_freeN(DST.viewport);
DRW_state_reset();
/* FIXME GL_DEPTH_TEST is enabled by default but it seems
* to trigger some bad behaviour / artifacts if it's turned
* on at this point. */
glDisable(GL_DEPTH_TEST);
/* Restore Drawing area. */
gpuPopAttrib();
glEnable(GL_SCISSOR_TEST);
GPU_framebuffer_restore();
#ifdef DEBUG
/* Avoid accidental reuse. */
memset(&DST, 0xFF, sizeof(DST));
#endif
}
void DRW_render_object_iter(
void *vedata, RenderEngine *engine, struct Depsgraph *depsgraph,
void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph))
{
DEG_OBJECT_ITER_FOR_RENDER_ENGINE(depsgraph, ob, DRW_iterator_mode_get())
{
callback(vedata, ob, engine, depsgraph);
}
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
}
/**
* object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing).
*/
@ -3796,7 +3865,7 @@ void DRW_state_dfdy_factors_get(float dfdyfac[2])
*/
bool DRW_state_is_fbo(void)
{
return (DST.default_framebuffer != NULL);
return ((DST.default_framebuffer != NULL) || DST.options.is_image_render);
}
/**
@ -3894,6 +3963,11 @@ const DRWContextState *DRW_context_state_get(void)
/** \name Init/Exit (DRW_engines)
* \{ */
bool DRW_engine_render_support(DrawEngineType *draw_engine_type)
{
return draw_engine_type->render_to_image;
}
void DRW_engine_register(DrawEngineType *draw_engine_type)
{
BLI_addtail(&DRW_engines, draw_engine_type);

View File

@ -154,4 +154,5 @@ DrawEngineType draw_engine_edit_armature_type = {
NULL,
&EDIT_ARMATURE_draw_scene,
NULL,
NULL,
};

View File

@ -347,4 +347,5 @@ DrawEngineType draw_engine_edit_curve_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_CURVE_draw_scene,
NULL,
NULL,
};

View File

@ -294,4 +294,5 @@ DrawEngineType draw_engine_edit_lattice_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_LATTICE_draw_scene,
NULL,
NULL,
};

View File

@ -610,4 +610,5 @@ DrawEngineType draw_engine_edit_mesh_type = {
NULL,
&EDIT_MESH_draw_scene,
NULL,
NULL,
};

View File

@ -248,4 +248,5 @@ DrawEngineType draw_engine_edit_metaball_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_METABALL_draw_scene,
NULL,
NULL,
};

View File

@ -266,4 +266,5 @@ DrawEngineType draw_engine_edit_surface_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_SURFACE_draw_scene,
NULL,
NULL,
};

View File

@ -309,4 +309,5 @@ DrawEngineType draw_engine_edit_text_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_TEXT_draw_scene,
NULL,
NULL,
};

View File

@ -2044,4 +2044,5 @@ DrawEngineType draw_engine_object_type = {
NULL,
&OBJECT_draw_scene,
NULL,
NULL,
};

View File

@ -414,4 +414,5 @@ DrawEngineType draw_engine_paint_texture_type = {
NULL, /* draw_background but not needed by mode engines */
&PAINT_TEXTURE_draw_scene,
NULL,
NULL,
};

View File

@ -213,4 +213,5 @@ DrawEngineType draw_engine_paint_vertex_type = {
NULL,
&PAINT_VERTEX_draw_scene,
NULL,
NULL,
};

View File

@ -251,4 +251,5 @@ DrawEngineType draw_engine_paint_weight_type = {
NULL,
&PAINT_WEIGHT_draw_scene,
NULL,
NULL,
};

View File

@ -261,4 +261,5 @@ DrawEngineType draw_engine_particle_type = {
NULL, /* draw_background but not needed by mode engines */
&PARTICLE_draw_scene,
NULL,
NULL,
};

View File

@ -195,4 +195,5 @@ DrawEngineType draw_engine_pose_type = {
NULL,
&POSE_draw_scene,
NULL,
NULL,
};

View File

@ -302,4 +302,5 @@ DrawEngineType draw_engine_sculpt_type = {
NULL, /* draw_background but not needed by mode engines */
&SCULPT_draw_scene,
NULL,
NULL,
};

View File

@ -844,6 +844,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
Main *mainp;
ViewLayer *view_layer = NULL;
Scene *scene = CTX_data_scene(C);
RenderEngineType *re_type = RE_engines_find(scene->view_render.engine_id);
Render *re;
wmJob *wm_job;
RenderJob *rj;
@ -856,6 +857,13 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
const char *name;
ScrArea *sa;
/* XXX FIXME If engine is an OpenGL engine do not run modal.
* This is a problem for animation rendering since you cannot abort them.
* This also does not open an image editor space. */
if (RE_engine_is_opengl(re_type)) {
return screen_render_exec(C, op);
}
/* only one render job at a time */
if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER))

View File

@ -183,6 +183,8 @@ void RE_engines_init(void);
void RE_engines_exit(void);
void RE_engines_register(struct Main *bmain, RenderEngineType *render_type);
bool RE_engine_is_opengl(RenderEngineType *render_type);
RenderEngineType *RE_engines_find(const char *idname);
rcti* RE_engine_get_current_tiles(struct Render *re, int *r_total_tiles, bool *r_needs_free);

View File

@ -155,6 +155,13 @@ bool RE_engine_is_external(Render *re)
return (re->engine && re->engine->type && re->engine->type->render_to_image);
}
bool RE_engine_is_opengl(RenderEngineType *render_type)
{
/* TODO refine? Can we have ogl render engine without ogl render pipeline? */
return (render_type->draw_engine != NULL) &&
DRW_engine_render_support(render_type->draw_engine);
}
/* Create, Free */
RenderEngine *RE_engine_create(RenderEngineType *type)