Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/editors/render/render_opengl.c153
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h2
-rw-r--r--source/blender/render/intern/source/render_result.c81
3 files changed, 210 insertions, 26 deletions
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 46353ec4a44..ee2772ce31a 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -40,6 +40,7 @@
#include "BLI_utildefines.h"
#include "BLI_jitter.h"
#include "BLI_threads.h"
+#include "BLI_task.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -130,6 +131,10 @@ typedef struct OGLRender {
wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/
void **movie_ctx_arr;
+ TaskPool *task_pool;
+ bool pool_ok;
+ SpinLock reports_lock;
+
#ifdef DEBUG_TIME
double time_start;
#endif
@@ -685,6 +690,24 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
oglrender->mh = NULL;
oglrender->movie_ctx_arr = NULL;
+ if (is_animation) {
+ TaskScheduler *task_scheduler = BLI_task_scheduler_get();
+ if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ oglrender->task_pool = BLI_task_pool_create_background(task_scheduler,
+ oglrender);
+ BLI_pool_set_num_threads(oglrender->task_pool, 1);
+ }
+ else {
+ oglrender->task_pool = BLI_task_pool_create(task_scheduler,
+ oglrender);
+ }
+ }
+ else {
+ oglrender->task_pool = NULL;
+ }
+ oglrender->pool_ok = true;
+ BLI_spin_init(&oglrender->reports_lock);
+
#ifdef DEBUG_TIME
oglrender->time_start = PIL_check_seconds_timer();
#endif
@@ -698,6 +721,10 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
Scene *scene = oglrender->scene;
int i;
+ BLI_task_pool_work_and_wait(oglrender->task_pool);
+ BLI_task_pool_free(oglrender->task_pool);
+ BLI_spin_end(&oglrender->reports_lock);
+
#ifdef DEBUG_TIME
printf("Total render time: %f\n", PIL_check_seconds_timer() - oglrender->time_start);
#endif
@@ -796,6 +823,102 @@ static bool screen_opengl_render_anim_initialize(bContext *C, wmOperator *op)
return true;
}
+typedef struct WriteTaskData {
+ RenderResult *rr;
+ int cfra;
+} WriteTaskData;
+
+static void write_result_func(TaskPool * __restrict pool,
+ void *task_data_v,
+ int UNUSED(thread_id))
+{
+ OGLRender *oglrender = (OGLRender *) BLI_task_pool_userdata(pool);
+ WriteTaskData *task_data = (WriteTaskData *) task_data_v;
+ Scene *scene = oglrender->scene;
+ RenderResult *rr = task_data->rr;
+ const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
+ const int cfra = task_data->cfra;
+ bool ok;
+ /* Construct local thread0safe copy of reports structure which we can
+ * safely pass to the underlying functions.
+ */
+ ReportList reports;
+ BKE_reports_init(&reports, oglrender->reports->flag & ~RPT_PRINT);
+ /* Do actual save logic here, depending on the file format. */
+ if (is_movie) {
+ /* We have to construct temporary scene with proper scene->r.cfra.
+ * This is because underlying calls do not use r.cfra but use scene
+ * for that.
+ */
+ Scene tmp_scene = *scene;
+ tmp_scene.r.cfra = cfra;
+ ok = RE_WriteRenderViewsMovie(&reports,
+ rr,
+ &tmp_scene,
+ &tmp_scene.r,
+ oglrender->mh,
+ oglrender->movie_ctx_arr,
+ oglrender->totvideos,
+ PRVRANGEON != 0);
+ }
+ else {
+ /* TODO(sergey): We can in theory save some CPU ticks here because we
+ * calculate file name again here.
+ */
+ char name[FILE_MAX];
+ BKE_image_path_from_imformat(name,
+ scene->r.pic,
+ oglrender->bmain->name,
+ cfra,
+ &scene->r.im_format,
+ (scene->r.scemode & R_EXTENSION) != 0,
+ true,
+ NULL);
+
+ BKE_render_result_stamp_info(scene, scene->camera, rr, false);
+ ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name);
+ if (!ok) {
+ BKE_reportf(&reports,
+ RPT_ERROR,
+ "Write error: cannot save %s",
+ name);
+ }
+ }
+ if (reports.list.first != NULL) {
+ BLI_spin_lock(&oglrender->reports_lock);
+ for (Report *report = reports.list.first;
+ report != NULL;
+ report = report->next)
+ {
+ BKE_report(oglrender->reports,
+ report->type,
+ report->message);
+ }
+ BLI_spin_unlock(&oglrender->reports_lock);
+ }
+ if (!ok) {
+ oglrender->pool_ok = false;
+ }
+ RE_FreeRenderResult(rr);
+}
+
+static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr)
+{
+ if (!oglrender->pool_ok) {
+ return false;
+ }
+ Scene *scene = oglrender->scene;
+ WriteTaskData *task_data = MEM_mallocN(sizeof(WriteTaskData), "write task data");
+ task_data->rr = rr;
+ task_data->cfra = scene->r.cfra;
+ BLI_task_pool_push(oglrender->task_pool,
+ write_result_func,
+ task_data,
+ true,
+ TASK_PRIORITY_LOW);
+ return true;
+}
+
static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -828,7 +951,9 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
&scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL);
if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
+ BLI_spin_lock(&oglrender->reports_lock);
BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name);
+ BLI_spin_unlock(&oglrender->reports_lock);
ok = true;
goto finally;
}
@@ -856,34 +981,10 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
/* save to disk */
rr = RE_AcquireResultRead(oglrender->re);
-
- if (is_movie) {
- ok = RE_WriteRenderViewsMovie(oglrender->reports, rr, scene, &scene->r, oglrender->mh,
- oglrender->movie_ctx_arr, oglrender->totvideos, PRVRANGEON != 0);
- if (ok) {
- printf("Append frame %d", scene->r.cfra);
- BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra);
- }
- }
- else {
- BKE_render_result_stamp_info(scene, scene->camera, rr, false);
- ok = RE_WriteRenderViewsImage(op->reports, rr, scene, true, name);
- if (ok) {
- printf("Saved: %s", name);
- BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name);
- }
- else {
- printf("Write error: cannot save %s\n", name);
- BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name);
- }
- }
-
+ RenderResult *new_rr = RE_DuplicateRenderResult(rr);
RE_ReleaseResult(oglrender->re);
-
- /* movie stats prints have no line break */
- printf("\n");
-
+ ok = schedule_write_result(oglrender, new_rr);
finally: /* Step the frame and bail early if needed */
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 3a99be706bf..7021477a702 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -391,6 +391,8 @@ bool RE_RenderResult_is_stereo(RenderResult *res);
struct RenderView *RE_RenderViewGetById(struct RenderResult *res, const int view_id);
struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char *viewname);
+RenderResult *RE_DuplicateRenderResult(RenderResult *rr);
+
/******* Debug pass helper functions *********/
#ifdef WITH_CYCLES_DEBUG
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 6ea46af6f7e..e3fc8174bd6 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -1665,3 +1665,84 @@ RenderView *RE_RenderViewGetByName(RenderResult *res, const char *viewname)
BLI_assert(res->views.first);
return rv ? rv : res->views.first;
}
+
+static RenderPass *duplicate_render_pass(RenderPass *rpass)
+{
+ RenderPass *new_rpass = MEM_mallocN(sizeof(RenderPass), "new render pass");
+ *new_rpass = *rpass;
+ new_rpass->next = new_rpass->prev = NULL;
+ if (new_rpass->rect != NULL) {
+ new_rpass->rect = MEM_dupallocN(new_rpass->rect);
+ }
+ return new_rpass;
+}
+
+static RenderLayer *duplicate_render_layer(RenderLayer *rl)
+{
+ RenderLayer *new_rl = MEM_mallocN(sizeof(RenderLayer), "new render layer");
+ *new_rl = *rl;
+ new_rl->next = new_rl->prev = NULL;
+ new_rl->passes.first = new_rl->passes.last = NULL;
+ new_rl->exrhandle = NULL;
+ if (new_rl->acolrect != NULL) {
+ new_rl->acolrect = MEM_dupallocN(new_rl->acolrect);
+ }
+ if (new_rl->scolrect != NULL) {
+ new_rl->scolrect = MEM_dupallocN(new_rl->scolrect);
+ }
+ if (new_rl->display_buffer != NULL) {
+ new_rl->display_buffer = MEM_dupallocN(new_rl->display_buffer);
+ }
+ for (RenderPass *rpass = rl->passes.first; rpass != NULL; rpass = rpass->next) {
+ RenderPass *new_rpass = duplicate_render_pass(rpass);
+ BLI_addtail(&new_rl->passes, new_rpass);
+ }
+ return new_rl;
+}
+
+static RenderView *duplicate_render_view(RenderView *rview)
+{
+ RenderView *new_rview = MEM_mallocN(sizeof(RenderView), "new render view");
+ *new_rview = *rview;
+ if (new_rview->rectf != NULL) {
+ new_rview->rectf = MEM_dupallocN(new_rview->rectf);
+ }
+ if (new_rview->rectf != NULL) {
+ new_rview->rectf = MEM_dupallocN(new_rview->rectf);
+ }
+ if (new_rview->rectz != NULL) {
+ new_rview->rectz = MEM_dupallocN(new_rview->rectz);
+ }
+ if (new_rview->rect32 != NULL) {
+ new_rview->rect32 = MEM_dupallocN(new_rview->rect32);
+ }
+ return new_rview;
+}
+
+RenderResult *RE_DuplicateRenderResult(RenderResult *rr)
+{
+ RenderResult *new_rr = MEM_mallocN(sizeof(RenderResult), "new render result");
+ *new_rr = *rr;
+ new_rr->next = new_rr->prev = NULL;
+ new_rr->layers.first = new_rr->layers.last = NULL;
+ new_rr->views.first = new_rr->views.last = NULL;
+ for (RenderLayer *rl = rr->layers.first; rl != NULL; rl = rl->next) {
+ RenderLayer *new_rl = duplicate_render_layer(rl);
+ BLI_addtail(&new_rr->layers, new_rl);
+ }
+ for (RenderView *rview = rr->views.first; rview != NULL; rview = rview->next) {
+ RenderView *new_rview = duplicate_render_view(rview);
+ BLI_addtail(&new_rr->views, new_rview);
+ }
+ if (new_rr->rect32 != NULL) {
+ new_rr->rect32 = MEM_dupallocN(new_rr->rect32);
+ }
+ if (new_rr->rectf != NULL) {
+ new_rr->rectf = MEM_dupallocN(new_rr->rectf);
+ }
+ if (new_rr->rectz != NULL) {
+ new_rr->rectz = MEM_dupallocN(new_rr->rectz);
+ }
+ new_rr->stamp_data = MEM_dupallocN(new_rr->stamp_data);
+ return new_rr;
+}