Validate that sampler compare function requires iOS GPU family 3v1

Bug: b/149025333
Change-Id: I8683188c6189a9390ac6568e4ab5434a6c1a99f9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/15942
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index 830b99a..2b4a6ec 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -106,7 +106,7 @@
         return RenderPipeline::Create(this, descriptor);
     }
     ResultOrError<SamplerBase*> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
-        return new Sampler(this, descriptor);
+        return Sampler::Create(this, descriptor);
     }
     ResultOrError<ShaderModuleBase*> Device::CreateShaderModuleImpl(
         const ShaderModuleDescriptor* descriptor) {
diff --git a/src/dawn_native/metal/SamplerMTL.h b/src/dawn_native/metal/SamplerMTL.h
index 776c935..205a7ec 100644
--- a/src/dawn_native/metal/SamplerMTL.h
+++ b/src/dawn_native/metal/SamplerMTL.h
@@ -25,12 +25,13 @@
 
     class Sampler : public SamplerBase {
       public:
-        Sampler(Device* device, const SamplerDescriptor* descriptor);
+        static ResultOrError<Sampler*> Create(Device* device, const SamplerDescriptor* descriptor);
         ~Sampler();
 
         id<MTLSamplerState> GetMTLSamplerState();
 
       private:
+        Sampler(Device* device, const SamplerDescriptor* descriptor);
         id<MTLSamplerState> mMtlSamplerState = nil;
     };
 
diff --git a/src/dawn_native/metal/SamplerMTL.mm b/src/dawn_native/metal/SamplerMTL.mm
index c58e582..e29fbe1 100644
--- a/src/dawn_native/metal/SamplerMTL.mm
+++ b/src/dawn_native/metal/SamplerMTL.mm
@@ -50,6 +50,20 @@
         }
     }
 
+    // static
+    ResultOrError<Sampler*> Sampler::Create(Device* device, const SamplerDescriptor* descriptor) {
+#if defined(DAWN_PLATFORM_IOS)
+        if (descriptor->compare != wgpu::CompareFunction::Never &&
+            ![device->GetMTLDevice() supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1]) {
+            // Unsupported before A9.
+            // TODO(b/149025333): Investigate emulation -- possibly expensive.
+            return DAWN_VALIDATION_ERROR(
+                "Sampler compare function requires at least iOS GPU family 3, version 1");
+        }
+#endif
+        return new Sampler(device, descriptor);
+    }
+
     Sampler::Sampler(Device* device, const SamplerDescriptor* descriptor)
         : SamplerBase(device, descriptor) {
         MTLSamplerDescriptor* mtlDesc = [MTLSamplerDescriptor new];
@@ -64,7 +78,12 @@
 
         mtlDesc.lodMinClamp = descriptor->lodMinClamp;
         mtlDesc.lodMaxClamp = descriptor->lodMaxClamp;
-        mtlDesc.compareFunction = ToMetalCompareFunction(descriptor->compare);
+
+        if (descriptor->compare != wgpu::CompareFunction::Never) {
+            // Anything other than Never is unsupported before A9, which we validate in
+            // Sampler::Create.
+            mtlDesc.compareFunction = ToMetalCompareFunction(descriptor->compare);
+        }
 
         mMtlSamplerState = [device->GetMTLDevice() newSamplerStateWithDescriptor:mtlDesc];