Cycles: disable progressive refine if denoising or save buffers is used.

Progressive refine undoes memory saving from save buffers, so enabling
both does not make much sense. Previously enabling progressive refine
would disable denoising, but it should be the other way around since
denoise actually affects the render result.

Includes some code refactor for progressive refine render buffers, and
avoids recomputing tiles for each progressive sample.
This commit is contained in:
Brecht Van Lommel 2017-10-10 02:28:23 +02:00
parent dc9eb8234f
commit 6199a606a6
Notes: blender-bot 2023-02-14 03:00:45 +01:00
Referenced by issue #68008, Branched Path Tracing will only use tiles with denoising off if progressive refine is disabled for Path Tracing.
7 changed files with 85 additions and 93 deletions

View File

@ -405,7 +405,12 @@ class CYCLES_RENDER_PT_performance(CyclesButtonsPanel, Panel):
sub.prop(rd, "tile_x", text="X")
sub.prop(rd, "tile_y", text="Y")
sub.prop(cscene, "use_progressive_refine")
subsub = sub.column()
subsub.active = not rd.use_save_buffers
for rl in rd.layers:
if rl.cycles.use_denoising:
subsub.active = False
subsub.prop(cscene, "use_progressive_refine")
col = split.column()
@ -595,7 +600,6 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
cscene = context.scene.cycles
layout = self.layout
layout.active = not cscene.use_progressive_refine
layout.prop(crl, "use_denoising", text="")
def draw(self, context):
@ -607,7 +611,7 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel):
rl = rd.layers.active
crl = rl.cycles
layout.active = crl.use_denoising and not cscene.use_progressive_refine
layout.active = crl.use_denoising
split = layout.split()

View File

@ -305,11 +305,10 @@ static void end_render_result(BL::RenderEngine& b_engine,
void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only, bool highlight)
{
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;
int h = params.height;
int x = rtile.x - session->tile_manager.params.full_x;
int y = rtile.y - session->tile_manager.params.full_y;
int w = rtile.w;
int h = rtile.h;
/* get render result */
BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str(), b_rview_name.c_str());
@ -401,7 +400,7 @@ void BlenderSession::render()
buffer_params.passes = passes;
PointerRNA crl = RNA_pointer_get(&b_layer_iter->ptr, "cycles");
bool use_denoising = !session_params.progressive_refine && get_boolean(crl, "use_denoising");
bool use_denoising = get_boolean(crl, "use_denoising");
buffer_params.denoising_data_pass = use_denoising;
session->tile_manager.schedule_denoising = use_denoising;
session->params.use_denoising = use_denoising;
@ -659,10 +658,9 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult& b_rr,
if(!buffers->copy_from_device())
return;
BufferParams& params = buffers->params;
float exposure = scene->film->exposure;
vector<float> pixels(params.width*params.height*4);
vector<float> pixels(rtile.w*rtile.h*4);
/* Adjust absolute sample number to the range. */
int sample = rtile.sample;

View File

