1use crate::ffi::{c_void, size_t};
16use num_traits::FromPrimitive;
17use std::env;
18use std::ffi::CString;
19use std::fmt;
20use std::iter;
21use std::mem;
22use std::ptr;
23use std::thread;
24use std::time::Duration;
25
26#[cfg(not(feature = "opencl_vendor_mesa"))]
27use crate::ffi::{
28 clCreateFromGLBuffer, clCreateFromGLRenderbuffer, clCreateFromGLTexture,
29 clCreateFromGLTexture2D, clCreateFromGLTexture3D, clEnqueueAcquireGLObjects,
30 clEnqueueReleaseGLObjects,
31};
32#[cfg(not(feature = "opencl_vendor_mesa"))]
33use crate::ffi::{cl_GLenum, cl_GLint, cl_GLuint, cl_gl_context_info};
34
35use crate::ffi::{
36 self, cl_addressing_mode, cl_bool, cl_buffer_create_type, cl_command_queue,
37 cl_command_queue_info, cl_context, cl_context_info, cl_context_properties, cl_device_id,
38 cl_device_info, cl_device_type, cl_event, cl_event_info, cl_filter_mode, cl_image_desc,
39 cl_image_format, cl_image_info, cl_int, cl_kernel, cl_kernel_arg_info, cl_kernel_info,
40 cl_kernel_work_group_info, cl_mem, cl_mem_flags, cl_mem_info, cl_mem_object_type,
41 cl_platform_id, cl_platform_info, cl_profiling_info, cl_program, cl_program_build_info,
42 cl_program_info, cl_sampler, cl_sampler_info, cl_uint,
43};
44
45use crate::error::{Error as OclCoreError, Result as OclCoreResult};
46
47use crate::{
48 AddressingMode, ArgVal, AsMem, BufferCreateType, BufferRegion, BuildProgramCallbackFn,
49 ClContextPtr, ClDeviceIdPtr, ClEventPtrRef, ClNullEventPtr, ClPlatformIdPtr, ClVersions,
50 ClWaitListPtr, CommandExecutionStatus, CommandQueue, CommandQueueInfo, CommandQueueInfoResult,
51 CommandQueueProperties, Context, ContextInfo, ContextInfoResult, ContextProperties,
52 CreateContextCallbackFn, DeviceId, DeviceInfo, DeviceInfoResult, DeviceType, Event,
53 EventCallbackFn, EventInfo, EventInfoResult, FilterMode, ImageDescriptor, ImageFormat,
54 ImageFormatParseResult, ImageInfo, ImageInfoResult, Kernel, KernelArgInfo, KernelArgInfoResult,
55 KernelInfo, KernelInfoResult, KernelWorkGroupInfo, KernelWorkGroupInfoResult, MapFlags, Mem,
56 MemCmdAll, MemCmdRw, MemFlags, MemInfo, MemInfoResult, MemMap, MemMigrationFlags,
57 MemObjectType, OclPrm, OpenclVersion, PlatformId, PlatformInfo, PlatformInfoResult,
58 ProfilingInfo, ProfilingInfoResult, Program, ProgramBuildInfo, ProgramBuildInfoResult,
59 ProgramInfo, ProgramInfoResult, Sampler, SamplerInfo, SamplerInfoResult, Status, UserDataPtr,
60};
61
62#[cfg(not(feature = "opencl_vendor_mesa"))]
63use crate::{GlContextInfo, GlContextInfoResult};
64
65#[cfg(target_os = "macos")]
67const CL_GL_SHARING_EXT: &str = "cl_APPLE_gl_sharing";
68#[cfg(not(target_os = "macos"))]
69const CL_GL_SHARING_EXT: &str = "cl_khr_gl_sharing";
70
71const KERNEL_DEBUG_SLEEP_DURATION_MS: u64 = 150;
72const PLATFORM_IDS_ATTEMPT_TIMEOUT_MS: u64 = 2000;
73const PLATFORM_IDS_ATTEMPT_COUNT: u64 = 5;
74
75pub extern "C" fn _dummy_event_callback(_: ffi::cl_event, _: i32, _: *mut c_void) {}
83
84pub extern "C" fn _complete_user_event(
94 src_event_ptr: cl_event,
95 event_status: i32,
96 user_data: *mut c_void,
97) {
98 #[cfg(not(feature = "event_debug_print"))]
99 let _ = src_event_ptr;
100
101 if event_status == CommandExecutionStatus::Complete as i32 && !user_data.is_null() {
102 let tar_event_ptr = user_data as *mut _ as cl_event;
103
104 unsafe {
105 let user_event = Event::from_raw(tar_event_ptr);
106
107 #[cfg(feature = "event_debug_print")]
108 println!(
109 "::_complete_user_event: Setting event complete for: \
110 source: {:?}, target: {:?}...",
111 src_event_ptr, &user_event
112 );
113
114 crate::set_user_event_status(&user_event, CommandExecutionStatus::Complete).unwrap();
115 }
116
117 #[cfg(feature = "event_debug_print")]
118 println!(
119 " - Event status has been set to 'CommandExecutionStatus::Complete' \
120 for event: {:?}",
121 tar_event_ptr
122 );
123 } else {
124 match CommandExecutionStatus::from_i32(event_status) {
127 Some(status_enum) => panic!(
128 "ocl_core::_complete_event: User data is null or event \
129 is not complete. Status: '{:?}'",
130 status_enum
131 ),
132 None => eval_errcode(
133 event_status,
134 (),
135 "clSetEventCallback",
136 Some(format!("src_event_ptr: {:?}", src_event_ptr)),
137 )
138 .unwrap(),
139 }
140 }
141}
142
143static SDK_DOCS_URL_PRE: &'static str =
150 "https://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/";
151static SDK_DOCS_URL_SUF: &'static str = ".html#errors";
152
153#[derive(thiserror::Error)]
155pub struct ApiError {
156 status: Status,
157 fn_name: &'static str,
158 fn_info: Option<String>,
159}
160
161impl ApiError {
162 pub fn new<S: Into<String>>(
163 errcode: i32,
164 fn_name: &'static str,
165 fn_info: Option<S>,
166 ) -> ApiError {
167 let status = match Status::from_i32(errcode) {
168 Some(s) => s,
169 None => panic!(
170 "ocl_core::Error::err_status: Invalid error code: '{}'. \
171 Aborting.",
172 errcode
173 ),
174 };
175
176 let fn_info = fn_info.map(|s| s.into());
177
178 ApiError {
179 status,
180 fn_name,
181 fn_info,
182 }
183 }
184
185 pub fn status(&self) -> Status {
186 self.status
187 }
188}
189
190impl fmt::Display for ApiError {
191 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
192 let fn_info_string = if let Some(ref fn_info) = self.fn_info {
193 format!("(\"{}\")", fn_info)
194 } else {
195 String::with_capacity(0)
196 };
197
198 let status_int = self.status as i32;
199
200 write!(
201 f,
202 "\n\n\
203 ################################ OPENCL ERROR ############################### \
204 \n\nError executing function: {}{} \
205 \n\nStatus error code: {:?} ({}) \
206 \n\nPlease visit the following url for more information: \n\n{}{}{} \n\n\
207 ############################################################################# \n",
208 self.fn_name,
209 fn_info_string,
210 self.status,
211 status_int,
212 SDK_DOCS_URL_PRE,
213 self.fn_name,
214 SDK_DOCS_URL_SUF
215 )
216 }
217}
218
219impl fmt::Debug for ApiError {
220 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221 fmt::Display::fmt(&self, f)
222 }
223}
224
225#[inline(always)]
229fn eval_errcode<T, S>(
230 errcode: cl_int,
231 result: T,
232 fn_name: &'static str,
233 fn_info: Option<S>,
234) -> OclCoreResult<T>
235where
236 S: Into<String>,
237{
238 if (Status::CL_SUCCESS as i32) == errcode {
239 Ok(result)
240 } else {
241 Err(ApiError::new(errcode, fn_name, fn_info).into())
242 }
243}
244
245#[derive(Debug, thiserror::Error)]
247pub enum ProgramBuildError {
248 #[error("Device list is empty. Aborting build.")]
249 DeviceListEmpty,
250 #[error(
251 "\n\n\
252 ###################### OPENCL PROGRAM BUILD DEBUG OUTPUT \
253 ######################\
254 \n\n{0}\n\
255 ########################################################\
256 #######################\
257 \n\n"
258 )]
259 BuildLog(String),
260 #[error("{0}")]
261 InfoResult(Box<OclCoreError>),
262}
263
264pub fn program_build_err<D: ClDeviceIdPtr>(
269 program: &Program,
270 device_ids: &[D],
271) -> Result<(), ProgramBuildError> {
272 if device_ids.is_empty() {
273 return Err(ProgramBuildError::DeviceListEmpty);
274 }
275
276 for device_id in device_ids.iter().cloned() {
277 match get_program_build_info(program, device_id, ProgramBuildInfo::BuildLog) {
278 Ok(ProgramBuildInfoResult::BuildLog(log)) => {
279 if log.len() > 1 {
280 return Err(ProgramBuildError::BuildLog(log));
281 }
282 }
283 Err(err) => return Err(ProgramBuildError::InfoResult(Box::new(err))),
284 _ => panic!("Unexpected 'ProgramBuildInfoResult' variant."),
285 }
286 }
287
288 Ok(())
289}
290
291#[allow(dead_code)]
293#[derive(Debug)]
294pub(crate) enum ApiFunction {
295 None,
296 RetainDevice,
297 ReleaseDevice,
298 CreateProgramWithIl,
299 CreateImage,
300 CreateFromGLTexture,
301 CreateFromD3D11Texture,
302 GetKernelArgInfo,
303 EnqueueFillBuffer,
304 EnqueueFillImage,
305 EnqueueMigrateMemObjects,
306 EnqueueMarkerWithWaitList,
307 EnqueueBarrierWithWaitList,
308 GetExtensionFunctionAddressForPlatform,
309 CompileProgram,
310 LinkProgram,
311}
312
313#[derive(Debug)]
315pub(crate) enum VersionKind {
316 Device,
317 Platform,
318}
319
320#[derive(Debug, thiserror::Error)]
322#[error("OpenCL ({kind:?}) version too low to use {function:?} (detected: {detected}, required: {required}).")]
323pub struct VersionLowError {
324 detected: OpenclVersion,
325 required: OpenclVersion,
326 function: ApiFunction,
327 kind: VersionKind,
328}
329
330#[derive(Debug, thiserror::Error)]
332pub enum ApiWrapperError {
333 #[error("Unable to get platform id list after {} seconds of waiting.", _0)]
334 GetPlatformIdsPlatformListUnavailable(u64),
335 #[error("`devices_max` can not be zero.")]
336 GetDeviceIdsDevicesMaxZero,
337 #[error("No devices specified.")]
338 CreateContextNoDevicesSpecified,
339 #[error("Buffer length and data length and do not match.")]
340 CreateBufferDataLengthMismatch,
341 #[error(
342 "One or more of the devices contained in the list provided to \
343 '::create_context` doesn't support the cl_gl_sharing extension and cannot be \
344 used to create a context associated with OpenGL. [FIXME: determine recommended \
345 resolution - gl_device list fn doesn't work yet]."
346 )]
347 CreateContextClGlSharingUnsupported,
348 #[error("Length of 'devices' must be greater than zero.")]
349 CreateProgramWithBinaryDevicesLenZero,
350 #[error(
351 "Length of 'devices' must equal the length of 'binaries' \
352 (e.g. one binary per device)."
353 )]
354 CreateProgramWithBinaryDevicesLenMismatch,
355 #[error(
356 "The specified function does not exist for the implementation or \
357 'platform' is not a valid platform."
358 )]
359 GetExtensionFunctionAddressForPlatformInvalidFunction,
360 #[error("No OpenCL platforms found. Check your driver.")]
361 DefaultPlatformNoPlatforms,
362 #[error(
363 "The default platform set by the environment variable \
364 'OCL_DEFAULT_PLATFORM_IDX' has an index which is out of range \
365 (index: [{default_platform_idx}], max: [{max_idx}])."
366 )]
367 DefaultPlatformEnvVarBadIdx {
368 default_platform_idx: usize,
369 max_idx: usize,
370 },
371 #[error(
372 "The default device type set by the environment variable \
373 'OCL_DEFAULT_DEVICE_TYPE': ('{0}') is invalid. Valid types are: 'DEFAULT', 'CPU', \
374 'GPU', 'ACCELERATOR', 'CUSTOM', and 'ALL'."
375 )]
376 DefaultDeviceTypeInvalidType(String),
377 #[error("The function pointer to {0} was not resolved.")]
378 ExtensionFunctionPointerNotResolved(String),
379}
380
381struct DevicePtrList(Vec<cl_device_id>);
392
393impl DevicePtrList {
394 fn new<D: ClDeviceIdPtr>(devices: Option<&[D]>) -> DevicePtrList {
396 let list = match devices {
397 Some(device_ids) => device_ids.iter().map(|d| d.as_ptr()).collect::<Vec<_>>(),
398 None => Vec::new(),
399 };
400
401 DevicePtrList(list)
402 }
403
404 fn as_ptr(&self) -> *const cl_device_id {
406 match self.0.len() {
407 0 => ptr::null(),
408 _ => self.0.as_ptr(),
409 }
410 }
411
412 fn num(&self) -> u32 {
414 self.0.len() as u32
415 }
416}
417
418impl<D> From<Option<&[D]>> for DevicePtrList
419where
420 D: ClDeviceIdPtr,
421{
422 fn from(devices: Option<&[D]>) -> DevicePtrList {
423 DevicePtrList::new(devices)
424 }
425}
426
427fn resolve_event_ptrs<En: ClNullEventPtr, Ewl: ClWaitListPtr>(
429 wait_list: Option<Ewl>,
430 new_event: Option<En>,
431) -> (cl_uint, *const cl_event, *mut cl_event) {
432 let (wait_list_len, wait_list_ptr) = match wait_list {
435 Some(wl) => {
436 if wl.count() > 0 {
437 (wl.count(), unsafe { wl.as_ptr_ptr() } as *const cl_event)
438 } else {
439 (0, ptr::null() as *const cl_event)
440 }
441 }
442 None => (0, ptr::null() as *const cl_event),
443 };
444
445 let new_event_ptr = match new_event {
446 Some(mut ne) => ne.alloc_new(),
447 None => ptr::null_mut() as *mut cl_event,
448 };
449
450 (wait_list_len, wait_list_ptr, new_event_ptr)
451}
452
453fn resolve_work_dims(work_dims: Option<&[usize; 3]>) -> *const size_t {
455 match work_dims {
456 Some(w) => w as *const [usize; 3] as *const size_t,
457 None => ptr::null(),
458 }
459}
460
461pub(crate) fn verify_versions(
463 versions: &[OpenclVersion],
464 required_version: [u16; 2],
465 function: ApiFunction,
466 kind: VersionKind,
467) -> OclCoreResult<()> {
468 let reqd_ver = OpenclVersion::from(required_version);
469
470 for &d_ver in versions {
471 if d_ver < reqd_ver {
472 return Err(VersionLowError {
473 detected: d_ver,
474 required: reqd_ver,
475 function,
476 kind,
477 }
478 .into());
479 }
480 }
481
482 Ok(())
483}
484
485fn verify_platform_version<V: ClVersions>(
488 provided_version: Option<&OpenclVersion>,
489 required_version: [u16; 2],
490 fallback_version_source: &V,
491 function: ApiFunction,
492) -> OclCoreResult<()> {
493 match provided_version {
494 Some(pv) => {
495 let vers = [*pv];
496 verify_versions(&vers, required_version, function, VersionKind::Platform)
497 }
498 None => fallback_version_source.verify_platform_version(required_version),
499 }
500}
501
502fn verify_device_version<V: ClVersions>(
505 provided_version: Option<&OpenclVersion>,
506 required_version: [u16; 2],
507 fallback_version_source: &V,
508 function: ApiFunction,
509) -> OclCoreResult<()> {
510 match provided_version {
511 Some(pv) => {
512 let ver = [*pv];
513 verify_versions(&ver, required_version, function, VersionKind::Device)
514 }
515 None => fallback_version_source.verify_device_versions(required_version),
516 }
517}
518
519fn verify_device_versions<V: ClVersions>(
521 provided_versions: Option<&[OpenclVersion]>,
522 required_version: [u16; 2],
523 fallback_versions_source: &V,
524 function: ApiFunction,
525) -> OclCoreResult<()> {
526 match provided_versions {
527 Some(pv) => verify_versions(pv, required_version, function, VersionKind::Device),
528 None => fallback_versions_source.verify_device_versions(required_version),
529 }
530}
531
532pub fn get_platform_ids() -> OclCoreResult<Vec<PlatformId>> {
544 let mut num_platforms = 0 as cl_uint;
545
546 let mut errcode: cl_int =
548 unsafe { ffi::clGetPlatformIDs(0, ptr::null_mut(), &mut num_platforms) };
549
550 if errcode == Status::CL_PLATFORM_NOT_FOUND_KHR as i32 {
553 let sleep_ms = PLATFORM_IDS_ATTEMPT_TIMEOUT_MS;
555 let mut iters_rmng = PLATFORM_IDS_ATTEMPT_COUNT;
556
557 while errcode == Status::CL_PLATFORM_NOT_FOUND_KHR as i32 {
558 if iters_rmng == 0 {
559 return Err(ApiWrapperError::GetPlatformIdsPlatformListUnavailable(
560 (PLATFORM_IDS_ATTEMPT_COUNT * sleep_ms) / 1000,
561 )
562 .into());
563 }
564
565 thread::sleep(Duration::from_millis(sleep_ms));
567
568 errcode = unsafe { ffi::clGetPlatformIDs(0, ptr::null_mut(), &mut num_platforms) };
570
571 iters_rmng -= 1;
572 }
573 }
574
575 eval_errcode(errcode, (), "clGetPlatformIDs", None::<String>)?;
576
577 if num_platforms == 0 {
579 return Ok(vec![]);
580 }
581
582 let mut null_vec: Vec<usize> = iter::repeat(0).take(num_platforms as usize).collect();
584 let (ptr, len, cap) = (null_vec.as_mut_ptr(), null_vec.len(), null_vec.capacity());
585
586 let mut platforms: Vec<PlatformId> = unsafe {
588 mem::forget(null_vec);
589 Vec::from_raw_parts(ptr as *mut PlatformId, len, cap)
590 };
591
592 errcode = unsafe {
593 ffi::clGetPlatformIDs(
594 num_platforms,
595 platforms.as_mut_ptr() as *mut cl_platform_id,
596 ptr::null_mut(),
597 )
598 };
599
600 eval_errcode(errcode, platforms, "clGetPlatformIDs", None::<String>)
601}
602
603pub fn get_platform_info<P: ClPlatformIdPtr>(
605 platform: P,
606 request: PlatformInfo,
607) -> OclCoreResult<PlatformInfoResult> {
608 let mut result_size = 0 as size_t;
609
610 let errcode = unsafe {
611 ffi::clGetPlatformInfo(
612 platform.as_ptr(),
613 request as cl_platform_info,
614 0 as size_t,
615 ptr::null_mut(),
616 &mut result_size as *mut size_t,
617 )
618 };
619
620 eval_errcode(errcode, (), "clGetPlatformInfo", None::<String>)?;
624
625 if result_size == 0 {
627 return PlatformInfoResult::from_bytes(request, vec![]);
628 }
629
630 let mut result: Vec<u8> = iter::repeat(32u8).take(result_size as usize).collect();
631
632 let errcode = unsafe {
633 ffi::clGetPlatformInfo(
634 platform.as_ptr(),
635 request as cl_platform_info,
636 result_size as size_t,
637 result.as_mut_ptr() as *mut c_void,
638 ptr::null_mut() as *mut size_t,
639 )
640 };
641
642 let result = eval_errcode(errcode, result, "clGetPlatformInfo", None::<String>)?;
643 PlatformInfoResult::from_bytes(request, result)
644}
645
646pub fn get_device_ids<P: ClPlatformIdPtr>(
652 platform: P,
653 device_types: Option<DeviceType>,
654 devices_max: Option<u32>,
655) -> OclCoreResult<Vec<DeviceId>> {
656 let device_types = device_types.unwrap_or(default_device_type()?);
657 let mut devices_available: cl_uint = 0;
658
659 let devices_max = match devices_max {
660 Some(d) => {
661 if d == 0 {
662 return Err(ApiWrapperError::GetDeviceIdsDevicesMaxZero.into());
663 } else {
664 d
665 }
666 }
667 None => crate::DEVICES_MAX,
668 };
669
670 let mut device_ids: Vec<DeviceId> = iter::repeat(unsafe { DeviceId::null() })
671 .take(devices_max as usize)
672 .collect();
673
674 let errcode = unsafe {
675 ffi::clGetDeviceIDs(
676 platform.as_ptr(),
677 device_types.bits() as cl_device_type,
678 devices_max,
679 device_ids.as_mut_ptr() as *mut cl_device_id,
680 &mut devices_available,
681 )
682 };
683 eval_errcode(errcode, (), "clGetDeviceIDs", None::<String>)?;
684
685 unsafe {
687 device_ids.set_len(devices_available as usize);
688 }
689 device_ids.shrink_to_fit();
690
691 Ok(device_ids)
692}
693
694pub fn get_device_info_raw<D: ClDeviceIdPtr>(device: D, request: u32) -> OclCoreResult<Vec<u8>> {
696 let mut result_size: size_t = 0;
697
698 let errcode = unsafe {
699 ffi::clGetDeviceInfo(
700 device.as_ptr() as cl_device_id,
701 request as cl_device_info,
702 0 as size_t,
703 ptr::null_mut(),
704 &mut result_size as *mut size_t,
705 )
706 };
707
708 if errcode < 0 {
714 if Status::from_i32(errcode).unwrap() == Status::CL_INVALID_VALUE {
715 return Err(OclCoreError::String(
716 "<unavailable (CL_INVALID_VALUE)>".to_string(),
717 ));
718 } else if Status::from_i32(errcode).unwrap() == Status::CL_INVALID_OPERATION {
719 return Err(OclCoreError::String(
720 "<unavailable (CL_INVALID_OPERATION)>".to_string(),
721 ));
722 }
723 }
724
725 eval_errcode(errcode, (), "clGetDeviceInfo", None::<String>)?;
726
727 if result_size == 0 {
729 return Ok(vec![]);
730 }
731
732 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
733
734 let errcode = unsafe {
735 ffi::clGetDeviceInfo(
736 device.as_ptr() as cl_device_id,
737 request as cl_device_info,
738 result_size as size_t,
739 result.as_mut_ptr() as *mut _ as *mut c_void,
740 ptr::null_mut(),
741 )
742 };
743
744 eval_errcode(errcode, result, "clGetDeviceInfo", None::<String>)
745}
746
747pub fn get_device_info<D: ClDeviceIdPtr>(
749 device: D,
750 request: DeviceInfo,
751) -> OclCoreResult<DeviceInfoResult> {
752 let result = get_device_info_raw(device, request as cl_device_info)?;
753
754 match request {
755 DeviceInfo::MaxWorkItemSizes => {
756 let max_wi_dims = match get_device_info(device, DeviceInfo::MaxWorkItemDimensions)? {
757 DeviceInfoResult::MaxWorkItemDimensions(d) => d,
758 _ => panic!(
760 "get_device_info(): Error determining dimensions for \
761 'DeviceInfo::MaxWorkItemSizes' due to mismatched variants."
762 ),
763 };
764 DeviceInfoResult::from_bytes_max_work_item_sizes(request, result, max_wi_dims)
765 }
766 _ => DeviceInfoResult::from_bytes(request, result),
767 }
768}
769
770pub fn create_sub_devices(device_version: Option<&OpenclVersion>) -> OclCoreResult<()> {
774 let _ = device_version;
781 unimplemented!();
782}
783
784pub unsafe fn retain_device(
788 device: &DeviceId,
789 device_version: Option<&OpenclVersion>,
790) -> OclCoreResult<()> {
791 verify_device_version(device_version, [1, 2], device, ApiFunction::RetainDevice)?;
792 eval_errcode(
793 ffi::clRetainDevice(device.as_ptr()),
794 (),
795 "clRetainDevice",
796 None::<String>,
797 )
798}
799
800pub unsafe fn release_device(
804 device: &DeviceId,
805 device_version: Option<&OpenclVersion>,
806) -> OclCoreResult<()> {
807 verify_device_version(device_version, [1, 2], device, ApiFunction::ReleaseDevice)?;
808 eval_errcode(
809 ffi::clReleaseDevice(device.as_ptr()),
810 (),
811 "clReleaseDevice",
812 None::<String>,
813 )
814}
815
816pub fn create_context<D: ClDeviceIdPtr>(
832 properties: Option<&ContextProperties>,
833 device_ids: &[D],
834 pfn_notify: Option<CreateContextCallbackFn>,
835 user_data: Option<UserDataPtr>,
836) -> OclCoreResult<Context> {
837 if device_ids.is_empty() {
838 return Err(ApiWrapperError::CreateContextNoDevicesSpecified.into());
839 }
840
841 if let Some(properties) = properties {
847 if properties.contains_gl_context_or_sharegroup() {
848 for &device in device_ids {
849 match device_supports_cl_gl_sharing(device) {
850 Ok(true) => {}
851 Ok(false) => {
852 return Err(ApiWrapperError::CreateContextClGlSharingUnsupported.into())
853 }
854 Err(err) => return Err(err),
855 }
856 }
857 }
858 }
859
860 let properties_bytes: Vec<isize> = match properties {
861 Some(props) => props.to_raw(),
862 None => Vec::<isize>::with_capacity(0),
863 };
864
865 let properties_ptr = if properties_bytes.is_empty() {
872 ptr::null() as *const cl_context_properties
873 } else {
874 properties_bytes.as_ptr()
875 };
876
877 let user_data_ptr = match user_data {
879 Some(_) => ptr::null_mut(),
880 None => ptr::null_mut(),
881 };
882
883 let device_ids: Vec<_> = device_ids.iter().map(|d| d.as_ptr()).collect();
884
885 let mut errcode: cl_int = 0;
886
887 let context_ptr = unsafe {
888 ffi::clCreateContext(
889 properties_ptr,
890 device_ids.len() as cl_uint,
891 device_ids.as_ptr() as *const cl_device_id,
892 pfn_notify,
893 user_data_ptr,
894 &mut errcode,
895 )
896 };
897 eval_errcode(errcode, context_ptr, "clCreateContext", None::<String>)
900 .map(|ctx_ptr| unsafe { Context::from_raw_create_ptr(ctx_ptr) })
901}
902
903pub fn create_context_from_type<D: ClDeviceIdPtr>(
915 properties: Option<&ContextProperties>,
916 device_type: DeviceType,
917 pfn_notify: Option<CreateContextCallbackFn>,
918 user_data: Option<UserDataPtr>,
919) -> OclCoreResult<Context> {
920 let properties_bytes: Vec<isize> = match properties {
924 Some(props) => props.to_raw(),
925 None => Vec::<isize>::with_capacity(0),
926 };
927
928 let properties_ptr = if properties_bytes.is_empty() {
935 ptr::null() as *const cl_context_properties
936 } else {
937 properties_bytes.as_ptr()
938 };
939
940 let user_data_ptr = match user_data {
942 Some(_) => ptr::null_mut(),
943 None => ptr::null_mut(),
944 };
945
946 let mut errcode: cl_int = 0;
947
948 let context_ptr = unsafe {
949 ffi::clCreateContextFromType(
950 properties_ptr,
951 device_type.bits(),
952 pfn_notify,
953 user_data_ptr,
954 &mut errcode,
955 )
956 };
957 eval_errcode(
958 errcode,
959 context_ptr,
960 "clCreateContextFromType",
961 None::<String>,
962 )
963 .map(|ctx_ptr| unsafe { Context::from_raw_create_ptr(ctx_ptr) })
964}
965
966pub unsafe fn retain_context<C>(context: C) -> OclCoreResult<()>
968where
969 C: ClContextPtr,
970{
971 eval_errcode(
972 ffi::clRetainContext(context.as_ptr()),
973 (),
974 "clRetainContext",
975 None::<String>,
976 )
977}
978
979pub unsafe fn release_context<C>(context: C) -> OclCoreResult<()>
981where
982 C: ClContextPtr,
983{
984 eval_errcode(
985 ffi::clReleaseContext(context.as_ptr()),
986 (),
987 "clReleaseContext",
988 None::<String>,
989 )
990}
991
992fn get_context_info_unparsed<C>(context: C, request: ContextInfo) -> OclCoreResult<Vec<u8>>
993where
994 C: ClContextPtr,
995{
996 let mut result_size: size_t = 0;
997
998 let errcode = unsafe {
999 ffi::clGetContextInfo(
1000 context.as_ptr() as cl_context,
1001 request as cl_context_info,
1002 0 as size_t,
1003 ptr::null_mut(),
1004 &mut result_size as *mut usize,
1005 )
1006 };
1007
1008 eval_errcode(errcode, (), "clGetContextInfo", None::<String>)?;
1009
1010 if !cfg!(release) {
1014 let err_if_zero_result_size = request as cl_context_info == ffi::CL_CONTEXT_DEVICES;
1015
1016 if result_size > 10000 || (result_size == 0 && err_if_zero_result_size) {
1017 return Err(OclCoreError::String(
1018 "\n\nocl::core::context_info(): \
1019 Possible invalid context detected. \n\
1020 Context info result size is either '> 10k bytes' or '== 0'. Almost certainly an \n\
1021 invalid context object. If not, please file an issue at: \n\
1022 https://github.com/cogciprocate/ocl/issues.\n\n"
1023 .to_string(),
1024 ));
1025 }
1026 }
1027
1028 if result_size == 0 {
1030 return Ok(vec![]);
1031 }
1032
1033 let mut result: Vec<u8> = iter::repeat(0).take(result_size).collect();
1034
1035 let errcode = unsafe {
1036 ffi::clGetContextInfo(
1037 context.as_ptr() as cl_context,
1038 request as cl_context_info,
1039 result_size as size_t,
1040 result.as_mut_ptr() as *mut c_void,
1041 ptr::null_mut(),
1042 )
1043 };
1044
1045 eval_errcode(errcode, result, "clGetContextInfo", None::<String>)
1046}
1047
1048pub fn get_context_info<C>(context: C, request: ContextInfo) -> OclCoreResult<ContextInfoResult>
1058where
1059 C: ClContextPtr,
1060{
1061 ContextInfoResult::from_bytes(request, get_context_info_unparsed(context, request)?)
1062}
1063
1064pub fn get_context_platform<C>(context: C) -> OclCoreResult<Option<PlatformId>>
1070where
1071 C: ClContextPtr,
1072{
1073 let props_raw_bytes = get_context_info_unparsed(context, ContextInfo::Properties)?;
1074
1075 let prop = unsafe {
1076 let props_raw = crate::util::bytes_into_vec::<isize>(props_raw_bytes)?;
1077 ContextProperties::extract_property_from_raw(crate::ContextProperty::Platform, &props_raw)
1078 };
1079
1080 if let Some(crate::ContextPropertyValue::Platform(plat)) = prop {
1081 Ok(Some(plat))
1082 } else {
1083 Ok(None)
1084 }
1085}
1086
1087#[cfg(not(feature = "opencl_vendor_mesa"))]
1093pub fn get_gl_context_info_khr(
1094 properties: &ContextProperties,
1095 request: GlContextInfo,
1096) -> OclCoreResult<GlContextInfoResult> {
1097 let cl_get_gl_context_info_khr_fn: ffi::clGetGLContextInfoKHR_fn = unsafe {
1098 let fn_name = match ::std::ffi::CString::new("clGetGLContextInfoKHR") {
1099 Ok(s) => s,
1100 Err(err) => return Err(err.into()),
1101 };
1102
1103 let plat = match properties.get_platform() {
1104 Some(p) => p,
1105 None => {
1106 return Err("ocl::core::get_gl_context_info_khr: \
1107 Context properties must specify a platform."
1108 .into());
1109 }
1110 };
1111
1112 let fn_ptr = ffi::clGetExtensionFunctionAddressForPlatform(
1113 plat.as_ptr(),
1114 fn_name.as_ptr() as *mut _,
1115 );
1116
1117 if fn_ptr.is_null() {
1118 return Err("Unable to get extension function \
1119 address for clGetGLContextInfoKHR. The function is not supported by this \
1120 platform."
1121 .into());
1122 }
1123
1124 std::mem::transmute(fn_ptr)
1125 };
1126
1127 let props_bytes = properties.to_raw();
1128 let mut result_size: size_t = 0;
1129
1130 let errcode = cl_get_gl_context_info_khr_fn(
1131 props_bytes.as_ptr(),
1132 request as cl_gl_context_info,
1133 0 as size_t,
1134 ptr::null_mut(),
1135 &mut result_size as *mut usize,
1136 );
1137
1138 eval_errcode(errcode, (), "clGetGlContextInfoKhr", None::<String>)?;
1142
1143 if result_size == 0 {
1144 return GlContextInfoResult::from_bytes(request, vec![]);
1145 }
1146
1147 let mut result: Vec<u8> = iter::repeat(0).take(result_size).collect();
1154
1155 let errcode = cl_get_gl_context_info_khr_fn(
1156 props_bytes.as_ptr(),
1157 request as cl_gl_context_info,
1158 result_size as size_t,
1159 result.as_mut_ptr() as *mut c_void,
1160 ptr::null_mut(),
1161 );
1162
1163 let result = eval_errcode(errcode, result, "clGetGlContextInfoKhr", None::<String>)?;
1164 GlContextInfoResult::from_bytes(request, result)
1165}
1166
1167pub fn create_command_queue<C, D>(
1173 context: C,
1174 device: D,
1175 properties: Option<CommandQueueProperties>,
1176) -> OclCoreResult<CommandQueue>
1177where
1178 C: ClContextPtr,
1179 D: ClDeviceIdPtr,
1180{
1181 verify_context(context)?;
1183
1184 let cmd_queue_props = match properties {
1185 Some(p) => p.bits,
1186 None => 0,
1187 };
1188
1189 let mut errcode: cl_int = 0;
1190
1191 let cq_ptr = unsafe {
1192 ffi::clCreateCommandQueue(
1193 context.as_ptr(),
1194 device.as_ptr(),
1195 cmd_queue_props,
1196 &mut errcode,
1197 )
1198 };
1199 eval_errcode(errcode, cq_ptr, "clCreateCommandQueue", None::<String>)
1200 .map(|cq_ptr| unsafe { CommandQueue::from_raw_create_ptr(cq_ptr) })
1201}
1202
1203pub unsafe fn retain_command_queue(queue: &CommandQueue) -> OclCoreResult<()> {
1205 eval_errcode(
1206 ffi::clRetainCommandQueue(queue.as_ptr()),
1207 (),
1208 "clRetainCommandQueue",
1209 None::<String>,
1210 )
1211}
1212
1213pub unsafe fn release_command_queue(queue: &CommandQueue) -> OclCoreResult<()> {
1217 eval_errcode(
1218 ffi::clReleaseCommandQueue(queue.as_ptr()),
1219 (),
1220 "clReleaseCommandQueue",
1221 None::<String>,
1222 )
1223}
1224
1225pub fn get_command_queue_info(
1227 queue: &CommandQueue,
1228 request: CommandQueueInfo,
1229) -> OclCoreResult<CommandQueueInfoResult> {
1230 let mut result_size: size_t = 0;
1231
1232 let errcode = unsafe {
1233 ffi::clGetCommandQueueInfo(
1234 queue.as_ptr() as cl_command_queue,
1235 request as cl_command_queue_info,
1236 0 as size_t,
1237 ptr::null_mut(),
1238 &mut result_size as *mut size_t,
1239 )
1240 };
1241
1242 eval_errcode(errcode, (), "clGetCommandQueueInfo", None::<String>)?;
1243
1244 if result_size == 0 {
1246 return CommandQueueInfoResult::from_bytes(request, vec![]);
1247 }
1248
1249 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
1250
1251 let errcode = unsafe {
1252 ffi::clGetCommandQueueInfo(
1253 queue.as_ptr() as cl_command_queue,
1254 request as cl_command_queue_info,
1255 result_size,
1256 result.as_mut_ptr() as *mut _ as *mut c_void,
1257 ptr::null_mut(),
1258 )
1259 };
1260
1261 let result = eval_errcode(errcode, result, "clGetCommandQueueInfo", None::<String>)?;
1262 CommandQueueInfoResult::from_bytes(request, result)
1263}
1264
1265pub unsafe fn create_buffer<C, T>(
1277 context: C,
1278 flags: MemFlags,
1279 len: usize,
1280 data: Option<&[T]>,
1281) -> OclCoreResult<Mem>
1282where
1283 C: ClContextPtr,
1284 T: OclPrm,
1285{
1286 verify_context(context)?;
1288
1289 let mut errcode: cl_int = 0;
1290
1291 let host_ptr = match data {
1292 Some(d) => {
1293 if d.len() != len {
1294 return Err(ApiWrapperError::CreateBufferDataLengthMismatch.into());
1295 }
1296 d.as_ptr() as cl_mem
1297 }
1298 None => ptr::null_mut(),
1299 };
1300
1301 let buf_ptr = ffi::clCreateBuffer(
1302 context.as_ptr(),
1303 flags.bits() as cl_mem_flags,
1304 len * mem::size_of::<T>(),
1305 host_ptr,
1306 &mut errcode,
1307 );
1308
1309 eval_errcode(errcode, buf_ptr, "clCreateBuffer", None::<String>)
1311 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1312}
1313
1314#[cfg(not(feature = "opencl_vendor_mesa"))]
1324pub unsafe fn create_from_gl_buffer<C>(
1325 context: C,
1326 gl_object: cl_GLuint,
1327 flags: MemFlags,
1328) -> OclCoreResult<Mem>
1329where
1330 C: ClContextPtr,
1331{
1332 verify_context(context)?;
1334
1335 let mut errcode: cl_int = 0;
1336
1337 let buf_ptr = clCreateFromGLBuffer(
1338 context.as_ptr(),
1339 flags.bits() as cl_mem_flags,
1340 gl_object,
1341 &mut errcode,
1342 );
1343
1344 eval_errcode(errcode, buf_ptr, "clCreateFromGLBuffer", None::<String>)
1345 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1346}
1347
1348#[cfg(not(feature = "opencl_vendor_mesa"))]
1358pub unsafe fn create_from_gl_renderbuffer<C>(
1359 context: C,
1360 renderbuffer: cl_GLuint,
1361 flags: MemFlags,
1362) -> OclCoreResult<Mem>
1363where
1364 C: ClContextPtr,
1365{
1366 verify_context(context)?;
1368
1369 let mut errcode: cl_int = 0;
1370
1371 let buf_ptr = clCreateFromGLRenderbuffer(
1372 context.as_ptr(),
1373 flags.bits() as cl_mem_flags,
1374 renderbuffer,
1375 &mut errcode,
1376 );
1377
1378 eval_errcode(
1379 errcode,
1380 buf_ptr,
1381 "clCreateFromGLRenderbuffer",
1382 None::<String>,
1383 )
1384 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1385}
1386
1387#[cfg(not(feature = "opencl_vendor_mesa"))]
1399pub unsafe fn create_from_gl_texture<C>(
1400 context: C,
1401 texture_target: cl_GLenum,
1402 miplevel: cl_GLint,
1403 texture: cl_GLuint,
1404 flags: MemFlags,
1405 device_versions: Option<&[OpenclVersion]>,
1406) -> OclCoreResult<Mem>
1407where
1408 C: ClContextPtr,
1409{
1410 verify_context(context)?;
1412
1413 verify_device_versions(
1415 device_versions,
1416 [1, 2],
1417 &context.as_ptr(),
1418 ApiFunction::CreateFromGLTexture,
1419 )?;
1420
1421 let mut errcode: cl_int = 0;
1439
1440 let buf_ptr = clCreateFromGLTexture(
1441 context.as_ptr(),
1442 flags.bits() as cl_mem_flags,
1443 texture_target,
1444 miplevel,
1445 texture,
1446 &mut errcode,
1447 );
1448
1449 eval_errcode(errcode, buf_ptr, "clCreateFromGLTexture", None::<String>)
1450 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1451}
1452
1453#[cfg(not(feature = "opencl_vendor_mesa"))]
1457pub unsafe fn create_from_gl_texture_2d<C>(
1458 context: C,
1459 texture_target: cl_GLenum,
1460 miplevel: cl_GLint,
1461 texture: cl_GLuint,
1462 flags: MemFlags,
1463) -> OclCoreResult<Mem>
1464where
1465 C: ClContextPtr,
1466{
1467 verify_context(context)?;
1469
1470 let mut errcode: cl_int = 0;
1471
1472 let buf_ptr = clCreateFromGLTexture2D(
1473 context.as_ptr(),
1474 flags.bits() as cl_mem_flags,
1475 texture_target,
1476 miplevel,
1477 texture,
1478 &mut errcode,
1479 );
1480
1481 eval_errcode(errcode, buf_ptr, "clCreateFromGLTexture2D", None::<String>)
1482 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1483}
1484
1485#[cfg(not(feature = "opencl_vendor_mesa"))]
1489pub unsafe fn create_from_gl_texture_3d<C>(
1490 context: C,
1491 texture_target: cl_GLenum,
1492 miplevel: cl_GLint,
1493 texture: cl_GLuint,
1494 flags: MemFlags,
1495) -> OclCoreResult<Mem>
1496where
1497 C: ClContextPtr,
1498{
1499 verify_context(context)?;
1501
1502 let mut errcode: cl_int = 0;
1503
1504 let buf_ptr = clCreateFromGLTexture3D(
1505 context.as_ptr(),
1506 flags.bits() as cl_mem_flags,
1507 texture_target,
1508 miplevel,
1509 texture,
1510 &mut errcode,
1511 );
1512
1513 eval_errcode(errcode, buf_ptr, "clCreateFromGLTexture3D", None::<String>)
1514 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1515}
1516
1517pub unsafe fn create_from_d3d11_buffer<C>(
1527 context: C,
1528 buffer: ffi::cl_id3d11_buffer,
1529 flags: MemFlags,
1530 extension_fns: &crate::ExtensionFunctions,
1531) -> OclCoreResult<Mem>
1532where
1533 C: ClContextPtr,
1534{
1535 verify_context(context)?;
1537
1538 match extension_fns.clCreateFromD3D11Buffer {
1539 Some(func) => {
1540 let mut errcode: cl_int = 0;
1541
1542 let buf_ptr = func(
1543 context.as_ptr(),
1544 flags.bits() as cl_mem_flags,
1545 buffer,
1546 &mut errcode,
1547 );
1548
1549 eval_errcode(errcode, buf_ptr, "clCreateFromD3D11Buffer", None::<String>)
1550 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1551 }
1552 None => Err(ApiWrapperError::ExtensionFunctionPointerNotResolved(
1553 "clCreateFromD3D11Buffer".into(),
1554 )
1555 .into()),
1556 }
1557}
1558
1559pub unsafe fn create_from_d3d11_texture2d<C>(
1569 context: C,
1570 texture: ffi::cl_id3d11_texture2d,
1571 subresource: cl_uint,
1572 flags: MemFlags,
1573 device_versions: Option<&[OpenclVersion]>,
1574 extension_fns: &crate::ExtensionFunctions,
1575) -> OclCoreResult<Mem>
1576where
1577 C: ClContextPtr,
1578{
1579 verify_context(context)?;
1581
1582 verify_device_versions(
1584 device_versions,
1585 [1, 2],
1586 &context.as_ptr(),
1587 ApiFunction::CreateFromD3D11Texture,
1588 )?;
1589
1590 match extension_fns.clCreateFromD3D11Texture2D {
1591 Some(func) => {
1592 let mut errcode: cl_int = 0;
1593
1594 let buf_ptr = func(
1595 context.as_ptr(),
1596 flags.bits() as cl_mem_flags,
1597 texture,
1598 subresource,
1599 &mut errcode,
1600 );
1601
1602 eval_errcode(
1603 errcode,
1604 buf_ptr,
1605 "clCreateFromD3D11Texture2D",
1606 None::<String>,
1607 )
1608 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1609 }
1610 None => Err(ApiWrapperError::ExtensionFunctionPointerNotResolved(
1611 "clCreateFromD3D11Texture2D".into(),
1612 )
1613 .into()),
1614 }
1615}
1616
1617pub unsafe fn create_from_d3d11_texture3d<C>(
1627 context: C,
1628 texture: ffi::cl_id3d11_texture3d,
1629 subresource: cl_uint,
1630 flags: MemFlags,
1631 device_versions: Option<&[OpenclVersion]>,
1632 extension_fns: &crate::ExtensionFunctions,
1633) -> OclCoreResult<Mem>
1634where
1635 C: ClContextPtr,
1636{
1637 verify_context(context)?;
1639
1640 verify_device_versions(
1642 device_versions,
1643 [1, 2],
1644 &context.as_ptr(),
1645 ApiFunction::CreateFromD3D11Texture,
1646 )?;
1647
1648 match extension_fns.clCreateFromD3D11Texture3D {
1649 Some(func) => {
1650 let mut errcode: cl_int = 0;
1651
1652 let buf_ptr = func(
1653 context.as_ptr(),
1654 flags.bits() as cl_mem_flags,
1655 texture,
1656 subresource,
1657 &mut errcode,
1658 );
1659
1660 eval_errcode(
1661 errcode,
1662 buf_ptr,
1663 "clCreateFromD3D11Texture3D",
1664 None::<String>,
1665 )
1666 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1667 }
1668 None => Err(ApiWrapperError::ExtensionFunctionPointerNotResolved(
1669 "clCreateFromD3D11Texture3D".into(),
1670 )
1671 .into()),
1672 }
1673}
1674
1675pub fn enqueue_acquire_d3d11_objects<En, Ewl>(
1682 command_queue: &CommandQueue,
1683 buffers: &[Mem],
1684 wait_list: Option<Ewl>,
1685 new_event: Option<En>,
1686 extension_fns: &crate::ExtensionFunctions,
1687) -> OclCoreResult<()>
1688where
1689 En: ClNullEventPtr,
1690 Ewl: ClWaitListPtr,
1691{
1692 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
1693
1694 match extension_fns.clEnqueueAcquireD3D11Objects {
1695 Some(func) => {
1696 let errcode = func(
1697 command_queue.as_ptr(),
1698 buffers.len() as u32,
1699 buffers.as_ptr() as *const cl_mem,
1700 wait_list_len,
1701 wait_list_ptr,
1702 new_event_ptr,
1703 );
1704
1705 eval_errcode(errcode, (), "clEnqueueAcquireD3D11Objects", None::<String>)
1706 }
1707 None => Err(ApiWrapperError::ExtensionFunctionPointerNotResolved(
1708 "clEnqueueAcquireD3D11Objects".into(),
1709 )
1710 .into()),
1711 }
1712}
1713
1714pub fn enqueue_release_d3d11_objects<En, Ewl>(
1721 command_queue: &CommandQueue,
1722 buffers: &[Mem],
1723 wait_list: Option<Ewl>,
1724 new_event: Option<En>,
1725 extension_fns: &crate::ExtensionFunctions,
1726) -> OclCoreResult<()>
1727where
1728 En: ClNullEventPtr,
1729 Ewl: ClWaitListPtr,
1730{
1731 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
1732
1733 match extension_fns.clEnqueueReleaseD3D11Objects {
1734 Some(func) => {
1735 let errcode = func(
1736 command_queue.as_ptr(),
1737 buffers.len() as u32,
1738 buffers.as_ptr() as *const cl_mem,
1739 wait_list_len,
1740 wait_list_ptr,
1741 new_event_ptr,
1742 );
1743
1744 eval_errcode(errcode, (), "clEnqueueReleaseD3D11Objects", None::<String>)
1745 }
1746 None => Err(ApiWrapperError::ExtensionFunctionPointerNotResolved(
1747 "clEnqueueReleaseD3D11Objects".into(),
1748 )
1749 .into()),
1750 }
1751}
1752
1753pub fn create_sub_buffer<T: OclPrm>(
1762 buffer: &Mem,
1763 flags: MemFlags,
1764 buffer_create_info: &BufferRegion<T>,
1765) -> OclCoreResult<Mem> {
1766 let buffer_create_type = BufferCreateType::Region;
1767 let buffer_create_info_bytes = buffer_create_info.to_bytes();
1768 let mut errcode = 0i32;
1769
1770 let sub_buf_ptr = unsafe {
1771 ffi::clCreateSubBuffer(
1772 buffer.as_ptr(),
1773 flags.bits(),
1774 buffer_create_type as cl_buffer_create_type,
1775 &buffer_create_info_bytes as *const _ as *const c_void,
1776 &mut errcode,
1777 )
1778 };
1779
1780 eval_errcode(errcode, sub_buf_ptr, "clCreateSubBuffer", None::<String>)
1781 .map(|ptr| unsafe { Mem::from_raw_create_ptr(ptr) })
1782}
1783
1784pub unsafe fn create_image<C, T>(
1795 context: C,
1796 flags: MemFlags,
1797 format: &ImageFormat,
1798 desc: &ImageDescriptor,
1799 data: Option<&[T]>,
1800 device_versions: Option<&[OpenclVersion]>,
1801) -> OclCoreResult<Mem>
1802where
1803 C: ClContextPtr,
1804 T: OclPrm,
1805{
1806 verify_context(context)?;
1808
1809 verify_device_versions(
1811 device_versions,
1812 [1, 2],
1813 &context.as_ptr(),
1814 ApiFunction::CreateImage,
1815 )?;
1816
1817 let mut errcode: cl_int = 0;
1818
1819 let host_ptr = match data {
1820 Some(d) => {
1821 d.as_ptr() as cl_mem
1824 }
1825 None => ptr::null_mut(),
1826 };
1827
1828 let image_ptr = ffi::clCreateImage(
1829 context.as_ptr(),
1830 flags.bits() as cl_mem_flags,
1831 &format.to_raw() as *const cl_image_format,
1832 &desc.to_raw() as *const cl_image_desc,
1833 host_ptr,
1834 &mut errcode as *mut cl_int,
1835 );
1836
1837 eval_errcode(errcode, image_ptr, "clCreateImage", None::<String>)
1838 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1839}
1840
1841pub unsafe fn retain_mem_object(mem: &Mem) -> OclCoreResult<()> {
1843 eval_errcode(
1844 ffi::clRetainMemObject(mem.as_ptr()),
1845 (),
1846 "clRetainMemObject",
1847 None::<String>,
1848 )
1849}
1850
1851pub unsafe fn release_mem_object(mem: &Mem) -> OclCoreResult<()> {
1853 eval_errcode(
1854 ffi::clReleaseMemObject(mem.as_ptr()),
1855 (),
1856 "clReleaseMemObject",
1857 None::<String>,
1858 )
1859}
1860
1861pub fn get_supported_image_formats<C>(
1872 context: C,
1873 flags: MemFlags,
1874 image_type: MemObjectType,
1875) -> OclCoreResult<Vec<ImageFormatParseResult>>
1876where
1877 C: ClContextPtr,
1878{
1879 let mut num_image_formats = 0 as cl_uint;
1880
1881 let errcode = unsafe {
1882 ffi::clGetSupportedImageFormats(
1883 context.as_ptr(),
1884 flags.bits() as cl_mem_flags,
1885 image_type as cl_mem_object_type,
1886 0 as cl_uint,
1887 ptr::null_mut() as *mut cl_image_format,
1888 &mut num_image_formats as *mut cl_uint,
1889 )
1890 };
1891 eval_errcode(errcode, (), "clGetSupportedImageFormats", None::<String>)?;
1892
1893 if num_image_formats == 0 {
1895 return Ok(vec![]);
1896 }
1897
1898 let mut image_formats: Vec<cl_image_format> = (0..(num_image_formats as usize))
1899 .map(|_| ImageFormat::new_raw())
1900 .collect();
1901
1902 debug_assert!(image_formats.len() == num_image_formats as usize && !image_formats.is_empty());
1903
1904 let errcode = unsafe {
1905 ffi::clGetSupportedImageFormats(
1906 context.as_ptr(),
1907 flags.bits() as cl_mem_flags,
1908 image_type as cl_mem_object_type,
1909 num_image_formats,
1910 image_formats.as_mut_ptr() as *mut _ as *mut cl_image_format,
1911 ptr::null_mut(),
1912 )
1913 };
1914
1915 eval_errcode(errcode, (), "clGetSupportedImageFormats", None::<String>)?;
1916 Ok(ImageFormat::list_from_raw(image_formats))
1917}
1918
1919pub fn get_mem_object_info(obj: &Mem, request: MemInfo) -> OclCoreResult<MemInfoResult> {
1921 let mut result_size: size_t = 0;
1922
1923 let errcode = unsafe {
1924 ffi::clGetMemObjectInfo(
1925 obj.as_ptr() as cl_mem,
1926 request as cl_mem_info,
1927 0 as size_t,
1928 ptr::null_mut(),
1929 &mut result_size as *mut size_t,
1930 )
1931 };
1932
1933 eval_errcode(errcode, (), "clGetMemObjectInfo", None::<String>)?;
1934
1935 if result_size == 0 {
1937 return MemInfoResult::from_bytes(request, vec![]);
1938 }
1939
1940 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
1941
1942 let errcode = unsafe {
1943 ffi::clGetMemObjectInfo(
1944 obj.as_ptr() as cl_mem,
1945 request as cl_mem_info,
1946 result_size,
1947 result.as_mut_ptr() as *mut _ as *mut c_void,
1948 ptr::null_mut(),
1949 )
1950 };
1951 let result = eval_errcode(errcode, result, "clGetMemObjectInfo", None::<String>)?;
1952 MemInfoResult::from_bytes(request, result)
1953}
1954
1955pub fn get_image_info(obj: &Mem, request: ImageInfo) -> OclCoreResult<ImageInfoResult> {
1957 let mut result_size: size_t = 0;
1958
1959 let errcode = unsafe {
1960 ffi::clGetImageInfo(
1961 obj.as_ptr() as cl_mem,
1962 request as cl_image_info,
1963 0 as size_t,
1964 ptr::null_mut(),
1965 &mut result_size as *mut size_t,
1966 )
1967 };
1968
1969 eval_errcode(errcode, (), "clGetImageInfo", None::<String>)?;
1970
1971 if result_size == 0 {
1973 return ImageInfoResult::from_bytes(request, vec![]);
1974 }
1975
1976 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
1977
1978 let errcode = unsafe {
1979 ffi::clGetImageInfo(
1980 obj.as_ptr() as cl_mem,
1981 request as cl_image_info,
1982 result_size,
1983 result.as_mut_ptr() as *mut _ as *mut c_void,
1984 ptr::null_mut(),
1985 )
1986 };
1987
1988 let result = eval_errcode(errcode, result, "clGetImageInfo", None::<String>)?;
1989 ImageInfoResult::from_bytes(request, result)
1990}
1991
1992pub fn set_mem_object_destructor_callback() -> OclCoreResult<()> {
1994 unimplemented!();
1998}
1999
2000pub fn create_sampler<C>(
2008 context: C,
2009 normalize_coords: bool,
2010 addressing_mode: AddressingMode,
2011 filter_mode: FilterMode,
2012) -> OclCoreResult<Sampler>
2013where
2014 C: ClContextPtr,
2015{
2016 let mut errcode = 0;
2017
2018 let sampler = unsafe {
2019 Sampler::from_raw_create_ptr(ffi::clCreateSampler(
2020 context.as_ptr(),
2021 normalize_coords as cl_bool,
2022 addressing_mode as cl_addressing_mode,
2023 filter_mode as cl_filter_mode,
2024 &mut errcode,
2025 ))
2026 };
2027
2028 eval_errcode(errcode, sampler, "clCreateSampler", None::<String>)
2029}
2030
2031pub unsafe fn retain_sampler(sampler: &Sampler) -> OclCoreResult<()> {
2033 eval_errcode(
2034 ffi::clRetainSampler(sampler.as_ptr()),
2035 (),
2036 "clRetainSampler",
2037 None::<String>,
2038 )
2039}
2040
2041pub unsafe fn release_sampler(sampler: &Sampler) -> OclCoreResult<()> {
2043 eval_errcode(
2044 ffi::clReleaseSampler(sampler.as_ptr()),
2045 (),
2046 "clReleaseSampler",
2047 None::<String>,
2048 )
2049}
2050
2051pub fn get_sampler_info(obj: &Sampler, request: SamplerInfo) -> OclCoreResult<SamplerInfoResult> {
2055 let mut result_size: size_t = 0;
2056
2057 let errcode = unsafe {
2058 ffi::clGetSamplerInfo(
2059 obj.as_ptr() as cl_sampler,
2060 request as cl_sampler_info,
2061 0 as size_t,
2062 ptr::null_mut(),
2063 &mut result_size as *mut size_t,
2064 )
2065 };
2066
2067 eval_errcode(errcode, (), "clGetSamplerInfo", None::<String>)?;
2072
2073 if result_size == 0 {
2075 return SamplerInfoResult::from_bytes(request, vec![]);
2076 }
2077
2078 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2079
2080 let errcode = unsafe {
2081 ffi::clGetSamplerInfo(
2082 obj.as_ptr() as cl_sampler,
2083 request as cl_sampler_info,
2084 result_size,
2085 result.as_mut_ptr() as *mut _ as *mut c_void,
2086 ptr::null_mut(),
2087 )
2088 };
2089
2090 let result = eval_errcode(errcode, result, "clGetSamplerInfo", None::<String>)?;
2091 SamplerInfoResult::from_bytes(request, result)
2092}
2093
2094pub fn create_program_with_source<C>(context: C, src_strings: &[CString]) -> OclCoreResult<Program>
2100where
2101 C: ClContextPtr,
2102{
2103 verify_context(context)?;
2105
2106 let ks_lens: Vec<usize> = src_strings.iter().map(|cs| cs.as_bytes().len()).collect();
2108
2109 let kern_string_ptrs: Vec<*const _> = src_strings.iter().map(|cs| cs.as_ptr()).collect();
2111
2112 let mut errcode: cl_int = 0;
2113
2114 let program_ptr = unsafe {
2115 ffi::clCreateProgramWithSource(
2116 context.as_ptr(),
2117 kern_string_ptrs.len() as cl_uint,
2118 kern_string_ptrs.as_ptr() as *const *const _,
2119 ks_lens.as_ptr() as *const usize,
2120 &mut errcode,
2121 )
2122 };
2123
2124 eval_errcode(
2125 errcode,
2126 program_ptr,
2127 "clCreateProgramWithSource",
2128 None::<String>,
2129 )
2130 .map(|ptr| unsafe { Program::from_raw_create_ptr(ptr) })
2131}
2132
2133pub fn create_program_with_binary<C, D>(
2141 context: C,
2142 devices: &[D],
2143 binaries: &[&[u8]],
2144) -> OclCoreResult<Program>
2145where
2146 C: ClContextPtr,
2147 D: ClDeviceIdPtr,
2148{
2149 if devices.is_empty() {
2150 return Err(ApiWrapperError::CreateProgramWithBinaryDevicesLenZero.into());
2151 }
2152
2153 if devices.len() != binaries.len() {
2154 return Err(ApiWrapperError::CreateProgramWithBinaryDevicesLenMismatch.into());
2155 }
2156
2157 let lengths: Vec<usize> = binaries.iter().map(|bin| bin.len()).collect();
2158 let mut binary_status: Vec<i32> = iter::repeat(0).take(devices.len()).collect();
2159 let mut errcode: cl_int = 0;
2160
2161 let ptrs = binaries.iter().map(|bin| bin.as_ptr()).collect::<Vec<_>>();
2162
2163 let program = unsafe {
2164 ffi::clCreateProgramWithBinary(
2165 context.as_ptr(),
2166 devices.len() as u32,
2167 devices.as_ptr() as *const _ as *const cl_device_id,
2168 lengths.as_ptr(),
2169 ptrs.as_ptr() as *const *const u8,
2170 binary_status.as_mut_ptr(),
2171 &mut errcode,
2172 )
2173 };
2174
2175 eval_errcode(errcode, (), "clCreateProgramWithBinary", None::<String>)?;
2176
2177 for (i, item) in binary_status.iter().enumerate() {
2178 eval_errcode(
2179 *item,
2180 (),
2181 "clCreateProgramWithBinary",
2182 Some(format!("Device [{}]", i)),
2183 )?;
2184 }
2185
2186 unsafe { Ok(Program::from_raw_create_ptr(program)) }
2187}
2188
2189pub fn create_program_with_built_in_kernels(
2193 device_version: Option<&OpenclVersion>,
2194) -> OclCoreResult<()> {
2195 let _ = device_version;
2201 unimplemented!();
2202}
2203
2204#[cfg(feature = "opencl_version_2_1")]
2208pub fn create_program_with_il<C>(
2209 context: C,
2210 il: &[u8],
2211 device_versions: Option<&[OpenclVersion]>,
2212) -> OclCoreResult<Program>
2213where
2214 C: ClContextPtr + ClVersions,
2215{
2216 verify_device_versions(
2217 device_versions,
2218 [2, 1],
2219 &context,
2220 ApiFunction::CreateProgramWithIl,
2221 )?;
2222
2223 let mut errcode: cl_int = 0;
2224
2225 let program_ptr = unsafe {
2226 ffi::clCreateProgramWithIL(
2227 context.as_ptr(),
2228 il.as_ptr() as *mut c_void,
2229 il.len(),
2230 &mut errcode,
2231 )
2232 };
2233
2234 eval_errcode(
2235 errcode,
2236 program_ptr,
2237 "clCreateProgramWithIL",
2238 None::<String>,
2239 )
2240 .map(|ptr| unsafe { Program::from_raw_create_ptr(ptr) })
2241}
2242
2243pub unsafe fn retain_program(program: &Program) -> OclCoreResult<()> {
2245 eval_errcode(
2246 ffi::clRetainProgram(program.as_ptr()),
2247 (),
2248 "clRetainProgram",
2249 None::<String>,
2250 )
2251}
2252
2253pub unsafe fn release_program(program: &Program) -> OclCoreResult<()> {
2255 eval_errcode(
2256 ffi::clReleaseProgram(program.as_ptr()),
2257 (),
2258 "clReleaseKernel",
2259 None::<String>,
2260 )
2261}
2262
2263pub struct UserDataPh(usize);
2264
2265impl UserDataPh {
2266 fn unwrapped(&self) -> *mut c_void {
2267 ptr::null_mut()
2268 }
2269}
2270
2271pub fn build_program<D: ClDeviceIdPtr>(
2280 program: &Program,
2281 devices: Option<&[D]>,
2282 options: &CString,
2283 pfn_notify: Option<BuildProgramCallbackFn>,
2284 user_data: Option<Box<UserDataPh>>,
2285) -> OclCoreResult<()> {
2286 assert!(
2287 pfn_notify.is_none() && user_data.is_none(),
2288 "ocl::core::build_program(): Callback functions not yet implemented."
2289 );
2290
2291 let device_ptrs = DevicePtrList::from(devices);
2292
2293 let user_data = match user_data {
2294 Some(ud) => ud.unwrapped(),
2295 None => ptr::null_mut(),
2296 };
2297
2298 let errcode = unsafe {
2299 ffi::clBuildProgram(
2300 program.as_ptr() as cl_program,
2301 device_ptrs.num(),
2302 device_ptrs.as_ptr(),
2303 options.as_ptr(),
2304 pfn_notify,
2305 user_data,
2306 )
2307 };
2308
2309 if errcode == Status::CL_BUILD_PROGRAM_FAILURE as i32 {
2310 if let Some(ds) = devices {
2311 program_build_err(program, ds).map_err(|err| err.into())
2312 } else {
2313 let ds = program.devices()?;
2314 program_build_err(program, &ds).map_err(|err| err.into())
2315 }
2316 } else {
2317 eval_errcode(errcode, (), "clBuildProgram", None::<String>)
2318 }
2319}
2320
2321#[cfg(feature = "opencl_version_1_2")]
2326pub fn compile_program<D: ClDeviceIdPtr>(
2327 program: &Program,
2328 devices: Option<&[D]>,
2329 options: &CString,
2330 input_headers: &[&Program],
2331 header_include_names: &[CString],
2332 pfn_notify: Option<BuildProgramCallbackFn>,
2333 user_data: Option<Box<UserDataPh>>,
2334 device_versions: Option<&[OpenclVersion]>,
2335) -> OclCoreResult<()> {
2336 verify_device_versions(
2337 device_versions,
2338 [1, 2],
2339 program,
2340 ApiFunction::CompileProgram,
2341 )?;
2342
2343 assert!(
2344 pfn_notify.is_none() && user_data.is_none(),
2345 "ocl::core::compile_program(): Callback functions not yet implemented."
2346 );
2347
2348 assert!(input_headers.len() == header_include_names.len(),
2349 "ocl::core::compile_program(): Length of input_headers and header_include_names should be equal.");
2350
2351 let device_ptrs = DevicePtrList::new(devices);
2352
2353 let input_hdrs_ptrs: Vec<_> = input_headers.iter().map(|cs| cs.as_ptr()).collect();
2354 let hdrs_names_ptrs: Vec<*const _> =
2355 header_include_names.iter().map(|cs| cs.as_ptr()).collect();
2356
2357 let (input_ptr, names_ptr) = if input_headers.is_empty() {
2359 (ptr::null(), ptr::null())
2360 } else {
2361 (input_hdrs_ptrs.as_ptr(), hdrs_names_ptrs.as_ptr())
2362 };
2363
2364 let user_data = match user_data {
2365 Some(ud) => ud.unwrapped(),
2366 None => ptr::null_mut(),
2367 };
2368
2369 let errcode = unsafe {
2370 ffi::clCompileProgram(
2371 program.as_ptr() as cl_program,
2372 device_ptrs.num(),
2373 device_ptrs.as_ptr(),
2374 options.as_ptr(),
2375 input_hdrs_ptrs.len() as cl_uint,
2376 input_ptr as *const cl_program,
2377 names_ptr as *const *const _,
2378 pfn_notify,
2379 user_data,
2380 )
2381 };
2382
2383 if errcode == Status::CL_COMPILE_PROGRAM_FAILURE as i32 {
2384 if let Some(ds) = devices {
2385 program_build_err(program, ds).map_err(|err| err.into())
2386 } else {
2387 let ds = program.devices()?;
2388 program_build_err(program, &ds).map_err(|err| err.into())
2389 }
2390 } else {
2391 eval_errcode(errcode, (), "clCompileProgram", None::<String>)
2392 }
2393}
2394
2395#[cfg(feature = "opencl_version_1_2")]
2400pub fn link_program<D: ClDeviceIdPtr, C: ClContextPtr>(
2401 context: C,
2402 devices: Option<&[D]>,
2403 options: &CString,
2404 input_programs: &[&Program],
2405 pfn_notify: Option<BuildProgramCallbackFn>,
2406 user_data: Option<Box<UserDataPh>>,
2407 device_versions: Option<&[OpenclVersion]>,
2408) -> OclCoreResult<Program> {
2409 verify_context(context)?;
2410 verify_device_versions(
2411 device_versions,
2412 [1, 2],
2413 &context.as_ptr(),
2414 ApiFunction::LinkProgram,
2415 )?;
2416
2417 assert!(
2418 pfn_notify.is_none() && user_data.is_none(),
2419 "ocl::core::link_program(): Callback functions not yet implemented."
2420 );
2421
2422 let device_ptrs = DevicePtrList::new(devices);
2423
2424 let input_programs_ptrs: Vec<_> = input_programs.iter().map(|cs| cs.as_ptr()).collect();
2425
2426 let user_data = match user_data {
2427 Some(ud) => ud.unwrapped(),
2428 None => ptr::null_mut(),
2429 };
2430
2431 let mut errcode: cl_int = 0;
2432
2433 let program_ptr = unsafe {
2434 ffi::clLinkProgram(
2435 context.as_ptr(),
2436 device_ptrs.num(),
2437 device_ptrs.as_ptr(),
2438 options.as_ptr(),
2439 input_programs_ptrs.len() as cl_uint,
2440 input_programs_ptrs.as_ptr() as *const cl_program,
2441 pfn_notify,
2442 user_data,
2443 &mut errcode,
2444 )
2445 };
2446
2447 eval_errcode(errcode, program_ptr, "clLinkProgram", None::<String>)
2448 .map(|ptr| unsafe { Program::from_raw_create_ptr(ptr) })
2449}
2450
2451fn get_program_info_raw(program: &Program, request: ProgramInfo) -> OclCoreResult<Vec<u8>> {
2463 let mut result_size: size_t = 0;
2464
2465 let errcode = unsafe {
2466 ffi::clGetProgramInfo(
2467 program.as_ptr() as cl_program,
2468 request as cl_program_info,
2469 0 as size_t,
2470 ptr::null_mut(),
2471 &mut result_size as *mut size_t,
2472 )
2473 };
2474
2475 eval_errcode(errcode, (), "clGetProgramInfo", None::<String>)?;
2476
2477 if result_size == 0 {
2479 return Ok(vec![]);
2480 }
2481
2482 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2483
2484 let errcode = unsafe {
2485 ffi::clGetProgramInfo(
2486 program.as_ptr() as cl_program,
2487 request as cl_program_info,
2488 result_size,
2489 result.as_mut_ptr() as *mut _ as *mut c_void,
2490 ptr::null_mut(),
2491 )
2492 };
2493
2494 eval_errcode(errcode, result, "clGetProgramInfo", None::<String>)
2495}
2496
2497fn get_program_info_binaries(program: &Program) -> OclCoreResult<Vec<Vec<u8>>> {
2500 let binary_sizes_raw = get_program_info_raw(program, ProgramInfo::BinarySizes)?;
2501 let binary_sizes = unsafe { crate::util::bytes_into_vec::<usize>(binary_sizes_raw)? };
2502
2503 let binaries = binary_sizes
2504 .into_iter()
2505 .map(|size| vec![0u8; size])
2506 .collect::<Vec<Vec<u8>>>();
2507
2508 let mut binary_ptrs = binaries.iter().map(|vec| vec.as_ptr()).collect::<Vec<_>>();
2509
2510 let errcode = unsafe {
2511 ffi::clGetProgramInfo(
2512 program.as_ptr() as cl_program,
2513 ProgramInfo::Binaries as cl_program_info,
2514 mem::size_of::<*mut c_void>() * binary_ptrs.len(),
2515 binary_ptrs.as_mut_ptr() as *mut _ as *mut c_void,
2516 ptr::null_mut(),
2517 )
2518 };
2519
2520 eval_errcode(errcode, binaries, "clGetProgramInfo", None::<String>)
2521}
2522
2523pub fn get_program_info(
2525 program: &Program,
2526 request: ProgramInfo,
2527) -> OclCoreResult<ProgramInfoResult> {
2528 match request {
2529 ProgramInfo::Binaries => {
2530 get_program_info_binaries(program).map(ProgramInfoResult::Binaries)
2531 }
2532 _ => {
2533 let result = get_program_info_raw(program, request)?;
2534 ProgramInfoResult::from_bytes(request, result)
2535 }
2536 }
2537}
2538
2539pub fn get_program_build_info<D: ClDeviceIdPtr + fmt::Debug>(
2541 obj: &Program,
2542 device_obj: D,
2543 request: ProgramBuildInfo,
2544) -> OclCoreResult<ProgramBuildInfoResult> {
2545 let mut result_size: size_t = 0;
2546
2547 let errcode = unsafe {
2548 ffi::clGetProgramBuildInfo(
2549 obj.as_ptr() as cl_program,
2550 device_obj.as_ptr() as cl_device_id,
2551 request as cl_program_build_info,
2552 0 as size_t,
2553 ptr::null_mut(),
2554 &mut result_size as *mut size_t,
2555 )
2556 };
2557
2558 eval_errcode(errcode, (), "clGetProgramBuildInfo", None::<String>)?;
2559
2560 if result_size == 0 {
2562 return ProgramBuildInfoResult::from_bytes(request, vec![]);
2563 }
2564
2565 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2566
2567 let errcode = unsafe {
2568 ffi::clGetProgramBuildInfo(
2569 obj.as_ptr() as cl_program,
2570 device_obj.as_ptr() as cl_device_id,
2571 request as cl_program_build_info,
2572 result_size as size_t,
2573 result.as_mut_ptr() as *mut _ as *mut c_void,
2574 ptr::null_mut(),
2575 )
2576 };
2577
2578 let result = eval_errcode(errcode, result, "clGetProgramBuildInfo", None::<String>)?;
2579 ProgramBuildInfoResult::from_bytes(request, result)
2580}
2581
2582pub fn create_kernel<S: AsRef<str>>(program: &Program, name: S) -> OclCoreResult<Kernel> {
2588 let mut err: cl_int = 0;
2589
2590 unsafe {
2591 let kernel_ptr = ffi::clCreateKernel(
2592 program.as_ptr(),
2593 CString::new(name.as_ref().as_bytes())?.as_ptr(),
2594 &mut err,
2595 );
2596
2597 eval_errcode(err, kernel_ptr, "clCreateKernel", Some(name.as_ref()))
2598 .map(|ptr| Kernel::from_raw_create_ptr(ptr))
2599 }
2600}
2601
2602pub fn create_kernels_in_program() -> OclCoreResult<()> {
2604 unimplemented!();
2609}
2610
2611pub unsafe fn retain_kernel(kernel: &Kernel) -> OclCoreResult<()> {
2613 eval_errcode(
2614 ffi::clRetainKernel(kernel.as_ptr()),
2615 (),
2616 "clRetainKernel",
2617 None::<String>,
2618 )
2619}
2620
2621pub unsafe fn release_kernel(kernel: &Kernel) -> OclCoreResult<()> {
2623 eval_errcode(
2624 ffi::clReleaseKernel(kernel.as_ptr()),
2625 (),
2626 "clReleaseKernel",
2627 None::<String>,
2628 )
2629}
2630
2631pub fn set_kernel_arg(kernel: &Kernel, index: u32, arg_val: ArgVal) -> OclCoreResult<()> {
2643 let (size, value) = arg_val.as_raw();
2644
2645 let err = unsafe { ffi::clSetKernelArg(kernel.as_ptr(), index, size, value) };
2646
2647 if err != Status::CL_SUCCESS as i32 {
2648 let name = get_kernel_name(kernel)?;
2649 eval_errcode(err, (), "clSetKernelArg", Some(name))
2650 } else {
2651 Ok(())
2652 }
2653}
2654
2655pub fn get_kernel_info(obj: &Kernel, request: KernelInfo) -> OclCoreResult<KernelInfoResult> {
2657 let mut result_size: size_t = 0;
2658
2659 let errcode = unsafe {
2660 ffi::clGetKernelInfo(
2661 obj.as_ptr() as cl_kernel,
2662 request as cl_kernel_info,
2663 0 as size_t,
2664 ptr::null_mut(),
2665 &mut result_size as *mut size_t,
2666 )
2667 };
2668
2669 eval_errcode(errcode, (), "clGetKernelInfo", None::<String>)?;
2670
2671 if result_size == 0 {
2673 return KernelInfoResult::from_bytes(request, vec![]);
2674 }
2675
2676 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2677
2678 let errcode = unsafe {
2679 ffi::clGetKernelInfo(
2680 obj.as_ptr() as cl_kernel,
2681 request as cl_kernel_info,
2682 result_size,
2683 result.as_mut_ptr() as *mut _ as *mut c_void,
2684 ptr::null_mut(),
2685 )
2686 };
2687
2688 let result = eval_errcode(errcode, result, "clGetKernelInfo", None::<String>)?;
2689 KernelInfoResult::from_bytes(request, result)
2690}
2691
2692pub fn get_kernel_arg_info(
2696 obj: &Kernel,
2697 arg_index: u32,
2698 request: KernelArgInfo,
2699 device_versions: Option<&[OpenclVersion]>,
2700) -> OclCoreResult<KernelArgInfoResult> {
2701 verify_device_versions(device_versions, [1, 2], obj, ApiFunction::GetKernelArgInfo)?;
2709
2710 let mut result_size: size_t = 0;
2711
2712 let errcode = unsafe {
2713 ffi::clGetKernelArgInfo(
2714 obj.as_ptr() as cl_kernel,
2715 arg_index as cl_uint,
2716 request as cl_kernel_arg_info,
2717 0 as size_t,
2718 ptr::null_mut(),
2719 &mut result_size as *mut size_t,
2720 )
2721 };
2722
2723 eval_errcode(errcode, (), "clGetKernelArgInfo", None::<String>)?;
2728
2729 if result_size == 0 {
2731 return KernelArgInfoResult::from_bytes(request, vec![]);
2732 }
2733
2734 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2735
2736 let errcode = unsafe {
2737 ffi::clGetKernelArgInfo(
2738 obj.as_ptr() as cl_kernel,
2739 arg_index as cl_uint,
2740 request as cl_kernel_arg_info,
2741 result_size,
2742 result.as_mut_ptr() as *mut _ as *mut c_void,
2743 ptr::null_mut(),
2744 )
2745 };
2746
2747 let result = eval_errcode(errcode, result, "clGetKernelArgInfo", None::<String>)?;
2748 KernelArgInfoResult::from_bytes(request, result)
2749}
2750
2751pub fn get_kernel_work_group_info<D: ClDeviceIdPtr>(
2753 obj: &Kernel,
2754 device_obj: D,
2755 request: KernelWorkGroupInfo,
2756) -> OclCoreResult<KernelWorkGroupInfoResult> {
2757 let mut result_size: size_t = 0;
2758
2759 let errcode = unsafe {
2760 ffi::clGetKernelWorkGroupInfo(
2761 obj.as_ptr() as cl_kernel,
2762 device_obj.as_ptr() as cl_device_id,
2763 request as cl_kernel_work_group_info,
2764 0 as size_t,
2765 ptr::null_mut(),
2766 &mut result_size as *mut size_t,
2767 )
2768 };
2769
2770 if let Err(err) = eval_errcode(errcode, (), "clGetKernelWorkGroupInfo", None::<String>) {
2772 if let Some(status) = err.api_status() {
2773 if request == KernelWorkGroupInfo::GlobalWorkSize && status == Status::CL_INVALID_VALUE
2775 {
2776 return Ok(KernelWorkGroupInfoResult::CustomBuiltinOnly);
2777 }
2778
2779 if status == Status::CL_INVALID_DEVICE {
2781 return Ok(KernelWorkGroupInfoResult::Unavailable(status));
2782 }
2783 }
2784
2785 return Err(err);
2786 }
2787
2788 if result_size == 0 {
2790 return KernelWorkGroupInfoResult::from_bytes(request, vec![]);
2791 }
2792
2793 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2794
2795 let errcode = unsafe {
2796 ffi::clGetKernelWorkGroupInfo(
2797 obj.as_ptr() as cl_kernel,
2798 device_obj.as_ptr() as cl_device_id,
2799 request as cl_kernel_work_group_info,
2800 result_size,
2801 result.as_mut_ptr() as *mut _ as *mut c_void,
2802 ptr::null_mut(),
2803 )
2804 };
2805
2806 let result = eval_errcode(errcode, result, "clGetKernelWorkGroupInfo", None::<String>)?;
2807 KernelWorkGroupInfoResult::from_bytes(request, result)
2808}
2809
2810pub fn wait_for_events(num_events: u32, event_list: &dyn ClWaitListPtr) -> OclCoreResult<()> {
2816 assert!(event_list.count() >= num_events);
2817
2818 let errcode = unsafe { ffi::clWaitForEvents(num_events, event_list.as_ptr_ptr()) };
2819
2820 eval_errcode(errcode, (), "clWaitForEvents", None::<String>)
2821}
2822
2823pub fn get_event_info<'e, E: ClEventPtrRef<'e>>(
2825 event: &'e E,
2826 request: EventInfo,
2827) -> OclCoreResult<EventInfoResult> {
2828 let mut result_size: size_t = 0;
2829
2830 let errcode = unsafe {
2831 ffi::clGetEventInfo(
2832 *event.as_ptr_ref(),
2833 request as cl_event_info,
2834 0 as size_t,
2835 ptr::null_mut(),
2836 &mut result_size as *mut size_t,
2837 )
2838 };
2839
2840 eval_errcode(errcode, (), "clGetEventInfo", None::<String>)?;
2841
2842 if result_size == 0 {
2844 return EventInfoResult::from_bytes(request, vec![]);
2845 }
2846
2847 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2848
2849 let errcode = unsafe {
2850 ffi::clGetEventInfo(
2851 *event.as_ptr_ref(),
2852 request as cl_event_info,
2853 result_size,
2854 result.as_mut_ptr() as *mut _ as *mut c_void,
2855 ptr::null_mut(),
2856 )
2857 };
2858
2859 let result = eval_errcode(errcode, result, "clGetEventInfo", None::<String>)?;
2860 EventInfoResult::from_bytes(request, result)
2861}
2862
2863pub fn create_user_event<C>(context: C) -> OclCoreResult<Event>
2865where
2866 C: ClContextPtr,
2867{
2868 let mut errcode = 0;
2869 let event = unsafe {
2870 Event::from_raw_create_ptr(ffi::clCreateUserEvent(context.as_ptr(), &mut errcode))
2871 };
2872 eval_errcode(errcode, event, "clCreateUserEvent", None::<String>)
2873}
2874
2875pub unsafe fn retain_event<'e, E: ClEventPtrRef<'e>>(event: &'e E) -> OclCoreResult<()> {
2877 eval_errcode(
2878 ffi::clRetainEvent(*event.as_ptr_ref()),
2879 (),
2880 "clRetainEvent",
2881 None::<String>,
2882 )
2883}
2884
2885pub unsafe fn release_event<'e, E: ClEventPtrRef<'e>>(event: &'e E) -> OclCoreResult<()> {
2887 eval_errcode(
2888 ffi::clReleaseEvent(*event.as_ptr_ref()),
2889 (),
2890 "clReleaseEvent",
2891 None::<String>,
2892 )
2893}
2894
2895pub fn set_user_event_status<'e, E: ClEventPtrRef<'e>>(
2915 event: &'e E,
2916 execution_status: CommandExecutionStatus,
2917) -> OclCoreResult<()> {
2918 unsafe {
2919 #[cfg(feature = "event_debug_print")]
2920 println!(
2921 "::set_user_event_status: Setting user event status for event: {:?}",
2922 *event.as_ptr_ref()
2923 );
2924
2925 eval_errcode(
2926 ffi::clSetUserEventStatus(*event.as_ptr_ref(), execution_status as cl_int),
2927 (),
2928 "clSetUserEventStatus",
2929 None::<String>,
2930 )
2931 }
2932}
2933
2934pub unsafe fn set_event_callback<'e, E: ClEventPtrRef<'e>>(
2942 event: &'e E,
2943 callback_trigger: CommandExecutionStatus,
2944 callback_receiver: Option<EventCallbackFn>,
2945 user_data: *mut c_void,
2946) -> OclCoreResult<()> {
2947 eval_errcode(
2948 ffi::clSetEventCallback(
2949 *event.as_ptr_ref(),
2950 callback_trigger as cl_int,
2951 callback_receiver,
2952 user_data,
2953 ),
2954 (),
2955 "clSetEventCallback",
2956 None::<String>,
2957 )
2958}
2959
2960pub fn get_event_profiling_info<'e, E: ClEventPtrRef<'e>>(
2966 event: &'e E,
2967 request: ProfilingInfo,
2968) -> OclCoreResult<ProfilingInfoResult> {
2969 let max_result_size_bytes = 8;
2971 let mut result_size: size_t = 0;
2972 let event: cl_event = unsafe { *event.as_ptr_ref() };
2973
2974 let errcode = unsafe {
2975 ffi::clGetEventProfilingInfo(
2976 event,
2977 request as cl_profiling_info,
2978 max_result_size_bytes,
2979 ptr::null_mut(),
2980 &mut result_size as *mut size_t,
2981 )
2982 };
2983
2984 assert!(result_size <= max_result_size_bytes);
2986
2987 if errcode < 0 && Status::from_i32(errcode).unwrap() == Status::CL_INVALID_VALUE {
2990 return Err(OclCoreError::String(
2991 "<unavailable (CL_INVALID_VALUE)>".to_string(),
2992 ));
2993 }
2994
2995 eval_errcode(errcode, (), "clGetEventProfilingInfo", None::<String>)?;
2996
2997 if result_size == 0 {
2999 return ProfilingInfoResult::from_bytes(request, vec![]);
3000 }
3001
3002 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
3003
3004 let errcode = unsafe {
3005 ffi::clGetEventProfilingInfo(
3006 event,
3007 request as cl_profiling_info,
3008 result_size,
3009 result.as_mut_ptr() as *mut _ as *mut c_void,
3010 ptr::null_mut(),
3011 )
3012 };
3013
3014 let result = eval_errcode(errcode, result, "clGetEventProfilingInfo", None::<String>)?;
3015 ProfilingInfoResult::from_bytes(request, result)
3016}
3017
3018pub fn flush(command_queue: &CommandQueue) -> OclCoreResult<()> {
3027 unsafe {
3028 eval_errcode(
3029 ffi::clFlush(command_queue.as_ptr()),
3030 (),
3031 "clFlush",
3032 None::<String>,
3033 )
3034 }
3035}
3036
3037pub fn finish(command_queue: &CommandQueue) -> OclCoreResult<()> {
3042 unsafe {
3043 let errcode = ffi::clFinish(command_queue.as_ptr());
3044 eval_errcode(errcode, (), "clFinish", None::<String>)
3045 }
3046}
3047
3048pub unsafe fn enqueue_read_buffer<T, M, En, Ewl>(
3065 command_queue: &CommandQueue,
3066 buffer: M,
3067 block: bool,
3068 offset: usize,
3069 data: &mut [T],
3070 wait_list: Option<Ewl>,
3071 new_event: Option<En>,
3072) -> OclCoreResult<()>
3073where
3074 T: OclPrm,
3075 En: ClNullEventPtr,
3076 Ewl: ClWaitListPtr,
3077 M: AsMem<T> + MemCmdRw,
3078{
3079 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3080
3081 let offset_bytes = offset * mem::size_of::<T>();
3082
3083 let errcode = ffi::clEnqueueReadBuffer(
3084 command_queue.as_ptr(),
3085 buffer.as_mem().as_ptr(),
3086 block as cl_uint,
3087 offset_bytes,
3088 (data.len() * mem::size_of::<T>()) as size_t,
3089 data.as_ptr() as cl_mem,
3090 wait_list_len,
3091 wait_list_ptr,
3092 new_event_ptr,
3093 );
3094
3095 eval_errcode(errcode, (), "clEnqueueReadBuffer", None::<String>)
3096}
3097
3098pub unsafe fn enqueue_read_buffer_rect<T, M, En, Ewl>(
3114 command_queue: &CommandQueue,
3115 buffer: M,
3116 block: bool,
3117 buffer_origin: [usize; 3],
3118 host_origin: [usize; 3],
3119 region: [usize; 3],
3120 buffer_row_pitch_bytes: usize,
3121 buffer_slc_pitch_bytes: usize,
3122 host_row_pitch_bytes: usize,
3123 host_slc_pitch_bytes: usize,
3124 data: &mut [T],
3125 wait_list: Option<Ewl>,
3126 new_event: Option<En>,
3127) -> OclCoreResult<()>
3128where
3129 T: OclPrm,
3130 En: ClNullEventPtr,
3131 Ewl: ClWaitListPtr,
3132 M: AsMem<T> + MemCmdRw,
3133{
3134 let buffer_origin_bytes = [
3135 buffer_origin[0] * mem::size_of::<T>(),
3136 buffer_origin[1],
3137 buffer_origin[2],
3138 ];
3139 let host_origin_bytes = [
3140 host_origin[0] * mem::size_of::<T>(),
3141 host_origin[1],
3142 host_origin[2],
3143 ];
3144 let region_bytes = [region[0] * mem::size_of::<T>(), region[1], region[2]];
3145
3146 if false {
3148 println!(
3149 "buffer_origin_bytes: {:?}, host_origin_bytes: {:?}, region_bytes: {:?}",
3150 buffer_origin_bytes, host_origin_bytes, region_bytes
3151 );
3152 println!(
3153 "buffer_row_pitch_bytes: {}, buffer_slc_pitch_bytes: {}, \
3154 host_row_pitch_bytes: {}, host_slc_pitch_bytes: {}",
3155 buffer_row_pitch_bytes,
3156 buffer_slc_pitch_bytes,
3157 host_row_pitch_bytes,
3158 host_slc_pitch_bytes
3159 );
3160 }
3161
3162 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3163
3164 let errcode = ffi::clEnqueueReadBufferRect(
3165 command_queue.as_ptr(),
3166 buffer.as_mem().as_ptr(),
3167 block as cl_uint,
3168 &buffer_origin_bytes as *const _ as *const usize,
3169 &host_origin_bytes as *const _ as *const usize,
3170 ®ion_bytes as *const _ as *const usize,
3171 buffer_row_pitch_bytes,
3172 buffer_slc_pitch_bytes,
3173 host_row_pitch_bytes,
3174 host_slc_pitch_bytes,
3175 data.as_ptr() as cl_mem,
3176 wait_list_len,
3177 wait_list_ptr,
3178 new_event_ptr,
3179 );
3180
3181 eval_errcode(errcode, (), "clEnqueueReadBufferRect", None::<String>)
3182}
3183
3184pub unsafe fn enqueue_write_buffer<T, M, En, Ewl>(
3194 command_queue: &CommandQueue,
3195 buffer: M,
3196 block: bool,
3197 offset: usize,
3198 data: &[T],
3199 wait_list: Option<Ewl>,
3200 new_event: Option<En>,
3201) -> OclCoreResult<()>
3202where
3203 T: OclPrm,
3204 En: ClNullEventPtr,
3205 Ewl: ClWaitListPtr,
3206 M: AsMem<T> + MemCmdRw,
3207{
3208 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3209
3210 let offset_bytes = offset * mem::size_of::<T>();
3211
3212 let errcode = ffi::clEnqueueWriteBuffer(
3213 command_queue.as_ptr(),
3214 buffer.as_mem().as_ptr(),
3215 block as cl_uint,
3216 offset_bytes,
3217 (data.len() * mem::size_of::<T>()) as size_t,
3218 data.as_ptr() as cl_mem,
3219 wait_list_len,
3220 wait_list_ptr,
3221 new_event_ptr,
3222 );
3223 eval_errcode(errcode, (), "clEnqueueWriteBuffer", None::<String>)
3224}
3225
3226pub unsafe fn enqueue_write_buffer_rect<T, M, En, Ewl>(
3241 command_queue: &CommandQueue,
3242 buffer: M,
3243 block: bool,
3244 buffer_origin: [usize; 3],
3245 host_origin: [usize; 3],
3246 region: [usize; 3],
3247 buffer_row_pitch_bytes: usize,
3248 buffer_slc_pitch_bytes: usize,
3249 host_row_pitch_bytes: usize,
3250 host_slc_pitch_bytes: usize,
3251 data: &[T],
3252 wait_list: Option<Ewl>,
3253 new_event: Option<En>,
3254) -> OclCoreResult<()>
3255where
3256 T: OclPrm,
3257 En: ClNullEventPtr,
3258 Ewl: ClWaitListPtr,
3259 M: AsMem<T> + MemCmdRw,
3260{
3261 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3262
3263 let buffer_origin_bytes = [
3264 buffer_origin[0] * mem::size_of::<T>(),
3265 buffer_origin[1],
3266 buffer_origin[2],
3267 ];
3268 let host_origin_bytes = [
3269 host_origin[0] * mem::size_of::<T>(),
3270 host_origin[1],
3271 host_origin[2],
3272 ];
3273 let region_bytes = [region[0] * mem::size_of::<T>(), region[1], region[2]];
3274
3275 let errcode = ffi::clEnqueueWriteBufferRect(
3276 command_queue.as_ptr(),
3277 buffer.as_mem().as_ptr(),
3278 block as cl_uint,
3279 &buffer_origin_bytes as *const _ as *const usize,
3280 &host_origin_bytes as *const _ as *const usize,
3281 ®ion_bytes as *const _ as *const usize,
3282 buffer_row_pitch_bytes,
3283 buffer_slc_pitch_bytes,
3284 host_row_pitch_bytes,
3285 host_slc_pitch_bytes,
3286 data.as_ptr() as cl_mem,
3287 wait_list_len,
3288 wait_list_ptr,
3289 new_event_ptr,
3290 );
3291 eval_errcode(errcode, (), "clEnqueueWriteBufferRect", None::<String>)
3292}
3293
3294#[cfg(not(feature = "opencl_vendor_mesa"))]
3300pub fn enqueue_fill_buffer<T, M, En, Ewl>(
3301 command_queue: &CommandQueue,
3302 buffer: M,
3303 pattern: T,
3304 offset: usize,
3305 len: usize,
3306 wait_list: Option<Ewl>,
3307 new_event: Option<En>,
3308 device_version: Option<&OpenclVersion>,
3309) -> OclCoreResult<()>
3310where
3311 T: OclPrm,
3312 En: ClNullEventPtr,
3313 Ewl: ClWaitListPtr,
3314 M: AsMem<T> + MemCmdRw,
3315{
3316 verify_device_version(
3317 device_version,
3318 [1, 2],
3319 command_queue,
3320 ApiFunction::EnqueueFillBuffer,
3321 )?;
3322
3323 let pattern_size = mem::size_of::<T>();
3324 let offset_bytes = offset * mem::size_of::<T>();
3325 let size_bytes = len * mem::size_of::<T>();
3326
3327 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3328
3329 let errcode = unsafe {
3330 ffi::clEnqueueFillBuffer(
3331 command_queue.as_ptr(),
3332 buffer.as_mem().as_ptr(),
3333 &pattern as *const _ as *const c_void,
3334 pattern_size,
3335 offset_bytes,
3336 size_bytes,
3337 wait_list_len,
3338 wait_list_ptr,
3339 new_event_ptr,
3340 )
3341 };
3342 eval_errcode(errcode, (), "clEnqueueFillBuffer", None::<String>)
3343}
3344
3345pub fn enqueue_copy_buffer<T, M, En, Ewl>(
3347 command_queue: &CommandQueue,
3348 src_buffer: M,
3349 dst_buffer: M,
3350 src_offset: usize,
3351 dst_offset: usize,
3352 len: usize,
3353 wait_list: Option<Ewl>,
3354 new_event: Option<En>,
3355) -> OclCoreResult<()>
3356where
3357 T: OclPrm,
3358 En: ClNullEventPtr,
3359 Ewl: ClWaitListPtr,
3360 M: AsMem<T> + MemCmdAll,
3361{
3362 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3363
3364 let src_offset_bytes = src_offset * mem::size_of::<T>();
3365 let dst_offset_bytes = dst_offset * mem::size_of::<T>();
3366 let len_bytes = len * mem::size_of::<T>();
3367
3368 let errcode = unsafe {
3369 ffi::clEnqueueCopyBuffer(
3370 command_queue.as_ptr(),
3371 src_buffer.as_mem().as_ptr(),
3372 dst_buffer.as_mem().as_ptr(),
3373 src_offset_bytes,
3374 dst_offset_bytes,
3375 len_bytes,
3376 wait_list_len,
3377 wait_list_ptr,
3378 new_event_ptr,
3379 )
3380 };
3381 eval_errcode(errcode, (), "clEnqueueCopyBuffer", None::<String>)
3382}
3383
3384pub fn enqueue_copy_buffer_rect<T, M, En, Ewl>(
3390 command_queue: &CommandQueue,
3391 src_buffer: M,
3392 dst_buffer: M,
3393 src_origin: [usize; 3],
3394 dst_origin: [usize; 3],
3395 region: [usize; 3],
3396 src_row_pitch_bytes: usize,
3397 src_slc_pitch_bytes: usize,
3398 dst_row_pitch_bytes: usize,
3399 dst_slc_pitch_bytes: usize,
3400 wait_list: Option<Ewl>,
3401 new_event: Option<En>,
3402) -> OclCoreResult<()>
3403where
3404 T: OclPrm,
3405 En: ClNullEventPtr,
3406 Ewl: ClWaitListPtr,
3407 M: AsMem<T> + MemCmdAll,
3408{
3409 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3410
3411 let src_origin_bytes = [
3412 src_origin[0] * mem::size_of::<T>(),
3413 src_origin[1],
3414 src_origin[2],
3415 ];
3416 let dst_origin_bytes = [
3417 dst_origin[0] * mem::size_of::<T>(),
3418 dst_origin[1],
3419 dst_origin[2],
3420 ];
3421 let region_bytes = [region[0] * mem::size_of::<T>(), region[1], region[2]];
3422
3423 let errcode = unsafe {
3424 ffi::clEnqueueCopyBufferRect(
3425 command_queue.as_ptr(),
3426 src_buffer.as_mem().as_ptr(),
3427 dst_buffer.as_mem().as_ptr(),
3428 &src_origin_bytes as *const _ as *const usize,
3429 &dst_origin_bytes as *const _ as *const usize,
3430 ®ion_bytes as *const _ as *const usize,
3431 src_row_pitch_bytes,
3432 src_slc_pitch_bytes,
3433 dst_row_pitch_bytes,
3434 dst_slc_pitch_bytes,
3435 wait_list_len,
3436 wait_list_ptr,
3437 new_event_ptr,
3438 )
3439 };
3440 eval_errcode(errcode, (), "clEnqueueCopyBufferRect", None::<String>)
3441}
3442
3443#[cfg(not(feature = "opencl_vendor_mesa"))]
3450pub fn enqueue_acquire_gl_objects<En, Ewl>(
3451 command_queue: &CommandQueue,
3452 buffers: &[Mem],
3453 wait_list: Option<Ewl>,
3454 new_event: Option<En>,
3455) -> OclCoreResult<()>
3456where
3457 En: ClNullEventPtr,
3458 Ewl: ClWaitListPtr,
3459{
3460 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3461
3462 let errcode = unsafe {
3463 clEnqueueAcquireGLObjects(
3464 command_queue.as_ptr(),
3465 buffers.len() as u32,
3466 buffers.as_ptr() as *const cl_mem,
3467 wait_list_len,
3468 wait_list_ptr,
3469 new_event_ptr,
3470 )
3471 };
3472 eval_errcode(errcode, (), "clEnqueueAcquireGLObjects", None::<String>)
3473}
3474
3475#[cfg(not(feature = "opencl_vendor_mesa"))]
3482pub fn enqueue_release_gl_objects<En, Ewl>(
3483 command_queue: &CommandQueue,
3484 buffers: &[Mem],
3485 wait_list: Option<Ewl>,
3486 new_event: Option<En>,
3487) -> OclCoreResult<()>
3488where
3489 En: ClNullEventPtr,
3490 Ewl: ClWaitListPtr,
3491{
3492 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3493
3494 let errcode = unsafe {
3495 clEnqueueReleaseGLObjects(
3496 command_queue.as_ptr(),
3497 buffers.len() as u32,
3498 buffers.as_ptr() as *const cl_mem,
3499 wait_list_len,
3500 wait_list_ptr,
3501 new_event_ptr,
3502 )
3503 };
3504 eval_errcode(errcode, (), "clEnqueueReleaseGLObjects", None::<String>)
3505}
3506
3507pub unsafe fn enqueue_read_image<T, M, En, Ewl>(
3519 command_queue: &CommandQueue,
3520 image: M,
3521 block: bool,
3522 origin: [usize; 3],
3523 region: [usize; 3],
3524 row_pitch_bytes: usize,
3525 slc_pitch_bytes: usize,
3526 data: &mut [T],
3527 wait_list: Option<Ewl>,
3528 new_event: Option<En>,
3529) -> OclCoreResult<()>
3530where
3531 T: OclPrm,
3532 En: ClNullEventPtr,
3533 Ewl: ClWaitListPtr,
3534 M: AsMem<T> + MemCmdRw,
3535{
3536 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3537
3538 let errcode = ffi::clEnqueueReadImage(
3539 command_queue.as_ptr(),
3540 image.as_mem().as_ptr(),
3541 block as cl_uint,
3542 &origin as *const _ as *const usize,
3543 ®ion as *const _ as *const usize,
3544 row_pitch_bytes,
3545 slc_pitch_bytes,
3546 data.as_ptr() as cl_mem,
3547 wait_list_len,
3548 wait_list_ptr,
3549 new_event_ptr,
3550 );
3551 eval_errcode(errcode, (), "clEnqueueReadImage", None::<String>)
3552}
3553
3554pub unsafe fn enqueue_write_image<T, M, En, Ewl>(
3567 command_queue: &CommandQueue,
3568 image: M,
3569 block: bool,
3570 origin: [usize; 3],
3571 region: [usize; 3],
3572 input_row_pitch_bytes: usize,
3573 input_slc_pitch_bytes: usize,
3574 data: &[T],
3575 wait_list: Option<Ewl>,
3576 new_event: Option<En>,
3577) -> OclCoreResult<()>
3578where
3579 T: OclPrm,
3580 En: ClNullEventPtr,
3581 Ewl: ClWaitListPtr,
3582 M: AsMem<T> + MemCmdRw,
3583{
3584 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3585
3586 let errcode = ffi::clEnqueueWriteImage(
3587 command_queue.as_ptr(),
3588 image.as_mem().as_ptr(),
3589 block as cl_uint,
3590 &origin as *const _ as *const usize,
3591 ®ion as *const _ as *const usize,
3592 input_row_pitch_bytes,
3593 input_slc_pitch_bytes,
3594 data.as_ptr() as cl_mem,
3595 wait_list_len,
3596 wait_list_ptr,
3597 new_event_ptr,
3598 );
3599 eval_errcode(errcode, (), "clEnqueueWriteImage", None::<String>)
3600}
3601
3602pub fn enqueue_fill_image<T, M, En, Ewl>(
3621 command_queue: &CommandQueue,
3622 image: M,
3623 color: &[T],
3624 origin: [usize; 3],
3625 region: [usize; 3],
3626 wait_list: Option<Ewl>,
3627 new_event: Option<En>,
3628 device_version: Option<&OpenclVersion>,
3629) -> OclCoreResult<()>
3630where
3631 T: OclPrm,
3632 En: ClNullEventPtr,
3633 Ewl: ClWaitListPtr,
3634 M: AsMem<T> + MemCmdAll,
3635{
3636 verify_device_version(
3638 device_version,
3639 [1, 2],
3640 command_queue,
3641 ApiFunction::EnqueueFillImage,
3642 )?;
3643
3644 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3645
3646 let errcode = unsafe {
3647 ffi::clEnqueueFillImage(
3648 command_queue.as_ptr(),
3649 image.as_mem().as_ptr(),
3650 color as *const _ as *const c_void,
3651 &origin as *const _ as *const usize,
3652 ®ion as *const _ as *const usize,
3653 wait_list_len,
3654 wait_list_ptr,
3655 new_event_ptr,
3656 )
3657 };
3658 eval_errcode(errcode, (), "clEnqueueFillImage", None::<String>)
3659}
3660
3661pub fn enqueue_copy_image<En, Ewl>(
3665 command_queue: &CommandQueue,
3666 src_image: &Mem,
3667 dst_image: &Mem,
3668 src_origin: [usize; 3],
3669 dst_origin: [usize; 3],
3670 region: [usize; 3],
3671 wait_list: Option<Ewl>,
3672 new_event: Option<En>,
3673) -> OclCoreResult<()>
3674where
3675 En: ClNullEventPtr,
3676 Ewl: ClWaitListPtr,
3677{
3678 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3679
3680 let errcode = unsafe {
3681 ffi::clEnqueueCopyImage(
3682 command_queue.as_ptr(),
3683 src_image.as_ptr(),
3684 dst_image.as_ptr(),
3685 &src_origin as *const _ as *const usize,
3686 &dst_origin as *const _ as *const usize,
3687 ®ion as *const _ as *const usize,
3688 wait_list_len,
3689 wait_list_ptr,
3690 new_event_ptr,
3691 )
3692 };
3693 eval_errcode(errcode, (), "clEnqueueCopyImage", None::<String>)
3694}
3695
3696pub fn enqueue_copy_image_to_buffer<T, M, En, Ewl>(
3700 command_queue: &CommandQueue,
3701 src_image: M,
3702 dst_buffer: M,
3703 src_origin: [usize; 3],
3704 region: [usize; 3],
3705 dst_offset: usize,
3706 wait_list: Option<Ewl>,
3707 new_event: Option<En>,
3708) -> OclCoreResult<()>
3709where
3710 T: OclPrm,
3711 En: ClNullEventPtr,
3712 Ewl: ClWaitListPtr,
3713 M: AsMem<T> + MemCmdAll,
3714{
3715 let dst_offset_bytes = dst_offset * mem::size_of::<T>();
3716
3717 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3718
3719 let errcode = unsafe {
3720 ffi::clEnqueueCopyImageToBuffer(
3721 command_queue.as_ptr(),
3722 src_image.as_mem().as_ptr(),
3723 dst_buffer.as_mem().as_ptr(),
3724 &src_origin as *const _ as *const usize,
3725 ®ion as *const _ as *const usize,
3726 dst_offset_bytes,
3727 wait_list_len,
3728 wait_list_ptr,
3729 new_event_ptr,
3730 )
3731 };
3732 eval_errcode(errcode, (), "clEnqueueCopyImageToBuffer", None::<String>)
3733}
3734
3735pub fn enqueue_copy_buffer_to_image<T, M, En, Ewl>(
3739 command_queue: &CommandQueue,
3740 src_buffer: M,
3741 dst_image: M,
3742 src_offset: usize,
3743 dst_origin: [usize; 3],
3744 region: [usize; 3],
3745 wait_list: Option<Ewl>,
3746 new_event: Option<En>,
3747) -> OclCoreResult<()>
3748where
3749 T: OclPrm,
3750 En: ClNullEventPtr,
3751 Ewl: ClWaitListPtr,
3752 M: AsMem<T> + MemCmdAll,
3753{
3754 let src_offset_bytes = src_offset * mem::size_of::<T>();
3755
3756 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3757
3758 let errcode = unsafe {
3759 ffi::clEnqueueCopyBufferToImage(
3760 command_queue.as_ptr(),
3761 src_buffer.as_mem().as_ptr(),
3762 dst_image.as_mem().as_ptr(),
3763 src_offset_bytes,
3764 &dst_origin as *const _ as *const usize,
3765 ®ion as *const _ as *const usize,
3766 wait_list_len,
3767 wait_list_ptr,
3768 new_event_ptr,
3769 )
3770 };
3771 eval_errcode(errcode, (), "clEnqueueCopyBufferToImage", None::<String>)
3772}
3773
3774#[inline]
3775unsafe fn _enqueue_map_buffer<T, M>(
3776 command_queue: &CommandQueue,
3777 buffer: M,
3778 block: bool,
3779 map_flags: MapFlags,
3780 offset: usize,
3781 len: usize,
3782 wait_list_len: cl_uint,
3783 wait_list_ptr: *const cl_event,
3784 new_event_ptr: *mut cl_event,
3785) -> OclCoreResult<*mut T>
3786where
3787 T: OclPrm,
3788 M: AsMem<T> + MemCmdAll,
3789{
3790 let offset_bytes = offset * mem::size_of::<T>();
3791 let size_bytes = len * mem::size_of::<T>();
3792
3793 let mut errcode = 0i32;
3794
3795 let mapped_ptr = ffi::clEnqueueMapBuffer(
3796 command_queue.as_ptr(),
3797 buffer.as_mem().as_ptr(),
3798 block as cl_uint,
3799 map_flags.bits(),
3800 offset_bytes,
3801 size_bytes,
3802 wait_list_len,
3803 wait_list_ptr,
3804 new_event_ptr,
3805 &mut errcode,
3806 );
3807
3808 eval_errcode(
3809 errcode,
3810 mapped_ptr as *mut T,
3811 "clEnqueueMapBuffer",
3812 None::<String>,
3813 )
3814}
3815
3816pub unsafe fn enqueue_map_buffer<T, M, En, Ewl>(
3833 command_queue: &CommandQueue,
3834 buffer: M,
3835 block: bool,
3836 map_flags: MapFlags,
3837 offset: usize,
3838 len: usize,
3839 wait_list: Option<Ewl>,
3840 new_event: Option<En>,
3841) -> OclCoreResult<MemMap<T>>
3842where
3843 T: OclPrm,
3844 En: ClNullEventPtr,
3845 Ewl: ClWaitListPtr,
3846 M: AsMem<T> + MemCmdAll,
3847{
3848 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3849
3850 let mapped_ptr_res = _enqueue_map_buffer(
3851 command_queue,
3852 buffer.as_mem(),
3853 block,
3854 map_flags,
3855 offset,
3856 len,
3857 wait_list_len,
3858 wait_list_ptr,
3859 new_event_ptr,
3860 );
3861
3862 mapped_ptr_res.map(|ptr| MemMap::from_raw(ptr))
3863}
3864
3865pub unsafe fn enqueue_map_image<T, M, En, Ewl>(
3885 command_queue: &CommandQueue,
3886 image: M,
3887 block: bool,
3888 map_flags: MapFlags,
3889 origin: [usize; 3],
3890 region: [usize; 3],
3891 row_pitch_bytes: &mut usize,
3892 slc_pitch_bytes: &mut usize,
3893 wait_list: Option<Ewl>,
3894 new_event: Option<En>,
3895) -> OclCoreResult<MemMap<T>>
3896where
3897 T: OclPrm,
3898 En: ClNullEventPtr,
3899 Ewl: ClWaitListPtr,
3900 M: AsMem<T> + MemCmdAll,
3901{
3902 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3903
3904 let mut errcode = 0i32;
3905
3906 let mapped_ptr = ffi::clEnqueueMapImage(
3907 command_queue.as_ptr(),
3908 image.as_mem().as_ptr(),
3909 block as cl_uint,
3910 map_flags.bits(),
3911 &origin as *const _ as *const usize,
3912 ®ion as *const _ as *const usize,
3913 row_pitch_bytes,
3914 slc_pitch_bytes,
3915 wait_list_len,
3916 wait_list_ptr,
3917 new_event_ptr,
3918 &mut errcode,
3919 );
3920
3921 eval_errcode(errcode, mapped_ptr, "clEnqueueMapImage", None::<String>)
3932 .map(|ptr| MemMap::from_raw(ptr as *mut _ as *mut T))
3933}
3934
3935pub fn enqueue_unmap_mem_object<T, M, En, Ewl>(
3940 command_queue: &CommandQueue,
3941 memobj: M,
3942 mapped_mem: &MemMap<T>,
3943 wait_list: Option<Ewl>,
3944 new_event: Option<En>,
3945) -> OclCoreResult<()>
3946where
3947 T: OclPrm,
3948 En: ClNullEventPtr,
3949 Ewl: ClWaitListPtr,
3950 M: AsMem<T> + MemCmdAll,
3951{
3952 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3953
3954 let errcode = unsafe {
3955 ffi::clEnqueueUnmapMemObject(
3956 command_queue.as_ptr(),
3957 memobj.as_mem().as_ptr(),
3958 mapped_mem.as_void_ptr(),
3959 wait_list_len,
3960 wait_list_ptr,
3961 new_event_ptr,
3962 )
3963 };
3964
3965 eval_errcode(errcode, (), "clEnqueueUnmapMemObject", None::<String>)
3966}
3967
3968pub fn enqueue_migrate_mem_objects<En: ClNullEventPtr, Ewl: ClWaitListPtr>(
3978 command_queue: &CommandQueue,
3979 mem_objects: &[Mem],
3980 flags: MemMigrationFlags,
3981 wait_list: Option<Ewl>,
3982 new_event: Option<En>,
3983 device_version: Option<&OpenclVersion>,
3984) -> OclCoreResult<()> {
3985 verify_device_version(
3987 device_version,
3988 [1, 2],
3989 command_queue,
3990 ApiFunction::EnqueueMigrateMemObjects,
3991 )?;
3992
3993 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
3994
3995 let errcode = unsafe {
3996 ffi::clEnqueueMigrateMemObjects(
3997 command_queue.as_ptr(),
3998 mem_objects.len() as u32,
3999 mem_objects.as_ptr() as *const _ as *const cl_mem,
4000 flags.bits(),
4001 wait_list_len,
4002 wait_list_ptr,
4003 new_event_ptr,
4004 )
4005 };
4006 eval_errcode(errcode, (), "clEnqueueMigrateMemObjects", None::<String>)
4007}
4008
4009pub unsafe fn enqueue_kernel<En: ClNullEventPtr, Ewl: ClWaitListPtr>(
4023 command_queue: &CommandQueue,
4024 kernel: &Kernel,
4025 work_dims: u32,
4026 global_work_offset: Option<[usize; 3]>,
4027 global_work_dims: &[usize; 3],
4028 local_work_dims: Option<[usize; 3]>,
4029 wait_list: Option<Ewl>,
4030 new_event: Option<En>,
4031) -> OclCoreResult<()> {
4032 #[cfg(feature = "kernel_debug_sleep")]
4033 #[allow(unused_imports)]
4034 use std::thread;
4035 #[cfg(feature = "kernel_debug_sleep")]
4036 #[allow(unused_imports)]
4037 use std::time::Duration;
4038
4039 #[cfg(feature = "kernel_debug_print")]
4040 println!(
4041 "Resolving events: wait_list: {:?}, new_event: {:?}",
4042 wait_list, new_event
4043 );
4044
4045 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
4046
4047 #[cfg(feature = "kernel_debug_print")]
4048 println!("Resolving global work offset: {:?}...", global_work_offset);
4049
4050 let gwo = resolve_work_dims(global_work_offset.as_ref());
4051
4052 #[cfg(feature = "kernel_debug_print")]
4053 println!("Assigning global work size: {:?}...", global_work_dims);
4054
4055 let gws = global_work_dims as *const size_t;
4056
4057 #[cfg(feature = "kernel_debug_print")]
4058 println!("Resolving local work size: {:?}...", local_work_dims);
4059
4060 let lws = resolve_work_dims(local_work_dims.as_ref());
4061
4062 #[cfg(feature = "kernel_debug_print")]
4063 println!("Preparing to print all details...");
4064
4065 #[cfg(feature = "kernel_debug_print")]
4066 print!(
4067 "core::enqueue_kernel('{}': \
4068 work_dims: {}, \
4069 gwo: {:?}, \
4070 gws: {:?}, \
4071 lws: {:?}, \
4072 wait_list_len: {}, \
4073 wait_list_ptr: {:?}, \
4074 new_event_ptr: {:?}) \
4075 ",
4076 get_kernel_name(&kernel),
4077 work_dims,
4078 global_work_offset,
4079 global_work_dims,
4080 local_work_dims,
4081 wait_list_len,
4082 wait_list_ptr,
4083 new_event_ptr,
4084 );
4085
4086 let errcode = ffi::clEnqueueNDRangeKernel(
4087 command_queue.as_ptr(),
4088 kernel.as_ptr() as cl_kernel,
4089 work_dims,
4090 gwo,
4091 gws,
4092 lws,
4093 wait_list_len,
4094 wait_list_ptr,
4095 new_event_ptr,
4096 );
4097
4098 if cfg!(feature = "kernel_debug_print") {
4099 println!("-> Status: {}.", errcode);
4100 }
4101 if cfg!(feature = "kernel_debug_sleep") {
4102 thread::sleep(Duration::from_millis(KERNEL_DEBUG_SLEEP_DURATION_MS));
4103 }
4104
4105 if errcode != 0 {
4106 let name = get_kernel_name(kernel)?;
4107 eval_errcode(errcode, (), "clEnqueueNDRangeKernel", Some(name))
4108 } else {
4109 Ok(())
4110 }
4111}
4112
4113pub unsafe fn enqueue_task<En: ClNullEventPtr, Ewl: ClWaitListPtr>(
4132 command_queue: &CommandQueue,
4133 kernel: &Kernel,
4134 wait_list: Option<Ewl>,
4135 new_event: Option<En>,
4136 kernel_name: Option<&str>,
4137) -> OclCoreResult<()> {
4138 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
4139
4140 let errcode = ffi::clEnqueueTask(
4141 command_queue.as_ptr(),
4142 kernel.as_ptr() as cl_kernel,
4143 wait_list_len,
4144 wait_list_ptr,
4145 new_event_ptr,
4146 );
4147 eval_errcode(errcode, (), "clEnqueueTask", kernel_name)
4148}
4149
4150pub fn enqueue_native_kernel() -> OclCoreResult<()> {
4152 unimplemented!();
4163}
4164
4165pub fn enqueue_marker_with_wait_list<En, Ewl>(
4172 command_queue: &CommandQueue,
4173 wait_list: Option<Ewl>,
4174 new_event: Option<En>,
4175 device_version: Option<&OpenclVersion>,
4176) -> OclCoreResult<()>
4177where
4178 En: ClNullEventPtr,
4179 Ewl: ClWaitListPtr,
4180{
4181 verify_device_version(
4183 device_version,
4184 [1, 2],
4185 command_queue,
4186 ApiFunction::EnqueueMarkerWithWaitList,
4187 )?;
4188
4189 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
4190
4191 let errcode = unsafe {
4192 ffi::clEnqueueMarkerWithWaitList(
4193 command_queue.as_ptr(),
4194 wait_list_len,
4195 wait_list_ptr,
4196 new_event_ptr,
4197 )
4198 };
4199 eval_errcode(errcode, (), "clEnqueueMarkerWithWaitList", None::<String>)
4200}
4201
4202pub fn enqueue_barrier_with_wait_list<En, Ewl>(
4208 command_queue: &CommandQueue,
4209 wait_list: Option<Ewl>,
4210 new_event: Option<En>,
4211 device_version: Option<&OpenclVersion>,
4212) -> OclCoreResult<()>
4213where
4214 En: ClNullEventPtr,
4215 Ewl: ClWaitListPtr,
4216{
4217 verify_device_version(
4219 device_version,
4220 [1, 2],
4221 command_queue,
4222 ApiFunction::EnqueueBarrierWithWaitList,
4223 )?;
4224
4225 let (wait_list_len, wait_list_ptr, new_event_ptr) = resolve_event_ptrs(wait_list, new_event);
4226
4227 let errcode = unsafe {
4228 ffi::clEnqueueBarrierWithWaitList(
4229 command_queue.as_ptr(),
4230 wait_list_len,
4231 wait_list_ptr,
4232 new_event_ptr,
4233 )
4234 };
4235 eval_errcode(errcode, (), "clEnqueueBarrierWithWaitList", None::<String>)
4236}
4237
4238pub unsafe fn get_extension_function_address_for_platform(
4287 platform: &PlatformId,
4288 func_name: &str,
4289 platform_version: Option<&OpenclVersion>,
4290) -> OclCoreResult<*mut c_void> {
4291 verify_platform_version(
4293 platform_version,
4294 [1, 2],
4295 platform,
4296 ApiFunction::GetExtensionFunctionAddressForPlatform,
4297 )?;
4298
4299 let func_name_c = CString::new(func_name)?;
4300
4301 let ext_fn =
4302 ffi::clGetExtensionFunctionAddressForPlatform(platform.as_ptr(), func_name_c.as_ptr());
4303
4304 if ext_fn.is_null() {
4305 Err(ApiWrapperError::GetExtensionFunctionAddressForPlatformInvalidFunction.into())
4306 } else {
4307 Ok(ext_fn)
4308 }
4309}
4310
4311pub fn device_versions(device_ids: &[DeviceId]) -> OclCoreResult<Vec<OpenclVersion>> {
4319 let mut d_versions = Vec::with_capacity(device_ids.len());
4320
4321 for device_id in device_ids {
4322 d_versions.push(device_id.version()?);
4323 }
4324
4325 Ok(d_versions)
4326}
4327
4328pub fn default_platform_idx() -> usize {
4331 match env::var("OCL_DEFAULT_PLATFORM_IDX") {
4332 Ok(s) => s.parse::<usize>().unwrap_or(0),
4333 Err(_) => 0,
4334 }
4335}
4336
4337pub fn default_platform() -> OclCoreResult<PlatformId> {
4339 let platform_list = get_platform_ids()?;
4340
4341 if platform_list.is_empty() {
4342 Err(ApiWrapperError::DefaultPlatformNoPlatforms.into())
4343 } else {
4344 let default_platform_idx = default_platform_idx();
4345 if default_platform_idx > platform_list.len() - 1 {
4346 Err(ApiWrapperError::DefaultPlatformEnvVarBadIdx {
4347 default_platform_idx,
4348 max_idx: platform_list.len() - 1,
4349 }
4350 .into())
4351 } else {
4352 Ok(platform_list[default_platform_idx])
4353 }
4354 }
4355}
4356
4357pub fn default_device_type() -> OclCoreResult<DeviceType> {
4360 match env::var("OCL_DEFAULT_DEVICE_TYPE") {
4361 Ok(ref s) => match s.trim() {
4362 "DEFAULT" => Ok(DeviceType::DEFAULT),
4363 "CPU" => Ok(DeviceType::CPU),
4364 "GPU" => Ok(DeviceType::GPU),
4365 "ACCELERATOR" => Ok(DeviceType::ACCELERATOR),
4366 "CUSTOM" => Ok(DeviceType::CUSTOM),
4367 "ALL" => Ok(DeviceType::ALL),
4368 _ => Err(ApiWrapperError::DefaultDeviceTypeInvalidType(s.to_owned()).into()),
4369 },
4370 Err(_) => Ok(DeviceType::ALL),
4373 }
4374}
4375
4376pub fn get_kernel_name(kernel: &Kernel) -> OclCoreResult<String> {
4378 let result = get_kernel_info(kernel, KernelInfo::FunctionName)?;
4379 Ok(result.into())
4380}
4381
4382pub fn create_build_program<C, D>(
4387 context: C,
4388 src_strings: &[CString],
4389 device_ids: Option<&[D]>,
4390 cmplr_opts: &CString,
4391) -> OclCoreResult<Program>
4392where
4393 C: ClContextPtr,
4394 D: ClDeviceIdPtr + fmt::Debug,
4395{
4396 let program = create_program_with_source(context, src_strings)?;
4397 build_program(&program, device_ids, cmplr_opts, None, None)?;
4398 Ok(program)
4399}
4400
4401#[allow(dead_code)]
4402pub fn wait_for_event<'e, E: ClEventPtrRef<'e>>(event: &'e E) -> OclCoreResult<()> {
4404 let errcode = unsafe { ffi::clWaitForEvents(1, event.as_ptr_ref()) };
4405 eval_errcode(errcode, (), "clWaitForEvents", None::<String>)
4406}
4407
4408pub fn event_status<'e, E: ClEventPtrRef<'e>>(
4410 event: &'e E,
4411) -> OclCoreResult<CommandExecutionStatus> {
4412 let mut status_int: cl_int = 0;
4413
4414 let errcode = unsafe {
4415 ffi::clGetEventInfo(
4416 *event.as_ptr_ref(),
4417 ffi::CL_EVENT_COMMAND_EXECUTION_STATUS,
4418 mem::size_of::<cl_int>(),
4419 &mut status_int as *mut _ as *mut c_void,
4420 ptr::null_mut(),
4421 )
4422 };
4423 eval_errcode(errcode, (), "clGetEventInfo", None::<String>)?;
4424
4425 CommandExecutionStatus::from_i32(status_int).ok_or_else(|| {
4426 OclCoreError::String(
4427 "Error converting \
4428 'clGetEventInfo' status output."
4429 .to_string(),
4430 )
4431 })
4432}
4433
4434pub fn event_is_complete<'e, E: ClEventPtrRef<'e>>(event: &'e E) -> OclCoreResult<bool> {
4436 let mut status_int: cl_int = 0;
4437
4438 let errcode = unsafe {
4439 ffi::clGetEventInfo(
4440 *event.as_ptr_ref(),
4441 ffi::CL_EVENT_COMMAND_EXECUTION_STATUS,
4442 mem::size_of::<cl_int>(),
4443 &mut status_int as *mut _ as *mut c_void,
4444 ptr::null_mut(),
4445 )
4446 };
4447
4448 #[cfg(feature = "event_debug_print")]
4449 unsafe {
4450 println!(
4451 "Event Status: {:?} (ptr: {:?})",
4452 CommandExecutionStatus::from_i32(status_int).unwrap(),
4453 *event.as_ptr_ref()
4454 );
4455 }
4456
4457 eval_errcode(
4458 errcode,
4459 status_int == CommandExecutionStatus::Complete as i32,
4460 "clEventGetInfo",
4461 Some("CL_EVENT_COMMAND_EXECUTION_STATUS"),
4462 )
4463}
4464
4465#[inline]
4484pub fn verify_context<C>(context: C) -> OclCoreResult<()>
4485where
4486 C: ClContextPtr,
4487{
4488 if cfg!(release) {
4490 Ok(())
4491 } else {
4492 match get_context_info(context, ContextInfo::Devices) {
4493 Err(err) => Err(err),
4494 _ => Ok(()),
4495 }
4496 }
4497}
4498
4499fn device_supports_cl_gl_sharing<D: ClDeviceIdPtr>(device: D) -> OclCoreResult<bool> {
4501 match get_device_info(device, DeviceInfo::Extensions) {
4502 Ok(DeviceInfoResult::Extensions(extensions)) => Ok(extensions.contains(CL_GL_SHARING_EXT)),
4503 Err(err) => Err(err),
4505 _ => unreachable!(),
4506 }
4507}
4508
4509pub fn get_command_queue_context_ptr(queue: &CommandQueue) -> OclCoreResult<cl_context> {
4511 let mut result = 0 as cl_context;
4512 let result_size = mem::size_of::<cl_context>();
4513
4514 let errcode = unsafe {
4515 ffi::clGetCommandQueueInfo(
4516 queue.as_ptr(),
4517 CommandQueueInfo::Context as cl_command_queue_info,
4518 result_size,
4519 &mut result as *mut _ as *mut c_void,
4520 ptr::null_mut(),
4521 )
4522 };
4523
4524 eval_errcode(
4525 errcode,
4526 result,
4527 "clGetCommandQueueInfo",
4528 Some("functions::get_command_queue_context_ptr"),
4529 )
4530}
4531
4532