199 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			199 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_HOST_HPP
							 | 
						||
| 
								 | 
							
								#define BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_HOST_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>
							 | 
						||
| 
								 | 
							
								#include <boost/compute/detail/iterator_plus_distance.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost {
							 | 
						||
| 
								 | 
							
								namespace compute {
							 | 
						||
| 
								 | 
							
								namespace detail {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class DeviceIterator, class HostIterator>
							 | 
						||
| 
								 | 
							
								inline HostIterator copy_to_host(DeviceIterator first,
							 | 
						||
| 
								 | 
							
								                                 DeviceIterator last,
							 | 
						||
| 
								 | 
							
								                                 HostIterator result,
							 | 
						||
| 
								 | 
							
								                                 command_queue &queue)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    typedef typename
							 | 
						||
| 
								 | 
							
								        std::iterator_traits<DeviceIterator>::value_type
							 | 
						||
| 
								 | 
							
								        value_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    size_t count = iterator_range_size(first, last);
							 | 
						||
| 
								 | 
							
								    if(count == 0){
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const buffer &buffer = first.get_buffer();
							 | 
						||
| 
								 | 
							
								    size_t offset = first.get_index();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    queue.enqueue_read_buffer(buffer,
							 | 
						||
| 
								 | 
							
								                              offset * sizeof(value_type),
							 | 
						||
| 
								 | 
							
								                              count * sizeof(value_type),
							 | 
						||
| 
								 | 
							
								                              ::boost::addressof(*result));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return iterator_plus_distance(result, count);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class DeviceIterator, class HostIterator>
							 | 
						||
| 
								 | 
							
								inline HostIterator copy_to_host_map(DeviceIterator first,
							 | 
						||
| 
								 | 
							
								                                     DeviceIterator last,
							 | 
						||
| 
								 | 
							
								                                     HostIterator 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 = first.get_index();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // map [first; last) buffer to host
							 | 
						||
| 
								 | 
							
								    value_type *pointer = static_cast<value_type*>(
							 | 
						||
| 
								 | 
							
								        queue.enqueue_map_buffer(
							 | 
						||
| 
								 | 
							
								            first.get_buffer(),
							 | 
						||
| 
								 | 
							
								            CL_MAP_READ,
							 | 
						||
| 
								 | 
							
								            offset * sizeof(value_type),
							 | 
						||
| 
								 | 
							
								            count * sizeof(value_type)
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // copy [first; last) to result buffer
							 | 
						||
| 
								 | 
							
								    std::copy(
							 | 
						||
| 
								 | 
							
								        pointer,
							 | 
						||
| 
								 | 
							
								        pointer + static_cast<difference_type>(count),
							 | 
						||
| 
								 | 
							
								        result
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // unmap [first; last)
							 | 
						||
| 
								 | 
							
								    boost::compute::event unmap_event = queue.enqueue_unmap_buffer(
							 | 
						||
| 
								 | 
							
								        first.get_buffer(),
							 | 
						||
| 
								 | 
							
								        static_cast<void*>(pointer)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    unmap_event.wait();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return iterator_plus_distance(result, count);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class DeviceIterator, class HostIterator>
							 | 
						||
| 
								 | 
							
								inline future<HostIterator> copy_to_host_async(DeviceIterator first,
							 | 
						||
| 
								 | 
							
								                                               DeviceIterator last,
							 | 
						||
| 
								 | 
							
								                                               HostIterator result,
							 | 
						||
| 
								 | 
							
								                                               command_queue &queue)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    typedef typename
							 | 
						||
| 
								 | 
							
								        std::iterator_traits<DeviceIterator>::value_type
							 | 
						||
| 
								 | 
							
								        value_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    size_t count = iterator_range_size(first, last);
							 | 
						||
| 
								 | 
							
								    if(count == 0){
							 | 
						||
| 
								 | 
							
								        return future<HostIterator>();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const buffer &buffer = first.get_buffer();
							 | 
						||
| 
								 | 
							
								    size_t offset = first.get_index();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    event event_ =
							 | 
						||
| 
								 | 
							
								        queue.enqueue_read_buffer_async(buffer,
							 | 
						||
| 
								 | 
							
								                                        offset * sizeof(value_type),
							 | 
						||
| 
								 | 
							
								                                        count * sizeof(value_type),
							 | 
						||
| 
								 | 
							
								                                        ::boost::addressof(*result));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return make_future(iterator_plus_distance(result, count), event_);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef CL_VERSION_2_0
							 | 
						||
| 
								 | 
							
								// copy_to_host() specialization for svm_ptr
							 | 
						||
| 
								 | 
							
								template<class T, class HostIterator>
							 | 
						||
| 
								 | 
							
								inline HostIterator copy_to_host(svm_ptr<T> first,
							 | 
						||
| 
								 | 
							
								                                 svm_ptr<T> last,
							 | 
						||
| 
								 | 
							
								                                 HostIterator result,
							 | 
						||
| 
								 | 
							
								                                 command_queue &queue)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    size_t count = iterator_range_size(first, last);
							 | 
						||
| 
								 | 
							
								    if(count == 0){
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    queue.enqueue_svm_memcpy(
							 | 
						||
| 
								 | 
							
								        ::boost::addressof(*result), first.get(), count * sizeof(T)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return result + count;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class T, class HostIterator>
							 | 
						||
| 
								 | 
							
								inline future<HostIterator> copy_to_host_async(svm_ptr<T> first,
							 | 
						||
| 
								 | 
							
								                                               svm_ptr<T> last,
							 | 
						||
| 
								 | 
							
								                                               HostIterator result,
							 | 
						||
| 
								 | 
							
								                                               command_queue &queue)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    size_t count = iterator_range_size(first, last);
							 | 
						||
| 
								 | 
							
								    if(count == 0){
							 | 
						||
| 
								 | 
							
								        return future<HostIterator>();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    event event_ = queue.enqueue_svm_memcpy_async(
							 | 
						||
| 
								 | 
							
								        ::boost::addressof(*result), first.get(), count * sizeof(T)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return make_future(iterator_plus_distance(result, count), event_);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class T, class HostIterator>
							 | 
						||
| 
								 | 
							
								inline HostIterator copy_to_host_map(svm_ptr<T> first,
							 | 
						||
| 
								 | 
							
								                                     svm_ptr<T> last,
							 | 
						||
| 
								 | 
							
								                                     HostIterator result,
							 | 
						||
| 
								 | 
							
								                                     command_queue &queue)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    size_t count = iterator_range_size(first, last);
							 | 
						||
| 
								 | 
							
								    if(count == 0){
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // map
							 | 
						||
| 
								 | 
							
								    queue.enqueue_svm_map(first.get(), count * sizeof(T), CL_MAP_READ);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // copy [first; last) to result
							 | 
						||
| 
								 | 
							
								    std::copy(
							 | 
						||
| 
								 | 
							
								        static_cast<T*>(first.get()),
							 | 
						||
| 
								 | 
							
								        static_cast<T*>(last.get()),
							 | 
						||
| 
								 | 
							
								        result
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // unmap [first; last)
							 | 
						||
| 
								 | 
							
								    queue.enqueue_svm_unmap(first.get()).wait();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return iterator_plus_distance(result, count);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#endif // CL_VERSION_2_0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // end detail namespace
							 | 
						||
| 
								 | 
							
								} // end compute namespace
							 | 
						||
| 
								 | 
							
								} // end boost namespace
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_HOST_HPP
							 |