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
19 #include "device/device.h"
20 #include "render/buffers.h"
21
22 #include "util/util_foreach.h"
23 #include "util/util_hash.h"
24 #include "util/util_math.h"
25 #include "util/util_opengl.h"
26 #include "util/util_time.h"
27 #include "util/util_types.h"
28
29 CCL_NAMESPACE_BEGIN
30
31 /* Buffer Params */
32
BufferParams()33 BufferParams::BufferParams()
34 {
35 width = 0;
36 height = 0;
37
38 full_x = 0;
39 full_y = 0;
40 full_width = 0;
41 full_height = 0;
42
43 denoising_data_pass = false;
44 denoising_clean_pass = false;
45 denoising_prefiltered_pass = false;
46
47 Pass::add(PASS_COMBINED, passes);
48 }
49
get_offset_stride(int & offset,int & stride)50 void BufferParams::get_offset_stride(int &offset, int &stride)
51 {
52 offset = -(full_x + full_y * width);
53 stride = width;
54 }
55
modified(const BufferParams & params)56 bool BufferParams::modified(const BufferParams ¶ms)
57 {
58 return !(full_x == params.full_x && full_y == params.full_y && width == params.width &&
59 height == params.height && full_width == params.full_width &&
60 full_height == params.full_height && Pass::equals(passes, params.passes) &&
61 denoising_data_pass == params.denoising_data_pass &&
62 denoising_clean_pass == params.denoising_clean_pass &&
63 denoising_prefiltered_pass == params.denoising_prefiltered_pass);
64 }
65
get_passes_size()66 int BufferParams::get_passes_size()
67 {
68 int size = 0;
69
70 for (size_t i = 0; i < passes.size(); i++)
71 size += passes[i].components;
72
73 if (denoising_data_pass) {
74 size += DENOISING_PASS_SIZE_BASE;
75 if (denoising_clean_pass)
76 size += DENOISING_PASS_SIZE_CLEAN;
77 if (denoising_prefiltered_pass)
78 size += DENOISING_PASS_SIZE_PREFILTERED;
79 }
80
81 return align_up(size, 4);
82 }
83
get_denoising_offset()84 int BufferParams::get_denoising_offset()
85 {
86 int offset = 0;
87
88 for (size_t i = 0; i < passes.size(); i++)
89 offset += passes[i].components;
90
91 return offset;
92 }
93
get_denoising_prefiltered_offset()94 int BufferParams::get_denoising_prefiltered_offset()
95 {
96 assert(denoising_prefiltered_pass);
97
98 int offset = get_denoising_offset();
99
100 offset += DENOISING_PASS_SIZE_BASE;
101 if (denoising_clean_pass) {
102 offset += DENOISING_PASS_SIZE_CLEAN;
103 }
104
105 return offset;
106 }
107
108 /* Render Buffer Task */
109
RenderTile()110 RenderTile::RenderTile()
111 {
112 x = 0;
113 y = 0;
114 w = 0;
115 h = 0;
116
117 sample = 0;
118 start_sample = 0;
119 num_samples = 0;
120 resolution = 0;
121
122 offset = 0;
123 stride = 0;
124
125 buffer = 0;
126
127 buffers = NULL;
128 }
129
130 /* Render Buffers */
131
RenderBuffers(Device * device)132 RenderBuffers::RenderBuffers(Device *device)
133 : buffer(device, "RenderBuffers", MEM_READ_WRITE),
134 map_neighbor_copied(false),
135 render_time(0.0f)
136 {
137 }
138
~RenderBuffers()139 RenderBuffers::~RenderBuffers()
140 {
141 buffer.free();
142 }
143
reset(BufferParams & params_)144 void RenderBuffers::reset(BufferParams ¶ms_)
145 {
146 params = params_;
147
148 /* re-allocate buffer */
149 buffer.alloc(params.width * params.get_passes_size(), params.height);
150 buffer.zero_to_device();
151 }
152
zero()153 void RenderBuffers::zero()
154 {
155 buffer.zero_to_device();
156 }
157
copy_from_device()158 bool RenderBuffers::copy_from_device()
159 {
160 if (!buffer.device_pointer)
161 return false;
162
163 buffer.copy_from_device(0, params.width * params.get_passes_size(), params.height);
164
165 return true;
166 }
167
get_denoising_pass_rect(int type,float exposure,int sample,int components,float * pixels)168 bool RenderBuffers::get_denoising_pass_rect(
169 int type, float exposure, int sample, int components, float *pixels)
170 {
171 if (buffer.data() == NULL) {
172 return false;
173 }
174
175 float scale = 1.0f;
176 float alpha_scale = 1.0f / sample;
177 if (type == DENOISING_PASS_PREFILTERED_COLOR || type == DENOISING_PASS_CLEAN ||
178 type == DENOISING_PASS_PREFILTERED_INTENSITY) {
179 scale *= exposure;
180 }
181 else if (type == DENOISING_PASS_PREFILTERED_VARIANCE) {
182 scale *= exposure * exposure * (sample - 1);
183 }
184
185 int offset;
186 if (type == DENOISING_PASS_CLEAN) {
187 /* The clean pass isn't changed by prefiltering, so we use the original one there. */
188 offset = type + params.get_denoising_offset();
189 scale /= sample;
190 }
191 else if (params.denoising_prefiltered_pass) {
192 offset = type + params.get_denoising_prefiltered_offset();
193 }
194 else {
195 switch (type) {
196 case DENOISING_PASS_PREFILTERED_DEPTH:
197 offset = params.get_denoising_offset() + DENOISING_PASS_DEPTH;
198 break;
199 case DENOISING_PASS_PREFILTERED_NORMAL:
200 offset = params.get_denoising_offset() + DENOISING_PASS_NORMAL;
201 break;
202 case DENOISING_PASS_PREFILTERED_ALBEDO:
203 offset = params.get_denoising_offset() + DENOISING_PASS_ALBEDO;
204 break;
205 case DENOISING_PASS_PREFILTERED_COLOR:
206 /* If we're not saving the prefiltering result, return the original noisy pass. */
207 offset = params.get_denoising_offset() + DENOISING_PASS_COLOR;
208 break;
209 default:
210 return false;
211 }
212 scale /= sample;
213 }
214
215 int pass_stride = params.get_passes_size();
216 int size = params.width * params.height;
217
218 float *in = buffer.data() + offset;
219
220 if (components == 1) {
221 for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
222 pixels[0] = in[0] * scale;
223 }
224 }
225 else if (components == 3) {
226 for (int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
227 pixels[0] = in[0] * scale;
228 pixels[1] = in[1] * scale;
229 pixels[2] = in[2] * scale;
230 }
231 }
232 else if (components == 4) {
233 /* Since the alpha channel is not involved in denoising, output the Combined alpha channel. */
234 assert(params.passes[0].type == PASS_COMBINED);
235 float *in_combined = buffer.data();
236
237 for (int i = 0; i < size; i++, in += pass_stride, in_combined += pass_stride, pixels += 4) {
238 float3 val = make_float3(in[0], in[1], in[2]);
239 if (type == DENOISING_PASS_PREFILTERED_COLOR && params.denoising_prefiltered_pass) {
240 /* Remove highlight compression from the image. */
241 val = color_highlight_uncompress(val);
242 }
243 pixels[0] = val.x * scale;
244 pixels[1] = val.y * scale;
245 pixels[2] = val.z * scale;
246 pixels[3] = saturate(in_combined[3] * alpha_scale);
247 }
248 }
249 else {
250 return false;
251 }
252
253 return true;
254 }
255
get_pass_rect(const string & name,float exposure,int sample,int components,float * pixels)256 bool RenderBuffers::get_pass_rect(
257 const string &name, float exposure, int sample, int components, float *pixels)
258 {
259 if (buffer.data() == NULL) {
260 return false;
261 }
262
263 float *sample_count = NULL;
264 if (name == "Combined") {
265 int sample_offset = 0;
266 for (size_t j = 0; j < params.passes.size(); j++) {
267 Pass &pass = params.passes[j];
268 if (pass.type != PASS_SAMPLE_COUNT) {
269 sample_offset += pass.components;
270 continue;
271 }
272 else {
273 sample_count = buffer.data() + sample_offset;
274 break;
275 }
276 }
277 }
278
279 int pass_offset = 0;
280
281 for (size_t j = 0; j < params.passes.size(); j++) {
282 Pass &pass = params.passes[j];
283
284 /* Pass is identified by both type and name, multiple of the same type
285 * may exist with a different name. */
286 if (pass.name != name) {
287 pass_offset += pass.components;
288 continue;
289 }
290
291 PassType type = pass.type;
292
293 float *in = buffer.data() + pass_offset;
294 int pass_stride = params.get_passes_size();
295
296 float scale = (pass.filter) ? 1.0f / (float)sample : 1.0f;
297 float scale_exposure = (pass.exposure) ? scale * exposure : scale;
298
299 int size = params.width * params.height;
300
301 if (components == 1 && type == PASS_RENDER_TIME) {
302 /* Render time is not stored by kernel, but measured per tile. */
303 float val = (float)(1000.0 * render_time / (params.width * params.height * sample));
304 for (int i = 0; i < size; i++, pixels++) {
305 pixels[0] = val;
306 }
307 }
308 else if (components == 1) {
309 assert(pass.components == components);
310
311 /* Scalar */
312 if (type == PASS_DEPTH) {
313 for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
314 float f = *in;
315 pixels[0] = (f == 0.0f) ? 1e10f : f * scale_exposure;
316 }
317 }
318 else if (type == PASS_MIST) {
319 for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
320 float f = *in;
321 pixels[0] = saturate(f * scale_exposure);
322 }
323 }
324 #ifdef WITH_CYCLES_DEBUG
325 else if (type == PASS_BVH_TRAVERSED_NODES || type == PASS_BVH_TRAVERSED_INSTANCES ||
326 type == PASS_BVH_INTERSECTIONS || type == PASS_RAY_BOUNCES) {
327 for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
328 float f = *in;
329 pixels[0] = f * scale;
330 }
331 }
332 #endif
333 else {
334 for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
335 float f = *in;
336 pixels[0] = f * scale_exposure;
337 }
338 }
339 }
340 else if (components == 3) {
341 assert(pass.components == 4);
342
343 /* RGBA */
344 if (type == PASS_SHADOW) {
345 for (int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
346 float4 f = make_float4(in[0], in[1], in[2], in[3]);
347 float invw = (f.w > 0.0f) ? 1.0f / f.w : 1.0f;
348
349 pixels[0] = f.x * invw;
350 pixels[1] = f.y * invw;
351 pixels[2] = f.z * invw;
352 }
353 }
354 else if (pass.divide_type != PASS_NONE) {
355 /* RGB lighting passes that need to divide out color */
356 pass_offset = 0;
357 for (size_t k = 0; k < params.passes.size(); k++) {
358 Pass &color_pass = params.passes[k];
359 if (color_pass.type == pass.divide_type)
360 break;
361 pass_offset += color_pass.components;
362 }
363
364 float *in_divide = buffer.data() + pass_offset;
365
366 for (int i = 0; i < size; i++, in += pass_stride, in_divide += pass_stride, pixels += 3) {
367 float3 f = make_float3(in[0], in[1], in[2]);
368 float3 f_divide = make_float3(in_divide[0], in_divide[1], in_divide[2]);
369
370 f = safe_divide_even_color(f * exposure, f_divide);
371
372 pixels[0] = f.x;
373 pixels[1] = f.y;
374 pixels[2] = f.z;
375 }
376 }
377 else {
378 /* RGB/vector */
379 for (int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
380 float3 f = make_float3(in[0], in[1], in[2]);
381
382 pixels[0] = f.x * scale_exposure;
383 pixels[1] = f.y * scale_exposure;
384 pixels[2] = f.z * scale_exposure;
385 }
386 }
387 }
388 else if (components == 4) {
389 assert(pass.components == components);
390
391 /* RGBA */
392 if (type == PASS_SHADOW) {
393 for (int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
394 float4 f = make_float4(in[0], in[1], in[2], in[3]);
395 float invw = (f.w > 0.0f) ? 1.0f / f.w : 1.0f;
396
397 pixels[0] = f.x * invw;
398 pixels[1] = f.y * invw;
399 pixels[2] = f.z * invw;
400 pixels[3] = 1.0f;
401 }
402 }
403 else if (type == PASS_MOTION) {
404 /* need to normalize by number of samples accumulated for motion */
405 pass_offset = 0;
406 for (size_t k = 0; k < params.passes.size(); k++) {
407 Pass &color_pass = params.passes[k];
408 if (color_pass.type == PASS_MOTION_WEIGHT)
409 break;
410 pass_offset += color_pass.components;
411 }
412
413 float *in_weight = buffer.data() + pass_offset;
414
415 for (int i = 0; i < size; i++, in += pass_stride, in_weight += pass_stride, pixels += 4) {
416 float4 f = make_float4(in[0], in[1], in[2], in[3]);
417 float w = in_weight[0];
418 float invw = (w > 0.0f) ? 1.0f / w : 0.0f;
419
420 pixels[0] = f.x * invw;
421 pixels[1] = f.y * invw;
422 pixels[2] = f.z * invw;
423 pixels[3] = f.w * invw;
424 }
425 }
426 else if (type == PASS_CRYPTOMATTE) {
427 for (int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
428 float4 f = make_float4(in[0], in[1], in[2], in[3]);
429 /* x and z contain integer IDs, don't rescale them.
430 y and w contain matte weights, they get scaled. */
431 pixels[0] = f.x;
432 pixels[1] = f.y * scale;
433 pixels[2] = f.z;
434 pixels[3] = f.w * scale;
435 }
436 }
437 else {
438 for (int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
439 if (sample_count && sample_count[i * pass_stride] < 0.0f) {
440 scale = (pass.filter) ? -1.0f / (sample_count[i * pass_stride]) : 1.0f;
441 scale_exposure = (pass.exposure) ? scale * exposure : scale;
442 }
443
444 float4 f = make_float4(in[0], in[1], in[2], in[3]);
445
446 pixels[0] = f.x * scale_exposure;
447 pixels[1] = f.y * scale_exposure;
448 pixels[2] = f.z * scale_exposure;
449
450 /* clamp since alpha might be > 1.0 due to russian roulette */
451 pixels[3] = saturate(f.w * scale);
452 }
453 }
454 }
455
456 return true;
457 }
458
459 return false;
460 }
461
set_pass_rect(PassType type,int components,float * pixels,int samples)462 bool RenderBuffers::set_pass_rect(PassType type, int components, float *pixels, int samples)
463 {
464 if (buffer.data() == NULL) {
465 return false;
466 }
467
468 int pass_offset = 0;
469
470 for (size_t j = 0; j < params.passes.size(); j++) {
471 Pass &pass = params.passes[j];
472
473 if (pass.type != type) {
474 pass_offset += pass.components;
475 continue;
476 }
477
478 float *out = buffer.data() + pass_offset;
479 int pass_stride = params.get_passes_size();
480 int size = params.width * params.height;
481
482 assert(pass.components == components);
483
484 for (int i = 0; i < size; i++, out += pass_stride, pixels += components) {
485 if (pass.filter) {
486 /* Scale by the number of samples, inverse of what we do in get_pass_rect.
487 * A better solution would be to remove the need for set_pass_rect entirely,
488 * and change baking to bake multiple objects in a tile at once. */
489 for (int j = 0; j < components; j++) {
490 out[j] = pixels[j] * samples;
491 }
492 }
493 else {
494 /* For non-filtered passes just straight copy, these may contain non-float data. */
495 memcpy(out, pixels, sizeof(float) * components);
496 }
497 }
498
499 return true;
500 }
501
502 return false;
503 }
504
505 /* Display Buffer */
506
DisplayBuffer(Device * device,bool linear)507 DisplayBuffer::DisplayBuffer(Device *device, bool linear)
508 : draw_width(0),
509 draw_height(0),
510 transparent(true), /* todo: determine from background */
511 half_float(linear),
512 rgba_byte(device, "display buffer byte"),
513 rgba_half(device, "display buffer half")
514 {
515 }
516
~DisplayBuffer()517 DisplayBuffer::~DisplayBuffer()
518 {
519 rgba_byte.free();
520 rgba_half.free();
521 }
522
reset(BufferParams & params_)523 void DisplayBuffer::reset(BufferParams ¶ms_)
524 {
525 draw_width = 0;
526 draw_height = 0;
527
528 params = params_;
529
530 /* allocate display pixels */
531 if (half_float) {
532 rgba_half.alloc_to_device(params.width, params.height);
533 }
534 else {
535 rgba_byte.alloc_to_device(params.width, params.height);
536 }
537 }
538
draw_set(int width,int height)539 void DisplayBuffer::draw_set(int width, int height)
540 {
541 assert(width <= params.width && height <= params.height);
542
543 draw_width = width;
544 draw_height = height;
545 }
546
draw(Device * device,const DeviceDrawParams & draw_params)547 void DisplayBuffer::draw(Device *device, const DeviceDrawParams &draw_params)
548 {
549 if (draw_width != 0 && draw_height != 0) {
550 device_memory &rgba = (half_float) ? (device_memory &)rgba_half : (device_memory &)rgba_byte;
551
552 device->draw_pixels(rgba,
553 0,
554 draw_width,
555 draw_height,
556 params.width,
557 params.height,
558 params.full_x,
559 params.full_y,
560 params.full_width,
561 params.full_height,
562 transparent,
563 draw_params);
564 }
565 }
566
draw_ready()567 bool DisplayBuffer::draw_ready()
568 {
569 return (draw_width != 0 && draw_height != 0);
570 }
571
572 CCL_NAMESPACE_END
573