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 &params)
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 &params_)
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 &params_)
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