From b8892db99abc6bc8cd14a64fd767dcbd725d4b59 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 6 Jul 2026 10:34:19 +0000 Subject: [PATCH 01/27] Add C++ sycl::queue bindings --- oneapi-rs-sys/build.rs | 3 +++ oneapi-rs-sys/include/queue.hpp | 19 +++++++++++++++++++ oneapi-rs-sys/include/types.hpp | 1 + oneapi-rs-sys/src/lib.rs | 3 +++ oneapi-rs-sys/src/queue-sys.rs | 22 ++++++++++++++++++++++ oneapi-rs-sys/src/queue.cpp | 19 +++++++++++++++++++ oneapi-rs-sys/src/types-sys.rs | 2 ++ 7 files changed, 69 insertions(+) create mode 100644 oneapi-rs-sys/include/queue.hpp create mode 100644 oneapi-rs-sys/src/queue-sys.rs create mode 100644 oneapi-rs-sys/src/queue.cpp diff --git a/oneapi-rs-sys/build.rs b/oneapi-rs-sys/build.rs index d0bd169..e07c63a 100644 --- a/oneapi-rs-sys/build.rs +++ b/oneapi-rs-sys/build.rs @@ -17,17 +17,20 @@ fn main() { "src/types-sys.rs", "src/platform-sys.rs", "src/device-sys.rs", + "src/queue-sys.rs", ]; let cpp_sources = [ "src/platform.cpp", "src/device.cpp", + "src/queue.cpp", ]; let cpp_headers = [ "include/types.hpp", "include/platform.hpp", "include/device.hpp", + "include/queue.hpp", ]; cxx_build::bridges(&rust_sources) diff --git a/oneapi-rs-sys/include/queue.hpp b/oneapi-rs-sys/include/queue.hpp new file mode 100644 index 0000000..55a6877 --- /dev/null +++ b/oneapi-rs-sys/include/queue.hpp @@ -0,0 +1,19 @@ +// +// Copyright (C) 2026 Intel Corporation +// +// Under the MIT License or the Apache License v2.0. +// See LICENSE-MIT and LICENSE-APACHE for license information. +// SPDX-License-Identifier: MIT OR Apache-2.0 +// + +#pragma once + +#include "oneapi-rs-sys/include/types.hpp" +#include "rust/cxx.h" + +#include + +namespace sycl_shims::queue { +std::unique_ptr new_queue(); +std::unique_ptr new_queue_from_device(Device const &); +} // namespace sycl_shims::queue diff --git a/oneapi-rs-sys/include/types.hpp b/oneapi-rs-sys/include/types.hpp index 1592c70..f97d0af 100644 --- a/oneapi-rs-sys/include/types.hpp +++ b/oneapi-rs-sys/include/types.hpp @@ -13,4 +13,5 @@ namespace sycl_shims { using Device = sycl::device; using Platform = sycl::platform; +using Queue = sycl::queue; } diff --git a/oneapi-rs-sys/src/lib.rs b/oneapi-rs-sys/src/lib.rs index 4163989..e61a3b8 100644 --- a/oneapi-rs-sys/src/lib.rs +++ b/oneapi-rs-sys/src/lib.rs @@ -14,3 +14,6 @@ pub mod platform; #[path = "device-sys.rs"] pub mod device; + +#[path = "queue-sys.rs"] +pub mod queue; diff --git a/oneapi-rs-sys/src/queue-sys.rs b/oneapi-rs-sys/src/queue-sys.rs new file mode 100644 index 0000000..b7b1c65 --- /dev/null +++ b/oneapi-rs-sys/src/queue-sys.rs @@ -0,0 +1,22 @@ +// +// Copyright (C) 2026 Intel Corporation +// +// Under the MIT License or the Apache License v2.0. +// See LICENSE-MIT and LICENSE-APACHE for license information. +// SPDX-License-Identifier: MIT OR Apache-2.0 +// + +#[cxx::bridge(namespace = "sycl_shims::queue")] +pub mod ffi { + unsafe extern "C++" { + include!("oneapi-rs-sys/include/queue.hpp"); + + #[namespace = "sycl_shims"] + type Queue = crate::types::ffi::Queue; + #[namespace = "sycl_shims"] + type Device = crate::types::ffi::Device; + + fn new_queue() -> UniquePtr; + fn new_queue_from_device(device: &Device) -> UniquePtr; + } +} diff --git a/oneapi-rs-sys/src/queue.cpp b/oneapi-rs-sys/src/queue.cpp new file mode 100644 index 0000000..22e012c --- /dev/null +++ b/oneapi-rs-sys/src/queue.cpp @@ -0,0 +1,19 @@ +// +// Copyright (C) 2026 Intel Corporation +// +// Under the MIT License or the Apache License v2.0. +// See LICENSE-MIT and LICENSE-APACHE for license information. +// SPDX-License-Identifier: MIT OR Apache-2.0 +// + +#include "oneapi-rs-sys/include/queue.hpp" +#include "oneapi-rs-sys/src/queue-sys.rs.h" + +namespace sycl_shims::queue { +std::unique_ptr new_queue() { + return std::make_unique(sycl::queue()); +} +std::unique_ptr new_queue_from_device(Device const & device) { + return std::make_unique(sycl::queue(device)); +} +} // namespace sycl_shims::queue diff --git a/oneapi-rs-sys/src/types-sys.rs b/oneapi-rs-sys/src/types-sys.rs index b14407f..5075deb 100644 --- a/oneapi-rs-sys/src/types-sys.rs +++ b/oneapi-rs-sys/src/types-sys.rs @@ -12,6 +12,7 @@ pub mod ffi { include!("oneapi-rs-sys/include/types.hpp"); type Device; type Platform; + type Queue; } // This is a workaround - cxx currently doesn't support passing @@ -39,6 +40,7 @@ pub mod ffi { impl UniquePtr {} impl UniquePtr {} + impl UniquePtr {} impl Vec {} impl Vec {} From a8ddc52845772f1cc769f839160660013143b772 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 6 Jul 2026 10:50:54 +0000 Subject: [PATCH 02/27] Add Rust Queue abstraction --- oneapi-rs/src/lib.rs | 1 + oneapi-rs/src/queue.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 oneapi-rs/src/queue.rs diff --git a/oneapi-rs/src/lib.rs b/oneapi-rs/src/lib.rs index c3dac94..2d97a53 100644 --- a/oneapi-rs/src/lib.rs +++ b/oneapi-rs/src/lib.rs @@ -9,3 +9,4 @@ pub mod info; pub mod platform; pub mod device; +pub mod queue; diff --git a/oneapi-rs/src/queue.rs b/oneapi-rs/src/queue.rs new file mode 100644 index 0000000..d8f4294 --- /dev/null +++ b/oneapi-rs/src/queue.rs @@ -0,0 +1,29 @@ +// +// Copyright (C) 2026 Intel Corporation +// +// Under the MIT License or the Apache License v2.0. +// See LICENSE-MIT and LICENSE-APACHE for license information. +// SPDX-License-Identifier: MIT OR Apache-2.0 +// + +use oneapi_rs_sys::queue::ffi; + +use crate::device::Device; + +/// The `Queue` connects a host program to a single device. Programs submit tasks to a device via the +/// `Queue` and may monitor the `Queue` for completion. A program initiates the task by submitting +/// a kernel. +pub struct Queue(pub(crate) cxx::UniquePtr); + +impl Queue { + /// Construct a `Queue` based on the device returned from the default selector. + pub fn new() -> Self { + Self(ffi::new_queue()) + } +} + +impl From<&Device> for Queue { + fn from(value: &Device) -> Self { + Self(ffi::new_queue_from_device(&value.0)) + } +} From bc7225e2e05afe34b65964c213db6c2c8b6a2230 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 6 Jul 2026 13:33:10 +0000 Subject: [PATCH 03/27] Add C++ USM module --- oneapi-rs-sys/build.rs | 3 +++ oneapi-rs-sys/include/usm.hpp | 18 ++++++++++++++++++ oneapi-rs-sys/src/lib.rs | 3 +++ oneapi-rs-sys/src/usm-sys.rs | 20 ++++++++++++++++++++ oneapi-rs-sys/src/usm.cpp | 16 ++++++++++++++++ 5 files changed, 60 insertions(+) create mode 100644 oneapi-rs-sys/include/usm.hpp create mode 100644 oneapi-rs-sys/src/usm-sys.rs create mode 100644 oneapi-rs-sys/src/usm.cpp diff --git a/oneapi-rs-sys/build.rs b/oneapi-rs-sys/build.rs index e07c63a..ea87a54 100644 --- a/oneapi-rs-sys/build.rs +++ b/oneapi-rs-sys/build.rs @@ -18,12 +18,14 @@ fn main() { "src/platform-sys.rs", "src/device-sys.rs", "src/queue-sys.rs", + "src/usm-sys.rs", ]; let cpp_sources = [ "src/platform.cpp", "src/device.cpp", "src/queue.cpp", + "src/usm.cpp", ]; let cpp_headers = [ @@ -31,6 +33,7 @@ fn main() { "include/platform.hpp", "include/device.hpp", "include/queue.hpp", + "src/usm.hpp", ]; cxx_build::bridges(&rust_sources) diff --git a/oneapi-rs-sys/include/usm.hpp b/oneapi-rs-sys/include/usm.hpp new file mode 100644 index 0000000..af6cd4b --- /dev/null +++ b/oneapi-rs-sys/include/usm.hpp @@ -0,0 +1,18 @@ +// +// Copyright (C) 2026 Intel Corporation +// +// Under the MIT License or the Apache License v2.0. +// See LICENSE-MIT and LICENSE-APACHE for license information. +// SPDX-License-Identifier: MIT OR Apache-2.0 +// + +#pragma once + +#include "oneapi-rs-sys/include/types.hpp" +#include "rust/cxx.h" + +#include + +namespace sycl_shims::usm { +std::uint8_t* malloc_device(std::size_t, Queue const &); +} // namespace sycl_shims::usm diff --git a/oneapi-rs-sys/src/lib.rs b/oneapi-rs-sys/src/lib.rs index e61a3b8..9f71b49 100644 --- a/oneapi-rs-sys/src/lib.rs +++ b/oneapi-rs-sys/src/lib.rs @@ -17,3 +17,6 @@ pub mod device; #[path = "queue-sys.rs"] pub mod queue; + +#[path = "usm-sys.rs"] +pub mod usm; diff --git a/oneapi-rs-sys/src/usm-sys.rs b/oneapi-rs-sys/src/usm-sys.rs new file mode 100644 index 0000000..5bf0d73 --- /dev/null +++ b/oneapi-rs-sys/src/usm-sys.rs @@ -0,0 +1,20 @@ +// +// Copyright (C) 2026 Intel Corporation +// +// Under the MIT License or the Apache License v2.0. +// See LICENSE-MIT and LICENSE-APACHE for license information. +// SPDX-License-Identifier: MIT OR Apache-2.0 +// + +#[cxx::bridge(namespace = "sycl_shims::usm")] +pub mod ffi { + unsafe extern "C++" { + #[namespace = "sycl_shims"] + type Queue = crate::types::ffi::Queue; + } + + extern "C++" { + include!("oneapi-rs-sys/include/usm.hpp"); + unsafe fn malloc_device(size: usize, queue: &Queue) -> Result<*mut u8>; + } +} diff --git a/oneapi-rs-sys/src/usm.cpp b/oneapi-rs-sys/src/usm.cpp new file mode 100644 index 0000000..5a0e649 --- /dev/null +++ b/oneapi-rs-sys/src/usm.cpp @@ -0,0 +1,16 @@ +// +// Copyright (C) 2026 Intel Corporation +// +// Under the MIT License or the Apache License v2.0. +// See LICENSE-MIT and LICENSE-APACHE for license information. +// SPDX-License-Identifier: MIT OR Apache-2.0 +// + +#include "oneapi-rs-sys/include/usm.hpp" +#include "oneapi-rs-sys/src/usm-sys.rs.h" + +namespace sycl_shims::usm { +std::uint8_t* malloc_device(std::size_t size, Queue const & queue) { + return static_cast(sycl::malloc_device(size, queue)); +} +} // namespace sycl_shims::usm From dff66f1ed27b35f9249cc8b66debdffedbf23c92 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 6 Jul 2026 14:46:12 +0000 Subject: [PATCH 04/27] Add C++ sycl::free binding --- oneapi-rs-sys/include/usm.hpp | 1 + oneapi-rs-sys/src/usm-sys.rs | 1 + oneapi-rs-sys/src/usm.cpp | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/oneapi-rs-sys/include/usm.hpp b/oneapi-rs-sys/include/usm.hpp index af6cd4b..9dea034 100644 --- a/oneapi-rs-sys/include/usm.hpp +++ b/oneapi-rs-sys/include/usm.hpp @@ -15,4 +15,5 @@ namespace sycl_shims::usm { std::uint8_t* malloc_device(std::size_t, Queue const &); +void free(std::uint8_t*, Queue const &); } // namespace sycl_shims::usm diff --git a/oneapi-rs-sys/src/usm-sys.rs b/oneapi-rs-sys/src/usm-sys.rs index 5bf0d73..571752b 100644 --- a/oneapi-rs-sys/src/usm-sys.rs +++ b/oneapi-rs-sys/src/usm-sys.rs @@ -16,5 +16,6 @@ pub mod ffi { extern "C++" { include!("oneapi-rs-sys/include/usm.hpp"); unsafe fn malloc_device(size: usize, queue: &Queue) -> Result<*mut u8>; + unsafe fn free(ptr: *mut u8, queue: &Queue); } } diff --git a/oneapi-rs-sys/src/usm.cpp b/oneapi-rs-sys/src/usm.cpp index 5a0e649..e53ec9e 100644 --- a/oneapi-rs-sys/src/usm.cpp +++ b/oneapi-rs-sys/src/usm.cpp @@ -13,4 +13,8 @@ namespace sycl_shims::usm { std::uint8_t* malloc_device(std::size_t size, Queue const & queue) { return static_cast(sycl::malloc_device(size, queue)); } + +void free(std::uint8_t* memory, Queue const & queue) { + sycl::free(static_cast(memory), queue); +} } // namespace sycl_shims::usm From 561b657a787e3b1d1499f8521e402cd1cdfa81fa Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 6 Jul 2026 14:51:41 +0000 Subject: [PATCH 05/27] Add Allocator trait --- Cargo.lock | 21 +++++++++++++++++++++ oneapi-rs/Cargo.toml | 1 + oneapi-rs/src/allocator.rs | 22 ++++++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 oneapi-rs/src/allocator.rs diff --git a/Cargo.lock b/Cargo.lock index 275eb5a..2765b20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -172,6 +172,7 @@ version = "0.1.0" dependencies = [ "cxx", "oneapi-rs-sys", + "thiserror", ] [[package]] @@ -269,6 +270,26 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.24" diff --git a/oneapi-rs/Cargo.toml b/oneapi-rs/Cargo.toml index 0615d00..e238b31 100644 --- a/oneapi-rs/Cargo.toml +++ b/oneapi-rs/Cargo.toml @@ -7,3 +7,4 @@ license = "MIT OR Apache-2.0" [dependencies] cxx = "1.0.194" oneapi-rs-sys = { path = "../oneapi-rs-sys" } +thiserror = "2.0.18" diff --git a/oneapi-rs/src/allocator.rs b/oneapi-rs/src/allocator.rs new file mode 100644 index 0000000..cfa2880 --- /dev/null +++ b/oneapi-rs/src/allocator.rs @@ -0,0 +1,22 @@ +use std::{alloc::Layout, ptr::NonNull}; +use thiserror::Error; + +/// A copy of the unstable [`Allocator`](std::alloc::Allocator) trait. +/// This module will become unnecessary when the [`Allocator`](std::alloc::Allocator) trait gets stabilized. + +#[derive(Error, Debug)] +pub enum AllocError { + #[error("the device used does not support USM allocation")] + FeatureNotSupported, + #[error("the device used does not correspond to any SYCL context")] + Invalid, + #[error("there's not enough memory to allocate")] + NoMemory, + #[error("other error")] + Other(String) +} + +pub unsafe trait Allocator { + fn allocate(&self, layout: Layout) -> Result, AllocError>; + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout); +} From de0bc580843f3aa00b8f50e966c4f518d73f7e45 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 6 Jul 2026 14:51:57 +0000 Subject: [PATCH 06/27] Add safe USM allocator abstraction --- oneapi-rs/src/lib.rs | 2 ++ oneapi-rs/src/usm.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 oneapi-rs/src/usm.rs diff --git a/oneapi-rs/src/lib.rs b/oneapi-rs/src/lib.rs index 2d97a53..4c59119 100644 --- a/oneapi-rs/src/lib.rs +++ b/oneapi-rs/src/lib.rs @@ -10,3 +10,5 @@ pub mod info; pub mod platform; pub mod device; pub mod queue; +pub mod usm; +pub mod allocator; diff --git a/oneapi-rs/src/usm.rs b/oneapi-rs/src/usm.rs new file mode 100644 index 0000000..bce57d2 --- /dev/null +++ b/oneapi-rs/src/usm.rs @@ -0,0 +1,31 @@ +use std::{alloc::Layout, ptr::NonNull}; + +use oneapi_rs_sys::usm::ffi; + +use crate::{allocator::{AllocError, Allocator}, queue::Queue}; + +pub struct DeviceAllocator<'a> { + queue: &'a Queue +} + +impl<'a> From<&'a Queue> for DeviceAllocator<'a> { + fn from(queue: &'a Queue) -> Self { + Self { queue } + } +} + +unsafe impl<'a> Allocator for DeviceAllocator<'a> { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + let ptr = unsafe { ffi::malloc_device(layout.size(), &self.queue.0) } + .map_err(|e| AllocError::Other(e.to_string()))?; + + let ptr = NonNull::new(ptr).ok_or(AllocError::NoMemory)?; + let slice = NonNull::slice_from_raw_parts(ptr, layout.size()); + + Ok(slice) + } + + unsafe fn deallocate(&self, ptr: NonNull, _layout: Layout) { + unsafe { ffi::free(ptr.as_ptr(), &self.queue.0); } + } +} From c16a4555ed3f26a84db60d8d6f4a6c0a70d04e5c Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 08:54:40 +0000 Subject: [PATCH 07/27] Add support for memory alignment --- oneapi-rs-sys/include/usm.hpp | 2 +- oneapi-rs-sys/src/usm-sys.rs | 2 +- oneapi-rs-sys/src/usm.cpp | 4 ++-- oneapi-rs/src/usm.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/oneapi-rs-sys/include/usm.hpp b/oneapi-rs-sys/include/usm.hpp index 9dea034..87b6edd 100644 --- a/oneapi-rs-sys/include/usm.hpp +++ b/oneapi-rs-sys/include/usm.hpp @@ -14,6 +14,6 @@ #include namespace sycl_shims::usm { -std::uint8_t* malloc_device(std::size_t, Queue const &); +std::uint8_t* aligned_alloc_device(std::size_t alignment, std::size_t bytes, Queue const &); void free(std::uint8_t*, Queue const &); } // namespace sycl_shims::usm diff --git a/oneapi-rs-sys/src/usm-sys.rs b/oneapi-rs-sys/src/usm-sys.rs index 571752b..5883c64 100644 --- a/oneapi-rs-sys/src/usm-sys.rs +++ b/oneapi-rs-sys/src/usm-sys.rs @@ -15,7 +15,7 @@ pub mod ffi { extern "C++" { include!("oneapi-rs-sys/include/usm.hpp"); - unsafe fn malloc_device(size: usize, queue: &Queue) -> Result<*mut u8>; + unsafe fn aligned_alloc_device(alignment: usize, bytes: usize, queue: &Queue) -> Result<*mut u8>; unsafe fn free(ptr: *mut u8, queue: &Queue); } } diff --git a/oneapi-rs-sys/src/usm.cpp b/oneapi-rs-sys/src/usm.cpp index e53ec9e..8a69af9 100644 --- a/oneapi-rs-sys/src/usm.cpp +++ b/oneapi-rs-sys/src/usm.cpp @@ -10,8 +10,8 @@ #include "oneapi-rs-sys/src/usm-sys.rs.h" namespace sycl_shims::usm { -std::uint8_t* malloc_device(std::size_t size, Queue const & queue) { - return static_cast(sycl::malloc_device(size, queue)); +std::uint8_t* aligned_alloc_device(std::size_t alignment, std::size_t bytes, Queue const & queue) { + return static_cast(sycl::aligned_alloc_device(alignment, bytes, queue)); } void free(std::uint8_t* memory, Queue const & queue) { diff --git a/oneapi-rs/src/usm.rs b/oneapi-rs/src/usm.rs index bce57d2..77e60f5 100644 --- a/oneapi-rs/src/usm.rs +++ b/oneapi-rs/src/usm.rs @@ -16,7 +16,7 @@ impl<'a> From<&'a Queue> for DeviceAllocator<'a> { unsafe impl<'a> Allocator for DeviceAllocator<'a> { fn allocate(&self, layout: Layout) -> Result, AllocError> { - let ptr = unsafe { ffi::malloc_device(layout.size(), &self.queue.0) } + let ptr = unsafe { ffi::aligned_alloc_device(layout.align(), layout.size(), &self.queue.0) } .map_err(|e| AllocError::Other(e.to_string()))?; let ptr = NonNull::new(ptr).ok_or(AllocError::NoMemory)?; From 1576121a9e47f6a070bfedf1d5d8304a66468d96 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 10:00:41 +0000 Subject: [PATCH 08/27] Add C++ aligned_alloc_host binding --- oneapi-rs-sys/include/usm.hpp | 1 + oneapi-rs-sys/src/usm-sys.rs | 1 + oneapi-rs-sys/src/usm.cpp | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/oneapi-rs-sys/include/usm.hpp b/oneapi-rs-sys/include/usm.hpp index 87b6edd..76cfa89 100644 --- a/oneapi-rs-sys/include/usm.hpp +++ b/oneapi-rs-sys/include/usm.hpp @@ -15,5 +15,6 @@ namespace sycl_shims::usm { std::uint8_t* aligned_alloc_device(std::size_t alignment, std::size_t bytes, Queue const &); +std::uint8_t* aligned_alloc_host(std::size_t alignment, std::size_t bytes, Queue const &); void free(std::uint8_t*, Queue const &); } // namespace sycl_shims::usm diff --git a/oneapi-rs-sys/src/usm-sys.rs b/oneapi-rs-sys/src/usm-sys.rs index 5883c64..9645005 100644 --- a/oneapi-rs-sys/src/usm-sys.rs +++ b/oneapi-rs-sys/src/usm-sys.rs @@ -16,6 +16,7 @@ pub mod ffi { extern "C++" { include!("oneapi-rs-sys/include/usm.hpp"); unsafe fn aligned_alloc_device(alignment: usize, bytes: usize, queue: &Queue) -> Result<*mut u8>; + unsafe fn aligned_alloc_host(alignment: usize, bytes: usize, queue: &Queue) -> Result<*mut u8>; unsafe fn free(ptr: *mut u8, queue: &Queue); } } diff --git a/oneapi-rs-sys/src/usm.cpp b/oneapi-rs-sys/src/usm.cpp index 8a69af9..3b6227b 100644 --- a/oneapi-rs-sys/src/usm.cpp +++ b/oneapi-rs-sys/src/usm.cpp @@ -14,6 +14,10 @@ std::uint8_t* aligned_alloc_device(std::size_t alignment, std::size_t bytes, Que return static_cast(sycl::aligned_alloc_device(alignment, bytes, queue)); } +std::uint8_t* aligned_alloc_host(std::size_t alignment, std::size_t bytes, Queue const & queue) { + return static_cast(sycl::aligned_alloc_host(alignment, bytes, queue)); +} + void free(std::uint8_t* memory, Queue const & queue) { sycl::free(static_cast(memory), queue); } From 68d217dd901953517374f563f3aceaacc98707f3 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 10:02:10 +0000 Subject: [PATCH 09/27] Add C++ aligned_alloc_shared binding --- oneapi-rs-sys/include/usm.hpp | 1 + oneapi-rs-sys/src/usm-sys.rs | 1 + oneapi-rs-sys/src/usm.cpp | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/oneapi-rs-sys/include/usm.hpp b/oneapi-rs-sys/include/usm.hpp index 76cfa89..af5085b 100644 --- a/oneapi-rs-sys/include/usm.hpp +++ b/oneapi-rs-sys/include/usm.hpp @@ -16,5 +16,6 @@ namespace sycl_shims::usm { std::uint8_t* aligned_alloc_device(std::size_t alignment, std::size_t bytes, Queue const &); std::uint8_t* aligned_alloc_host(std::size_t alignment, std::size_t bytes, Queue const &); +std::uint8_t* aligned_alloc_shared(std::size_t alignment, std::size_t bytes, Queue const &); void free(std::uint8_t*, Queue const &); } // namespace sycl_shims::usm diff --git a/oneapi-rs-sys/src/usm-sys.rs b/oneapi-rs-sys/src/usm-sys.rs index 9645005..7324e40 100644 --- a/oneapi-rs-sys/src/usm-sys.rs +++ b/oneapi-rs-sys/src/usm-sys.rs @@ -17,6 +17,7 @@ pub mod ffi { include!("oneapi-rs-sys/include/usm.hpp"); unsafe fn aligned_alloc_device(alignment: usize, bytes: usize, queue: &Queue) -> Result<*mut u8>; unsafe fn aligned_alloc_host(alignment: usize, bytes: usize, queue: &Queue) -> Result<*mut u8>; + unsafe fn aligned_alloc_shared(alignment: usize, bytes: usize, queue: &Queue) -> Result<*mut u8>; unsafe fn free(ptr: *mut u8, queue: &Queue); } } diff --git a/oneapi-rs-sys/src/usm.cpp b/oneapi-rs-sys/src/usm.cpp index 3b6227b..22f09c1 100644 --- a/oneapi-rs-sys/src/usm.cpp +++ b/oneapi-rs-sys/src/usm.cpp @@ -18,6 +18,10 @@ std::uint8_t* aligned_alloc_host(std::size_t alignment, std::size_t bytes, Queue return static_cast(sycl::aligned_alloc_host(alignment, bytes, queue)); } +std::uint8_t* aligned_alloc_shared(std::size_t alignment, std::size_t bytes, Queue const & queue) { + return static_cast(sycl::aligned_alloc_shared(alignment, bytes, queue)); +} + void free(std::uint8_t* memory, Queue const & queue) { sycl::free(static_cast(memory), queue); } From 0ee4ce7c57b73415452ab515c92642602ccbc0a3 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 10:46:35 +0000 Subject: [PATCH 10/27] Add generic UsmAllocator trait --- oneapi-rs/src/usm.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/oneapi-rs/src/usm.rs b/oneapi-rs/src/usm.rs index 77e60f5..4722d98 100644 --- a/oneapi-rs/src/usm.rs +++ b/oneapi-rs/src/usm.rs @@ -3,6 +3,12 @@ use std::{alloc::Layout, ptr::NonNull}; use oneapi_rs_sys::usm::ffi; use crate::{allocator::{AllocError, Allocator}, queue::Queue}; +type CxxResult = cxx::core::result::Result; + +trait UsmAllocator { + unsafe fn alloc(&self, alignment: usize, bytes: usize) -> CxxResult<*mut u8>; + fn get_queue(&self) -> &Queue; +} pub struct DeviceAllocator<'a> { queue: &'a Queue @@ -14,9 +20,20 @@ impl<'a> From<&'a Queue> for DeviceAllocator<'a> { } } -unsafe impl<'a> Allocator for DeviceAllocator<'a> { +impl<'a> UsmAllocator for DeviceAllocator<'a> { + unsafe fn alloc(&self, alignment: usize, bytes: usize) -> CxxResult<*mut u8> { + unsafe { ffi::aligned_alloc_device(alignment, bytes, &self.queue.0) } + } + + fn get_queue(&self) -> &Queue { + &self.queue + } +} + +unsafe impl Allocator for T +where T: UsmAllocator { fn allocate(&self, layout: Layout) -> Result, AllocError> { - let ptr = unsafe { ffi::aligned_alloc_device(layout.align(), layout.size(), &self.queue.0) } + let ptr = unsafe { self.alloc(layout.align(), layout.size()) } .map_err(|e| AllocError::Other(e.to_string()))?; let ptr = NonNull::new(ptr).ok_or(AllocError::NoMemory)?; @@ -26,6 +43,6 @@ unsafe impl<'a> Allocator for DeviceAllocator<'a> { } unsafe fn deallocate(&self, ptr: NonNull, _layout: Layout) { - unsafe { ffi::free(ptr.as_ptr(), &self.queue.0); } + unsafe { ffi::free(ptr.as_ptr(), &self.get_queue().0); } } } From 1042197fffe0ba5997d2c0aa0fd3d5ba6395c58b Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 10:49:51 +0000 Subject: [PATCH 11/27] Hide DeviceAllocator --- oneapi-rs/src/usm.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oneapi-rs/src/usm.rs b/oneapi-rs/src/usm.rs index 4722d98..3e063bf 100644 --- a/oneapi-rs/src/usm.rs +++ b/oneapi-rs/src/usm.rs @@ -10,7 +10,8 @@ trait UsmAllocator { fn get_queue(&self) -> &Queue; } -pub struct DeviceAllocator<'a> { +#[allow(dead_code)] +pub(crate) struct DeviceAllocator<'a> { queue: &'a Queue } From ec64da1c1635f5dc11301d64e384f30db442d427 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 10:51:47 +0000 Subject: [PATCH 12/27] Add a host allocator --- oneapi-rs/src/usm.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/oneapi-rs/src/usm.rs b/oneapi-rs/src/usm.rs index 3e063bf..d4900ad 100644 --- a/oneapi-rs/src/usm.rs +++ b/oneapi-rs/src/usm.rs @@ -31,6 +31,26 @@ impl<'a> UsmAllocator for DeviceAllocator<'a> { } } +pub struct HostAllocator<'a> { + queue: &'a Queue +} + +impl<'a> From<&'a Queue> for HostAllocator<'a> { + fn from(queue: &'a Queue) -> Self { + Self { queue } + } +} + +impl<'a> UsmAllocator for HostAllocator<'a> { + unsafe fn alloc(&self, alignment: usize, bytes: usize) -> CxxResult<*mut u8> { + unsafe { ffi::aligned_alloc_host(alignment, bytes, &self.queue.0) } + } + + fn get_queue(&self) -> &Queue { + &self.queue + } +} + unsafe impl Allocator for T where T: UsmAllocator { fn allocate(&self, layout: Layout) -> Result, AllocError> { From dd960839caaaf51221267838fcaa741840a02b5e Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 10:53:18 +0000 Subject: [PATCH 13/27] Add a shared allocator --- oneapi-rs/src/usm.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/oneapi-rs/src/usm.rs b/oneapi-rs/src/usm.rs index d4900ad..164d948 100644 --- a/oneapi-rs/src/usm.rs +++ b/oneapi-rs/src/usm.rs @@ -51,6 +51,26 @@ impl<'a> UsmAllocator for HostAllocator<'a> { } } +pub struct SharedAllocator<'a> { + queue: &'a Queue +} + +impl<'a> From<&'a Queue> for SharedAllocator<'a> { + fn from(queue: &'a Queue) -> Self { + Self { queue } + } +} + +impl<'a> UsmAllocator for SharedAllocator<'a> { + unsafe fn alloc(&self, alignment: usize, bytes: usize) -> CxxResult<*mut u8> { + unsafe { ffi::aligned_alloc_shared(alignment, bytes, &self.queue.0) } + } + + fn get_queue(&self) -> &Queue { + &self.queue + } +} + unsafe impl Allocator for T where T: UsmAllocator { fn allocate(&self, layout: Layout) -> Result, AllocError> { From 5c9c7c1383c8f738d440c2cca4f018b60efc4f07 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 12:32:24 +0000 Subject: [PATCH 14/27] Use allocator_api2 --- Cargo.lock | 7 +++ oneapi-rs/Cargo.toml | 1 + oneapi-rs/src/allocator.rs | 22 -------- oneapi-rs/src/lib.rs | 1 - oneapi-rs/src/usm.rs | 102 ++++++++++++++++--------------------- 5 files changed, 52 insertions(+), 81 deletions(-) delete mode 100644 oneapi-rs/src/allocator.rs diff --git a/Cargo.lock b/Cargo.lock index 2765b20..ac1796a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "allocator-api2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c880a97d28a3681c0267bd29cff89621202715b065127cd445fa0f0fe0aa2880" + [[package]] name = "anstyle" version = "1.0.14" @@ -170,6 +176,7 @@ dependencies = [ name = "oneapi-rs" version = "0.1.0" dependencies = [ + "allocator-api2", "cxx", "oneapi-rs-sys", "thiserror", diff --git a/oneapi-rs/Cargo.toml b/oneapi-rs/Cargo.toml index e238b31..3bb6be3 100644 --- a/oneapi-rs/Cargo.toml +++ b/oneapi-rs/Cargo.toml @@ -5,6 +5,7 @@ edition = "2024" license = "MIT OR Apache-2.0" [dependencies] +allocator-api2 = "0.4.0" cxx = "1.0.194" oneapi-rs-sys = { path = "../oneapi-rs-sys" } thiserror = "2.0.18" diff --git a/oneapi-rs/src/allocator.rs b/oneapi-rs/src/allocator.rs deleted file mode 100644 index cfa2880..0000000 --- a/oneapi-rs/src/allocator.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::{alloc::Layout, ptr::NonNull}; -use thiserror::Error; - -/// A copy of the unstable [`Allocator`](std::alloc::Allocator) trait. -/// This module will become unnecessary when the [`Allocator`](std::alloc::Allocator) trait gets stabilized. - -#[derive(Error, Debug)] -pub enum AllocError { - #[error("the device used does not support USM allocation")] - FeatureNotSupported, - #[error("the device used does not correspond to any SYCL context")] - Invalid, - #[error("there's not enough memory to allocate")] - NoMemory, - #[error("other error")] - Other(String) -} - -pub unsafe trait Allocator { - fn allocate(&self, layout: Layout) -> Result, AllocError>; - unsafe fn deallocate(&self, ptr: NonNull, layout: Layout); -} diff --git a/oneapi-rs/src/lib.rs b/oneapi-rs/src/lib.rs index 4c59119..a59adf5 100644 --- a/oneapi-rs/src/lib.rs +++ b/oneapi-rs/src/lib.rs @@ -11,4 +11,3 @@ pub mod platform; pub mod device; pub mod queue; pub mod usm; -pub mod allocator; diff --git a/oneapi-rs/src/usm.rs b/oneapi-rs/src/usm.rs index 164d948..92e54e7 100644 --- a/oneapi-rs/src/usm.rs +++ b/oneapi-rs/src/usm.rs @@ -1,89 +1,75 @@ -use std::{alloc::Layout, ptr::NonNull}; +// +// Copyright (C) 2026 Intel Corporation +// +// Under the MIT License or the Apache License v2.0. +// See LICENSE-MIT and LICENSE-APACHE for license information. +// SPDX-License-Identifier: MIT OR Apache-2.0 +// + +use crate::queue::Queue; use oneapi_rs_sys::usm::ffi; +use allocator_api2::alloc::{Allocator, AllocError}; + +use std::{alloc::Layout, marker::PhantomData, ptr::NonNull}; -use crate::{allocator::{AllocError, Allocator}, queue::Queue}; type CxxResult = cxx::core::result::Result; -trait UsmAllocator { - unsafe fn alloc(&self, alignment: usize, bytes: usize) -> CxxResult<*mut u8>; - fn get_queue(&self) -> &Queue; +pub struct UsmAllocator<'a, T: UsmAllocatorKind> { + queue: &'a Queue, + _kind: PhantomData } -#[allow(dead_code)] -pub(crate) struct DeviceAllocator<'a> { - queue: &'a Queue +pub trait UsmAllocatorKind { + unsafe fn alloc(alignment: usize, bytes: usize, queue: &Queue) -> CxxResult<*mut u8>; } -impl<'a> From<&'a Queue> for DeviceAllocator<'a> { +impl<'a, T: UsmAllocatorKind> From<&'a Queue> for UsmAllocator<'a, T> { fn from(queue: &'a Queue) -> Self { - Self { queue } - } -} - -impl<'a> UsmAllocator for DeviceAllocator<'a> { - unsafe fn alloc(&self, alignment: usize, bytes: usize) -> CxxResult<*mut u8> { - unsafe { ffi::aligned_alloc_device(alignment, bytes, &self.queue.0) } - } - - fn get_queue(&self) -> &Queue { - &self.queue + Self { + queue, + _kind: PhantomData + } } } -pub struct HostAllocator<'a> { - queue: &'a Queue -} +unsafe impl Allocator for UsmAllocator<'_, T> { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + let ptr = unsafe { T::alloc(layout.align(), layout.size(), &self.queue) } + .map_err(|_e| AllocError)?; -impl<'a> From<&'a Queue> for HostAllocator<'a> { - fn from(queue: &'a Queue) -> Self { - Self { queue } - } -} + let ptr = NonNull::new(ptr).ok_or(AllocError)?; + let slice = NonNull::slice_from_raw_parts(ptr, layout.size()); -impl<'a> UsmAllocator for HostAllocator<'a> { - unsafe fn alloc(&self, alignment: usize, bytes: usize) -> CxxResult<*mut u8> { - unsafe { ffi::aligned_alloc_host(alignment, bytes, &self.queue.0) } + Ok(slice) } - fn get_queue(&self) -> &Queue { - &self.queue + unsafe fn deallocate(&self, ptr: NonNull, _layout: Layout) { + unsafe { ffi::free(ptr.as_ptr(), &self.queue.0); } } } -pub struct SharedAllocator<'a> { - queue: &'a Queue -} +#[allow(dead_code)] +pub(crate) struct DeviceAllocator; -impl<'a> From<&'a Queue> for SharedAllocator<'a> { - fn from(queue: &'a Queue) -> Self { - Self { queue } +impl UsmAllocatorKind for DeviceAllocator { + unsafe fn alloc(alignment: usize, bytes: usize, queue: &Queue) -> CxxResult<*mut u8> { + unsafe { ffi::aligned_alloc_device(alignment, bytes, &queue.0) } } } -impl<'a> UsmAllocator for SharedAllocator<'a> { - unsafe fn alloc(&self, alignment: usize, bytes: usize) -> CxxResult<*mut u8> { - unsafe { ffi::aligned_alloc_shared(alignment, bytes, &self.queue.0) } - } +pub struct HostAllocator; - fn get_queue(&self) -> &Queue { - &self.queue +impl UsmAllocatorKind for HostAllocator { + unsafe fn alloc(alignment: usize, bytes: usize, queue: &Queue) -> CxxResult<*mut u8> { + unsafe { ffi::aligned_alloc_host(alignment, bytes, &queue.0) } } } -unsafe impl Allocator for T -where T: UsmAllocator { - fn allocate(&self, layout: Layout) -> Result, AllocError> { - let ptr = unsafe { self.alloc(layout.align(), layout.size()) } - .map_err(|e| AllocError::Other(e.to_string()))?; +pub struct SharedAllocator; - let ptr = NonNull::new(ptr).ok_or(AllocError::NoMemory)?; - let slice = NonNull::slice_from_raw_parts(ptr, layout.size()); - - Ok(slice) - } - - unsafe fn deallocate(&self, ptr: NonNull, _layout: Layout) { - unsafe { ffi::free(ptr.as_ptr(), &self.get_queue().0); } +impl UsmAllocatorKind for SharedAllocator { + unsafe fn alloc(alignment: usize, bytes: usize, queue: &Queue) -> CxxResult<*mut u8> { + unsafe { ffi::aligned_alloc_shared(alignment, bytes, &queue.0) } } } From 2682dfa50f1b57caad52f3ac69684f56ee729711 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 14:24:02 +0000 Subject: [PATCH 15/27] Add a Buffer abstraction --- oneapi-rs/src/buffer.rs | 56 +++++++++++++++++++++++++++++++++++++++++ oneapi-rs/src/lib.rs | 1 + oneapi-rs/src/usm.rs | 4 +++ 3 files changed, 61 insertions(+) create mode 100644 oneapi-rs/src/buffer.rs diff --git a/oneapi-rs/src/buffer.rs b/oneapi-rs/src/buffer.rs new file mode 100644 index 0000000..356da80 --- /dev/null +++ b/oneapi-rs/src/buffer.rs @@ -0,0 +1,56 @@ +// +// Copyright (C) 2026 Intel Corporation +// +// Under the MIT License or the Apache License v2.0. +// See LICENSE-MIT and LICENSE-APACHE for license information. +// SPDX-License-Identifier: MIT OR Apache-2.0 +// + +use std::{alloc::{Layout, handle_alloc_error}, ops::{Deref, DerefMut}, ptr::NonNull}; + +use crate::usm::UsmAlloc; + +pub struct Buffer { + data: NonNull<[T; N]>, + layout: Layout, + allocator: A, +} + +impl Buffer { + pub(crate) fn new(allocator: A) -> Self { + let layout = Layout::new::<[T; N]>(); + let ptr = match allocator.allocate(layout.clone()) { + Ok(ptr) => ptr, + _ => handle_alloc_error(layout) + }; + + Self { + data: ptr.cast(), + layout, + allocator, + } + } +} + +impl Deref for Buffer { + type Target = [T]; + fn deref(&self) -> &Self::Target { + unsafe { + self.data.as_ref() + } + } +} + +impl DerefMut for Buffer { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { + self.data.as_mut() + } + } +} + +impl Drop for Buffer { + fn drop(&mut self) { + unsafe { self.allocator.deallocate(self.data.cast(), self.layout); } + } +} diff --git a/oneapi-rs/src/lib.rs b/oneapi-rs/src/lib.rs index a59adf5..82cd93a 100644 --- a/oneapi-rs/src/lib.rs +++ b/oneapi-rs/src/lib.rs @@ -11,3 +11,4 @@ pub mod platform; pub mod device; pub mod queue; pub mod usm; +pub mod buffer; diff --git a/oneapi-rs/src/usm.rs b/oneapi-rs/src/usm.rs index 92e54e7..d756775 100644 --- a/oneapi-rs/src/usm.rs +++ b/oneapi-rs/src/usm.rs @@ -20,6 +20,10 @@ pub struct UsmAllocator<'a, T: UsmAllocatorKind> { _kind: PhantomData } +pub trait UsmAlloc : Allocator {} + +impl<'a, T: UsmAllocatorKind> UsmAlloc for UsmAllocator<'a, T> {} + pub trait UsmAllocatorKind { unsafe fn alloc(alignment: usize, bytes: usize, queue: &Queue) -> CxxResult<*mut u8>; } From 02c5d3a90c9520b6e22883fe7739bde2669291aa Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 14:24:26 +0000 Subject: [PATCH 16/27] Add alloc shared support --- oneapi-rs/src/queue.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/oneapi-rs/src/queue.rs b/oneapi-rs/src/queue.rs index d8f4294..d085a04 100644 --- a/oneapi-rs/src/queue.rs +++ b/oneapi-rs/src/queue.rs @@ -8,7 +8,7 @@ use oneapi_rs_sys::queue::ffi; -use crate::device::Device; +use crate::{buffer::Buffer, device::Device, usm::{SharedAllocator, UsmAllocator}}; /// The `Queue` connects a host program to a single device. Programs submit tasks to a device via the /// `Queue` and may monitor the `Queue` for completion. A program initiates the task by submitting @@ -20,6 +20,11 @@ impl Queue { pub fn new() -> Self { Self(ffi::new_queue()) } + + pub fn alloc_shared(&self) -> Buffer> { + let allocator = UsmAllocator::from(self); + Buffer::new(allocator) + } } impl From<&Device> for Queue { From 6df58cc56c98ad3c79144a7b22080d5a5d9e1d52 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 14:24:39 +0000 Subject: [PATCH 17/27] Add alloc example --- oneapi-rs/examples/alloc.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 oneapi-rs/examples/alloc.rs diff --git a/oneapi-rs/examples/alloc.rs b/oneapi-rs/examples/alloc.rs new file mode 100644 index 0000000..f73e8c6 --- /dev/null +++ b/oneapi-rs/examples/alloc.rs @@ -0,0 +1,24 @@ +// +// Copyright (C) 2026 Intel Corporation +// +// Under the MIT License or the Apache License v2.0. +// See LICENSE-MIT and LICENSE-APACHE for license information. +// SPDX-License-Identifier: MIT OR Apache-2.0 +// + +use oneapi_rs::queue::Queue; + +fn main() { + let queue = Queue::new(); + let mut buffer = queue.alloc_shared::(); + + for i in 0..buffer.len() { + buffer[i] = i as u32; + } + + for e in buffer.iter() { + print!("{e} ") + } + + println!(); +} From 3d2a2d8c4cd89f0ce298718609769d2f860ac684 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 14:36:55 +0000 Subject: [PATCH 18/27] Add missing header to source list --- oneapi-rs-sys/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oneapi-rs-sys/build.rs b/oneapi-rs-sys/build.rs index ea87a54..63ef79e 100644 --- a/oneapi-rs-sys/build.rs +++ b/oneapi-rs-sys/build.rs @@ -33,7 +33,7 @@ fn main() { "include/platform.hpp", "include/device.hpp", "include/queue.hpp", - "src/usm.hpp", + "include/usm.hpp", ]; cxx_build::bridges(&rust_sources) From 53955dc219391131bb4f14a4bc22cb4d1521e9d6 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 7 Jul 2026 14:38:10 +0000 Subject: [PATCH 19/27] Add alloc host support --- oneapi-rs/src/queue.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/oneapi-rs/src/queue.rs b/oneapi-rs/src/queue.rs index d085a04..df66ef4 100644 --- a/oneapi-rs/src/queue.rs +++ b/oneapi-rs/src/queue.rs @@ -8,7 +8,7 @@ use oneapi_rs_sys::queue::ffi; -use crate::{buffer::Buffer, device::Device, usm::{SharedAllocator, UsmAllocator}}; +use crate::{buffer::Buffer, device::Device, usm::{HostAllocator, SharedAllocator, UsmAllocator}}; /// The `Queue` connects a host program to a single device. Programs submit tasks to a device via the /// `Queue` and may monitor the `Queue` for completion. A program initiates the task by submitting @@ -21,6 +21,11 @@ impl Queue { Self(ffi::new_queue()) } + pub fn alloc_host(&self) -> Buffer> { + let allocator = UsmAllocator::from(self); + Buffer::new(allocator) + } + pub fn alloc_shared(&self) -> Buffer> { let allocator = UsmAllocator::from(self); Buffer::new(allocator) From 10dc6a5b52ab66ea8e3ab5688b6682168cc30f57 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Fri, 10 Jul 2026 14:47:54 +0000 Subject: [PATCH 20/27] Determine buffer size at runtime --- oneapi-rs/examples/alloc.rs | 2 +- oneapi-rs/src/buffer.rs | 24 +++++++++++++----------- oneapi-rs/src/queue.rs | 8 ++++---- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/oneapi-rs/examples/alloc.rs b/oneapi-rs/examples/alloc.rs index f73e8c6..193e636 100644 --- a/oneapi-rs/examples/alloc.rs +++ b/oneapi-rs/examples/alloc.rs @@ -10,7 +10,7 @@ use oneapi_rs::queue::Queue; fn main() { let queue = Queue::new(); - let mut buffer = queue.alloc_shared::(); + let mut buffer = queue.alloc_shared::(10); for i in 0..buffer.len() { buffer[i] = i as u32; diff --git a/oneapi-rs/src/buffer.rs b/oneapi-rs/src/buffer.rs index 356da80..98d754c 100644 --- a/oneapi-rs/src/buffer.rs +++ b/oneapi-rs/src/buffer.rs @@ -6,19 +6,20 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 // -use std::{alloc::{Layout, handle_alloc_error}, ops::{Deref, DerefMut}, ptr::NonNull}; +use std::{alloc::{Layout, handle_alloc_error}, ops::{Deref, DerefMut}, ptr::NonNull, slice}; use crate::usm::UsmAlloc; -pub struct Buffer { - data: NonNull<[T; N]>, +pub struct Buffer { + data: NonNull, + len: usize, layout: Layout, allocator: A, } -impl Buffer { - pub(crate) fn new(allocator: A) -> Self { - let layout = Layout::new::<[T; N]>(); +impl Buffer { + pub(crate) fn new(allocator: A, len: usize) -> Self { + let layout = Layout::array::(len).unwrap(); let ptr = match allocator.allocate(layout.clone()) { Ok(ptr) => ptr, _ => handle_alloc_error(layout) @@ -26,30 +27,31 @@ impl Buffer { Self { data: ptr.cast(), + len, layout, allocator, } } } -impl Deref for Buffer { +impl Deref for Buffer { type Target = [T]; fn deref(&self) -> &Self::Target { unsafe { - self.data.as_ref() + slice::from_raw_parts(self.data.as_ptr(), self.len) } } } -impl DerefMut for Buffer { +impl DerefMut for Buffer { fn deref_mut(&mut self) -> &mut Self::Target { unsafe { - self.data.as_mut() + slice::from_raw_parts_mut(self.data.as_ptr(), self.len) } } } -impl Drop for Buffer { +impl Drop for Buffer { fn drop(&mut self) { unsafe { self.allocator.deallocate(self.data.cast(), self.layout); } } diff --git a/oneapi-rs/src/queue.rs b/oneapi-rs/src/queue.rs index df66ef4..63d7a5f 100644 --- a/oneapi-rs/src/queue.rs +++ b/oneapi-rs/src/queue.rs @@ -21,14 +21,14 @@ impl Queue { Self(ffi::new_queue()) } - pub fn alloc_host(&self) -> Buffer> { + pub fn alloc_host(&self, len: usize) -> Buffer> { let allocator = UsmAllocator::from(self); - Buffer::new(allocator) + Buffer::new(allocator, len) } - pub fn alloc_shared(&self) -> Buffer> { + pub fn alloc_shared(&self, len: usize) -> Buffer> { let allocator = UsmAllocator::from(self); - Buffer::new(allocator) + Buffer::new(allocator, len) } } From 8f106afbb0a89bd19eccdcee5a7313cbc527dd5d Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 13 Jul 2026 13:36:02 +0000 Subject: [PATCH 21/27] Mark uninitialized allocations as unsafe --- oneapi-rs/examples/alloc.rs | 2 +- oneapi-rs/src/buffer.rs | 2 +- oneapi-rs/src/queue.rs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/oneapi-rs/examples/alloc.rs b/oneapi-rs/examples/alloc.rs index 193e636..5cecde4 100644 --- a/oneapi-rs/examples/alloc.rs +++ b/oneapi-rs/examples/alloc.rs @@ -10,7 +10,7 @@ use oneapi_rs::queue::Queue; fn main() { let queue = Queue::new(); - let mut buffer = queue.alloc_shared::(10); + let mut buffer = unsafe { queue.alloc_uninit_shared::(10) }; for i in 0..buffer.len() { buffer[i] = i as u32; diff --git a/oneapi-rs/src/buffer.rs b/oneapi-rs/src/buffer.rs index 98d754c..7736984 100644 --- a/oneapi-rs/src/buffer.rs +++ b/oneapi-rs/src/buffer.rs @@ -18,7 +18,7 @@ pub struct Buffer { } impl Buffer { - pub(crate) fn new(allocator: A, len: usize) -> Self { + pub(crate) unsafe fn new(allocator: A, len: usize) -> Self { let layout = Layout::array::(len).unwrap(); let ptr = match allocator.allocate(layout.clone()) { Ok(ptr) => ptr, diff --git a/oneapi-rs/src/queue.rs b/oneapi-rs/src/queue.rs index 63d7a5f..36b8a55 100644 --- a/oneapi-rs/src/queue.rs +++ b/oneapi-rs/src/queue.rs @@ -21,14 +21,14 @@ impl Queue { Self(ffi::new_queue()) } - pub fn alloc_host(&self, len: usize) -> Buffer> { + pub unsafe fn alloc_uninit_host(&self, len: usize) -> Buffer> { let allocator = UsmAllocator::from(self); - Buffer::new(allocator, len) + unsafe { Buffer::new(allocator, len) } } - pub fn alloc_shared(&self, len: usize) -> Buffer> { + pub unsafe fn alloc_uninit_shared(&self, len: usize) -> Buffer> { let allocator = UsmAllocator::from(self); - Buffer::new(allocator, len) + unsafe { Buffer::new(allocator, len) } } } From c45267a1321e14be6721b01cd279bd6f4b03851f Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 13 Jul 2026 14:18:21 +0000 Subject: [PATCH 22/27] Add Buffer documentation --- oneapi-rs/src/buffer.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/oneapi-rs/src/buffer.rs b/oneapi-rs/src/buffer.rs index 7736984..6bff96b 100644 --- a/oneapi-rs/src/buffer.rs +++ b/oneapi-rs/src/buffer.rs @@ -10,6 +10,18 @@ use std::{alloc::{Layout, handle_alloc_error}, ops::{Deref, DerefMut}, ptr::NonN use crate::usm::UsmAlloc; +/// The Buffer struct defines a shared array of one, two or three dimensions that can be used +/// by the SYCL kernel. Buffers are templated on the type of their data, and the number of +/// dimensions that the data is stored and accessed through. + +/// A Buffer does not map to only one underlying backend object, and all SYCL backend memory objects +/// may be temporary for use on a specific device. + +/// Buffers can be constructed by methods provided by the [`Queue`](`crate::queue::Queue`) class. + +/// The Buffer struct template takes a template parameter [`UsmAlloc`](`crate::usm::UsmAlloc`) for +/// specifying an allocator which is used by the SYCL runtime when allocating temporary memory on +/// the host. pub struct Buffer { data: NonNull, len: usize, @@ -18,6 +30,8 @@ pub struct Buffer { } impl Buffer { + /// Creates a new buffer given an allocator. + /// Safety: returns uninitialized memory. pub(crate) unsafe fn new(allocator: A, len: usize) -> Self { let layout = Layout::array::(len).unwrap(); let ptr = match allocator.allocate(layout.clone()) { From 2e0b61fccdacdce77019dd53b42970af36b31669 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 13 Jul 2026 14:27:58 +0000 Subject: [PATCH 23/27] Add USM documentation --- oneapi-rs/src/usm.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/oneapi-rs/src/usm.rs b/oneapi-rs/src/usm.rs index d756775..d78ef2d 100644 --- a/oneapi-rs/src/usm.rs +++ b/oneapi-rs/src/usm.rs @@ -15,11 +15,13 @@ use std::{alloc::Layout, marker::PhantomData, ptr::NonNull}; type CxxResult = cxx::core::result::Result; +/// An instance of a USM allocator. pub struct UsmAllocator<'a, T: UsmAllocatorKind> { queue: &'a Queue, _kind: PhantomData } +/// A marker trait for USM allocators. pub trait UsmAlloc : Allocator {} impl<'a, T: UsmAllocatorKind> UsmAlloc for UsmAllocator<'a, T> {} @@ -53,6 +55,8 @@ unsafe impl Allocator for UsmAllocator<'_, T> { } } +/// An allocator for Device-side buffers +/// Safety: memory allocated by this allocator cannot be accessed on the host side #[allow(dead_code)] pub(crate) struct DeviceAllocator; @@ -62,6 +66,7 @@ impl UsmAllocatorKind for DeviceAllocator { } } +/// An allocator for Host-side buffers pub struct HostAllocator; impl UsmAllocatorKind for HostAllocator { @@ -70,6 +75,7 @@ impl UsmAllocatorKind for HostAllocator { } } +/// An allocator for shared memory buffers pub struct SharedAllocator; impl UsmAllocatorKind for SharedAllocator { From 409e687df3cf68b2955606bf55486a8fabb9e105 Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 13 Jul 2026 14:30:05 +0000 Subject: [PATCH 24/27] Add Queue::alloc_uninit_* documentation --- oneapi-rs/src/queue.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/oneapi-rs/src/queue.rs b/oneapi-rs/src/queue.rs index 36b8a55..cb236a4 100644 --- a/oneapi-rs/src/queue.rs +++ b/oneapi-rs/src/queue.rs @@ -21,11 +21,17 @@ impl Queue { Self(ffi::new_queue()) } + /// Allocates memory and creates a host-side [`Buffer`](crate::buffer::Buffer) that can store + /// an array of T. + /// Safety: the buffer contents are uninitialized. pub unsafe fn alloc_uninit_host(&self, len: usize) -> Buffer> { let allocator = UsmAllocator::from(self); unsafe { Buffer::new(allocator, len) } } + /// Allocates memory and creates a shared [`Buffer`](crate::buffer::Buffer) that can store + /// an array of T. + /// Safety: the buffer contents are uninitialized. pub unsafe fn alloc_uninit_shared(&self, len: usize) -> Buffer> { let allocator = UsmAllocator::from(self); unsafe { Buffer::new(allocator, len) } From f8f78c1f4ab00d02aec90809e1976073b78e160c Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 13 Jul 2026 14:33:03 +0000 Subject: [PATCH 25/27] Mark UsmAlloc as an unsafe trait --- oneapi-rs/src/usm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oneapi-rs/src/usm.rs b/oneapi-rs/src/usm.rs index d78ef2d..e5d64bd 100644 --- a/oneapi-rs/src/usm.rs +++ b/oneapi-rs/src/usm.rs @@ -22,9 +22,9 @@ pub struct UsmAllocator<'a, T: UsmAllocatorKind> { } /// A marker trait for USM allocators. -pub trait UsmAlloc : Allocator {} +pub unsafe trait UsmAlloc : Allocator {} -impl<'a, T: UsmAllocatorKind> UsmAlloc for UsmAllocator<'a, T> {} +unsafe impl<'a, T: UsmAllocatorKind> UsmAlloc for UsmAllocator<'a, T> {} pub trait UsmAllocatorKind { unsafe fn alloc(alignment: usize, bytes: usize, queue: &Queue) -> CxxResult<*mut u8>; From a1ae562b7225270496d39eafb77ef056de23b20f Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Mon, 13 Jul 2026 15:24:40 +0000 Subject: [PATCH 26/27] Fix doc formatting --- oneapi-rs/src/queue.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/oneapi-rs/src/queue.rs b/oneapi-rs/src/queue.rs index cb236a4..d1000e9 100644 --- a/oneapi-rs/src/queue.rs +++ b/oneapi-rs/src/queue.rs @@ -21,16 +21,14 @@ impl Queue { Self(ffi::new_queue()) } - /// Allocates memory and creates a host-side [`Buffer`](crate::buffer::Buffer) that can store - /// an array of T. + /// Allocates memory and creates a host-side [`Buffer`] that can store an array of T. /// Safety: the buffer contents are uninitialized. pub unsafe fn alloc_uninit_host(&self, len: usize) -> Buffer> { let allocator = UsmAllocator::from(self); unsafe { Buffer::new(allocator, len) } } - /// Allocates memory and creates a shared [`Buffer`](crate::buffer::Buffer) that can store - /// an array of T. + /// Allocates memory and creates a shared [`Buffer`] that can store an array of T. /// Safety: the buffer contents are uninitialized. pub unsafe fn alloc_uninit_shared(&self, len: usize) -> Buffer> { let allocator = UsmAllocator::from(self); From 693bfafbe3ada1bf31cdb1b3e890177cb21ec53d Mon Sep 17 00:00:00 2001 From: Szymon Zadworny Date: Tue, 14 Jul 2026 08:54:35 +0000 Subject: [PATCH 27/27] Style fixes --- oneapi-rs-sys/include/usm.hpp | 6 +++--- oneapi-rs-sys/src/usm-sys.rs | 6 +++--- oneapi-rs-sys/src/usm.cpp | 12 ++++++------ oneapi-rs/src/buffer.rs | 6 +++--- oneapi-rs/src/usm.rs | 14 +++++++------- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/oneapi-rs-sys/include/usm.hpp b/oneapi-rs-sys/include/usm.hpp index af5085b..d946121 100644 --- a/oneapi-rs-sys/include/usm.hpp +++ b/oneapi-rs-sys/include/usm.hpp @@ -14,8 +14,8 @@ #include namespace sycl_shims::usm { -std::uint8_t* aligned_alloc_device(std::size_t alignment, std::size_t bytes, Queue const &); -std::uint8_t* aligned_alloc_host(std::size_t alignment, std::size_t bytes, Queue const &); -std::uint8_t* aligned_alloc_shared(std::size_t alignment, std::size_t bytes, Queue const &); +std::uint8_t* aligned_alloc_device(std::size_t alignment, std::size_t num_bytes, Queue const &); +std::uint8_t* aligned_alloc_host(std::size_t alignment, std::size_t num_bytes, Queue const &); +std::uint8_t* aligned_alloc_shared(std::size_t alignment, std::size_t num_bytes, Queue const &); void free(std::uint8_t*, Queue const &); } // namespace sycl_shims::usm diff --git a/oneapi-rs-sys/src/usm-sys.rs b/oneapi-rs-sys/src/usm-sys.rs index 7324e40..2f6cb51 100644 --- a/oneapi-rs-sys/src/usm-sys.rs +++ b/oneapi-rs-sys/src/usm-sys.rs @@ -15,9 +15,9 @@ pub mod ffi { extern "C++" { include!("oneapi-rs-sys/include/usm.hpp"); - unsafe fn aligned_alloc_device(alignment: usize, bytes: usize, queue: &Queue) -> Result<*mut u8>; - unsafe fn aligned_alloc_host(alignment: usize, bytes: usize, queue: &Queue) -> Result<*mut u8>; - unsafe fn aligned_alloc_shared(alignment: usize, bytes: usize, queue: &Queue) -> Result<*mut u8>; + unsafe fn aligned_alloc_device(alignment: usize, num_bytes: usize, queue: &Queue) -> Result<*mut u8>; + unsafe fn aligned_alloc_host(alignment: usize, num_bytes: usize, queue: &Queue) -> Result<*mut u8>; + unsafe fn aligned_alloc_shared(alignment: usize, num_bytes: usize, queue: &Queue) -> Result<*mut u8>; unsafe fn free(ptr: *mut u8, queue: &Queue); } } diff --git a/oneapi-rs-sys/src/usm.cpp b/oneapi-rs-sys/src/usm.cpp index 22f09c1..9004fa7 100644 --- a/oneapi-rs-sys/src/usm.cpp +++ b/oneapi-rs-sys/src/usm.cpp @@ -10,16 +10,16 @@ #include "oneapi-rs-sys/src/usm-sys.rs.h" namespace sycl_shims::usm { -std::uint8_t* aligned_alloc_device(std::size_t alignment, std::size_t bytes, Queue const & queue) { - return static_cast(sycl::aligned_alloc_device(alignment, bytes, queue)); +std::uint8_t* aligned_alloc_device(std::size_t alignment, std::size_t num_bytes, Queue const & queue) { + return static_cast(sycl::aligned_alloc_device(alignment, num_bytes, queue)); } -std::uint8_t* aligned_alloc_host(std::size_t alignment, std::size_t bytes, Queue const & queue) { - return static_cast(sycl::aligned_alloc_host(alignment, bytes, queue)); +std::uint8_t* aligned_alloc_host(std::size_t alignment, std::size_t num_bytes, Queue const & queue) { + return static_cast(sycl::aligned_alloc_host(alignment, num_bytes, queue)); } -std::uint8_t* aligned_alloc_shared(std::size_t alignment, std::size_t bytes, Queue const & queue) { - return static_cast(sycl::aligned_alloc_shared(alignment, bytes, queue)); +std::uint8_t* aligned_alloc_shared(std::size_t alignment, std::size_t num_bytes, Queue const & queue) { + return static_cast(sycl::aligned_alloc_shared(alignment, num_bytes, queue)); } void free(std::uint8_t* memory, Queue const & queue) { diff --git a/oneapi-rs/src/buffer.rs b/oneapi-rs/src/buffer.rs index 6bff96b..c174815 100644 --- a/oneapi-rs/src/buffer.rs +++ b/oneapi-rs/src/buffer.rs @@ -13,12 +13,12 @@ use crate::usm::UsmAlloc; /// The Buffer struct defines a shared array of one, two or three dimensions that can be used /// by the SYCL kernel. Buffers are templated on the type of their data, and the number of /// dimensions that the data is stored and accessed through. - +/// /// A Buffer does not map to only one underlying backend object, and all SYCL backend memory objects /// may be temporary for use on a specific device. - +/// /// Buffers can be constructed by methods provided by the [`Queue`](`crate::queue::Queue`) class. - +/// /// The Buffer struct template takes a template parameter [`UsmAlloc`](`crate::usm::UsmAlloc`) for /// specifying an allocator which is used by the SYCL runtime when allocating temporary memory on /// the host. diff --git a/oneapi-rs/src/usm.rs b/oneapi-rs/src/usm.rs index e5d64bd..a4d0060 100644 --- a/oneapi-rs/src/usm.rs +++ b/oneapi-rs/src/usm.rs @@ -27,7 +27,7 @@ pub unsafe trait UsmAlloc : Allocator {} unsafe impl<'a, T: UsmAllocatorKind> UsmAlloc for UsmAllocator<'a, T> {} pub trait UsmAllocatorKind { - unsafe fn alloc(alignment: usize, bytes: usize, queue: &Queue) -> CxxResult<*mut u8>; + unsafe fn alloc(alignment: usize, num_bytes: usize, queue: &Queue) -> CxxResult<*mut u8>; } impl<'a, T: UsmAllocatorKind> From<&'a Queue> for UsmAllocator<'a, T> { @@ -61,8 +61,8 @@ unsafe impl Allocator for UsmAllocator<'_, T> { pub(crate) struct DeviceAllocator; impl UsmAllocatorKind for DeviceAllocator { - unsafe fn alloc(alignment: usize, bytes: usize, queue: &Queue) -> CxxResult<*mut u8> { - unsafe { ffi::aligned_alloc_device(alignment, bytes, &queue.0) } + unsafe fn alloc(alignment: usize, num_bytes: usize, queue: &Queue) -> CxxResult<*mut u8> { + unsafe { ffi::aligned_alloc_device(alignment, num_bytes, &queue.0) } } } @@ -70,8 +70,8 @@ impl UsmAllocatorKind for DeviceAllocator { pub struct HostAllocator; impl UsmAllocatorKind for HostAllocator { - unsafe fn alloc(alignment: usize, bytes: usize, queue: &Queue) -> CxxResult<*mut u8> { - unsafe { ffi::aligned_alloc_host(alignment, bytes, &queue.0) } + unsafe fn alloc(alignment: usize, num_bytes: usize, queue: &Queue) -> CxxResult<*mut u8> { + unsafe { ffi::aligned_alloc_host(alignment, num_bytes, &queue.0) } } } @@ -79,7 +79,7 @@ impl UsmAllocatorKind for HostAllocator { pub struct SharedAllocator; impl UsmAllocatorKind for SharedAllocator { - unsafe fn alloc(alignment: usize, bytes: usize, queue: &Queue) -> CxxResult<*mut u8> { - unsafe { ffi::aligned_alloc_shared(alignment, bytes, &queue.0) } + unsafe fn alloc(alignment: usize, num_bytes: usize, queue: &Queue) -> CxxResult<*mut u8> { + unsafe { ffi::aligned_alloc_shared(alignment, num_bytes, &queue.0) } } }