66615bf336c2019639cfe523b8e9b7a078ec8755
[blender-staging.git] / intern / cycles / render / bake.cpp
1 /*
2  * Copyright 2011-2014 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/bake.h"
18 #include "render/integrator.h"
19
20 CCL_NAMESPACE_BEGIN
21
22 BakeData::BakeData(const int object, const size_t tri_offset, const size_t num_pixels):
23 m_object(object),
24 m_tri_offset(tri_offset),
25 m_num_pixels(num_pixels)
26 {
27         m_primitive.resize(num_pixels);
28         m_u.resize(num_pixels);
29         m_v.resize(num_pixels);
30         m_dudx.resize(num_pixels);
31         m_dudy.resize(num_pixels);
32         m_dvdx.resize(num_pixels);
33         m_dvdy.resize(num_pixels);
34 }
35
36 BakeData::~BakeData()
37 {
38         m_primitive.clear();
39         m_u.clear();
40         m_v.clear();
41         m_dudx.clear();
42         m_dudy.clear();
43         m_dvdx.clear();
44         m_dvdy.clear();
45 }
46
47 void BakeData::set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy)
48 {
49         m_primitive[i] = (prim == -1 ? -1 : m_tri_offset + prim);
50         m_u[i] = uv[0];
51         m_v[i] = uv[1];
52         m_dudx[i] = dudx;
53         m_dudy[i] = dudy;
54         m_dvdx[i] = dvdx;
55         m_dvdy[i] = dvdy;
56 }
57
58 void BakeData::set_null(int i)
59 {
60         m_primitive[i] = -1;
61 }
62
63 int BakeData::object()
64 {
65         return m_object;
66 }
67
68 size_t BakeData::size()
69 {
70         return m_num_pixels;
71 }
72
73 bool BakeData::is_valid(int i)
74 {
75         return m_primitive[i] != -1;
76 }
77
78 uint4 BakeData::data(int i)
79 {
80         return make_uint4(
81                 m_object,
82                 m_primitive[i],
83                 __float_as_int(m_u[i]),
84                 __float_as_int(m_v[i])
85                 );
86 }
87
88 uint4 BakeData::differentials(int i)
89 {
90         return make_uint4(
91                   __float_as_int(m_dudx[i]),
92                   __float_as_int(m_dudy[i]),
93                   __float_as_int(m_dvdx[i]),
94                   __float_as_int(m_dvdy[i])
95                   );
96 }
97
98 BakeManager::BakeManager()
99 {
100         m_bake_data = NULL;
101         m_is_baking = false;
102         need_update = true;
103         m_shader_limit = 512 * 512;
104 }
105
106 BakeManager::~BakeManager()
107 {
108         if(m_bake_data)
109                 delete m_bake_data;
110 }
111
112 bool BakeManager::get_baking()
113 {
114         return m_is_baking;
115 }
116
117 void BakeManager::set_baking(const bool value)
118 {
119         m_is_baking = value;
120 }
121
122 BakeData *BakeManager::init(const int object, const size_t tri_offset, const size_t num_pixels)
123 {
124         m_bake_data = new BakeData(object, tri_offset, num_pixels);
125         return m_bake_data;
126 }
127
128 void BakeManager::set_shader_limit(const size_t x, const size_t y)
129 {
130         m_shader_limit = x * y;
131         m_shader_limit = (size_t)pow(2, ceil(log(m_shader_limit)/log(2)));
132 }
133
134 bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, const int pass_filter, BakeData *bake_data, float result[])
135 {
136         size_t num_pixels = bake_data->size();
137
138         int num_samples = is_aa_pass(shader_type)? scene->integrator->aa_samples : 1;
139
140         /* calculate the total pixel samples for the progress bar */
141         total_pixel_samples = 0;
142         for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
143                 size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
144                 total_pixel_samples += shader_size * num_samples;
145         }
146         progress.reset_sample();
147         progress.set_total_pixel_samples(total_pixel_samples);
148
149         for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
150                 size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
151
152                 /* setup input for device task */
153                 device_vector<uint4> d_input(device, "bake_input", MEM_READ_ONLY);
154                 uint4 *d_input_data = d_input.resize(shader_size * 2);
155                 size_t d_input_size = 0;
156
157                 for(size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
158                         d_input_data[d_input_size++] = bake_data->data(i);
159                         d_input_data[d_input_size++] = bake_data->differentials(i);
160                 }
161
162                 if(d_input_size == 0) {
163                         m_is_baking = false;
164                         return false;
165                 }
166
167                 /* run device task */
168                 device_vector<float4> d_output(device, "bake_output", MEM_READ_WRITE);
169                 d_output.resize(shader_size);
170
171                 /* needs to be up to data for attribute access */
172                 device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
173
174                 device->mem_alloc(d_input);
175                 device->mem_copy_to(d_input);
176                 device->mem_alloc(d_output);
177                 device->mem_zero(d_output);
178
179                 DeviceTask task(DeviceTask::SHADER);
180                 task.shader_input = d_input.device_pointer;
181                 task.shader_output = d_output.device_pointer;
182                 task.shader_eval_type = shader_type;
183                 task.shader_filter = pass_filter;
184                 task.shader_x = 0;
185                 task.offset = shader_offset;
186                 task.shader_w = d_output.size();
187                 task.num_samples = num_samples;
188                 task.get_cancel = function_bind(&Progress::get_cancel, &progress);
189                 task.update_progress_sample = function_bind(&Progress::add_samples_update, &progress, _1, _2);
190
191                 device->task_add(task);
192                 device->task_wait();
193
194                 if(progress.get_cancel()) {
195                         device->mem_free(d_input);
196                         device->mem_free(d_output);
197                         m_is_baking = false;
198                         return false;
199                 }
200
201                 device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float4));
202                 device->mem_free(d_input);
203                 device->mem_free(d_output);
204
205                 /* read result */
206                 int k = 0;
207
208                 float4 *offset = (float4*)d_output.data_pointer;
209
210                 size_t depth = 4;
211                 for(size_t i=shader_offset; i < (shader_offset + shader_size); i++) {
212                         size_t index = i * depth;
213                         float4 out = offset[k++];
214
215                         if(bake_data->is_valid(i)) {
216                                 for(size_t j=0; j < 4; j++) {
217                                         result[index + j] = out[j];
218                                 }
219                         }
220                 }
221         }
222
223         m_is_baking = false;
224         return true;
225 }
226
227 void BakeManager::device_update(Device * /*device*/,
228                                 DeviceScene * /*dscene*/,
229                                 Scene * /*scene*/,
230                                 Progress& progress)
231 {
232         if(!need_update)
233                 return;
234
235         if(progress.get_cancel()) return;
236
237         need_update = false;
238 }
239
240 void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
241 {
242 }
243
244 bool BakeManager::is_aa_pass(ShaderEvalType type)
245 {
246         switch(type) {
247                 case SHADER_EVAL_UV:
248                 case SHADER_EVAL_NORMAL:
249                         return false;
250                 default:
251                         return true;
252         }
253 }
254
255 /* Keep it synced with kernel_bake.h logic */
256 int BakeManager::shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter)
257 {
258         const int component_flags = pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_COLOR);
259
260         switch(type) {
261                 case SHADER_EVAL_AO:
262                         return BAKE_FILTER_AO;
263                 case SHADER_EVAL_SHADOW:
264                         return BAKE_FILTER_DIRECT;
265                 case SHADER_EVAL_DIFFUSE:
266                         return BAKE_FILTER_DIFFUSE | component_flags;
267                 case SHADER_EVAL_GLOSSY:
268                         return BAKE_FILTER_GLOSSY | component_flags;
269                 case SHADER_EVAL_TRANSMISSION:
270                         return BAKE_FILTER_TRANSMISSION | component_flags;
271                 case SHADER_EVAL_SUBSURFACE:
272                         return BAKE_FILTER_SUBSURFACE | component_flags;
273                 case SHADER_EVAL_COMBINED:
274                         return pass_filter;
275                 default:
276                         return 0;
277         }
278 }
279
280 CCL_NAMESPACE_END