Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Leeson <leesonw>2021-10-26 09:30:15 +0300
committerWilliam Leeson <william@blender.org>2021-10-26 17:11:27 +0300
commit366262bef5426fa98e75c96a1562dd16001fba26 (patch)
tree80a4fd4c204d1e48bc25dd42bf93c6923e5959c4 /intern/cycles/integrator
parent4094868f7301ed06e6fd0710d1e9193796eb857d (diff)
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
Diffstat (limited to 'intern/cycles/integrator')
-rw-r--r--intern/cycles/integrator/path_trace_work_gpu.cpp5
-rw-r--r--intern/cycles/integrator/tile.cpp58
-rw-r--r--intern/cycles/integrator/tile.h3
-rw-r--r--intern/cycles/integrator/work_tile_scheduler.cpp9
-rw-r--r--intern/cycles/integrator/work_tile_scheduler.h8
5 files changed, 68 insertions, 15 deletions
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_size(image_size_px_, samples_num_, max_num_path_states_);
+ tile_size_ = tile_calculate_best_size(
+ image_size_px_, samples_num_, max_num_path_states_, scrambling_distance_);
VLOG(3) << "Will schedule tiles of size " << tile_size_;
diff --git a/intern/cycles/integrator/work_tile_scheduler.h b/intern/cycles/integrator/work_tile_scheduler.h
index 155bba5cb68..d9fa7e84431 100644
--- a/intern/cycles/integrator/work_tile_scheduler.h
+++ b/intern/cycles/integrator/work_tile_scheduler.h
@@ -38,7 +38,10 @@ class WorkTileScheduler {
void set_max_num_path_states(int max_num_path_states);
/* Scheduling will happen for pixels within a big tile denotes by its parameters. */
- void reset(const BufferParams &buffer_params, int sample_start, int samples_num);
+ void reset(const BufferParams &buffer_params,
+ int sample_start,
+ int samples_num,
+ float scrambling_distance);
/* Get work for a device.
* Returns true if there is still work to be done and initialize the work tile to all
@@ -68,6 +71,9 @@ class WorkTileScheduler {
* Will be passed over to the KernelWorkTile. */
int offset_, stride_;
+ /* Scrambling Distance requires adapted tile size */
+ float scrambling_distance_;
+
/* Start sample of index and number of samples which are to be rendered.
* The scheduler will cover samples range of [start, start + num] over the entire image
* (splitting into a smaller work tiles). */