add BLI_strcpy_rlen, replace strcat, which was used in misleading way.
[blender.git] / intern / cycles / device / device_memory.h
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #ifndef __DEVICE_MEMORY_H__
20 #define __DEVICE_MEMORY_H__
21
22 /* Device Memory
23  *
24  * This file defines data types that can be used in device memory arrays, and
25  * a device_vector<T> type to store such arrays.
26  *
27  * device_vector<T> contains an STL vector, metadata about the data type,
28  * dimensions, elements, and a device pointer. For the CPU device this is just
29  * a pointer to the STL vector data, as no copying needs to take place. For
30  * other devices this is a pointer to device memory, where we will copy memory
31  * to and from. */
32
33 #include "util_debug.h"
34 #include "util_types.h"
35 #include "util_vector.h"
36
37 CCL_NAMESPACE_BEGIN
38
39 enum MemoryType {
40         MEM_READ_ONLY,
41         MEM_WRITE_ONLY,
42         MEM_READ_WRITE
43 };
44
45 /* Supported Data Types */
46
47 enum DataType {
48         TYPE_UCHAR,
49         TYPE_UINT,
50         TYPE_INT,
51         TYPE_FLOAT
52 };
53
54 static inline size_t datatype_size(DataType datatype) 
55 {
56         switch(datatype) {
57                 case TYPE_UCHAR: return sizeof(uchar);
58                 case TYPE_FLOAT: return sizeof(float);
59                 case TYPE_UINT: return sizeof(uint);
60                 case TYPE_INT: return sizeof(int);
61                 default: return 0;
62         }
63 }
64
65 /* Traits for data types */
66
67 template<typename T> struct device_type_traits {
68         static const DataType data_type = TYPE_UCHAR;
69         static const int num_elements = 0;
70 };
71
72 template<> struct device_type_traits<uchar> {
73         static const DataType data_type = TYPE_UCHAR;
74         static const int num_elements = 1;
75 };
76
77 template<> struct device_type_traits<uchar2> {
78         static const DataType data_type = TYPE_UCHAR;
79         static const int num_elements = 2;
80 };
81
82 template<> struct device_type_traits<uchar3> {
83         static const DataType data_type = TYPE_UCHAR;
84         static const int num_elements = 3;
85 };
86
87 template<> struct device_type_traits<uchar4> {
88         static const DataType data_type = TYPE_UCHAR;
89         static const int num_elements = 4;
90 };
91
92 template<> struct device_type_traits<uint> {
93         static const DataType data_type = TYPE_UINT;
94         static const int num_elements = 1;
95 };
96
97 template<> struct device_type_traits<uint2> {
98         static const DataType data_type = TYPE_UINT;
99         static const int num_elements = 2;
100 };
101
102 template<> struct device_type_traits<uint3> {
103         static const DataType data_type = TYPE_UINT;
104         static const int num_elements = 3;
105 };
106
107 template<> struct device_type_traits<uint4> {
108         static const DataType data_type = TYPE_UINT;
109         static const int num_elements = 4;
110 };
111
112 template<> struct device_type_traits<int> {
113         static const DataType data_type = TYPE_INT;
114         static const int num_elements = 1;
115 };
116
117 template<> struct device_type_traits<int2> {
118         static const DataType data_type = TYPE_INT;
119         static const int num_elements = 2;
120 };
121
122 template<> struct device_type_traits<int3> {
123         static const DataType data_type = TYPE_INT;
124         static const int num_elements = 3;
125 };
126
127 template<> struct device_type_traits<int4> {
128         static const DataType data_type = TYPE_INT;
129         static const int num_elements = 4;
130 };
131
132 template<> struct device_type_traits<float> {
133         static const DataType data_type = TYPE_FLOAT;
134         static const int num_elements = 1;
135 };
136
137 template<> struct device_type_traits<float2> {
138         static const DataType data_type = TYPE_FLOAT;
139         static const int num_elements = 2;
140 };
141
142 template<> struct device_type_traits<float3> {
143         static const DataType data_type = TYPE_FLOAT;
144         static const int num_elements = 3;
145 };
146
147 template<> struct device_type_traits<float4> {
148         static const DataType data_type = TYPE_FLOAT;
149         static const int num_elements = 4;
150 };
151
152 /* Device Memory */
153
154 class device_memory
155 {
156 public:
157         size_t memory_size() { return data_size*data_elements*datatype_size(data_type); }
158
159         /* data information */
160         DataType data_type;
161         int data_elements;
162         device_ptr data_pointer;
163         size_t data_size;
164         size_t data_width;
165         size_t data_height;
166
167         /* device pointer */
168         device_ptr device_pointer;
169
170 protected:
171         device_memory() {}
172         virtual ~device_memory() { assert(!device_pointer); }
173
174         /* no copying */
175         device_memory(const device_memory&);
176         device_memory& operator = (const device_memory&);
177 };
178
179 /* Device Vector */
180
181 template<typename T> class device_vector : public device_memory
182 {
183 public:
184         device_vector()
185         {
186                 data_type = device_type_traits<T>::data_type;
187                 data_elements = device_type_traits<T>::num_elements;
188                 data_pointer = 0;
189                 data_size = 0;
190                 data_width = 0;
191                 data_height = 0;
192
193                 assert(data_elements > 0);
194
195                 device_pointer = 0;
196         }
197
198         virtual ~device_vector() {}
199
200         /* vector functions */
201         T *resize(size_t width, size_t height = 0)
202         {
203                 data_size = (height == 0)? width: width*height;
204                 data.resize(data_size);
205                 data_pointer = (device_ptr)&data[0];
206                 data_width = width;
207                 data_height = height;
208
209                 return &data[0];
210         }
211
212         T *copy(T *ptr, size_t width, size_t height = 0)
213         {
214                 T *mem = resize(width, height);
215                 memcpy(mem, ptr, memory_size());
216                 return mem;
217         }
218
219         void copy_at(T *ptr, size_t offset, size_t size)
220         {
221                 if(size > 0) {
222                         size_t mem_size = size*data_elements*datatype_size(data_type);
223                         memcpy(&data[0] + offset, ptr, mem_size);
224                 }
225         }
226
227         void reference(T *ptr, size_t width, size_t height = 0)
228         {
229                 data.clear();
230                 data_size = (height == 0)? width: width*height;
231                 data_pointer = (device_ptr)ptr;
232                 data_width = width;
233                 data_height = height;
234         }
235
236         void clear()
237         {
238                 data.clear();
239                 data_pointer = 0;
240                 data_width = 0;
241                 data_height = 0;
242                 data_size = 0;
243         }
244
245         size_t size()
246         {
247                 return data.size();
248         }
249
250 private:
251         array<T> data;
252         bool referenced;
253 };
254
255 CCL_NAMESPACE_END
256
257 #endif /* __DEVICE_MEMORY_H__ */
258