1use std::cmp::min;
10
11use bytemuck::Pod;
12use oneapi_rs_sys::{queue::ffi, types::ffi::EventPtr};
13
14use crate::{
15 buffer::{
16 Buffer, DeviceBuffer, EnqueuedBuffer, EnqueuedDeviceBuffer, EnqueuedHostBuffer,
17 EnqueuedSharedBuffer, HostBuffer, SharedBuffer,
18 },
19 context::Context,
20 device::Device,
21 event::Event,
22 kernel::{Kernel, KernelArgumentList},
23 range::{NdRange, ValidDimension},
24 usm::{UsmAlloc, UsmAllocator},
25};
26
27pub struct Queue(pub(crate) cxx::UniquePtr<ffi::Queue>);
31
32impl Queue {
33 pub fn new() -> Self {
35 Self(ffi::new_queue())
36 }
37
38 pub fn new_immediate() -> Self {
40 Self(ffi::new_queue_immediate())
41 }
42
43 pub fn get_context(&self) -> Context {
45 ffi::get_context(&self.0).into()
46 }
47
48 pub fn alloc_host<T: Pod>(&mut self, len: usize) -> EnqueuedHostBuffer<T> {
50 unsafe {
51 let mut buffer = self.alloc_uninit_host(len);
52 let event = self.memset(&mut buffer, 0);
53 EnqueuedBuffer::new(buffer, event)
54 }
55 }
56
57 pub fn alloc_shared<T: Pod>(&mut self, len: usize) -> EnqueuedSharedBuffer<T> {
59 unsafe {
60 let mut buffer = self.alloc_uninit_shared(len);
61 let event = self.memset(&mut buffer, 0);
62 EnqueuedBuffer::new(buffer, event)
63 }
64 }
65
66 pub fn alloc_device<T: Pod>(&mut self, len: usize) -> EnqueuedDeviceBuffer<T> {
68 unsafe {
69 let mut buffer = self.alloc_uninit_device(len);
70 let event = self.memset(&mut buffer, 0);
71 EnqueuedBuffer::new(buffer, event)
72 }
73 }
74
75 pub unsafe fn alloc_uninit_host<T>(&self, len: usize) -> HostBuffer<T> {
78 let allocator = UsmAllocator::from(self);
79 unsafe { Buffer::new(allocator, len) }
80 }
81
82 pub unsafe fn alloc_uninit_shared<T>(&self, len: usize) -> SharedBuffer<T> {
85 let allocator = UsmAllocator::from(self);
86 unsafe { Buffer::new(allocator, len) }
87 }
88
89 pub unsafe fn alloc_uninit_device<T>(&self, len: usize) -> DeviceBuffer<T> {
92 let allocator = UsmAllocator::from(self);
93 unsafe { Buffer::new(allocator, len) }
94 }
95
96 pub unsafe fn memset<T, A: UsmAlloc>(
99 &mut self,
100 buffer: &mut Buffer<T, A>,
101 value: i32,
102 ) -> Event {
103 unsafe { self.memset_with_deps(buffer, value, &[]) }
104 }
105
106 pub unsafe fn memset_with_deps<T, A: UsmAlloc>(
109 &mut self,
110 buffer: &mut Buffer<T, A>,
111 value: i32,
112 dep_events: &[&Event],
113 ) -> Event {
114 let ptr = buffer.get_byte_ptr();
115 let num_bytes = buffer.get_byte_size();
116 let dep_events = dep_events
117 .iter()
118 .map(|e| EventPtr {
119 ptr: (*e).clone().0,
120 })
121 .collect::<Vec<_>>();
122 unsafe { ffi::memset(&mut self.0, ptr, value, num_bytes, dep_events) }.into()
123 }
124
125 pub fn barrier(&mut self) -> Event {
127 self.barrier_with_deps(&[])
128 }
129
130 pub fn barrier_with_deps(&mut self, dep_events: &[&Event]) -> Event {
132 let dep_events = dep_events
133 .iter()
134 .map(|e| EventPtr {
135 ptr: (*e).clone().0,
136 })
137 .collect::<Vec<_>>();
138 ffi::barrier(&mut self.0, dep_events).into()
139 }
140
141 pub fn wait(&mut self) {
143 ffi::wait(&mut self.0);
144 }
145
146 pub unsafe fn launch<const ARGC: usize, const DIMENSIONS: usize>(
149 &mut self,
150 nd_range: NdRange<DIMENSIONS>,
151 kernel: &Kernel,
152 args: impl KernelArgumentList<ARGC>,
153 ) -> Event
154 where
155 NdRange<DIMENSIONS>: ValidDimension,
156 {
157 unsafe { nd_range.launch(self, kernel, args) }
158 }
159
160 pub fn copy<T, A1, A2>(&mut self, src: &Buffer<T, A1>, dst: &mut Buffer<T, A2>) -> Event
165 where
166 T: Pod,
167 A1: UsmAlloc,
168 A2: UsmAlloc,
169 {
170 self.copy_with_deps(src, dst, &[])
171 }
172
173 pub fn copy_with_deps<T, A1, A2>(
179 &mut self,
180 src: &Buffer<T, A1>,
181 dst: &mut Buffer<T, A2>,
182 dep_events: &[&Event],
183 ) -> Event
184 where
185 T: Pod,
186 A1: UsmAlloc,
187 A2: UsmAlloc,
188 {
189 let dep_events = dep_events
191 .iter()
192 .map(|e| EventPtr {
193 ptr: (*e).clone().0,
194 })
195 .collect::<Vec<_>>();
196
197 let amount = min(src.get_len(), dst.get_len());
198 let num_bytes = amount * size_of::<T>();
199 unsafe {
200 ffi::memcpy(
201 &mut self.0,
202 dst.get_byte_ptr(),
203 src.get_byte_ptr(),
204 num_bytes,
205 dep_events,
206 )
207 }
208 .into()
209 }
210}
211
212impl From<&Device> for Queue {
213 fn from(value: &Device) -> Self {
214 Self(ffi::new_queue_from_device(&value.0))
215 }
216}
217
218impl From<cxx::UniquePtr<ffi::Queue>> for Queue {
219 fn from(value: cxx::UniquePtr<ffi::Queue>) -> Self {
220 Self(value)
221 }
222}
223
224impl Clone for Queue {
225 fn clone(&self) -> Self {
226 ffi::clone(&self.0).into()
227 }
228}