[Bf-blender-cvs] [ab1c7a7] soc-2016-cycles_denoising: Render API/Cycles: Add separate "keep highlights" parameter to the end_result function to fix Save Buffers with Denoising

Lukas Stockner noreply at git.blender.org
Sat Aug 6 05:40:54 CEST 2016


Commit: ab1c7a717d0afa75e5c218641a8f068c6baf4465
Author: Lukas Stockner
Date:   Tue Jul 26 03:36:31 2016 +0200
Branches: soc-2016-cycles_denoising
https://developer.blender.org/rBab1c7a717d0afa75e5c218641a8f068c6baf4465

Render API/Cycles: Add separate "keep highlights" parameter to the end_result function to fix Save Buffers with Denoising

===================================================================

M	intern/cycles/blender/blender_session.cpp
A	intern/cycles/kernel/kernel_filter_old.h
M	source/blender/makesrna/intern/rna_render.c
M	source/blender/render/extern/include/RE_engine.h
M	source/blender/render/intern/source/external_engine.c

===================================================================

diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index b520fb6..84bcd26 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -318,9 +318,10 @@ static BL::RenderResult begin_render_result(BL::RenderEngine& b_engine,
 static void end_render_result(BL::RenderEngine& b_engine,
                               BL::RenderResult& b_rr,
                               bool cancel,
+                              bool highlight,
                               bool do_merge_results)
 {
-	b_engine.end_result(b_rr, (int)cancel, (int)do_merge_results);
+	b_engine.end_result(b_rr, (int)cancel, (int) highlight, (int)do_merge_results);
 }
 
 static void add_pass(BL::RenderEngine& b_engine,
@@ -368,12 +369,12 @@ void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_upda
 			update_render_result(b_rr, b_rlay, rtile);
 		}
 
-		end_render_result(b_engine, b_rr, highlight, true);
+		end_render_result(b_engine, b_rr, true, highlight, true);
 	}
 	else {
 		/* write result */
 		write_render_result(b_rr, b_rlay, rtile);
-		end_render_result(b_engine, b_rr, false, true);
+		end_render_result(b_engine, b_rr, false, false, true);
 	}
 }
 
@@ -420,7 +421,7 @@ void BlenderSession::render()
 
 		/* layer will be missing if it was disabled in the UI */
 		if(b_single_rlay == b_rr.layers.end()) {
-			end_render_result(b_engine, b_rr, true, false);
+			end_render_result(b_engine, b_rr, true, true, false);
 			continue;
 		}
 
@@ -526,7 +527,7 @@ void BlenderSession::render()
 		}
 
 		/* free result without merging */
-		end_render_result(b_engine, b_rr, true, false);
+		end_render_result(b_engine, b_rr, true, true, false);
 
 		if(session->progress.get_cancel())
 			break;
