cl3/
command_queue.rs

1// Copyright (c) 2020-2025 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//! `OpenCL` Command Queue API.
16
17#![allow(unused_unsafe)]
18#![allow(non_camel_case_types, deprecated)]
19#![allow(
20    clippy::too_many_arguments,
21    clippy::not_unsafe_ptr_arg_deref,
22    clippy::missing_safety_doc
23)]
24
25pub use opencl_sys::{
26    CL_BLOCKING, CL_INVALID_VALUE, CL_NON_BLOCKING, CL_QUEUE_CONTEXT, CL_QUEUE_DEVICE,
27    CL_QUEUE_DEVICE_DEFAULT, CL_QUEUE_ON_DEVICE, CL_QUEUE_ON_DEVICE_DEFAULT,
28    CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, CL_QUEUE_PROFILING_ENABLE, CL_QUEUE_PROPERTIES,
29    CL_QUEUE_PROPERTIES_ARRAY, CL_QUEUE_REFERENCE_COUNT, CL_QUEUE_SIZE, CL_SUCCESS, cl_bool,
30    cl_command_queue, cl_command_queue_info, cl_command_queue_properties, cl_context, cl_device_id,
31    cl_event, cl_int, cl_kernel, cl_map_flags, cl_mem, cl_mem_migration_flags, cl_queue_properties,
32    cl_uint, cl_ulong,
33};
34
35use super::info_type::InfoType;
36use super::{api_info_size, api_info_value, api_info_vector};
37use libc::{c_void, intptr_t, size_t};
38use std::mem;
39use std::ptr;
40
41/// Create an `OpenCL` host or device command-queue on a specific device.
42///
43/// Calls `clCreateCommandQueue` to create an `OpenCL` context.
44/// Deprecated in `CL_VERSION_2_0` by `create_command_queue_with_properties`.
45///
46/// * `context` - a valid `OpenCL` context.
47/// * `device` - a device or sub-device associated with context.
48/// * `properties` - a list of properties for the command-queue, see
49///   [cl_command_queue_properties](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#legacy-queue-properties-table).
50///
51/// returns a Result containing the new `OpenCL` command-queue
52/// or the error code from the `OpenCL` C API function.
53///
54/// # Safety
55///
56/// This is unsafe when device is not a member of context.
57#[cfg_attr(
58    any(
59        feature = "CL_VERSION_2_0",
60        feature = "CL_VERSION_2_1",
61        feature = "CL_VERSION_2_2",
62        feature = "CL_VERSION_3_0"
63    ),
64    deprecated(
65        since = "0.1.0",
66        note = "From CL_VERSION_2_0 use create_command_queue_with_properties"
67    )
68)]
69#[inline]
70pub unsafe fn create_command_queue(
71    context: cl_context,
72    device: cl_device_id,
73    properties: cl_command_queue_properties,
74) -> Result<cl_command_queue, cl_int> {
75    let mut status: cl_int = CL_INVALID_VALUE;
76    let queue: cl_command_queue = cl_call!(clCreateCommandQueue(
77        context,
78        device,
79        properties,
80        &raw mut status
81    ));
82    if CL_SUCCESS == status {
83        Ok(queue)
84    } else {
85        Err(status)
86    }
87}
88
89/// Create an `OpenCL` host or device command-queue on a specific device.
90///
91/// Calls clCreateCommandQueueWithProperties to create an `OpenCL` context.
92/// `CL_VERSION_2_0` onwards.
93///
94/// * `context` - a valid `OpenCL` context.
95/// * `device` - a device or sub-device associated with context.
96/// * `properties` - a null terminated list of properties for the command-queue, see
97///   [cl_queue_properties](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#queue-properties-table).
98///
99/// returns a Result containing the new `OpenCL` command-queue
100/// or the error code from the `OpenCL` C API function.
101///
102/// # Safety
103///
104/// This is unsafe when device is not a member of context.
105#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
106#[inline]
107pub unsafe fn create_command_queue_with_properties(
108    context: cl_context,
109    device: cl_device_id,
110    properties: *const cl_queue_properties,
111) -> Result<cl_command_queue, cl_int> {
112    let mut status: cl_int = CL_INVALID_VALUE;
113    let queue: cl_command_queue = cl_call!(clCreateCommandQueueWithProperties(
114        context,
115        device,
116        properties,
117        &raw mut status
118    ));
119    if CL_SUCCESS == status {
120        Ok(queue)
121    } else {
122        Err(status)
123    }
124}
125
126/// Retain an `OpenCL` command-queue.
127/// Calls clRetainCommandQueue to increment the command-queue reference count.
128///
129/// * `command_queue` - the `OpenCL` command-queue.
130///
131/// returns an empty Result or the error code from the `OpenCL` C API function.
132///
133/// # Safety
134///
135/// This function is unsafe because it changes the `OpenCL` object reference count.
136#[inline]
137pub unsafe fn retain_command_queue(command_queue: cl_command_queue) -> Result<(), cl_int> {
138    let status: cl_int = cl_call!(clRetainCommandQueue(command_queue));
139    if CL_SUCCESS == status {
140        Ok(())
141    } else {
142        Err(status)
143    }
144}
145
146/// Release an `OpenCL` command-queue.
147/// Calls clReleaseCommandQueue to decrement the command-queue reference count.
148///
149///  * `command_queue` - the `OpenCL` command-queue.
150///
151/// returns an empty Result or the error code from the `OpenCL` C API function.
152///
153/// # Safety
154///
155/// This function is unsafe because it changes the `OpenCL` object reference count.
156#[inline]
157pub unsafe fn release_command_queue(command_queue: cl_command_queue) -> Result<(), cl_int> {
158    let status: cl_int = cl_call!(clReleaseCommandQueue(command_queue));
159    if CL_SUCCESS == status {
160        Ok(())
161    } else {
162        Err(status)
163    }
164}
165
166/// Get data about an `OpenCL` command-queue.
167/// Calls clGetCommandQueueInfo to get the desired data about the command-queue.
168pub fn get_command_queue_data(
169    command_queue: cl_command_queue,
170    param_name: cl_command_queue_info,
171) -> Result<Vec<u8>, cl_int> {
172    api_info_size!(get_size, clGetCommandQueueInfo);
173    let size = get_size(command_queue, param_name)?;
174    api_info_vector!(get_vector, u8, clGetCommandQueueInfo);
175    get_vector(command_queue, param_name, size)
176}
177
178/// Get specific information about an `OpenCL` command-queue.
179/// Calls `clGetCommandQueueInfo` to get the desired information about the command-queue.
180///
181/// * `command_queue` - the `OpenCL` command-queue.
182/// * `param_name` - the type of command-queue information being queried, see:
183///   [Command Queue Parameter](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#command-queue-param-table).
184///
185/// returns a Result containing the desired information in an `InfoType` enum
186/// or the error code from the `OpenCL` C API function.
187pub fn get_command_queue_info(
188    command_queue: cl_command_queue,
189    param_name: cl_command_queue_info,
190) -> Result<InfoType, cl_int> {
191    match param_name {
192        CL_QUEUE_REFERENCE_COUNT
193        | CL_QUEUE_SIZE // CL_VERSION_2_0
194         => {
195            api_info_value!(get_value, cl_uint, clGetCommandQueueInfo);
196            Ok(InfoType::Uint(get_value(command_queue, param_name)?))
197        }
198
199        CL_QUEUE_PROPERTIES => {
200            api_info_value!(get_value, cl_ulong, clGetCommandQueueInfo);
201            Ok(InfoType::Ulong(get_value(command_queue, param_name)?))
202        }
203
204        CL_QUEUE_CONTEXT
205        | CL_QUEUE_DEVICE
206        | CL_QUEUE_DEVICE_DEFAULT // CL_VERSION_2_1
207        => {
208            api_info_value!(get_value, intptr_t, clGetCommandQueueInfo);
209            Ok(InfoType::Ptr(get_value(command_queue, param_name)?))
210        }
211
212        CL_QUEUE_PROPERTIES_ARRAY // CL_VERSION_3_0
213        => {
214            api_info_size!(get_size, clGetCommandQueueInfo);
215            api_info_vector!(get_vec, cl_ulong, clGetCommandQueueInfo);
216            let size = get_size(command_queue, param_name)?;
217            Ok(InfoType::VecUlong(get_vec(
218                command_queue,
219                param_name,
220                size,
221            )?))
222        }
223
224        | _ => {
225            Ok(InfoType::VecUchar(get_command_queue_data(command_queue, param_name)?))
226        }
227    }
228}
229
230/// Flush commands to a device.
231/// Calls clFlush to flush an `OpenCL` command-queue.
232///
233/// * `command_queue` - the `OpenCL` command-queue.
234///
235/// returns an empty Result or the error code from the `OpenCL` C API function.
236#[inline]
237pub fn flush(command_queue: cl_command_queue) -> Result<(), cl_int> {
238    let status: cl_int = unsafe { cl_call!(clFlush(command_queue)) };
239    if CL_SUCCESS == status {
240        Ok(())
241    } else {
242        Err(status)
243    }
244}
245
246/// Wait for completion of commands on a device.
247/// Calls clFinish and blocks until all previously queued commands have completed.
248///
249/// * `command_queue` - the `OpenCL` command-queue.
250///
251/// returns an empty Result or the error code from the `OpenCL` C API function.
252#[inline]
253pub fn finish(command_queue: cl_command_queue) -> Result<(), cl_int> {
254    let status: cl_int = unsafe { cl_call!(clFinish(command_queue)) };
255    if CL_SUCCESS == status {
256        Ok(())
257    } else {
258        Err(status)
259    }
260}
261
262// `OpenCL` command-queue enqueue commands.
263
264#[inline]
265pub unsafe fn enqueue_read_buffer(
266    command_queue: cl_command_queue,
267    buffer: cl_mem,
268    blocking_read: cl_bool,
269    offset: size_t,
270    size: size_t,
271    ptr: *mut c_void,
272    num_events_in_wait_list: cl_uint,
273    event_wait_list: *const cl_event,
274) -> Result<cl_event, cl_int> {
275    let mut event: cl_event = ptr::null_mut();
276    let status: cl_int = cl_call!(clEnqueueReadBuffer(
277        command_queue,
278        buffer,
279        blocking_read,
280        offset,
281        size,
282        ptr,
283        num_events_in_wait_list,
284        event_wait_list,
285        &raw mut event,
286    ));
287    if CL_SUCCESS == status {
288        Ok(event)
289    } else {
290        Err(status)
291    }
292}
293
294#[inline]
295pub unsafe fn enqueue_read_buffer_rect(
296    command_queue: cl_command_queue,
297    buffer: cl_mem,
298    blocking_read: cl_bool,
299    buffer_origin: *const size_t,
300    host_origin: *const size_t,
301    region: *const size_t,
302    buffer_row_pitch: size_t,
303    buffer_slice_pitch: size_t,
304    host_row_pitch: size_t,
305    host_slice_pitch: size_t,
306    ptr: *mut c_void,
307    num_events_in_wait_list: cl_uint,
308    event_wait_list: *const cl_event,
309) -> Result<cl_event, cl_int> {
310    let mut event: cl_event = ptr::null_mut();
311    let status: cl_int = cl_call!(clEnqueueReadBufferRect(
312        command_queue,
313        buffer,
314        blocking_read,
315        buffer_origin,
316        host_origin,
317        region,
318        buffer_row_pitch,
319        buffer_slice_pitch,
320        host_row_pitch,
321        host_slice_pitch,
322        ptr,
323        num_events_in_wait_list,
324        event_wait_list,
325        &raw mut event,
326    ));
327    if CL_SUCCESS == status {
328        Ok(event)
329    } else {
330        Err(status)
331    }
332}
333
334#[inline]
335pub unsafe fn enqueue_write_buffer(
336    command_queue: cl_command_queue,
337    buffer: cl_mem,
338    blocking_write: cl_bool,
339    offset: size_t,
340    size: size_t,
341    ptr: *const c_void,
342    num_events_in_wait_list: cl_uint,
343    event_wait_list: *const cl_event,
344) -> Result<cl_event, cl_int> {
345    let mut event: cl_event = ptr::null_mut();
346    let status: cl_int = cl_call!(clEnqueueWriteBuffer(
347        command_queue,
348        buffer,
349        blocking_write,
350        offset,
351        size,
352        ptr,
353        num_events_in_wait_list,
354        event_wait_list,
355        &raw mut event,
356    ));
357    if CL_SUCCESS == status {
358        Ok(event)
359    } else {
360        Err(status)
361    }
362}
363
364#[inline]
365pub unsafe fn enqueue_write_buffer_rect(
366    command_queue: cl_command_queue,
367    buffer: cl_mem,
368    blocking_write: cl_bool,
369    buffer_origin: *const size_t,
370    host_origin: *const size_t,
371    region: *const size_t,
372    buffer_row_pitch: size_t,
373    buffer_slice_pitch: size_t,
374    host_row_pitch: size_t,
375    host_slice_pitch: size_t,
376    ptr: *const c_void,
377    num_events_in_wait_list: cl_uint,
378    event_wait_list: *const cl_event,
379) -> Result<cl_event, cl_int> {
380    let mut event: cl_event = ptr::null_mut();
381    let status: cl_int = cl_call!(clEnqueueWriteBufferRect(
382        command_queue,
383        buffer,
384        blocking_write,
385        buffer_origin,
386        host_origin,
387        region,
388        buffer_row_pitch,
389        buffer_slice_pitch,
390        host_row_pitch,
391        host_slice_pitch,
392        ptr,
393        num_events_in_wait_list,
394        event_wait_list,
395        &raw mut event,
396    ));
397    if CL_SUCCESS == status {
398        Ok(event)
399    } else {
400        Err(status)
401    }
402}
403
404#[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
405#[inline]
406pub unsafe fn enqueue_fill_buffer(
407    command_queue: cl_command_queue,
408    buffer: cl_mem,
409    pattern: *const c_void,
410    pattern_size: size_t,
411    offset: size_t,
412    size: size_t,
413    num_events_in_wait_list: cl_uint,
414    event_wait_list: *const cl_event,
415) -> Result<cl_event, cl_int> {
416    let mut event: cl_event = ptr::null_mut();
417    let status: cl_int = cl_call!(clEnqueueFillBuffer(
418        command_queue,
419        buffer,
420        pattern,
421        pattern_size,
422        offset,
423        size,
424        num_events_in_wait_list,
425        event_wait_list,
426        &raw mut event,
427    ));
428    if CL_SUCCESS == status {
429        Ok(event)
430    } else {
431        Err(status)
432    }
433}
434
435#[inline]
436pub unsafe fn enqueue_copy_buffer(
437    command_queue: cl_command_queue,
438    src_buffer: cl_mem,
439    dst_buffer: cl_mem,
440    src_offset: size_t,
441    dst_offset: size_t,
442    size: size_t,
443    num_events_in_wait_list: cl_uint,
444    event_wait_list: *const cl_event,
445) -> Result<cl_event, cl_int> {
446    let mut event: cl_event = ptr::null_mut();
447    let status: cl_int = cl_call!(clEnqueueCopyBuffer(
448        command_queue,
449        src_buffer,
450        dst_buffer,
451        src_offset,
452        dst_offset,
453        size,
454        num_events_in_wait_list,
455        event_wait_list,
456        &raw mut event,
457    ));
458    if CL_SUCCESS == status {
459        Ok(event)
460    } else {
461        Err(status)
462    }
463}
464
465#[inline]
466pub unsafe fn enqueue_copy_buffer_rect(
467    command_queue: cl_command_queue,
468    src_buffer: cl_mem,
469    dst_buffer: cl_mem,
470    src_origin: *const size_t,
471    dst_origin: *const size_t,
472    region: *const size_t,
473    src_row_pitch: size_t,
474    src_slice_pitch: size_t,
475    dst_row_pitch: size_t,
476    dst_slice_pitch: size_t,
477    num_events_in_wait_list: cl_uint,
478    event_wait_list: *const cl_event,
479) -> Result<cl_event, cl_int> {
480    let mut event: cl_event = ptr::null_mut();
481    let status: cl_int = cl_call!(clEnqueueCopyBufferRect(
482        command_queue,
483        src_buffer,
484        dst_buffer,
485        src_origin,
486        dst_origin,
487        region,
488        src_row_pitch,
489        src_slice_pitch,
490        dst_row_pitch,
491        dst_slice_pitch,
492        num_events_in_wait_list,
493        event_wait_list,
494        &raw mut event,
495    ));
496    if CL_SUCCESS == status {
497        Ok(event)
498    } else {
499        Err(status)
500    }
501}
502
503#[inline]
504pub unsafe fn enqueue_read_image(
505    command_queue: cl_command_queue,
506    image: cl_mem,
507    blocking_read: cl_bool,
508    origin: *const size_t,
509    region: *const size_t,
510    row_pitch: size_t,
511    slice_pitch: size_t,
512    ptr: *mut c_void,
513    num_events_in_wait_list: cl_uint,
514    event_wait_list: *const cl_event,
515) -> Result<cl_event, cl_int> {
516    let mut event: cl_event = ptr::null_mut();
517    let status: cl_int = cl_call!(clEnqueueReadImage(
518        command_queue,
519        image,
520        blocking_read,
521        origin,
522        region,
523        row_pitch,
524        slice_pitch,
525        ptr,
526        num_events_in_wait_list,
527        event_wait_list,
528        &raw mut event,
529    ));
530    if CL_SUCCESS == status {
531        Ok(event)
532    } else {
533        Err(status)
534    }
535}
536
537#[inline]
538pub unsafe fn enqueue_write_image(
539    command_queue: cl_command_queue,
540    image: cl_mem,
541    blocking_write: cl_bool,
542    origin: *const size_t,
543    region: *const size_t,
544    row_pitch: size_t,
545    slice_pitch: size_t,
546    ptr: *mut c_void,
547    num_events_in_wait_list: cl_uint,
548    event_wait_list: *const cl_event,
549) -> Result<cl_event, cl_int> {
550    let mut event: cl_event = ptr::null_mut();
551    let status: cl_int = cl_call!(clEnqueueWriteImage(
552        command_queue,
553        image,
554        blocking_write,
555        origin,
556        region,
557        row_pitch,
558        slice_pitch,
559        ptr,
560        num_events_in_wait_list,
561        event_wait_list,
562        &raw mut event,
563    ));
564    if CL_SUCCESS == status {
565        Ok(event)
566    } else {
567        Err(status)
568    }
569}
570
571#[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
572#[inline]
573pub unsafe fn enqueue_fill_image(
574    command_queue: cl_command_queue,
575    image: cl_mem,
576    fill_color: *const c_void,
577    origin: *const size_t,
578    region: *const size_t,
579    num_events_in_wait_list: cl_uint,
580    event_wait_list: *const cl_event,
581) -> Result<cl_event, cl_int> {
582    let mut event: cl_event = ptr::null_mut();
583    let status: cl_int = cl_call!(clEnqueueFillImage(
584        command_queue,
585        image,
586        fill_color,
587        origin,
588        region,
589        num_events_in_wait_list,
590        event_wait_list,
591        &raw mut event,
592    ));
593    if CL_SUCCESS == status {
594        Ok(event)
595    } else {
596        Err(status)
597    }
598}
599
600#[inline]
601pub unsafe fn enqueue_copy_image(
602    command_queue: cl_command_queue,
603    src_image: cl_mem,
604    dst_image: cl_mem,
605    src_origin: *const size_t,
606    dst_origin: *const size_t,
607    region: *const size_t,
608    num_events_in_wait_list: cl_uint,
609    event_wait_list: *const cl_event,
610) -> Result<cl_event, cl_int> {
611    let mut event: cl_event = ptr::null_mut();
612    let status: cl_int = cl_call!(clEnqueueCopyImage(
613        command_queue,
614        src_image,
615        dst_image,
616        src_origin,
617        dst_origin,
618        region,
619        num_events_in_wait_list,
620        event_wait_list,
621        &raw mut event,
622    ));
623    if CL_SUCCESS == status {
624        Ok(event)
625    } else {
626        Err(status)
627    }
628}
629
630#[inline]
631pub unsafe fn enqueue_copy_image_to_buffer(
632    command_queue: cl_command_queue,
633    src_image: cl_mem,
634    dst_buffer: cl_mem,
635    src_origin: *const size_t,
636    region: *const size_t,
637    dst_offset: size_t,
638    num_events_in_wait_list: cl_uint,
639    event_wait_list: *const cl_event,
640) -> Result<cl_event, cl_int> {
641    let mut event: cl_event = ptr::null_mut();
642    let status: cl_int = cl_call!(clEnqueueCopyImageToBuffer(
643        command_queue,
644        src_image,
645        dst_buffer,
646        src_origin,
647        region,
648        dst_offset,
649        num_events_in_wait_list,
650        event_wait_list,
651        &raw mut event,
652    ));
653    if CL_SUCCESS == status {
654        Ok(event)
655    } else {
656        Err(status)
657    }
658}
659
660#[inline]
661pub unsafe fn enqueue_copy_buffer_to_image(
662    command_queue: cl_command_queue,
663    src_buffer: cl_mem,
664    dst_image: cl_mem,
665    src_offset: size_t,
666    dst_origin: *const size_t,
667    region: *const size_t,
668    num_events_in_wait_list: cl_uint,
669    event_wait_list: *const cl_event,
670) -> Result<cl_event, cl_int> {
671    let mut event: cl_event = ptr::null_mut();
672    let status: cl_int = cl_call!(clEnqueueCopyBufferToImage(
673        command_queue,
674        src_buffer,
675        dst_image,
676        src_offset,
677        dst_origin,
678        region,
679        num_events_in_wait_list,
680        event_wait_list,
681        &raw mut event,
682    ));
683    if CL_SUCCESS == status {
684        Ok(event)
685    } else {
686        Err(status)
687    }
688}
689
690/// Note: returns event NOT pointer for consistency with other enqueue functions.
691/// The buffer pointer is returned in the `buffer_ptr` mutable reference.
692#[inline]
693pub unsafe fn enqueue_map_buffer(
694    command_queue: cl_command_queue,
695    buffer: cl_mem,
696    blocking_map: cl_bool,
697    map_flags: cl_map_flags,
698    offset: size_t,
699    size: size_t,
700    buffer_ptr: &mut cl_mem,
701    num_events_in_wait_list: cl_uint,
702    event_wait_list: *const cl_event,
703) -> Result<cl_event, cl_int> {
704    let mut event: cl_event = ptr::null_mut();
705    let mut status: cl_int = CL_INVALID_VALUE;
706    *buffer_ptr = cl_call!(clEnqueueMapBuffer(
707        command_queue,
708        buffer,
709        blocking_map,
710        map_flags,
711        offset,
712        size,
713        num_events_in_wait_list,
714        event_wait_list,
715        &raw mut event,
716        &raw mut status,
717    ));
718    if CL_SUCCESS == status {
719        Ok(event)
720    } else {
721        Err(status)
722    }
723}
724
725/// Note: returns event NOT pointer for consistency with other enqueue functions.
726/// The image pointer is returned in the `image_ptr` mutable reference.
727#[inline]
728pub unsafe fn enqueue_map_image(
729    command_queue: cl_command_queue,
730    image: cl_mem,
731    blocking_map: cl_bool,
732    map_flags: cl_map_flags,
733    origin: *const size_t,
734    region: *const size_t,
735    image_row_pitch: *mut size_t,
736    image_slice_pitch: *mut size_t,
737    image_ptr: &mut cl_mem,
738    num_events_in_wait_list: cl_uint,
739    event_wait_list: *const cl_event,
740) -> Result<*mut c_void, cl_int> {
741    let mut event: cl_event = ptr::null_mut();
742    let mut status: cl_int = CL_INVALID_VALUE;
743    *image_ptr = cl_call!(clEnqueueMapImage(
744        command_queue,
745        image,
746        blocking_map,
747        map_flags,
748        origin,
749        region,
750        image_row_pitch,
751        image_slice_pitch,
752        num_events_in_wait_list,
753        event_wait_list,
754        &raw mut event,
755        &raw mut status,
756    ));
757    if CL_SUCCESS == status {
758        Ok(event)
759    } else {
760        Err(status)
761    }
762}
763
764#[inline]
765pub unsafe fn enqueue_unmap_mem_object(
766    command_queue: cl_command_queue,
767    memobj: cl_mem,
768    mapped_ptr: *mut c_void,
769    num_events_in_wait_list: cl_uint,
770    event_wait_list: *const cl_event,
771) -> Result<cl_event, cl_int> {
772    let mut event: cl_event = ptr::null_mut();
773    let status: cl_int = cl_call!(clEnqueueUnmapMemObject(
774        command_queue,
775        memobj,
776        mapped_ptr,
777        num_events_in_wait_list,
778        event_wait_list,
779        &raw mut event,
780    ));
781    if CL_SUCCESS == status {
782        Ok(event)
783    } else {
784        Err(status)
785    }
786}
787
788#[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
789#[inline]
790pub unsafe fn enqueue_migrate_mem_object(
791    command_queue: cl_command_queue,
792    num_mem_objects: cl_uint,
793    mem_objects: *const cl_mem,
794    flags: cl_mem_migration_flags,
795    num_events_in_wait_list: cl_uint,
796    event_wait_list: *const cl_event,
797) -> Result<cl_event, cl_int> {
798    let mut event: cl_event = ptr::null_mut();
799    let status: cl_int = cl_call!(clEnqueueMigrateMemObjects(
800        command_queue,
801        num_mem_objects,
802        mem_objects,
803        flags,
804        num_events_in_wait_list,
805        event_wait_list,
806        &raw mut event,
807    ));
808    if CL_SUCCESS == status {
809        Ok(event)
810    } else {
811        Err(status)
812    }
813}
814
815#[inline]
816pub unsafe fn enqueue_nd_range_kernel(
817    command_queue: cl_command_queue,
818    kernel: cl_kernel,
819    work_dim: cl_uint,
820    global_work_offset: *const size_t,
821    global_work_dims: *const size_t,
822    local_work_dims: *const size_t,
823    num_events_in_wait_list: cl_uint,
824    event_wait_list: *const cl_event,
825) -> Result<cl_event, cl_int> {
826    let mut event: cl_event = ptr::null_mut();
827    let status: cl_int = cl_call!(clEnqueueNDRangeKernel(
828        command_queue,
829        kernel,
830        work_dim,
831        global_work_offset,
832        global_work_dims,
833        local_work_dims,
834        num_events_in_wait_list,
835        event_wait_list,
836        &raw mut event,
837    ));
838    if CL_SUCCESS == status {
839        Ok(event)
840    } else {
841        Err(status)
842    }
843}
844
845// Deprecated in CL_VERSION_2_0
846#[cfg_attr(
847    any(
848        feature = "CL_VERSION_2_0",
849        feature = "CL_VERSION_2_1",
850        feature = "CL_VERSION_2_2",
851        feature = "CL_VERSION_3_0"
852    ),
853    deprecated(
854        since = "0.1.0",
855        note = "From CL_VERSION_2_0 use enqueue_nd_range_kernel"
856    )
857)]
858#[inline]
859pub unsafe fn enqueue_task(
860    command_queue: cl_command_queue,
861    kernel: cl_kernel,
862    num_events_in_wait_list: cl_uint,
863    event_wait_list: *const cl_event,
864) -> Result<cl_event, cl_int> {
865    let mut event: cl_event = ptr::null_mut();
866    let status: cl_int = cl_call!(clEnqueueTask(
867        command_queue,
868        kernel,
869        num_events_in_wait_list,
870        event_wait_list,
871        &raw mut event,
872    ));
873    if CL_SUCCESS == status {
874        Ok(event)
875    } else {
876        Err(status)
877    }
878}
879
880#[inline]
881pub unsafe fn enqueue_native_kernel(
882    command_queue: cl_command_queue,
883    user_func: Option<unsafe extern "C" fn(*mut c_void)>,
884    args: *mut c_void,
885    cb_args: size_t,
886    num_mem_objects: cl_uint,
887    mem_list: *const cl_mem,
888    args_mem_loc: *const *const c_void,
889    num_events_in_wait_list: cl_uint,
890    event_wait_list: *const cl_event,
891) -> Result<cl_event, cl_int> {
892    let mut event: cl_event = ptr::null_mut();
893    let status: cl_int = cl_call!(clEnqueueNativeKernel(
894        command_queue,
895        user_func,
896        args,
897        cb_args,
898        num_mem_objects,
899        mem_list,
900        args_mem_loc,
901        num_events_in_wait_list,
902        event_wait_list,
903        &raw mut event,
904    ));
905    if CL_SUCCESS == status {
906        Ok(event)
907    } else {
908        Err(status)
909    }
910}
911
912#[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
913#[inline]
914pub unsafe fn enqueue_marker_with_wait_list(
915    command_queue: cl_command_queue,
916    num_events_in_wait_list: cl_uint,
917    event_wait_list: *const cl_event,
918) -> Result<cl_event, cl_int> {
919    let mut event: cl_event = ptr::null_mut();
920    let status: cl_int = cl_call!(clEnqueueMarkerWithWaitList(
921        command_queue,
922        num_events_in_wait_list,
923        event_wait_list,
924        &raw mut event,
925    ));
926    if CL_SUCCESS == status {
927        Ok(event)
928    } else {
929        Err(status)
930    }
931}
932
933#[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
934#[inline]
935pub unsafe fn enqueue_barrier_with_wait_list(
936    command_queue: cl_command_queue,
937    num_events_in_wait_list: cl_uint,
938    event_wait_list: *const cl_event,
939) -> Result<cl_event, cl_int> {
940    let mut event: cl_event = ptr::null_mut();
941    let status: cl_int = cl_call!(clEnqueueBarrierWithWaitList(
942        command_queue,
943        num_events_in_wait_list,
944        event_wait_list,
945        &raw mut event,
946    ));
947    if CL_SUCCESS == status {
948        Ok(event)
949    } else {
950        Err(status)
951    }
952}
953
954#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
955#[inline]
956pub unsafe fn enqueue_svm_free(
957    command_queue: cl_command_queue,
958    num_svm_pointers: cl_uint,
959    svm_pointers: *const *const c_void,
960    pfn_free_func: Option<
961        unsafe extern "C" fn(
962            queue: cl_command_queue,
963            num_svm_pointers: cl_uint,
964            svm_pointers: *mut *mut c_void,
965            user_data: *mut c_void,
966        ),
967    >,
968    user_data: *mut c_void,
969    num_events_in_wait_list: cl_uint,
970    event_wait_list: *const cl_event,
971) -> Result<cl_event, cl_int> {
972    let mut event: cl_event = ptr::null_mut();
973    let status: cl_int = cl_call!(clEnqueueSVMFree(
974        command_queue,
975        num_svm_pointers,
976        svm_pointers,
977        pfn_free_func,
978        user_data,
979        num_events_in_wait_list,
980        event_wait_list,
981        &raw mut event,
982    ));
983    if CL_SUCCESS == status {
984        Ok(event)
985    } else {
986        Err(status)
987    }
988}
989
990#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
991#[inline]
992pub unsafe fn enqueue_svm_mem_cpy(
993    command_queue: cl_command_queue,
994    blocking_copy: cl_bool,
995    dst_ptr: *mut c_void,
996    src_ptr: *const c_void,
997    size: size_t,
998    num_events_in_wait_list: cl_uint,
999    event_wait_list: *const cl_event,
1000) -> Result<cl_event, cl_int> {
1001    let mut event: cl_event = ptr::null_mut();
1002    let status: cl_int = cl_call!(clEnqueueSVMMemcpy(
1003        command_queue,
1004        blocking_copy,
1005        dst_ptr,
1006        src_ptr,
1007        size,
1008        num_events_in_wait_list,
1009        event_wait_list,
1010        &raw mut event,
1011    ));
1012    if CL_SUCCESS == status {
1013        Ok(event)
1014    } else {
1015        Err(status)
1016    }
1017}
1018
1019#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
1020#[inline]
1021pub unsafe fn enqueue_svm_mem_fill(
1022    command_queue: cl_command_queue,
1023    svm_ptr: *mut c_void,
1024    pattern: *const c_void,
1025    pattern_size: size_t,
1026    size: size_t,
1027    num_events_in_wait_list: cl_uint,
1028    event_wait_list: *const cl_event,
1029) -> Result<cl_event, cl_int> {
1030    let mut event: cl_event = ptr::null_mut();
1031    let status: cl_int = cl_call!(clEnqueueSVMMemFill(
1032        command_queue,
1033        svm_ptr,
1034        pattern,
1035        pattern_size,
1036        size,
1037        num_events_in_wait_list,
1038        event_wait_list,
1039        &raw mut event,
1040    ));
1041    if CL_SUCCESS == status {
1042        Ok(event)
1043    } else {
1044        Err(status)
1045    }
1046}
1047
1048#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
1049#[inline]
1050pub unsafe fn enqueue_svm_map(
1051    command_queue: cl_command_queue,
1052    blocking_map: cl_bool,
1053    flags: cl_map_flags,
1054    svm_ptr: *mut c_void,
1055    size: size_t,
1056    num_events_in_wait_list: cl_uint,
1057    event_wait_list: *const cl_event,
1058) -> Result<cl_event, cl_int> {
1059    let mut event: cl_event = ptr::null_mut();
1060    let status: cl_int = cl_call!(clEnqueueSVMMap(
1061        command_queue,
1062        blocking_map,
1063        flags,
1064        svm_ptr,
1065        size,
1066        num_events_in_wait_list,
1067        event_wait_list,
1068        &raw mut event,
1069    ));
1070    if CL_SUCCESS == status {
1071        Ok(event)
1072    } else {
1073        Err(status)
1074    }
1075}
1076
1077#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
1078#[inline]
1079pub unsafe fn enqueue_svm_unmap(
1080    command_queue: cl_command_queue,
1081    svm_ptr: *mut c_void,
1082    num_events_in_wait_list: cl_uint,
1083    event_wait_list: *const cl_event,
1084) -> Result<cl_event, cl_int> {
1085    let mut event: cl_event = ptr::null_mut();
1086    let status: cl_int = cl_call!(clEnqueueSVMUnmap(
1087        command_queue,
1088        svm_ptr,
1089        num_events_in_wait_list,
1090        event_wait_list,
1091        &raw mut event,
1092    ));
1093    if CL_SUCCESS == status {
1094        Ok(event)
1095    } else {
1096        Err(status)
1097    }
1098}
1099
1100#[cfg(any(feature = "CL_VERSION_2_1", feature = "dynamic"))]
1101#[inline]
1102pub unsafe fn enqueue_svm_migrate_mem(
1103    command_queue: cl_command_queue,
1104    num_svm_pointers: cl_uint,
1105    svm_pointers: *const *const c_void,
1106    sizes: *const size_t,
1107    flags: cl_mem_migration_flags,
1108    num_events_in_wait_list: cl_uint,
1109    event_wait_list: *const cl_event,
1110) -> Result<cl_event, cl_int> {
1111    let mut event: cl_event = ptr::null_mut();
1112    let status: cl_int = cl_call!(clEnqueueSVMMigrateMem(
1113        command_queue,
1114        num_svm_pointers,
1115        svm_pointers,
1116        sizes,
1117        flags,
1118        num_events_in_wait_list,
1119        event_wait_list,
1120        &raw mut event,
1121    ));
1122    if CL_SUCCESS == status {
1123        Ok(event)
1124    } else {
1125        Err(status)
1126    }
1127}
1128
1129#[cfg(test)]
1130mod tests {
1131    use super::*;
1132    use crate::context::{create_context, release_context};
1133    use crate::device::{CL_DEVICE_TYPE_GPU, get_device_ids};
1134    use crate::error_codes::error_text;
1135    use crate::platform::get_platform_ids;
1136
1137    #[test]
1138    fn test_command_queue() {
1139        let platform_ids = get_platform_ids().unwrap();
1140
1141        // Choose the first platform
1142        let platform_id = platform_ids[0];
1143
1144        let device_ids = get_device_ids(platform_id, CL_DEVICE_TYPE_GPU).unwrap();
1145        assert!(0 < device_ids.len());
1146
1147        let device_id = device_ids[0];
1148
1149        let context = create_context(&device_ids, ptr::null(), None, ptr::null_mut());
1150        let context = context.unwrap();
1151
1152        let queue = unsafe {
1153            create_command_queue(
1154                context,
1155                device_id,
1156                CL_QUEUE_PROFILING_ENABLE | CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE,
1157            )
1158            .unwrap()
1159        };
1160
1161        let value = get_command_queue_info(queue, CL_QUEUE_CONTEXT).unwrap();
1162        let value = intptr_t::from(value);
1163        println!("CL_QUEUE_CONTEXT: {:X}", value);
1164        assert_eq!(context, value as cl_context);
1165
1166        let value = get_command_queue_info(queue, CL_QUEUE_DEVICE).unwrap();
1167        let value = intptr_t::from(value);
1168        println!("CL_QUEUE_DEVICE: {:X}", value);
1169        assert_eq!(device_id, value as cl_device_id);
1170
1171        let value = get_command_queue_info(queue, CL_QUEUE_REFERENCE_COUNT).unwrap();
1172        let value = cl_uint::from(value);
1173        println!("CL_QUEUE_REFERENCE_COUNT: {}", value);
1174        assert_eq!(1, value);
1175
1176        let value = get_command_queue_info(queue, CL_QUEUE_PROPERTIES).unwrap();
1177        let value = cl_ulong::from(value);
1178        println!("CL_QUEUE_PROPERTIES: {}", value);
1179
1180        // CL_VERSION_2_0 value
1181        match get_command_queue_info(queue, CL_QUEUE_SIZE) {
1182            Ok(value) => {
1183                let value = cl_uint::from(value);
1184                println!("CL_QUEUE_SIZE: {}", value);
1185            }
1186            Err(e) => println!("OpenCL error, CL_QUEUE_SIZE: {}", error_text(e)),
1187        };
1188
1189        // CL_VERSION_2_1 value
1190        match get_command_queue_info(queue, CL_QUEUE_DEVICE_DEFAULT) {
1191            Ok(value) => {
1192                let value = intptr_t::from(value);
1193                println!("CL_QUEUE_DEVICE_DEFAULT: {:X}", value);
1194            }
1195            Err(e) => println!("OpenCL error, CL_QUEUE_DEVICE_DEFAULT: {}", error_text(e)),
1196        };
1197
1198        // CL_VERSION_3_0 value
1199        match get_command_queue_info(queue, CL_QUEUE_PROPERTIES_ARRAY) {
1200            Ok(value) => {
1201                let value = Vec::<cl_ulong>::from(value);
1202                println!("CL_QUEUE_PROPERTIES_ARRAY: {}", value.len());
1203            }
1204            Err(e) => println!("OpenCL error, CL_QUEUE_PROPERTIES_ARRAY: {}", error_text(e)),
1205        };
1206
1207        unsafe {
1208            release_command_queue(queue).unwrap();
1209            release_context(context).unwrap();
1210        }
1211    }
1212}