diff options
Diffstat (limited to 'intern/cycles/render/session.cpp')
-rw-r--r-- | intern/cycles/render/session.cpp | 135 |
1 files changed, 119 insertions, 16 deletions
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index cd410e4e011..41212c2db84 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -34,16 +34,22 @@ CCL_NAMESPACE_BEGIN +/* Note about preserve_tile_device option for tile manager: + * progressive refine and viewport rendering does requires tiles to + * always be allocated for the same device + */ Session::Session(const SessionParams& params_) : params(params_), tile_manager(params.progressive, params.samples, params.tile_size, params.start_resolution, - (params.background)? 1: max(params.device.multi_devices.size(), 1)) + params.background == false || params.progressive_refine, params.background, + max(params.device.multi_devices.size(), 1)), + stats() { device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background); TaskScheduler::init(params.threads); - device = Device::create(params.device, params.background, params.threads); + device = Device::create(params.device, stats, params.background); if(params.background) { buffers = NULL; @@ -96,6 +102,9 @@ Session::~Session() display->write(device, params.output_path); } + foreach(RenderBuffers *buffers, tile_buffers) + delete buffers; + delete buffers; delete display; delete scene; @@ -173,9 +182,12 @@ bool Session::draw_gpu(BufferParams& buffer_params) void Session::run_gpu() { + bool tiles_written = false; + start_time = time_dt(); reset_time = time_dt(); paused_time = 0.0; + last_update_time = time_dt(); if(!params.background) progress.set_start_time(start_time + paused_time); @@ -267,10 +279,15 @@ void Session::run_gpu() if(device->error_message() != "") progress.set_cancel(device->error_message()); + tiles_written = update_progressive_refine(progress.get_cancel()); + if(progress.get_cancel()) break; } } + + if(!tiles_written) + update_progressive_refine(true); } /* CPU Session */ @@ -313,14 +330,18 @@ bool Session::draw_cpu(BufferParams& buffer_params) bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) { - if(progress.get_cancel()) - return false; + if(progress.get_cancel()) { + if(params.progressive_refine == false) { + /* for progressive refine current sample should be finished for all tiles */ + return false; + } + } thread_scoped_lock tile_lock(tile_mutex); /* get next tile from manager */ Tile tile; - int device_num = (params.background)? 0: device->device_number(tile_device); + int device_num = device->device_number(tile_device); if(!tile_manager.next_tile(tile, device_num)) return false; @@ -338,7 +359,7 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) /* in case of a permant buffer, return it, otherwise we will allocate * a new temporary buffer */ - if(!write_render_tile_cb) { + if(!params.background) { tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride); rtile.buffer = buffers->buffer.device_pointer; @@ -360,9 +381,30 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) buffer_params.get_offset_stride(rtile.offset, rtile.stride); - /* allocate buffers */ RenderBuffers *tilebuffers = new RenderBuffers(tile_device); - tilebuffers->reset(tile_device, buffer_params); + + /* allocate buffers */ + if(params.progressive_refine) { + tile_lock.lock(); + + if(tile_buffers.size() == 0) + tile_buffers.resize(tile_manager.state.num_tiles, NULL); + + tilebuffers = tile_buffers[tile.index]; + if(tilebuffers == NULL) { + tilebuffers = new RenderBuffers(tile_device); + tile_buffers[tile.index] = tilebuffers; + + tilebuffers->reset(tile_device, buffer_params); + } + + tile_lock.unlock(); + } + else { + tilebuffers = new RenderBuffers(tile_device); + + tilebuffers->reset(tile_device, buffer_params); + } rtile.buffer = tilebuffers->buffer.device_pointer; rtile.rng_state = tilebuffers->rng_state.device_pointer; @@ -377,9 +419,11 @@ void Session::update_tile_sample(RenderTile& rtile) thread_scoped_lock tile_lock(tile_mutex); if(update_render_tile_cb) { - /* todo: optimize this by making it thread safe and removing lock */ + if(params.progressive_refine == false) { + /* todo: optimize this by making it thread safe and removing lock */ - update_render_tile_cb(rtile); + update_render_tile_cb(rtile); + } } update_status_time(); @@ -390,10 +434,12 @@ void Session::release_tile(RenderTile& rtile) thread_scoped_lock tile_lock(tile_mutex); if(write_render_tile_cb) { - /* todo: optimize this by making it thread safe and removing lock */ - write_render_tile_cb(rtile); + if(params.progressive_refine == false) { + /* todo: optimize this by making it thread safe and removing lock */ + write_render_tile_cb(rtile); - delete rtile.buffers; + delete rtile.buffers; + } } update_status_time(); @@ -401,6 +447,10 @@ void Session::release_tile(RenderTile& rtile) void Session::run_cpu() { + bool tiles_written = false; + + last_update_time = time_dt(); + { /* reset once to start */ thread_scoped_lock reset_lock(delayed_reset.mutex); @@ -502,10 +552,15 @@ void Session::run_cpu() if(device->error_message() != "") progress.set_cancel(device->error_message()); + + tiles_written = update_progressive_refine(progress.get_cancel()); } progress.set_update(); } + + if(!tiles_written) + update_progressive_refine(true); } void Session::run() @@ -657,10 +712,13 @@ void Session::update_status_time(bool show_pause, bool show_done) string status, substatus; if(!params.progressive) { + bool is_gpu = params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL; + bool is_multidevice = params.device.multi_devices.size() > 1; + bool is_cpu = params.device.type == DEVICE_CPU; + substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles); - if(params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL || - (params.device.type == DEVICE_CPU && num_tiles == 1)) { + if((is_gpu && !is_multidevice) || (is_cpu && num_tiles == 1)) { /* when rendering on GPU multithreading happens within single tile, as in * tiles are handling sequentially and in this case we could display * currently rendering sample number @@ -722,6 +780,7 @@ void Session::path_trace() task.get_cancel = function_bind(&Progress::get_cancel, &this->progress); task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1); task.update_progress_sample = function_bind(&Session::update_progress_sample, this); + task.need_finish_queue = params.progressive_refine; device->task_add(task); } @@ -752,5 +811,49 @@ void Session::tonemap() display_outdated = false; } -CCL_NAMESPACE_END +bool Session::update_progressive_refine(bool cancel) +{ + int sample = tile_manager.state.sample + 1; + bool write = sample == params.samples || cancel; + double current_time = time_dt(); + + if (current_time - last_update_time < 1.0) { + /* if last sample was processed, we need to write buffers anyway */ + if (!write) + return false; + } + + if(params.progressive_refine) { + foreach(RenderBuffers *buffers, tile_buffers) { + RenderTile rtile; + rtile.buffers = buffers; + rtile.sample = sample; + + if(write) + write_render_tile_cb(rtile); + else + update_render_tile_cb(rtile); + } + } + + last_update_time = current_time; + + return write; +} + +void Session::device_free() +{ + scene->device_free(); + + foreach(RenderBuffers *buffers, tile_buffers) + delete buffers; + + tile_buffers.clear(); + + /* used from background render only, so no need to + * re-create render/display buffers here + */ +} + +CCL_NAMESPACE_END |