Cycles: Improve denoising speed on GPUs with small tile sizes
[blender.git] / intern / cycles / util / util_math_matrix.h
index 7269d391956780acc212fdb54882f20333045089..382dad64ea5e6939970f08c8319b248ecf58daf9 100644 (file)
@@ -98,7 +98,10 @@ ccl_device_inline void math_vec3_add(float3 *v, int n, float *x, float3 w)
 ccl_device_inline void math_vec3_add_strided(ccl_global float3 *v, int n, float *x, float3 w, int stride)
 {
        for(int i = 0; i < n; i++) {
-               v[i*stride] += w*x[i];
+               ccl_global float *elem = (ccl_global float*) (v + i*stride);
+               atomic_add_and_fetch_float(elem+0, w.x*x[i]);
+               atomic_add_and_fetch_float(elem+1, w.y*x[i]);
+               atomic_add_and_fetch_float(elem+2, w.z*x[i]);
        }
 }
 
@@ -136,7 +139,7 @@ ccl_device_inline void math_trimatrix_add_gramian_strided(ccl_global float *A,
 {
        for(int row = 0; row < n; row++) {
                for(int col = 0; col <= row; col++) {
-                       MATHS(A, row, col, stride) += v[row]*v[col]*weight;
+                       atomic_add_and_fetch_float(&MATHS(A, row, col, stride), v[row]*v[col]*weight);
                }
        }
 }
@@ -223,20 +226,20 @@ ccl_device void math_matrix_jacobi_eigendecomposition(float *A, ccl_global float
 {
        const float singular_epsilon = 1e-9f;
 
-       for (int row = 0; row < n; row++) {
-               for (int col = 0; col < n; col++) {
+       for(int row = 0; row < n; row++) {
+               for(int col = 0; col < n; col++) {
                        MATS(V, n, row, col, v_stride) = (col == row) ? 1.0f : 0.0f;
                }
        }
 
-       for (int sweep = 0; sweep < 8; sweep++) {
+       for(int sweep = 0; sweep < 8; sweep++) {
                float off_diagonal = 0.0f;
-               for (int row = 1; row < n; row++) {
-                       for (int col = 0; col < row; col++) {
+               for(int row = 1; row < n; row++) {
+                       for(int col = 0; col < row; col++) {
                                off_diagonal += fabsf(MAT(A, n, row, col));
                        }
                }
-               if (off_diagonal < 1e-7f) {
+               if(off_diagonal < 1e-7f) {
                        /* The matrix has nearly reached diagonal form.
                         * Since the eigenvalues are only used to determine truncation, their exact values aren't required - a relative error of a few ULPs won't matter at all. */
                        break;
@@ -253,7 +256,7 @@ ccl_device void math_matrix_jacobi_eigendecomposition(float *A, ccl_global float
                                float abs_element = fabsf(element);
 
                                /* If we're in a later sweep and the element already is very small, just set it to zero and skip the rotation. */
-                               if (sweep > 3 && abs_element <= singular_epsilon*fabsf(MAT(A, n, row, row)) && abs_element <= singular_epsilon*fabsf(MAT(A, n, col, col))) {
+                               if(sweep > 3 && abs_element <= singular_epsilon*fabsf(MAT(A, n, row, row)) && abs_element <= singular_epsilon*fabsf(MAT(A, n, col, col))) {
                                        MAT(A, n, row, col) = 0.0f;
                                        continue;
                                }
@@ -272,10 +275,10 @@ ccl_device void math_matrix_jacobi_eigendecomposition(float *A, ccl_global float
                                 * Then, we compute sin(phi) and cos(phi) themselves. */
                                float singular_diff = MAT(A, n, row, row) - MAT(A, n, col, col);
                                float ratio;
-                               if (abs_element > singular_epsilon*fabsf(singular_diff)) {
+                               if(abs_element > singular_epsilon*fabsf(singular_diff)) {
                                        float cot_2phi = 0.5f*singular_diff / element;
                                        ratio = 1.0f / (fabsf(cot_2phi) + sqrtf(1.0f + cot_2phi*cot_2phi));
-                                       if (cot_2phi < 0.0f) ratio = -ratio; /* Copy sign. */
+                                       if(cot_2phi < 0.0f) ratio = -ratio; /* Copy sign. */
                                }
                                else {
                                        ratio = element / singular_diff;
@@ -315,21 +318,21 @@ ccl_device void math_matrix_jacobi_eigendecomposition(float *A, ccl_global float
        }
 
        /* Sort eigenvalues and the associated eigenvectors. */
-       for (int i = 0; i < n - 1; i++) {
+       for(int i = 0; i < n - 1; i++) {
                float v = MAT(A, n, i, i);
                int k = i;
-               for (int j = i; j < n; j++) {
-                       if (MAT(A, n, j, j) >= v) {
+               for(int j = i; j < n; j++) {
+                       if(MAT(A, n, j, j) >= v) {
                                v = MAT(A, n, j, j);
                                k = j;
                        }
                }
-               if (k != i) {
+               if(k != i) {
                        /* Swap eigenvalues. */
                        MAT(A, n, k, k) = MAT(A, n, i, i);
                        MAT(A, n, i, i) = v;
                        /* Swap eigenvectors. */
-                       for (int j = 0; j < n; j++) {
+                       for(int j = 0; j < n; j++) {
                                float v = MATS(V, n, i, j, v_stride);
                                MATS(V, n, i, j, v_stride) = MATS(V, n, k, j, v_stride);
                                MATS(V, n, k, j, v_stride) = v;