Changeset View
Changeset View
Standalone View
Standalone View
source/blender/render/intern/source/pipeline.c
| Show First 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | |||||
| #include "BKE_report.h" | #include "BKE_report.h" | ||||
| #include "BKE_scene.h" | #include "BKE_scene.h" | ||||
| #include "BKE_sequencer.h" | #include "BKE_sequencer.h" | ||||
| #include "BKE_sound.h" | #include "BKE_sound.h" | ||||
| #include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */ | #include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */ | ||||
| #include "DEG_depsgraph.h" | #include "DEG_depsgraph.h" | ||||
| #include "DEG_depsgraph_build.h" | #include "DEG_depsgraph_build.h" | ||||
| #include "DEG_depsgraph_debug.h" | |||||
| #include "DEG_depsgraph_query.h" | #include "DEG_depsgraph_query.h" | ||||
| #include "PIL_time.h" | #include "PIL_time.h" | ||||
| #include "IMB_colormanagement.h" | #include "IMB_colormanagement.h" | ||||
| #include "IMB_imbuf.h" | #include "IMB_imbuf.h" | ||||
| #include "IMB_imbuf_types.h" | #include "IMB_imbuf_types.h" | ||||
| #include "IMB_metadata.h" | #include "IMB_metadata.h" | ||||
| ▲ Show 20 Lines • Show All 1,340 Lines • ▼ Show 20 Lines | for (re1 = RenderGlobal.renderlist.first; re1; re1 = re1->next) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| /* returns fully composited render-result on given time step (in RenderData) */ | /* returns fully composited render-result on given time step (in RenderData) */ | ||||
| static void do_render_composite(Render *re) | static void do_render_composite(Render *re) | ||||
| { | { | ||||
| bNodeTree *ntree = re->scene->nodetree; | bNodeTree *ntree = re->pipeline_scene_eval->nodetree; | ||||
| int update_newframe = 0; | int update_newframe = 0; | ||||
| if (composite_needs_render(re->scene, 1)) { | if (composite_needs_render(re->pipeline_scene_eval, 1)) { | ||||
| /* save memory... free all cached images */ | /* save memory... free all cached images */ | ||||
| ntreeFreeCache(ntree); | ntreeFreeCache(ntree); | ||||
| /* render the frames | /* render the frames | ||||
| * it could be optimized to render only the needed view | * it could be optimized to render only the needed view | ||||
| * but what if a scene has a different number of views | * but what if a scene has a different number of views | ||||
| * than the main scene? */ | * than the main scene? */ | ||||
| do_render(re); | do_render(re); | ||||
| Show All 21 Lines | if (re->r.scemode & R_SINGLE_LAYER) { | ||||
| BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); | BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); | ||||
| render_result_single_layer_end(re); | render_result_single_layer_end(re); | ||||
| BLI_rw_mutex_unlock(&re->resultmutex); | BLI_rw_mutex_unlock(&re->resultmutex); | ||||
| } | } | ||||
| if (!re->test_break(re->tbh)) { | if (!re->test_break(re->tbh)) { | ||||
| if (ntree) { | if (ntree) { | ||||
| ntreeCompositTagRender(re->scene); | ntreeCompositTagRender(re->pipeline_scene_eval); | ||||
| } | } | ||||
| if (ntree && re->scene->use_nodes && re->r.scemode & R_DOCOMP) { | if (ntree && re->scene->use_nodes && re->r.scemode & R_DOCOMP) { | ||||
| /* checks if there are render-result nodes that need scene */ | /* checks if there are render-result nodes that need scene */ | ||||
| if ((re->r.scemode & R_SINGLE_LAYER) == 0) { | if ((re->r.scemode & R_SINGLE_LAYER) == 0) { | ||||
| ntree_render_scenes(re); | ntree_render_scenes(re); | ||||
| } | } | ||||
| if (!re->test_break(re->tbh)) { | if (!re->test_break(re->tbh)) { | ||||
| ntree->stats_draw = render_composit_stats; | ntree->stats_draw = render_composit_stats; | ||||
| ntree->test_break = re->test_break; | ntree->test_break = re->test_break; | ||||
| ntree->progress = re->progress; | ntree->progress = re->progress; | ||||
| ntree->sdh = re; | ntree->sdh = re; | ||||
| ntree->tbh = re->tbh; | ntree->tbh = re->tbh; | ||||
| ntree->prh = re->prh; | ntree->prh = re->prh; | ||||
| if (update_newframe) { | if (update_newframe) { | ||||
| /* If we have consistent depsgraph now would be a time to update them. */ | /* If we have consistent depsgraph now would be a time to update them. */ | ||||
| } | } | ||||
| RenderView *rv; | RenderView *rv; | ||||
| for (rv = re->result->views.first; rv; rv = rv->next) { | for (rv = re->result->views.first; rv; rv = rv->next) { | ||||
| ntreeCompositExecTree(re->scene, | ntreeCompositExecTree(re->pipeline_scene_eval, | ||||
| ntree, | ntree, | ||||
| &re->r, | &re->r, | ||||
| true, | true, | ||||
| G.background == 0, | G.background == 0, | ||||
| &re->scene->view_settings, | &re->scene->view_settings, | ||||
| &re->scene->display_settings, | &re->scene->display_settings, | ||||
| rv->name); | rv->name); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | static void do_render_seq(Render *re) | ||||
| else { | else { | ||||
| re_x = re->result->rectx; | re_x = re->result->rectx; | ||||
| re_y = re->result->recty; | re_y = re->result->recty; | ||||
| } | } | ||||
| tot_views = BKE_scene_multiview_num_views_get(&re->r); | tot_views = BKE_scene_multiview_num_views_get(&re->r); | ||||
| ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs"); | ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs"); | ||||
| /* TODO(sergey): Currently depsgraph is only used to check whether it is an active | BKE_sequencer_new_render_data( | ||||
| * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet, | re->main, re->pipeline_depsgraph, re->scene, re_x, re_y, 100, true, &context); | ||||
| * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph | |||||
| * within tjhe render pipeline, somehow. | |||||
| */ | |||||
| BKE_sequencer_new_render_data(re->main, NULL, re->scene, re_x, re_y, 100, true, &context); | |||||
| /* the renderresult gets destroyed during the rendering, so we first collect all ibufs | /* the renderresult gets destroyed during the rendering, so we first collect all ibufs | ||||
| * and then we populate the final renderesult */ | * and then we populate the final renderesult */ | ||||
| for (view_id = 0; view_id < tot_views; view_id++) { | for (view_id = 0; view_id < tot_views; view_id++) { | ||||
| context.view_id = view_id; | context.view_id = view_id; | ||||
| out = BKE_sequencer_give_ibuf(&context, cfra, 0); | out = BKE_sequencer_give_ibuf(&context, cfra, 0); | ||||
| if (out) { | if (out) { | ||||
| ibuf_arr[view_id] = IMB_dupImBuf(out); | ibuf_arr[view_id] = IMB_dupImBuf(out); | ||||
| IMB_metadata_copy(ibuf_arr[view_id], out); | IMB_metadata_copy(ibuf_arr[view_id], out); | ||||
| IMB_freeImBuf(out); | IMB_freeImBuf(out); | ||||
| BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf_arr[view_id]); | BKE_sequencer_imbuf_from_sequencer_space(re->pipeline_scene_eval, ibuf_arr[view_id]); | ||||
| } | } | ||||
| else { | else { | ||||
| ibuf_arr[view_id] = NULL; | ibuf_arr[view_id] = NULL; | ||||
| } | } | ||||
| } | } | ||||
| rr = re->result; | rr = re->result; | ||||
| Show All 11 Lines | if (ibuf_arr[view_id]) { | ||||
| if (ibuf_arr[view_id]->metadata && (re->r.stamp & R_STAMP_STRIPMETA)) { | if (ibuf_arr[view_id]->metadata && (re->r.stamp & R_STAMP_STRIPMETA)) { | ||||
| /* ensure render stamp info first */ | /* ensure render stamp info first */ | ||||
| BKE_render_result_stamp_info(NULL, NULL, rr, true); | BKE_render_result_stamp_info(NULL, NULL, rr, true); | ||||
| BKE_stamp_info_from_imbuf(rr, ibuf_arr[view_id]); | BKE_stamp_info_from_imbuf(rr, ibuf_arr[view_id]); | ||||
| } | } | ||||
| if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */ | if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */ | ||||
| Editing *ed = re->scene->ed; | Editing *ed = re->pipeline_scene_eval->ed; | ||||
| if (ed) { | if (ed) { | ||||
| BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, true); | BKE_sequencer_free_imbuf(re->pipeline_scene_eval, &ed->seqbase, true); | ||||
| } | } | ||||
| } | } | ||||
| IMB_freeImBuf(ibuf_arr[view_id]); | IMB_freeImBuf(ibuf_arr[view_id]); | ||||
| } | } | ||||
| else { | else { | ||||
| /* render result is delivered empty in most cases, nevertheless we handle all cases */ | /* render result is delivered empty in most cases, nevertheless we handle all cases */ | ||||
| render_result_rect_fill_zero(rr, view_id); | render_result_rect_fill_zero(rr, view_id); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 411 Lines • ▼ Show 20 Lines | static int render_initialize_from_main(Render *re, | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| void RE_SetReports(Render *re, ReportList *reports) | void RE_SetReports(Render *re, ReportList *reports) | ||||
| { | { | ||||
| re->reports = reports; | re->reports = reports; | ||||
| } | } | ||||
| static void render_update_depsgraph(Render *re) | |||||
| { | |||||
| Scene *scene = re->scene; | |||||
| /* TODO(sergey): This doesn't run any callbacks and doesn't do sound update. But we can not use | |||||
| * BKE_scene_graph_update_for_newframe() because that one builds dependency graph for view layer | |||||
| * and not for the render pipeline. */ | |||||
| DEG_evaluate_on_framechange(re->main, re->pipeline_depsgraph, CFRA); | |||||
| } | |||||
| static void render_init_depsgraph(Render *re) | |||||
| { | |||||
| Scene *scene = re->scene; | |||||
| ViewLayer *view_layer = BKE_view_layer_default_render(re->scene); | |||||
| re->pipeline_depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER); | |||||
| DEG_debug_name_set(re->pipeline_depsgraph, "RENDER PIPELINE"); | |||||
| /* Make sure there is a correct evaluated scene pointer. */ | |||||
| DEG_graph_build_for_render_pipeline(re->pipeline_depsgraph, re->main, scene, view_layer); | |||||
| /* Update immediately so we have proper evaluated scene. */ | |||||
| render_update_depsgraph(re); | |||||
| re->pipeline_scene_eval = DEG_get_evaluated_scene(re->pipeline_depsgraph); | |||||
| } | |||||
| /* general Blender frame render call */ | /* general Blender frame render call */ | ||||
| void RE_RenderFrame(Render *re, | void RE_RenderFrame(Render *re, | ||||
| Main *bmain, | Main *bmain, | ||||
| Scene *scene, | Scene *scene, | ||||
| ViewLayer *single_layer, | ViewLayer *single_layer, | ||||
| Object *camera_override, | Object *camera_override, | ||||
| int frame, | int frame, | ||||
| const bool write_still) | const bool write_still) | ||||
| { | { | ||||
| BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT); | BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT); | ||||
| /* Ugly global still... | /* Ugly global still... | ||||
| * is to prevent preview events and signal subsurfs etc to make full resol. */ | * is to prevent preview events and signal subsurfs etc to make full resol. */ | ||||
| G.is_rendering = true; | G.is_rendering = true; | ||||
| scene->r.cfra = frame; | scene->r.cfra = frame; | ||||
| if (render_initialize_from_main( | if (render_initialize_from_main( | ||||
| re, &scene->r, bmain, scene, single_layer, camera_override, 0, 0)) { | re, &scene->r, bmain, scene, single_layer, camera_override, 0, 0)) { | ||||
| const RenderData rd = scene->r; | const RenderData rd = scene->r; | ||||
| MEM_reset_peak_memory(); | MEM_reset_peak_memory(); | ||||
| render_init_depsgraph(re); | |||||
| BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE); | BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE); | ||||
| do_render_all_options(re); | do_render_all_options(re); | ||||
| if (write_still && !G.is_break) { | if (write_still && !G.is_break) { | ||||
| if (BKE_imtype_is_movie(rd.im_format.imtype)) { | if (BKE_imtype_is_movie(rd.im_format.imtype)) { | ||||
| /* operator checks this but in case its called from elsewhere */ | /* operator checks this but in case its called from elsewhere */ | ||||
| printf("Error: cant write single images with a movie format!\n"); | printf("Error: cant write single images with a movie format!\n"); | ||||
| ▲ Show 20 Lines • Show All 381 Lines • ▼ Show 20 Lines | void RE_RenderAnim(Render *re, | ||||
| BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT); | BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT); | ||||
| /* do not fully call for each frame, it initializes & pops output window */ | /* do not fully call for each frame, it initializes & pops output window */ | ||||
| if (!render_initialize_from_main(re, &rd, bmain, scene, single_layer, camera_override, 0, 1)) { | if (!render_initialize_from_main(re, &rd, bmain, scene, single_layer, camera_override, 0, 1)) { | ||||
| return; | return; | ||||
| } | } | ||||
| render_init_depsgraph(re); | |||||
| if (is_movie) { | if (is_movie) { | ||||
| size_t width, height; | size_t width, height; | ||||
| int i; | int i; | ||||
| bool is_error = false; | bool is_error = false; | ||||
| get_videos_dimensions(re, &rd, &width, &height); | get_videos_dimensions(re, &rd, &width, &height); | ||||
| mh = BKE_movie_handle_get(rd.im_format.imtype); | mh = BKE_movie_handle_get(rd.im_format.imtype); | ||||
| ▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | for (nfra = sfra, scene->r.cfra = sfra; scene->r.cfra <= efra; scene->r.cfra++) { | ||||
| /* TODO(sergey): Currently depsgraph is only used to check whether it is an active | /* TODO(sergey): Currently depsgraph is only used to check whether it is an active | ||||
| * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet, | * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet, | ||||
| * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph | * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph | ||||
| * within tjhe render pipeline, somehow. | * within tjhe render pipeline, somehow. | ||||
| */ | */ | ||||
| BKE_animsys_evaluate_animdata(NULL, scene, &scene->id, adt, ctime, ADT_RECALC_ALL); | BKE_animsys_evaluate_animdata(NULL, scene, &scene->id, adt, ctime, ADT_RECALC_ALL); | ||||
| } | } | ||||
| render_update_depsgraph(re); | |||||
| /* only border now, todo: camera lens. (ton) */ | /* only border now, todo: camera lens. (ton) */ | ||||
| render_initialize_from_main(re, &rd, bmain, scene, single_layer, camera_override, 1, 0); | render_initialize_from_main(re, &rd, bmain, scene, single_layer, camera_override, 1, 0); | ||||
| if (nfra != scene->r.cfra) { | if (nfra != scene->r.cfra) { | ||||
| /* Skip this frame, but could update for physics and particles system. */ | /* Skip this frame, but could update for physics and particles system. */ | ||||
| continue; | continue; | ||||
| } | } | ||||
| else { | else { | ||||
| ▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | void RE_PreviewRender(Render *re, Main *bmain, Scene *sce) | ||||
| do_render_3d(re); | do_render_3d(re); | ||||
| } | } | ||||
| void RE_CleanAfterRender(Render *re) | void RE_CleanAfterRender(Render *re) | ||||
| { | { | ||||
| /* Destroy the opengl context in the correct thread. */ | /* Destroy the opengl context in the correct thread. */ | ||||
| RE_gl_context_destroy(re); | RE_gl_context_destroy(re); | ||||
| if (re->pipeline_depsgraph != NULL) { | |||||
| DEG_graph_free(re->pipeline_depsgraph); | |||||
| } | |||||
| re->pipeline_depsgraph = NULL; | |||||
| re->pipeline_scene_eval = NULL; | |||||
| } | } | ||||
| /* note; repeated win/disprect calc... solve that nicer, also in compo */ | /* note; repeated win/disprect calc... solve that nicer, also in compo */ | ||||
| /* only the temp file! */ | /* only the temp file! */ | ||||
| bool RE_ReadRenderResult(Scene *scene, Scene *scenode) | bool RE_ReadRenderResult(Scene *scene, Scene *scenode) | ||||
| { | { | ||||
| Render *re; | Render *re; | ||||
| ▲ Show 20 Lines • Show All 233 Lines • Show Last 20 Lines | |||||