use super::{uniform, ComputeEngine};
use crate::{UnifiedTensor, WgpuContext};
#[derive(Clone, Copy)]
#[repr(u32)]
enum Layout {
Plain = 0,
TransposedB = 1,
TransposedA = 2,
}
impl ComputeEngine {
pub fn matmul(
&self,
ctx: &WgpuContext,
a: &UnifiedTensor,
b: &UnifiedTensor,
out: &UnifiedTensor,
) {
let dims = (a.shape[0] as u32, a.shape[1] as u32, b.shape[1] as u32);
self.matmul_dispatch(ctx, Layout::Plain, dims, a, b, out);
}
pub fn matmul_bt(
&self,
ctx: &WgpuContext,
a: &UnifiedTensor,
b: &UnifiedTensor,
out: &UnifiedTensor,
) {
let dims = (a.shape[0] as u32, a.shape[1] as u32, b.shape[0] as u32);
self.matmul_dispatch(ctx, Layout::TransposedB, dims, a, b, out);
}
pub fn matmul_at(
&self,
ctx: &WgpuContext,
a: &UnifiedTensor,
b: &UnifiedTensor,
out: &UnifiedTensor,
) {
let dims = (a.shape[1] as u32, a.shape[0] as u32, b.shape[1] as u32);
self.matmul_dispatch(ctx, Layout::TransposedA, dims, a, b, out);
}
fn matmul_dispatch(
&self,
ctx: &WgpuContext,
layout: Layout,
(m, k, n): (u32, u32, u32),
a: &UnifiedTensor,
b: &UnifiedTensor,
out: &UnifiedTensor,
) {
let params = uniform(ctx, bytemuck::cast_slice(&[m, k, n, layout as u32]));
self.run(
ctx,
&self.matmul,
&[
(0, a.buffer()),
(1, b.buffer()),
(2, out.buffer()),
(3, ¶ms),
],
(n.div_ceil(64), m.div_ceil(64), 1),
);
}
}