Tomato Cycles: internal cleanup of tile-based integrator

This commit solves couple of issues appeared with new integrator:

- Render job progress bar is now shows progress based on number of
  rendered tiles. This is the same as Blender Internal does.

  This still requires some further thoughts because for GPU it's
  better to use single tile and in this case progress bar should
  be based on number of rendered samples.

- Removes "global" sample counter from progress descriptor. There's
  no more global-being sample which makes sense.

  This counter was replaced with tile counter.

- Use proper sample number when copying render buffer to blender.
  It used to be final sample number used which lead to tiles
  appearing from complete dark to normal brightness as they're
  being rendered. Now tile would be displayed with proper
  brightness starting from the very first sample.

  Use sample counter stored in render tile descriptor and pass
  it to update / write callbacks.

This was tested on CPU and GPU CUDA rendering.

Additional change:

  OpenCL rendering now should be cancellable before it finished
  rendering all the samples (the same change as for CPU/CUDA from
  a while ago).

This part of commit wasn't actually tested, would do it later.
This commit is contained in:
Sergey Sharybin
2012-08-03 15:18:42 +00:00
parent 82158b7c34
commit b5e1419e5b
11 changed files with 73 additions and 62 deletions

View File

@@ -189,9 +189,9 @@ static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr,
RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data, (int)cancel);
}
void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool do_update_only)
void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only)
{
BufferParams& params = buffers->params;
BufferParams& params = rtile.buffers->params;
int x = params.full_x - session->tile_manager.params.full_x;
int y = params.full_y - session->tile_manager.params.full_y;
int w = params.width;
@@ -211,31 +211,31 @@ void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool
if (do_update_only) {
/* update only needed */
update_render_result(b_rr, b_rlay, buffers);
update_render_result(b_rr, b_rlay, rtile);
end_render_result(b_engine, b_rr, true);
}
else {
/* write result */
write_render_result(b_rr, b_rlay, buffers);
write_render_result(b_rr, b_rlay, rtile);
end_render_result(b_engine, b_rr);
}
}
void BlenderSession::write_render_buffers(RenderBuffers *buffers)
void BlenderSession::write_render_tile(RenderTile& rtile)
{
do_write_update_render_buffers(buffers, false);
do_write_update_render_tile(rtile, false);
}
void BlenderSession::update_render_buffers(RenderBuffers *buffers)
void BlenderSession::update_render_tile(RenderTile& rtile)
{
do_write_update_render_buffers(buffers, true);
do_write_update_render_tile(rtile, true);
}
void BlenderSession::render()
{
/* set callback to write out render results */
session->write_render_buffers_cb = function_bind(&BlenderSession::write_render_buffers, this, _1);
session->update_render_buffers_cb = function_bind(&BlenderSession::update_render_buffers, this, _1);
session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1);
/* get buffer parameters */
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
@@ -305,22 +305,20 @@ void BlenderSession::render()
}
/* clear callback */
session->write_render_buffers_cb = NULL;
session->update_render_buffers_cb = NULL;
session->write_render_tile_cb = NULL;
session->update_render_tile_cb = NULL;
}
void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers, bool do_update_only)
void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only)
{
RenderBuffers *buffers = rtile.buffers;
/* copy data from device */
if(!buffers->copy_from_device())
return;
BufferParams& params = buffers->params;
float exposure = scene->film->exposure;
double total_time, sample_time;
int sample;
session->progress.get_sample(sample, total_time, sample_time);
vector<float> pixels(params.width*params.height*4);
@@ -336,27 +334,27 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::Re
int components = b_pass.channels();
/* copy pixels */
if(buffers->get_pass(pass_type, exposure, sample, components, &pixels[0]))
if(buffers->get_pass_rect(pass_type, exposure, rtile.sample, components, &pixels[0]))
rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]);
}
}
/* copy combined pass */
if(buffers->get_pass(PASS_COMBINED, exposure, sample, 4, &pixels[0]))
if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0]))
rna_RenderLayer_rect_set(&b_rlay.ptr, &pixels[0]);
/* tag result as updated */
RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data);
}
void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers)
void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile)
{
do_write_update_render_result(b_rr, b_rlay, buffers, false);
do_write_update_render_result(b_rr, b_rlay, rtile, false);
}
void BlenderSession::update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers)
void BlenderSession::update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile)
{
do_write_update_render_result(b_rr, b_rlay, buffers, true);
do_write_update_render_result(b_rr, b_rlay, rtile, true);
}
void BlenderSession::synchronize()
@@ -461,11 +459,12 @@ void BlenderSession::get_status(string& status, string& substatus)
void BlenderSession::get_progress(float& progress, double& total_time)
{
double sample_time;
int sample;
double tile_time;
int tile;
int tile_total = session->tile_manager.state.num_tiles;
session->progress.get_sample(sample, total_time, sample_time);
progress = ((float)sample/(float)session->params.samples);
session->progress.get_tile(tile, total_time, tile_time);
progress = ((float)tile/(float)tile_total);
}
void BlenderSession::update_status_progress()

