diff options
6 files changed, 78 insertions, 57 deletions
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index 6c0257b10a0..56ec5ad0df9 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -389,9 +389,9 @@ if(WITH_OPENMP) message(STATUS "Using ${LIBDIR}/openmp for OpenMP") set(OPENMP_CUSTOM ON) set(OPENMP_FOUND ON) - set(OpenMP_C_FLAGS "-Xclang -fopenmp -I${LIBDIR}/openmp/include") - set(OpenMP_CXX_FLAGS "-Xclang -fopenmp -I${LIBDIR}/openmp/include") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${LIBDIR}/openmp/lib -lomp") + set(OpenMP_C_FLAGS "-Xclang -fopenmp -I\"${LIBDIR}/openmp/include\"") + set(OpenMP_CXX_FLAGS "-Xclang -fopenmp -I\"${LIBDIR}/openmp/include\"") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L\"${LIBDIR}/openmp/lib\" -lomp") # Copy libomp.dylib to allow executables like datatoc to work. if(CMAKE_MAKE_PROGRAM MATCHES "xcodebuild") diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 870cb5554a0..8c0a277668f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -206,7 +206,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, ViewLayer *view_layer, +static void cmp_node_rlayer_create_outputs_cb(void *UNUSED(userdata), Scene *scene, ViewLayer *view_layer, 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. @@ -238,7 +238,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, view_layer, cmp_node_rlayer_create_outputs_cb); + RE_engine_update_render_passes(engine, scene, view_layer, 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 9e0ac0087ee..cdd696e56bb 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -100,7 +100,7 @@ typedef struct RenderEngineType { ExtensionRNA ext; } RenderEngineType; -typedef void (*update_render_passes_cb_t)(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer, +typedef void (*update_render_passes_cb_t)(void *userdata, struct Scene *scene, struct ViewLayer *view_layer, const char *name, int channels, const char *chanid, int type); typedef struct RenderEngine { @@ -128,6 +128,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; @@ -168,7 +169,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 ViewLayer *view_layer, - 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 ViewLayer *view_layer, const char *name, int channels, const char *chanid, int type); diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index 687927027f0..d7636a150ef 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -85,7 +85,6 @@ struct RenderPass *gp_add_pass(struct RenderResult *rr, struct RenderLayer *rl, void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart, const char *viewname); void render_result_exr_file_path(struct Scene *scene, const char *layname, int sample, char *filepath); -int render_result_exr_file_read_sample(struct Render *re, int sample, struct RenderEngine *engine); int render_result_exr_file_read_path(struct RenderResult *rr, struct RenderLayer *rl_single, const char *filepath); /* EXR cache */ diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index f437ec90db9..153d41627c9 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -762,10 +762,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 */ @@ -795,7 +792,7 @@ int RE_engine_render(Render *re, int do_all) } void RE_engine_update_render_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer, - update_render_passes_cb_t callback) + update_render_passes_cb_t callback, void *callback_data) { if (!(scene && view_layer && engine && callback && engine->type->update_render_passes)) { return; @@ -804,7 +801,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, view_layer); + engine->update_render_passes_cb = NULL; + engine->update_render_passes_data = NULL; BLI_mutex_unlock(&engine->update_render_passes_mutex); } @@ -816,7 +816,7 @@ void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, s return; } - engine->update_render_passes_cb(engine, scene, view_layer, name, channels, chanid, type); + engine->update_render_passes_cb(engine->update_render_passes_data, scene, view_layer, name, channels, chanid, type); } void RE_engine_free_blender_memory(RenderEngine *engine) diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 4809c643522..6e0eaa68b82 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -1058,19 +1058,28 @@ void render_result_save_empty_result_tiles(Render *re) } } -static void render_result_register_pass_cb(RenderEngine *engine, Scene *UNUSED(scene), ViewLayer *view_layer, - 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), ViewLayer *UNUSED(view_layer), + const char *name, int channels, const char *chan_id, int UNUSED(type)) { - RE_engine_add_pass(engine, name, channels, chanid, view_layer->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) { - ViewLayer *view_layer; - view_layer = BLI_findstring(&re->view_layers, rl->name, offsetof(ViewLayer, name)); + ViewLayer *view_layer = BLI_findstring(&re->view_layers, rl->name, offsetof(ViewLayer, name)); if (view_layer) { - RE_engine_update_render_passes(engine, re->scene, view_layer, render_result_register_pass_cb); + RE_engine_update_render_passes(engine, re->scene, view_layer, templates_register_pass_cb, templates); } } } @@ -1078,14 +1087,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); @@ -1096,11 +1118,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; } @@ -1108,10 +1128,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); + } + BLI_rw_mutex_unlock(&re->resultmutex); + } } /* save part into exr file */ @@ -1140,31 +1186,6 @@ void render_result_exr_file_path(Scene *scene, const char *layname, int sample, BLI_make_file_string("/", filepath, BKE_tempdir_session(), name); } -/* only for temp buffer, makes exact copy of render result */ -int render_result_exr_file_read_sample(Render *re, int sample, RenderEngine *engine) -{ - RenderLayer *rl; - char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = ""; - bool success = true; - - RE_FreeRenderResult(re->result); - re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); - - for (rl = re->result->layers.first; rl; rl = rl->next) { - render_result_create_all_passes(engine, re, rl); - - render_result_exr_file_path(re->scene, rl->name, sample, 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); - success = false; - } - } - - return success; -} - /* called for reading temp files, and for external engines */ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, const char *filepath) { |