Commit: 24c74f23a2d8b86574c948ee8134041561b19050
Author: Mai Lavelle
Date:   Wed Dec 14 04:17:28 2016 -0500
Branches: cycles_split_kernel
https://developer.blender.org/rB24c74f23a2d8b86574c948ee8134041561b19050

Cycles: Tile updates for split kernel

Better feedback is given from tiles by updating while rendering, where
as before tiles would only be displayed when fully complete. Rendering
is a little slower from this, but there may be ways to reduce that
effect at some point.

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

M       intern/cycles/device/device_cpu.cpp
M       intern/cycles/device/device_split_kernel.cpp
M       intern/cycles/device/device_split_kernel.h
M       intern/cycles/device/opencl/opencl_split.cpp

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

diff --git a/intern/cycles/device/device_cpu.cpp 
b/intern/cycles/device/device_cpu.cpp
index 3511195..3811e43 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -455,8 +455,6 @@ public:
                        device_memory data;
                        split_kernel.path_trace(&task, tile, data);
 
-                       tile.sample = tile.start_sample + tile.num_samples;
-
                        task.release_tile(tile);
 
                        if(task_pool.canceled()) {
diff --git a/intern/cycles/device/device_split_kernel.cpp 
b/intern/cycles/device/device_split_kernel.cpp
index d400bfb..dcbb682 100644
--- a/intern/cycles/device/device_split_kernel.cpp
+++ b/intern/cycles/device/device_split_kernel.cpp
@@ -19,13 +19,18 @@
 #include "kernel_types.h"
 #include "kernel_split_data.h"
 
+#include "util_time.h"
+
 CCL_NAMESPACE_BEGIN
 
+static const double alpha = 0.1; /* alpha for rolling average */
+
 DeviceSplitKernel::DeviceSplitKernel(Device *device) : device(device)
 {
-       path_iteration_times = PATH_ITER_INC_FACTOR;
        current_max_closure = -1;
        first_tile = true;
+
+       avg_time_per_sample = 0.0;
 }
 
 DeviceSplitKernel::~DeviceSplitKernel()
@@ -211,26 +216,6 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
                device->mem_alloc("split_data", split_data, MEM_READ_WRITE);
        }
 
-       if(device->have_error()) {
-               return false;
-       }
-
-       
if(!device->enqueue_split_kernel_data_init(KernelDimensions(global_size, 
local_size),
-                                                  tile,
-                                                  num_global_elements,
-                                                  num_parallel_samples,
-                                                  kgbuffer,
-                                                  kernel_data,
-                                                  split_data,
-                                                  ray_state,
-                                                  queue_index,
-                                                  use_queues_flag,
-                                                  work_pool_wgs
-                                                  ))
-       {
-               return false;
-       }
-
 #define ENQUEUE_SPLIT_KERNEL(name, global_size, local_size) \
                if(device->have_error()) { \
                        return false; \
@@ -239,72 +224,96 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
                        return false; \
                }
 
-       /* Record number of time host intervention has been made */
-       unsigned int numHostIntervention = 0;
-       unsigned int numNextPathIterTimes = path_iteration_times;
-       bool canceled = false;
-
-       bool activeRaysAvailable = true;
-       while(activeRaysAvailable) {
-               /* Twice the global work size of other kernels for
-                * ckPathTraceKernel_shadow_blocked_direct_lighting. */
-               size_t global_size_shadow_blocked[2];
-               global_size_shadow_blocked[0] = global_size[0] * 2;
-               global_size_shadow_blocked[1] = global_size[1];
-
-               /* Do path-iteration in host [Enqueue Path-iteration kernels. */
-               for(int PathIter = 0; PathIter < path_iteration_times; 
PathIter++) {
-                       ENQUEUE_SPLIT_KERNEL(scene_intersect, global_size, 
local_size);
-                       ENQUEUE_SPLIT_KERNEL(lamp_emission, global_size, 
local_size);
-                       ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, 
local_size);
-                       ENQUEUE_SPLIT_KERNEL(background_buffer_update, 
global_size, local_size);
-                       ENQUEUE_SPLIT_KERNEL(shader_eval, global_size, 
local_size);
-                       
ENQUEUE_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao, global_size, 
local_size);
-                       ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, 
local_size);
-                       ENQUEUE_SPLIT_KERNEL(shadow_blocked, 
global_size_shadow_blocked, local_size);
-                       ENQUEUE_SPLIT_KERNEL(next_iteration_setup, global_size, 
local_size);
+       tile.sample = tile.start_sample;
 
