/* * Copyright 2011-2013 Blender Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ #ifndef __DEVICE_MEMORY_H__ #define __DEVICE_MEMORY_H__ /* Device Memory * * This file defines data types that can be used in device memory arrays, and * a device_vector type to store such arrays. * * device_vector 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. */ #include "util_debug.h" #include "util_types.h" #include "util_vector.h" CCL_NAMESPACE_BEGIN enum MemoryType { MEM_READ_ONLY, MEM_WRITE_ONLY, MEM_READ_WRITE }; /* Supported Data Types */ enum DataType { TYPE_UCHAR, TYPE_UINT, TYPE_INT, TYPE_FLOAT, TYPE_HALF }; static inline size_t datatype_size(DataType datatype) { switch(datatype) { case TYPE_UCHAR: return sizeof(uchar); case TYPE_FLOAT: return sizeof(float); case TYPE_UINT: return sizeof(uint); case TYPE_INT: return sizeof(int); case TYPE_HALF: return sizeof(half); default: return 0; } } /* Traits for data types */ template struct device_type_traits { static const DataType data_type = TYPE_UCHAR; static const int num_elements = 0; }; template<> struct device_type_traits { static const DataType data_type = TYPE_UCHAR; static const int num_elements = 1; }; template<> struct device_type_traits { static const DataType data_type = TYPE_UCHAR; static const int num_elements = 2; }; template<> struct device_type_traits { static const DataType data_type = TYPE_UCHAR; static const int num_elements = 3; }; template<> struct device_type_traits { static const DataType data_type = TYPE_UCHAR; static const int num_elements = 4; }; template<> struct device_type_traits { static const DataType data_type = TYPE_UINT; static const int num_elements = 1; }; template<> struct device_type_traits { static const DataType data_type = TYPE_UINT; static const int num_elements = 2; }; template<> struct device_type_traits { static const DataType data_type = TYPE_UINT; static const int num_elements = 3; }; template<> struct device_type_traits { static const DataType data_type = TYPE_UINT; static const int num_elements = 4; }; template<> struct device_type_traits { static const DataType data_type = TYPE_INT; static const int num_elements = 1; }; template<> struct device_type_traits { static const DataType data_type = TYPE_INT; static const int num_elements = 2; }; template<> struct device_type_traits { static const DataType data_type = TYPE_INT; static const int num_elements = 3; }; template<> struct device_type_traits { static const DataType data_type = TYPE_INT; static const int num_elements = 4; }; template<> struct device_type_traits { static const DataType data_type = TYPE_FLOAT; static const int num_elements = 1; }; template<> struct device_type_traits { static const DataType data_type = TYPE_FLOAT; static const int num_elements = 2; }; template<> struct device_type_traits { static const DataType data_type = TYPE_FLOAT; static const int num_elements = 3; }; template<> struct device_type_traits { static const DataType data_type = TYPE_FLOAT; static const int num_elements = 4; }; template<> struct device_type_traits { static const DataType data_type = TYPE_HALF; static const int num_elements = 4; }; /* Device Memory */ class device_memory { public: size_t memory_size() { return data_size*data_elements*datatype_size(data_type); } /* data information */ DataType data_type; int data_elements; device_ptr data_pointer; size_t data_size; size_t data_width; size_t data_height; /* device pointer */ device_ptr device_pointer; protected: device_memory() {} virtual ~device_memory() { assert(!device_pointer); } /* no copying */ device_memory(const device_memory&); device_memory& operator = (const device_memory&); }; /* Device Vector */ template class device_vector : public device_memory { public: device_vector() { data_type = device_type_traits::data_type; data_elements = device_type_traits::num_elements; data_pointer = 0; data_size = 0; data_width = 0; data_height = 0; assert(data_elements > 0); device_pointer = 0; } virtual ~device_vector() {} /* vector functions */ T *resize(size_t width, size_t height = 0) { data_size = (height == 0)? width: width*height; data.resize(data_size); data_pointer = (device_ptr)&data[0]; data_width = width; data_height = height; return &data[0]; } T *copy(T *ptr, size_t width, size_t height = 0) { T *mem = resize(width, height); memcpy(mem, ptr, memory_size()); return mem; } void copy_at(T *ptr, size_t offset, size_t size) { if(size > 0) { size_t mem_size = size*data_elements*datatype_size(data_type); memcpy(&data[0] + offset, ptr, mem_size); } } void reference(T *ptr, size_t width, size_t height = 0) { data.clear(); data_size = (height == 0)? width: width*height; data_pointer = (device_ptr)ptr; data_width = width; data_height = height; } void clear() { data.clear(); data_pointer = 0; data_width = 0; data_height = 0; data_size = 0; } size_t size() { return data.size(); } private: array data; }; CCL_NAMESPACE_END #endif /* __DEVICE_MEMORY_H__ */