opencl3/
memory.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::missing_safety_doc)]
17
18use core::marker::PhantomData;
19
20pub use cl3::memory::*;
21
22use super::context::Context;
23
24use super::Result;
25#[cfg(any(feature = "cl_intel_dx9_media_sharing", feature = "dynamic"))]
26#[allow(unused_imports)]
27use cl3::dx9_media_sharing;
28#[allow(unused_imports)]
29use cl3::egl;
30#[allow(unused_imports)]
31use cl3::ext;
32use cl3::gl;
33use cl3::memory;
34use cl3::sampler;
35
36#[allow(unused_imports)]
37use cl3::types::{
38    cl_addressing_mode, cl_bool, cl_filter_mode, cl_sampler, cl_sampler_info, cl_sampler_properties,
39};
40
41use libc::{c_void, intptr_t, size_t};
42use std::mem;
43
44pub trait ClMem {
45    fn get(&self) -> cl_mem;
46
47    fn get_mut(&mut self) -> cl_mem;
48
49    fn mem_type(&self) -> Result<cl_mem_object_type> {
50        Ok(memory::get_mem_object_info(self.get(), CL_MEM_TYPE)?.into())
51    }
52
53    fn flags(&self) -> Result<cl_mem_flags> {
54        Ok(memory::get_mem_object_info(self.get(), CL_MEM_FLAGS)?.into())
55    }
56
57    fn size(&self) -> Result<size_t> {
58        Ok(memory::get_mem_object_info(self.get(), CL_MEM_SIZE)?.into())
59    }
60
61    fn host_ptr(&self) -> Result<intptr_t> {
62        Ok(memory::get_mem_object_info(self.get(), CL_MEM_HOST_PTR)?.into())
63    }
64
65    fn map_count(&self) -> Result<cl_uint> {
66        Ok(memory::get_mem_object_info(self.get(), CL_MEM_MAP_COUNT)?.into())
67    }
68
69    fn reference_count(&self) -> Result<cl_uint> {
70        Ok(memory::get_mem_object_info(self.get(), CL_MEM_REFERENCE_COUNT)?.into())
71    }
72
73    fn context(&self) -> Result<cl_context> {
74        Ok(intptr_t::from(memory::get_mem_object_info(self.get(), CL_MEM_CONTEXT)?) as cl_context)
75    }
76
77    fn associated_memobject(&self) -> Result<cl_mem> {
78        Ok(intptr_t::from(memory::get_mem_object_info(
79            self.get(),
80            CL_MEM_ASSOCIATED_MEMOBJECT,
81        )?) as cl_mem)
82    }
83
84    fn offset(&self) -> Result<size_t> {
85        Ok(memory::get_mem_object_info(self.get(), CL_MEM_OFFSET)?.into())
86    }
87
88    fn uses_svm_pointer(&self) -> Result<cl_uint> {
89        Ok(memory::get_mem_object_info(self.get(), CL_MEM_USES_SVM_POINTER)?.into())
90    }
91
92    /// CL_VERSION_3_0
93    fn properties(&self) -> Result<Vec<cl_ulong>> {
94        Ok(memory::get_mem_object_info(self.get(), CL_MEM_PROPERTIES)?.into())
95    }
96
97    /// Get memory data about an OpenCL memory object.
98    /// Calls clGetMemObjectInfo to get the desired data about the memory object.
99    fn get_mem_data(&self, param_name: cl_mem_info) -> Result<Vec<u8>> {
100        Ok(get_mem_object_data(self.get(), param_name)?)
101    }
102
103    /// Query an OpenGL object used to create an OpenCL memory object.  
104    ///
105    /// returns a Result containing the OpenGL object type and name
106    /// or the error code from the OpenCL C API function.
107    fn gl_object_info(&self) -> Result<(gl::cl_GLuint, gl::cl_GLuint)> {
108        Ok(gl::get_gl_object_info(self.get())?)
109    }
110}
111
112/// An OpenCL buffer.
113///
114/// Implements the Drop trait to call release_mem_object when the object is dropped.
115#[derive(Debug)]
116pub struct Buffer<T> {
117    buffer: cl_mem,
118    #[doc(hidden)]
119    _type: PhantomData<T>,
120}
121
122impl<T> From<Buffer<T>> for cl_mem {
123    fn from(value: Buffer<T>) -> Self {
124        value.buffer
125    }
126}
127
128impl<T> ClMem for Buffer<T> {
129    fn get(&self) -> cl_mem {
130        self.buffer
131    }
132
133    fn get_mut(&mut self) -> cl_mem {
134        self.buffer
135    }
136}
137
138impl<T> Drop for Buffer<T> {
139    fn drop(&mut self) {
140        unsafe { memory::release_mem_object(self.get()).expect("Error: clReleaseMemObject") };
141    }
142}
143
144unsafe impl<T: Send> Send for Buffer<T> {}
145unsafe impl<T: Sync> Sync for Buffer<T> {}
146
147impl<T> Buffer<T> {
148    pub const fn new(buffer: cl_mem) -> Self {
149        Self {
150            buffer,
151            _type: PhantomData,
152        }
153    }
154
155    /// Create a Buffer for a context.  
156    ///
157    /// * `context` - a valid OpenCL context.
158    /// * `flags` - a bit-field used to specify allocation and usage information
159    ///   about the image memory object being created, see:
160    ///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
161    /// * `count` - the number of T objects to be allocated.
162    /// * `host_ptr` - a pointer to the buffer data that may already be allocated
163    ///   by the application.
164    ///
165    /// returns a Result containing the new OpenCL buffer object
166    /// or the error code from the OpenCL C API function.
167    pub unsafe fn create(
168        context: &Context,
169        flags: cl_mem_flags,
170        count: size_t,
171        host_ptr: *mut c_void,
172    ) -> Result<Self> {
173        unsafe {
174            let buffer =
175                memory::create_buffer(context.get(), flags, count * mem::size_of::<T>(), host_ptr)?;
176            Ok(Self::new(buffer))
177        }
178    }
179
180    /// Create an OpenCL buffer object for a context.
181    ///
182    /// CL_VERSION_3_0
183    ///
184    /// * `context` - a valid OpenCL context.
185    /// * `properties` - an optional null terminated list of properties.
186    /// * `flags` - a bit-field used to specify allocation and usage information
187    ///   about the image memory object being created, see:
188    ///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
189    /// * `count` - the number of T objects to be allocated.
190    /// * `host_ptr` - a pointer to the buffer data that may already be allocated
191    ///   by the application.
192    ///
193    /// returns a Result containing the new OpenCL buffer object
194    /// or the error code from the OpenCL C API function.
195    #[cfg(any(feature = "CL_VERSION_3_0", feature = "dynamic"))]
196    pub unsafe fn create_with_properties(
197        context: &Context,
198        properties: *const cl_mem_properties,
199        flags: cl_mem_flags,
200        count: size_t,
201        host_ptr: *mut c_void,
202    ) -> Result<Self> {
203        unsafe {
204            let buffer = memory::create_buffer_with_properties(
205                context.get(),
206                properties,
207                flags,
208                count * mem::size_of::<T>(),
209                host_ptr,
210            )?;
211            Ok(Self::new(buffer))
212        }
213    }
214
215    /// Create an OpenCL buffer object for a context from an OpenGL buffer.  
216    ///
217    /// * `context` - a valid OpenCL context created from an OpenGL context.
218    /// * `flags` - a bit-field used to specify allocation and usage information
219    ///   about the image memory object being created, see:
220    ///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
221    /// * `bufobj` - the OpenGL buffer.  
222    ///
223    /// returns a Result containing the new OpenCL buffer object
224    /// or the error code from the OpenCL C API function.
225    pub unsafe fn create_from_gl_buffer(
226        context: &Context,
227        flags: cl_mem_flags,
228        bufobj: gl::cl_GLuint,
229    ) -> Result<Self> {
230        unsafe {
231            let buffer = gl::create_from_gl_buffer(context.get(), flags, bufobj)?;
232            Ok(Self::new(buffer))
233        }
234    }
235
236    #[cfg(any(
237        feature = "cl_intel_create_buffer_with_properties",
238        feature = "dynamic"
239    ))]
240    pub unsafe fn create_with_properties_intel(
241        context: &Context,
242        properties: *const ext::cl_mem_properties_intel,
243        flags: cl_mem_flags,
244        count: size_t,
245        host_ptr: *mut c_void,
246    ) -> Result<Self> {
247        unsafe {
248            let buffer = ext::create_buffer_with_properties_intel(
249                context.get(),
250                properties,
251                flags,
252                count * mem::size_of::<T>(),
253                host_ptr,
254            )?;
255            Ok(Self::new(buffer))
256        }
257    }
258
259    /// Create an new OpenCL buffer object from an existing buffer object.
260    ///
261    /// See: [SubBuffer Attributes](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#subbuffer-create-info-table).  
262    ///
263    /// * `flags` - a bit-field used to specify allocation and usage information
264    ///   about the sub-buffer memory object being created, see:
265    ///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
266    /// * `origin` - the offset in number of objects of type `T`.
267    /// * `count` - the size of the sub-buffer in number of objects of type `T`.
268    ///
269    /// returns a Result containing the new OpenCL buffer object
270    /// or the error code from the OpenCL C API function.
271    pub unsafe fn create_sub_buffer(
272        &self,
273        flags: cl_mem_flags,
274        origin: usize,
275        count: usize,
276    ) -> Result<Self> {
277        unsafe {
278            let buffer_create_info = cl_buffer_region {
279                origin: origin * std::mem::size_of::<T>(),
280                size: count * std::mem::size_of::<T>(),
281            };
282            let buffer = memory::create_sub_buffer(
283                self.buffer,
284                flags,
285                CL_BUFFER_CREATE_TYPE_REGION,
286                &buffer_create_info as *const _ as *const c_void,
287            )?;
288            Ok(Self::new(buffer))
289        }
290    }
291}
292
293/// An OpenCL image.
294///
295/// Has methods to return information from calls to clGetImageInfo with the
296/// appropriate parameters.  
297/// Implements the Drop trait to call release_mem_object when the object is dropped.
298#[derive(Debug)]
299pub struct Image {
300    image: cl_mem,
301}
302
303impl From<Image> for cl_mem {
304    fn from(value: Image) -> Self {
305        value.image
306    }
307}
308
309impl ClMem for Image {
310    fn get(&self) -> cl_mem {
311        self.image
312    }
313
314    fn get_mut(&mut self) -> cl_mem {
315        self.image
316    }
317}
318
319impl Drop for Image {
320    fn drop(&mut self) {
321        unsafe { memory::release_mem_object(self.get()).expect("Error: clReleaseMemObject") };
322    }
323}
324
325unsafe impl Send for Image {}
326
327impl Image {
328    pub const fn new(image: cl_mem) -> Self {
329        Self { image }
330    }
331
332    /// Create an OpenCL image object for a context.  
333    ///
334    /// * `context` - a valid OpenCL context.
335    /// * `flags` - a bit-field used to specify allocation and usage information
336    ///   about the image memory object being created, see:
337    ///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
338    /// * `image_format` - a pointer to a structure that describes format properties
339    ///   of the image to be allocated.
340    /// * `image_desc` - a pointer to a structure that describes type and dimensions
341    ///   of the image to be allocated.
342    /// * `host_ptr` - a pointer to the image data that may already be allocated
343    ///   by the application.
344    ///
345    /// returns a Result containing the new OpenCL image object
346    /// or the error code from the OpenCL C API function.
347    #[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
348    pub unsafe fn create(
349        context: &Context,
350        flags: cl_mem_flags,
351        image_format: *const cl_image_format,
352        image_desc: *const cl_image_desc,
353        host_ptr: *mut c_void,
354    ) -> Result<Self> {
355        unsafe {
356            let image =
357                memory::create_image(context.get(), flags, image_format, image_desc, host_ptr)?;
358            Ok(Self::new(image))
359        }
360    }
361
362    /// Create an OpenCL image object for a context.
363    ///
364    /// CL_VERSION_3_0
365    ///
366    /// * `context` - a valid OpenCL context.
367    /// * `properties` - an optional null terminated list of properties.
368    /// * `flags` - a bit-field used to specify allocation and usage information
369    ///   about the image memory object being created, see:
370    ///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
371    /// * `image_format` - a pointer to a structure that describes format properties
372    ///   of the image to be allocated.
373    /// * `image_desc` - a pointer to a structure that describes type and dimensions
374    ///   of the image to be allocated.
375    /// * `host_ptr` - a pointer to the image data that may already be allocated
376    ///   by the application.
377    ///
378    /// returns a Result containing the new OpenCL image object
379    /// or the error code from the OpenCL C API function.
380    #[cfg(any(feature = "CL_VERSION_3_0", feature = "dynamic"))]
381    pub unsafe fn create_with_properties(
382        context: &Context,
383        properties: *const cl_mem_properties,
384        flags: cl_mem_flags,
385        image_format: *const cl_image_format,
386        image_desc: *const cl_image_desc,
387        host_ptr: *mut c_void,
388    ) -> Result<Self> {
389        unsafe {
390            let image = memory::create_image_with_properties(
391                context.get(),
392                properties,
393                flags,
394                image_format,
395                image_desc,
396                host_ptr,
397            )?;
398            Ok(Self::new(image))
399        }
400    }
401
402    /// Create an OpenCL image object, image array object, or image buffer object
403    /// for a context.
404    ///
405    /// From an OpenGL: texture object, texture array object, texture buffer object,
406    /// or a single face of an OpenGL cubemap texture object.  
407    ///
408    /// * `context` - a valid OpenCL context created from an OpenGL context.
409    /// * `flags` - a bit-field used to specify allocation and usage information
410    ///   about the image memory object being created, see:
411    ///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
412    /// * `texture_target` - used to define the image type of texture.  
413    /// * `miplevel ` - used to define the mipmap level.  
414    /// * `texture  ` - the name of a GL buffer texture object.
415    ///
416    /// returns a Result containing the new OpenCL image object
417    /// or the error code from the OpenCL C API function.
418    pub unsafe fn create_from_gl_texture(
419        context: &Context,
420        flags: cl_mem_flags,
421        texture_target: gl::cl_GLenum,
422        miplevel: gl::cl_GLint,
423        texture: gl::cl_GLuint,
424    ) -> Result<Self> {
425        unsafe {
426            let image = gl::create_from_gl_texture(
427                context.get(),
428                flags,
429                texture_target,
430                miplevel,
431                texture,
432            )?;
433            Ok(Self::new(image))
434        }
435    }
436
437    /// Create an OpenCL 2D image object from an OpenGL renderbuffer object.  
438    ///
439    /// * `context` - a valid OpenCL context created from an OpenGL context.
440    /// * `flags` - a bit-field used to specify allocation and usage information
441    ///   about the image memory object being created, see:
442    ///   [Memory Flags](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#memory-flags-table).
443    /// * `renderbuffer`  - a GL renderbuffer object.  
444    ///
445    /// returns a Result containing the new OpenCL image object
446    /// or the error code from the OpenCL C API function.
447    pub unsafe fn create_from_gl_render_buffer(
448        context: &Context,
449        flags: cl_mem_flags,
450        renderbuffer: gl::cl_GLuint,
451    ) -> Result<Self> {
452        unsafe {
453            let image = gl::create_from_gl_render_buffer(context.get(), flags, renderbuffer)?;
454            Ok(Self::new(image))
455        }
456    }
457
458    /// Create an OpenCL image object, from the EGLImage source provided as image.  
459    /// Requires the cl_khr_egl_image extension.  
460    ///
461    /// * `context` - a valid OpenCL context created from an OpenGL context.
462    /// * `display` - should be of type EGLDisplay, cast into the type CLeglDisplayKHR
463    /// * `image` - should be of type EGLImageKHR, cast into the type CLeglImageKHR.  
464    /// * `flags` -  usage information about the memory object being created.  
465    /// * `properties` - a null terminated list of property names and their
466    ///   corresponding values.  
467    ///
468    /// returns a Result containing the new OpenCL image object
469    /// or the error code from the OpenCL C API function.
470    #[cfg(any(feature = "cl_khr_egl_image", feature = "dynamic"))]
471    #[inline]
472    pub unsafe fn create_from_egl_image(
473        context: &Context,
474        display: egl::CLeglDisplayKHR,
475        image: egl::CLeglImageKHR,
476        flags: cl_mem_flags,
477        properties: &[egl::cl_egl_image_properties_khr],
478    ) -> Result<Self> {
479        unsafe {
480            let image = egl::create_from_egl_image(
481                context.get(),
482                display,
483                image,
484                flags,
485                properties.as_ptr(),
486            )?;
487            Ok(Self::new(image))
488        }
489    }
490
491    #[cfg(any(feature = "cl_intel_dx9_media_sharing", feature = "dynamic"))]
492    #[inline]
493    pub unsafe fn create_from_dx9_media_surface_intel(
494        context: &Context,
495        flags: cl_mem_flags,
496        resource: dx9_media_sharing::IDirect3DSurface9_ptr,
497        shared_handle: dx9_media_sharing::HANDLE,
498        plane: cl_uint,
499    ) -> Result<Self> {
500        unsafe {
501            let image = dx9_media_sharing::create_from_dx9_media_surface_intel(
502                context.get(),
503                flags,
504                resource,
505                shared_handle,
506                plane,
507            )?;
508            Ok(Self::new(image))
509        }
510    }
511
512    pub fn format(&self) -> Result<Vec<cl_image_format>> {
513        Ok(memory::get_image_info(self.image, CL_IMAGE_FORMAT)?.into())
514    }
515
516    pub fn element_size(&self) -> Result<size_t> {
517        Ok(memory::get_image_info(self.image, CL_IMAGE_ELEMENT_SIZE)?.into())
518    }
519
520    pub fn row_pitch(&self) -> Result<size_t> {
521        Ok(memory::get_image_info(self.image, CL_IMAGE_ROW_PITCH)?.into())
522    }
523
524    pub fn slice_pitch(&self) -> Result<size_t> {
525        Ok(memory::get_image_info(self.image, CL_IMAGE_SLICE_PITCH)?.into())
526    }
527
528    pub fn width(&self) -> Result<size_t> {
529        Ok(memory::get_image_info(self.image, CL_IMAGE_WIDTH)?.into())
530    }
531
532    pub fn height(&self) -> Result<size_t> {
533        Ok(memory::get_image_info(self.image, CL_IMAGE_HEIGHT)?.into())
534    }
535
536    pub fn depth(&self) -> Result<size_t> {
537        Ok(memory::get_image_info(self.image, CL_IMAGE_DEPTH)?.into())
538    }
539    pub fn array_size(&self) -> Result<size_t> {
540        Ok(memory::get_image_info(self.image, CL_IMAGE_ARRAY_SIZE)?.into())
541    }
542
543    pub fn buffer(&self) -> Result<cl_mem> {
544        Ok(intptr_t::from(memory::get_image_info(self.image, CL_IMAGE_BUFFER)?) as cl_mem)
545    }
546
547    pub fn num_mip_levels(&self) -> Result<cl_uint> {
548        Ok(memory::get_image_info(self.image, CL_IMAGE_NUM_MIP_LEVELS)?.into())
549    }
550
551    pub fn num_samples(&self) -> Result<cl_uint> {
552        Ok(memory::get_image_info(self.image, CL_IMAGE_NUM_SAMPLES)?.into())
553    }
554
555    /// Get data about an OpenCL image object.
556    /// Calls clGetImageInfo to get the desired data about the image object.
557    pub fn get_data(&self, param_name: cl_image_info) -> Result<Vec<u8>> {
558        Ok(get_image_data(self.image, param_name)?)
559    }
560
561    ///  Get information about the GL texture target associated with a memory object.
562    pub fn gl_texture_target(&self) -> Result<cl_uint> {
563        Ok(gl::get_gl_texture_info(self.image, gl::CL_GL_TEXTURE_TARGET)?.into())
564    }
565
566    /// Get information about the GL mipmap level associated with a memory object.
567    pub fn gl_mipmap_level(&self) -> Result<cl_int> {
568        Ok(gl::get_gl_texture_info(self.image, gl::CL_GL_MIPMAP_LEVEL)?.into())
569    }
570
571    ///  Get information about the GL number of samples associated with a memory object.
572    pub fn gl_num_samples(&self) -> Result<cl_int> {
573        Ok(gl::get_gl_texture_info(self.image, gl::CL_GL_NUM_SAMPLES)?.into())
574    }
575
576    ///  Get GL texture information associated with a memory object.
577    pub fn get_gl_texture_data(&self, param_name: gl::cl_gl_texture_info) -> Result<Vec<u8>> {
578        Ok(gl::get_gl_texture_data(self.image, param_name)?)
579    }
580}
581
582/// An OpenCL sampler.  
583/// Has methods to return information from calls to clGetSamplerInfo with the
584/// appropriate parameters.  
585/// Implements the Drop trait to call release_sampler when the object is dropped.
586#[derive(Debug)]
587pub struct Sampler {
588    sampler: cl_sampler,
589}
590
591impl From<Sampler> for cl_sampler {
592    fn from(value: Sampler) -> Self {
593        value.sampler
594    }
595}
596
597impl Drop for Sampler {
598    fn drop(&mut self) {
599        unsafe { sampler::release_sampler(self.sampler).expect("Error: clReleaseSampler") };
600    }
601}
602
603unsafe impl Send for Sampler {}
604
605impl Sampler {
606    pub const fn new(sampler: cl_sampler) -> Self {
607        Self { sampler }
608    }
609
610    #[cfg_attr(
611        any(
612            feature = "CL_VERSION_2_0",
613            feature = "CL_VERSION_2_1",
614            feature = "CL_VERSION_2_2",
615            feature = "CL_VERSION_3_0"
616        ),
617        deprecated(
618            since = "0.1.0",
619            note = "From CL_VERSION_2_0 use create_sampler_with_properties"
620        )
621    )]
622    pub fn create(
623        context: &Context,
624        normalize_coords: cl_bool,
625        addressing_mode: cl_addressing_mode,
626        filter_mode: cl_filter_mode,
627    ) -> Result<Self> {
628        let sampler = sampler::create_sampler(
629            context.get(),
630            normalize_coords,
631            addressing_mode,
632            filter_mode,
633        )?;
634        Ok(Self::new(sampler))
635    }
636
637    #[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
638    pub fn create_with_properties(
639        context: &Context,
640        properties: *const cl_sampler_properties,
641    ) -> Result<Self> {
642        let sampler = sampler::create_sampler_with_properties(context.get(), properties)?;
643        Ok(Self::new(sampler))
644    }
645
646    pub const fn get(&self) -> cl_sampler {
647        self.sampler
648    }
649
650    pub fn reference_count(&self) -> Result<cl_uint> {
651        Ok(sampler::get_sampler_info(self.get(), sampler::CL_SAMPLER_REFERENCE_COUNT)?.into())
652    }
653
654    pub fn context(&self) -> Result<cl_context> {
655        Ok(intptr_t::from(sampler::get_sampler_info(
656            self.get(),
657            sampler::CL_SAMPLER_CONTEXT,
658        )?) as cl_context)
659    }
660
661    pub fn normalized_coords(&self) -> Result<bool> {
662        Ok(cl_uint::from(sampler::get_sampler_info(
663            self.get(),
664            sampler::CL_SAMPLER_NORMALIZED_COORDS,
665        )?) != CL_FALSE)
666    }
667
668    pub fn addressing_mode(&self) -> Result<cl_addressing_mode> {
669        Ok(sampler::get_sampler_info(self.get(), sampler::CL_SAMPLER_ADDRESSING_MODE)?.into())
670    }
671
672    pub fn filter_mode(&self) -> Result<cl_filter_mode> {
673        Ok(sampler::get_sampler_info(self.get(), sampler::CL_SAMPLER_FILTER_MODE)?.into())
674    }
675
676    pub fn sampler_properties(&self) -> Result<Vec<intptr_t>> {
677        Ok(sampler::get_sampler_info(self.get(), sampler::CL_SAMPLER_PROPERTIES)?.into())
678    }
679
680    /// Get data about an OpenCL sampler object.
681    /// Calls clGetDeviceInfo to get the desired data about the sampler object.
682    pub fn get_data(&self, param_name: cl_sampler_info) -> Result<Vec<u8>> {
683        Ok(sampler::get_sampler_data(self.get(), param_name)?)
684    }
685}
686
687/// An OpenCL pipe.  
688/// Has methods to return information from calls to clGetPipeInfo with the
689/// appropriate parameters.  
690/// Implements the Drop trait to call release_mem_object when the object is dropped.
691#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
692#[derive(Debug)]
693pub struct Pipe {
694    pipe: cl_mem,
695}
696
697#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
698impl From<cl_mem> for Pipe {
699    fn from(pipe: cl_mem) -> Self {
700        Self { pipe }
701    }
702}
703
704#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
705impl From<Pipe> for cl_mem {
706    fn from(value: Pipe) -> Self {
707        value.pipe as Self
708    }
709}
710
711#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
712impl ClMem for Pipe {
713    fn get(&self) -> cl_mem {
714        self.pipe
715    }
716
717    fn get_mut(&mut self) -> cl_mem {
718        self.pipe
719    }
720}
721
722#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
723impl Drop for Pipe {
724    fn drop(&mut self) {
725        unsafe { memory::release_mem_object(self.get()).expect("Error: clReleaseMemObject") };
726    }
727}
728
729#[cfg(any(feature = "CL_VERSION_2_0", feature = "dynamic"))]
730impl Pipe {
731    pub const fn new(pipe: cl_mem) -> Self {
732        Self { pipe }
733    }
734
735    pub unsafe fn create(
736        context: &Context,
737        flags: cl_mem_flags,
738        pipe_packet_size: cl_uint,
739        pipe_max_packets: cl_uint,
740    ) -> Result<Self> {
741        unsafe {
742            let pipe =
743                memory::create_pipe(context.get(), flags, pipe_packet_size, pipe_max_packets)?;
744            Ok(Self::new(pipe))
745        }
746    }
747
748    pub fn pipe_packet_size(&self) -> Result<cl_uint> {
749        Ok(memory::get_pipe_info(self.get(), CL_PIPE_PACKET_SIZE)?.into())
750    }
751
752    pub fn pipe_max_packets(&self) -> Result<cl_uint> {
753        Ok(memory::get_pipe_info(self.get(), CL_PIPE_MAX_PACKETS)?.into())
754    }
755
756    pub fn pipe_properties(&self) -> Result<Vec<intptr_t>> {
757        Ok(memory::get_pipe_info(self.get(), CL_PIPE_PROPERTIES)?.into())
758    }
759
760    /// Get data about an OpenCL pipe object.  
761    /// Calls clGetPipeInfo to get the desired information about the pipe object.
762    pub fn get_data(&self, param_name: cl_pipe_info) -> Result<Vec<u8>> {
763        Ok(memory::get_pipe_data(self.get(), param_name)?)
764    }
765}
766
767#[cfg(test)]
768mod tests {
769    use super::*;
770    use crate::context::Context;
771    use crate::device::{CL_DEVICE_TYPE_GPU, Device};
772    use crate::platform::get_platforms;
773    use crate::types::cl_float;
774    use std::ptr;
775
776    #[test]
777    fn test_memory_buffer() {
778        let platforms = get_platforms().unwrap();
779        assert!(0 < platforms.len());
780
781        // Get the first platform
782        let platform = &platforms[0];
783
784        let devices = platform.get_devices(CL_DEVICE_TYPE_GPU).unwrap();
785        assert!(0 < devices.len());
786
787        // Get the first device
788        let device = Device::new(devices[0]);
789        let context = Context::from_device(&device).unwrap();
790
791        const ARRAY_SIZE: usize = 1024;
792
793        let buffer = unsafe {
794            Buffer::<cl_float>::create(&context, CL_MEM_WRITE_ONLY, ARRAY_SIZE, ptr::null_mut())
795                .unwrap()
796        };
797
798        let value = buffer.mem_type().unwrap();
799        println!("buffer.mem_type(): {}", value);
800        assert_eq!(CL_MEM_OBJECT_BUFFER, value);
801
802        let value = buffer.flags().unwrap();
803        println!("buffer.flags(): {}", value);
804        assert_eq!(CL_MEM_WRITE_ONLY, value);
805
806        let value = buffer.size().unwrap();
807        println!("buffer.size(): {}", value);
808        assert_eq!(ARRAY_SIZE * mem::size_of::<cl_float>(), value);
809
810        let value = buffer.host_ptr().unwrap();
811        println!("buffer.host_ptr(): {:?}", value);
812        assert_eq!(0, value);
813
814        let value = buffer.map_count().unwrap();
815        println!("buffer.map_count(): {}", value);
816        assert_eq!(0, value);
817
818        let value = buffer.reference_count().unwrap();
819        println!("buffer.reference_count(): {}", value);
820        assert_eq!(1, value);
821
822        let value = buffer.context().unwrap();
823        assert!(context.get() == value);
824
825        let value = buffer.associated_memobject().unwrap() as intptr_t;
826        println!("buffer.associated_memobject(): {:?}", value);
827        assert_eq!(0, value);
828
829        let value = buffer.offset().unwrap();
830        println!("buffer.offset(): {}", value);
831        assert_eq!(0, value);
832
833        let value = buffer.uses_svm_pointer().unwrap();
834        println!("buffer.uses_svm_pointer(): {}", value);
835        assert_eq!(0, value);
836
837        // CL_VERSION_3_0
838        match buffer.properties() {
839            Ok(value) => {
840                println!("buffer.properties: {:?}", value)
841            }
842            Err(e) => println!("OpenCL error, CL_MEM_PROPERTIES: {:?}, {}", e, e),
843        }
844    }
845}