Editor/Inference/FlowSingleBlock.cs
// C# adaptation of FlowHMR's MMSingleStreamBlock. See THIRD_PARTY_NOTICES.md.
using System;
using System.Threading;
namespace HumanoidMocapX.Inference;
internal sealed class FlowSingleBlock
{
readonly FlowLinear modulation, first, second;
readonly Tensor queryScale, keyScale;
internal FlowSingleBlock(FlowWeights weights, int index, int width, int heads)
{
var name = "single_blocks." + index;
modulation = new(weights, name + ".modulation.linear", width, 3 * width);
first = new(weights, name + ".linear1", width, 7 * width);
second = new(weights, name + ".linear2", 5 * width, width);
queryScale = weights.Get(name + ".q_norm.weight", width / heads);
keyScale = weights.Get(name + ".k_norm.weight", width / heads);
}
internal void Run(Span<float> features, ReadOnlySpan<float> activatedAdapter, FlowBlockBuffers buffers, CancellationToken cancellation)
{
var width = buffers.Width; var rows = 2 * buffers.Frames;
var gates = buffers.Gates.AsSpan(0, 3 * width);
modulation.Run(activatedAdapter, 1, gates, cancellation);
buffers.LayerNorm.Run(features, buffers.Normalized);
FlowConditioning.Modulate(buffers.Normalized, gates[..width], gates.Slice(width, width));
first.Run(buffers.Normalized, rows, buffers.Packed, cancellation);
buffers.PrepareQkv(buffers.Packed, rows, 7 * width, 0, queryScale, keyScale);
buffers.Attend(cancellation);
for (var row = 0; row < rows; row++)
{
var joined = buffers.Joined.AsSpan(row * 5 * width, 5 * width);
buffers.Attended.AsSpan(row * width, width).CopyTo(joined[..width]);
buffers.Packed.AsSpan(row * 7 * width + 3 * width, 4 * width).CopyTo(joined[width..]);
FlowConditioning.Gelu(joined[width..]);
}
second.Run(buffers.Joined, rows, buffers.Projected, cancellation);
FlowConditioning.AddGated(features, buffers.Projected, gates.Slice(2 * width, width));
}
}