1 //---------------------------------------------------------------------------// 2 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com> 3 // 4 // Distributed under the Boost Software License, Version 1.0 5 // See accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt 7 // 8 // See http://boostorg.github.com/compute for more information. 9 //---------------------------------------------------------------------------// 10 11 #ifndef BOOST_COMPUTE_MEMORY_OBJECT_HPP 12 #define BOOST_COMPUTE_MEMORY_OBJECT_HPP 13 14 #include <boost/compute/config.hpp> 15 #include <boost/compute/context.hpp> 16 #include <boost/compute/kernel.hpp> 17 #include <boost/compute/detail/get_object_info.hpp> 18 #include <boost/compute/detail/assert_cl_success.hpp> 19 20 namespace boost { 21 namespace compute { 22 23 /// \class memory_object 24 /// \brief Base-class for memory objects. 25 /// 26 /// The memory_object class is the base-class for memory objects on 27 /// compute devices. 28 /// 29 /// \see buffer, vector 30 class memory_object 31 { 32 public: 33 /// Flags for the creation of memory objects. 34 enum mem_flags { 35 read_write = CL_MEM_READ_WRITE, 36 read_only = CL_MEM_READ_ONLY, 37 write_only = CL_MEM_WRITE_ONLY, 38 use_host_ptr = CL_MEM_USE_HOST_PTR, 39 alloc_host_ptr = CL_MEM_ALLOC_HOST_PTR, 40 copy_host_ptr = CL_MEM_COPY_HOST_PTR 41 #ifdef BOOST_COMPUTE_CL_VERSION_1_2 42 , 43 host_write_only = CL_MEM_HOST_WRITE_ONLY, 44 host_read_only = CL_MEM_HOST_READ_ONLY, 45 host_no_access = CL_MEM_HOST_NO_ACCESS 46 #endif 47 }; 48 49 /// Symbolic names for the OpenCL address spaces. 50 enum address_space { 51 global_memory, 52 local_memory, 53 private_memory, 54 constant_memory 55 }; 56 57 /// Returns the underlying OpenCL memory object. get() const58 cl_mem& get() const 59 { 60 return const_cast<cl_mem &>(m_mem); 61 } 62 63 /// Returns the size of the memory object in bytes. get_memory_size() const64 size_t get_memory_size() const 65 { 66 return get_memory_info<size_t>(CL_MEM_SIZE); 67 } 68 69 /// Returns the type for the memory object. get_memory_type() const70 cl_mem_object_type get_memory_type() const 71 { 72 return get_memory_info<cl_mem_object_type>(CL_MEM_TYPE); 73 } 74 75 /// Returns the flags for the memory object. get_memory_flags() const76 cl_mem_flags get_memory_flags() const 77 { 78 return get_memory_info<cl_mem_flags>(CL_MEM_FLAGS); 79 } 80 81 /// Returns the context for the memory object. get_context() const82 context get_context() const 83 { 84 return context(get_memory_info<cl_context>(CL_MEM_CONTEXT)); 85 } 86 87 /// Returns the host pointer associated with the memory object. get_host_ptr() const88 void* get_host_ptr() const 89 { 90 return get_memory_info<void *>(CL_MEM_HOST_PTR); 91 } 92 93 /// Returns the reference count for the memory object. reference_count() const94 uint_ reference_count() const 95 { 96 return get_memory_info<uint_>(CL_MEM_REFERENCE_COUNT); 97 } 98 99 /// Returns information about the memory object. 100 /// 101 /// \see_opencl_ref{clGetMemObjectInfo} 102 template<class T> get_memory_info(cl_mem_info info) const103 T get_memory_info(cl_mem_info info) const 104 { 105 return detail::get_object_info<T>(clGetMemObjectInfo, m_mem, info); 106 } 107 108 #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) 109 /// Registers a function to be called when the memory object is deleted 110 /// and its resources freed. 111 /// 112 /// \see_opencl_ref{clSetMemObjectDestructorCallback} 113 /// 114 /// \opencl_version_warning{1,1} set_destructor_callback(void (BOOST_COMPUTE_CL_CALLBACK * callback)(cl_mem memobj,void * user_data),void * user_data=0)115 void set_destructor_callback(void (BOOST_COMPUTE_CL_CALLBACK *callback)( 116 cl_mem memobj, void *user_data 117 ), 118 void *user_data = 0) 119 { 120 cl_int ret = clSetMemObjectDestructorCallback(m_mem, callback, user_data); 121 if(ret != CL_SUCCESS){ 122 BOOST_THROW_EXCEPTION(opencl_error(ret)); 123 } 124 } 125 /// Registers a function to be called when the memory object is deleted 126 /// and its resources freed. 127 /// 128 /// The function specified by \p callback must be invokable with zero 129 /// arguments (e.g. \c callback()). 130 /// 131 /// \opencl_version_warning{1,1} 132 template<class Function> set_destructor_callback(Function callback)133 void set_destructor_callback(Function callback) 134 { 135 set_destructor_callback( 136 destructor_callback_invoker, 137 new boost::function<void()>(callback) 138 ); 139 } 140 #endif // BOOST_COMPUTE_CL_VERSION_1_1 141 142 /// Returns \c true if the memory object is the same as \p other. operator ==(const memory_object & other) const143 bool operator==(const memory_object &other) const 144 { 145 return m_mem == other.m_mem; 146 } 147 148 /// Returns \c true if the memory object is different from \p other. operator !=(const memory_object & other) const149 bool operator!=(const memory_object &other) const 150 { 151 return m_mem != other.m_mem; 152 } 153 154 private: 155 #ifdef BOOST_COMPUTE_CL_VERSION_1_1 156 /// \internal_ 157 static void BOOST_COMPUTE_CL_CALLBACK destructor_callback_invoker(cl_mem,void * user_data)158 destructor_callback_invoker(cl_mem, void *user_data) 159 { 160 boost::function<void()> *callback = 161 static_cast<boost::function<void()> *>(user_data); 162 163 (*callback)(); 164 165 delete callback; 166 } 167 #endif // BOOST_COMPUTE_CL_VERSION_1_1 168 169 protected: 170 /// \internal_ memory_object()171 memory_object() 172 : m_mem(0) 173 { 174 } 175 176 /// \internal_ memory_object(cl_mem mem,bool retain=true)177 explicit memory_object(cl_mem mem, bool retain = true) 178 : m_mem(mem) 179 { 180 if(m_mem && retain){ 181 clRetainMemObject(m_mem); 182 } 183 } 184 185 /// \internal_ memory_object(const memory_object & other)186 memory_object(const memory_object &other) 187 : m_mem(other.m_mem) 188 { 189 if(m_mem){ 190 clRetainMemObject(m_mem); 191 } 192 } 193 194 /// \internal_ operator =(const memory_object & other)195 memory_object& operator=(const memory_object &other) 196 { 197 if(this != &other){ 198 if(m_mem){ 199 clReleaseMemObject(m_mem); 200 } 201 202 m_mem = other.m_mem; 203 204 if(m_mem){ 205 clRetainMemObject(m_mem); 206 } 207 } 208 209 return *this; 210 } 211 212 #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES 213 /// \internal_ memory_object(memory_object && other)214 memory_object(memory_object&& other) BOOST_NOEXCEPT 215 : m_mem(other.m_mem) 216 { 217 other.m_mem = 0; 218 } 219 220 /// \internal_ operator =(memory_object && other)221 memory_object& operator=(memory_object&& other) BOOST_NOEXCEPT 222 { 223 if(m_mem){ 224 clReleaseMemObject(m_mem); 225 } 226 227 m_mem = other.m_mem; 228 other.m_mem = 0; 229 230 return *this; 231 } 232 #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES 233 234 /// \internal_ ~memory_object()235 ~memory_object() 236 { 237 if(m_mem){ 238 BOOST_COMPUTE_ASSERT_CL_SUCCESS( 239 clReleaseMemObject(m_mem) 240 ); 241 } 242 } 243 244 protected: 245 cl_mem m_mem; 246 }; 247 248 namespace detail { 249 250 // set_kernel_arg specialization for memory_object 251 template<> 252 struct set_kernel_arg<memory_object> 253 { operator ()boost::compute::detail::set_kernel_arg254 void operator()(kernel &kernel_, size_t index, const memory_object &mem) 255 { 256 kernel_.set_arg(index, mem.get()); 257 } 258 }; 259 260 } // end detail namespace 261 } // end compute namespace 262 } // end boost namespace 263 264 #endif // BOOST_COMPUTE_MEMORY_OBJECT_HPP 265