1 /*
2 * Copyright 2011-2013 Blender Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include "device/device_task.h"
21
22 #include "render/buffers.h"
23
24 #include "util/util_algorithm.h"
25 #include "util/util_time.h"
26
27 CCL_NAMESPACE_BEGIN
28
29 /* Device Task */
30
DeviceTask(Type type_)31 DeviceTask::DeviceTask(Type type_)
32 : type(type_),
33 x(0),
34 y(0),
35 w(0),
36 h(0),
37 rgba_byte(0),
38 rgba_half(0),
39 buffer(0),
40 sample(0),
41 num_samples(1),
42 shader_input(0),
43 shader_output(0),
44 shader_eval_type(0),
45 shader_filter(0),
46 shader_x(0),
47 shader_w(0),
48 buffers(nullptr)
49 {
50 last_update_time = time_dt();
51 }
52
get_subtask_count(int num,int max_size) const53 int DeviceTask::get_subtask_count(int num, int max_size) const
54 {
55 if (max_size != 0) {
56 int max_size_num;
57
58 if (type == SHADER) {
59 max_size_num = (shader_w + max_size - 1) / max_size;
60 }
61 else {
62 max_size = max(1, max_size / w);
63 max_size_num = (h + max_size - 1) / max_size;
64 }
65
66 num = max(max_size_num, num);
67 }
68
69 if (type == SHADER) {
70 num = min(shader_w, num);
71 }
72 else if (type == RENDER) {
73 }
74 else {
75 num = min(h, num);
76 }
77
78 return num;
79 }
80
split(list<DeviceTask> & tasks,int num,int max_size) const81 void DeviceTask::split(list<DeviceTask> &tasks, int num, int max_size) const
82 {
83 num = get_subtask_count(num, max_size);
84
85 if (type == SHADER) {
86 for (int i = 0; i < num; i++) {
87 int tx = shader_x + (shader_w / num) * i;
88 int tw = (i == num - 1) ? shader_w - i * (shader_w / num) : shader_w / num;
89
90 DeviceTask task = *this;
91
92 task.shader_x = tx;
93 task.shader_w = tw;
94
95 tasks.push_back(task);
96 }
97 }
98 else if (type == RENDER) {
99 for (int i = 0; i < num; i++)
100 tasks.push_back(*this);
101 }
102 else {
103 for (int i = 0; i < num; i++) {
104 int ty = y + (h / num) * i;
105 int th = (i == num - 1) ? h - i * (h / num) : h / num;
106
107 DeviceTask task = *this;
108
109 task.y = ty;
110 task.h = th;
111
112 tasks.push_back(task);
113 }
114 }
115 }
116
update_progress(RenderTile * rtile,int pixel_samples)117 void DeviceTask::update_progress(RenderTile *rtile, int pixel_samples)
118 {
119 if (type == FILM_CONVERT)
120 return;
121
122 if (update_progress_sample) {
123 if (pixel_samples == -1) {
124 pixel_samples = shader_w;
125 }
126 update_progress_sample(pixel_samples, rtile ? rtile->sample : 0);
127 }
128
129 if (update_tile_sample) {
130 double current_time = time_dt();
131
132 if (current_time - last_update_time >= 1.0) {
133 update_tile_sample(*rtile);
134
135 last_update_time = current_time;
136 }
137 }
138 }
139
140 /* Adaptive Sampling */
141
AdaptiveSampling()142 AdaptiveSampling::AdaptiveSampling() : use(true), adaptive_step(0), min_samples(0)
143 {
144 }
145
146 /* Render samples in steps that align with the adaptive filtering. */
align_static_samples(int samples) const147 int AdaptiveSampling::align_static_samples(int samples) const
148 {
149 if (samples > adaptive_step) {
150 /* Make multiple of adaptive_step. */
151 while (samples % adaptive_step != 0) {
152 samples--;
153 }
154 }
155 else if (samples < adaptive_step) {
156 /* Make divisor of adaptive_step. */
157 while (adaptive_step % samples != 0) {
158 samples--;
159 }
160 }
161
162 return max(samples, 1);
163 }
164
165 /* Render samples in steps that align with the adaptive filtering, with the
166 * suggested number of samples dynamically changing. */
align_dynamic_samples(int offset,int samples) const167 int AdaptiveSampling::align_dynamic_samples(int offset, int samples) const
168 {
169 /* Round so that we end up on multiples of adaptive_samples. */
170 samples += offset;
171
172 if (samples > adaptive_step) {
173 /* Make multiple of adaptive_step. */
174 while (samples % adaptive_step != 0) {
175 samples--;
176 }
177 }
178
179 samples -= offset;
180
181 return max(samples, 1);
182 }
183
need_filter(int sample) const184 bool AdaptiveSampling::need_filter(int sample) const
185 {
186 if (sample > min_samples) {
187 return (sample & (adaptive_step - 1)) == (adaptive_step - 1);
188 }
189 else {
190 return false;
191 }
192 }
193
194 CCL_NAMESPACE_END
195