diff --git a/intern/cycles/kernel/kernel_filter_old.h b/intern/cycles/kernel/kernel_filter_old.h
new file mode 100644
index 0000000..fac52ec
--- /dev/null
+++ b/intern/cycles/kernel/kernel_filter_old.h
@@ -0,0 +1,748 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+/* Performs Singular Value Decomposition on A, fills V and S2 (containing the squares of the singular values) and returns the estimated rank */
+ccl_device int orig_svd(float *A, float *V, float *S2, int n)
+{
+	int  i, j, k, EstColRank = n, RotCount = n, SweepCount = 0;
+	int slimit = 8;
+	float eps = 1e-8f;
+	float e2 = 10.f * n * eps * eps;
+	float tol = 0.1f * eps;
+	float vt, p, x0, y0, q, r, c0, s0, d1, d2;
+
+	for(int r = 0; r < n; r++)
+		for(int c = 0; c < n; c++)
+			V[r*n+c] = (c == r)? 1.0f: 0.0f;
+
+	while (RotCount != 0 && SweepCount++ <= slimit) {
+		RotCount = EstColRank * (EstColRank - 1) / 2;
+
+		for (j = 0; j < EstColRank-1; ++j) {
+			for (k = j+1; k < EstColRank; ++k) {
+				p = q = r = 0.0;
+
+				for (i = 0; i < n; ++i) {
+					x0 = A[i * n + j];
+					y0 = A[i * n + k];
+					p += x0 * y0;
+					q += x0 * x0;
+					r += y0 * y0;
+				}
+
+				S2[j] = q;
+				S2[k] = r;
+
+				if (q >= r) {
+					if (q <= e2 * S2[0] || fabsf(p) <= tol * q)
+						RotCount--;
+					else {
+						p /= q;
+						r = 1.f - r/q;
+						vt = sqrtf(4.0f * p * p + r * r);
+						c0 = sqrtf(0.5f * (1.f + r / vt));
+						s0 = p / (vt*c0);
+
+						// Rotation
+						for (i = 0; i < n; ++i) {
+							d1 = A[i * n + j];
+							d2 = A[i * n + k];
+							A[i * n + j] = d1*c0+d2*s0;
+							A[i * n + k] = -d1*s0+d2*c0;
+						}
+						for (i = 0; i < n; ++i) {
+							d1 = V[i * n + j];
+							d2 = V[i * n + k];
+							V[i * n + j] = d1 * c0 + d2 * s0;
+							V[i * n + k] = -d1 * s0 + d2 * c0;
+						}
+					}
+				} else {
+					p /= r;
+					q = q / r - 1.f;
+					vt = sqrtf(4.f * p * p + q * q);
+					s0 = sqrtf(0.5f * (1.f - q / vt));
+					if (p < 0.f)
+						s0 = -s0;
+					c0 = p / (vt * s0);
+
+					// Rotation
+					for (i = 0; i < n; ++i) {
+						d1 = A[i * n + j];
+						d2 = A[i * n + k];
+						A[i * n + j] = d1 * c0 + d2 * s0;
+						A[i * n + k] = -d1 * s0 + d2 * c0;
+					}
+					for (i = 0; i < n; ++i) {
+						d1 = V[i * n + j];
+						d2 = V[i * n + k];
+						V[i * n + j] = d1 * c0 + d2 * s0;
+						V[i * n + k] = -d1 * s0 + d2 * c0;
+					}
+				}
+			}
+		}
+		while (EstColRank >= 3 && S2[EstColRank-1] <= S2[0] * tol + tol * tol)
+			EstColRank--;
+	}
+	return EstColRank;
+}
+
+ccl_device void orig_cholesky(float *A, int n, float *L)
+{
+	for (int i = 0; i < n; ++i) {
+		for (int j = 0; j <= i; ++j) {
+			float s = 0.0f;
+			for (int k = 0; k < j; ++k)
+				s += L[i * n + k] * L[j * n + k];
+			L[i * n + j] = (i == j) ? sqrtf(A[i * n + i] - s) : (1.0f / L[j * n + j] * (A[j * n + i] - s));
+		}
+	}
+}
+
+#define Buf_F(x, y, o) (buffers[((y) * w + (x)) * kernel_data.film.pass_stride + (o)])
+#define Buf_F3(x, y, o) *((float3*) (buffers + ((y) * w + (x)) * kernel_data.film.pass_stride + (o)))
+#define Buf_F4(x, y, o) *((float4*) (buffers + ((y) * w + (x)) * kernel_data.film.pass_stride + (o)))
+
+ccl_device_inline void filter_get_color_passes(KernelGlobals *kg, int &m_C, int &v_C)
+{
+	m_C = kernel_data.film.pass_denoising + 20;
+	v_C = kernel_data.film.pass_denoising + 23;
+}
+
+ccl_device void kernel_filter1_pixel(KernelGlobals *kg, float *buffers, int x, int y, int w, int h, int samples, int halfWindow, float bandwidthFactor, FilterStorage* storage)
+{
+	float invS = 1.0f / samples;
+	float invSv = 1.0f / (samples - 1);
+
+	int2 lo = make_int2(max(x - halfWindow, 0), max(y - halfWindow, 0));
+	int2 hi = make_int2(min(x + halfWindow, w-1), min(y + halfWindow, h-1));
+	int num = (hi.x - lo.x + 1) * (hi.y - lo.y + 1);
+
+	int m_D = kernel_data.film.pass_denoising + 12, v_D = kernel_data.film.pass_denoising + 13,
+	    m_N = kernel_data.film.pass_denoising, m_T = kernel_data.film.pass_denoising + 6,
+	    v_N = kernel_data.film.pass_denoising + 3, v_T = kernel_data.film.pass_denoising + 9,
+	    m_C, v_C;
+	filter_get_color_passes(kg, m_C, v_C);
+
+	float3 meanT = make_float3(0.0f, 0.0f, 0.0f);
+	float3 meanN = make_float3(0.0f, 0.0f, 0.0f);
+	float meanD = 0.0f;
+
+	for(int py = lo.y; py <= hi.y; py++) {
+		for(int px = lo.x; px <= hi.x; px++) {
+			meanT += Buf_F3(px, py, m_T) * invS;
+			meanN += Buf_F3(px, py, m_N) * invS;
+			meanD += Buf_F (px, py, m_D) * invS;
+		}
+	}
+	meanT /= num;
+	meanN /= num;
+	meanD /= num;
+
+#ifdef WITH_CYCLES_DEBUG_FILTER
+	storage->means[0] = meanN.x;
+	storage->means[1] = meanN.y;
+	storage->means[2] = meanN.z;
+	storage->means[3] = meanT.x;
+	storage->means[4] = meanT.y;
+	storage->means[5] = meanT.z;
+	storage->means[6] = meanD;
+#endif
+
+	float delta[9], transform[81], norm;
+	int rank;
+	/* Generate transform */
+	{
+		float top_nD = 0.0f;
+		float3 top_nN = make_float3(0.0f, 0.0f, 0.0f);
+		float3 top_nT = make_float3(0.0f, 0.0f, 0.0f);
+		for(int py = lo.y; py <= hi.y; py++) {
+			for(int px = lo.x; px <= hi.x; px++) {
+/* Instead of going for the highest value, which might be a firefly, the code uses the 5th highest value
+ * (kind of like a median filter, but we want to keep near the maximum for non-firefly pixels).
+ * To do that, the 5 highest values are kept around and every value is insertion-sorted into it if it belongs there.
+ * In the end, we can then just pick the smallest of the 5 values and have our percentile filter in linear time. */
+/*#define UPDATE_TOP(top, v, len) \
+	if(top[0] < v) { \
+		top[0] = v; \
+		for(int i = 0; i < (len)-1; i++) { \
+			if(top[i+1] >= top[i]) break; \
+			float t = top[i+1]; \
+			top[i+1] = top[i]; \
+			top[i] = t; \
+		} \
+	}*/
+#define UPDATE_TOP(top, v, len) if(top < v) top = v;
+#define UPDATE_TOP3(top, v, len) if(top.x < fabsf(v.x)) top.x = fabsf(v.x); if(top.y < fabsf(v.y)) top.y = fabsf(v.y); if(top.z < fabsf(v.z)) top.z = fabsf(v.z);
+				float nD = fabsf(Buf_F(px, py, m_D) * invS - meanD);
+				UPDATE_TOP(top_nD, nD, 5)
+				float3 nN = (Buf_F3(px, py, m_N) * invS - meanN);
+				UPDATE_TOP3(top_nN, nN, 5)
+				float3 nT = (Buf_F3(px, py, m_T) * invS - meanT);
+				UPDATE_TOP3(top_nT, nT, 5)
+#undef UPDATE_TOP
+			}
+		}
+
+		float nD = 1.0f / max(top_nD, 0.01f);
+		float3 nN = 1.0f / max(top_nN, make_float3(0.01f, 0.01f, 0.01f));
+		float3 nT = 1.0f / max(top_nT, make_float3(0.01f, 0.01f, 0.01f));
+
+		norm = 0.0f;
+		for(int i = 0; i < 81; i++)
+			transform[i] = 0.0f;
+		for(int py = lo.y; py <= hi.y; py++) {
+			for(int px = lo.x; px <= hi.x; px++) {
+				delta[0] = ((float) px - x) / halfWindow;
+				delta[1] = ((float) py - y) / halfWindow;
+				delta[2] = (Buf_F(px, py, m_D) * invS - meanD) * nD;
+				float3 dN = (Buf_F3(px, py, m_N) * invS - meanN) * nN;
+				delta[3] = dN.x;
+				delta[4] = dN.y;
+				delta[5] = dN.z;
+				float3 dT = (Buf_F3(px, py, m_T) * invS - meanT) * nT;
+				delta[6] = dT.x;
+				delta[7] = dT.y;
+				delta[8] = dT.z;
+
+				for(int r = 0; r < 9; r++)
+					for(int c = r; c < 9; c++)
+						transform[9*r+c] += delta[r]*delta[c];
+
+				//norm += 10.0f * nD * nD * Buf_F(px, py, v_D) * invSv * invS;
+				norm += nD*nD*Buf_F(px, py, v_D) * invSv * invS + 3.0f * average(nN * nN * Buf_F3(px, py, v_N) * invSv * invS) + 3.0f * average(nT * nT * Buf_F3(px, py, v_T) * invSv * invS);
+			}
+		}
+
+		/* Here, transform is self-adjoint (TODO term symmetric?) by construction, so one half can be copied from the other one */
+		for(int r = 1; r < 9; r++)
+			for(int c = 0; c < r; c++)
+				transform[9*r+c] = transform[9*c+r];
+
+		float V[81], S[9];
+		rank = orig_svd(transform, V, S, 9);
+
+		for(int i = 0; i < 9; i++) {
+			S[i] = sqrtf(fabsf(S[i]));
+#ifdef WITH_CYCLES_DEBUG_FILTER
+			storage->singular[i] = S[i];
+#endif
+		}
+
+#ifdef WITH_CYCLES_DEBUG_FILTER
+		storage->scales[0] = nN.x;
+		storage-

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list