194 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| //---------------------------------------------------------------------------//
 | |
| // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
 | |
| //
 | |
| // 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_ALGORITHM_DETAIL_COPY_TO_DEVICE_HPP
 | |
| #define BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_DEVICE_HPP
 | |
| 
 | |
| #include <iterator>
 | |
| 
 | |
| #include <boost/utility/addressof.hpp>
 | |
| 
 | |
| #include <boost/compute/command_queue.hpp>
 | |
| #include <boost/compute/async/future.hpp>
 | |
| #include <boost/compute/iterator/buffer_iterator.hpp>
 | |
| #include <boost/compute/memory/svm_ptr.hpp>
 | |
| 
 | |
| namespace boost {
 | |
| namespace compute {
 | |
| namespace detail {
 | |
| 
 | |
| template<class HostIterator, class DeviceIterator>
 | |
| inline DeviceIterator copy_to_device(HostIterator first,
 | |
|                                      HostIterator last,
 | |
|                                      DeviceIterator result,
 | |
|                                      command_queue &queue)
 | |
| {
 | |
|     typedef typename
 | |
|         std::iterator_traits<DeviceIterator>::value_type
 | |
|         value_type;
 | |
|     typedef typename
 | |
|         std::iterator_traits<DeviceIterator>::difference_type
 | |
|         difference_type;
 | |
| 
 | |
|     size_t count = iterator_range_size(first, last);
 | |
|     if(count == 0){
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     size_t offset = result.get_index();
 | |
| 
 | |
|     queue.enqueue_write_buffer(result.get_buffer(),
 | |
|                                offset * sizeof(value_type),
 | |
|                                count * sizeof(value_type),
 | |
|                                ::boost::addressof(*first));
 | |
| 
 | |
|     return result + static_cast<difference_type>(count);
 | |
| }
 | |
| 
 | |
| template<class HostIterator, class DeviceIterator>
 | |
| inline DeviceIterator copy_to_device_map(HostIterator first,
 | |
|                                          HostIterator last,
 | |
|                                          DeviceIterator result,
 | |
|                                          command_queue &queue)
 | |
| {
 | |
|     typedef typename
 | |
|         std::iterator_traits<DeviceIterator>::value_type
 | |
|         value_type;
 | |
|     typedef typename
 | |
|         std::iterator_traits<DeviceIterator>::difference_type
 | |
|         difference_type;
 | |
| 
 | |
|     size_t count = iterator_range_size(first, last);
 | |
|     if(count == 0){
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     size_t offset = result.get_index();
 | |
| 
 | |
|     // map result buffer to host
 | |
|     value_type *pointer = static_cast<value_type*>(
 | |
|         queue.enqueue_map_buffer(
 | |
|             result.get_buffer(),
 | |
|             CL_MAP_WRITE,
 | |
|             offset * sizeof(value_type),
 | |
|             count * sizeof(value_type)
 | |
|         )
 | |
|     );
 | |
| 
 | |
|     // copy [first; last) to result buffer
 | |
|     std::copy(first, last, pointer);
 | |
| 
 | |
|     // unmap result buffer
 | |
|     boost::compute::event unmap_event = queue.enqueue_unmap_buffer(
 | |
|         result.get_buffer(),
 | |
|         static_cast<void*>(pointer)
 | |
|     );
 | |
|     unmap_event.wait();
 | |
| 
 | |
|     return result + static_cast<difference_type>(count);
 | |
| }
 | |
| 
 | |
| template<class HostIterator, class DeviceIterator>
 | |
| inline future<DeviceIterator> copy_to_device_async(HostIterator first,
 | |
|                                                    HostIterator last,
 | |
|                                                    DeviceIterator result,
 | |
|                                                    command_queue &queue)
 | |
| {
 | |
|     typedef typename
 | |
|         std::iterator_traits<DeviceIterator>::value_type
 | |
|         value_type;
 | |
|     typedef typename
 | |
|         std::iterator_traits<DeviceIterator>::difference_type
 | |
|         difference_type;
 | |
| 
 | |
|     size_t count = iterator_range_size(first, last);
 | |
|     if(count == 0){
 | |
|         return future<DeviceIterator>();
 | |
|     }
 | |
| 
 | |
|     size_t offset = result.get_index();
 | |
| 
 | |
|     event event_ =
 | |
|         queue.enqueue_write_buffer_async(result.get_buffer(),
 | |
|                                          offset * sizeof(value_type),
 | |
|                                          count * sizeof(value_type),
 | |
|                                          ::boost::addressof(*first));
 | |
| 
 | |
|     return make_future(result + static_cast<difference_type>(count), event_);
 | |
| }
 | |
| 
 | |
| #ifdef CL_VERSION_2_0
 | |
| // copy_to_device() specialization for svm_ptr
 | |
| template<class HostIterator, class T>
 | |
| inline svm_ptr<T> copy_to_device(HostIterator first,
 | |
|                                  HostIterator last,
 | |
|                                  svm_ptr<T> result,
 | |
|                                  command_queue &queue)
 | |
| {
 | |
|     size_t count = iterator_range_size(first, last);
 | |
|     if(count == 0){
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     queue.enqueue_svm_memcpy(
 | |
|         result.get(), ::boost::addressof(*first), count * sizeof(T)
 | |
|     );
 | |
| 
 | |
|     return result + count;
 | |
| }
 | |
| 
 | |
| template<class HostIterator, class T>
 | |
| inline future<svm_ptr<T> > copy_to_device_async(HostIterator first,
 | |
|                                                 HostIterator last,
 | |
|                                                 svm_ptr<T> result,
 | |
|                                                 command_queue &queue)
 | |
| {
 | |
|     size_t count = iterator_range_size(first, last);
 | |
|     if(count == 0){
 | |
|         return future<svm_ptr<T> >();
 | |
|     }
 | |
| 
 | |
|     event event_ = queue.enqueue_svm_memcpy_async(
 | |
|         result.get(), ::boost::addressof(*first), count * sizeof(T)
 | |
|     );
 | |
| 
 | |
|     return make_future(result + count, event_);
 | |
| }
 | |
| 
 | |
| template<class HostIterator, class T>
 | |
| inline svm_ptr<T> copy_to_device_map(HostIterator first,
 | |
|                                               HostIterator last,
 | |
|                                               svm_ptr<T> result,
 | |
|                                               command_queue &queue)
 | |
| {
 | |
|     size_t count = iterator_range_size(first, last);
 | |
|     if(count == 0){
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     // map
 | |
|     queue.enqueue_svm_map(result.get(), count * sizeof(T), CL_MAP_WRITE);
 | |
| 
 | |
|     // copy [first; last) to result buffer
 | |
|     std::copy(first, last, static_cast<T*>(result.get()));
 | |
| 
 | |
|     // unmap result
 | |
|     queue.enqueue_svm_unmap(result.get()).wait();
 | |
| 
 | |
|     return result + count;
 | |
| }
 | |
| #endif // CL_VERSION_2_0
 | |
| 
 | |
| } // end detail namespace
 | |
| } // end compute namespace
 | |
| } // end boost namespace
 | |
| 
 | |
| #endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_DEVICE_HPP
 | 