-                       if(task->get_cancel()) {
-                               canceled = true;
-                               break;
-                       }
-               }
+       while(tile.sample < tile.start_sample + tile.num_samples) {
+               /* to keep track of how long it takes to run a number of 
samples */
+               double start_time = time_dt();
 
-               /* Decide if we should exit path-iteration in host. */
-               device->mem_copy_from(ray_state, 0, global_size[0] * 
global_size[1] * sizeof(char), 1, 1);
+               /* initial guess to start rolling average */
+               const int initial_num_samples = 1;
+               /* approx number of samples per second */
+               int samples_per_second = (avg_time_per_sample > 0.0) ?
+                                        int(1.0 / avg_time_per_sample) + 1 : 
initial_num_samples;
 
-               activeRaysAvailable = false;
+               RenderTile subtile = tile;
+               subtile.start_sample = tile.sample;
+               subtile.num_samples = min(samples_per_second, tile.start_sample 
+ tile.num_samples - tile.sample);
 
-               for(int rayStateIter = 0;
-                   rayStateIter < global_size[0] * global_size[1];
-                   ++rayStateIter)
+               if(device->have_error()) {
+                       return false;
+               }
+
+               
if(!device->enqueue_split_kernel_data_init(KernelDimensions(global_size, 
local_size),
+                                                          subtile,
+                                                          num_global_elements,
+                                                          num_parallel_samples,
+                                                          kgbuffer,
+                                                          kernel_data,
+                                                          split_data,
+                                                          ray_state,
+                                                          queue_index,
+                                                          use_queues_flag,
+                                                          work_pool_wgs
+                                                          ))
                {
-                       if(int8_t(ray_state.get_data()[rayStateIter]) != 
RAY_INACTIVE) {
-                               /* Not all rays are RAY_INACTIVE. */
-                               activeRaysAvailable = true;
-                               break;
-                       }
+                       return false;
                }
 
-               if(activeRaysAvailable) {
-                       numHostIntervention++;
-                       path_iteration_times = PATH_ITER_INC_FACTOR;
-                       /* Host intervention done before all rays become 
RAY_INACTIVE;
-                        * Set do more initial iterations for the next tile.
-                        */
-                       numNextPathIterTimes += PATH_ITER_INC_FACTOR;
+               bool activeRaysAvailable = true;
+
+               while(activeRaysAvailable) {
+                       /* Twice the global work size of other kernels for
+                        * ckPathTraceKernel_shadow_blocked_direct_lighting. */
+                       size_t global_size_shadow_blocked[2];
+                       global_size_shadow_blocked[0] = global_size[0] * 2;
+                       global_size_shadow_blocked[1] = global_size[1];
+
+                       /* Do path-iteration in host [Enqueue Path-iteration 
kernels. */
+                       for(int PathIter = 0; PathIter < 16; PathIter++) {
+                               ENQUEUE_SPLIT_KERNEL(scene_intersect, 
global_size, local_size);
+                               ENQUEUE_SPLIT_KERNEL(lamp_emission, 
global_size, local_size);
+                               ENQUEUE_SPLIT_KERNEL(queue_enqueue, 
global_size, local_size);
+                               ENQUEUE_SPLIT_KERNEL(background_buffer_update, 
global_size, local_size);
+                               ENQUEUE_SPLIT_KERNEL(shader_eval, global_size, 
local_size);
+                               
ENQUEUE_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao, global_size, 
local_size);
+                               ENQUEUE_SPLIT_KERNEL(direct_lighting, 
global_size, local_size);
+                               ENQUEUE_SPLIT_KERNEL(shadow_blocked, 
global_size_shadow_blocked, local_size);
+                               ENQUEUE_SPLIT_KERNEL(next_iteration_setup, 
global_size, local_size);
+
+                               if(task->get_cancel()) {
+                                       return true;
+                               }
+                       }
+
+                       /* Decide if we should exit path-iteration in host. */
+                       device->mem_copy_from(ray_state, 0, global_size[0] * 
global_size[1] * sizeof(char), 1, 1);
+
+                       activeRaysAvailable = false;
+
+                       for(int rayStateIter = 0; rayStateIter < global_size[0] 
* global_size[1]; ++rayStateIter) {
+                               if(int8_t(ray_state.get_data()[rayStateIter]) 
!= RAY_INACTIVE) {
+                                       /* Not all rays are RAY_INACTIVE. */
+                                       activeRaysAvailable = true;
+                                       break;
+                               }
+                       }
+
+                       if(task->get_cancel()) {
+                               return true;
+                       }
                }
 
-               if(task->get_cancel()) {
-                       canceled = true;
-                       break;
+               double time_per_sample = ((time_dt()-start_time) / 
subtile.num_samples);
+
+               if(avg_time_per_sample == 0.0) {
+                       /* start rolling average */
+                       avg_time_per_sample = time_per_sample;
+               }
+               else {
+                       avg_time_per_sample = alpha*time_per_sample + 
(1.0-alpha)*avg_time_per_sample;
                }
-       }
 
-       /* Execute SumALLRadiance kernel to accumulate radiance calculated in
-        * per_sample_output_buffers into RenderTile's output buffer.
-        */
-       if(!canceled) {
                size_t sum_all_radiance_local_size[2] = {16, 16};
                size_t sum_all_radiance_global_size[2];
                sum_all_radiance_global_size[0] =
@@ -317,22 +326,15 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
                ENQUEUE_SPLIT_KERNEL(sum_all_radiance,
                                     sum_all_radiance_global_size,
                                     sum_all_radiance_local_size);
-       }
 
 #undef ENQUEUE_SPLIT_KERNEL
 
-       if(numHostIntervention == 0) {
-               /* This means that we are executing kernel more than required
-                * Must avoid this for the next sample/tile.
-                */
-               path_iteration_times = ((numNextPathIterTimes - 
PATH_ITER_INC_FACTOR) <= 0) ?
-               PATH_ITER_INC_FACTOR : numNextPathIterTimes - 
PATH_ITER_INC_FACTOR;
-       }
-       else {
-               /* Number of path-iterations done for this tile is set as
-                * Initial path-iteration times for the next tile
-                */
-               path_iteration_times = numNextPathIterTimes;
+               tile.sample += subtile.num_samples;
+               task->update_progress(&tile, tile.w*tile.h*subtile.num_samples);
+
+               if(task->get_cancel()) {
+                       return true;
+               }
        }
 
        return true;
diff --git a/intern/cycles/device/device_split_kernel.h 
b/intern/cycles/device/device_split_kernel.h
index 78bbfc7..e4567b3 100644
--- a/intern/cycles/device/device_split_kernel.h
+++ b/intern/cycles/device/device_split_kernel.h
@@ -22,13 +22,6 @@
 
 CCL_NAMESPACE_BEGIN
 
-/* This value may be tuned according to the scene we are rendering.
- *
- * Modifying PATH_ITER_INC_FACTOR value proportional to number of expected
- * ray-bounces will improve performance.
- */
-#define PATH_ITER_INC_FACTOR 8
-
 /* When allocate global memory in chunks. We may not be able to
  * allocate exactly "CL_DEVICE_MAX_MEM_ALLOC_SIZE" bytes in chunks;
  * Since some bytes may be needed for aligning chunks of memory;
@@ -64,8 +57,8 @@ private:
        /* Flag to make sceneintersect and lampemission kernel use queues. */
        device_memory use_queues_flag;
 
-       /* Number of path-iterations to be done in one shot. */
-       unsigned int path_iteration_times;
+       /* Approximate time it takes to complete one sample */
+       double avg_time_per_sample;
 
        /* Work pool with respect to each w

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to