Commit: d8b42751625c915113b64f5a2d9c72f19f009fee
Author: Alaska
Date:   Thu Dec 9 09:12:24 2021 +0100
Branches: master
https://developer.blender.org/rBd8b42751625c915113b64f5a2d9c72f19f009fee

Cycles-X: Add hysteresis to resolution divider algorithm

Adds hysteresis to the resolution divider algorithm to avoid having the 
resolution bounce around when on the boundary of two resolutions.

Reviewed By: brecht, leesonw

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

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

M       intern/cycles/integrator/render_scheduler.cpp
M       intern/cycles/integrator/render_scheduler.h

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

diff --git a/intern/cycles/integrator/render_scheduler.cpp 
b/intern/cycles/integrator/render_scheduler.cpp
index ac82b151f45..4a73955a95f 100644
--- a/intern/cycles/integrator/render_scheduler.cpp
+++ b/intern/cycles/integrator/render_scheduler.cpp
@@ -1085,14 +1085,8 @@ void RenderScheduler::update_start_resolution_divider()
                                         first_render_time_.denoise_time +
                                         first_render_time_.display_update_time;
 
-  /* Allow some percent of tolerance, so that if the render time is close 
enough to the higher
-   * resolution we prefer to use it instead of going way lower resolution and 
time way below the
-   * desired one. */
   const int resolution_divider_for_update = 
calculate_resolution_divider_for_time(
-      desired_update_interval_in_seconds * 1.4, actual_time_per_update);
-
-  /* TODO(sergey): Need to add hysteresis to avoid resolution divider bouncing 
around when actual
-   * render time is somewhere on a boundary between two resolutions. */
+      desired_update_interval_in_seconds, actual_time_per_update, 
start_resolution_divider_);
 
   /* Never increase resolution to higher than the pixel size (which is 
possible if the scene is
    * simple and compute device is fast). */
@@ -1179,12 +1173,14 @@ void RenderScheduler::check_time_limit_reached()
  * Utility functions.
  */
 
-int RenderScheduler::calculate_resolution_divider_for_time(double 
desired_time, double actual_time)
+int RenderScheduler::calculate_resolution_divider_for_time(double desired_time,
+                                                           double actual_time,
+                                                           int 
previous_resolution_divider)
 {
   /* TODO(sergey): There should a non-iterative analytical formula here. */
 
   int resolution_divider = 1;
-
+  double pre_division_time = actual_time;
   /* This algorithm iterates through resolution dividers until a divider is 
found that achieves
    * the desired render time. A limit of default_start_resolution_divider_ is 
put in place as the
    * maximum resolution divider to avoid an unreadable viewport due to a low 
resolution.
@@ -1192,12 +1188,26 @@ int 
RenderScheduler::calculate_resolution_divider_for_time(double desired_time,
    * calculation to better predict the performance impact of changing 
resolution divisions as
    * the sample count can also change between resolution divisions. */
   while (actual_time > desired_time && resolution_divider < 
default_start_resolution_divider_) {
+    pre_division_time = actual_time;
     int pre_resolution_division_samples = 
get_num_samples_during_navigation(resolution_divider);
     resolution_divider = resolution_divider * 2;
     int post_resolution_division_samples = 
get_num_samples_during_navigation(resolution_divider);
     actual_time /= 4.0 * pre_resolution_division_samples / 
post_resolution_division_samples;
   }
 
+  /* Hysteresis to avoid resolution divider bouncing around when actual render 
time is somewhere
+   * on a boundary between two resolutions. This system allows some percentage 
of tolerance so
+   * that the viewport tends towards remaining at higher resolutions rather 
than dropping to a
+   * lower resolution if performance is close to, but not quite reaching the 
target frame rate.
+   * This system also tends to not increase the viewport resolution unless the 
hardware can
+   * exceed the performance target by a certain percentage. This is to help 
ensure the viewport
+   * remains responsive after increasing the resolution. */
+  if (resolution_divider > previous_resolution_divider && pre_division_time < 
desired_time * 1.5) {
+    return resolution_divider / 2;
+  }
+  if (resolution_divider < previous_resolution_divider && pre_division_time > 
desired_time / 1.3) {
+    return resolution_divider * 2;
+  }
   return resolution_divider;
 }
 
diff --git a/intern/cycles/integrator/render_scheduler.h 
b/intern/cycles/integrator/render_scheduler.h
index 28f563c46e3..705bb3b46ba 100644
--- a/intern/cycles/integrator/render_scheduler.h
+++ b/intern/cycles/integrator/render_scheduler.h
@@ -462,7 +462,9 @@ class RenderScheduler {
    * desired one. This call assumes linear dependency of render time from 
number of pixels
    * (quadratic dependency from the resolution divider): resolution divider of 
2 brings render time
    * down by a factor of 4. */
-  int calculate_resolution_divider_for_time(double desired_time, double 
actual_time);
+  int calculate_resolution_divider_for_time(double desired_time,
+                                            double actual_time,
+                                            int previous_resolution_divider);
 };
 
 int calculate_resolution_divider_for_resolution(int width, int height, int 
resolution);

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to