opencl_api/api/
sampler.rs

1/*
2 * sampler.rs - Sampler object API wrappers (Part of OpenCL Runtime Layer).
3 *
4 * Copyright 2020-2021 Naman Bishnoi
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18//!
19//! A sampler object describes how to sample an image when the image is read in the kernel.
20//! The built-in functions to read from an image in a kernel take a sampler as an argument.
21//! The sampler arguments to the image read function can be sampler objects created using
22//! OpenCL functions and passed as argument values to the kernel or can be samplers declared
23//! inside a kernel.
24//!
25use crate::objects::enums::{ParamValue, Size};
26use crate::objects::functions::status_update;
27use crate::objects::structs::{SamplerInfo, StatusCode};
28use crate::objects::types::{APIResult, ContextPtr, LongProperties, SamplerPtr};
29use crate::{gen_param_value, size_getter};
30use libc::c_void;
31use opencl_heads::ffi;
32use opencl_heads::ffi::clGetSamplerInfo;
33use opencl_heads::types::*;
34use std::ptr;
35
36//TODO: Generalize the AddressingMode and FilterMode structs for create_sampler
37//Deprecated since OpenCL 2.0
38pub fn create_sampler(
39    context: &ContextPtr,
40    normalized_coords: cl_bool,
41    addressing_mode: cl_addressing_mode,
42    filter_mode: cl_filter_mode,
43) -> APIResult<SamplerPtr> {
44    let fn_name = "clCreateSampler";
45    let mut status_code = StatusCode::INVALID_VALUE;
46    let sampler_ptr = unsafe {
47        ffi::clCreateSampler(
48            context.unwrap(),
49            normalized_coords,
50            addressing_mode,
51            filter_mode,
52            &mut status_code,
53        )
54    };
55    status_update(
56        status_code,
57        fn_name,
58        SamplerPtr::from_ptr(sampler_ptr, fn_name)?,
59    )
60}
61
62/// * context must be a valid OpenCL context.
63/// * sampler_properties specifies a list of sampler property names and their
64/// corresponding values. Each sampler property name is immediately followed
65/// by the corresponding desired value. The list is terminated with 0. The
66/// list of supported properties is described in the Sampler Properties table.
67/// If a supported property and its value is not specified in sampler_properties,
68/// its default value will be used. sampler_properties can be NULL in which
69/// case the default values for supported sampler properties will be used.
70pub fn create_sampler_with_properties(
71    context: &ContextPtr,
72    // sampler_properties: Option<[cl_ulong; 5]>,
73    sampler_properties: &LongProperties,
74) -> APIResult<SamplerPtr> {
75    let fn_name = "clCreateSamplerWithProperties";
76    let mut status_code = StatusCode::INVALID_VALUE;
77    let sampler_properties = match sampler_properties {
78        Some(x) => x.as_ptr(),
79        None => ptr::null(),
80    };
81    let sampler_ptr = unsafe {
82        ffi::clCreateSamplerWithProperties(context.unwrap(), sampler_properties, &mut status_code)
83    };
84    status_update(
85        status_code,
86        fn_name,
87        SamplerPtr::from_ptr(sampler_ptr, fn_name)?,
88    )
89}
90
91pub fn retain_sampler(sampler: &SamplerPtr) -> APIResult<()> {
92    let fn_name = "clRetainSampler";
93    let status_code = unsafe { ffi::clRetainSampler(sampler.unwrap()) };
94    status_update(status_code, fn_name, ())
95}
96pub fn release_sampler(sampler: &SamplerPtr) -> APIResult<()> {
97    let fn_name = "clReleaseSampler";
98    let status_code = unsafe { ffi::clReleaseSampler(sampler.unwrap()) };
99    status_update(status_code, fn_name, ())
100}
101
102pub fn get_sampler_info(
103    sampler: &SamplerPtr,
104    param_name: cl_sampler_info,
105) -> APIResult<ParamValue> {
106    type S = SamplerInfo;
107    let fn_name = "clGetSamplerInfo";
108    let sampler = sampler.unwrap();
109    size_getter!(get_sampler_info_size, clGetSamplerInfo);
110    match param_name {
111        S::ADDRESSING_MODE | S::FILTER_MODE | S::NORMALIZED_COORDS | S::REFERENCE_COUNT => {
112            let param_value = gen_param_value!(clGetSamplerInfo, u32, sampler, param_name);
113            Ok(ParamValue::UInt(param_value))
114        }
115        S::CONTEXT => {
116            let param_value = gen_param_value!(clGetSamplerInfo, isize, sampler, param_name);
117            Ok(ParamValue::CPtr(param_value))
118        }
119        // Missing before 3.0
120        S::PROPERTIES => {
121            let size = get_sampler_info_size(sampler, param_name)?;
122            let param_value = gen_param_value!(clGetSamplerInfo, isize, sampler, param_name, size);
123            Ok(ParamValue::ArrCPtr(param_value))
124        }
125        _ => status_update(40404, fn_name, ParamValue::default()),
126    }
127}
128
129/************************/
130/* /\ /\ /\ /\ /\ /\ /\ */
131/*|__|__|__|__|__|__|__|*/
132/*|  |  |  |  |  |  |  |*/
133/*|  |  Unit Tests  |  |*/
134/*|__|__|__|__|__|__|__|*/
135/*|__|__|__|__|__|__|__|*/
136/************************/
137
138#[cfg(test)]
139mod tests {
140    use super::*;
141    use crate::api::context::{create_context, release_context};
142    use crate::api::device::get_device_ids;
143    use crate::api::platform::get_platform_ids;
144    use crate::objects::bitfields::DeviceType;
145    use crate::objects::property::SamplerProperties;
146    use crate::objects::structs::{AddressingMode, FilterMode};
147    use crate::objects::traits::GetSetGo;
148    use crate::objects::types::{PlatformPtr, WrapMutPtr};
149
150    #[test]
151    fn test_create_sampler() {
152        let platform_ids = get_platform_ids().unwrap();
153        // Choose the first platform
154        // let platform_id = platform_ids[0];
155        let platform_id = PlatformPtr::from_ptr(platform_ids[0], "test_fn").unwrap();
156
157        let device_ids =
158            get_device_ids(&platform_id, DeviceType::new(DeviceType::DEFAULT).unwrap()).unwrap();
159        assert!(0 < device_ids.len());
160
161        let context = create_context(&None, device_ids, None, WrapMutPtr::null());
162        let context = context.unwrap();
163
164        // TODO: Generalize the property generator for every API
165        // let sampler_properties = Some([
166        //     SamplerInfo::ADDRESSING_MODE as cl_ulong,
167        //     AddressingMode::REPEAT as cl_ulong,
168        //     SamplerInfo::FILTER_MODE as cl_ulong,
169        //     FilterMode::LINEAR as cl_ulong,
170        //     0,
171        // ]);
172
173        // let sampler_props = SamplerProps {
174        //     normalized_coords: true,
175        //     addressing_mode: Some(AddressingMode::new(AddressingMode::REPEAT).unwrap()),
176        //     // addressing_mode: Some(AddressingMode::REPEAT),
177        //     // filter_mode: Some(FilterMode::LINEAR),
178        //     filter_mode: Some(FilterMode::new(FilterMode::LINEAR).unwrap()),
179        // }
180        // .gen();
181        let sampler_props = SamplerProperties.gen(
182            None,
183            Some(AddressingMode::new(AddressingMode::REPEAT).unwrap()),
184            Some(FilterMode::new(FilterMode::LINEAR).unwrap()),
185        );
186
187        let sampler = create_sampler_with_properties(&context, &sampler_props);
188        let sampler = sampler.unwrap();
189        // eprintln!("CL_CONTEXT_PTR: {:?}", context);
190        assert_ne!(sampler.unwrap(), ptr::null_mut());
191        release_sampler(&sampler).unwrap();
192        release_context(context).unwrap();
193    }
194
195    #[test]
196    fn test_get_sampler_info() {
197        let platform_ids = get_platform_ids().unwrap();
198        // Choose the first platform
199        // let platform_id = platform_ids[0];
200        let platform_id = PlatformPtr::from_ptr(platform_ids[0], "test_fn").unwrap();
201
202        let device_ids =
203            get_device_ids(&platform_id, DeviceType::new(DeviceType::DEFAULT).unwrap()).unwrap();
204        assert!(0 < device_ids.len());
205
206        let context = create_context(&None, device_ids, None, WrapMutPtr::null());
207        let context = context.unwrap();
208
209        // TODO: Generalize the property generator for every API
210        // let sampler_properties = Some([
211        //     SamplerInfo::ADDRESSING_MODE as cl_ulong,
212        //     AddressingMode::REPEAT as cl_ulong,
213        //     SamplerInfo::FILTER_MODE as cl_ulong,
214        //     FilterMode::LINEAR as cl_ulong,
215        //     0,
216        // ]);
217        // let sampler_props = SamplerProps {
218        //     normalized_coords: true,
219        //     addressing_mode: Some(AddressingMode::new(AddressingMode::REPEAT).unwrap()),
220        //     filter_mode: Some(FilterMode::new(FilterMode::LINEAR).unwrap()),
221        // }
222        // .gen();
223        let sampler_props = SamplerProperties.gen(
224            Some(true),
225            Some(AddressingMode::new(AddressingMode::REPEAT).unwrap()),
226            Some(FilterMode::new(FilterMode::LINEAR).unwrap()),
227        );
228
229        let sampler = create_sampler_with_properties(&context, &sampler_props);
230        let sampler = sampler.unwrap();
231        // Context information
232        let sampler_context = get_sampler_info(&sampler, SamplerInfo::CONTEXT);
233        eprintln!("{:?}", sampler_context);
234        match sampler_context {
235            Ok(_) => assert!(true),
236            Err(_) => assert!(false),
237        };
238        // Reference count
239        let sampler_reference_count = get_sampler_info(&sampler, SamplerInfo::REFERENCE_COUNT);
240        eprintln!("{:?}", sampler_reference_count);
241        match sampler_reference_count {
242            Ok(_) => assert!(true),
243            Err(_) => assert!(false),
244        };
245        // Addressing mode
246        let sampler_addressing_mode = get_sampler_info(&sampler, SamplerInfo::ADDRESSING_MODE);
247        eprintln!("{:?}", sampler_addressing_mode);
248        match sampler_addressing_mode {
249            Ok(_) => assert!(true),
250            Err(_) => assert!(false),
251        };
252        // Filter mode
253        let sampler_filter_mode = get_sampler_info(&sampler, SamplerInfo::FILTER_MODE);
254        eprintln!("{:?}", sampler_filter_mode);
255        match sampler_filter_mode {
256            Ok(_) => assert!(true),
257            Err(_) => assert!(false),
258        };
259        release_sampler(&sampler).unwrap();
260        release_context(context).unwrap();
261    }
262}