1#![allow(deprecated)]
16#![allow(clippy::too_many_arguments, clippy::missing_safety_doc)]
17
18pub use cl3::command_queue::*;
19
20use super::context::Context;
21
22use super::Result;
23use super::device::Device;
24use super::event::Event;
25use super::memory::*;
26
27#[allow(unused_imports)]
28use cl3::d3d10;
29#[allow(unused_imports)]
30use cl3::d3d11;
31#[allow(unused_imports)]
32use cl3::dx9_media_sharing;
33#[allow(unused_imports)]
34use cl3::egl;
35#[allow(unused_imports)]
36use cl3::ext;
37use cl3::gl;
38#[allow(unused_imports)]
39use cl3::types::cl_program;
40#[allow(unused_imports)]
41use libc::{c_char, c_void, size_t};
42use std::mem;
43use std::ptr;
44
45#[derive(Debug)]
50pub struct CommandQueue {
51 queue: cl_command_queue,
52 max_work_item_dimensions: cl_uint,
53}
54
55impl From<CommandQueue> for cl_command_queue {
56 fn from(value: CommandQueue) -> Self {
57 value.queue
58 }
59}
60
61impl Drop for CommandQueue {
62 fn drop(&mut self) {
63 unsafe { release_command_queue(self.queue).expect("Error: clReleaseCommandQueue") };
64 }
65}
66
67unsafe impl Send for CommandQueue {}
68unsafe impl Sync for CommandQueue {}
69
70impl CommandQueue {
71 pub const fn new(queue: cl_command_queue, max_work_item_dimensions: cl_uint) -> Self {
72 Self {
73 queue,
74 max_work_item_dimensions,
75 }
76 }
77
78 pub fn wrap_cl_command_queue(queue: cl_command_queue, device: &Device) -> Result<Self> {
79 let max_work_item_dimensions = device.max_work_item_dimensions()?;
80 Ok(Self::new(queue, max_work_item_dimensions))
81 }
82
83 pub const fn get(&self) -> cl_command_queue {
85 self.queue
86 }
87
88 pub const fn max_work_item_dimensions(&self) -> cl_uint {
91 self.max_work_item_dimensions
92 }
93
94 #[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
111 #[cfg_attr(
112 any(
113 feature = "CL_VERSION_2_0",
114 feature = "CL_VERSION_2_1",
115 feature = "CL_VERSION_2_2",
116 feature = "CL_VERSION_3_0"
117 ),
118 deprecated(
119 since = "0.1.0",
120 note = "From CL_VERSION_2_0 use create_command_queue_with_properties"
121 )
122 )]
123 pub unsafe fn create(
124 context: &Context,
125 device_id: cl_device_id,
126 properties: cl_command_queue_properties,
127 ) -> Result<Self> {
128 unsafe {
129 let queue = create_command_queue(context.get(), device_id, properties)?;
130 let device = Device::new(device_id);
131 let max_work_item_dimensions = device.max_work_item_dimensions()?;
132 Ok(Self::new(queue, max_work_item_dimensions))
133 }
134 }
135
136 #[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
147 #[cfg_attr(
148 any(
149 feature = "CL_VERSION_2_0",
150 feature = "CL_VERSION_2_1",
151 feature = "CL_VERSION_2_2",
152 feature = "CL_VERSION_3_0"
153 ),
154 deprecated(
155 since = "0.1.0",
156 note = "From CL_VERSION_2_0 use create_command_queue_with_properties"
157 )
158 )]
159 pub fn create_default(
160 context: &Context,
161 properties: cl_command_queue_properties,
162 ) -> Result<Self> {
163 unsafe { Self::create(context, context.default_device(), properties) }
164 }
165
166 #[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
182 pub unsafe fn create_with_properties(
183 context: &Context,
184 device_id: cl_device_id,
185 properties: cl_command_queue_properties,
186 queue_size: cl_uint,
187 ) -> Result<Self> {
188 unsafe {
189 let queue = if (0 < properties) || (0 < queue_size) {
190 let mut props: [cl_queue_properties; 5] = [0; 5];
191
192 let mut index = 0;
193 if 0 < properties {
194 props[index] = CL_QUEUE_PROPERTIES as cl_queue_properties;
195 props[index + 1] = properties as cl_queue_properties;
196 index += 2;
197 }
198
199 if 0 < queue_size {
200 props[index] = CL_QUEUE_SIZE as cl_queue_properties;
201 props[index + 1] = queue_size as cl_queue_properties;
202 }
203 create_command_queue_with_properties(context.get(), device_id, props.as_ptr())?
204 } else {
205 create_command_queue_with_properties(context.get(), device_id, ptr::null())?
206 };
207
208 let device = Device::new(device_id);
209 let max_work_item_dimensions = device.max_work_item_dimensions()?;
210 Ok(Self::new(queue, max_work_item_dimensions))
211 }
212 }
213
214 #[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
225 pub fn create_default_with_properties(
226 context: &Context,
227 properties: cl_command_queue_properties,
228 queue_size: cl_uint,
229 ) -> Result<Self> {
230 unsafe {
231 Self::create_with_properties(context, context.default_device(), properties, queue_size)
232 }
233 }
234
235 #[cfg(any(feature = "cl_khr_create_command_queue", feature = "dynamic"))]
236 pub fn create_with_properties_khr(
237 context: &Context,
238 device_id: cl_device_id,
239 properties: &[ext::cl_queue_properties_khr],
240 ) -> Result<Self> {
241 let queue = ext::create_command_queue_with_properties_khr(
242 context.get(),
243 device_id,
244 properties.as_ptr(),
245 )?;
246
247 let device = Device::new(device_id);
248 let max_work_item_dimensions = device.max_work_item_dimensions()?;
249 Ok(Self::new(queue, max_work_item_dimensions))
250 }
251
252 pub fn flush(&self) -> Result<()> {
255 Ok(flush(self.queue)?)
256 }
257
258 pub fn finish(&self) -> Result<()> {
261 Ok(finish(self.queue)?)
262 }
263
264 pub unsafe fn enqueue_read_buffer<T>(
265 &self,
266 buffer: &Buffer<T>,
267 blocking_read: cl_bool,
268 offset: size_t,
269 data: &mut [T],
270 event_wait_list: &[cl_event],
271 ) -> Result<Event> {
272 unsafe {
273 let event = enqueue_read_buffer(
274 self.queue,
275 buffer.get(),
276 blocking_read,
277 offset,
278 mem::size_of_val(data),
279 data.as_mut_ptr() as cl_mem,
280 event_wait_list.len() as cl_uint,
281 if !event_wait_list.is_empty() {
282 event_wait_list.as_ptr()
283 } else {
284 ptr::null()
285 },
286 )?;
287 Ok(Event::new(event))
288 }
289 }
290
291 #[allow(clippy::as_ptr_cast_mut)]
292 pub unsafe fn enqueue_read_buffer_rect<T>(
293 &self,
294 buffer: &Buffer<T>,
295 blocking_read: cl_bool,
296 buffer_origin: *const size_t,
297 host_origin: *const size_t,
298 region: *const size_t,
299 buffer_row_pitch: size_t,
300 buffer_slice_pitch: size_t,
301 host_row_pitch: size_t,
302 host_slice_pitch: size_t,
303 ptr: *mut c_void,
304 event_wait_list: &[cl_event],
305 ) -> Result<Event> {
306 unsafe {
307 let event = enqueue_read_buffer_rect(
308 self.queue,
309 buffer.get(),
310 blocking_read,
311 buffer_origin,
312 host_origin,
313 region,
314 buffer_row_pitch,
315 buffer_slice_pitch,
316 host_row_pitch,
317 host_slice_pitch,
318 ptr,
319 event_wait_list.len() as cl_uint,
320 if !event_wait_list.is_empty() {
321 event_wait_list.as_ptr()
322 } else {
323 ptr::null()
324 },
325 )?;
326 Ok(Event::new(event))
327 }
328 }
329
330 #[allow(clippy::as_ptr_cast_mut)]
331 pub unsafe fn enqueue_write_buffer<T>(
332 &self,
333 buffer: &mut Buffer<T>,
334 blocking_write: cl_bool,
335 offset: size_t,
336 data: &[T],
337 event_wait_list: &[cl_event],
338 ) -> Result<Event> {
339 unsafe {
340 let event = enqueue_write_buffer(
341 self.queue,
342 buffer.get_mut(),
343 blocking_write,
344 offset,
345 mem::size_of_val(data),
346 data.as_ptr() as cl_mem,
347 event_wait_list.len() as cl_uint,
348 if !event_wait_list.is_empty() {
349 event_wait_list.as_ptr()
350 } else {
351 ptr::null()
352 },
353 )?;
354 Ok(Event::new(event))
355 }
356 }
357
358 pub unsafe fn enqueue_write_buffer_rect<T>(
359 &self,
360 buffer: &mut Buffer<T>,
361 blocking_write: cl_bool,
362 buffer_origin: *const size_t,
363 host_origin: *const size_t,
364 region: *const size_t,
365 buffer_row_pitch: size_t,
366 buffer_slice_pitch: size_t,
367 host_row_pitch: size_t,
368 host_slice_pitch: size_t,
369 ptr: *mut c_void,
370 event_wait_list: &[cl_event],
371 ) -> Result<Event> {
372 unsafe {
373 let event = enqueue_write_buffer_rect(
374 self.queue,
375 buffer.get_mut(),
376 blocking_write,
377 buffer_origin,
378 host_origin,
379 region,
380 buffer_row_pitch,
381 buffer_slice_pitch,
382 host_row_pitch,
383 host_slice_pitch,
384 ptr,
385 event_wait_list.len() as cl_uint,
386 if !event_wait_list.is_empty() {
387 event_wait_list.as_ptr()
388 } else {
389 ptr::null()
390 },
391 )?;
392 Ok(Event::new(event))
393 }
394 }
395
396 #[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
397 #[allow(clippy::as_ptr_cast_mut)]
398 pub unsafe fn enqueue_fill_buffer<T>(
399 &self,
400 buffer: &mut Buffer<T>,
401 pattern: &[T],
402 offset: size_t,
403 size: size_t,
404 event_wait_list: &[cl_event],
405 ) -> Result<Event> {
406 unsafe {
407 let event = enqueue_fill_buffer(
408 self.queue,
409 buffer.get_mut(),
410 pattern.as_ptr() as cl_mem,
411 mem::size_of_val(pattern),
412 offset,
413 size,
414 event_wait_list.len() as cl_uint,
415 if !event_wait_list.is_empty() {
416 event_wait_list.as_ptr()
417 } else {
418 ptr::null()
419 },
420 )?;
421 Ok(Event::new(event))
422 }
423 }
424
425 pub unsafe fn enqueue_copy_buffer<T>(
426 &self,
427 src_buffer: &Buffer<T>,
428 dst_buffer: &mut Buffer<T>,
429 src_offset: size_t,
430 dst_offset: size_t,
431 size: size_t,
432 event_wait_list: &[cl_event],
433 ) -> Result<Event> {
434 unsafe {
435 let event = enqueue_copy_buffer(
436 self.queue,
437 src_buffer.get(),
438 dst_buffer.get_mut(),
439 src_offset,
440 dst_offset,
441 size,
442 event_wait_list.len() as cl_uint,
443 if !event_wait_list.is_empty() {
444 event_wait_list.as_ptr()
445 } else {
446 ptr::null()
447 },
448 )?;
449 Ok(Event::new(event))
450 }
451 }
452
453 pub unsafe fn enqueue_copy_buffer_rect<T>(
454 &self,
455 src_buffer: &Buffer<T>,
456 dst_buffer: &mut Buffer<T>,
457 src_origin: *const size_t,
458 dst_origin: *const size_t,
459 region: *const size_t,
460 src_row_pitch: size_t,
461 src_slice_pitch: size_t,
462 dst_row_pitch: size_t,
463 dst_slice_pitch: size_t,
464 event_wait_list: &[cl_event],
465 ) -> Result<Event> {
466 unsafe {
467 let event = enqueue_copy_buffer_rect(
468 self.queue,
469 src_buffer.get(),
470 dst_buffer.get_mut(),
471 src_origin,
472 dst_origin,
473 region,
474 src_row_pitch,
475 src_slice_pitch,
476 dst_row_pitch,
477 dst_slice_pitch,
478 event_wait_list.len() as cl_uint,
479 if !event_wait_list.is_empty() {
480 event_wait_list.as_ptr()
481 } else {
482 ptr::null()
483 },
484 )?;
485 Ok(Event::new(event))
486 }
487 }
488
489 pub unsafe fn enqueue_read_image(
490 &self,
491 image: &Image,
492 blocking_read: cl_bool,
493 origin: *const size_t,
494 region: *const size_t,
495 row_pitch: size_t,
496 slice_pitch: size_t,
497 ptr: *mut c_void,
498 event_wait_list: &[cl_event],
499 ) -> Result<Event> {
500 unsafe {
501 let event = enqueue_read_image(
502 self.queue,
503 image.get(),
504 blocking_read,
505 origin,
506 region,
507 row_pitch,
508 slice_pitch,
509 ptr,
510 event_wait_list.len() as cl_uint,
511 if !event_wait_list.is_empty() {
512 event_wait_list.as_ptr()
513 } else {
514 ptr::null()
515 },
516 )?;
517 Ok(Event::new(event))
518 }
519 }
520
521 pub unsafe fn enqueue_write_image(
522 &self,
523 image: &mut Image,
524 blocking_write: cl_bool,
525 origin: *const size_t,
526 region: *const size_t,
527 row_pitch: size_t,
528 slice_pitch: size_t,
529 ptr: *mut c_void,
530 event_wait_list: &[cl_event],
531 ) -> Result<Event> {
532 unsafe {
533 let event = enqueue_write_image(
534 self.queue,
535 image.get_mut(),
536 blocking_write,
537 origin,
538 region,
539 row_pitch,
540 slice_pitch,
541 ptr,
542 event_wait_list.len() as cl_uint,
543 if !event_wait_list.is_empty() {
544 event_wait_list.as_ptr()
545 } else {
546 ptr::null()
547 },
548 )?;
549 Ok(Event::new(event))
550 }
551 }
552
553 #[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
554 pub unsafe fn enqueue_fill_image(
555 &self,
556 image: &mut Image,
557 fill_color: *const c_void,
558 origin: *const size_t,
559 region: *const size_t,
560 event_wait_list: &[cl_event],
561 ) -> Result<Event> {
562 unsafe {
563 let event = enqueue_fill_image(
564 self.queue,
565 image.get_mut(),
566 fill_color,
567 origin,
568 region,
569 event_wait_list.len() as cl_uint,
570 if !event_wait_list.is_empty() {
571 event_wait_list.as_ptr()
572 } else {
573 ptr::null()
574 },
575 )?;
576 Ok(Event::new(event))
577 }
578 }
579
580 pub unsafe fn enqueue_copy_image(
581 &self,
582 src_image: &Image,
583 dst_image: &mut Image,
584 src_origin: *const size_t,
585 dst_origin: *const size_t,
586 region: *const size_t,
587 event_wait_list: &[cl_event],
588 ) -> Result<Event> {
589 unsafe {
590 let event = enqueue_copy_image(
591 self.queue,
592 src_image.get(),
593 dst_image.get_mut(),
594 src_origin,
595 dst_origin,
596 region,
597 event_wait_list.len() as cl_uint,
598 if !event_wait_list.is_empty() {
599 event_wait_list.as_ptr()
600 } else {
601 ptr::null()
602 },
603 )?;
604 Ok(Event::new(event))
605 }
606 }
607
608 pub unsafe fn enqueue_copy_image_to_buffer<T>(
609 &self,
610 src_image: &Image,
611 dst_buffer: &mut Buffer<T>,
612 src_origin: *const size_t,
613 region: *const size_t,
614 dst_offset: size_t,
615 event_wait_list: &[cl_event],
616 ) -> Result<Event> {
617 unsafe {
618 let event = enqueue_copy_image_to_buffer(
619 self.queue,
620 src_image.get(),
621 dst_buffer.get_mut(),
622 src_origin,
623 region,
624 dst_offset,
625 event_wait_list.len() as cl_uint,
626 if !event_wait_list.is_empty() {
627 event_wait_list.as_ptr()
628 } else {
629 ptr::null()
630 },
631 )?;
632 Ok(Event::new(event))
633 }
634 }
635
636 pub unsafe fn enqueue_copy_buffer_to_image<T>(
637 &self,
638 src_buffer: &Buffer<T>,
639 dst_image: &mut Image,
640 src_offset: size_t,
641 dst_origin: *const size_t,
642 region: *const size_t,
643 event_wait_list: &[cl_event],
644 ) -> Result<Event> {
645 unsafe {
646 let event = enqueue_copy_buffer_to_image(
647 self.queue,
648 src_buffer.get(),
649 dst_image.get_mut(),
650 src_offset,
651 dst_origin,
652 region,
653 event_wait_list.len() as cl_uint,
654 if !event_wait_list.is_empty() {
655 event_wait_list.as_ptr()
656 } else {
657 ptr::null()
658 },
659 )?;
660 Ok(Event::new(event))
661 }
662 }
663
664 pub unsafe fn enqueue_map_buffer<T>(
665 &self,
666 buffer: &Buffer<T>,
667 blocking_map: cl_bool,
668 map_flags: cl_map_flags,
669 offset: size_t,
670 size: size_t,
671 buffer_ptr: &mut cl_mem,
672 event_wait_list: &[cl_event],
673 ) -> Result<Event> {
674 unsafe {
675 let event = enqueue_map_buffer(
676 self.queue,
677 buffer.get(),
678 blocking_map,
679 map_flags,
680 offset,
681 size,
682 buffer_ptr,
683 event_wait_list.len() as cl_uint,
684 if !event_wait_list.is_empty() {
685 event_wait_list.as_ptr()
686 } else {
687 ptr::null()
688 },
689 )?;
690 Ok(Event::new(event))
691 }
692 }
693
694 pub unsafe fn enqueue_map_image(
695 &self,
696 image: &Image,
697 blocking_map: cl_bool,
698 map_flags: cl_map_flags,
699 origin: *const size_t,
700 region: *const size_t,
701 image_row_pitch: *mut size_t,
702 image_slice_pitch: *mut size_t,
703 image_ptr: &mut cl_mem,
704 event_wait_list: &[cl_event],
705 ) -> Result<Event> {
706 unsafe {
707 let event = enqueue_map_image(
708 self.queue,
709 image.get(),
710 blocking_map,
711 map_flags,
712 origin,
713 region,
714 image_row_pitch,
715 image_slice_pitch,
716 image_ptr,
717 event_wait_list.len() as cl_uint,
718 if !event_wait_list.is_empty() {
719 event_wait_list.as_ptr()
720 } else {
721 ptr::null()
722 },
723 )?;
724 Ok(Event::new(event))
725 }
726 }
727
728 pub unsafe fn enqueue_unmap_mem_object(
729 &self,
730 memobj: cl_mem,
731 mapped_ptr: *mut c_void,
732 event_wait_list: &[cl_event],
733 ) -> Result<Event> {
734 unsafe {
735 let event = enqueue_unmap_mem_object(
736 self.queue,
737 memobj,
738 mapped_ptr,
739 event_wait_list.len() as cl_uint,
740 if !event_wait_list.is_empty() {
741 event_wait_list.as_ptr()
742 } else {
743 ptr::null()
744 },
745 )?;
746 Ok(Event::new(event))
747 }
748 }
749
750 #[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
751 pub unsafe fn enqueue_migrate_mem_object(
752 &self,
753 num_mem_objects: cl_uint,
754 mem_objects: *const cl_mem,
755 flags: cl_mem_migration_flags,
756 event_wait_list: &[cl_event],
757 ) -> Result<Event> {
758 unsafe {
759 let event = enqueue_migrate_mem_object(
760 self.queue,
761 num_mem_objects,
762 mem_objects,
763 flags,
764 event_wait_list.len() as cl_uint,
765 if !event_wait_list.is_empty() {
766 event_wait_list.as_ptr()
767 } else {
768 ptr::null()
769 },
770 )?;
771 Ok(Event::new(event))
772 }
773 }
774
775 #[cfg(any(feature = "cl_ext_migrate_memobject", feature = "dynamic"))]
776 pub unsafe fn enqueue_migrate_mem_object_ext(
777 &self,
778 num_mem_objects: cl_uint,
779 mem_objects: *const cl_mem,
780 flags: ext::cl_mem_migration_flags_ext,
781 event_wait_list: &[cl_event],
782 ) -> Result<Event> {
783 unsafe {
784 let event = ext::enqueue_migrate_mem_object_ext(
785 self.queue,
786 num_mem_objects,
787 mem_objects,
788 flags,
789 event_wait_list.len() as cl_uint,
790 if !event_wait_list.is_empty() {
791 event_wait_list.as_ptr()
792 } else {
793 ptr::null()
794 },
795 )?;
796 Ok(Event::new(event))
797 }
798 }
799
800 pub unsafe fn enqueue_nd_range_kernel(
801 &self,
802 kernel: cl_kernel,
803 work_dim: cl_uint,
804 global_work_offsets: *const size_t,
805 global_work_sizes: *const size_t,
806 local_work_sizes: *const size_t,
807 event_wait_list: &[cl_event],
808 ) -> Result<Event> {
809 unsafe {
810 let event = enqueue_nd_range_kernel(
811 self.queue,
812 kernel,
813 work_dim,
814 global_work_offsets,
815 global_work_sizes,
816 local_work_sizes,
817 event_wait_list.len() as cl_uint,
818 if !event_wait_list.is_empty() {
819 event_wait_list.as_ptr()
820 } else {
821 ptr::null()
822 },
823 )?;
824 Ok(Event::new(event))
825 }
826 }
827
828 #[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
829 #[cfg_attr(
830 any(
831 feature = "CL_VERSION_2_0",
832 feature = "CL_VERSION_2_1",
833 feature = "CL_VERSION_2_2",
834 feature = "CL_VERSION_3_0"
835 ),
836 deprecated(
837 since = "0.1.0",
838 note = "From CL_VERSION_2_0 use enqueue_nd_range_kernel"
839 )
840 )]
841 pub unsafe fn enqueue_task(
842 &self,
843 kernel: cl_kernel,
844 event_wait_list: &[cl_event],
845 ) -> Result<Event> {
846 unsafe {
847 let event = enqueue_task(
848 self.queue,
849 kernel,
850 event_wait_list.len() as cl_uint,
851 if !event_wait_list.is_empty() {
852 event_wait_list.as_ptr()
853 } else {
854 ptr::null()
855 },
856 )?;
857 Ok(Event::new(event))
858 }
859 }
860
861 #[allow(clippy::as_ptr_cast_mut)]
862 pub unsafe fn enqueue_native_kernel(
863 &self,
864 user_func: Option<unsafe extern "C" fn(*mut c_void)>,
865 args: &[*mut c_void],
866 mem_list: &[cl_mem],
867 args_mem_loc: &[*const c_void],
868 event_wait_list: &[cl_event],
869 ) -> Result<Event> {
870 unsafe {
871 let event = enqueue_native_kernel(
872 self.queue,
873 user_func,
874 args.as_ptr() as *mut c_void,
875 args.len() as size_t,
876 mem_list.len() as cl_uint,
877 if !mem_list.is_empty() {
878 mem_list.as_ptr()
879 } else {
880 ptr::null()
881 },
882 args_mem_loc.as_ptr(),
883 event_wait_list.len() as cl_uint,
884 if !event_wait_list.is_empty() {
885 event_wait_list.as_ptr()
886 } else {
887 ptr::null()
888 },
889 )?;
890 Ok(Event::new(event))
891 }
892 }
893
894 #[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
895 pub unsafe fn enqueue_marker_with_wait_list(
896 &self,
897 event_wait_list: &[cl_event],
898 ) -> Result<Event> {
899 unsafe {
900 let event = enqueue_marker_with_wait_list(
901 self.queue,
902 event_wait_list.len() as cl_uint,
903 if !event_wait_list.is_empty() {
904 event_wait_list.as_ptr()
905 } else {
906 ptr::null()
907 },
908 )?;
909 Ok(Event::new(event))
910 }
911 }
912
913 #[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
914 pub unsafe fn enqueue_barrier_with_wait_list(
915 &self,
916 event_wait_list: &[cl_event],
917 ) -> Result<Event> {
918 unsafe {
919 let event = enqueue_barrier_with_wait_list(
920 self.queue,
921 event_wait_list.len() as cl_uint,
922 if !event_wait_list.is_empty() {
923 event_wait_list.as_ptr()
924 } else {
925 ptr::null()
926 },
927 )?;
928 Ok(Event::new(event))
929 }
930 }
931
932 #[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
933 pub unsafe fn enqueue_svm_free(
934 &self,
935 svm_pointers: &[*const c_void],
936 pfn_free_func: Option<
937 unsafe extern "C" fn(
938 queue: cl_command_queue,
939 num_svm_pointers: cl_uint,
940 svm_pointers: *mut *mut c_void,
941 user_data: *mut c_void,
942 ),
943 >,
944 user_data: *mut c_void,
945 event_wait_list: &[cl_event],
946 ) -> Result<Event> {
947 unsafe {
948 let event = enqueue_svm_free(
949 self.queue,
950 svm_pointers.len() as cl_uint,
951 svm_pointers.as_ptr(),
952 pfn_free_func,
953 user_data,
954 event_wait_list.len() as cl_uint,
955 if !event_wait_list.is_empty() {
956 event_wait_list.as_ptr()
957 } else {
958 ptr::null()
959 },
960 )?;
961 Ok(Event::new(event))
962 }
963 }
964
965 #[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
966 pub unsafe fn enqueue_svm_mem_cpy(
967 &self,
968 blocking_copy: cl_bool,
969 dst_ptr: *mut c_void,
970 src_ptr: *const c_void,
971 size: size_t,
972 event_wait_list: &[cl_event],
973 ) -> Result<Event> {
974 unsafe {
975 let event = enqueue_svm_mem_cpy(
976 self.queue,
977 blocking_copy,
978 dst_ptr,
979 src_ptr,
980 size,
981 event_wait_list.len() as cl_uint,
982 if !event_wait_list.is_empty() {
983 event_wait_list.as_ptr()
984 } else {
985 ptr::null()
986 },
987 )?;
988 Ok(Event::new(event))
989 }
990 }
991
992 #[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
993 pub unsafe fn enqueue_svm_mem_fill<T>(
994 &self,
995 svm_ptr: *mut c_void,
996 pattern: &[T],
997 size: size_t,
998 event_wait_list: &[cl_event],
999 ) -> Result<Event> {
1000 unsafe {
1001 let event = enqueue_svm_mem_fill(
1002 self.queue,
1003 svm_ptr,
1004 pattern.as_ptr() as *const c_void,
1005 mem::size_of_val(pattern),
1006 size,
1007 event_wait_list.len() as cl_uint,
1008 if !event_wait_list.is_empty() {
1009 event_wait_list.as_ptr()
1010 } else {
1011 ptr::null()
1012 },
1013 )?;
1014 Ok(Event::new(event))
1015 }
1016 }
1017
1018 #[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
1019 pub unsafe fn enqueue_svm_map<T>(
1020 &self,
1021 blocking_map: cl_bool,
1022 flags: cl_map_flags,
1023 svm: &mut [T],
1024 event_wait_list: &[cl_event],
1025 ) -> Result<Event> {
1026 unsafe {
1027 let event = enqueue_svm_map(
1028 self.queue,
1029 blocking_map,
1030 flags,
1031 svm.as_mut_ptr() as *mut c_void,
1032 mem::size_of_val(svm),
1033 event_wait_list.len() as cl_uint,
1034 if !event_wait_list.is_empty() {
1035 event_wait_list.as_ptr()
1036 } else {
1037 ptr::null()
1038 },
1039 )?;
1040 Ok(Event::new(event))
1041 }
1042 }
1043
1044 #[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
1045 #[allow(clippy::as_ptr_cast_mut)]
1046 pub unsafe fn enqueue_svm_unmap<T>(
1047 &self,
1048 svm: &[T],
1049 event_wait_list: &[cl_event],
1050 ) -> Result<Event> {
1051 unsafe {
1052 let event = enqueue_svm_unmap(
1053 self.queue,
1054 svm.as_ptr() as *mut c_void,
1055 event_wait_list.len() as cl_uint,
1056 if !event_wait_list.is_empty() {
1057 event_wait_list.as_ptr()
1058 } else {
1059 ptr::null()
1060 },
1061 )?;
1062 Ok(Event::new(event))
1063 }
1064 }
1065
1066 #[cfg(any(feature = "CL_VERSION_2_1", feature = "dynamic"))]
1067 pub unsafe fn enqueue_svm_migrate_mem(
1068 &self,
1069 svm_pointers: &[*const c_void],
1070 sizes: *const size_t,
1071 flags: cl_mem_migration_flags,
1072 event_wait_list: &[cl_event],
1073 ) -> Result<Event> {
1074 unsafe {
1075 let event = enqueue_svm_migrate_mem(
1076 self.queue,
1077 svm_pointers.len() as cl_uint,
1078 svm_pointers.as_ptr(),
1079 sizes,
1080 flags,
1081 event_wait_list.len() as cl_uint,
1082 if !event_wait_list.is_empty() {
1083 event_wait_list.as_ptr()
1084 } else {
1085 ptr::null()
1086 },
1087 )?;
1088 Ok(Event::new(event))
1089 }
1090 }
1091
1092 pub unsafe fn enqueue_acquire_gl_objects(
1093 &self,
1094 mem_objects: &[*const c_void],
1095 event_wait_list: &[cl_event],
1096 ) -> Result<Event> {
1097 unsafe {
1098 let event = gl::enqueue_acquire_gl_objects(
1099 self.queue,
1100 mem_objects.len() as cl_uint,
1101 mem_objects.as_ptr() as *const *mut c_void,
1102 event_wait_list.len() as cl_uint,
1103 if !event_wait_list.is_empty() {
1104 event_wait_list.as_ptr()
1105 } else {
1106 ptr::null()
1107 },
1108 )?;
1109 Ok(Event::new(event))
1110 }
1111 }
1112
1113 pub unsafe fn enqueue_release_gl_objects(
1114 &self,
1115 mem_objects: &[*const c_void],
1116 event_wait_list: &[cl_event],
1117 ) -> Result<Event> {
1118 unsafe {
1119 let event = gl::enqueue_release_gl_objects(
1120 self.queue,
1121 mem_objects.len() as cl_uint,
1122 mem_objects.as_ptr() as *const *mut c_void,
1123 event_wait_list.len() as cl_uint,
1124 if !event_wait_list.is_empty() {
1125 event_wait_list.as_ptr()
1126 } else {
1127 ptr::null()
1128 },
1129 )?;
1130 Ok(Event::new(event))
1131 }
1132 }
1133
1134 #[cfg(any(feature = "cl_khr_egl_image", feature = "dynamic"))]
1135 #[inline]
1136 pub unsafe fn enqueue_acquire_egl_objects(
1137 &self,
1138 mem_objects: &[*const c_void],
1139 event_wait_list: &[cl_event],
1140 ) -> Result<Event> {
1141 unsafe {
1142 let event = egl::enqueue_acquire_egl_objects(
1143 self.queue,
1144 mem_objects.len() as cl_uint,
1145 mem_objects.as_ptr() as *const *mut c_void,
1146 event_wait_list.len() as cl_uint,
1147 if !event_wait_list.is_empty() {
1148 event_wait_list.as_ptr()
1149 } else {
1150 ptr::null()
1151 },
1152 )?;
1153 Ok(Event::new(event))
1154 }
1155 }
1156
1157 #[cfg(any(feature = "cl_khr_egl_image", feature = "dynamic"))]
1158 #[inline]
1159 pub unsafe fn enqueue_release_egl_objects(
1160 &self,
1161 mem_objects: &[*const c_void],
1162 event_wait_list: &[cl_event],
1163 ) -> Result<Event> {
1164 unsafe {
1165 let event = egl::enqueue_release_egl_objects(
1166 self.queue,
1167 mem_objects.len() as cl_uint,
1168 mem_objects.as_ptr() as *const *mut c_void,
1169 event_wait_list.len() as cl_uint,
1170 if !event_wait_list.is_empty() {
1171 event_wait_list.as_ptr()
1172 } else {
1173 ptr::null()
1174 },
1175 )?;
1176 Ok(Event::new(event))
1177 }
1178 }
1179
1180 #[cfg(any(feature = "cl_img_use_gralloc_ptr", feature = "dynamic"))]
1181 #[inline]
1182 pub unsafe fn enqueue_acquire_gralloc_objects_img(
1183 &self,
1184 mem_objects: &[*const c_void],
1185 event_wait_list: &[cl_event],
1186 ) -> Result<Event> {
1187 unsafe {
1188 let event = ext::enqueue_acquire_gralloc_objects_img(
1189 self.queue,
1190 mem_objects.len() as cl_uint,
1191 mem_objects.as_ptr() as *const *mut c_void,
1192 event_wait_list.len() as cl_uint,
1193 if !event_wait_list.is_empty() {
1194 event_wait_list.as_ptr()
1195 } else {
1196 ptr::null()
1197 },
1198 )?;
1199 Ok(Event::new(event))
1200 }
1201 }
1202
1203 #[cfg(any(feature = "cl_img_use_gralloc_ptr", feature = "dynamic"))]
1204 #[inline]
1205 pub unsafe fn enqueue_release_gralloc_objects_img(
1206 &self,
1207 mem_objects: &[*const c_void],
1208 event_wait_list: &[cl_event],
1209 ) -> Result<Event> {
1210 unsafe {
1211 let event = ext::enqueue_release_gralloc_objects_img(
1212 self.queue,
1213 mem_objects.len() as cl_uint,
1214 mem_objects.as_ptr() as *const *mut c_void,
1215 event_wait_list.len() as cl_uint,
1216 if !event_wait_list.is_empty() {
1217 event_wait_list.as_ptr()
1218 } else {
1219 ptr::null()
1220 },
1221 )?;
1222 Ok(Event::new(event))
1223 }
1224 }
1225
1226 #[cfg(any(feature = "cl_khr_external_memory", feature = "dynamic"))]
1227 #[inline]
1228 pub unsafe fn enqueue_acquire_external_mem_objects_khr(
1229 &self,
1230 mem_objects: &[*const c_void],
1231 event_wait_list: &[cl_event],
1232 ) -> Result<Event> {
1233 unsafe {
1234 let event = ext::enqueue_acquire_external_mem_objects_khr(
1235 self.queue,
1236 mem_objects.len() as cl_uint,
1237 mem_objects.as_ptr() as *const *mut c_void,
1238 event_wait_list.len() as cl_uint,
1239 if !event_wait_list.is_empty() {
1240 event_wait_list.as_ptr()
1241 } else {
1242 ptr::null()
1243 },
1244 )?;
1245 Ok(Event::new(event))
1246 }
1247 }
1248
1249 #[cfg(any(feature = "cl_khr_external_memory", feature = "dynamic"))]
1250 #[inline]
1251 pub unsafe fn enqueue_release_external_mem_objects_khr(
1252 &self,
1253 mem_objects: &[*const c_void],
1254 event_wait_list: &[cl_event],
1255 ) -> Result<Event> {
1256 unsafe {
1257 let event = ext::enqueue_release_external_mem_objects_khr(
1258 self.queue,
1259 mem_objects.len() as cl_uint,
1260 mem_objects.as_ptr() as *const *mut c_void,
1261 event_wait_list.len() as cl_uint,
1262 if !event_wait_list.is_empty() {
1263 event_wait_list.as_ptr()
1264 } else {
1265 ptr::null()
1266 },
1267 )?;
1268 Ok(Event::new(event))
1269 }
1270 }
1271
1272 #[cfg(any(feature = "cl_khr_semaphore", feature = "dynamic"))]
1273 #[inline]
1274 pub unsafe fn enqueue_wait_semaphores_khr(
1275 &self,
1276 sema_objects: &[*const c_void],
1277 sema_payload_list: *const ext::cl_semaphore_payload_khr,
1278 event_wait_list: &[cl_event],
1279 ) -> Result<Event> {
1280 unsafe {
1281 let event = ext::enqueue_wait_semaphores_khr(
1282 self.queue,
1283 sema_objects.len() as cl_uint,
1284 sema_objects.as_ptr() as *const *mut c_void,
1285 sema_payload_list,
1286 event_wait_list.len() as cl_uint,
1287 if !event_wait_list.is_empty() {
1288 event_wait_list.as_ptr()
1289 } else {
1290 ptr::null()
1291 },
1292 )?;
1293 Ok(Event::new(event))
1294 }
1295 }
1296
1297 #[cfg(any(feature = "cl_khr_semaphore", feature = "dynamic"))]
1298 #[inline]
1299 pub unsafe fn enqueue_signal_semaphores_khr(
1300 &self,
1301 sema_objects: &[*const c_void],
1302 sema_payload_list: *const ext::cl_semaphore_payload_khr,
1303 event_wait_list: &[cl_event],
1304 ) -> Result<Event> {
1305 unsafe {
1306 let event = ext::enqueue_signal_semaphores_khr(
1307 self.queue,
1308 sema_objects.len() as cl_uint,
1309 sema_objects.as_ptr() as *const *mut c_void,
1310 sema_payload_list,
1311 event_wait_list.len() as cl_uint,
1312 if !event_wait_list.is_empty() {
1313 event_wait_list.as_ptr()
1314 } else {
1315 ptr::null()
1316 },
1317 )?;
1318 Ok(Event::new(event))
1319 }
1320 }
1321
1322 #[cfg(any(feature = "cl_intel_dx9_media_sharing", feature = "dynamic"))]
1323 #[inline]
1324 pub unsafe fn enqueue_acquire_dx9_objects_intel(
1325 &self,
1326 mem_objects: &[*const c_void],
1327 event_wait_list: &[cl_event],
1328 ) -> Result<Event> {
1329 unsafe {
1330 let event = dx9_media_sharing::enqueue_acquire_dx9_objects_intel(
1331 self.queue,
1332 mem_objects.len() as cl_uint,
1333 mem_objects.as_ptr() as *const *mut c_void,
1334 event_wait_list.len() as cl_uint,
1335 if !event_wait_list.is_empty() {
1336 event_wait_list.as_ptr()
1337 } else {
1338 ptr::null()
1339 },
1340 )?;
1341 Ok(Event::new(event))
1342 }
1343 }
1344
1345 #[cfg(any(feature = "cl_intel_dx9_media_sharing", feature = "dynamic"))]
1346 #[inline]
1347 pub unsafe fn enqueue_release_dx9_objects_intel(
1348 &self,
1349 mem_objects: &[*const c_void],
1350 event_wait_list: &[cl_event],
1351 ) -> Result<Event> {
1352 unsafe {
1353 let event = dx9_media_sharing::enqueue_release_dx9_objects_intel(
1354 self.queue,
1355 mem_objects.len() as cl_uint,
1356 mem_objects.as_ptr() as *const *mut c_void,
1357 event_wait_list.len() as cl_uint,
1358 if !event_wait_list.is_empty() {
1359 event_wait_list.as_ptr()
1360 } else {
1361 ptr::null()
1362 },
1363 )?;
1364 Ok(Event::new(event))
1365 }
1366 }
1367
1368 #[cfg(any(feature = "cl_img_generate_mipmap", feature = "dynamic"))]
1369 #[allow(clippy::cast_possible_truncation)]
1370 #[inline]
1371 pub unsafe fn enqueue_generate_mipmap_img(
1372 &self,
1373 src_image: cl_mem,
1374 dst_image: cl_mem,
1375 mipmap_filter_mode: ext::cl_mipmap_filter_mode_img,
1376 array_region: *const size_t,
1377 mip_region: *const size_t,
1378 event_wait_list: &[cl_event],
1379 ) -> Result<Event> {
1380 unsafe {
1381 let event = ext::enqueue_generate_mipmap_img(
1382 self.queue,
1383 src_image,
1384 dst_image,
1385 mipmap_filter_mode,
1386 array_region,
1387 mip_region,
1388 event_wait_list.len() as cl_uint,
1389 if !event_wait_list.is_empty() {
1390 event_wait_list.as_ptr()
1391 } else {
1392 ptr::null()
1393 },
1394 )?;
1395 Ok(Event::new(event))
1396 }
1397 }
1398
1399 #[cfg(any(feature = "cl_intel_program_scope_host_pipe", feature = "dynamic"))]
1400 pub unsafe fn enqueue_read_host_pipe_intel(
1401 &self,
1402 program: cl_program,
1403 pipe_symbol: *const c_char,
1404 blocking_read: cl_bool,
1405 ptr: *mut c_void,
1406 size: size_t,
1407 event_wait_list: &[cl_event],
1408 ) -> Result<Event> {
1409 unsafe {
1410 let event = ext::enqueue_read_host_pipe_intel(
1411 self.queue,
1412 program,
1413 pipe_symbol,
1414 blocking_read,
1415 ptr,
1416 size,
1417 event_wait_list.len() as cl_uint,
1418 if !event_wait_list.is_empty() {
1419 event_wait_list.as_ptr()
1420 } else {
1421 ptr::null()
1422 },
1423 )?;
1424 Ok(Event::new(event))
1425 }
1426 }
1427
1428 #[cfg(any(feature = "cl_intel_program_scope_host_pipe", feature = "dynamic"))]
1429 pub unsafe fn enqueue_write_host_pipe_intel(
1430 &self,
1431 program: cl_program,
1432 pipe_symbol: *const c_char,
1433 blocking_write: cl_bool,
1434 ptr: *const c_void,
1435 size: size_t,
1436 event_wait_list: &[cl_event],
1437 ) -> Result<Event> {
1438 unsafe {
1439 let event = ext::enqueue_write_host_pipe_intel(
1440 self.queue,
1441 program,
1442 pipe_symbol,
1443 blocking_write,
1444 ptr,
1445 size,
1446 event_wait_list.len() as cl_uint,
1447 if !event_wait_list.is_empty() {
1448 event_wait_list.as_ptr()
1449 } else {
1450 ptr::null()
1451 },
1452 )?;
1453 Ok(Event::new(event))
1454 }
1455 }
1456
1457 pub fn context(&self) -> Result<cl_context> {
1458 Ok(isize::from(get_command_queue_info(self.queue, CL_QUEUE_CONTEXT)?) as cl_context)
1459 }
1460
1461 pub fn device(&self) -> Result<cl_device_id> {
1462 Ok(isize::from(get_command_queue_info(self.queue, CL_QUEUE_DEVICE)?) as cl_device_id)
1463 }
1464
1465 pub fn reference_count(&self) -> Result<cl_uint> {
1466 Ok(get_command_queue_info(self.queue, CL_QUEUE_REFERENCE_COUNT)?.into())
1467 }
1468
1469 pub fn properties(&self) -> Result<cl_ulong> {
1470 Ok(get_command_queue_info(self.queue, CL_QUEUE_PROPERTIES)?.into())
1471 }
1472
1473 pub fn size(&self) -> Result<cl_uint> {
1475 Ok(get_command_queue_info(self.queue, CL_QUEUE_SIZE)?.into())
1476 }
1477
1478 pub fn device_default(&self) -> Result<cl_device_id> {
1480 Ok(
1481 isize::from(get_command_queue_info(self.queue, CL_QUEUE_DEVICE_DEFAULT)?)
1482 as cl_device_id,
1483 )
1484 }
1485
1486 pub fn properties_array(&self) -> Result<Vec<cl_ulong>> {
1488 Ok(get_command_queue_info(self.queue, CL_QUEUE_PROPERTIES_ARRAY)?.into())
1489 }
1490
1491 pub fn get_data(&self, param_name: cl_command_queue_info) -> Result<Vec<u8>> {
1494 Ok(get_command_queue_data(self.queue, param_name)?)
1495 }
1496}
1497
1498#[cfg(test)]
1499mod tests {
1500 use super::*;
1501 use crate::context::Context;
1502 use crate::device::Device;
1503 use crate::platform::get_platforms;
1504 use cl3::device::CL_DEVICE_TYPE_GPU;
1505 use libc::intptr_t;
1506
1507 #[test]
1508 fn test_command_queue() {
1509 let platforms = get_platforms().unwrap();
1510 assert!(0 < platforms.len());
1511
1512 let platform = &platforms[0];
1514
1515 let devices = platform.get_devices(CL_DEVICE_TYPE_GPU).unwrap();
1516 assert!(0 < devices.len());
1517
1518 let device = Device::new(devices[0]);
1520 let context = Context::from_device(&device).unwrap();
1521
1522 let queue = unsafe {
1524 CommandQueue::create(
1525 &context,
1526 context.default_device(),
1527 CL_QUEUE_PROFILING_ENABLE,
1528 )
1529 .expect("CommandQueue::create failed")
1530 };
1531
1532 let value = queue.context().unwrap();
1533 assert!(context.get() == value);
1534
1535 let value = queue.device().unwrap();
1536 assert!(device.id() == value);
1537
1538 let value = queue.reference_count().unwrap();
1539 println!("queue.reference_count(): {}", value);
1540 assert_eq!(1, value);
1541
1542 let value = queue.properties().unwrap();
1543 println!("queue.properties(): {:X}", value);
1544 match queue.size() {
1548 Ok(value) => println!("queue.size(): {:?}", value),
1549 Err(e) => println!("OpenCL error, queue.size(): {}", e),
1550 }
1551
1552 match queue.device_default() {
1554 Ok(value) => println!("queue.device_default(): {:X}", value as intptr_t),
1555 Err(e) => println!("OpenCL error, queue.device_default(): {}", e),
1556 }
1557
1558 match queue.properties_array() {
1560 Ok(value) => println!("queue.properties_array(): {:?}", value),
1561 Err(e) => println!("OpenCL error, queue.properties_array(): {}", e),
1562 }
1563 }
1564
1565 #[test]
1566 fn test_command_queue_from_cl3() {
1567 let platforms = get_platforms().unwrap();
1568 assert!(0 < platforms.len());
1569
1570 let platform = &platforms[0];
1572
1573 let devices = platform.get_devices(CL_DEVICE_TYPE_GPU).unwrap();
1574 assert!(0 < devices.len());
1575
1576 let device = Device::new(devices[0]);
1578 let context = Context::from_device(&device).unwrap();
1579
1580 let command_queue = unsafe { cl3::command_queue::create_command_queue(context.get(), device.id(), 0) }.expect("Failed to create command queue");
1581 let command_queue = CommandQueue::wrap_cl_command_queue(command_queue, &device).expect("Failed to get max_item_working_size");
1582 assert!(command_queue.properties().unwrap() == 0, "Properties were set to 0 above")
1583 }
1584}