opencl_api/api/
image.rs

1/*
2 * image.rs - Image 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//! An image object is used to store a one-, two- or three-dimensional texture, frame-buffer or image.
20//! The elements of an image object are selected from a list of predefined image formats.
21//! The minimum number of elements in a memory object is one.
22
23use crate::objects::bitfields::{MapFlags, MemFlags};
24use crate::objects::enums::{ParamValue, Size};
25use crate::objects::functions::status_update;
26use crate::objects::structs::{ImageInfo, StatusCode};
27use crate::objects::traits::GetSetGo;
28use crate::objects::types::{APIResult, ContextPtr, EventPtr, MemFormatList, MemPtr, QueuePtr};
29use crate::objects::wrappers::{WrappedMutablePointer, WrappedPointer};
30use crate::{gen_object_list, gen_param_value, get_count, size_getter};
31use libc::c_void;
32use opencl_heads::ffi;
33use opencl_heads::ffi::{clGetImageInfo, clGetSupportedImageFormats};
34use opencl_heads::types::*;
35use std::ptr;
36
37pub fn create_image(
38    context: &ContextPtr,
39    flags: MemFlags,
40    image_format: WrappedPointer<cl_image_format>,
41    image_desc: WrappedPointer<cl_image_desc>,
42    host: WrappedMutablePointer<c_void>,
43) -> APIResult<MemPtr> {
44    let fn_name = "clCreateImage";
45    let mut status_code = StatusCode::INVALID_VALUE;
46    let mem_ptr = unsafe {
47        ffi::clCreateImage(
48            context.unwrap(),
49            flags.get(),
50            image_format.unwrap(),
51            image_desc.unwrap(),
52            host.unwrap(),
53            &mut status_code,
54        )
55    };
56    status_update(status_code, fn_name, MemPtr::from_ptr(mem_ptr, fn_name)?)
57}
58
59pub fn create_image_with_properties(
60    context: &ContextPtr,
61    properties: WrappedPointer<cl_mem_properties>,
62    flags: MemFlags,
63    image_format: WrappedPointer<cl_image_format>,
64    image_desc: WrappedPointer<cl_image_desc>,
65    host_ptr: WrappedMutablePointer<c_void>,
66) -> APIResult<MemPtr> {
67    let fn_name = "clCreateImageWithProperties";
68    let mut status_code = StatusCode::INVALID_VALUE;
69    let mem_ptr = unsafe {
70        ffi::clCreateImageWithProperties(
71            context.unwrap(),
72            properties.unwrap(),
73            flags.get(),
74            image_format.unwrap(),
75            image_desc.unwrap(),
76            host_ptr.unwrap(),
77            &mut status_code,
78        )
79    };
80    status_update(status_code, fn_name, MemPtr::from_ptr(mem_ptr, fn_name)?)
81}
82
83pub fn create_image_2d(
84    context: &ContextPtr,
85    flags: MemFlags,
86    image_format: WrappedPointer<cl_image_format>,
87    image_width: size_t,
88    image_height: size_t,
89    image_row_pitch: size_t,
90    host_ptr: WrappedMutablePointer<c_void>,
91) -> APIResult<MemPtr> {
92    let fn_name = "clCreateImage2D";
93    let mut status_code = StatusCode::INVALID_VALUE;
94    let mem_ptr = unsafe {
95        ffi::clCreateImage2D(
96            context.unwrap(),
97            flags.get(),
98            image_format.unwrap(),
99            image_width,
100            image_height,
101            image_row_pitch,
102            host_ptr.unwrap(),
103            &mut status_code,
104        )
105    };
106    status_update(status_code, fn_name, MemPtr::from_ptr(mem_ptr, fn_name)?)
107}
108
109pub fn create_image_3d(
110    context: &ContextPtr,
111    flags: MemFlags,
112    image_format: WrappedPointer<cl_image_format>,
113    image_width: size_t,
114    image_height: size_t,
115    image_depth: size_t,
116    image_row_pitch: size_t,
117    image_slice_pitch: size_t,
118    host_ptr: WrappedMutablePointer<c_void>,
119) -> APIResult<MemPtr> {
120    let fn_name = "clCreateImage3D";
121    let mut status_code = StatusCode::INVALID_VALUE;
122    let mem_ptr = unsafe {
123        ffi::clCreateImage3D(
124            context.unwrap(),
125            flags.get(),
126            image_format.unwrap(),
127            image_width,
128            image_height,
129            image_depth,
130            image_row_pitch,
131            image_slice_pitch,
132            host_ptr.unwrap(),
133            &mut status_code,
134        )
135    };
136    status_update(status_code, fn_name, MemPtr::from_ptr(mem_ptr, fn_name)?)
137}
138
139// TODO: Check buffer types for api compatiblity
140
141pub fn get_supported_image_formats(
142    context: &ContextPtr,
143    flags: MemFlags,
144    image_type: cl_mem_object_type,
145) -> APIResult<MemFormatList> {
146    let flags = flags.get();
147    let context = context.unwrap();
148    let image_format_count = get_count!(clGetSupportedImageFormats, context, flags, image_type);
149
150    gen_object_list!(
151        clGetSupportedImageFormats,
152        cl_image_format,
153        image_format_count,
154        context,
155        flags,
156        image_type
157    )
158}
159
160// TODO: Check supported image struct's return types
161
162pub fn enqueue_read_image(
163    command_queue: &QueuePtr,
164    image: &MemPtr,
165    blocking_read: cl_bool,
166    origin: WrappedPointer<size_t>,
167    region: WrappedPointer<size_t>,
168    row_pitch: size_t,
169    slice_pitch: size_t,
170    ptr: WrappedMutablePointer<c_void>,
171    num_events_in_wait_list: cl_uint,
172    event_wait_list: WrappedPointer<cl_event>,
173) -> APIResult<EventPtr> {
174    let fn_name = "clEnqueueReadImage";
175    let mut event_ptr = ptr::null_mut();
176    let status_code = unsafe {
177        ffi::clEnqueueReadImage(
178            command_queue.unwrap(),
179            image.unwrap(),
180            blocking_read,
181            origin.unwrap(),
182            region.unwrap(),
183            row_pitch,
184            slice_pitch,
185            ptr.unwrap(),
186            num_events_in_wait_list,
187            event_wait_list.unwrap(),
188            &mut event_ptr,
189        )
190    };
191    status_update(
192        status_code,
193        fn_name,
194        EventPtr::from_ptr(event_ptr, fn_name)?,
195    )
196}
197pub fn enqueue_write_image(
198    command_queue: &QueuePtr,
199    image: &MemPtr,
200    blocking_write: cl_bool,
201    origin: WrappedPointer<size_t>,
202    region: WrappedPointer<size_t>,
203    row_pitch: size_t,
204    slice_pitch: size_t,
205    ptr: WrappedPointer<c_void>,
206    num_events_in_wait_list: cl_uint,
207    event_wait_list: WrappedPointer<cl_event>,
208) -> APIResult<EventPtr> {
209    let fn_name = "clEnqueueReadImage";
210    let mut event_ptr = ptr::null_mut();
211    let status_code = unsafe {
212        ffi::clEnqueueWriteImage(
213            command_queue.unwrap(),
214            image.unwrap(),
215            blocking_write,
216            origin.unwrap(),
217            region.unwrap(),
218            row_pitch,
219            slice_pitch,
220            ptr.unwrap(),
221            num_events_in_wait_list,
222            event_wait_list.unwrap(),
223            &mut event_ptr,
224        )
225    };
226    status_update(
227        status_code,
228        fn_name,
229        EventPtr::from_ptr(event_ptr, fn_name)?,
230    )
231}
232
233pub fn enqueue_copy_image(
234    command_queue: &QueuePtr,
235    src_image: &MemPtr,
236    dst_image: &MemPtr,
237    src_origin: WrappedPointer<size_t>,
238    dst_origin: WrappedPointer<size_t>,
239    region: WrappedPointer<size_t>,
240    num_events_in_wait_list: cl_uint,
241    event_wait_list: WrappedPointer<cl_event>,
242) -> APIResult<EventPtr> {
243    let fn_name = "clEnqueueCopyImage";
244    let mut event_ptr = ptr::null_mut();
245    let status_code = unsafe {
246        ffi::clEnqueueCopyImage(
247            command_queue.unwrap(),
248            src_image.unwrap(),
249            dst_image.unwrap(),
250            src_origin.unwrap(),
251            dst_origin.unwrap(),
252            region.unwrap(),
253            num_events_in_wait_list,
254            event_wait_list.unwrap(),
255            &mut event_ptr,
256        )
257    };
258    status_update(
259        status_code,
260        fn_name,
261        EventPtr::from_ptr(event_ptr, fn_name)?,
262    )
263}
264
265pub fn enqueue_fill_image(
266    command_queue: &QueuePtr,
267    image: &MemPtr,
268    fill_color: WrappedPointer<c_void>,
269    origin: WrappedPointer<size_t>,
270    region: WrappedPointer<size_t>,
271    num_events_in_wait_list: cl_uint,
272    event_wait_list: WrappedPointer<cl_event>,
273) -> APIResult<EventPtr> {
274    let fn_name = "clEnqueueFillImage";
275    let mut event_ptr = ptr::null_mut();
276    let status_code = unsafe {
277        ffi::clEnqueueFillImage(
278            command_queue.unwrap(),
279            image.unwrap(),
280            fill_color.unwrap(),
281            origin.unwrap(),
282            region.unwrap(),
283            num_events_in_wait_list,
284            event_wait_list.unwrap(),
285            &mut event_ptr,
286        )
287    };
288    status_update(
289        status_code,
290        fn_name,
291        EventPtr::from_ptr(event_ptr, fn_name)?,
292    )
293}
294
295pub fn enqueue_copy_image_to_buffer(
296    command_queue: &QueuePtr,
297    src_image: &MemPtr,
298    dst_buffer: &MemPtr,
299    src_origin: WrappedPointer<size_t>,
300    region: WrappedPointer<size_t>,
301    dst_offset: size_t,
302    num_events_in_wait_list: cl_uint,
303    event_wait_list: WrappedPointer<cl_event>,
304) -> APIResult<EventPtr> {
305    let fn_name = "clEnqueueCopyImageToBuffer";
306    let mut event_ptr = ptr::null_mut();
307    let status_code = unsafe {
308        ffi::clEnqueueCopyImageToBuffer(
309            command_queue.unwrap(),
310            src_image.unwrap(),
311            dst_buffer.unwrap(),
312            src_origin.unwrap(),
313            region.unwrap(),
314            dst_offset,
315            num_events_in_wait_list,
316            event_wait_list.unwrap(),
317            &mut event_ptr,
318        )
319    };
320    status_update(
321        status_code,
322        fn_name,
323        EventPtr::from_ptr(event_ptr, fn_name)?,
324    )
325}
326
327pub fn enqueue_copy_buffer_to_image(
328    command_queue: QueuePtr,
329    src_buffer: MemPtr,
330    dst_image: MemPtr,
331    src_offset: size_t,
332    dst_origin: WrappedPointer<size_t>,
333    region: WrappedPointer<size_t>,
334    num_events_in_wait_list: cl_uint,
335    event_wait_list: WrappedPointer<cl_event>,
336) -> APIResult<EventPtr> {
337    let fn_name = "clEnqueueCopyBufferToImage";
338    let mut event_ptr = ptr::null_mut();
339    let status_code = unsafe {
340        ffi::clEnqueueCopyBufferToImage(
341            command_queue.unwrap(),
342            src_buffer.unwrap(),
343            dst_image.unwrap(),
344            src_offset,
345            dst_origin.unwrap(),
346            region.unwrap(),
347            num_events_in_wait_list,
348            event_wait_list.unwrap(),
349            &mut event_ptr,
350        )
351    };
352    status_update(
353        status_code,
354        fn_name,
355        EventPtr::from_ptr(event_ptr, fn_name)?,
356    )
357}
358
359pub fn enqueue_map_image(
360    command_queue: &QueuePtr,
361    image: &MemPtr,
362    blocking_map: cl_bool,
363    map_flags: MapFlags,
364    origin: WrappedPointer<size_t>,
365    region: WrappedPointer<size_t>,
366    image_row_pitch: WrappedMutablePointer<size_t>,
367    image_slice_pitch: WrappedMutablePointer<size_t>,
368    num_events_in_wait_list: cl_uint,
369    event_wait_list: WrappedPointer<cl_event>,
370    mapped_region: &mut cl_mem,
371) -> APIResult<EventPtr> {
372    let fn_name = "clEnqueueMapImage";
373    let mut status_code = StatusCode::INVALID_VALUE;
374    let mut event_ptr = ptr::null_mut();
375    *mapped_region = unsafe {
376        ffi::clEnqueueMapImage(
377            command_queue.unwrap(),
378            image.unwrap(),
379            blocking_map,
380            map_flags.get(),
381            origin.unwrap(),
382            region.unwrap(),
383            image_row_pitch.unwrap(),
384            image_slice_pitch.unwrap(),
385            num_events_in_wait_list,
386            event_wait_list.unwrap(),
387            &mut event_ptr,
388            &mut status_code,
389        )
390    };
391    status_update(
392        status_code,
393        fn_name,
394        EventPtr::from_ptr(event_ptr, fn_name)?,
395    )
396}
397
398pub fn get_image_info(image: &MemPtr, param_name: cl_image_info) -> APIResult<ParamValue> {
399    let image = image.unwrap();
400    size_getter!(get_image_info_size, clGetImageInfo);
401    match param_name {
402        ImageInfo::ELEMENT_SIZE
403        | ImageInfo::ROW_PITCH
404        | ImageInfo::SLICE_PITCH
405        | ImageInfo::WIDTH
406        | ImageInfo::HEIGHT
407        | ImageInfo::DEPTH
408        | ImageInfo::ARRAY_SIZE => {
409            let param_value = gen_param_value!(clGetImageInfo, usize, image, param_name);
410            Ok(ParamValue::CSize(param_value))
411        }
412        // missing before 1.2 and depr by 2.0
413        ImageInfo::BUFFER => {
414            let param_value = gen_param_value!(clGetImageInfo, isize, image, param_name);
415            Ok(ParamValue::CPtr(param_value))
416        }
417        ImageInfo::NUM_MIP_LEVELS | ImageInfo::NUM_SAMPLES => {
418            let param_value = gen_param_value!(clGetImageInfo, u32, image, param_name);
419            Ok(ParamValue::UInt(param_value))
420        }
421        ImageInfo::FORMAT => {
422            let size = get_image_info_size(image, param_name)?;
423            let param_value =
424                gen_param_value!(clGetImageInfo, cl_image_format, image, param_name, size);
425            Ok(ParamValue::ImageFormat(param_value))
426        }
427        _ => status_update(40404, "clGetImageInfo", ParamValue::default()),
428    }
429}
430
431// TODO: Add unit tests for this file.