Cycles Denoising: Split main function into logical steps
This commit is contained in:
@@ -732,8 +732,6 @@ public:
|
|||||||
task.map_neighbor_tiles(rtiles, this);
|
task.map_neighbor_tiles(rtiles, this);
|
||||||
denoising.tiles_from_rendertiles(rtiles);
|
denoising.tiles_from_rendertiles(rtiles);
|
||||||
|
|
||||||
denoising.init_from_devicetask(task);
|
|
||||||
|
|
||||||
denoising.run_denoising();
|
denoising.run_denoising();
|
||||||
|
|
||||||
task.unmap_neighbor_tiles(rtiles, this);
|
task.unmap_neighbor_tiles(rtiles, this);
|
||||||
@@ -766,7 +764,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
RenderTile tile;
|
RenderTile tile;
|
||||||
DenoisingTask denoising(this);
|
DenoisingTask denoising(this, task);
|
||||||
|
|
||||||
while(task.acquire_tile(this, tile)) {
|
while(task.acquire_tile(this, tile)) {
|
||||||
if(tile.task == RenderTile::PATH_TRACE) {
|
if(tile.task == RenderTile::PATH_TRACE) {
|
||||||
|
|||||||
@@ -1632,8 +1632,6 @@ public:
|
|||||||
task.map_neighbor_tiles(rtiles, this);
|
task.map_neighbor_tiles(rtiles, this);
|
||||||
denoising.tiles_from_rendertiles(rtiles);
|
denoising.tiles_from_rendertiles(rtiles);
|
||||||
|
|
||||||
denoising.init_from_devicetask(task);
|
|
||||||
|
|
||||||
denoising.run_denoising();
|
denoising.run_denoising();
|
||||||
|
|
||||||
task.unmap_neighbor_tiles(rtiles, this);
|
task.unmap_neighbor_tiles(rtiles, this);
|
||||||
@@ -2074,7 +2072,7 @@ public:
|
|||||||
|
|
||||||
/* keep rendering tiles until done */
|
/* keep rendering tiles until done */
|
||||||
RenderTile tile;
|
RenderTile tile;
|
||||||
DenoisingTask denoising(this);
|
DenoisingTask denoising(this, *task);
|
||||||
|
|
||||||
while(task->acquire_tile(this, tile)) {
|
while(task->acquire_tile(this, tile)) {
|
||||||
if(tile.task == RenderTile::PATH_TRACE) {
|
if(tile.task == RenderTile::PATH_TRACE) {
|
||||||
|
|||||||
@@ -20,12 +20,24 @@
|
|||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
DenoisingTask::DenoisingTask(Device *device)
|
DenoisingTask::DenoisingTask(Device *device, const DeviceTask &task)
|
||||||
: tiles_mem(device, "denoising tiles_mem", MEM_READ_WRITE),
|
: tiles_mem(device, "denoising tiles_mem", MEM_READ_WRITE),
|
||||||
storage(device),
|
storage(device),
|
||||||
buffer(device),
|
buffer(device),
|
||||||
device(device)
|
device(device)
|
||||||
{
|
{
|
||||||
|
radius = task.denoising_radius;
|
||||||
|
nlm_k_2 = powf(2.0f, lerp(-5.0f, 3.0f, task.denoising_strength));
|
||||||
|
if(task.denoising_relative_pca) {
|
||||||
|
pca_threshold = -powf(10.0f, lerp(-8.0f, 0.0f, task.denoising_feature_strength));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pca_threshold = powf(10.0f, lerp(-5.0f, 3.0f, task.denoising_feature_strength));
|
||||||
|
}
|
||||||
|
|
||||||
|
render_buffer.pass_stride = task.pass_stride;
|
||||||
|
render_buffer.denoising_data_offset = task.pass_denoising_data;
|
||||||
|
render_buffer.denoising_clean_offset = task.pass_denoising_clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
DenoisingTask::~DenoisingTask()
|
DenoisingTask::~DenoisingTask()
|
||||||
@@ -41,26 +53,6 @@ DenoisingTask::~DenoisingTask()
|
|||||||
tiles_mem.free();
|
tiles_mem.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DenoisingTask::init_from_devicetask(const DeviceTask &task)
|
|
||||||
{
|
|
||||||
radius = task.denoising_radius;
|
|
||||||
nlm_k_2 = powf(2.0f, lerp(-5.0f, 3.0f, task.denoising_strength));
|
|
||||||
if(task.denoising_relative_pca) {
|
|
||||||
pca_threshold = -powf(10.0f, lerp(-8.0f, 0.0f, task.denoising_feature_strength));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pca_threshold = powf(10.0f, lerp(-5.0f, 3.0f, task.denoising_feature_strength));
|
|
||||||
}
|
|
||||||
|
|
||||||
render_buffer.pass_stride = task.pass_stride;
|
|
||||||
render_buffer.denoising_data_offset = task.pass_denoising_data;
|
|
||||||
render_buffer.denoising_clean_offset = task.pass_denoising_clean;
|
|
||||||
|
|
||||||
/* Expand filter_area by radius pixels and clamp the result to the extent of the neighboring tiles */
|
|
||||||
rect = rect_from_shape(filter_area.x, filter_area.y, filter_area.z, filter_area.w);
|
|
||||||
rect = rect_expand(rect, radius);
|
|
||||||
rect = rect_clip(rect, make_int4(tiles->x[0], tiles->y[0], tiles->x[3], tiles->y[3]));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DenoisingTask::tiles_from_rendertiles(RenderTile *rtiles)
|
void DenoisingTask::tiles_from_rendertiles(RenderTile *rtiles)
|
||||||
{
|
{
|
||||||
@@ -88,20 +80,28 @@ void DenoisingTask::tiles_from_rendertiles(RenderTile *rtiles)
|
|||||||
functions.set_tiles(buffers);
|
functions.set_tiles(buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DenoisingTask::run_denoising()
|
void DenoisingTask::setup_denoising_buffer()
|
||||||
{
|
{
|
||||||
/* Allocate denoising buffer. */
|
/* Expand filter_area by radius pixels and clamp the result to the extent of the neighboring tiles */
|
||||||
|
rect = rect_from_shape(filter_area.x, filter_area.y, filter_area.z, filter_area.w);
|
||||||
|
rect = rect_expand(rect, radius);
|
||||||
|
rect = rect_clip(rect, make_int4(tiles->x[0], tiles->y[0], tiles->x[3], tiles->y[3]));
|
||||||
|
|
||||||
buffer.passes = 14;
|
buffer.passes = 14;
|
||||||
buffer.width = rect.z - rect.x;
|
buffer.width = rect.z - rect.x;
|
||||||
buffer.stride = align_up(buffer.width, 4);
|
buffer.stride = align_up(buffer.width, 4);
|
||||||
buffer.h = rect.w - rect.y;
|
buffer.h = rect.w - rect.y;
|
||||||
buffer.pass_stride = align_up(buffer.stride * buffer.h, divide_up(device->mem_sub_ptr_alignment(), sizeof(float)));
|
int alignment_floats = divide_up(device->mem_sub_ptr_alignment(), sizeof(float));
|
||||||
buffer.mem.alloc_to_device(buffer.pass_stride * buffer.passes, false);
|
buffer.pass_stride = align_up(buffer.stride * buffer.h, alignment_floats);
|
||||||
|
/* Pad the total size by four floats since the SIMD kernels might go a bit over the end. */
|
||||||
|
int mem_size = align_up(buffer.pass_stride * buffer.passes + 4, alignment_floats);
|
||||||
|
buffer.mem.alloc_to_device(mem_size, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenoisingTask::prefilter_shadowing()
|
||||||
|
{
|
||||||
device_ptr null_ptr = (device_ptr) 0;
|
device_ptr null_ptr = (device_ptr) 0;
|
||||||
|
|
||||||
/* Prefilter shadow feature. */
|
|
||||||
{
|
|
||||||
device_sub_ptr unfiltered_a (buffer.mem, 0, buffer.pass_stride);
|
device_sub_ptr unfiltered_a (buffer.mem, 0, buffer.pass_stride);
|
||||||
device_sub_ptr unfiltered_b (buffer.mem, 1*buffer.pass_stride, buffer.pass_stride);
|
device_sub_ptr unfiltered_b (buffer.mem, 1*buffer.pass_stride, buffer.pass_stride);
|
||||||
device_sub_ptr sample_var (buffer.mem, 2*buffer.pass_stride, buffer.pass_stride);
|
device_sub_ptr sample_var (buffer.mem, 2*buffer.pass_stride, buffer.pass_stride);
|
||||||
@@ -147,7 +147,7 @@ bool DenoisingTask::run_denoising()
|
|||||||
functions.combine_halves(final_a, final_b, *shadow_pass, null_ptr, 0, rect);
|
functions.combine_halves(final_a, final_b, *shadow_pass, null_ptr, 0, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prefilter general features. */
|
void DenoisingTask::prefilter_features()
|
||||||
{
|
{
|
||||||
device_sub_ptr unfiltered (buffer.mem, 8*buffer.pass_stride, buffer.pass_stride);
|
device_sub_ptr unfiltered (buffer.mem, 8*buffer.pass_stride, buffer.pass_stride);
|
||||||
device_sub_ptr variance (buffer.mem, 9*buffer.pass_stride, buffer.pass_stride);
|
device_sub_ptr variance (buffer.mem, 9*buffer.pass_stride, buffer.pass_stride);
|
||||||
@@ -172,7 +172,7 @@ bool DenoisingTask::run_denoising()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy color passes. */
|
void DenoisingTask::prefilter_color()
|
||||||
{
|
{
|
||||||
int mean_from[] = {20, 21, 22};
|
int mean_from[] = {20, 21, 22};
|
||||||
int variance_from[] = {23, 24, 25};
|
int variance_from[] = {23, 24, 25};
|
||||||
@@ -181,6 +181,13 @@ bool DenoisingTask::run_denoising()
|
|||||||
int num_color_passes = 3;
|
int num_color_passes = 3;
|
||||||
|
|
||||||
storage.temporary_color.alloc_to_device(3*buffer.pass_stride, false);
|
storage.temporary_color.alloc_to_device(3*buffer.pass_stride, false);
|
||||||
|
device_sub_ptr nlm_temporary_1(storage.temporary_color, 0*buffer.pass_stride, buffer.pass_stride);
|
||||||
|
device_sub_ptr nlm_temporary_2(storage.temporary_color, 1*buffer.pass_stride, buffer.pass_stride);
|
||||||
|
device_sub_ptr nlm_temporary_3(storage.temporary_color, 2*buffer.pass_stride, buffer.pass_stride);
|
||||||
|
|
||||||
|
nlm_state.temporary_1_ptr = *nlm_temporary_1;
|
||||||
|
nlm_state.temporary_2_ptr = *nlm_temporary_2;
|
||||||
|
nlm_state.temporary_3_ptr = *nlm_temporary_3;
|
||||||
|
|
||||||
for(int pass = 0; pass < num_color_passes; pass++) {
|
for(int pass = 0; pass < num_color_passes; pass++) {
|
||||||
device_sub_ptr color_pass(storage.temporary_color, pass*buffer.pass_stride, buffer.pass_stride);
|
device_sub_ptr color_pass(storage.temporary_color, pass*buffer.pass_stride, buffer.pass_stride);
|
||||||
@@ -188,20 +195,27 @@ bool DenoisingTask::run_denoising()
|
|||||||
functions.get_feature(mean_from[pass], variance_from[pass], *color_pass, *color_var_pass);
|
functions.get_feature(mean_from[pass], variance_from[pass], *color_pass, *color_var_pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
device_sub_ptr depth_pass (buffer.mem, 0, buffer.pass_stride);
|
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 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);
|
device_sub_ptr output_pass (buffer.mem, mean_to[0]*buffer.pass_stride, 3*buffer.pass_stride);
|
||||||
functions.detect_outliers(storage.temporary_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);
|
||||||
}
|
|
||||||
|
storage.temporary_color.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DenoisingTask::construct_transform()
|
||||||
|
{
|
||||||
storage.w = filter_area.z;
|
storage.w = filter_area.z;
|
||||||
storage.h = filter_area.w;
|
storage.h = filter_area.w;
|
||||||
|
|
||||||
storage.transform.alloc_to_device(storage.w*storage.h*TRANSFORM_SIZE, false);
|
storage.transform.alloc_to_device(storage.w*storage.h*TRANSFORM_SIZE, false);
|
||||||
storage.rank.alloc_to_device(storage.w*storage.h, false);
|
storage.rank.alloc_to_device(storage.w*storage.h, false);
|
||||||
|
|
||||||
functions.construct_transform();
|
functions.construct_transform();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenoisingTask::reconstruct()
|
||||||
|
{
|
||||||
|
|
||||||
device_only_memory<float> temporary_1(device, "Denoising NLM temporary 1");
|
device_only_memory<float> temporary_1(device, "Denoising NLM temporary 1");
|
||||||
device_only_memory<float> temporary_2(device, "Denoising NLM temporary 2");
|
device_only_memory<float> temporary_2(device, "Denoising NLM temporary 2");
|
||||||
@@ -222,13 +236,22 @@ bool DenoisingTask::run_denoising()
|
|||||||
reconstruction_state.source_w = rect.z-rect.x;
|
reconstruction_state.source_w = rect.z-rect.x;
|
||||||
reconstruction_state.source_h = rect.w-rect.y;
|
reconstruction_state.source_h = rect.w-rect.y;
|
||||||
|
|
||||||
{
|
|
||||||
device_sub_ptr color_ptr (buffer.mem, 8*buffer.pass_stride, 3*buffer.pass_stride);
|
device_sub_ptr color_ptr (buffer.mem, 8*buffer.pass_stride, 3*buffer.pass_stride);
|
||||||
device_sub_ptr color_var_ptr(buffer.mem, 11*buffer.pass_stride, 3*buffer.pass_stride);
|
device_sub_ptr color_var_ptr(buffer.mem, 11*buffer.pass_stride, 3*buffer.pass_stride);
|
||||||
functions.reconstruct(*color_ptr, *color_var_ptr, render_buffer.ptr);
|
functions.reconstruct(*color_ptr, *color_var_ptr, render_buffer.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
void DenoisingTask::run_denoising()
|
||||||
|
{
|
||||||
|
setup_denoising_buffer();
|
||||||
|
|
||||||
|
prefilter_shadowing();
|
||||||
|
prefilter_features();
|
||||||
|
prefilter_color();
|
||||||
|
|
||||||
|
construct_transform();
|
||||||
|
reconstruct();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|||||||
@@ -138,12 +138,10 @@ public:
|
|||||||
{}
|
{}
|
||||||
} storage;
|
} storage;
|
||||||
|
|
||||||
DenoisingTask(Device *device);
|
DenoisingTask(Device *device, const DeviceTask &task);
|
||||||
~DenoisingTask();
|
~DenoisingTask();
|
||||||
|
|
||||||
void init_from_devicetask(const DeviceTask &task);
|
void run_denoising();
|
||||||
|
|
||||||
bool run_denoising();
|
|
||||||
|
|
||||||
struct DenoiseBuffers {
|
struct DenoiseBuffers {
|
||||||
int pass_stride;
|
int pass_stride;
|
||||||
@@ -160,6 +158,14 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Device *device;
|
Device *device;
|
||||||
|
|
||||||
|
void set_render_buffer(RenderTile *rtiles);
|
||||||
|
void setup_denoising_buffer();
|
||||||
|
void prefilter_shadowing();
|
||||||
|
void prefilter_features();
|
||||||
|
void prefilter_color();
|
||||||
|
void construct_transform();
|
||||||
|
void reconstruct();
|
||||||
};
|
};
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|||||||
@@ -1095,8 +1095,6 @@ void OpenCLDeviceBase::denoise(RenderTile &rtile, DenoisingTask& denoising, cons
|
|||||||
task.map_neighbor_tiles(rtiles, this);
|
task.map_neighbor_tiles(rtiles, this);
|
||||||
denoising.tiles_from_rendertiles(rtiles);
|
denoising.tiles_from_rendertiles(rtiles);
|
||||||
|
|
||||||
denoising.init_from_devicetask(task);
|
|
||||||
|
|
||||||
denoising.run_denoising();
|
denoising.run_denoising();
|
||||||
|
|
||||||
task.unmap_neighbor_tiles(rtiles, this);
|
task.unmap_neighbor_tiles(rtiles, this);
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public:
|
|||||||
}
|
}
|
||||||
else if(task->type == DeviceTask::RENDER) {
|
else if(task->type == DeviceTask::RENDER) {
|
||||||
RenderTile tile;
|
RenderTile tile;
|
||||||
DenoisingTask denoising(this);
|
DenoisingTask denoising(this, *task);
|
||||||
|
|
||||||
/* Keep rendering tiles until done. */
|
/* Keep rendering tiles until done. */
|
||||||
while(task->acquire_tile(this, tile)) {
|
while(task->acquire_tile(this, tile)) {
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ public:
|
|||||||
}
|
}
|
||||||
else if(task->type == DeviceTask::RENDER) {
|
else if(task->type == DeviceTask::RENDER) {
|
||||||
RenderTile tile;
|
RenderTile tile;
|
||||||
DenoisingTask denoising(this);
|
DenoisingTask denoising(this, *task);
|
||||||
|
|
||||||
/* Allocate buffer for kernel globals */
|
/* Allocate buffer for kernel globals */
|
||||||
device_only_memory<KernelGlobalsDummy> kgbuffer(this, "kernel_globals");
|
device_only_memory<KernelGlobalsDummy> kgbuffer(this, "kernel_globals");
|
||||||
|
|||||||
Reference in New Issue
Block a user