Fix T51560: Black pixels on a denoising render
authorLukas Stockner <lukas.stockner@freenet.de>
Fri, 19 May 2017 21:04:13 +0000 (23:04 +0200)
committerLukas Stockner <lukas.stockner@freenet.de>
Fri, 19 May 2017 21:31:49 +0000 (23:31 +0200)
Once again, numerical instabilities causing the Cholesky decomposition to fail.

However, further increasing the diagonal correction just because of a few
pixels in very specific scenes and settings seems unjustified.
Therefore, this commit simply falls back to the basic NLM-filtered pixel
if the more advanced model fails.

intern/cycles/kernel/filter/filter_reconstruction.h
intern/cycles/util/util_math_float3.h

index 13e90f8233bd03dddba80b21529146818f096497..dc90f318570d1f0e847a52b75bd470422d70644e 100644 (file)
@@ -85,9 +85,17 @@ ccl_device_inline void kernel_filter_finalize(int x, int y, int w, int h,
        const int stride = storage_stride;
 #endif
 
        const int stride = storage_stride;
 #endif
 
+       /* The weighted average of pixel colors (essentially, the NLM-filtered image).
+        * In case the solution of the linear model fails due to numerical issues,
+        * fall back to this value. */
+       float3 mean_color = XtWY[0]/XtWX[0];
+
        math_trimatrix_vec3_solve(XtWX, XtWY, (*rank)+1, stride);
 
        float3 final_color = XtWY[0];
        math_trimatrix_vec3_solve(XtWX, XtWY, (*rank)+1, stride);
 
        float3 final_color = XtWY[0];
+       if(!isfinite3_safe(final_color)) {
+               final_color = mean_color;
+       }
 
        ccl_global float *combined_buffer = buffer + (y*buffer_params.y + x + buffer_params.x)*buffer_params.z;
        final_color *= sample;
 
        ccl_global float *combined_buffer = buffer + (y*buffer_params.y + x + buffer_params.x)*buffer_params.z;
        final_color *= sample;
index a754be413fedbc7f5aaa1fcf06d97d13551adcde..5327d9f7cc6c801ca67dad3f64a79e74182a4a90 100644 (file)
@@ -367,6 +367,11 @@ ccl_device_inline bool isequal_float3(const float3 a, const float3 b)
 #endif
 }
 
 #endif
 }
 
+ccl_device_inline bool isfinite3_safe(float3 v)
+{
+       return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z);
+}
+
 ccl_device_inline float3 ensure_finite3(float3 v)
 {
        if(!isfinite_safe(v.x)) v.x = 0.0;
 ccl_device_inline float3 ensure_finite3(float3 v)
 {
        if(!isfinite_safe(v.x)) v.x = 0.0;