Cleanup some texture checks (#4544)

Add `isTextureFormatFilterable` and use where things were
being checked more manually. Also use `isTextureFormatBlendable`
where it was being checked manually.
diff --git a/src/webgpu/format_info.ts b/src/webgpu/format_info.ts
index cab60c8..90dc078 100644
--- a/src/webgpu/format_info.ts
+++ b/src/webgpu/format_info.ts
@@ -2400,6 +2400,22 @@
 }
 
 /**
+ * Returns true if a texture can be filtered.
+ */
+export function isTextureFormatFilterable(device: GPUDevice, format: GPUTextureFormat): boolean {
+  const type = getTextureFormatType(format);
+  switch (type) {
+    case 'float':
+      return true;
+    case 'unfilterable-float':
+      assert(is32Float(format));
+      return hasFeature(device.features, 'float32-filterable');
+    default:
+      return false;
+  }
+}
+
+/**
  * Returns the texture's type (float, unsigned-float, sint, uint, depth)
  */
 export function getTextureFormatType(format: GPUTextureFormat, aspect: GPUTextureAspect = 'all') {
diff --git a/src/webgpu/gpu_test.ts b/src/webgpu/gpu_test.ts
index 519e1b3..8def905 100644
--- a/src/webgpu/gpu_test.ts
+++ b/src/webgpu/gpu_test.ts
@@ -32,8 +32,6 @@
   getRequiredFeatureForTextureFormat,
   isTextureFormatUsableAsRenderAttachment,
   isTextureFormatMultisampled,
-  is32Float,
-  isSintOrUintFormat,
   isTextureFormatResolvable,
   isDepthTextureFormat,
   isStencilTextureFormat,
@@ -41,6 +39,8 @@
   textureDimensionAndFormatCompatibleForDevice,
   isTextureFormatUsableWithStorageAccessMode,
   isTextureFormatUsableWithCopyExternalImageToTexture,
+  isTextureFormatFilterable,
+  isTextureFormatBlendable,
 } from './format_info.js';
 import { checkElementsEqual, checkElementsBetween } from './util/check_contents.js';
 import { CommandBufferMaker, EncoderType } from './util/command_buffer_maker.js';
@@ -604,26 +604,14 @@
   skipIfTextureFormatNotBlendable(...formats: (GPUTextureFormat | undefined)[]) {
     for (const format of formats) {
       if (format === undefined) continue;
-      this.skipIf(isSintOrUintFormat(format), 'sint/uint formats are not blendable');
-      if (is32Float(format)) {
-        this.skipIf(
-          !hasFeature(this.device.features, 'float32-blendable'),
-          `texture format '${format}' is not blendable`
-        );
-      }
+      this.skipIf(!isTextureFormatBlendable(this.device, format), `${format} is not blendable`);
     }
   }
 
   skipIfTextureFormatNotFilterable(...formats: (GPUTextureFormat | undefined)[]) {
     for (const format of formats) {
       if (format === undefined) continue;
-      this.skipIf(isSintOrUintFormat(format), 'sint/uint formats are not filterable');
-      if (is32Float(format)) {
-        this.skipIf(
-          !hasFeature(this.device.features, 'float32-filterable'),
-          `texture format '${format}' is not filterable`
-        );
-      }
+      this.skipIf(!isTextureFormatFilterable(this.device, format), `${format} is not filterable`);
     }
   }
 
diff --git a/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts b/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts
index c5a58c0..a694867 100644
--- a/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts
+++ b/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts
@@ -120,13 +120,7 @@
 ) {
   t.skipIfTextureFormatNotSupported(format);
   if (filter === 'linear') {
-    t.skipIf(isDepthTextureFormat(format), 'depth texture are unfilterable');
-
-    const type = getTextureFormatType(format);
-    if (type === 'unfilterable-float') {
-      assert(is32Float(format));
-      t.skipIfDeviceDoesNotHaveFeature('float32-filterable');
-    }
+    t.skipIfTextureFormatNotFilterable(format);
   }
 }