diff --git a/Tests/FFAITests/Ops/OpsSpecialPathTests.swift b/Tests/FFAITests/Ops/OpsSpecialPathTests.swift index f852b2f6..0c3bbe33 100644 --- a/Tests/FFAITests/Ops/OpsSpecialPathTests.swift +++ b/Tests/FFAITests/Ops/OpsSpecialPathTests.swift @@ -1142,7 +1142,16 @@ struct OpsSpecialPathTests { // MARK: - MoE batched-prefill variants - @Test("moeGatherDequantGemmInt4Bm8 f32 — dispatch on BM=8 tile shape") + // Gated on Apple GPU Family 9+ (M3+) like the bm64 MPP cells: the bm8 + // path lowers MPP cooperative-tensor matmul, and on a Family < 9 runner + // (the macos-latest pool is mixed M1/M3 hardware) the PSO either zeroes + // output or fails to compile outright on newer toolchains, fatal-erroring + // PSOCache. Reuses the single availability gate so this stays in sync. + @Test( + "moeGatherDequantGemmInt4Bm8 f32 — dispatch on BM=8 tile shape", + .enabled( + if: MoEBgemmBm64MppTests.mppCooperativeTensorAvailable, + "MPP cooperative tensor — Apple GPU Family 9+")) func moeBm8Smoke() { // TODO: needs production-shape correctness reference — the // kernel's BM=8 tile is exercised at decode top-K; the BM=16 diff --git a/Tests/MetalTileSwiftTests/KernelManifestSmokeTests.swift b/Tests/MetalTileSwiftTests/KernelManifestSmokeTests.swift index 7835573f..4a3a4662 100644 --- a/Tests/MetalTileSwiftTests/KernelManifestSmokeTests.swift +++ b/Tests/MetalTileSwiftTests/KernelManifestSmokeTests.swift @@ -45,6 +45,21 @@ import Testing @Suite("Kernel manifest PSO smoke") struct KernelManifestSmokeTests { + /// MPP cooperative-tensor kernels (`_mpp_` / `bgemm`) lower simdgroup + /// matmul that needs Apple GPU Family 9+ (M3+). The macos-latest runner + /// pool is mixed M1/M3 hardware; on a Family < 9 host the Metal compiler + /// rejects the cooperative-tensor body, so the manifest sweep skips those + /// kernels there. They are covered by ffai-kernels' own GPU correctness + /// suite on adequate hardware. Detection mirrors `PSOCache.isMppKernel`. + static let mppCooperativeTensorAvailable: Bool = { + guard let device = MTLCreateSystemDefaultDevice() else { return false } + return device.supportsFamily(.apple9) + }() + + static func isMppKernel(_ name: String) -> Bool { + name.contains("_mpp_") || name.contains("bgemm") + } + /// JSON shape mirrored from `metaltile-codegen::emit::write_manifest`. /// Only `name` is parsed — the rest is left flexible so manifest /// schema bumps don't fail the test. @@ -91,6 +106,10 @@ struct KernelManifestSmokeTests { var failures: [String] = [] for entry in manifest.kernels { + // Fast-skip the obviously-MPP kernels by name on Family < 9. + if !Self.mppCooperativeTensorAvailable, Self.isMppKernel(entry.name) { + continue + } do { let pso = try cache.pipelineStateThrowing(for: entry.name) #expect( @@ -98,6 +117,18 @@ struct KernelManifestSmokeTests { "kernel \(entry.name) reports zero maxTotalThreadsPerThreadgroup — Metal refused to instantiate" ) } catch { + // Cooperative-tensor (MMA) kernels are not all named `_mpp_` / + // `bgemm` (e.g. the `_nax_` steel-GEMM cells). On a Family < 9 + // runner the Metal compiler rejects every cooperative-tensor + // body with "unsupported deferred-static-alloca-size"; treat + // that specific compile error as a skip on inadequate hardware + // (these are verified upstream on M3+) rather than a failure. + // Any other compile error is still a real failure. + if !Self.mppCooperativeTensorAvailable, + "\(error)".contains("deferred-static-alloca-size") + { + continue + } failures.append("\(entry.name): \(error)") } }