Repository navigation
[WebGPU] Add int4 and uint4 QuantizeLinear and Reshape - #33792
Merged
Edward Chen (edgchen1) merged 5 commits intoNov 5, 2026
Merged
Conversation
Chromium's WebNN backend (ONNX opset 21) reshapes broadcastable (De)QuantizeLinear scale and zero point tensors to the scalar or 1-D shape the ONNX ops take. The CPU Reshape kernels only register IRv9 types (no int4/uint4), so constant folding cannot fold a Reshape of an int4/uint4 zero point, and with CPU EP fallback disabled the WebGPU EP must run it. Reshape is a pure copy/view, so the 4-bit types are safe to add from opset 21, the first opset whose schema allows them. This is why the WebNN dequantizeLinear "int4/uint4 1D tensor of odd size" and "uint4 4D tensor with broadcasting 4D scale and uint4 4D zeroPoint" conformance tests failed even though the DequantizeLinear kernel already supports int4/uint4. Co-authored-by: edgchen1 <18449977+edgchen1@users.noreply.github.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Adds int4/uint4 output (and zero point) to the WebGPU QuantizeLinear kernel for opsets 21-22, 23, 24, 25-27 and 28. Each invocation packs 8 4-bit results into one u32 word, first element in the low nibble, so odd element counts and packed output bytes are never shared between invocations. Results saturate to [-8, 7] / [0, 15]. The 4-bit zero point is read from packed u32 storage and sign-extended for int4. Main's exact rounding, precision filter and int8/uint8 WGSL are unchanged. Semantics and packing follow Edward Chen's unmerged branch edgchen1/webgpu_quantizelinear, applied to main's current kernel. Tests mirror the WebNN quantizeLinear/dequantizeLinear int4/uint4 conformance vectors, including the Reshape nodes Chromium inserts before the op, plus rounding/saturation, multi-word per-axis and blocked zero points, all opsets, output_dtype without a zero point and a Q -> DQ round trip, all pinned to WebGPU with CPU fallback disabled. Co-authored-by: edgchen1 <18449977+edgchen1@users.noreply.github.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
There are no active review issues for the WebGPU int4/uint4 QuantizeLinear and Reshape changes.
No open issues 🎉
What changed in this PR
Extends the WebGPU execution provider with int4/uint4 QuantizeLinear output and Reshape support, addressing WebNN conformance gaps when CPU fallback is disabled.
Changes:
- Adds packed 4-bit quantization with signed zero-point handling, saturation, and odd-sized output support.
- Enables int4/uint4 Reshape from opset 21.
- Adds WebGPU-pinned tests for conformance vectors, rounding, per-axis and blocked quantization, reshaped parameters, and round trips.
| File | Description |
|---|---|
onnxruntime/test/providers/webgpu/tensor/reshape_op_test.cc |
Tests 4-bit Reshape with inputs, initializers, and scalar outputs. |
onnxruntime/test/providers/webgpu/tensor/quantize_linear_test.cc |
Adds 4-bit quantization and dequantization regression coverage. |
onnxruntime/core/providers/webgpu/tensor/reshape.cc |
Registers 4-bit Reshape types from opset 21. |
onnxruntime/core/providers/webgpu/quantization/quantize_linear.h |
Adds the 4-bit shader mode and updates packing comments. |
onnxruntime/core/providers/webgpu/quantization/quantize_linear.cc |
Implements 4-bit packing, zero-point extraction, saturation, and type registration. |
Review effort: Balanced
adrastogi
marked this pull request as ready for review
November 2, 2026 23:19
adrastogi
requested review from
Edward Chen (edgchen1) and
Jiajia Qin (qjia7)
November 3, 2026 19:10
…gpu-int4-quantize-linear
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Edward Chen (edgchen1)
approved these changes
Nov 5, 2026
Edward Chen (edgchen1)
deleted the
adityar-microsoft-webgpu-int4-quantize-linear
branch
November 5, 2026 16:59
1 task done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds int4/uint4 support to the WebGPU EP for the W3C WebNN
quantizeLinear/dequantizeLinearconformance (WPT) cases. Every gap was found by WPT running on the WebGPU EP with CPU fallback disabled (Edge Canary, RTX/D3D12).Commits:
[1]becomes a scalar, and[1,1,2,1]becomes[2]for per-axis.y/y_zero_pointfor opsets 21-22, 23, 24, 25-27 and 28.precisionfilter in both GetCapability paths, and the int8/uint8 WGSL. The plugin EP looks kernels up in the same registry, so it claims the new types without changes toep/ep.cc.Semantics and packing (two 4-bit values per byte, sign extension, blocked quantization, saturation ranges) follow Edward Chen (@edgchen1)'s unmerged branch
edgchen1/webgpu_quantizelinear. That branch refactors QL/DQ into a WGSL template plusquantization_utils, but it predates #33683. This PR applies the same semantics to main's current kernel instead of porting the refactor.Tests are pinned to WebGPU with CPU EP fallback disabled:
onnxruntime/test/providers/webgpu/tensor/quantize_linear_test.cc:output_dtypewithout a zero point, and a Q -> DQ round trip.onnxruntime/test/providers/webgpu/tensor/reshape_op_test.cc: int4/uint4 Reshape, including to a scalar, from both an input and an initializer.The existing CPU
QuantizeLinearOpTest.Int4/UInt4/OddLarge_*tests now also run on WebGPU.Validation (Windows ARM64, NVIDIA RTX Spark N1X / D3D12, at 50323bf):
onnxruntime_provider_test --gtest_filter="WebGpuQuantizeLinearTest.*:WebGpuDequantizeLinearTest.*:TensorOpTest.Reshape*:QuantizeLinearOpTest.*:DequantizeLinearOpTest.*:QuantizeLinearOp21BlockedTest.*:QuantizeLinearOpMLFloat16Test.*:QuantizeLinearPrecisionTest.*": 188 tests, 184 passed, 0 failed, 4 skipped. The skips are DML-only.since_version >= 99),TensorOpTest.Reshape_int4_webgpuandWebGpuDequantizeLinearTest.Int4WebNNConformance_Float/Float16fail at session initialization, because the node lands on CPU.Int4PerAxisMultiWordZeroPoint, which has no Reshape, still passes.WebGpuQuantizeLinearTest.Int4*test fails on values.--use_webgpu shared_lib) built from 50323bf with Edge Canary 159.0.4372.0 and ORT runtime 1.28.3:quantizeLinear: 29/29 pass (was 15/29)dequantizeLinear: 33/33 pass (was 27/33)reshape: 67/67 passqdq_subgraph: 43/43 passMotivation and Context
This fixes the WebNN conformance failures on the WebGPU EP:
quantizeLinear.https.any.js, 14 subtests (f32 and f16 each):dequantizeLinear.https.any.js, 6 subtests:WebNN disables CPU fallback, so an unclaimed node makes the graph fail to build.