ClangFormat: apply to source, most of intern
[blender.git] / intern / cycles / render / coverage.cpp
1 /*
2  * Copyright 2018 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 "render/coverage.h"
18 #include "kernel/kernel_compat_cpu.h"
19 #include "kernel/split/kernel_split_data.h"
20 #include "kernel/kernel_globals.h"
21 #include "kernel/kernel_id_passes.h"
22 #include "kernel/kernel_types.h"
23 #include "util/util_map.h"
24 #include "util/util_vector.h"
25
26 CCL_NAMESPACE_BEGIN
27
28 static bool crypomatte_comp(const pair<float, float> &i, const pair<float, float> j)
29 {
30   return i.first > j.first;
31 }
32
33 void Coverage::finalize()
34 {
35   int pass_offset = 0;
36   if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
37     finalize_buffer(coverage_object, pass_offset);
38     pass_offset += kernel_data.film.cryptomatte_depth * 4;
39   }
40   if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
41     finalize_buffer(coverage_material, pass_offset);
42     pass_offset += kernel_data.film.cryptomatte_depth * 4;
43   }
44   if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
45     finalize_buffer(coverage_asset, pass_offset);
46   }
47 }
48
49 void Coverage::init_path_trace()
50 {
51   kg->coverage_object = kg->coverage_material = kg->coverage_asset = NULL;
52
53   if (kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
54     if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
55       coverage_object.clear();
56       coverage_object.resize(tile.w * tile.h);
57     }
58     if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
59       coverage_material.clear();
60       coverage_material.resize(tile.w * tile.h);
61     }
62     if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
63       coverage_asset.clear();
64       coverage_asset.resize(tile.w * tile.h);
65     }
66   }
67 }
68
69 void Coverage::init_pixel(int x, int y)
70 {
71   if (kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
72     const int pixel_index = tile.w * (y - tile.y) + x - tile.x;
73     if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
74       kg->coverage_object = &coverage_object[pixel_index];
75     }
76     if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
77       kg->coverage_material = &coverage_material[pixel_index];
78     }
79     if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
80       kg->coverage_asset = &coverage_asset[pixel_index];
81     }
82   }
83 }
84
85 void Coverage::finalize_buffer(vector<CoverageMap> &coverage, const int pass_offset)
86 {
87   if (kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
88     flatten_buffer(coverage, pass_offset);
89   }
90   else {
91     sort_buffer(pass_offset);
92   }
93 }
94
95 void Coverage::flatten_buffer(vector<CoverageMap> &coverage, const int pass_offset)
96 {
97   /* Sort the coverage map and write it to the output */
98   int pixel_index = 0;
99   int pass_stride = tile.buffers->params.get_passes_size();
100   for (int y = 0; y < tile.h; ++y) {
101     for (int x = 0; x < tile.w; ++x) {
102       const CoverageMap &pixel = coverage[pixel_index];
103       if (!pixel.empty()) {
104         /* buffer offset */
105         int index = x + y * tile.stride;
106         float *buffer = (float *)tile.buffer + index * pass_stride;
107
108         /* sort the cryptomatte pixel */
109         vector<pair<float, float>> sorted_pixel;
110         for (CoverageMap::const_iterator it = pixel.begin(); it != pixel.end(); ++it) {
111           sorted_pixel.push_back(std::make_pair(it->second, it->first));
112         }
113         sort(sorted_pixel.begin(), sorted_pixel.end(), crypomatte_comp);
114         int num_slots = 2 * (kernel_data.film.cryptomatte_depth);
115         if (sorted_pixel.size() > num_slots) {
116           float leftover = 0.0f;
117           for (vector<pair<float, float>>::iterator it = sorted_pixel.begin() + num_slots;
118                it != sorted_pixel.end();
119                ++it) {
120             leftover += it->first;
121           }
122           sorted_pixel[num_slots - 1].first += leftover;
123         }
124         int limit = min(num_slots, sorted_pixel.size());
125         for (int i = 0; i < limit; ++i) {
126           kernel_write_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset,
127                                 2 * (kernel_data.film.cryptomatte_depth),
128                                 sorted_pixel[i].second,
129                                 sorted_pixel[i].first);
130         }
131       }
132       ++pixel_index;
133     }
134   }
135 }
136
137 void Coverage::sort_buffer(const int pass_offset)
138 {
139   /* Sort the coverage map and write it to the output */
140   int pass_stride = tile.buffers->params.get_passes_size();
141   for (int y = 0; y < tile.h; ++y) {
142     for (int x = 0; x < tile.w; ++x) {
143       /* buffer offset */
144       int index = x + y * tile.stride;
145       float *buffer = (float *)tile.buffer + index * pass_stride;
146       kernel_sort_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset,
147                            2 * (kernel_data.film.cryptomatte_depth));
148     }
149   }
150 }
151
152 CCL_NAMESPACE_END