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