Render Engines: fix crash when changing render engine during rendering
authorSergey Sharybin <sergey.vfx@gmail.com>
Tue, 13 Nov 2012 11:00:46 +0000 (11:00 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Tue, 13 Nov 2012 11:00:46 +0000 (11:00 +0000)
Crash would have been happen when changing render ending at the same time
rendering happens. It could be final Cycles render or even preview LUX render.

source/blender/render/extern/include/RE_engine.h
source/blender/render/intern/source/external_engine.c
source/blender/render/intern/source/pipeline.c

index 1331c287d7c4c6ea0497332bff611df08b471285..d2ffc3a0e26d326f3423fa064b153a567199a6d8 100644 (file)
@@ -60,6 +60,7 @@ struct Scene;
 #define RE_ENGINE_PREVIEW              2
 #define RE_ENGINE_DO_DRAW              4
 #define RE_ENGINE_DO_UPDATE            8
+#define RE_ENGINE_RENDERING            16
 
 extern ListBase R_engines;
 
index 8bdb805ada215059fcb4c9ccf53d204b81c24fe4..9053bc84bbc78c38bd4a354e062119a6969ec399 100644 (file)
@@ -316,6 +316,7 @@ int RE_engine_render(Render *re, int do_all)
 {
        RenderEngineType *type = RE_engines_find(re->r.engine);
        RenderEngine *engine;
+       int persistent_data = re->r.mode & R_PERSISTENT_DATA;
 
        /* verify if we can render */
        if (!type->render)
@@ -349,11 +350,17 @@ int RE_engine_render(Render *re, int do_all)
        re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0;
 
        /* render */
-       if (!re->engine)
-               re->engine = RE_engine_create(type);
-
        engine = re->engine;
 
+       if (!engine) {
+               engine = RE_engine_create(type);
+
+               if (persistent_data)
+                       re->engine = engine;
+       }
+
+       engine->flag |= RE_ENGINE_RENDERING;
+
        /* TODO: actually link to a parent which shouldn't happen */
        engine->re = re;
 
@@ -382,8 +389,13 @@ int RE_engine_render(Render *re, int do_all)
        if (type->render)
                type->render(engine, re->scene);
 
-       if (!(re->r.mode & R_PERSISTENT_DATA)) {
-               RE_engine_free(re->engine);
+       engine->tile_x = 0;
+       engine->tile_y = 0;
+       engine->flag &= ~RE_ENGINE_RENDERING;
+
+       /* re->engine becomes zero if user changed active render engine during render */
+       if (!persistent_data || !re->engine) {
+               RE_engine_free(engine);
                re->engine = NULL;
        }
 
@@ -393,8 +405,6 @@ int RE_engine_render(Render *re, int do_all)
                BLI_rw_mutex_unlock(&re->resultmutex);
        }
 
-       engine->tile_x = 0;
-       engine->tile_y = 0;
        freeparts(re);
 
        render_result_free_list(&engine->fullresult, engine->fullresult.first);
index 85cafa077596cb36950aa2e13114c7f663421ddf..f2549f04659d80ff8fdfc703f322c1365a8f8280 100644 (file)
@@ -432,7 +432,10 @@ void RE_FreePersistentData(void)
        /* render engines can be kept around for quick re-render, this clears all */
        for (re = RenderGlobal.renderlist.first; re; re = re->next) {
                if (re->engine) {
-                       RE_engine_free(re->engine);
+                       /* if engine is currently rendering, just tag it to be freed when render is finished */
+                       if (!(re->engine->flag & RE_ENGINE_RENDERING))
+                               RE_engine_free(re->engine);
+
                        re->engine = NULL;
                }
        }