Project revived from Feb2017
[EroSomnia.git] / deps / boost_1_63_0 / boost / compute / algorithm / fill.hpp
blobc711f46b94ef1f32655eda772a97d4d66bc80b3b
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 //---------------------------------------------------------------------------//
11 #ifndef BOOST_COMPUTE_ALGORITHM_FILL_HPP
12 #define BOOST_COMPUTE_ALGORITHM_FILL_HPP
14 #include <iterator>
16 #include <boost/mpl/int.hpp>
17 #include <boost/mpl/vector.hpp>
18 #include <boost/mpl/contains.hpp>
19 #include <boost/utility/enable_if.hpp>
21 #include <boost/compute/cl.hpp>
22 #include <boost/compute/system.hpp>
23 #include <boost/compute/command_queue.hpp>
24 #include <boost/compute/algorithm/copy.hpp>
25 #include <boost/compute/async/future.hpp>
26 #include <boost/compute/iterator/constant_iterator.hpp>
27 #include <boost/compute/iterator/discard_iterator.hpp>
28 #include <boost/compute/detail/is_buffer_iterator.hpp>
29 #include <boost/compute/detail/iterator_range_size.hpp>
31 namespace boost {
32 namespace compute {
33 namespace detail {
35 namespace mpl = boost::mpl;
37 // fills the range [first, first + count) with value using copy()
38 template<class BufferIterator, class T>
39 inline void fill_with_copy(BufferIterator first,
40 size_t count,
41 const T &value,
42 command_queue &queue)
44 ::boost::compute::copy(
45 ::boost::compute::make_constant_iterator(value, 0),
46 ::boost::compute::make_constant_iterator(value, count),
47 first,
48 queue
52 // fills the range [first, first + count) with value using copy_async()
53 template<class BufferIterator, class T>
54 inline future<void> fill_async_with_copy(BufferIterator first,
55 size_t count,
56 const T &value,
57 command_queue &queue)
59 return ::boost::compute::copy_async(
60 ::boost::compute::make_constant_iterator(value, 0),
61 ::boost::compute::make_constant_iterator(value, count),
62 first,
63 queue
67 #if defined(CL_VERSION_1_2)
69 // meta-function returing true if Iterator points to a range of values
70 // that can be filled using clEnqueueFillBuffer(). to meet this criteria
71 // it must have a buffer accessible through iter.get_buffer() and the
72 // size of its value_type must by in {1, 2, 4, 8, 16, 32, 64, 128}.
73 template<class Iterator>
74 struct is_valid_fill_buffer_iterator :
75 public mpl::and_<
76 is_buffer_iterator<Iterator>,
77 mpl::contains<
78 mpl::vector<
79 mpl::int_<1>,
80 mpl::int_<2>,
81 mpl::int_<4>,
82 mpl::int_<8>,
83 mpl::int_<16>,
84 mpl::int_<32>,
85 mpl::int_<64>,
86 mpl::int_<128>
88 mpl::int_<
89 sizeof(typename std::iterator_traits<Iterator>::value_type)
92 >::type { };
94 template<>
95 struct is_valid_fill_buffer_iterator<discard_iterator> : public boost::false_type {};
97 // specialization which uses clEnqueueFillBuffer for buffer iterators
98 template<class BufferIterator, class T>
99 inline void
100 dispatch_fill(BufferIterator first,
101 size_t count,
102 const T &value,
103 command_queue &queue,
104 typename boost::enable_if<
105 is_valid_fill_buffer_iterator<BufferIterator>
106 >::type* = 0)
108 typedef typename std::iterator_traits<BufferIterator>::value_type value_type;
110 if(count == 0){
111 // nothing to do
112 return;
115 // check if the device supports OpenCL 1.2 (required for enqueue_fill_buffer)
116 if(!queue.check_device_version(1, 2)){
117 return fill_with_copy(first, count, value, queue);
120 value_type pattern = static_cast<value_type>(value);
121 size_t offset = static_cast<size_t>(first.get_index());
123 if(count == 1){
124 // use clEnqueueWriteBuffer() directly when writing a single value
125 // to the device buffer. this is potentially more efficient and also
126 // works around a bug in the intel opencl driver.
127 queue.enqueue_write_buffer(
128 first.get_buffer(),
129 offset * sizeof(value_type),
130 sizeof(value_type),
131 &pattern
134 else {
135 queue.enqueue_fill_buffer(
136 first.get_buffer(),
137 &pattern,
138 sizeof(value_type),
139 offset * sizeof(value_type),
140 count * sizeof(value_type)
145 template<class BufferIterator, class T>
146 inline future<void>
147 dispatch_fill_async(BufferIterator first,
148 size_t count,
149 const T &value,
150 command_queue &queue,
151 typename boost::enable_if<
152 is_valid_fill_buffer_iterator<BufferIterator>
153 >::type* = 0)
155 typedef typename std::iterator_traits<BufferIterator>::value_type value_type;
157 // check if the device supports OpenCL 1.2 (required for enqueue_fill_buffer)
158 if(!queue.check_device_version(1, 2)){
159 return fill_async_with_copy(first, count, value, queue);
162 value_type pattern = static_cast<value_type>(value);
163 size_t offset = static_cast<size_t>(first.get_index());
165 event event_ =
166 queue.enqueue_fill_buffer(first.get_buffer(),
167 &pattern,
168 sizeof(value_type),
169 offset * sizeof(value_type),
170 count * sizeof(value_type));
172 return future<void>(event_);
175 #ifdef CL_VERSION_2_0
176 // specializations for svm_ptr<T>
177 template<class T>
178 inline void dispatch_fill(svm_ptr<T> first,
179 size_t count,
180 const T &value,
181 command_queue &queue)
183 if(count == 0){
184 return;
187 queue.enqueue_svm_fill(
188 first.get(), &value, sizeof(T), count * sizeof(T)
192 template<class T>
193 inline future<void> dispatch_fill_async(svm_ptr<T> first,
194 size_t count,
195 const T &value,
196 command_queue &queue)
198 if(count == 0){
199 return future<void>();
202 event event_ = queue.enqueue_svm_fill(
203 first.get(), &value, sizeof(T), count * sizeof(T)
206 return future<void>(event_);
208 #endif // CL_VERSION_2_0
210 // default implementations
211 template<class BufferIterator, class T>
212 inline void
213 dispatch_fill(BufferIterator first,
214 size_t count,
215 const T &value,
216 command_queue &queue,
217 typename boost::disable_if<
218 is_valid_fill_buffer_iterator<BufferIterator>
219 >::type* = 0)
221 fill_with_copy(first, count, value, queue);
224 template<class BufferIterator, class T>
225 inline future<void>
226 dispatch_fill_async(BufferIterator first,
227 size_t count,
228 const T &value,
229 command_queue &queue,
230 typename boost::disable_if<
231 is_valid_fill_buffer_iterator<BufferIterator>
232 >::type* = 0)
234 return fill_async_with_copy(first, count, value, queue);
236 #else
237 template<class BufferIterator, class T>
238 inline void dispatch_fill(BufferIterator first,
239 size_t count,
240 const T &value,
241 command_queue &queue)
243 fill_with_copy(first, count, value, queue);
246 template<class BufferIterator, class T>
247 inline future<void> dispatch_fill_async(BufferIterator first,
248 size_t count,
249 const T &value,
250 command_queue &queue)
252 return fill_async_with_copy(first, count, value, queue);
254 #endif // !defined(CL_VERSION_1_2)
256 } // end detail namespace
258 /// Fills the range [\p first, \p last) with \p value.
260 /// \param first first element in the range to fill
261 /// \param last last element in the range to fill
262 /// \param value value to copy to each element
263 /// \param queue command queue to perform the operation
265 /// For example, to fill a vector on the device with sevens:
266 /// \code
267 /// // vector on the device
268 /// boost::compute::vector<int> vec(10, context);
270 /// // fill vector with sevens
271 /// boost::compute::fill(vec.begin(), vec.end(), 7, queue);
272 /// \endcode
274 /// \see boost::compute::fill_n()
275 template<class BufferIterator, class T>
276 inline void fill(BufferIterator first,
277 BufferIterator last,
278 const T &value,
279 command_queue &queue = system::default_queue())
281 size_t count = detail::iterator_range_size(first, last);
282 if(count == 0){
283 return;
286 detail::dispatch_fill(first, count, value, queue);
289 template<class BufferIterator, class T>
290 inline future<void> fill_async(BufferIterator first,
291 BufferIterator last,
292 const T &value,
293 command_queue &queue = system::default_queue())
295 size_t count = detail::iterator_range_size(first, last);
296 if(count == 0){
297 return future<void>();
300 return detail::dispatch_fill_async(first, count, value, queue);
303 } // end compute namespace
304 } // end boost namespace
306 #endif // BOOST_COMPUTE_ALGORITHM_FILL_HPP