diff --git a/backends/webgpu/test/op_tests/cases.py b/backends/webgpu/test/op_tests/cases.py index ef0222afd48..2bb6ff68165 100644 --- a/backends/webgpu/test/op_tests/cases.py +++ b/backends/webgpu/test/op_tests/cases.py @@ -679,6 +679,50 @@ def _leaky_relu_suite() -> WebGPUTestSuite: atol=1e-4, rtol=1e-3, ) +from executorch.backends.webgpu.test.ops.test_upsample_bilinear2d import ( + UpsampleBilinear2dModule, +) + + +@register_op_test("upsample_bilinear2d") +def _upsample_bilinear2d_suite() -> WebGPUTestSuite: + # DPT/Depth-Anything bilinear resize head. Both align_corners branches + + # a non-integer ratio (5->8) that discriminates the two source-index + # formulas (see upsample_bilinear2d.wgsl). + return WebGPUTestSuite( + module_factory=lambda scale_factor, align_corners: UpsampleBilinear2dModule( + scale_factor, align_corners + ), + cases=[ + Case( + name="af_false_2x", + construct={"scale_factor": 2.0, "align_corners": False}, + inputs=(InputSpec(shape=(1, 8, 36, 36), gen=_upsample_det_input),), + ), + Case( + name="af_false_non_2x", + construct={"scale_factor": 1.6, "align_corners": False}, + inputs=(InputSpec(shape=(1, 2, 5, 5), gen=_upsample_det_input),), + ), + Case( + name="af_false_tiny", + construct={"scale_factor": 2.0, "align_corners": False}, + inputs=(InputSpec(shape=(1, 4, 5, 7), gen=_upsample_det_input),), + ), + Case( + name="af_true_2x", + construct={"scale_factor": 2.0, "align_corners": True}, + inputs=(InputSpec(shape=(1, 4, 7, 7), gen=_upsample_det_input),), + ), + Case( + name="af_true_non_2x", + construct={"scale_factor": 1.6, "align_corners": True}, + inputs=(InputSpec(shape=(1, 2, 5, 5), gen=_upsample_det_input),), + ), + ], + atol=1e-4, + rtol=1e-3, + ) from executorch.backends.webgpu.test.ops.test_max_pool2d import ( _det_input as _maxpool_det_input, MaxPool2dModule, diff --git a/backends/webgpu/test/ops/test_upsample_bilinear2d.py b/backends/webgpu/test/ops/test_upsample_bilinear2d.py new file mode 100644 index 00000000000..baa34f4b3e9 --- /dev/null +++ b/backends/webgpu/test/ops/test_upsample_bilinear2d.py @@ -0,0 +1,29 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +"""`aten.upsample_bilinear2d.vec` module for the WebGPU op-test framework. + +Bilinear upsample is on the Depth-Anything / DPT reassemble+fusion head +(`F.interpolate(..., mode="bilinear", align_corners=...)`), which resizes the +ViT patch grid back to image resolution. +""" + +import torch + + +class UpsampleBilinear2dModule(torch.nn.Module): + def __init__(self, scale_factor: float, align_corners: bool) -> None: + super().__init__() + self.scale_factor = scale_factor + self.align_corners = align_corners + + def forward(self, x: torch.Tensor) -> torch.Tensor: + return torch.nn.functional.interpolate( + x, + scale_factor=self.scale_factor, + mode="bilinear", + align_corners=self.align_corners, + )