oarust 0.8.6

GPU-first semantic computing engine written in Rust
// Linear-family adaptation of OA's bounded FP32 gate/up provider.
// Donor: source/cpp/lib/oa/ml/shader/compute/nn/linear/gateUpSwigluBias.slang

import storage;
import attributes;

struct PushConstants {
	uint input_index;
	uint gate_weight_index;
	uint up_weight_index;
	uint gate_bias_index;
	uint up_bias_index;
	uint output_index;
	uint m;
	uint n;
	uint k;
};

[[vk::push_constant]] PushConstants push;
[[vk::binding(0, 0)]] RWByteAddressBuffer storage_buffers[];

static const uint BM = 32;
static const uint BN = 32;
static const uint BK = 32;
static const uint BK_PAD = BK + 1;

groupshared float shared_input[BM * BK_PAD];
groupshared float shared_gate_weight[BN * BK_PAD];
groupshared float shared_up_weight[BN * BK_PAD];

[kernel_name("gate_up_swiglu_bias")]
[domain("ml")]
[variant("generic")]
[dtype("f32")]
[status("experimental")]
[shader("compute")]
[numthreads(256, 1, 1)]
void main(uint3 group_id : SV_GroupID, uint3 thread_id : SV_GroupThreadID) {
	uint thread = thread_id.x;
	uint row_base = group_id.x * BM;
	uint column_base = group_id.y * BN;
	uint local_row = thread / 8;
	uint local_column_base = (thread % 8) * 4;
	uint row = row_base + local_row;

	float gate[4];
	float up[4];
	[[unroll]] for (uint output = 0; output < 4; ++output) {
		gate[output] = 0.0f;
		up[output] = 0.0f;
	}

	for (uint k_base = 0; k_base < push.k; k_base += BK) {
		[[unroll]] for (uint load = 0; load < 4; ++load) {
			uint linear = thread + load * 256;
			uint tile_row = linear / BK;
			uint tile_k = linear % BK;
			uint global_k = k_base + tile_k;
			uint input_row = row_base + tile_row;
			uint weight_row = column_base + tile_row;
			uint shared = tile_row * BK_PAD + tile_k;
			shared_input[shared] = input_row < push.m && global_k < push.k
				? load_f32(storage_buffers[push.input_index], input_row * push.k + global_k)
				: 0.0f;
			shared_gate_weight[shared] = weight_row < push.n && global_k < push.k
				? load_f32(storage_buffers[push.gate_weight_index], weight_row * push.k + global_k)
				: 0.0f;
			shared_up_weight[shared] = weight_row < push.n && global_k < push.k
				? load_f32(storage_buffers[push.up_weight_index], weight_row * push.k + global_k)
				: 0.0f;
		}
		GroupMemoryBarrierWithGroupSync();

		[[unroll]] for (uint inner = 0; inner < BK; ++inner) {
			float activation = shared_input[local_row * BK_PAD + inner];
			[[unroll]] for (uint output = 0; output < 4; ++output) {
				uint local_column = local_column_base + output;
				uint weight = local_column * BK_PAD + inner;
				gate[output] += activation * shared_gate_weight[weight];
				up[output] += activation * shared_up_weight[weight];
			}
		}
		GroupMemoryBarrierWithGroupSync();
	}

	if (row >= push.m) return;
	[[unroll]] for (uint output = 0; output < 4; ++output) {
		uint column = column_base + local_column_base + output;
		if (column >= push.n) continue;
		float gate_bias = gate[output]
			+ load_f32(storage_buffers[push.gate_bias_index], column);
		float up_bias = up[output]
			+ load_f32(storage_buffers[push.up_bias_index], column);
		float silu = gate_bias / (1.0f + exp(-gate_bias));
		store_f32(
			storage_buffers[push.output_index],
			row * push.n + column,
			silu * up_bias
		);
	}
}