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