Final Fix T41222 Blender gives weird ouput when baking (4096*4096) resolution on GPU
[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 "bake.h"
18 #include "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 int BakeData::object()
59 {
60         return m_object;
61 }
62
63 size_t BakeData::size()
64 {
65         return m_num_pixels;
66 }
67
68 bool BakeData::is_valid(int i)
69 {
70         return m_primitive[i] != -1;
71 }
72
73 uint4 BakeData::data(int i)
74 {
75         return make_uint4(
76                 m_object,
77                 m_primitive[i],
78                 __float_as_int(m_u[i]),
79                 __float_as_int(m_v[i])
80                 );
81 }
82
83 uint4 BakeData::differentials(int i)
84 {
85         return make_uint4(
86                   __float_as_int(m_dudx[i]),
87                   __float_as_int(m_dudy[i]),
88                   __float_as_int(m_dvdx[i]),
89                   __float_as_int(m_dvdy[i])
90                   );
91 }
92
93 BakeManager::BakeManager()
94 {
95         m_bake_data = NULL;
96         m_is_baking = false;
97         need_update = true;
98         m_shader_limit = 512 * 512;
99 }
100
101 BakeManager::~BakeManager()
102 {
103         if(m_bake_data)
104                 delete m_bake_data;
105 }
106
107 bool BakeManager::get_baking()
108 {
109         return m_is_baking;
110 }
111
112 void BakeManager::set_baking(const bool value)
113 {
114         m_is_baking = value;
115 }
116
117 BakeData *BakeManager::init(const int object, const size_t tri_offset, const size_t num_pixels)
118 {
119         m_bake_data = new BakeData(object, tri_offset, num_pixels);
120         return m_bake_data;
121 }
122
123 void BakeManager::set_shader_limit(const size_t x, const size_t y)
124 {
125         m_shader_limit = x * y;
126         m_shader_limit = pow(2, ceil(log(m_shader_limit)/log(2)));
127 }
128
129 bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, BakeData *bake_data, float result[])
130 {
131         size_t num_pixels = bake_data->size();
132
133         progress.reset_sample();
134         this->num_parts = 0;
135
136         /* calculate the total parts for the progress bar */
137         for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
138                 size_t shader_size = fminf(num_pixels - shader_offset, m_shader_limit);
139
140                 DeviceTask task(DeviceTask::SHADER);
141                 task.shader_w = shader_size;
142
143                 this->num_parts += device->get_split_task_count(task);
144         }
145
146         this->num_samples = is_aa_pass(shader_type)? scene->integrator->aa_samples : 1;
147
148         for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
149                 size_t shader_size = fminf(num_pixels - shader_offset, m_shader_limit);
150
151                 /* setup input for device task */
152                 device_vector<uint4> d_input;
153                 uint4 *d_input_data = d_input.resize(shader_size * 2);
154                 size_t d_input_size = 0;
155
156                 for(size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
157                         d_input_data[d_input_size++] = bake_data->data(i);
158                         d_input_data[d_input_size++] = bake_data->differentials(i);
159                 }
160
161                 if(d_input_size == 0) {
162                         m_is_baking = false;
163                         return false;
164                 }
165
166                 /* run device task */
167                 device_vector<float4> d_output;
168                 d_output.resize(shader_size);
169
170                 /* needs to be up to data for attribute access */
171                 device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
172
173                 device->mem_alloc(d_input, MEM_READ_ONLY);
174                 device->mem_copy_to(d_input);
175                 device->mem_alloc(d_output, MEM_WRITE_ONLY);
176
177                 DeviceTask task(DeviceTask::SHADER);
178                 task.shader_input = d_input.device_pointer;
179                 task.shader_output = d_output.device_pointer;
180                 task.shader_eval_type = shader_type;
181                 task.shader_x = 0;
182                 task.shader_w = d_output.size();
183                 task.num_samples = this->num_samples;
184                 task.get_cancel = function_bind(&Progress::get_cancel, &progress);
185                 task.update_progress_sample = function_bind(&Progress::increment_sample_update, &progress);
186
187                 device->task_add(task);
188                 device->task_wait();
189
190                 if(progress.get_cancel()) {
191                         device->mem_free(d_input);
192                         device->mem_free(d_output);
193                         m_is_baking = false;
194                         return false;
195                 }
196
197                 device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float4));
198                 device->mem_free(d_input);
199                 device->mem_free(d_output);
200
201                 /* read result */
202                 int k = 0;
203
204                 float4 *offset = (float4*)d_output.data_pointer;
205
206                 size_t depth = 4;
207                 for(size_t i=shader_offset; i < (shader_offset + shader_size); i++) {
208                         size_t index = i * depth;
209                         float4 out = offset[k++];
210
211                         if(bake_data->is_valid(i)) {
212                                 for(size_t j=0; j < 4; j++) {
213                                         result[index + j] = out[j];
214                                 }
215                         }
216                 }
217         }
218
219         m_is_baking = false;
220         return true;
221 }
222
223 void BakeManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
224 {
225         if(!need_update)
226                 return;
227
228         if(progress.get_cancel()) return;
229
230         need_update = false;
231 }
232
233 void BakeManager::device_free(Device *device, DeviceScene *dscene)
234 {
235 }
236
237 bool BakeManager::is_aa_pass(ShaderEvalType type)
238 {
239         switch(type) {
240                 case SHADER_EVAL_UV:
241                 case SHADER_EVAL_NORMAL:
242                         return false;
243                 default:
244                         return true;
245         }
246 }
247
248 bool BakeManager::is_light_pass(ShaderEvalType type)
249 {
250         switch(type) {
251                 case SHADER_EVAL_AO:
252                 case SHADER_EVAL_COMBINED:
253                 case SHADER_EVAL_SHADOW:
254                 case SHADER_EVAL_DIFFUSE_DIRECT:
255                 case SHADER_EVAL_GLOSSY_DIRECT:
256                 case SHADER_EVAL_TRANSMISSION_DIRECT:
257                 case SHADER_EVAL_SUBSURFACE_DIRECT:
258                 case SHADER_EVAL_DIFFUSE_INDIRECT:
259                 case SHADER_EVAL_GLOSSY_INDIRECT:
260                 case SHADER_EVAL_TRANSMISSION_INDIRECT:
261                 case SHADER_EVAL_SUBSURFACE_INDIRECT:
262                         return true;
263                 default:
264                         return false;
265         }
266 }
267
268 CCL_NAMESPACE_END