]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/compute/command_queue.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / compute / command_queue.hpp
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_COMMAND_QUEUE_HPP
12 #define BOOST_COMPUTE_COMMAND_QUEUE_HPP
13
14 #include <cstddef>
15 #include <algorithm>
16
17 #include <boost/assert.hpp>
18
19 #include <boost/compute/config.hpp>
20 #include <boost/compute/event.hpp>
21 #include <boost/compute/buffer.hpp>
22 #include <boost/compute/device.hpp>
23 #include <boost/compute/kernel.hpp>
24 #include <boost/compute/context.hpp>
25 #include <boost/compute/exception.hpp>
26 #include <boost/compute/image/image1d.hpp>
27 #include <boost/compute/image/image2d.hpp>
28 #include <boost/compute/image/image3d.hpp>
29 #include <boost/compute/image/image_object.hpp>
30 #include <boost/compute/utility/wait_list.hpp>
31 #include <boost/compute/detail/get_object_info.hpp>
32 #include <boost/compute/detail/assert_cl_success.hpp>
33 #include <boost/compute/detail/diagnostic.hpp>
34 #include <boost/compute/utility/extents.hpp>
35
36 namespace boost {
37 namespace compute {
38 namespace detail {
39
40 inline void BOOST_COMPUTE_CL_CALLBACK
41 nullary_native_kernel_trampoline(void *user_func_ptr)
42 {
43 void (*user_func)();
44 std::memcpy(&user_func, user_func_ptr, sizeof(user_func));
45 user_func();
46 }
47
48 } // end detail namespace
49
50 /// \class command_queue
51 /// \brief A command queue.
52 ///
53 /// Command queues provide the interface for interacting with compute
54 /// devices. The command_queue class provides methods to copy data to
55 /// and from a compute device as well as execute compute kernels.
56 ///
57 /// Command queues are created for a compute device within a compute
58 /// context.
59 ///
60 /// For example, to create a context and command queue for the default device
61 /// on the system (this is the normal set up code used by almost all OpenCL
62 /// programs):
63 /// \code
64 /// #include <boost/compute/core.hpp>
65 ///
66 /// // get the default compute device
67 /// boost::compute::device device = boost::compute::system::default_device();
68 ///
69 /// // set up a compute context and command queue
70 /// boost::compute::context context(device);
71 /// boost::compute::command_queue queue(context, device);
72 /// \endcode
73 ///
74 /// The default command queue for the system can be obtained with the
75 /// system::default_queue() method.
76 ///
77 /// \see buffer, context, kernel
78 class command_queue
79 {
80 public:
81 enum properties {
82 enable_profiling = CL_QUEUE_PROFILING_ENABLE,
83 enable_out_of_order_execution = CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
84 #ifdef BOOST_COMPUTE_CL_VERSION_2_0
85 ,
86 on_device = CL_QUEUE_ON_DEVICE,
87 on_device_default = CL_QUEUE_ON_DEVICE_DEFAULT
88 #endif
89 };
90
91 enum map_flags {
92 map_read = CL_MAP_READ,
93 map_write = CL_MAP_WRITE
94 #ifdef BOOST_COMPUTE_CL_VERSION_1_2
95 ,
96 map_write_invalidate_region = CL_MAP_WRITE_INVALIDATE_REGION
97 #endif
98 };
99
100 #ifdef BOOST_COMPUTE_CL_VERSION_1_2
101 enum mem_migration_flags {
102 migrate_to_host = CL_MIGRATE_MEM_OBJECT_HOST,
103 migrate_content_undefined = CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED
104 };
105 #endif // BOOST_COMPUTE_CL_VERSION_1_2
106
107 /// Creates a null command queue.
108 command_queue()
109 : m_queue(0)
110 {
111 }
112
113 explicit command_queue(cl_command_queue queue, bool retain = true)
114 : m_queue(queue)
115 {
116 if(m_queue && retain){
117 clRetainCommandQueue(m_queue);
118 }
119 }
120
121 /// Creates a command queue in \p context for \p device with
122 /// \p properties.
123 ///
124 /// \see_opencl_ref{clCreateCommandQueue}
125 command_queue(const context &context,
126 const device &device,
127 cl_command_queue_properties properties = 0)
128 {
129 BOOST_ASSERT(device.id() != 0);
130
131 cl_int error = 0;
132
133 #ifdef BOOST_COMPUTE_CL_VERSION_2_0
134 if (device.check_version(2, 0)){
135 std::vector<cl_queue_properties> queue_properties;
136 if(properties){
137 queue_properties.push_back(CL_QUEUE_PROPERTIES);
138 queue_properties.push_back(cl_queue_properties(properties));
139 queue_properties.push_back(cl_queue_properties(0));
140 }
141
142 const cl_queue_properties *queue_properties_ptr =
143 queue_properties.empty() ? 0 : &queue_properties[0];
144
145 m_queue = clCreateCommandQueueWithProperties(
146 context, device.id(), queue_properties_ptr, &error
147 );
148 } else
149 #endif
150 {
151 // Suppress deprecated declarations warning
152 BOOST_COMPUTE_DISABLE_DEPRECATED_DECLARATIONS();
153 m_queue = clCreateCommandQueue(
154 context, device.id(), properties, &error
155 );
156 BOOST_COMPUTE_ENABLE_DEPRECATED_DECLARATIONS();
157 }
158
159 if(!m_queue){
160 BOOST_THROW_EXCEPTION(opencl_error(error));
161 }
162 }
163
164 /// Creates a new command queue object as a copy of \p other.
165 command_queue(const command_queue &other)
166 : m_queue(other.m_queue)
167 {
168 if(m_queue){
169 clRetainCommandQueue(m_queue);
170 }
171 }
172
173 /// Copies the command queue object from \p other to \c *this.
174 command_queue& operator=(const command_queue &other)
175 {
176 if(this != &other){
177 if(m_queue){
178 clReleaseCommandQueue(m_queue);
179 }
180
181 m_queue = other.m_queue;
182
183 if(m_queue){
184 clRetainCommandQueue(m_queue);
185 }
186 }
187
188 return *this;
189 }
190
191 #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
192 /// Move-constructs a new command queue object from \p other.
193 command_queue(command_queue&& other) BOOST_NOEXCEPT
194 : m_queue(other.m_queue)
195 {
196 other.m_queue = 0;
197 }
198
199 /// Move-assigns the command queue from \p other to \c *this.
200 command_queue& operator=(command_queue&& other) BOOST_NOEXCEPT
201 {
202 if(m_queue){
203 clReleaseCommandQueue(m_queue);
204 }
205
206 m_queue = other.m_queue;
207 other.m_queue = 0;
208
209 return *this;
210 }
211 #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
212
213 /// Destroys the command queue.
214 ///
215 /// \see_opencl_ref{clReleaseCommandQueue}
216 ~command_queue()
217 {
218 if(m_queue){
219 BOOST_COMPUTE_ASSERT_CL_SUCCESS(
220 clReleaseCommandQueue(m_queue)
221 );
222 }
223 }
224
225 /// Returns the underlying OpenCL command queue.
226 cl_command_queue& get() const
227 {
228 return const_cast<cl_command_queue &>(m_queue);
229 }
230
231 /// Returns the device that the command queue issues commands to.
232 device get_device() const
233 {
234 return device(get_info<cl_device_id>(CL_QUEUE_DEVICE));
235 }
236
237 /// Returns the context for the command queue.
238 context get_context() const
239 {
240 return context(get_info<cl_context>(CL_QUEUE_CONTEXT));
241 }
242
243 /// Returns information about the command queue.
244 ///
245 /// \see_opencl_ref{clGetCommandQueueInfo}
246 template<class T>
247 T get_info(cl_command_queue_info info) const
248 {
249 return detail::get_object_info<T>(clGetCommandQueueInfo, m_queue, info);
250 }
251
252 /// \overload
253 template<int Enum>
254 typename detail::get_object_info_type<command_queue, Enum>::type
255 get_info() const;
256
257 /// Returns the properties for the command queue.
258 cl_command_queue_properties get_properties() const
259 {
260 return get_info<cl_command_queue_properties>(CL_QUEUE_PROPERTIES);
261 }
262
263 #if defined(BOOST_COMPUTE_CL_VERSION_2_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
264 /// Returns the current default device command queue for the underlying device.
265 ///
266 /// \opencl_version_warning{2,1}
267 command_queue get_default_device_queue() const
268 {
269 return command_queue(get_info<cl_command_queue>(CL_QUEUE_DEVICE_DEFAULT));
270 }
271
272 /// Replaces the default device command queue for the underlying device
273 /// with this command queue. Command queue must have been created
274 /// with CL_QUEUE_ON_DEVICE flag.
275 ///
276 /// \see_opencl21_ref{clSetDefaultDeviceCommandQueue}
277 ///
278 /// \opencl_version_warning{2,1}
279 void set_as_default_device_queue() const
280 {
281 cl_int ret = clSetDefaultDeviceCommandQueue(
282 this->get_context().get(),
283 this->get_device().get(),
284 m_queue
285 );
286 if(ret != CL_SUCCESS){
287 BOOST_THROW_EXCEPTION(opencl_error(ret));
288 }
289 }
290 #endif // BOOST_COMPUTE_CL_VERSION_2_1
291
292 /// Enqueues a command to read data from \p buffer to host memory.
293 ///
294 /// \see_opencl_ref{clEnqueueReadBuffer}
295 ///
296 /// \see copy()
297 event enqueue_read_buffer(const buffer &buffer,
298 size_t offset,
299 size_t size,
300 void *host_ptr,
301 const wait_list &events = wait_list())
302 {
303 BOOST_ASSERT(m_queue != 0);
304 BOOST_ASSERT(size <= buffer.size());
305 BOOST_ASSERT(buffer.get_context() == this->get_context());
306 BOOST_ASSERT(host_ptr != 0);
307
308 event event_;
309
310 cl_int ret = clEnqueueReadBuffer(
311 m_queue,
312 buffer.get(),
313 CL_TRUE,
314 offset,
315 size,
316 host_ptr,
317 events.size(),
318 events.get_event_ptr(),
319 &event_.get()
320 );
321
322 if(ret != CL_SUCCESS){
323 BOOST_THROW_EXCEPTION(opencl_error(ret));
324 }
325
326 return event_;
327 }
328
329 /// Enqueues a command to read data from \p buffer to host memory. The
330 /// copy will be performed asynchronously.
331 ///
332 /// \see_opencl_ref{clEnqueueReadBuffer}
333 ///
334 /// \see copy_async()
335 event enqueue_read_buffer_async(const buffer &buffer,
336 size_t offset,
337 size_t size,
338 void *host_ptr,
339 const wait_list &events = wait_list())
340 {
341 BOOST_ASSERT(m_queue != 0);
342 BOOST_ASSERT(size <= buffer.size());
343 BOOST_ASSERT(buffer.get_context() == this->get_context());
344 BOOST_ASSERT(host_ptr != 0);
345
346 event event_;
347
348 cl_int ret = clEnqueueReadBuffer(
349 m_queue,
350 buffer.get(),
351 CL_FALSE,
352 offset,
353 size,
354 host_ptr,
355 events.size(),
356 events.get_event_ptr(),
357 &event_.get()
358 );
359
360 if(ret != CL_SUCCESS){
361 BOOST_THROW_EXCEPTION(opencl_error(ret));
362 }
363
364 return event_;
365 }
366
367 #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
368 /// Enqueues a command to read a rectangular region from \p buffer to
369 /// host memory.
370 ///
371 /// \see_opencl_ref{clEnqueueReadBufferRect}
372 ///
373 /// \opencl_version_warning{1,1}
374 event enqueue_read_buffer_rect(const buffer &buffer,
375 const size_t buffer_origin[3],
376 const size_t host_origin[3],
377 const size_t region[3],
378 size_t buffer_row_pitch,
379 size_t buffer_slice_pitch,
380 size_t host_row_pitch,
381 size_t host_slice_pitch,
382 void *host_ptr,
383 const wait_list &events = wait_list())
384 {
385 BOOST_ASSERT(m_queue != 0);
386 BOOST_ASSERT(buffer.get_context() == this->get_context());
387 BOOST_ASSERT(host_ptr != 0);
388
389 event event_;
390
391 cl_int ret = clEnqueueReadBufferRect(
392 m_queue,
393 buffer.get(),
394 CL_TRUE,
395 buffer_origin,
396 host_origin,
397 region,
398 buffer_row_pitch,
399 buffer_slice_pitch,
400 host_row_pitch,
401 host_slice_pitch,
402 host_ptr,
403 events.size(),
404 events.get_event_ptr(),
405 &event_.get()
406 );
407
408 if(ret != CL_SUCCESS){
409 BOOST_THROW_EXCEPTION(opencl_error(ret));
410 }
411
412 return event_;
413 }
414
415 /// Enqueues a command to read a rectangular region from \p buffer to
416 /// host memory. The copy will be performed asynchronously.
417 ///
418 /// \see_opencl_ref{clEnqueueReadBufferRect}
419 ///
420 /// \opencl_version_warning{1,1}
421 event enqueue_read_buffer_rect_async(const buffer &buffer,
422 const size_t buffer_origin[3],
423 const size_t host_origin[3],
424 const size_t region[3],
425 size_t buffer_row_pitch,
426 size_t buffer_slice_pitch,
427 size_t host_row_pitch,
428 size_t host_slice_pitch,
429 void *host_ptr,
430 const wait_list &events = wait_list())
431 {
432 BOOST_ASSERT(m_queue != 0);
433 BOOST_ASSERT(buffer.get_context() == this->get_context());
434 BOOST_ASSERT(host_ptr != 0);
435
436 event event_;
437
438 cl_int ret = clEnqueueReadBufferRect(
439 m_queue,
440 buffer.get(),
441 CL_FALSE,
442 buffer_origin,
443 host_origin,
444 region,
445 buffer_row_pitch,
446 buffer_slice_pitch,
447 host_row_pitch,
448 host_slice_pitch,
449 host_ptr,
450 events.size(),
451 events.get_event_ptr(),
452 &event_.get()
453 );
454
455 if(ret != CL_SUCCESS){
456 BOOST_THROW_EXCEPTION(opencl_error(ret));
457 }
458
459 return event_;
460 }
461 #endif // BOOST_COMPUTE_CL_VERSION_1_1
462
463 /// Enqueues a command to write data from host memory to \p buffer.
464 ///
465 /// \see_opencl_ref{clEnqueueWriteBuffer}
466 ///
467 /// \see copy()
468 event enqueue_write_buffer(const buffer &buffer,
469 size_t offset,
470 size_t size,
471 const void *host_ptr,
472 const wait_list &events = wait_list())
473 {
474 BOOST_ASSERT(m_queue != 0);
475 BOOST_ASSERT(size <= buffer.size());
476 BOOST_ASSERT(buffer.get_context() == this->get_context());
477 BOOST_ASSERT(host_ptr != 0);
478
479 event event_;
480
481 cl_int ret = clEnqueueWriteBuffer(
482 m_queue,
483 buffer.get(),
484 CL_TRUE,
485 offset,
486 size,
487 host_ptr,
488 events.size(),
489 events.get_event_ptr(),
490 &event_.get()
491 );
492
493 if(ret != CL_SUCCESS){
494 BOOST_THROW_EXCEPTION(opencl_error(ret));
495 }
496
497 return event_;
498 }
499
500 /// Enqueues a command to write data from host memory to \p buffer.
501 /// The copy is performed asynchronously.
502 ///
503 /// \see_opencl_ref{clEnqueueWriteBuffer}
504 ///
505 /// \see copy_async()
506 event enqueue_write_buffer_async(const buffer &buffer,
507 size_t offset,
508 size_t size,
509 const void *host_ptr,
510 const wait_list &events = wait_list())
511 {
512 BOOST_ASSERT(m_queue != 0);
513 BOOST_ASSERT(size <= buffer.size());
514 BOOST_ASSERT(buffer.get_context() == this->get_context());
515 BOOST_ASSERT(host_ptr != 0);
516
517 event event_;
518
519 cl_int ret = clEnqueueWriteBuffer(
520 m_queue,
521 buffer.get(),
522 CL_FALSE,
523 offset,
524 size,
525 host_ptr,
526 events.size(),
527 events.get_event_ptr(),
528 &event_.get()
529 );
530
531 if(ret != CL_SUCCESS){
532 BOOST_THROW_EXCEPTION(opencl_error(ret));
533 }
534
535 return event_;
536 }
537
538 #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
539 /// Enqueues a command to write a rectangular region from host memory
540 /// to \p buffer.
541 ///
542 /// \see_opencl_ref{clEnqueueWriteBufferRect}
543 ///
544 /// \opencl_version_warning{1,1}
545 event enqueue_write_buffer_rect(const buffer &buffer,
546 const size_t buffer_origin[3],
547 const size_t host_origin[3],
548 const size_t region[3],
549 size_t buffer_row_pitch,
550 size_t buffer_slice_pitch,
551 size_t host_row_pitch,
552 size_t host_slice_pitch,
553 void *host_ptr,
554 const wait_list &events = wait_list())
555 {
556 BOOST_ASSERT(m_queue != 0);
557 BOOST_ASSERT(buffer.get_context() == this->get_context());
558 BOOST_ASSERT(host_ptr != 0);
559
560 event event_;
561
562 cl_int ret = clEnqueueWriteBufferRect(
563 m_queue,
564 buffer.get(),
565 CL_TRUE,
566 buffer_origin,
567 host_origin,
568 region,
569 buffer_row_pitch,
570 buffer_slice_pitch,
571 host_row_pitch,
572 host_slice_pitch,
573 host_ptr,
574 events.size(),
575 events.get_event_ptr(),
576 &event_.get()
577 );
578
579 if(ret != CL_SUCCESS){
580 BOOST_THROW_EXCEPTION(opencl_error(ret));
581 }
582
583 return event_;
584 }
585
586 /// Enqueues a command to write a rectangular region from host memory
587 /// to \p buffer. The copy is performed asynchronously.
588 ///
589 /// \see_opencl_ref{clEnqueueWriteBufferRect}
590 ///
591 /// \opencl_version_warning{1,1}
592 event enqueue_write_buffer_rect_async(const buffer &buffer,
593 const size_t buffer_origin[3],
594 const size_t host_origin[3],
595 const size_t region[3],
596 size_t buffer_row_pitch,
597 size_t buffer_slice_pitch,
598 size_t host_row_pitch,
599 size_t host_slice_pitch,
600 void *host_ptr,
601 const wait_list &events = wait_list())
602 {
603 BOOST_ASSERT(m_queue != 0);
604 BOOST_ASSERT(buffer.get_context() == this->get_context());
605 BOOST_ASSERT(host_ptr != 0);
606
607 event event_;
608
609 cl_int ret = clEnqueueWriteBufferRect(
610 m_queue,
611 buffer.get(),
612 CL_FALSE,
613 buffer_origin,
614 host_origin,
615 region,
616 buffer_row_pitch,
617 buffer_slice_pitch,
618 host_row_pitch,
619 host_slice_pitch,
620 host_ptr,
621 events.size(),
622 events.get_event_ptr(),
623 &event_.get()
624 );
625
626 if(ret != CL_SUCCESS){
627 BOOST_THROW_EXCEPTION(opencl_error(ret));
628 }
629
630 return event_;
631 }
632 #endif // BOOST_COMPUTE_CL_VERSION_1_1
633
634 /// Enqueues a command to copy data from \p src_buffer to
635 /// \p dst_buffer.
636 ///
637 /// \see_opencl_ref{clEnqueueCopyBuffer}
638 ///
639 /// \see copy()
640 event enqueue_copy_buffer(const buffer &src_buffer,
641 const buffer &dst_buffer,
642 size_t src_offset,
643 size_t dst_offset,
644 size_t size,
645 const wait_list &events = wait_list())
646 {
647 BOOST_ASSERT(m_queue != 0);
648 BOOST_ASSERT(src_offset + size <= src_buffer.size());
649 BOOST_ASSERT(dst_offset + size <= dst_buffer.size());
650 BOOST_ASSERT(src_buffer.get_context() == this->get_context());
651 BOOST_ASSERT(dst_buffer.get_context() == this->get_context());
652
653 event event_;
654
655 cl_int ret = clEnqueueCopyBuffer(
656 m_queue,
657 src_buffer.get(),
658 dst_buffer.get(),
659 src_offset,
660 dst_offset,
661 size,
662 events.size(),
663 events.get_event_ptr(),
664 &event_.get()
665 );
666
667 if(ret != CL_SUCCESS){
668 BOOST_THROW_EXCEPTION(opencl_error(ret));
669 }
670
671 return event_;
672 }
673
674 #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
675 /// Enqueues a command to copy a rectangular region from
676 /// \p src_buffer to \p dst_buffer.
677 ///
678 /// \see_opencl_ref{clEnqueueCopyBufferRect}
679 ///
680 /// \opencl_version_warning{1,1}
681 event enqueue_copy_buffer_rect(const buffer &src_buffer,
682 const buffer &dst_buffer,
683 const size_t src_origin[3],
684 const size_t dst_origin[3],
685 const size_t region[3],
686 size_t buffer_row_pitch,
687 size_t buffer_slice_pitch,
688 size_t host_row_pitch,
689 size_t host_slice_pitch,
690 const wait_list &events = wait_list())
691 {
692 BOOST_ASSERT(m_queue != 0);
693 BOOST_ASSERT(src_buffer.get_context() == this->get_context());
694 BOOST_ASSERT(dst_buffer.get_context() == this->get_context());
695
696 event event_;
697
698 cl_int ret = clEnqueueCopyBufferRect(
699 m_queue,
700 src_buffer.get(),
701 dst_buffer.get(),
702 src_origin,
703 dst_origin,
704 region,
705 buffer_row_pitch,
706 buffer_slice_pitch,
707 host_row_pitch,
708 host_slice_pitch,
709 events.size(),
710 events.get_event_ptr(),
711 &event_.get()
712 );
713
714 if(ret != CL_SUCCESS){
715 BOOST_THROW_EXCEPTION(opencl_error(ret));
716 }
717
718 return event_;
719 }
720 #endif // BOOST_COMPUTE_CL_VERSION_1_1
721
722 #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
723 /// Enqueues a command to fill \p buffer with \p pattern.
724 ///
725 /// \see_opencl_ref{clEnqueueFillBuffer}
726 ///
727 /// \opencl_version_warning{1,2}
728 ///
729 /// \see fill()
730 event enqueue_fill_buffer(const buffer &buffer,
731 const void *pattern,
732 size_t pattern_size,
733 size_t offset,
734 size_t size,
735 const wait_list &events = wait_list())
736 {
737 BOOST_ASSERT(m_queue != 0);
738 BOOST_ASSERT(offset + size <= buffer.size());
739 BOOST_ASSERT(buffer.get_context() == this->get_context());
740
741 event event_;
742
743 cl_int ret = clEnqueueFillBuffer(
744 m_queue,
745 buffer.get(),
746 pattern,
747 pattern_size,
748 offset,
749 size,
750 events.size(),
751 events.get_event_ptr(),
752 &event_.get()
753 );
754
755 if(ret != CL_SUCCESS){
756 BOOST_THROW_EXCEPTION(opencl_error(ret));
757 }
758
759 return event_;
760 }
761 #endif // BOOST_COMPUTE_CL_VERSION_1_2
762
763 /// Enqueues a command to map \p buffer into the host address space.
764 /// Event associated with map operation is returned through
765 /// \p map_buffer_event parameter.
766 ///
767 /// \see_opencl_ref{clEnqueueMapBuffer}
768 void* enqueue_map_buffer(const buffer &buffer,
769 cl_map_flags flags,
770 size_t offset,
771 size_t size,
772 event &map_buffer_event,
773 const wait_list &events = wait_list())
774 {
775 BOOST_ASSERT(m_queue != 0);
776 BOOST_ASSERT(offset + size <= buffer.size());
777 BOOST_ASSERT(buffer.get_context() == this->get_context());
778
779 cl_int ret = 0;
780 void *pointer = clEnqueueMapBuffer(
781 m_queue,
782 buffer.get(),
783 CL_TRUE,
784 flags,
785 offset,
786 size,
787 events.size(),
788 events.get_event_ptr(),
789 &map_buffer_event.get(),
790 &ret
791 );
792
793 if(ret != CL_SUCCESS){
794 BOOST_THROW_EXCEPTION(opencl_error(ret));
795 }
796
797 return pointer;
798 }
799
800 /// \overload
801 void* enqueue_map_buffer(const buffer &buffer,
802 cl_map_flags flags,
803 size_t offset,
804 size_t size,
805 const wait_list &events = wait_list())
806 {
807 event event_;
808 return enqueue_map_buffer(buffer, flags, offset, size, event_, events);
809 }
810
811 /// Enqueues a command to map \p buffer into the host address space.
812 /// Map operation is performed asynchronously. The pointer to the mapped
813 /// region cannot be used until the map operation has completed.
814 ///
815 /// Event associated with map operation is returned through
816 /// \p map_buffer_event parameter.
817 ///
818 /// \see_opencl_ref{clEnqueueMapBuffer}
819 void* enqueue_map_buffer_async(const buffer &buffer,
820 cl_map_flags flags,
821 size_t offset,
822 size_t size,
823 event &map_buffer_event,
824 const wait_list &events = wait_list())
825 {
826 BOOST_ASSERT(m_queue != 0);
827 BOOST_ASSERT(offset + size <= buffer.size());
828 BOOST_ASSERT(buffer.get_context() == this->get_context());
829
830 cl_int ret = 0;
831 void *pointer = clEnqueueMapBuffer(
832 m_queue,
833 buffer.get(),
834 CL_FALSE,
835 flags,
836 offset,
837 size,
838 events.size(),
839 events.get_event_ptr(),
840 &map_buffer_event.get(),
841 &ret
842 );
843
844 if(ret != CL_SUCCESS){
845 BOOST_THROW_EXCEPTION(opencl_error(ret));
846 }
847
848 return pointer;
849 }
850
851 /// Enqueues a command to unmap \p buffer from the host memory space.
852 ///
853 /// \see_opencl_ref{clEnqueueUnmapMemObject}
854 event enqueue_unmap_buffer(const buffer &buffer,
855 void *mapped_ptr,
856 const wait_list &events = wait_list())
857 {
858 BOOST_ASSERT(buffer.get_context() == this->get_context());
859
860 return enqueue_unmap_mem_object(buffer.get(), mapped_ptr, events);
861 }
862
863 /// Enqueues a command to unmap \p mem from the host memory space.
864 ///
865 /// \see_opencl_ref{clEnqueueUnmapMemObject}
866 event enqueue_unmap_mem_object(cl_mem mem,
867 void *mapped_ptr,
868 const wait_list &events = wait_list())
869 {
870 BOOST_ASSERT(m_queue != 0);
871
872 event event_;
873
874 cl_int ret = clEnqueueUnmapMemObject(
875 m_queue,
876 mem,
877 mapped_ptr,
878 events.size(),
879 events.get_event_ptr(),
880 &event_.get()
881 );
882
883 if(ret != CL_SUCCESS){
884 BOOST_THROW_EXCEPTION(opencl_error(ret));
885 }
886
887 return event_;
888 }
889
890 /// Enqueues a command to read data from \p image to host memory.
891 ///
892 /// \see_opencl_ref{clEnqueueReadImage}
893 event enqueue_read_image(const image_object& image,
894 const size_t *origin,
895 const size_t *region,
896 size_t row_pitch,
897 size_t slice_pitch,
898 void *host_ptr,
899 const wait_list &events = wait_list())
900 {
901 BOOST_ASSERT(m_queue != 0);
902
903 event event_;
904
905 cl_int ret = clEnqueueReadImage(
906 m_queue,
907 image.get(),
908 CL_TRUE,
909 origin,
910 region,
911 row_pitch,
912 slice_pitch,
913 host_ptr,
914 events.size(),
915 events.get_event_ptr(),
916 &event_.get()
917 );
918
919 if(ret != CL_SUCCESS){
920 BOOST_THROW_EXCEPTION(opencl_error(ret));
921 }
922
923 return event_;
924 }
925
926 /// \overload
927 template<size_t N>
928 event enqueue_read_image(const image_object& image,
929 const extents<N> origin,
930 const extents<N> region,
931 void *host_ptr,
932 size_t row_pitch = 0,
933 size_t slice_pitch = 0,
934 const wait_list &events = wait_list())
935 {
936 BOOST_ASSERT(image.get_context() == this->get_context());
937
938 size_t origin3[3] = { 0, 0, 0 };
939 size_t region3[3] = { 1, 1, 1 };
940
941 std::copy(origin.data(), origin.data() + N, origin3);
942 std::copy(region.data(), region.data() + N, region3);
943
944 return enqueue_read_image(
945 image, origin3, region3, row_pitch, slice_pitch, host_ptr, events
946 );
947 }
948
949 /// Enqueues a command to write data from host memory to \p image.
950 ///
951 /// \see_opencl_ref{clEnqueueWriteImage}
952 event enqueue_write_image(image_object& image,
953 const size_t *origin,
954 const size_t *region,
955 const void *host_ptr,
956 size_t input_row_pitch = 0,
957 size_t input_slice_pitch = 0,
958 const wait_list &events = wait_list())
959 {
960 BOOST_ASSERT(m_queue != 0);
961
962 event event_;
963
964 cl_int ret = clEnqueueWriteImage(
965 m_queue,
966 image.get(),
967 CL_TRUE,
968 origin,
969 region,
970 input_row_pitch,
971 input_slice_pitch,
972 host_ptr,
973 events.size(),
974 events.get_event_ptr(),
975 &event_.get()
976 );
977
978 if(ret != CL_SUCCESS){
979 BOOST_THROW_EXCEPTION(opencl_error(ret));
980 }
981
982 return event_;
983 }
984
985 /// \overload
986 template<size_t N>
987 event enqueue_write_image(image_object& image,
988 const extents<N> origin,
989 const extents<N> region,
990 const void *host_ptr,
991 const size_t input_row_pitch = 0,
992 const size_t input_slice_pitch = 0,
993 const wait_list &events = wait_list())
994 {
995 BOOST_ASSERT(image.get_context() == this->get_context());
996
997 size_t origin3[3] = { 0, 0, 0 };
998 size_t region3[3] = { 1, 1, 1 };
999
1000 std::copy(origin.data(), origin.data() + N, origin3);
1001 std::copy(region.data(), region.data() + N, region3);
1002
1003 return enqueue_write_image(
1004 image, origin3, region3, host_ptr, input_row_pitch, input_slice_pitch, events
1005 );
1006 }
1007
1008 /// Enqueues a command to map \p image into the host address space.
1009 ///
1010 /// Event associated with map operation is returned through
1011 /// \p map_image_event parameter.
1012 ///
1013 /// \see_opencl_ref{clEnqueueMapImage}
1014 void* enqueue_map_image(const image_object &image,
1015 cl_map_flags flags,
1016 const size_t *origin,
1017 const size_t *region,
1018 size_t &output_row_pitch,
1019 size_t &output_slice_pitch,
1020 event &map_image_event,
1021 const wait_list &events = wait_list())
1022 {
1023 BOOST_ASSERT(m_queue != 0);
1024 BOOST_ASSERT(image.get_context() == this->get_context());
1025
1026 cl_int ret = 0;
1027 void *pointer = clEnqueueMapImage(
1028 m_queue,
1029 image.get(),
1030 CL_TRUE,
1031 flags,
1032 origin,
1033 region,
1034 &output_row_pitch,
1035 &output_slice_pitch,
1036 events.size(),
1037 events.get_event_ptr(),
1038 &map_image_event.get(),
1039 &ret
1040 );
1041
1042 if(ret != CL_SUCCESS){
1043 BOOST_THROW_EXCEPTION(opencl_error(ret));
1044 }
1045
1046 return pointer;
1047 }
1048
1049 /// \overload
1050 void* enqueue_map_image(const image_object &image,
1051 cl_map_flags flags,
1052 const size_t *origin,
1053 const size_t *region,
1054 size_t &output_row_pitch,
1055 size_t &output_slice_pitch,
1056 const wait_list &events = wait_list())
1057 {
1058 event event_;
1059 return enqueue_map_image(
1060 image, flags, origin, region,
1061 output_row_pitch, output_slice_pitch, event_, events
1062 );
1063 }
1064
1065 /// \overload
1066 template<size_t N>
1067 void* enqueue_map_image(image_object& image,
1068 cl_map_flags flags,
1069 const extents<N> origin,
1070 const extents<N> region,
1071 size_t &output_row_pitch,
1072 size_t &output_slice_pitch,
1073 event &map_image_event,
1074 const wait_list &events = wait_list())
1075 {
1076 BOOST_ASSERT(image.get_context() == this->get_context());
1077
1078 size_t origin3[3] = { 0, 0, 0 };
1079 size_t region3[3] = { 1, 1, 1 };
1080
1081 std::copy(origin.data(), origin.data() + N, origin3);
1082 std::copy(region.data(), region.data() + N, region3);
1083
1084 return enqueue_map_image(
1085 image, flags, origin3, region3,
1086 output_row_pitch, output_slice_pitch, map_image_event, events
1087 );
1088 }
1089
1090 /// \overload
1091 template<size_t N>
1092 void* enqueue_map_image(image_object& image,
1093 cl_map_flags flags,
1094 const extents<N> origin,
1095 const extents<N> region,
1096 size_t &output_row_pitch,
1097 size_t &output_slice_pitch,
1098 const wait_list &events = wait_list())
1099 {
1100 event event_;
1101 return enqueue_map_image(
1102 image, flags, origin, region,
1103 output_row_pitch, output_slice_pitch, event_, events
1104 );
1105 }
1106
1107 /// Enqueues a command to map \p image into the host address space.
1108 /// Map operation is performed asynchronously. The pointer to the mapped
1109 /// region cannot be used until the map operation has completed.
1110 ///
1111 /// Event associated with map operation is returned through
1112 /// \p map_image_event parameter.
1113 ///
1114 /// \see_opencl_ref{clEnqueueMapImage}
1115 void* enqueue_map_image_async(const image_object &image,
1116 cl_map_flags flags,
1117 const size_t *origin,
1118 const size_t *region,
1119 size_t &output_row_pitch,
1120 size_t &output_slice_pitch,
1121 event &map_image_event,
1122 const wait_list &events = wait_list())
1123 {
1124 BOOST_ASSERT(m_queue != 0);
1125 BOOST_ASSERT(image.get_context() == this->get_context());
1126
1127 cl_int ret = 0;
1128 void *pointer = clEnqueueMapImage(
1129 m_queue,
1130 image.get(),
1131 CL_FALSE,
1132 flags,
1133 origin,
1134 region,
1135 &output_row_pitch,
1136 &output_slice_pitch,
1137 events.size(),
1138 events.get_event_ptr(),
1139 &map_image_event.get(),
1140 &ret
1141 );
1142
1143 if(ret != CL_SUCCESS){
1144 BOOST_THROW_EXCEPTION(opencl_error(ret));
1145 }
1146
1147 return pointer;
1148 }
1149
1150 /// \overload
1151 template<size_t N>
1152 void* enqueue_map_image_async(image_object& image,
1153 cl_map_flags flags,
1154 const extents<N> origin,
1155 const extents<N> region,
1156 size_t &output_row_pitch,
1157 size_t &output_slice_pitch,
1158 event &map_image_event,
1159 const wait_list &events = wait_list())
1160 {
1161 BOOST_ASSERT(image.get_context() == this->get_context());
1162
1163 size_t origin3[3] = { 0, 0, 0 };
1164 size_t region3[3] = { 1, 1, 1 };
1165
1166 std::copy(origin.data(), origin.data() + N, origin3);
1167 std::copy(region.data(), region.data() + N, region3);
1168
1169 return enqueue_map_image_async(
1170 image, flags, origin3, region3,
1171 output_row_pitch, output_slice_pitch, map_image_event, events
1172 );
1173 }
1174
1175 /// Enqueues a command to unmap \p image from the host memory space.
1176 ///
1177 /// \see_opencl_ref{clEnqueueUnmapMemObject}
1178 event enqueue_unmap_image(const image_object &image,
1179 void *mapped_ptr,
1180 const wait_list &events = wait_list())
1181 {
1182 BOOST_ASSERT(image.get_context() == this->get_context());
1183
1184 return enqueue_unmap_mem_object(image.get(), mapped_ptr, events);
1185 }
1186
1187 /// Enqueues a command to copy data from \p src_image to \p dst_image.
1188 ///
1189 /// \see_opencl_ref{clEnqueueCopyImage}
1190 event enqueue_copy_image(const image_object& src_image,
1191 image_object& dst_image,
1192 const size_t *src_origin,
1193 const size_t *dst_origin,
1194 const size_t *region,
1195 const wait_list &events = wait_list())
1196 {
1197 BOOST_ASSERT(m_queue != 0);
1198
1199 event event_;
1200
1201 cl_int ret = clEnqueueCopyImage(
1202 m_queue,
1203 src_image.get(),
1204 dst_image.get(),
1205 src_origin,
1206 dst_origin,
1207 region,
1208 events.size(),
1209 events.get_event_ptr(),
1210 &event_.get()
1211 );
1212
1213 if(ret != CL_SUCCESS){
1214 BOOST_THROW_EXCEPTION(opencl_error(ret));
1215 }
1216
1217 return event_;
1218 }
1219
1220 /// \overload
1221 template<size_t N>
1222 event enqueue_copy_image(const image_object& src_image,
1223 image_object& dst_image,
1224 const extents<N> src_origin,
1225 const extents<N> dst_origin,
1226 const extents<N> region,
1227 const wait_list &events = wait_list())
1228 {
1229 BOOST_ASSERT(src_image.get_context() == this->get_context());
1230 BOOST_ASSERT(dst_image.get_context() == this->get_context());
1231 BOOST_ASSERT_MSG(src_image.format() == dst_image.format(),
1232 "Source and destination image formats must match.");
1233
1234 size_t src_origin3[3] = { 0, 0, 0 };
1235 size_t dst_origin3[3] = { 0, 0, 0 };
1236 size_t region3[3] = { 1, 1, 1 };
1237
1238 std::copy(src_origin.data(), src_origin.data() + N, src_origin3);
1239 std::copy(dst_origin.data(), dst_origin.data() + N, dst_origin3);
1240 std::copy(region.data(), region.data() + N, region3);
1241
1242 return enqueue_copy_image(
1243 src_image, dst_image, src_origin3, dst_origin3, region3, events
1244 );
1245 }
1246
1247 /// Enqueues a command to copy data from \p src_image to \p dst_buffer.
1248 ///
1249 /// \see_opencl_ref{clEnqueueCopyImageToBuffer}
1250 event enqueue_copy_image_to_buffer(const image_object& src_image,
1251 memory_object& dst_buffer,
1252 const size_t *src_origin,
1253 const size_t *region,
1254 size_t dst_offset,
1255 const wait_list &events = wait_list())
1256 {
1257 BOOST_ASSERT(m_queue != 0);
1258
1259 event event_;
1260
1261 cl_int ret = clEnqueueCopyImageToBuffer(
1262 m_queue,
1263 src_image.get(),
1264 dst_buffer.get(),
1265 src_origin,
1266 region,
1267 dst_offset,
1268 events.size(),
1269 events.get_event_ptr(),
1270 &event_.get()
1271 );
1272
1273 if(ret != CL_SUCCESS){
1274 BOOST_THROW_EXCEPTION(opencl_error(ret));
1275 }
1276
1277 return event_;
1278 }
1279
1280 /// Enqueues a command to copy data from \p src_buffer to \p dst_image.
1281 ///
1282 /// \see_opencl_ref{clEnqueueCopyBufferToImage}
1283 event enqueue_copy_buffer_to_image(const memory_object& src_buffer,
1284 image_object& dst_image,
1285 size_t src_offset,
1286 const size_t *dst_origin,
1287 const size_t *region,
1288 const wait_list &events = wait_list())
1289 {
1290 BOOST_ASSERT(m_queue != 0);
1291
1292 event event_;
1293
1294 cl_int ret = clEnqueueCopyBufferToImage(
1295 m_queue,
1296 src_buffer.get(),
1297 dst_image.get(),
1298 src_offset,
1299 dst_origin,
1300 region,
1301 events.size(),
1302 events.get_event_ptr(),
1303 &event_.get()
1304 );
1305
1306 if(ret != CL_SUCCESS){
1307 BOOST_THROW_EXCEPTION(opencl_error(ret));
1308 }
1309
1310 return event_;
1311 }
1312
1313 #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
1314 /// Enqueues a command to fill \p image with \p fill_color.
1315 ///
1316 /// \see_opencl_ref{clEnqueueFillImage}
1317 ///
1318 /// \opencl_version_warning{1,2}
1319 event enqueue_fill_image(image_object& image,
1320 const void *fill_color,
1321 const size_t *origin,
1322 const size_t *region,
1323 const wait_list &events = wait_list())
1324 {
1325 BOOST_ASSERT(m_queue != 0);
1326
1327 event event_;
1328
1329 cl_int ret = clEnqueueFillImage(
1330 m_queue,
1331 image.get(),
1332 fill_color,
1333 origin,
1334 region,
1335 events.size(),
1336 events.get_event_ptr(),
1337 &event_.get()
1338 );
1339
1340 if(ret != CL_SUCCESS){
1341 BOOST_THROW_EXCEPTION(opencl_error(ret));
1342 }
1343
1344 return event_;
1345 }
1346
1347 /// \overload
1348 template<size_t N>
1349 event enqueue_fill_image(image_object& image,
1350 const void *fill_color,
1351 const extents<N> origin,
1352 const extents<N> region,
1353 const wait_list &events = wait_list())
1354 {
1355 BOOST_ASSERT(image.get_context() == this->get_context());
1356
1357 size_t origin3[3] = { 0, 0, 0 };
1358 size_t region3[3] = { 1, 1, 1 };
1359
1360 std::copy(origin.data(), origin.data() + N, origin3);
1361 std::copy(region.data(), region.data() + N, region3);
1362
1363 return enqueue_fill_image(
1364 image, fill_color, origin3, region3, events
1365 );
1366 }
1367
1368 /// Enqueues a command to migrate \p mem_objects.
1369 ///
1370 /// \see_opencl_ref{clEnqueueMigrateMemObjects}
1371 ///
1372 /// \opencl_version_warning{1,2}
1373 event enqueue_migrate_memory_objects(uint_ num_mem_objects,
1374 const cl_mem *mem_objects,
1375 cl_mem_migration_flags flags,
1376 const wait_list &events = wait_list())
1377 {
1378 BOOST_ASSERT(m_queue != 0);
1379
1380 event event_;
1381
1382 cl_int ret = clEnqueueMigrateMemObjects(
1383 m_queue,
1384 num_mem_objects,
1385 mem_objects,
1386 flags,
1387 events.size(),
1388 events.get_event_ptr(),
1389 &event_.get()
1390 );
1391
1392 if(ret != CL_SUCCESS){
1393 BOOST_THROW_EXCEPTION(opencl_error(ret));
1394 }
1395
1396 return event_;
1397 }
1398 #endif // BOOST_COMPUTE_CL_VERSION_1_2
1399
1400 /// Enqueues a kernel for execution.
1401 ///
1402 /// \see_opencl_ref{clEnqueueNDRangeKernel}
1403 event enqueue_nd_range_kernel(const kernel &kernel,
1404 size_t work_dim,
1405 const size_t *global_work_offset,
1406 const size_t *global_work_size,
1407 const size_t *local_work_size,
1408 const wait_list &events = wait_list())
1409 {
1410 BOOST_ASSERT(m_queue != 0);
1411 BOOST_ASSERT(kernel.get_context() == this->get_context());
1412
1413 event event_;
1414
1415 cl_int ret = clEnqueueNDRangeKernel(
1416 m_queue,
1417 kernel,
1418 static_cast<cl_uint>(work_dim),
1419 global_work_offset,
1420 global_work_size,
1421 local_work_size,
1422 events.size(),
1423 events.get_event_ptr(),
1424 &event_.get()
1425 );
1426
1427 if(ret != CL_SUCCESS){
1428 BOOST_THROW_EXCEPTION(opencl_error(ret));
1429 }
1430
1431 return event_;
1432 }
1433
1434 /// \overload
1435 template<size_t N>
1436 event enqueue_nd_range_kernel(const kernel &kernel,
1437 const extents<N> &global_work_offset,
1438 const extents<N> &global_work_size,
1439 const extents<N> &local_work_size,
1440 const wait_list &events = wait_list())
1441 {
1442 return enqueue_nd_range_kernel(
1443 kernel,
1444 N,
1445 global_work_offset.data(),
1446 global_work_size.data(),
1447 local_work_size.data(),
1448 events
1449 );
1450 }
1451
1452 /// Convenience method which calls enqueue_nd_range_kernel() with a
1453 /// one-dimensional range.
1454 event enqueue_1d_range_kernel(const kernel &kernel,
1455 size_t global_work_offset,
1456 size_t global_work_size,
1457 size_t local_work_size,
1458 const wait_list &events = wait_list())
1459 {
1460 return enqueue_nd_range_kernel(
1461 kernel,
1462 1,
1463 &global_work_offset,
1464 &global_work_size,
1465 local_work_size ? &local_work_size : 0,
1466 events
1467 );
1468 }
1469
1470 /// Enqueues a kernel to execute using a single work-item.
1471 ///
1472 /// \see_opencl_ref{clEnqueueTask}
1473 event enqueue_task(const kernel &kernel, const wait_list &events = wait_list())
1474 {
1475 BOOST_ASSERT(m_queue != 0);
1476 BOOST_ASSERT(kernel.get_context() == this->get_context());
1477
1478 event event_;
1479
1480 // clEnqueueTask() was deprecated in OpenCL 2.0. In that case we
1481 // just forward to the equivalent clEnqueueNDRangeKernel() call.
1482 #ifdef BOOST_COMPUTE_CL_VERSION_2_0
1483 size_t one = 1;
1484 cl_int ret = clEnqueueNDRangeKernel(
1485 m_queue, kernel, 1, 0, &one, &one,
1486 events.size(), events.get_event_ptr(), &event_.get()
1487 );
1488 #else
1489 cl_int ret = clEnqueueTask(
1490 m_queue, kernel, events.size(), events.get_event_ptr(), &event_.get()
1491 );
1492 #endif
1493
1494 if(ret != CL_SUCCESS){
1495 BOOST_THROW_EXCEPTION(opencl_error(ret));
1496 }
1497
1498 return event_;
1499 }
1500
1501 /// Enqueues a function to execute on the host.
1502 event enqueue_native_kernel(void (BOOST_COMPUTE_CL_CALLBACK *user_func)(void *),
1503 void *args,
1504 size_t cb_args,
1505 uint_ num_mem_objects,
1506 const cl_mem *mem_list,
1507 const void **args_mem_loc,
1508 const wait_list &events = wait_list())
1509 {
1510 BOOST_ASSERT(m_queue != 0);
1511
1512 event event_;
1513 cl_int ret = clEnqueueNativeKernel(
1514 m_queue,
1515 user_func,
1516 args,
1517 cb_args,
1518 num_mem_objects,
1519 mem_list,
1520 args_mem_loc,
1521 events.size(),
1522 events.get_event_ptr(),
1523 &event_.get()
1524 );
1525 if(ret != CL_SUCCESS){
1526 BOOST_THROW_EXCEPTION(opencl_error(ret));
1527 }
1528
1529 return event_;
1530 }
1531
1532 /// Convenience overload for enqueue_native_kernel() which enqueues a
1533 /// native kernel on the host with a nullary function.
1534 event enqueue_native_kernel(void (BOOST_COMPUTE_CL_CALLBACK *user_func)(void),
1535 const wait_list &events = wait_list())
1536 {
1537 return enqueue_native_kernel(
1538 detail::nullary_native_kernel_trampoline,
1539 reinterpret_cast<void *>(&user_func),
1540 sizeof(user_func),
1541 0,
1542 0,
1543 0,
1544 events
1545 );
1546 }
1547
1548 /// Flushes the command queue.
1549 ///
1550 /// \see_opencl_ref{clFlush}
1551 void flush()
1552 {
1553 BOOST_ASSERT(m_queue != 0);
1554
1555 cl_int ret = clFlush(m_queue);
1556 if(ret != CL_SUCCESS){
1557 BOOST_THROW_EXCEPTION(opencl_error(ret));
1558 }
1559 }
1560
1561 /// Blocks until all outstanding commands in the queue have finished.
1562 ///
1563 /// \see_opencl_ref{clFinish}
1564 void finish()
1565 {
1566 BOOST_ASSERT(m_queue != 0);
1567
1568 cl_int ret = clFinish(m_queue);
1569 if(ret != CL_SUCCESS){
1570 BOOST_THROW_EXCEPTION(opencl_error(ret));
1571 }
1572 }
1573
1574 /// Enqueues a barrier in the queue.
1575 void enqueue_barrier()
1576 {
1577 BOOST_ASSERT(m_queue != 0);
1578 cl_int ret = CL_SUCCESS;
1579
1580 #ifdef BOOST_COMPUTE_CL_VERSION_1_2
1581 if(get_device().check_version(1, 2)){
1582 ret = clEnqueueBarrierWithWaitList(m_queue, 0, 0, 0);
1583 } else
1584 #endif // BOOST_COMPUTE_CL_VERSION_1_2
1585 {
1586 // Suppress deprecated declarations warning
1587 BOOST_COMPUTE_DISABLE_DEPRECATED_DECLARATIONS();
1588 ret = clEnqueueBarrier(m_queue);
1589 BOOST_COMPUTE_ENABLE_DEPRECATED_DECLARATIONS();
1590 }
1591
1592 if(ret != CL_SUCCESS){
1593 BOOST_THROW_EXCEPTION(opencl_error(ret));
1594 }
1595 }
1596
1597 #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
1598 /// Enqueues a barrier in the queue after \p events.
1599 ///
1600 /// \opencl_version_warning{1,2}
1601 event enqueue_barrier(const wait_list &events)
1602 {
1603 BOOST_ASSERT(m_queue != 0);
1604
1605 event event_;
1606 cl_int ret = CL_SUCCESS;
1607
1608 ret = clEnqueueBarrierWithWaitList(
1609 m_queue, events.size(), events.get_event_ptr(), &event_.get()
1610 );
1611
1612 if(ret != CL_SUCCESS){
1613 BOOST_THROW_EXCEPTION(opencl_error(ret));
1614 }
1615
1616 return event_;
1617 }
1618 #endif // BOOST_COMPUTE_CL_VERSION_1_2
1619
1620 /// Enqueues a marker in the queue and returns an event that can be
1621 /// used to track its progress.
1622 event enqueue_marker()
1623 {
1624 event event_;
1625 cl_int ret = CL_SUCCESS;
1626
1627 #ifdef BOOST_COMPUTE_CL_VERSION_1_2
1628 if(get_device().check_version(1, 2)){
1629 ret = clEnqueueMarkerWithWaitList(m_queue, 0, 0, &event_.get());
1630 } else
1631 #endif
1632 {
1633 // Suppress deprecated declarations warning
1634 BOOST_COMPUTE_DISABLE_DEPRECATED_DECLARATIONS();
1635 ret = clEnqueueMarker(m_queue, &event_.get());
1636 BOOST_COMPUTE_ENABLE_DEPRECATED_DECLARATIONS();
1637 }
1638
1639 if(ret != CL_SUCCESS){
1640 BOOST_THROW_EXCEPTION(opencl_error(ret));
1641 }
1642
1643 return event_;
1644 }
1645
1646 #if defined(BOOST_COMPUTE_CL_VERSION_1_2) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
1647 /// Enqueues a marker after \p events in the queue and returns an
1648 /// event that can be used to track its progress.
1649 ///
1650 /// \opencl_version_warning{1,2}
1651 event enqueue_marker(const wait_list &events)
1652 {
1653 event event_;
1654
1655 cl_int ret = clEnqueueMarkerWithWaitList(
1656 m_queue, events.size(), events.get_event_ptr(), &event_.get()
1657 );
1658
1659 if(ret != CL_SUCCESS){
1660 BOOST_THROW_EXCEPTION(opencl_error(ret));
1661 }
1662
1663 return event_;
1664 }
1665 #endif // BOOST_COMPUTE_CL_VERSION_1_2
1666
1667 #if defined(BOOST_COMPUTE_CL_VERSION_2_0) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
1668 /// Enqueues a command to copy \p size bytes of data from \p src_ptr to
1669 /// \p dst_ptr.
1670 ///
1671 /// \opencl_version_warning{2,0}
1672 ///
1673 /// \see_opencl2_ref{clEnqueueSVMMemcpy}
1674 event enqueue_svm_memcpy(void *dst_ptr,
1675 const void *src_ptr,
1676 size_t size,
1677 const wait_list &events = wait_list())
1678 {
1679 event event_;
1680
1681 cl_int ret = clEnqueueSVMMemcpy(
1682 m_queue,
1683 CL_TRUE,
1684 dst_ptr,
1685 src_ptr,
1686 size,
1687 events.size(),
1688 events.get_event_ptr(),
1689 &event_.get()
1690 );
1691
1692 if(ret != CL_SUCCESS){
1693 BOOST_THROW_EXCEPTION(opencl_error(ret));
1694 }
1695
1696 return event_;
1697 }
1698
1699 /// Enqueues a command to copy \p size bytes of data from \p src_ptr to
1700 /// \p dst_ptr. The operation is performed asynchronously.
1701 ///
1702 /// \opencl_version_warning{2,0}
1703 ///
1704 /// \see_opencl2_ref{clEnqueueSVMMemcpy}
1705 event enqueue_svm_memcpy_async(void *dst_ptr,
1706 const void *src_ptr,
1707 size_t size,
1708 const wait_list &events = wait_list())
1709 {
1710 event event_;
1711
1712 cl_int ret = clEnqueueSVMMemcpy(
1713 m_queue,
1714 CL_FALSE,
1715 dst_ptr,
1716 src_ptr,
1717 size,
1718 events.size(),
1719 events.get_event_ptr(),
1720 &event_.get()
1721 );
1722
1723 if(ret != CL_SUCCESS){
1724 BOOST_THROW_EXCEPTION(opencl_error(ret));
1725 }
1726
1727 return event_;
1728 }
1729
1730 /// Enqueues a command to fill \p size bytes of data at \p svm_ptr with
1731 /// \p pattern.
1732 ///
1733 /// \opencl_version_warning{2,0}
1734 ///
1735 /// \see_opencl2_ref{clEnqueueSVMMemFill}
1736 event enqueue_svm_fill(void *svm_ptr,
1737 const void *pattern,
1738 size_t pattern_size,
1739 size_t size,
1740 const wait_list &events = wait_list())
1741
1742 {
1743 event event_;
1744
1745 cl_int ret = clEnqueueSVMMemFill(
1746 m_queue,
1747 svm_ptr,
1748 pattern,
1749 pattern_size,
1750 size,
1751 events.size(),
1752 events.get_event_ptr(),
1753 &event_.get()
1754 );
1755
1756 if(ret != CL_SUCCESS){
1757 BOOST_THROW_EXCEPTION(opencl_error(ret));
1758 }
1759
1760 return event_;
1761 }
1762
1763 /// Enqueues a command to free \p svm_ptr.
1764 ///
1765 /// \opencl_version_warning{2,0}
1766 ///
1767 /// \see_opencl2_ref{clEnqueueSVMFree}
1768 ///
1769 /// \see svm_free()
1770 event enqueue_svm_free(void *svm_ptr,
1771 const wait_list &events = wait_list())
1772 {
1773 event event_;
1774
1775 cl_int ret = clEnqueueSVMFree(
1776 m_queue,
1777 1,
1778 &svm_ptr,
1779 0,
1780 0,
1781 events.size(),
1782 events.get_event_ptr(),
1783 &event_.get()
1784 );
1785
1786 if(ret != CL_SUCCESS){
1787 BOOST_THROW_EXCEPTION(opencl_error(ret));
1788 }
1789
1790 return event_;
1791 }
1792
1793 /// Enqueues a command to map \p svm_ptr to the host memory space.
1794 ///
1795 /// \opencl_version_warning{2,0}
1796 ///
1797 /// \see_opencl2_ref{clEnqueueSVMMap}
1798 event enqueue_svm_map(void *svm_ptr,
1799 size_t size,
1800 cl_map_flags flags,
1801 const wait_list &events = wait_list())
1802 {
1803 event event_;
1804
1805 cl_int ret = clEnqueueSVMMap(
1806 m_queue,
1807 CL_TRUE,
1808 flags,
1809 svm_ptr,
1810 size,
1811 events.size(),
1812 events.get_event_ptr(),
1813 &event_.get()
1814 );
1815
1816 if(ret != CL_SUCCESS){
1817 BOOST_THROW_EXCEPTION(opencl_error(ret));
1818 }
1819
1820 return event_;
1821 }
1822
1823 /// Enqueues a command to unmap \p svm_ptr from the host memory space.
1824 ///
1825 /// \opencl_version_warning{2,0}
1826 ///
1827 /// \see_opencl2_ref{clEnqueueSVMUnmap}
1828 event enqueue_svm_unmap(void *svm_ptr,
1829 const wait_list &events = wait_list())
1830 {
1831 event event_;
1832
1833 cl_int ret = clEnqueueSVMUnmap(
1834 m_queue,
1835 svm_ptr,
1836 events.size(),
1837 events.get_event_ptr(),
1838 &event_.get()
1839 );
1840
1841 if(ret != CL_SUCCESS){
1842 BOOST_THROW_EXCEPTION(opencl_error(ret));
1843 }
1844
1845 return event_;
1846 }
1847 #endif // BOOST_COMPUTE_CL_VERSION_2_0
1848
1849 #if defined(BOOST_COMPUTE_CL_VERSION_2_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
1850 /// Enqueues a command to indicate which device a set of ranges of SVM allocations
1851 /// should be associated with. The pair \p svm_ptrs[i] and \p sizes[i] together define
1852 /// the starting address and number of bytes in a range to be migrated.
1853 ///
1854 /// If \p sizes is empty, then that means every allocation containing any \p svm_ptrs[i]
1855 /// is to be migrated. Also, if \p sizes[i] is zero, then the entire allocation containing
1856 /// \p svm_ptrs[i] is migrated.
1857 ///
1858 /// \opencl_version_warning{2,1}
1859 ///
1860 /// \see_opencl21_ref{clEnqueueSVMMigrateMem}
1861 event enqueue_svm_migrate_memory(const std::vector<const void*> &svm_ptrs,
1862 const std::vector<size_t> &sizes,
1863 const cl_mem_migration_flags flags = 0,
1864 const wait_list &events = wait_list())
1865 {
1866 BOOST_ASSERT(svm_ptrs.size() == sizes.size() || sizes.size() == 0);
1867 event event_;
1868
1869 cl_int ret = clEnqueueSVMMigrateMem(
1870 m_queue,
1871 static_cast<cl_uint>(svm_ptrs.size()),
1872 const_cast<void const **>(&svm_ptrs[0]),
1873 sizes.size() > 0 ? &sizes[0] : NULL,
1874 flags,
1875 events.size(),
1876 events.get_event_ptr(),
1877 &event_.get()
1878 );
1879
1880 if(ret != CL_SUCCESS){
1881 BOOST_THROW_EXCEPTION(opencl_error(ret));
1882 }
1883
1884 return event_;
1885 }
1886
1887 /// Enqueues a command to indicate which device a range of SVM allocation
1888 /// should be associated with. The pair \p svm_ptr and \p size together define
1889 /// the starting address and number of bytes in a range to be migrated.
1890 ///
1891 /// If \p size is 0, then the entire allocation containing \p svm_ptr is
1892 /// migrated. The default value for \p size is 0.
1893 ///
1894 /// \opencl_version_warning{2,1}
1895 ///
1896 /// \see_opencl21_ref{clEnqueueSVMMigrateMem}
1897 event enqueue_svm_migrate_memory(const void* svm_ptr,
1898 const size_t size = 0,
1899 const cl_mem_migration_flags flags = 0,
1900 const wait_list &events = wait_list())
1901 {
1902 event event_;
1903
1904 cl_int ret = clEnqueueSVMMigrateMem(
1905 m_queue,
1906 cl_uint(1),
1907 &svm_ptr,
1908 &size,
1909 flags,
1910 events.size(),
1911 events.get_event_ptr(),
1912 &event_.get()
1913 );
1914
1915 if(ret != CL_SUCCESS){
1916 BOOST_THROW_EXCEPTION(opencl_error(ret));
1917 }
1918
1919 return event_;
1920 }
1921 #endif // BOOST_COMPUTE_CL_VERSION_2_1
1922
1923 /// Returns \c true if the command queue is the same at \p other.
1924 bool operator==(const command_queue &other) const
1925 {
1926 return m_queue == other.m_queue;
1927 }
1928
1929 /// Returns \c true if the command queue is different from \p other.
1930 bool operator!=(const command_queue &other) const
1931 {
1932 return m_queue != other.m_queue;
1933 }
1934
1935 /// \internal_
1936 operator cl_command_queue() const
1937 {
1938 return m_queue;
1939 }
1940
1941 /// \internal_
1942 bool check_device_version(int major, int minor) const
1943 {
1944 return get_device().check_version(major, minor);
1945 }
1946
1947 private:
1948 cl_command_queue m_queue;
1949 };
1950
1951 inline buffer buffer::clone(command_queue &queue) const
1952 {
1953 buffer copy(get_context(), size(), get_memory_flags());
1954 queue.enqueue_copy_buffer(*this, copy, 0, 0, size());
1955 return copy;
1956 }
1957
1958 inline image1d image1d::clone(command_queue &queue) const
1959 {
1960 image1d copy(
1961 get_context(), width(), format(), get_memory_flags()
1962 );
1963
1964 queue.enqueue_copy_image(*this, copy, origin(), copy.origin(), size());
1965
1966 return copy;
1967 }
1968
1969 inline image2d image2d::clone(command_queue &queue) const
1970 {
1971 image2d copy(
1972 get_context(), width(), height(), format(), get_memory_flags()
1973 );
1974
1975 queue.enqueue_copy_image(*this, copy, origin(), copy.origin(), size());
1976
1977 return copy;
1978 }
1979
1980 inline image3d image3d::clone(command_queue &queue) const
1981 {
1982 image3d copy(
1983 get_context(), width(), height(), depth(), format(), get_memory_flags()
1984 );
1985
1986 queue.enqueue_copy_image(*this, copy, origin(), copy.origin(), size());
1987
1988 return copy;
1989 }
1990
1991 /// \internal_ define get_info() specializations for command_queue
1992 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(command_queue,
1993 ((cl_context, CL_QUEUE_CONTEXT))
1994 ((cl_device_id, CL_QUEUE_DEVICE))
1995 ((uint_, CL_QUEUE_REFERENCE_COUNT))
1996 ((cl_command_queue_properties, CL_QUEUE_PROPERTIES))
1997 )
1998
1999 #ifdef BOOST_COMPUTE_CL_VERSION_2_1
2000 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(command_queue,
2001 ((cl_command_queue, CL_QUEUE_DEVICE_DEFAULT))
2002 )
2003 #endif // BOOST_COMPUTE_CL_VERSION_2_1
2004
2005 } // end compute namespace
2006 } // end boost namespace
2007
2008 #endif // BOOST_COMPUTE_COMMAND_QUEUE_HPP