1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2016 Jakub Szuppe <j.szuppe@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 // Undefining BOOST_COMPUTE_USE_OFFLINE_CACHE macro as we want to modify cached
12 // parameters for copy algorithm without any undesirable consequences (like
13 // saving modified values of those parameters).
14 #ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE
15     #undef BOOST_COMPUTE_USE_OFFLINE_CACHE
16 #endif
17 
18 #define BOOST_TEST_MODULE TestCopyTypeMismatch
19 #include <boost/test/unit_test.hpp>
20 
21 #include <list>
22 #include <vector>
23 #include <string>
24 #include <sstream>
25 #include <iterator>
26 #include <iostream>
27 
28 #include <boost/compute/svm.hpp>
29 #include <boost/compute/system.hpp>
30 #include <boost/compute/functional.hpp>
31 #include <boost/compute/command_queue.hpp>
32 #include <boost/compute/algorithm/copy.hpp>
33 #include <boost/compute/async/future.hpp>
34 #include <boost/compute/container/vector.hpp>
35 #include <boost/compute/detail/device_ptr.hpp>
36 #include <boost/compute/memory/svm_ptr.hpp>
37 #include <boost/compute/detail/parameter_cache.hpp>
38 
39 #include "quirks.hpp"
40 #include "check_macros.hpp"
41 #include "context_setup.hpp"
42 
43 namespace bc = boost::compute;
44 namespace compute = boost::compute;
45 
BOOST_AUTO_TEST_CASE(is_same_ignore_const)46 BOOST_AUTO_TEST_CASE(is_same_ignore_const)
47 {
48     BOOST_STATIC_ASSERT((
49         boost::compute::detail::is_same_value_type<
50             std::vector<int>::iterator,
51             compute::buffer_iterator<int>
52         >::value
53     ));
54     BOOST_STATIC_ASSERT((
55         boost::compute::detail::is_same_value_type<
56             std::vector<int>::const_iterator,
57             compute::buffer_iterator<int>
58         >::value
59     ));
60     BOOST_STATIC_ASSERT((
61         boost::compute::detail::is_same_value_type<
62             std::vector<int>::iterator,
63             compute::buffer_iterator<const int>
64         >::value
65     ));
66     BOOST_STATIC_ASSERT((
67         boost::compute::detail::is_same_value_type<
68             std::vector<int>::const_iterator,
69             compute::buffer_iterator<const int>
70         >::value
71     ));
72 }
73 
BOOST_AUTO_TEST_CASE(copy_to_device_float_to_double)74 BOOST_AUTO_TEST_CASE(copy_to_device_float_to_double)
75 {
76     if(!device.supports_extension("cl_khr_fp64")) {
77         std::cout << "skipping test: device does not support double" << std::endl;
78         return;
79     }
80 
81     using compute::double_;
82     using compute::float_;
83 
84     float_ host[] = { 6.1f, 10.2f, 19.3f, 25.4f };
85     bc::vector<double_> device_vector(4, context);
86 
87     // copy host float data to double device vector
88     bc::copy(host, host + 4, device_vector.begin(), queue);
89     CHECK_RANGE_EQUAL(double_, 4, device_vector, (6.1f, 10.2f, 19.3f, 25.4f));
90 }
91 
BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int)92 BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int)
93 {
94     using compute::int_;
95     using compute::float_;
96 
97     float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
98     bc::vector<int_> device_vector(4, context);
99 
100     // copy host float data to int device vector
101     bc::copy(host, host + 4, device_vector.begin(), queue);
102     CHECK_RANGE_EQUAL(
103         int_,
104         4,
105         device_vector,
106         (
107             static_cast<int_>(6.1f),
108             static_cast<int_>(-10.2f),
109             static_cast<int_>(19.3f),
110             static_cast<int_>(25.4f)
111         )
112     );
113 }
114 
115 // HOST -> DEVICE
116 
BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_mapping_device_vector)117 BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_mapping_device_vector)
118 {
119     using compute::int_;
120     using compute::uint_;
121     using compute::float_;
122 
123     float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
124     bc::vector<int_> device_vector(4, context);
125 
126     std::string cache_key =
127         std::string("__boost_compute_copy_to_device_float_int");
128     boost::shared_ptr<bc::detail::parameter_cache> parameters =
129         bc::detail::parameter_cache::get_global_cache(device);
130 
131     // save
132     uint_ map_copy_threshold =
133         parameters->get(cache_key, "map_copy_threshold", 0);
134 
135     // force copy_to_device_map (mapping device vector to the host)
136     parameters->set(cache_key, "map_copy_threshold", 1024);
137 
138     // copy host float data to int device vector
139     bc::copy(host, host + 4, device_vector.begin(), queue);
140     CHECK_RANGE_EQUAL(
141         int_,
142         4,
143         device_vector,
144         (
145             static_cast<int_>(6.1f),
146             static_cast<int_>(-10.2f),
147             static_cast<int_>(19.3f),
148             static_cast<int_>(25.4f)
149         )
150     );
151 
152     // restore
153     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
154 }
155 
BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_convert_on_host)156 BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_convert_on_host)
157 {
158     using compute::int_;
159     using compute::uint_;
160     using compute::float_;
161 
162     std::string cache_key =
163         std::string("__boost_compute_copy_to_device_float_int");
164     boost::shared_ptr<bc::detail::parameter_cache> parameters =
165         bc::detail::parameter_cache::get_global_cache(device);
166 
167     // save
168     uint_ map_copy_threshold =
169         parameters->get(cache_key, "map_copy_threshold", 0);
170     uint_ direct_copy_threshold =
171         parameters->get(cache_key, "direct_copy_threshold", 0);
172 
173     // force copying by casting input data on host and performing
174     // normal copy host->device (since types match now)
175     parameters->set(cache_key, "map_copy_threshold", 0);
176     parameters->set(cache_key, "direct_copy_threshold", 1024);
177 
178     float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
179     bc::vector<int_> device_vector(4, context);
180 
181     // copy host float data to int device vector
182     bc::copy(host, host + 4, device_vector.begin(), queue);
183     CHECK_RANGE_EQUAL(
184         int_,
185         4,
186         device_vector,
187         (
188             static_cast<int_>(6.1f),
189             static_cast<int_>(-10.2f),
190             static_cast<int_>(19.3f),
191             static_cast<int_>(25.4f)
192         )
193     );
194 
195     // restore
196     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
197     parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
198 }
199 
BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_with_transform)200 BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_with_transform)
201 {
202     using compute::int_;
203     using compute::uint_;
204     using compute::float_;
205 
206     std::string cache_key =
207         std::string("__boost_compute_copy_to_device_float_int");
208     boost::shared_ptr<bc::detail::parameter_cache> parameters =
209         bc::detail::parameter_cache::get_global_cache(device);
210 
211     // save
212     uint_ map_copy_threshold =
213         parameters->get(cache_key, "map_copy_threshold", 0);
214     uint_ direct_copy_threshold =
215         parameters->get(cache_key, "direct_copy_threshold", 0);
216 
217     // force copying by mapping input data to the device memory
218     // and using transform operation for casting & copying
219     parameters->set(cache_key, "map_copy_threshold", 0);
220     parameters->set(cache_key, "direct_copy_threshold", 0);
221 
222     float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
223     bc::vector<int_> device_vector(4, context);
224 
225     // copy host float data to int device vector
226     bc::copy(host, host + 4, device_vector.begin(), queue);
227     CHECK_RANGE_EQUAL(
228         int_,
229         4,
230         device_vector,
231         (
232             static_cast<int_>(6.1f),
233             static_cast<int_>(-10.2f),
234             static_cast<int_>(19.3f),
235             static_cast<int_>(25.4f)
236         )
237     );
238 
239     // restore
240     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
241     parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
242 }
243 
BOOST_AUTO_TEST_CASE(copy_async_to_device_float_to_int)244 BOOST_AUTO_TEST_CASE(copy_async_to_device_float_to_int)
245 {
246     using compute::int_;
247     using compute::float_;
248 
249     float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
250     bc::vector<int_> device_vector(4, context);
251 
252     // copy host float data to int device vector
253     compute::future<void> future =
254         bc::copy_async(host, host + 4, device_vector.begin(), queue);
255     future.wait();
256 
257     CHECK_RANGE_EQUAL(
258         int_,
259         4,
260         device_vector,
261         (
262             static_cast<int_>(6.1f),
263             static_cast<int_>(-10.2f),
264             static_cast<int_>(19.3f),
265             static_cast<int_>(25.4f)
266         )
267     );
268 }
269 
BOOST_AUTO_TEST_CASE(copy_async_to_device_float_to_int_empty)270 BOOST_AUTO_TEST_CASE(copy_async_to_device_float_to_int_empty)
271 {
272     using compute::int_;
273     using compute::float_;
274 
275     float_ host[] = { 6.1f, -10.2f, 19.3f, 25.4f };
276     bc::vector<int_> device_vector(size_t(4), int_(1), queue);
277 
278     // copy nothing to int device vector
279     compute::future<bc::vector<int_>::iterator > future =
280         bc::copy_async(host, host, device_vector.begin(), queue);
281     if(future.valid()) {
282         future.wait();
283     }
284 
285     CHECK_RANGE_EQUAL(
286         int_,
287         4,
288         device_vector,
289         (
290             int_(1),
291             int_(1),
292             int_(1),
293             int_(1)
294         )
295     );
296 }
297 
298 // Test copying from a std::list to a bc::vector. This differs from
299 // the test copying from std::vector because std::list has non-contiguous
300 // storage for its data values.
BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_list_device_map)301 BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_list_device_map)
302 {
303     using compute::int_;
304     using compute::uint_;
305     using compute::float_;
306 
307     std::string cache_key =
308         std::string("__boost_compute_copy_to_device_float_int");
309     boost::shared_ptr<bc::detail::parameter_cache> parameters =
310         bc::detail::parameter_cache::get_global_cache(device);
311 
312     // save
313     uint_ map_copy_threshold =
314         parameters->get(cache_key, "map_copy_threshold", 0);
315 
316     // force copy_to_device_map (mapping device vector to the host)
317     parameters->set(cache_key, "map_copy_threshold", 1024);
318 
319     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
320     std::list<float_> host(data, data + 4);
321     bc::vector<int_> device_vector(4, context);
322 
323     // copy host float data to int device vector
324     bc::copy(host.begin(), host.end(), device_vector.begin(), queue);
325     CHECK_RANGE_EQUAL(
326         int_,
327         4,
328         device_vector,
329         (
330             static_cast<int_>(6.1f),
331             static_cast<int_>(-10.2f),
332             static_cast<int_>(19.3f),
333             static_cast<int_>(25.4f)
334         )
335     );
336 
337     // restore
338     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
339 }
340 
341 // Test copying from a std::list to a bc::vector. This differs from
342 // the test copying from std::vector because std::list has non-contiguous
343 // storage for its data values.
BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_list_convert_on_host)344 BOOST_AUTO_TEST_CASE(copy_to_device_float_to_int_list_convert_on_host)
345 {
346     using compute::int_;
347     using compute::uint_;
348     using compute::float_;
349 
350     std::string cache_key =
351         std::string("__boost_compute_copy_to_device_float_int");
352     boost::shared_ptr<bc::detail::parameter_cache> parameters =
353         bc::detail::parameter_cache::get_global_cache(device);
354 
355     // save
356     uint_ map_copy_threshold =
357         parameters->get(cache_key, "map_copy_threshold", 0);
358     uint_ direct_copy_threshold =
359         parameters->get(cache_key, "direct_copy_threshold", 0);
360 
361     // force copying by casting input data on host and performing
362     // normal copy host->device (since types match now)
363     parameters->set(cache_key, "map_copy_threshold", 0);
364     parameters->set(cache_key, "direct_copy_threshold", 1024);
365 
366     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
367     std::list<float_> host(data, data + 4);
368     bc::vector<int_> device_vector(4, context);
369 
370     // copy host float data to int device vector
371     bc::copy(host.begin(), host.end(), device_vector.begin(), queue);
372     CHECK_RANGE_EQUAL(
373         int_,
374         4,
375         device_vector,
376         (
377             static_cast<int_>(6.1f),
378             static_cast<int_>(-10.2f),
379             static_cast<int_>(19.3f),
380             static_cast<int_>(25.4f)
381         )
382     );
383 
384     // restore
385     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
386     parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
387 }
388 
389 // SVM requires OpenCL 2.0
390 #if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
BOOST_AUTO_TEST_CASE(copy_to_device_svm_float_to_int_map)391 BOOST_AUTO_TEST_CASE(copy_to_device_svm_float_to_int_map)
392 {
393     REQUIRES_OPENCL_VERSION(2, 0);
394 
395     using compute::int_;
396     using compute::uint_;
397     using compute::float_;
398 
399     std::string cache_key =
400         std::string("__boost_compute_copy_to_device_float_int");
401     boost::shared_ptr<bc::detail::parameter_cache> parameters =
402         bc::detail::parameter_cache::get_global_cache(device);
403 
404     // save
405     uint_ map_copy_threshold =
406         parameters->get(cache_key, "map_copy_threshold", 0);
407 
408     // force copy_to_device_map (mapping device vector to the host)
409     parameters->set(cache_key, "map_copy_threshold", 1024);
410 
411     float_ host[] = { 5.1f, -10.3f, 19.4f, 26.7f };
412     compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
413 
414     // copy host float data to int device vector
415     bc::copy(host, host + 4, ptr, queue);
416 
417     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
418     CHECK_HOST_RANGE_EQUAL(
419         int_,
420         4,
421         static_cast<int_*>(ptr.get()),
422         (
423             static_cast<int_>(5.1f),
424             static_cast<int_>(-10.3f),
425             static_cast<int_>(19.4f),
426             static_cast<int_>(26.7f)
427         )
428     );
429     queue.enqueue_svm_unmap(ptr.get()).wait();
430 
431     compute::svm_free(context, ptr);
432 
433     // restore
434     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
435 }
436 
BOOST_AUTO_TEST_CASE(copy_to_device_svm_float_to_int_convert_on_host)437 BOOST_AUTO_TEST_CASE(copy_to_device_svm_float_to_int_convert_on_host)
438 {
439     REQUIRES_OPENCL_VERSION(2, 0);
440 
441     if(bug_in_svmmemcpy(device)){
442         std::cerr << "skipping svmmemcpy test case" << std::endl;
443         return;
444     }
445 
446     using compute::int_;
447     using compute::uint_;
448     using compute::float_;
449 
450     std::string cache_key =
451         std::string("__boost_compute_copy_to_device_float_int");
452     boost::shared_ptr<bc::detail::parameter_cache> parameters =
453         bc::detail::parameter_cache::get_global_cache(device);
454 
455     // save
456     uint_ map_copy_threshold =
457         parameters->get(cache_key, "map_copy_threshold", 0);
458     uint_ direct_copy_threshold =
459         parameters->get(cache_key, "direct_copy_threshold", 0);
460 
461     // force copying by casting input data on host and performing
462     // normal copy host->device (since types match now)
463     parameters->set(cache_key, "map_copy_threshold", 0);
464     parameters->set(cache_key, "direct_copy_threshold", 1024);
465 
466     float_ host[] = { 0.1f, 10.3f, 9.4f, -26.7f };
467     compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
468 
469     // copy host float data to int device vector
470     bc::copy(host, host + 4, ptr, queue);
471 
472     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
473     CHECK_HOST_RANGE_EQUAL(
474         int_,
475         4,
476         static_cast<int_*>(ptr.get()),
477         (
478             static_cast<int_>(0.1f),
479             static_cast<int_>(10.3f),
480             static_cast<int_>(9.4f),
481             static_cast<int_>(-26.7f)
482         )
483     );
484     queue.enqueue_svm_unmap(ptr.get()).wait();
485 
486     compute::svm_free(context, ptr);
487 
488     // restore
489     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
490     parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
491 }
492 
BOOST_AUTO_TEST_CASE(copy_to_device_svm_float_to_int_with_transform)493 BOOST_AUTO_TEST_CASE(copy_to_device_svm_float_to_int_with_transform)
494 {
495     REQUIRES_OPENCL_VERSION(2, 0);
496 
497     using compute::int_;
498     using compute::uint_;
499     using compute::float_;
500 
501     std::string cache_key =
502         std::string("__boost_compute_copy_to_device_float_int");
503     boost::shared_ptr<bc::detail::parameter_cache> parameters =
504         bc::detail::parameter_cache::get_global_cache(device);
505 
506     // save
507     uint_ map_copy_threshold =
508         parameters->get(cache_key, "map_copy_threshold", 0);
509     uint_ direct_copy_threshold =
510         parameters->get(cache_key, "direct_copy_threshold", 0);
511 
512     // force copying by mapping input data to the device memory
513     // and using transform operation (copy kernel) for casting & copying
514     parameters->set(cache_key, "map_copy_threshold", 0);
515     parameters->set(cache_key, "direct_copy_threshold", 0);
516 
517     float_ host[] = { 4.1f, -11.3f, 219.4f, -26.7f };
518     compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
519 
520     // copy host float data to int device vector
521     bc::copy(host, host + 4, ptr, queue);
522 
523     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
524     CHECK_HOST_RANGE_EQUAL(
525         int_,
526         4,
527         static_cast<int_*>(ptr.get()),
528         (
529             static_cast<int_>(4.1f),
530             static_cast<int_>(-11.3f),
531             static_cast<int_>(219.4f),
532             static_cast<int_>(-26.7f)
533         )
534     );
535     queue.enqueue_svm_unmap(ptr.get()).wait();
536 
537     compute::svm_free(context, ptr);
538 
539     // restore
540     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
541     parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
542 }
543 
BOOST_AUTO_TEST_CASE(copy_async_to_device_svm_float_to_int)544 BOOST_AUTO_TEST_CASE(copy_async_to_device_svm_float_to_int)
545 {
546     REQUIRES_OPENCL_VERSION(2, 0);
547 
548     using compute::int_;
549     using compute::uint_;
550     using compute::float_;
551 
552     float_ host[] = { 44.1f, -14.3f, 319.4f, -26.7f };
553     compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
554 
555     // copy host float data to int device vector
556     compute::future<void> future =
557         bc::copy_async(host, host + 4, ptr, queue);
558     future.wait();
559 
560     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
561     CHECK_HOST_RANGE_EQUAL(
562         int_,
563         4,
564         static_cast<int_*>(ptr.get()),
565         (
566             static_cast<int_>(44.1f),
567             static_cast<int_>(-14.3f),
568             static_cast<int_>(319.4f),
569             static_cast<int_>(-26.7f)
570         )
571     );
572     queue.enqueue_svm_unmap(ptr.get()).wait();
573 
574     compute::svm_free(context, ptr);
575 }
576 #endif
577 
578 // DEVICE -> DEVICE
579 
BOOST_AUTO_TEST_CASE(copy_on_device_float_to_int)580 BOOST_AUTO_TEST_CASE(copy_on_device_float_to_int)
581 {
582     using compute::int_;
583     using compute::float_;
584 
585     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
586     bc::vector<float_> device_fvector(data, data + 4, queue);
587     bc::vector<int_> device_ivector(4, context);
588 
589     // copy device float vector to device int vector
590     bc::copy(
591         device_fvector.begin(),
592         device_fvector.end(),
593         device_ivector.begin(),
594         queue
595     );
596 
597     CHECK_RANGE_EQUAL(
598         int_,
599         4,
600         device_ivector,
601         (
602             static_cast<int_>(6.1f),
603             static_cast<int_>(-10.2f),
604             static_cast<int_>(19.3f),
605             static_cast<int_>(25.4f)
606         )
607     );
608 }
609 
BOOST_AUTO_TEST_CASE(copy_async_on_device_float_to_int)610 BOOST_AUTO_TEST_CASE(copy_async_on_device_float_to_int)
611 {
612     using compute::int_;
613     using compute::float_;
614 
615     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
616     bc::vector<float_> device_fvector(data, data + 4, queue);
617     bc::vector<int_> device_ivector(4, context);
618 
619     // copy device float vector to device int vector
620     compute::future<void> future =
621         bc::copy_async(
622             device_fvector.begin(),
623             device_fvector.end(),
624             device_ivector.begin(),
625             queue
626         );
627     future.wait();
628 
629     CHECK_RANGE_EQUAL(
630         int_,
631         4,
632         device_ivector,
633         (
634             static_cast<int_>(6.1f),
635             static_cast<int_>(-10.2f),
636             static_cast<int_>(19.3f),
637             static_cast<int_>(25.4f)
638         )
639     );
640 }
641 
BOOST_AUTO_TEST_CASE(copy_async_on_device_float_to_int_empty)642 BOOST_AUTO_TEST_CASE(copy_async_on_device_float_to_int_empty)
643 {
644     using compute::int_;
645     using compute::float_;
646 
647     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
648     bc::vector<float_> device_fvector(data, data + 4, queue);
649     bc::vector<int_> device_ivector(size_t(4), int_(1), queue);
650 
651     // copy device float vector to device int vector
652     compute::future<void> future =
653         bc::copy_async(
654             device_fvector.begin(),
655             device_fvector.begin(),
656             device_ivector.begin(),
657             queue
658         );
659     if(future.valid()) {
660         future.wait();
661     }
662 
663     CHECK_RANGE_EQUAL(
664         int_,
665         4,
666         device_ivector,
667         (
668             int_(1),
669             int_(1),
670             int_(1),
671             int_(1)
672         )
673     );
674 }
675 
676 // SVM requires OpenCL 2.0
677 #if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
BOOST_AUTO_TEST_CASE(copy_on_device_buffer_to_svm_float_to_int)678 BOOST_AUTO_TEST_CASE(copy_on_device_buffer_to_svm_float_to_int)
679 {
680     REQUIRES_OPENCL_VERSION(2, 0);
681 
682     using compute::int_;
683     using compute::float_;
684 
685     float_ data[] = { 65.1f, -110.2f, -19.3f, 26.7f };
686     bc::vector<float_> device_vector(data, data + 4, queue);
687     compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
688 
689     // copy host float data to int svm memory
690     bc::copy(device_vector.begin(), device_vector.end(), ptr, queue);
691 
692     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
693     CHECK_HOST_RANGE_EQUAL(
694         int_,
695         4,
696         static_cast<int_*>(ptr.get()),
697         (
698             static_cast<int_>(65.1f),
699             static_cast<int_>(-110.2f),
700             static_cast<int_>(-19.3f),
701             static_cast<int_>(26.7f)
702         )
703     );
704     queue.enqueue_svm_unmap(ptr.get()).wait();
705 
706     compute::svm_free(context, ptr);
707 }
708 
BOOST_AUTO_TEST_CASE(copy_on_device_svm_to_buffer_float_to_int)709 BOOST_AUTO_TEST_CASE(copy_on_device_svm_to_buffer_float_to_int)
710 {
711     REQUIRES_OPENCL_VERSION(2, 0);
712 
713     using compute::int_;
714     using compute::float_;
715 
716     float_ data[] = { 6.1f, 11.2f, 19.3f, 6.7f };
717     bc::vector<int_> device_vector(4, context);
718     compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
719 
720     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
721     for(size_t i = 0; i < 4; i++) {
722         static_cast<float_*>(ptr.get())[i] = data[i];
723     }
724     queue.enqueue_svm_unmap(ptr.get()).wait();
725 
726     // copy host float svm data to int device vector
727     bc::copy(ptr, ptr + 4, device_vector.begin(), queue);
728 
729     CHECK_RANGE_EQUAL(
730         int_,
731         4,
732         device_vector,
733         (
734             static_cast<int_>(6.1f),
735             static_cast<int_>(11.2f),
736             static_cast<int_>(19.3f),
737             static_cast<int_>(6.7f)
738         )
739     );
740 
741     compute::svm_free(context, ptr);
742 }
743 
BOOST_AUTO_TEST_CASE(copy_on_device_svm_to_svm_float_to_int)744 BOOST_AUTO_TEST_CASE(copy_on_device_svm_to_svm_float_to_int)
745 {
746     REQUIRES_OPENCL_VERSION(2, 0);
747 
748     using compute::int_;
749     using compute::float_;
750 
751     float_ data[] = { 0.1f, -10.2f, -1.3f, 2.7f };
752     compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
753     compute::svm_ptr<int_> ptr2 = compute::svm_alloc<int_>(context, 4);
754 
755     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
756     for(size_t i = 0; i < 4; i++) {
757         static_cast<float_*>(ptr.get())[i] = data[i];
758     }
759     queue.enqueue_svm_unmap(ptr.get()).wait();
760 
761     // copy host float svm to int svm
762     bc::copy(ptr, ptr + 4, ptr2, queue);
763 
764     queue.enqueue_svm_map(ptr2.get(), 4 * sizeof(cl_int), CL_MAP_READ);
765     CHECK_HOST_RANGE_EQUAL(
766         int_,
767         4,
768         static_cast<int_*>(ptr2.get()),
769         (
770             static_cast<int_>(0.1f),
771             static_cast<int_>(-10.2f),
772             static_cast<int_>(-1.3f),
773             static_cast<int_>(2.7f)
774         )
775     );
776     queue.enqueue_svm_unmap(ptr2.get()).wait();
777 
778     compute::svm_free(context, ptr);
779     compute::svm_free(context, ptr2);
780 }
781 
BOOST_AUTO_TEST_CASE(copy_async_on_device_buffer_to_svm_float_to_int)782 BOOST_AUTO_TEST_CASE(copy_async_on_device_buffer_to_svm_float_to_int)
783 {
784     REQUIRES_OPENCL_VERSION(2, 0);
785 
786     using compute::int_;
787     using compute::float_;
788 
789     float_ data[] = { 65.1f, -110.2f, -19.3f, 26.7f };
790     bc::vector<float_> device_vector(data, data + 4, queue);
791     compute::svm_ptr<int_> ptr = compute::svm_alloc<int_>(context, 4);
792 
793     // copy host float data to int svm memory
794     compute::future<bc::svm_ptr<int_> > future =
795         bc::copy_async(device_vector.begin(), device_vector.end(), ptr, queue);
796     future.wait();
797 
798     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_READ);
799     CHECK_HOST_RANGE_EQUAL(
800         int_,
801         4,
802         static_cast<int_*>(ptr.get()),
803         (
804             static_cast<int_>(65.1f),
805             static_cast<int_>(-110.2f),
806             static_cast<int_>(-19.3f),
807             static_cast<int_>(26.7f)
808         )
809     );
810     queue.enqueue_svm_unmap(ptr.get()).wait();
811 
812     compute::svm_free(context, ptr);
813 }
814 
BOOST_AUTO_TEST_CASE(copy_async_on_device_svm_to_buffer_float_to_int)815 BOOST_AUTO_TEST_CASE(copy_async_on_device_svm_to_buffer_float_to_int)
816 {
817     REQUIRES_OPENCL_VERSION(2, 0);
818 
819     using compute::int_;
820     using compute::float_;
821 
822     float_ data[] = { 65.1f, -110.2f, -19.3f, 26.7f };
823     bc::vector<int_> device_vector(4, context);
824     compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
825 
826     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
827     for(size_t i = 0; i < 4; i++) {
828         static_cast<float_*>(ptr.get())[i] = data[i];
829     }
830     queue.enqueue_svm_unmap(ptr.get()).wait();
831 
832     // copy host float svm data to int device vector
833     compute::future<bc::vector<int_>::iterator > future =
834         bc::copy_async(ptr, ptr + 4, device_vector.begin(), queue);
835     future.wait();
836 
837     CHECK_RANGE_EQUAL(
838         int_,
839         4,
840         device_vector,
841         (
842             static_cast<int_>(65.1f),
843             static_cast<int_>(-110.2f),
844             static_cast<int_>(-19.3f),
845             static_cast<int_>(26.7f)
846         )
847     );
848 
849     compute::svm_free(context, ptr);
850 }
851 
BOOST_AUTO_TEST_CASE(copy_async_on_device_svm_to_svm_float_to_int)852 BOOST_AUTO_TEST_CASE(copy_async_on_device_svm_to_svm_float_to_int)
853 {
854     REQUIRES_OPENCL_VERSION(2, 0);
855 
856     using compute::int_;
857     using compute::float_;
858 
859     float_ data[] = { 0.1f, -10.2f, -1.3f, 2.7f };
860     compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
861     compute::svm_ptr<int_> ptr2 = compute::svm_alloc<int_>(context, 4);
862 
863     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
864     for(size_t i = 0; i < 4; i++) {
865         static_cast<float_*>(ptr.get())[i] = data[i];
866     }
867     queue.enqueue_svm_unmap(ptr.get()).wait();
868 
869     // copy host float svm to int svm
870     compute::future<bc::svm_ptr<int_> > future =
871         bc::copy_async(ptr, ptr + 4, ptr2, queue);
872     future.wait();
873 
874     queue.enqueue_svm_map(ptr2.get(), 4 * sizeof(cl_int), CL_MAP_READ);
875     CHECK_HOST_RANGE_EQUAL(
876         int_,
877         4,
878         static_cast<int_*>(ptr2.get()),
879         (
880             static_cast<int_>(0.1f),
881             static_cast<int_>(-10.2f),
882             static_cast<int_>(-1.3f),
883             static_cast<int_>(2.7f)
884         )
885     );
886     queue.enqueue_svm_unmap(ptr2.get()).wait();
887 
888     compute::svm_free(context, ptr);
889     compute::svm_free(context, ptr2);
890 }
891 #endif
892 
893 // DEVICE -> HOST
894 
BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int)895 BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int)
896 {
897     using compute::int_;
898     using compute::float_;
899 
900     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
901     bc::vector<float_> device_vector(data, data + 4, queue);
902 
903     std::vector<int_> host_vector(4);
904     // copy device float vector to int host vector
905     bc::copy(device_vector.begin(), device_vector.end(), host_vector.begin(), queue);
906     CHECK_HOST_RANGE_EQUAL(
907         int_,
908         4,
909         host_vector.begin(),
910         (
911             static_cast<int_>(6.1f),
912             static_cast<int_>(-10.2f),
913             static_cast<int_>(19.3f),
914             static_cast<int_>(25.4f)
915         )
916     );
917 }
918 
BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int_map)919 BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int_map)
920 {
921     using compute::int_;
922     using compute::uint_;
923     using compute::float_;
924 
925     std::string cache_key =
926         std::string("__boost_compute_copy_to_host_float_int");
927     boost::shared_ptr<bc::detail::parameter_cache> parameters =
928         bc::detail::parameter_cache::get_global_cache(device);
929 
930     // save
931     uint_ map_copy_threshold =
932         parameters->get(cache_key, "map_copy_threshold", 0);
933 
934     // force copy_to_host_map (mapping device vector to the host)
935     parameters->set(cache_key, "map_copy_threshold", 1024);
936 
937     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
938     bc::vector<float_> device_vector(data, data + 4, queue);
939 
940     std::vector<int_> host_vector(4);
941     // copy device float vector to int host vector
942     bc::copy(device_vector.begin(), device_vector.end(), host_vector.begin(), queue);
943     CHECK_HOST_RANGE_EQUAL(
944         int_,
945         4,
946         host_vector.begin(),
947         (
948             static_cast<int_>(6.1f),
949             static_cast<int_>(-10.2f),
950             static_cast<int_>(19.3f),
951             static_cast<int_>(25.4f)
952         )
953     );
954 
955     // restore
956     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
957 }
958 
BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int_convert_on_host)959 BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int_convert_on_host)
960 {
961     using compute::int_;
962     using compute::uint_;
963     using compute::float_;
964 
965     std::string cache_key =
966         std::string("__boost_compute_copy_to_host_float_int");
967     boost::shared_ptr<bc::detail::parameter_cache> parameters =
968         bc::detail::parameter_cache::get_global_cache(device);
969 
970     // save
971     uint_ map_copy_threshold =
972         parameters->get(cache_key, "map_copy_threshold", 0);
973     uint_ direct_copy_threshold =
974         parameters->get(cache_key, "direct_copy_threshold", 0);
975 
976     // force copying by copying input device vector to temporary
977     // host vector of the same type and then copying from that temporary
978     // vector to result using std::copy()
979     parameters->set(cache_key, "map_copy_threshold", 0);
980     parameters->set(cache_key, "direct_copy_threshold", 1024);
981 
982     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
983     bc::vector<float_> device_vector(data, data + 4, queue);
984 
985     std::vector<int_> host_vector(4);
986     // copy device float vector to int host vector
987     bc::copy(device_vector.begin(), device_vector.end(), host_vector.begin(), queue);
988     CHECK_HOST_RANGE_EQUAL(
989         int_,
990         4,
991         host_vector.begin(),
992         (
993             static_cast<int_>(6.1f),
994             static_cast<int_>(-10.2f),
995             static_cast<int_>(19.3f),
996             static_cast<int_>(25.4f)
997         )
998     );
999 
1000     // restore
1001     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
1002     parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
1003 }
1004 
BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int_convert_on_device)1005 BOOST_AUTO_TEST_CASE(copy_to_host_float_to_int_convert_on_device)
1006 {
1007     using compute::int_;
1008     using compute::uint_;
1009     using compute::float_;
1010 
1011     std::string cache_key =
1012         std::string("__boost_compute_copy_to_host_float_int");
1013     boost::shared_ptr<bc::detail::parameter_cache> parameters =
1014         bc::detail::parameter_cache::get_global_cache(device);
1015 
1016     // save
1017     uint_ map_copy_threshold =
1018         parameters->get(cache_key, "map_copy_threshold", 0);
1019     uint_ direct_copy_threshold =
1020         parameters->get(cache_key, "direct_copy_threshold", 0);
1021 
1022     // force copying by mapping output data to the device memory
1023     // and using transform operation for casting & copying
1024     parameters->set(cache_key, "map_copy_threshold", 0);
1025     parameters->set(cache_key, "direct_copy_threshold", 0);
1026 
1027     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
1028     bc::vector<float_> device_vector(data, data + 4, queue);
1029 
1030     std::vector<int_> host_vector(4);
1031     // copy device float vector to int host vector
1032     bc::copy(device_vector.begin(), device_vector.end(), host_vector.begin(), queue);
1033     CHECK_HOST_RANGE_EQUAL(
1034         int_,
1035         4,
1036         host_vector.begin(),
1037         (
1038             static_cast<int_>(6.1f),
1039             static_cast<int_>(-10.2f),
1040             static_cast<int_>(19.3f),
1041             static_cast<int_>(25.4f)
1042         )
1043     );
1044 
1045     // restore
1046     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
1047     parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
1048 }
1049 
1050 // Test copying from a bc::vector to a std::list . This differs from
1051 // the test copying to std::vector because std::list has non-contiguous
1052 // storage for its data values.
BOOST_AUTO_TEST_CASE(copy_to_host_list_float_to_int_map)1053 BOOST_AUTO_TEST_CASE(copy_to_host_list_float_to_int_map)
1054 {
1055     using compute::int_;
1056     using compute::uint_;
1057     using compute::float_;
1058 
1059     std::string cache_key =
1060         std::string("__boost_compute_copy_to_host_float_int");
1061     boost::shared_ptr<bc::detail::parameter_cache> parameters =
1062         bc::detail::parameter_cache::get_global_cache(device);
1063 
1064     // save
1065     uint_ map_copy_threshold =
1066         parameters->get(cache_key, "map_copy_threshold", 0);
1067 
1068     // force copy_to_host_map (mapping device vector to the host)
1069     parameters->set(cache_key, "map_copy_threshold", 1024);
1070 
1071     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
1072     bc::vector<float_> device_vector(data, data + 4, queue);
1073 
1074     std::list<int_> host_list(4);
1075     // copy device float vector to int host vector
1076     bc::copy(device_vector.begin(), device_vector.end(), host_list.begin(), queue);
1077 
1078     int_ expected[4] = {
1079         static_cast<int_>(6.1f),
1080         static_cast<int_>(-10.2f),
1081         static_cast<int_>(19.3f),
1082         static_cast<int_>(25.4f)
1083     };
1084     BOOST_CHECK_EQUAL_COLLECTIONS(
1085         host_list.begin(), host_list.end(),
1086         expected, expected + 4
1087     );
1088 
1089     // restore
1090     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
1091 }
1092 
1093 // Test copying from a bc::vector to a std::list . This differs from
1094 // the test copying to std::vector because std::list has non-contiguous
1095 // storage for its data values.
BOOST_AUTO_TEST_CASE(copy_to_host_list_float_to_int_covert_on_host)1096 BOOST_AUTO_TEST_CASE(copy_to_host_list_float_to_int_covert_on_host)
1097 {
1098     using compute::int_;
1099     using compute::uint_;
1100     using compute::float_;
1101 
1102     std::string cache_key =
1103         std::string("__boost_compute_copy_to_host_float_int");
1104     boost::shared_ptr<bc::detail::parameter_cache> parameters =
1105         bc::detail::parameter_cache::get_global_cache(device);
1106 
1107     // save
1108     uint_ map_copy_threshold =
1109         parameters->get(cache_key, "map_copy_threshold", 0);
1110     uint_ direct_copy_threshold =
1111         parameters->get(cache_key, "direct_copy_threshold", 0);
1112 
1113     // force copying by copying input device vector to temporary
1114     // host vector of the same type and then copying from that temporary
1115     // vector to result using std::copy()
1116     parameters->set(cache_key, "map_copy_threshold", 0);
1117     parameters->set(cache_key, "direct_copy_threshold", 1024);
1118 
1119     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
1120     bc::vector<float_> device_vector(data, data + 4, queue);
1121 
1122     std::list<int_> host_list(4);
1123     // copy device float vector to int host vector
1124     bc::copy(device_vector.begin(), device_vector.end(), host_list.begin(), queue);
1125     int_ expected[4] = {
1126         static_cast<int_>(6.1f),
1127         static_cast<int_>(-10.2f),
1128         static_cast<int_>(19.3f),
1129         static_cast<int_>(25.4f)
1130     };
1131     BOOST_CHECK_EQUAL_COLLECTIONS(
1132         host_list.begin(), host_list.end(),
1133         expected, expected + 4
1134     );
1135 
1136     // restore
1137     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
1138     parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
1139 }
1140 
BOOST_AUTO_TEST_CASE(copy_async_to_host_float_to_int)1141 BOOST_AUTO_TEST_CASE(copy_async_to_host_float_to_int)
1142 {
1143     using compute::int_;
1144     using compute::float_;
1145 
1146     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
1147     bc::vector<float_> device_vector(data, data + 4, queue);
1148     std::vector<int_> host_vector(device_vector.size());
1149 
1150     // copy device float vector to host int vector
1151     compute::future<void> future =
1152         bc::copy_async(
1153             device_vector.begin(),
1154             device_vector.end(),
1155             host_vector.begin(),
1156             queue
1157         );
1158     future.wait();
1159 
1160     CHECK_HOST_RANGE_EQUAL(
1161         int_,
1162         4,
1163         host_vector.begin(),
1164         (
1165             static_cast<int_>(6.1f),
1166             static_cast<int_>(-10.2f),
1167             static_cast<int_>(19.3f),
1168             static_cast<int_>(25.4f)
1169         )
1170     );
1171 }
1172 
BOOST_AUTO_TEST_CASE(copy_async_to_host_float_to_int_empty)1173 BOOST_AUTO_TEST_CASE(copy_async_to_host_float_to_int_empty)
1174 {
1175     using compute::int_;
1176     using compute::float_;
1177 
1178     float_ data[] = { 6.1f, -10.2f, 19.3f, 25.4f };
1179     bc::vector<float_> device_vector(data, data + 4, queue);
1180     std::vector<int_> host_vector(device_vector.size(), int_(1));
1181 
1182     // copy device float vector to host int vector
1183     compute::future<void> future =
1184         bc::copy_async(
1185             device_vector.begin(),
1186             device_vector.begin(),
1187             host_vector.begin(),
1188             queue
1189         );
1190     if(future.valid()) {
1191         future.wait();
1192     }
1193 
1194     CHECK_HOST_RANGE_EQUAL(
1195         int_,
1196         4,
1197         host_vector.begin(),
1198         (
1199             int_(1),
1200             int_(1),
1201             int_(1),
1202             int_(1)
1203         )
1204     );
1205 }
1206 
1207 // SVM requires OpenCL 2.0
1208 #if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
BOOST_AUTO_TEST_CASE(copy_to_host_svm_float_to_int_map)1209 BOOST_AUTO_TEST_CASE(copy_to_host_svm_float_to_int_map)
1210 {
1211     REQUIRES_OPENCL_VERSION(2, 0);
1212 
1213     using compute::int_;
1214     using compute::uint_;
1215     using compute::float_;
1216 
1217     std::string cache_key =
1218         std::string("__boost_compute_copy_to_host_float_int");
1219     boost::shared_ptr<bc::detail::parameter_cache> parameters =
1220         bc::detail::parameter_cache::get_global_cache(device);
1221 
1222     // save
1223     uint_ map_copy_threshold =
1224         parameters->get(cache_key, "map_copy_threshold", 0);
1225 
1226     // force copy_to_host_map (mapping device vector to the host)
1227     parameters->set(cache_key, "map_copy_threshold", 1024);
1228 
1229     float_ data[] = { 6.1f, 1.2f, 1.3f, -66.7f };
1230     std::vector<int_> host_vector(4, 0);
1231     compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
1232 
1233     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
1234     for(size_t i = 0; i < 4; i++) {
1235         static_cast<float_*>(ptr.get())[i] = data[i];
1236     }
1237     queue.enqueue_svm_unmap(ptr.get()).wait();
1238 
1239     // copy host float svm data to int host vector
1240     bc::copy(ptr, ptr + 4, host_vector.begin(), queue);
1241 
1242     CHECK_HOST_RANGE_EQUAL(
1243         int_,
1244         4,
1245         host_vector.begin(),
1246         (
1247             static_cast<int_>(6.1f),
1248             static_cast<int_>(1.2f),
1249             static_cast<int_>(1.3f),
1250             static_cast<int_>(-66.7f)
1251         )
1252     );
1253 
1254     compute::svm_free(context, ptr);
1255 
1256     // restore
1257     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
1258 }
1259 
BOOST_AUTO_TEST_CASE(copy_to_host_svm_float_to_int_convert_on_host)1260 BOOST_AUTO_TEST_CASE(copy_to_host_svm_float_to_int_convert_on_host)
1261 {
1262     REQUIRES_OPENCL_VERSION(2, 0);
1263 
1264     if(bug_in_svmmemcpy(device)){
1265         std::cerr << "skipping svmmemcpy test case" << std::endl;
1266         return;
1267     }
1268 
1269     using compute::int_;
1270     using compute::uint_;
1271     using compute::float_;
1272 
1273     std::string cache_key =
1274         std::string("__boost_compute_copy_to_host_float_int");
1275     boost::shared_ptr<bc::detail::parameter_cache> parameters =
1276         bc::detail::parameter_cache::get_global_cache(device);
1277 
1278     // save
1279     uint_ map_copy_threshold =
1280         parameters->get(cache_key, "map_copy_threshold", 0);
1281     uint_ direct_copy_threshold =
1282         parameters->get(cache_key, "direct_copy_threshold", 0);
1283 
1284     // force copying by copying input device vector to temporary
1285     // host vector of the same type and then copying from that temporary
1286     // vector to result using std::copy()
1287     parameters->set(cache_key, "map_copy_threshold", 0);
1288     parameters->set(cache_key, "direct_copy_threshold", 1024);
1289 
1290     float_ data[] = { 6.1f, 1.2f, 1.3f, 766.7f };
1291     std::vector<int_> host_vector(4, 0);
1292     compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
1293 
1294     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
1295     for(size_t i = 0; i < 4; i++) {
1296         static_cast<float_*>(ptr.get())[i] = data[i];
1297     }
1298     queue.enqueue_svm_unmap(ptr.get()).wait();
1299 
1300     // copy host float svm data to int host vector
1301     bc::copy(ptr, ptr + 4, host_vector.begin(), queue);
1302 
1303     CHECK_HOST_RANGE_EQUAL(
1304         int_,
1305         4,
1306         host_vector.begin(),
1307         (
1308             static_cast<int_>(6.1f),
1309             static_cast<int_>(1.2f),
1310             static_cast<int_>(1.3f),
1311             static_cast<int_>(766.7f)
1312         )
1313     );
1314 
1315     compute::svm_free(context, ptr);
1316 
1317     // restore
1318     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
1319     parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
1320 }
1321 
BOOST_AUTO_TEST_CASE(copy_to_host_svm_float_to_int_transform)1322 BOOST_AUTO_TEST_CASE(copy_to_host_svm_float_to_int_transform)
1323 {
1324     REQUIRES_OPENCL_VERSION(2, 0);
1325 
1326     using compute::int_;
1327     using compute::uint_;
1328     using compute::float_;
1329 
1330     std::string cache_key =
1331         std::string("__boost_compute_copy_to_host_float_int");
1332     boost::shared_ptr<bc::detail::parameter_cache> parameters =
1333         bc::detail::parameter_cache::get_global_cache(device);
1334 
1335     // save
1336     uint_ map_copy_threshold =
1337         parameters->get(cache_key, "map_copy_threshold", 0);
1338     uint_ direct_copy_threshold =
1339         parameters->get(cache_key, "direct_copy_threshold", 0);
1340 
1341     // force copying by copying input device vector to temporary
1342     // host vector of the same type and then copying from that temporary
1343     // vector to result using std::copy()
1344     parameters->set(cache_key, "map_copy_threshold", 0);
1345     parameters->set(cache_key, "direct_copy_threshold", 0);
1346 
1347     float_ data[] = { 0.1f, 11.2f, 1.3f, -66.7f };
1348     std::vector<int_> host_vector(4, 0);
1349     compute::svm_ptr<float_> ptr = compute::svm_alloc<float_>(context, 4);
1350 
1351     queue.enqueue_svm_map(ptr.get(), 4 * sizeof(cl_int), CL_MAP_WRITE);
1352     for(size_t i = 0; i < 4; i++) {
1353         static_cast<float_*>(ptr.get())[i] = data[i];
1354     }
1355     queue.enqueue_svm_unmap(ptr.get()).wait();
1356 
1357     // copy host float svm data to int host vector
1358     bc::copy(ptr, ptr + 4, host_vector.begin(), queue);
1359 
1360     CHECK_HOST_RANGE_EQUAL(
1361         int_,
1362         4,
1363         host_vector.begin(),
1364         (
1365             static_cast<int_>(0.1f),
1366             static_cast<int_>(11.2f),
1367             static_cast<int_>(1.3f),
1368             static_cast<int_>(-66.7f)
1369         )
1370     );
1371 
1372     compute::svm_free(context, ptr);
1373 
1374     // restore
1375     parameters->set(cache_key, "map_copy_threshold", map_copy_threshold);
1376     parameters->set(cache_key, "direct_copy_threshold", direct_copy_threshold);
1377 }
1378 #endif
1379 
1380 BOOST_AUTO_TEST_SUITE_END()
1381