Skip to main content

cubecl_std/tensor/view/
launch.rs

1use cubecl_core::prelude::*;
2use std::{marker::PhantomData, ops::Deref, sync::Arc};
3
4use crate::tensor::{
5    View, ViewExpand, VirtualViewMutExpand,
6    layout::{Coordinates, Coords1d, Layout, VirtualLayoutExpand},
7    view::ViewType,
8};
9
10mod layout {
11    use core::{cell::RefCell, fmt::Debug, hash::Hash};
12
13    use alloc::rc::Rc;
14    use cubecl_core::{
15        self as cubecl,
16        format::DebugRaw,
17        hash::{StableHash, StableHasher},
18        zspace::{Shape, Strides, metadata::Metadata},
19    };
20
21    use crate::tensor::layout::LayoutExpand;
22
23    use super::*;
24
25    #[allow(clippy::len_without_is_empty)]
26    pub trait BufferArg: 'static {
27        fn len(&self) -> usize;
28        fn shape(&self) -> &[usize];
29        fn strides(&self) -> &[usize];
30    }
31
32    impl<R: Runtime> BufferArg for TensorArg<R> {
33        fn len(&self) -> usize {
34            self.size()
35        }
36
37        fn shape(&self) -> &[usize] {
38            self.shape()
39        }
40
41        fn strides(&self) -> &[usize] {
42            self.strides()
43        }
44    }
45    impl<R: Runtime> BufferArg for ArrayArg<R> {
46        fn len(&self) -> usize {
47            self.size()
48        }
49
50        fn shape(&self) -> &[usize] {
51            self.shape()
52        }
53
54        fn strides(&self) -> &[usize] {
55            &[1]
56        }
57    }
58    impl<R: Runtime, K: TensorMapKind> BufferArg for TensorMapArg<R, K> {
59        fn len(&self) -> usize {
60            self.tensor.size()
61        }
62
63        fn shape(&self) -> &[usize] {
64            self.tensor.shape()
65        }
66
67        fn strides(&self) -> &[usize] {
68            self.tensor.strides()
69        }
70    }
71
72    impl BufferArg for Metadata {
73        fn len(&self) -> usize {
74            self.shape.num_elements()
75        }
76
77        fn shape(&self) -> &[usize] {
78            &self.shape
79        }
80
81        fn strides(&self) -> &[usize] {
82            &self.strides
83        }
84    }
85
86    /// Special launch arg that gets the handle and types of the view, to allow inferring launch
87    /// state based on type/handle metadata, avoiding duplication. All `LaunchArg`s also implement
88    /// this trait.
89    pub trait ViewLayoutLaunchArg: CubeType + Send + Sync + 'static {
90        /// The runtime argument for the kernel.
91        type RuntimeArg<R: Runtime>: Send + Sync;
92        /// Compilation argument.
93        type CompilationArg: CompilationArg;
94
95        fn register<R: Runtime, B: BufferArg>(
96            arg: Self::RuntimeArg<R>,
97            buffer: &B,
98            ty: Type,
99            launcher: &mut KernelLauncher<R>,
100        ) -> Self::CompilationArg;
101
102        /// Register an input variable during compilation that fill the [`KernelBuilder`].
103        fn expand(
104            arg: &Self::CompilationArg,
105            ty: Type,
106            builder: &mut KernelBuilder,
107        ) -> <Self as CubeType>::ExpandType;
108
109        /// Register an output variable during compilation that fill the [`KernelBuilder`].
110        fn expand_output(
111            arg: &Self::CompilationArg,
112            ty: Type,
113            builder: &mut KernelBuilder,
114        ) -> <Self as CubeType>::ExpandType {
115            Self::expand(arg, ty, builder)
116        }
117    }
118
119    impl<T: LaunchArg> ViewLayoutLaunchArg for T {
120        type RuntimeArg<R: Runtime> = <T as LaunchArg>::RuntimeArg<R>;
121        type CompilationArg = <T as LaunchArg>::CompilationArg;
122
123        fn register<R: Runtime, B: BufferArg>(
124            arg: Self::RuntimeArg<R>,
125            _buffer: &B,
126            _ty: Type,
127            launcher: &mut KernelLauncher<R>,
128        ) -> Self::CompilationArg {
129            <T as LaunchArg>::register(arg, launcher)
130        }
131
132        fn expand(
133            arg: &Self::CompilationArg,
134            _ty: Type,
135            builder: &mut KernelBuilder,
136        ) -> <Self as CubeType>::ExpandType {
137            <T as LaunchArg>::expand(arg, builder)
138        }
139
140        fn expand_output(
141            arg: &Self::CompilationArg,
142            _ty: Type,
143            builder: &mut KernelBuilder,
144        ) -> <Self as CubeType>::ExpandType {
145            <T as LaunchArg>::expand_output(arg, builder)
146        }
147    }
148
149    pub struct VirtualViewLayoutLaunch<C: Coordinates, S: Coordinates, B: BufferArg, R: Runtime> {
150        _ty: core::marker::PhantomData<R>,
151        #[allow(clippy::type_complexity)]
152        register: Box<
153            dyn FnOnce(&B, Type, &mut KernelLauncher<R>) -> VirtualViewLayoutCompilationArg<C, S>
154                + Send
155                + Sync,
156        >,
157    }
158
159    impl<C: Coordinates, S: Coordinates, B: BufferArg, R: Runtime> VirtualViewLayoutLaunch<C, S, B, R> {
160        pub fn new<L: Layout<Coordinates = C, SourceCoordinates = S> + ViewLayoutLaunchArg>(
161            layout: L::RuntimeArg<R>,
162        ) -> Self {
163            Self {
164                _ty: PhantomData,
165                register: Box::new(move |buffer, ty, launcher| {
166                    let comp_arg = L::register::<R, B>(layout, buffer, ty, launcher);
167                    let comp_arg_2 = comp_arg.clone();
168                    let expand = Rc::new(RefCell::new(
169                        move |ty: Type, builder: &mut KernelBuilder, is_out: bool| {
170                            let expand = match is_out {
171                                true => L::expand_output(&comp_arg_2, ty, builder),
172                                false => L::expand(&comp_arg_2, ty, builder),
173                            };
174                            VirtualLayoutExpand::new(expand)
175                        },
176                    ));
177                    VirtualViewLayoutCompilationArg::new(comp_arg, expand)
178                }),
179            }
180        }
181
182        pub fn register(
183            self,
184            buffer: &B,
185            ty: Type,
186            launcher: &mut KernelLauncher<R>,
187        ) -> VirtualViewLayoutCompilationArg<C, S> {
188            (self.register)(buffer, ty, launcher)
189        }
190    }
191
192    type ExpandFn<C, S> =
193        Rc<RefCell<dyn FnMut(Type, &mut KernelBuilder, bool) -> VirtualLayoutExpand<C, S> + Send>>;
194
195    #[derive(Clone)]
196    pub struct VirtualViewLayoutCompilationArg<C: Coordinates, S: Coordinates> {
197        type_name: String,
198        debug: Rc<dyn core::fmt::Debug>,
199        hash: StableHash,
200        expand: ExpandFn<C, S>,
201    }
202
203    // SAFETY: The struct is readonly, so `Sync` is safe to implement
204    unsafe impl<C: Coordinates, S: Coordinates> Send for VirtualViewLayoutCompilationArg<C, S> {}
205    unsafe impl<C: Coordinates, S: Coordinates> Sync for VirtualViewLayoutCompilationArg<C, S> {}
206
207    impl<C: Coordinates, S: Coordinates> VirtualViewLayoutCompilationArg<C, S> {
208        pub fn new<L: CompilationArg + 'static>(arg: L, expand: ExpandFn<C, S>) -> Self {
209            // Hash ahead of time so we don't need to store the actual data, which would be far
210            // more complex
211            let hash = StableHasher::hash_one(&arg);
212            Self {
213                type_name: core::any::type_name::<L>().to_string(),
214                debug: Rc::new(arg),
215                hash,
216                expand,
217            }
218        }
219
220        pub fn expand(&self, ty: Type, builder: &mut KernelBuilder) -> VirtualLayoutExpand<C, S> {
221            let mut expand = self.expand.borrow_mut();
222            (expand)(ty, builder, false)
223        }
224
225        pub fn expand_output(
226            &self,
227            ty: Type,
228            builder: &mut KernelBuilder,
229        ) -> VirtualLayoutExpand<C, S> {
230            let mut expand = self.expand.borrow_mut();
231            (expand)(ty, builder, true)
232        }
233    }
234
235    impl<C: Coordinates, S: Coordinates> PartialEq for VirtualViewLayoutCompilationArg<C, S> {
236        fn eq(&self, other: &Self) -> bool {
237            self.type_name == other.type_name && self.hash == other.hash
238        }
239    }
240    impl<C: Coordinates, S: Coordinates> Eq for VirtualViewLayoutCompilationArg<C, S> {}
241
242    impl<C: Coordinates, S: Coordinates> core::hash::Hash for VirtualViewLayoutCompilationArg<C, S> {
243        fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
244            self.type_name.hash(state);
245            self.hash.hash(state);
246        }
247    }
248
249    impl<C: Coordinates, S: Coordinates> core::fmt::Debug for VirtualViewLayoutCompilationArg<C, S> {
250        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
251            f.debug_struct(stringify!(VirtualLayout))
252                .field("type", &DebugRaw(&self.type_name))
253                .field("value", &self.debug)
254                .finish()
255        }
256    }
257
258    #[derive(CubeType)]
259    pub struct ConcreteLayout<L: Layout + ViewLayoutLaunchArg> {
260        value: L,
261    }
262
263    #[cube]
264    impl<L: Layout + ViewLayoutLaunchArg> Layout for ConcreteLayout<L> {
265        type Coordinates = L::Coordinates;
266        type SourceCoordinates = L::SourceCoordinates;
267
268        fn to_source_pos(&self, pos: Self::Coordinates) -> Self::SourceCoordinates {
269            self.value.to_source_pos(pos)
270        }
271
272        fn to_source_pos_checked(&self, pos: Self::Coordinates) -> (Self::SourceCoordinates, bool) {
273            self.value.to_source_pos_checked(pos)
274        }
275
276        fn shape(&self) -> Self::Coordinates {
277            self.value.shape()
278        }
279
280        fn is_in_bounds(&self, pos: Self::Coordinates) -> bool {
281            self.value.is_in_bounds(pos)
282        }
283    }
284
285    impl<L: Layout + ViewLayoutLaunchArg> Deref for ConcreteLayout<L> {
286        type Target = L;
287
288        fn deref(&self) -> &Self::Target {
289            &self.value
290        }
291    }
292
293    impl<L: Layout + ViewLayoutLaunchArg> Deref for ConcreteLayoutExpand<L> {
294        type Target = <L as CubeType>::ExpandType;
295
296        fn deref(&self) -> &Self::Target {
297            &self.value
298        }
299    }
300
301    pub struct ConcreteLayoutLaunch<L: Layout + ViewLayoutLaunchArg, R: Runtime> {
302        meta: Metadata,
303        ty: Type,
304        value: L::RuntimeArg<R>,
305    }
306
307    impl<L: Layout + ViewLayoutLaunchArg, R: Runtime> ConcreteLayoutLaunch<L, R> {
308        pub fn new(meta: Metadata, ty: Type, value: L::RuntimeArg<R>) -> Self {
309            Self { meta, ty, value }
310        }
311
312        pub fn from_handle(handle: &TensorBinding<R>, ty: Type, value: L::RuntimeArg<R>) -> Self {
313            Self {
314                meta: Metadata {
315                    shape: handle.shape.clone(),
316                    strides: handle.strides.clone(),
317                },
318                ty,
319                value,
320            }
321        }
322
323        pub fn from_shape_strides(
324            shape: Shape,
325            strides: Strides,
326            ty: Type,
327            value: L::RuntimeArg<R>,
328        ) -> Self {
329            Self {
330                meta: Metadata { shape, strides },
331                ty,
332                value,
333            }
334        }
335    }
336
337    pub struct ConcreteLayoutCompilationArg<L: Layout + ViewLayoutLaunchArg> {
338        ty: Type,
339        value: L::CompilationArg,
340    }
341
342    impl<L: Layout + ViewLayoutLaunchArg> Debug for ConcreteLayoutCompilationArg<L> {
343        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
344            f.debug_struct("ConcreteLayoutCompilationArg")
345                .field("ty", &self.ty)
346                .field("value", &self.value)
347                .finish()
348        }
349    }
350
351    impl<L: Layout + ViewLayoutLaunchArg> Hash for ConcreteLayoutCompilationArg<L> {
352        fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
353            self.ty.hash(state);
354            self.value.hash(state);
355        }
356    }
357
358    impl<L: Layout + ViewLayoutLaunchArg> Eq for ConcreteLayoutCompilationArg<L> {}
359    impl<L: Layout + ViewLayoutLaunchArg> PartialEq for ConcreteLayoutCompilationArg<L> {
360        fn eq(&self, other: &Self) -> bool {
361            self.ty == other.ty && self.value == other.value
362        }
363    }
364
365    impl<L: Layout + ViewLayoutLaunchArg> Clone for ConcreteLayoutCompilationArg<L> {
366        fn clone(&self) -> Self {
367            Self {
368                ty: self.ty,
369                value: self.value.clone(),
370            }
371        }
372    }
373
374    impl<L: Layout + ViewLayoutLaunchArg> LaunchArg for ConcreteLayout<L> {
375        type RuntimeArg<R: Runtime> = ConcreteLayoutLaunch<L, R>;
376        type CompilationArg = ConcreteLayoutCompilationArg<L>;
377
378        fn register<R: Runtime>(
379            arg: Self::RuntimeArg<R>,
380            launcher: &mut KernelLauncher<R>,
381        ) -> Self::CompilationArg {
382            ConcreteLayoutCompilationArg {
383                value: L::register(arg.value, &arg.meta, arg.ty, launcher),
384                ty: arg.ty,
385            }
386        }
387
388        fn expand(
389            arg: &Self::CompilationArg,
390            builder: &mut KernelBuilder,
391        ) -> <Self as CubeType>::ExpandType {
392            ConcreteLayoutExpand {
393                value: L::expand(&arg.value, arg.ty, builder),
394            }
395        }
396
397        fn expand_output(
398            arg: &Self::CompilationArg,
399            builder: &mut KernelBuilder,
400        ) -> <Self as CubeType>::ExpandType {
401            ConcreteLayoutExpand {
402                value: L::expand_output(&arg.value, arg.ty, builder),
403            }
404        }
405    }
406}
407
408pub use layout::*;
409
410mod dynamic {
411    use cubecl_common::quant::scheme::QuantScheme;
412
413    use crate::{
414        quant::{
415            self,
416            view::{RegisterDynamic, run_with_quant_type},
417        },
418        tensor::{
419            VirtualViewExpand,
420            launch::layout::{ViewLayoutLaunchArg, VirtualViewLayoutLaunch},
421            layout::as_dyn::{IntoDyn, IntoDyn2Layout, IntoDynLayout},
422        },
423    };
424
425    use super::*;
426
427    #[allow(clippy::type_complexity)]
428    pub enum ViewArg<C: Coordinates, R: Runtime> {
429        Array(
430            ArrayArg<R>,
431            VirtualViewLayoutLaunch<C, Coords1d, ArrayArg<R>, R>,
432        ),
433        Tensor(
434            TensorArg<R>,
435            VirtualViewLayoutLaunch<C, Coords1d, TensorArg<R>, R>,
436        ),
437        TensorMapTiled(
438            TensorMapArg<R, Tiled>,
439            VirtualViewLayoutLaunch<C, Sequence<i32>, TensorMapArg<R, Tiled>, R>,
440        ),
441        TensorMapIm2col(
442            TensorMapArg<R, Im2col>,
443            VirtualViewLayoutLaunch<C, (Sequence<i32>, Sequence<i32>), TensorMapArg<R, Im2col>, R>,
444        ),
445        Quantized {
446            values: Box<ViewArg<C, R>>,
447            scales: Box<ViewArg<C, R>>,
448            scheme: QuantScheme,
449        },
450    }
451
452    impl<C: Coordinates, R: Runtime> ViewArg<C, R> {
453        pub fn new_array<
454            L: Layout<Coordinates = C, SourceCoordinates = Coords1d> + ViewLayoutLaunchArg,
455        >(
456            buffer: ArrayArg<R>,
457            layout: L::RuntimeArg<R>,
458        ) -> Self {
459            let layout = VirtualViewLayoutLaunch::new::<L>(layout);
460            ViewArg::Array(buffer, layout)
461        }
462
463        pub fn new_tensor<
464            L: Layout<Coordinates = C, SourceCoordinates = Coords1d> + ViewLayoutLaunchArg,
465        >(
466            buffer: TensorArg<R>,
467            layout: L::RuntimeArg<R>,
468        ) -> Self {
469            let layout = VirtualViewLayoutLaunch::new::<L>(layout);
470            ViewArg::Tensor(buffer, layout)
471        }
472
473        pub fn new_tensor_map_tiled<
474            L: Layout<Coordinates = C, SourceCoordinates: IntoDyn> + ViewLayoutLaunchArg,
475        >(
476            buffer: TensorMapArg<R, Tiled>,
477            layout: L::RuntimeArg<R>,
478        ) -> ViewArg<C, R> {
479            let layout = VirtualViewLayoutLaunch::new::<IntoDynLayout<L>>(layout);
480            ViewArg::TensorMapTiled(buffer, layout)
481        }
482
483        pub fn new_tensor_map_im2col<
484            L: Layout<Coordinates = C, SourceCoordinates = (P, O)> + ViewLayoutLaunchArg,
485            P: IntoDyn,
486            O: IntoDyn,
487        >(
488            buffer: TensorMapArg<R, Im2col>,
489            layout: L::RuntimeArg<R>,
490        ) -> ViewArg<C, R> {
491            let layout = VirtualViewLayoutLaunch::new::<IntoDyn2Layout<L, P, O>>(layout);
492            ViewArg::TensorMapIm2col(buffer, layout)
493        }
494
495        /// Create a new view arg that dequantizes on read.
496        /// The scales layout should take values indices and map them to the corresponding scale.
497        pub fn new_quantized(values: Self, scales: Self, scheme: QuantScheme) -> Self {
498            Self::Quantized {
499                values: Box::new(values),
500                scales: Box::new(scales),
501                scheme,
502            }
503        }
504    }
505    #[derive(Clone)]
506    pub enum ViewCompilationArg<C: Coordinates> {
507        Array {
508            buffer: ArrayCompilationArg,
509            layout: VirtualViewLayoutCompilationArg<C, Coords1d>,
510        },
511        TensorMapTiled {
512            buffer: (),
513            layout: VirtualViewLayoutCompilationArg<C, Sequence<i32>>,
514        },
515        TensorMapIm2col {
516            buffer: (),
517            layout: VirtualViewLayoutCompilationArg<C, (Sequence<i32>, Sequence<i32>)>,
518        },
519        Quantized {
520            values: Box<ViewCompilationArg<C>>,
521            scales: Box<ViewCompilationArg<C>>,
522            scheme: QuantScheme,
523        },
524    }
525
526    impl<C: Coordinates> Eq for ViewCompilationArg<C> {}
527    impl<C: Coordinates> PartialEq for ViewCompilationArg<C> {
528        fn eq(&self, other: &Self) -> bool {
529            match (self, other) {
530                (
531                    ViewCompilationArg::Array { buffer, layout },
532                    ViewCompilationArg::Array {
533                        buffer: buffer_other,
534                        layout: layout_other,
535                    },
536                ) => buffer == buffer_other && layout == layout_other,
537                (
538                    ViewCompilationArg::TensorMapTiled { buffer, layout },
539                    ViewCompilationArg::TensorMapTiled {
540                        buffer: buffer_other,
541                        layout: layout_other,
542                    },
543                ) => buffer == buffer_other && layout == layout_other,
544                (
545                    ViewCompilationArg::TensorMapIm2col { buffer, layout },
546                    ViewCompilationArg::TensorMapIm2col {
547                        buffer: buffer_other,
548                        layout: layout_other,
549                    },
550                ) => buffer == buffer_other && layout == layout_other,
551                (
552                    ViewCompilationArg::Quantized {
553                        values,
554                        scales,
555                        scheme,
556                    },
557                    ViewCompilationArg::Quantized {
558                        values: values_other,
559                        scales: scales_other,
560                        scheme: scheme_other,
561                    },
562                ) => values == values_other && scales == scales_other && scheme == scheme_other,
563                _ => false,
564            }
565        }
566    }
567    impl<C: Coordinates> core::hash::Hash for ViewCompilationArg<C> {
568        fn hash<H: core::hash::Hasher>(&self, ra_expand_state: &mut H) {
569            match self {
570                ViewCompilationArg::Array { buffer, layout } => {
571                    buffer.hash(ra_expand_state);
572                    layout.hash(ra_expand_state);
573                }
574                ViewCompilationArg::TensorMapTiled { buffer, layout } => {
575                    buffer.hash(ra_expand_state);
576                    layout.hash(ra_expand_state);
577                }
578                ViewCompilationArg::TensorMapIm2col { buffer, layout } => {
579                    buffer.hash(ra_expand_state);
580                    layout.hash(ra_expand_state);
581                }
582                ViewCompilationArg::Quantized {
583                    values,
584                    scales,
585                    scheme,
586                } => {
587                    values.hash(ra_expand_state);
588                    scales.hash(ra_expand_state);
589                    scheme.hash(ra_expand_state);
590                }
591            }
592        }
593    }
594    impl<C: Coordinates> core::fmt::Debug for ViewCompilationArg<C> {
595        fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
596            match self {
597                ViewCompilationArg::Array { buffer, layout } => f
598                    .debug_struct("ArrayView")
599                    .field("buffer", &buffer)
600                    .field("layout", &layout)
601                    .finish(),
602                ViewCompilationArg::TensorMapTiled { buffer, layout } => f
603                    .debug_struct("TensorMapTiledView")
604                    .field("buffer", &buffer)
605                    .field("layout", &layout)
606                    .finish(),
607                ViewCompilationArg::TensorMapIm2col { buffer, layout } => f
608                    .debug_struct("TensorMapIm2colView")
609                    .field("buffer", &buffer)
610                    .field("layout", &layout)
611                    .finish(),
612                ViewCompilationArg::Quantized {
613                    values,
614                    scales,
615                    scheme,
616                } => f
617                    .debug_struct("QuantizedView")
618                    .field("values", &values)
619                    .field("scales", &scales)
620                    .field("scheme", &scheme)
621                    .finish(),
622            }
623        }
624    }
625
626    impl<E: CubePrimitive, C: Coordinates + 'static, IO: SliceVisibility> LaunchArg for View<E, C, IO> {
627        type RuntimeArg<R: Runtime> = ViewArg<C, R>;
628        type CompilationArg = ViewCompilationArg<C>;
629
630        fn register<R: Runtime>(
631            arg: Self::RuntimeArg<R>,
632            launcher: &mut KernelLauncher<R>,
633        ) -> Self::CompilationArg {
634            let ty = launcher.with_scope(|scope| E::as_type(scope));
635            match arg {
636                ViewArg::Array(buffer, layout) => ViewCompilationArg::Array {
637                    layout: layout.register(&buffer, ty, launcher),
638                    buffer: <Array<E> as LaunchArg>::register(buffer, launcher),
639                },
640                ViewArg::Tensor(buffer, layout) => ViewCompilationArg::Array {
641                    layout: layout.register(&buffer, ty, launcher),
642                    buffer: <Array<E> as LaunchArg>::register(buffer.into_array_arg(), launcher),
643                },
644                ViewArg::TensorMapTiled(buffer, layout) => ViewCompilationArg::TensorMapTiled {
645                    layout: layout.register(&buffer, ty, launcher),
646                    buffer: <TensorMap<E, Tiled> as LaunchArg>::register(buffer, launcher),
647                },
648                ViewArg::TensorMapIm2col(buffer, layout) => ViewCompilationArg::TensorMapIm2col {
649                    layout: layout.register(&buffer, ty, launcher),
650                    buffer: <TensorMap<E, Im2col> as LaunchArg>::register(buffer, launcher),
651                },
652                ViewArg::Quantized {
653                    values,
654                    scales,
655                    scheme,
656                } => {
657                    let register = RegisterDynamic {
658                        values: *values,
659                        scales: *scales,
660                        scheme,
661                        launcher,
662                        _ty: PhantomData::<E>,
663                    };
664                    run_with_quant_type(register, scheme)
665                }
666            }
667        }
668        fn expand(
669            arg: &Self::CompilationArg,
670            builder: &mut KernelBuilder,
671        ) -> <Self as CubeType>::ExpandType {
672            let ty = E::as_type(&builder.scope);
673            match arg {
674                ViewCompilationArg::Array { buffer, layout } => {
675                    let layout = layout.expand(ty, builder);
676                    let buffer = <Array<E> as LaunchArg>::expand(buffer, builder);
677                    let view =
678                        VirtualViewMutExpand::<E, C, Coords1d, Array<E>>::new(buffer, layout);
679                    ViewExpand::<E, C, IO> {
680                        inner: ViewType::ReadWrite(Arc::new(view)),
681                        _io: PhantomData,
682                    }
683                }
684                ViewCompilationArg::TensorMapTiled { buffer, layout } => {
685                    let layout = layout.expand(ty, builder);
686                    let buffer = <TensorMap<E, Tiled> as LaunchArg>::expand(buffer, builder);
687                    let view =
688                        VirtualViewMutExpand::<E, C, Sequence<i32>, TensorMap<E, Tiled>>::new(
689                            buffer, layout,
690                        );
691                    ViewExpand::<E, C, IO> {
692                        inner: ViewType::ReadWrite(Arc::new(view)),
693                        _io: PhantomData,
694                    }
695                }
696                ViewCompilationArg::TensorMapIm2col { buffer, layout } => {
697                    let layout = layout.expand(ty, builder);
698                    let buffer = <TensorMap<E, Im2col> as LaunchArg>::expand(buffer, builder);
699                    let view = VirtualViewExpand::<
700                        E,
701                        C,
702                        (Sequence<i32>, Sequence<i32>),
703                        TensorMap<E, Im2col>,
704                    >::new(buffer, layout);
705                    ViewExpand::<E, C, IO> {
706                        inner: ViewType::Read(Arc::new(view)),
707                        _io: PhantomData,
708                    }
709                }
710                ViewCompilationArg::Quantized {
711                    values,
712                    scales,
713                    scheme,
714                } => quant::view::expand_dynamic(values, scales, *scheme, builder),
715            }
716        }
717        fn expand_output(
718            arg: &Self::CompilationArg,
719            builder: &mut KernelBuilder,
720        ) -> <Self as CubeType>::ExpandType {
721            let ty = E::as_type(&builder.scope);
722            match arg {
723                ViewCompilationArg::Array { buffer, layout } => {
724                    let layout = layout.expand_output(ty, builder);
725                    let buffer = <Array<E> as LaunchArg>::expand_output(buffer, builder);
726                    let view =
727                        VirtualViewMutExpand::<E, C, Coords1d, Array<E>>::new(buffer, layout);
728                    ViewExpand::<E, C, IO> {
729                        inner: ViewType::ReadWrite(Arc::new(view)),
730                        _io: PhantomData,
731                    }
732                }
733                ViewCompilationArg::TensorMapTiled { buffer, layout } => {
734                    let layout = layout.expand_output(ty, builder);
735                    let buffer = <TensorMap<E, Tiled> as LaunchArg>::expand_output(buffer, builder);
736                    let view =
737                        VirtualViewMutExpand::<E, C, Sequence<i32>, TensorMap<E, Tiled>>::new(
738                            buffer, layout,
739                        );
740                    ViewExpand::<E, C, IO> {
741                        inner: ViewType::ReadWrite(Arc::new(view)),
742                        _io: PhantomData,
743                    }
744                }
745                ViewCompilationArg::TensorMapIm2col { .. } => {
746                    unimplemented!("Im2col tensor maps can't be used as outputs");
747                }
748                ViewCompilationArg::Quantized { .. } => panic!("Quantized views must be readonly"),
749            }
750        }
751    }
752}
753
754pub use dynamic::*;