2e3022e2c026417b03ebb2e0c2059b56485614ff
[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
19 CCL_NAMESPACE_BEGIN
20
21 BakeData::BakeData(const int object, const int tri_offset, const int num_pixels):
22 m_object(object),
23 m_tri_offset(tri_offset),
24 m_num_pixels(num_pixels)
25 {
26         m_primitive.resize(num_pixels);
27         m_u.resize(num_pixels);
28         m_v.resize(num_pixels);
29 }
30
31 BakeData::~BakeData()
32 {
33         m_primitive.clear();
34         m_u.clear();
35         m_v.clear();
36 }
37
38 void BakeData::set(int i, int prim, float uv[2])
39 {
40         m_primitive[i] = (prim == -1 ? -1 : m_tri_offset + prim);
41         m_u[i] = uv[0];
42         m_v[i] = uv[1];
43 }
44
45 int BakeData::object()
46 {
47         return m_object;
48 }
49
50 int BakeData::size()
51 {
52         return m_num_pixels;
53 }
54
55 bool BakeData::is_valid(int i)
56 {
57         return m_primitive[i] != -1;
58 }
59
60 uint4 BakeData::data(int i)
61 {
62         return make_uint4(
63                 m_object,
64                 m_primitive[i],
65                 __float_as_int(m_u[i]),
66                 __float_as_int(m_v[i])
67                 );
68 }
69
70 BakeManager::BakeManager()
71 {
72         m_bake_data = NULL;
73         m_is_baking = false;
74         need_update = true;
75 }
76
77 BakeManager::~BakeManager()
78 {
79         if(m_bake_data)
80                 delete m_bake_data;
81 }
82
83 bool BakeManager::get_baking()
84 {
85         return m_is_baking;
86 }
87
88 void BakeManager::set_baking(const bool value)
89 {
90         m_is_baking = value;
91 }
92
93 BakeData *BakeManager::init(const int object, const int tri_offset, const int num_pixels)
94 {
95         m_bake_data = new BakeData(object, tri_offset, num_pixels);
96         return m_bake_data;
97 }
98
99 bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, BakeData *bake_data, float result[])
100 {
101         size_t limit = bake_data->size();
102
103         /* setup input for device task */
104         device_vector<uint4> d_input;
105         uint4 *d_input_data = d_input.resize(limit);
106         size_t d_input_size = 0;
107
108         for(size_t i = 0; i < limit; i++) {
109                 d_input_data[d_input_size++] = bake_data->data(i);
110         }
111
112         if(d_input_size == 0)
113                 return false;
114
115         /* run device task */
116         device_vector<float4> d_output;
117         d_output.resize(d_input_size);
118
119         /* needs to be up to data for attribute access */
120         device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
121
122         device->mem_alloc(d_input, MEM_READ_ONLY);
123         device->mem_copy_to(d_input);
124         device->mem_alloc(d_output, MEM_WRITE_ONLY);
125
126         DeviceTask task(DeviceTask::SHADER);
127         task.shader_input = d_input.device_pointer;
128         task.shader_output = d_output.device_pointer;
129         task.shader_eval_type = shader_type;
130         task.shader_x = 0;
131         task.shader_w = d_output.size();
132         task.get_cancel = function_bind(&Progress::get_cancel, &progress);
133
134         device->task_add(task);
135         device->task_wait();
136
137         if(progress.get_cancel()) {
138                 device->mem_free(d_input);
139                 device->mem_free(d_output);
140                 m_is_baking = false;
141                 return false;
142         }
143
144         device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float4));
145         device->mem_free(d_input);
146         device->mem_free(d_output);
147
148         /* read result */
149         int k = 0;
150
151         float4 *offset = (float4*)d_output.data_pointer;
152
153         size_t depth = 4;
154         for(size_t i = 0; i < limit; i++) {
155                 size_t index = i * depth;
156                 float4 out = offset[k++];
157
158                 if(bake_data->is_valid(i)) {
159                         for(size_t j=0; j < 4; j++) {
160                                 result[index + j] = out[j];
161                         }
162                 }
163         }
164
165         m_is_baking = false;
166         return true;
167 }
168
169 void BakeManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
170 {
171         if(!need_update)
172                 return;
173
174         if(progress.get_cancel()) return;
175
176         need_update = false;
177 }
178
179 void BakeManager::device_free(Device *device, DeviceScene *dscene)
180 {
181 }
182
183 CCL_NAMESPACE_END