]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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_ALGORITHM_DETAIL_COPY_TO_HOST_HPP | |
12 | #define BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_HOST_HPP | |
13 | ||
14 | #include <iterator> | |
15 | ||
16 | #include <boost/utility/addressof.hpp> | |
17 | ||
18 | #include <boost/compute/command_queue.hpp> | |
19 | #include <boost/compute/async/future.hpp> | |
20 | #include <boost/compute/iterator/buffer_iterator.hpp> | |
21 | #include <boost/compute/memory/svm_ptr.hpp> | |
22 | #include <boost/compute/detail/iterator_plus_distance.hpp> | |
23 | ||
24 | namespace boost { | |
25 | namespace compute { | |
26 | namespace detail { | |
27 | ||
28 | template<class DeviceIterator, class HostIterator> | |
29 | inline HostIterator copy_to_host(DeviceIterator first, | |
30 | DeviceIterator last, | |
31 | HostIterator result, | |
92f5a8d4 TL |
32 | command_queue &queue, |
33 | const wait_list &events) | |
7c673cae FG |
34 | { |
35 | typedef typename | |
36 | std::iterator_traits<DeviceIterator>::value_type | |
37 | value_type; | |
38 | ||
39 | size_t count = iterator_range_size(first, last); | |
40 | if(count == 0){ | |
41 | return result; | |
42 | } | |
43 | ||
44 | const buffer &buffer = first.get_buffer(); | |
45 | size_t offset = first.get_index(); | |
46 | ||
47 | queue.enqueue_read_buffer(buffer, | |
48 | offset * sizeof(value_type), | |
49 | count * sizeof(value_type), | |
92f5a8d4 TL |
50 | ::boost::addressof(*result), |
51 | events); | |
7c673cae FG |
52 | |
53 | return iterator_plus_distance(result, count); | |
54 | } | |
55 | ||
56 | template<class DeviceIterator, class HostIterator> | |
57 | inline HostIterator copy_to_host_map(DeviceIterator first, | |
58 | DeviceIterator last, | |
59 | HostIterator result, | |
92f5a8d4 TL |
60 | command_queue &queue, |
61 | const wait_list &events) | |
7c673cae FG |
62 | { |
63 | typedef typename | |
64 | std::iterator_traits<DeviceIterator>::value_type | |
65 | value_type; | |
66 | typedef typename | |
67 | std::iterator_traits<DeviceIterator>::difference_type | |
68 | difference_type; | |
69 | ||
70 | size_t count = iterator_range_size(first, last); | |
71 | if(count == 0){ | |
72 | return result; | |
73 | } | |
74 | ||
75 | size_t offset = first.get_index(); | |
76 | ||
77 | // map [first; last) buffer to host | |
78 | value_type *pointer = static_cast<value_type*>( | |
79 | queue.enqueue_map_buffer( | |
80 | first.get_buffer(), | |
81 | CL_MAP_READ, | |
82 | offset * sizeof(value_type), | |
92f5a8d4 TL |
83 | count * sizeof(value_type), |
84 | events | |
7c673cae FG |
85 | ) |
86 | ); | |
87 | ||
88 | // copy [first; last) to result buffer | |
89 | std::copy( | |
90 | pointer, | |
91 | pointer + static_cast<difference_type>(count), | |
92 | result | |
93 | ); | |
94 | ||
95 | // unmap [first; last) | |
96 | boost::compute::event unmap_event = queue.enqueue_unmap_buffer( | |
97 | first.get_buffer(), | |
98 | static_cast<void*>(pointer) | |
99 | ); | |
100 | unmap_event.wait(); | |
101 | ||
102 | return iterator_plus_distance(result, count); | |
103 | } | |
104 | ||
105 | template<class DeviceIterator, class HostIterator> | |
106 | inline future<HostIterator> copy_to_host_async(DeviceIterator first, | |
107 | DeviceIterator last, | |
108 | HostIterator result, | |
92f5a8d4 TL |
109 | command_queue &queue, |
110 | const wait_list &events) | |
7c673cae FG |
111 | { |
112 | typedef typename | |
113 | std::iterator_traits<DeviceIterator>::value_type | |
114 | value_type; | |
115 | ||
116 | size_t count = iterator_range_size(first, last); | |
117 | if(count == 0){ | |
118 | return future<HostIterator>(); | |
119 | } | |
120 | ||
121 | const buffer &buffer = first.get_buffer(); | |
122 | size_t offset = first.get_index(); | |
123 | ||
124 | event event_ = | |
125 | queue.enqueue_read_buffer_async(buffer, | |
126 | offset * sizeof(value_type), | |
127 | count * sizeof(value_type), | |
92f5a8d4 TL |
128 | ::boost::addressof(*result), |
129 | events); | |
7c673cae FG |
130 | |
131 | return make_future(iterator_plus_distance(result, count), event_); | |
132 | } | |
133 | ||
b32b8144 | 134 | #ifdef BOOST_COMPUTE_CL_VERSION_2_0 |
7c673cae FG |
135 | // copy_to_host() specialization for svm_ptr |
136 | template<class T, class HostIterator> | |
137 | inline HostIterator copy_to_host(svm_ptr<T> first, | |
138 | svm_ptr<T> last, | |
139 | HostIterator result, | |
92f5a8d4 TL |
140 | command_queue &queue, |
141 | const wait_list &events) | |
7c673cae FG |
142 | { |
143 | size_t count = iterator_range_size(first, last); | |
144 | if(count == 0){ | |
145 | return result; | |
146 | } | |
147 | ||
148 | queue.enqueue_svm_memcpy( | |
92f5a8d4 | 149 | ::boost::addressof(*result), first.get(), count * sizeof(T), events |
7c673cae FG |
150 | ); |
151 | ||
152 | return result + count; | |
153 | } | |
154 | ||
155 | template<class T, class HostIterator> | |
156 | inline future<HostIterator> copy_to_host_async(svm_ptr<T> first, | |
157 | svm_ptr<T> last, | |
158 | HostIterator result, | |
92f5a8d4 TL |
159 | command_queue &queue, |
160 | const wait_list &events) | |
7c673cae FG |
161 | { |
162 | size_t count = iterator_range_size(first, last); | |
163 | if(count == 0){ | |
164 | return future<HostIterator>(); | |
165 | } | |
166 | ||
167 | event event_ = queue.enqueue_svm_memcpy_async( | |
92f5a8d4 | 168 | ::boost::addressof(*result), first.get(), count * sizeof(T), events |
7c673cae FG |
169 | ); |
170 | ||
171 | return make_future(iterator_plus_distance(result, count), event_); | |
172 | } | |
173 | ||
174 | template<class T, class HostIterator> | |
175 | inline HostIterator copy_to_host_map(svm_ptr<T> first, | |
176 | svm_ptr<T> last, | |
177 | HostIterator result, | |
92f5a8d4 TL |
178 | command_queue &queue, |
179 | const wait_list &events) | |
7c673cae FG |
180 | { |
181 | size_t count = iterator_range_size(first, last); | |
182 | if(count == 0){ | |
183 | return result; | |
184 | } | |
185 | ||
186 | // map | |
92f5a8d4 | 187 | queue.enqueue_svm_map(first.get(), count * sizeof(T), CL_MAP_READ, events); |
7c673cae FG |
188 | |
189 | // copy [first; last) to result | |
190 | std::copy( | |
191 | static_cast<T*>(first.get()), | |
192 | static_cast<T*>(last.get()), | |
193 | result | |
194 | ); | |
195 | ||
196 | // unmap [first; last) | |
197 | queue.enqueue_svm_unmap(first.get()).wait(); | |
198 | ||
199 | return iterator_plus_distance(result, count); | |
200 | } | |
b32b8144 | 201 | #endif // BOOST_COMPUTE_CL_VERSION_2_0 |
7c673cae FG |
202 | |
203 | } // end detail namespace | |
204 | } // end compute namespace | |
205 | } // end boost namespace | |
206 | ||
207 | #endif // BOOST_COMPUTE_ALGORITHM_DETAIL_COPY_TO_HOST_HPP |