@ -573,8 +573,7 @@ array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles");
if(get_boolean(crp, "denoising_store_passes") &&
get_boolean(crp, "use_denoising") &&
!session_params.progressive_refine) {
get_boolean(crp, "use_denoising")) {
b_engine.add_pass("Denoising Normal", 3, "XYZ", b_srlay.name().c_str());
b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_srlay.name().c_str());
b_engine.add_pass("Denoising Albedo", 3, "RGB", b_srlay.name().c_str());
@ -676,8 +675,9 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
params.experimental = (get_enum(cscene, "feature_set") != 0);
/* threads */
if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED)
params.threads = b_scene.render().threads();
BL::RenderSettings b_r = b_scene.render();
if(b_r.threads_mode() == BL::RenderSettings::threads_mode_FIXED)
params.threads = b_r.threads();
else
params.threads = 0;
@ -819,11 +819,24 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
params.start_resolution = get_int(cscene, "preview_start_resolution");
params.pixel_size = b_engine.get_preview_pixel_size(b_scene);
/* other parameters */
params.cancel_timeout = (double)get_float(cscene, "debug_cancel_timeout");
params.reset_timeout = (double)get_float(cscene, "debug_reset_timeout");
params.text_timeout = (double)get_float(cscene, "debug_text_timeout");
params.progressive_refine = get_boolean(cscene, "use_progressive_refine");
/* progressive refine */
params.progressive_refine = get_boolean(cscene, "use_progressive_refine") &&
!b_r.use_save_buffers();
if(params.progressive_refine) {
BL::RenderSettings::layers_iterator b_rlay;
for(b_r.layers.begin(b_rlay); b_rlay != b_r.layers.end(); ++b_rlay) {
PointerRNA crl = RNA_pointer_get(&b_rlay->ptr, "cycles");
if(get_boolean(crl, "use_denoising")) {
params.progressive_refine = false;
}
}
}
if(background) {
if(params.progressive_refine)

View File

@ -114,9 +114,7 @@ Session::~Session()
}
/* clean up */
foreach(RenderTile &rtile, render_tiles)
delete rtile.buffers;
tile_manager.free_device();
tile_manager.device_free();
delete buffers;
delete display;
@ -380,19 +378,17 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
/* in case of a permanent buffer, return it, otherwise we will allocate
* a new temporary buffer */
if(!(params.background && params.output_path.empty())) {
if(buffers) {
tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
rtile.buffer = buffers->buffer.device_pointer;
rtile.buffers = buffers;
tile->buffers = buffers;
device->map_tile(tile_device, rtile);
return true;
}
bool store_rtile = false;
if(tile->buffers == NULL) {
/* fill buffer parameters */
BufferParams buffer_params = tile_manager.params;
@ -402,52 +398,15 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
buffer_params.height = rtile.h;
/* allocate buffers */
if(params.progressive_refine) {
tile_lock.lock();
if(render_tiles.size() == 0) {
RenderTile nulltile;
nulltile.buffers = NULL;
render_tiles.resize(tile_manager.state.num_tiles, nulltile);
}
/* In certain circumstances number of tiles in the tile manager could
* be changed. This is not supported by the progressive refine feature.
*/
assert(render_tiles.size() == tile_manager.state.num_tiles);
RenderTile &stored_rtile = render_tiles[tile->index];
if(stored_rtile.buffers == NULL) {
tile->buffers = new RenderBuffers(tile_device);
tile->buffers->reset(tile_device, buffer_params);
store_rtile = true;
}
else {
assert(rtile.x == stored_rtile.x &&
rtile.y == stored_rtile.y &&
rtile.w == stored_rtile.w &&
rtile.h == stored_rtile.h);
tile_lock.unlock();
tile->buffers = stored_rtile.buffers;
}
}
else {
tile->buffers = new RenderBuffers(tile_device);
tile->buffers->reset(tile_device, buffer_params);
}
tile->buffers = new RenderBuffers(tile_device);
tile->buffers->reset(tile_device, buffer_params);
}
tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride);
rtile.buffer = tile->buffers->buffer.device_pointer;
rtile.buffers = tile->buffers;
rtile.sample = 0;
if(store_rtile) {
render_tiles[tile->index] = rtile;
tile_lock.unlock();
}
rtile.sample = tile_manager.state.sample;
/* this will tag tile as IN PROGRESS in blender-side render pipeline,
* which is needed to highlight currently rendering tile before first
@ -484,10 +443,11 @@ void Session::release_tile(RenderTile& rtile)
if(tile_manager.finish_tile(rtile.tile_index, delete_tile)) {
if(write_render_tile_cb && params.progressive_refine == false) {
write_render_tile_cb(rtile);
if(delete_tile) {
delete rtile.buffers;
tile_manager.state.tiles[rtile.tile_index].buffers = NULL;
}
}
if(delete_tile) {
delete rtile.buffers;
tile_manager.state.tiles[rtile.tile_index].buffers = NULL;
}
}
else {
@ -794,10 +754,10 @@ bool Session::draw(BufferParams& buffer_params, DeviceDrawParams &draw_params)
void Session::reset_(BufferParams& buffer_params, int samples)
{
if(buffers) {
if(buffer_params.modified(buffers->params)) {
gpu_draw_ready = false;
buffers->reset(device, buffer_params);
if(buffers && buffer_params.modified(tile_manager.params)) {
gpu_draw_ready = false;
buffers->reset(device, buffer_params);
if(display) {
display->reset(device, buffer_params);
}
}
@ -819,15 +779,6 @@ void Session::reset(BufferParams& buffer_params, int samples)
reset_gpu(buffer_params, samples);
else
reset_cpu(buffer_params, samples);
if(params.progressive_refine) {
thread_scoped_lock buffers_lock(buffers_mutex);
foreach(RenderTile &rtile, render_tiles)
delete rtile.buffers;
render_tiles.clear();
}
}
void Session::set_samples(int samples)
@ -1045,8 +996,18 @@ bool Session::update_progressive_refine(bool cancel)
}
if(params.progressive_refine) {
foreach(RenderTile &rtile, render_tiles) {
foreach(Tile& tile, tile_manager.state.tiles) {
if(!tile.buffers) {
continue;
}
RenderTile rtile;
rtile.x = tile_manager.state.buffer.full_x + tile.x;
rtile.y = tile_manager.state.buffer.full_y + tile.y;
rtile.w = tile.w;
rtile.h = tile.h;
rtile.sample = sample;
rtile.buffers = tile.buffers;
if(write) {
if(write_render_tile_cb)
@ -1068,11 +1029,7 @@ void Session::device_free()
{
scene->device_free();
foreach(RenderTile &tile, render_tiles)
delete tile.buffers;
tile_manager.free_device();
render_tiles.clear();
tile_manager.device_free();
/* used from background render only, so no need to
* re-create render/display buffers here

View File

@ -221,8 +221,6 @@ protected:
double last_update_time;
bool update_progressive_refine(bool cancel);
vector<RenderTile> render_tiles;
DeviceRequestedFeatures get_requested_device_features();
/* ** Split kernel routines ** */