View File

@@ -30,6 +30,7 @@ CCL_NAMESPACE_BEGIN
class Scene;
class Session;
class RenderBuffers;
class RenderTile;
class BlenderSession {
public:
@@ -48,14 +49,14 @@ public:
/* offline render */
void render();
void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers);
void write_render_buffers(RenderBuffers *buffers);
void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile);
void write_render_tile(RenderTile& rtile);
/* update functions are used to update display buffer only after sample was rendered
* only needed for better visual feedback
*/
void update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers);
void update_render_buffers(RenderBuffers *buffers);
void update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile);
void update_render_tile(RenderTile& rtile);
/* interactive updates */
void synchronize();
@@ -89,8 +90,8 @@ public:
int width, height;
protected:
void do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers, bool do_update_only);
void do_write_update_render_buffers(RenderBuffers *buffers, bool do_update_only);
void do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only);
void do_write_update_render_tile(RenderTile& rtile, bool do_update_only);
};
CCL_NAMESPACE_END

View File

@@ -55,7 +55,6 @@ void rna_ColorRamp_eval(void *coba, float position, float color[4]);
void rna_Scene_frame_set(void *scene, int frame, float subframe);
void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr);
void BKE_image_user_file_path(void *iuser, void *ima, char *path);
}
CCL_NAMESPACE_BEGIN

View File

@@ -167,6 +167,7 @@ public:
}
}
tile.sample = sample + 1;
task.update_progress(tile);
}
}
@@ -189,6 +190,7 @@ public:
}
}
tile.sample = sample + 1;
task.update_progress(tile);
}
}

View File

@@ -837,11 +837,13 @@ public:
int end_sample = tile.start_sample + tile.num_samples;
for(int sample = start_sample; sample < end_sample; sample++) {
if (task->get_cancel()) {
if (task->get_cancel())
break;
}
path_trace(tile, sample);
tile.sample = sample + 1;
task->update_progress(tile);
}

View File

@@ -685,9 +685,17 @@ public:
int start_sample = tile.start_sample;
int end_sample = tile.start_sample + tile.num_samples;
for(int sample = start_sample; sample < end_sample; sample++)
for(int sample = start_sample; sample < end_sample; sample++) {
if (task->get_cancel())
break;
path_trace(tile, sample);
tile.sample = sample + 1;
task->update_progress(tile);
}
task->release_tile(tile);
}
}

View File

@@ -158,7 +158,7 @@ bool RenderBuffers::copy_from_device()
return true;
}
bool RenderBuffers::get_pass(PassType type, float exposure, int sample, int components, float *pixels)
bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels)
{
int pass_offset = 0;

View File

@@ -79,7 +79,7 @@ public:
void reset(Device *device, BufferParams& params);
bool copy_from_device();
bool get_pass(PassType type, float exposure, int sample, int components, float *pixels);
bool get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels);
protected:
void device_free();
@@ -129,6 +129,7 @@ public:
int x, y, w, h;
int start_sample;
int num_samples;
int sample;
int resolution;
int offset;
int stride;

View File

