[Bf-blender-cvs] [366262bef54] master: Distance Scrambling for for Cycles X - Sobol version

William Leeson noreply at git.blender.org
Tue Oct 26 16:13:43 CEST 2021


Commit: 366262bef5426fa98e75c96a1562dd16001fba26
Author: William Leeson
Date:   Tue Oct 26 08:30:15 2021 +0200
Branches: master
https://developer.blender.org/rB366262bef5426fa98e75c96a1562dd16001fba26

Distance Scrambling for for Cycles X - Sobol version

Cycles:Distance Scrambling for Cycles Sobol Sampler

This option implements micro jittering an is based on the INRIA
research paper [[ https://hal.inria.fr/hal-01325702/document | on micro jittering ]]
and work by Lukas Stockner for implementing the scrambling distance.
It works by controlling the correlation between pixels by either using
a user supplied value or an adaptive algorithm to limit the maximum
deviation of the sample values between pixels.

This is a follow up of https://developer.blender.org/D12316

The PMJ version can be found here: https://developer.blender.org/D12511

Reviewed By: leesonw

Differential Revision: https://developer.blender.org/D12318

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

M	intern/cycles/blender/addon/properties.py
M	intern/cycles/blender/addon/ui.py
M	intern/cycles/blender/sync.cpp
M	intern/cycles/integrator/path_trace_work_gpu.cpp
M	intern/cycles/integrator/tile.cpp
M	intern/cycles/integrator/tile.h
M	intern/cycles/integrator/work_tile_scheduler.cpp
M	intern/cycles/integrator/work_tile_scheduler.h
M	intern/cycles/kernel/sample/pattern.h
M	intern/cycles/kernel/types.h
M	intern/cycles/scene/integrator.cpp
M	intern/cycles/scene/integrator.h
M	intern/cycles/test/integrator_tile_test.cpp
M	release/datafiles/locale
M	release/scripts/addons
M	release/scripts/addons_contrib
M	source/tools

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

diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 0f92238015d..e5853529d1c 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -342,6 +342,24 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
         default='PROGRESSIVE_MUTI_JITTER',
     )
 
+    scrambling_distance: FloatProperty(
+        name="Scrambling Distance",
+        default=1.0,
+        min=0.0, max=1.0,
+        description="Lower values give faster rendering with GPU rendering and less noise with all devices at the cost of possible artifacts if set too low",
+    )
+    preview_scrambling_distance: BoolProperty(
+        name="Scrambling Distance viewport",
+        default=False,
+        description="Uses the Scrambling Distance value for the viewport. Faster but may flicker",
+    )
+
+    adaptive_scrambling_distance: BoolProperty(
+        name="Adaptive Scrambling Distance",
+        default=False,
+        description="Uses a formula to adapt the scrambling distance strength based on the sample count",
+    )
+
     use_layer_samples: EnumProperty(
         name="Layer Samples",
         description="How to use per view layer sample settings",
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index facf1b08676..47907481b03 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -289,6 +289,13 @@ class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
         col = layout.column(align=True)
         col.active = not(cscene.use_adaptive_sampling)
         col.prop(cscene, "sampling_pattern", text="Pattern")
+        col = layout.column(align=True)
+        col.active = cscene.sampling_pattern == 'SOBOL' and not cscene.use_adaptive_sampling
+        col.prop(cscene, "scrambling_distance", text="Scrambling Distance Strength")
+        col.prop(cscene, "adaptive_scrambling_distance", text="Adaptive Scrambling Distance")
+        col = layout.column(align=True)
+        col.active = ((cscene.scrambling_distance < 1.0) or cscene.adaptive_scrambling_distance) and cscene.sampling_pattern == 'SOBOL' and not cscene.use_adaptive_sampling
+        col.prop(cscene, "preview_scrambling_distance", text="Viewport Scrambling Distance")
 
         layout.separator()
 
diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp
index 73d3a4436b5..f6f490077a7 100644
--- a/intern/cycles/blender/sync.cpp
+++ b/intern/cycles/blender/sync.cpp
@@ -352,6 +352,21 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
     integrator->set_adaptive_min_samples(get_int(cscene, "adaptive_min_samples"));
   }
 
+  int samples = get_int(cscene, "samples");
+  float scrambling_distance = get_float(cscene, "scrambling_distance");
+  bool adaptive_scrambling_distance = get_boolean(cscene, "adaptive_scrambling_distance");
+  if (adaptive_scrambling_distance) {
+    scrambling_distance *= 4.0f / sqrtf(samples);
+  }
+
+  /* only use scrambling distance in the viewport if user wants to and disable with AS */
+  bool preview_scrambling_distance = get_boolean(cscene, "preview_scrambling_distance");
+  if ((preview && !preview_scrambling_distance) || sampling_pattern != SAMPLING_PATTERN_SOBOL)
+    scrambling_distance = 1.0f;
+
+  VLOG(1) << "Used Scrambling Distance: " << scrambling_distance;
+  integrator->set_scrambling_distance(scrambling_distance);
+
   if (get_boolean(cscene, "use_fast_gi")) {
     if (preview) {
       integrator->set_ao_bounces(get_int(cscene, "ao_bounces"));
diff --git a/intern/cycles/integrator/path_trace_work_gpu.cpp b/intern/cycles/integrator/path_trace_work_gpu.cpp
index b7dc4e5d181..251bec0dc8f 100644
--- a/intern/cycles/integrator/path_trace_work_gpu.cpp
+++ b/intern/cycles/integrator/path_trace_work_gpu.cpp
@@ -258,7 +258,10 @@ void PathTraceWorkGPU::render_samples(RenderStatistics &statistics,
    * schedules work in halves of available number of paths. */
   work_tile_scheduler_.set_max_num_path_states(max_num_paths_ / 8);
 
-  work_tile_scheduler_.reset(effective_buffer_params_, start_sample, samples_num);
+  work_tile_scheduler_.reset(effective_buffer_params_,
+                             start_sample,
+                             samples_num,
+                             device_scene_->data.integrator.scrambling_distance);
 
   enqueue_reset();
 
diff --git a/intern/cycles/integrator/tile.cpp b/intern/cycles/integrator/tile.cpp
index 7ea73451d80..b49e1b27b83 100644
--- a/intern/cycles/integrator/tile.cpp
+++ b/intern/cycles/integrator/tile.cpp
@@ -48,7 +48,8 @@ ccl_device_inline uint round_up_to_power_of_two(uint x)
 
 TileSize tile_calculate_best_size(const int2 &image_size,
                                   const int num_samples,
-                                  const int max_num_path_states)
+                                  const int max_num_path_states,
+                                  const float scrambling_distance)
 {
   if (max_num_path_states == 1) {
     /* Simple case: avoid any calculation, which could cause rounding issues. */
@@ -71,17 +72,54 @@ TileSize tile_calculate_best_size(const int2 &image_size,
    *  - Keep values a power of two, for more integer fit into the maximum number of paths. */
 
   TileSize tile_size;
-
-  /* Calculate tile size as if it is the most possible one to fit an entire range of samples.
-   * The idea here is to keep tiles as small as possible, and keep device occupied by scheduling
-   * multiple tiles with the same coordinates rendering different samples. */
   const int num_path_states_per_sample = max_num_path_states / num_samples;
-  if (num_path_states_per_sample != 0) {
-    tile_size.width = round_down_to_power_of_two(lround(sqrt(num_path_states_per_sample)));
-    tile_size.height = tile_size.width;
+  if (scrambling_distance < 0.9f) {
+    /* Prefer large tiles for scrambling distance. */
+    if (image_size.x * image_size.y <= num_path_states_per_sample) {
+      tile_size.width = image_size.x;
+      tile_size.height = image_size.y;
+    }
+    else {
+      /* Pick the option with the biggest tile size */
+      int heightOption = num_path_states_per_sample / image_size.x;
+      int widthOption = num_path_states_per_sample / image_size.y;
+      // Check if these options are possible
+      if ((heightOption > 0) || (widthOption > 0)) {
+        int area1 = image_size.x * heightOption;
+        int area2 = widthOption * image_size.y;
+        /* The option with the biggest pixel area */
+        if (area1 >= area2) {
+          tile_size.width = image_size.x;
+          tile_size.height = heightOption;
+        }
+        else {
+          tile_size.width = widthOption;
+          tile_size.height = image_size.y;
+        }
+      }
+      else {  // Large tiles are not an option so use square tiles
+        if (num_path_states_per_sample != 0) {
+          tile_size.width = round_down_to_power_of_two(lround(sqrt(num_path_states_per_sample)));
+          tile_size.height = tile_size.width;
+        }
+        else {
+          tile_size.width = tile_size.height = 1;
+        }
+      }
+    }
   }
   else {
-    tile_size.width = tile_size.height = 1;
+    /* Calculate tile size as if it is the most possible one to fit an entire range of samples.
+     * The idea here is to keep tiles as small as possible, and keep device occupied by scheduling
+     * multiple tiles with the same coordinates rendering different samples. */
+
+    if (num_path_states_per_sample != 0) {
+      tile_size.width = round_down_to_power_of_two(lround(sqrt(num_path_states_per_sample)));
+      tile_size.height = tile_size.width;
+    }
+    else {
+      tile_size.width = tile_size.height = 1;
+    }
   }
 
   if (num_samples == 1) {
@@ -93,7 +131,7 @@ TileSize tile_calculate_best_size(const int2 &image_size,
     tile_size.num_samples = min(round_up_to_power_of_two(lround(sqrt(num_samples / 2))),
                                 static_cast<uint>(num_samples));
 
-    const int tile_area = tile_size.width / tile_size.height;
+    const int tile_area = tile_size.width * tile_size.height;
     tile_size.num_samples = min(tile_size.num_samples, max_num_path_states / tile_area);
   }
 
diff --git a/intern/cycles/integrator/tile.h b/intern/cycles/integrator/tile.h
index 879c68b875c..61f7d736115 100644
--- a/intern/cycles/integrator/tile.h
+++ b/intern/cycles/integrator/tile.h
@@ -51,6 +51,7 @@ std::ostream &operator<<(std::ostream &os, const TileSize &tile_size);
  * possible, and have as many threads active for every tile as possible. */
 TileSize tile_calculate_best_size(const int2 &image_size,
                                   const int num_samples,
-                                  const int max_num_path_states);
+                                  const int max_num_path_states,
+                                  const float scrambling_distance);
 
 CCL_NAMESPACE_END
diff --git a/intern/cycles/integrator/work_tile_scheduler.cpp b/intern/cycles/integrator/work_tile_scheduler.cpp
index c874dffde91..2d1ac07db7f 100644
--- a/intern/cycles/integrator/work_tile_scheduler.cpp
+++ b/intern/cycles/integrator/work_tile_scheduler.cpp
@@ -33,13 +33,17 @@ void WorkTileScheduler::set_max_num_path_states(int max_num_path_states)
   max_num_path_states_ = max_num_path_states;
 }
 
-void WorkTileScheduler::reset(const BufferParams &buffer_params, int sample_start, int samples_num)
+void WorkTileScheduler::reset(const BufferParams &buffer_params,
+                              int sample_start,
+                              int samples_num,
+                              float scrambling_distance)
 {
   /* Image buffer parameters. */
   image_full_offset_px_.x = buffer_params.full_x;
   image_full_offset_px_.y = buffer_params.full_y;
 
   image_size_px_ = make_int2(buffer_params.width, buffer_params.height);
+  scrambling_distance_ = scrambling_distance;
 
   offset_ = buffer_params.offset;
   stride_ = buffer_params.stride;
@@ -54,7 +58,8 @@ void WorkTileScheduler::reset(const BufferParams &buffer_params, int sample_star
 
 void WorkTileScheduler::reset_scheduler_state()
 {
-  tile_size_ = tile_calculate_best_siz

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list