Commit: 4c3be0bf52292add5cdf23be5f4affb76f1b747d
Author: Brecht Van Lommel
Date:   Fri Mar 1 19:09:17 2019 +0100
Branches: blender2.7
https://developer.blender.org/rB4c3be0bf52292add5cdf23be5f4affb76f1b747d

Fix T62073: Cycles random hangs rendering with Save Buffers on.

===================================================================

M       source/blender/nodes/composite/nodes/node_composite_image.c
M       source/blender/render/extern/include/RE_engine.h
M       source/blender/render/intern/source/external_engine.c
M       source/blender/render/intern/source/render_result.c

===================================================================

diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c 
b/source/blender/nodes/composite/nodes/node_composite_image.c
index e22f685461b..4d0e63a7fdc 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -205,7 +205,7 @@ void node_cmp_rlayers_register_pass(bNodeTree *ntree, bNode 
*node, Scene *scene,
        }
 }
 
-static void cmp_node_rlayer_create_outputs_cb(RenderEngine *UNUSED(engine), 
Scene *scene, SceneRenderLayer *srl,
+static void cmp_node_rlayer_create_outputs_cb(void *UNUSED(userdata), Scene 
*scene, SceneRenderLayer *srl,
                                               const char *name, int 
UNUSED(channels), const char *UNUSED(chanid), int type)
 {
        /* Register the pass in all scenes that have a render layer node for 
this layer.
@@ -235,7 +235,7 @@ static void cmp_node_rlayer_create_outputs(bNodeTree 
*ntree, bNode *node, LinkNo
                                node->storage = data;
 
                                RenderEngine *engine = 
RE_engine_create(engine_type);
-                               RE_engine_update_render_passes(engine, scene, 
srl, cmp_node_rlayer_create_outputs_cb);
+                               RE_engine_update_render_passes(engine, scene, 
srl, cmp_node_rlayer_create_outputs_cb, NULL);
                                RE_engine_free(engine);
 
                                MEM_freeN(data);
diff --git a/source/blender/render/extern/include/RE_engine.h 
b/source/blender/render/extern/include/RE_engine.h
index e83d772eb6a..a4ec7ec6aa1 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -96,7 +96,7 @@ typedef struct RenderEngineType {
        ExtensionRNA ext;
 } RenderEngineType;
 
-typedef void (*update_render_passes_cb_t)(struct RenderEngine *engine, struct 
Scene *scene, struct SceneRenderLayer *srl,
+typedef void (*update_render_passes_cb_t)(void *userdata, struct Scene *scene, 
struct SceneRenderLayer *srl,
                                           const char *name, int channels, 
const char *chanid, int type);
 
 typedef struct RenderEngine {
@@ -125,6 +125,7 @@ typedef struct RenderEngine {
        /* callback for render pass query */
        ThreadMutex update_render_passes_mutex;
        update_render_passes_cb_t update_render_passes_cb;
+       void *update_render_passes_data;
 
        rctf last_viewplane;
        rcti last_disprect;
@@ -165,7 +166,7 @@ bool RE_engine_is_external(struct Render *re);
 void RE_engine_frame_set(struct RenderEngine *engine, int frame, float 
subframe);
 
 void RE_engine_update_render_passes(struct RenderEngine *engine, struct Scene 
*scene, struct SceneRenderLayer *srl,
-                                    update_render_passes_cb_t callback);
+                                    update_render_passes_cb_t callback, void 
*callback_data);
 void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, 
struct SceneRenderLayer *srl,
                              const char *name, int channels, const char 
*chanid, int type);
 
diff --git a/source/blender/render/intern/source/external_engine.c 
b/source/blender/render/intern/source/external_engine.c
index 86c8156e768..8401eae0e24 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -742,10 +742,7 @@ int RE_engine_render(Render *re, int do_all)
        BLI_rw_mutex_lock(&re->partsmutex, THREAD_LOCK_WRITE);
 
        if (re->result->do_exr_tile) {
-               BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
-               render_result_save_empty_result_tiles(re);
                render_result_exr_file_end(re, engine);
-               BLI_rw_mutex_unlock(&re->resultmutex);
        }
 
        /* re->engine becomes zero if user changed active render engine during 
render */
@@ -775,7 +772,7 @@ int RE_engine_render(Render *re, int do_all)
 }
 
 void RE_engine_update_render_passes(struct RenderEngine *engine, struct Scene 
*scene, struct SceneRenderLayer *srl,
-                                    update_render_passes_cb_t callback)
+                                    update_render_passes_cb_t callback, void 
*callback_data)
 {
        if (!(scene && srl && engine && callback && 
engine->type->update_render_passes)) {
                return;
@@ -784,7 +781,10 @@ void RE_engine_update_render_passes(struct RenderEngine 
*engine, struct Scene *s
        BLI_mutex_lock(&engine->update_render_passes_mutex);
 
        engine->update_render_passes_cb = callback;
+       engine->update_render_passes_data = callback_data;
        engine->type->update_render_passes(engine, scene, srl);
+       engine->update_render_passes_cb = NULL;
+       engine->update_render_passes_data = NULL;
 
        BLI_mutex_unlock(&engine->update_render_passes_mutex);
 }
@@ -796,5 +796,5 @@ void RE_engine_register_pass(struct RenderEngine *engine, 
struct Scene *scene, s
                return;
        }
 
-       engine->update_render_passes_cb(engine, scene, srl, name, channels, 
chanid, type);
+       engine->update_render_passes_cb(engine->update_render_passes_data, 
scene, srl, name, channels, chanid, type);
 }
diff --git a/source/blender/render/intern/source/render_result.c 
b/source/blender/render/intern/source/render_result.c
index 822c996c504..24430df31d6 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -1108,19 +1108,29 @@ void render_result_save_empty_result_tiles(Render *re)
        }
 }
 
