Cycles: Make shadow catcher an optional feature for OpenCL
[blender.git] / intern / cycles / device / device_memory.h
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 #ifndef __DEVICE_MEMORY_H__
18 #define __DEVICE_MEMORY_H__
19
20 /* Device Memory
21  *
22  * This file defines data types that can be used in device memory arrays, and
23  * a device_vector<T> type to store such arrays.
24  *
25  * device_vector<T> contains an STL vector, metadata about the data type,
26  * dimensions, elements, and a device pointer. For the CPU device this is just
27  * a pointer to the STL vector data, as no copying needs to take place. For
28  * other devices this is a pointer to device memory, where we will copy memory
29  * to and from. */
30
31 #include "util_debug.h"
32 #include "util_half.h"
33 #include "util_types.h"
34 #include "util_vector.h"
35
36 CCL_NAMESPACE_BEGIN
37
38 enum MemoryType {
39         MEM_READ_ONLY,
40         MEM_WRITE_ONLY,
41         MEM_READ_WRITE
42 };
43
44 /* Supported Data Types */
45
46 enum DataType {
47         TYPE_UCHAR,
48         TYPE_UINT,
49         TYPE_INT,
50         TYPE_FLOAT,
51         TYPE_HALF,
52         TYPE_UINT64,
53 };
54
55 static inline size_t datatype_size(DataType datatype) 
56 {
57         switch(datatype) {
58                 case TYPE_UCHAR: return sizeof(uchar);
59                 case TYPE_FLOAT: return sizeof(float);
60                 case TYPE_UINT: return sizeof(uint);
61                 case TYPE_INT: return sizeof(int);
62                 case TYPE_HALF: return sizeof(half);
63                 case TYPE_UINT64: return sizeof(uint64_t);
64                 default: return 0;
65         }
66 }
67
68 /* Traits for data types */
69
70 template<typename T> struct device_type_traits {
71         static const DataType data_type = TYPE_UCHAR;
72         static const int num_elements = 0;
73 };
74
75 template<> struct device_type_traits<uchar> {
76         static const DataType data_type = TYPE_UCHAR;
77         static const int num_elements = 1;
78 };
79
80 template<> struct device_type_traits<uchar2> {
81         static const DataType data_type = TYPE_UCHAR;
82         static const int num_elements = 2;
83 };
84
85 template<> struct device_type_traits<uchar3> {
86         static const DataType data_type = TYPE_UCHAR;
87         static const int num_elements = 3;
88 };
89
90 template<> struct device_type_traits<uchar4> {
91         static const DataType data_type = TYPE_UCHAR;
92         static const int num_elements = 4;
93 };
94
95 template<> struct device_type_traits<uint> {
96         static const DataType data_type = TYPE_UINT;
97         static const int num_elements = 1;
98 };
99
100 template<> struct device_type_traits<uint2> {
101         static const DataType data_type = TYPE_UINT;
102         static const int num_elements = 2;
103 };
104
105 template<> struct device_type_traits<uint3> {
106         static const DataType data_type = TYPE_UINT;
107         static const int num_elements = 3;
108 };
109
110 template<> struct device_type_traits<uint4> {
111         static const DataType data_type = TYPE_UINT;
112         static const int num_elements = 4;
113 };
114
115 template<> struct device_type_traits<int> {
116         static const DataType data_type = TYPE_INT;
117         static const int num_elements = 1;
118 };
119
120 template<> struct device_type_traits<int2> {
121         static const DataType data_type = TYPE_INT;
122         static const int num_elements = 2;
123 };
124
125 template<> struct device_type_traits<int3> {
126         static const DataType data_type = TYPE_INT;
127         static const int num_elements = 3;
128 };
129
130 template<> struct device_type_traits<int4> {
131         static const DataType data_type = TYPE_INT;
132         static const int num_elements = 4;
133 };
134
135 template<> struct device_type_traits<float> {
136         static const DataType data_type = TYPE_FLOAT;
137         static const int num_elements = 1;
138 };
139
140 template<> struct device_type_traits<float2> {
141         static const DataType data_type = TYPE_FLOAT;
142         static const int num_elements = 2;
143 };
144
145 template<> struct device_type_traits<float3> {
146         static const DataType data_type = TYPE_FLOAT;
147         static const int num_elements = 3;
148 };
149
150 template<> struct device_type_traits<float4> {
151         static const DataType data_type = TYPE_FLOAT;
152         static const int num_elements = 4;
153 };
154
155 template<> struct device_type_traits<half> {
156         static const DataType data_type = TYPE_HALF;
157         static const int num_elements = 1;
158 };
159
160 template<> struct device_type_traits<half4> {
161         static const DataType data_type = TYPE_HALF;
162         static const int num_elements = 4;
163 };
164
165 template<> struct device_type_traits<uint64_t> {
166         static const DataType data_type = TYPE_UINT64;
167         static const int num_elements = 1;
168 };
169
170 /* Device Memory */
171
172 class device_memory
173 {
174 public:
175         size_t memory_size() { return data_size*data_elements*datatype_size(data_type); }
176
177         /* data information */
178         DataType data_type;
179         int data_elements;
180         device_ptr data_pointer;
181         size_t data_size;
182         size_t device_size;
183         size_t data_width;
184         size_t data_height;
185         size_t data_depth;
186
187         /* device pointer */
188         device_ptr device_pointer;
189
190         device_memory()
191         {
192                 data_type = device_type_traits<uchar>::data_type;
193                 data_elements = device_type_traits<uchar>::num_elements;
194                 data_pointer = 0;
195                 data_size = 0;
196                 device_size = 0;
197                 data_width = 0;
198                 data_height = 0;
199                 data_depth = 0;
200                 device_pointer = 0;
201         }
202         virtual ~device_memory() { assert(!device_pointer); }
203
204         void resize(size_t size)
205         {
206                 data_size = size;
207                 data_width = size;
208         }
209
210 protected:
211         /* no copying */
212         device_memory(const device_memory&);
213         device_memory& operator = (const device_memory&);
214 };
215
216 /* Device Vector */
217
218 template<typename T> class device_vector : public device_memory
219 {
220 public:
221         device_vector()
222         {
223                 data_type = device_type_traits<T>::data_type;
224                 data_elements = device_type_traits<T>::num_elements;
225
226                 assert(data_elements > 0);
227         }
228
229         virtual ~device_vector() {}
230
231         /* vector functions */
232         T *resize(size_t width, size_t height = 0, size_t depth = 0)
233         {
234                 data_size = width * ((height == 0)? 1: height) * ((depth == 0)? 1: depth);
235                 if(data.resize(data_size) == NULL) {
236                         clear();
237                         return NULL;
238                 }
239                 data_width = width;
240                 data_height = height;
241                 data_depth = depth;
242                 if(data_size == 0) {
243                         data_pointer = 0;
244                         return NULL;
245                 }
246                 data_pointer = (device_ptr)&data[0];
247                 return &data[0];
248         }
249
250         T *copy(T *ptr, size_t width, size_t height = 0, size_t depth = 0)
251         {
252                 T *mem = resize(width, height, depth);
253                 if(mem != NULL) {
254                         memcpy(mem, ptr, memory_size());
255                 }
256                 return mem;
257         }
258
259         void copy_at(T *ptr, size_t offset, size_t size)
260         {
261                 if(size > 0) {
262                         size_t mem_size = size*data_elements*datatype_size(data_type);
263                         memcpy(&data[0] + offset, ptr, mem_size);
264                 }
265         }
266
267         void reference(T *ptr, size_t width, size_t height = 0, size_t depth = 0)
268         {
269                 data.clear();
270                 data_size = width * ((height == 0)? 1: height) * ((depth == 0)? 1: depth);
271                 data_pointer = (device_ptr)ptr;
272                 data_width = width;
273                 data_height = height;
274                 data_depth = depth;
275         }
276
277         void clear()
278         {
279                 data.clear();
280                 data_pointer = 0;
281                 data_width = 0;
282                 data_height = 0;
283                 data_depth = 0;
284                 data_size = 0;
285                 device_pointer = 0;
286         }
287
288         size_t size()
289         {
290                 return data.size();
291         }
292
293         T* get_data()
294         {
295                 return &data[0];
296         }
297
298 private:
299         array<T> data;
300 };
301
302 CCL_NAMESPACE_END
303
304 #endif /* __DEVICE_MEMORY_H__ */
305