package platform import ( "os" "os/exec" "runtime" "strings" "gitgud.io/mike/mpv-manager/pkg/log" ) func detectCPU() CPUInfo { info := CPUInfo{ Features: []string{}, } if runtime.GOOS == "windows" { info = detectCPUWindows() } else if runtime.GOOS == "linux" { info = detectCPULinux() } else if runtime.GOOS == "darwin" { info = detectCPUDarwin() } info.SupportsAVX2 = checkAVX2(info.Features) info.SupportsAVX512 = checkAVX512(info.Features) info.SupportsNEON = checkNEON(info.Features) // Normalize vendor name for consistent color coding and display info.VendorDisplay = getVendorDisplay(info.Vendor) info.Vendor = info.VendorDisplay // Only set ArchitectureLevel if not already set (Windows sets it directly via cpuid) if info.ArchitectureLevel == "" { info.ArchitectureLevel = detectArchitectureLevel(info.Features) } return info } func detectCPULinux() CPUInfo { info := CPUInfo{} if data, err := os.ReadFile("/proc/cpuinfo"); err == nil { content := string(data) lines := strings.Split(content, "\n") for _, line := range lines { line = strings.TrimSpace(line) if strings.HasPrefix(line, "vendor_id") { parts := strings.SplitN(line, ":", 2) if len(parts) == 2 { info.Vendor = strings.TrimSpace(parts[1]) } } else if strings.HasPrefix(line, "model name") { parts := strings.SplitN(line, ":", 2) if len(parts) == 2 { info.Model = strings.TrimSpace(parts[1]) } } else if strings.HasPrefix(line, "flags") || strings.HasPrefix(line, "Features") { parts := strings.SplitN(line, ":", 2) if len(parts) == 2 { features := strings.Fields(strings.TrimSpace(parts[1])) info.Features = features } } } } else { log.Warn("Failed to read /proc/cpuinfo: " + err.Error()) } return info } func detectCPUDarwin() CPUInfo { info := CPUInfo{ Vendor: "Apple", } if output, err := exec.Command("sysctl", "-n", "machdep.cpu.brand_string").Output(); err == nil { info.Model = strings.TrimSpace(string(output)) } else if runtime.GOARCH == "arm64" { info.Model = "Apple Silicon" } else { info.Model = "Intel" } // Set features based on architecture (ALWAYS, not just when sysctl fails) if runtime.GOARCH == "arm64" { info.Features = []string{"arm64", "neon"} } else { // Intel Mac - try to get actual features, or use reasonable defaults info.Features = []string{"x86-64", "sse", "sse2", "sse3", "ssse3", "sse4_1", "sse4_2"} // Could also check for AVX2 via sysctl hw.optional.avx2_0 } return info } func checkAVX2(features []string) bool { for _, feature := range features { if strings.Contains(strings.ToLower(feature), "avx2") { return true } } return false } func checkAVX512(features []string) bool { for _, feature := range features { if strings.Contains(strings.ToLower(feature), "avx512") { return true } } return false } func checkNEON(features []string) bool { for _, feature := range features { if strings.Contains(strings.ToLower(feature), "neon") { return true } } return false } func getVendorDisplay(vendor string) string { switch vendor { case "GenuineIntel": return "Intel" case "AuthenticAMD": return "AMD" case "nvidia": return "NVIDIA" case "amd": return "AMD" case "intel": return "Intel" case "apple": return "Apple" default: return vendor } } func detectArchitectureLevel(features []string) string { // Check for ARM architecture first for _, feature := range features { featureLower := strings.ToLower(feature) if strings.Contains(featureLower, "arm64") || strings.Contains(featureLower, "aarch64") || strings.Contains(featureLower, "neon") { return "arm64" } } // x86-64 detection hasAVX2 := false hasAVX512 := false for _, feature := range features { featureLower := strings.ToLower(feature) if strings.Contains(featureLower, "avx2") { hasAVX2 = true } if strings.Contains(featureLower, "avx512") { hasAVX512 = true } } if hasAVX512 { return "x86-64-v4" } if hasAVX2 { return "x86-64-v3" } return "x86-64-v2" } func (p *Platform) SupportsX86_64_v3() bool { return (p.Arch == "amd64" || p.Arch == "x86_64") && p.CPUInfo.SupportsAVX2 }