AutoRig/Dl/HardwareAdvisor.cs

Utility that decides whether a catalog model will fit and perform acceptably on the local machine for a given mesh. It computes peak memory = BaseRamBytes + RamPerVertexBytes * vertexCount, compares it against supplied available memory, and returns a Verdict plus a human explanation string.

namespace AutoRig.Dl;

/// <summary>Whether this machine can run a catalog model on a given mesh (spec §8).</summary>
public enum Verdict
{
    Recommended,
    Slow,
    Insufficient,
}

/// <summary>
/// Estimates whether a catalog model fits this machine AND this mesh: peak memory =
/// base + per-vertex cost at the analysis-proxy resolution, compared against the
/// memory actually available right now.
/// </summary>
public static class HardwareAdvisor
{
    const int SlowVertexThreshold = 150_000;

    /// <summary>
    /// Assesses fit with the available memory injected by the caller: probing the
    /// machine (GC.GetGCMemoryInfo) is whitelist-banned engine-side, so the editor
    /// layer measures and passes the number in.
    /// </summary>
    public static (Verdict Verdict, string Explanation) Assess(
        CatalogEntry entry, int vertexCount, long availableBytes )
    {
        ArgumentNullException.ThrowIfNull( entry );

        var peak = entry.BaseRamBytes + (long)(entry.RamPerVertexBytes * vertexCount);
        var peakGb = peak / (1024.0 * 1024 * 1024);
        var availableGb = availableBytes / (1024.0 * 1024 * 1024);

        if ( peak > availableBytes )
        {
            return (Verdict.Insufficient,
                $"Needs about {peakGb:0.0} GB free memory for this mesh; this machine has {availableGb:0.0} GB. "
                + "The geometric solver works on any hardware.");
        }
        if ( peak > availableBytes * 0.7 || vertexCount > SlowVertexThreshold )
        {
            return (Verdict.Slow,
                $"Will run, but expect several minutes: ~{peakGb:0.0} GB of {availableGb:0.0} GB free, "
                + $"{vertexCount:n0} vertices on the CPU.");
        }
        return (Verdict.Recommended,
            $"Fits comfortably: ~{peakGb:0.0} GB of {availableGb:0.0} GB free.");
    }
}