ferrotensor_backend/engine/
matmul.rs1use super::{uniform, ComputeEngine};
4use crate::{UnifiedTensor, WgpuContext};
5
6#[derive(Clone, Copy)]
8#[repr(u32)]
9enum Layout {
10 Plain = 0,
12 TransposedB = 1,
14 TransposedA = 2,
16}
17
18impl ComputeEngine {
19 pub fn matmul(
21 &self,
22 ctx: &WgpuContext,
23 a: &UnifiedTensor,
24 b: &UnifiedTensor,
25 out: &UnifiedTensor,
26 ) {
27 let dims = (a.shape[0] as u32, a.shape[1] as u32, b.shape[1] as u32);
28 self.matmul_dispatch(ctx, Layout::Plain, dims, a, b, out);
29 }
30
31 pub fn matmul_bt(
34 &self,
35 ctx: &WgpuContext,
36 a: &UnifiedTensor,
37 b: &UnifiedTensor,
38 out: &UnifiedTensor,
39 ) {
40 let dims = (a.shape[0] as u32, a.shape[1] as u32, b.shape[0] as u32);
41 self.matmul_dispatch(ctx, Layout::TransposedB, dims, a, b, out);
42 }
43
44 pub fn matmul_at(
47 &self,
48 ctx: &WgpuContext,
49 a: &UnifiedTensor,
50 b: &UnifiedTensor,
51 out: &UnifiedTensor,
52 ) {
53 let dims = (a.shape[1] as u32, a.shape[0] as u32, b.shape[1] as u32);
54 self.matmul_dispatch(ctx, Layout::TransposedA, dims, a, b, out);
55 }
56
57 fn matmul_dispatch(
58 &self,
59 ctx: &WgpuContext,
60 layout: Layout,
61 (m, k, n): (u32, u32, u32),
62 a: &UnifiedTensor,
63 b: &UnifiedTensor,
64 out: &UnifiedTensor,
65 ) {
66 let params = uniform(ctx, bytemuck::cast_slice(&[m, k, n, layout as u32]));
67 self.run(
69 ctx,
70 &self.matmul,
71 &[
72 (0, a.buffer()),
73 (1, b.buffer()),
74 (2, out.buffer()),
75 (3, ¶ms),
76 ],
77 (n.div_ceil(64), m.div_ceil(64), 1),
78 );
79 }
80}