Skip to main content

cubecl_std/tensor/view/
launch.rs

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