sycl_rs/lib.rs
1//
2// Copyright (C) 2026 Intel Corporation
3//
4// Under the MIT License or the Apache License v2.0.
5// See LICENSE-MIT and LICENSE-APACHE for license information.
6// SPDX-License-Identifier: MIT OR Apache-2.0
7//
8
9//! # SYCL-rs
10//! SYCL-rs is a set of (mostly) safe Rust bindings for SYCL - an open, royalty-free,
11//! cross-platform abstraction layer that enables code for heterogeneous and offload processors to
12//! be written using modern ISO C++, and provides APIs and abstractions to find devices
13//! (CPUs, GPUs, FPGAs ...) on which code can be executed, and to manage data resources and code
14//! execution on those devices.
15//!
16//! # System dependencies
17//! Make sure to install the [Intel oneAPI toolkit](https://www.intel.com/content/www/us/en/developer/tools/oneapi/oneapi-toolkit-download.html).
18//! Then source the `setvars.sh` file:
19//! ```bash
20//! source <oneapi_install_directory>/setvars.sh
21//! ```
22//!
23//! This project was tested on oneAPI Toolkit 2026.1 and requires the Unified Runtime over Level Zero
24//! driver version 1.14.37020 or newer. For more detailed information check out the
25//! [required extensions](crate#required-extensions) section.
26//!
27//! # Getting started
28//! ### Building the crate
29//! Before building this crate you need to source the `setvars.sh` file. You can then build it as
30//! usual with cargo:
31//! ```bash
32//! cargo build --release
33//! ```
34//!
35//! You must also source `setvars.sh` before running any SYCL program.
36//!
37//! ### Hello world
38//!
39//! ```
40//! # use sycl_rs::prelude::*;
41//!
42//! # static IOTA_SRC: &str = r#"
43//! # #include <sycl/sycl.hpp>
44//! # namespace syclext = sycl::ext::oneapi;
45//! # namespace syclexp = sycl::ext::oneapi::experimental;
46//! #
47//! # extern "C"
48//! # SYCL_EXT_ONEAPI_FUNCTION_PROPERTY((syclexp::nd_range_kernel<1>))
49//! # void iota(float start, float *ptr) {
50//! # size_t id = syclext::this_work_item::get_nd_item<1>().get_global_linear_id();
51//! # ptr[id] = start + static_cast<float>(id);
52//! # }
53//! # "#;
54//! #
55//! fn main() -> sycl_rs::Result<()> {
56//! // 1. Create a Queue. It's the main entry point to the SYCL API.
57//! let mut queue = Queue::new();
58//! let mut device_array = queue.alloc_device::<f32>(1024)?.wait()?;
59//!
60//! // 3. Build a SYCL kernel.
61//! let kernel = queue
62//! .get_context()
63//! .create_kernel_bundle_from_source(IOTA_SRC)?
64//! .build()?
65//! .get_kernel("iota")?;
66//!
67//! // 4. Launch your kernel.
68//! unsafe {
69//! queue.launch(
70//! NdRange::new([1024], [16]),
71//! &kernel,
72//! (3.14_f32, &mut device_array),
73//! )
74//! }?
75//! .wait()?;
76//!
77//! let mut host_array = queue.alloc_host::<f32>(1024)?.wait()?;
78//!
79//! // 5. Copy your data to the host.
80//! queue.copy(&device_array, &mut host_array)?.wait()?;
81//!
82//! // You can access your host data just like a normal Rust slice.
83//! for e in host_array.iter() {
84//! print!("{e} ");
85//! }
86//! println!();
87//!
88//! Ok(())
89//! }
90//! ```
91//!
92//! # Safety model
93//! - USM allocations are represented by a zero-cost [`UsmBox`](crate::usmbox::UsmBox) type managed
94//! through RAII.
95//! - Note: `UsmBox` arrays do not rely on accessors, unlike SYCL buffers.
96//! - `UsmBox`es are zero-initialized by default.
97//! - `UsmBox`es can only store types that implement [`bytemuck::Pod`].
98//! - Kernel launch is inherently unsafe. In particular, the caller must ensure that every argument
99//! has the correct representation, layout, and alignment.
100//!
101//! # Asynchronous programming model
102//! Each queue operation returns an [`Event`](`crate::event::Event`). You can synchronously
103//! [`.wait()`](crate::event::Event::wait) for it, or asynchronously `.await` it.
104//!
105//! You can also synchronously call [`Queue::wait()`](crate::queue::Queue::wait) to wait for a
106//! [`Queue`](crate::queue::Queue) directly. To do the same asynchronously you have to `.await` an
107//! event returned by [`Queue::barrier()`](crate::queue::Queue::barrier).
108//!
109//! All basic SYCL wrapper types (`Queue`, `Event`, `Context`, `Platform`, `Device`) are thread safe as
110//! indicated by the provided [`Send`] and [`Sync`] trait implementations. However - `UsmBox`es are
111//! not thread-safe. If you need a thread-safe `UsmBox` you need to wrap it in an `Arc<Mutex<T>>`.
112//!
113//! # Required extensions
114//! This project requires the following SYCL extensions to work:
115//! - [sycl_ext_oneapi_kernel_compiler](https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/experimental/sycl_ext_oneapi_kernel_compiler.asciidoc)
116//! - [sycl_ext_oneapi_raw_kernel_arg](https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/experimental/sycl_ext_oneapi_raw_kernel_arg.asciidoc)
117//!
118//! The following extensions are also required for async support:
119//! - [sycl_ext_intel_queue_immediate_command_list](https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/supported/sycl_ext_intel_queue_immediate_command_list.asciidoc)
120//! - [sycl_ext_oneapi_enqueue_barrier](https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/supported/sycl_ext_oneapi_enqueue_barrier.asciidoc)
121
122pub mod context;
123pub mod device;
124pub mod event;
125pub mod info;
126pub mod kernel;
127pub mod platform;
128pub mod prelude;
129pub mod queue;
130pub mod range;
131pub mod usm;
132pub mod usmbox;
133
134pub type SyclError = cxx::Exception;
135pub type Result<T> = std::result::Result<T, SyclError>;
136
137mod private {
138 pub trait Sealed {}
139}