Blender  V2.93
device_memory.h
Go to the documentation of this file.
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  * Data types for allocating, copying and freeing device memory. */
23 
24 #include "util/util_array.h"
25 #include "util/util_half.h"
26 #include "util/util_string.h"
27 #include "util/util_texture.h"
28 #include "util/util_types.h"
29 #include "util/util_vector.h"
30 
32 
33 class Device;
34 
35 enum MemoryType {
42 };
43 
44 /* Supported Data Types */
45 
46 enum DataType {
55 };
56 
57 static inline size_t datatype_size(DataType datatype)
58 {
59  switch (datatype) {
60  case TYPE_UNKNOWN:
61  return 1;
62  case TYPE_UCHAR:
63  return sizeof(uchar);
64  case TYPE_FLOAT:
65  return sizeof(float);
66  case TYPE_UINT:
67  return sizeof(uint);
68  case TYPE_UINT16:
69  return sizeof(uint16_t);
70  case TYPE_INT:
71  return sizeof(int);
72  case TYPE_HALF:
73  return sizeof(half);
74  case TYPE_UINT64:
75  return sizeof(uint64_t);
76  default:
77  return 0;
78  }
79 }
80 
81 /* Traits for data types */
82 
83 template<typename T> struct device_type_traits {
85  static const int num_elements = sizeof(T);
86 };
87 
88 template<> struct device_type_traits<uchar> {
89  static const DataType data_type = TYPE_UCHAR;
90  static const int num_elements = 1;
91 };
92 
93 template<> struct device_type_traits<uchar2> {
94  static const DataType data_type = TYPE_UCHAR;
95  static const int num_elements = 2;
96 };
97 
98 template<> struct device_type_traits<uchar3> {
99  static const DataType data_type = TYPE_UCHAR;
100  static const int num_elements = 3;
101 };
102 
103 template<> struct device_type_traits<uchar4> {
104  static const DataType data_type = TYPE_UCHAR;
105  static const int num_elements = 4;
106 };
107 
108 template<> struct device_type_traits<uint> {
109  static const DataType data_type = TYPE_UINT;
110  static const int num_elements = 1;
111 };
112 
113 template<> struct device_type_traits<uint2> {
114  static const DataType data_type = TYPE_UINT;
115  static const int num_elements = 2;
116 };
117 
118 template<> struct device_type_traits<uint3> {
119  static const DataType data_type = TYPE_UINT;
120  static const int num_elements = 3;
121 };
122 
123 template<> struct device_type_traits<uint4> {
124  static const DataType data_type = TYPE_UINT;
125  static const int num_elements = 4;
126 };
127 
128 template<> struct device_type_traits<int> {
129  static const DataType data_type = TYPE_INT;
130  static const int num_elements = 1;
131 };
132 
133 template<> struct device_type_traits<int2> {
134  static const DataType data_type = TYPE_INT;
135  static const int num_elements = 2;
136 };
137 
138 template<> struct device_type_traits<int3> {
139  static const DataType data_type = TYPE_INT;
140  static const int num_elements = 3;
141 };
142 
143 template<> struct device_type_traits<int4> {
144  static const DataType data_type = TYPE_INT;
145  static const int num_elements = 4;
146 };
147 
148 template<> struct device_type_traits<float> {
149  static const DataType data_type = TYPE_FLOAT;
150  static const int num_elements = 1;
151 };
152 
153 template<> struct device_type_traits<float2> {
154  static const DataType data_type = TYPE_FLOAT;
155  static const int num_elements = 2;
156 };
157 
158 template<> struct device_type_traits<float3> {
159  static const DataType data_type = TYPE_FLOAT;
160  static const int num_elements = 4;
161 };
162 
163 template<> struct device_type_traits<float4> {
164  static const DataType data_type = TYPE_FLOAT;
165  static const int num_elements = 4;
166 };
167 
168 template<> struct device_type_traits<half> {
169  static const DataType data_type = TYPE_HALF;
170  static const int num_elements = 1;
171 };
172 
173 template<> struct device_type_traits<ushort4> {
175  static const int num_elements = 4;
176 };
177 
178 template<> struct device_type_traits<uint16_t> {
180  static const int num_elements = 1;
181 };
182 
183 template<> struct device_type_traits<half4> {
184  static const DataType data_type = TYPE_HALF;
185  static const int num_elements = 4;
186 };
187 
188 template<> struct device_type_traits<uint64_t> {
190  static const int num_elements = 1;
191 };
192 
193 /* Device Memory
194  *
195  * Base class for all device memory. This should not be allocated directly,
196  * instead the appropriate subclass can be used. */
197 
199  public:
200  size_t memory_size()
201  {
203  }
204  size_t memory_elements_size(int elements)
205  {
206  return elements * data_elements * datatype_size(data_type);
207  }
208 
209  /* Data information. */
212  size_t data_size;
213  size_t device_size;
214  size_t data_width;
215  size_t data_height;
216  size_t data_depth;
218  const char *name;
219 
220  /* Pointers. */
225  /* reference counter for shared_pointer */
227 
228  virtual ~device_memory();
229 
230  void swap_device(Device *new_device, size_t new_device_size, device_ptr new_device_ptr);
231  void restore_device();
232 
233  bool is_resident(Device *sub_device) const;
234 
235  protected:
236  friend class CUDADevice;
237  friend class OptiXDevice;
238 
239  /* Only create through subclasses. */
240  device_memory(Device *device, const char *name, MemoryType type);
241  device_memory(device_memory &&other) noexcept;
242 
243  /* No copying allowed. */
244  device_memory(const device_memory &) = delete;
246 
247  /* Host allocation on the device. All host_pointer memory should be
248  * allocated with these functions, for devices that support using
249  * the same pointer for host and device. */
250  void *host_alloc(size_t size);
251  void host_free();
252 
253  /* Device memory allocation and copying. */
254  void device_alloc();
255  void device_free();
256  void device_copy_to();
257  void device_copy_from(int y, int w, int h, int elem);
258  void device_zero();
259 
264  bool modified;
265 };
266 
267 /* Device Only Memory
268  *
269  * Working memory only needed by the device, with no corresponding allocation
270  * on the host. Only used internally in the device implementations. */
271 
272 template<typename T> class device_only_memory : public device_memory {
273  public:
274  device_only_memory(Device *device, const char *name, bool allow_host_memory_fallback = false)
275  : device_memory(device, name, allow_host_memory_fallback ? MEM_READ_WRITE : MEM_DEVICE_ONLY)
276  {
279  }
280 
281  device_only_memory(device_only_memory &&other) noexcept : device_memory(std::move(other))
282  {
283  }
284 
286  {
287  free();
288  }
289 
290  void alloc_to_device(size_t num, bool shrink_to_fit = true)
291  {
292  size_t new_size = num;
293  bool reallocate;
294 
295  if (shrink_to_fit) {
296  reallocate = (data_size != new_size);
297  }
298  else {
299  reallocate = (data_size < new_size);
300  }
301 
302  if (reallocate) {
303  device_free();
304  data_size = new_size;
305  device_alloc();
306  }
307  }
308 
309  void free()
310  {
311  device_free();
312  data_size = 0;
313  }
314 
316  {
317  device_zero();
318  }
319 };
320 
321 /* Device Vector
322  *
323  * Data vector to exchange data between host and device. Memory will be
324  * allocated on the host first with alloc() and resize, and then filled
325  * in and copied to the device with copy_to_device(). Or alternatively
326  * allocated and set to zero on the device with zero_to_device().
327  *
328  * When using memory type MEM_GLOBAL, a pointer to this memory will be
329  * automatically attached to kernel globals, using the provided name
330  * matching an entry in kernel_textures.h. */
331 
332 template<typename T> class device_vector : public device_memory {
333  public:
336  {
339  modified = true;
340  need_realloc_ = true;
341 
342  assert(data_elements > 0);
343  }
344 
345  virtual ~device_vector()
346  {
347  free();
348  }
349 
350  /* Host memory allocation. */
351  T *alloc(size_t width, size_t height = 0, size_t depth = 0)
352  {
353  size_t new_size = size(width, height, depth);
354 
355  if (new_size != data_size) {
356  device_free();
357  host_free();
358  host_pointer = host_alloc(sizeof(T) * new_size);
359  modified = true;
360  assert(device_pointer == 0);
361  }
362 
363  data_size = new_size;
364  data_width = width;
366  data_depth = depth;
367 
368  return data();
369  }
370 
371  /* Host memory resize. Only use this if the original data needs to be
372  * preserved, it is faster to call alloc() if it can be discarded. */
373  T *resize(size_t width, size_t height = 0, size_t depth = 0)
374  {
375  size_t new_size = size(width, height, depth);
376 
377  if (new_size != data_size) {
378  void *new_ptr = host_alloc(sizeof(T) * new_size);
379 
380  if (new_size && data_size) {
381  size_t min_size = ((new_size < data_size) ? new_size : data_size);
382  memcpy((T *)new_ptr, (T *)host_pointer, sizeof(T) * min_size);
383  }
384 
385  device_free();
386  host_free();
387  host_pointer = new_ptr;
388  assert(device_pointer == 0);
389  }
390 
391  data_size = new_size;
392  data_width = width;
394  data_depth = depth;
395 
396  return data();
397  }
398 
399  /* Take over data from an existing array. */
401  {
402  device_free();
403  host_free();
404 
405  data_size = from.size();
406  data_width = 0;
407  data_height = 0;
408  data_depth = 0;
409  host_pointer = from.steal_pointer();
410  assert(device_pointer == 0);
411  }
412 
413  void give_data(array<T> &to)
414  {
415  device_free();
416 
418  data_size = 0;
419  data_width = 0;
420  data_height = 0;
421  data_depth = 0;
422  host_pointer = 0;
423  assert(device_pointer == 0);
424  }
425 
426  /* Free device and host memory. */
427  void free()
428  {
429  device_free();
430  host_free();
431 
432  data_size = 0;
433  data_width = 0;
434  data_height = 0;
435  data_depth = 0;
436  host_pointer = 0;
437  modified = true;
438  need_realloc_ = true;
439  assert(device_pointer == 0);
440  }
441 
442  void free_if_need_realloc(bool force_free)
443  {
444  if (need_realloc_ || force_free) {
445  free();
446  }
447  }
448 
449  bool is_modified() const
450  {
451  return modified;
452  }
453 
455  {
456  return need_realloc_;
457  }
458 
460  {
461  modified = true;
462  }
463 
464  void tag_realloc()
465  {
466  need_realloc_ = true;
467  tag_modified();
468  }
469 
470  size_t size() const
471  {
472  return data_size;
473  }
474 
475  T *data()
476  {
477  return (T *)host_pointer;
478  }
479 
480  T &operator[](size_t i)
481  {
482  assert(i < data_size);
483  return data()[i];
484  }
485 
487  {
488  if (data_size != 0) {
489  device_copy_to();
490  }
491  }
492 
494  {
495  if (!modified) {
496  return;
497  }
498 
499  copy_to_device();
500  }
501 
503  {
504  modified = false;
505  need_realloc_ = false;
506  }
507 
509  {
511  }
512 
513  void copy_from_device(int y, int w, int h)
514  {
515  device_copy_from(y, w, h, sizeof(T));
516  }
517 
519  {
520  device_zero();
521  }
522 
523  void move_device(Device *new_device)
524  {
526  device_free();
527  device = new_device;
528  copy_to_device();
529  }
530 
531  protected:
532  size_t size(size_t width, size_t height, size_t depth)
533  {
534  return width * ((height == 0) ? 1 : height) * ((depth == 0) ? 1 : depth);
535  }
536 };
537 
538 /* Pixel Memory
539  *
540  * Device memory to efficiently draw as pixels to the screen in interactive
541  * rendering. Only copying pixels from the device is supported, not copying to. */
542 
543 template<typename T> class device_pixels : public device_vector<T> {
544  public:
546  {
547  }
548 
549  void alloc_to_device(size_t width, size_t height, size_t depth = 0)
550  {
552 
555  }
556  }
557 
558  T *copy_from_device(int y, int w, int h)
559  {
560  device_memory::device_copy_from(y, w, h, sizeof(T));
561  return device_vector<T>::data();
562  }
563 };
564 
565 /* Device Sub Memory
566  *
567  * Pointer into existing memory. It is not allocated separately, but created
568  * from an already allocated base memory. It is freed automatically when it
569  * goes out of scope, which should happen before base memory is freed.
570  *
571  * Note: some devices require offset and size of the sub_ptr to be properly
572  * aligned to device->mem_address_alingment(). */
573 
575  public:
576  device_sub_ptr(device_memory &mem, int offset, int size);
577  ~device_sub_ptr();
578 
580  {
581  return ptr;
582  }
583 
584  protected:
585  /* No copying. */
587 
590 };
591 
592 /* Device Texture
593  *
594  * 2D or 3D image texture memory. */
595 
597  public:
599  const char *name,
600  const uint slot,
601  ImageDataType image_data_type,
602  InterpolationType interpolation,
603  ExtensionType extension);
604  ~device_texture();
605 
606  void *alloc(const size_t width, const size_t height, const size_t depth = 0);
607  void copy_to_device();
608 
611 
612  protected:
613  size_t size(const size_t width, const size_t height, const size_t depth)
614  {
615  return width * ((height == 0) ? 1 : height) * ((depth == 0) ? 1 : depth);
616  }
617 };
618 
620 
621 #endif /* __DEVICE_MEMORY_H__ */
typedef float(TangentPoint)[2]
unsigned char uchar
Definition: BLI_sys_types.h:86
unsigned int uint
Definition: BLI_sys_types.h:83
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
Definition: device.h:293
void set_data(T *ptr_, size_t datasize)
Definition: util_array.h:134
friend class CUDADevice
const char * name
MemoryType type
bool is_resident(Device *sub_device) const
device_memory & operator=(const device_memory &)=delete
size_t memory_elements_size(int elements)
size_t data_height
device_memory(const device_memory &)=delete
void * host_pointer
size_t original_device_size
DataType data_type
device_memory(Device *device, const char *name, MemoryType type)
void device_copy_from(int y, int w, int h, int elem)
device_ptr original_device_ptr
Device * original_device
size_t memory_size()
device_ptr device_pointer
void * shared_pointer
void * host_alloc(size_t size)
virtual ~device_memory()
Device * device
size_t device_size
void swap_device(Device *new_device, size_t new_device_size, device_ptr new_device_ptr)
friend class OptiXDevice
device_only_memory(device_only_memory &&other) noexcept
virtual ~device_only_memory()
void alloc_to_device(size_t num, bool shrink_to_fit=true)
device_only_memory(Device *device, const char *name, bool allow_host_memory_fallback=false)
T * copy_from_device(int y, int w, int h)
void alloc_to_device(size_t width, size_t height, size_t depth=0)
device_pixels(Device *device, const char *name)
device_sub_ptr & operator=(const device_sub_ptr &)
device_ptr ptr
device_ptr operator*() const
device_sub_ptr(device_memory &mem, int offset, int size)
TextureInfo info
size_t size(const size_t width, const size_t height, const size_t depth)
void * alloc(const size_t width, const size_t height, const size_t depth=0)
device_texture(Device *device, const char *name, const uint slot, ImageDataType image_data_type, InterpolationType interpolation, ExtensionType extension)
T * alloc(size_t width, size_t height=0, size_t depth=0)
void clear_modified()
void copy_from_device()
size_t size() const
device_vector(Device *device, const char *name, MemoryType type)
void copy_to_device_if_modified()
void tag_modified()
void copy_from_device(int y, int w, int h)
bool need_realloc()
size_t size(size_t width, size_t height, size_t depth)
void move_device(Device *new_device)
virtual ~device_vector()
void copy_to_device()
T & operator[](size_t i)
void give_data(array< T > &to)
T * resize(size_t width, size_t height=0, size_t depth=0)
void tag_realloc()
bool is_modified() const
void steal_data(array< T > &from)
void free_if_need_realloc(bool force_free)
void zero_to_device()
Definition: util_half.h:41
StackEntry * from
static size_t datatype_size(DataType datatype)
Definition: device_memory.h:57
MemoryType
Definition: device_memory.h:35
@ MEM_PIXELS
Definition: device_memory.h:41
@ MEM_GLOBAL
Definition: device_memory.h:39
@ MEM_TEXTURE
Definition: device_memory.h:40
@ MEM_READ_WRITE
Definition: device_memory.h:37
@ MEM_DEVICE_ONLY
Definition: device_memory.h:38
@ MEM_READ_ONLY
Definition: device_memory.h:36
DataType
Definition: device_memory.h:46
@ TYPE_FLOAT
Definition: device_memory.h:52
@ TYPE_INT
Definition: device_memory.h:51
@ TYPE_UNKNOWN
Definition: device_memory.h:47
@ TYPE_HALF
Definition: device_memory.h:53
@ TYPE_UINT
Definition: device_memory.h:50
@ TYPE_UINT16
Definition: device_memory.h:49
@ TYPE_UINT64
Definition: device_memory.h:54
@ TYPE_UCHAR
Definition: device_memory.h:48
unsigned short half
#define CCL_NAMESPACE_END
#define T
unsigned short uint16_t
Definition: stdint.h:82
unsigned __int64 uint64_t
Definition: stdint.h:93
static const DataType data_type
Definition: device_memory.h:84
static const int num_elements
Definition: device_memory.h:85
float max
ImageDataType
Definition: util_texture.h:51
InterpolationType
Definition: util_texture.h:38
ExtensionType
Definition: util_texture.h:84
uint64_t device_ptr
Definition: util_types.h:62