@@ -339,7 +339,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_buffers_cb) {
if(!write_render_tile_cb) {
tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
rtile.buffer = buffers->buffer.device_pointer;
@@ -377,11 +377,11 @@ void Session::update_tile_sample(RenderTile& rtile)
{
thread_scoped_lock tile_lock(tile_mutex);
if(update_render_buffers_cb) {
if(update_render_tile_cb) {
/* todo: optimize this by making it thread safe and removing lock */
if(!progress.get_cancel())
update_render_buffers_cb(rtile.buffers);
update_render_tile_cb(rtile);
}
update_status_time();
@@ -391,10 +391,10 @@ void Session::release_tile(RenderTile& rtile)
{
thread_scoped_lock tile_lock(tile_mutex);
if(write_render_buffers_cb) {
if(write_render_tile_cb) {
/* todo: optimize this by making it thread safe and removing lock */
if(!progress.get_cancel())
write_render_buffers_cb(rtile.buffers);
write_render_tile_cb(rtile);
delete rtile.buffers;
}
@@ -648,8 +648,6 @@ void Session::update_scene()
void Session::update_status_time(bool show_pause, bool show_done)
{
int sample = tile_manager.state.sample;
int num_samples = tile_manager.state.num_samples;
int resolution = tile_manager.state.resolution;
int num_tiles = tile_manager.state.num_tiles;
int tile = tile_manager.state.num_rendered_tiles;
@@ -677,14 +675,15 @@ void Session::update_status_time(bool show_pause, bool show_done)
if(preview_time == 0.0 && resolution == 1)
preview_time = time_dt();
double sample_time = (sample == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample);
double tile_time = (tile == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample);
/* negative can happen when we pause a bit before rendering, can discard that */
if(preview_time < 0.0) preview_time = 0.0;
progress.set_sample(sample + num_samples, sample_time);
progress.set_tile(tile, tile_time);
}
void Session::path_trace()
{
/* add path trace task */

View File

@@ -105,8 +105,8 @@ public:
TileManager tile_manager;
int sample;
boost::function<void(RenderBuffers*)> write_render_buffers_cb;
boost::function<void(RenderBuffers*)> update_render_buffers_cb;
boost::function<void(RenderTile&)> write_render_tile_cb;
boost::function<void(RenderTile&)> update_render_tile_cb;
Session(const SessionParams& params);
~Session();

View File

@@ -36,10 +36,10 @@ class Progress {
public:
Progress()
{
sample = 0;
tile = 0;
start_time = time_dt();
total_time = 0.0f;
sample_time = 0.0f;
tile_time = 0.0f;
status = "Initializing";
substatus = "";
update_cb = NULL;
@@ -57,8 +57,8 @@ public:
{
thread_scoped_lock lock(progress.progress_mutex);
progress.get_sample(sample, total_time, sample_time);
progress.get_status(status, substatus);
progress.get_tile(tile, total_time, tile_time);
return *this;
}
@@ -90,7 +90,7 @@ public:
cancel_cb = function;
}
/* sample and timing information */
/* tile and timing information */
void set_start_time(double start_time_)
{
@@ -99,22 +99,22 @@ public:
start_time = start_time_;
}
void set_sample(int sample_, double sample_time_)
void set_tile(int tile_, double tile_time_)
{
thread_scoped_lock lock(progress_mutex);
sample = sample_;
tile = tile_;
total_time = time_dt() - start_time;
sample_time = sample_time_;
tile_time = tile_time_;
}
void get_sample(int& sample_, double& total_time_, double& sample_time_)
void get_tile(int& tile_, double& total_time_, double& tile_time_)
{
thread_scoped_lock lock(progress_mutex);
sample_ = sample;
tile_ = tile;
total_time_ = (total_time > 0.0)? total_time: 0.0;
sample_time_ = sample_time;
tile_time_ = tile_time;
}
/* status messages */
@@ -170,11 +170,11 @@ protected:
boost::function<void(void)> update_cb;
boost::function<void(void)> cancel_cb;
int sample;
int tile;
double start_time;
double total_time;
double sample_time;
double tile_time;
string status;
string substatus;