1use std::ptr;
16use std::mem;
17use std::ffi::CString;
18use std::iter;
19use std::thread;
20use std::time::Duration;
21use std::env;
22use std::fmt;
23use failure::Fail;
24use crate::ffi::{size_t, c_void};
25use num_traits::FromPrimitive;
26
27#[cfg(not(feature="opencl_vendor_mesa"))]
28use crate::ffi::{cl_GLuint, cl_GLint, cl_GLenum, cl_gl_context_info,};
29#[cfg(not(feature="opencl_vendor_mesa"))]
30use crate::ffi::{clCreateFromGLBuffer, clCreateFromGLRenderbuffer, clCreateFromGLTexture,
31 clCreateFromGLTexture2D, clCreateFromGLTexture3D, clEnqueueAcquireGLObjects,
32 clEnqueueReleaseGLObjects};
33
34use crate::ffi::{self, cl_bool, cl_int, cl_uint, cl_platform_id, cl_device_id, cl_device_type,
35 cl_device_info, cl_platform_info, cl_context, cl_context_info, cl_context_properties,
36 cl_image_format, cl_image_desc, cl_kernel, cl_program_build_info, cl_mem, cl_mem_info,
37 cl_mem_flags, cl_mem_object_type, cl_buffer_create_type, cl_event, cl_program,
38 cl_addressing_mode, cl_filter_mode, cl_command_queue_info, cl_command_queue, cl_image_info,
39 cl_sampler, cl_sampler_info, cl_program_info, cl_kernel_info, cl_kernel_arg_info,
40 cl_kernel_work_group_info, cl_event_info, cl_profiling_info};
41
42use crate::error::{Error as OclCoreError, Result as OclCoreResult};
43
44use crate::{OclPrm, PlatformId, DeviceId, Context, ContextProperties, ContextInfo,
45 ContextInfoResult, MemFlags, CommandQueue, Mem, MemObjectType, Program,
46 Kernel, ClNullEventPtr, Sampler, ArgVal, DeviceType, ImageFormat, ImageDescriptor,
47 CommandExecutionStatus, AddressingMode, FilterMode, PlatformInfo, PlatformInfoResult,
48 DeviceInfo, DeviceInfoResult, CommandQueueInfo, CommandQueueInfoResult, MemInfo, MemInfoResult,
49 ImageInfo, ImageInfoResult, SamplerInfo, SamplerInfoResult, ProgramInfo, ProgramInfoResult,
50 ProgramBuildInfo, ProgramBuildInfoResult, KernelInfo, KernelInfoResult, KernelArgInfo,
51 KernelArgInfoResult, KernelWorkGroupInfo, KernelWorkGroupInfoResult, ClEventPtrRef,
52 ClWaitListPtr, EventInfo, EventInfoResult, ProfilingInfo, ProfilingInfoResult,
53 CreateContextCallbackFn, UserDataPtr, ClPlatformIdPtr, ClDeviceIdPtr, ClContextPtr,
54 EventCallbackFn, BuildProgramCallbackFn, MemMigrationFlags, MapFlags, BufferRegion,
55 BufferCreateType, OpenclVersion, ClVersions, Status, CommandQueueProperties, MemMap, AsMem,
56 MemCmdRw, MemCmdAll, Event, ImageFormatParseResult};
57
58#[cfg(not(feature="opencl_vendor_mesa"))]
59use crate::{GlContextInfo, GlContextInfoResult};
60
61#[cfg(target_os="macos")]
63const CL_GL_SHARING_EXT: &str = "cl_APPLE_gl_sharing";
64#[cfg(not(target_os="macos"))]
65const CL_GL_SHARING_EXT: &str = "cl_khr_gl_sharing";
66
67const KERNEL_DEBUG_SLEEP_DURATION_MS: u64 = 150;
68const PLATFORM_IDS_ATTEMPT_TIMEOUT_MS: u64 = 2000;
69const PLATFORM_IDS_ATTEMPT_COUNT: u64 = 5;
70
71pub extern "C" fn _dummy_event_callback(_: ffi::cl_event, _: i32, _: *mut c_void) {}
80
81
82pub extern "C" fn _complete_user_event(src_event_ptr: cl_event, event_status: i32,
92 user_data: *mut c_void)
93{
94 #[cfg(not(feature = "event_debug_print"))]
95 let _ = src_event_ptr;
96
97 if event_status == CommandExecutionStatus::Complete as i32 && !user_data.is_null() {
98 let tar_event_ptr = user_data as *mut _ as cl_event;
99
100 unsafe {
101 let user_event = Event::from_raw(tar_event_ptr);
102
103 #[cfg(feature = "event_debug_print")]
104 println!("::_complete_user_event: Setting event complete for: \
105 source: {:?}, target: {:?}...", src_event_ptr, &user_event);
106
107 crate::set_user_event_status(&user_event, CommandExecutionStatus::Complete).unwrap();
108 }
109
110 #[cfg(feature = "event_debug_print")]
111 println!(" - Event status has been set to 'CommandExecutionStatus::Complete' \
112 for event: {:?}", tar_event_ptr);
113 } else {
114 match CommandExecutionStatus::from_i32(event_status) {
117 Some(status_enum) => panic!("ocl_core::_complete_event: User data is null or event \
118 is not complete. Status: '{:?}'", status_enum),
119 None => eval_errcode(event_status, (), "clSetEventCallback",
120 Some(format!("src_event_ptr: {:?}", src_event_ptr))).unwrap(),
121 }
122 }
123}
124
125static SDK_DOCS_URL_PRE: &'static str = "https://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/";
132static SDK_DOCS_URL_SUF: &'static str = ".html#errors";
133
134
135pub struct ApiError {
137 status: Status,
138 fn_name: &'static str,
139 fn_info: Option<String>,
140}
141
142impl ApiError {
143 pub fn new<S: Into<String>>(errcode: i32, fn_name: &'static str, fn_info: Option<S>) -> ApiError {
144 let status = match Status::from_i32(errcode) {
145 Some(s) => s,
146 None => panic!("ocl_core::Error::err_status: Invalid error code: '{}'. \
147 Aborting.", errcode),
148 };
149
150 let fn_info = fn_info.map(|s| s.into());
151
152 ApiError {
153 status,
154 fn_name,
155 fn_info,
156 }
157 }
158
159 pub fn status(&self) -> Status {
160 self.status
161 }
162}
163
164impl Fail for ApiError {}
165
166impl fmt::Display for ApiError {
167 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
168 let fn_info_string = if let Some(ref fn_info) = self.fn_info {
169 format!("(\"{}\")", fn_info)
170 } else {
171 String::with_capacity(0)
172 };
173
174 let status_int = self.status as i32;
175
176 write!(f, "\n\n\
177 ################################ OPENCL ERROR ############################### \
178 \n\nError executing function: {}{} \
179 \n\nStatus error code: {:?} ({}) \
180 \n\nPlease visit the following url for more information: \n\n{}{}{} \n\n\
181 ############################################################################# \n",
182 self.fn_name, fn_info_string, self.status, status_int,
183 SDK_DOCS_URL_PRE, self.fn_name, SDK_DOCS_URL_SUF)
184 }
185}
186
187impl fmt::Debug for ApiError {
188 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
189 fmt::Display::fmt(&self, f)
190 }
191}
192
193#[inline(always)]
197fn eval_errcode<T, S>(errcode: cl_int, result: T, fn_name: &'static str, fn_info: Option<S>)
198 -> OclCoreResult<T>
199 where S: Into<String> {
200 if (Status::CL_SUCCESS as i32) == errcode {
201 Ok(result)
202 } else {
203 Err(ApiError::new(errcode, fn_name, fn_info).into())
204 }
205}
206
207
208#[derive(Debug, Fail)]
210pub enum ProgramBuildError {
211 #[fail(display = "Device list is empty. Aborting build.")]
212 DeviceListEmpty,
213 #[fail(display =
214 "\n\n\
215 ###################### OPENCL PROGRAM BUILD DEBUG OUTPUT \
216 ######################\
217 \n\n{}\n\
218 ########################################################\
219 #######################\
220 \n\n",
221 _0
222 )]
223 BuildLog(String),
224 #[fail(display = "{}", _0)]
225 InfoResult(Box<OclCoreError>),
226}
227
228
229pub fn program_build_err<D: ClDeviceIdPtr>(program: &Program, device_ids: &[D])
234 -> Result<(), ProgramBuildError> {
235 if device_ids.is_empty() {
236 return Err(ProgramBuildError::DeviceListEmpty);
237 }
238
239 for device_id in device_ids.iter().cloned() {
240 match get_program_build_info(program, device_id, ProgramBuildInfo::BuildLog) {
241 Ok(ProgramBuildInfoResult::BuildLog(log)) => {
242 if log.len() > 1 {
243 return Err(ProgramBuildError::BuildLog(log));
244 }
245 },
246 Err(err) => return Err(ProgramBuildError::InfoResult(Box::new(err))),
247 _ => panic!("Unexpected 'ProgramBuildInfoResult' variant."),
248 }
249 }
250
251 Ok(())
252}
253
254
255#[allow(dead_code)]
257#[derive(Debug)]
258pub(crate) enum ApiFunction {
259 None,
260 RetainDevice,
261 ReleaseDevice,
262 CreateProgramWithIl,
263 CreateImage,
264 CreateFromGLTexture,
265 GetKernelArgInfo,
266 EnqueueFillBuffer,
267 EnqueueFillImage,
268 EnqueueMigrateMemObjects,
269 EnqueueMarkerWithWaitList,
270 EnqueueBarrierWithWaitList,
271 GetExtensionFunctionAddressForPlatform,
272 CompileProgram,
273 LinkProgram,
274}
275
276
277#[derive(Debug)]
279pub(crate) enum VersionKind {
280 Device,
281 Platform,
282}
283
284
285#[derive(Debug, Fail)]
287#[fail(display = "OpenCL ({:?}) version too low to use {:?} (detected: {}, required: {}).",
288 kind, function, detected, required)]
289pub struct VersionLowError {
290 detected: OpenclVersion,
291 required: OpenclVersion,
292 function: ApiFunction,
293 kind: VersionKind,
294}
295
296
297#[derive(Debug, Fail)]
299pub enum ApiWrapperError {
300 #[fail(display = "Unable to get platform id list after {} seconds of waiting.", _0)]
301 GetPlatformIdsPlatformListUnavailable(u64),
302 #[fail(display = "`devices_max` can not be zero.")]
303 GetDeviceIdsDevicesMaxZero,
304 #[fail(display = "No devices specified.")]
305 CreateContextNoDevicesSpecified,
306 #[fail(display = "Buffer length and data length and do not match.")]
307 CreateBufferDataLengthMismatch,
308 #[fail(display = "One or more of the devices contained in the list provided to \
309 '::create_context` doesn't support the cl_gl_sharing extension and cannot be \
310 used to create a context associated with OpenGL. [FIXME: determine recommended \
311 resolution - gl_device list fn doesn't work yet].")]
312 CreateContextClGlSharingUnsupported,
313 #[fail(display = "Length of 'devices' must be greater than zero.")]
314 CreateProgramWithBinaryDevicesLenZero,
315 #[fail(display = "Length of 'devices' must equal the length of 'binaries' \
316 (e.g. one binary per device).")]
317 CreateProgramWithBinaryDevicesLenMismatch,
318 #[fail(display = "The specified function does not exist for the implementation or \
319 'platform' is not a valid platform.")]
320 GetExtensionFunctionAddressForPlatformInvalidFunction,
321 #[fail(display = "No OpenCL platforms found. Check your driver.")]
322 DefaultPlatformNoPlatforms,
323 #[fail(display = "The default platform set by the environment variable \
324 'OCL_DEFAULT_PLATFORM_IDX' has an index which is out of range \
325 (index: [{}], max: [{}]).", default_platform_idx, max_idx)]
326 DefaultPlatformEnvVarBadIdx { default_platform_idx: usize, max_idx: usize },
327 #[fail(display = "The default device type set by the environment variable \
328 'OCL_DEFAULT_DEVICE_TYPE': ('{}') is invalid. Valid types are: 'DEFAULT', 'CPU', \
329 'GPU', 'ACCELERATOR', 'CUSTOM', and 'ALL'.", _0)]
330 DefaultDeviceTypeInvalidType(String),
331}
332
333
334struct DevicePtrList(Vec<cl_device_id>);
345
346impl DevicePtrList {
347 fn new<D: ClDeviceIdPtr>(devices: Option<&[D]>) -> DevicePtrList {
349 let list = match devices {
350 Some(device_ids) => {
351 device_ids.iter().map(|d| d.as_ptr()).collect::<Vec<_>>()
352 },
353 None => Vec::new(),
354 };
355
356 DevicePtrList(list)
357 }
358
359 fn as_ptr(&self) -> *const cl_device_id {
361 match self.0.len() {
362 0 => ptr::null(),
363 _ => self.0.as_ptr(),
364 }
365 }
366
367 fn num(&self) -> u32 {
369 self.0.len() as u32
370 }
371}
372
373impl<D> From<Option<&[D]>> for DevicePtrList where D: ClDeviceIdPtr {
374 fn from(devices: Option<&[D]>) -> DevicePtrList {
375 DevicePtrList::new(devices)
376 }
377}
378
379
380fn resolve_event_ptrs<En: ClNullEventPtr, Ewl: ClWaitListPtr>(wait_list: Option<Ewl>,
382 new_event: Option<En>) -> (cl_uint, *const cl_event, *mut cl_event)
383{
384 let (wait_list_len, wait_list_ptr) = match wait_list {
387 Some(wl) => {
388 if wl.count() > 0 {
389 (wl.count(), unsafe { wl.as_ptr_ptr() } as *const cl_event)
390 } else {
391 (0, ptr::null() as *const cl_event)
392 }
393 },
394 None => (0, ptr::null() as *const cl_event),
395 };
396
397 let new_event_ptr = match new_event {
398 Some(mut ne) => ne.alloc_new(),
399 None => ptr::null_mut() as *mut cl_event,
400 };
401
402 (wait_list_len, wait_list_ptr, new_event_ptr)
403}
404
405fn resolve_work_dims(work_dims: Option<&[usize; 3]>) -> *const size_t {
407 match work_dims {
408 Some(w) => w as *const [usize; 3] as *const size_t,
409 None => ptr::null(),
410 }
411}
412
413pub(crate) fn verify_versions(versions: &[OpenclVersion], required_version: [u16; 2],
415 function: ApiFunction, kind: VersionKind) -> OclCoreResult<()> {
416 let reqd_ver = OpenclVersion::from(required_version);
417
418 for &d_ver in versions {
419 if d_ver < reqd_ver {
420 return Err(VersionLowError {
421 detected: d_ver,
422 required: reqd_ver,
423 function,
424 kind,
425 }.into())
426 }
427 }
428
429 Ok(())
430}
431
432fn verify_platform_version<V: ClVersions>(provided_version: Option<&OpenclVersion>,
435 required_version: [u16; 2], fallback_version_source: &V, function: ApiFunction)
436 -> OclCoreResult<()> {
437 match provided_version {
438 Some(pv) => {
439 let vers = [*pv];
440 verify_versions(&vers, required_version, function, VersionKind::Platform)
441 },
442 None => fallback_version_source.verify_platform_version(required_version),
443 }
444}
445
446fn verify_device_version<V: ClVersions>(provided_version: Option<&OpenclVersion>,
449 required_version: [u16; 2], fallback_version_source: &V, function: ApiFunction)
450 -> OclCoreResult<()> {
451 match provided_version {
452 Some(pv) => {
453 let ver = [*pv];
454 verify_versions(&ver, required_version, function, VersionKind::Device)
455 },
456 None => fallback_version_source.verify_device_versions(required_version),
457 }
458}
459
460fn verify_device_versions<V: ClVersions>(provided_versions: Option<&[OpenclVersion]>,
462 required_version: [u16; 2], fallback_versions_source: &V, function: ApiFunction)
463 -> OclCoreResult<()> {
464 match provided_versions {
465 Some(pv) => verify_versions(pv, required_version, function, VersionKind::Device),
466 None => fallback_versions_source.verify_device_versions(required_version),
467 }
468}
469
470pub fn get_platform_ids() -> OclCoreResult<Vec<PlatformId>> {
482 let mut num_platforms = 0 as cl_uint;
483
484 let mut errcode: cl_int = unsafe {
486 ffi::clGetPlatformIDs(0, ptr::null_mut(), &mut num_platforms)
487 };
488
489 if errcode == Status::CL_PLATFORM_NOT_FOUND_KHR as i32 {
492 let sleep_ms = PLATFORM_IDS_ATTEMPT_TIMEOUT_MS;
494 let mut iters_rmng = PLATFORM_IDS_ATTEMPT_COUNT;
495
496 while errcode == Status::CL_PLATFORM_NOT_FOUND_KHR as i32 {
497 if iters_rmng == 0 {
498 return Err(ApiWrapperError::GetPlatformIdsPlatformListUnavailable(
499 (PLATFORM_IDS_ATTEMPT_COUNT * sleep_ms) / 1000).into())
500 }
501
502 thread::sleep(Duration::from_millis(sleep_ms));
504
505 errcode = unsafe {
507 ffi::clGetPlatformIDs(0, ptr::null_mut(), &mut num_platforms)
508 };
509
510 iters_rmng -= 1;
511 }
512 }
513
514 r#try!(eval_errcode(errcode, (), "clGetPlatformIDs", None::<String>));
515
516 if num_platforms == 0 {
518 return Ok(vec![]);
519 }
520
521 let mut null_vec: Vec<usize> = iter::repeat(0).take(num_platforms as usize).collect();
523 let (ptr, len, cap) = (null_vec.as_mut_ptr(), null_vec.len(), null_vec.capacity());
524
525 let mut platforms: Vec<PlatformId> = unsafe {
527 mem::forget(null_vec);
528 Vec::from_raw_parts(ptr as *mut PlatformId, len, cap)
529 };
530
531 errcode = unsafe {
532 ffi::clGetPlatformIDs(
533 num_platforms,
534 platforms.as_mut_ptr() as *mut cl_platform_id,
535 ptr::null_mut()
536 )
537 };
538
539 eval_errcode(errcode, platforms, "clGetPlatformIDs", None::<String>)
540}
541
542pub fn get_platform_info<P: ClPlatformIdPtr>(platform: P, request: PlatformInfo,
544 ) -> OclCoreResult<PlatformInfoResult>
545{
546 let mut result_size = 0 as size_t;
547
548 let errcode = unsafe {
549 ffi::clGetPlatformInfo(
550 platform.as_ptr(),
551 request as cl_platform_info,
552 0 as size_t,
553 ptr::null_mut(),
554 &mut result_size as *mut size_t,
555 )
556 };
557
558 eval_errcode(errcode, (), "clGetPlatformInfo", None::<String>)?;
562
563 if result_size == 0 {
565 return PlatformInfoResult::from_bytes(request, vec![]);
566 }
567
568 let mut result: Vec<u8> = iter::repeat(32u8).take(result_size as usize).collect();
569
570 let errcode = unsafe {
571 ffi::clGetPlatformInfo(
572 platform.as_ptr(),
573 request as cl_platform_info,
574 result_size as size_t,
575 result.as_mut_ptr() as *mut c_void,
576 ptr::null_mut() as *mut size_t,
577 )
578 };
579
580 let result = eval_errcode(errcode, result, "clGetPlatformInfo", None::<String>)?;
581 PlatformInfoResult::from_bytes(request, result)
582}
583
584pub fn get_device_ids<P: ClPlatformIdPtr>(
590 platform: P,
591 device_types: Option<DeviceType>,
592 devices_max: Option<u32>,
593 ) -> OclCoreResult<Vec<DeviceId>>
594{
595 let device_types = device_types.unwrap_or(r#try!(default_device_type()));
596 let mut devices_available: cl_uint = 0;
597
598 let devices_max = match devices_max {
599 Some(d) => {
600 if d == 0 {
601 return Err(ApiWrapperError::GetDeviceIdsDevicesMaxZero.into());
602 } else {
603 d
604 }
605 },
606 None => crate::DEVICES_MAX,
607 };
608
609 let mut device_ids: Vec<DeviceId> = iter::repeat(unsafe { DeviceId::null() } )
610 .take(devices_max as usize).collect();
611
612 let errcode = unsafe { ffi::clGetDeviceIDs(
613 platform.as_ptr(),
614 device_types.bits() as cl_device_type,
615 devices_max,
616 device_ids.as_mut_ptr() as *mut cl_device_id,
617 &mut devices_available,
618 ) };
619 r#try!(eval_errcode(errcode, (), "clGetDeviceIDs", None::<String>));
620
621 unsafe { device_ids.set_len(devices_available as usize); }
623 device_ids.shrink_to_fit();
624
625 Ok(device_ids)
626}
627
628pub fn get_device_info_raw<D: ClDeviceIdPtr>(device: D, request: u32) -> OclCoreResult<Vec<u8>> {
630 let mut result_size: size_t = 0;
631
632 let errcode = unsafe { ffi::clGetDeviceInfo(
633 device.as_ptr() as cl_device_id,
634 request as cl_device_info,
635 0 as size_t,
636 ptr::null_mut(),
637 &mut result_size as *mut size_t,
638 ) };
639
640 if errcode < 0 {
646 if Status::from_i32(errcode).unwrap() == Status::CL_INVALID_VALUE {
647 return Err(OclCoreError::from("<unavailable (CL_INVALID_VALUE)>"));
648 } else if Status::from_i32(errcode).unwrap() == Status::CL_INVALID_OPERATION {
649 return Err(OclCoreError::from("<unavailable (CL_INVALID_OPERATION)>"));
650 }
651 }
652
653 eval_errcode(errcode, (), "clGetDeviceInfo", None::<String>)?;
654
655 if result_size == 0 {
657 return Ok(vec![]);
658 }
659
660 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
661
662 let errcode = unsafe { ffi::clGetDeviceInfo(
663 device.as_ptr() as cl_device_id,
664 request as cl_device_info,
665 result_size as size_t,
666 result.as_mut_ptr() as *mut _ as *mut c_void,
667 ptr::null_mut(),
668 ) };
669
670 eval_errcode(errcode, result, "clGetDeviceInfo", None::<String>)
671}
672
673pub fn get_device_info<D: ClDeviceIdPtr>(device: D, request: DeviceInfo)
675 -> OclCoreResult<DeviceInfoResult>
676{
677 let result = get_device_info_raw(device, request as cl_device_info)?;
678
679 match request {
680 DeviceInfo::MaxWorkItemSizes => {
681 let max_wi_dims = match get_device_info(device, DeviceInfo::MaxWorkItemDimensions)? {
682 DeviceInfoResult::MaxWorkItemDimensions(d) => d,
683 _ => panic!("get_device_info(): Error determining dimensions for \
685 'DeviceInfo::MaxWorkItemSizes' due to mismatched variants."),
686 };
687 DeviceInfoResult::from_bytes_max_work_item_sizes(request, result, max_wi_dims)
688 },
689 _ => DeviceInfoResult::from_bytes(request, result)
690 }
691}
692
693pub fn create_sub_devices(device_version: Option<&OpenclVersion>) -> OclCoreResult<()> {
697 let _ = device_version;
704 unimplemented!();
705}
706
707pub unsafe fn retain_device(device: &DeviceId, device_version: Option<&OpenclVersion>)
711 -> OclCoreResult<()> {
712 verify_device_version(device_version, [1, 2], device, ApiFunction::RetainDevice)?;
713 eval_errcode(ffi::clRetainDevice(device.as_ptr()), (), "clRetainDevice", None::<String>)
714}
715
716pub unsafe fn release_device(device: &DeviceId, device_version: Option<&OpenclVersion>)
720 -> OclCoreResult<()> {
721 verify_device_version(device_version, [1, 2], device, ApiFunction::ReleaseDevice)?;
722 eval_errcode(ffi::clReleaseDevice(device.as_ptr()), (), "clReleaseDevice", None::<String>)
723}
724
725pub fn create_context<D: ClDeviceIdPtr>(properties: Option<&ContextProperties>, device_ids: &[D],
741 pfn_notify: Option<CreateContextCallbackFn>, user_data: Option<UserDataPtr>
742 ) -> OclCoreResult<Context>
743{
744 if device_ids.is_empty() {
745 return Err(ApiWrapperError::CreateContextNoDevicesSpecified.into())
746 }
747
748 if let Some(properties) = properties {
754 if properties.contains_gl_context_or_sharegroup() {
755 for &device in device_ids {
756 match device_supports_cl_gl_sharing(device) {
757 Ok(true) => {},
758 Ok(false) => {
759 return Err(ApiWrapperError::CreateContextClGlSharingUnsupported.into())
760 },
761 Err(err) => return Err(err),
762 }
763 }
764 }
765 }
766
767 let properties_bytes: Vec<isize> = match properties {
768 Some(props) => props.to_raw(),
769 None => Vec::<isize>::with_capacity(0),
770 };
771
772 let properties_ptr = if properties_bytes.is_empty() {
779 ptr::null() as *const cl_context_properties
780 } else {
781 properties_bytes.as_ptr()
782 };
783
784 let user_data_ptr = match user_data {
786 Some(_) => ptr::null_mut(),
787 None => ptr::null_mut(),
788 };
789
790 let device_ids: Vec<_> = device_ids.iter().map(|d| d.as_ptr()).collect();
791
792 let mut errcode: cl_int = 0;
793
794 let context_ptr = unsafe { ffi::clCreateContext(
795 properties_ptr,
796 device_ids.len() as cl_uint,
797 device_ids.as_ptr() as *const cl_device_id,
798 pfn_notify,
799 user_data_ptr,
800 &mut errcode,
801 ) };
802 eval_errcode(errcode, context_ptr, "clCreateContext", None::<String>)
805 .map(|ctx_ptr| unsafe { Context::from_raw_create_ptr(ctx_ptr) })
806}
807
808pub fn create_context_from_type<D: ClDeviceIdPtr>(properties: Option<&ContextProperties>,
820 device_type: DeviceType, pfn_notify: Option<CreateContextCallbackFn>,
821 user_data: Option<UserDataPtr>) -> OclCoreResult<Context> {
822
823 let properties_bytes: Vec<isize> = match properties {
827 Some(props) => props.to_raw(),
828 None => Vec::<isize>::with_capacity(0),
829 };
830
831 let properties_ptr = if properties_bytes.is_empty() {
838 ptr::null() as *const cl_context_properties
839 } else {
840 properties_bytes.as_ptr()
841 };
842
843 let user_data_ptr = match user_data {
845 Some(_) => ptr::null_mut(),
846 None => ptr::null_mut(),
847 };
848
849 let mut errcode: cl_int = 0;
850
851 let context_ptr = unsafe { ffi::clCreateContextFromType(
852 properties_ptr,
853 device_type.bits(),
854 pfn_notify,
855 user_data_ptr,
856 &mut errcode,
857 ) };
858 eval_errcode(errcode, context_ptr, "clCreateContextFromType", None::<String>)
859 .map(|ctx_ptr| unsafe { Context::from_raw_create_ptr(ctx_ptr) })
860}
861
862pub unsafe fn retain_context<C>(context: C) -> OclCoreResult<()>
864 where C: ClContextPtr
865{
866 eval_errcode(ffi::clRetainContext(context.as_ptr()), (), "clRetainContext", None::<String>)
867}
868
869pub unsafe fn release_context<C>(context: C) -> OclCoreResult<()>
871 where C: ClContextPtr
872{
873 eval_errcode(ffi::clReleaseContext(context.as_ptr()), (), "clReleaseContext", None::<String>)
874}
875
876fn get_context_info_unparsed<C>(context: C, request: ContextInfo)
877 -> OclCoreResult<Vec<u8>>
878 where C: ClContextPtr
879{
880 let mut result_size: size_t = 0;
881
882 let errcode = unsafe { ffi::clGetContextInfo(
883 context.as_ptr() as cl_context,
884 request as cl_context_info,
885 0 as size_t,
886 ptr::null_mut(),
887 &mut result_size as *mut usize,
888 ) };
889
890 eval_errcode(errcode, (), "clGetContextInfo", None::<String>)?;
891
892 if !cfg!(release) {
896 let err_if_zero_result_size = request as cl_context_info == ffi::CL_CONTEXT_DEVICES;
897
898 if result_size > 10000 || (result_size == 0 && err_if_zero_result_size) {
899 return Err(OclCoreError::from("\n\nocl::core::context_info(): \
900 Possible invalid context detected. \n\
901 Context info result size is either '> 10k bytes' or '== 0'. Almost certainly an \n\
902 invalid context object. If not, please file an issue at: \n\
903 https://github.com/cogciprocate/ocl/issues.\n\n"));
904 }
905 }
906
907 if result_size == 0 {
909 return Ok(vec![]);
910 }
911
912 let mut result: Vec<u8> = iter::repeat(0).take(result_size).collect();
913
914 let errcode = unsafe { ffi::clGetContextInfo(
915 context.as_ptr() as cl_context,
916 request as cl_context_info,
917 result_size as size_t,
918 result.as_mut_ptr() as *mut c_void,
919 ptr::null_mut(),
920 ) };
921
922 eval_errcode(errcode, result, "clGetContextInfo", None::<String>)
923}
924
925pub fn get_context_info<C>(context: C, request: ContextInfo) -> OclCoreResult<ContextInfoResult>
935 where C: ClContextPtr {
936 ContextInfoResult::from_bytes(request, get_context_info_unparsed(context, request)?)
937}
938
939pub fn get_context_platform<C>(context: C) -> OclCoreResult<Option<PlatformId>>
945 where C: ClContextPtr
946{
947 let props_raw_bytes = get_context_info_unparsed(context, ContextInfo::Properties)?;
948
949 let prop = unsafe {
950 let props_raw = crate::util::bytes_into_vec::<isize>(props_raw_bytes)?;
951 ContextProperties::extract_property_from_raw(crate::ContextProperty::Platform, &props_raw)
952 };
953
954 if let Some(crate::ContextPropertyValue::Platform(plat)) = prop {
955 Ok(Some(plat))
956 } else {
957 Ok(None)
958 }
959}
960
961#[cfg(not(feature="opencl_vendor_mesa"))]
982pub fn get_gl_context_info_khr(properties: &ContextProperties, request: GlContextInfo)
983 -> OclCoreResult<GlContextInfoResult>
984{
985 let cl_get_gl_context_info_khr_fn = unsafe {
986 let fn_name = match ::std::ffi::CString::new("clGetGLContextInfoKHR") {
987 Ok(s) => s,
988 Err(err) => return Err(err.into()),
989 };
990
991 let plat = match properties.get_platform() {
992 Some(p) => p,
993 None => {
994 return Err("ocl::core::get_gl_context_info_khr: \
995 Context properties must specify a platform.".into());
996 },
997 };
998
999 let fn_ptr = ffi::clGetExtensionFunctionAddressForPlatform(plat.as_ptr(),
1000 fn_name.as_ptr() as *mut _);
1001
1002 if fn_ptr.is_null() {
1003 return Err("Unable to get extension function \
1004 address for clGetGLContextInfoKHR. The function is not supported by this \
1005 platform.".into());
1006 }
1007
1008 fn_ptr as ffi::clGetGLContextInfoKHR_fn
1009 };
1010
1011 let props_bytes = properties.to_raw();
1012 let mut result_size: size_t = 0;
1013
1014 let errcode = unsafe { (*cl_get_gl_context_info_khr_fn)(
1015 props_bytes.as_ptr(),
1016 request as cl_gl_context_info,
1017 0 as size_t,
1018 ptr::null_mut(),
1019 &mut result_size as *mut usize,
1020 ) };
1021
1022 eval_errcode(errcode, (), "clGetGlContextInfoKhr", None::<String>)?;
1026
1027 if result_size == 0 {
1028 return GlContextInfoResult::from_bytes(request, vec![]);
1029 }
1030
1031 let mut result: Vec<u8> = iter::repeat(0).take(result_size).collect();
1038
1039 let errcode = unsafe { (*cl_get_gl_context_info_khr_fn)(
1040 props_bytes.as_ptr(),
1041 request as cl_gl_context_info,
1042 result_size as size_t,
1043 result.as_mut_ptr() as *mut c_void,
1044 ptr::null_mut(),
1045 ) };
1046
1047 let result = eval_errcode(errcode, result, "clGetGlContextInfoKhr", None::<String>)?;
1048 GlContextInfoResult::from_bytes(request, result)
1049}
1050
1051
1052pub fn create_command_queue<C, D>(
1058 context: C,
1059 device: D,
1060 properties: Option<CommandQueueProperties>,
1061 ) -> OclCoreResult<CommandQueue>
1062 where C: ClContextPtr, D: ClDeviceIdPtr
1063{
1064 r#try!(verify_context(context));
1066
1067 let cmd_queue_props = match properties {
1068 Some(p) => p.bits,
1069 None => 0,
1070 };
1071
1072 let mut errcode: cl_int = 0;
1073
1074 let cq_ptr = unsafe { ffi::clCreateCommandQueue(
1075 context.as_ptr(),
1076 device.as_ptr(),
1077 cmd_queue_props,
1078 &mut errcode
1079 ) };
1080 eval_errcode(errcode, cq_ptr, "clCreateCommandQueue", None::<String>)
1081 .map(|cq_ptr| unsafe { CommandQueue::from_raw_create_ptr(cq_ptr) })
1082
1083}
1084
1085pub unsafe fn retain_command_queue(queue: &CommandQueue) -> OclCoreResult<()> {
1087 eval_errcode(ffi::clRetainCommandQueue(queue.as_ptr()), (), "clRetainCommandQueue", None::<String>)
1088}
1089
1090pub unsafe fn release_command_queue(queue: &CommandQueue) -> OclCoreResult<()> {
1094 eval_errcode(ffi::clReleaseCommandQueue(queue.as_ptr()), (), "clReleaseCommandQueue", None::<String>)
1095}
1096
1097pub fn get_command_queue_info(queue: &CommandQueue, request: CommandQueueInfo,
1099 ) -> OclCoreResult<CommandQueueInfoResult>
1100{
1101 let mut result_size: size_t = 0;
1102
1103 let errcode = unsafe { ffi::clGetCommandQueueInfo(
1104 queue.as_ptr() as cl_command_queue,
1105 request as cl_command_queue_info,
1106 0 as size_t,
1107 ptr::null_mut(),
1108 &mut result_size as *mut size_t,
1109 ) };
1110
1111 eval_errcode(errcode, (), "clGetCommandQueueInfo", None::<String>)?;
1112
1113 if result_size == 0 {
1115 return CommandQueueInfoResult::from_bytes(request, vec![]);
1116 }
1117
1118 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
1119
1120 let errcode = unsafe { ffi::clGetCommandQueueInfo(
1121 queue.as_ptr() as cl_command_queue,
1122 request as cl_command_queue_info,
1123 result_size,
1124 result.as_mut_ptr() as *mut _ as *mut c_void,
1125 ptr::null_mut(),
1126 ) };
1127
1128 let result = eval_errcode(errcode, result, "clGetCommandQueueInfo", None::<String>)?;
1129 CommandQueueInfoResult::from_bytes(request, result)
1130}
1131
1132pub unsafe fn create_buffer<C, T>(
1144 context: C,
1145 flags: MemFlags,
1146 len: usize,
1147 data: Option<&[T]>,
1148 ) -> OclCoreResult<Mem>
1149 where C: ClContextPtr, T: OclPrm
1150{
1151 r#try!(verify_context(context));
1153
1154 let mut errcode: cl_int = 0;
1155
1156 let host_ptr = match data {
1157 Some(d) => {
1158 if d.len() != len {
1159 return Err(ApiWrapperError::CreateBufferDataLengthMismatch.into())
1160 }
1161 d.as_ptr() as cl_mem
1162 },
1163 None => ptr::null_mut(),
1164 };
1165
1166 let buf_ptr = ffi::clCreateBuffer(
1167 context.as_ptr(),
1168 flags.bits() as cl_mem_flags,
1169 len * mem::size_of::<T>(),
1170 host_ptr,
1171 &mut errcode,
1172 );
1173
1174 eval_errcode(errcode, buf_ptr, "clCreateBuffer", None::<String>)
1176 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1177}
1178
1179#[cfg(not(feature="opencl_vendor_mesa"))]
1189pub unsafe fn create_from_gl_buffer<C>(
1190 context: C,
1191 gl_object: cl_GLuint,
1192 flags: MemFlags
1193 ) -> OclCoreResult<Mem>
1194 where C: ClContextPtr
1195{
1196 r#try!(verify_context(context));
1198
1199 let mut errcode: cl_int = 0;
1200
1201 let buf_ptr = clCreateFromGLBuffer(
1202 context.as_ptr(),
1203 flags.bits() as cl_mem_flags,
1204 gl_object,
1205 &mut errcode);
1206
1207 eval_errcode(errcode, buf_ptr, "clCreateFromGLBuffer", None::<String>)
1208 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1209}
1210
1211#[cfg(not(feature="opencl_vendor_mesa"))]
1221pub unsafe fn create_from_gl_renderbuffer<C>(
1222 context: C,
1223 renderbuffer: cl_GLuint,
1224 flags: MemFlags
1225 ) -> OclCoreResult<Mem>
1226 where C: ClContextPtr
1227{
1228 r#try!(verify_context(context));
1230
1231 let mut errcode: cl_int = 0;
1232
1233 let buf_ptr = clCreateFromGLRenderbuffer(
1234 context.as_ptr(),
1235 flags.bits() as cl_mem_flags,
1236 renderbuffer,
1237 &mut errcode);
1238
1239 eval_errcode(errcode, buf_ptr, "clCreateFromGLRenderbuffer", None::<String>)
1240 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1241}
1242
1243#[cfg(not(feature="opencl_vendor_mesa"))]
1257pub unsafe fn create_from_gl_texture<C>(
1258 context: C,
1259 texture_target: cl_GLenum,
1260 miplevel: cl_GLint,
1261 texture: cl_GLuint,
1262 flags: MemFlags,
1263 device_versions: Option<&[OpenclVersion]>,
1264 ) -> OclCoreResult<Mem>
1265 where C: ClContextPtr
1266{
1267 r#try!(verify_context(context));
1269
1270 verify_device_versions(device_versions, [1, 2], &context.as_ptr(),
1272 ApiFunction::CreateFromGLTexture)?;
1273
1274 let mut errcode: cl_int = 0;
1292
1293 let buf_ptr = clCreateFromGLTexture(
1294 context.as_ptr(),
1295 flags.bits() as cl_mem_flags,
1296 texture_target,
1297 miplevel,
1298 texture,
1299 &mut errcode);
1300
1301 eval_errcode(errcode, buf_ptr, "clCreateFromGLTexture", None::<String>)
1302 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1303}
1304
1305#[cfg(not(feature="opencl_vendor_mesa"))]
1309pub unsafe fn create_from_gl_texture_2d<C>(
1310 context: C,
1311 texture_target: cl_GLenum,
1312 miplevel: cl_GLint,
1313 texture: cl_GLuint,
1314 flags: MemFlags
1315 ) -> OclCoreResult<Mem>
1316 where C: ClContextPtr
1317{
1318 r#try!(verify_context(context));
1320
1321 let mut errcode: cl_int = 0;
1322
1323 let buf_ptr = clCreateFromGLTexture2D(
1324 context.as_ptr(),
1325 flags.bits() as cl_mem_flags,
1326 texture_target,
1327 miplevel,
1328 texture,
1329 &mut errcode);
1330
1331 eval_errcode(errcode, buf_ptr, "clCreateFromGLTexture2D", None::<String>)
1332 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1333}
1334
1335#[cfg(not(feature="opencl_vendor_mesa"))]
1339pub unsafe fn create_from_gl_texture_3d<C>(
1340 context: C,
1341 texture_target: cl_GLenum,
1342 miplevel: cl_GLint,
1343 texture: cl_GLuint,
1344 flags: MemFlags
1345 ) -> OclCoreResult<Mem>
1346 where C: ClContextPtr
1347{
1348 r#try!(verify_context(context));
1350
1351 let mut errcode: cl_int = 0;
1352
1353 let buf_ptr = clCreateFromGLTexture3D(
1354 context.as_ptr(),
1355 flags.bits() as cl_mem_flags,
1356 texture_target,
1357 miplevel,
1358 texture,
1359 &mut errcode);
1360
1361 eval_errcode(errcode, buf_ptr, "clCreateFromGLTexture3D", None::<String>)
1362 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1363}
1364
1365pub fn create_sub_buffer<T: OclPrm>(
1374 buffer: &Mem,
1375 flags: MemFlags,
1376 buffer_create_info: &BufferRegion<T>,
1377 ) -> OclCoreResult<Mem>
1378{
1379 let buffer_create_type = BufferCreateType::Region;
1380 let buffer_create_info_bytes = buffer_create_info.to_bytes();
1381 let mut errcode = 0i32;
1382
1383 let sub_buf_ptr = unsafe { ffi::clCreateSubBuffer(
1384 buffer.as_ptr(),
1385 flags.bits(),
1386 buffer_create_type as cl_buffer_create_type,
1387 &buffer_create_info_bytes as *const _ as *const c_void,
1388 &mut errcode,
1389 ) };
1390
1391 eval_errcode(errcode, sub_buf_ptr, "clCreateSubBuffer", None::<String>)
1392 .map(|ptr| unsafe { Mem::from_raw_create_ptr(ptr) })
1393}
1394
1395pub unsafe fn create_image<C, T>(
1406 context: C,
1407 flags: MemFlags,
1408 format: &ImageFormat,
1409 desc: &ImageDescriptor,
1410 data: Option<&[T]>,
1411 device_versions: Option<&[OpenclVersion]>,
1412 ) -> OclCoreResult<Mem>
1413 where C: ClContextPtr, T: OclPrm
1414{
1415 r#try!(verify_context(context));
1417
1418 verify_device_versions(device_versions, [1, 2], &context.as_ptr(), ApiFunction::CreateImage)?;
1420
1421 let mut errcode: cl_int = 0;
1422
1423 let host_ptr = match data {
1424 Some(d) => {
1425 d.as_ptr() as cl_mem
1428 },
1429 None => ptr::null_mut(),
1430 };
1431
1432 let image_ptr = ffi::clCreateImage(
1433 context.as_ptr(),
1434 flags.bits() as cl_mem_flags,
1435 &format.to_raw() as *const cl_image_format,
1436 &desc.to_raw() as *const cl_image_desc,
1437 host_ptr,
1438 &mut errcode as *mut cl_int,
1439 );
1440
1441 eval_errcode(errcode, image_ptr, "clCreateImage", None::<String>)
1442 .map(|ptr| Mem::from_raw_create_ptr(ptr))
1443}
1444
1445pub unsafe fn retain_mem_object(mem: &Mem) -> OclCoreResult<()> {
1447 eval_errcode(ffi::clRetainMemObject(mem.as_ptr()), (), "clRetainMemObject", None::<String>)
1448}
1449
1450pub unsafe fn release_mem_object(mem: &Mem) -> OclCoreResult<()> {
1452 eval_errcode(ffi::clReleaseMemObject(mem.as_ptr()), (), "clReleaseMemObject", None::<String>)
1453}
1454
1455pub fn get_supported_image_formats<C>(
1466 context: C,
1467 flags: MemFlags,
1468 image_type: MemObjectType,
1469 ) -> OclCoreResult<Vec<ImageFormatParseResult>>
1470 where C: ClContextPtr
1471{
1472 let mut num_image_formats = 0 as cl_uint;
1473
1474 let errcode = unsafe { ffi::clGetSupportedImageFormats(
1475 context.as_ptr(),
1476 flags.bits() as cl_mem_flags,
1477 image_type as cl_mem_object_type,
1478 0 as cl_uint,
1479 ptr::null_mut() as *mut cl_image_format,
1480 &mut num_image_formats as *mut cl_uint,
1481 ) };
1482 r#try!(eval_errcode(errcode, (), "clGetSupportedImageFormats", None::<String>));
1483
1484 if num_image_formats == 0 {
1486 return Ok(vec![]);
1487 }
1488
1489 let mut image_formats: Vec<cl_image_format> = (0..(num_image_formats as usize)).map(|_| {
1490 ImageFormat::new_raw()
1491 } ).collect();
1492
1493 debug_assert!(image_formats.len() == num_image_formats as usize && !image_formats.is_empty());
1494
1495 let errcode = unsafe { ffi::clGetSupportedImageFormats(
1496 context.as_ptr(),
1497 flags.bits() as cl_mem_flags,
1498 image_type as cl_mem_object_type,
1499 num_image_formats,
1500 image_formats.as_mut_ptr() as *mut _ as *mut cl_image_format,
1501 ptr::null_mut(),
1502 ) };
1503
1504 r#try!(eval_errcode(errcode, (), "clGetSupportedImageFormats", None::<String>));
1505 Ok(ImageFormat::list_from_raw(image_formats))
1506}
1507
1508
1509pub fn get_mem_object_info(obj: &Mem, request: MemInfo) -> OclCoreResult<MemInfoResult> {
1511 let mut result_size: size_t = 0;
1512
1513 let errcode = unsafe { ffi::clGetMemObjectInfo(
1514 obj.as_ptr() as cl_mem,
1515 request as cl_mem_info,
1516 0 as size_t,
1517 ptr::null_mut(),
1518 &mut result_size as *mut size_t,
1519 ) };
1520
1521 eval_errcode(errcode, (), "clGetMemObjectInfo", None::<String>)?;
1522
1523 if result_size == 0 {
1525 return MemInfoResult::from_bytes(request, vec![]);
1526 }
1527
1528 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
1529
1530 let errcode = unsafe { ffi::clGetMemObjectInfo(
1531 obj.as_ptr() as cl_mem,
1532 request as cl_mem_info,
1533 result_size,
1534 result.as_mut_ptr() as *mut _ as *mut c_void,
1535 ptr::null_mut(),
1536 ) };
1537 let result = eval_errcode(errcode, result, "clGetMemObjectInfo", None::<String>)?;
1538 MemInfoResult::from_bytes(request, result)
1539}
1540
1541
1542pub fn get_image_info(obj: &Mem, request: ImageInfo) -> OclCoreResult<ImageInfoResult> {
1544 let mut result_size: size_t = 0;
1545
1546 let errcode = unsafe { ffi::clGetImageInfo(
1547 obj.as_ptr() as cl_mem,
1548 request as cl_image_info,
1549 0 as size_t,
1550 ptr::null_mut(),
1551 &mut result_size as *mut size_t,
1552 ) };
1553
1554 eval_errcode(errcode, (), "clGetImageInfo", None::<String>)?;
1555
1556 if result_size == 0 {
1558 return ImageInfoResult::from_bytes(request, vec![]);
1559 }
1560
1561 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
1562
1563 let errcode = unsafe { ffi::clGetImageInfo(
1564 obj.as_ptr() as cl_mem,
1565 request as cl_image_info,
1566 result_size,
1567 result.as_mut_ptr() as *mut _ as *mut c_void,
1568 ptr::null_mut(),
1569 ) };
1570
1571 let result = eval_errcode(errcode, result, "clGetImageInfo", None::<String>)?;
1572 ImageInfoResult::from_bytes(request, result)
1573}
1574
1575pub fn set_mem_object_destructor_callback() -> OclCoreResult<()> {
1577 unimplemented!();
1581}
1582
1583pub fn create_sampler<C>(context: C, normalize_coords: bool, addressing_mode: AddressingMode,
1591 filter_mode: FilterMode) -> OclCoreResult<Sampler>
1592 where C: ClContextPtr
1593{
1594 let mut errcode = 0;
1595
1596 let sampler = unsafe { Sampler::from_raw_create_ptr(ffi::clCreateSampler(
1597 context.as_ptr(),
1598 normalize_coords as cl_bool,
1599 addressing_mode as cl_addressing_mode,
1600 filter_mode as cl_filter_mode,
1601 &mut errcode,
1602 )) };
1603
1604 eval_errcode(errcode, sampler, "clCreateSampler", None::<String>)
1605}
1606
1607pub unsafe fn retain_sampler(sampler: &Sampler) -> OclCoreResult<()> {
1609 eval_errcode(ffi::clRetainSampler(sampler.as_ptr()), (), "clRetainSampler", None::<String>)
1610}
1611
1612pub unsafe fn release_sampler(sampler: &Sampler) -> OclCoreResult<()> {
1614 eval_errcode(ffi::clReleaseSampler(sampler.as_ptr()), (), "clReleaseSampler", None::<String>)
1615}
1616
1617pub fn get_sampler_info(obj: &Sampler, request: SamplerInfo,
1621 ) -> OclCoreResult<SamplerInfoResult>
1622{
1623 let mut result_size: size_t = 0;
1624
1625 let errcode = unsafe { ffi::clGetSamplerInfo(
1626 obj.as_ptr() as cl_sampler,
1627 request as cl_sampler_info,
1628 0 as size_t,
1629 ptr::null_mut(),
1630 &mut result_size as *mut size_t,
1631 ) };
1632
1633 eval_errcode(errcode, (), "clGetSamplerInfo", None::<String>)?;
1638
1639 if result_size == 0 {
1641 return SamplerInfoResult::from_bytes(request, vec![]);
1642 }
1643
1644 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
1645
1646 let errcode = unsafe { ffi::clGetSamplerInfo(
1647 obj.as_ptr() as cl_sampler,
1648 request as cl_sampler_info,
1649 result_size,
1650 result.as_mut_ptr() as *mut _ as *mut c_void,
1651 ptr::null_mut(),
1652 ) };
1653
1654 let result = eval_errcode(errcode, result, "clGetSamplerInfo", None::<String>)?;
1655 SamplerInfoResult::from_bytes(request, result)
1656}
1657
1658pub fn create_program_with_source<C>(
1664 context: C,
1665 src_strings: &[CString],
1666 ) -> OclCoreResult<Program>
1667 where C: ClContextPtr
1668{
1669 r#try!(verify_context(context));
1671
1672 let ks_lens: Vec<usize> = src_strings.iter().map(|cs| cs.as_bytes().len()).collect();
1674
1675 let kern_string_ptrs: Vec<*const _> = src_strings.iter().map(|cs| cs.as_ptr()).collect();
1677
1678 let mut errcode: cl_int = 0;
1679
1680 let program_ptr = unsafe { ffi::clCreateProgramWithSource(
1681 context.as_ptr(),
1682 kern_string_ptrs.len() as cl_uint,
1683 kern_string_ptrs.as_ptr() as *const *const _,
1684 ks_lens.as_ptr() as *const usize,
1685 &mut errcode,
1686 ) };
1687
1688 eval_errcode(errcode, program_ptr, "clCreateProgramWithSource", None::<String>)
1689 .map(|ptr| unsafe { Program::from_raw_create_ptr(ptr) })
1690}
1691
1692
1693pub fn create_program_with_binary<C, D>(
1701 context: C,
1702 devices: &[D],
1703 binaries: &[&[u8]],
1704 ) -> OclCoreResult<Program>
1705 where C: ClContextPtr, D: ClDeviceIdPtr
1706{
1707 if devices.is_empty() {
1708 return Err(ApiWrapperError::CreateProgramWithBinaryDevicesLenZero.into())
1709 }
1710
1711 if devices.len() != binaries.len() {
1712 return Err(ApiWrapperError::CreateProgramWithBinaryDevicesLenMismatch.into())
1713 }
1714
1715 let lengths: Vec<usize> = binaries.iter().map(|bin| bin.len()).collect();
1716 let mut binary_status: Vec<i32> = iter::repeat(0).take(devices.len()).collect();
1717 let mut errcode: cl_int = 0;
1718
1719 let ptrs = binaries.iter().map(|bin| bin.as_ptr()).collect::<Vec<_>>();
1720
1721 let program = unsafe { ffi::clCreateProgramWithBinary(
1722 context.as_ptr(),
1723 devices.len() as u32,
1724 devices.as_ptr() as *const _ as *const cl_device_id,
1725 lengths.as_ptr(),
1726 ptrs.as_ptr() as *const *const u8,
1727 binary_status.as_mut_ptr(),
1728 &mut errcode,
1729 ) };
1730
1731 r#try!(eval_errcode(errcode, (), "clCreateProgramWithBinary", None::<String>));
1732
1733 for (i, item) in binary_status.iter().enumerate() {
1734 r#try!(eval_errcode(*item, (), "clCreateProgramWithBinary", Some(format!("Device [{}]", i))));
1735 }
1736
1737 unsafe { Ok(Program::from_raw_create_ptr(program)) }
1738}
1739
1740pub fn create_program_with_built_in_kernels(device_version: Option<&OpenclVersion>)
1744 -> OclCoreResult<()> {
1745 let _ = device_version;
1751 unimplemented!();
1752}
1753
1754#[cfg(feature = "opencl_version_2_1")]
1758pub fn create_program_with_il<C>(
1759 context: C,
1760 il: &[u8],
1761 device_versions: Option<&[OpenclVersion]>,
1762 ) -> OclCoreResult<Program>
1763 where C: ClContextPtr + ClVersions
1764{
1765 verify_device_versions(device_versions, [2, 1], &context, ApiFunction::CreateProgramWithIl)?;
1766
1767 let mut errcode: cl_int = 0;
1768
1769 let program_ptr = unsafe { ffi::clCreateProgramWithIL(
1770 context.as_ptr(),
1771 il.as_ptr() as *mut c_void,
1772 il.len(),
1773 &mut errcode,
1774 ) };
1775
1776 eval_errcode(errcode, program_ptr, "clCreateProgramWithIL", None::<String>)
1777 .map(|ptr| unsafe { Program::from_raw_create_ptr(ptr) })
1778}
1779
1780pub unsafe fn retain_program(program: &Program) -> OclCoreResult<()> {
1782 eval_errcode(ffi::clRetainProgram(program.as_ptr()), (), "clRetainProgram", None::<String>)
1783}
1784
1785pub unsafe fn release_program(program: &Program) -> OclCoreResult<()> {
1787 eval_errcode(ffi::clReleaseProgram(program.as_ptr()), (), "clReleaseKernel", None::<String>)
1788}
1789
1790pub struct UserDataPh(usize);
1791
1792impl UserDataPh {
1793 fn unwrapped(&self) -> *mut c_void {
1794 ptr::null_mut()
1795 }
1796}
1797
1798pub fn build_program<D: ClDeviceIdPtr>(
1807 program: &Program,
1808 devices: Option<&[D]>,
1809 options: &CString,
1810 pfn_notify: Option<BuildProgramCallbackFn>,
1811 user_data: Option<Box<UserDataPh>>,
1812 ) -> OclCoreResult<()>
1813{
1814 assert!(pfn_notify.is_none() && user_data.is_none(),
1815 "ocl::core::build_program(): Callback functions not yet implemented.");
1816
1817 let device_ptrs = DevicePtrList::from(devices);
1818
1819 let user_data = match user_data {
1820 Some(ud) => ud.unwrapped(),
1821 None => ptr::null_mut(),
1822 };
1823
1824 let errcode = unsafe { ffi::clBuildProgram(
1825 program.as_ptr() as cl_program,
1826 device_ptrs.num(),
1827 device_ptrs.as_ptr(),
1828 options.as_ptr(),
1829 pfn_notify,
1830 user_data,
1831 ) };
1832
1833 if errcode == Status::CL_BUILD_PROGRAM_FAILURE as i32 {
1834 if let Some(ds) = devices {
1835 program_build_err(program, ds).map_err(|err| err.into())
1836 } else {
1837 let ds = program.devices()?;
1838 program_build_err(program, &ds).map_err(|err| err.into())
1839 }
1840 } else {
1841 eval_errcode(errcode, (), "clBuildProgram", None::<String>)
1842 }
1843}
1844
1845#[cfg(feature = "opencl_version_1_2")]
1850pub fn compile_program<D: ClDeviceIdPtr>(
1851 program: &Program,
1852 devices: Option<&[D]>,
1853 options: &CString,
1854 input_headers: &[&Program],
1855 header_include_names: &[CString],
1856 pfn_notify: Option<BuildProgramCallbackFn>,
1857 user_data: Option<Box<UserDataPh>>,
1858 device_versions: Option<&[OpenclVersion]>,
1859 ) -> OclCoreResult<()>
1860{
1861 verify_device_versions(device_versions, [1, 2], program, ApiFunction::CompileProgram)?;
1862
1863 assert!(pfn_notify.is_none() && user_data.is_none(),
1864 "ocl::core::compile_program(): Callback functions not yet implemented.");
1865
1866 assert!(input_headers.len() == header_include_names.len(),
1867 "ocl::core::compile_program(): Length of input_headers and header_include_names should be equal.");
1868
1869 let device_ptrs = DevicePtrList::new(devices);
1870
1871 let input_hdrs_ptrs: Vec<_> = input_headers.iter().map(|cs| cs.as_ptr()).collect();
1872 let hdrs_names_ptrs: Vec<*const _> = header_include_names.iter().map(|cs| cs.as_ptr()).collect();
1873
1874 let (input_ptr, names_ptr) = if input_headers.is_empty() {
1876 (ptr::null(), ptr::null())
1877 } else {
1878 (input_hdrs_ptrs.as_ptr(), hdrs_names_ptrs.as_ptr())
1879 };
1880
1881 let user_data = match user_data {
1882 Some(ud) => ud.unwrapped(),
1883 None => ptr::null_mut(),
1884 };
1885
1886 let errcode = unsafe { ffi::clCompileProgram(
1887 program.as_ptr() as cl_program,
1888 device_ptrs.num(),
1889 device_ptrs.as_ptr(),
1890 options.as_ptr(),
1891 input_hdrs_ptrs.len() as cl_uint,
1892 input_ptr as *const cl_program,
1893 names_ptr as *const *const _,
1894 pfn_notify,
1895 user_data,
1896 ) };
1897
1898 if errcode == Status::CL_COMPILE_PROGRAM_FAILURE as i32 {
1899 if let Some(ds) = devices {
1900 program_build_err(program, ds).map_err(|err| err.into())
1901 } else {
1902 let ds = program.devices()?;
1903 program_build_err(program, &ds).map_err(|err| err.into())
1904 }
1905 } else {
1906 eval_errcode(errcode, (), "clCompileProgram", None::<String>)
1907 }
1908}
1909
1910#[cfg(feature = "opencl_version_1_2")]
1915pub fn link_program<D: ClDeviceIdPtr, C: ClContextPtr>(
1916 context: C,
1917 devices: Option<&[D]>,
1918 options: &CString,
1919 input_programs: &[&Program],
1920 pfn_notify: Option<BuildProgramCallbackFn>,
1921 user_data: Option<Box<UserDataPh>>,
1922 device_versions: Option<&[OpenclVersion]>,
1923 ) -> OclCoreResult<Program>
1924{
1925 r#try!(verify_context(context));
1926 verify_device_versions(device_versions, [1, 2], &context.as_ptr(), ApiFunction::LinkProgram)?;
1927
1928 assert!(pfn_notify.is_none() && user_data.is_none(),
1929 "ocl::core::link_program(): Callback functions not yet implemented.");
1930
1931 let device_ptrs = DevicePtrList::new(devices);
1932
1933 let input_programs_ptrs: Vec<_> = input_programs.iter().map(|cs| cs.as_ptr()).collect();
1934
1935 let user_data = match user_data {
1936 Some(ud) => ud.unwrapped(),
1937 None => ptr::null_mut(),
1938 };
1939
1940 let mut errcode: cl_int = 0;
1941
1942 let program_ptr = unsafe { ffi::clLinkProgram(
1943 context.as_ptr(),
1944 device_ptrs.num(),
1945 device_ptrs.as_ptr(),
1946 options.as_ptr(),
1947 input_programs_ptrs.len() as cl_uint,
1948 input_programs_ptrs.as_ptr() as *const cl_program,
1949 pfn_notify,
1950 user_data,
1951 &mut errcode,
1952 ) };
1953
1954 eval_errcode(errcode, program_ptr, "clLinkProgram", None::<String>)
1955 .map(|ptr| unsafe { Program::from_raw_create_ptr(ptr) })
1956}
1957
1958fn get_program_info_raw(program: &Program, request: ProgramInfo) -> OclCoreResult<Vec<u8>> {
1971 let mut result_size: size_t = 0;
1972
1973 let errcode = unsafe { ffi::clGetProgramInfo(
1974 program.as_ptr() as cl_program,
1975 request as cl_program_info,
1976 0 as size_t,
1977 ptr::null_mut(),
1978 &mut result_size as *mut size_t,
1979 ) };
1980
1981 eval_errcode(errcode, (), "clGetProgramInfo", None::<String>)?;
1982
1983 if result_size == 0 {
1985 return Ok(vec![]);
1986 }
1987
1988 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
1989
1990 let errcode = unsafe { ffi::clGetProgramInfo(
1991 program.as_ptr() as cl_program,
1992 request as cl_program_info,
1993 result_size,
1994 result.as_mut_ptr() as *mut _ as *mut c_void,
1995 ptr::null_mut(),
1996 ) };
1997
1998 eval_errcode(errcode, result, "clGetProgramInfo", None::<String>)
1999}
2000
2001fn get_program_info_binaries(program: &Program) -> OclCoreResult<Vec<Vec<u8>>> {
2004 let binary_sizes_raw = get_program_info_raw(program, ProgramInfo::BinarySizes)?;
2005 let binary_sizes = unsafe { crate::util::bytes_into_vec::<usize>(binary_sizes_raw)? };
2006
2007 let binaries = binary_sizes.into_iter().map(|size| {
2008 vec![0u8; size]
2009 }).collect::<Vec<Vec<u8>>>();
2010
2011 let mut binary_ptrs = binaries.iter().map(|vec| {
2012 vec.as_ptr()
2013 }).collect::<Vec<_>>();
2014
2015 let errcode = unsafe { ffi::clGetProgramInfo(
2016 program.as_ptr() as cl_program,
2017 ProgramInfo::Binaries as cl_program_info,
2018 mem::size_of::<*mut c_void>() * binary_ptrs.len(),
2019 binary_ptrs.as_mut_ptr() as *mut _ as *mut c_void,
2020 ptr::null_mut(),
2021 ) };
2022
2023 eval_errcode(errcode, binaries, "clGetProgramInfo", None::<String>)
2024}
2025
2026pub fn get_program_info(program: &Program, request: ProgramInfo) -> OclCoreResult<ProgramInfoResult> {
2028 match request {
2029 ProgramInfo::Binaries => {
2030 get_program_info_binaries(program).map(ProgramInfoResult::Binaries)
2031 },
2032 _ => {
2033 let result = get_program_info_raw(program, request)?;
2034 ProgramInfoResult::from_bytes(request, result)
2035 },
2036 }
2037}
2038
2039pub fn get_program_build_info<D: ClDeviceIdPtr + fmt::Debug>(obj: &Program, device_obj: D,
2041 request: ProgramBuildInfo) -> OclCoreResult<ProgramBuildInfoResult>
2042{
2043 let mut result_size: size_t = 0;
2044
2045 let errcode = unsafe { ffi::clGetProgramBuildInfo(
2046 obj.as_ptr() as cl_program,
2047 device_obj.as_ptr() as cl_device_id,
2048 request as cl_program_build_info,
2049 0 as size_t,
2050 ptr::null_mut(),
2051 &mut result_size as *mut size_t,
2052 ) };
2053
2054 eval_errcode(errcode, (), "clGetProgramBuildInfo", None::<String>)?;
2055
2056 if result_size == 0 {
2058 return ProgramBuildInfoResult::from_bytes(request, vec![]);
2059 }
2060
2061 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2062
2063 let errcode = unsafe { ffi::clGetProgramBuildInfo(
2064 obj.as_ptr() as cl_program,
2065 device_obj.as_ptr() as cl_device_id,
2066 request as cl_program_build_info,
2067 result_size as size_t,
2068 result.as_mut_ptr() as *mut _ as *mut c_void,
2069 ptr::null_mut(),
2070 ) };
2071
2072 let result = eval_errcode(errcode, result, "clGetProgramBuildInfo", None::<String>)?;
2073 ProgramBuildInfoResult::from_bytes(request, result)
2074}
2075
2076pub fn create_kernel<S: AsRef<str>>(program: &Program, name: S) -> OclCoreResult<Kernel> {
2082 let mut err: cl_int = 0;
2083
2084 unsafe {
2085 let kernel_ptr = ffi::clCreateKernel(
2086 program.as_ptr(),
2087 r#try!(CString::new(name.as_ref().as_bytes())).as_ptr(),
2088 &mut err,
2089 );
2090
2091 eval_errcode(err, kernel_ptr, "clCreateKernel", Some(name.as_ref()))
2092 .map(|ptr| Kernel::from_raw_create_ptr(ptr))
2093 }
2094}
2095
2096pub fn create_kernels_in_program() -> OclCoreResult<()> {
2098 unimplemented!();
2103}
2104
2105pub unsafe fn retain_kernel(kernel: &Kernel) -> OclCoreResult<()> {
2107 eval_errcode(ffi::clRetainKernel(kernel.as_ptr()), (), "clRetainKernel", None::<String>)
2108}
2109
2110pub unsafe fn release_kernel(kernel: &Kernel) -> OclCoreResult<()> {
2112 eval_errcode(ffi::clReleaseKernel(kernel.as_ptr()), (), "clReleaseKernel", None::<String>)
2113}
2114
2115
2116pub fn set_kernel_arg(kernel: &Kernel, index: u32, arg_val: ArgVal)
2128 -> OclCoreResult<()>
2129{
2130 let (size, value) = arg_val.as_raw();
2131
2132 let err = unsafe { ffi::clSetKernelArg(
2133 kernel.as_ptr(),
2134 index,
2135 size,
2136 value,
2137 ) };
2138
2139 if err != Status::CL_SUCCESS as i32 {
2140 let name = get_kernel_name(kernel)?;
2141 eval_errcode(err, (), "clSetKernelArg", Some(name))
2142 } else {
2143 Ok(())
2144 }
2145}
2146
2147pub fn get_kernel_info(obj: &Kernel, request: KernelInfo) -> OclCoreResult<KernelInfoResult> {
2149 let mut result_size: size_t = 0;
2150
2151 let errcode = unsafe { ffi::clGetKernelInfo(
2152 obj.as_ptr() as cl_kernel,
2153 request as cl_kernel_info,
2154 0 as size_t,
2155 ptr::null_mut(),
2156 &mut result_size as *mut size_t,
2157 ) };
2158
2159 eval_errcode(errcode, (), "clGetKernelInfo", None::<String>)?;
2160
2161 if result_size == 0 {
2163 return KernelInfoResult::from_bytes(request, vec![]);
2164 }
2165
2166 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2167
2168 let errcode = unsafe { ffi::clGetKernelInfo(
2169 obj.as_ptr() as cl_kernel,
2170 request as cl_kernel_info,
2171 result_size,
2172 result.as_mut_ptr() as *mut _ as *mut c_void,
2173 ptr::null_mut(),
2174 ) };
2175
2176 let result = eval_errcode(errcode, result, "clGetKernelInfo", None::<String>)?;
2177 KernelInfoResult::from_bytes(request, result)
2178}
2179
2180pub fn get_kernel_arg_info(obj: &Kernel, arg_index: u32, request: KernelArgInfo,
2184 device_versions: Option<&[OpenclVersion]>) -> OclCoreResult<KernelArgInfoResult>
2185{
2186 verify_device_versions(device_versions, [1, 2], obj, ApiFunction::GetKernelArgInfo)?;
2194
2195 let mut result_size: size_t = 0;
2196
2197 let errcode = unsafe { ffi::clGetKernelArgInfo(
2198 obj.as_ptr() as cl_kernel,
2199 arg_index as cl_uint,
2200 request as cl_kernel_arg_info,
2201 0 as size_t,
2202 ptr::null_mut(),
2203 &mut result_size as *mut size_t,
2204 ) };
2205
2206 eval_errcode(errcode, (), "clGetKernelArgInfo", None::<String>)?;
2211
2212 if result_size == 0 {
2214 return KernelArgInfoResult::from_bytes(request, vec![]);
2215 }
2216
2217 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2218
2219 let errcode = unsafe { ffi::clGetKernelArgInfo(
2220 obj.as_ptr() as cl_kernel,
2221 arg_index as cl_uint,
2222 request as cl_kernel_arg_info,
2223 result_size,
2224 result.as_mut_ptr() as *mut _ as *mut c_void,
2225 ptr::null_mut(),
2226 ) };
2227
2228 let result = eval_errcode(errcode, result, "clGetKernelArgInfo", None::<String>)?;
2229 KernelArgInfoResult::from_bytes(request, result)
2230}
2231
2232pub fn get_kernel_work_group_info<D: ClDeviceIdPtr>(obj: &Kernel, device_obj: D,
2234 request: KernelWorkGroupInfo) -> OclCoreResult<KernelWorkGroupInfoResult>
2235{
2236 let mut result_size: size_t = 0;
2237
2238 let errcode = unsafe { ffi::clGetKernelWorkGroupInfo(
2239 obj.as_ptr() as cl_kernel,
2240 device_obj.as_ptr() as cl_device_id,
2241 request as cl_kernel_work_group_info,
2242 0 as size_t,
2243 ptr::null_mut(),
2244 &mut result_size as *mut size_t,
2245 ) };
2246
2247 if let Err(err) = eval_errcode(errcode, (), "clGetKernelWorkGroupInfo", None::<String>) {
2249 if let Some(status) = err.api_status() {
2250 if request == KernelWorkGroupInfo::GlobalWorkSize &&
2252 status == Status::CL_INVALID_VALUE {
2253 return Ok(KernelWorkGroupInfoResult::CustomBuiltinOnly);
2254 }
2255
2256 if status == Status::CL_INVALID_DEVICE {
2258 return Ok(KernelWorkGroupInfoResult::Unavailable(status));
2259 }
2260 }
2261
2262 return Err(err);
2263 }
2264
2265 if result_size == 0 {
2267 return KernelWorkGroupInfoResult::from_bytes(request, vec![]);
2268 }
2269
2270 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2271
2272 let errcode = unsafe { ffi::clGetKernelWorkGroupInfo(
2273 obj.as_ptr() as cl_kernel,
2274 device_obj.as_ptr() as cl_device_id,
2275 request as cl_kernel_work_group_info,
2276 result_size,
2277 result.as_mut_ptr() as *mut _ as *mut c_void,
2278 ptr::null_mut(),
2279 ) };
2280
2281 let result = eval_errcode(errcode, result, "clGetKernelWorkGroupInfo", None::<String>)?;
2282 KernelWorkGroupInfoResult::from_bytes(request, result)
2283}
2284
2285pub fn wait_for_events(num_events: u32, event_list: &dyn ClWaitListPtr) -> OclCoreResult<()> {
2291 assert!(event_list.count() >= num_events);
2292
2293 let errcode = unsafe {
2294 ffi::clWaitForEvents(num_events, event_list.as_ptr_ptr())
2295 };
2296
2297 eval_errcode(errcode, (), "clWaitForEvents", None::<String>)
2298}
2299
2300pub fn get_event_info<'e, E: ClEventPtrRef<'e>>(event: &'e E, request: EventInfo) -> OclCoreResult<EventInfoResult> {
2302 let mut result_size: size_t = 0;
2303
2304 let errcode = unsafe { ffi::clGetEventInfo(
2305 *event.as_ptr_ref(),
2306 request as cl_event_info,
2307 0 as size_t,
2308 ptr::null_mut(),
2309 &mut result_size as *mut size_t,
2310 ) };
2311
2312 eval_errcode(errcode, (), "clGetEventInfo", None::<String>)?;
2313
2314 if result_size == 0 {
2316 return EventInfoResult::from_bytes(request, vec![]);
2317 }
2318
2319 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2320
2321 let errcode = unsafe { ffi::clGetEventInfo(
2322 *event.as_ptr_ref(),
2323 request as cl_event_info,
2324 result_size,
2325 result.as_mut_ptr() as *mut _ as *mut c_void,
2326 ptr::null_mut(),
2327 ) };
2328
2329 let result = eval_errcode(errcode, result, "clGetEventInfo", None::<String>)?;
2330 EventInfoResult::from_bytes(request, result)
2331}
2332
2333pub fn create_user_event<C>(context: C) -> OclCoreResult<Event>
2335 where C: ClContextPtr
2336{
2337 let mut errcode = 0;
2338 let event = unsafe { Event::from_raw_create_ptr(ffi::clCreateUserEvent(context.as_ptr(), &mut errcode)) };
2339 eval_errcode(errcode, event, "clCreateUserEvent", None::<String>)
2340}
2341
2342pub unsafe fn retain_event<'e, E: ClEventPtrRef<'e>>(event: &'e E) -> OclCoreResult<()> {
2344 eval_errcode(ffi::clRetainEvent(*event.as_ptr_ref()), (), "clRetainEvent", None::<String>)
2345}
2346
2347pub unsafe fn release_event<'e, E: ClEventPtrRef<'e>>(event: &'e E) -> OclCoreResult<()> {
2349 eval_errcode(ffi::clReleaseEvent(*event.as_ptr_ref()), (), "clReleaseEvent", None::<String>)
2350}
2351
2352pub fn set_user_event_status<'e,E: ClEventPtrRef<'e>>(event: &'e E,
2372 execution_status: CommandExecutionStatus) -> OclCoreResult<()>
2373{
2374 unsafe {
2375 #[cfg(feature = "event_debug_print")]
2376 println!("::set_user_event_status: Setting user event status for event: {:?}", *event.as_ptr_ref());
2377
2378 eval_errcode(ffi::clSetUserEventStatus(*event.as_ptr_ref(), execution_status as cl_int),
2379 (), "clSetUserEventStatus", None::<String>)
2380 }
2381}
2382
2383pub unsafe fn set_event_callback<'e, E: ClEventPtrRef<'e>>(
2391 event: &'e E,
2392 callback_trigger: CommandExecutionStatus,
2393 callback_receiver: Option<EventCallbackFn>,
2394 user_data: *mut c_void,
2395 ) -> OclCoreResult<()>
2396{
2397 eval_errcode(ffi::clSetEventCallback(
2398 *event.as_ptr_ref(),
2399 callback_trigger as cl_int,
2400 callback_receiver,
2401 user_data,
2402 ), (), "clSetEventCallback", None::<String>)
2403}
2404
2405pub fn get_event_profiling_info<'e, E: ClEventPtrRef<'e>>(event: &'e E, request: ProfilingInfo)
2411 -> OclCoreResult<ProfilingInfoResult> {
2412 let max_result_size_bytes = 8;
2414 let mut result_size: size_t = 0;
2415 let event: cl_event = unsafe { *event.as_ptr_ref() };
2416
2417 let errcode = unsafe { ffi::clGetEventProfilingInfo(
2418 event,
2419 request as cl_profiling_info,
2420 max_result_size_bytes,
2421 ptr::null_mut(),
2422 &mut result_size as *mut size_t,
2423 ) };
2424
2425 assert!(result_size <= max_result_size_bytes);
2427
2428 if errcode < 0 && Status::from_i32(errcode).unwrap() == Status::CL_INVALID_VALUE {
2431 return Err(OclCoreError::from("<unavailable (CL_INVALID_VALUE)>"));
2432 }
2433
2434 eval_errcode(errcode, (), "clGetEventProfilingInfo", None::<String>)?;
2435
2436 if result_size == 0 {
2438 return ProfilingInfoResult::from_bytes(request, vec![]);
2439 }
2440
2441 let mut result: Vec<u8> = iter::repeat(0u8).take(result_size).collect();
2442
2443 let errcode = unsafe { ffi::clGetEventProfilingInfo(
2444 event,
2445 request as cl_profiling_info,
2446 result_size,
2447 result.as_mut_ptr() as *mut _ as *mut c_void,
2448 ptr::null_mut(),
2449 ) };
2450
2451 let result = eval_errcode(errcode, result, "clGetEventProfilingInfo", None::<String>)?;
2452 ProfilingInfoResult::from_bytes(request, result)
2453}
2454
2455pub fn flush(command_queue: &CommandQueue) -> OclCoreResult<()> {
2464 unsafe { eval_errcode(ffi::clFlush(command_queue.as_ptr()), (), "clFlush", None::<String>) }
2465}
2466
2467pub fn finish(command_queue: &CommandQueue) -> OclCoreResult<()> {
2472 unsafe {
2473 let errcode = ffi::clFinish(command_queue.as_ptr());
2474 eval_errcode(errcode, (), "clFinish", None::<String>)
2475 }
2476}
2477
2478pub unsafe fn enqueue_read_buffer<T, M, En, Ewl>(
2495 command_queue: &CommandQueue,
2496 buffer: M,
2497 block: bool,
2498 offset: usize,
2499 data: &mut [T],
2500 wait_list: Option<Ewl>,
2501 new_event: Option<En>,
2502 ) -> OclCoreResult<()>
2503 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdRw
2504{
2505 let (wait_list_len, wait_list_ptr, new_event_ptr) =
2506 resolve_event_ptrs(wait_list, new_event);
2507
2508 let offset_bytes = offset * mem::size_of::<T>();
2509
2510 let errcode = ffi::clEnqueueReadBuffer(
2511 command_queue.as_ptr(),
2512 buffer.as_mem().as_ptr(),
2513 block as cl_uint,
2514 offset_bytes,
2515 (data.len() * mem::size_of::<T>()) as size_t,
2516 data.as_ptr() as cl_mem,
2517 wait_list_len,
2518 wait_list_ptr,
2519 new_event_ptr,
2520 );
2521
2522 eval_errcode(errcode, (), "clEnqueueReadBuffer", None::<String>)
2523}
2524
2525pub unsafe fn enqueue_read_buffer_rect<T, M, En, Ewl>(
2541 command_queue: &CommandQueue,
2542 buffer: M,
2543 block: bool,
2544 buffer_origin: [usize; 3],
2545 host_origin: [usize; 3],
2546 region: [usize; 3],
2547 buffer_row_pitch_bytes: usize,
2548 buffer_slc_pitch_bytes: usize,
2549 host_row_pitch_bytes: usize,
2550 host_slc_pitch_bytes: usize,
2551 data: &mut [T],
2552 wait_list: Option<Ewl>,
2553 new_event: Option<En>,
2554 ) -> OclCoreResult<()>
2555 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdRw
2556{
2557 let buffer_origin_bytes = [buffer_origin[0] * mem::size_of::<T>(),
2558 buffer_origin[1], buffer_origin[2]];
2559 let host_origin_bytes = [host_origin[0] * mem::size_of::<T>(),
2560 host_origin[1], host_origin[2]];
2561 let region_bytes = [region[0] * mem::size_of::<T>(), region[1], region[2]];
2562
2563 if false {
2565 println!("buffer_origin_bytes: {:?}, host_origin_bytes: {:?}, region_bytes: {:?}",
2566 buffer_origin_bytes, host_origin_bytes, region_bytes);
2567 println!("buffer_row_pitch_bytes: {}, buffer_slc_pitch_bytes: {}, \
2568 host_row_pitch_bytes: {}, host_slc_pitch_bytes: {}",
2569 buffer_row_pitch_bytes, buffer_slc_pitch_bytes, host_row_pitch_bytes, host_slc_pitch_bytes);
2570 }
2571
2572 let (wait_list_len, wait_list_ptr, new_event_ptr) =
2573 resolve_event_ptrs(wait_list, new_event);
2574
2575 let errcode = ffi::clEnqueueReadBufferRect(
2576 command_queue.as_ptr(),
2577 buffer.as_mem().as_ptr(),
2578 block as cl_uint,
2579 &buffer_origin_bytes as *const _ as *const usize,
2580 &host_origin_bytes as *const _ as *const usize,
2581 ®ion_bytes as *const _ as *const usize,
2582 buffer_row_pitch_bytes,
2583 buffer_slc_pitch_bytes,
2584 host_row_pitch_bytes,
2585 host_slc_pitch_bytes,
2586 data.as_ptr() as cl_mem,
2587 wait_list_len,
2588 wait_list_ptr,
2589 new_event_ptr,
2590 );
2591
2592 eval_errcode(errcode, (), "clEnqueueReadBufferRect", None::<String>)
2593}
2594
2595pub unsafe fn enqueue_write_buffer<T, M, En, Ewl>(
2605 command_queue: &CommandQueue,
2606 buffer: M,
2607 block: bool,
2608 offset: usize,
2609 data: &[T],
2610 wait_list: Option<Ewl>,
2611 new_event: Option<En>,
2612 ) -> OclCoreResult<()>
2613 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdRw
2614{
2615 let (wait_list_len, wait_list_ptr, new_event_ptr) =
2616 resolve_event_ptrs(wait_list, new_event);
2617
2618 let offset_bytes = offset * mem::size_of::<T>();
2619
2620 let errcode = ffi::clEnqueueWriteBuffer(
2621 command_queue.as_ptr(),
2622 buffer.as_mem().as_ptr(),
2623 block as cl_uint,
2624 offset_bytes,
2625 (data.len() * mem::size_of::<T>()) as size_t,
2626 data.as_ptr() as cl_mem,
2627 wait_list_len,
2628 wait_list_ptr,
2629 new_event_ptr,
2630 );
2631 eval_errcode(errcode, (), "clEnqueueWriteBuffer", None::<String>)
2632}
2633
2634pub unsafe fn enqueue_write_buffer_rect<T, M, En, Ewl>(
2649 command_queue: &CommandQueue,
2650 buffer: M,
2651 block: bool,
2652 buffer_origin: [usize; 3],
2653 host_origin: [usize; 3],
2654 region: [usize; 3],
2655 buffer_row_pitch_bytes: usize,
2656 buffer_slc_pitch_bytes: usize,
2657 host_row_pitch_bytes: usize,
2658 host_slc_pitch_bytes: usize,
2659 data: &[T],
2660 wait_list: Option<Ewl>,
2661 new_event: Option<En>,
2662 ) -> OclCoreResult<()>
2663 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdRw
2664{
2665 let (wait_list_len, wait_list_ptr, new_event_ptr) =
2666 resolve_event_ptrs(wait_list, new_event);
2667
2668 let buffer_origin_bytes = [buffer_origin[0] * mem::size_of::<T>(),
2669 buffer_origin[1], buffer_origin[2]];
2670 let host_origin_bytes = [host_origin[0] * mem::size_of::<T>(),
2671 host_origin[1], host_origin[2]];
2672 let region_bytes = [region[0] * mem::size_of::<T>(), region[1], region[2]];
2673
2674 let errcode = ffi::clEnqueueWriteBufferRect(
2675 command_queue.as_ptr(),
2676 buffer.as_mem().as_ptr(),
2677 block as cl_uint,
2678 &buffer_origin_bytes as *const _ as *const usize,
2679 &host_origin_bytes as *const _ as *const usize,
2680 ®ion_bytes as *const _ as *const usize,
2681 buffer_row_pitch_bytes,
2682 buffer_slc_pitch_bytes,
2683 host_row_pitch_bytes,
2684 host_slc_pitch_bytes,
2685 data.as_ptr() as cl_mem,
2686 wait_list_len,
2687 wait_list_ptr,
2688 new_event_ptr,
2689 );
2690 eval_errcode(errcode, (), "clEnqueueWriteBufferRect", None::<String>)
2691}
2692
2693#[cfg(not(feature="opencl_vendor_mesa"))]
2699pub fn enqueue_fill_buffer<T, M, En, Ewl>(
2700 command_queue: &CommandQueue,
2701 buffer: M,
2702 pattern: T,
2703 offset: usize,
2704 len: usize,
2705 wait_list: Option<Ewl>,
2706 new_event: Option<En>,
2707 device_version: Option<&OpenclVersion>
2708 ) -> OclCoreResult<()>
2709 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdRw
2710{
2711 verify_device_version(device_version, [1, 2], command_queue,
2712 ApiFunction::EnqueueFillBuffer)?;
2713
2714 let pattern_size = mem::size_of::<T>();
2715 let offset_bytes = offset * mem::size_of::<T>();
2716 let size_bytes = len * mem::size_of::<T>();
2717
2718 let (wait_list_len, wait_list_ptr, new_event_ptr)
2719 = resolve_event_ptrs(wait_list, new_event);
2720
2721 let errcode = unsafe { ffi::clEnqueueFillBuffer(
2722 command_queue.as_ptr(),
2723 buffer.as_mem().as_ptr(),
2724 &pattern as *const _ as *const c_void,
2725 pattern_size,
2726 offset_bytes,
2727 size_bytes,
2728 wait_list_len,
2729 wait_list_ptr,
2730 new_event_ptr,
2731 ) };
2732 eval_errcode(errcode, (), "clEnqueueFillBuffer", None::<String>)
2733}
2734
2735pub fn enqueue_copy_buffer<T, M, En, Ewl>(
2737 command_queue: &CommandQueue,
2738 src_buffer: M,
2739 dst_buffer: M,
2740 src_offset: usize,
2741 dst_offset: usize,
2742 len: usize,
2743 wait_list: Option<Ewl>,
2744 new_event: Option<En>,
2745 ) -> OclCoreResult<()>
2746 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdAll
2747{
2748 let (wait_list_len, wait_list_ptr, new_event_ptr)
2749 = resolve_event_ptrs(wait_list, new_event);
2750
2751 let src_offset_bytes = src_offset * mem::size_of::<T>();
2752 let dst_offset_bytes = dst_offset * mem::size_of::<T>();
2753 let len_bytes = len * mem::size_of::<T>();
2754
2755 let errcode = unsafe { ffi::clEnqueueCopyBuffer(
2756 command_queue.as_ptr(),
2757 src_buffer.as_mem().as_ptr(),
2758 dst_buffer.as_mem().as_ptr(),
2759 src_offset_bytes,
2760 dst_offset_bytes,
2761 len_bytes,
2762 wait_list_len,
2763 wait_list_ptr,
2764 new_event_ptr,
2765 ) };
2766 eval_errcode(errcode, (), "clEnqueueCopyBuffer", None::<String>)
2767}
2768
2769pub fn enqueue_copy_buffer_rect<T, M, En, Ewl>(
2775 command_queue: &CommandQueue,
2776 src_buffer: M,
2777 dst_buffer: M,
2778 src_origin: [usize; 3],
2779 dst_origin: [usize; 3],
2780 region: [usize; 3],
2781 src_row_pitch_bytes: usize,
2782 src_slc_pitch_bytes: usize,
2783 dst_row_pitch_bytes: usize,
2784 dst_slc_pitch_bytes: usize,
2785 wait_list: Option<Ewl>,
2786 new_event: Option<En>,
2787 ) -> OclCoreResult<()>
2788 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdAll
2789{
2790 let (wait_list_len, wait_list_ptr, new_event_ptr) =
2791 resolve_event_ptrs(wait_list, new_event);
2792
2793 let src_origin_bytes = [src_origin[0] * mem::size_of::<T>(),
2794 src_origin[1], src_origin[2]];
2795 let dst_origin_bytes = [dst_origin[0] * mem::size_of::<T>(),
2796 dst_origin[1], dst_origin[2]];
2797 let region_bytes = [region[0] * mem::size_of::<T>(), region[1], region[2]];
2798
2799 let errcode = unsafe { ffi::clEnqueueCopyBufferRect(
2800 command_queue.as_ptr(),
2801 src_buffer.as_mem().as_ptr(),
2802 dst_buffer.as_mem().as_ptr(),
2803 &src_origin_bytes as *const _ as *const usize,
2804 &dst_origin_bytes as *const _ as *const usize,
2805 ®ion_bytes as *const _ as *const usize,
2806 src_row_pitch_bytes,
2807 src_slc_pitch_bytes,
2808 dst_row_pitch_bytes,
2809 dst_slc_pitch_bytes,
2810 wait_list_len,
2811 wait_list_ptr,
2812 new_event_ptr,
2813 ) };
2814 eval_errcode(errcode, (), "clEnqueueCopyBufferRect", None::<String>)
2815}
2816
2817#[cfg(not(feature="opencl_vendor_mesa"))]
2824pub fn enqueue_acquire_gl_objects<En, Ewl>(
2825 command_queue: &CommandQueue,
2826 buffers: &[Mem],
2827 wait_list: Option<Ewl>,
2828 new_event: Option<En>,
2829 ) -> OclCoreResult<()>
2830 where En: ClNullEventPtr, Ewl: ClWaitListPtr
2831{
2832 let (wait_list_len, wait_list_ptr, new_event_ptr) =
2833 resolve_event_ptrs(wait_list, new_event);
2834
2835 let errcode = unsafe { clEnqueueAcquireGLObjects(
2836 command_queue.as_ptr(),
2837 buffers.len() as u32,
2838 buffers.as_ptr() as *const cl_mem,
2839 wait_list_len,
2840 wait_list_ptr,
2841 new_event_ptr
2842 ) };
2843 eval_errcode(errcode, (), "clEnqueueAcquireGLObjects", None::<String>)
2844}
2845
2846#[cfg(not(feature="opencl_vendor_mesa"))]
2853pub fn enqueue_release_gl_objects<En, Ewl>(
2854 command_queue: &CommandQueue,
2855 buffers: &[Mem],
2856 wait_list: Option<Ewl>,
2857 new_event: Option<En>,
2858 ) -> OclCoreResult<()>
2859 where En: ClNullEventPtr, Ewl: ClWaitListPtr
2860{
2861 let (wait_list_len, wait_list_ptr, new_event_ptr) =
2862 resolve_event_ptrs(wait_list, new_event);
2863
2864 let errcode = unsafe { clEnqueueReleaseGLObjects(
2865 command_queue.as_ptr(),
2866 buffers.len() as u32,
2867 buffers.as_ptr() as *const cl_mem,
2868 wait_list_len,
2869 wait_list_ptr,
2870 new_event_ptr
2871 ) };
2872 eval_errcode(errcode, (), "clEnqueueReleaseGLObjects", None::<String>)
2873}
2874
2875
2876pub unsafe fn enqueue_read_image<T, M, En, Ewl>(
2888 command_queue: &CommandQueue,
2889 image: M,
2890 block: bool,
2891 origin: [usize; 3],
2892 region: [usize; 3],
2893 row_pitch_bytes: usize,
2894 slc_pitch_bytes: usize,
2895 data: &mut [T],
2896 wait_list: Option<Ewl>,
2897 new_event: Option<En>,
2898 ) -> OclCoreResult<()>
2899 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdRw
2900{
2901 let (wait_list_len, wait_list_ptr, new_event_ptr)
2902 = resolve_event_ptrs(wait_list, new_event);
2903
2904 let errcode = ffi::clEnqueueReadImage(
2905 command_queue.as_ptr(),
2906 image.as_mem().as_ptr(),
2907 block as cl_uint,
2908 &origin as *const _ as *const usize,
2909 ®ion as *const _ as *const usize,
2910 row_pitch_bytes,
2911 slc_pitch_bytes,
2912 data.as_ptr() as cl_mem,
2913 wait_list_len,
2914 wait_list_ptr,
2915 new_event_ptr,
2916 );
2917 eval_errcode(errcode, (), "clEnqueueReadImage", None::<String>)
2918}
2919
2920
2921pub unsafe fn enqueue_write_image<T, M, En, Ewl>(
2934 command_queue: &CommandQueue,
2935 image: M,
2936 block: bool,
2937 origin: [usize; 3],
2938 region: [usize; 3],
2939 input_row_pitch_bytes: usize,
2940 input_slc_pitch_bytes: usize,
2941 data: &[T],
2942 wait_list: Option<Ewl>,
2943 new_event: Option<En>,
2944 ) -> OclCoreResult<()>
2945 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdRw
2946{
2947 let (wait_list_len, wait_list_ptr, new_event_ptr)
2948 = resolve_event_ptrs(wait_list, new_event);
2949
2950 let errcode = ffi::clEnqueueWriteImage(
2951 command_queue.as_ptr(),
2952 image.as_mem().as_ptr(),
2953 block as cl_uint,
2954 &origin as *const _ as *const usize,
2955 ®ion as *const _ as *const usize,
2956 input_row_pitch_bytes,
2957 input_slc_pitch_bytes,
2958 data.as_ptr() as cl_mem,
2959 wait_list_len,
2960 wait_list_ptr,
2961 new_event_ptr,
2962 );
2963 eval_errcode(errcode, (), "clEnqueueWriteImage", None::<String>)
2964}
2965
2966pub fn enqueue_fill_image<T, M, En, Ewl>(
2985 command_queue: &CommandQueue,
2986 image: M,
2987 color: &[T],
2988 origin: [usize; 3],
2989 region: [usize; 3],
2990 wait_list: Option<Ewl>,
2991 new_event: Option<En>,
2992 device_version: Option<&OpenclVersion>
2993 ) -> OclCoreResult<()>
2994 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdAll
2995{
2996 verify_device_version(device_version, [1, 2], command_queue,
2998 ApiFunction::EnqueueFillImage)?;
2999
3000 let (wait_list_len, wait_list_ptr, new_event_ptr)
3001 = resolve_event_ptrs(wait_list, new_event);
3002
3003 let errcode = unsafe { ffi::clEnqueueFillImage(
3004 command_queue.as_ptr(),
3005 image.as_mem().as_ptr(),
3006 color as *const _ as *const c_void,
3007 &origin as *const _ as *const usize,
3008 ®ion as *const _ as *const usize,
3009 wait_list_len,
3010 wait_list_ptr,
3011 new_event_ptr,
3012 ) };
3013 eval_errcode(errcode, (), "clEnqueueFillImage", None::<String>)
3014}
3015
3016
3017pub fn enqueue_copy_image<En, Ewl>(
3021 command_queue: &CommandQueue,
3022 src_image: &Mem,
3023 dst_image: &Mem,
3024 src_origin: [usize; 3],
3025 dst_origin: [usize; 3],
3026 region: [usize; 3],
3027 wait_list: Option<Ewl>,
3028 new_event: Option<En>,
3029 ) -> OclCoreResult<()>
3030 where En: ClNullEventPtr, Ewl: ClWaitListPtr
3031{
3032 let (wait_list_len, wait_list_ptr, new_event_ptr)
3033 = resolve_event_ptrs(wait_list, new_event);
3034
3035 let errcode = unsafe { ffi::clEnqueueCopyImage(
3036 command_queue.as_ptr(),
3037 src_image.as_ptr(),
3038 dst_image.as_ptr(),
3039 &src_origin as *const _ as *const usize,
3040 &dst_origin as *const _ as *const usize,
3041 ®ion as *const _ as *const usize,
3042 wait_list_len,
3043 wait_list_ptr,
3044 new_event_ptr,
3045 ) };
3046 eval_errcode(errcode, (), "clEnqueueCopyImage", None::<String>)
3047}
3048
3049pub fn enqueue_copy_image_to_buffer<T, M, En, Ewl>(
3056 command_queue: &CommandQueue,
3057 src_image: M,
3058 dst_buffer: M,
3059 src_origin: [usize; 3],
3060 region: [usize; 3],
3061 dst_offset: usize,
3062 wait_list: Option<Ewl>,
3063 new_event: Option<En>,
3064 ) -> OclCoreResult<()>
3065 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdAll
3066{
3067 let dst_offset_bytes = dst_offset * mem::size_of::<T>();
3068
3069 let (wait_list_len, wait_list_ptr, new_event_ptr)
3070 = resolve_event_ptrs(wait_list, new_event);
3071
3072 let errcode = unsafe { ffi::clEnqueueCopyImageToBuffer(
3073 command_queue.as_ptr(),
3074 src_image.as_mem().as_ptr(),
3075 dst_buffer.as_mem().as_ptr(),
3076 &src_origin as *const _ as *const usize,
3077 ®ion as *const _ as *const usize,
3078 dst_offset_bytes,
3079 wait_list_len,
3080 wait_list_ptr,
3081 new_event_ptr,
3082 ) };
3083 eval_errcode(errcode, (), "clEnqueueCopyImageToBuffer", None::<String>)
3084}
3085
3086pub fn enqueue_copy_buffer_to_image<T, M, En, Ewl>(
3093 command_queue: &CommandQueue,
3094 src_buffer: M,
3095 dst_image: M,
3096 src_offset: usize,
3097 dst_origin: [usize; 3],
3098 region: [usize; 3],
3099 wait_list: Option<Ewl>,
3100 new_event: Option<En>,
3101 ) -> OclCoreResult<()>
3102 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdAll
3103{
3104 let src_offset_bytes = src_offset * mem::size_of::<T>();
3105
3106 let (wait_list_len, wait_list_ptr, new_event_ptr)
3107 = resolve_event_ptrs(wait_list, new_event);
3108
3109 let errcode = unsafe { ffi::clEnqueueCopyBufferToImage(
3110 command_queue.as_ptr(),
3111 src_buffer.as_mem().as_ptr(),
3112 dst_image.as_mem().as_ptr(),
3113 src_offset_bytes,
3114 &dst_origin as *const _ as *const usize,
3115 ®ion as *const _ as *const usize,
3116 wait_list_len,
3117 wait_list_ptr,
3118 new_event_ptr,
3119 ) };
3120 eval_errcode(errcode, (), "clEnqueueCopyBufferToImage", None::<String>)
3121}
3122
3123#[inline]
3124unsafe fn _enqueue_map_buffer<T, M>(
3125 command_queue: &CommandQueue,
3126 buffer: M,
3127 block: bool,
3128 map_flags: MapFlags,
3129 offset: usize,
3130 len: usize,
3131 wait_list_len: cl_uint,
3132 wait_list_ptr: *const cl_event,
3133 new_event_ptr: *mut cl_event,
3134 ) -> OclCoreResult<*mut T>
3135 where T: OclPrm, M: AsMem<T> + MemCmdAll
3136{
3137 let offset_bytes = offset * mem::size_of::<T>();
3138 let size_bytes = len * mem::size_of::<T>();
3139
3140 let mut errcode = 0i32;
3141
3142 let mapped_ptr = ffi::clEnqueueMapBuffer(
3143 command_queue.as_ptr(),
3144 buffer.as_mem().as_ptr(),
3145 block as cl_uint,
3146 map_flags.bits(),
3147 offset_bytes,
3148 size_bytes,
3149 wait_list_len,
3150 wait_list_ptr,
3151 new_event_ptr,
3152 &mut errcode,
3153 );
3154
3155 eval_errcode(errcode, mapped_ptr as *mut T, "clEnqueueMapBuffer", None::<String>)
3156}
3157
3158pub unsafe fn enqueue_map_buffer<T, M, En, Ewl>(
3175 command_queue: &CommandQueue,
3176 buffer: M,
3177 block: bool,
3178 map_flags: MapFlags,
3179 offset: usize,
3180 len: usize,
3181 wait_list: Option<Ewl>,
3182 new_event: Option<En>,
3183 ) -> OclCoreResult<MemMap<T>>
3184 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdAll
3185{
3186 let (wait_list_len, wait_list_ptr, new_event_ptr) =
3187 resolve_event_ptrs(wait_list, new_event);
3188
3189 let mapped_ptr_res = _enqueue_map_buffer(command_queue, buffer.as_mem(), block, map_flags, offset, len,
3190 wait_list_len, wait_list_ptr, new_event_ptr);
3191
3192 mapped_ptr_res.map(|ptr| MemMap::from_raw(ptr))
3193}
3194
3195pub unsafe fn enqueue_map_image<T, M, En, Ewl>(
3215 command_queue: &CommandQueue,
3216 image: M,
3217 block: bool,
3218 map_flags: MapFlags,
3219 origin: [usize; 3],
3220 region: [usize; 3],
3221 row_pitch_bytes: &mut usize,
3222 slc_pitch_bytes: &mut usize,
3223 wait_list: Option<Ewl>,
3224 new_event: Option<En>,
3225 ) -> OclCoreResult<MemMap<T>>
3226 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdAll
3227{
3228 let (wait_list_len, wait_list_ptr, new_event_ptr) =
3229 resolve_event_ptrs(wait_list, new_event);
3230
3231 let mut errcode = 0i32;
3232
3233 let mapped_ptr = ffi::clEnqueueMapImage(
3234 command_queue.as_ptr(),
3235 image.as_mem().as_ptr(),
3236 block as cl_uint,
3237 map_flags.bits(),
3238 &origin as *const _ as *const usize,
3239 ®ion as *const _ as *const usize,
3240 row_pitch_bytes,
3241 slc_pitch_bytes,
3242 wait_list_len,
3243 wait_list_ptr,
3244 new_event_ptr,
3245 &mut errcode,
3246 );
3247
3248 eval_errcode(errcode, mapped_ptr, "clEnqueueMapImage", None::<String>)
3259 .map(|ptr| MemMap::from_raw(ptr as *mut _ as *mut T))
3260}
3261
3262pub fn enqueue_unmap_mem_object<T, M, En, Ewl>(
3267 command_queue: &CommandQueue,
3268 memobj: M,
3269 mapped_mem: &MemMap<T>,
3270 wait_list: Option<Ewl>,
3271 new_event: Option<En>,
3272 ) -> OclCoreResult<()>
3273 where T: OclPrm, En: ClNullEventPtr, Ewl: ClWaitListPtr, M: AsMem<T> + MemCmdAll
3274{
3275 let (wait_list_len, wait_list_ptr, new_event_ptr) =
3276 resolve_event_ptrs(wait_list, new_event);
3277
3278 let errcode = unsafe { ffi::clEnqueueUnmapMemObject(
3279 command_queue.as_ptr(),
3280 memobj.as_mem().as_ptr(),
3281 mapped_mem.as_void_ptr(),
3282 wait_list_len,
3283 wait_list_ptr,
3284 new_event_ptr,
3285 ) };
3286
3287 eval_errcode(errcode, (), "clEnqueueUnmapMemObject", None::<String>)
3288}
3289
3290pub fn enqueue_migrate_mem_objects<En: ClNullEventPtr, Ewl: ClWaitListPtr>(
3300 command_queue: &CommandQueue,
3301 mem_objects: &[Mem],
3302 flags: MemMigrationFlags,
3303 wait_list: Option<Ewl>,
3304 new_event: Option<En>,
3305 device_version: Option<&OpenclVersion>
3306 ) -> OclCoreResult<()>
3307{
3308 verify_device_version(device_version, [1, 2], command_queue,
3310 ApiFunction::EnqueueMigrateMemObjects)?;
3311
3312 let (wait_list_len, wait_list_ptr, new_event_ptr)
3313 = resolve_event_ptrs(wait_list, new_event);
3314
3315 let errcode = unsafe { ffi::clEnqueueMigrateMemObjects(
3316 command_queue.as_ptr(),
3317 mem_objects.len() as u32,
3318 mem_objects.as_ptr() as *const _ as *const cl_mem,
3319 flags.bits(),
3320 wait_list_len,
3321 wait_list_ptr,
3322 new_event_ptr,
3323 ) };
3324 eval_errcode(errcode, (), "clEnqueueMigrateMemObjects", None::<String>)
3325}
3326
3327pub unsafe fn enqueue_kernel<En: ClNullEventPtr, Ewl: ClWaitListPtr> (
3341 command_queue: &CommandQueue,
3342 kernel: &Kernel,
3343 work_dims: u32,
3344 global_work_offset: Option<[usize; 3]>,
3345 global_work_dims: &[usize; 3],
3346 local_work_dims: Option<[usize; 3]>,
3347 wait_list: Option<Ewl>,
3348 new_event: Option<En>,
3349 ) -> OclCoreResult<()>
3350{
3351 #[cfg(feature="kernel_debug_sleep")]
3352 #[allow(unused_imports)] use std::thread;
3353 #[cfg(feature="kernel_debug_sleep")]
3354 #[allow(unused_imports)] use std::time::Duration;
3355
3356 #[cfg(feature="kernel_debug_print")]
3357 println!("Resolving events: wait_list: {:?}, new_event: {:?}", wait_list, new_event);
3358
3359 let (wait_list_len, wait_list_ptr, new_event_ptr) =
3360 resolve_event_ptrs(wait_list, new_event);
3361
3362 #[cfg(feature="kernel_debug_print")]
3363 println!("Resolving global work offset: {:?}...", global_work_offset);
3364
3365 let gwo = resolve_work_dims(global_work_offset.as_ref());
3366
3367 #[cfg(feature="kernel_debug_print")]
3368 println!("Assigning global work size: {:?}...", global_work_dims);
3369
3370 let gws = global_work_dims as *const size_t;
3371
3372 #[cfg(feature="kernel_debug_print")]
3373 println!("Resolving local work size: {:?}...", local_work_dims);
3374
3375 let lws = resolve_work_dims(local_work_dims.as_ref());
3376
3377 #[cfg(feature="kernel_debug_print")]
3378 println!("Preparing to print all details...");
3379
3380 #[cfg(feature="kernel_debug_print")]
3381 print!("core::enqueue_kernel('{}': \
3382 work_dims: {}, \
3383 gwo: {:?}, \
3384 gws: {:?}, \
3385 lws: {:?}, \
3386 wait_list_len: {}, \
3387 wait_list_ptr: {:?}, \
3388 new_event_ptr: {:?}) \
3389 ",
3390 get_kernel_name(&kernel),
3391 work_dims,
3392 global_work_offset,
3393 global_work_dims,
3394 local_work_dims,
3395 wait_list_len,
3396 wait_list_ptr,
3397 new_event_ptr,
3398 );
3399
3400 let errcode = ffi::clEnqueueNDRangeKernel(
3401 command_queue.as_ptr(),
3402 kernel.as_ptr() as cl_kernel,
3403 work_dims,
3404 gwo,
3405 gws,
3406 lws,
3407 wait_list_len,
3408 wait_list_ptr,
3409 new_event_ptr,
3410 );
3411
3412 if cfg!(feature="kernel_debug_print") { println!("-> Status: {}.", errcode); }
3413 if cfg!(feature="kernel_debug_sleep") {
3414 thread::sleep(Duration::from_millis(KERNEL_DEBUG_SLEEP_DURATION_MS));
3415 }
3416
3417 if errcode != 0 {
3418 let name = get_kernel_name(kernel)?;
3419 eval_errcode(errcode, (), "clEnqueueNDRangeKernel", Some(name))
3420 } else {
3421 Ok(())
3422 }
3423}
3424
3425pub unsafe fn enqueue_task<En: ClNullEventPtr, Ewl: ClWaitListPtr>(
3444 command_queue: &CommandQueue,
3445 kernel: &Kernel,
3446 wait_list: Option<Ewl>,
3447 new_event: Option<En>,
3448 kernel_name: Option<&str>
3449 ) -> OclCoreResult<()>
3450{
3451 let (wait_list_len, wait_list_ptr, new_event_ptr) =
3452 resolve_event_ptrs(wait_list, new_event);
3453
3454 let errcode = ffi::clEnqueueTask(
3455 command_queue.as_ptr(),
3456 kernel.as_ptr() as cl_kernel,
3457 wait_list_len,
3458 wait_list_ptr,
3459 new_event_ptr,
3460 );
3461 eval_errcode(errcode, (), "clEnqueueTask", kernel_name)
3462}
3463
3464pub fn enqueue_native_kernel() -> OclCoreResult<()> {
3466 unimplemented!();
3477}
3478
3479pub fn enqueue_marker_with_wait_list<En, Ewl>(
3486 command_queue: &CommandQueue,
3487 wait_list: Option<Ewl>,
3488 new_event: Option<En>,
3489 device_version: Option<&OpenclVersion>
3490 ) -> OclCoreResult<()>
3491 where En: ClNullEventPtr, Ewl: ClWaitListPtr
3492{
3493 verify_device_version(device_version, [1, 2], command_queue,
3495 ApiFunction::EnqueueMarkerWithWaitList)?;
3496
3497 let (wait_list_len, wait_list_ptr, new_event_ptr) =
3498 resolve_event_ptrs(wait_list, new_event);
3499
3500 let errcode = unsafe { ffi::clEnqueueMarkerWithWaitList(
3501 command_queue.as_ptr(),
3502 wait_list_len,
3503 wait_list_ptr,
3504 new_event_ptr,
3505 ) };
3506 eval_errcode(errcode, (), "clEnqueueMarkerWithWaitList", None::<String>)
3507}
3508
3509pub fn enqueue_barrier_with_wait_list<En, Ewl>(
3515 command_queue: &CommandQueue,
3516 wait_list: Option<Ewl>,
3517 new_event: Option<En>,
3518 device_version: Option<&OpenclVersion>
3519 ) -> OclCoreResult<()>
3520 where En: ClNullEventPtr, Ewl: ClWaitListPtr
3521{
3522 verify_device_version(device_version, [1, 2], command_queue,
3524 ApiFunction::EnqueueBarrierWithWaitList)?;
3525
3526 let (wait_list_len, wait_list_ptr, new_event_ptr) =
3527 resolve_event_ptrs(wait_list, new_event);
3528
3529 let errcode = unsafe { ffi::clEnqueueBarrierWithWaitList(
3530 command_queue.as_ptr(),
3531 wait_list_len,
3532 wait_list_ptr,
3533 new_event_ptr,
3534 ) };
3535 eval_errcode(errcode, (), "clEnqueueBarrierWithWaitList", None::<String>)
3536}
3537
3538
3539
3540pub unsafe fn get_extension_function_address_for_platform(
3589 platform: &PlatformId,
3590 func_name: &str,
3591 platform_version: Option<&OpenclVersion>
3592 ) -> OclCoreResult<*mut c_void>
3593{
3594 verify_platform_version(platform_version, [1, 2], platform,
3596 ApiFunction::GetExtensionFunctionAddressForPlatform)?;
3597
3598 let func_name_c = r#try!(CString::new(func_name));
3599
3600 let ext_fn = ffi::clGetExtensionFunctionAddressForPlatform(
3601 platform.as_ptr(),
3602 func_name_c.as_ptr(),
3603 );
3604
3605 if ext_fn.is_null() {
3606 Err(ApiWrapperError::GetExtensionFunctionAddressForPlatformInvalidFunction.into())
3607 } else {
3608 Ok(ext_fn)
3609 }
3610}
3611
3612pub fn device_versions(device_ids: &[DeviceId]) -> OclCoreResult<Vec<OpenclVersion>> {
3621 let mut d_versions = Vec::with_capacity(device_ids.len());
3622
3623 for device_id in device_ids {
3624 d_versions.push(r#try!(device_id.version()));
3625 }
3626
3627 Ok(d_versions)
3628}
3629
3630pub fn default_platform_idx() -> usize {
3633 match env::var("OCL_DEFAULT_PLATFORM_IDX") {
3634 Ok(s) => s.parse::<usize>().unwrap_or(0),
3635 Err(_) => 0,
3636 }
3637}
3638
3639pub fn default_platform() -> OclCoreResult<PlatformId> {
3641 let platform_list = r#try!(get_platform_ids());
3642
3643 if platform_list.is_empty() {
3644 Err(ApiWrapperError::DefaultPlatformNoPlatforms.into())
3645 } else {
3646 let default_platform_idx = default_platform_idx();
3647 if default_platform_idx > platform_list.len() - 1 {
3648 Err(ApiWrapperError::DefaultPlatformEnvVarBadIdx {
3649 default_platform_idx, max_idx: platform_list.len() - 1}.into())
3650 } else {
3651 Ok(platform_list[default_platform_idx])
3652 }
3653 }
3654}
3655
3656pub fn default_device_type() -> OclCoreResult<DeviceType> {
3659 match env::var("OCL_DEFAULT_DEVICE_TYPE") {
3660 Ok(ref s) => match s.trim() {
3661 "DEFAULT" => Ok(DeviceType::DEFAULT),
3662 "CPU" => Ok(DeviceType::CPU),
3663 "GPU" => Ok(DeviceType::GPU),
3664 "ACCELERATOR" => Ok(DeviceType::ACCELERATOR),
3665 "CUSTOM" => Ok(DeviceType::CUSTOM),
3666 "ALL" => Ok(DeviceType::ALL),
3667 _ => Err(ApiWrapperError::DefaultDeviceTypeInvalidType(s.to_owned()).into()),
3668 },
3669 Err(_) => Ok(DeviceType::ALL),
3672 }
3673}
3674
3675pub fn get_kernel_name(kernel: &Kernel) -> OclCoreResult<String> {
3677 let result = get_kernel_info(kernel, KernelInfo::FunctionName)?;
3678 Ok(result.into())
3679}
3680
3681pub fn create_build_program<C, D>(
3686 context: C,
3687 src_strings: &[CString],
3688 device_ids: Option<&[D]>,
3689 cmplr_opts: &CString,
3690 ) -> OclCoreResult<Program>
3691 where C: ClContextPtr, D: ClDeviceIdPtr + fmt::Debug
3692{
3693 let program = r#try!(create_program_with_source(context, src_strings));
3694 r#try!(build_program(&program, device_ids, cmplr_opts, None, None));
3695 Ok(program)
3696}
3697
3698
3699#[allow(dead_code)]
3700pub fn wait_for_event<'e, E: ClEventPtrRef<'e>>(event: &'e E) -> OclCoreResult<()> {
3702 let errcode = unsafe {
3703 ffi::clWaitForEvents(1, event.as_ptr_ref())
3704 };
3705 eval_errcode(errcode, (), "clWaitForEvents", None::<String>)
3706}
3707
3708pub fn event_status<'e, E: ClEventPtrRef<'e>>(event: &'e E) -> OclCoreResult<CommandExecutionStatus> {
3710 let mut status_int: cl_int = 0;
3711
3712 let errcode = unsafe {
3713 ffi::clGetEventInfo(
3714 *event.as_ptr_ref(),
3715 ffi::CL_EVENT_COMMAND_EXECUTION_STATUS,
3716 mem::size_of::<cl_int>(),
3717 &mut status_int as *mut _ as *mut c_void,
3718 ptr::null_mut(),
3719 )
3720 };
3721 r#try!(eval_errcode(errcode, (), "clGetEventInfo", None::<String>));
3722
3723 CommandExecutionStatus::from_i32(status_int).ok_or_else(|| OclCoreError::from("Error converting \
3724 'clGetEventInfo' status output."))
3725}
3726
3727pub fn event_is_complete<'e, E: ClEventPtrRef<'e>>(event: &'e E) -> OclCoreResult<bool> {
3729 let mut status_int: cl_int = 0;
3730
3731 let errcode = unsafe {
3732 ffi::clGetEventInfo(
3733 *event.as_ptr_ref(),
3734 ffi::CL_EVENT_COMMAND_EXECUTION_STATUS,
3735 mem::size_of::<cl_int>(),
3736 &mut status_int as *mut _ as *mut c_void,
3737 ptr::null_mut(),
3738 )
3739 };
3740
3741 #[cfg(feature = "event_debug_print")]
3742 unsafe {
3743 println!("Event Status: {:?} (ptr: {:?})",
3744 CommandExecutionStatus::from_i32(status_int).unwrap(),
3745 *event.as_ptr_ref());
3746 }
3747
3748 eval_errcode(errcode, status_int == CommandExecutionStatus::Complete as i32,
3749 "clEventGetInfo", Some("CL_EVENT_COMMAND_EXECUTION_STATUS"))
3750}
3751
3752
3753
3754#[inline]
3773pub fn verify_context<C>(context: C) -> OclCoreResult<()>
3774 where C: ClContextPtr
3775{
3776 if cfg!(release) {
3778 Ok(())
3779 } else {
3780 match get_context_info(context, ContextInfo::Devices) {
3781 Err(err) => Err(err),
3782 _ => Ok(()),
3783 }
3784 }
3785}
3786
3787
3788fn device_supports_cl_gl_sharing<D: ClDeviceIdPtr>(device: D) -> OclCoreResult<bool> {
3790 match get_device_info(device, DeviceInfo::Extensions) {
3791 Ok(DeviceInfoResult::Extensions(extensions)) => Ok(extensions.contains(CL_GL_SHARING_EXT)),
3792 Err(err) => Err(err),
3794 _ => unreachable!(),
3795 }
3796}
3797
3798
3799pub fn get_command_queue_context_ptr(queue: &CommandQueue) -> OclCoreResult<cl_context> {
3801 let mut result = 0 as cl_context;
3802 let result_size = mem::size_of::<cl_context>();
3803
3804 let errcode = unsafe { ffi::clGetCommandQueueInfo(
3805 queue.as_ptr(),
3806 CommandQueueInfo::Context as cl_command_queue_info,
3807 result_size,
3808 &mut result as *mut _ as *mut c_void,
3809 ptr::null_mut(),
3810 ) };
3811
3812 eval_errcode(errcode, result, "clGetCommandQueueInfo",
3813 Some("functions::get_command_queue_context_ptr"))
3814}
3815
3816
3817