1use std::marker::PhantomData;
2
3use cubecl::prelude::*;
4use cubecl_core::{self as cubecl, ir::VectorSize, prelude::barrier::Barrier, unexpanded};
5
6use crate::tensor::{
7 ViewOperations, ViewOperationsExpand, ViewOperationsMut, ViewOperationsMutExpand, VirtualView,
8 VirtualViewMut,
9 layout::{Coordinates, Layout, VirtualLayout, VirtualLayoutExpand, slice::SliceLayout},
10};
11
12#[derive(Clone, Copy)]
16pub struct View<'a, E: CubePrimitive, C: Coordinates> {
17 _layout: PhantomData<C>,
18 _ty: PhantomData<E>,
19 _lifetime: PhantomData<&'a ()>,
20}
21
22#[derive(Clone, Copy)]
24pub struct ViewExpand<'a, E: CubePrimitive, C: Coordinates> {
25 pub(super) inner: &'a (dyn ViewOperationsExpand<E, C> + 'a),
26}
27
28#[derive(Clone, Copy)]
32pub struct ViewMut<'a, E: CubePrimitive, C: Coordinates> {
33 _layout: PhantomData<C>,
34 _ty: PhantomData<E>,
35 _lifetime: PhantomData<&'a mut ()>,
36}
37
38#[derive(Clone, Copy)]
40pub struct ViewMutExpand<'a, E: CubePrimitive, C: Coordinates> {
41 pub(super) inner: &'a (dyn ViewOperationsMutExpand<E, C> + 'a),
42}
43
44macro_rules! impl_cube_type {
45 ($ty: ident, $expand: ident) => {
46 impl<'a, E: CubePrimitive, C: Coordinates + 'a> CubeType for $ty<'a, E, C> {
47 type ExpandType = $expand<'a, E, C>;
48 }
49
50 impl<'a, E: CubePrimitive, C: Coordinates> IntoExpand for $expand<'a, E, C> {
51 type Expand = $expand<'a, E, C>;
52
53 fn into_expand(self, _: &Scope) -> Self::Expand {
54 self
55 }
56 }
57
58 impl<'a, E: CubePrimitive, C: Coordinates> ExpandTypeClone for $expand<'a, E, C> {
59 fn clone_unchecked(&self) -> Self {
60 self.clone()
61 }
62 }
63
64 impl<'a, E: CubePrimitive, C: Coordinates> IntoMut for $expand<'a, E, C> {
65 fn into_mut(self, _scope: &Scope) -> Self {
66 self
67 }
68 }
69
70 impl<'a, E: CubePrimitive, C: Coordinates> CubeDebug for $expand<'a, E, C> {}
71
72 impl<'a, E: CubePrimitive, C: Coordinates> AsRefExpand for $expand<'a, E, C> {
73 fn __expand_ref_method(&self, _: &Scope) -> &Self {
74 self
75 }
76 }
77 impl<'a, E: CubePrimitive, C: Coordinates> AsMutExpand for $expand<'a, E, C> {
78 fn __expand_ref_mut_method(&mut self, _: &Scope) -> &mut Self {
79 self
80 }
81 }
82 impl<'a, E: CubePrimitive, C: Coordinates> DerefExpand for $expand<'a, E, C> {
83 type Target = Self;
84
85 fn __expand_deref_method(&self, _: &Scope) -> Self::Target {
86 self.clone()
87 }
88 }
89 };
90}
91
92impl_cube_type!(View, ViewExpand);
93impl_cube_type!(ViewMut, ViewMutExpand);
94
95impl<'a, E: CubePrimitive, C: Coordinates + 'a> View<'a, E, C> {
96 #[allow(unused_variables)]
99 pub fn new<V: ViewOperations<E, S> + 'a, S: Coordinates>(
100 view: V,
101 layout: impl Into<VirtualLayout<C, S>>,
102 ) -> Self {
103 View {
104 _layout: PhantomData,
105 _ty: PhantomData,
106 _lifetime: PhantomData,
107 }
108 }
109
110 pub fn __expand_new<V: ViewOperations<E, S> + 'a, S: Coordinates + 'a>(
112 scope: &Scope,
113 view: V::ExpandType,
114 layout: VirtualLayoutExpand<C, S>,
115 ) -> ViewExpand<'a, E, C> {
116 ViewExpand::new(
117 scope,
118 VirtualView::<E, C, S, V>::__expand_new(scope, view, layout),
119 )
120 }
121}
122
123impl<'a, E: CubePrimitive, C: Coordinates + 'a> ViewMut<'a, E, C> {
124 #[allow(unused_variables)]
127 pub fn new<V: ViewOperationsMut<E, S> + 'a, S: Coordinates>(
128 view: V,
129 layout: impl Into<VirtualLayout<C, S>>,
130 ) -> Self {
131 ViewMut {
132 _layout: PhantomData,
133 _ty: PhantomData,
134 _lifetime: PhantomData,
135 }
136 }
137
138 pub fn __expand_new<V: ViewOperationsMut<E, S> + 'a, S: Coordinates + 'a>(
140 scope: &Scope,
141 view: V::ExpandType,
142 layout: VirtualLayoutExpand<C, S>,
143 ) -> ViewMutExpand<'a, E, C> {
144 ViewMutExpand::new(
145 scope,
146 VirtualViewMut::<E, C, S, V>::__expand_new(scope, view, layout),
147 )
148 }
149}
150
151macro_rules! impl_read {
152 ($ty: ident, $expand: ident) => {
153 impl<'a, E: CubePrimitive, C: Coordinates + 'a> $ty<'a, E, C> {
154 pub fn view<T: Coordinates + 'a>(
155 self,
156 _layout: impl Into<VirtualLayout<T, C>>,
157 ) -> $ty<'a, E, T> {
158 unexpanded!()
159 }
160
161 pub fn __expand_view<T: Coordinates + 'a>(
162 scope: &Scope,
163 this: $expand<'a, E, C>,
164 layout: VirtualLayoutExpand<T, C>,
165 ) -> $expand<'a, E, T> {
166 this.__expand_view_method(scope, layout)
167 }
168 }
169
170 impl<'a, E: CubePrimitive, C: Coordinates + 'a> $expand<'a, E, C> {
171 pub fn __expand_view_method<T: Coordinates + 'a>(
172 self,
173 scope: &Scope,
174 layout: VirtualLayoutExpand<T, C>,
175 ) -> $expand<'a, E, T> {
176 $ty::__expand_new::<$ty<'a, E, C>, C>(scope, self, layout)
177 }
178 }
179
180 #[cube]
181 impl<'a, E: CubePrimitive, C: Coordinates> $ty<'a, E, C> {
182 pub fn shape(&self) -> C {
184 intrinsic!(|scope| self.inner.__expand_shape_method(scope))
185 }
186
187 #[allow(unused_variables)]
189 pub fn is_in_bounds(&self, pos: C) -> bool {
190 intrinsic!(|scope| self.inner.__expand_is_in_bounds_method(scope, pos))
191 }
192 }
193
194 #[cube]
195 impl<'a, E: CubePrimitive, C: Coordinates> $ty<'a, E, C> {
196 #[allow(unused_variables)]
198 pub fn read(&self, pos: C) -> E {
199 intrinsic!(|scope| self.inner.__expand_read_method(scope, pos))
200 }
201
202 #[allow(unused_variables)]
205 pub fn read_unchecked(&self, pos: C) -> E {
206 intrinsic!(|scope| self.inner.__expand_read_unchecked_method(scope, pos))
207 }
208
209 #[allow(unused_variables)]
211 pub fn read_checked(&self, pos: C) -> E {
212 intrinsic!(|scope| self.inner.__expand_read_checked_method(scope, pos))
213 }
214
215 #[allow(unused_variables)]
217 pub fn read_masked(&self, pos: C, mask_value: E) -> E {
218 intrinsic!(|scope| self
219 .inner
220 .__expand_read_masked_method(scope, pos, mask_value))
221 }
222
223 pub fn as_linear_slice(&self) -> &'a [E] {
229 intrinsic!(|scope| {
230 let shape = self.inner.__expand_shape_method(scope);
231 let origin = C::__expand_from_int(scope, shape.clone_unchecked(), 0);
232 let one = C::__expand_from_int(scope, shape.clone_unchecked(), 1);
234 let shape = C::__expand_max(scope, shape, one.clone_unchecked());
235 let end = C::__expand_sub(scope, shape, one);
236 let slice = self
237 .inner
238 .__expand_as_linear_slice_method(scope, origin, end);
239 scope.create_kernel_ref(slice.expand.into())
240 })
241 }
242
243 pub fn vector_size(&self) -> comptime_type!(VectorSize) {
244 intrinsic!(|scope| self.inner.vector_size())
245 }
246 }
247
248 impl<'a, E: CubePrimitive, C: Coordinates> $expand<'a, E, C> {
249 pub(super) fn __expand_as_linear_slice_inner_method(
250 &self,
251 scope: &Scope,
252 pos: C::ExpandType,
253 end: C::ExpandType,
254 ) -> &SliceExpand<E> {
255 self.inner.__expand_as_linear_slice_method(scope, pos, end)
256 }
257 }
258
259 #[cube]
260 impl<'a, E: CubePrimitive, C: Coordinates + 'static> $ty<'a, E, C> {
261 #[allow(unused_variables)]
265 pub fn slice(self, pos: C, size: C) -> $ty<'a, E, C> {
266 intrinsic!(|scope| self.slice(scope, pos, size, true))
267 }
268
269 #[allow(unused_variables)]
275 pub fn slice_unchecked(self, pos: C, size: C) -> $ty<'a, E, C> {
276 intrinsic!(|scope| self.slice(scope, pos, size, false))
277 }
278 }
279
280 impl<'a, E: CubePrimitive, C: Coordinates + 'static> $expand<'a, E, C> {
281 fn slice(
282 self,
283 scope: &Scope,
284 pos: C::ExpandType,
285 size: C::ExpandType,
286 checked: bool,
287 ) -> $expand<'a, E, C> {
288 let shape = self.__expand_shape_method(scope);
289 let pos = C::__expand_min(scope, pos, shape.clone_unchecked());
290 let max_size = C::__expand_sub(scope, shape, pos.clone_unchecked());
291 let size = C::__expand_min(scope, size, max_size);
292 let layout = SliceLayout::__expand_new(scope, pos, size, checked);
293 $ty::__expand_new::<$ty<'a, E, C>, _>(scope, self, layout.into())
294 }
295 }
296
297 #[cube]
298 impl<'a, E: CubePrimitive, C: Coordinates + 'a> $ty<'a, E, C> {
299 #[allow(unused_variables)]
302 pub fn tensor_map_load(&self, barrier: &Barrier, shared_memory: &mut [E], pos: C) {
303 intrinsic!(|scope| {
304 self.inner
305 .__expand_tensor_map_load_method(scope, barrier, shared_memory, pos)
306 })
307 }
308 }
309 };
310}
311
312impl_read!(View, ViewExpand);
313impl_read!(ViewMut, ViewMutExpand);
314
315impl<'a, E: CubePrimitive, C: Coordinates + 'a> ViewMut<'a, E, C> {
316 #[allow(unused_variables)]
319 pub fn as_read(self) -> View<'a, E, C> {
320 unexpanded!()
321 }
322
323 pub fn __expand_as_read(scope: &Scope, this: ViewMutExpand<'a, E, C>) -> ViewExpand<'a, E, C> {
324 this.__expand_as_read_method(scope)
325 }
326}
327
328impl<'a, E: CubePrimitive, C: Coordinates + 'a> ViewMutExpand<'a, E, C> {
329 pub fn __expand_as_read_method(self, _scope: &Scope) -> ViewExpand<'a, E, C> {
330 let inner: &'a (dyn ViewOperationsExpand<E, C> + 'a) = self.inner;
331 ViewExpand { inner }
332 }
333}
334
335impl<'a, E: CubePrimitive, C: Coordinates> ViewExpand<'a, E, C> {
336 pub fn new<V: ViewOperationsExpand<E, C> + 'a>(scope: &Scope, view: V) -> Self {
337 let inner: &dyn ViewOperationsExpand<E, C> = scope.create_kernel_ref(view);
338 ViewExpand { inner }
339 }
340}
341
342impl<'a, E: CubePrimitive, C: Coordinates> ViewMutExpand<'a, E, C> {
343 pub fn new<V: ViewOperationsMutExpand<E, C> + 'a>(scope: &Scope, view: V) -> Self {
344 let inner: &mut dyn ViewOperationsMutExpand<E, C> = scope.create_kernel_ref(view);
345 ViewMutExpand { inner }
346 }
347}
348
349impl<'a, E: CubePrimitive, C: Coordinates + 'a> ViewMut<'a, E, C> {
350 pub fn view_mut<'b, T: Coordinates + 'a>(
351 self,
352 _layout: impl Layout<Coordinates = T, SourceCoordinates = C>,
353 ) -> ViewMut<'b, E, T>
354 where
355 'a: 'b,
356 {
357 unexpanded!()
358 }
359
360 pub fn __expand_view_mut<T: Coordinates + 'a>(
361 scope: &Scope,
362 this: ViewMutExpand<'a, E, C>,
363 layout: VirtualLayoutExpand<T, C>,
364 ) -> ViewMutExpand<'a, E, T> {
365 this.__expand_view_mut_method(scope, layout)
366 }
367}
368
369impl<'a, E: CubePrimitive, C: Coordinates + 'a> ViewMutExpand<'a, E, C> {
370 pub fn __expand_view_mut_method<'b, T: Coordinates + 'a>(
371 self,
372 scope: &Scope,
373 layout: VirtualLayoutExpand<T, C>,
374 ) -> ViewMutExpand<'b, E, T>
375 where
376 'a: 'b,
377 {
378 ViewMut::__expand_new::<ViewMut<'a, E, C>, C>(scope, self, layout)
379 }
380}
381
382#[cube]
383impl<'a, E: CubePrimitive, C: Coordinates> ViewMut<'a, E, C> {
384 #[allow(unused_variables)]
386 pub fn write(&mut self, pos: C, value: E) {
387 intrinsic!(|scope| self.inner.__expand_write_method(scope, pos, value));
388 }
389
390 #[allow(unused_variables)]
392 pub fn write_checked(&mut self, pos: C, value: E) {
393 intrinsic!(|scope| self.inner.__expand_write_checked_method(scope, pos, value));
394 }
395
396 pub fn as_linear_slice_mut(&mut self) -> &'a mut [E] {
402 intrinsic!(|scope| {
403 let shape = self.inner.__expand_shape_method(scope);
404 let origin = C::__expand_from_int(scope, shape.clone_unchecked(), 0);
405 let one = C::__expand_from_int(scope, shape.clone_unchecked(), 1);
407 let shape = C::__expand_max(scope, shape, one.clone_unchecked());
408 let end = C::__expand_sub(scope, shape, one);
409 let slice = self
410 .inner
411 .__expand_as_linear_slice_mut_method(scope, origin, end);
412 scope.create_kernel_ref(slice.expand.into())
413 })
414 }
415}
416
417impl<'a, E: CubePrimitive, C: Coordinates> ViewMutExpand<'a, E, C> {
418 pub(super) fn __expand_to_linear_slice_mut_inner_method(
419 &mut self,
420 scope: &Scope,
421 pos: C::ExpandType,
422 end: C::ExpandType,
423 ) -> &mut SliceExpand<E> {
424 self.inner
425 .__expand_as_linear_slice_mut_method(scope, pos, end)
426 }
427}
428
429#[cube]
430impl<'a, E: CubePrimitive, C: Coordinates + 'static> ViewMut<'a, E, C> {
431 #[allow(unused_variables)]
435 pub fn slice_mut(self, pos: C, size: C) -> ViewMut<'a, E, C> {
436 intrinsic!(|scope| self.slice_mut(scope, pos, size, true))
437 }
438
439 #[allow(unused_variables)]
446 pub fn slice_mut_unchecked(self, pos: C, size: C) -> ViewMut<'a, E, C> {
447 intrinsic!(|scope| self.slice_mut(scope, pos, size, false))
448 }
449}
450
451impl<'a, E: CubePrimitive, C: Coordinates + 'static> ViewMutExpand<'a, E, C> {
452 fn slice_mut(
453 &self,
454 scope: &Scope,
455 pos: C::ExpandType,
456 size: C::ExpandType,
457 checked: bool,
458 ) -> ViewMutExpand<'a, E, C> {
459 let shape = self.__expand_shape_method(scope);
460 let pos = C::__expand_min(scope, pos, shape.clone_unchecked());
461 let max_size = C::__expand_sub(scope, shape, pos.clone_unchecked());
462 let size = C::__expand_min(scope, size, max_size);
463 let layout = SliceLayout::__expand_new(scope, pos, size, checked);
464 self.clone().__expand_view_mut_method(scope, layout.into())
465 }
466}
467
468#[cube]
469impl<'a, E: CubePrimitive, C: Coordinates> ViewMut<'a, E, C> {
470 #[allow(unused_variables)]
473 pub fn tensor_map_store(&self, shared_memory: &[E], pos: C) {
474 intrinsic!(|scope| {
475 self.inner
476 .__expand_tensor_map_store_method(scope, shared_memory, pos)
477 })
478 }
479}