OpenGL render: Limit number of scheduled frames for write

Previously if the rendering is much faster than saving (for example,
when transcoding stuff via VSE) it was possible to have 100s of frames
in memory.

This isn't ideal because of limited amount of RAM, so need to have
some sort of limit. This is exactly what is implemented in this commit.
This commit is contained in:
Sergey Sharybin 2016-10-07 17:46:13 +02:00
parent ae2471b850
commit 8e586c594f

@ -84,6 +84,10 @@
# include "PIL_time.h" # include "PIL_time.h"
#endif #endif
// TODO(sergey): Find better approximation of the scheduled frames.
// For really highres renders it might fail still.
#define MAX_SCHEDULED_FRAMES 8
typedef struct OGLRender { typedef struct OGLRender {
Main *bmain; Main *bmain;
Render *re; Render *re;
@ -136,6 +140,9 @@ typedef struct OGLRender {
bool pool_ok; bool pool_ok;
bool is_animation; bool is_animation;
SpinLock reports_lock; SpinLock reports_lock;
unsigned int num_scheduled_frames;
ThreadMutex task_mutex;
ThreadCondition task_condition;
#ifdef DEBUG_TIME #ifdef DEBUG_TIME
double time_start; double time_start;
@ -712,6 +719,9 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
oglrender->task_scheduler = NULL; oglrender->task_scheduler = NULL;
oglrender->task_pool = NULL; oglrender->task_pool = NULL;
} }
oglrender->num_scheduled_frames = 0;
BLI_mutex_init(&oglrender->task_mutex);
BLI_condition_init(&oglrender->task_condition);
#ifdef DEBUG_TIME #ifdef DEBUG_TIME
oglrender->time_start = PIL_check_seconds_timer(); oglrender->time_start = PIL_check_seconds_timer();
@ -732,6 +742,8 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
BLI_task_scheduler_free(oglrender->task_scheduler); BLI_task_scheduler_free(oglrender->task_scheduler);
BLI_spin_end(&oglrender->reports_lock); BLI_spin_end(&oglrender->reports_lock);
} }
BLI_mutex_end(&oglrender->task_mutex);
BLI_condition_end(&oglrender->task_condition);
#ifdef DEBUG_TIME #ifdef DEBUG_TIME
printf("Total render time: %f\n", PIL_check_seconds_timer() - oglrender->time_start); printf("Total render time: %f\n", PIL_check_seconds_timer() - oglrender->time_start);
@ -850,6 +862,10 @@ static void write_result_func(TaskPool * __restrict pool,
/* Don't attempt to write if we've got an error. */ /* Don't attempt to write if we've got an error. */
if (!oglrender->pool_ok || G.is_break) { if (!oglrender->pool_ok || G.is_break) {
RE_FreeRenderResult(rr); RE_FreeRenderResult(rr);
BLI_mutex_lock(&oglrender->task_mutex);
oglrender->num_scheduled_frames--;
BLI_condition_notify_all(&oglrender->task_condition);
BLI_mutex_unlock(&oglrender->task_mutex);
return; return;
} }
/* Construct local thread0safe copy of reports structure which we can /* Construct local thread0safe copy of reports structure which we can
@ -913,6 +929,10 @@ static void write_result_func(TaskPool * __restrict pool,
oglrender->pool_ok = false; oglrender->pool_ok = false;
} }
RE_FreeRenderResult(rr); RE_FreeRenderResult(rr);
BLI_mutex_lock(&oglrender->task_mutex);
oglrender->num_scheduled_frames--;
BLI_condition_notify_all(&oglrender->task_condition);
BLI_mutex_unlock(&oglrender->task_mutex);
} }
static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr) static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr)
@ -925,6 +945,13 @@ static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr)
WriteTaskData *task_data = MEM_mallocN(sizeof(WriteTaskData), "write task data"); WriteTaskData *task_data = MEM_mallocN(sizeof(WriteTaskData), "write task data");
task_data->rr = rr; task_data->rr = rr;
task_data->cfra = scene->r.cfra; task_data->cfra = scene->r.cfra;
BLI_mutex_lock(&oglrender->task_mutex);
oglrender->num_scheduled_frames++;
if (oglrender->num_scheduled_frames > MAX_SCHEDULED_FRAMES) {
BLI_condition_wait(&oglrender->task_condition,
&oglrender->task_mutex);
}
BLI_mutex_unlock(&oglrender->task_mutex);
BLI_task_pool_push(oglrender->task_pool, BLI_task_pool_push(oglrender->task_pool,
write_result_func, write_result_func,
task_data, task_data,