Impr: Operator >>> support - #2784
Conversation
Resolution Time Benchmark---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Random Branching (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.95, 1.86, 4.41, 5.99, 7.20, 11.19, 23.35, 24.75]
line [0.92, 1.83, 4.31, 6.01, 7.53, 11.81, 22.93, 21.52]
line [0.92, 1.91, 4.13, 6.74, 8.44, 10.98, 21.63, 23.78]
---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Linear Recursion (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.29, 0.52, 0.68, 0.82, 1.10, 1.15, 1.36, 1.60]
line [0.26, 0.51, 0.64, 0.84, 1.17, 1.10, 1.40, 1.50]
line [0.31, 0.50, 0.65, 0.77, 1.08, 1.14, 1.43, 1.54]
---
config:
themeVariables:
xyChart:
plotColorPalette: "#E63946, #3B82F6, #059669"
---
xychart
title "Full Tree (🔴 PR | 🔵 main | 🟢 release)"
x-axis "max depth" [1, 2, 3, 4, 5, 6, 7, 8]
y-axis "time (ms)"
line [0.87, 2.06, 4.15, 6.93, 12.28, 26.71, 52.38, 108.46]
line [0.74, 2.10, 3.62, 6.87, 12.80, 25.82, 53.43, 107.59]
line [0.99, 2.11, 4.37, 6.49, 13.04, 27.03, 56.37, 113.91]
|
There was a problem hiding this comment.
Pull request overview
Adds support for JavaScript’s unsigned right shift operator (>>> / >>>=) in the TypeGPU TGSL → WGSL generator to match WGSL’s u32 shift semantics, and updates affected code to use it (avoiding CPU/GPU behavioral mismatches caused by JS >> being sign-preserving).
Changes:
- Extend WGSL generation to accept
>>>/>>>=, mapping them to WGSL>>/>>=, and validate/diagnose shift operand types (including deprecation warnings foru32 >>). - Fix CPU-side vector
u32right-shift behavior to use>>>(matching WGSL logical shift) and expand bit-shift test coverage. - Update examples/packages and ESLint rule to allow and prefer
>>>where unsigned right shift semantics are intended.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/typegpu/tests/std/numeric/bitShift.test.ts | Adds extensive coverage for shift typing, >>> support, and u32 >> deprecation warnings. |
| packages/typegpu/src/tgsl/wgslGenerator.ts | Implements >>> / >>>= support, operand validation, and deprecation warning for u32 LHS with >>. |
| packages/typegpu/src/std/operators.ts | Tightens std.bitShiftLeft/Right to vector-only usage and improves runtime argument error messaging. |
| packages/typegpu/src/data/wgslTypes.ts | Adds helpers to recognize integer32 scalars/vectors for generator validation. |
| packages/typegpu/src/data/vectorOps.ts | Fixes CPU vecNu right shift to use >>> (logical) instead of >> (arithmetic). |
| packages/typegpu-sort/src/bitonic/bitonicSort.ts | Switches to >>> for index computations intended to be unsigned shifts. |
| packages/typegpu-radiance-cascades/src/cascades.ts | Replaces unsigned shifts with >>> and ensures loop index type aligns with shifting needs. |
| packages/typegpu-noise/src/utils.ts | Removes prior std.isBeingTranspiled() branching for rotate-left and uses >>> consistently. |
| packages/typegpu-geometry/src/lines/polylineVariableWidth.ts | Uses >>> for unsigned index extraction. |
| packages/typegpu-geometry/src/lines/lineVariableWidth.ts | Uses >>> for unsigned index extraction. |
| packages/eslint-plugin/tests/rules/noUnsupportedSyntax.test.ts | Updates rule tests to no longer flag >>> / >>>= as unsupported. |
| packages/eslint-plugin/src/rules/noUnsupportedSyntax.ts | Allows >>> / >>>= by removing them from unsupported operator lists. |
| apps/typegpu-docs/src/examples/simulation/game-of-life/shaders/bitpacked-compute.ts | Uses >>> for bitpacking shifts to match u32 behavior. |
| apps/typegpu-docs/src/examples/simulation/game-of-life/index.ts | Uses >>> when extracting bits from u32 packed textures. |
| apps/typegpu-docs/src/examples/rendering/radiance-cascades/index.ts | Updates unsigned shifts in the demo pipeline to >>>. |
| apps/typegpu-docs/src/examples/image-processing/selfie-segmentation/post-processing/kernels.ts | Replaces scalar std.bitShiftRight with >>> for correct unsigned coordinate extraction. |
| apps/typegpu-docs/src/examples/image-processing/selfie-segmentation/inference/video-preprocess.ts | Replaces scalar std.bitShiftRight with >>> for correct unsigned coordinate extraction. |
| apps/typegpu-docs/src/examples/image-processing/ascii-filter/index.ts | Uses >>> for unsigned bit extraction from u32 glyph bitfields. |
| apps/typegpu-docs/src/examples/geometry/lines-combinations/index.ts | Updates checker pattern computation to use >>> on u32 screen coordinates. |
| apps/typegpu-docs/src/examples/algorithms/genetic-racing/index.ts | Uses >>> for unpacking packed u32 values. |
| apps/typegpu-docs/src/examples/algorithms/bitonic-sort/index.ts | Uses >>> for extracting upper bits from an index seed. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Caution
This PR introduces a type regression that breaks pnpm run test:types across dependent workspace packages.
Reviewed changes
This PR implements JavaScript >>>/>>>= operator support by mapping them to WGSL >>/>>= for unsigned left-hand sides; deprecates using >>/>>= with unsigned LHS; tightens codegen-time validation for all bit-shift operators; updates CPU-side unsigned-vector right shifts to use JS >>> semantics; migrates unsigned right-shift call sites; and removes >>>/>>>= from the ESLint unsupported-syntax list.
Type regression in infixOperators union
Removing scalar LHS overloads from cpuBitShiftLeft/cpuBitShiftRight leaves packages/typegpu/src/tgsl/infixDispatch.ts unable to call the infixOperators union members. tsc reports TS2349 in every workspace package that type-checks against typegpu.
The bit-shift functions can disallow scalar LHS while still exposing a DualFn signature compatible with the other infix operators, e.g. by keeping a scalar-scalar overload that throws at runtime or by adjusting infixDispatch.ts so it does not require a common callable signature across the union.
Technical details
# Type regression in infixOperators union
## Affected sites
- packages/typegpu/src/std/operators.ts:321 — `cpuBitShiftLeft` no longer has a scalar-scalar overload, so `DualFn<...>` contributes only vector signatures to `infixOperators`.
- packages/typegpu/src/std/operators.ts:351 — `cpuBitShiftRight` has the same issue.
- packages/typegpu/src/tgsl/infixDispatch.ts:64 — `opImpl(this as never, arg as never)` receives a union of `DualFn<...>` types with no common callable signature.
## Required outcome
- `pnpm run test:types` passes for the whole workspace.
## Suggested approach
- Restore a scalar-scalar overload on `cpuBitShiftLeft`/`cpuBitShiftRight` that throws at runtime, satisfying the union's common-callable-signature requirement without exposing working scalar support.
- Alternatively, constrain or widen the `InfixOperator`/`infixOperators` types so the runtime dispatch function does not require a callable common signature.Kimi K2 (free via Pullfrog for OSS) | 𝕏
Bundle size comparison (
|
| 🟢 Decreased | ➖ Unchanged | 🔴 Increased (max 0.22%) | ❔ Unknown |
|---|---|---|---|
| 0 | 207 | 115 | 0 |
import { ... } in PR vs import * as ... in PR (is the library tree-Shakeable?):
| Test | tsdown |
|---|---|
| tgpu_init.ts | 260.63 kB ( |
| tgpu_initFromDevice.ts | 260.10 kB ( |
| tgpu_resolve.ts | 166.00 kB ( |
| tgpu_resolveWithContext.ts | 165.94 kB ( |
| tgpu_bindGroupLayout.ts | 69.29 kB ( |
| tgpu_mutableAccessor.ts | 66.30 kB ( |
| tgpu_accessor.ts | 66.28 kB ( |
| tgpu_privateVar.ts | 65.63 kB ( |
| tgpu_workgroupVar.ts | 65.63 kB ( |
| tgpu_const.ts | 64.87 kB ( |
| tgpu_fn.ts | 38.45 kB ( |
| tgpu_fragmentFn.ts | 38.45 kB ( |
| tgpu_vertexFn.ts | 38.27 kB ( |
| tgpu_computeFn.ts | 37.97 kB ( |
| tgpu_vertexLayout.ts | 27.08 kB ( |
| tgpu_comptime.ts | 14.77 kB ( |
| tgpu_unroll.ts | 1.66 kB ( |
| tgpu_slot.ts | 1.54 kB ( |
| tgpu_lazy.ts | 1.19 kB ( |
If you wish to run a comparison for other, slower bundlers, run the 'Tree-shake test' from the GitHub Actions menu.
|
pkg.pr.new packages benchmark commit |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
The latest commit (75f0744) addressed the prior type regression by widening the call signature in packages/typegpu/src/tgsl/infixDispatch.ts: opImpl is now cast to (lhs: unknown, rhs: unknown) => unknown before invocation, so the infixOperators union no longer needs a common callable signature across DualFn members.
I verified the fix by running pnpm run --filter typegpu test:types and the equivalent checks on the dependent packages previously reported as failing (@typegpu/color, @typegpu/gl, @typegpu/geometry, @typegpu/sdf, @typegpu/radiance-cascades, typegpu-testing-utility), all of which now pass. The bit-shift test suite (pnpm run --filter typegpu test -- bitShift.test.ts) and the ESLint plugin tests (pnpm run --filter eslint-plugin-typegpu test) also pass.
Kimi K2 (free via Pullfrog for OSS) | 𝕏

Closes #2768.