Skip to main content

opencl3/
command_queue.rs

1// Copyright (c) 2020-2024 Via Technology Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![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/// An OpenCL command-queue.
46///
47/// Operations on OpenCL memory and kernel objects are performed using a
48/// command-queue.
49#[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    /// Get the underlying OpenCL cl_command_queue.
84    pub const fn get(&self) -> cl_command_queue {
85        self.queue
86    }
87
88    /// Get the max_work_item_dimensions for the device that the underlying OpenCL
89    /// device.
90    pub const fn max_work_item_dimensions(&self) -> cl_uint {
91        self.max_work_item_dimensions
92    }
93
94    /// Create an OpenCL command-queue on a specific device.
95    ///
96    /// Queries the device the max_work_item_dimensions.  
97    /// Deprecated in CL_VERSION_2_0 by create_command_queue_with_properties.
98    ///
99    /// * `context` - a valid OpenCL context.
100    /// * `device_id` - a device or sub-device associated with context.
101    /// * `properties` - a list of properties for the command-queue, see
102    ///   [cl_command_queue_properties](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#legacy-queue-properties-table).
103    ///
104    /// returns a Result containing the new CommandQueue
105    /// or the error code from the OpenCL C API function.
106    ///
107    /// # Safety
108    ///
109    /// This is unsafe when a device is not a member of context.
110    #[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    /// Create an OpenCL command-queue on the context default device.  
137    /// Queries the device the max_work_item_dimensions.  
138    /// Deprecated in CL_VERSION_2_0 by create_command_queue_with_properties.
139    ///
140    /// * `context` - a valid OpenCL context.
141    /// * `properties` - a list of properties for the command-queue, see
142    ///   [cl_command_queue_properties](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#legacy-queue-properties-table).
143    ///
144    /// returns a Result containing the new CommandQueue
145    /// or the error code from the OpenCL C API function.
146    #[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    /// Create an OpenCL command-queue on a specific device.  
167    /// Queries the device the max_work_item_dimensions.  
168    /// CL_VERSION_2_0 onwards.
169    ///
170    /// * `context` - a valid OpenCL context.
171    /// * `device_id` - a device or sub-device associated with context.
172    /// * `properties` - a null terminated list of properties for the command-queue, see
173    ///   [cl_queue_properties](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#queue-properties-table).
174    ///
175    /// returns a Result containing the new CommandQueue
176    /// or the error code from the OpenCL C API function.
177    ///
178    /// # Safety
179    ///
180    /// This is unsafe when a device is not a member of context.
181    #[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    /// Create an OpenCL command-queue on the default device.  
215    /// Queries the device the max_work_item_dimensions.  
216    /// CL_VERSION_2_0 onwards.
217    ///
218    /// * `context` - a valid OpenCL context.
219    /// * `properties` - a null terminated list of properties for the command-queue, see
220    ///   [cl_queue_properties](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#queue-properties-table).
221    ///
222    /// returns a Result containing the new CommandQueue
223    /// or the error code from the OpenCL C API function.
224    #[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    /// Flush commands to a device.  
253    /// returns an empty Result or the error code from the OpenCL C API function.
254    pub fn flush(&self) -> Result<()> {
255        Ok(flush(self.queue)?)
256    }
257
258    /// Wait for completion of commands on a device.  
259    /// returns an empty Result or the error code from the OpenCL C API function.
260    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    /// CL_VERSION_2_0
1474    pub fn size(&self) -> Result<cl_uint> {
1475        Ok(get_command_queue_info(self.queue, CL_QUEUE_SIZE)?.into())
1476    }
1477
1478    /// CL_VERSION_2_1
1479    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    /// CL_VERSION_3_0
1487    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    /// Get data about an OpenCL command-queue.
1492    /// Calls clGetCommandQueueInfo to get the desired data about the command-queue.
1493    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        // Get the first platform
1513        let platform = &platforms[0];
1514
1515        let devices = platform.get_devices(CL_DEVICE_TYPE_GPU).unwrap();
1516        assert!(0 < devices.len());
1517
1518        // Get the first device
1519        let device = Device::new(devices[0]);
1520        let context = Context::from_device(&device).unwrap();
1521
1522        // Create a command_queue on the Context's device
1523        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        // assert_eq!(2, value);
1545
1546        // CL_VERSION_2_0 value
1547        match queue.size() {
1548            Ok(value) => println!("queue.size(): {:?}", value),
1549            Err(e) => println!("OpenCL error, queue.size(): {}", e),
1550        }
1551
1552        // CL_VERSION_2_1 value
1553        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        // CL_VERSION_3_0 value
1559        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        // Get the first platform
1571        let platform = &platforms[0];
1572
1573        let devices = platform.get_devices(CL_DEVICE_TYPE_GPU).unwrap();
1574        assert!(0 < devices.len());
1575
1576        // Get the first device
1577        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}