//---------------------------------------------------------------------------// // Copyright (c) 2013 Kyle Lutz // // Distributed under the Boost Software License, Version 1.0 // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt // // See http://boostorg.github.com/compute for more information. //---------------------------------------------------------------------------// #ifndef BOOST_COMPUTE_MEMORY_OBJECT_HPP #define BOOST_COMPUTE_MEMORY_OBJECT_HPP #include #include #include #include #include namespace boost { namespace compute { /// \class memory_object /// \brief Base-class for memory objects. /// /// The memory_object class is the base-class for memory objects on /// compute devices. /// /// \see buffer, vector class memory_object { public: /// Flags for the creation of memory objects. enum mem_flags { read_write = CL_MEM_READ_WRITE, read_only = CL_MEM_READ_ONLY, write_only = CL_MEM_WRITE_ONLY, use_host_ptr = CL_MEM_USE_HOST_PTR, alloc_host_ptr = CL_MEM_ALLOC_HOST_PTR, copy_host_ptr = CL_MEM_COPY_HOST_PTR #ifdef CL_VERSION_1_2 , host_write_only = CL_MEM_HOST_WRITE_ONLY, host_read_only = CL_MEM_HOST_READ_ONLY, host_no_access = CL_MEM_HOST_NO_ACCESS #endif }; /// Symbolic names for the OpenCL address spaces. enum address_space { global_memory, local_memory, private_memory, constant_memory }; /// Returns the underlying OpenCL memory object. cl_mem& get() const { return const_cast(m_mem); } /// Returns the size of the memory object in bytes. size_t get_memory_size() const { return get_memory_info(CL_MEM_SIZE); } /// Returns the type for the memory object. cl_mem_object_type get_memory_type() const { return get_memory_info(CL_MEM_TYPE); } /// Returns the flags for the memory object. cl_mem_flags get_memory_flags() const { return get_memory_info(CL_MEM_FLAGS); } /// Returns the context for the memory object. context get_context() const { return context(get_memory_info(CL_MEM_CONTEXT)); } /// Returns the host pointer associated with the memory object. void* get_host_ptr() const { return get_memory_info(CL_MEM_HOST_PTR); } /// Returns the reference count for the memory object. uint_ reference_count() const { return get_memory_info(CL_MEM_REFERENCE_COUNT); } /// Returns information about the memory object. /// /// \see_opencl_ref{clGetMemObjectInfo} template T get_memory_info(cl_mem_info info) const { return detail::get_object_info(clGetMemObjectInfo, m_mem, info); } #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED) /// Registers a function to be called when the memory object is deleted /// and its resources freed. /// /// \see_opencl_ref{clSetMemObjectDestructorCallback} /// /// \opencl_version_warning{1,1} void set_destructor_callback(void (BOOST_COMPUTE_CL_CALLBACK *callback)( cl_mem memobj, void *user_data ), void *user_data = 0) { cl_int ret = clSetMemObjectDestructorCallback(m_mem, callback, user_data); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(opencl_error(ret)); } } /// Registers a function to be called when the memory object is deleted /// and its resources freed. /// /// The function specified by \p callback must be invokable with zero /// arguments (e.g. \c callback()). /// /// \opencl_version_warning{1,1} template void set_destructor_callback(Function callback) { set_destructor_callback( destructor_callback_invoker, new boost::function(callback) ); } #endif // CL_VERSION_1_1 /// Returns \c true if the memory object is the same as \p other. bool operator==(const memory_object &other) const { return m_mem == other.m_mem; } /// Returns \c true if the memory object is different from \p other. bool operator!=(const memory_object &other) const { return m_mem != other.m_mem; } private: #ifdef CL_VERSION_1_1 /// \internal_ static void BOOST_COMPUTE_CL_CALLBACK destructor_callback_invoker(cl_mem, void *user_data) { boost::function *callback = static_cast *>(user_data); (*callback)(); delete callback; } #endif // CL_VERSION_1_1 protected: /// \internal_ memory_object() : m_mem(0) { } /// \internal_ explicit memory_object(cl_mem mem, bool retain = true) : m_mem(mem) { if(m_mem && retain){ clRetainMemObject(m_mem); } } /// \internal_ memory_object(const memory_object &other) : m_mem(other.m_mem) { if(m_mem){ clRetainMemObject(m_mem); } } /// \internal_ memory_object& operator=(const memory_object &other) { if(this != &other){ if(m_mem){ clReleaseMemObject(m_mem); } m_mem = other.m_mem; if(m_mem){ clRetainMemObject(m_mem); } } return *this; } #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES /// \internal_ memory_object(memory_object&& other) BOOST_NOEXCEPT : m_mem(other.m_mem) { other.m_mem = 0; } /// \internal_ memory_object& operator=(memory_object&& other) BOOST_NOEXCEPT { if(m_mem){ clReleaseMemObject(m_mem); } m_mem = other.m_mem; other.m_mem = 0; return *this; } #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES /// \internal_ ~memory_object() { if(m_mem){ BOOST_COMPUTE_ASSERT_CL_SUCCESS( clReleaseMemObject(m_mem) ); } } protected: cl_mem m_mem; }; namespace detail { // set_kernel_arg specialization for memory_object template<> struct set_kernel_arg { void operator()(kernel &kernel_, size_t index, const memory_object &mem) { kernel_.set_arg(index, mem.get()); } }; } // end detail namespace } // end compute namespace } // end boost namespace #endif // BOOST_COMPUTE_MEMORY_OBJECT_HPP