Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2017-10-21 02:09:59 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2017-10-24 02:25:19 +0300
commit070a668d04844610059aaedc80c49e9038fd1779 (patch)
treecad5c64972e45b4ee19cc8e11cdd9adedd7a2f08 /intern/cycles/device/device_memory.h
parentaa8b4c5d8124c0379eeee9eacd1a0887a573d7d7 (diff)
Code refactor: move more memory allocation logic into device API.
* Remove tex_* and pixels_* functions, replace by mem_*. * Add MEM_TEXTURE and MEM_PIXELS as memory types recognized by devices. * No longer create device_memory and call mem_* directly, always go through device_only_memory, device_vector and device_pixels.
Diffstat (limited to 'intern/cycles/device/device_memory.h')
-rw-r--r--intern/cycles/device/device_memory.h240
1 files changed, 184 insertions, 56 deletions
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h
index 3dfecde59d8..7bf8bdc1cea 100644
--- a/intern/cycles/device/device_memory.h
+++ b/intern/cycles/device/device_memory.h
@@ -19,14 +19,7 @@
/* Device Memory
*
- * This file defines data types that can be used in device memory arrays, and
- * a device_vector<T> type to store such arrays.
- *
- * device_vector<T> contains an STL vector, metadata about the data type,
- * dimensions, elements, and a device pointer. For the CPU device this is just
- * a pointer to the STL vector data, as no copying needs to take place. For
- * other devices this is a pointer to device memory, where we will copy memory
- * to and from. */
+ * Data types for allocating, copying and freeing device memory. */
#include "util/util_debug.h"
#include "util/util_half.h"
@@ -41,7 +34,9 @@ class Device;
enum MemoryType {
MEM_READ_ONLY,
MEM_WRITE_ONLY,
- MEM_READ_WRITE
+ MEM_READ_WRITE,
+ MEM_TEXTURE,
+ MEM_PIXELS
};
/* Supported Data Types */
@@ -172,7 +167,10 @@ template<> struct device_type_traits<uint64_t> {
static const int num_elements = 1;
};
-/* Device Memory */
+/* Device Memory
+ *
+ * Base class for all device memory. This should not be allocated directly,
+ * instead the appropriate subclass can be used. */
class device_memory
{
@@ -182,7 +180,7 @@ public:
return elements*data_elements*datatype_size(data_type);
}
- /* data information */
+ /* Data information. */
DataType data_type;
int data_elements;
device_ptr data_pointer;
@@ -196,25 +194,39 @@ public:
InterpolationType interpolation;
ExtensionType extension;
- /* device pointer */
+ /* Device pointer. */
Device *device;
device_ptr device_pointer;
- device_memory(Device *device, const char *name, MemoryType type);
virtual ~device_memory();
- void resize(size_t size)
- {
- data_size = size;
- data_width = size;
- }
-
protected:
- /* no copying */
+ /* Only create through subclasses. */
+ device_memory(Device *device, const char *name, MemoryType type);
+
+ /* No copying allowed. */
device_memory(const device_memory&);
device_memory& operator = (const device_memory&);
+
+ /* Host allocation on the device. All data_pointer memory should be
+ * allocated with these functions, for devices that support using
+ * the same pointer for host and device. */
+ device_ptr host_alloc(size_t size);
+ void host_free(device_ptr ptr, size_t size);
+
+ /* Device memory allocation and copying. */
+ void device_alloc();
+ void device_free();
+ void device_copy_to();
+ void device_copy_from(int y, int w, int h, int elem);
+ void device_zero();
};
+/* Device Only Memory
+ *
+ * Working memory only needed by the device, with no corresponding allocation
+ * on the host. Only used internally in the device implementations. */
+
template<typename T>
class device_only_memory : public device_memory
{
@@ -226,18 +238,43 @@ public:
data_elements = max(device_type_traits<T>::num_elements, 1);
}
- void resize(size_t num)
+ virtual ~device_only_memory()
+ {
+ free();
+ }
+
+ void alloc_to_device(size_t num)
+ {
+ data_size = num*sizeof(T);
+ device_alloc();
+ }
+
+ void free()
+ {
+ device_free();
+ }
+
+ void zero_to_device()
{
- device_memory::resize(num*sizeof(T));
+ device_zero();
}
};
-/* Device Vector */
+/* Device Vector
+ *
+ * Data vector to exchange data between host and device. Memory will be
+ * allocated on the host first with alloc() and resize, and then filled
+ * in and copied to the device with copy_to_device(). Or alternatively
+ * allocated and set to zero on the device with zero_to_device().
+ *
+ * When using memory type MEM_TEXTURE, a pointer to this memory will be
+ * automatically attached to kernel globals, using the provided name
+ * matching an entry in kernel_textures.h. */
template<typename T> class device_vector : public device_memory
{
public:
- device_vector(Device *device, const char *name, MemoryType type = MEM_READ_ONLY)
+ device_vector(Device *device, const char *name, MemoryType type)
: device_memory(device, name, type)
{
data_type = device_type_traits<T>::data_type;
@@ -246,84 +283,175 @@ public:
assert(data_elements > 0);
}
- virtual ~device_vector() {}
+ virtual ~device_vector()
+ {
+ free();
+ }
- /* vector functions */
- T *resize(size_t width, size_t height = 0, size_t depth = 0)
+ /* Host memory allocation. */
+ T *alloc(size_t width, size_t height = 0, size_t depth = 0)
{
- data_size = width * ((height == 0)? 1: height) * ((depth == 0)? 1: depth);
- if(data.resize(data_size) == NULL) {
- clear();
- return NULL;
+ size_t new_size = size(width, height, depth);
+
+ if(new_size != data_size) {
+ device_free();
+ host_free(data_pointer, sizeof(T)*data_size);
+ data_pointer = host_alloc(sizeof(T)*new_size);
}
+
+ data_size = new_size;
data_width = width;
data_height = height;
data_depth = depth;
- if(data_size == 0) {
- data_pointer = 0;
- return NULL;
+ assert(device_ptr == 0);
+
+ return get_data();
+ }
+
+ /* Host memory resize. Only use this if the original data needs to be
+ * preserved, it is faster to call alloc() if it can be discarded. */
+ T *resize(size_t width, size_t height = 0, size_t depth = 0)
+ {
+ size_t new_size = size(width, height, depth);
+
+ if(new_size != data_size) {
+ device_ptr new_ptr = host_alloc(sizeof(T)*new_size);
+
+ if(new_size && data_size) {
+ size_t min_size = ((new_size < data_size)? new_size: data_size);
+ memcpy((T*)new_ptr, (T*)data_pointer, sizeof(T)*min_size);
+ }
+
+ device_free();
+ host_free(data_pointer, sizeof(T)*data_size);
+ data_pointer = new_ptr;
}
- data_pointer = (device_ptr)&data[0];
- return &data[0];
+
+ data_size = new_size;
+ data_width = width;
+ data_height = height;
+ data_depth = depth;
+ assert(device_ptr == 0);
+
+ return get_data();
}
+ /* Take over data from an existing array. */
void steal_data(array<T>& from)
{
- data.steal_data(from);
- data_size = data.size();
- data_pointer = (data_size)? (device_ptr)&data[0]: 0;
- data_width = data_size;
+ device_free();
+ host_free(data_pointer, sizeof(T)*data_size);
+
+ data_size = from.size();
+ data_width = 0;
data_height = 0;
data_depth = 0;
+ data_pointer = (device_ptr)from.steal_pointer();
+ assert(device_pointer == 0);
}
- void clear()
+ /* Free device and host memory. */
+ void free()
{
- data.clear();
- data_pointer = 0;
+ device_free();
+ host_free(data_pointer, sizeof(T)*data_size);
+
+ data_size = 0;
data_width = 0;
data_height = 0;
data_depth = 0;
- data_size = 0;
- device_pointer = 0;
+ data_pointer = 0;
+ assert(device_pointer == 0);
}
size_t size()
{
- return data.size();
+ return data_size;
}
T* get_data()
{
- return &data[0];
+ return (T*)data_pointer;
}
T& operator[](size_t i)
{
- return data[i];
+ assert(i < data_size);
+ return get_data()[i];
}
-private:
- array<T> data;
+ void copy_to_device()
+ {
+ device_copy_to();
+ }
+
+ void copy_from_device(int y, int w, int h)
+ {
+ device_copy_from(y, w, h, sizeof(T));
+ }
+
+ void zero_to_device()
+ {
+ device_zero();
+ }
+
+protected:
+ size_t size(size_t width, size_t height, size_t depth)
+ {
+ return width * ((height == 0)? 1: height) * ((depth == 0)? 1: depth);
+ }
};
-/* A device_sub_ptr is a pointer into another existing memory.
- * Therefore, it is not allocated separately, but just created from the already allocated base memory.
- * It is freed automatically when it goes out of scope, which should happen before the base memory is freed.
- * Note that some devices require the offset and size of the sub_ptr to be properly aligned. */
+/* Pixel Memory
+ *
+ * Device memory to efficiently draw as pixels to the screen in interactive
+ * rendering. Only copying pixels from the device is supported, not copying to. */
+
+template<typename T> class device_pixels : public device_vector<T>
+{
+public:
+ device_pixels(Device *device, const char *name)
+ : device_vector<T>(device, name, MEM_PIXELS)
+ {
+ }
+
+ void alloc_to_device(size_t width, size_t height, size_t depth = 0)
+ {
+ device_vector<T>::alloc(width, height, depth);
+ device_memory::device_alloc();
+ }
+
+ T *copy_from_device(int y, int w, int h)
+ {
+ device_memory::device_copy_from(y, w, h, sizeof(T));
+ return device_vector<T>::get_data();
+ }
+};
+
+/* Device Sub Memory
+ *
+ * Pointer into existing memory. It is not allocated separately, but created
+ * from an already allocated base memory. It is freed automatically when it
+ * goes out of scope, which should happen before base memory is freed.
+ *
+ * Note: some devices require offset and size of the sub_ptr to be properly
+ * aligned to device->mem_address_alingment(). */
+
class device_sub_ptr
{
public:
device_sub_ptr(device_memory& mem, int offset, int size);
~device_sub_ptr();
- /* No copying. */
- device_sub_ptr& operator = (const device_sub_ptr&);
device_ptr operator*() const
{
return ptr;
}
+
protected:
+ /* No copying. */
+ device_sub_ptr& operator = (const device_sub_ptr&);
+
Device *device;
device_ptr ptr;
};