cl3/
memory.rs

1// Copyright (c) 2020-2025 Via Technology Ltd. All Rights Reserved.
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` Memory Object API.
16
17#![allow(unused_unsafe)]
18#![allow(non_camel_case_types)]
19#![allow(clippy::not_unsafe_ptr_arg_deref)]
20
21pub use opencl_sys::{
22    CL_A, CL_ABGR, CL_ADDRESS_CLAMP, CL_ADDRESS_CLAMP_TO_EDGE, CL_ADDRESS_MIRRORED_REPEAT,
23    CL_ADDRESS_NONE, CL_ADDRESS_REPEAT, CL_ARGB, CL_BGRA, CL_BUFFER_CREATE_TYPE_REGION, CL_DEPTH,
24    CL_FALSE, CL_FILTER_LINEAR, CL_FILTER_NEAREST, CL_FLOAT, CL_HALF_FLOAT, CL_IMAGE_ARRAY_SIZE,
25    CL_IMAGE_BUFFER, CL_IMAGE_DEPTH, CL_IMAGE_ELEMENT_SIZE, CL_IMAGE_FORMAT, CL_IMAGE_HEIGHT,
26    CL_IMAGE_NUM_MIP_LEVELS, CL_IMAGE_NUM_SAMPLES, CL_IMAGE_ROW_PITCH, CL_IMAGE_SLICE_PITCH,
27    CL_IMAGE_WIDTH, CL_INTENSITY, CL_INVALID_VALUE, CL_LUMINANCE, CL_MAP_READ, CL_MAP_WRITE,
28    CL_MAP_WRITE_INVALIDATE_REGION, CL_MEM_ALLOC_HOST_PTR, CL_MEM_ASSOCIATED_MEMOBJECT,
29    CL_MEM_CONTEXT, CL_MEM_COPY_HOST_PTR, CL_MEM_FLAGS, CL_MEM_HOST_NO_ACCESS, CL_MEM_HOST_PTR,
30    CL_MEM_HOST_READ_ONLY, CL_MEM_HOST_WRITE_ONLY, CL_MEM_KERNEL_READ_AND_WRITE, CL_MEM_MAP_COUNT,
31    CL_MEM_OBJECT_BUFFER, CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE1D_ARRAY,
32    CL_MEM_OBJECT_IMAGE1D_BUFFER, CL_MEM_OBJECT_IMAGE2D, CL_MEM_OBJECT_IMAGE2D_ARRAY,
33    CL_MEM_OBJECT_IMAGE3D, CL_MEM_OBJECT_PIPE, CL_MEM_OFFSET, CL_MEM_PROPERTIES, CL_MEM_READ_ONLY,
34    CL_MEM_READ_WRITE, CL_MEM_REFERENCE_COUNT, CL_MEM_SIZE, CL_MEM_SVM_ATOMICS,
35    CL_MEM_SVM_FINE_GRAIN_BUFFER, CL_MEM_TYPE, CL_MEM_USE_HOST_PTR, CL_MEM_USES_SVM_POINTER,
36    CL_MEM_WRITE_ONLY, CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED, CL_MIGRATE_MEM_OBJECT_HOST,
37    CL_PIPE_MAX_PACKETS, CL_PIPE_PACKET_SIZE, CL_PIPE_PROPERTIES, CL_R, CL_RA, CL_RG, CL_RGB,
38    CL_RGBA, CL_RGBx, CL_RGx, CL_Rx, CL_SIGNED_INT8, CL_SIGNED_INT16, CL_SIGNED_INT32,
39    CL_SNORM_INT8, CL_SNORM_INT16, CL_SUCCESS, CL_TRUE, CL_UNORM_INT_101010, CL_UNORM_INT_101010_2,
40    CL_UNORM_INT8, CL_UNORM_INT16, CL_UNORM_SHORT_555, CL_UNORM_SHORT_565, CL_UNSIGNED_INT8,
41    CL_UNSIGNED_INT16, CL_UNSIGNED_INT32, CL_sRGB, CL_sRGBA, CL_sRGBx, cl_buffer_create_type,
42    cl_buffer_region, cl_context, cl_image_desc, cl_image_format, cl_image_info, cl_int, cl_mem,
43    cl_mem_flags, cl_mem_info, cl_mem_object_type, cl_mem_properties, cl_pipe_info,
44    cl_svm_mem_flags, cl_uint, cl_ulong,
45};
46
47use super::info_type::InfoType;
48use super::{api_info_size, api_info_value, api_info_vector};
49use libc::{c_void, intptr_t, size_t};
50use std::mem;
51use std::ptr;
52
53/// Create an `OpenCL` buffer object for a `context`.
54/// Calls `clCreateBuffer` to create an `OpenCL` buffer object.
55///
56/// * `context` - a valid `OpenCL` context.
57/// * `flags` - a bit-field used to specify allocation and usage information
58///   about the image memory object being created, see:
59///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
60/// * `size` - the size in bytes of the buffer memory object to be allocated.
61/// * `host_ptr` - a pointer to the buffer data that may already be allocated
62///   by the application.
63///
64/// returns a Result containing the new `OpenCL` buffer object
65/// or the error code from the `OpenCL` C API function.
66///
67/// # Safety
68///
69/// This function is unsafe because incorrect `flags` can cause undefined behaviour.
70#[inline]
71pub unsafe fn create_buffer(
72    context: cl_context,
73    flags: cl_mem_flags,
74    size: size_t,
75    host_ptr: *mut c_void,
76) -> Result<cl_mem, cl_int> {
77    let mut status: cl_int = CL_INVALID_VALUE;
78    let mem: cl_mem = cl_call!(clCreateBuffer(
79        context,
80        flags,
81        size,
82        host_ptr,
83        &raw mut status
84    ));
85    if CL_SUCCESS == status {
86        Ok(mem)
87    } else {
88        Err(status)
89    }
90}
91
92/// Create an new `OpenCL` buffer object from an existing buffer object.
93/// Calls `clCreateSubBuffer` to create an `OpenCL` sub-buffer object.
94///
95/// * `buffer` - a valid `OpenCL` buffer.
96/// * `flags` - a bit-field used to specify allocation and usage information
97///   about the sub-buffer memory object being created, see:
98///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
99/// * `buffer_create_type`,`buffer_create_info` - describe the type of
100///   buffer object to be created, see:
101///   [SubBuffer Attributes](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#subbuffer-create-info-table).
102///
103/// returns a Result containing the new `OpenCL` buffer object
104/// or the error code from the `OpenCL` C API function.
105///
106/// # Safety
107///
108/// This function is unsafe because incorrect `flags` can cause undefined behaviour.
109#[inline]
110pub unsafe fn create_sub_buffer(
111    buffer: cl_mem,
112    flags: cl_mem_flags,
113    buffer_create_type: cl_buffer_create_type,
114    buffer_create_info: *const c_void,
115) -> Result<cl_mem, cl_int> {
116    let mut status: cl_int = CL_INVALID_VALUE;
117    let mem: cl_mem = cl_call!(clCreateSubBuffer(
118        buffer,
119        flags,
120        buffer_create_type,
121        buffer_create_info,
122        &raw mut status,
123    ));
124    if CL_SUCCESS == status {
125        Ok(mem)
126    } else {
127        Err(status)
128    }
129}
130
131/// Create an `OpenCL` image object for a `context`.
132/// Calls `clCreateImage` to create an `OpenCL` image object.
133///
134/// * `context` - a valid `OpenCL` context.
135/// * `flags` - a bit-field used to specify allocation and usage information
136///   about the image memory object being created, see:
137///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
138/// * `image_format` - a pointer to a structure that describes format properties
139///   of the image to be allocated.
140/// * `image_desc` - a pointer to a structure that describes type and dimensions
141///   of the image to be allocated.
142/// * `host_ptr` - a pointer to the image data that may already be allocated
143///   by the application.
144///
145/// returns a Result containing the new `OpenCL` image object
146/// or the error code from the `OpenCL` C API function.
147///
148/// # Safety
149///
150/// This function is unsafe because incorrect `flags` can cause undefined behaviour.
151#[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
152#[inline]
153pub unsafe fn create_image(
154    context: cl_context,
155    flags: cl_mem_flags,
156    image_format: *const cl_image_format,
157    image_desc: *const cl_image_desc,
158    host_ptr: *mut c_void,
159) -> Result<cl_mem, cl_int> {
160    let mut status: cl_int = CL_INVALID_VALUE;
161    let mem: cl_mem = cl_call!(clCreateImage(
162        context,
163        flags,
164        image_format,
165        image_desc,
166        host_ptr,
167        &raw mut status,
168    ));
169    if CL_SUCCESS == status {
170        Ok(mem)
171    } else {
172        Err(status)
173    }
174}
175
176/// Create an `OpenCL` pipe object for a context.
177/// Calls `clCreatePipe` to create an `OpenCL` pipe object.
178/// `CL_VERSION_2_0`
179///
180/// * `context` - a valid `OpenCL` context.
181/// * `flags` - a bit-field used to specify allocation and usage information
182///   about the image memory object being created, see:
183///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
184/// * `pipe_packet_size` - the size in bytes of a pipe packet.
185/// * `pipe_max_packets` -the maximum number of packets the pipe can hold.
186/// * `properties` - currently must be NULL.
187///
188/// returns a Result containing the new `OpenCL` pipe object
189/// or the error code from the `OpenCL` C API function.
190///
191/// # Safety
192///
193/// This function is unsafe because incorrect `flags` can cause undefined behaviour.
194#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
195#[inline]
196pub unsafe fn create_pipe(
197    context: cl_context,
198    flags: cl_mem_flags,
199    pipe_packet_size: cl_uint,
200    pipe_max_packets: cl_uint,
201    // properties: *const cl_pipe_properties,
202) -> Result<cl_mem, cl_int> {
203    let mut status: cl_int = CL_INVALID_VALUE;
204    let mem: cl_mem = cl_call!(clCreatePipe(
205        context,
206        flags,
207        pipe_packet_size,
208        pipe_max_packets,
209        ptr::null(),
210        &raw mut status,
211    ));
212    if CL_SUCCESS == status {
213        Ok(mem)
214    } else {
215        Err(status)
216    }
217}
218
219/// Create an `OpenCL` buffer object for a context.
220/// Calls `clCreateBufferWithProperties` to create an `OpenCL` buffer object.
221/// `CL_VERSION_3_0`
222///
223/// * `context` - a valid `OpenCL` context.
224/// * `properties` - an optional null terminated list of properties.
225/// * `flags` - a bit-field used to specify allocation and usage information
226///   about the image memory object being created, see:
227///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
228/// * `size` - the size in bytes of the buffer memory object to be allocated.
229/// * `host_ptr` - a pointer to the buffer data that may already be allocated
230///   by the application.
231///
232/// returns a Result containing the new `OpenCL` buffer object
233/// or the error code from the `OpenCL` C API function.
234///
235/// # Safety
236///
237/// This function is unsafe because incorrect `flags` can cause undefined behaviour.
238#[cfg(any(feature = "CL_VERSION_3_0", feature = "dynamic"))]
239#[inline]
240pub unsafe fn create_buffer_with_properties(
241    context: cl_context,
242    properties: *const cl_mem_properties,
243    flags: cl_mem_flags,
244    size: size_t,
245    host_ptr: *mut c_void,
246) -> Result<cl_mem, cl_int> {
247    let mut status: cl_int = CL_INVALID_VALUE;
248    let mem: cl_mem = cl_call!(clCreateBufferWithProperties(
249        context,
250        properties,
251        flags,
252        size,
253        host_ptr,
254        &raw mut status
255    ));
256    if CL_SUCCESS == status {
257        Ok(mem)
258    } else {
259        Err(status)
260    }
261}
262
263/// Create an `OpenCL` image object for a context.
264/// Calls `clCreateImage` to create an `OpenCL` image object.
265/// `CL_VERSION_3_0`
266///
267/// * `context` - a valid `OpenCL` context.
268/// * `properties` - an optional null terminated list of properties.
269/// * `flags` - a bit-field used to specify allocation and usage information
270///   about the image memory object being created, see:
271///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
272/// * `image_format` - a pointer to a structure that describes format properties
273///   of the image to be allocated.
274/// * `image_desc` - a pointer to a structure that describes type and dimensions
275///   of the image to be allocated.
276/// * `host_ptr` - a pointer to the image data that may already be allocated
277///   by the application.
278///
279/// returns a Result containing the new `OpenCL` image object
280/// or the error code from the `OpenCL` C API function.
281///
282/// # Safety
283///
284/// This function is unsafe because incorrect `flags` can cause undefined behaviour.
285#[inline]
286#[cfg(any(feature = "CL_VERSION_3_0", feature = "dynamic"))]
287pub unsafe fn create_image_with_properties(
288    context: cl_context,
289    properties: *const cl_mem_properties,
290    flags: cl_mem_flags,
291    image_format: *const cl_image_format,
292    image_desc: *const cl_image_desc,
293    host_ptr: *mut c_void,
294) -> Result<cl_mem, cl_int> {
295    let mut status: cl_int = CL_INVALID_VALUE;
296    let mem: cl_mem = cl_call!(clCreateImageWithProperties(
297        context,
298        properties,
299        flags,
300        image_format,
301        image_desc,
302        host_ptr,
303        &raw mut status,
304    ));
305    if CL_SUCCESS == status {
306        Ok(mem)
307    } else {
308        Err(status)
309    }
310}
311
312/// Retain an `OpenCL` memory object.
313/// Calls `clRetainMemObject` to increment the memory object reference count.
314///
315/// * `memobj` - the `OpenCL` memory object.
316///
317/// returns an empty Result or the error code from the `OpenCL` C API function.
318///
319/// # Safety
320///
321/// This function is unsafe because it changes the `OpenCL` object reference count.
322#[inline]
323pub unsafe fn retain_mem_object(memobj: cl_mem) -> Result<(), cl_int> {
324    let status: cl_int = cl_call!(clRetainMemObject(memobj));
325    if CL_SUCCESS == status {
326        Ok(())
327    } else {
328        Err(status)
329    }
330}
331
332/// Release an `OpenCL` memory object.
333/// Calls `clReleaseMemObject` to decrement the memory object reference count.
334///
335/// * `memobj` - the `OpenCL` memory object.
336///
337/// returns an empty Result or the error code from the `OpenCL` C API function.
338///
339/// # Safety
340///
341/// This function is unsafe because it changes the `OpenCL` object reference count.
342#[inline]
343pub unsafe fn release_mem_object(memobj: cl_mem) -> Result<(), cl_int> {
344    let status: cl_int = cl_call!(clReleaseMemObject(memobj));
345    if CL_SUCCESS == status {
346        Ok(())
347    } else {
348        Err(status)
349    }
350}
351
352fn count_supported_image_formats(
353    context: cl_context,
354    flags: cl_mem_flags,
355    image_type: cl_mem_object_type,
356) -> Result<cl_uint, cl_int> {
357    let mut count: cl_uint = 0;
358    let status: cl_int = unsafe {
359        cl_call!(clGetSupportedImageFormats(
360            context,
361            flags,
362            image_type,
363            0,
364            ptr::null_mut(),
365            &raw mut count
366        ))
367    };
368    if CL_SUCCESS == status {
369        Ok(count)
370    } else {
371        Err(status)
372    }
373}
374
375/// Get the list of image formats supported by an `OpenCL` implementation for a
376/// specified context, image type, and allocation information.
377///
378/// Calls `clGetSupportedImageFormats` to get the desired information about the program.
379///
380/// * `context` - a valid `OpenCL` context on which the image object(s) will be created.
381/// * `flags` - a bit-field used to specify allocation and usage information
382///   about the image memory object being created, see:
383///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
384/// * `image_type` - describes the image type.
385///
386/// returns a Result containing the desired information in an `InfoType` enum
387/// or the error code from the `OpenCL` C API function.
388#[inline]
389pub fn get_supported_image_formats(
390    context: cl_context,
391    flags: cl_mem_flags,
392    image_type: cl_mem_object_type,
393) -> Result<Vec<cl_image_format>, cl_int> {
394    let count: cl_uint = count_supported_image_formats(context, flags, image_type)?;
395    let mut image_formats: Vec<cl_image_format> = Vec::with_capacity(count as usize);
396    let status: cl_int = unsafe {
397        image_formats.set_len(count as usize);
398        cl_call!(clGetSupportedImageFormats(
399            context,
400            flags,
401            image_type,
402            count,
403            image_formats.as_mut_ptr(),
404            ptr::null_mut(),
405        ))
406    };
407    if CL_SUCCESS == status {
408        Ok(image_formats)
409    } else {
410        Err(status)
411    }
412}
413
414/// Get data about an `OpenCL` memory object.
415/// Calls `clGetMemObjectInfo` to get the desired data about the memory object.
416pub fn get_mem_object_data(memobj: cl_mem, param_name: cl_mem_info) -> Result<Vec<u8>, cl_int> {
417    api_info_size!(get_size, clGetMemObjectInfo);
418    let size = get_size(memobj, param_name)?;
419    api_info_vector!(get_vector, u8, clGetMemObjectInfo);
420    get_vector(memobj, param_name, size)
421}
422
423/// Get information common to all `OpenCL` memory objects (buffer and image objects).
424/// Calls `clGetMemObjectInfo` to get the desired information about the memory objects.
425///
426/// * `memobj` - the `OpenCL` memory objects.
427/// * `param_name` - the type of memory object information being queried, see:
428///   [Memory Object Info](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#mem-info-table).
429///
430/// returns a Result containing the desired information in an `InfoType` enum
431/// or the error code from the `OpenCL` C API function.
432pub fn get_mem_object_info(memobj: cl_mem, param_name: cl_mem_info) -> Result<InfoType, cl_int> {
433    match param_name {
434        CL_MEM_TYPE
435        | CL_MEM_MAP_COUNT
436        | CL_MEM_REFERENCE_COUNT
437        | CL_MEM_USES_SVM_POINTER // CL_VERSION_2_0
438        => {
439            api_info_value!(get_value, cl_uint, clGetMemObjectInfo);
440            Ok(InfoType::Uint(get_value(memobj, param_name)?))
441        }
442
443        CL_MEM_FLAGS => {
444            api_info_value!(get_value, cl_ulong, clGetMemObjectInfo);
445            Ok(InfoType::Ulong(get_value(memobj, param_name)?))
446        }
447
448        CL_MEM_SIZE | CL_MEM_OFFSET => {
449            api_info_value!(get_value, size_t, clGetMemObjectInfo);
450            Ok(InfoType::Size(get_value(memobj, param_name)?))
451        }
452
453        CL_MEM_HOST_PTR | CL_MEM_CONTEXT | CL_MEM_ASSOCIATED_MEMOBJECT => {
454            api_info_value!(get_value, intptr_t, clGetMemObjectInfo);
455            Ok(InfoType::Ptr(get_value(memobj, param_name)?))
456        }
457
458        CL_MEM_PROPERTIES // CL_VERSION_3_0
459        => {
460            api_info_size!(get_size, clGetMemObjectInfo);
461            api_info_vector!(get_vec, cl_ulong, clGetMemObjectInfo);
462            let size = get_size(memobj, param_name)?;
463            Ok(InfoType::VecUlong(get_vec(memobj, param_name, size)?))
464        }
465
466        _ => Ok(InfoType::VecUchar(get_mem_object_data(memobj, param_name)?))
467    }
468}
469
470/// Get data about an `OpenCL` image object.
471/// Calls `clGetImageInfo` to get the desired data about the image object.
472pub fn get_image_data(image: cl_mem, param_name: cl_image_info) -> Result<Vec<u8>, cl_int> {
473    api_info_size!(get_size, clGetImageInfo);
474    let size = get_size(image, param_name)?;
475    api_info_vector!(get_vector, u8, clGetImageInfo);
476    get_vector(image, param_name, size)
477}
478
479/// Get information specific to an `OpenCL` image object.
480/// Calls `clGetImageInfo` to get the desired information about the image object.
481///
482/// * `image` - the `OpenCL` image object.
483/// * `param_name` - the type of memory object information being queried, see:
484///   [Image Object Info](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#image-info-table).
485///
486/// returns a Result containing the desired information in an `InfoType` enum
487/// or the error code from the `OpenCL` C API function.
488pub fn get_image_info(image: cl_mem, param_name: cl_image_info) -> Result<InfoType, cl_int> {
489    match param_name {
490        CL_IMAGE_FORMAT => {
491            api_info_size!(get_size, clGetImageInfo);
492            api_info_vector!(get_vec, cl_image_format, clGetImageInfo);
493            let size = get_size(image, param_name)?;
494            Ok(InfoType::VecImageFormat(get_vec(image, param_name, size)?))
495        }
496
497        CL_IMAGE_ELEMENT_SIZE
498        | CL_IMAGE_ROW_PITCH
499        | CL_IMAGE_SLICE_PITCH
500        | CL_IMAGE_WIDTH
501        | CL_IMAGE_HEIGHT
502        | CL_IMAGE_DEPTH
503        | CL_IMAGE_ARRAY_SIZE => {
504            api_info_value!(get_value, size_t, clGetImageInfo);
505            Ok(InfoType::Size(get_value(image, param_name)?))
506        }
507
508        CL_IMAGE_BUFFER => {
509            api_info_value!(get_value, intptr_t, clGetImageInfo);
510            Ok(InfoType::Ptr(get_value(image, param_name)?))
511        }
512
513        CL_IMAGE_NUM_MIP_LEVELS | CL_IMAGE_NUM_SAMPLES => {
514            api_info_value!(get_value, cl_uint, clGetImageInfo);
515            Ok(InfoType::Uint(get_value(image, param_name)?))
516        }
517
518        _ => Ok(InfoType::VecUchar(get_image_data(image, param_name)?)),
519    }
520}
521
522/// Get data about an `OpenCL` pipe object.
523/// Calls `clGetPipeInfo` to get the desired data about the pipe object.
524#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
525pub fn get_pipe_data(pipe: cl_mem, param_name: cl_pipe_info) -> Result<Vec<u8>, cl_int> {
526    api_info_size!(get_size, clGetPipeInfo);
527    let size = get_size(pipe, param_name)?;
528    api_info_vector!(get_vector, u8, clGetPipeInfo);
529    get_vector(pipe, param_name, size)
530}
531
532/// Get information specific to an `OpenCL` pipe object.
533/// Calls `clGetPipeInfo` to get the desired information about the pipe object.
534/// `CL_VERSION_2_0`
535///
536/// * `pipe` - the `OpenCL` pipe object.
537/// * `param_name` - the type of pipe object information being queried, see:
538///   [Pipe Object Queries](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#pipe-info-table).
539///
540/// returns a Result containing the desired information in an `InfoType` enum
541/// or the error code from the `OpenCL` C API function.
542#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
543pub fn get_pipe_info(pipe: cl_mem, param_name: cl_pipe_info) -> Result<InfoType, cl_int> {
544    match param_name {
545        CL_PIPE_PACKET_SIZE | CL_PIPE_MAX_PACKETS => {
546            api_info_value!(get_value, cl_uint, clGetPipeInfo);
547            Ok(InfoType::Uint(get_value(pipe, param_name)?))
548        }
549        // CL_VERSION_3_0
550        CL_PIPE_PROPERTIES => {
551            api_info_size!(get_size, clGetPipeInfo);
552            api_info_vector!(get_vec, intptr_t, clGetPipeInfo);
553            let size = get_size(pipe, param_name)?;
554            Ok(InfoType::VecIntPtr(get_vec(pipe, param_name, size)?))
555        }
556
557        _ => Ok(InfoType::VecUchar(get_pipe_data(pipe, param_name)?)),
558    }
559}
560
561/// Register a callback function with an `OpenCL` memory object that is called when the
562/// memory object is destroyed.
563/// Calls `clSetMemObjectDestructorCallback`.
564///
565/// * `memobj` - the `OpenCL` memory object.
566/// * `pfn_notify` - callback function to be registered by the application.
567/// * `user_data` - passed as the `user_data` argument when `pfn_notify` is called.
568///
569/// returns an empty Result or the error code from the `OpenCL` C API function.
570///
571/// # Safety
572///
573/// This function is unsafe because `user_data` must be valid.
574#[inline]
575pub unsafe fn set_mem_object_destructor_callback(
576    memobj: cl_mem,
577    pfn_notify: extern "C" fn(cl_mem, *mut c_void),
578    user_data: *mut c_void,
579) -> Result<(), cl_int> {
580    let status: cl_int = cl_call!(clSetMemObjectDestructorCallback(
581        memobj,
582        Some(pfn_notify),
583        user_data
584    ));
585    if CL_SUCCESS == status {
586        Ok(())
587    } else {
588        Err(status)
589    }
590}
591
592/// Allocate a shared virtual memory (SVM) buffer that can be shared by the
593/// host and all devices in an `OpenCL` context.
594/// Calls `clSVMAlloc`.
595/// `CL_VERSION_2_0`
596///
597/// * `context` - a valid `OpenCL` context.
598/// * `flags` - a bit-field used to specify allocation and usage information, see:
599///   [SVM Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#svm-flags-table).
600/// * `size` - the size in bytes of the SVM buffer to be allocated.
601/// * `alignment` - the minimum alignment in bytes that is required for the
602///   newly created buffers memory region.
603///
604/// returns Result containing the address of the SVM buffer
605/// or the error code: `CL_INVALID_VALUE` if the address is NULL.
606///
607/// # Safety
608///
609/// This function is unsafe because `flags` must be valid.
610#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
611#[inline]
612pub unsafe fn svm_alloc(
613    context: cl_context,
614    flags: cl_svm_mem_flags,
615    size: size_t,
616    alignment: cl_uint,
617) -> Result<*mut c_void, cl_int> {
618    let ptr = cl_call!(clSVMAlloc(context, flags, size, alignment));
619    if ptr.is_null() {
620        Err(CL_INVALID_VALUE)
621    } else {
622        Ok(ptr)
623    }
624}
625
626/// Free a shared virtual memory (SVM) buffer allocated using `clSVMAlloc`.
627/// Calls `clSVMFree`.
628/// `CL_VERSION_2_0`
629///
630/// * `context` - the valid `OpenCL` context used to create the SVM buffer.
631/// * `svm_pointer` - the value returned by a call to clSVMAlloc.
632///
633/// # Safety
634///
635/// This function is unsafe because `svm_pointer` is no longer valid after it is called.
636#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
637#[inline]
638pub unsafe fn svm_free(context: cl_context, svm_pointer: *mut c_void) -> Result<(), cl_int> {
639    cl_call!(clSVMFree(context, svm_pointer));
640    Ok(())
641}