[Bf-blender-cvs] [e020820] soc-2016-cycles_denoising: Cycles: Implement multi-frame denoising buffers
Lukas Stockner
noreply at git.blender.org
Sat Aug 13 05:12:38 CEST 2016
Commit: e0208200464f95533f9be128c5b5e43bc5bf6c8f
Author: Lukas Stockner
Date: Sat Aug 13 04:06:26 2016 +0200
Branches: soc-2016-cycles_denoising
https://developer.blender.org/rBe0208200464f95533f9be128c5b5e43bc5bf6c8f
Cycles: Implement multi-frame denoising buffers
This commit changes the prefiltering code so that it processes all included frames.
===================================================================
M intern/cycles/device/device_cpu.cpp
M intern/cycles/render/session.cpp
===================================================================
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index 9ca1d03..8d77a52d 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -208,7 +208,7 @@ public:
}
};
- float* denoise_fill_buffer(KernelGlobals *kg, int sample, int4 rect, float** buffers, int* tile_x, int* tile_y, int *offsets, int *strides)
+ float* denoise_fill_buffer(KernelGlobals *kg, int sample, int4 rect, float** buffers, int* tile_x, int* tile_y, int *offsets, int *strides, int frames, int *frame_strides)
{
void(*filter_divide_shadow)(KernelGlobals*, int, float**, int, int, int*, int*, int*, int*, float*, float*, float*, float*, int4);
void(*filter_get_feature)(KernelGlobals*, int, float**, int, int, int, int, int*, int*, int*, int*, float*, float*, int4);
@@ -268,144 +268,151 @@ public:
}
int w = align_up(rect.z - rect.x, 4), h = (rect.w - rect.y);
- float *filter_buffer = new float[22*w*h];
+ int pass_stride = w*h*frames;
+ float *filter_buffers = new float[22*pass_stride];
-
- /* ==== Step 1: Prefilter general features. ==== */
- {
- float *unfiltered = filter_buffer + 16*w*h;
- /* Order in render buffers:
- * Normal[X, Y, Z] NormalVar[X, Y, Z] Albedo[R, G, B] AlbedoVar[R, G, B ] Depth DepthVar
- * 0 1 2 3 4 5 6 7 8 9 10 11 12 13
- *
- * Order in denoise buffer:
- * Normal[X, XVar, Y, YVar, Z, ZVar] Depth DepthVar Shadow ShadowVar Albedo[R, RVar, G, GVar, B, BVar] Color[R, RVar, G, GVar, B, BVar]
- * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
- *
- * Order of processing: |NormalXYZ|Depth|AlbedoXYZ |
- * | | | | */
- int mean_from[] = { 0, 1, 2, 6, 7, 8, 12 };
- int variance_from[] = { 3, 4, 5, 9, 10, 11, 13 };
- int offset_to[] = { 0, 2, 4, 10, 12, 14, 6 };
- for(int i = 0; i < 7; i++) {
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = rect.x; x < rect.z; x++) {
- filter_get_feature(kg, sample, buffers, mean_from[i], variance_from[i], x, y, tile_x, tile_y, offsets, strides, unfiltered, filter_buffer + (offset_to[i]+1)*w*h, rect);
+ for(int frame = 0; frame < frames; frame++) {
+ float *filter_buffer = filter_buffers + w*h*frame;
+ float *buffer[9];
+ for(int i = 0; i < 9; i++) {
+ buffer[i] = buffers[i] + frame_strides[i]*frame;
+ }
+ /* ==== Step 1: Prefilter general features. ==== */
+ {
+ float *unfiltered = filter_buffer + 16*pass_stride;
+ /* Order in render buffers:
+ * Normal[X, Y, Z] NormalVar[X, Y, Z] Albedo[R, G, B] AlbedoVar[R, G, B ] Depth DepthVar
+ * 0 1 2 3 4 5 6 7 8 9 10 11 12 13
+ *
+ * Order in denoise buffer:
+ * Normal[X, XVar, Y, YVar, Z, ZVar] Depth DepthVar Shadow ShadowVar Albedo[R, RVar, G, GVar, B, BVar] Color[R, RVar, G, GVar, B, BVar]
+ * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
+ *
+ * Order of processing: |NormalXYZ|Depth|AlbedoXYZ |
+ * | | | | */
+ int mean_from[] = { 0, 1, 2, 6, 7, 8, 12 };
+ int variance_from[] = { 3, 4, 5, 9, 10, 11, 13 };
+ int offset_to[] = { 0, 2, 4, 10, 12, 14, 6 };
+ for(int i = 0; i < 7; i++) {
+ for(int y = rect.y; y < rect.w; y++) {
+ for(int x = rect.x; x < rect.z; x++) {
+ filter_get_feature(kg, sample, buffer, mean_from[i], variance_from[i], x, y, tile_x, tile_y, offsets, strides, unfiltered, filter_buffer + (offset_to[i]+1)*pass_stride, rect);
+ }
}
- }
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = rect.x; x < rect.z; x++) {
- filter_non_local_means(x, y, unfiltered, unfiltered, filter_buffer + (offset_to[i]+1)*w*h, filter_buffer + offset_to[i]*w*h, rect, 2, 2, 1, 0.25f);
+ for(int y = rect.y; y < rect.w; y++) {
+ for(int x = rect.x; x < rect.z; x++) {
+ filter_non_local_means(x, y, unfiltered, unfiltered, filter_buffer + (offset_to[i]+1)*pass_stride, filter_buffer + offset_to[i]*pass_stride, rect, 2, 2, 1, 0.25f);
+ }
}
- }
#ifdef WITH_CYCLES_DEBUG_FILTER
#define WRITE_DEBUG(name, var) debug_write_pfm(string_printf("debug_%dx%d_feature%d_%s.pfm", tile.x, tile.y, i, name).c_str(), var, w, h, 1, w)
- WRITE_DEBUG("unfiltered", unfiltered);
- WRITE_DEBUG("sampleV", filter_buffer + (offset_to[i]+1)*w*h);
- WRITE_DEBUG("filtered", filter_buffer + offset_to[i]*w*h);
+ WRITE_DEBUG("unfiltered", unfiltered);
+ WRITE_DEBUG("sampleV", filter_buffer + (offset_to[i]+1)*pass_stride);
+ WRITE_DEBUG("filtered", filter_buffer + offset_to[i]*pass_stride);
#undef WRITE_DEBUG
#endif
+ }
}
- }
- /* ==== Step 2: Prefilter shadow feature. ==== */
- {
- /* Reuse some passes of the filter_buffer for temporary storage. */
- float *sampleV = filter_buffer + 16*w*h, *sampleVV = filter_buffer + 17*w*h, *bufferV = filter_buffer + 18*w*h, *cleanV = filter_buffer + 19*w*h;
- float *unfiltered = filter_buffer + 20*w*h;
-
- /* Get the A/B unfiltered passes, the combined sample variance, the estimated variance of the sample variance and the buffer variance. */
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = rect.x; x < rect.z; x++) {
- filter_divide_shadow(kg, sample, buffers, x, y, tile_x, tile_y, offsets, strides, unfiltered, sampleV, sampleVV, bufferV, rect);
+ /* ==== Step 2: Prefilter shadow feature. ==== */
+ {
+ /* Reuse some passes of the filter_buffer for temporary storage. */
+ float *sampleV = filter_buffer + 16*pass_stride, *sampleVV = filter_buffer + 17*pass_stride, *bufferV = filter_buffer + 18*pass_stride, *cleanV = filter_buffer + 19*pass_stride;
+ float *unfiltered = filter_buffer + 20*pass_stride;
+
+ /* Get the A/B unfiltered passes, the combined sample variance, the estimated variance of the sample variance and the buffer variance. */
+ for(int y = rect.y; y < rect.w; y++) {
+ for(int x = rect.x; x < rect.z; x++) {
+ filter_divide_shadow(kg, sample, buffer, x, y, tile_x, tile_y, offsets, strides, unfiltered, sampleV, sampleVV, bufferV, rect);
+ }
}
- }
#ifdef WITH_CYCLES_DEBUG_FILTER
#define WRITE_DEBUG(name, var) debug_write_pfm(string_printf("debug_%dx%d_shadow_%s.pfm", tile.x, tile.y, name).c_str(), var, w, h, 1, w)
- WRITE_DEBUG("unfilteredA", unfiltered);
- WRITE_DEBUG("unfilteredB", unfiltered + w*h);
- WRITE_DEBUG("bufferV", bufferV);
- WRITE_DEBUG("sampleV", sampleV);
- WRITE_DEBUG("sampleVV", sampleVV);
+ WRITE_DEBUG("unfilteredA", unfiltered);
+ WRITE_DEBUG("unfilteredB", unfiltered + pass_stride);
+ WRITE_DEBUG("bufferV", bufferV);
+ WRITE_DEBUG("sampleV", sampleV);
+ WRITE_DEBUG("sampleVV", sampleVV);
#endif
- /* Smooth the (generally pretty noisy) buffer variance using the spatial information from the sample variance. */
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = rect.x; x < rect.z; x++) {
- filter_non_local_means(x, y, bufferV, sampleV, sampleVV, cleanV, rect, 3, 1, 4, 1.0f);
+ /* Smooth the (generally pretty noisy) buffer variance using the spatial information from the sample variance. */
+ for(int y = rect.y; y < rect.w; y++) {
+ for(int x = rect.x; x < rect.z; x++) {
+ filter_non_local_means(x, y, bufferV, sampleV, sampleVV, cleanV, rect, 3, 1, 4, 1.0f);
+ }
}
- }
#ifdef WITH_CYCLES_DEBUG_FILTER
- WRITE_DEBUG("cleanV", cleanV);
+ WRITE_DEBUG("cleanV", cleanV);
#endif
- /* Use the smoothed variance to filter the two shadow half images using each other for weight calculation. */
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = rect.x; x < rect.z; x++) {
- filter_non_local_means(x, y, unfiltered, unfiltered + w*h, cleanV, sampleV, rect, 5, 3, 1, 0.25f);
- filter_non_local_means(x, y, unfiltered + w*h, unfiltered, cleanV, bufferV, rect, 5, 3, 1, 0.25f);
+ /* Use the smoothed variance to filter the two shadow half images using each other for weight calculation. */
+ for(int y = rect.y; y < rect.w; y++) {
+ for(int x = rect.x; x < rect.z; x++) {
+ filter_non_local_means(x, y, unfiltered, unfiltered + pass_stride, cleanV, sampleV, rect, 5, 3, 1, 0.25f);
+ filter_non_local_means(x, y, unfiltered + pass_stride, unfiltered, cleanV, bufferV, rect, 5, 3, 1, 0.25f);
+ }
}
- }
#ifdef WITH_CYCLES_DEBUG_FILTER
- WRITE_DEBUG("filteredA", sampleV);
- WRITE_DEBUG("filteredB", bufferV);
+ WRITE_DEBUG("filteredA", sampleV);
+ WRITE_DEBUG("filteredB", bufferV);
#endif
- /* Estimate the residual variance between the two filtered halves. */
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = rect.x; x < rect.z; x++) {
- filter_combine_halves(x, y, NULL, sampleVV, sampleV, bufferV, rect);
+ /* Estimate the residual variance between the two filtered halves. */
+ for(int y = rect.y; y < rect.w; y++) {
+ for(int x = rect.x; x < rect.z; x++) {
+ filter_combine_halves(x, y, NULL, sampleVV, sampleV, bufferV, rect);
+ }
}
- }
#ifdef WITH_CYCLES_DEBUG_FILTER
- WRITE_DEBUG("residualV", sampleVV);
+ WRITE_DEBUG("residualV", sampleVV);
#endif
- /* Use the residual variance for a second filter pass. */
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = rect.x; x < rect.z; x++) {
- filter_non_local_means(x, y, sampleV, bufferV, sampleVV, unfiltered , rect, 4, 2, 1, 0.25f);
- filter_non_local_means(x, y, bufferV, sampleV, sampleVV, unfiltered + w*h, rect, 4, 2, 1, 0.25f);
+ /* Use the residual variance for a second filter pass. */
+ for(int y = rect.y; y < rect.w; y++) {
+ for(int x = rect.x; x < rect.z; x++) {
+ filter_non_local_means(x, y, sampleV, bufferV, sampleVV, unfiltered , rect, 4, 2, 1, 0.25f);
+ filter_non_local_means(x, y, bufferV, sampleV, sampleVV, unfiltered + pass_stride, rect, 4, 2, 1, 0.25f);
+ }
}
- }
#ifdef WITH_CYCLES_DEBUG_FILTER
- WRITE_DEBUG("
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list