From 39d4ef0bc4fdce9a2e38539c1952c99b6c7ef60f Mon Sep 17 00:00:00 2001 From: maj00r Date: Tue, 3 Nov 2026 20:29:18 +0100 Subject: [PATCH] Read AVX2 from the processor Avx2.IsSupported says whether the starter's own code may use AVX2, and the AOT compiler fixes that at build time to its baseline, which has none. A published starter told every player that their processor lacked AVX2. The check now reads CPUID: AVX2 in leaf 7, AVX and OSXSAVE in leaf 1. --- StarterNG/Infrastructure/CpuFeatures.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/StarterNG/Infrastructure/CpuFeatures.cs b/StarterNG/Infrastructure/CpuFeatures.cs index aa750ef..50c52a8 100644 --- a/StarterNG/Infrastructure/CpuFeatures.cs +++ b/StarterNG/Infrastructure/CpuFeatures.cs @@ -12,5 +12,21 @@ public static class CpuFeatures /// processor. Other architectures cannot run them at all, which is not this. /// public static bool LacksAvx2 => - RuntimeInformation.ProcessArchitecture is Architecture.X64 or Architecture.X86 && !Avx2.IsSupported; + RuntimeInformation.ProcessArchitecture is Architecture.X64 or Architecture.X86 && !HasAvx2(); + + /// + /// Asks the processor itself. Avx2.IsSupported only says whether the starter's own + /// code may use AVX2, and the AOT compiler fixes that at build time to its baseline, + /// which has no AVX2, so a published starter always read false. + /// + static bool HasAvx2() + { + if (!X86Base.IsSupported || X86Base.CpuId(0, 0).Eax < 7) + return false; + // Leaf 1 ECX: bit 27 the system saves the extended registers (OSXSAVE), bit 28 AVX. + // Leaf 7 EBX: bit 5 AVX2. + const int osxsaveAndAvx = (1 << 27) | (1 << 28); + return (X86Base.CpuId(1, 0).Ecx & osxsaveAndAvx) == osxsaveAndAvx && + (X86Base.CpuId(7, 0).Ebx & (1 << 5)) != 0; + } }