-static void render_result_register_pass_cb(RenderEngine *engine, Scene 
*UNUSED(scene), SceneRenderLayer *srl,
-                                           const char *name, int channels, 
const char *chanid, int UNUSED(type))
+/* Compute list of passes needed by render engine. */
+static void templates_register_pass_cb(void *userdata, Scene *UNUSED(scene), 
SceneRenderLayer *UNUSED(srl),
+                                       const char *name, int channels, const 
char *chan_id, int UNUSED(type))
 {
-       RE_engine_add_pass(engine, name, channels, chanid, srl->name);
+       ListBase *templates = userdata;
+       RenderPass *pass = MEM_callocN(sizeof(RenderPass), 
"RenderPassTemplate");
+
+       pass->channels = channels;
+       BLI_strncpy(pass->name, name, sizeof(pass->name));
+       BLI_strncpy(pass->chan_id, chan_id, sizeof(pass->chan_id));
+
+       BLI_addtail(templates, pass);
 }
 
-static void render_result_create_all_passes(RenderEngine *engine, Render *re, 
RenderLayer *rl)
+static void render_result_get_pass_templates(RenderEngine *engine, Render *re, 
RenderLayer *rl, ListBase *templates)
 {
+       BLI_listbase_clear(templates);
+
        if (engine && engine->type->update_render_passes) {
                SceneRenderLayer *srl;
                srl = BLI_findstring(&re->r.layers, rl->name, 
offsetof(SceneRenderLayer, name));
                if (srl) {
-                       RE_engine_update_render_passes(engine, re->scene, srl, 
render_result_register_pass_cb);
+                       RE_engine_update_render_passes(engine, re->scene, srl, 
templates_register_pass_cb, templates);
                }
        }
 }
@@ -1128,14 +1138,27 @@ static void 
render_result_create_all_passes(RenderEngine *engine, Render *re, Re
 /* begin write of exr tile file */
 void render_result_exr_file_begin(Render *re, RenderEngine *engine)
 {
-       RenderResult *rr;
-       RenderLayer *rl;
        char str[FILE_MAX];
 
-       for (rr = re->result; rr; rr = rr->next) {
-               for (rl = rr->layers.first; rl; rl = rl->next) {
-                       render_result_create_all_passes(engine, re, rl);
+       for (RenderResult *rr = re->result; rr; rr = rr->next) {
+               for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next) {
+                       /* Get passes needed by engine. Normally we would wait 
for the
+                        * engine to create them, but for EXR file we need to 
know in
+                        * advance. */
+                       ListBase templates;
+                       render_result_get_pass_templates(engine, re, rl, 
&templates);
+
+                       /* Create render passes requested by engine. Only this 
part is
+                        * mutex locked to avoid deadlock with Python GIL. */
+                       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+                       for (RenderPass *pass = templates.first; pass; pass = 
pass->next) {
+                               render_result_add_pass(re->result, pass->name, 
pass->channels, pass->chan_id, rl->name, NULL);
+                       }
+                       BLI_rw_mutex_unlock(&re->resultmutex);
+
+                       BLI_freelistN(&templates);
 
+                       /* Open EXR file for writing. */
                        render_result_exr_file_path(re->scene, rl->name, 
rr->sample_nr, str);
                        printf("write exr tmp file, %dx%d, %s\n", rr->rectx, 
rr->recty, str);
                        IMB_exrtile_begin_write(rl->exrhandle, str, 0, 
rr->rectx, rr->recty, re->partx, re->party);
@@ -1146,11 +1169,9 @@ void render_result_exr_file_begin(Render *re, 
RenderEngine *engine)
 /* end write of exr tile file, read back first sample */
 void render_result_exr_file_end(Render *re, RenderEngine *engine)
 {
-       RenderResult *rr;
-       RenderLayer *rl;
-
-       for (rr = re->result; rr; rr = rr->next) {
-               for (rl = rr->layers.first; rl; rl = rl->next) {
+       /* Close EXR files. */
+       for (RenderResult *rr = re->result; rr; rr = rr->next) {
+               for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next) {
                        IMB_exr_close(rl->exrhandle);
                        rl->exrhandle = NULL;
                }
@@ -1158,10 +1179,36 @@ void render_result_exr_file_end(Render *re, 
RenderEngine *engine)
                rr->do_exr_tile = false;
        }
 
+       /* Create new render result in memory instead of on disk. */
+       BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
        render_result_free_list(&re->fullresult, re->result);
-       re->result = NULL;
+       re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, 
RR_ALL_LAYERS, RR_ALL_VIEWS);
+       BLI_rw_mutex_unlock(&re->resultmutex);
+
+       for (RenderLayer *rl = re->result->layers.first; rl; rl = rl->next) {
+               /* Get passes needed by engine. */
+               ListBase templates;
+               render_result_get_pass_templates(engine, re, rl, &templates);
+
+               /* Create render passes requested by engine. Only this part is
+                * mutex locked to avoid deadlock with Python GIL. */
+               BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
+               for (RenderPass *pass = templates.first; pass; pass = 
pass->next) {
+                       render_result_add_pass(re->result, pass->name, 
pass->channels, pass->chan_id, rl->name, NULL);
+               }
+
+               BLI_freelistN(&templates);
 
-       render_result_exr_file_read_sample(re, 0, engine);
+               /* Render passes contents from file. */
+               char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = "";
+               render_result_exr_file_path(re->scene, rl->name, 0, str);
+               printf("read exr tmp file: %s\n", str);
+
+               if (!render_result_exr_file_read_path(re->result, rl, str)) {
+                       printf("cannot read: %s\n", str);
+       

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to