diff options
-rw-r--r-- | intern/cycles/blender/addon/properties.py | 5 | ||||
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 2 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 7 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.cpp | 8 | ||||
-rw-r--r-- | intern/cycles/device/device_cpu.cpp | 24 | ||||
-rw-r--r-- | intern/cycles/device/device_cuda.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/device/device_opencl.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/device/device_task.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/session.cpp | 93 | ||||
-rw-r--r-- | intern/cycles/render/session.h | 9 | ||||
-rw-r--r-- | intern/cycles/render/tile.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/render/tile.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/image.c | 14 | ||||
-rw-r--r-- | source/blender/compositor/operations/COM_ViewerBaseOperation.cpp | 2 | ||||
-rw-r--r-- | source/blender/editors/render/render_internal.c | 4 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image.c | 2 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_colormanagement.h | 3 | ||||
-rw-r--r-- | source/blender/imbuf/intern/colormanagement.c | 4 |
18 files changed, 158 insertions, 36 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 0fadfa0afc8..f2a88f0d96c 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -284,6 +284,11 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): description="Cache last built BVH to disk for faster re-render if no geometry changed", default=False, ) + cls.use_progressive_refine = BoolProperty( + name="Progressive Refine", + description="Instead of rendering each tile until it is finished, refine the whole image progressively so rendering can be stopped manually when the noise is low enough", + default=False, + ) @classmethod def unregister(cls): diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index ca43c345bfa..93309f63a84 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -198,6 +198,8 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.prop(rd, "parts_x", text="X") sub.prop(rd, "parts_y", text="Y") + sub.prop(cscene, "use_progressive_refine") + subsub = sub.column() subsub.enabled = not rd.use_border subsub.prop(rd, "use_save_buffers") diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 7b80c520e72..0a09102bd4f 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -466,9 +466,12 @@ void BlenderSession::get_progress(float& progress, double& total_time) session->progress.get_tile(tile, total_time, tile_time); sample = session->progress.get_sample(); - samples_per_tile = session->tile_manager.state.num_samples; + samples_per_tile = session->params.samples; - progress = ((float)sample/(float)(tile_total * samples_per_tile)); + if(samples_per_tile) + progress = ((float)sample/(float)(tile_total * samples_per_tile)); + else + progress = 0.0; } void BlenderSession::update_status_progress() diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 3d36eba0c4b..00130f357dd 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -380,8 +380,14 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use params.reset_timeout = get_float(cscene, "debug_reset_timeout"); params.text_timeout = get_float(cscene, "debug_text_timeout"); + params.progressive_refine = get_boolean(cscene, "use_progressive_refine"); + if(background) { - params.progressive = false; + if(params.progressive_refine) + params.progressive = true; + else + params.progressive = false; + params.start_resolution = INT_MAX; } else diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 4c54671b0d0..b727a83d024 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -135,8 +135,10 @@ public: void thread_path_trace(DeviceTask& task) { - if(task_pool.cancelled()) - return; + if(task_pool.cancelled()) { + if(task.need_finish_queue == false) + return; + } #ifdef WITH_OSL if(kernel_osl_use(kg)) @@ -154,8 +156,10 @@ public: #ifdef WITH_OPTIMIZED_KERNEL if(system_cpu_support_optimized()) { for(int sample = start_sample; sample < end_sample; sample++) { - if (task.get_cancel() || task_pool.cancelled()) - break; + if (task.get_cancel() || task_pool.cancelled()) { + if(task.need_finish_queue == false) + break; + } for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { @@ -173,8 +177,10 @@ public: #endif { for(int sample = start_sample; sample < end_sample; sample++) { - if (task.get_cancel() || task_pool.cancelled()) - break; + if (task.get_cancel() || task_pool.cancelled()) { + if(task.need_finish_queue == false) + break; + } for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { @@ -191,8 +197,10 @@ public: task.release_tile(tile); - if(task_pool.cancelled()) - break; + if(task_pool.cancelled()) { + if(task.need_finish_queue == false) + break; + } } #ifdef WITH_OSL diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index c8dcfdc2f3d..04b4cb0950a 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -837,8 +837,10 @@ public: int end_sample = tile.start_sample + tile.num_samples; for(int sample = start_sample; sample < end_sample; sample++) { - if (task->get_cancel()) - break; + if (task->get_cancel()) { + if(task->need_finish_queue == false) + break; + } path_trace(tile, sample); diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 673ffdf79fd..aa4f17ea325 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -686,8 +686,10 @@ public: int end_sample = tile.start_sample + tile.num_samples; for(int sample = start_sample; sample < end_sample; sample++) { - if (task->get_cancel()) - break; + if (task->get_cancel()) { + if(task->need_finish_queue == false) + break; + } path_trace(tile, sample); diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h index cfb3d8d988e..8ca8b88ea49 100644 --- a/intern/cycles/device/device_task.h +++ b/intern/cycles/device/device_task.h @@ -65,6 +65,7 @@ public: boost::function<void(RenderTile&)> release_tile; boost::function<bool(void)> get_cancel; + bool need_finish_queue; protected: double last_update_time; }; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index cd410e4e011..65b20f1dd2c 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -96,6 +96,9 @@ Session::~Session() display->write(device, params.output_path); } + foreach(RenderBuffers *buffers, tile_buffers) + delete buffers; + delete buffers; delete display; delete scene; @@ -173,6 +176,8 @@ 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; @@ -267,10 +272,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,8 +323,12 @@ 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); @@ -338,7 +352,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 +374,35 @@ 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) { + int tile_x = rtile.x / params.tile_size.x; + int tile_y = rtile.y / params.tile_size.y; + + int tile_index = tile_y * tile_manager.state.tile_w + tile_x; + + 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 +417,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 +432,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 +445,8 @@ void Session::release_tile(RenderTile& rtile) void Session::run_cpu() { + bool tiles_written = false; + { /* reset once to start */ thread_scoped_lock reset_lock(delayed_reset.mutex); @@ -502,10 +548,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() @@ -722,6 +773,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 +804,24 @@ void Session::tonemap() display_outdated = false; } -CCL_NAMESPACE_END +bool Session::update_progressive_refine(bool cancel) +{ + int sample = tile_manager.state.sample + 1; + + if(params.progressive_refine) { + foreach(RenderBuffers *buffers, tile_buffers) { + RenderTile rtile; + rtile.buffers = buffers; + rtile.sample = sample; + + if(rtile.sample == params.samples || cancel) + write_render_tile_cb(rtile); + else + update_render_tile_cb(rtile); + } + } + + return sample == params.samples; +} +CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index eda8b3da60e..dc3e7504766 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -25,6 +25,7 @@ #include "util_progress.h" #include "util_thread.h" +#include "util_vector.h" CCL_NAMESPACE_BEGIN @@ -42,6 +43,7 @@ class SessionParams { public: DeviceInfo device; bool background; + bool progressive_refine; string output_path; bool progressive; @@ -58,6 +60,7 @@ public: SessionParams() { background = false; + progressive_refine = false; output_path = ""; progressive = false; @@ -76,6 +79,7 @@ public: { return !(device.type == params.device.type && device.id == params.device.id && background == params.background + && progressive_refine == params.progressive_refine && output_path == params.output_path /* && samples == params.samples */ && progressive == params.progressive @@ -173,6 +177,11 @@ protected: double reset_time; double preview_time; double paused_time; + + /* progressive refine */ + bool update_progressive_refine(bool cancel); + + vector<RenderBuffers *> tile_buffers; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 874f1a6b3aa..02c0ee640a3 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -102,6 +102,8 @@ void TileManager::set_tiles() } state.num_tiles = state.tiles.size(); + state.tile_w = (tile_size.x >= image_w) ? 1 : (image_w + tile_size.x - 1) / tile_size.x; + state.tile_h = (tile_size.y >= image_h) ? 1 : (image_h + tile_size.y - 1) / tile_size.y; state.buffer.width = image_w; state.buffer.height = image_h; diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index d820f74e3bd..587dfbe4f1a 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -54,6 +54,8 @@ public: int resolution_divider; int num_tiles; int num_rendered_tiles; + int tile_w; + int tile_h; list<Tile> tiles; } state; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index c003a86a0b7..9a1ea15da97 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2617,11 +2617,21 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ /* free rect buffer if float buffer changes, so it can be recreated with * the updated result, and also in case we got byte buffer from sequencer, * so we don't keep reference to freed buffer */ - if (ibuf->rect_float != rectf || rect || !rectf) + if (ibuf->rect_float != rectf || rect) imb_freerectImBuf(ibuf); - if (rect) + if (rect) { ibuf->rect = rect; + } + else { + /* byte buffer of render result has been freed, make sure image buffers + * does not reference to this buffer anymore + * need check for whether byte buffer was allocated and owned by image itself + * or if it's reusing buffer from render result + */ + if ((ibuf->mall & IB_rect) == 0) + ibuf->rect = NULL; + } if (rectf) { ibuf->rect_float = rectf; diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp index d9ca131721f..55a001530ee 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp @@ -107,7 +107,7 @@ void ViewerBaseOperation:: updateImage(rcti *rect) { IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, NULL, getWidth(), 0, 0, this->m_viewSettings, this->m_displaySettings, - rect->xmin, rect->ymin, rect->xmax, rect->ymax); + rect->xmin, rect->ymin, rect->xmax, rect->ymax, FALSE); WM_main_add_notifier(NC_WINDOW | ND_DRAW, NULL); } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index c08ea2b6429..b61280f14ce 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -80,7 +80,6 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat float *rectf = NULL; int ymin, ymax, xmin, xmax; int rymin, rxmin; - /* unsigned char *rectc; */ /* UNUSED */ /* if renrect argument, we only refresh scanlines */ if (renrect) { @@ -143,11 +142,10 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat imb_addrectImBuf(ibuf); rectf += 4 * (rr->rectx * ymin + xmin); - /* rectc = (unsigned char *)(ibuf->rect + ibuf->x * rymin + rxmin); */ /* UNUSED */ IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin, &scene->view_settings, &scene->display_settings, - rxmin, rymin, rxmin + xmax, rymin + ymax); + rxmin, rymin, rxmin + xmax, rymin + ymax, TRUE); } /* ****************************** render invoking ***************** */ diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index f60d34428b3..480d4ee6ac1 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -4249,7 +4249,7 @@ static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image, IMB_partial_display_buffer_update(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, ibuf->x, 0, 0, &scene->view_settings, &scene->display_settings, imapaintpartial.x1, imapaintpartial.y1, - imapaintpartial.x2, imapaintpartial.y2); + imapaintpartial.x2, imapaintpartial.y2, FALSE); } else { ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index e2604241caf..0653956e113 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -130,7 +130,8 @@ void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, i void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_buffer, const unsigned char *buffer_byte, int stride, int offset_x, int offset_y, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, - int xmin, int ymin, int xmax, int ymax); + int xmin, int ymin, int xmax, int ymax, + int update_orig_byte_buffer); /* ** Pixel processor functions ** */ struct ColormanageProcessor *IMB_colormanagement_display_processor_new(const struct ColorManagedViewSettings *view_settings, diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 37510c10e9a..40b07c02cd7 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -2382,9 +2382,9 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, const unsigned char *byte_buffer, int stride, int offset_x, int offset_y, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, - int xmin, int ymin, int xmax, int ymax) + int xmin, int ymin, int xmax, int ymax, int update_orig_byte_buffer) { - if (ibuf->rect && ibuf->rect_float) { + if ((ibuf->rect && ibuf->rect_float) || update_orig_byte_buffer) { /* update byte buffer created by legacy color management */ unsigned char *rect = (unsigned char *) ibuf->rect; |