View File

@ -17,6 +17,7 @@
#include "render/tile.h"
#include "util/util_algorithm.h"
#include "util/util_foreach.h"
#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
@ -113,14 +114,16 @@ TileManager::~TileManager()
{
}
void TileManager::free_device()
void TileManager::device_free()
{
if(schedule_denoising) {
if(schedule_denoising || progressive) {
for(int i = 0; i < state.tiles.size(); i++) {
delete state.tiles[i].buffers;
state.tiles[i].buffers = NULL;
}
}
state.tiles.clear();
}
static int get_divider(int w, int h, int start_resolution)
@ -150,7 +153,7 @@ void TileManager::reset(BufferParams& params_, int num_samples_)
state.resolution_divider = get_divider(params.width, params.height, start_resolution);
state.render_tiles.clear();
state.denoising_tiles.clear();
state.tiles.clear();
device_free();
}
void TileManager::set_samples(int num_samples_)
@ -196,7 +199,7 @@ int TileManager::gen_tiles(bool sliced)
int slice_num = sliced? num: 1;
int tile_w = (tile_size.x >= image_w) ? 1 : divide_up(image_w, tile_size.x);
state.tiles.clear();
device_free();
state.render_tiles.clear();
state.denoising_tiles.clear();
state.render_tiles.resize(num);
@ -345,6 +348,14 @@ int TileManager::gen_tiles(bool sliced)
return idx;
}
void TileManager::gen_render_tiles()
{
/* Regenerate just the render tiles for progressive render. */
foreach(Tile& tile, state.tiles) {
state.render_tiles[tile.device].push_back(tile.index);
}
}
void TileManager::set_tiles()
{
int resolution = state.resolution_divider;
@ -401,6 +412,10 @@ bool TileManager::finish_tile(int index, bool &delete_tile)
{
delete_tile = false;
if(progressive) {
return true;
}
switch(state.tiles[index].state) {
case Tile::RENDER:
{
@ -501,7 +516,13 @@ bool TileManager::next()
state.num_samples = range_num_samples;
state.resolution_divider = pixel_size;
set_tiles();
if(state.sample == 0) {
set_tiles();
}
else {
gen_render_tiles();
}
}
return true;

View File

@ -91,7 +91,7 @@ public:
bool preserve_tile_device, bool background, TileOrder tile_order, int num_devices = 1, int pixel_size = 1);
~TileManager();
void free_device();
void device_free();
void reset(BufferParams& params, int num_samples);
void set_samples(int num_samples);
bool next();
@ -146,6 +146,7 @@ protected:
/* Generate tile list, return number of tiles. */
int gen_tiles(bool sliced);
void gen_render_tiles();
int get_neighbor_index(int index, int neighbor);
bool check_neighbor_state(int index, Tile::State state);