Cycles: avoid reallocating tile denoising memory many times during render.
This commit is contained in:
parent
df886b178c
commit
bd4bea3e98
|
@ -712,12 +712,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void denoise(DeviceTask &task, RenderTile &tile)
|
||||
void denoise(DeviceTask &task, DenoisingTask& denoising, RenderTile &tile)
|
||||
{
|
||||
tile.sample = tile.start_sample + tile.num_samples;
|
||||
|
||||
DenoisingTask denoising(this);
|
||||
|
||||
denoising.functions.construct_transform = function_bind(&CPUDevice::denoising_construct_transform, this, &denoising);
|
||||
denoising.functions.reconstruct = function_bind(&CPUDevice::denoising_reconstruct, this, _1, _2, _3, &denoising);
|
||||
denoising.functions.divide_shadow = function_bind(&CPUDevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
|
||||
|
@ -769,6 +767,8 @@ public:
|
|||
}
|
||||
|
||||
RenderTile tile;
|
||||
DenoisingTask denoising(this);
|
||||
|
||||
while(task.acquire_tile(this, tile)) {
|
||||
if(tile.task == RenderTile::PATH_TRACE) {
|
||||
if(use_split_kernel) {
|
||||
|
@ -780,7 +780,7 @@ public:
|
|||
}
|
||||
}
|
||||
else if(tile.task == RenderTile::DENOISE) {
|
||||
denoise(task, tile);
|
||||
denoise(task, denoising, tile);
|
||||
}
|
||||
|
||||
task.release_tile(tile);
|
||||
|
|
|
@ -1408,10 +1408,8 @@ public:
|
|||
return !have_error();
|
||||
}
|
||||
|
||||
void denoise(RenderTile &rtile, const DeviceTask &task)
|
||||
void denoise(RenderTile &rtile, DenoisingTask& denoising, const DeviceTask &task)
|
||||
{
|
||||
DenoisingTask denoising(this);
|
||||
|
||||
denoising.functions.construct_transform = function_bind(&CUDADevice::denoising_construct_transform, this, &denoising);
|
||||
denoising.functions.reconstruct = function_bind(&CUDADevice::denoising_reconstruct, this, _1, _2, _3, &denoising);
|
||||
denoising.functions.divide_shadow = function_bind(&CUDADevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
|
||||
|
@ -1857,8 +1855,6 @@ public:
|
|||
CUDAContextScope scope(this);
|
||||
|
||||
if(task->type == DeviceTask::RENDER) {
|
||||
RenderTile tile;
|
||||
|
||||
DeviceRequestedFeatures requested_features;
|
||||
if(use_split_kernel()) {
|
||||
if(split_kernel == NULL) {
|
||||
|
@ -1870,6 +1866,9 @@ public:
|
|||
device_vector<WorkTile> work_tiles(this, "work_tiles", MEM_READ_ONLY);
|
||||
|
||||
/* keep rendering tiles until done */
|
||||
RenderTile tile;
|
||||
DenoisingTask denoising(this);
|
||||
|
||||
while(task->acquire_tile(this, tile)) {
|
||||
if(tile.task == RenderTile::PATH_TRACE) {
|
||||
if(use_split_kernel()) {
|
||||
|
@ -1883,7 +1882,7 @@ public:
|
|||
else if(tile.task == RenderTile::DENOISE) {
|
||||
tile.sample = tile.start_sample + tile.num_samples;
|
||||
|
||||
denoise(tile, *task);
|
||||
denoise(tile, denoising, *task);
|
||||
|
||||
task->update_progress(&tile, tile.w*tile.h);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,27 @@
|
|||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
DenoisingTask::DenoisingTask(Device *device)
|
||||
: tiles_mem(device, "denoising tiles_mem", MEM_READ_WRITE),
|
||||
storage(device),
|
||||
buffer(device),
|
||||
device(device)
|
||||
{
|
||||
}
|
||||
|
||||
DenoisingTask::~DenoisingTask()
|
||||
{
|
||||
storage.XtWX.free();
|
||||
storage.XtWY.free();
|
||||
storage.transform.free();
|
||||
storage.rank.free();
|
||||
storage.temporary_1.free();
|
||||
storage.temporary_2.free();
|
||||
storage.temporary_color.free();
|
||||
buffer.mem.free();
|
||||
tiles_mem.free();
|
||||
}
|
||||
|
||||
void DenoisingTask::init_from_devicetask(const DeviceTask &task)
|
||||
{
|
||||
radius = task.denoising_radius;
|
||||
|
@ -75,7 +96,7 @@ bool DenoisingTask::run_denoising()
|
|||
buffer.w = align_up(rect.z - rect.x, 4);
|
||||
buffer.h = rect.w - rect.y;
|
||||
buffer.pass_stride = align_up(buffer.w * buffer.h, divide_up(device->mem_address_alignment(), sizeof(float)));
|
||||
buffer.mem.alloc_to_device(buffer.pass_stride * buffer.passes);
|
||||
buffer.mem.alloc_to_device(buffer.pass_stride * buffer.passes, false);
|
||||
|
||||
device_ptr null_ptr = (device_ptr) 0;
|
||||
|
||||
|
@ -159,11 +180,10 @@ bool DenoisingTask::run_denoising()
|
|||
int variance_to[] = {11, 12, 13};
|
||||
int num_color_passes = 3;
|
||||
|
||||
device_only_memory<float> temp_color(device, "Denoising temporary color");
|
||||
temp_color.alloc_to_device(3*buffer.pass_stride);
|
||||
storage.temporary_color.alloc_to_device(3*buffer.pass_stride, false);
|
||||
|
||||
for(int pass = 0; pass < num_color_passes; pass++) {
|
||||
device_sub_ptr color_pass(temp_color, pass*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr color_pass(storage.temporary_color, pass*buffer.pass_stride, buffer.pass_stride);
|
||||
device_sub_ptr color_var_pass(buffer.mem, variance_to[pass]*buffer.pass_stride, buffer.pass_stride);
|
||||
functions.get_feature(mean_from[pass], variance_from[pass], *color_pass, *color_var_pass);
|
||||
}
|
||||
|
@ -172,28 +192,24 @@ bool DenoisingTask::run_denoising()
|
|||
device_sub_ptr depth_pass (buffer.mem, 0, buffer.pass_stride);
|
||||
device_sub_ptr color_var_pass(buffer.mem, variance_to[0]*buffer.pass_stride, 3*buffer.pass_stride);
|
||||
device_sub_ptr output_pass (buffer.mem, mean_to[0]*buffer.pass_stride, 3*buffer.pass_stride);
|
||||
functions.detect_outliers(temp_color.device_pointer, *color_var_pass, *depth_pass, *output_pass);
|
||||
functions.detect_outliers(storage.temporary_color.device_pointer, *color_var_pass, *depth_pass, *output_pass);
|
||||
}
|
||||
|
||||
temp_color.free();
|
||||
}
|
||||
|
||||
storage.w = filter_area.z;
|
||||
storage.h = filter_area.w;
|
||||
storage.transform.alloc_to_device(storage.w*storage.h*TRANSFORM_SIZE);
|
||||
storage.rank.alloc_to_device(storage.w*storage.h);
|
||||
storage.transform.alloc_to_device(storage.w*storage.h*TRANSFORM_SIZE, false);
|
||||
storage.rank.alloc_to_device(storage.w*storage.h, false);
|
||||
|
||||
functions.construct_transform();
|
||||
|
||||
device_only_memory<float> temporary_1(device, "Denoising NLM temporary 1");
|
||||
device_only_memory<float> temporary_2(device, "Denoising NLM temporary 2");
|
||||
temporary_1.alloc_to_device(buffer.w*buffer.h);
|
||||
temporary_2.alloc_to_device(buffer.w*buffer.h);
|
||||
reconstruction_state.temporary_1_ptr = temporary_1.device_pointer;
|
||||
reconstruction_state.temporary_2_ptr = temporary_2.device_pointer;
|
||||
storage.temporary_1.alloc_to_device(buffer.w*buffer.h, false);
|
||||
storage.temporary_2.alloc_to_device(buffer.w*buffer.h, false);
|
||||
reconstruction_state.temporary_1_ptr = storage.temporary_1.device_pointer;
|
||||
reconstruction_state.temporary_2_ptr = storage.temporary_2.device_pointer;
|
||||
|
||||
storage.XtWX.alloc_to_device(storage.w*storage.h*XTWX_SIZE);
|
||||
storage.XtWY.alloc_to_device(storage.w*storage.h*XTWY_SIZE);
|
||||
storage.XtWX.alloc_to_device(storage.w*storage.h*XTWX_SIZE, false);
|
||||
storage.XtWY.alloc_to_device(storage.w*storage.h*XTWY_SIZE, false);
|
||||
|
||||
reconstruction_state.filter_rect = make_int4(filter_area.x-rect.x, filter_area.y-rect.y, storage.w, storage.h);
|
||||
int tile_coordinate_offset = filter_area.y*render_buffer.stride + filter_area.x;
|
||||
|
@ -210,14 +226,6 @@ bool DenoisingTask::run_denoising()
|
|||
functions.reconstruct(*color_ptr, *color_var_ptr, render_buffer.ptr);
|
||||
}
|
||||
|
||||
storage.XtWX.free();
|
||||
storage.XtWY.free();
|
||||
storage.transform.free();
|
||||
storage.rank.free();
|
||||
temporary_1.free();
|
||||
temporary_2.free();
|
||||
buffer.mem.free();
|
||||
tiles_mem.free();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -121,6 +121,9 @@ public:
|
|||
device_only_memory<int> rank;
|
||||
device_only_memory<float> XtWX;
|
||||
device_only_memory<float3> XtWY;
|
||||
device_only_memory<float> temporary_1;
|
||||
device_only_memory<float> temporary_2;
|
||||
device_only_memory<float> temporary_color;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
|
@ -128,16 +131,15 @@ public:
|
|||
: transform(device, "denoising transform"),
|
||||
rank(device, "denoising rank"),
|
||||
XtWX(device, "denoising XtWX"),
|
||||
XtWY(device, "denoising XtWY")
|
||||
XtWY(device, "denoising XtWY"),
|
||||
temporary_1(device, "denoising NLM temporary 1"),
|
||||
temporary_2(device, "denoising NLM temporary 2"),
|
||||
temporary_color(device, "denoising temporary color")
|
||||
{}
|
||||
} storage;
|
||||
|
||||
DenoisingTask(Device *device)
|
||||
: tiles_mem(device, "denoising tiles_mem", MEM_READ_WRITE),
|
||||
storage(device),
|
||||
buffer(device),
|
||||
device(device)
|
||||
{}
|
||||
DenoisingTask(Device *device);
|
||||
~DenoisingTask();
|
||||
|
||||
void init_from_devicetask(const DeviceTask &task);
|
||||
|
||||
|
|
|
@ -243,15 +243,29 @@ public:
|
|||
free();
|
||||
}
|
||||
|
||||
void alloc_to_device(size_t num)
|
||||
void alloc_to_device(size_t num, bool shrink_to_fit = true)
|
||||
{
|
||||
data_size = num*sizeof(T);
|
||||
device_alloc();
|
||||
size_t new_size = num*sizeof(T);
|
||||
bool reallocate;
|
||||
|
||||
if(shrink_to_fit) {
|
||||
reallocate = (data_size != new_size);
|
||||
}
|
||||
else {
|
||||
reallocate = (data_size < new_size);
|
||||
}
|
||||
|
||||
if(reallocate) {
|
||||
device_free();
|
||||
data_size = new_size;
|
||||
device_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
void free()
|
||||
{
|
||||
device_free();
|
||||
data_size = 0;
|
||||
}
|
||||
|
||||
void zero_to_device()
|
||||
|
|
|
@ -360,7 +360,7 @@ public:
|
|||
void film_convert(DeviceTask& task, device_ptr buffer, device_ptr rgba_byte, device_ptr rgba_half);
|
||||
void shader(DeviceTask& task);
|
||||
|
||||
void denoise(RenderTile& tile, const DeviceTask& task);
|
||||
void denoise(RenderTile& tile, DenoisingTask& denoising, const DeviceTask& task);
|
||||
|
||||
class OpenCLDeviceTask : public DeviceTask {
|
||||
public:
|
||||
|
|
|
@ -1066,10 +1066,8 @@ bool OpenCLDeviceBase::denoising_set_tiles(device_ptr *buffers,
|
|||
return true;
|
||||
}
|
||||
|
||||
void OpenCLDeviceBase::denoise(RenderTile &rtile, const DeviceTask &task)
|
||||
void OpenCLDeviceBase::denoise(RenderTile &rtile, DenoisingTask& denoising, const DeviceTask &task)
|
||||
{
|
||||
DenoisingTask denoising(this);
|
||||
|
||||
denoising.functions.set_tiles = function_bind(&OpenCLDeviceBase::denoising_set_tiles, this, _1, &denoising);
|
||||
denoising.functions.construct_transform = function_bind(&OpenCLDeviceBase::denoising_construct_transform, this, &denoising);
|
||||
denoising.functions.reconstruct = function_bind(&OpenCLDeviceBase::denoising_reconstruct, this, _1, _2, _3, &denoising);
|
||||
|
|
|
@ -105,6 +105,8 @@ public:
|
|||
}
|
||||
else if(task->type == DeviceTask::RENDER) {
|
||||
RenderTile tile;
|
||||
DenoisingTask denoising(this);
|
||||
|
||||
/* Keep rendering tiles until done. */
|
||||
while(task->acquire_tile(this, tile)) {
|
||||
if(tile.task == RenderTile::PATH_TRACE) {
|
||||
|
@ -137,7 +139,7 @@ public:
|
|||
}
|
||||
else if(tile.task == RenderTile::DENOISE) {
|
||||
tile.sample = tile.start_sample + tile.num_samples;
|
||||
denoise(tile, *task);
|
||||
denoise(tile, denoising, *task);
|
||||
task->update_progress(&tile, tile.w*tile.h);
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,7 @@ public:
|
|||
}
|
||||
else if(task->type == DeviceTask::RENDER) {
|
||||
RenderTile tile;
|
||||
DenoisingTask denoising(this);
|
||||
|
||||
/* Allocate buffer for kernel globals */
|
||||
device_only_memory<KernelGlobalsDummy> kgbuffer(this, "kernel_globals");
|
||||
|
@ -155,7 +156,7 @@ public:
|
|||
}
|
||||
else if(tile.task == RenderTile::DENOISE) {
|
||||
tile.sample = tile.start_sample + tile.num_samples;
|
||||
denoise(tile, *task);
|
||||
denoise(tile, denoising, *task);
|
||||
task->update_progress(&tile, tile.w*tile.h);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue