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:
authorSergey Sharybin <sergey.vfx@gmail.com>2012-10-13 16:38:32 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2012-10-13 16:38:32 +0400
commit3b88a29abfdba618cc874f06ac8312218ae29b00 (patch)
treee67cd19270bda424ff929b81e7d23dc62f2b5478
parent51105bb2bd57b1a56517b30384304326b6bc75fb (diff)
Cycles: progressive refine option
Just makes progressive refine :) This means the whole image would be refined gradually using as much threads as it's set in performance settings. Having enough tiles is required to have this option working as it's expected. Technically it's implemented by repeatedly computing next sample for all the tiles before switching to next sample. This works around 7-12% slower than regular tile-based rendering, so use this option only if you really need it. This commit also fixes progressive update of image when Save Buffers option is enabled. And one more thing this commit fixes is handling display buffer with Save Buffers option enabled. If this option is enabled image buffer wouldn't have neither byte nor float buffer until image is fully rendered which could backfire in missing image while rendering in cases color management cache became full. This issue solved by allocating byte buffer for image buffer from tile update callback. Patch was reviewed by Brecht. He also made some minor edits to original version to patch. Thanks, man!
-rw-r--r--intern/cycles/blender/addon/properties.py5
-rw-r--r--intern/cycles/blender/addon/ui.py2
-rw-r--r--intern/cycles/blender/blender_session.cpp7
-rw-r--r--intern/cycles/blender/blender_sync.cpp8
-rw-r--r--intern/cycles/device/device_cpu.cpp24
-rw-r--r--intern/cycles/device/device_cuda.cpp6
-rw-r--r--intern/cycles/device/device_opencl.cpp6
-rw-r--r--intern/cycles/device/device_task.h1
-rw-r--r--intern/cycles/render/session.cpp93
-rw-r--r--intern/cycles/render/session.h9
-rw-r--r--intern/cycles/render/tile.cpp2
-rw-r--r--intern/cycles/render/tile.h2
-rw-r--r--source/blender/blenkernel/intern/image.c14
-rw-r--r--source/blender/compositor/operations/COM_ViewerBaseOperation.cpp2
-rw-r--r--source/blender/editors/render/render_internal.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c2
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h3
-rw-r--r--source/blender/imbuf/intern/colormanagement.c4
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;