diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-07-10 15:40:28 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-07-10 16:31:34 +0300 |
commit | c90a0d5dda535a42697503e130b0c2fc123fe491 (patch) | |
tree | 0791abda94c63b54c2255b77ba9fbfee17edbe67 /source/blender/draw/intern | |
parent | 873d7f7e14e080f75e75ed7c6c07f326e588cecb (diff) |
DRW: Add new features from lightcache branch
- Change gl_context_mutex to a ticket mutex ensuring interactivity even
when rendering.
- Add DRW_custom_pipeline for using DRW outside of the viewport and render
pipeline.
- DRW_opengl_render_context_*** and DRW_gawain_render_context_*** to use
with DRW_custom_pipeline.
- Add possibility to bypass deferred compilation on demand (not User
demand).
- Add union to access DRWMatrixState members more easily.
Diffstat (limited to 'source/blender/draw/intern')
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 28 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 115 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.h | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_shader.c | 20 |
4 files changed, 130 insertions, 35 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index e0c8cb36e2f..4d1b8269494 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -240,14 +240,14 @@ struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines); struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines); struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines); struct GPUShader *DRW_shader_create_3D_depth_only(void); -struct GPUMaterial *DRW_shader_find_from_world(struct World *wo, const void *engine_type, int options); -struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma, const void *engine_type, int options); +struct GPUMaterial *DRW_shader_find_from_world(struct World *wo, const void *engine_type, int options, bool no_deferred); +struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma, const void *engine_type, int options, bool no_deferred); struct GPUMaterial *DRW_shader_create_from_world( struct Scene *scene, struct World *wo, const void *engine_type, int options, - const char *vert, const char *geom, const char *frag_lib, const char *defines); + const char *vert, const char *geom, const char *frag_lib, const char *defines, bool no_deferred); struct GPUMaterial *DRW_shader_create_from_material( struct Scene *scene, struct Material *ma, const void *engine_type, int options, - const char *vert, const char *geom, const char *frag_lib, const char *defines); + const char *vert, const char *geom, const char *frag_lib, const char *defines, bool no_deferred); void DRW_shader_free(struct GPUShader *shader); #define DRW_SHADER_FREE_SAFE(shader) do { \ if (shader != NULL) { \ @@ -410,6 +410,7 @@ void DRW_pass_sort_shgroup_z(DRWPass *pass); /* Viewport */ typedef enum { + /* keep in sync with the union struct DRWMatrixState. */ DRW_MAT_PERS = 0, DRW_MAT_PERSINV, DRW_MAT_VIEW, @@ -421,7 +422,18 @@ typedef enum { } DRWViewportMatrixType; typedef struct DRWMatrixState { - float mat[DRW_MAT_COUNT][4][4]; + union { + float mat[DRW_MAT_COUNT][4][4]; + struct { + /* keep in sync with the enum DRWViewportMatrixType. */ + float persmat[4][4]; + float persinv[4][4]; + float viewmat[4][4]; + float viewinv[4][4]; + float winmat[4][4]; + float wininv[4][4]; + }; + }; } DRWMatrixState; void DRW_viewport_init(const bContext *C); @@ -454,6 +466,12 @@ void DRW_render_object_iter( void (*callback)(void *vedata, struct Object *ob, struct RenderEngine *engine, struct Depsgraph *depsgraph)); void DRW_render_instance_buffer_finish(void); +void DRW_custom_pipeline( + DrawEngineType *draw_engine_type, + struct Depsgraph *depsgraph, + void (*callback)(void *vedata, void *user_data), + void *user_data); + /* ViewLayers */ void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type); void **DRW_view_layer_engine_data_ensure_ex( diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 311a223dcdd..30f7742fd35 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1256,7 +1256,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx) /* XXX Really nasty locking. But else this could * be executed by the material previews thread * while rendering a viewport. */ - BLI_mutex_lock(&DST.gl_context_mutex); + BLI_ticket_mutex_lock(DST.gl_context_mutex); /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); @@ -1284,7 +1284,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx) drw_engines_disable(); - BLI_mutex_unlock(&DST.gl_context_mutex); + BLI_ticket_mutex_unlock(DST.gl_context_mutex); } } @@ -1554,14 +1554,10 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) /* Changing Context */ 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); + DRW_opengl_render_context_enable(re_gl_context); + /* We need to query gwn context after a gl context has been bound. */ 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. */ + DRW_gawain_render_context_enable(re_gwn_context); } else { DRW_opengl_context_enable(); @@ -1640,12 +1636,8 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) /* Changing Context */ 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); + DRW_gawain_render_context_disable(re_gwn_context); + DRW_opengl_render_context_disable(re_gl_context); } else { DRW_opengl_context_disable(); @@ -1671,6 +1663,56 @@ void DRW_render_object_iter( DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END } +/* Assume a valid gl context is bound (and that the gl_context_mutex has been aquired). + * This function only setup DST and execute the given function. + * Warning: similar to DRW_render_to_image you cannot use default lists (dfbl & dtxl). */ +void DRW_custom_pipeline( + DrawEngineType *draw_engine_type, + struct Depsgraph *depsgraph, + void (*callback)(void *vedata, void *user_data), + void *user_data) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + DST.options.is_image_render = true; + DST.options.is_scene_render = true; + DST.options.draw_background = false; + + DST.draw_ctx = (DRWContextState){ + .scene = scene, + .view_layer = view_layer, + .engine_type = NULL, + .depsgraph = depsgraph, + .object_mode = OB_MODE_OBJECT, + }; + drw_context_state_init(); + + DST.viewport = GPU_viewport_create(); + const int size[2] = {1, 1}; + GPU_viewport_size_set(DST.viewport, size); + + drw_viewport_var_init(); + + DRW_hair_init(); + + ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine_type); + + /* Execute the callback */ + callback(data, user_data); + DST.buffer_finish_called = false; + + GPU_viewport_free(DST.viewport); + GPU_framebuffer_restore(); + +#ifdef DEBUG + /* Avoid accidental reuse. */ + drw_state_ensure_not_reused(&DST); +#endif +} + static struct DRWSelectBuffer { struct GPUFrameBuffer *framebuffer; struct GPUTexture *texture_depth; @@ -2280,7 +2322,7 @@ void DRW_opengl_context_create(void) { BLI_assert(DST.gl_context == NULL); /* Ensure it's called once */ - BLI_mutex_init(&DST.gl_context_mutex); + DST.gl_context_mutex = BLI_ticket_mutex_alloc(); if (!G.background) { immDeactivate(); } @@ -2305,7 +2347,7 @@ void DRW_opengl_context_destroy(void) GWN_context_active_set(DST.gwn_context); GWN_context_discard(DST.gwn_context); WM_opengl_context_dispose(DST.gl_context); - BLI_mutex_end(&DST.gl_context_mutex); + BLI_ticket_mutex_free(DST.gl_context_mutex); } } @@ -2315,7 +2357,7 @@ void DRW_opengl_context_enable(void) /* IMPORTANT: We dont support immediate mode in render mode! * This shall remain in effect until immediate mode supports * multiple threads. */ - BLI_mutex_lock(&DST.gl_context_mutex); + BLI_ticket_mutex_lock(DST.gl_context_mutex); if (BLI_thread_is_main()) { if (!G.background) { immDeactivate(); @@ -2349,8 +2391,43 @@ void DRW_opengl_context_disable(void) GWN_context_active_set(NULL); } - BLI_mutex_unlock(&DST.gl_context_mutex); + BLI_ticket_mutex_unlock(DST.gl_context_mutex); } } +void DRW_opengl_render_context_enable(void *re_gl_context) +{ + /* If thread is main you should use DRW_opengl_context_enable(). */ + BLI_assert(!BLI_thread_is_main()); + + /* TODO get rid of the blocking. Only here because of the static global DST. */ + BLI_ticket_mutex_lock(DST.gl_context_mutex); + WM_opengl_context_activate(re_gl_context); +} + +void DRW_opengl_render_context_disable(void *re_gl_context) +{ + glFlush(); + WM_opengl_context_release(re_gl_context); + /* TODO get rid of the blocking. */ + BLI_ticket_mutex_unlock(DST.gl_context_mutex); +} + +/* Needs to be called AFTER DRW_opengl_render_context_enable() */ +void DRW_gawain_render_context_enable(void *re_gwn_context) +{ + /* If thread is main you should use DRW_opengl_context_enable(). */ + BLI_assert(!BLI_thread_is_main()); + + GWN_context_active_set(re_gwn_context); + DRW_shape_cache_reset(); /* XXX fix that too. */ +} + +/* Needs to be called BEFORE DRW_opengl_render_context_disable() */ +void DRW_gawain_render_context_disable(void *UNUSED(re_gwn_context)) +{ + DRW_shape_cache_reset(); /* XXX fix that too. */ + GWN_context_active_set(NULL); +} + /** \} */ diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 91a30fa45ae..6eae3459c2b 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -373,7 +373,7 @@ typedef struct DRWManager { * the top portion of the struct so DO NOT MOVE IT! */ void *gl_context; /* Unique ghost context used by the draw manager. */ Gwn_Context *gwn_context; - ThreadMutex gl_context_mutex; /* Mutex to lock the drw manager and avoid concurent context usage. */ + TicketMutex *gl_context_mutex; /* Mutex to lock the drw manager and avoid concurent context usage. */ /** GPU Resource State: Memory storage between drawing. */ struct { diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index 435c6c77e59..b0aec4a7600 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -154,10 +154,10 @@ static void drw_deferred_shader_compilation_free(void *custom_data) MEM_freeN(comp); } -static void drw_deferred_shader_add(GPUMaterial *mat) +static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) { /* Do not deferre the compilation if we are rendering for image. */ - if (DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION) { + if (DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION || !deferred) { /* Double checking that this GPUMaterial is not going to be * compiled by another thread. */ DRW_deferred_shader_remove(mat); @@ -308,10 +308,10 @@ GPUShader *DRW_shader_create_3D_depth_only(void) return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY); } -GPUMaterial *DRW_shader_find_from_world(World *wo, const void *engine_type, int options) +GPUMaterial *DRW_shader_find_from_world(World *wo, const void *engine_type, int options, bool deferred) { GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options); - if (DRW_state_is_image_render()) { + if (DRW_state_is_image_render() || !deferred) { if (mat != NULL && GPU_material_status(mat) == GPU_MAT_QUEUED) { /* XXX Hack : we return NULL so that the engine will call DRW_shader_create_from_XXX * with the shader code and we will resume the compilation from there. */ @@ -321,10 +321,10 @@ GPUMaterial *DRW_shader_find_from_world(World *wo, const void *engine_type, int return mat; } -GPUMaterial *DRW_shader_find_from_material(Material *ma, const void *engine_type, int options) +GPUMaterial *DRW_shader_find_from_material(Material *ma, const void *engine_type, int options, bool deferred) { GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options); - if (DRW_state_is_image_render()) { + if (DRW_state_is_image_render() || !deferred) { if (mat != NULL && GPU_material_status(mat) == GPU_MAT_QUEUED) { /* XXX Hack : we return NULL so that the engine will call DRW_shader_create_from_XXX * with the shader code and we will resume the compilation from there. */ @@ -336,7 +336,7 @@ GPUMaterial *DRW_shader_find_from_material(Material *ma, const void *engine_type GPUMaterial *DRW_shader_create_from_world( struct Scene *scene, World *wo, const void *engine_type, int options, - const char *vert, const char *geom, const char *frag_lib, const char *defines) + const char *vert, const char *geom, const char *frag_lib, const char *defines, bool deferred) { GPUMaterial *mat = NULL; if (DRW_state_is_image_render()) { @@ -350,7 +350,7 @@ GPUMaterial *DRW_shader_create_from_world( } if (GPU_material_status(mat) == GPU_MAT_QUEUED) { - drw_deferred_shader_add(mat); + drw_deferred_shader_add(mat, deferred); } return mat; @@ -358,7 +358,7 @@ GPUMaterial *DRW_shader_create_from_world( GPUMaterial *DRW_shader_create_from_material( struct Scene *scene, Material *ma, const void *engine_type, int options, - const char *vert, const char *geom, const char *frag_lib, const char *defines) + const char *vert, const char *geom, const char *frag_lib, const char *defines, bool deferred) { GPUMaterial *mat = NULL; if (DRW_state_is_image_render()) { @@ -372,7 +372,7 @@ GPUMaterial *DRW_shader_create_from_material( } if (GPU_material_status(mat) == GPU_MAT_QUEUED) { - drw_deferred_shader_add(mat); + drw_deferred_shader_add(mat, deferred); } return mat; |