1 //---------------------------------------------------------------------------// 2 // Copyright (c) 2013-2014 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_CONTAINER_MAPPED_VIEW_HPP 12 #define BOOST_COMPUTE_CONTAINER_MAPPED_VIEW_HPP 13 14 #include <cstddef> 15 #include <exception> 16 17 #include <boost/config.hpp> 18 #include <boost/throw_exception.hpp> 19 20 #include <boost/compute/buffer.hpp> 21 #include <boost/compute/system.hpp> 22 #include <boost/compute/context.hpp> 23 #include <boost/compute/command_queue.hpp> 24 #include <boost/compute/iterator/buffer_iterator.hpp> 25 26 namespace boost { 27 namespace compute { 28 29 /// \class mapped_view 30 /// \brief A mapped view of host memory. 31 /// 32 /// The mapped_view class simplifies mapping host-memory to a compute 33 /// device. This allows for host-allocated memory to be used with the 34 /// Boost.Compute algorithms. 35 /// 36 /// The following example shows how to map a simple C-array containing 37 /// data on the host to the device and run the reduce() algorithm to 38 /// calculate the sum: 39 /// 40 /// \snippet test/test_mapped_view.cpp reduce 41 /// 42 /// \see buffer 43 template<class T> 44 class mapped_view 45 { 46 public: 47 typedef T value_type; 48 typedef size_t size_type; 49 typedef ptrdiff_t difference_type; 50 typedef buffer_iterator<T> iterator; 51 typedef buffer_iterator<T> const_iterator; 52 53 /// Creates a null mapped_view object. mapped_view()54 mapped_view() 55 { 56 m_mapped_ptr = 0; 57 } 58 59 /// Creates a mapped_view for \p host_ptr with \p n elements. After 60 /// constructing a mapped_view the data is available for use by a 61 /// compute device. Use the \p unmap() method to make the updated data 62 /// available to the host. mapped_view(T * host_ptr,size_type n,const context & context=system::default_context ())63 mapped_view(T *host_ptr, 64 size_type n, 65 const context &context = system::default_context()) 66 : m_buffer(_make_mapped_buffer(host_ptr, n, context)) 67 { 68 m_mapped_ptr = 0; 69 } 70 71 /// Creates a read-only mapped_view for \p host_ptr with \p n elements. 72 /// After constructing a mapped_view the data is available for use by a 73 /// compute device. Use the \p unmap() method to make the updated data 74 /// available to the host. mapped_view(const T * host_ptr,size_type n,const context & context=system::default_context ())75 mapped_view(const T *host_ptr, 76 size_type n, 77 const context &context = system::default_context()) 78 : m_buffer(_make_mapped_buffer(host_ptr, n, context)) 79 { 80 m_mapped_ptr = 0; 81 } 82 83 /// Creates a copy of \p other. mapped_view(const mapped_view<T> & other)84 mapped_view(const mapped_view<T> &other) 85 : m_buffer(other.m_buffer) 86 { 87 m_mapped_ptr = 0; 88 } 89 90 /// Copies the mapped buffer from \p other. operator =(const mapped_view<T> & other)91 mapped_view<T>& operator=(const mapped_view<T> &other) 92 { 93 if(this != &other){ 94 m_buffer = other.m_buffer; 95 m_mapped_ptr = 0; 96 } 97 98 return *this; 99 } 100 101 /// Destroys the mapped_view object. ~mapped_view()102 ~mapped_view() 103 { 104 } 105 106 /// Returns an iterator to the first element in the mapped_view. begin()107 iterator begin() 108 { 109 return ::boost::compute::make_buffer_iterator<T>(m_buffer, 0); 110 } 111 112 /// Returns a const_iterator to the first element in the mapped_view. begin() const113 const_iterator begin() const 114 { 115 return ::boost::compute::make_buffer_iterator<T>(m_buffer, 0); 116 } 117 118 /// Returns a const_iterator to the first element in the mapped_view. cbegin() const119 const_iterator cbegin() const 120 { 121 return begin(); 122 } 123 124 /// Returns an iterator to one past the last element in the mapped_view. end()125 iterator end() 126 { 127 return ::boost::compute::make_buffer_iterator<T>(m_buffer, size()); 128 } 129 130 /// Returns a const_iterator to one past the last element in the mapped_view. end() const131 const_iterator end() const 132 { 133 return ::boost::compute::make_buffer_iterator<T>(m_buffer, size()); 134 } 135 136 /// Returns a const_iterator to one past the last element in the mapped_view. cend() const137 const_iterator cend() const 138 { 139 return end(); 140 } 141 142 /// Returns the number of elements in the mapped_view. size() const143 size_type size() const 144 { 145 return m_buffer.size() / sizeof(T); 146 } 147 148 /// Returns the host data pointer. get_host_ptr()149 T* get_host_ptr() 150 { 151 return static_cast<T *>(m_buffer.get_info<void *>(CL_MEM_HOST_PTR)); 152 } 153 154 /// Returns the host data pointer. get_host_ptr() const155 const T* get_host_ptr() const 156 { 157 return static_cast<T *>(m_buffer.get_info<void *>(CL_MEM_HOST_PTR)); 158 } 159 160 /// Resizes the mapped_view to \p size elements. resize(size_type size)161 void resize(size_type size) 162 { 163 T *old_ptr = get_host_ptr(); 164 165 m_buffer = _make_mapped_buffer(old_ptr, size, m_buffer.get_context()); 166 } 167 168 /// Returns \c true if the mapped_view is empty. empty() const169 bool empty() const 170 { 171 return size() == 0; 172 } 173 174 /// Returns the mapped buffer. get_buffer() const175 const buffer& get_buffer() const 176 { 177 return m_buffer; 178 } 179 180 /// Maps the buffer into the host address space. 181 /// 182 /// \see_opencl_ref{clEnqueueMapBuffer} map(cl_map_flags flags,command_queue & queue)183 void map(cl_map_flags flags, command_queue &queue) 184 { 185 BOOST_ASSERT(m_mapped_ptr == 0); 186 187 m_mapped_ptr = queue.enqueue_map_buffer( 188 m_buffer, flags, 0, m_buffer.size() 189 ); 190 } 191 192 /// Maps the buffer into the host address space for reading and writing. 193 /// 194 /// Equivalent to: 195 /// \code 196 /// map(CL_MAP_READ | CL_MAP_WRITE, queue); 197 /// \endcode map(command_queue & queue)198 void map(command_queue &queue) 199 { 200 map(CL_MAP_READ | CL_MAP_WRITE, queue); 201 } 202 203 /// Unmaps the buffer from the host address space. 204 /// 205 /// \see_opencl_ref{clEnqueueUnmapMemObject} unmap(command_queue & queue)206 void unmap(command_queue &queue) 207 { 208 BOOST_ASSERT(m_mapped_ptr != 0); 209 210 queue.enqueue_unmap_buffer(m_buffer, m_mapped_ptr); 211 212 m_mapped_ptr = 0; 213 } 214 215 private: 216 /// \internal_ _make_mapped_buffer(T * host_ptr,size_t n,const context & context)217 static buffer _make_mapped_buffer(T *host_ptr, 218 size_t n, 219 const context &context) 220 { 221 return buffer( 222 context, 223 n * sizeof(T), 224 buffer::read_write | buffer::use_host_ptr, 225 host_ptr 226 ); 227 } 228 229 /// \internal_ _make_mapped_buffer(const T * host_ptr,size_t n,const context & context)230 static buffer _make_mapped_buffer(const T *host_ptr, 231 size_t n, 232 const context &context) 233 { 234 return buffer( 235 context, 236 n * sizeof(T), 237 buffer::read_only | buffer::use_host_ptr, 238 const_cast<void *>(static_cast<const void *>(host_ptr)) 239 ); 240 } 241 242 private: 243 buffer m_buffer; 244 void *m_mapped_ptr; 245 }; 246 247 } // end compute namespace 248 } // end boost namespace 249 250 #endif // BOOST_COMPUTE_CONTAINER_MAPPED_VIEW_HPP 251